gtfs-sqljs 0.3.0 → 0.4.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/dist/index.d.ts +12 -7
- package/dist/index.js +55 -63
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -292,8 +292,8 @@ interface Agency {
|
|
|
292
292
|
interface Stop {
|
|
293
293
|
stop_id: string;
|
|
294
294
|
stop_name: string;
|
|
295
|
-
stop_lat
|
|
296
|
-
stop_lon
|
|
295
|
+
stop_lat?: number;
|
|
296
|
+
stop_lon?: number;
|
|
297
297
|
stop_code?: string;
|
|
298
298
|
stop_desc?: string;
|
|
299
299
|
zone_id?: string;
|
|
@@ -310,8 +310,8 @@ interface Stop {
|
|
|
310
310
|
*/
|
|
311
311
|
interface Route {
|
|
312
312
|
route_id: string;
|
|
313
|
-
route_short_name
|
|
314
|
-
route_long_name
|
|
313
|
+
route_short_name?: string;
|
|
314
|
+
route_long_name?: string;
|
|
315
315
|
route_type: number;
|
|
316
316
|
agency_id?: string;
|
|
317
317
|
route_desc?: string;
|
|
@@ -342,8 +342,8 @@ interface Trip {
|
|
|
342
342
|
*/
|
|
343
343
|
interface StopTime {
|
|
344
344
|
trip_id: string;
|
|
345
|
-
arrival_time
|
|
346
|
-
departure_time
|
|
345
|
+
arrival_time?: string;
|
|
346
|
+
departure_time?: string;
|
|
347
347
|
stop_id: string;
|
|
348
348
|
stop_sequence: number;
|
|
349
349
|
stop_headsign?: string;
|
|
@@ -426,7 +426,7 @@ interface Frequency {
|
|
|
426
426
|
interface Transfer {
|
|
427
427
|
from_stop_id: string;
|
|
428
428
|
to_stop_id: string;
|
|
429
|
-
transfer_type
|
|
429
|
+
transfer_type?: number;
|
|
430
430
|
min_transfer_time?: number;
|
|
431
431
|
}
|
|
432
432
|
/**
|
|
@@ -965,6 +965,11 @@ declare class GtfsSqlJs {
|
|
|
965
965
|
* @param urls - Optional array of feed URLs. If not provided, uses configured feed URLs
|
|
966
966
|
*/
|
|
967
967
|
fetchRealtimeData(urls?: string[]): Promise<void>;
|
|
968
|
+
/**
|
|
969
|
+
* Load GTFS Realtime data from pre-loaded protobuf buffers
|
|
970
|
+
* @param buffers - Array of Uint8Array protobuf-encoded GTFS-RT feed messages
|
|
971
|
+
*/
|
|
972
|
+
loadRealtimeDataFromBuffers(buffers: Uint8Array[]): Promise<void>;
|
|
968
973
|
/**
|
|
969
974
|
* Clear all realtime data from the database
|
|
970
975
|
*/
|
package/dist/index.js
CHANGED
|
@@ -69,8 +69,8 @@ var GTFS_SCHEMA = [
|
|
|
69
69
|
columns: [
|
|
70
70
|
{ name: "stop_id", type: "TEXT", required: true, primaryKey: true },
|
|
71
71
|
{ name: "stop_name", type: "TEXT", required: true },
|
|
72
|
-
{ name: "stop_lat", type: "REAL", required:
|
|
73
|
-
{ name: "stop_lon", type: "REAL", required:
|
|
72
|
+
{ name: "stop_lat", type: "REAL", required: false },
|
|
73
|
+
{ name: "stop_lon", type: "REAL", required: false },
|
|
74
74
|
{ name: "stop_code", type: "TEXT", required: false },
|
|
75
75
|
{ name: "stop_desc", type: "TEXT", required: false },
|
|
76
76
|
{ name: "zone_id", type: "TEXT", required: false },
|
|
@@ -92,8 +92,8 @@ var GTFS_SCHEMA = [
|
|
|
92
92
|
name: "routes",
|
|
93
93
|
columns: [
|
|
94
94
|
{ name: "route_id", type: "TEXT", required: true, primaryKey: true },
|
|
95
|
-
{ name: "route_short_name", type: "TEXT", required:
|
|
96
|
-
{ name: "route_long_name", type: "TEXT", required:
|
|
95
|
+
{ name: "route_short_name", type: "TEXT", required: false },
|
|
96
|
+
{ name: "route_long_name", type: "TEXT", required: false },
|
|
97
97
|
{ name: "route_type", type: "INTEGER", required: true },
|
|
98
98
|
{ name: "agency_id", type: "TEXT", required: false },
|
|
99
99
|
{ name: "route_desc", type: "TEXT", required: false },
|
|
@@ -132,8 +132,8 @@ var GTFS_SCHEMA = [
|
|
|
132
132
|
name: "stop_times",
|
|
133
133
|
columns: [
|
|
134
134
|
{ name: "trip_id", type: "TEXT", required: true },
|
|
135
|
-
{ name: "arrival_time", type: "TEXT", required:
|
|
136
|
-
{ name: "departure_time", type: "TEXT", required:
|
|
135
|
+
{ name: "arrival_time", type: "TEXT", required: false },
|
|
136
|
+
{ name: "departure_time", type: "TEXT", required: false },
|
|
137
137
|
{ name: "stop_id", type: "TEXT", required: true },
|
|
138
138
|
{ name: "stop_sequence", type: "INTEGER", required: true },
|
|
139
139
|
{ name: "stop_headsign", type: "TEXT", required: false },
|
|
@@ -236,7 +236,7 @@ var GTFS_SCHEMA = [
|
|
|
236
236
|
columns: [
|
|
237
237
|
{ name: "from_stop_id", type: "TEXT", required: true },
|
|
238
238
|
{ name: "to_stop_id", type: "TEXT", required: true },
|
|
239
|
-
{ name: "transfer_type", type: "INTEGER", required:
|
|
239
|
+
{ name: "transfer_type", type: "INTEGER", required: false },
|
|
240
240
|
{ name: "min_transfer_time", type: "INTEGER", required: false }
|
|
241
241
|
],
|
|
242
242
|
indexes: [
|
|
@@ -340,13 +340,6 @@ function getAllCreateIndexStatements() {
|
|
|
340
340
|
|
|
341
341
|
// src/loaders/zip-loader.ts
|
|
342
342
|
import JSZip from "jszip";
|
|
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
343
|
async function loadGTFSZip(zipData, skipFiles) {
|
|
351
344
|
const zip = await JSZip.loadAsync(zipData);
|
|
352
345
|
const skipSet = skipFiles ? new Set(skipFiles) : null;
|
|
@@ -414,15 +407,6 @@ async function fetchZip(source, onProgress) {
|
|
|
414
407
|
}
|
|
415
408
|
throw new Error("fetch is not available to load URL");
|
|
416
409
|
}
|
|
417
|
-
if (isNodeEnvironment()) {
|
|
418
|
-
try {
|
|
419
|
-
const fs = await import("fs");
|
|
420
|
-
const buffer = await fs.promises.readFile(source);
|
|
421
|
-
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
|
422
|
-
} catch (error) {
|
|
423
|
-
throw new Error(`Failed to read GTFS ZIP file: ${error}`);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
410
|
if (typeof fetch !== "undefined") {
|
|
427
411
|
const response = await fetch(source);
|
|
428
412
|
if (!response.ok) {
|
|
@@ -887,15 +871,6 @@ async function fetchProtobuf(source) {
|
|
|
887
871
|
const arrayBuffer2 = await response2.arrayBuffer();
|
|
888
872
|
return new Uint8Array(arrayBuffer2);
|
|
889
873
|
}
|
|
890
|
-
if (isNodeEnvironment()) {
|
|
891
|
-
try {
|
|
892
|
-
const fs = await import("fs");
|
|
893
|
-
const buffer = await fs.promises.readFile(source);
|
|
894
|
-
return new Uint8Array(buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength));
|
|
895
|
-
} catch (error) {
|
|
896
|
-
throw new Error(`Failed to read GTFS-RT file from ${source}: ${error instanceof Error ? error.message : String(error)}`);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
874
|
const response = await fetch(source, {
|
|
900
875
|
headers: {
|
|
901
876
|
"Accept": "application/x-protobuf, application/octet-stream"
|
|
@@ -907,12 +882,13 @@ async function fetchProtobuf(source) {
|
|
|
907
882
|
const arrayBuffer = await response.arrayBuffer();
|
|
908
883
|
return new Uint8Array(arrayBuffer);
|
|
909
884
|
}
|
|
910
|
-
var
|
|
911
|
-
function
|
|
912
|
-
if (!
|
|
913
|
-
|
|
885
|
+
var feedMessageType = null;
|
|
886
|
+
function getFeedMessageType() {
|
|
887
|
+
if (!feedMessageType) {
|
|
888
|
+
const root = protobuf.parse(GTFS_RT_PROTO).root;
|
|
889
|
+
feedMessageType = root.lookupType("transit_realtime.FeedMessage");
|
|
914
890
|
}
|
|
915
|
-
return
|
|
891
|
+
return feedMessageType;
|
|
916
892
|
}
|
|
917
893
|
function camelToSnake(str) {
|
|
918
894
|
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
@@ -1044,27 +1020,20 @@ function insertTripUpdates(db, updates, timestamp) {
|
|
|
1044
1020
|
tripStmt.free();
|
|
1045
1021
|
stopTimeStmt.free();
|
|
1046
1022
|
}
|
|
1047
|
-
|
|
1048
|
-
const
|
|
1049
|
-
const
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
defaults: false,
|
|
1059
|
-
arrays: true,
|
|
1060
|
-
objects: true,
|
|
1061
|
-
oneofs: true
|
|
1062
|
-
});
|
|
1063
|
-
} catch (error) {
|
|
1064
|
-
throw new Error(`Failed to fetch or parse GTFS-RT feed from ${url}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1065
|
-
}
|
|
1023
|
+
function decodeFeedMessage(data) {
|
|
1024
|
+
const FeedMessage = getFeedMessageType();
|
|
1025
|
+
const message = FeedMessage.decode(data);
|
|
1026
|
+
return FeedMessage.toObject(message, {
|
|
1027
|
+
longs: Number,
|
|
1028
|
+
enums: Number,
|
|
1029
|
+
bytes: String,
|
|
1030
|
+
defaults: false,
|
|
1031
|
+
arrays: true,
|
|
1032
|
+
objects: true,
|
|
1033
|
+
oneofs: true
|
|
1066
1034
|
});
|
|
1067
|
-
|
|
1035
|
+
}
|
|
1036
|
+
function processRealtimeFeeds(db, feeds) {
|
|
1068
1037
|
const now = Math.floor(Date.now() / 1e3);
|
|
1069
1038
|
const allAlerts = [];
|
|
1070
1039
|
const allVehiclePositions = [];
|
|
@@ -1104,6 +1073,20 @@ async function loadRealtimeData(db, feedUrls) {
|
|
|
1104
1073
|
throw error;
|
|
1105
1074
|
}
|
|
1106
1075
|
}
|
|
1076
|
+
async function loadRealtimeData(db, feedUrls) {
|
|
1077
|
+
const buffers = await Promise.all(feedUrls.map(async (url) => {
|
|
1078
|
+
try {
|
|
1079
|
+
return await fetchProtobuf(url);
|
|
1080
|
+
} catch (error) {
|
|
1081
|
+
throw new Error(`Failed to fetch GTFS-RT feed from ${url}: ${error instanceof Error ? error.message : String(error)}`);
|
|
1082
|
+
}
|
|
1083
|
+
}));
|
|
1084
|
+
await loadRealtimeDataFromBuffers(db, buffers);
|
|
1085
|
+
}
|
|
1086
|
+
async function loadRealtimeDataFromBuffers(db, buffers) {
|
|
1087
|
+
const feeds = buffers.map((buffer) => decodeFeedMessage(buffer));
|
|
1088
|
+
processRealtimeFeeds(db, feeds);
|
|
1089
|
+
}
|
|
1107
1090
|
|
|
1108
1091
|
// src/cache/checksum.ts
|
|
1109
1092
|
async function computeChecksum(data) {
|
|
@@ -1257,8 +1240,8 @@ function rowToStop(row) {
|
|
|
1257
1240
|
return {
|
|
1258
1241
|
stop_id: String(row.stop_id),
|
|
1259
1242
|
stop_name: String(row.stop_name),
|
|
1260
|
-
stop_lat: Number(row.stop_lat),
|
|
1261
|
-
stop_lon: Number(row.stop_lon),
|
|
1243
|
+
stop_lat: row.stop_lat !== null ? Number(row.stop_lat) : void 0,
|
|
1244
|
+
stop_lon: row.stop_lon !== null ? Number(row.stop_lon) : void 0,
|
|
1262
1245
|
stop_code: row.stop_code ? String(row.stop_code) : void 0,
|
|
1263
1246
|
stop_desc: row.stop_desc ? String(row.stop_desc) : void 0,
|
|
1264
1247
|
zone_id: row.zone_id ? String(row.zone_id) : void 0,
|
|
@@ -1317,8 +1300,8 @@ function getRoutes(db, filters = {}) {
|
|
|
1317
1300
|
function rowToRoute(row) {
|
|
1318
1301
|
return {
|
|
1319
1302
|
route_id: String(row.route_id),
|
|
1320
|
-
route_short_name: String(row.route_short_name),
|
|
1321
|
-
route_long_name: String(row.route_long_name),
|
|
1303
|
+
route_short_name: row.route_short_name ? String(row.route_short_name) : void 0,
|
|
1304
|
+
route_long_name: row.route_long_name ? String(row.route_long_name) : void 0,
|
|
1322
1305
|
route_type: Number(row.route_type),
|
|
1323
1306
|
agency_id: row.agency_id ? String(row.agency_id) : void 0,
|
|
1324
1307
|
route_desc: row.route_desc ? String(row.route_desc) : void 0,
|
|
@@ -1868,8 +1851,8 @@ function findInsertionPosition(orderedStopIds, newStopId, tripStops, currentInde
|
|
|
1868
1851
|
function rowToStopTime(row) {
|
|
1869
1852
|
return {
|
|
1870
1853
|
trip_id: String(row.trip_id),
|
|
1871
|
-
arrival_time: String(row.arrival_time),
|
|
1872
|
-
departure_time: String(row.departure_time),
|
|
1854
|
+
arrival_time: row.arrival_time ? String(row.arrival_time) : void 0,
|
|
1855
|
+
departure_time: row.departure_time ? String(row.departure_time) : void 0,
|
|
1873
1856
|
stop_id: String(row.stop_id),
|
|
1874
1857
|
stop_sequence: Number(row.stop_sequence),
|
|
1875
1858
|
stop_headsign: row.stop_headsign ? String(row.stop_headsign) : void 0,
|
|
@@ -2947,6 +2930,15 @@ var GtfsSqlJs = class _GtfsSqlJs {
|
|
|
2947
2930
|
await loadRealtimeData(this.db, feedUrls);
|
|
2948
2931
|
this.lastRealtimeFetchTimestamp = Math.floor(Date.now() / 1e3);
|
|
2949
2932
|
}
|
|
2933
|
+
/**
|
|
2934
|
+
* Load GTFS Realtime data from pre-loaded protobuf buffers
|
|
2935
|
+
* @param buffers - Array of Uint8Array protobuf-encoded GTFS-RT feed messages
|
|
2936
|
+
*/
|
|
2937
|
+
async loadRealtimeDataFromBuffers(buffers) {
|
|
2938
|
+
if (!this.db) throw new Error("Database not initialized");
|
|
2939
|
+
await loadRealtimeDataFromBuffers(this.db, buffers);
|
|
2940
|
+
this.lastRealtimeFetchTimestamp = Math.floor(Date.now() / 1e3);
|
|
2941
|
+
}
|
|
2950
2942
|
/**
|
|
2951
2943
|
* Clear all realtime data from the database
|
|
2952
2944
|
*/
|