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.
- package/dist/bin/gtfs-export.js +60 -23
- package/dist/bin/gtfs-export.js.map +1 -1
- package/dist/bin/gtfs-import.js +165 -132
- package/dist/bin/gtfs-import.js.map +1 -1
- package/dist/bin/gtfsrealtime-update.js +159 -130
- package/dist/bin/gtfsrealtime-update.js.map +1 -1
- package/dist/index.js +171 -137
- package/dist/index.js.map +1 -1
- package/dist/models/models.d.ts +44 -3
- package/dist/models/models.js +55 -18
- package/dist/models/models.js.map +1 -1
- package/package.json +4 -3
|
@@ -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-
|
|
506
|
-
var
|
|
507
|
-
filenameBase: "
|
|
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
|
-
|
|
638
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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
|
-
|
|
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
|
-
|
|
736
|
-
const
|
|
737
|
-
|
|
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
|
-
|
|
762
|
-
|
|
763
|
-
|
|
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(
|
|
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
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
)
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
const
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
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(
|
|
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
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
)
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
984
|
+
import sqlString4 from "sqlstring-sqlite";
|
|
956
985
|
|
|
957
986
|
// src/bin/gtfsrealtime-update.ts
|
|
958
987
|
var pe = new PrettyError();
|