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.
Files changed (92) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +283 -0
  3. package/assets/architecture.png +0 -0
  4. package/dist/config.d.ts +221 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +200 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/enrichment/index.d.ts +6 -0
  9. package/dist/enrichment/index.d.ts.map +1 -0
  10. package/dist/enrichment/index.js +6 -0
  11. package/dist/enrichment/index.js.map +1 -0
  12. package/dist/enrichment/route-matcher.d.ts +64 -0
  13. package/dist/enrichment/route-matcher.d.ts.map +1 -0
  14. package/dist/enrichment/route-matcher.js +121 -0
  15. package/dist/enrichment/route-matcher.js.map +1 -0
  16. package/dist/errors.d.ts +70 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +104 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/gtfs/index.d.ts +7 -0
  21. package/dist/gtfs/index.d.ts.map +1 -0
  22. package/dist/gtfs/index.js +7 -0
  23. package/dist/gtfs/index.js.map +1 -0
  24. package/dist/gtfs/parser.d.ts +39 -0
  25. package/dist/gtfs/parser.d.ts.map +1 -0
  26. package/dist/gtfs/parser.js +189 -0
  27. package/dist/gtfs/parser.js.map +1 -0
  28. package/dist/gtfs/sync.d.ts +72 -0
  29. package/dist/gtfs/sync.d.ts.map +1 -0
  30. package/dist/gtfs/sync.js +271 -0
  31. package/dist/gtfs/sync.js.map +1 -0
  32. package/dist/index.d.ts +203 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +342 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/parsers/gps-full.d.ts +39 -0
  37. package/dist/parsers/gps-full.d.ts.map +1 -0
  38. package/dist/parsers/gps-full.js +212 -0
  39. package/dist/parsers/gps-full.js.map +1 -0
  40. package/dist/parsers/gps-lite.d.ts +60 -0
  41. package/dist/parsers/gps-lite.d.ts.map +1 -0
  42. package/dist/parsers/gps-lite.js +141 -0
  43. package/dist/parsers/gps-lite.js.map +1 -0
  44. package/dist/parsers/index.d.ts +7 -0
  45. package/dist/parsers/index.d.ts.map +1 -0
  46. package/dist/parsers/index.js +7 -0
  47. package/dist/parsers/index.js.map +1 -0
  48. package/dist/schemas.d.ts +129 -0
  49. package/dist/schemas.d.ts.map +1 -0
  50. package/dist/schemas.js +200 -0
  51. package/dist/schemas.js.map +1 -0
  52. package/dist/scripts/test-city-specific.d.ts +2 -0
  53. package/dist/scripts/test-city-specific.d.ts.map +1 -0
  54. package/dist/scripts/test-city-specific.js +264 -0
  55. package/dist/scripts/test-city-specific.js.map +1 -0
  56. package/dist/scripts/test-config-options.d.ts +2 -0
  57. package/dist/scripts/test-config-options.d.ts.map +1 -0
  58. package/dist/scripts/test-config-options.js +166 -0
  59. package/dist/scripts/test-config-options.js.map +1 -0
  60. package/dist/scripts/test-data-quality.d.ts +2 -0
  61. package/dist/scripts/test-data-quality.d.ts.map +1 -0
  62. package/dist/scripts/test-data-quality.js +204 -0
  63. package/dist/scripts/test-data-quality.js.map +1 -0
  64. package/dist/scripts/test-error-handling.d.ts +2 -0
  65. package/dist/scripts/test-error-handling.d.ts.map +1 -0
  66. package/dist/scripts/test-error-handling.js +146 -0
  67. package/dist/scripts/test-error-handling.js.map +1 -0
  68. package/dist/scripts/test-live.d.ts +2 -0
  69. package/dist/scripts/test-live.d.ts.map +1 -0
  70. package/dist/scripts/test-live.js +121 -0
  71. package/dist/scripts/test-live.js.map +1 -0
  72. package/dist/types.d.ts +120 -0
  73. package/dist/types.d.ts.map +1 -0
  74. package/dist/types.js +25 -0
  75. package/dist/types.js.map +1 -0
  76. package/dist/utils/coordinates.d.ts +68 -0
  77. package/dist/utils/coordinates.d.ts.map +1 -0
  78. package/dist/utils/coordinates.js +98 -0
  79. package/dist/utils/coordinates.js.map +1 -0
  80. package/dist/utils/encoding.d.ts +47 -0
  81. package/dist/utils/encoding.d.ts.map +1 -0
  82. package/dist/utils/encoding.js +153 -0
  83. package/dist/utils/encoding.js.map +1 -0
  84. package/dist/utils/index.d.ts +8 -0
  85. package/dist/utils/index.d.ts.map +1 -0
  86. package/dist/utils/index.js +8 -0
  87. package/dist/utils/index.js.map +1 -0
  88. package/dist/utils/time.d.ts +50 -0
  89. package/dist/utils/time.d.ts.map +1 -0
  90. package/dist/utils/time.js +94 -0
  91. package/dist/utils/time.js.map +1 -0
  92. package/package.json +84 -0
@@ -0,0 +1,121 @@
1
+ import { LtTransport } from '../index.js';
2
+ import { ALL_CITY_IDS, CITY_CONFIGS } from '../config.js';
3
+ function getErrorMessage(error) {
4
+ if (error instanceof Error) {
5
+ return error.message;
6
+ }
7
+ return String(error);
8
+ }
9
+ async function runLiveTest() {
10
+ console.log('🚀 Starting Live SDK Tests...\n');
11
+ const client = new LtTransport({
12
+ requestTimeout: 30000, // Longer timeout for live tests
13
+ filterStale: false, // We want to see stale data stats
14
+ autoEnrich: true,
15
+ });
16
+ const cityStats = {};
17
+ let totalErrors = 0;
18
+ for (const city of ALL_CITY_IDS) {
19
+ console.log(`\n---------------------------------------------------`);
20
+ console.log(`Testing City: ${city.toUpperCase()} (${CITY_CONFIGS[city].tier} tier)`);
21
+ console.log(`---------------------------------------------------`);
22
+ const stats = {
23
+ gps: { available: false, count: 0, stale: 0, invalidCoords: 0 },
24
+ gtfs: { routes: 0, stops: 0, synced: false },
25
+ enrichment: { matched: 0 }
26
+ };
27
+ try {
28
+ // 1. Test GPS Stream
29
+ console.log(`📡 Fetching live vehicles...`);
30
+ if (CITY_CONFIGS[city].gps.enabled) {
31
+ try {
32
+ const vehicles = await client.getVehicles(city);
33
+ stats.gps.available = true;
34
+ stats.gps.count = vehicles.length;
35
+ stats.gps.stale = vehicles.filter(v => v.isStale).length;
36
+ stats.gps.invalidCoords = vehicles.filter(v => v.latitude === 0 || v.longitude === 0).length;
37
+ console.log(` ✅ Success: ${String(vehicles.length)} vehicles found`);
38
+ console.log(` - Stale: ${String(stats.gps.stale)}`);
39
+ console.log(` - enriching...`); // Will be checked after sync
40
+ // Check sample vehicle
41
+ if (vehicles.length > 0 && vehicles[0] !== undefined) {
42
+ const sample = vehicles[0];
43
+ console.log(` 🔍 Sample: [${sample.route}] ${sample.vehicleNumber} (${sample.type})`);
44
+ console.log(` Lat/Lon: ${sample.latitude.toFixed(4)}, ${sample.longitude.toFixed(4)}`);
45
+ console.log(` Measured: ${sample.measuredAt.toISOString()}`);
46
+ }
47
+ }
48
+ catch (err) {
49
+ console.error(` ❌ GPS Error: ${getErrorMessage(err)}`);
50
+ totalErrors++;
51
+ }
52
+ }
53
+ else {
54
+ console.log(` ⚠️ GPS not enabled for this city.`);
55
+ }
56
+ // 2. Test GTFS Sync
57
+ console.log(`⬇️ Syncing GTFS data...`);
58
+ try {
59
+ const syncResult = await client.sync(city);
60
+ stats.gtfs.synced = true;
61
+ stats.gtfs.routes = syncResult.routeCount;
62
+ stats.gtfs.stops = syncResult.stopCount;
63
+ console.log(` ✅ Synced: ${syncResult.status}`);
64
+ console.log(` - Routes: ${String(syncResult.routeCount)}`);
65
+ console.log(` - Stops: ${String(syncResult.stopCount)}`);
66
+ }
67
+ catch (err) {
68
+ console.error(` ❌ GTFS Sync Error: ${getErrorMessage(err)}`);
69
+ totalErrors++;
70
+ }
71
+ // 3. Test GTFS Data Access
72
+ if (stats.gtfs.synced) {
73
+ try {
74
+ const routes = await client.getRoutes(city);
75
+ const stops = await client.getStops(city);
76
+ console.log(` ✅ Cache verified: ${String(routes.length)} routes, ${String(stops.length)} stops loaded.`);
77
+ }
78
+ catch (err) {
79
+ console.error(` ❌ GTFS Access Error: ${getErrorMessage(err)}`);
80
+ totalErrors++;
81
+ }
82
+ }
83
+ // 4. Test Enrichment (Fetch vehicles again if GPS enabled)
84
+ if (CITY_CONFIGS[city].gps.enabled && stats.gtfs.synced) {
85
+ // Wait a bit to ensure async processing doesn't race? No, getVehicles should await enrichment.
86
+ const vehicles = await client.getVehicles(city);
87
+ const enriched = vehicles.filter(v => v.destination !== null);
88
+ stats.enrichment.matched = enriched.length;
89
+ console.log(` ✨ Enrichment: ${String(enriched.length)}/${String(vehicles.length)} vehicles have destinations`);
90
+ }
91
+ }
92
+ catch (err) {
93
+ console.error(`❌ Critical City Error: ${getErrorMessage(err)}`);
94
+ totalErrors++;
95
+ }
96
+ cityStats[city] = stats;
97
+ }
98
+ console.log('\n===================================================');
99
+ console.log('TEST SUMMARY');
100
+ console.log('===================================================');
101
+ console.table(Object.entries(cityStats).map(([city, s]) => ({
102
+ City: city,
103
+ Vehicles: s.gps.count,
104
+ 'Stale%': s.gps.count ? String(Math.round((s.gps.stale / s.gps.count) * 100)) + '%' : '-',
105
+ 'Routes': s.gtfs.routes,
106
+ 'Stops': s.gtfs.stops,
107
+ 'Enriched': s.enrichment.matched
108
+ })));
109
+ if (totalErrors > 0) {
110
+ console.error(`\n❌ Completed with ${String(totalErrors)} errors.`);
111
+ process.exit(1);
112
+ }
113
+ else {
114
+ console.log(`\n✅ All tests passed successfully!`);
115
+ }
116
+ }
117
+ runLiveTest().catch((err) => {
118
+ console.error(getErrorMessage(err));
119
+ process.exit(1);
120
+ });
121
+ //# sourceMappingURL=test-live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-live.js","sourceRoot":"","sources":["../../src/scripts/test-live.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Core type definitions for Lithuanian Public Transport SDK
3
+ * @module types
4
+ */
5
+ import type { CityId } from './config.js';
6
+ export type { CityId, CityTier } from './config.js';
7
+ /**
8
+ * Vehicle types from Lithuanian public transport.
9
+ * - bus: Standard city buses (GTFS route_type 3)
10
+ * - trolleybus: Electric trolleybuses (GTFS route_type 800)
11
+ * - ferry: Water transport / boats (GTFS route_type 4 or 1200) - seasonal in Vilnius
12
+ * - unknown: Unrecognized vehicle type
13
+ */
14
+ export type VehicleType = 'bus' | 'trolleybus' | 'ferry' | 'unknown';
15
+ /**
16
+ * GTFS route_type to VehicleType mapping.
17
+ * Uses both standard and extended GTFS route types.
18
+ */
19
+ export declare const GTFS_ROUTE_TYPE_MAP: Readonly<Record<number, VehicleType>>;
20
+ /**
21
+ * Lithuanian transport type names to VehicleType mapping.
22
+ * Used when parsing GPS data streams.
23
+ */
24
+ export declare const LT_TRANSPORT_TYPE_MAP: Readonly<Record<string, VehicleType>>;
25
+ /**
26
+ * Normalized vehicle object representing a single public transport vehicle.
27
+ * This interface is consistent across all cities regardless of data source format.
28
+ */
29
+ export interface Vehicle {
30
+ /** Unique identifier for this vehicle tracking record */
31
+ readonly id: string;
32
+ /** Vehicle number/code as displayed on the vehicle */
33
+ readonly vehicleNumber: string;
34
+ /** Route identifier (e.g., "4G", "N1", "S11") - always a string */
35
+ readonly route: string;
36
+ /** Type of vehicle */
37
+ readonly type: VehicleType;
38
+ /** Latitude in WGS84 decimal degrees */
39
+ readonly latitude: number;
40
+ /** Longitude in WGS84 decimal degrees */
41
+ readonly longitude: number;
42
+ /** Heading/bearing in degrees (0-359, 0 = North) */
43
+ readonly bearing: number;
44
+ /** Current speed in km/h */
45
+ readonly speed: number;
46
+ /** Destination/terminus name, if available */
47
+ readonly destination: string | null;
48
+ /** Delay in seconds (positive = late, negative = early), if available */
49
+ readonly delaySeconds: number | null;
50
+ /** Trip identifier from source system, if available */
51
+ readonly tripId: string | null;
52
+ /** GTFS trip reference, if available (Vilnius only) */
53
+ readonly gtfsTripId: string | null;
54
+ /** Next stop ID (Kaunas only) */
55
+ readonly nextStopId: string | null;
56
+ /** Predicted arrival time at next stop in seconds from midnight (Kaunas only) */
57
+ readonly arrivalTimeSeconds: number | null;
58
+ /**
59
+ * Whether this data is considered stale.
60
+ * True if measurement time is older than configured threshold.
61
+ */
62
+ readonly isStale: boolean;
63
+ /**
64
+ * Timestamp when the GPS position was measured.
65
+ * Falls back to server receive time if measurement time unavailable.
66
+ */
67
+ readonly measuredAt: Date;
68
+ }
69
+ /**
70
+ * Static stop/station data from GTFS.
71
+ */
72
+ export interface Stop {
73
+ /** Unique stop identifier from GTFS */
74
+ readonly id: string;
75
+ /** Short code for the stop, if available */
76
+ readonly code: string | null;
77
+ /** Human-readable stop name */
78
+ readonly name: string;
79
+ /** Additional description, if available */
80
+ readonly description: string | null;
81
+ /** Latitude in WGS84 decimal degrees */
82
+ readonly latitude: number;
83
+ /** Longitude in WGS84 decimal degrees */
84
+ readonly longitude: number;
85
+ }
86
+ /**
87
+ * Route information from GTFS.
88
+ */
89
+ export interface Route {
90
+ /** Unique route identifier from GTFS */
91
+ readonly id: string;
92
+ /** Short route name (e.g., "4G", "N1") */
93
+ readonly shortName: string;
94
+ /** Full route name with endpoints */
95
+ readonly longName: string;
96
+ /** Type of vehicles on this route */
97
+ readonly type: VehicleType;
98
+ /** Route color for display (hex without #) */
99
+ readonly color: string;
100
+ /** Text color for display on route color background (hex without #) */
101
+ readonly textColor: string;
102
+ }
103
+ /**
104
+ * Result of a GTFS sync operation.
105
+ */
106
+ export interface SyncResult {
107
+ /** City that was synced */
108
+ readonly city: CityId;
109
+ /** Whether data was updated or already current */
110
+ readonly status: 'updated' | 'up-to-date';
111
+ /** Number of routes in cache after sync */
112
+ readonly routeCount: number;
113
+ /** Number of stops in cache after sync */
114
+ readonly stopCount: number;
115
+ /** Last-Modified timestamp from server */
116
+ readonly lastModified: string | null;
117
+ /** When this sync was performed */
118
+ readonly syncedAt: Date;
119
+ }
120
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Core type definitions for Lithuanian Public Transport SDK
3
+ * @module types
4
+ */
5
+ /**
6
+ * GTFS route_type to VehicleType mapping.
7
+ * Uses both standard and extended GTFS route types.
8
+ */
9
+ export const GTFS_ROUTE_TYPE_MAP = {
10
+ 3: 'bus', // Standard GTFS: Bus
11
+ 800: 'trolleybus', // Extended GTFS: Trolleybus
12
+ 4: 'ferry', // Standard GTFS: Ferry
13
+ 1200: 'ferry', // Extended GTFS: Ferry Service
14
+ };
15
+ /**
16
+ * Lithuanian transport type names to VehicleType mapping.
17
+ * Used when parsing GPS data streams.
18
+ */
19
+ export const LT_TRANSPORT_TYPE_MAP = {
20
+ 'Autobusai': 'bus',
21
+ 'Troleibusai': 'trolleybus',
22
+ 'Laivai': 'ferry',
23
+ 'Keltai': 'ferry',
24
+ };
25
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA0C;IACxE,CAAC,EAAE,KAAK,EAAU,qBAAqB;IACvC,GAAG,EAAE,YAAY,EAAE,4BAA4B;IAC/C,CAAC,EAAE,OAAO,EAAQ,uBAAuB;IACzC,IAAI,EAAE,OAAO,EAAK,+BAA+B;CACzC,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAA0C;IAC1E,WAAW,EAAE,KAAK;IAClB,aAAa,EAAE,YAAY;IAC3B,QAAQ,EAAE,OAAO;IACjB,QAAQ,EAAE,OAAO;CACT,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Coordinate normalization and validation utilities
3
+ * @module utils/coordinates
4
+ */
5
+ /**
6
+ * Lithuania's geographic bounding box in WGS84 decimal degrees.
7
+ * Used to validate coordinates are within expected range.
8
+ */
9
+ export declare const LITHUANIA_BOUNDS: {
10
+ /** Minimum latitude (southern border) */
11
+ readonly latMin: 53.89;
12
+ /** Maximum latitude (northern border) */
13
+ readonly latMax: 56.45;
14
+ /** Minimum longitude (western border) */
15
+ readonly lonMin: 20.93;
16
+ /** Maximum longitude (eastern border) */
17
+ readonly lonMax: 26.83;
18
+ };
19
+ /**
20
+ * Normalize a raw integer coordinate to WGS84 decimal degrees.
21
+ *
22
+ * @param raw - Raw coordinate as integer (e.g., 25255492 for ~25.255492°)
23
+ * @returns Normalized coordinate in decimal degrees
24
+ *
25
+ * @example
26
+ * normalizeCoordinate(25255492) // => 25.255492
27
+ * normalizeCoordinate(54633886) // => 54.633886
28
+ */
29
+ export declare function normalizeCoordinate(raw: number): number;
30
+ /**
31
+ * Check if coordinates fall within Lithuania's bounding box.
32
+ *
33
+ * @param lat - Latitude in WGS84 decimal degrees
34
+ * @param lon - Longitude in WGS84 decimal degrees
35
+ * @returns true if coordinates are within Lithuania
36
+ *
37
+ * @example
38
+ * isValidLithuaniaCoord(54.687, 25.279) // => true (Vilnius)
39
+ * isValidLithuaniaCoord(48.856, 2.352) // => false (Paris)
40
+ */
41
+ export declare function isValidLithuaniaCoord(lat: number, lon: number): boolean;
42
+ /**
43
+ * Validate and normalize raw integer coordinates.
44
+ * Returns null if coordinates are invalid or outside Lithuania.
45
+ *
46
+ * @param rawLat - Raw latitude as integer
47
+ * @param rawLon - Raw longitude as integer
48
+ * @returns Object with normalized lat/lon, or null if invalid
49
+ */
50
+ export declare function normalizeAndValidateCoordinates(rawLat: number, rawLon: number): {
51
+ latitude: number;
52
+ longitude: number;
53
+ } | null;
54
+ /**
55
+ * Normalize bearing to 0-359 range.
56
+ *
57
+ * @param bearing - Raw bearing value
58
+ * @returns Normalized bearing in degrees
59
+ */
60
+ export declare function normalizeBearing(bearing: number): number;
61
+ /**
62
+ * Normalize speed to non-negative value.
63
+ *
64
+ * @param speed - Raw speed value
65
+ * @returns Speed in km/h, minimum 0
66
+ */
67
+ export declare function normalizeSpeed(speed: number): number;
68
+ //# sourceMappingURL=coordinates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinates.d.ts","sourceRoot":"","sources":["../../src/utils/coordinates.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB;IAC3B,yCAAyC;;IAEzC,yCAAyC;;IAEzC,yCAAyC;;IAEzC,yCAAyC;;CAEjC,CAAC;AAQX;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAOvE;AAED;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAahD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKpD"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Coordinate normalization and validation utilities
3
+ * @module utils/coordinates
4
+ */
5
+ /**
6
+ * Lithuania's geographic bounding box in WGS84 decimal degrees.
7
+ * Used to validate coordinates are within expected range.
8
+ */
9
+ export const LITHUANIA_BOUNDS = {
10
+ /** Minimum latitude (southern border) */
11
+ latMin: 53.89,
12
+ /** Maximum latitude (northern border) */
13
+ latMax: 56.45,
14
+ /** Minimum longitude (western border) */
15
+ lonMin: 20.93,
16
+ /** Maximum longitude (eastern border) */
17
+ lonMax: 26.83,
18
+ };
19
+ /**
20
+ * Coordinate divisor for stops.lt integer format.
21
+ * Raw coordinates are multiplied by 1,000,000 to avoid floating point.
22
+ */
23
+ const COORDINATE_DIVISOR = 1_000_000;
24
+ /**
25
+ * Normalize a raw integer coordinate to WGS84 decimal degrees.
26
+ *
27
+ * @param raw - Raw coordinate as integer (e.g., 25255492 for ~25.255492°)
28
+ * @returns Normalized coordinate in decimal degrees
29
+ *
30
+ * @example
31
+ * normalizeCoordinate(25255492) // => 25.255492
32
+ * normalizeCoordinate(54633886) // => 54.633886
33
+ */
34
+ export function normalizeCoordinate(raw) {
35
+ return raw / COORDINATE_DIVISOR;
36
+ }
37
+ /**
38
+ * Check if coordinates fall within Lithuania's bounding box.
39
+ *
40
+ * @param lat - Latitude in WGS84 decimal degrees
41
+ * @param lon - Longitude in WGS84 decimal degrees
42
+ * @returns true if coordinates are within Lithuania
43
+ *
44
+ * @example
45
+ * isValidLithuaniaCoord(54.687, 25.279) // => true (Vilnius)
46
+ * isValidLithuaniaCoord(48.856, 2.352) // => false (Paris)
47
+ */
48
+ export function isValidLithuaniaCoord(lat, lon) {
49
+ return (lat >= LITHUANIA_BOUNDS.latMin &&
50
+ lat <= LITHUANIA_BOUNDS.latMax &&
51
+ lon >= LITHUANIA_BOUNDS.lonMin &&
52
+ lon <= LITHUANIA_BOUNDS.lonMax);
53
+ }
54
+ /**
55
+ * Validate and normalize raw integer coordinates.
56
+ * Returns null if coordinates are invalid or outside Lithuania.
57
+ *
58
+ * @param rawLat - Raw latitude as integer
59
+ * @param rawLon - Raw longitude as integer
60
+ * @returns Object with normalized lat/lon, or null if invalid
61
+ */
62
+ export function normalizeAndValidateCoordinates(rawLat, rawLon) {
63
+ if (!Number.isFinite(rawLat) || !Number.isFinite(rawLon)) {
64
+ return null;
65
+ }
66
+ const latitude = normalizeCoordinate(rawLat);
67
+ const longitude = normalizeCoordinate(rawLon);
68
+ if (!isValidLithuaniaCoord(latitude, longitude)) {
69
+ return null;
70
+ }
71
+ return { latitude, longitude };
72
+ }
73
+ /**
74
+ * Normalize bearing to 0-359 range.
75
+ *
76
+ * @param bearing - Raw bearing value
77
+ * @returns Normalized bearing in degrees
78
+ */
79
+ export function normalizeBearing(bearing) {
80
+ if (!Number.isFinite(bearing)) {
81
+ return 0;
82
+ }
83
+ // Handle negative values and wrap around
84
+ return ((bearing % 360) + 360) % 360;
85
+ }
86
+ /**
87
+ * Normalize speed to non-negative value.
88
+ *
89
+ * @param speed - Raw speed value
90
+ * @returns Speed in km/h, minimum 0
91
+ */
92
+ export function normalizeSpeed(speed) {
93
+ if (!Number.isFinite(speed) || speed < 0) {
94
+ return 0;
95
+ }
96
+ return speed;
97
+ }
98
+ //# sourceMappingURL=coordinates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinates.js","sourceRoot":"","sources":["../../src/utils/coordinates.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,yCAAyC;IACzC,MAAM,EAAE,KAAK;IACb,yCAAyC;IACzC,MAAM,EAAE,KAAK;IACb,yCAAyC;IACzC,MAAM,EAAE,KAAK;IACb,yCAAyC;IACzC,MAAM,EAAE,KAAK;CACL,CAAC;AAEX;;;GAGG;AACH,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAErC;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,OAAO,GAAG,GAAG,kBAAkB,CAAC;AAClC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW,EAAE,GAAW;IAC5D,OAAO,CACL,GAAG,IAAI,gBAAgB,CAAC,MAAM;QAC9B,GAAG,IAAI,gBAAgB,CAAC,MAAM;QAC9B,GAAG,IAAI,gBAAgB,CAAC,MAAM;QAC9B,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAC/B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,+BAA+B,CAC7C,MAAc,EACd,MAAc;IAEd,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAE9C,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACjC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,yCAAyC;IACzC,OAAO,CAAC,CAAC,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACzC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Text encoding utilities for handling Windows-1257 and mojibake repair
3
+ * @module utils/encoding
4
+ */
5
+ /**
6
+ * Attempt to repair mojibake (garbled text) caused by encoding mismatches.
7
+ * Common when Windows-1257 encoded text is read as UTF-8.
8
+ *
9
+ * @param text - Potentially corrupted text
10
+ * @returns Repaired text with Lithuanian characters restored
11
+ *
12
+ * @example
13
+ * repairMojibake('Autobusų parkas(EiÅ¡iÅ¡kių pl.)')
14
+ * // => 'Autobusų parkas(Eišiškių pl.)'
15
+ */
16
+ export declare function repairMojibake(text: string): string;
17
+ /**
18
+ * Check if text contains likely mojibake patterns.
19
+ *
20
+ * @param text - Text to check
21
+ * @returns true if mojibake patterns detected
22
+ */
23
+ export declare function hasMojibake(text: string): boolean;
24
+ /**
25
+ * Decode a byte array from Windows-1257 (Baltic) encoding to UTF-8 string.
26
+ *
27
+ * @param bytes - Raw bytes in Windows-1257 encoding
28
+ * @returns Decoded UTF-8 string
29
+ */
30
+ export declare function decodeWindows1257(bytes: Uint8Array): string;
31
+ /**
32
+ * Decode text from an ArrayBuffer, trying UTF-8 first, then falling back
33
+ * to Windows-1257 if mojibake is detected.
34
+ *
35
+ * @param buffer - Raw data buffer
36
+ * @returns Properly decoded string
37
+ */
38
+ export declare function decodeBalticText(buffer: ArrayBuffer): string;
39
+ /**
40
+ * Clean and normalize a text field from transport data.
41
+ * Handles encoding issues and trims whitespace.
42
+ *
43
+ * @param text - Raw text field
44
+ * @returns Cleaned text
45
+ */
46
+ export declare function cleanTextField(text: string): string;
47
+ //# sourceMappingURL=encoding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../../src/utils/encoding.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoCH;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASnD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjD;AAyBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAe3D;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAoB5D;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWnD"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Text encoding utilities for handling Windows-1257 and mojibake repair
3
+ * @module utils/encoding
4
+ */
5
+ /**
6
+ * Common mojibake patterns when Windows-1257 text is incorrectly decoded as UTF-8.
7
+ * Maps corrupted sequences to correct Lithuanian characters.
8
+ */
9
+ const MOJIBAKE_REPAIRS = new Map([
10
+ // Lowercase Lithuanian letters
11
+ ['Ä…', 'ą'],
12
+ ['ć', 'ć'], // Not Lithuanian but may appear
13
+ ['Ä—', 'ė'],
14
+ ['Ä™', 'ę'], // Not Lithuanian but may appear
15
+ ['į', 'į'],
16
+ ['Å¡', 'š'],
17
+ ['ų', 'ų'],
18
+ ['Å«', 'ū'],
19
+ ['ž', 'ž'],
20
+ // Uppercase Lithuanian letters
21
+ ['Ä„', 'Ą'],
22
+ ['Ć', 'Ć'], // Not Lithuanian but may appear
23
+ ['Ä–', 'Ė'],
24
+ ['Ę', 'Ę'], // Not Lithuanian but may appear
25
+ ['Ä®', 'Į'],
26
+ ['Å ', 'Š'],
27
+ ['Ų', 'Ų'],
28
+ ['Ū', 'Ū'],
29
+ ['Ž', 'Ž'],
30
+ // Additional patterns that may occur
31
+ ['è', 'č'],
32
+ ['Ã ', 'ę'],
33
+ ['Å„', 'ń'],
34
+ ['Ä', 'č'], // Sometimes Ä alone appears for č
35
+ ]);
36
+ /**
37
+ * Attempt to repair mojibake (garbled text) caused by encoding mismatches.
38
+ * Common when Windows-1257 encoded text is read as UTF-8.
39
+ *
40
+ * @param text - Potentially corrupted text
41
+ * @returns Repaired text with Lithuanian characters restored
42
+ *
43
+ * @example
44
+ * repairMojibake('Autobusų parkas(EiÅ¡iÅ¡kių pl.)')
45
+ * // => 'Autobusų parkas(Eišiškių pl.)'
46
+ */
47
+ export function repairMojibake(text) {
48
+ let result = text;
49
+ for (const [corrupted, correct] of MOJIBAKE_REPAIRS) {
50
+ // Use global replace for all occurrences
51
+ result = result.split(corrupted).join(correct);
52
+ }
53
+ return result;
54
+ }
55
+ /**
56
+ * Check if text contains likely mojibake patterns.
57
+ *
58
+ * @param text - Text to check
59
+ * @returns true if mojibake patterns detected
60
+ */
61
+ export function hasMojibake(text) {
62
+ for (const corrupted of MOJIBAKE_REPAIRS.keys()) {
63
+ if (text.includes(corrupted)) {
64
+ return true;
65
+ }
66
+ }
67
+ return false;
68
+ }
69
+ /**
70
+ * Windows-1257 (Baltic) code page byte-to-character mapping.
71
+ * Only maps bytes 128-255; 0-127 are identical to ASCII.
72
+ */
73
+ const WINDOWS_1257_MAP = [
74
+ // 0x80-0x8F
75
+ '\u20AC', '', '\u201A', '', '\u201E', '\u2026', '\u2020', '\u2021', '', '\u2030', '', '\u2039', '', '\u00A8', '\u02C7', '\u00B8',
76
+ // 0x90-0x9F
77
+ '', '\u2018', '\u2019', '\u201C', '\u201D', '\u2022', '\u2013', '\u2014', '', '\u2122', '', '\u203A', '', '\u00AF', '\u02DB', '',
78
+ // 0xA0-0xAF
79
+ '\u00A0', '', '\u00A2', '\u00A3', '\u00A4', '', '\u00A6', '\u00A7', '\u00D8', '\u00A9', '\u0156', '\u00AB', '\u00AC', '\u00AD', '\u00AE', '\u00C6',
80
+ // 0xB0-0xBF
81
+ '\u00B0', '\u00B1', '\u00B2', '\u00B3', '\u00B4', '\u00B5', '\u00B6', '\u00B7', '\u00F8', '\u00B9', '\u0157', '\u00BB', '\u00BC', '\u00BD', '\u00BE', '\u00E6',
82
+ // 0xC0-0xCF
83
+ '\u0104', '\u012E', '\u0100', '\u0106', '\u00C4', '\u00C5', '\u0118', '\u0112', '\u010C', '\u00C9', '\u0179', '\u0116', '\u0122', '\u0136', '\u012A', '\u013B',
84
+ // 0xD0-0xDF
85
+ '\u0160', '\u0143', '\u0145', '\u00D3', '\u014C', '\u00D5', '\u00D6', '\u00D7', '\u0172', '\u0141', '\u015A', '\u016A', '\u00DC', '\u017B', '\u017D', '\u00DF',
86
+ // 0xE0-0xEF
87
+ '\u0105', '\u012F', '\u0101', '\u0107', '\u00E4', '\u00E5', '\u0119', '\u0113', '\u010D', '\u00E9', '\u017A', '\u0117', '\u0123', '\u0137', '\u012B', '\u013C',
88
+ // 0xF0-0xFF
89
+ '\u0161', '\u0144', '\u0146', '\u00F3', '\u014D', '\u00F5', '\u00F6', '\u00F7', '\u0173', '\u0142', '\u015B', '\u016B', '\u00FC', '\u017C', '\u017E', '\u02D9',
90
+ ];
91
+ /**
92
+ * Decode a byte array from Windows-1257 (Baltic) encoding to UTF-8 string.
93
+ *
94
+ * @param bytes - Raw bytes in Windows-1257 encoding
95
+ * @returns Decoded UTF-8 string
96
+ */
97
+ export function decodeWindows1257(bytes) {
98
+ const chars = [];
99
+ for (const byte of bytes) {
100
+ if (byte < 128) {
101
+ // ASCII range - direct mapping
102
+ chars.push(String.fromCharCode(byte));
103
+ }
104
+ else {
105
+ // Extended range - use Windows-1257 mapping
106
+ const mapped = WINDOWS_1257_MAP[byte - 128];
107
+ chars.push(mapped !== undefined && mapped !== '' ? mapped : '?');
108
+ }
109
+ }
110
+ return chars.join('');
111
+ }
112
+ /**
113
+ * Decode text from an ArrayBuffer, trying UTF-8 first, then falling back
114
+ * to Windows-1257 if mojibake is detected.
115
+ *
116
+ * @param buffer - Raw data buffer
117
+ * @returns Properly decoded string
118
+ */
119
+ export function decodeBalticText(buffer) {
120
+ const bytes = new Uint8Array(buffer);
121
+ // First, try UTF-8 decoding
122
+ const decoder = new TextDecoder('utf-8', { fatal: false });
123
+ let text = decoder.decode(bytes);
124
+ // Check for mojibake patterns
125
+ if (hasMojibake(text)) {
126
+ // Try to repair the mojibake
127
+ text = repairMojibake(text);
128
+ }
129
+ // If still looks corrupted, try Windows-1257 directly
130
+ // (Check for remaining replacement characters or known patterns)
131
+ if (text.includes('\uFFFD') || /[\x80-\x9F]/.test(text)) {
132
+ text = decodeWindows1257(bytes);
133
+ }
134
+ return text;
135
+ }
136
+ /**
137
+ * Clean and normalize a text field from transport data.
138
+ * Handles encoding issues and trims whitespace.
139
+ *
140
+ * @param text - Raw text field
141
+ * @returns Cleaned text
142
+ */
143
+ export function cleanTextField(text) {
144
+ if (!text)
145
+ return '';
146
+ // Repair any mojibake
147
+ let cleaned = repairMojibake(text.trim());
148
+ // Remove any control characters (ASCII 0-31 and 127)
149
+ // eslint-disable-next-line no-control-regex
150
+ cleaned = cleaned.replace(/[\x00-\x1F\x7F]/g, '');
151
+ return cleaned;
152
+ }
153
+ //# sourceMappingURL=encoding.js.map