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 CHANGED
@@ -292,8 +292,8 @@ interface Agency {
292
292
  interface Stop {
293
293
  stop_id: string;
294
294
  stop_name: string;
295
- stop_lat: number;
296
- stop_lon: number;
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: string;
314
- route_long_name: string;
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: string;
346
- departure_time: string;
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: number;
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: true },
73
- { name: "stop_lon", type: "REAL", required: true },
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: true },
96
- { name: "route_long_name", type: "TEXT", required: true },
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: true },
136
- { name: "departure_time", type: "TEXT", required: true },
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: true },
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 gtfsRtRoot = null;
911
- function loadGtfsRtProto() {
912
- if (!gtfsRtRoot) {
913
- gtfsRtRoot = protobuf.parse(GTFS_RT_PROTO).root;
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 gtfsRtRoot;
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
- async function loadRealtimeData(db, feedUrls) {
1048
- const root = loadGtfsRtProto();
1049
- const FeedMessage = root.lookupType("transit_realtime.FeedMessage");
1050
- const fetchPromises = feedUrls.map(async (url) => {
1051
- try {
1052
- const data = await fetchProtobuf(url);
1053
- const message = FeedMessage.decode(data);
1054
- return FeedMessage.toObject(message, {
1055
- longs: Number,
1056
- enums: Number,
1057
- bytes: String,
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
- const feeds = await Promise.all(fetchPromises);
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
  */