lt-public-transport-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +283 -0
- package/assets/architecture.png +0 -0
- package/dist/config.d.ts +221 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +200 -0
- package/dist/config.js.map +1 -0
- package/dist/enrichment/index.d.ts +6 -0
- package/dist/enrichment/index.d.ts.map +1 -0
- package/dist/enrichment/index.js +6 -0
- package/dist/enrichment/index.js.map +1 -0
- package/dist/enrichment/route-matcher.d.ts +64 -0
- package/dist/enrichment/route-matcher.d.ts.map +1 -0
- package/dist/enrichment/route-matcher.js +121 -0
- package/dist/enrichment/route-matcher.js.map +1 -0
- package/dist/errors.d.ts +70 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +104 -0
- package/dist/errors.js.map +1 -0
- package/dist/gtfs/index.d.ts +7 -0
- package/dist/gtfs/index.d.ts.map +1 -0
- package/dist/gtfs/index.js +7 -0
- package/dist/gtfs/index.js.map +1 -0
- package/dist/gtfs/parser.d.ts +39 -0
- package/dist/gtfs/parser.d.ts.map +1 -0
- package/dist/gtfs/parser.js +189 -0
- package/dist/gtfs/parser.js.map +1 -0
- package/dist/gtfs/sync.d.ts +72 -0
- package/dist/gtfs/sync.d.ts.map +1 -0
- package/dist/gtfs/sync.js +271 -0
- package/dist/gtfs/sync.js.map +1 -0
- package/dist/index.d.ts +203 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +342 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/gps-full.d.ts +39 -0
- package/dist/parsers/gps-full.d.ts.map +1 -0
- package/dist/parsers/gps-full.js +212 -0
- package/dist/parsers/gps-full.js.map +1 -0
- package/dist/parsers/gps-lite.d.ts +60 -0
- package/dist/parsers/gps-lite.d.ts.map +1 -0
- package/dist/parsers/gps-lite.js +141 -0
- package/dist/parsers/gps-lite.js.map +1 -0
- package/dist/parsers/index.d.ts +7 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +7 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/schemas.d.ts +129 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +200 -0
- package/dist/schemas.js.map +1 -0
- package/dist/scripts/test-city-specific.d.ts +2 -0
- package/dist/scripts/test-city-specific.d.ts.map +1 -0
- package/dist/scripts/test-city-specific.js +264 -0
- package/dist/scripts/test-city-specific.js.map +1 -0
- package/dist/scripts/test-config-options.d.ts +2 -0
- package/dist/scripts/test-config-options.d.ts.map +1 -0
- package/dist/scripts/test-config-options.js +166 -0
- package/dist/scripts/test-config-options.js.map +1 -0
- package/dist/scripts/test-data-quality.d.ts +2 -0
- package/dist/scripts/test-data-quality.d.ts.map +1 -0
- package/dist/scripts/test-data-quality.js +204 -0
- package/dist/scripts/test-data-quality.js.map +1 -0
- package/dist/scripts/test-error-handling.d.ts +2 -0
- package/dist/scripts/test-error-handling.d.ts.map +1 -0
- package/dist/scripts/test-error-handling.js +146 -0
- package/dist/scripts/test-error-handling.js.map +1 -0
- package/dist/scripts/test-live.d.ts +2 -0
- package/dist/scripts/test-live.d.ts.map +1 -0
- package/dist/scripts/test-live.js +121 -0
- package/dist/scripts/test-live.js.map +1 -0
- package/dist/types.d.ts +120 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +25 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/coordinates.d.ts +68 -0
- package/dist/utils/coordinates.d.ts.map +1 -0
- package/dist/utils/coordinates.js +98 -0
- package/dist/utils/coordinates.js.map +1 -0
- package/dist/utils/encoding.d.ts +47 -0
- package/dist/utils/encoding.d.ts.map +1 -0
- package/dist/utils/encoding.js +153 -0
- package/dist/utils/encoding.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/time.d.ts +50 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +94 -0
- package/dist/utils/time.js.map +1 -0
- package/package.json +84 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* City configuration matrix for Lithuanian Public Transport SDK
|
|
3
|
+
* @module config
|
|
4
|
+
*/
|
|
5
|
+
// =============================================================================
|
|
6
|
+
// City Configuration Matrix
|
|
7
|
+
// =============================================================================
|
|
8
|
+
/**
|
|
9
|
+
* Base URL for stops.lt infrastructure.
|
|
10
|
+
*/
|
|
11
|
+
const BASE_URL = 'https://www.stops.lt';
|
|
12
|
+
/**
|
|
13
|
+
* Helper to build GPS full URL.
|
|
14
|
+
*/
|
|
15
|
+
function gpsFullUrl(city) {
|
|
16
|
+
return `${BASE_URL}/${city}/gps_full.txt`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Helper to build GPS lite URL.
|
|
20
|
+
*/
|
|
21
|
+
function gpsLiteUrl(city) {
|
|
22
|
+
return `${BASE_URL}/${city}/gps.txt`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Helper to build GTFS URL.
|
|
26
|
+
* Note: URL pattern uses double city name: /city/city/gtfs.zip
|
|
27
|
+
*/
|
|
28
|
+
function gtfsUrl(city) {
|
|
29
|
+
return `${BASE_URL}/${city}/${city}/gtfs.zip`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* City configuration matrix with all supported cities.
|
|
33
|
+
*
|
|
34
|
+
* Data Quality Tiers:
|
|
35
|
+
* - Gold: Full GPS streams with 12-18 columns including destination, delay, equipment
|
|
36
|
+
* - Silver: Lite GPS streams with 8-9 columns, requires GTFS enrichment for destinations
|
|
37
|
+
* - Bronze: GTFS only, no real-time GPS data available
|
|
38
|
+
*
|
|
39
|
+
* Column Counts (empirically verified 2026-01-05):
|
|
40
|
+
* - Vilnius: 18 columns (MatavimoLaikas, KryptiesTipas, ReisoIdGTFS)
|
|
41
|
+
* - Kaunas: 14 columns (Grafikas, SekanciosStotelesNum, AtvykimoLaikasSekundemis - NO MatavimoLaikas)
|
|
42
|
+
* - Klaipėda: 12 columns (minimal format)
|
|
43
|
+
* - Alytus: 13 columns
|
|
44
|
+
* - Druskininkai: 13 columns
|
|
45
|
+
* - Panevėžys: 9 columns lite (no header)
|
|
46
|
+
* - Tauragė: 8 columns lite (no header, alphanumeric routes like S11)
|
|
47
|
+
*/
|
|
48
|
+
const CITY_CONFIGS_INTERNAL = {
|
|
49
|
+
vilnius: {
|
|
50
|
+
id: 'vilnius',
|
|
51
|
+
tier: 'gold',
|
|
52
|
+
gps: {
|
|
53
|
+
enabled: true,
|
|
54
|
+
format: 'full',
|
|
55
|
+
url: gpsFullUrl('vilnius'),
|
|
56
|
+
},
|
|
57
|
+
gtfs: {
|
|
58
|
+
enabled: true,
|
|
59
|
+
url: gtfsUrl('vilnius'),
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
kaunas: {
|
|
63
|
+
id: 'kaunas',
|
|
64
|
+
tier: 'gold',
|
|
65
|
+
gps: {
|
|
66
|
+
enabled: true,
|
|
67
|
+
format: 'full',
|
|
68
|
+
url: gpsFullUrl('kaunas'),
|
|
69
|
+
},
|
|
70
|
+
gtfs: {
|
|
71
|
+
enabled: true,
|
|
72
|
+
url: gtfsUrl('kaunas'),
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
klaipeda: {
|
|
76
|
+
id: 'klaipeda',
|
|
77
|
+
tier: 'gold',
|
|
78
|
+
gps: {
|
|
79
|
+
enabled: true,
|
|
80
|
+
format: 'full',
|
|
81
|
+
url: gpsFullUrl('klaipeda'),
|
|
82
|
+
},
|
|
83
|
+
gtfs: {
|
|
84
|
+
enabled: true,
|
|
85
|
+
url: gtfsUrl('klaipeda'),
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
alytus: {
|
|
89
|
+
id: 'alytus',
|
|
90
|
+
tier: 'gold',
|
|
91
|
+
gps: {
|
|
92
|
+
enabled: true,
|
|
93
|
+
format: 'full',
|
|
94
|
+
url: gpsFullUrl('alytus'),
|
|
95
|
+
},
|
|
96
|
+
gtfs: {
|
|
97
|
+
enabled: true,
|
|
98
|
+
url: gtfsUrl('alytus'),
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
druskininkai: {
|
|
102
|
+
id: 'druskininkai',
|
|
103
|
+
tier: 'gold',
|
|
104
|
+
gps: {
|
|
105
|
+
enabled: true,
|
|
106
|
+
format: 'full',
|
|
107
|
+
url: gpsFullUrl('druskininkai'),
|
|
108
|
+
},
|
|
109
|
+
gtfs: {
|
|
110
|
+
enabled: true,
|
|
111
|
+
url: gtfsUrl('druskininkai'),
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
panevezys: {
|
|
115
|
+
id: 'panevezys',
|
|
116
|
+
tier: 'silver',
|
|
117
|
+
gps: {
|
|
118
|
+
enabled: true,
|
|
119
|
+
format: 'lite',
|
|
120
|
+
url: gpsLiteUrl('panevezys'),
|
|
121
|
+
},
|
|
122
|
+
gtfs: {
|
|
123
|
+
enabled: true,
|
|
124
|
+
url: gtfsUrl('panevezys'),
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
taurage: {
|
|
128
|
+
id: 'taurage',
|
|
129
|
+
tier: 'silver',
|
|
130
|
+
gps: {
|
|
131
|
+
enabled: true,
|
|
132
|
+
format: 'lite',
|
|
133
|
+
url: gpsLiteUrl('taurage'),
|
|
134
|
+
},
|
|
135
|
+
gtfs: {
|
|
136
|
+
enabled: true,
|
|
137
|
+
url: gtfsUrl('taurage'),
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
siauliai: {
|
|
141
|
+
id: 'siauliai',
|
|
142
|
+
tier: 'bronze',
|
|
143
|
+
gps: {
|
|
144
|
+
enabled: false,
|
|
145
|
+
format: null,
|
|
146
|
+
url: null,
|
|
147
|
+
},
|
|
148
|
+
gtfs: {
|
|
149
|
+
enabled: true,
|
|
150
|
+
url: gtfsUrl('siauliai'),
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
utena: {
|
|
154
|
+
id: 'utena',
|
|
155
|
+
tier: 'bronze',
|
|
156
|
+
gps: {
|
|
157
|
+
enabled: false,
|
|
158
|
+
format: null,
|
|
159
|
+
url: null,
|
|
160
|
+
},
|
|
161
|
+
gtfs: {
|
|
162
|
+
enabled: true,
|
|
163
|
+
url: gtfsUrl('utena'),
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* City configuration matrix with all supported cities.
|
|
169
|
+
*/
|
|
170
|
+
export const CITY_CONFIGS = CITY_CONFIGS_INTERNAL;
|
|
171
|
+
/**
|
|
172
|
+
* List of all supported city IDs.
|
|
173
|
+
*/
|
|
174
|
+
export const ALL_CITY_IDS = Object.keys(CITY_CONFIGS);
|
|
175
|
+
/**
|
|
176
|
+
* Get configuration for a specific city.
|
|
177
|
+
* @throws Error if city ID is invalid
|
|
178
|
+
*/
|
|
179
|
+
export function getCityConfig(city) {
|
|
180
|
+
return CITY_CONFIGS[city];
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get all cities of a specific tier.
|
|
184
|
+
*/
|
|
185
|
+
export function getCitiesByTier(tier) {
|
|
186
|
+
return ALL_CITY_IDS.filter(city => CITY_CONFIGS[city].tier === tier);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Check if a city has GPS data available.
|
|
190
|
+
*/
|
|
191
|
+
export function hasGpsData(city) {
|
|
192
|
+
return CITY_CONFIGS[city].gps.enabled;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Check if a city has GTFS data available.
|
|
196
|
+
*/
|
|
197
|
+
export function hasGtfsData(city) {
|
|
198
|
+
return CITY_CONFIGS[city].gtfs.enabled;
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/enrichment/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/enrichment/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,UAAU,EACV,aAAa,EACb,cAAc,GAEf,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route matching and data enrichment for silver-tier cities
|
|
3
|
+
* @module enrichment/route-matcher
|
|
4
|
+
*
|
|
5
|
+
* Silver-tier cities (Panevėžys, Tauragė) provide lite GPS streams
|
|
6
|
+
* that lack destination and route long name. This module enriches
|
|
7
|
+
* vehicles with data from GTFS routes.
|
|
8
|
+
*/
|
|
9
|
+
import type { Route, Vehicle } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Result of route enrichment lookup.
|
|
12
|
+
*/
|
|
13
|
+
export interface EnrichmentResult {
|
|
14
|
+
/** Destination/terminus name from route long name */
|
|
15
|
+
destination: string | null;
|
|
16
|
+
/** Full route name */
|
|
17
|
+
routeLongName: string | null;
|
|
18
|
+
/** Whether a match was found */
|
|
19
|
+
matched: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Route cache with O(1) case-insensitive lookup.
|
|
23
|
+
* The normalized map uses uppercase keys for fast matching.
|
|
24
|
+
*/
|
|
25
|
+
export interface RouteCache {
|
|
26
|
+
/** Primary map: exact short name -> Route */
|
|
27
|
+
readonly routes: Map<string, Route>;
|
|
28
|
+
/** Normalized map: uppercase short name -> Route (for O(1) case-insensitive lookup) */
|
|
29
|
+
readonly normalizedRoutes: Map<string, Route>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Build a RouteCache from a routes map.
|
|
33
|
+
* Pre-builds the normalized (uppercase) lookup map.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildRouteCache(routes: Map<string, Route>): RouteCache;
|
|
36
|
+
/**
|
|
37
|
+
* Match a GPS route to GTFS route data.
|
|
38
|
+
*
|
|
39
|
+
* Matching strategy:
|
|
40
|
+
* 1. Exact match on route short name (case-sensitive) - O(1)
|
|
41
|
+
* 2. Case-insensitive match via normalized map - O(1)
|
|
42
|
+
*
|
|
43
|
+
* @param gpsRoute - Route identifier from GPS stream
|
|
44
|
+
* @param cache - RouteCache with pre-built normalized lookup
|
|
45
|
+
* @returns Enrichment result with destination and route name
|
|
46
|
+
*/
|
|
47
|
+
export declare function matchRoute(gpsRoute: string, cache: RouteCache): EnrichmentResult;
|
|
48
|
+
/**
|
|
49
|
+
* Enrich a vehicle with GTFS route data.
|
|
50
|
+
*
|
|
51
|
+
* @param vehicle - Vehicle to enrich
|
|
52
|
+
* @param cache - RouteCache with pre-built normalized lookup
|
|
53
|
+
* @returns New vehicle with enriched data (or original if no match)
|
|
54
|
+
*/
|
|
55
|
+
export declare function enrichVehicle(vehicle: Vehicle, cache: RouteCache): Vehicle;
|
|
56
|
+
/**
|
|
57
|
+
* Enrich an array of vehicles with GTFS route data.
|
|
58
|
+
*
|
|
59
|
+
* @param vehicles - Vehicles to enrich
|
|
60
|
+
* @param cache - RouteCache with pre-built normalized lookup
|
|
61
|
+
* @returns New array with enriched vehicles
|
|
62
|
+
*/
|
|
63
|
+
export declare function enrichVehicles(vehicles: Vehicle[], cache: RouteCache): Vehicle[];
|
|
64
|
+
//# sourceMappingURL=route-matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-matcher.d.ts","sourceRoot":"","sources":["../../src/enrichment/route-matcher.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAMlD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,sBAAsB;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAC;CAClB;AAMD;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACpC,uFAAuF;IACvF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC/C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,UAAU,CAQtE;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,UAAU,GAChB,gBAAgB,CAsBlB;AA6CD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,UAAU,GAChB,OAAO,CAiBT;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,UAAU,GAChB,OAAO,EAAE,CAEX"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route matching and data enrichment for silver-tier cities
|
|
3
|
+
* @module enrichment/route-matcher
|
|
4
|
+
*
|
|
5
|
+
* Silver-tier cities (Panevėžys, Tauragė) provide lite GPS streams
|
|
6
|
+
* that lack destination and route long name. This module enriches
|
|
7
|
+
* vehicles with data from GTFS routes.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Build a RouteCache from a routes map.
|
|
11
|
+
* Pre-builds the normalized (uppercase) lookup map.
|
|
12
|
+
*/
|
|
13
|
+
export function buildRouteCache(routes) {
|
|
14
|
+
const normalizedRoutes = new Map();
|
|
15
|
+
for (const [key, route] of routes) {
|
|
16
|
+
normalizedRoutes.set(key.toUpperCase(), route);
|
|
17
|
+
}
|
|
18
|
+
return { routes, normalizedRoutes };
|
|
19
|
+
}
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Route Matcher
|
|
22
|
+
// =============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* Match a GPS route to GTFS route data.
|
|
25
|
+
*
|
|
26
|
+
* Matching strategy:
|
|
27
|
+
* 1. Exact match on route short name (case-sensitive) - O(1)
|
|
28
|
+
* 2. Case-insensitive match via normalized map - O(1)
|
|
29
|
+
*
|
|
30
|
+
* @param gpsRoute - Route identifier from GPS stream
|
|
31
|
+
* @param cache - RouteCache with pre-built normalized lookup
|
|
32
|
+
* @returns Enrichment result with destination and route name
|
|
33
|
+
*/
|
|
34
|
+
export function matchRoute(gpsRoute, cache) {
|
|
35
|
+
// Empty route - no enrichment possible
|
|
36
|
+
if (!gpsRoute || gpsRoute.trim() === '') {
|
|
37
|
+
return { destination: null, routeLongName: null, matched: false };
|
|
38
|
+
}
|
|
39
|
+
const normalized = gpsRoute.trim();
|
|
40
|
+
// 1. Try exact match - O(1)
|
|
41
|
+
const exactRoute = cache.routes.get(normalized);
|
|
42
|
+
if (exactRoute) {
|
|
43
|
+
return extractEnrichment(exactRoute);
|
|
44
|
+
}
|
|
45
|
+
// 2. Try case-insensitive match via normalized map - O(1)
|
|
46
|
+
const upperRoute = cache.normalizedRoutes.get(normalized.toUpperCase());
|
|
47
|
+
if (upperRoute) {
|
|
48
|
+
return extractEnrichment(upperRoute);
|
|
49
|
+
}
|
|
50
|
+
// 3. No match found
|
|
51
|
+
return { destination: null, routeLongName: null, matched: false };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Extract enrichment data from a matched route.
|
|
55
|
+
*/
|
|
56
|
+
function extractEnrichment(route) {
|
|
57
|
+
// Parse destination from long name
|
|
58
|
+
// Common patterns:
|
|
59
|
+
// - "Terminus A - Terminus B"
|
|
60
|
+
// - "Terminus A – Terminus B" (en-dash)
|
|
61
|
+
// - Just use the full long name if no separator
|
|
62
|
+
let destination = null;
|
|
63
|
+
if (route.longName !== '' && route.longName.length > 0) {
|
|
64
|
+
// Try to extract destination (usually after separator)
|
|
65
|
+
const separators = [' - ', ' – ', ' — ', ' / '];
|
|
66
|
+
for (const sep of separators) {
|
|
67
|
+
if (route.longName.includes(sep)) {
|
|
68
|
+
const parts = route.longName.split(sep);
|
|
69
|
+
const lastPart = parts[parts.length - 1];
|
|
70
|
+
// Use the last part as destination (typical direction)
|
|
71
|
+
if (lastPart !== undefined) {
|
|
72
|
+
destination = lastPart.trim();
|
|
73
|
+
}
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// If no separator found, use full long name
|
|
78
|
+
destination ??= route.longName;
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
destination,
|
|
82
|
+
routeLongName: route.longName !== '' ? route.longName : null,
|
|
83
|
+
matched: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// Vehicle Enrichment
|
|
88
|
+
// =============================================================================
|
|
89
|
+
/**
|
|
90
|
+
* Enrich a vehicle with GTFS route data.
|
|
91
|
+
*
|
|
92
|
+
* @param vehicle - Vehicle to enrich
|
|
93
|
+
* @param cache - RouteCache with pre-built normalized lookup
|
|
94
|
+
* @returns New vehicle with enriched data (or original if no match)
|
|
95
|
+
*/
|
|
96
|
+
export function enrichVehicle(vehicle, cache) {
|
|
97
|
+
// Skip if already has destination
|
|
98
|
+
if (vehicle.destination !== null && vehicle.destination !== '') {
|
|
99
|
+
return vehicle;
|
|
100
|
+
}
|
|
101
|
+
const enrichment = matchRoute(vehicle.route, cache);
|
|
102
|
+
if (!enrichment.matched) {
|
|
103
|
+
return vehicle;
|
|
104
|
+
}
|
|
105
|
+
// Return new vehicle with enriched data
|
|
106
|
+
return {
|
|
107
|
+
...vehicle,
|
|
108
|
+
destination: enrichment.destination,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Enrich an array of vehicles with GTFS route data.
|
|
113
|
+
*
|
|
114
|
+
* @param vehicles - Vehicles to enrich
|
|
115
|
+
* @param cache - RouteCache with pre-built normalized lookup
|
|
116
|
+
* @returns New array with enriched vehicles
|
|
117
|
+
*/
|
|
118
|
+
export function enrichVehicles(vehicles, cache) {
|
|
119
|
+
return vehicles.map(v => enrichVehicle(v, cache));
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=route-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-matcher.js","sourceRoot":"","sources":["../../src/enrichment/route-matcher.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for Lithuanian Public Transport SDK
|
|
3
|
+
* @module errors
|
|
4
|
+
*/
|
|
5
|
+
import type { CityId } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Base error class for transport SDK errors.
|
|
8
|
+
*/
|
|
9
|
+
export declare abstract class TransportError extends Error {
|
|
10
|
+
/** City associated with this error, if applicable */
|
|
11
|
+
abstract readonly city: CityId | null;
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Error thrown when a network request fails.
|
|
16
|
+
*/
|
|
17
|
+
export declare class TransportNetworkError extends TransportError {
|
|
18
|
+
readonly cityId: CityId;
|
|
19
|
+
readonly statusCode?: number | undefined;
|
|
20
|
+
readonly cause?: Error | undefined;
|
|
21
|
+
readonly city: CityId;
|
|
22
|
+
constructor(message: string, cityId: CityId, statusCode?: number | undefined, cause?: Error | undefined);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Error thrown when GPS data is requested for a bronze-tier city.
|
|
26
|
+
*/
|
|
27
|
+
export declare class GpsNotAvailableError extends TransportError {
|
|
28
|
+
readonly city: CityId;
|
|
29
|
+
constructor(cityId: CityId);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Error thrown when GTFS data is required but not yet synced.
|
|
33
|
+
*/
|
|
34
|
+
export declare class SyncRequiredError extends TransportError {
|
|
35
|
+
readonly city: CityId;
|
|
36
|
+
constructor(cityId: CityId);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Error thrown when GTFS sync fails.
|
|
40
|
+
*/
|
|
41
|
+
export declare class GtfsSyncError extends TransportError {
|
|
42
|
+
readonly cause?: Error | undefined;
|
|
43
|
+
readonly city: CityId;
|
|
44
|
+
constructor(cityId: CityId, message: string, cause?: Error | undefined);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Error thrown when parsing GPS or GTFS data fails.
|
|
48
|
+
*/
|
|
49
|
+
export declare class ParseError extends TransportError {
|
|
50
|
+
readonly line?: number | undefined;
|
|
51
|
+
readonly rawData?: string | undefined;
|
|
52
|
+
readonly city: CityId | null;
|
|
53
|
+
constructor(message: string, cityId?: CityId, line?: number | undefined, rawData?: string | undefined);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Error thrown when an invalid city ID is provided.
|
|
57
|
+
*/
|
|
58
|
+
export declare class InvalidCityError extends TransportError {
|
|
59
|
+
readonly city: null;
|
|
60
|
+
constructor(providedCity: string);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Type guard to check if an error is a TransportError.
|
|
64
|
+
*/
|
|
65
|
+
export declare function isTransportError(error: unknown): error is TransportError;
|
|
66
|
+
/**
|
|
67
|
+
* Type guard to check if an error is a network error.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isNetworkError(error: unknown): error is TransportNetworkError;
|
|
70
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;GAEG;AACH,8BAAsB,cAAe,SAAQ,KAAK;IAChD,qDAAqD;IACrD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;gBAE1B,OAAO,EAAE,MAAM;CAQ5B;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,cAAc;aAKrC,MAAM,EAAE,MAAM;aACd,UAAU,CAAC,EAAE,MAAM;aACnB,KAAK,CAAC,EAAE,KAAK;IAN/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAGpB,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,cAAc;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,MAAM,EAAE,MAAM;CAI3B;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,cAAc;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,MAAM,EAAE,MAAM;CAI3B;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,cAAc;aAM7B,KAAK,CAAC,EAAE,KAAK;IAL/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAGpB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,cAAc;aAM1B,IAAI,CAAC,EAAE,MAAM;aACb,OAAO,CAAC,EAAE,MAAM;IANlC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;gBAG3B,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,EACC,IAAI,CAAC,EAAE,MAAM,YAAA,EACb,OAAO,CAAC,EAAE,MAAM,YAAA;CAQnC;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IAClD,QAAQ,CAAC,IAAI,OAAQ;gBAET,YAAY,EAAE,MAAM;CAGjC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAExE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAE7E"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for Lithuanian Public Transport SDK
|
|
3
|
+
* @module errors
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Base error class for transport SDK errors.
|
|
7
|
+
*/
|
|
8
|
+
export class TransportError extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = this.constructor.name;
|
|
12
|
+
// Maintains proper stack trace for where error was thrown (V8 engines)
|
|
13
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
14
|
+
Error.captureStackTrace(this, this.constructor);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Error thrown when a network request fails.
|
|
20
|
+
*/
|
|
21
|
+
export class TransportNetworkError extends TransportError {
|
|
22
|
+
cityId;
|
|
23
|
+
statusCode;
|
|
24
|
+
cause;
|
|
25
|
+
city;
|
|
26
|
+
constructor(message, cityId, statusCode, cause) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.cityId = cityId;
|
|
29
|
+
this.statusCode = statusCode;
|
|
30
|
+
this.cause = cause;
|
|
31
|
+
this.city = cityId;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Error thrown when GPS data is requested for a bronze-tier city.
|
|
36
|
+
*/
|
|
37
|
+
export class GpsNotAvailableError extends TransportError {
|
|
38
|
+
city;
|
|
39
|
+
constructor(cityId) {
|
|
40
|
+
super(`GPS data is not available for ${cityId} (bronze tier city). Use GTFS static data instead.`);
|
|
41
|
+
this.city = cityId;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Error thrown when GTFS data is required but not yet synced.
|
|
46
|
+
*/
|
|
47
|
+
export class SyncRequiredError extends TransportError {
|
|
48
|
+
city;
|
|
49
|
+
constructor(cityId) {
|
|
50
|
+
super(`GTFS data for ${cityId} is not synced. Call sync('${cityId}') first.`);
|
|
51
|
+
this.city = cityId;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Error thrown when GTFS sync fails.
|
|
56
|
+
*/
|
|
57
|
+
export class GtfsSyncError extends TransportError {
|
|
58
|
+
cause;
|
|
59
|
+
city;
|
|
60
|
+
constructor(cityId, message, cause) {
|
|
61
|
+
super(`GTFS sync failed for ${cityId}: ${message}`);
|
|
62
|
+
this.cause = cause;
|
|
63
|
+
this.city = cityId;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Error thrown when parsing GPS or GTFS data fails.
|
|
68
|
+
*/
|
|
69
|
+
export class ParseError extends TransportError {
|
|
70
|
+
line;
|
|
71
|
+
rawData;
|
|
72
|
+
city;
|
|
73
|
+
constructor(message, cityId, line, rawData) {
|
|
74
|
+
const fullMessage = cityId !== undefined
|
|
75
|
+
? `Parse error for ${cityId}${line !== undefined ? ` at line ${String(line)}` : ''}: ${message}`
|
|
76
|
+
: `Parse error: ${message}`;
|
|
77
|
+
super(fullMessage);
|
|
78
|
+
this.line = line;
|
|
79
|
+
this.rawData = rawData;
|
|
80
|
+
this.city = cityId ?? null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Error thrown when an invalid city ID is provided.
|
|
85
|
+
*/
|
|
86
|
+
export class InvalidCityError extends TransportError {
|
|
87
|
+
city = null;
|
|
88
|
+
constructor(providedCity) {
|
|
89
|
+
super(`Invalid city ID: '${providedCity}'. See ALL_CITY_IDS for valid options.`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Type guard to check if an error is a TransportError.
|
|
94
|
+
*/
|
|
95
|
+
export function isTransportError(error) {
|
|
96
|
+
return error instanceof TransportError;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Type guard to check if an error is a network error.
|
|
100
|
+
*/
|
|
101
|
+
export function isNetworkError(error) {
|
|
102
|
+
return error instanceof TransportNetworkError;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,OAAgB,cAAe,SAAQ,KAAK;IAIhD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,uEAAuE;QACvE,IAAI,OAAO,KAAK,CAAC,iBAAiB,KAAK,UAAU,EAAE,CAAC;YAClD,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IAKrC;IACA;IACA;IANT,IAAI,CAAS;IAEtB,YACE,OAAe,EACC,MAAc,EACd,UAAmB,EACnB,KAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAJC,WAAM,GAAN,MAAM,CAAQ;QACd,eAAU,GAAV,UAAU,CAAS;QACnB,UAAK,GAAL,KAAK,CAAQ;QAG7B,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;IACrB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,oBAAqB,SAAQ,cAAc;IAC7C,IAAI,CAAS;IAEtB,YAAY,MAAc;QACxB,KAAK,CAAC,iCAAiC,MAAM,oDAAoD,CAAC,CAAC;QACnG,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;IACrB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,iBAAkB,SAAQ,cAAc;IAC1C,IAAI,CAAS;IAEtB,YAAY,MAAc;QACxB,KAAK,CAAC,iBAAiB,MAAM,8BAA8B,MAAM,WAAW,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;IACrB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,cAAc;IAM7B;IALT,IAAI,CAAS;IAEtB,YACE,MAAc,EACd,OAAe,EACC,KAAa;QAE7B,KAAK,CAAC,wBAAwB,MAAM,KAAK,OAAO,EAAE,CAAC,CAAC;QAFpC,UAAK,GAAL,KAAK,CAAQ;QAG7B,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC;IACrB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,UAAW,SAAQ,cAAc;IAM1B;IACA;IANT,IAAI,CAAgB;IAE7B,YACE,OAAe,EACf,MAAe,EACC,IAAa,EACb,OAAgB;QAEhC,MAAM,WAAW,GAAG,MAAM,KAAK,SAAS;YACtC,CAAC,CAAC,mBAAmB,MAAM,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,EAAE;YAChG,CAAC,CAAC,gBAAgB,OAAO,EAAE,CAAC;QAC9B,KAAK,CAAC,WAAW,CAAC,CAAC;QANH,SAAI,GAAJ,IAAI,CAAS;QACb,YAAO,GAAP,OAAO,CAAS;QAMhC,IAAI,CAAC,IAAI,GAAG,MAAM,IAAI,IAAI,CAAC;IAC7B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,gBAAiB,SAAQ,cAAc;IACzC,IAAI,GAAG,IAAI,CAAC;IAErB,YAAY,YAAoB;QAC9B,KAAK,CAAC,qBAAqB,YAAY,wCAAwC,CAAC,CAAC;IACnF,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,KAAK,YAAY,cAAc,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,KAAK,YAAY,qBAAqB,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GTFS module exports
|
|
3
|
+
* @module gtfs
|
|
4
|
+
*/
|
|
5
|
+
export { parseRoutesContent, parseStopsContent, } from './parser.js';
|
|
6
|
+
export { syncGtfs, loadGtfsCache, loadCachedRoutes, loadCachedStops, type SyncOptions, type GtfsCache, } from './sync.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gtfs/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,GACf,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gtfs/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,eAAe,GAGhB,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GTFS file parsers for routes.txt and stops.txt
|
|
3
|
+
* @module gtfs/parser
|
|
4
|
+
*/
|
|
5
|
+
import type { Route, Stop } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Parse routes.txt content into a Map keyed by route short name.
|
|
8
|
+
*
|
|
9
|
+
* GTFS routes.txt fields:
|
|
10
|
+
* - route_id: Unique identifier
|
|
11
|
+
* - agency_id: Agency reference
|
|
12
|
+
* - route_short_name: Short name (e.g., "4G", "N1")
|
|
13
|
+
* - route_long_name: Full name with endpoints
|
|
14
|
+
* - route_desc: Description
|
|
15
|
+
* - route_type: GTFS route type (3=bus, 800=trolleybus)
|
|
16
|
+
* - route_url: URL
|
|
17
|
+
* - route_color: Background color (hex)
|
|
18
|
+
* - route_text_color: Text color (hex)
|
|
19
|
+
*
|
|
20
|
+
* @param content - Raw routes.txt content
|
|
21
|
+
* @returns Map from route short name to Route object
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseRoutesContent(content: string): Map<string, Route>;
|
|
24
|
+
/**
|
|
25
|
+
* Parse stops.txt content into an array of Stop objects.
|
|
26
|
+
*
|
|
27
|
+
* GTFS stops.txt fields:
|
|
28
|
+
* - stop_id: Unique identifier
|
|
29
|
+
* - stop_code: Short code
|
|
30
|
+
* - stop_name: Human-readable name
|
|
31
|
+
* - stop_desc: Description
|
|
32
|
+
* - stop_lat: Latitude
|
|
33
|
+
* - stop_lon: Longitude
|
|
34
|
+
*
|
|
35
|
+
* @param content - Raw stops.txt content
|
|
36
|
+
* @returns Array of Stop objects
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseStopsContent(content: string): Stop[];
|
|
39
|
+
//# sourceMappingURL=parser.d.ts.map
|