gtfs-sqljs 0.2.0 → 0.3.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/README.md +3 -2
- package/dist/index.d.ts +14 -7
- package/dist/index.js +90 -92
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="logo.svg" alt="gtfs-sqljs logo" width="200" height="200">
|
|
2
|
+
<img src="illustrations/logo.svg" alt="gtfs-sqljs logo" width="200" height="200">
|
|
3
3
|
<h1>gtfs-sqljs</h1>
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/gtfs-sqljs)
|
|
@@ -97,7 +97,8 @@ Full API documentation: [API Reference](https://sysdevrun.github.io/gtfs-sqljs/d
|
|
|
97
97
|
|
|
98
98
|
### Static Methods
|
|
99
99
|
|
|
100
|
-
- `GtfsSqlJs.fromZip(zipPath, options?)` - Create instance from GTFS ZIP file
|
|
100
|
+
- `GtfsSqlJs.fromZip(zipPath, options?)` - Create instance from GTFS ZIP file path or URL
|
|
101
|
+
- `GtfsSqlJs.fromZipData(zipData, options?)` - Create instance from pre-loaded GTFS ZIP data (`ArrayBuffer` or `Uint8Array`)
|
|
101
102
|
- `GtfsSqlJs.fromDatabase(database, options?)` - Create instance from existing database
|
|
102
103
|
|
|
103
104
|
### Instance Methods
|
package/dist/index.d.ts
CHANGED
|
@@ -385,7 +385,8 @@ interface FareAttribute {
|
|
|
385
385
|
price: number;
|
|
386
386
|
currency_type: string;
|
|
387
387
|
payment_method: number;
|
|
388
|
-
transfers
|
|
388
|
+
/** Number of transfers permitted. null means unlimited. */
|
|
389
|
+
transfers: number | null;
|
|
389
390
|
agency_id?: string;
|
|
390
391
|
transfer_duration?: number;
|
|
391
392
|
}
|
|
@@ -713,19 +714,25 @@ declare class GtfsSqlJs {
|
|
|
713
714
|
*/
|
|
714
715
|
private constructor();
|
|
715
716
|
/**
|
|
716
|
-
* Create GtfsSqlJs instance from GTFS ZIP file
|
|
717
|
+
* Create GtfsSqlJs instance from GTFS ZIP file path or URL
|
|
717
718
|
*/
|
|
718
719
|
static fromZip(zipPath: string, options?: Omit<GtfsSqlJsOptions, 'zipPath' | 'database'>): Promise<GtfsSqlJs>;
|
|
720
|
+
/**
|
|
721
|
+
* Create GtfsSqlJs instance from pre-loaded GTFS ZIP data
|
|
722
|
+
* @param source - Optional original path/URL, used for cache key generation and metadata
|
|
723
|
+
*/
|
|
724
|
+
static fromZipData(zipData: ArrayBuffer | Uint8Array, options?: Omit<GtfsSqlJsOptions, 'zipPath' | 'database'>, source?: string): Promise<GtfsSqlJs>;
|
|
719
725
|
/**
|
|
720
726
|
* Create GtfsSqlJs instance from existing SQLite database
|
|
721
727
|
*/
|
|
722
728
|
static fromDatabase(database: ArrayBuffer, options?: Omit<GtfsSqlJsOptions, 'zipPath' | 'database'>): Promise<GtfsSqlJs>;
|
|
723
729
|
/**
|
|
724
|
-
* Initialize from ZIP
|
|
730
|
+
* Initialize from pre-loaded ZIP data
|
|
731
|
+
* @param source - Optional original path/URL, used for cache key generation and metadata
|
|
725
732
|
*/
|
|
726
|
-
private
|
|
733
|
+
private initFromZipData;
|
|
727
734
|
/**
|
|
728
|
-
* Helper method to load GTFS data from zip data
|
|
735
|
+
* Helper method to load GTFS data from zip data
|
|
729
736
|
* Used by both cache-enabled and cache-disabled paths
|
|
730
737
|
*/
|
|
731
738
|
private loadFromZipData;
|
|
@@ -1057,8 +1064,8 @@ interface IndexDefinition {
|
|
|
1057
1064
|
declare const GTFS_SCHEMA: TableSchema[];
|
|
1058
1065
|
|
|
1059
1066
|
/**
|
|
1060
|
-
* Compute SHA-256 checksum of data
|
|
1061
|
-
* Uses Web Crypto API (available in
|
|
1067
|
+
* Compute SHA-256 checksum of data.
|
|
1068
|
+
* Uses the global Web Crypto API (available in browsers and Node.js 18+).
|
|
1062
1069
|
*/
|
|
1063
1070
|
declare function computeChecksum(data: ArrayBuffer | Uint8Array): Promise<string>;
|
|
1064
1071
|
/**
|
package/dist/index.js
CHANGED
|
@@ -185,7 +185,7 @@ var GTFS_SCHEMA = [
|
|
|
185
185
|
{ name: "price", type: "REAL", required: true },
|
|
186
186
|
{ name: "currency_type", type: "TEXT", required: true },
|
|
187
187
|
{ name: "payment_method", type: "INTEGER", required: true },
|
|
188
|
-
{ name: "transfers", type: "INTEGER", required:
|
|
188
|
+
{ name: "transfers", type: "INTEGER", required: false },
|
|
189
189
|
{ name: "agency_id", type: "TEXT", required: false },
|
|
190
190
|
{ name: "transfer_duration", type: "INTEGER", required: false }
|
|
191
191
|
]
|
|
@@ -340,25 +340,28 @@ function getAllCreateIndexStatements() {
|
|
|
340
340
|
|
|
341
341
|
// src/loaders/zip-loader.ts
|
|
342
342
|
import JSZip from "jszip";
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
343
|
+
|
|
344
|
+
// src/utils/env.ts
|
|
345
|
+
function isNodeEnvironment() {
|
|
346
|
+
return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// src/loaders/zip-loader.ts
|
|
350
|
+
async function loadGTFSZip(zipData, skipFiles) {
|
|
350
351
|
const zip = await JSZip.loadAsync(zipData);
|
|
352
|
+
const skipSet = skipFiles ? new Set(skipFiles) : null;
|
|
351
353
|
const files = {};
|
|
352
354
|
const filePromises = [];
|
|
353
355
|
zip.forEach((relativePath, file) => {
|
|
354
|
-
if (
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
356
|
+
if (file.dir) return;
|
|
357
|
+
const fileName = relativePath.split("/").pop() || relativePath;
|
|
358
|
+
if (!(fileName in GTFS_FILE_MAPPING)) return;
|
|
359
|
+
if (skipSet?.has(fileName)) return;
|
|
360
|
+
filePromises.push(
|
|
361
|
+
file.async("string").then((content) => {
|
|
362
|
+
files[fileName] = content;
|
|
363
|
+
})
|
|
364
|
+
);
|
|
362
365
|
});
|
|
363
366
|
await Promise.all(filePromises);
|
|
364
367
|
return files;
|
|
@@ -411,8 +414,7 @@ async function fetchZip(source, onProgress) {
|
|
|
411
414
|
}
|
|
412
415
|
throw new Error("fetch is not available to load URL");
|
|
413
416
|
}
|
|
414
|
-
|
|
415
|
-
if (isNode) {
|
|
417
|
+
if (isNodeEnvironment()) {
|
|
416
418
|
try {
|
|
417
419
|
const fs = await import("fs");
|
|
418
420
|
const buffer = await fs.promises.readFile(source);
|
|
@@ -430,6 +432,24 @@ async function fetchZip(source, onProgress) {
|
|
|
430
432
|
}
|
|
431
433
|
throw new Error("No method available to load ZIP file");
|
|
432
434
|
}
|
|
435
|
+
var GTFS_FILE_MAPPING = {
|
|
436
|
+
"agency.txt": "agency",
|
|
437
|
+
"stops.txt": "stops",
|
|
438
|
+
"routes.txt": "routes",
|
|
439
|
+
"trips.txt": "trips",
|
|
440
|
+
"stop_times.txt": "stop_times",
|
|
441
|
+
"calendar.txt": "calendar",
|
|
442
|
+
"calendar_dates.txt": "calendar_dates",
|
|
443
|
+
"fare_attributes.txt": "fare_attributes",
|
|
444
|
+
"fare_rules.txt": "fare_rules",
|
|
445
|
+
"shapes.txt": "shapes",
|
|
446
|
+
"frequencies.txt": "frequencies",
|
|
447
|
+
"transfers.txt": "transfers",
|
|
448
|
+
"pathways.txt": "pathways",
|
|
449
|
+
"levels.txt": "levels",
|
|
450
|
+
"feed_info.txt": "feed_info",
|
|
451
|
+
"attributions.txt": "attributions"
|
|
452
|
+
};
|
|
433
453
|
|
|
434
454
|
// src/loaders/csv-parser.ts
|
|
435
455
|
import Papa from "papaparse";
|
|
@@ -867,8 +887,7 @@ async function fetchProtobuf(source) {
|
|
|
867
887
|
const arrayBuffer2 = await response2.arrayBuffer();
|
|
868
888
|
return new Uint8Array(arrayBuffer2);
|
|
869
889
|
}
|
|
870
|
-
|
|
871
|
-
if (isNode) {
|
|
890
|
+
if (isNodeEnvironment()) {
|
|
872
891
|
try {
|
|
873
892
|
const fs = await import("fs");
|
|
874
893
|
const buffer = await fs.promises.readFile(source);
|
|
@@ -898,24 +917,13 @@ function loadGtfsRtProto() {
|
|
|
898
917
|
function camelToSnake(str) {
|
|
899
918
|
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
900
919
|
}
|
|
901
|
-
function
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
return obj.map(convertKeysToSnakeCase);
|
|
907
|
-
}
|
|
908
|
-
if (typeof obj === "object") {
|
|
909
|
-
const result = {};
|
|
910
|
-
for (const key in obj) {
|
|
911
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
912
|
-
const snakeKey = camelToSnake(key);
|
|
913
|
-
result[snakeKey] = convertKeysToSnakeCase(obj[key]);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
return result;
|
|
920
|
+
function convertObjectKeysToSnakeCase(obj) {
|
|
921
|
+
const result = {};
|
|
922
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
923
|
+
const snakeKey = camelToSnake(key);
|
|
924
|
+
result[snakeKey] = value !== null && typeof value === "object" && !Array.isArray(value) ? convertObjectKeysToSnakeCase(value) : value;
|
|
917
925
|
}
|
|
918
|
-
return
|
|
926
|
+
return result;
|
|
919
927
|
}
|
|
920
928
|
function parseTranslatedString(ts) {
|
|
921
929
|
if (!ts || !ts.translation || ts.translation.length === 0) {
|
|
@@ -936,8 +944,8 @@ function insertAlerts(db, alerts, timestamp) {
|
|
|
936
944
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
937
945
|
`);
|
|
938
946
|
for (const alert of alerts) {
|
|
939
|
-
const activePeriodSnake =
|
|
940
|
-
const informedEntitySnake =
|
|
947
|
+
const activePeriodSnake = (alert.activePeriod ?? []).map(convertObjectKeysToSnakeCase);
|
|
948
|
+
const informedEntitySnake = (alert.informedEntity ?? []).map(convertObjectKeysToSnakeCase);
|
|
941
949
|
stmt.run([
|
|
942
950
|
alert.id,
|
|
943
951
|
JSON.stringify(activePeriodSnake),
|
|
@@ -1098,24 +1106,16 @@ async function loadRealtimeData(db, feedUrls) {
|
|
|
1098
1106
|
}
|
|
1099
1107
|
|
|
1100
1108
|
// src/cache/checksum.ts
|
|
1101
|
-
async function getCrypto() {
|
|
1102
|
-
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
1103
|
-
return crypto;
|
|
1104
|
-
}
|
|
1105
|
-
if (typeof globalThis !== "undefined") {
|
|
1106
|
-
try {
|
|
1107
|
-
const { webcrypto } = await import("crypto");
|
|
1108
|
-
return webcrypto;
|
|
1109
|
-
} catch {
|
|
1110
|
-
throw new Error("Web Crypto API not available");
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
throw new Error("Crypto not available in this environment");
|
|
1114
|
-
}
|
|
1115
1109
|
async function computeChecksum(data) {
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1110
|
+
let buffer;
|
|
1111
|
+
if (data instanceof ArrayBuffer) {
|
|
1112
|
+
buffer = data;
|
|
1113
|
+
} else {
|
|
1114
|
+
const copy = new ArrayBuffer(data.byteLength);
|
|
1115
|
+
new Uint8Array(copy).set(data);
|
|
1116
|
+
buffer = copy;
|
|
1117
|
+
}
|
|
1118
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
|
|
1119
1119
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
1120
1120
|
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1121
1121
|
return hashHex;
|
|
@@ -1591,11 +1591,10 @@ function getTrips(db, filters = {}, stalenessThreshold = 120) {
|
|
|
1591
1591
|
}
|
|
1592
1592
|
if (serviceIds) {
|
|
1593
1593
|
const serviceIdArray = Array.isArray(serviceIds) ? serviceIds : [serviceIds];
|
|
1594
|
-
if (serviceIdArray.length
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
}
|
|
1594
|
+
if (serviceIdArray.length === 0) return [];
|
|
1595
|
+
const placeholders = serviceIdArray.map(() => "?").join(", ");
|
|
1596
|
+
conditions.push(needsRoutesJoin ? `t.service_id IN (${placeholders})` : `service_id IN (${placeholders})`);
|
|
1597
|
+
params.push(...serviceIdArray);
|
|
1599
1598
|
}
|
|
1600
1599
|
if (directionId !== void 0) {
|
|
1601
1600
|
const directionIds = Array.isArray(directionId) ? directionId : [directionId];
|
|
@@ -1720,11 +1719,10 @@ function getStopTimes(db, filters = {}, stalenessThreshold = 120) {
|
|
|
1720
1719
|
}
|
|
1721
1720
|
if (serviceIds) {
|
|
1722
1721
|
const serviceIdArray = Array.isArray(serviceIds) ? serviceIds : [serviceIds];
|
|
1723
|
-
if (serviceIdArray.length
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
}
|
|
1722
|
+
if (serviceIdArray.length === 0) return [];
|
|
1723
|
+
const placeholders = serviceIdArray.map(() => "?").join(", ");
|
|
1724
|
+
conditions.push(`t.service_id IN (${placeholders})`);
|
|
1725
|
+
params.push(...serviceIdArray);
|
|
1728
1726
|
}
|
|
1729
1727
|
if (directionId !== void 0) {
|
|
1730
1728
|
const directionIds = Array.isArray(directionId) ? directionId : [directionId];
|
|
@@ -1812,7 +1810,7 @@ function buildOrderedStopList(db, tripIds) {
|
|
|
1812
1810
|
if (!tripStopSequences.has(tripId)) {
|
|
1813
1811
|
tripStopSequences.set(tripId, []);
|
|
1814
1812
|
}
|
|
1815
|
-
tripStopSequences.get(tripId)
|
|
1813
|
+
tripStopSequences.get(tripId)?.push({ stop_id: stopId, stop_sequence: stopSequence });
|
|
1816
1814
|
}
|
|
1817
1815
|
stmt.free();
|
|
1818
1816
|
const orderedStopIds = [];
|
|
@@ -2310,7 +2308,7 @@ function getTripUpdates(db, filters = {}, stalenessThreshold = 120) {
|
|
|
2310
2308
|
if (!stopTimesByTripId.has(stu.trip_id)) {
|
|
2311
2309
|
stopTimesByTripId.set(stu.trip_id, []);
|
|
2312
2310
|
}
|
|
2313
|
-
stopTimesByTripId.get(stu.trip_id)
|
|
2311
|
+
stopTimesByTripId.get(stu.trip_id)?.push(stu);
|
|
2314
2312
|
}
|
|
2315
2313
|
for (const tu of tripUpdates) {
|
|
2316
2314
|
tu.stop_time_update = stopTimesByTripId.get(tu.trip_id) || [];
|
|
@@ -2336,7 +2334,7 @@ function getAllTripUpdates(db) {
|
|
|
2336
2334
|
if (!stopTimesByTripId.has(stu.trip_id)) {
|
|
2337
2335
|
stopTimesByTripId.set(stu.trip_id, []);
|
|
2338
2336
|
}
|
|
2339
|
-
stopTimesByTripId.get(stu.trip_id)
|
|
2337
|
+
stopTimesByTripId.get(stu.trip_id)?.push(stu);
|
|
2340
2338
|
}
|
|
2341
2339
|
for (const tu of tripUpdates) {
|
|
2342
2340
|
tu.stop_time_update = stopTimesByTripId.get(tu.trip_id) || [];
|
|
@@ -2359,11 +2357,19 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2359
2357
|
this.lastRealtimeFetchTimestamp = null;
|
|
2360
2358
|
}
|
|
2361
2359
|
/**
|
|
2362
|
-
* Create GtfsSqlJs instance from GTFS ZIP file
|
|
2360
|
+
* Create GtfsSqlJs instance from GTFS ZIP file path or URL
|
|
2363
2361
|
*/
|
|
2364
2362
|
static async fromZip(zipPath, options = {}) {
|
|
2363
|
+
const zipData = await fetchZip(zipPath, options.onProgress);
|
|
2364
|
+
return _GtfsSqlJs.fromZipData(zipData, options, zipPath);
|
|
2365
|
+
}
|
|
2366
|
+
/**
|
|
2367
|
+
* Create GtfsSqlJs instance from pre-loaded GTFS ZIP data
|
|
2368
|
+
* @param source - Optional original path/URL, used for cache key generation and metadata
|
|
2369
|
+
*/
|
|
2370
|
+
static async fromZipData(zipData, options = {}, source) {
|
|
2365
2371
|
const instance = new _GtfsSqlJs();
|
|
2366
|
-
await instance.
|
|
2372
|
+
await instance.initFromZipData(zipData, options, source);
|
|
2367
2373
|
return instance;
|
|
2368
2374
|
}
|
|
2369
2375
|
/**
|
|
@@ -2375,9 +2381,10 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2375
2381
|
return instance;
|
|
2376
2382
|
}
|
|
2377
2383
|
/**
|
|
2378
|
-
* Initialize from ZIP
|
|
2384
|
+
* Initialize from pre-loaded ZIP data
|
|
2385
|
+
* @param source - Optional original path/URL, used for cache key generation and metadata
|
|
2379
2386
|
*/
|
|
2380
|
-
async
|
|
2387
|
+
async initFromZipData(zipData, options, source) {
|
|
2381
2388
|
const onProgress = options.onProgress;
|
|
2382
2389
|
const {
|
|
2383
2390
|
cache: userCache,
|
|
@@ -2398,20 +2405,14 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2398
2405
|
percentComplete: 0,
|
|
2399
2406
|
message: "Checking cache..."
|
|
2400
2407
|
});
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
zipData2 = await fetchZip(zipPath, onProgress);
|
|
2404
|
-
} else {
|
|
2405
|
-
zipData2 = zipPath;
|
|
2406
|
-
}
|
|
2407
|
-
const filesize = zipData2.byteLength;
|
|
2408
|
-
const checksum = await computeZipChecksum(zipData2);
|
|
2408
|
+
const filesize = zipData.byteLength;
|
|
2409
|
+
const checksum = await computeZipChecksum(zipData);
|
|
2409
2410
|
const cacheKey = generateCacheKey(
|
|
2410
2411
|
checksum,
|
|
2411
2412
|
LIB_VERSION,
|
|
2412
2413
|
cacheVersion,
|
|
2413
2414
|
filesize,
|
|
2414
|
-
|
|
2415
|
+
source,
|
|
2415
2416
|
skipFiles
|
|
2416
2417
|
);
|
|
2417
2418
|
const cacheEntry = await cache.get(cacheKey);
|
|
@@ -2460,7 +2461,7 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2460
2461
|
return;
|
|
2461
2462
|
}
|
|
2462
2463
|
}
|
|
2463
|
-
await this.loadFromZipData(
|
|
2464
|
+
await this.loadFromZipData(zipData, options, onProgress);
|
|
2464
2465
|
onProgress?.({
|
|
2465
2466
|
phase: "saving_cache",
|
|
2466
2467
|
currentFile: null,
|
|
@@ -2476,7 +2477,7 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2476
2477
|
checksum,
|
|
2477
2478
|
version: cacheVersion,
|
|
2478
2479
|
timestamp: Date.now(),
|
|
2479
|
-
source
|
|
2480
|
+
source,
|
|
2480
2481
|
size: dbBuffer.byteLength,
|
|
2481
2482
|
skipFiles
|
|
2482
2483
|
});
|
|
@@ -2492,12 +2493,6 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2492
2493
|
});
|
|
2493
2494
|
return;
|
|
2494
2495
|
}
|
|
2495
|
-
let zipData;
|
|
2496
|
-
if (typeof zipPath === "string") {
|
|
2497
|
-
zipData = await fetchZip(zipPath, onProgress);
|
|
2498
|
-
} else {
|
|
2499
|
-
zipData = zipPath;
|
|
2500
|
-
}
|
|
2501
2496
|
await this.loadFromZipData(zipData, options, onProgress);
|
|
2502
2497
|
onProgress?.({
|
|
2503
2498
|
phase: "complete",
|
|
@@ -2511,10 +2506,13 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2511
2506
|
});
|
|
2512
2507
|
}
|
|
2513
2508
|
/**
|
|
2514
|
-
* Helper method to load GTFS data from zip data
|
|
2509
|
+
* Helper method to load GTFS data from zip data
|
|
2515
2510
|
* Used by both cache-enabled and cache-disabled paths
|
|
2516
2511
|
*/
|
|
2517
2512
|
async loadFromZipData(zipData, options, onProgress) {
|
|
2513
|
+
if (!this.SQL) {
|
|
2514
|
+
throw new Error("SQL.js not initialized");
|
|
2515
|
+
}
|
|
2518
2516
|
this.db = new this.SQL.Database();
|
|
2519
2517
|
this.db.run("PRAGMA synchronous = OFF");
|
|
2520
2518
|
this.db.run("PRAGMA journal_mode = MEMORY");
|
|
@@ -2546,7 +2544,7 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2546
2544
|
percentComplete: 35,
|
|
2547
2545
|
message: "Extracting GTFS ZIP file"
|
|
2548
2546
|
});
|
|
2549
|
-
const files = await loadGTFSZip(zipData);
|
|
2547
|
+
const files = await loadGTFSZip(zipData, options.skipFiles);
|
|
2550
2548
|
onProgress?.({
|
|
2551
2549
|
phase: "inserting_data",
|
|
2552
2550
|
currentFile: null,
|