gtfs 4.13.4 → 4.14.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 +36 -20
- package/dist/bin/gtfs-export.js.map +1 -1
- package/dist/bin/gtfs-import.js +90 -59
- package/dist/bin/gtfs-import.js.map +1 -1
- package/dist/bin/gtfsrealtime-update.js +86 -195
- package/dist/bin/gtfsrealtime-update.js.map +1 -1
- package/dist/index.d.ts +20 -9
- package/dist/index.js +94 -65
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
|
@@ -299,143 +299,6 @@ var stopTimeUpdates = {
|
|
|
299
299
|
]
|
|
300
300
|
};
|
|
301
301
|
|
|
302
|
-
// src/models/gtfs-realtime/vehicle-positions.ts
|
|
303
|
-
var vehiclePositions = {
|
|
304
|
-
filenameBase: "vehicle_positions",
|
|
305
|
-
extension: "gtfs-realtime",
|
|
306
|
-
schema: [
|
|
307
|
-
{
|
|
308
|
-
name: "update_id",
|
|
309
|
-
type: "text",
|
|
310
|
-
required: true,
|
|
311
|
-
primary: true,
|
|
312
|
-
index: true,
|
|
313
|
-
source: "id"
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
name: "bearing",
|
|
317
|
-
type: "real",
|
|
318
|
-
source: "vehicle.position.bearing",
|
|
319
|
-
default: null
|
|
320
|
-
},
|
|
321
|
-
{
|
|
322
|
-
name: "latitude",
|
|
323
|
-
type: "real",
|
|
324
|
-
min: -90,
|
|
325
|
-
max: 90,
|
|
326
|
-
source: "vehicle.position.latitude",
|
|
327
|
-
default: null
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
name: "longitude",
|
|
331
|
-
type: "real",
|
|
332
|
-
source: "vehicle.position.longitude",
|
|
333
|
-
min: -180,
|
|
334
|
-
max: 180,
|
|
335
|
-
default: null
|
|
336
|
-
},
|
|
337
|
-
{
|
|
338
|
-
name: "speed",
|
|
339
|
-
type: "real",
|
|
340
|
-
min: 0,
|
|
341
|
-
source: "vehicle.position.speed",
|
|
342
|
-
default: null
|
|
343
|
-
},
|
|
344
|
-
{
|
|
345
|
-
name: "current_stop_sequence",
|
|
346
|
-
type: "integer",
|
|
347
|
-
source: "vehicle.currentStopSequence",
|
|
348
|
-
default: null
|
|
349
|
-
},
|
|
350
|
-
{
|
|
351
|
-
name: "trip_id",
|
|
352
|
-
type: "text",
|
|
353
|
-
index: true,
|
|
354
|
-
source: "vehicle.trip.tripId",
|
|
355
|
-
default: null
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
name: "trip_start_date",
|
|
359
|
-
type: "text",
|
|
360
|
-
index: true,
|
|
361
|
-
source: "vehicle.trip.startDate",
|
|
362
|
-
default: null
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
name: "trip_start_time",
|
|
366
|
-
type: "text",
|
|
367
|
-
index: true,
|
|
368
|
-
source: "vehicle.trip.startTime",
|
|
369
|
-
default: null
|
|
370
|
-
},
|
|
371
|
-
{
|
|
372
|
-
name: "congestion_level",
|
|
373
|
-
type: "text",
|
|
374
|
-
source: "vehicle.congestionLevel",
|
|
375
|
-
default: null
|
|
376
|
-
},
|
|
377
|
-
{
|
|
378
|
-
name: "occupancy_status",
|
|
379
|
-
type: "text",
|
|
380
|
-
source: "vehicle.occupancyStatus",
|
|
381
|
-
default: null
|
|
382
|
-
},
|
|
383
|
-
{
|
|
384
|
-
name: "occupancy_percentage",
|
|
385
|
-
type: "integer",
|
|
386
|
-
source: "vehicle.occupancyPercentage",
|
|
387
|
-
default: null
|
|
388
|
-
},
|
|
389
|
-
{
|
|
390
|
-
name: "vehicle_stop_status",
|
|
391
|
-
type: "text",
|
|
392
|
-
source: "vehicle.vehicleStopStatus",
|
|
393
|
-
default: null
|
|
394
|
-
},
|
|
395
|
-
{
|
|
396
|
-
name: "vehicle_id",
|
|
397
|
-
type: "text",
|
|
398
|
-
index: true,
|
|
399
|
-
source: "vehicle.vehicle.id",
|
|
400
|
-
default: null
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
name: "vehicle_label",
|
|
404
|
-
type: "text",
|
|
405
|
-
source: "vehicle.vehicle.label",
|
|
406
|
-
default: null
|
|
407
|
-
},
|
|
408
|
-
{
|
|
409
|
-
name: "vehicle_license_plate",
|
|
410
|
-
type: "text",
|
|
411
|
-
source: "vehicle.vehicle.licensePlate",
|
|
412
|
-
default: null
|
|
413
|
-
},
|
|
414
|
-
{
|
|
415
|
-
name: "vehicle_wheelchair_accessible",
|
|
416
|
-
type: "text",
|
|
417
|
-
source: "vehicle.vehicle.wheelchairAccessible",
|
|
418
|
-
default: null
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
name: "timestamp",
|
|
422
|
-
type: "text",
|
|
423
|
-
source: "vehicle.timestamp",
|
|
424
|
-
default: null
|
|
425
|
-
},
|
|
426
|
-
{
|
|
427
|
-
name: "created_timestamp",
|
|
428
|
-
type: "integer",
|
|
429
|
-
required: true
|
|
430
|
-
},
|
|
431
|
-
{
|
|
432
|
-
name: "expiration_timestamp",
|
|
433
|
-
type: "integer",
|
|
434
|
-
required: true
|
|
435
|
-
}
|
|
436
|
-
]
|
|
437
|
-
};
|
|
438
|
-
|
|
439
302
|
// src/models/gtfs-realtime/service-alerts.ts
|
|
440
303
|
var serviceAlerts = {
|
|
441
304
|
filenameBase: "service_alerts",
|
|
@@ -620,17 +483,20 @@ function convertLongTimeToDate(longDate) {
|
|
|
620
483
|
}
|
|
621
484
|
|
|
622
485
|
// src/lib/import.ts
|
|
623
|
-
var downloadGtfsRealtimeData = async (
|
|
624
|
-
|
|
486
|
+
var downloadGtfsRealtimeData = async (urlAndHeaders, task) => {
|
|
487
|
+
task.log(`Downloading GTFS-Realtime from ${urlAndHeaders.url}`);
|
|
488
|
+
const response = await fetch(urlAndHeaders.url, {
|
|
625
489
|
method: "GET",
|
|
626
490
|
headers: {
|
|
627
|
-
...
|
|
491
|
+
...urlAndHeaders.headers ?? {},
|
|
628
492
|
"Accept-Encoding": "gzip"
|
|
629
493
|
},
|
|
630
494
|
signal: task.downloadTimeout ? AbortSignal.timeout(task.downloadTimeout) : void 0
|
|
631
495
|
});
|
|
632
496
|
if (response.status !== 200) {
|
|
633
|
-
task.logWarning(
|
|
497
|
+
task.logWarning(
|
|
498
|
+
`Unable to download GTFS-Realtime from ${urlAndHeaders.url}`
|
|
499
|
+
);
|
|
634
500
|
return null;
|
|
635
501
|
}
|
|
636
502
|
const buffer = await response.arrayBuffer();
|
|
@@ -711,48 +577,70 @@ var prepareRealtimeValue = (entity, column, task) => {
|
|
|
711
577
|
);
|
|
712
578
|
};
|
|
713
579
|
var updateRealtimeData = async (task) => {
|
|
714
|
-
if (
|
|
580
|
+
if (task.realtimeAlerts === void 0 && task.realtimeTripUpdates === void 0 && task.realtimeVehiclePositions === void 0) {
|
|
715
581
|
return;
|
|
716
582
|
}
|
|
717
583
|
const db = openDb({
|
|
718
584
|
sqlitePath: task.sqlitePath
|
|
719
585
|
});
|
|
720
|
-
task.
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
586
|
+
if (task.realtimeAlerts?.url) {
|
|
587
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
588
|
+
task.realtimeAlerts,
|
|
589
|
+
task
|
|
590
|
+
);
|
|
591
|
+
if (gtfsRealtimeData?.entity) {
|
|
592
|
+
task.log(`Download successful`);
|
|
593
|
+
let totalLineCount = 0;
|
|
594
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
595
|
+
const fieldValues = serviceAlerts.schema.map(
|
|
596
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
597
|
+
);
|
|
598
|
+
try {
|
|
599
|
+
db.prepare(
|
|
600
|
+
`REPLACE INTO ${serviceAlerts.filenameBase} (${serviceAlerts.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
601
|
+
).run();
|
|
602
|
+
} catch (error) {
|
|
603
|
+
task.logWarning("Import error: " + error.message);
|
|
604
|
+
}
|
|
605
|
+
const alertTargetArray = [];
|
|
606
|
+
for (const informedEntity of entity.alert.informedEntity) {
|
|
607
|
+
informedEntity.parent = entity;
|
|
608
|
+
const subValues = serviceAlertTargets.schema.map(
|
|
609
|
+
(column) => prepareRealtimeValue(informedEntity, column, task)
|
|
610
|
+
);
|
|
611
|
+
alertTargetArray.push(`(${subValues.join(", ")})`);
|
|
612
|
+
totalLineCount++;
|
|
613
|
+
}
|
|
614
|
+
try {
|
|
615
|
+
db.prepare(
|
|
616
|
+
`REPLACE INTO ${serviceAlertTargets.filenameBase} (${serviceAlertTargets.schema.map((column) => column.name).join(", ")}) VALUES ${alertTargetArray.join(", ")}`
|
|
617
|
+
).run();
|
|
618
|
+
} catch (error) {
|
|
619
|
+
task.logWarning("Import error: " + error.message);
|
|
620
|
+
}
|
|
621
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
754
622
|
}
|
|
755
|
-
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (task.realtimeTripUpdates?.url) {
|
|
626
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
627
|
+
task.realtimeTripUpdates,
|
|
628
|
+
task
|
|
629
|
+
);
|
|
630
|
+
if (gtfsRealtimeData?.entity) {
|
|
631
|
+
task.log(`Download successful`);
|
|
632
|
+
let totalLineCount = 0;
|
|
633
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
634
|
+
const fieldValues = tripUpdates.schema.map(
|
|
635
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
636
|
+
);
|
|
637
|
+
try {
|
|
638
|
+
db.prepare(
|
|
639
|
+
`REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
640
|
+
).run();
|
|
641
|
+
} catch (error) {
|
|
642
|
+
task.logWarning("Import error: " + error.message);
|
|
643
|
+
}
|
|
756
644
|
const stopTimeUpdateArray = [];
|
|
757
645
|
for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
|
|
758
646
|
stopTimeUpdate.parent = entity;
|
|
@@ -769,26 +657,31 @@ var updateRealtimeData = async (task) => {
|
|
|
769
657
|
} catch (error) {
|
|
770
658
|
task.logWarning("Import error: " + error.message);
|
|
771
659
|
}
|
|
660
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
772
661
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
if (task.realtimeVehiclePositions?.url) {
|
|
665
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
666
|
+
task.realtimeVehiclePositions,
|
|
667
|
+
task
|
|
668
|
+
);
|
|
669
|
+
if (gtfsRealtimeData?.entity) {
|
|
670
|
+
task.log(`Download successful`);
|
|
671
|
+
let totalLineCount = 0;
|
|
672
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
673
|
+
const fieldValues = tripUpdates.schema.map(
|
|
674
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
675
|
+
);
|
|
783
676
|
try {
|
|
784
677
|
db.prepare(
|
|
785
|
-
`REPLACE INTO ${
|
|
678
|
+
`REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
786
679
|
).run();
|
|
787
680
|
} catch (error) {
|
|
788
681
|
task.logWarning("Import error: " + error.message);
|
|
789
682
|
}
|
|
683
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
790
684
|
}
|
|
791
|
-
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
792
685
|
}
|
|
793
686
|
}
|
|
794
687
|
task.log(`GTFS-Realtime data import complete`);
|
|
@@ -812,12 +705,10 @@ async function updateGtfsRealtime(initialConfig) {
|
|
|
812
705
|
deleteExpiredRealtimeData(config);
|
|
813
706
|
await Promise.all(
|
|
814
707
|
config.agencies.map(async (agency2) => {
|
|
815
|
-
if (agency2.realtimeUrls === void 0) {
|
|
816
|
-
return;
|
|
817
|
-
}
|
|
818
708
|
const task = {
|
|
819
|
-
|
|
820
|
-
|
|
709
|
+
realtimeAlerts: agency2.realtimeAlerts,
|
|
710
|
+
realtimeTripUpdates: agency2.realtimeTripUpdates,
|
|
711
|
+
realtimeVehiclePositions: agency2.realtimeVehiclePositions,
|
|
821
712
|
downloadTimeout: config.downloadTimeout,
|
|
822
713
|
gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,
|
|
823
714
|
sqlitePath: config.sqlitePath,
|
|
@@ -840,7 +731,7 @@ async function updateGtfsRealtime(initialConfig) {
|
|
|
840
731
|
} catch (error) {
|
|
841
732
|
if (error?.code === "SQLITE_CANTOPEN") {
|
|
842
733
|
logError2(
|
|
843
|
-
`
|
|
734
|
+
`Unable to open sqlite database "${config.sqlitePath}" defined as \`sqlitePath\` config.json. Ensure the parent directory exists or remove \`sqlitePath\` from config.json.`
|
|
844
735
|
);
|
|
845
736
|
}
|
|
846
737
|
throw error;
|