gtfs 4.13.4 → 4.14.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/README.md +36 -20
- package/dist/bin/gtfs-export.js +4 -8
- package/dist/bin/gtfs-export.js.map +1 -1
- package/dist/bin/gtfs-import.js +93 -66
- package/dist/bin/gtfs-import.js.map +1 -1
- package/dist/bin/gtfsrealtime-update.js +89 -197
- package/dist/bin/gtfsrealtime-update.js.map +1 -1
- package/dist/index.d.ts +325 -43
- package/dist/index.js +116 -88
- package/dist/index.js.map +1 -1
- package/dist/models/models.d.ts +0 -8
- package/dist/models/models.js +0 -5
- package/dist/models/models.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",
|
|
@@ -578,6 +441,7 @@ function openDb(config = null) {
|
|
|
578
441
|
// src/lib/geojson-utils.ts
|
|
579
442
|
import {
|
|
580
443
|
cloneDeep,
|
|
444
|
+
compact,
|
|
581
445
|
filter,
|
|
582
446
|
groupBy,
|
|
583
447
|
last,
|
|
@@ -620,17 +484,20 @@ function convertLongTimeToDate(longDate) {
|
|
|
620
484
|
}
|
|
621
485
|
|
|
622
486
|
// src/lib/import.ts
|
|
623
|
-
var downloadGtfsRealtimeData = async (
|
|
624
|
-
|
|
487
|
+
var downloadGtfsRealtimeData = async (urlAndHeaders, task) => {
|
|
488
|
+
task.log(`Downloading GTFS-Realtime from ${urlAndHeaders.url}`);
|
|
489
|
+
const response = await fetch(urlAndHeaders.url, {
|
|
625
490
|
method: "GET",
|
|
626
491
|
headers: {
|
|
627
|
-
...
|
|
492
|
+
...urlAndHeaders.headers ?? {},
|
|
628
493
|
"Accept-Encoding": "gzip"
|
|
629
494
|
},
|
|
630
495
|
signal: task.downloadTimeout ? AbortSignal.timeout(task.downloadTimeout) : void 0
|
|
631
496
|
});
|
|
632
497
|
if (response.status !== 200) {
|
|
633
|
-
task.logWarning(
|
|
498
|
+
task.logWarning(
|
|
499
|
+
`Unable to download GTFS-Realtime from ${urlAndHeaders.url}`
|
|
500
|
+
);
|
|
634
501
|
return null;
|
|
635
502
|
}
|
|
636
503
|
const buffer = await response.arrayBuffer();
|
|
@@ -711,48 +578,70 @@ var prepareRealtimeValue = (entity, column, task) => {
|
|
|
711
578
|
);
|
|
712
579
|
};
|
|
713
580
|
var updateRealtimeData = async (task) => {
|
|
714
|
-
if (
|
|
581
|
+
if (task.realtimeAlerts === void 0 && task.realtimeTripUpdates === void 0 && task.realtimeVehiclePositions === void 0) {
|
|
715
582
|
return;
|
|
716
583
|
}
|
|
717
584
|
const db = openDb({
|
|
718
585
|
sqlitePath: task.sqlitePath
|
|
719
586
|
});
|
|
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
|
-
|
|
587
|
+
if (task.realtimeAlerts?.url) {
|
|
588
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
589
|
+
task.realtimeAlerts,
|
|
590
|
+
task
|
|
591
|
+
);
|
|
592
|
+
if (gtfsRealtimeData?.entity) {
|
|
593
|
+
task.log(`Download successful`);
|
|
594
|
+
let totalLineCount = 0;
|
|
595
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
596
|
+
const fieldValues = serviceAlerts.schema.map(
|
|
597
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
598
|
+
);
|
|
599
|
+
try {
|
|
600
|
+
db.prepare(
|
|
601
|
+
`REPLACE INTO ${serviceAlerts.filenameBase} (${serviceAlerts.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
602
|
+
).run();
|
|
603
|
+
} catch (error) {
|
|
604
|
+
task.logWarning("Import error: " + error.message);
|
|
605
|
+
}
|
|
606
|
+
const alertTargetArray = [];
|
|
607
|
+
for (const informedEntity of entity.alert.informedEntity) {
|
|
608
|
+
informedEntity.parent = entity;
|
|
609
|
+
const subValues = serviceAlertTargets.schema.map(
|
|
610
|
+
(column) => prepareRealtimeValue(informedEntity, column, task)
|
|
611
|
+
);
|
|
612
|
+
alertTargetArray.push(`(${subValues.join(", ")})`);
|
|
613
|
+
totalLineCount++;
|
|
614
|
+
}
|
|
615
|
+
try {
|
|
616
|
+
db.prepare(
|
|
617
|
+
`REPLACE INTO ${serviceAlertTargets.filenameBase} (${serviceAlertTargets.schema.map((column) => column.name).join(", ")}) VALUES ${alertTargetArray.join(", ")}`
|
|
618
|
+
).run();
|
|
619
|
+
} catch (error) {
|
|
620
|
+
task.logWarning("Import error: " + error.message);
|
|
621
|
+
}
|
|
622
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
754
623
|
}
|
|
755
|
-
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if (task.realtimeTripUpdates?.url) {
|
|
627
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
628
|
+
task.realtimeTripUpdates,
|
|
629
|
+
task
|
|
630
|
+
);
|
|
631
|
+
if (gtfsRealtimeData?.entity) {
|
|
632
|
+
task.log(`Download successful`);
|
|
633
|
+
let totalLineCount = 0;
|
|
634
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
635
|
+
const fieldValues = tripUpdates.schema.map(
|
|
636
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
637
|
+
);
|
|
638
|
+
try {
|
|
639
|
+
db.prepare(
|
|
640
|
+
`REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
641
|
+
).run();
|
|
642
|
+
} catch (error) {
|
|
643
|
+
task.logWarning("Import error: " + error.message);
|
|
644
|
+
}
|
|
756
645
|
const stopTimeUpdateArray = [];
|
|
757
646
|
for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
|
|
758
647
|
stopTimeUpdate.parent = entity;
|
|
@@ -769,26 +658,31 @@ var updateRealtimeData = async (task) => {
|
|
|
769
658
|
} catch (error) {
|
|
770
659
|
task.logWarning("Import error: " + error.message);
|
|
771
660
|
}
|
|
661
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
772
662
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (task.realtimeVehiclePositions?.url) {
|
|
666
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
667
|
+
task.realtimeVehiclePositions,
|
|
668
|
+
task
|
|
669
|
+
);
|
|
670
|
+
if (gtfsRealtimeData?.entity) {
|
|
671
|
+
task.log(`Download successful`);
|
|
672
|
+
let totalLineCount = 0;
|
|
673
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
674
|
+
const fieldValues = tripUpdates.schema.map(
|
|
675
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
676
|
+
);
|
|
783
677
|
try {
|
|
784
678
|
db.prepare(
|
|
785
|
-
`REPLACE INTO ${
|
|
679
|
+
`REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
786
680
|
).run();
|
|
787
681
|
} catch (error) {
|
|
788
682
|
task.logWarning("Import error: " + error.message);
|
|
789
683
|
}
|
|
684
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
790
685
|
}
|
|
791
|
-
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
792
686
|
}
|
|
793
687
|
}
|
|
794
688
|
task.log(`GTFS-Realtime data import complete`);
|
|
@@ -812,12 +706,10 @@ async function updateGtfsRealtime(initialConfig) {
|
|
|
812
706
|
deleteExpiredRealtimeData(config);
|
|
813
707
|
await Promise.all(
|
|
814
708
|
config.agencies.map(async (agency2) => {
|
|
815
|
-
if (agency2.realtimeUrls === void 0) {
|
|
816
|
-
return;
|
|
817
|
-
}
|
|
818
709
|
const task = {
|
|
819
|
-
|
|
820
|
-
|
|
710
|
+
realtimeAlerts: agency2.realtimeAlerts,
|
|
711
|
+
realtimeTripUpdates: agency2.realtimeTripUpdates,
|
|
712
|
+
realtimeVehiclePositions: agency2.realtimeVehiclePositions,
|
|
821
713
|
downloadTimeout: config.downloadTimeout,
|
|
822
714
|
gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,
|
|
823
715
|
sqlitePath: config.sqlitePath,
|
|
@@ -840,7 +732,7 @@ async function updateGtfsRealtime(initialConfig) {
|
|
|
840
732
|
} catch (error) {
|
|
841
733
|
if (error?.code === "SQLITE_CANTOPEN") {
|
|
842
734
|
logError2(
|
|
843
|
-
`
|
|
735
|
+
`Unable to open sqlite database "${config.sqlitePath}" defined as \`sqlitePath\` config.json. Ensure the parent directory exists or remove \`sqlitePath\` from config.json.`
|
|
844
736
|
);
|
|
845
737
|
}
|
|
846
738
|
throw error;
|
|
@@ -848,7 +740,7 @@ async function updateGtfsRealtime(initialConfig) {
|
|
|
848
740
|
}
|
|
849
741
|
|
|
850
742
|
// src/lib/export.ts
|
|
851
|
-
import { without, compact } from "lodash-es";
|
|
743
|
+
import { without, compact as compact2 } from "lodash-es";
|
|
852
744
|
import pluralize2 from "pluralize";
|
|
853
745
|
import { stringify } from "csv-stringify";
|
|
854
746
|
import sqlString3 from "sqlstring-sqlite";
|
|
@@ -862,7 +754,7 @@ import sqlString4 from "sqlstring-sqlite";
|
|
|
862
754
|
import { omit as omit3, pick } from "lodash-es";
|
|
863
755
|
|
|
864
756
|
// src/lib/gtfs/shapes.ts
|
|
865
|
-
import { compact as
|
|
757
|
+
import { compact as compact3, omit as omit4, pick as pick2 } from "lodash-es";
|
|
866
758
|
import { featureCollection as featureCollection2 } from "@turf/helpers";
|
|
867
759
|
|
|
868
760
|
// src/lib/gtfs/stops.ts
|