gtfs 4.18.6 → 4.19.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 +65 -8
- package/dist/bin/gtfs-export.js +24 -14
- package/dist/bin/gtfs-export.js.map +1 -1
- package/dist/bin/gtfs-import.js +71 -49
- package/dist/bin/gtfs-import.js.map +1 -1
- package/dist/bin/gtfsrealtime-update.js +43 -37
- package/dist/bin/gtfsrealtime-update.js.map +1 -1
- package/dist/index.d.ts +34 -4
- package/dist/index.js +128 -52
- package/dist/index.js.map +1 -1
- package/dist/models/models.d.ts +58 -10
- package/dist/models/models.js +24 -14
- package/dist/models/models.js.map +1 -1
- package/package.json +8 -6
package/dist/bin/gtfs-import.js
CHANGED
|
@@ -1126,6 +1126,7 @@ var routes = {
|
|
|
1126
1126
|
{
|
|
1127
1127
|
name: "agency_id",
|
|
1128
1128
|
type: "text",
|
|
1129
|
+
index: true,
|
|
1129
1130
|
prefix: true
|
|
1130
1131
|
},
|
|
1131
1132
|
{
|
|
@@ -1378,7 +1379,8 @@ var stops = {
|
|
|
1378
1379
|
},
|
|
1379
1380
|
{
|
|
1380
1381
|
name: "stop_code",
|
|
1381
|
-
type: "text"
|
|
1382
|
+
type: "text",
|
|
1383
|
+
index: true
|
|
1382
1384
|
},
|
|
1383
1385
|
{
|
|
1384
1386
|
name: "stop_name",
|
|
@@ -1664,6 +1666,14 @@ var trips = {
|
|
|
1664
1666
|
type: "integer",
|
|
1665
1667
|
min: 0,
|
|
1666
1668
|
max: 2
|
|
1669
|
+
},
|
|
1670
|
+
{
|
|
1671
|
+
name: "safe_duration_factor",
|
|
1672
|
+
type: "real"
|
|
1673
|
+
},
|
|
1674
|
+
{
|
|
1675
|
+
name: "safe_duration_offset",
|
|
1676
|
+
type: "real"
|
|
1667
1677
|
}
|
|
1668
1678
|
]
|
|
1669
1679
|
};
|
|
@@ -2872,16 +2882,14 @@ var serviceAlerts = {
|
|
|
2872
2882
|
{
|
|
2873
2883
|
name: "start_time",
|
|
2874
2884
|
type: "text",
|
|
2875
|
-
required: true,
|
|
2876
2885
|
source: "alert.activePeriod[0].start",
|
|
2877
|
-
default:
|
|
2886
|
+
default: null
|
|
2878
2887
|
},
|
|
2879
2888
|
{
|
|
2880
2889
|
name: "end_time",
|
|
2881
2890
|
type: "text",
|
|
2882
|
-
required: true,
|
|
2883
2891
|
source: "alert.activePeriod[0].end",
|
|
2884
|
-
default:
|
|
2892
|
+
default: null
|
|
2885
2893
|
},
|
|
2886
2894
|
{
|
|
2887
2895
|
name: "header_text",
|
|
@@ -2941,7 +2949,7 @@ var serviceAlertInformedEntities = {
|
|
|
2941
2949
|
{
|
|
2942
2950
|
name: "stop_id",
|
|
2943
2951
|
type: "text",
|
|
2944
|
-
|
|
2952
|
+
primary: true,
|
|
2945
2953
|
source: "stopId",
|
|
2946
2954
|
default: null,
|
|
2947
2955
|
prefix: true
|
|
@@ -2949,7 +2957,7 @@ var serviceAlertInformedEntities = {
|
|
|
2949
2957
|
{
|
|
2950
2958
|
name: "route_id",
|
|
2951
2959
|
type: "text",
|
|
2952
|
-
|
|
2960
|
+
primary: true,
|
|
2953
2961
|
source: "routeId",
|
|
2954
2962
|
default: null,
|
|
2955
2963
|
prefix: true
|
|
@@ -2957,14 +2965,14 @@ var serviceAlertInformedEntities = {
|
|
|
2957
2965
|
{
|
|
2958
2966
|
name: "route_type",
|
|
2959
2967
|
type: "integer",
|
|
2960
|
-
|
|
2968
|
+
primary: true,
|
|
2961
2969
|
source: "routeType",
|
|
2962
2970
|
default: null
|
|
2963
2971
|
},
|
|
2964
2972
|
{
|
|
2965
2973
|
name: "trip_id",
|
|
2966
2974
|
type: "text",
|
|
2967
|
-
|
|
2975
|
+
primary: true,
|
|
2968
2976
|
source: "trip.tripId",
|
|
2969
2977
|
default: null,
|
|
2970
2978
|
prefix: true
|
|
@@ -2972,7 +2980,7 @@ var serviceAlertInformedEntities = {
|
|
|
2972
2980
|
{
|
|
2973
2981
|
name: "direction_id",
|
|
2974
2982
|
type: "integer",
|
|
2975
|
-
|
|
2983
|
+
primary: true,
|
|
2976
2984
|
source: "directionId",
|
|
2977
2985
|
default: null
|
|
2978
2986
|
},
|
|
@@ -3489,7 +3497,8 @@ var passengerEvents = {
|
|
|
3489
3497
|
{
|
|
3490
3498
|
name: "trip_stop_sequence",
|
|
3491
3499
|
type: "integer",
|
|
3492
|
-
min: 1
|
|
3500
|
+
min: 1,
|
|
3501
|
+
required: true
|
|
3493
3502
|
},
|
|
3494
3503
|
{
|
|
3495
3504
|
name: "scheduled_stop_sequence",
|
|
@@ -3715,7 +3724,8 @@ var stopVisits = {
|
|
|
3715
3724
|
},
|
|
3716
3725
|
{
|
|
3717
3726
|
name: "ramp_deployed_time",
|
|
3718
|
-
type: "
|
|
3727
|
+
type: "real",
|
|
3728
|
+
min: 0
|
|
3719
3729
|
},
|
|
3720
3730
|
{
|
|
3721
3731
|
name: "ramp_failure",
|
|
@@ -3723,12 +3733,12 @@ var stopVisits = {
|
|
|
3723
3733
|
},
|
|
3724
3734
|
{
|
|
3725
3735
|
name: "kneel_deployed_time",
|
|
3726
|
-
type: "
|
|
3736
|
+
type: "real",
|
|
3727
3737
|
min: 0
|
|
3728
3738
|
},
|
|
3729
3739
|
{
|
|
3730
3740
|
name: "lift_deployed_time",
|
|
3731
|
-
type: "
|
|
3741
|
+
type: "real",
|
|
3732
3742
|
min: 0
|
|
3733
3743
|
},
|
|
3734
3744
|
{
|
|
@@ -4328,7 +4338,7 @@ function getTimestampColumnName(columnName) {
|
|
|
4328
4338
|
return columnName.endsWith("time") ? `${columnName}stamp` : `${columnName}_timestamp`;
|
|
4329
4339
|
}
|
|
4330
4340
|
function applyPrefixToValue(value, columnShouldBePrefixed, prefix) {
|
|
4331
|
-
if (!columnShouldBePrefixed || prefix === void 0 || value === null) {
|
|
4341
|
+
if (!columnShouldBePrefixed || prefix === void 0 || value === null || value === void 0) {
|
|
4332
4342
|
return value;
|
|
4333
4343
|
}
|
|
4334
4344
|
return `${prefix}${value}`;
|
|
@@ -4391,13 +4401,15 @@ async function fetchGtfsRealtimeData(type, task) {
|
|
|
4391
4401
|
try {
|
|
4392
4402
|
const response = await fetch(urlConfig.url, {
|
|
4393
4403
|
method: "GET",
|
|
4404
|
+
redirect: "follow",
|
|
4394
4405
|
headers: {
|
|
4406
|
+
"User-Agent": "node-gtfs",
|
|
4395
4407
|
...urlConfig.headers ?? {},
|
|
4396
4408
|
"Accept-Encoding": "gzip"
|
|
4397
4409
|
},
|
|
4398
4410
|
signal: task.downloadTimeout ? AbortSignal.timeout(task.downloadTimeout) : void 0
|
|
4399
4411
|
});
|
|
4400
|
-
if (response.
|
|
4412
|
+
if (!response.ok) {
|
|
4401
4413
|
throw new GtfsError(`HTTP ${response.status}: ${response.statusText}`, {
|
|
4402
4414
|
code: "GTFS_DOWNLOAD_HTTP" /* GTFS_DOWNLOAD_HTTP */,
|
|
4403
4415
|
category: "download" /* DOWNLOAD */,
|
|
@@ -4470,12 +4482,17 @@ function createServiceAlertsProcessor(db, task) {
|
|
|
4470
4482
|
db,
|
|
4471
4483
|
serviceAlertInformedEntities
|
|
4472
4484
|
);
|
|
4485
|
+
const deleteInformedEntitiesStmt = db.prepare(
|
|
4486
|
+
`DELETE FROM ${serviceAlertInformedEntities.filenameBase} WHERE alert_id = ?`
|
|
4487
|
+
);
|
|
4473
4488
|
return async (batch) => {
|
|
4474
4489
|
let recordCount = 0;
|
|
4475
4490
|
let errorCount = 0;
|
|
4476
4491
|
db.transaction(() => {
|
|
4477
4492
|
for (const entity of batch) {
|
|
4478
4493
|
try {
|
|
4494
|
+
const alertId = applyPrefixToValue(entity.id, true, task.prefix);
|
|
4495
|
+
deleteInformedEntitiesStmt.run(alertId);
|
|
4479
4496
|
const alertValues = serviceAlerts.schema.map((column) => prepareRealtimeFieldValue(entity, column, task));
|
|
4480
4497
|
alertStmt.run(alertValues);
|
|
4481
4498
|
recordCount++;
|
|
@@ -4508,6 +4525,9 @@ function createTripUpdatesProcessor(db, task) {
|
|
|
4508
4525
|
db,
|
|
4509
4526
|
stopTimeUpdates
|
|
4510
4527
|
);
|
|
4528
|
+
const deleteStopTimesByTripStmt = db.prepare(
|
|
4529
|
+
`DELETE FROM ${stopTimeUpdates.filenameBase} WHERE trip_id = ? AND trip_start_time IS ?`
|
|
4530
|
+
);
|
|
4511
4531
|
return async (batch) => {
|
|
4512
4532
|
let recordCount = 0;
|
|
4513
4533
|
let errorCount = 0;
|
|
@@ -4518,6 +4538,15 @@ function createTripUpdatesProcessor(db, task) {
|
|
|
4518
4538
|
tripUpdateStmt.run(tripUpdateValues);
|
|
4519
4539
|
recordCount++;
|
|
4520
4540
|
if (entity.tripUpdate?.stopTimeUpdate?.length) {
|
|
4541
|
+
const tripId = applyPrefixToValue(
|
|
4542
|
+
entity.tripUpdate?.trip?.tripId ?? null,
|
|
4543
|
+
true,
|
|
4544
|
+
task.prefix
|
|
4545
|
+
);
|
|
4546
|
+
const tripStartTime = entity.tripUpdate?.trip?.startTime ?? null;
|
|
4547
|
+
if (tripId !== null) {
|
|
4548
|
+
deleteStopTimesByTripStmt.run(tripId, tripStartTime);
|
|
4549
|
+
}
|
|
4521
4550
|
for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
|
|
4522
4551
|
stopTimeUpdate.parent = entity;
|
|
4523
4552
|
const stopTimeValues = stopTimeUpdates.schema.map(
|
|
@@ -4578,41 +4607,30 @@ async function updateGtfsRealtimeData(task) {
|
|
|
4578
4607
|
tripupdates: 0,
|
|
4579
4608
|
vehiclepositions: 0
|
|
4580
4609
|
};
|
|
4581
|
-
const processingPromises = [];
|
|
4582
4610
|
if (alertsData?.entity?.length) {
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
createServiceAlertsProcessor(db, task)
|
|
4588
|
-
).then((result) => {
|
|
4589
|
-
recordCounts.alerts = result.recordCount;
|
|
4590
|
-
})
|
|
4611
|
+
const result = await processBatch(
|
|
4612
|
+
alertsData.entity,
|
|
4613
|
+
BATCH_SIZE,
|
|
4614
|
+
createServiceAlertsProcessor(db, task)
|
|
4591
4615
|
);
|
|
4616
|
+
recordCounts.alerts = result.recordCount;
|
|
4592
4617
|
}
|
|
4593
4618
|
if (tripUpdatesData?.entity?.length) {
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
createTripUpdatesProcessor(db, task)
|
|
4599
|
-
).then((result) => {
|
|
4600
|
-
recordCounts.tripupdates = result.recordCount;
|
|
4601
|
-
})
|
|
4619
|
+
const result = await processBatch(
|
|
4620
|
+
tripUpdatesData.entity,
|
|
4621
|
+
BATCH_SIZE,
|
|
4622
|
+
createTripUpdatesProcessor(db, task)
|
|
4602
4623
|
);
|
|
4624
|
+
recordCounts.tripupdates = result.recordCount;
|
|
4603
4625
|
}
|
|
4604
4626
|
if (vehiclePositionsData?.entity?.length) {
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
createVehiclePositionsProcessor(db, task)
|
|
4610
|
-
).then((result) => {
|
|
4611
|
-
recordCounts.vehiclepositions = result.recordCount;
|
|
4612
|
-
})
|
|
4627
|
+
const result = await processBatch(
|
|
4628
|
+
vehiclePositionsData.entity,
|
|
4629
|
+
BATCH_SIZE,
|
|
4630
|
+
createVehiclePositionsProcessor(db, task)
|
|
4613
4631
|
);
|
|
4632
|
+
recordCounts.vehiclepositions = result.recordCount;
|
|
4614
4633
|
}
|
|
4615
|
-
await Promise.all(processingPromises);
|
|
4616
4634
|
task.log(
|
|
4617
4635
|
`GTFS-Realtime import complete: ${recordCounts.alerts} alerts, ${recordCounts.tripupdates} trip updates, ${recordCounts.vehiclepositions} vehicle positions`
|
|
4618
4636
|
);
|
|
@@ -4640,10 +4658,14 @@ var downloadGtfsFiles = async (task) => {
|
|
|
4640
4658
|
try {
|
|
4641
4659
|
const response = await fetch(task.url, {
|
|
4642
4660
|
method: "GET",
|
|
4643
|
-
|
|
4661
|
+
redirect: "follow",
|
|
4662
|
+
headers: {
|
|
4663
|
+
"User-Agent": "node-gtfs",
|
|
4664
|
+
...task.headers
|
|
4665
|
+
},
|
|
4644
4666
|
signal: task.downloadTimeout ? AbortSignal.timeout(task.downloadTimeout) : void 0
|
|
4645
4667
|
});
|
|
4646
|
-
if (response.
|
|
4668
|
+
if (!response.ok) {
|
|
4647
4669
|
throw new GtfsError(
|
|
4648
4670
|
`Unable to download GTFS from ${task.url}. Got status ${response.status}.`,
|
|
4649
4671
|
{
|
|
@@ -4756,18 +4778,18 @@ var extractGtfsFiles = async (task) => {
|
|
|
4756
4778
|
var createGtfsTables = (db) => {
|
|
4757
4779
|
for (const model of Object.values(models_exports)) {
|
|
4758
4780
|
if (!model.schema) {
|
|
4759
|
-
|
|
4781
|
+
continue;
|
|
4760
4782
|
}
|
|
4761
4783
|
const sqlColumnCreateStatements = [];
|
|
4762
4784
|
for (const column of model.schema) {
|
|
4763
4785
|
const checks = [];
|
|
4764
|
-
if (column.min !== void 0 && column.max) {
|
|
4786
|
+
if (column.min !== void 0 && column.max !== void 0) {
|
|
4765
4787
|
checks.push(
|
|
4766
4788
|
`${column.name} >= ${column.min} AND ${column.name} <= ${column.max}`
|
|
4767
4789
|
);
|
|
4768
|
-
} else if (column.min) {
|
|
4790
|
+
} else if (column.min !== void 0) {
|
|
4769
4791
|
checks.push(`${column.name} >= ${column.min}`);
|
|
4770
|
-
} else if (column.max) {
|
|
4792
|
+
} else if (column.max !== void 0) {
|
|
4771
4793
|
checks.push(`${column.name} <= ${column.max}`);
|
|
4772
4794
|
}
|
|
4773
4795
|
if (column.type === "integer") {
|
|
@@ -4816,7 +4838,7 @@ var createGtfsTables = (db) => {
|
|
|
4816
4838
|
var createGtfsIndexes = (db) => {
|
|
4817
4839
|
for (const model of Object.values(models_exports)) {
|
|
4818
4840
|
if (!model.schema) {
|
|
4819
|
-
|
|
4841
|
+
continue;
|
|
4820
4842
|
}
|
|
4821
4843
|
for (const column of model.schema) {
|
|
4822
4844
|
if (column.index) {
|