diff --git a/lib/__tests__/parser.test.ts b/lib/__tests__/parser.test.ts new file mode 100644 index 0000000..dde7fe9 --- /dev/null +++ b/lib/__tests__/parser.test.ts @@ -0,0 +1,144 @@ +import { describe, expect, it } from 'vitest'; +import { parseQuery, validateQuery } from '../parser'; + +describe('parseQuery — structured queries', () => { + it('parses type, operator, region, radius', () => { + const parsed = parseQuery('type:data_center operator:google region:bavaria radius:100'); + expect(parsed.type).toBe('data_center'); + expect(parsed.operator).toBe('google'); + expect(parsed.region).toBe('bavaria'); + expect(parsed.radius).toBe(100); + }); + + it('parses country and near', () => { + const parsed = parseQuery('type:airport country:france'); + expect(parsed.type).toBe('airport'); + expect(parsed.country).toBe('france'); + }); + + it('ignores unknown type keys', () => { + const parsed = parseQuery('type:not_a_real_type region:karnataka'); + expect(parsed.type).toBeNull(); + }); + + it('caps radius at 500 km', () => { + const parsed = parseQuery('type:telecom near:delhi radius:9999'); + expect(parsed.radius).toBe(500); + }); + + it('decodes underscores in operator and region values', () => { + const parsed = parseQuery('type:power_plant operator:tata_power region:tamil_nadu'); + expect(parsed.operator).toBe('tata power'); + expect(parsed.region).toBe('tamil nadu'); + }); + + it('defaults radius to 50 when unspecified', () => { + const parsed = parseQuery('type:telecom region:karnataka'); + expect(parsed.radius).toBe(50); + }); +}); + +describe('parseQuery — natural language', () => { + it('extracts telecom towers in a region', () => { + const parsed = parseQuery('telecom towers in karnataka'); + expect(parsed.type).toBe('telecom'); + expect(parsed.region).toBe('karnataka'); + expect(parsed.near).toBeNull(); + }); + + it('extracts "near X" as a proximity search', () => { + const parsed = parseQuery('power plants near mumbai'); + expect(parsed.type).toBe('power_plant'); + expect(parsed.near).toBe('mumbai'); + expect(parsed.region).toBeNull(); + }); + + it('extracts data centers', () => { + const parsed = parseQuery('data centers in california'); + expect(parsed.type).toBe('data_center'); + expect(parsed.region).toBe('california'); + }); + + it('extracts airports', () => { + expect(parseQuery('airports in germany').type).toBe('airport'); + }); + + it('extracts substations', () => { + expect(parseQuery('substations in texas').type).toBe('substation'); + }); + + it('normalizes an operator alias to its canonical form', () => { + const parsed = parseQuery('aws data centers in oregon'); + expect(parsed.operator).toBe('amazon'); + }); + + it('parses an explicit radius from "within"', () => { + const parsed = parseQuery('cell towers near delhi within 25 km'); + expect(parsed.near).toBe('delhi'); + expect(parsed.radius).toBe(25); + }); + + it('strips stopwords like "show all" from the region', () => { + const parsed = parseQuery('show all hospitals in mumbai'); + expect(parsed.type).toBe('hospital'); + expect(parsed.region?.toLowerCase()).toContain('mumbai'); + }); + + it('recognises cell vs broadcast vs radio tower variants', () => { + expect(parseQuery('cell towers in chennai').type).toBe('cell_tower'); + expect(parseQuery('broadcast towers in chennai').type).toBe('broadcast_tower'); + expect(parseQuery('radio towers in chennai').type).toBe('radio_tower'); + }); + + it('recognises surveillance / CCTV', () => { + expect(parseQuery('surveillance cameras in london').type).toBe('surveillance_camera'); + expect(parseQuery('cctv in london').type).toBe('surveillance_camera'); + }); +}); + +describe('parseQuery — empty / whitespace', () => { + it('returns an empty ParsedQuery for an empty string', () => { + const parsed = parseQuery(''); + expect(parsed.type).toBeNull(); + expect(parsed.region).toBeNull(); + expect(parsed.near).toBeNull(); + expect(parsed.raw).toBe(''); + }); + + it('trims whitespace', () => { + const parsed = parseQuery(' telecom towers in karnataka '); + expect(parsed.type).toBe('telecom'); + expect(parsed.region).toBe('karnataka'); + }); +}); + +describe('validateQuery', () => { + it('rejects queries with no type and no operator', () => { + const parsed = parseQuery('in karnataka'); + const result = validateQuery(parsed); + expect(result.valid).toBe(false); + expect(result.error).toMatch(/asset type or operator/i); + }); + + it('rejects queries with no geographic scope', () => { + const parsed = parseQuery('type:data_center'); + const result = validateQuery(parsed); + expect(result.valid).toBe(false); + expect(result.error).toMatch(/geographic scope/i); + }); + + it('accepts a complete structured query', () => { + const parsed = parseQuery('type:telecom region:karnataka'); + expect(validateQuery(parsed).valid).toBe(true); + }); + + it('accepts a complete natural query', () => { + const parsed = parseQuery('power plants in california'); + expect(validateQuery(parsed).valid).toBe(true); + }); + + it('accepts a "near" proximity query', () => { + const parsed = parseQuery('data centers near london'); + expect(validateQuery(parsed).valid).toBe(true); + }); +}); diff --git a/lib/asset-types.ts b/lib/asset-types.ts new file mode 100644 index 0000000..d47809b --- /dev/null +++ b/lib/asset-types.ts @@ -0,0 +1,1042 @@ +/** + * Asset type catalog and operator alias dictionary. + * + * ASSET_TYPE_MAP maps a canonical asset type key (e.g. "power_plant") to the + * OSM tag selector(s) used to match it via Overpass, plus a human-readable label. + * OPERATOR_ALIASES maps a canonical operator name to known variants (used by + * the natural-language parser to normalize operator mentions). + */ + +export interface AssetTypeConfig { + osmTags: Record | Record[]; + label: string; +} + + +export const ASSET_TYPE_MAP: Record = { + telecom: { + osmTags: [ + { 'man_made': 'tower', 'tower:type': ['communication', 'telecommunications'] }, + { 'man_made': 'communications_tower' }, + { 'communication:mobile_phone': 'yes' } + ], + label: 'Telecom Tower' + }, + tower: { + osmTags: [ + { 'man_made': 'tower', 'tower:type': ['communication', 'telecommunications'] }, + { 'man_made': 'communications_tower' }, + { 'communication:mobile_phone': 'yes' } + ], + label: 'Telecom Tower' + }, + data_center: { + osmTags: { 'building': 'data_centre' }, + label: 'Data Center' + }, + datacenter: { + osmTags: { 'building': 'data_centre' }, + label: 'Data Center' + }, + power_plant: { + osmTags: { 'power': 'plant' }, + label: 'Power Plant' + }, + powerplant: { + osmTags: { 'power': 'plant' }, + label: 'Power Plant' + }, + substation: { + osmTags: { 'power': 'substation' }, + label: 'Substation' + }, + port: { + osmTags: { 'landuse': 'port' }, + label: 'Port' + }, + harbour: { + osmTags: { 'harbour': 'yes' }, + label: 'Harbour' + }, + warehouse: { + osmTags: { 'building': 'warehouse' }, + label: 'Warehouse' + }, + building: { + osmTags: { 'building': 'yes' }, + label: 'Building' + }, + airport: { + osmTags: { 'aeroway': 'aerodrome' }, + label: 'Airport' + }, + helipad: { + osmTags: { 'aeroway': 'helipad' }, + label: 'Helipad' + }, + railyard: { + osmTags: { 'landuse': 'railway' }, + label: 'Rail Yard' + }, + rail_yard: { + osmTags: { 'landuse': 'railway' }, + label: 'Rail Yard' + }, + refinery: { + osmTags: { 'man_made': 'petroleum_well' }, + label: 'Refinery' + }, + pipeline: { + osmTags: { 'man_made': 'pipeline' }, + label: 'Pipeline' + }, + solar: { + osmTags: { 'power': 'generator', 'generator:source': 'solar' }, + label: 'Solar Farm' + }, + wind: { + osmTags: { 'power': 'generator', 'generator:source': 'wind' }, + label: 'Wind Farm' + }, + nuclear: { + osmTags: { 'power': 'generator', 'generator:source': 'nuclear' }, + label: 'Nuclear Plant' + }, + dam: { + osmTags: { 'waterway': 'dam' }, + label: 'Dam' + }, + military: { + osmTags: { 'landuse': 'military' }, + label: 'Military Installation' + }, + prison: { + osmTags: { 'amenity': 'prison' }, + label: 'Prison' + }, + hospital: { + osmTags: { 'amenity': 'hospital' }, + label: 'Hospital' + }, + embassy: { + osmTags: { 'amenity': 'embassy' }, + label: 'Embassy' + }, + factory: { + osmTags: { 'building': 'industrial' }, + label: 'Factory' + }, + industrial: { + osmTags: { 'landuse': 'industrial' }, + label: 'Industrial Zone' + }, + school: { + osmTags: { 'amenity': 'school' }, + label: 'School' + }, + university: { + osmTags: { 'amenity': 'university' }, + label: 'University' + }, + college: { + osmTags: { 'amenity': 'college' }, + label: 'College' + }, + stadium: { + osmTags: { 'leisure': 'stadium' }, + label: 'Stadium' + }, + fire_station: { + osmTags: { 'amenity': 'fire_station' }, + label: 'Fire Station' + }, + police: { + osmTags: { 'amenity': 'police' }, + label: 'Police Station' + }, + courthouse: { + osmTags: { 'amenity': 'courthouse' }, + label: 'Courthouse' + }, + bank: { + osmTags: { 'amenity': 'bank' }, + label: 'Bank' + }, + atm: { + osmTags: { 'amenity': 'atm' }, + label: 'ATM' + }, + fuel: { + osmTags: { 'amenity': 'fuel' }, + label: 'Fuel Station' + }, + gas_station: { + osmTags: { 'amenity': 'fuel' }, + label: 'Gas Station' + }, + petrol: { + osmTags: { 'amenity': 'fuel' }, + label: 'Petrol Station' + }, + charging_station: { + osmTags: { 'amenity': 'charging_station' }, + label: 'EV Charging Station' + }, + water_tower: { + osmTags: { 'man_made': 'water_tower' }, + label: 'Water Tower' + }, + water_treatment: { + osmTags: { 'man_made': 'water_works' }, + label: 'Water Treatment Plant' + }, + wastewater: { + osmTags: { 'man_made': 'wastewater_plant' }, + label: 'Wastewater Plant' + }, + sewage: { + osmTags: { 'man_made': 'wastewater_plant' }, + label: 'Sewage Plant' + }, + landfill: { + osmTags: { 'landuse': 'landfill' }, + label: 'Landfill' + }, + quarry: { + osmTags: { 'landuse': 'quarry' }, + label: 'Quarry' + }, + mine: { + osmTags: { 'landuse': 'quarry' }, + label: 'Mine' + }, + oil_well: { + osmTags: { 'man_made': 'petroleum_well' }, + label: 'Oil Well' + }, + gas_well: { + osmTags: { 'man_made': 'petroleum_well' }, + label: 'Gas Well' + }, + storage_tank: { + osmTags: { 'man_made': 'storage_tank' }, + label: 'Storage Tank' + }, + silo: { + osmTags: { 'man_made': 'silo' }, + label: 'Silo' + }, + chimney: { + osmTags: { 'man_made': 'chimney' }, + label: 'Chimney' + }, + cooling_tower: { + osmTags: { 'man_made': 'cooling_tower' }, + label: 'Cooling Tower' + }, + lighthouse: { + osmTags: { 'man_made': 'lighthouse' }, + label: 'Lighthouse' + }, + radar: { + osmTags: { 'man_made': 'radar' }, + label: 'Radar' + }, + surveillance_camera: { + osmTags: [ + { 'man_made': 'surveillance', 'surveillance:type': 'camera' }, + { 'man_made': 'surveillance', 'surveillance': 'outdoor' }, + { 'man_made': 'surveillance', 'surveillance': 'indoor' }, + { 'man_made': 'surveillance', 'surveillance': 'public' }, + { 'surveillance:type': 'camera' }, + { 'man_made': 'surveillance' } + ], + label: 'Surveillance Camera' + }, + cctv: { + osmTags: [ + { 'man_made': 'surveillance', 'surveillance:type': 'camera' }, + { 'man_made': 'surveillance', 'surveillance': 'outdoor' }, + { 'man_made': 'surveillance', 'surveillance': 'indoor' }, + { 'man_made': 'surveillance', 'surveillance': 'public' }, + { 'surveillance:type': 'camera' }, + { 'man_made': 'surveillance' } + ], + label: 'Surveillance Camera' + }, + antenna: { + osmTags: { 'man_made': 'antenna' }, + label: 'Antenna' + }, + mast: { + osmTags: { 'man_made': 'mast' }, + label: 'Mast' + }, + bridge: { + osmTags: { 'man_made': 'bridge' }, + label: 'Bridge' + }, + tunnel: { + osmTags: { 'tunnel': 'yes' }, + label: 'Tunnel' + }, + ferry_terminal: { + osmTags: { 'amenity': 'ferry_terminal' }, + label: 'Ferry Terminal' + }, + bus_station: { + osmTags: { 'amenity': 'bus_station' }, + label: 'Bus Station' + }, + train_station: { + osmTags: { 'railway': 'station' }, + label: 'Train Station' + }, + metro: { + osmTags: { 'railway': 'subway_entrance' }, + label: 'Metro Station' + }, + parking: { + osmTags: { 'amenity': 'parking' }, + label: 'Parking' + }, + cemetery: { + osmTags: { 'landuse': 'cemetery' }, + label: 'Cemetery' + }, + place_of_worship: { + osmTags: { 'amenity': 'place_of_worship' }, + label: 'Place of Worship' + }, + mosque: { + osmTags: { 'amenity': 'place_of_worship', 'religion': 'muslim' }, + label: 'Mosque' + }, + church: { + osmTags: { 'amenity': 'place_of_worship', 'religion': 'christian' }, + label: 'Church' + }, + temple: { + osmTags: { 'amenity': 'place_of_worship', 'religion': 'hindu' }, + label: 'Temple' + }, + synagogue: { + osmTags: { 'amenity': 'place_of_worship', 'religion': 'jewish' }, + label: 'Synagogue' + }, + library: { + osmTags: { 'amenity': 'library' }, + label: 'Library' + }, + museum: { + osmTags: { 'tourism': 'museum' }, + label: 'Museum' + }, + theatre: { + osmTags: { 'amenity': 'theatre' }, + label: 'Theatre' + }, + cinema: { + osmTags: { 'amenity': 'cinema' }, + label: 'Cinema' + }, + hotel: { + osmTags: { 'tourism': 'hotel' }, + label: 'Hotel' + }, + pharmacy: { + osmTags: { 'amenity': 'pharmacy' }, + label: 'Pharmacy' + }, + clinic: { + osmTags: { 'amenity': 'clinic' }, + label: 'Clinic' + }, + dentist: { + osmTags: { 'amenity': 'dentist' }, + label: 'Dentist' + }, + veterinary: { + osmTags: { 'amenity': 'veterinary' }, + label: 'Veterinary' + }, + post_office: { + osmTags: { 'amenity': 'post_office' }, + label: 'Post Office' + }, + recycling: { + osmTags: { 'amenity': 'recycling' }, + label: 'Recycling Center' + }, + observatory: { + osmTags: { 'man_made': 'observatory' }, + label: 'Observatory' + }, + crane: { + osmTags: { 'man_made': 'crane' }, + label: 'Crane' + }, + windmill: { + osmTags: { 'man_made': 'windmill' }, + label: 'Windmill' + }, + watermill: { + osmTags: { 'man_made': 'watermill' }, + label: 'Watermill' + }, + works: { + osmTags: { 'man_made': 'works' }, + label: 'Works' + }, + gasometer: { + osmTags: { 'man_made': 'gasometer' }, + label: 'Gasometer' + }, + bunker: { + osmTags: { 'military': 'bunker' }, + label: 'Bunker' + }, + barracks: { + osmTags: { 'military': 'barracks' }, + label: 'Barracks' + }, + airfield: { + osmTags: { 'military': 'airfield' }, + label: 'Military Airfield' + }, + naval_base: { + osmTags: { 'military': 'naval_base' }, + label: 'Naval Base' + }, + nuclear_site: { + osmTags: { 'military': 'nuclear_explosion_site' }, + label: 'Nuclear Site' + }, + range: { + osmTags: { 'military': 'range' }, + label: 'Military Range' + }, + checkpoint: { + osmTags: { 'military': 'checkpoint' }, + label: 'Checkpoint' + }, + border_control: { + osmTags: { 'barrier': 'border_control' }, + label: 'Border Control' + }, + // Additional infrastructure types + hydroelectric: { + osmTags: { 'power': 'generator', 'generator:source': 'hydro' }, + label: 'Hydroelectric Plant' + }, + geothermal: { + osmTags: { 'power': 'generator', 'generator:source': 'geothermal' }, + label: 'Geothermal Plant' + }, + biogas: { + osmTags: { 'power': 'generator', 'generator:source': 'biogas' }, + label: 'Biogas Plant' + }, + biomass: { + osmTags: { 'power': 'generator', 'generator:source': 'biomass' }, + label: 'Biomass Plant' + }, + tidal: { + osmTags: { 'power': 'generator', 'generator:source': 'tidal' }, + label: 'Tidal Power Plant' + }, + coal: { + osmTags: { 'power': 'generator', 'generator:source': 'coal' }, + label: 'Coal Power Plant' + }, + gas_power: { + osmTags: { 'power': 'generator', 'generator:source': 'gas' }, + label: 'Gas Power Plant' + }, + oil_power: { + osmTags: { 'power': 'generator', 'generator:source': 'oil' }, + label: 'Oil Power Plant' + }, + transformer: { + osmTags: { 'power': 'transformer' }, + label: 'Transformer' + }, + power_line: { + osmTags: { 'power': 'line' }, + label: 'Power Line' + }, + power_pole: { + osmTags: { 'power': 'pole' }, + label: 'Power Pole' + }, + // Transportation additions + runway: { + osmTags: { 'aeroway': 'runway' }, + label: 'Runway' + }, + taxiway: { + osmTags: { 'aeroway': 'taxiway' }, + label: 'Taxiway' + }, + terminal: { + osmTags: { 'aeroway': 'terminal' }, + label: 'Airport Terminal' + }, + hangar: { + osmTags: { 'aeroway': 'hangar' }, + label: 'Hangar' + }, + seaport: { + osmTags: { 'industrial': 'port' }, + label: 'Seaport' + }, + marina: { + osmTags: { 'leisure': 'marina' }, + label: 'Marina' + }, + shipyard: { + osmTags: { 'industrial': 'shipyard' }, + label: 'Shipyard' + }, + dock: { + osmTags: { 'waterway': 'dock' }, + label: 'Dock' + }, + tram_stop: { + osmTags: { 'railway': 'tram_stop' }, + label: 'Tram Stop' + }, + halt: { + osmTags: { 'railway': 'halt' }, + label: 'Railway Halt' + }, + level_crossing: { + osmTags: { 'railway': 'level_crossing' }, + label: 'Level Crossing' + }, + toll_booth: { + osmTags: { 'barrier': 'toll_booth' }, + label: 'Toll Booth' + }, + weigh_station: { + osmTags: { 'amenity': 'weighbridge' }, + label: 'Weigh Station' + }, + // Communication + cell_tower: { + osmTags: [ + { 'communication:mobile_phone': 'yes' }, + { 'tower:type': 'communications_tower' }, + { 'man_made': 'communications_tower' } + ], + label: 'Cell Tower' + }, + radio_tower: { + osmTags: { 'man_made': 'tower', 'tower:type': 'communication' }, + label: 'Radio Tower' + }, + broadcast_tower: { + osmTags: { 'man_made': 'tower', 'tower:type': 'broadcast' }, + label: 'Broadcast Tower' + }, + satellite_dish: { + osmTags: { 'man_made': 'satellite_dish' }, + label: 'Satellite Dish' + }, + telephone_exchange: { + osmTags: { 'telecom': 'exchange' }, + label: 'Telephone Exchange' + }, + // Emergency Services + ambulance_station: { + osmTags: { 'emergency': 'ambulance_station' }, + label: 'Ambulance Station' + }, + emergency_phone: { + osmTags: { 'emergency': 'phone' }, + label: 'Emergency Phone' + }, + fire_hydrant: { + osmTags: { 'emergency': 'fire_hydrant' }, + label: 'Fire Hydrant' + }, + lifeguard: { + osmTags: { 'emergency': 'lifeguard' }, + label: 'Lifeguard Station' + }, + rescue_station: { + osmTags: { 'emergency': 'rescue_station' }, + label: 'Rescue Station' + }, + coast_guard: { + osmTags: { 'emergency': 'coast_guard' }, + label: 'Coast Guard' + }, + // Government & Administrative + townhall: { + osmTags: { 'amenity': 'townhall' }, + label: 'Town Hall' + }, + government: { + osmTags: { 'office': 'government' }, + label: 'Government Office' + }, + customs: { + osmTags: { 'office': 'customs' }, + label: 'Customs Office' + }, + tax_office: { + osmTags: { 'office': 'tax' }, + label: 'Tax Office' + }, + // Education additions + kindergarten: { + osmTags: { 'amenity': 'kindergarten' }, + label: 'Kindergarten' + }, + driving_school: { + osmTags: { 'amenity': 'driving_school' }, + label: 'Driving School' + }, + research: { + osmTags: { 'amenity': 'research_institute' }, + label: 'Research Institute' + }, + // Industrial additions + brewery: { + osmTags: { 'craft': 'brewery' }, + label: 'Brewery' + }, + distillery: { + osmTags: { 'craft': 'distillery' }, + label: 'Distillery' + }, + sawmill: { + osmTags: { 'craft': 'sawmill' }, + label: 'Sawmill' + }, + slaughterhouse: { + osmTags: { 'industrial': 'slaughterhouse' }, + label: 'Slaughterhouse' + }, + scrap_yard: { + osmTags: { 'industrial': 'scrap_yard' }, + label: 'Scrap Yard' + }, + depot: { + osmTags: { 'industrial': 'depot' }, + label: 'Depot' + }, + recycling_plant: { + osmTags: { 'industrial': 'recycling' }, + label: 'Recycling Plant' + }, + // Leisure & Sports + sports_centre: { + osmTags: { 'leisure': 'sports_centre' }, + label: 'Sports Centre' + }, + swimming_pool: { + osmTags: { 'leisure': 'swimming_pool' }, + label: 'Swimming Pool' + }, + golf_course: { + osmTags: { 'leisure': 'golf_course' }, + label: 'Golf Course' + }, + racetrack: { + osmTags: { 'leisure': 'track' }, + label: 'Racetrack' + }, + ice_rink: { + osmTags: { 'leisure': 'ice_rink' }, + label: 'Ice Rink' + }, + // Tourism + campsite: { + osmTags: { 'tourism': 'camp_site' }, + label: 'Campsite' + }, + caravan_site: { + osmTags: { 'tourism': 'caravan_site' }, + label: 'Caravan Site' + }, + theme_park: { + osmTags: { 'tourism': 'theme_park' }, + label: 'Theme Park' + }, + zoo: { + osmTags: { 'tourism': 'zoo' }, + label: 'Zoo' + }, + aquarium: { + osmTags: { 'tourism': 'aquarium' }, + label: 'Aquarium' + }, + viewpoint: { + osmTags: { 'tourism': 'viewpoint' }, + label: 'Viewpoint' + }, + attraction: { + osmTags: { 'tourism': 'attraction' }, + label: 'Tourist Attraction' + }, + // Healthcare additions + nursing_home: { + osmTags: { 'amenity': 'nursing_home' }, + label: 'Nursing Home' + }, + hospice: { + osmTags: { 'amenity': 'hospice' }, + label: 'Hospice' + }, + blood_bank: { + osmTags: { 'healthcare': 'blood_bank' }, + label: 'Blood Bank' + }, + // Agriculture + farm: { + osmTags: { 'landuse': 'farmland' }, + label: 'Farm' + }, + greenhouse: { + osmTags: { 'building': 'greenhouse' }, + label: 'Greenhouse' + }, + orchard: { + osmTags: { 'landuse': 'orchard' }, + label: 'Orchard' + }, + vineyard: { + osmTags: { 'landuse': 'vineyard' }, + label: 'Vineyard' + }, + // Other notable structures + monument: { + osmTags: { 'historic': 'monument' }, + label: 'Monument' + }, + memorial: { + osmTags: { 'historic': 'memorial' }, + label: 'Memorial' + }, + castle: { + osmTags: { 'historic': 'castle' }, + label: 'Castle' + }, + fort: { + osmTags: { 'historic': 'fort' }, + label: 'Fort' + }, + ruins: { + osmTags: { 'historic': 'ruins' }, + label: 'Ruins' + }, + archaeological_site: { + osmTags: { 'historic': 'archaeological_site' }, + label: 'Archaeological Site' + }, + clock_tower: { + osmTags: { 'man_made': 'tower', 'tower:type': 'clock' }, + label: 'Clock Tower' + }, + bell_tower: { + osmTags: { 'man_made': 'tower', 'tower:type': 'bell_tower' }, + label: 'Bell Tower' + }, + water_well: { + osmTags: { 'man_made': 'water_well' }, + label: 'Water Well' + }, + reservoir: { + osmTags: { 'landuse': 'reservoir' }, + label: 'Reservoir' + }, + pumping_station: { + osmTags: { 'man_made': 'pumping_station' }, + label: 'Pumping Station' + }, + sewage_plant: { + osmTags: { 'man_made': 'wastewater_plant' }, + label: 'Sewage Plant' + }, + // Transportation - Highway facilities + rest_area: { + osmTags: { 'highway': 'rest_area' }, + label: 'Rest Area' + }, + service_area: { + osmTags: { 'highway': 'services' }, + label: 'Service Area' + }, + // Aviation - Control + atc_tower: { + osmTags: { 'aeroway': 'control_tower' }, + label: 'ATC Tower' + }, + // Public Utilities + bicycle_parking: { + osmTags: { 'amenity': 'bicycle_parking' }, + label: 'Bicycle Parking' + }, + drinking_water: { + osmTags: { 'amenity': 'drinking_water' }, + label: 'Drinking Water' + }, + public_toilet: { + osmTags: { 'amenity': 'toilets' }, + label: 'Public Toilet' + }, + bench: { + osmTags: { 'amenity': 'bench' }, + label: 'Bench' + }, + waste_basket: { + osmTags: { 'amenity': 'waste_basket' }, + label: 'Waste Basket' + }, + // Maritime additions + pier: { + osmTags: { 'man_made': 'pier' }, + label: 'Pier' + }, + jetty: { + osmTags: { 'man_made': 'jetty' }, + label: 'Jetty' + }, + slipway: { + osmTags: { 'leisure': 'slipway' }, + label: 'Slipway' + }, + boat_lift: { + osmTags: { 'waterway': 'boat_lift' }, + label: 'Boat Lift' + }, + mooring: { + osmTags: { 'waterway': 'mooring' }, + label: 'Mooring' + }, + // Cable Transport + aerialway: { + osmTags: { 'aerialway': 'cable_car' }, + label: 'Cable Car' + }, + gondola: { + osmTags: { 'aerialway': 'gondola' }, + label: 'Gondola' + }, + funicular: { + osmTags: { 'aerialway': 'funicular' }, + label: 'Funicular' + }, + chairlift: { + osmTags: { 'aerialway': 'chair_lift' }, + label: 'Chairlift' + }, + // Energy Storage & Distribution + battery_storage: { + osmTags: { 'power': 'generator', 'generator:source': 'battery' }, + label: 'Battery Storage' + }, + converter: { + osmTags: { 'power': 'converter' }, + label: 'Power Converter' + }, + switch: { + osmTags: { 'power': 'switch' }, + label: 'Power Switch' + }, + // Street Infrastructure + street_lamp: { + osmTags: { 'highway': 'street_lamp' }, + label: 'Street Lamp' + }, + traffic_signals: { + osmTags: { 'highway': 'traffic_signals' }, + label: 'Traffic Signals' + }, + // Emergency Infrastructure + siren: { + osmTags: { 'emergency': 'siren' }, + label: 'Emergency Siren' + }, + defibrillator: { + osmTags: { 'emergency': 'defibrillator' }, + label: 'Defibrillator' + }, + assembly_point: { + osmTags: { 'emergency': 'assembly_point' }, + label: 'Assembly Point' + }, + life_ring: { + osmTags: { 'emergency': 'life_ring' }, + label: 'Life Ring' + }, + // Tourism Infrastructure + information: { + osmTags: { 'tourism': 'information' }, + label: 'Tourist Information' + }, + picnic_site: { + osmTags: { 'tourism': 'picnic_site' }, + label: 'Picnic Site' + }, + // Commercial + supermarket: { + osmTags: { 'shop': 'supermarket' }, + label: 'Supermarket' + }, + mall: { + osmTags: { 'shop': 'mall' }, + label: 'Shopping Mall' + }, + marketplace: { + osmTags: { 'amenity': 'marketplace' }, + label: 'Marketplace' + }, + // Shared Mobility + bicycle_rental: { + osmTags: { 'amenity': 'bicycle_rental' }, + label: 'Bike Sharing' + }, + car_sharing: { + osmTags: { 'amenity': 'car_sharing' }, + label: 'Car Sharing' + }, + // Science & Research + planetarium: { + osmTags: { 'amenity': 'planetarium' }, + label: 'Planetarium' + }, + laboratory: { + osmTags: { 'man_made': 'laboratory' }, + label: 'Laboratory' + }, + // Construction + construction_site: { + osmTags: { 'landuse': 'construction' }, + label: 'Construction Site' + }, + // Food & Beverage Production + winery: { + osmTags: { 'craft': 'winery' }, + label: 'Winery' + }, + bakery: { + osmTags: { 'craft': 'bakery' }, + label: 'Bakery' + }, + dairy: { + osmTags: { 'craft': 'dairy' }, + label: 'Dairy' + }, + // Additional Transport + taxi_stand: { + osmTags: { 'amenity': 'taxi' }, + label: 'Taxi Stand' + }, + bicycle_repair: { + osmTags: { 'amenity': 'bicycle_repair_station' }, + label: 'Bicycle Repair Station' + }, + car_wash: { + osmTags: { 'amenity': 'car_wash' }, + label: 'Car Wash' + }, + // Postal & Communication + post_box: { + osmTags: { 'amenity': 'post_box' }, + label: 'Post Box' + }, + telephone: { + osmTags: { 'amenity': 'telephone' }, + label: 'Public Telephone' + }, + // Community + community_centre: { + osmTags: { 'amenity': 'community_centre' }, + label: 'Community Centre' + }, + social_facility: { + osmTags: { 'amenity': 'social_facility' }, + label: 'Social Facility' + }, + shelter: { + osmTags: { 'amenity': 'shelter' }, + label: 'Shelter' + }, + // Food Services + restaurant: { + osmTags: { 'amenity': 'restaurant' }, + label: 'Restaurant' + }, + cafe: { + osmTags: { 'amenity': 'cafe' }, + label: 'Cafe' + }, + fast_food: { + osmTags: { 'amenity': 'fast_food' }, + label: 'Fast Food' + }, + // Recreation + playground: { + osmTags: { 'leisure': 'playground' }, + label: 'Playground' + }, + park: { + osmTags: { 'leisure': 'park' }, + label: 'Park' + }, + pitch: { + osmTags: { 'leisure': 'pitch' }, + label: 'Sports Pitch' + }, + // Water Features + fountain: { + osmTags: { 'amenity': 'fountain' }, + label: 'Fountain' + }, + waterfall: { + osmTags: { 'waterway': 'waterfall' }, + label: 'Waterfall' + }, + hot_spring: { + osmTags: { 'natural': 'hot_spring' }, + label: 'Hot Spring' + }, + // Safety & Monitoring + monitoring_station: { + osmTags: { 'man_made': 'monitoring_station' }, + label: 'Monitoring Station' + }, + weather_station: { + osmTags: { 'man_made': 'weather_station' }, + label: 'Weather Station' + } +}; + +export const OPERATOR_ALIASES: Record = { + 'airtel': ['bharti airtel', 'airtel india', 'airtel telecom'], + 'jio': ['reliance jio', 'jio infocomm'], + 'vodafone': ['vodafone idea', 'vi', 'vodafone india'], + 'bsnl': ['bharat sanchar nigam'], + 'google': ['google llc', 'google inc'], + 'amazon': ['amazon web services', 'aws'], + 'microsoft': ['microsoft azure', 'azure'], + 'meta': ['facebook', 'meta platforms'], + 'apple': ['apple inc'], + 'at&t': ['att', 'at and t'], + 'verizon': ['verizon wireless'], + 't-mobile': ['tmobile', 't mobile'], + 'vodacom': ['vodacom group'], + 'mtn': ['mtn group'], + 'orange': ['orange telecom'], + 'telefonica': ['movistar'], + 'china mobile': ['cmcc'], + 'china unicom': [], + 'china telecom': [], + 'ntpc': ['national thermal power corporation'], + 'adani': ['adani power', 'adani green'], + 'tata': ['tata power', 'tata steel'], + 'reliance': ['reliance industries', 'ril'] +}; diff --git a/lib/overpass.ts b/lib/overpass.ts index d27165d..be55b05 100644 --- a/lib/overpass.ts +++ b/lib/overpass.ts @@ -1,4 +1,5 @@ -import { Asset, ASSET_TYPE_MAP } from './types'; +import { Asset } from './types'; +import { ASSET_TYPE_MAP } from './asset-types'; const OVERPASS_APIS = [ 'https://overpass-api.de/api/interpreter', diff --git a/lib/parser.ts b/lib/parser.ts index ee0833b..c95dbd5 100644 --- a/lib/parser.ts +++ b/lib/parser.ts @@ -1,4 +1,5 @@ -import { ParsedQuery, ASSET_TYPE_MAP, OPERATOR_ALIASES } from './types'; +import { ParsedQuery } from './types'; +import { ASSET_TYPE_MAP, OPERATOR_ALIASES } from './asset-types'; const STRUCTURED_PATTERN = /^(?:type:|operator:|region:|country:|near:|radius:)/i; diff --git a/lib/types.ts b/lib/types.ts index 2f7b328..cc59538 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -50,1030 +50,5 @@ export interface SearchError { code: string; } -export const ASSET_TYPE_MAP: Record | Record[]; label: string }> = { - telecom: { - osmTags: [ - { 'man_made': 'tower', 'tower:type': ['communication', 'telecommunications'] }, - { 'man_made': 'communications_tower' }, - { 'communication:mobile_phone': 'yes' } - ], - label: 'Telecom Tower' - }, - tower: { - osmTags: [ - { 'man_made': 'tower', 'tower:type': ['communication', 'telecommunications'] }, - { 'man_made': 'communications_tower' }, - { 'communication:mobile_phone': 'yes' } - ], - label: 'Telecom Tower' - }, - data_center: { - osmTags: { 'building': 'data_centre' }, - label: 'Data Center' - }, - datacenter: { - osmTags: { 'building': 'data_centre' }, - label: 'Data Center' - }, - power_plant: { - osmTags: { 'power': 'plant' }, - label: 'Power Plant' - }, - powerplant: { - osmTags: { 'power': 'plant' }, - label: 'Power Plant' - }, - substation: { - osmTags: { 'power': 'substation' }, - label: 'Substation' - }, - port: { - osmTags: { 'landuse': 'port' }, - label: 'Port' - }, - harbour: { - osmTags: { 'harbour': 'yes' }, - label: 'Harbour' - }, - warehouse: { - osmTags: { 'building': 'warehouse' }, - label: 'Warehouse' - }, - building: { - osmTags: { 'building': 'yes' }, - label: 'Building' - }, - airport: { - osmTags: { 'aeroway': 'aerodrome' }, - label: 'Airport' - }, - helipad: { - osmTags: { 'aeroway': 'helipad' }, - label: 'Helipad' - }, - railyard: { - osmTags: { 'landuse': 'railway' }, - label: 'Rail Yard' - }, - rail_yard: { - osmTags: { 'landuse': 'railway' }, - label: 'Rail Yard' - }, - refinery: { - osmTags: { 'man_made': 'petroleum_well' }, - label: 'Refinery' - }, - pipeline: { - osmTags: { 'man_made': 'pipeline' }, - label: 'Pipeline' - }, - solar: { - osmTags: { 'power': 'generator', 'generator:source': 'solar' }, - label: 'Solar Farm' - }, - wind: { - osmTags: { 'power': 'generator', 'generator:source': 'wind' }, - label: 'Wind Farm' - }, - nuclear: { - osmTags: { 'power': 'generator', 'generator:source': 'nuclear' }, - label: 'Nuclear Plant' - }, - dam: { - osmTags: { 'waterway': 'dam' }, - label: 'Dam' - }, - military: { - osmTags: { 'landuse': 'military' }, - label: 'Military Installation' - }, - prison: { - osmTags: { 'amenity': 'prison' }, - label: 'Prison' - }, - hospital: { - osmTags: { 'amenity': 'hospital' }, - label: 'Hospital' - }, - embassy: { - osmTags: { 'amenity': 'embassy' }, - label: 'Embassy' - }, - factory: { - osmTags: { 'building': 'industrial' }, - label: 'Factory' - }, - industrial: { - osmTags: { 'landuse': 'industrial' }, - label: 'Industrial Zone' - }, - school: { - osmTags: { 'amenity': 'school' }, - label: 'School' - }, - university: { - osmTags: { 'amenity': 'university' }, - label: 'University' - }, - college: { - osmTags: { 'amenity': 'college' }, - label: 'College' - }, - stadium: { - osmTags: { 'leisure': 'stadium' }, - label: 'Stadium' - }, - fire_station: { - osmTags: { 'amenity': 'fire_station' }, - label: 'Fire Station' - }, - police: { - osmTags: { 'amenity': 'police' }, - label: 'Police Station' - }, - courthouse: { - osmTags: { 'amenity': 'courthouse' }, - label: 'Courthouse' - }, - bank: { - osmTags: { 'amenity': 'bank' }, - label: 'Bank' - }, - atm: { - osmTags: { 'amenity': 'atm' }, - label: 'ATM' - }, - fuel: { - osmTags: { 'amenity': 'fuel' }, - label: 'Fuel Station' - }, - gas_station: { - osmTags: { 'amenity': 'fuel' }, - label: 'Gas Station' - }, - petrol: { - osmTags: { 'amenity': 'fuel' }, - label: 'Petrol Station' - }, - charging_station: { - osmTags: { 'amenity': 'charging_station' }, - label: 'EV Charging Station' - }, - water_tower: { - osmTags: { 'man_made': 'water_tower' }, - label: 'Water Tower' - }, - water_treatment: { - osmTags: { 'man_made': 'water_works' }, - label: 'Water Treatment Plant' - }, - wastewater: { - osmTags: { 'man_made': 'wastewater_plant' }, - label: 'Wastewater Plant' - }, - sewage: { - osmTags: { 'man_made': 'wastewater_plant' }, - label: 'Sewage Plant' - }, - landfill: { - osmTags: { 'landuse': 'landfill' }, - label: 'Landfill' - }, - quarry: { - osmTags: { 'landuse': 'quarry' }, - label: 'Quarry' - }, - mine: { - osmTags: { 'landuse': 'quarry' }, - label: 'Mine' - }, - oil_well: { - osmTags: { 'man_made': 'petroleum_well' }, - label: 'Oil Well' - }, - gas_well: { - osmTags: { 'man_made': 'petroleum_well' }, - label: 'Gas Well' - }, - storage_tank: { - osmTags: { 'man_made': 'storage_tank' }, - label: 'Storage Tank' - }, - silo: { - osmTags: { 'man_made': 'silo' }, - label: 'Silo' - }, - chimney: { - osmTags: { 'man_made': 'chimney' }, - label: 'Chimney' - }, - cooling_tower: { - osmTags: { 'man_made': 'cooling_tower' }, - label: 'Cooling Tower' - }, - lighthouse: { - osmTags: { 'man_made': 'lighthouse' }, - label: 'Lighthouse' - }, - radar: { - osmTags: { 'man_made': 'radar' }, - label: 'Radar' - }, - surveillance_camera: { - osmTags: [ - { 'man_made': 'surveillance', 'surveillance:type': 'camera' }, - { 'man_made': 'surveillance', 'surveillance': 'outdoor' }, - { 'man_made': 'surveillance', 'surveillance': 'indoor' }, - { 'man_made': 'surveillance', 'surveillance': 'public' }, - { 'surveillance:type': 'camera' }, - { 'man_made': 'surveillance' } - ], - label: 'Surveillance Camera' - }, - cctv: { - osmTags: [ - { 'man_made': 'surveillance', 'surveillance:type': 'camera' }, - { 'man_made': 'surveillance', 'surveillance': 'outdoor' }, - { 'man_made': 'surveillance', 'surveillance': 'indoor' }, - { 'man_made': 'surveillance', 'surveillance': 'public' }, - { 'surveillance:type': 'camera' }, - { 'man_made': 'surveillance' } - ], - label: 'Surveillance Camera' - }, - antenna: { - osmTags: { 'man_made': 'antenna' }, - label: 'Antenna' - }, - mast: { - osmTags: { 'man_made': 'mast' }, - label: 'Mast' - }, - bridge: { - osmTags: { 'man_made': 'bridge' }, - label: 'Bridge' - }, - tunnel: { - osmTags: { 'tunnel': 'yes' }, - label: 'Tunnel' - }, - ferry_terminal: { - osmTags: { 'amenity': 'ferry_terminal' }, - label: 'Ferry Terminal' - }, - bus_station: { - osmTags: { 'amenity': 'bus_station' }, - label: 'Bus Station' - }, - train_station: { - osmTags: { 'railway': 'station' }, - label: 'Train Station' - }, - metro: { - osmTags: { 'railway': 'subway_entrance' }, - label: 'Metro Station' - }, - parking: { - osmTags: { 'amenity': 'parking' }, - label: 'Parking' - }, - cemetery: { - osmTags: { 'landuse': 'cemetery' }, - label: 'Cemetery' - }, - place_of_worship: { - osmTags: { 'amenity': 'place_of_worship' }, - label: 'Place of Worship' - }, - mosque: { - osmTags: { 'amenity': 'place_of_worship', 'religion': 'muslim' }, - label: 'Mosque' - }, - church: { - osmTags: { 'amenity': 'place_of_worship', 'religion': 'christian' }, - label: 'Church' - }, - temple: { - osmTags: { 'amenity': 'place_of_worship', 'religion': 'hindu' }, - label: 'Temple' - }, - synagogue: { - osmTags: { 'amenity': 'place_of_worship', 'religion': 'jewish' }, - label: 'Synagogue' - }, - library: { - osmTags: { 'amenity': 'library' }, - label: 'Library' - }, - museum: { - osmTags: { 'tourism': 'museum' }, - label: 'Museum' - }, - theatre: { - osmTags: { 'amenity': 'theatre' }, - label: 'Theatre' - }, - cinema: { - osmTags: { 'amenity': 'cinema' }, - label: 'Cinema' - }, - hotel: { - osmTags: { 'tourism': 'hotel' }, - label: 'Hotel' - }, - pharmacy: { - osmTags: { 'amenity': 'pharmacy' }, - label: 'Pharmacy' - }, - clinic: { - osmTags: { 'amenity': 'clinic' }, - label: 'Clinic' - }, - dentist: { - osmTags: { 'amenity': 'dentist' }, - label: 'Dentist' - }, - veterinary: { - osmTags: { 'amenity': 'veterinary' }, - label: 'Veterinary' - }, - post_office: { - osmTags: { 'amenity': 'post_office' }, - label: 'Post Office' - }, - recycling: { - osmTags: { 'amenity': 'recycling' }, - label: 'Recycling Center' - }, - observatory: { - osmTags: { 'man_made': 'observatory' }, - label: 'Observatory' - }, - crane: { - osmTags: { 'man_made': 'crane' }, - label: 'Crane' - }, - windmill: { - osmTags: { 'man_made': 'windmill' }, - label: 'Windmill' - }, - watermill: { - osmTags: { 'man_made': 'watermill' }, - label: 'Watermill' - }, - works: { - osmTags: { 'man_made': 'works' }, - label: 'Works' - }, - gasometer: { - osmTags: { 'man_made': 'gasometer' }, - label: 'Gasometer' - }, - bunker: { - osmTags: { 'military': 'bunker' }, - label: 'Bunker' - }, - barracks: { - osmTags: { 'military': 'barracks' }, - label: 'Barracks' - }, - airfield: { - osmTags: { 'military': 'airfield' }, - label: 'Military Airfield' - }, - naval_base: { - osmTags: { 'military': 'naval_base' }, - label: 'Naval Base' - }, - nuclear_site: { - osmTags: { 'military': 'nuclear_explosion_site' }, - label: 'Nuclear Site' - }, - range: { - osmTags: { 'military': 'range' }, - label: 'Military Range' - }, - checkpoint: { - osmTags: { 'military': 'checkpoint' }, - label: 'Checkpoint' - }, - border_control: { - osmTags: { 'barrier': 'border_control' }, - label: 'Border Control' - }, - // Additional infrastructure types - hydroelectric: { - osmTags: { 'power': 'generator', 'generator:source': 'hydro' }, - label: 'Hydroelectric Plant' - }, - geothermal: { - osmTags: { 'power': 'generator', 'generator:source': 'geothermal' }, - label: 'Geothermal Plant' - }, - biogas: { - osmTags: { 'power': 'generator', 'generator:source': 'biogas' }, - label: 'Biogas Plant' - }, - biomass: { - osmTags: { 'power': 'generator', 'generator:source': 'biomass' }, - label: 'Biomass Plant' - }, - tidal: { - osmTags: { 'power': 'generator', 'generator:source': 'tidal' }, - label: 'Tidal Power Plant' - }, - coal: { - osmTags: { 'power': 'generator', 'generator:source': 'coal' }, - label: 'Coal Power Plant' - }, - gas_power: { - osmTags: { 'power': 'generator', 'generator:source': 'gas' }, - label: 'Gas Power Plant' - }, - oil_power: { - osmTags: { 'power': 'generator', 'generator:source': 'oil' }, - label: 'Oil Power Plant' - }, - transformer: { - osmTags: { 'power': 'transformer' }, - label: 'Transformer' - }, - power_line: { - osmTags: { 'power': 'line' }, - label: 'Power Line' - }, - power_pole: { - osmTags: { 'power': 'pole' }, - label: 'Power Pole' - }, - // Transportation additions - runway: { - osmTags: { 'aeroway': 'runway' }, - label: 'Runway' - }, - taxiway: { - osmTags: { 'aeroway': 'taxiway' }, - label: 'Taxiway' - }, - terminal: { - osmTags: { 'aeroway': 'terminal' }, - label: 'Airport Terminal' - }, - hangar: { - osmTags: { 'aeroway': 'hangar' }, - label: 'Hangar' - }, - seaport: { - osmTags: { 'industrial': 'port' }, - label: 'Seaport' - }, - marina: { - osmTags: { 'leisure': 'marina' }, - label: 'Marina' - }, - shipyard: { - osmTags: { 'industrial': 'shipyard' }, - label: 'Shipyard' - }, - dock: { - osmTags: { 'waterway': 'dock' }, - label: 'Dock' - }, - tram_stop: { - osmTags: { 'railway': 'tram_stop' }, - label: 'Tram Stop' - }, - halt: { - osmTags: { 'railway': 'halt' }, - label: 'Railway Halt' - }, - level_crossing: { - osmTags: { 'railway': 'level_crossing' }, - label: 'Level Crossing' - }, - toll_booth: { - osmTags: { 'barrier': 'toll_booth' }, - label: 'Toll Booth' - }, - weigh_station: { - osmTags: { 'amenity': 'weighbridge' }, - label: 'Weigh Station' - }, - // Communication - cell_tower: { - osmTags: [ - { 'communication:mobile_phone': 'yes' }, - { 'tower:type': 'communications_tower' }, - { 'man_made': 'communications_tower' } - ], - label: 'Cell Tower' - }, - radio_tower: { - osmTags: { 'man_made': 'tower', 'tower:type': 'communication' }, - label: 'Radio Tower' - }, - broadcast_tower: { - osmTags: { 'man_made': 'tower', 'tower:type': 'broadcast' }, - label: 'Broadcast Tower' - }, - satellite_dish: { - osmTags: { 'man_made': 'satellite_dish' }, - label: 'Satellite Dish' - }, - telephone_exchange: { - osmTags: { 'telecom': 'exchange' }, - label: 'Telephone Exchange' - }, - // Emergency Services - ambulance_station: { - osmTags: { 'emergency': 'ambulance_station' }, - label: 'Ambulance Station' - }, - emergency_phone: { - osmTags: { 'emergency': 'phone' }, - label: 'Emergency Phone' - }, - fire_hydrant: { - osmTags: { 'emergency': 'fire_hydrant' }, - label: 'Fire Hydrant' - }, - lifeguard: { - osmTags: { 'emergency': 'lifeguard' }, - label: 'Lifeguard Station' - }, - rescue_station: { - osmTags: { 'emergency': 'rescue_station' }, - label: 'Rescue Station' - }, - coast_guard: { - osmTags: { 'emergency': 'coast_guard' }, - label: 'Coast Guard' - }, - // Government & Administrative - townhall: { - osmTags: { 'amenity': 'townhall' }, - label: 'Town Hall' - }, - government: { - osmTags: { 'office': 'government' }, - label: 'Government Office' - }, - customs: { - osmTags: { 'office': 'customs' }, - label: 'Customs Office' - }, - tax_office: { - osmTags: { 'office': 'tax' }, - label: 'Tax Office' - }, - // Education additions - kindergarten: { - osmTags: { 'amenity': 'kindergarten' }, - label: 'Kindergarten' - }, - driving_school: { - osmTags: { 'amenity': 'driving_school' }, - label: 'Driving School' - }, - research: { - osmTags: { 'amenity': 'research_institute' }, - label: 'Research Institute' - }, - // Industrial additions - brewery: { - osmTags: { 'craft': 'brewery' }, - label: 'Brewery' - }, - distillery: { - osmTags: { 'craft': 'distillery' }, - label: 'Distillery' - }, - sawmill: { - osmTags: { 'craft': 'sawmill' }, - label: 'Sawmill' - }, - slaughterhouse: { - osmTags: { 'industrial': 'slaughterhouse' }, - label: 'Slaughterhouse' - }, - scrap_yard: { - osmTags: { 'industrial': 'scrap_yard' }, - label: 'Scrap Yard' - }, - depot: { - osmTags: { 'industrial': 'depot' }, - label: 'Depot' - }, - recycling_plant: { - osmTags: { 'industrial': 'recycling' }, - label: 'Recycling Plant' - }, - // Leisure & Sports - sports_centre: { - osmTags: { 'leisure': 'sports_centre' }, - label: 'Sports Centre' - }, - swimming_pool: { - osmTags: { 'leisure': 'swimming_pool' }, - label: 'Swimming Pool' - }, - golf_course: { - osmTags: { 'leisure': 'golf_course' }, - label: 'Golf Course' - }, - racetrack: { - osmTags: { 'leisure': 'track' }, - label: 'Racetrack' - }, - ice_rink: { - osmTags: { 'leisure': 'ice_rink' }, - label: 'Ice Rink' - }, - // Tourism - campsite: { - osmTags: { 'tourism': 'camp_site' }, - label: 'Campsite' - }, - caravan_site: { - osmTags: { 'tourism': 'caravan_site' }, - label: 'Caravan Site' - }, - theme_park: { - osmTags: { 'tourism': 'theme_park' }, - label: 'Theme Park' - }, - zoo: { - osmTags: { 'tourism': 'zoo' }, - label: 'Zoo' - }, - aquarium: { - osmTags: { 'tourism': 'aquarium' }, - label: 'Aquarium' - }, - viewpoint: { - osmTags: { 'tourism': 'viewpoint' }, - label: 'Viewpoint' - }, - attraction: { - osmTags: { 'tourism': 'attraction' }, - label: 'Tourist Attraction' - }, - // Healthcare additions - nursing_home: { - osmTags: { 'amenity': 'nursing_home' }, - label: 'Nursing Home' - }, - hospice: { - osmTags: { 'amenity': 'hospice' }, - label: 'Hospice' - }, - blood_bank: { - osmTags: { 'healthcare': 'blood_bank' }, - label: 'Blood Bank' - }, - // Agriculture - farm: { - osmTags: { 'landuse': 'farmland' }, - label: 'Farm' - }, - greenhouse: { - osmTags: { 'building': 'greenhouse' }, - label: 'Greenhouse' - }, - orchard: { - osmTags: { 'landuse': 'orchard' }, - label: 'Orchard' - }, - vineyard: { - osmTags: { 'landuse': 'vineyard' }, - label: 'Vineyard' - }, - // Other notable structures - monument: { - osmTags: { 'historic': 'monument' }, - label: 'Monument' - }, - memorial: { - osmTags: { 'historic': 'memorial' }, - label: 'Memorial' - }, - castle: { - osmTags: { 'historic': 'castle' }, - label: 'Castle' - }, - fort: { - osmTags: { 'historic': 'fort' }, - label: 'Fort' - }, - ruins: { - osmTags: { 'historic': 'ruins' }, - label: 'Ruins' - }, - archaeological_site: { - osmTags: { 'historic': 'archaeological_site' }, - label: 'Archaeological Site' - }, - clock_tower: { - osmTags: { 'man_made': 'tower', 'tower:type': 'clock' }, - label: 'Clock Tower' - }, - bell_tower: { - osmTags: { 'man_made': 'tower', 'tower:type': 'bell_tower' }, - label: 'Bell Tower' - }, - water_well: { - osmTags: { 'man_made': 'water_well' }, - label: 'Water Well' - }, - reservoir: { - osmTags: { 'landuse': 'reservoir' }, - label: 'Reservoir' - }, - pumping_station: { - osmTags: { 'man_made': 'pumping_station' }, - label: 'Pumping Station' - }, - sewage_plant: { - osmTags: { 'man_made': 'wastewater_plant' }, - label: 'Sewage Plant' - }, - // Transportation - Highway facilities - rest_area: { - osmTags: { 'highway': 'rest_area' }, - label: 'Rest Area' - }, - service_area: { - osmTags: { 'highway': 'services' }, - label: 'Service Area' - }, - // Aviation - Control - atc_tower: { - osmTags: { 'aeroway': 'control_tower' }, - label: 'ATC Tower' - }, - // Public Utilities - bicycle_parking: { - osmTags: { 'amenity': 'bicycle_parking' }, - label: 'Bicycle Parking' - }, - drinking_water: { - osmTags: { 'amenity': 'drinking_water' }, - label: 'Drinking Water' - }, - public_toilet: { - osmTags: { 'amenity': 'toilets' }, - label: 'Public Toilet' - }, - bench: { - osmTags: { 'amenity': 'bench' }, - label: 'Bench' - }, - waste_basket: { - osmTags: { 'amenity': 'waste_basket' }, - label: 'Waste Basket' - }, - // Maritime additions - pier: { - osmTags: { 'man_made': 'pier' }, - label: 'Pier' - }, - jetty: { - osmTags: { 'man_made': 'jetty' }, - label: 'Jetty' - }, - slipway: { - osmTags: { 'leisure': 'slipway' }, - label: 'Slipway' - }, - boat_lift: { - osmTags: { 'waterway': 'boat_lift' }, - label: 'Boat Lift' - }, - mooring: { - osmTags: { 'waterway': 'mooring' }, - label: 'Mooring' - }, - // Cable Transport - aerialway: { - osmTags: { 'aerialway': 'cable_car' }, - label: 'Cable Car' - }, - gondola: { - osmTags: { 'aerialway': 'gondola' }, - label: 'Gondola' - }, - funicular: { - osmTags: { 'aerialway': 'funicular' }, - label: 'Funicular' - }, - chairlift: { - osmTags: { 'aerialway': 'chair_lift' }, - label: 'Chairlift' - }, - // Energy Storage & Distribution - battery_storage: { - osmTags: { 'power': 'generator', 'generator:source': 'battery' }, - label: 'Battery Storage' - }, - converter: { - osmTags: { 'power': 'converter' }, - label: 'Power Converter' - }, - switch: { - osmTags: { 'power': 'switch' }, - label: 'Power Switch' - }, - // Street Infrastructure - street_lamp: { - osmTags: { 'highway': 'street_lamp' }, - label: 'Street Lamp' - }, - traffic_signals: { - osmTags: { 'highway': 'traffic_signals' }, - label: 'Traffic Signals' - }, - // Emergency Infrastructure - siren: { - osmTags: { 'emergency': 'siren' }, - label: 'Emergency Siren' - }, - defibrillator: { - osmTags: { 'emergency': 'defibrillator' }, - label: 'Defibrillator' - }, - assembly_point: { - osmTags: { 'emergency': 'assembly_point' }, - label: 'Assembly Point' - }, - life_ring: { - osmTags: { 'emergency': 'life_ring' }, - label: 'Life Ring' - }, - // Tourism Infrastructure - information: { - osmTags: { 'tourism': 'information' }, - label: 'Tourist Information' - }, - picnic_site: { - osmTags: { 'tourism': 'picnic_site' }, - label: 'Picnic Site' - }, - // Commercial - supermarket: { - osmTags: { 'shop': 'supermarket' }, - label: 'Supermarket' - }, - mall: { - osmTags: { 'shop': 'mall' }, - label: 'Shopping Mall' - }, - marketplace: { - osmTags: { 'amenity': 'marketplace' }, - label: 'Marketplace' - }, - // Shared Mobility - bicycle_rental: { - osmTags: { 'amenity': 'bicycle_rental' }, - label: 'Bike Sharing' - }, - car_sharing: { - osmTags: { 'amenity': 'car_sharing' }, - label: 'Car Sharing' - }, - // Science & Research - planetarium: { - osmTags: { 'amenity': 'planetarium' }, - label: 'Planetarium' - }, - laboratory: { - osmTags: { 'man_made': 'laboratory' }, - label: 'Laboratory' - }, - // Construction - construction_site: { - osmTags: { 'landuse': 'construction' }, - label: 'Construction Site' - }, - // Food & Beverage Production - winery: { - osmTags: { 'craft': 'winery' }, - label: 'Winery' - }, - bakery: { - osmTags: { 'craft': 'bakery' }, - label: 'Bakery' - }, - dairy: { - osmTags: { 'craft': 'dairy' }, - label: 'Dairy' - }, - // Additional Transport - taxi_stand: { - osmTags: { 'amenity': 'taxi' }, - label: 'Taxi Stand' - }, - bicycle_repair: { - osmTags: { 'amenity': 'bicycle_repair_station' }, - label: 'Bicycle Repair Station' - }, - car_wash: { - osmTags: { 'amenity': 'car_wash' }, - label: 'Car Wash' - }, - // Postal & Communication - post_box: { - osmTags: { 'amenity': 'post_box' }, - label: 'Post Box' - }, - telephone: { - osmTags: { 'amenity': 'telephone' }, - label: 'Public Telephone' - }, - // Community - community_centre: { - osmTags: { 'amenity': 'community_centre' }, - label: 'Community Centre' - }, - social_facility: { - osmTags: { 'amenity': 'social_facility' }, - label: 'Social Facility' - }, - shelter: { - osmTags: { 'amenity': 'shelter' }, - label: 'Shelter' - }, - // Food Services - restaurant: { - osmTags: { 'amenity': 'restaurant' }, - label: 'Restaurant' - }, - cafe: { - osmTags: { 'amenity': 'cafe' }, - label: 'Cafe' - }, - fast_food: { - osmTags: { 'amenity': 'fast_food' }, - label: 'Fast Food' - }, - // Recreation - playground: { - osmTags: { 'leisure': 'playground' }, - label: 'Playground' - }, - park: { - osmTags: { 'leisure': 'park' }, - label: 'Park' - }, - pitch: { - osmTags: { 'leisure': 'pitch' }, - label: 'Sports Pitch' - }, - // Water Features - fountain: { - osmTags: { 'amenity': 'fountain' }, - label: 'Fountain' - }, - waterfall: { - osmTags: { 'waterway': 'waterfall' }, - label: 'Waterfall' - }, - hot_spring: { - osmTags: { 'natural': 'hot_spring' }, - label: 'Hot Spring' - }, - // Safety & Monitoring - monitoring_station: { - osmTags: { 'man_made': 'monitoring_station' }, - label: 'Monitoring Station' - }, - weather_station: { - osmTags: { 'man_made': 'weather_station' }, - label: 'Weather Station' - } -}; -export const OPERATOR_ALIASES: Record = { - 'airtel': ['bharti airtel', 'airtel india', 'airtel telecom'], - 'jio': ['reliance jio', 'jio infocomm'], - 'vodafone': ['vodafone idea', 'vi', 'vodafone india'], - 'bsnl': ['bharat sanchar nigam'], - 'google': ['google llc', 'google inc'], - 'amazon': ['amazon web services', 'aws'], - 'microsoft': ['microsoft azure', 'azure'], - 'meta': ['facebook', 'meta platforms'], - 'apple': ['apple inc'], - 'at&t': ['att', 'at and t'], - 'verizon': ['verizon wireless'], - 't-mobile': ['tmobile', 't mobile'], - 'vodacom': ['vodacom group'], - 'mtn': ['mtn group'], - 'orange': ['orange telecom'], - 'telefonica': ['movistar'], - 'china mobile': ['cmcc'], - 'china unicom': [], - 'china telecom': [], - 'ntpc': ['national thermal power corporation'], - 'adani': ['adani power', 'adani green'], - 'tata': ['tata power', 'tata steel'], - 'reliance': ['reliance industries', 'ril'] -}; +export { ASSET_TYPE_MAP, OPERATOR_ALIASES, type AssetTypeConfig } from './asset-types'; diff --git a/package-lock.json b/package-lock.json index ebc828c..b80c0f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,8 @@ "eslint": "^9", "eslint-config-next": "16.1.4", "tailwindcss": "^4", - "typescript": "^5" + "typescript": "^5", + "vitest": "^4.1.8" } }, "node_modules/@alloc/quick-lru": { @@ -78,7 +79,6 @@ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -289,21 +289,21 @@ } }, "node_modules/@emnapi/core": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", - "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.1.0", + "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", "license": "MIT", "optional": true, "dependencies": { @@ -311,9 +311,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "dev": true, "license": "MIT", "optional": true, @@ -1238,6 +1238,16 @@ "node": ">=12.4.0" } }, + "node_modules/@oxc-project/types": { + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", @@ -1432,6 +1442,307 @@ "react-dom": "^19.0.0" } }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", + "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", + "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", + "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", + "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", + "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", + "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", + "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", + "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1439,6 +1750,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, "node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", @@ -1730,6 +2048,24 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1791,7 +2127,6 @@ "integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1802,7 +2137,6 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -1852,7 +2186,6 @@ "integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.53.1", "@typescript-eslint/types": "8.53.1", @@ -2384,29 +2717,141 @@ } } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "node_modules/@vitest/expect": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz", + "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==", "dev": true, "license": "MIT", - "peer": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, - "engines": { - "node": ">=0.4.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@vitest/mocker": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz", + "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==", "dev": true, "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.8", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz", + "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz", + "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.8", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz", + "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "@vitest/utils": "4.1.8", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz", + "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz", + "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.8", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, "node_modules/ajv": { "version": "6.12.6", @@ -2618,6 +3063,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -2677,7 +3132,6 @@ "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/types": "^7.26.0" } @@ -2742,7 +3196,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2837,6 +3290,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3242,6 +3705,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -3331,7 +3801,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3517,7 +3986,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -3741,6 +4209,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -3751,6 +4229,16 @@ "node": ">=0.10.0" } }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3892,6 +4380,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4823,8 +5326,7 @@ "version": "1.9.4", "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", - "license": "BSD-2-Clause", - "peer": true + "license": "BSD-2-Clause" }, "node_modules/leaflet.markercluster": { "version": "1.5.3", @@ -5231,9 +5733,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { "type": "github", @@ -5276,7 +5778,6 @@ "resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz", "integrity": "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==", "license": "MIT", - "peer": true, "dependencies": { "@next/env": "16.1.6", "@swc/helpers": "0.5.15", @@ -5483,6 +5984,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.2.tgz", + "integrity": "sha512-AWGB9WFcRXOQs48Z/udjI5ZcZMHXwX8XPByNpOydgcGsDLIzjGizhoMWJyKAWze7AVW/2W1i+/gPX4YtKe5cyg==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -5591,6 +6106,13 @@ "dev": true, "license": "MIT" }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -5621,9 +6143,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -5641,7 +6163,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5707,7 +6229,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -5717,7 +6238,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -5842,6 +6362,40 @@ "node": ">=0.10.0" } }, + "node_modules/rolldown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", + "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6143,6 +6697,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6159,6 +6720,20 @@ "dev": true, "license": "MIT" }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", @@ -6389,15 +6964,32 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -6425,12 +7017,11 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6438,6 +7029,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6593,7 +7194,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6728,6 +7328,473 @@ "punycode": "^2.1.0" } }, + "node_modules/vite": { + "version": "8.0.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", + "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/vite/node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz", + "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.8", + "@vitest/mocker": "4.1.8", + "@vitest/pretty-format": "4.1.8", + "@vitest/runner": "4.1.8", + "@vitest/snapshot": "4.1.8", + "@vitest/spy": "4.1.8", + "@vitest/utils": "4.1.8", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.8", + "@vitest/browser-preview": "4.1.8", + "@vitest/browser-webdriverio": "4.1.8", + "@vitest/coverage-istanbul": "4.1.8", + "@vitest/coverage-v8": "4.1.8", + "@vitest/ui": "4.1.8", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6833,6 +7900,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -6869,7 +7953,6 @@ "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "dev": true, "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index a91ad99..3a272a8 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "eslint" + "lint": "eslint", + "test": "vitest run", + "test:watch": "vitest" }, "dependencies": { "@radix-ui/react-scroll-area": "^1.2.10", @@ -32,6 +34,7 @@ "eslint": "^9", "eslint-config-next": "16.1.4", "tailwindcss": "^4", - "typescript": "^5" + "typescript": "^5", + "vitest": "^4.1.8" } } diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..ba81bd0 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from 'vitest/config'; +import path from 'node:path'; + +export default defineConfig({ + resolve: { + alias: { + '@': path.resolve(__dirname, '.'), + }, + }, + test: { + environment: 'node', + include: ['**/*.test.ts'], + }, +});