gtfs 4.16.0 → 4.17.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.
@@ -122,21 +122,24 @@ var tripUpdates = {
122
122
  required: true,
123
123
  primary: true,
124
124
  index: true,
125
- source: "id"
125
+ source: "id",
126
+ prefix: true
126
127
  },
127
128
  {
128
129
  name: "vehicle_id",
129
130
  type: "text",
130
131
  index: true,
131
132
  source: "tripUpdate.vehicle.id",
132
- default: null
133
+ default: null,
134
+ prefix: true
133
135
  },
134
136
  {
135
137
  name: "trip_id",
136
138
  type: "text",
137
139
  index: true,
138
140
  source: "tripUpdate.trip.tripId",
139
- default: null
141
+ default: null,
142
+ prefix: true
140
143
  },
141
144
  {
142
145
  name: "trip_start_time",
@@ -155,7 +158,8 @@ var tripUpdates = {
155
158
  type: "text",
156
159
  index: true,
157
160
  source: "tripUpdate.trip.routeId",
158
- default: null
161
+ default: null,
162
+ prefix: true
159
163
  },
160
164
  {
161
165
  name: "start_date",
@@ -198,7 +202,8 @@ var stopTimeUpdates = {
198
202
  type: "text",
199
203
  index: true,
200
204
  source: "parent.tripUpdate.trip.tripId",
201
- default: null
205
+ default: null,
206
+ prefix: true
202
207
  },
203
208
  {
204
209
  name: "trip_start_time",
@@ -217,14 +222,16 @@ var stopTimeUpdates = {
217
222
  type: "text",
218
223
  index: true,
219
224
  source: "parent.tripUpdate.trip.routeId",
220
- default: null
225
+ default: null,
226
+ prefix: true
221
227
  },
222
228
  {
223
229
  name: "stop_id",
224
230
  type: "text",
225
231
  index: true,
226
232
  source: "stopId",
227
- default: null
233
+ default: null,
234
+ prefix: true
228
235
  },
229
236
  {
230
237
  name: "stop_sequence",
@@ -286,7 +293,8 @@ var vehiclePositions = {
286
293
  required: true,
287
294
  primary: true,
288
295
  index: true,
289
- source: "id"
296
+ source: "id",
297
+ prefix: true
290
298
  },
291
299
  {
292
300
  name: "bearing",
@@ -328,7 +336,8 @@ var vehiclePositions = {
328
336
  type: "text",
329
337
  index: true,
330
338
  source: "vehicle.trip.tripId",
331
- default: null
339
+ default: null,
340
+ prefix: true
332
341
  },
333
342
  {
334
343
  name: "trip_start_date",
@@ -373,7 +382,8 @@ var vehiclePositions = {
373
382
  type: "text",
374
383
  index: true,
375
384
  source: "vehicle.vehicle.id",
376
- default: null
385
+ default: null,
386
+ prefix: true
377
387
  },
378
388
  {
379
389
  name: "vehicle_label",
@@ -423,7 +433,8 @@ var serviceAlerts = {
423
433
  required: true,
424
434
  primary: true,
425
435
  index: true,
426
- source: "id"
436
+ source: "id",
437
+ prefix: true
427
438
  },
428
439
  {
429
440
  name: "active_period",
@@ -502,9 +513,9 @@ var serviceAlerts = {
502
513
  ]
503
514
  };
504
515
 
505
- // src/models/gtfs-realtime/service-alert-targets.ts
506
- var serviceAlertTargets = {
507
- filenameBase: "service_alert_targets",
516
+ // src/models/gtfs-realtime/service-alert-informed_entities.ts
517
+ var serviceAlertInformedEntities = {
518
+ filenameBase: "service_alert_informed_entities",
508
519
  extension: "gtfs-realtime",
509
520
  schema: [
510
521
  {
@@ -512,20 +523,45 @@ var serviceAlertTargets = {
512
523
  type: "text",
513
524
  required: true,
514
525
  primary: true,
515
- source: "parent.id"
526
+ source: "parent.id",
527
+ prefix: true
516
528
  },
517
529
  {
518
530
  name: "stop_id",
519
531
  type: "text",
520
532
  index: true,
521
533
  source: "stopId",
522
- default: null
534
+ default: null,
535
+ prefix: true
523
536
  },
524
537
  {
525
538
  name: "route_id",
526
539
  type: "text",
527
540
  index: true,
528
541
  source: "routeId",
542
+ default: null,
543
+ prefix: true
544
+ },
545
+ {
546
+ name: "route_type",
547
+ type: "integer",
548
+ index: true,
549
+ source: "routeType",
550
+ default: null
551
+ },
552
+ {
553
+ name: "trip_id",
554
+ type: "text",
555
+ index: true,
556
+ source: "trip.tripId",
557
+ default: null,
558
+ prefix: true
559
+ },
560
+ {
561
+ name: "direction_id",
562
+ type: "integer",
563
+ index: true,
564
+ source: "directionId",
529
565
  default: null
530
566
  },
531
567
  {
@@ -595,8 +631,8 @@ import { feature, featureCollection } from "@turf/helpers";
595
631
  // src/lib/import-gtfs-realtime.ts
596
632
  import pluralize from "pluralize";
597
633
  import GtfsRealtimeBindings from "gtfs-realtime-bindings";
598
- import sqlString2 from "sqlstring-sqlite";
599
634
  import mapSeries from "promise-map-series";
635
+ import { get } from "lodash-es";
600
636
 
601
637
  // src/lib/utils.ts
602
638
  import sqlString from "sqlstring-sqlite";
@@ -633,39 +669,14 @@ function convertLongTimeToDate(longDate) {
633
669
  Long.fromBits(low, high, unsigned).toNumber() * 1e3
634
670
  ).toISOString();
635
671
  }
636
-
637
- // src/lib/import-gtfs-realtime.ts
638
- function getNestedProperty(obj, defaultValue, path2) {
639
- if (path2 === void 0) return defaultValue;
640
- const arr = path2.split(".");
641
- while (arr.length) {
642
- const nextKey = arr.shift();
643
- if (nextKey === void 0) {
644
- return defaultValue;
645
- } else if (obj == null) {
646
- return defaultValue;
647
- } else if (nextKey?.includes("[")) {
648
- const arrayKey = nextKey.match(/(\w*)\[(\d+)\]/);
649
- if (arrayKey === null) {
650
- return defaultValue;
651
- }
652
- if (obj[arrayKey[1]] === void 0) {
653
- return defaultValue;
654
- }
655
- if (obj[arrayKey[1]][arrayKey[2]] === void 0) {
656
- return defaultValue;
657
- }
658
- obj = obj[arrayKey[1]][arrayKey[2]];
659
- } else {
660
- if (obj[nextKey] === void 0) {
661
- return defaultValue;
662
- }
663
- obj = obj[nextKey];
664
- }
672
+ function applyPrefixToValue(value, columnShouldBePrefixed, prefix) {
673
+ if (!columnShouldBePrefixed || prefix === void 0 || value === null) {
674
+ return value;
665
675
  }
666
- if (obj?.__isLong__) return convertLongTimeToDate(obj);
667
- return obj;
676
+ return `${prefix}${value}`;
668
677
  }
678
+
679
+ // src/lib/import-gtfs-realtime.ts
669
680
  async function fetchGtfsRealtimeData(urlConfig, task) {
670
681
  task.log(`Downloading GTFS-Realtime from ${urlConfig.url}`);
671
682
  const response = await fetch(urlConfig.url, {
@@ -690,7 +701,7 @@ async function fetchGtfsRealtimeData(urlConfig, task) {
690
701
  enums: String,
691
702
  longs: String,
692
703
  bytes: String,
693
- defaults: true,
704
+ defaults: false,
694
705
  arrays: true,
695
706
  objects: true,
696
707
  oneofs: true
@@ -712,7 +723,7 @@ function removeExpiredRealtimeData(config) {
712
723
  `DELETE FROM service_alerts WHERE expiration_timestamp <= strftime('%s','now')`
713
724
  ).run();
714
725
  db.prepare(
715
- `DELETE FROM service_alert_targets WHERE expiration_timestamp <= strftime('%s','now')`
726
+ `DELETE FROM service_alert_informed_entities WHERE expiration_timestamp <= strftime('%s','now')`
716
727
  ).run();
717
728
  log(config)(`Removed expired GTFS-Realtime data\r`, true);
718
729
  }
@@ -723,100 +734,117 @@ function prepareRealtimeFieldValue(entity, column, task) {
723
734
  if (column.name === "expiration_timestamp") {
724
735
  return task.currentTimestamp + task.gtfsRealtimeExpirationSeconds;
725
736
  }
726
- const value = getNestedProperty(entity, column.default, column.source);
727
- if (column.type === "json") {
728
- return sqlString2.escape(JSON.stringify(value));
729
- }
730
- return sqlString2.escape(value);
737
+ const baseValue = column.source === void 0 ? column.default : get(entity, column.source, column.default);
738
+ const timeAdjustedValue = baseValue?.__isLong__ ? convertLongTimeToDate(baseValue) : baseValue;
739
+ const prefixedValue = applyPrefixToValue(
740
+ timeAdjustedValue,
741
+ column.prefix,
742
+ task.prefix
743
+ );
744
+ return column.type === "json" ? JSON.stringify(prefixedValue) : prefixedValue;
731
745
  }
732
746
  async function processRealtimeAlerts(db, gtfsRealtimeData, task) {
733
- task.log(`Download successful`);
747
+ const alertStmt = db.prepare(
748
+ `REPLACE INTO ${serviceAlerts.filenameBase} (${serviceAlerts.schema.map((column) => column.name).join(
749
+ ", "
750
+ )}) VALUES (${serviceAlerts.schema.map(() => "?").join(", ")})`
751
+ );
752
+ const informedEntityStmt = db.prepare(
753
+ `REPLACE INTO ${serviceAlertInformedEntities.filenameBase} (${serviceAlertInformedEntities.schema.map((column) => column.name).join(
754
+ ", "
755
+ )}) VALUES (${serviceAlertInformedEntities.schema.map(() => "?").join(", ")})`
756
+ );
734
757
  let totalLineCount = 0;
735
- for (const entity of gtfsRealtimeData.entity) {
736
- const fieldValues = serviceAlerts.schema.map(
737
- (column) => prepareRealtimeFieldValue(entity, column, task)
738
- );
739
- try {
740
- db.prepare(
741
- `REPLACE INTO ${serviceAlerts.filenameBase} (${serviceAlerts.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
742
- ).run();
743
- } catch (error) {
744
- task.logWarning(`Import error: ${error.message}`);
745
- }
746
- if (!entity.alert.informedEntity || entity.alert.informedEntity.length === 0) {
747
- task.logWarning(
748
- `Import error: No informed entities found for alert id=${entity.id}`
758
+ db.transaction(() => {
759
+ for (const entity of gtfsRealtimeData.entity) {
760
+ const fieldValues = serviceAlerts.schema.map(
761
+ (column) => prepareRealtimeFieldValue(entity, column, task)
749
762
  );
750
- } else {
751
- const alertTargetArray = [];
752
- for (const informedEntity of entity.alert.informedEntity) {
753
- informedEntity.parent = entity;
754
- const subValues = serviceAlertTargets.schema.map(
755
- (column) => prepareRealtimeFieldValue(informedEntity, column, task)
756
- );
757
- alertTargetArray.push(`(${subValues.join(", ")})`);
758
- totalLineCount++;
759
- }
760
763
  try {
761
- db.prepare(
762
- `REPLACE INTO ${serviceAlertTargets.filenameBase} (${serviceAlertTargets.schema.map((column) => column.name).join(", ")}) VALUES ${alertTargetArray.join(", ")}`
763
- ).run();
764
+ alertStmt.run(fieldValues);
765
+ if (entity.alert.informedEntity?.length) {
766
+ const informedEntities = entity.alert.informedEntity.map(
767
+ (informedEntity) => {
768
+ informedEntity.parent = entity;
769
+ return serviceAlertInformedEntities.schema.map(
770
+ (column) => prepareRealtimeFieldValue(informedEntity, column, task)
771
+ );
772
+ }
773
+ );
774
+ for (const values of informedEntities) {
775
+ informedEntityStmt.run(values);
776
+ }
777
+ }
778
+ totalLineCount++;
764
779
  } catch (error) {
765
780
  task.logWarning(`Import error: ${error.message}`);
766
781
  }
767
782
  }
768
- task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
769
- }
783
+ task.log(
784
+ `Importing - GTFS-Realtime service alerts - ${totalLineCount} entries imported\r`,
785
+ true
786
+ );
787
+ })();
770
788
  }
771
789
  async function processRealtimeTripUpdates(db, gtfsRealtimeData, task) {
772
- task.log(`Download successful`);
773
790
  let totalLineCount = 0;
774
- for (const entity of gtfsRealtimeData.entity) {
775
- const fieldValues = tripUpdates.schema.map(
776
- (column) => prepareRealtimeFieldValue(entity, column, task)
777
- );
778
- try {
779
- db.prepare(
780
- `REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
781
- ).run();
782
- } catch (error) {
783
- task.logWarning(`Import error: ${error.message}`);
784
- }
785
- const stopTimeUpdateArray = [];
786
- for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
787
- stopTimeUpdate.parent = entity;
788
- const subValues = stopTimeUpdates.schema.map(
789
- (column) => prepareRealtimeFieldValue(stopTimeUpdate, column, task)
790
- );
791
- stopTimeUpdateArray.push(`(${subValues.join(", ")})`);
792
- totalLineCount++;
793
- }
794
- try {
795
- db.prepare(
796
- `REPLACE INTO ${stopTimeUpdates.filenameBase} (${stopTimeUpdates.schema.map((column) => column.name).join(", ")}) VALUES ${stopTimeUpdateArray.join(", ")}`
797
- ).run();
798
- } catch (error) {
799
- task.logWarning(`Import error: ${error.message}`);
791
+ const tripUpdateStmt = db.prepare(
792
+ `REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(
793
+ ", "
794
+ )}) VALUES (${tripUpdates.schema.map(() => "?").join(", ")})`
795
+ );
796
+ const stopTimeStmt = db.prepare(
797
+ `REPLACE INTO ${stopTimeUpdates.filenameBase} (${stopTimeUpdates.schema.map((column) => column.name).join(
798
+ ", "
799
+ )}) VALUES (${stopTimeUpdates.schema.map(() => "?").join(", ")})`
800
+ );
801
+ db.transaction(() => {
802
+ for (const entity of gtfsRealtimeData.entity) {
803
+ try {
804
+ const fieldValues = tripUpdates.schema.map(
805
+ (column) => prepareRealtimeFieldValue(entity, column, task)
806
+ );
807
+ tripUpdateStmt.run(fieldValues);
808
+ for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
809
+ stopTimeUpdate.parent = entity;
810
+ const values = stopTimeUpdates.schema.map(
811
+ (column) => prepareRealtimeFieldValue(stopTimeUpdate, column, task)
812
+ );
813
+ stopTimeStmt.run(values);
814
+ }
815
+ totalLineCount++;
816
+ } catch (error) {
817
+ task.logWarning(`Import error: ${error.message}`);
818
+ }
800
819
  }
801
- task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
802
- }
820
+ task.log(
821
+ `Importing - GTFS-Realtime trip updates - ${totalLineCount} entries imported\r`,
822
+ true
823
+ );
824
+ })();
803
825
  }
804
826
  async function processRealtimeVehiclePositions(db, gtfsRealtimeData, task) {
805
- task.log(`Download successful`);
806
827
  let totalLineCount = 0;
807
- for (const entity of gtfsRealtimeData.entity) {
808
- const fieldValues = vehiclePositions.schema.map(
809
- (column) => prepareRealtimeFieldValue(entity, column, task)
810
- );
811
- try {
812
- db.prepare(
813
- `REPLACE INTO ${vehiclePositions.filenameBase} (${vehiclePositions.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
814
- ).run();
815
- } catch (error) {
816
- task.logWarning(`Import error: ${error.message}`);
828
+ const vehiclePositionStmt = db.prepare(
829
+ `REPLACE INTO ${vehiclePositions.filenameBase} (${vehiclePositions.schema.map((column) => column.name).join(
830
+ ", "
831
+ )}) VALUES (${vehiclePositions.schema.map(() => "?").join(", ")})`
832
+ );
833
+ db.transaction(() => {
834
+ for (const entity of gtfsRealtimeData.entity) {
835
+ try {
836
+ const fieldValues = vehiclePositions.schema.map((column) => prepareRealtimeFieldValue(entity, column, task));
837
+ vehiclePositionStmt.run(fieldValues);
838
+ totalLineCount++;
839
+ } catch (error) {
840
+ task.logWarning(`Import error: ${error.message}`);
841
+ }
817
842
  }
818
- task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
819
- }
843
+ task.log(
844
+ `Importing - GTFS-Realtime vehicle positions - ${totalLineCount} entries imported\r`,
845
+ true
846
+ );
847
+ })();
820
848
  }
821
849
  async function updateGtfsRealtimeData(task) {
822
850
  if (task.realtimeAlerts === void 0 && task.realtimeTripUpdates === void 0 && task.realtimeVehiclePositions === void 0) {
@@ -897,6 +925,7 @@ async function updateGtfsRealtime(initialConfig) {
897
925
  gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,
898
926
  ignoreErrors: config.ignoreErrors,
899
927
  sqlitePath: config.sqlitePath,
928
+ prefix: agency2.prefix,
900
929
  currentTimestamp: Math.floor(Date.now() / 1e3),
901
930
  log: log(config),
902
931
  logWarning: logWarning(config),
@@ -933,12 +962,12 @@ async function updateGtfsRealtime(initialConfig) {
933
962
  import { without, compact as compact2 } from "lodash-es";
934
963
  import pluralize3 from "pluralize";
935
964
  import { stringify } from "csv-stringify";
936
- import sqlString3 from "sqlstring-sqlite";
965
+ import sqlString2 from "sqlstring-sqlite";
937
966
  import mapSeries3 from "promise-map-series";
938
967
  import untildify4 from "untildify";
939
968
 
940
969
  // src/lib/advancedQuery.ts
941
- import sqlString4 from "sqlstring-sqlite";
970
+ import sqlString3 from "sqlstring-sqlite";
942
971
 
943
972
  // src/lib/gtfs/routes.ts
944
973
  import { omit as omit3, pick } from "lodash-es";
@@ -952,7 +981,7 @@ import { omit as omit5, orderBy, pick as pick3 } from "lodash-es";
952
981
 
953
982
  // src/lib/gtfs/stop-times.ts
954
983
  import { omit as omit6 } from "lodash-es";
955
- import sqlString5 from "sqlstring-sqlite";
984
+ import sqlString4 from "sqlstring-sqlite";
956
985
 
957
986
  // src/bin/gtfsrealtime-update.ts
958
987
  var pe = new PrettyError();