gtfs 4.14.3 → 4.14.5
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 +1 -1
- package/dist/bin/gtfs-export.js +1 -0
- package/dist/bin/gtfs-export.js.map +1 -1
- package/dist/bin/gtfs-import.js +156 -125
- package/dist/bin/gtfs-import.js.map +1 -1
- package/dist/bin/gtfsrealtime-update.js +133 -109
- package/dist/bin/gtfsrealtime-update.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +179 -149
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/bin/gtfs-import.js
CHANGED
|
@@ -3318,6 +3318,7 @@ function setDefaultConfig(initialConfig) {
|
|
|
3318
3318
|
const defaults = {
|
|
3319
3319
|
sqlitePath: ":memory:",
|
|
3320
3320
|
ignoreDuplicates: false,
|
|
3321
|
+
ignoreErrors: false,
|
|
3321
3322
|
gtfsRealtimeExpirationSeconds: 0
|
|
3322
3323
|
};
|
|
3323
3324
|
return {
|
|
@@ -3346,6 +3347,9 @@ function padLeadingZeros(time) {
|
|
|
3346
3347
|
|
|
3347
3348
|
// src/lib/import.ts
|
|
3348
3349
|
var downloadFiles = async (task) => {
|
|
3350
|
+
if (!task.url) {
|
|
3351
|
+
throw new Error("No `url` specified in config");
|
|
3352
|
+
}
|
|
3349
3353
|
task.log(`Downloading GTFS from ${task.url}`);
|
|
3350
3354
|
task.path = `${task.downloadDir}/gtfs.zip`;
|
|
3351
3355
|
const response = await fetch(task.url, {
|
|
@@ -3354,7 +3358,9 @@ var downloadFiles = async (task) => {
|
|
|
3354
3358
|
signal: task.downloadTimeout ? AbortSignal.timeout(task.downloadTimeout) : void 0
|
|
3355
3359
|
});
|
|
3356
3360
|
if (response.status !== 200) {
|
|
3357
|
-
throw new Error(
|
|
3361
|
+
throw new Error(
|
|
3362
|
+
`Unable to download GTFS from ${task.url}. Got status ${response.status}.`
|
|
3363
|
+
);
|
|
3358
3364
|
}
|
|
3359
3365
|
const buffer = await response.arrayBuffer();
|
|
3360
3366
|
await writeFile(task.path, Buffer.from(buffer));
|
|
@@ -3372,7 +3378,7 @@ var downloadGtfsRealtimeData = async (urlAndHeaders, task) => {
|
|
|
3372
3378
|
});
|
|
3373
3379
|
if (response.status !== 200) {
|
|
3374
3380
|
task.logWarning(
|
|
3375
|
-
`Unable to download GTFS-Realtime from ${urlAndHeaders.url}
|
|
3381
|
+
`Unable to download GTFS-Realtime from ${urlAndHeaders.url}. Got status ${response.status}.`
|
|
3376
3382
|
);
|
|
3377
3383
|
return null;
|
|
3378
3384
|
}
|
|
@@ -3440,103 +3446,127 @@ var updateRealtimeData = async (task) => {
|
|
|
3440
3446
|
sqlitePath: task.sqlitePath
|
|
3441
3447
|
});
|
|
3442
3448
|
if (task.realtimeAlerts?.url) {
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
const
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
try {
|
|
3455
|
-
db.prepare(
|
|
3456
|
-
`REPLACE INTO ${serviceAlerts.filenameBase} (${serviceAlerts.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
3457
|
-
).run();
|
|
3458
|
-
} catch (error) {
|
|
3459
|
-
task.logWarning("Import error: " + error.message);
|
|
3460
|
-
}
|
|
3461
|
-
const alertTargetArray = [];
|
|
3462
|
-
for (const informedEntity of entity.alert.informedEntity) {
|
|
3463
|
-
informedEntity.parent = entity;
|
|
3464
|
-
const subValues = serviceAlertTargets.schema.map(
|
|
3465
|
-
(column) => prepareRealtimeValue(informedEntity, column, task)
|
|
3449
|
+
try {
|
|
3450
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
3451
|
+
task.realtimeAlerts,
|
|
3452
|
+
task
|
|
3453
|
+
);
|
|
3454
|
+
if (gtfsRealtimeData?.entity) {
|
|
3455
|
+
task.log(`Download successful`);
|
|
3456
|
+
let totalLineCount = 0;
|
|
3457
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
3458
|
+
const fieldValues = serviceAlerts.schema.map(
|
|
3459
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
3466
3460
|
);
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3461
|
+
try {
|
|
3462
|
+
db.prepare(
|
|
3463
|
+
`REPLACE INTO ${serviceAlerts.filenameBase} (${serviceAlerts.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
3464
|
+
).run();
|
|
3465
|
+
} catch (error) {
|
|
3466
|
+
task.logWarning("Import error: " + error.message);
|
|
3467
|
+
}
|
|
3468
|
+
const alertTargetArray = [];
|
|
3469
|
+
for (const informedEntity of entity.alert.informedEntity) {
|
|
3470
|
+
informedEntity.parent = entity;
|
|
3471
|
+
const subValues = serviceAlertTargets.schema.map(
|
|
3472
|
+
(column) => prepareRealtimeValue(informedEntity, column, task)
|
|
3473
|
+
);
|
|
3474
|
+
alertTargetArray.push(`(${subValues.join(", ")})`);
|
|
3475
|
+
totalLineCount++;
|
|
3476
|
+
}
|
|
3477
|
+
try {
|
|
3478
|
+
db.prepare(
|
|
3479
|
+
`REPLACE INTO ${serviceAlertTargets.filenameBase} (${serviceAlertTargets.schema.map((column) => column.name).join(", ")}) VALUES ${alertTargetArray.join(", ")}`
|
|
3480
|
+
).run();
|
|
3481
|
+
} catch (error) {
|
|
3482
|
+
task.logWarning("Import error: " + error.message);
|
|
3483
|
+
}
|
|
3484
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
3476
3485
|
}
|
|
3477
|
-
|
|
3486
|
+
}
|
|
3487
|
+
} catch (error) {
|
|
3488
|
+
if (task.ignoreErrors) {
|
|
3489
|
+
task.logError(error.message);
|
|
3490
|
+
} else {
|
|
3491
|
+
throw error;
|
|
3478
3492
|
}
|
|
3479
3493
|
}
|
|
3480
3494
|
}
|
|
3481
3495
|
if (task.realtimeTripUpdates?.url) {
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
const
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
try {
|
|
3494
|
-
db.prepare(
|
|
3495
|
-
`REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
3496
|
-
).run();
|
|
3497
|
-
} catch (error) {
|
|
3498
|
-
task.logWarning("Import error: " + error.message);
|
|
3499
|
-
}
|
|
3500
|
-
const stopTimeUpdateArray = [];
|
|
3501
|
-
for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
|
|
3502
|
-
stopTimeUpdate.parent = entity;
|
|
3503
|
-
const subValues = stopTimeUpdates.schema.map(
|
|
3504
|
-
(column) => prepareRealtimeValue(stopTimeUpdate, column, task)
|
|
3496
|
+
try {
|
|
3497
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
3498
|
+
task.realtimeTripUpdates,
|
|
3499
|
+
task
|
|
3500
|
+
);
|
|
3501
|
+
if (gtfsRealtimeData?.entity) {
|
|
3502
|
+
task.log(`Download successful`);
|
|
3503
|
+
let totalLineCount = 0;
|
|
3504
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
3505
|
+
const fieldValues = tripUpdates.schema.map(
|
|
3506
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
3505
3507
|
);
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3508
|
+
try {
|
|
3509
|
+
db.prepare(
|
|
3510
|
+
`REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
3511
|
+
).run();
|
|
3512
|
+
} catch (error) {
|
|
3513
|
+
task.logWarning("Import error: " + error.message);
|
|
3514
|
+
}
|
|
3515
|
+
const stopTimeUpdateArray = [];
|
|
3516
|
+
for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
|
|
3517
|
+
stopTimeUpdate.parent = entity;
|
|
3518
|
+
const subValues = stopTimeUpdates.schema.map(
|
|
3519
|
+
(column) => prepareRealtimeValue(stopTimeUpdate, column, task)
|
|
3520
|
+
);
|
|
3521
|
+
stopTimeUpdateArray.push(`(${subValues.join(", ")})`);
|
|
3522
|
+
totalLineCount++;
|
|
3523
|
+
}
|
|
3524
|
+
try {
|
|
3525
|
+
db.prepare(
|
|
3526
|
+
`REPLACE INTO ${stopTimeUpdates.filenameBase} (${stopTimeUpdates.schema.map((column) => column.name).join(", ")}) VALUES ${stopTimeUpdateArray.join(", ")}`
|
|
3527
|
+
).run();
|
|
3528
|
+
} catch (error) {
|
|
3529
|
+
task.logWarning("Import error: " + error.message);
|
|
3530
|
+
}
|
|
3531
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
3515
3532
|
}
|
|
3516
|
-
|
|
3533
|
+
}
|
|
3534
|
+
} catch (error) {
|
|
3535
|
+
if (task.ignoreErrors) {
|
|
3536
|
+
task.logError(error.message);
|
|
3537
|
+
} else {
|
|
3538
|
+
throw error;
|
|
3517
3539
|
}
|
|
3518
3540
|
}
|
|
3519
3541
|
}
|
|
3520
3542
|
if (task.realtimeVehiclePositions?.url) {
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
const
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3543
|
+
try {
|
|
3544
|
+
const gtfsRealtimeData = await downloadGtfsRealtimeData(
|
|
3545
|
+
task.realtimeVehiclePositions,
|
|
3546
|
+
task
|
|
3547
|
+
);
|
|
3548
|
+
if (gtfsRealtimeData?.entity) {
|
|
3549
|
+
task.log(`Download successful`);
|
|
3550
|
+
let totalLineCount = 0;
|
|
3551
|
+
for (const entity of gtfsRealtimeData.entity) {
|
|
3552
|
+
const fieldValues = vehiclePositions.schema.map(
|
|
3553
|
+
(column) => prepareRealtimeValue(entity, column, task)
|
|
3554
|
+
);
|
|
3555
|
+
try {
|
|
3556
|
+
db.prepare(
|
|
3557
|
+
`REPLACE INTO ${vehiclePositions.filenameBase} (${vehiclePositions.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
|
|
3558
|
+
).run();
|
|
3559
|
+
} catch (error) {
|
|
3560
|
+
task.logWarning("Import error: " + error.message);
|
|
3561
|
+
}
|
|
3562
|
+
task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
|
|
3538
3563
|
}
|
|
3539
|
-
|
|
3564
|
+
}
|
|
3565
|
+
} catch (error) {
|
|
3566
|
+
if (task.ignoreErrors) {
|
|
3567
|
+
task.logError(error.message);
|
|
3568
|
+
} else {
|
|
3569
|
+
throw error;
|
|
3540
3570
|
}
|
|
3541
3571
|
}
|
|
3542
3572
|
}
|
|
@@ -3547,6 +3577,9 @@ var getTextFiles = async (folderPath) => {
|
|
|
3547
3577
|
return files.filter((filename) => filename.slice(-3) === "txt");
|
|
3548
3578
|
};
|
|
3549
3579
|
var readFiles = async (task) => {
|
|
3580
|
+
if (!task.path) {
|
|
3581
|
+
throw new Error("No `path` specified in config");
|
|
3582
|
+
}
|
|
3550
3583
|
const gtfsPath = untildify3(task.path);
|
|
3551
3584
|
task.log(`Importing GTFS from ${task.path}\r`);
|
|
3552
3585
|
if (path2.extname(gtfsPath) === ".zip") {
|
|
@@ -3843,47 +3876,45 @@ async function importGtfs(initialConfig) {
|
|
|
3843
3876
|
)} using SQLite database at ${config.sqlitePath}`
|
|
3844
3877
|
);
|
|
3845
3878
|
createTables(db);
|
|
3846
|
-
await mapSeries(
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
throw error;
|
|
3883
|
-
}
|
|
3879
|
+
await mapSeries(config.agencies, async (agency2) => {
|
|
3880
|
+
try {
|
|
3881
|
+
const tempPath = temporaryDirectory();
|
|
3882
|
+
const task = {
|
|
3883
|
+
exclude: agency2.exclude,
|
|
3884
|
+
url: agency2.url,
|
|
3885
|
+
headers: agency2.headers,
|
|
3886
|
+
realtimeAlerts: agency2.realtimeAlerts,
|
|
3887
|
+
realtimeTripUpdates: agency2.realtimeTripUpdates,
|
|
3888
|
+
realtimeVehiclePositions: agency2.realtimeVehiclePositions,
|
|
3889
|
+
downloadDir: tempPath,
|
|
3890
|
+
downloadTimeout: config.downloadTimeout,
|
|
3891
|
+
gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,
|
|
3892
|
+
path: agency2.path,
|
|
3893
|
+
csvOptions: config.csvOptions || {},
|
|
3894
|
+
ignoreDuplicates: config.ignoreDuplicates,
|
|
3895
|
+
ignoreErrors: config.ignoreErrors,
|
|
3896
|
+
sqlitePath: config.sqlitePath,
|
|
3897
|
+
prefix: agency2.prefix,
|
|
3898
|
+
currentTimestamp: Math.floor(Date.now() / 1e3),
|
|
3899
|
+
log: log2,
|
|
3900
|
+
logWarning: logWarning2,
|
|
3901
|
+
logError: logError2
|
|
3902
|
+
};
|
|
3903
|
+
if (task.url) {
|
|
3904
|
+
await downloadFiles(task);
|
|
3905
|
+
}
|
|
3906
|
+
await readFiles(task);
|
|
3907
|
+
await importFiles(task);
|
|
3908
|
+
await updateRealtimeData(task);
|
|
3909
|
+
await rm2(tempPath, { recursive: true });
|
|
3910
|
+
} catch (error) {
|
|
3911
|
+
if (config.ignoreErrors) {
|
|
3912
|
+
logError2(error.message);
|
|
3913
|
+
} else {
|
|
3914
|
+
throw error;
|
|
3884
3915
|
}
|
|
3885
3916
|
}
|
|
3886
|
-
);
|
|
3917
|
+
});
|
|
3887
3918
|
log2(
|
|
3888
3919
|
`Completed GTFS import for ${pluralize("agency", agencyCount, true)}
|
|
3889
3920
|
`
|