@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 @@
1
+ {"version":3,"file":"gtfs-archive.js","sourceRoot":"","sources":["../src/gtfs-archive.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,KAAK,EAAgB,MAAM,WAAW,CAAA;AAS/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAiB3C;;;;;;;GAOG;AACH,MAAM,OAAO,WAAW;IACf,OAAO,CAAsB;IAErC,YAAoB,OAA6B;QAChD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAiC;QAC/C,MAAM,KAAK,GACV,OAAO,YAAY,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,CAAA;QAClE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;QAE1B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAA;QAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,gDAAgD;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;YAC/C,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACxB,CAAC;QACF,CAAC;QAED,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,QAAgB;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClC,CAAC;IAED;;OAEG;IACH,SAAS;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACvC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CAAC,QAAgB;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACxC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QAEvB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QACzB,OAAO,IAAI,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;IACnD,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,CAAC,IAAI,CACV,QAAW;QAEX,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAC/C,IAAI,CAAC,KAAK;YAAE,OAAM;QAElB,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA;QAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CACvC,IAAI,cAAc,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAC1C,CAAA;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAA;QACpC,IAAI,CAAC;YACJ,OAAO,IAAI,EAAE,CAAC;gBACb,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;gBAC3C,IAAI,IAAI;oBAAE,MAAK;gBACf,MAAM,KAAsC,CAAA;YAC7C,CAAC;QACF,CAAC;gBAAS,CAAC;YACV,MAAM,CAAC,WAAW,EAAE,CAAA;QACrB,CAAC;IACF,CAAC;CACD"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @osmix/gtfs - Convert GTFS transit feeds to OSM format.
3
+ *
4
+ * Parses zipped GTFS files lazily and converts transit data to OpenStreetMap entities:
5
+ * - **Stops** become **Nodes** with public transport tags
6
+ * - **Routes** become **Ways** with shape geometry
7
+ *
8
+ * Files are only parsed when needed, not upfront.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { fromGtfs } from "@osmix/gtfs"
13
+ *
14
+ * const response = await fetch("https://example.com/gtfs.zip")
15
+ * const zipData = await response.arrayBuffer()
16
+ * const osm = await fromGtfs(zipData, { id: "transit" })
17
+ *
18
+ * console.log(`Imported ${osm.nodes.size} stops and ${osm.ways.size} routes`)
19
+ * ```
20
+ *
21
+ * @example Using GtfsArchive directly for custom processing
22
+ * ```ts
23
+ * import { GtfsArchive } from "@osmix/gtfs"
24
+ *
25
+ * const archive = GtfsArchive.fromZip(zipData)
26
+ *
27
+ * // Only parse stops - other files remain unread
28
+ * for await (const stop of archive.iterStops()) {
29
+ * console.log(stop.stop_name)
30
+ * }
31
+ * ```
32
+ *
33
+ * @module @osmix/gtfs
34
+ */
35
+ export { fromGtfs, GtfsOsmBuilder } from "./from-gtfs";
36
+ export { GtfsArchive, type GtfsFileName, type GtfsFileTypeMap, } from "./gtfs-archive";
37
+ export { type GtfsAgency, type GtfsConversionOptions, type GtfsFeed, type GtfsRoute, type GtfsShapePoint, type GtfsStop, type GtfsStopTime, type GtfsTrip, routeTypeToOsmRoute, wheelchairBoardingToOsm, } from "./types";
38
+ export { isGtfsZip } from "./utils";
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EACN,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,GACpB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACN,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,mBAAmB,EACnB,uBAAuB,GACvB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @osmix/gtfs - Convert GTFS transit feeds to OSM format.
3
+ *
4
+ * Parses zipped GTFS files lazily and converts transit data to OpenStreetMap entities:
5
+ * - **Stops** become **Nodes** with public transport tags
6
+ * - **Routes** become **Ways** with shape geometry
7
+ *
8
+ * Files are only parsed when needed, not upfront.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { fromGtfs } from "@osmix/gtfs"
13
+ *
14
+ * const response = await fetch("https://example.com/gtfs.zip")
15
+ * const zipData = await response.arrayBuffer()
16
+ * const osm = await fromGtfs(zipData, { id: "transit" })
17
+ *
18
+ * console.log(`Imported ${osm.nodes.size} stops and ${osm.ways.size} routes`)
19
+ * ```
20
+ *
21
+ * @example Using GtfsArchive directly for custom processing
22
+ * ```ts
23
+ * import { GtfsArchive } from "@osmix/gtfs"
24
+ *
25
+ * const archive = GtfsArchive.fromZip(zipData)
26
+ *
27
+ * // Only parse stops - other files remain unread
28
+ * for await (const stop of archive.iterStops()) {
29
+ * console.log(stop.stop_name)
30
+ * }
31
+ * ```
32
+ *
33
+ * @module @osmix/gtfs
34
+ */
35
+ export { fromGtfs, GtfsOsmBuilder } from "./from-gtfs";
36
+ export { GtfsArchive, } from "./gtfs-archive";
37
+ export { routeTypeToOsmRoute, wheelchairBoardingToOsm, } from "./types";
38
+ export { isGtfsZip } from "./utils";
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EACN,WAAW,GAGX,MAAM,gBAAgB,CAAA;AACvB,OAAO,EASN,mBAAmB,EACnB,uBAAuB,GACvB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * GTFS to OSM conversion utilities.
3
+ *
4
+ * Imports GTFS transit feeds into Osm indexes, mapping:
5
+ * - Stops → Nodes with transit tags
6
+ * - Routes → Ways with shape geometry
7
+ *
8
+ * Uses lazy, on-demand parsing - files are only parsed when needed.
9
+ *
10
+ * @module
11
+ */
12
+ import { Osm, type OsmOptions } from "@osmix/core";
13
+ import { type ProgressEvent } from "@osmix/shared/progress";
14
+ import { GtfsArchive } from "./gtfs-archive";
15
+ import type { GtfsConversionOptions } from "./types";
16
+ /**
17
+ * Create an Osm index from a zipped GTFS file.
18
+ *
19
+ * Parses the GTFS zip lazily - only reading files when needed.
20
+ * Converts stops and routes to OSM entities:
21
+ * - Stops become nodes with transit-related tags
22
+ * - Routes become ways with shape geometry (if available) or stop sequence
23
+ *
24
+ * @param zipData - The GTFS zip file as ArrayBuffer or Uint8Array
25
+ * @param options - Osm index options (id, header)
26
+ * @param gtfsOptions - GTFS conversion options
27
+ * @param onProgress - Progress callback for UI feedback
28
+ * @returns Populated Osm index with built indexes
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { fromGtfs } from "@osmix/gtfs"
33
+ *
34
+ * const response = await fetch("https://example.com/gtfs.zip")
35
+ * const zipData = await response.arrayBuffer()
36
+ * const osm = await fromGtfs(zipData, { id: "transit" })
37
+ *
38
+ * console.log(`Imported ${osm.nodes.size} stops`)
39
+ * ```
40
+ */
41
+ export declare function fromGtfs(zipData: ArrayBuffer | Uint8Array, options?: Partial<OsmOptions>, gtfsOptions?: GtfsConversionOptions, onProgress?: (progress: ProgressEvent) => void): Promise<Osm>;
42
+ /**
43
+ * Builder class for converting GTFS data to OSM entities.
44
+ *
45
+ * Uses lazy parsing - only reads GTFS files when needed.
46
+ */
47
+ export declare class GtfsOsmBuilder {
48
+ private osm;
49
+ private onProgress;
50
+ private nextNodeId;
51
+ private nextWayId;
52
+ private stopIdToNodeId;
53
+ constructor(osmOptions?: Partial<OsmOptions>, onProgress?: (progress: ProgressEvent) => void);
54
+ /**
55
+ * Process GTFS stops into OSM nodes.
56
+ * Uses streaming iteration to avoid loading all stops at once.
57
+ */
58
+ processStops(archive: GtfsArchive): Promise<void>;
59
+ /**
60
+ * Process GTFS routes into OSM ways.
61
+ * Creates one way per unique (shape_id, route_id) pair, so each route gets
62
+ * its own way with correct metadata even when routes share the same shape.
63
+ *
64
+ * @param archive - The GTFS archive
65
+ */
66
+ processRoutes(archive: GtfsArchive): Promise<void>;
67
+ /**
68
+ * Create a way from shape points.
69
+ */
70
+ private createWayFromShape;
71
+ /**
72
+ * Build the OSM index with all entities.
73
+ */
74
+ buildOsm(): Osm;
75
+ }
76
+ //# sourceMappingURL=from-gtfs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"from-gtfs.d.ts","sourceRoot":"","sources":["../../src/from-gtfs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,GAAG,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAEN,KAAK,aAAa,EAElB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,qBAAqB,EAAkB,MAAM,SAAS,CAAA;AAGpE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,QAAQ,CAC7B,OAAO,EAAE,WAAW,GAAG,UAAU,EACjC,OAAO,GAAE,OAAO,CAAC,UAAU,CAAM,EACjC,WAAW,GAAE,qBAA0B,EACvC,UAAU,GAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAkB,GACzD,OAAO,CAAC,GAAG,CAAC,CAad;AAED;;;;GAIG;AACH,qBAAa,cAAc;IAC1B,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,UAAU,CAAmC;IAErD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,SAAS,CAAK;IAGtB,OAAO,CAAC,cAAc,CAA4B;gBAGjD,UAAU,GAAE,OAAO,CAAC,UAAU,CAAM,EACpC,UAAU,GAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAkB;IAM5D;;;OAGG;IACG,YAAY,CAAC,OAAO,EAAE,WAAW;IAgCvC;;;;;;OAMG;IACG,aAAa,CAAC,OAAO,EAAE,WAAW;IAmFxC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA6B1B;;OAEG;IACH,QAAQ,IAAI,GAAG;CAMf"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * GTFS to OSM conversion utilities.
3
+ *
4
+ * Imports GTFS transit feeds into Osm indexes, mapping:
5
+ * - Stops → Nodes with transit tags
6
+ * - Routes → Ways with shape geometry
7
+ *
8
+ * Uses lazy, on-demand parsing - files are only parsed when needed.
9
+ *
10
+ * @module
11
+ */
12
+ import { Osm } from "@osmix/core";
13
+ import { logProgress, progressEvent, } from "@osmix/shared/progress";
14
+ import { GtfsArchive } from "./gtfs-archive";
15
+ import { routeToTags, stopToTags } from "./utils";
16
+ /**
17
+ * Create an Osm index from a zipped GTFS file.
18
+ *
19
+ * Parses the GTFS zip lazily - only reading files when needed.
20
+ * Converts stops and routes to OSM entities:
21
+ * - Stops become nodes with transit-related tags
22
+ * - Routes become ways with shape geometry (if available) or stop sequence
23
+ *
24
+ * @param zipData - The GTFS zip file as ArrayBuffer or Uint8Array
25
+ * @param options - Osm index options (id, header)
26
+ * @param gtfsOptions - GTFS conversion options
27
+ * @param onProgress - Progress callback for UI feedback
28
+ * @returns Populated Osm index with built indexes
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { fromGtfs } from "@osmix/gtfs"
33
+ *
34
+ * const response = await fetch("https://example.com/gtfs.zip")
35
+ * const zipData = await response.arrayBuffer()
36
+ * const osm = await fromGtfs(zipData, { id: "transit" })
37
+ *
38
+ * console.log(`Imported ${osm.nodes.size} stops`)
39
+ * ```
40
+ */
41
+ export async function fromGtfs(zipData, options = {}, gtfsOptions = {}, onProgress = logProgress) {
42
+ onProgress(progressEvent("Opening GTFS archive..."));
43
+ const archive = GtfsArchive.fromZip(zipData);
44
+ const builder = new GtfsOsmBuilder(options, onProgress);
45
+ if (gtfsOptions.includeStops ?? true) {
46
+ await builder.processStops(archive);
47
+ }
48
+ if (gtfsOptions.includeRoutes ?? true) {
49
+ await builder.processRoutes(archive);
50
+ }
51
+ return builder.buildOsm();
52
+ }
53
+ /**
54
+ * Builder class for converting GTFS data to OSM entities.
55
+ *
56
+ * Uses lazy parsing - only reads GTFS files when needed.
57
+ */
58
+ export class GtfsOsmBuilder {
59
+ osm;
60
+ onProgress;
61
+ nextNodeId = -1;
62
+ nextWayId = -1;
63
+ // Map GTFS stop_id to OSM node ID
64
+ stopIdToNodeId = new Map();
65
+ constructor(osmOptions = {}, onProgress = logProgress) {
66
+ this.osm = new Osm(osmOptions);
67
+ this.onProgress = onProgress;
68
+ }
69
+ /**
70
+ * Process GTFS stops into OSM nodes.
71
+ * Uses streaming iteration to avoid loading all stops at once.
72
+ */
73
+ async processStops(archive) {
74
+ let count = 0;
75
+ this.onProgress(progressEvent("Processing stops..."));
76
+ for await (const stop of archive.iter("stops.txt")) {
77
+ const lat = Number.parseFloat(stop.stop_lat);
78
+ const lon = Number.parseFloat(stop.stop_lon);
79
+ if (Number.isNaN(lat) || Number.isNaN(lon))
80
+ continue;
81
+ const tags = stopToTags(stop);
82
+ const nodeId = this.nextNodeId--;
83
+ this.osm.nodes.addNode({
84
+ id: nodeId,
85
+ lat,
86
+ lon,
87
+ tags,
88
+ });
89
+ this.stopIdToNodeId.set(stop.stop_id, nodeId);
90
+ count++;
91
+ if (count % 1000 === 0) {
92
+ this.onProgress(progressEvent(`Processed ${count} stops...`));
93
+ }
94
+ }
95
+ this.onProgress(progressEvent(`Added ${count} stops as nodes`));
96
+ }
97
+ /**
98
+ * Process GTFS routes into OSM ways.
99
+ * Creates one way per unique (shape_id, route_id) pair, so each route gets
100
+ * its own way with correct metadata even when routes share the same shape.
101
+ *
102
+ * @param archive - The GTFS archive
103
+ */
104
+ async processRoutes(archive) {
105
+ this.onProgress(progressEvent("Processing routes..."));
106
+ // Build shape lookup if shapes exist
107
+ const shapeMap = new Map();
108
+ if (archive.hasFile("shapes.txt")) {
109
+ this.onProgress(progressEvent("Loading shape data..."));
110
+ for await (const point of archive.iter("shapes.txt")) {
111
+ const points = shapeMap.get(point.shape_id) ?? [];
112
+ points.push(point);
113
+ shapeMap.set(point.shape_id, points);
114
+ }
115
+ // Sort each shape by sequence
116
+ for (const points of shapeMap.values()) {
117
+ points.sort((a, b) => Number.parseInt(a.shape_pt_sequence, 10) -
118
+ Number.parseInt(b.shape_pt_sequence, 10));
119
+ }
120
+ }
121
+ else {
122
+ throw Error("No shape data found. Cannot process routes.");
123
+ }
124
+ // Group trips by (shape_id, route_id) to ensure each route gets its own way
125
+ // even when multiple routes share the same shape geometry
126
+ const shapeRouteToTrips = new Map();
127
+ this.onProgress(progressEvent("Loading trip data..."));
128
+ for await (const trip of archive.iter("trips.txt")) {
129
+ if (!trip.shape_id)
130
+ continue;
131
+ const key = `${trip.shape_id}:${trip.route_id}`;
132
+ const existing = shapeRouteToTrips.get(key);
133
+ if (existing) {
134
+ existing.tripIds.push(trip.trip_id);
135
+ }
136
+ else {
137
+ shapeRouteToTrips.set(key, { tripIds: [trip.trip_id] });
138
+ }
139
+ }
140
+ // Load routes into a map for lookup
141
+ const routeMap = new Map();
142
+ for await (const route of archive.iter("routes.txt")) {
143
+ routeMap.set(route.route_id, routeToTags(route));
144
+ }
145
+ // Process unique (shape, route) pairs - one way per combination
146
+ let count = 0;
147
+ for (const [key, { tripIds }] of shapeRouteToTrips) {
148
+ const [shapeId, routeId] = key.split(":");
149
+ const routeTags = routeMap.get(routeId);
150
+ if (!routeTags)
151
+ continue;
152
+ const shapePoints = shapeMap.get(shapeId);
153
+ if (!shapePoints || shapePoints.length < 2) {
154
+ this.onProgress(progressEvent(`No shape data found for shape ${shapeId}`, "error"));
155
+ continue;
156
+ }
157
+ // Build tags with route info and all trip IDs for this route
158
+ const tags = {
159
+ ...routeTags,
160
+ "gtfs:shape_id": shapeId,
161
+ "gtfs:trip_ids": tripIds.join(";"),
162
+ "gtfs:trip_count": tripIds.length,
163
+ };
164
+ // Create way from shape points
165
+ this.createWayFromShape(tags, shapePoints);
166
+ count++;
167
+ if (count % 100 === 0) {
168
+ this.onProgress(progressEvent(`Processed ${count} shape-route pairs...`));
169
+ }
170
+ }
171
+ this.onProgress(progressEvent(`Added ${count} shape-route pairs as ways`));
172
+ }
173
+ /**
174
+ * Create a way from shape points.
175
+ */
176
+ createWayFromShape(tags, shapePoints) {
177
+ const nodeRefs = [];
178
+ for (const point of shapePoints) {
179
+ const lat = Number.parseFloat(point.shape_pt_lat);
180
+ const lon = Number.parseFloat(point.shape_pt_lon);
181
+ if (Number.isNaN(lat) || Number.isNaN(lon))
182
+ continue;
183
+ // Create a node for this shape point
184
+ const nodeId = this.nextNodeId--;
185
+ this.osm.nodes.addNode({
186
+ id: nodeId,
187
+ lat,
188
+ lon,
189
+ });
190
+ nodeRefs.push(nodeId);
191
+ }
192
+ if (nodeRefs.length >= 2) {
193
+ const wayId = this.nextWayId--;
194
+ this.osm.ways.addWay({
195
+ id: wayId,
196
+ refs: nodeRefs,
197
+ tags,
198
+ });
199
+ }
200
+ }
201
+ /**
202
+ * Build the OSM index with all entities.
203
+ */
204
+ buildOsm() {
205
+ this.onProgress(progressEvent("Building indexes..."));
206
+ this.osm.buildIndexes();
207
+ this.osm.buildSpatialIndexes();
208
+ return this.osm;
209
+ }
210
+ }
211
+ //# sourceMappingURL=from-gtfs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"from-gtfs.js","sourceRoot":"","sources":["../../src/from-gtfs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Lazy GTFS archive parser with streaming CSV support.
3
+ *
4
+ * Only parses CSV files when they are accessed, not upfront.
5
+ * Uses @std/csv CsvParseStream for true line-by-line streaming.
6
+ *
7
+ * @module
8
+ */
9
+ import type { GtfsAgency, GtfsRoute, GtfsShapePoint, GtfsStop, GtfsStopTime, GtfsTrip } from "./types";
10
+ /**
11
+ * Map of GTFS filenames to their record types.
12
+ */
13
+ export interface GtfsFileTypeMap {
14
+ "agency.txt": GtfsAgency;
15
+ "stops.txt": GtfsStop;
16
+ "routes.txt": GtfsRoute;
17
+ "trips.txt": GtfsTrip;
18
+ "stop_times.txt": GtfsStopTime;
19
+ "shapes.txt": GtfsShapePoint;
20
+ }
21
+ /** Valid GTFS filenames that can be parsed. */
22
+ export type GtfsFileName = keyof GtfsFileTypeMap;
23
+ /**
24
+ * Lazy GTFS archive that only parses files on demand.
25
+ *
26
+ * Files are read from the zip and parsed only when their
27
+ * corresponding getter is called for the first time.
28
+ * Streaming iterators parse CSV line-by-line without loading
29
+ * the entire file into memory.
30
+ */
31
+ export declare class GtfsArchive {
32
+ private entries;
33
+ private constructor();
34
+ /**
35
+ * Create a GtfsArchive from zip data.
36
+ */
37
+ static fromZip(zipData: ArrayBuffer | Uint8Array): GtfsArchive;
38
+ /**
39
+ * Check if a file exists in the archive.
40
+ */
41
+ hasFile(filename: string): boolean;
42
+ /**
43
+ * List all files in the archive.
44
+ */
45
+ listFiles(): string[];
46
+ /**
47
+ * Get a readable stream of bytes for a file.
48
+ */
49
+ private getFileBytes;
50
+ /**
51
+ * Stream parse a CSV file, yielding typed records one at a time.
52
+ *
53
+ * The return type is automatically inferred based on the filename:
54
+ * - `"stops.txt"` → `AsyncGenerator<GtfsStop>`
55
+ * - `"routes.txt"` → `AsyncGenerator<GtfsRoute>`
56
+ * - `"shapes.txt"` → `AsyncGenerator<GtfsShapePoint>`
57
+ * - etc.
58
+ *
59
+ * @param filename - The GTFS filename to parse (e.g., "stops.txt")
60
+ * @returns An async generator yielding typed records
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * for await (const stop of archive.iter("stops.txt")) {
65
+ * console.log(stop.stop_name) // TypeScript knows this is GtfsStop
66
+ * }
67
+ * ```
68
+ */
69
+ iter<F extends GtfsFileName>(filename: F): AsyncGenerator<GtfsFileTypeMap[F], void, unknown>;
70
+ }
71
+ //# sourceMappingURL=gtfs-archive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gtfs-archive.d.ts","sourceRoot":"","sources":["../../src/gtfs-archive.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EACX,UAAU,EACV,SAAS,EACT,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,MAAM,SAAS,CAAA;AAGhB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,YAAY,EAAE,UAAU,CAAA;IACxB,WAAW,EAAE,QAAQ,CAAA;IACrB,YAAY,EAAE,SAAS,CAAA;IACvB,WAAW,EAAE,QAAQ,CAAA;IACrB,gBAAgB,EAAE,YAAY,CAAA;IAC9B,YAAY,EAAE,cAAc,CAAA;CAC5B;AAED,+CAA+C;AAC/C,MAAM,MAAM,YAAY,GAAG,MAAM,eAAe,CAAA;AAEhD;;;;;;;GAOG;AACH,qBAAa,WAAW;IACvB,OAAO,CAAC,OAAO,CAAsB;IAErC,OAAO;IAIP;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,GAAG,WAAW;IAiB9D;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIlC;;OAEG;IACH,SAAS,IAAI,MAAM,EAAE;IAIrB;;OAEG;YACW,YAAY;IAQ1B;;;;;;;;;;;;;;;;;;OAkBG;IACI,IAAI,CAAC,CAAC,SAAS,YAAY,EACjC,QAAQ,EAAE,CAAC,GACT,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC;CAoBpD"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Lazy GTFS archive parser with streaming CSV support.
3
+ *
4
+ * Only parses CSV files when they are accessed, not upfront.
5
+ * Uses @std/csv CsvParseStream for true line-by-line streaming.
6
+ *
7
+ * @module
8
+ */
9
+ import { CsvParseStream } from "@std/csv/parse-stream";
10
+ import { unzip } from "but-unzip";
11
+ import { bytesToTextStream } from "./utils";
12
+ /**
13
+ * Lazy GTFS archive that only parses files on demand.
14
+ *
15
+ * Files are read from the zip and parsed only when their
16
+ * corresponding getter is called for the first time.
17
+ * Streaming iterators parse CSV line-by-line without loading
18
+ * the entire file into memory.
19
+ */
20
+ export class GtfsArchive {
21
+ entries;
22
+ constructor(entries) {
23
+ this.entries = entries;
24
+ }
25
+ /**
26
+ * Create a GtfsArchive from zip data.
27
+ */
28
+ static fromZip(zipData) {
29
+ const bytes = zipData instanceof Uint8Array ? zipData : new Uint8Array(zipData);
30
+ const items = unzip(bytes);
31
+ const entries = new Map();
32
+ for (const item of items) {
33
+ // Remove directory prefix and store by filename
34
+ const name = item.filename.replace(/^.*\//, "");
35
+ if (name.endsWith(".txt")) {
36
+ entries.set(name, item);
37
+ }
38
+ }
39
+ return new GtfsArchive(entries);
40
+ }
41
+ /**
42
+ * Check if a file exists in the archive.
43
+ */
44
+ hasFile(filename) {
45
+ return this.entries.has(filename);
46
+ }
47
+ /**
48
+ * List all files in the archive.
49
+ */
50
+ listFiles() {
51
+ return Array.from(this.entries.keys());
52
+ }
53
+ /**
54
+ * Get a readable stream of bytes for a file.
55
+ */
56
+ async getFileBytes(filename) {
57
+ const entry = this.entries.get(filename);
58
+ if (!entry)
59
+ return null;
60
+ const data = entry.read();
61
+ return data instanceof Promise ? await data : data;
62
+ }
63
+ /**
64
+ * Stream parse a CSV file, yielding typed records one at a time.
65
+ *
66
+ * The return type is automatically inferred based on the filename:
67
+ * - `"stops.txt"` → `AsyncGenerator<GtfsStop>`
68
+ * - `"routes.txt"` → `AsyncGenerator<GtfsRoute>`
69
+ * - `"shapes.txt"` → `AsyncGenerator<GtfsShapePoint>`
70
+ * - etc.
71
+ *
72
+ * @param filename - The GTFS filename to parse (e.g., "stops.txt")
73
+ * @returns An async generator yielding typed records
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * for await (const stop of archive.iter("stops.txt")) {
78
+ * console.log(stop.stop_name) // TypeScript knows this is GtfsStop
79
+ * }
80
+ * ```
81
+ */
82
+ async *iter(filename) {
83
+ const bytes = await this.getFileBytes(filename);
84
+ if (!bytes)
85
+ return;
86
+ const textStream = bytesToTextStream(bytes);
87
+ const csvStream = textStream.pipeThrough(new CsvParseStream({ skipFirstRow: true }));
88
+ const reader = csvStream.getReader();
89
+ try {
90
+ while (true) {
91
+ const { value, done } = await reader.read();
92
+ if (done)
93
+ break;
94
+ yield value;
95
+ }
96
+ }
97
+ finally {
98
+ reader.releaseLock();
99
+ }
100
+ }
101
+ }
102
+ //# sourceMappingURL=gtfs-archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gtfs-archive.js","sourceRoot":"","sources":["../../src/gtfs-archive.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,KAAK,EAAgB,MAAM,WAAW,CAAA;AAS/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAiB3C;;;;;;;GAOG;AACH,MAAM,OAAO,WAAW;IACf,OAAO,CAAsB;IAErC,YAAoB,OAA6B;QAChD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAiC;QAC/C,MAAM,KAAK,GACV,OAAO,YAAY,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,CAAA;QAClE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAA;QAE1B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAA;QAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,gDAAgD;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;YAC/C,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACxB,CAAC;QACF,CAAC;QAED,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAA;IAChC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,QAAgB;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClC,CAAC;IAED;;OAEG;IACH,SAAS;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IACvC,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CAAC,QAAgB;QAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACxC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QAEvB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QACzB,OAAO,IAAI,YAAY,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;IACnD,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAK,CAAC,CAAC,IAAI,CACV,QAAW;QAEX,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAC/C,IAAI,CAAC,KAAK;YAAE,OAAM;QAElB,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA;QAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,CACvC,IAAI,cAAc,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAC1C,CAAA;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAA;QACpC,IAAI,CAAC;YACJ,OAAO,IAAI,EAAE,CAAC;gBACb,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAA;gBAC3C,IAAI,IAAI;oBAAE,MAAK;gBACf,MAAM,KAAsC,CAAA;YAC7C,CAAC;QACF,CAAC;gBAAS,CAAC;YACV,MAAM,CAAC,WAAW,EAAE,CAAA;QACrB,CAAC;IACF,CAAC;CACD"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @osmix/gtfs - Convert GTFS transit feeds to OSM format.
3
+ *
4
+ * Parses zipped GTFS files lazily and converts transit data to OpenStreetMap entities:
5
+ * - **Stops** become **Nodes** with public transport tags
6
+ * - **Routes** become **Ways** with shape geometry
7
+ *
8
+ * Files are only parsed when needed, not upfront.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { fromGtfs } from "@osmix/gtfs"
13
+ *
14
+ * const response = await fetch("https://example.com/gtfs.zip")
15
+ * const zipData = await response.arrayBuffer()
16
+ * const osm = await fromGtfs(zipData, { id: "transit" })
17
+ *
18
+ * console.log(`Imported ${osm.nodes.size} stops and ${osm.ways.size} routes`)
19
+ * ```
20
+ *
21
+ * @example Using GtfsArchive directly for custom processing
22
+ * ```ts
23
+ * import { GtfsArchive } from "@osmix/gtfs"
24
+ *
25
+ * const archive = GtfsArchive.fromZip(zipData)
26
+ *
27
+ * // Only parse stops - other files remain unread
28
+ * for await (const stop of archive.iterStops()) {
29
+ * console.log(stop.stop_name)
30
+ * }
31
+ * ```
32
+ *
33
+ * @module @osmix/gtfs
34
+ */
35
+ export { fromGtfs, GtfsOsmBuilder } from "./from-gtfs";
36
+ export { GtfsArchive, type GtfsFileName, type GtfsFileTypeMap, } from "./gtfs-archive";
37
+ export { type GtfsAgency, type GtfsConversionOptions, type GtfsFeed, type GtfsRoute, type GtfsShapePoint, type GtfsStop, type GtfsStopTime, type GtfsTrip, routeTypeToOsmRoute, wheelchairBoardingToOsm, } from "./types";
38
+ export { isGtfsZip } from "./utils";
39
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EACN,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,eAAe,GACpB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACN,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,mBAAmB,EACnB,uBAAuB,GACvB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @osmix/gtfs - Convert GTFS transit feeds to OSM format.
3
+ *
4
+ * Parses zipped GTFS files lazily and converts transit data to OpenStreetMap entities:
5
+ * - **Stops** become **Nodes** with public transport tags
6
+ * - **Routes** become **Ways** with shape geometry
7
+ *
8
+ * Files are only parsed when needed, not upfront.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { fromGtfs } from "@osmix/gtfs"
13
+ *
14
+ * const response = await fetch("https://example.com/gtfs.zip")
15
+ * const zipData = await response.arrayBuffer()
16
+ * const osm = await fromGtfs(zipData, { id: "transit" })
17
+ *
18
+ * console.log(`Imported ${osm.nodes.size} stops and ${osm.ways.size} routes`)
19
+ * ```
20
+ *
21
+ * @example Using GtfsArchive directly for custom processing
22
+ * ```ts
23
+ * import { GtfsArchive } from "@osmix/gtfs"
24
+ *
25
+ * const archive = GtfsArchive.fromZip(zipData)
26
+ *
27
+ * // Only parse stops - other files remain unread
28
+ * for await (const stop of archive.iterStops()) {
29
+ * console.log(stop.stop_name)
30
+ * }
31
+ * ```
32
+ *
33
+ * @module @osmix/gtfs
34
+ */
35
+ export { fromGtfs, GtfsOsmBuilder } from "./from-gtfs";
36
+ export { GtfsArchive, } from "./gtfs-archive";
37
+ export { routeTypeToOsmRoute, wheelchairBoardingToOsm, } from "./types";
38
+ export { isGtfsZip } from "./utils";
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,EACN,WAAW,GAGX,MAAM,gBAAgB,CAAA;AACvB,OAAO,EASN,mBAAmB,EACnB,uBAAuB,GACvB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}