@osmix/gtfs 0.0.1

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 (60) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +200 -0
  3. package/dist/from-gtfs.d.ts +76 -0
  4. package/dist/from-gtfs.d.ts.map +1 -0
  5. package/dist/from-gtfs.js +211 -0
  6. package/dist/from-gtfs.js.map +1 -0
  7. package/dist/gtfs-archive.d.ts +71 -0
  8. package/dist/gtfs-archive.d.ts.map +1 -0
  9. package/dist/gtfs-archive.js +102 -0
  10. package/dist/gtfs-archive.js.map +1 -0
  11. package/dist/index.d.ts +39 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +39 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/src/from-gtfs.d.ts +76 -0
  16. package/dist/src/from-gtfs.d.ts.map +1 -0
  17. package/dist/src/from-gtfs.js +211 -0
  18. package/dist/src/from-gtfs.js.map +1 -0
  19. package/dist/src/gtfs-archive.d.ts +71 -0
  20. package/dist/src/gtfs-archive.d.ts.map +1 -0
  21. package/dist/src/gtfs-archive.js +102 -0
  22. package/dist/src/gtfs-archive.js.map +1 -0
  23. package/dist/src/index.d.ts +39 -0
  24. package/dist/src/index.d.ts.map +1 -0
  25. package/dist/src/index.js +39 -0
  26. package/dist/src/index.js.map +1 -0
  27. package/dist/src/types.d.ts +139 -0
  28. package/dist/src/types.d.ts.map +1 -0
  29. package/dist/src/types.js +48 -0
  30. package/dist/src/types.js.map +1 -0
  31. package/dist/src/utils.d.ts +25 -0
  32. package/dist/src/utils.d.ts.map +1 -0
  33. package/dist/src/utils.js +210 -0
  34. package/dist/src/utils.js.map +1 -0
  35. package/dist/test/from-gtfs.test.d.ts +2 -0
  36. package/dist/test/from-gtfs.test.d.ts.map +1 -0
  37. package/dist/test/from-gtfs.test.js +389 -0
  38. package/dist/test/from-gtfs.test.js.map +1 -0
  39. package/dist/test/helpers.d.ts +14 -0
  40. package/dist/test/helpers.d.ts.map +1 -0
  41. package/dist/test/helpers.js +84 -0
  42. package/dist/test/helpers.js.map +1 -0
  43. package/dist/types.d.ts +139 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +48 -0
  46. package/dist/types.js.map +1 -0
  47. package/dist/utils.d.ts +25 -0
  48. package/dist/utils.d.ts.map +1 -0
  49. package/dist/utils.js +211 -0
  50. package/dist/utils.js.map +1 -0
  51. package/package.json +53 -0
  52. package/src/from-gtfs.ts +259 -0
  53. package/src/gtfs-archive.ts +138 -0
  54. package/src/index.ts +54 -0
  55. package/src/types.ts +184 -0
  56. package/src/utils.ts +226 -0
  57. package/test/from-gtfs.test.ts +501 -0
  58. package/test/helpers.ts +118 -0
  59. package/tsconfig.build.json +5 -0
  60. package/tsconfig.json +9 -0
@@ -0,0 +1,139 @@
1
+ /**
2
+ * GTFS (General Transit Feed Specification) type definitions.
3
+ *
4
+ * @module
5
+ */
6
+ /**
7
+ * GTFS stop from stops.txt.
8
+ * Represents a transit stop or station.
9
+ */
10
+ export interface GtfsStop {
11
+ stop_id: string;
12
+ stop_code?: string;
13
+ stop_name: string;
14
+ stop_desc?: string;
15
+ stop_lat: string;
16
+ stop_lon: string;
17
+ zone_id?: string;
18
+ stop_url?: string;
19
+ /** 0 = stop, 1 = station, 2 = entrance/exit, 3 = generic node, 4 = boarding area */
20
+ location_type?: string;
21
+ parent_station?: string;
22
+ stop_timezone?: string;
23
+ /** 0 = no info, 1 = accessible, 2 = not accessible */
24
+ wheelchair_boarding?: string;
25
+ level_id?: string;
26
+ platform_code?: string;
27
+ }
28
+ /**
29
+ * GTFS route from routes.txt.
30
+ * Represents a transit route/line.
31
+ */
32
+ export interface GtfsRoute {
33
+ route_id: string;
34
+ agency_id?: string;
35
+ route_short_name?: string;
36
+ route_long_name?: string;
37
+ route_desc?: string;
38
+ /**
39
+ * Route type:
40
+ * 0 = Tram, 1 = Subway, 2 = Rail, 3 = Bus, 4 = Ferry,
41
+ * 5 = Cable tram, 6 = Aerial lift, 7 = Funicular,
42
+ * 11 = Trolleybus, 12 = Monorail
43
+ */
44
+ route_type: string;
45
+ route_url?: string;
46
+ route_color?: string;
47
+ route_text_color?: string;
48
+ route_sort_order?: string;
49
+ continuous_pickup?: string;
50
+ continuous_drop_off?: string;
51
+ network_id?: string;
52
+ }
53
+ /**
54
+ * GTFS shape point from shapes.txt.
55
+ * Defines the geographic path of a route.
56
+ */
57
+ export interface GtfsShapePoint {
58
+ shape_id: string;
59
+ shape_pt_lat: string;
60
+ shape_pt_lon: string;
61
+ shape_pt_sequence: string;
62
+ shape_dist_traveled?: string;
63
+ }
64
+ /**
65
+ * GTFS trip from trips.txt.
66
+ * Represents a specific trip on a route.
67
+ */
68
+ export interface GtfsTrip {
69
+ trip_id: string;
70
+ route_id: string;
71
+ service_id: string;
72
+ trip_headsign?: string;
73
+ trip_short_name?: string;
74
+ direction_id?: string;
75
+ block_id?: string;
76
+ shape_id?: string;
77
+ wheelchair_accessible?: string;
78
+ bikes_allowed?: string;
79
+ }
80
+ /**
81
+ * GTFS stop time from stop_times.txt.
82
+ * Links trips to stops with timing info.
83
+ */
84
+ export interface GtfsStopTime {
85
+ trip_id: string;
86
+ arrival_time?: string;
87
+ departure_time?: string;
88
+ stop_id: string;
89
+ stop_sequence: string;
90
+ stop_headsign?: string;
91
+ pickup_type?: string;
92
+ drop_off_type?: string;
93
+ continuous_pickup?: string;
94
+ continuous_drop_off?: string;
95
+ shape_dist_traveled?: string;
96
+ timepoint?: string;
97
+ }
98
+ /**
99
+ * GTFS agency from agency.txt.
100
+ */
101
+ export interface GtfsAgency {
102
+ agency_id?: string;
103
+ agency_name: string;
104
+ agency_url: string;
105
+ agency_timezone: string;
106
+ agency_lang?: string;
107
+ agency_phone?: string;
108
+ agency_fare_url?: string;
109
+ agency_email?: string;
110
+ }
111
+ /**
112
+ * Parsed GTFS feed with all relevant files.
113
+ */
114
+ export interface GtfsFeed {
115
+ agencies: GtfsAgency[];
116
+ stops: GtfsStop[];
117
+ routes: GtfsRoute[];
118
+ trips: GtfsTrip[];
119
+ stopTimes: GtfsStopTime[];
120
+ shapes: GtfsShapePoint[];
121
+ }
122
+ /**
123
+ * Options for GTFS to OSM conversion.
124
+ */
125
+ export interface GtfsConversionOptions {
126
+ /** Whether to include stops as nodes. Default: true */
127
+ includeStops?: boolean;
128
+ /** Whether to include routes as ways. Default: true */
129
+ includeRoutes?: boolean;
130
+ }
131
+ /**
132
+ * Map GTFS route_type to OSM route tag value.
133
+ */
134
+ export declare function routeTypeToOsmRoute(routeType: string): string;
135
+ /**
136
+ * Map GTFS wheelchair_boarding to OSM wheelchair tag value.
137
+ */
138
+ export declare function wheelchairBoardingToOsm(value: string | undefined): string | undefined;
139
+ //# 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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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * GTFS (General Transit Feed Specification) type definitions.
3
+ *
4
+ * @module
5
+ */
6
+ /**
7
+ * Map GTFS route_type to OSM route tag value.
8
+ */
9
+ export function routeTypeToOsmRoute(routeType) {
10
+ switch (routeType) {
11
+ case "0":
12
+ return "tram";
13
+ case "1":
14
+ return "subway";
15
+ case "2":
16
+ return "train";
17
+ case "3":
18
+ return "bus";
19
+ case "4":
20
+ return "ferry";
21
+ case "5":
22
+ return "tram"; // Cable tram
23
+ case "6":
24
+ return "aerialway";
25
+ case "7":
26
+ return "funicular";
27
+ case "11":
28
+ return "trolleybus";
29
+ case "12":
30
+ return "train"; // Monorail
31
+ default:
32
+ return "bus";
33
+ }
34
+ }
35
+ /**
36
+ * Map GTFS wheelchair_boarding to OSM wheelchair tag value.
37
+ */
38
+ export function wheelchairBoardingToOsm(value) {
39
+ switch (value) {
40
+ case "1":
41
+ return "yes";
42
+ case "2":
43
+ return "no";
44
+ default:
45
+ return undefined;
46
+ }
47
+ }
48
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuIH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACpD,QAAQ,SAAS,EAAE,CAAC;QACnB,KAAK,GAAG;YACP,OAAO,MAAM,CAAA;QACd,KAAK,GAAG;YACP,OAAO,QAAQ,CAAA;QAChB,KAAK,GAAG;YACP,OAAO,OAAO,CAAA;QACf,KAAK,GAAG;YACP,OAAO,KAAK,CAAA;QACb,KAAK,GAAG;YACP,OAAO,OAAO,CAAA;QACf,KAAK,GAAG;YACP,OAAO,MAAM,CAAA,CAAC,aAAa;QAC5B,KAAK,GAAG;YACP,OAAO,WAAW,CAAA;QACnB,KAAK,GAAG;YACP,OAAO,WAAW,CAAA;QACnB,KAAK,IAAI;YACR,OAAO,YAAY,CAAA;QACpB,KAAK,IAAI;YACR,OAAO,OAAO,CAAA,CAAC,WAAW;QAC3B;YACC,OAAO,KAAK,CAAA;IACd,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACtC,KAAyB;IAEzB,QAAQ,KAAK,EAAE,CAAC;QACf,KAAK,GAAG;YACP,OAAO,KAAK,CAAA;QACb,KAAK,GAAG;YACP,OAAO,IAAI,CAAA;QACZ;YACC,OAAO,SAAS,CAAA;IAClB,CAAC;AACF,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { OsmTags } from "@osmix/shared/types";
2
+ import { type GtfsRoute, type GtfsStop, type GtfsTrip } from "./types";
3
+ /**
4
+ * Check if a ZIP file (as bytes) is a GTFS archive by looking for characteristic GTFS files.
5
+ * GTFS archives must contain at least agency.txt, stops.txt, routes.txt, trips.txt,
6
+ * and stop_times.txt according to the GTFS specification.
7
+ */
8
+ export declare function isGtfsZip(bytes: Uint8Array): boolean;
9
+ /**
10
+ * Convert a GTFS stop to OSM tags.
11
+ */
12
+ export declare function stopToTags(stop: GtfsStop): OsmTags;
13
+ /**
14
+ * Convert a GTFS route to OSM tags.
15
+ */
16
+ export declare function routeToTags(route: GtfsRoute): OsmTags;
17
+ /**
18
+ * Convert a GTFS trip to OSM tags.
19
+ */
20
+ export declare function tripToTags(trip: GtfsTrip): OsmTags;
21
+ /**
22
+ * Create a ReadableStream of text from file bytes.
23
+ */
24
+ export declare function bytesToTextStream(bytes: Uint8Array): ReadableStream<string>;
25
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EACN,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,QAAQ,EAGb,MAAM,SAAS,CAAA;AAEhB;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CA0FpD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAoClD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CA4BrD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAelD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAqB3E"}
@@ -0,0 +1,210 @@
1
+ import { normalizeHexColor } from "@osmix/shared/color";
2
+ import { routeTypeToOsmRoute, wheelchairBoardingToOsm, } from "./types";
3
+ /**
4
+ * Check if a ZIP file (as bytes) is a GTFS archive by looking for characteristic GTFS files.
5
+ * GTFS archives must contain at least agency.txt, stops.txt, routes.txt, trips.txt,
6
+ * and stop_times.txt according to the GTFS specification.
7
+ */
8
+ export function isGtfsZip(bytes) {
9
+ // GTFS required files per the spec
10
+ const requiredGtfsFiles = [
11
+ "agency.txt",
12
+ "stops.txt",
13
+ "routes.txt",
14
+ "trips.txt",
15
+ "stop_times.txt",
16
+ ];
17
+ // Find filenames in the ZIP by scanning for the local file headers
18
+ // ZIP local file header signature: 0x04034b50 (little-endian: 50 4b 03 04)
19
+ const foundFiles = new Set();
20
+ const decoder = new TextDecoder();
21
+ let pos = 0;
22
+ while (pos < bytes.length - 30) {
23
+ // Check for ZIP local file header signature
24
+ const isLocalHeader = bytes[pos] === 0x50 &&
25
+ bytes[pos + 1] === 0x4b &&
26
+ bytes[pos + 2] === 0x03 &&
27
+ bytes[pos + 3] === 0x04;
28
+ if (isLocalHeader) {
29
+ // Read filename length at offset 26-27 (little-endian)
30
+ const nameLen = (bytes[pos + 26] ?? 0) | ((bytes[pos + 27] ?? 0) << 8);
31
+ // Read extra field length at offset 28-29 (little-endian)
32
+ const extraLen = (bytes[pos + 28] ?? 0) | ((bytes[pos + 29] ?? 0) << 8);
33
+ // Defensive bounds check
34
+ if (nameLen < 0 || extraLen < 0)
35
+ break;
36
+ if (pos + 30 + nameLen + extraLen > bytes.length)
37
+ break;
38
+ // General purpose bit flag at offset 6-7 (little-endian)
39
+ // Bit 3 indicates the presence of a data descriptor, in which case
40
+ // the compressed size fields in the local header are zero and the
41
+ // actual sizes follow the compressed data.
42
+ const flags = (bytes[pos + 6] ?? 0) | ((bytes[pos + 7] ?? 0) << 8);
43
+ const hasDataDescriptor = (flags & 0x0008) !== 0;
44
+ // Extract filename (starts at offset 30)
45
+ const nameBytes = bytes.slice(pos + 30, pos + 30 + nameLen);
46
+ const filename = decoder.decode(nameBytes);
47
+ // Normalize path - extract just the filename part
48
+ const basename = filename.replace(/^.*\//, "").toLowerCase();
49
+ if (basename) {
50
+ foundFiles.add(basename);
51
+ }
52
+ if (!hasDataDescriptor) {
53
+ // Read compressed size at offset 18-21 (little-endian).
54
+ // Use >>> 0 to ensure unsigned 32-bit interpretation, since
55
+ // JavaScript bitwise operations return signed 32-bit integers.
56
+ // Without this, files >= 2GB would produce negative values.
57
+ const compSize = ((bytes[pos + 18] ?? 0) |
58
+ ((bytes[pos + 19] ?? 0) << 8) |
59
+ ((bytes[pos + 20] ?? 0) << 16) |
60
+ ((bytes[pos + 21] ?? 0) << 24)) >>>
61
+ 0;
62
+ // Move to next entry using the known compressed size
63
+ pos += 30 + nameLen + extraLen + compSize;
64
+ }
65
+ else {
66
+ // When a data descriptor is present, the compressed size is not
67
+ // available in the local header. Skip past the header, filename,
68
+ // and extra fields, then scan forward for the next local header
69
+ // signature. This avoids getting stuck at the same position when
70
+ // the compressed size field is zero.
71
+ pos += 30 + nameLen + extraLen;
72
+ while (pos < bytes.length - 3) {
73
+ const nextIsHeader = bytes[pos] === 0x50 &&
74
+ bytes[pos + 1] === 0x4b &&
75
+ bytes[pos + 2] === 0x03 &&
76
+ bytes[pos + 3] === 0x04;
77
+ if (nextIsHeader)
78
+ break;
79
+ pos++;
80
+ }
81
+ }
82
+ }
83
+ else {
84
+ pos++;
85
+ }
86
+ }
87
+ // Check if all required GTFS files are present
88
+ return requiredGtfsFiles.every((f) => foundFiles.has(f));
89
+ }
90
+ /**
91
+ * Convert a GTFS stop to OSM tags.
92
+ */
93
+ export function stopToTags(stop) {
94
+ const tags = {
95
+ public_transport: "platform",
96
+ };
97
+ if (stop.stop_name)
98
+ tags["name"] = stop.stop_name;
99
+ if (stop.stop_id)
100
+ tags["ref"] = stop.stop_id;
101
+ if (stop.stop_code)
102
+ tags["ref:gtfs:stop_code"] = stop.stop_code;
103
+ if (stop.stop_desc)
104
+ tags["description"] = stop.stop_desc;
105
+ if (stop.stop_url)
106
+ tags["website"] = stop.stop_url;
107
+ if (stop.platform_code)
108
+ tags["ref:platform"] = stop.platform_code;
109
+ // Location type determines more specific tagging
110
+ const locationType = stop.location_type ?? "0";
111
+ switch (locationType) {
112
+ case "1":
113
+ tags["public_transport"] = "station";
114
+ break;
115
+ case "2":
116
+ // Entrances are not platforms - remove the default and use railway tag
117
+ delete tags["public_transport"];
118
+ tags["railway"] = "subway_entrance";
119
+ break;
120
+ case "3":
121
+ // Generic node - keep as platform
122
+ break;
123
+ case "4":
124
+ tags["public_transport"] = "platform";
125
+ break;
126
+ }
127
+ // Wheelchair accessibility
128
+ const wheelchair = wheelchairBoardingToOsm(stop.wheelchair_boarding);
129
+ if (wheelchair)
130
+ tags["wheelchair"] = wheelchair;
131
+ return tags;
132
+ }
133
+ /**
134
+ * Convert a GTFS route to OSM tags.
135
+ */
136
+ export function routeToTags(route) {
137
+ const tags = {
138
+ route: routeTypeToOsmRoute(route.route_type),
139
+ };
140
+ // Use long name if available, otherwise short name
141
+ if (route.route_long_name) {
142
+ tags["name"] = route.route_long_name;
143
+ }
144
+ else if (route.route_short_name) {
145
+ tags["name"] = route.route_short_name;
146
+ }
147
+ if (route.route_short_name)
148
+ tags["ref"] = route.route_short_name;
149
+ if (route.route_id)
150
+ tags["ref:gtfs:route_id"] = route.route_id;
151
+ if (route.route_desc)
152
+ tags["description"] = route.route_desc;
153
+ if (route.route_url)
154
+ tags["website"] = route.route_url;
155
+ // Route color (validate and normalize hex color)
156
+ const color = normalizeHexColor(route.route_color);
157
+ if (color)
158
+ tags["color"] = color;
159
+ const textColor = normalizeHexColor(route.route_text_color);
160
+ if (textColor)
161
+ tags["text_color"] = textColor;
162
+ // Route type as additional tag
163
+ tags["gtfs:route_type"] = route.route_type;
164
+ return tags;
165
+ }
166
+ /**
167
+ * Convert a GTFS trip to OSM tags.
168
+ */
169
+ export function tripToTags(trip) {
170
+ const tags = {};
171
+ tags["ref:gtfs:trip_id"] = trip.trip_id;
172
+ if (trip.service_id)
173
+ tags["ref:gtfs:service_id"] = trip.service_id;
174
+ if (trip.trip_headsign)
175
+ tags["ref:gtfs:trip_headsign"] = trip.trip_headsign;
176
+ if (trip.trip_short_name)
177
+ tags["ref:gtfs:trip_short_name"] = trip.trip_short_name;
178
+ if (trip.direction_id)
179
+ tags["ref:gtfs:direction_id"] = trip.direction_id;
180
+ if (trip.block_id)
181
+ tags["ref:gtfs:block_id"] = trip.block_id;
182
+ if (trip.shape_id)
183
+ tags["ref:gtfs:shape_id"] = trip.shape_id;
184
+ if (trip.wheelchair_accessible)
185
+ tags["ref:gtfs:wheelchair_accessible"] = trip.wheelchair_accessible;
186
+ if (trip.bikes_allowed)
187
+ tags["ref:gtfs:bikes_allowed"] = trip.bikes_allowed;
188
+ return tags;
189
+ }
190
+ /**
191
+ * Create a ReadableStream of text from file bytes.
192
+ */
193
+ export function bytesToTextStream(bytes) {
194
+ const decoder = new TextDecoder();
195
+ let offset = 0;
196
+ const chunkSize = 64 * 1024; // 64KB chunks
197
+ return new ReadableStream({
198
+ pull(controller) {
199
+ if (offset >= bytes.length) {
200
+ controller.close();
201
+ return;
202
+ }
203
+ const end = Math.min(offset + chunkSize, bytes.length);
204
+ const chunk = bytes.subarray(offset, end);
205
+ offset = end;
206
+ controller.enqueue(decoder.decode(chunk, { stream: offset < bytes.length }));
207
+ },
208
+ });
209
+ }
210
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=from-gtfs.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"from-gtfs.test.d.ts","sourceRoot":"","sources":["../../test/from-gtfs.test.ts"],"names":[],"mappings":""}