gtfs 4.17.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/index.js CHANGED
@@ -1285,7 +1285,8 @@ var stops = {
1285
1285
  {
1286
1286
  name: "parent_station",
1287
1287
  type: "text",
1288
- index: true
1288
+ index: true,
1289
+ prefix: true
1289
1290
  },
1290
1291
  {
1291
1292
  name: "stop_timezone",
@@ -2381,21 +2382,24 @@ var tripUpdates = {
2381
2382
  required: true,
2382
2383
  primary: true,
2383
2384
  index: true,
2384
- source: "id"
2385
+ source: "id",
2386
+ prefix: true
2385
2387
  },
2386
2388
  {
2387
2389
  name: "vehicle_id",
2388
2390
  type: "text",
2389
2391
  index: true,
2390
2392
  source: "tripUpdate.vehicle.id",
2391
- default: null
2393
+ default: null,
2394
+ prefix: true
2392
2395
  },
2393
2396
  {
2394
2397
  name: "trip_id",
2395
2398
  type: "text",
2396
2399
  index: true,
2397
2400
  source: "tripUpdate.trip.tripId",
2398
- default: null
2401
+ default: null,
2402
+ prefix: true
2399
2403
  },
2400
2404
  {
2401
2405
  name: "trip_start_time",
@@ -2414,7 +2418,8 @@ var tripUpdates = {
2414
2418
  type: "text",
2415
2419
  index: true,
2416
2420
  source: "tripUpdate.trip.routeId",
2417
- default: null
2421
+ default: null,
2422
+ prefix: true
2418
2423
  },
2419
2424
  {
2420
2425
  name: "start_date",
@@ -2457,7 +2462,8 @@ var stopTimeUpdates = {
2457
2462
  type: "text",
2458
2463
  index: true,
2459
2464
  source: "parent.tripUpdate.trip.tripId",
2460
- default: null
2465
+ default: null,
2466
+ prefix: true
2461
2467
  },
2462
2468
  {
2463
2469
  name: "trip_start_time",
@@ -2476,14 +2482,16 @@ var stopTimeUpdates = {
2476
2482
  type: "text",
2477
2483
  index: true,
2478
2484
  source: "parent.tripUpdate.trip.routeId",
2479
- default: null
2485
+ default: null,
2486
+ prefix: true
2480
2487
  },
2481
2488
  {
2482
2489
  name: "stop_id",
2483
2490
  type: "text",
2484
2491
  index: true,
2485
2492
  source: "stopId",
2486
- default: null
2493
+ default: null,
2494
+ prefix: true
2487
2495
  },
2488
2496
  {
2489
2497
  name: "stop_sequence",
@@ -2545,7 +2553,8 @@ var vehiclePositions = {
2545
2553
  required: true,
2546
2554
  primary: true,
2547
2555
  index: true,
2548
- source: "id"
2556
+ source: "id",
2557
+ prefix: true
2549
2558
  },
2550
2559
  {
2551
2560
  name: "bearing",
@@ -2587,7 +2596,8 @@ var vehiclePositions = {
2587
2596
  type: "text",
2588
2597
  index: true,
2589
2598
  source: "vehicle.trip.tripId",
2590
- default: null
2599
+ default: null,
2600
+ prefix: true
2591
2601
  },
2592
2602
  {
2593
2603
  name: "trip_start_date",
@@ -2632,7 +2642,8 @@ var vehiclePositions = {
2632
2642
  type: "text",
2633
2643
  index: true,
2634
2644
  source: "vehicle.vehicle.id",
2635
- default: null
2645
+ default: null,
2646
+ prefix: true
2636
2647
  },
2637
2648
  {
2638
2649
  name: "vehicle_label",
@@ -2682,7 +2693,8 @@ var serviceAlerts = {
2682
2693
  required: true,
2683
2694
  primary: true,
2684
2695
  index: true,
2685
- source: "id"
2696
+ source: "id",
2697
+ prefix: true
2686
2698
  },
2687
2699
  {
2688
2700
  name: "active_period",
@@ -2771,21 +2783,24 @@ var serviceAlertInformedEntities = {
2771
2783
  type: "text",
2772
2784
  required: true,
2773
2785
  primary: true,
2774
- source: "parent.id"
2786
+ source: "parent.id",
2787
+ prefix: true
2775
2788
  },
2776
2789
  {
2777
2790
  name: "stop_id",
2778
2791
  type: "text",
2779
2792
  index: true,
2780
2793
  source: "stopId",
2781
- default: null
2794
+ default: null,
2795
+ prefix: true
2782
2796
  },
2783
2797
  {
2784
2798
  name: "route_id",
2785
2799
  type: "text",
2786
2800
  index: true,
2787
2801
  source: "routeId",
2788
- default: null
2802
+ default: null,
2803
+ prefix: true
2789
2804
  },
2790
2805
  {
2791
2806
  name: "route_type",
@@ -2799,7 +2814,8 @@ var serviceAlertInformedEntities = {
2799
2814
  type: "text",
2800
2815
  index: true,
2801
2816
  source: "trip.tripId",
2802
- default: null
2817
+ default: null,
2818
+ prefix: true
2803
2819
  },
2804
2820
  {
2805
2821
  name: "direction_id",
@@ -3383,8 +3399,8 @@ function stopsToGeoJSONFeatureCollection(stops2) {
3383
3399
  // src/lib/import-gtfs-realtime.ts
3384
3400
  import pluralize from "pluralize";
3385
3401
  import GtfsRealtimeBindings from "gtfs-realtime-bindings";
3386
- import sqlString2 from "sqlstring-sqlite";
3387
3402
  import mapSeries from "promise-map-series";
3403
+ import { get } from "lodash-es";
3388
3404
 
3389
3405
  // src/lib/utils.ts
3390
3406
  import sqlString from "sqlstring-sqlite";
@@ -3545,39 +3561,14 @@ function formatCurrency(value, currency) {
3545
3561
  function getTimestampColumnName(columnName) {
3546
3562
  return columnName.endsWith("time") ? `${columnName}stamp` : `${columnName}_timestamp`;
3547
3563
  }
3548
-
3549
- // src/lib/import-gtfs-realtime.ts
3550
- function getNestedProperty(obj, defaultValue, path3) {
3551
- if (path3 === void 0) return defaultValue;
3552
- const arr = path3.split(".");
3553
- while (arr.length) {
3554
- const nextKey = arr.shift();
3555
- if (nextKey === void 0) {
3556
- return defaultValue;
3557
- } else if (obj == null) {
3558
- return defaultValue;
3559
- } else if (nextKey?.includes("[")) {
3560
- const arrayKey = nextKey.match(/(\w*)\[(\d+)\]/);
3561
- if (arrayKey === null) {
3562
- return defaultValue;
3563
- }
3564
- if (obj[arrayKey[1]] === void 0) {
3565
- return defaultValue;
3566
- }
3567
- if (obj[arrayKey[1]][arrayKey[2]] === void 0) {
3568
- return defaultValue;
3569
- }
3570
- obj = obj[arrayKey[1]][arrayKey[2]];
3571
- } else {
3572
- if (obj[nextKey] === void 0) {
3573
- return defaultValue;
3574
- }
3575
- obj = obj[nextKey];
3576
- }
3564
+ function applyPrefixToValue(value, columnShouldBePrefixed, prefix) {
3565
+ if (!columnShouldBePrefixed || prefix === void 0 || value === null) {
3566
+ return value;
3577
3567
  }
3578
- if (obj?.__isLong__) return convertLongTimeToDate(obj);
3579
- return obj;
3568
+ return `${prefix}${value}`;
3580
3569
  }
3570
+
3571
+ // src/lib/import-gtfs-realtime.ts
3581
3572
  async function fetchGtfsRealtimeData(urlConfig, task) {
3582
3573
  task.log(`Downloading GTFS-Realtime from ${urlConfig.url}`);
3583
3574
  const response = await fetch(urlConfig.url, {
@@ -3635,100 +3626,117 @@ function prepareRealtimeFieldValue(entity, column, task) {
3635
3626
  if (column.name === "expiration_timestamp") {
3636
3627
  return task.currentTimestamp + task.gtfsRealtimeExpirationSeconds;
3637
3628
  }
3638
- const value = getNestedProperty(entity, column.default, column.source);
3639
- if (column.type === "json") {
3640
- return sqlString2.escape(JSON.stringify(value));
3641
- }
3642
- return sqlString2.escape(value);
3629
+ const baseValue = column.source === void 0 ? column.default : get(entity, column.source, column.default);
3630
+ const timeAdjustedValue = baseValue?.__isLong__ ? convertLongTimeToDate(baseValue) : baseValue;
3631
+ const prefixedValue = applyPrefixToValue(
3632
+ timeAdjustedValue,
3633
+ column.prefix,
3634
+ task.prefix
3635
+ );
3636
+ return column.type === "json" ? JSON.stringify(prefixedValue) : prefixedValue;
3643
3637
  }
3644
3638
  async function processRealtimeAlerts(db, gtfsRealtimeData, task) {
3645
- task.log(`Download successful`);
3639
+ const alertStmt = db.prepare(
3640
+ `REPLACE INTO ${serviceAlerts.filenameBase} (${serviceAlerts.schema.map((column) => column.name).join(
3641
+ ", "
3642
+ )}) VALUES (${serviceAlerts.schema.map(() => "?").join(", ")})`
3643
+ );
3644
+ const informedEntityStmt = db.prepare(
3645
+ `REPLACE INTO ${serviceAlertInformedEntities.filenameBase} (${serviceAlertInformedEntities.schema.map((column) => column.name).join(
3646
+ ", "
3647
+ )}) VALUES (${serviceAlertInformedEntities.schema.map(() => "?").join(", ")})`
3648
+ );
3646
3649
  let totalLineCount = 0;
3647
- for (const entity of gtfsRealtimeData.entity) {
3648
- const fieldValues = serviceAlerts.schema.map(
3649
- (column) => prepareRealtimeFieldValue(entity, column, task)
3650
- );
3651
- try {
3652
- db.prepare(
3653
- `REPLACE INTO ${serviceAlerts.filenameBase} (${serviceAlerts.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
3654
- ).run();
3655
- } catch (error) {
3656
- task.logWarning(`Import error: ${error.message}`);
3657
- }
3658
- if (!entity.alert.informedEntity || entity.alert.informedEntity.length === 0) {
3659
- task.logWarning(
3660
- `Import error: No informed entities found for alert id=${entity.id}`
3650
+ db.transaction(() => {
3651
+ for (const entity of gtfsRealtimeData.entity) {
3652
+ const fieldValues = serviceAlerts.schema.map(
3653
+ (column) => prepareRealtimeFieldValue(entity, column, task)
3661
3654
  );
3662
- } else {
3663
- const informedEntities = [];
3664
- for (const informedEntity of entity.alert.informedEntity) {
3665
- informedEntity.parent = entity;
3666
- const subValues = serviceAlertInformedEntities.schema.map(
3667
- (column) => prepareRealtimeFieldValue(informedEntity, column, task)
3668
- );
3669
- informedEntities.push(`(${subValues.join(", ")})`);
3670
- totalLineCount++;
3671
- }
3672
3655
  try {
3673
- db.prepare(
3674
- `REPLACE INTO ${serviceAlertInformedEntities.filenameBase} (${serviceAlertInformedEntities.schema.map((column) => column.name).join(", ")}) VALUES ${informedEntities.join(", ")}`
3675
- ).run();
3656
+ alertStmt.run(fieldValues);
3657
+ if (entity.alert.informedEntity?.length) {
3658
+ const informedEntities = entity.alert.informedEntity.map(
3659
+ (informedEntity) => {
3660
+ informedEntity.parent = entity;
3661
+ return serviceAlertInformedEntities.schema.map(
3662
+ (column) => prepareRealtimeFieldValue(informedEntity, column, task)
3663
+ );
3664
+ }
3665
+ );
3666
+ for (const values of informedEntities) {
3667
+ informedEntityStmt.run(values);
3668
+ }
3669
+ }
3670
+ totalLineCount++;
3676
3671
  } catch (error) {
3677
3672
  task.logWarning(`Import error: ${error.message}`);
3678
3673
  }
3679
3674
  }
3680
- task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
3681
- }
3675
+ task.log(
3676
+ `Importing - GTFS-Realtime service alerts - ${totalLineCount} entries imported\r`,
3677
+ true
3678
+ );
3679
+ })();
3682
3680
  }
3683
3681
  async function processRealtimeTripUpdates(db, gtfsRealtimeData, task) {
3684
- task.log(`Download successful`);
3685
3682
  let totalLineCount = 0;
3686
- for (const entity of gtfsRealtimeData.entity) {
3687
- const fieldValues = tripUpdates.schema.map(
3688
- (column) => prepareRealtimeFieldValue(entity, column, task)
3689
- );
3690
- try {
3691
- db.prepare(
3692
- `REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
3693
- ).run();
3694
- } catch (error) {
3695
- task.logWarning(`Import error: ${error.message}`);
3696
- }
3697
- const stopTimeUpdateArray = [];
3698
- for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
3699
- stopTimeUpdate.parent = entity;
3700
- const subValues = stopTimeUpdates.schema.map(
3701
- (column) => prepareRealtimeFieldValue(stopTimeUpdate, column, task)
3702
- );
3703
- stopTimeUpdateArray.push(`(${subValues.join(", ")})`);
3704
- totalLineCount++;
3705
- }
3706
- try {
3707
- db.prepare(
3708
- `REPLACE INTO ${stopTimeUpdates.filenameBase} (${stopTimeUpdates.schema.map((column) => column.name).join(", ")}) VALUES ${stopTimeUpdateArray.join(", ")}`
3709
- ).run();
3710
- } catch (error) {
3711
- task.logWarning(`Import error: ${error.message}`);
3683
+ const tripUpdateStmt = db.prepare(
3684
+ `REPLACE INTO ${tripUpdates.filenameBase} (${tripUpdates.schema.map((column) => column.name).join(
3685
+ ", "
3686
+ )}) VALUES (${tripUpdates.schema.map(() => "?").join(", ")})`
3687
+ );
3688
+ const stopTimeStmt = db.prepare(
3689
+ `REPLACE INTO ${stopTimeUpdates.filenameBase} (${stopTimeUpdates.schema.map((column) => column.name).join(
3690
+ ", "
3691
+ )}) VALUES (${stopTimeUpdates.schema.map(() => "?").join(", ")})`
3692
+ );
3693
+ db.transaction(() => {
3694
+ for (const entity of gtfsRealtimeData.entity) {
3695
+ try {
3696
+ const fieldValues = tripUpdates.schema.map(
3697
+ (column) => prepareRealtimeFieldValue(entity, column, task)
3698
+ );
3699
+ tripUpdateStmt.run(fieldValues);
3700
+ for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
3701
+ stopTimeUpdate.parent = entity;
3702
+ const values = stopTimeUpdates.schema.map(
3703
+ (column) => prepareRealtimeFieldValue(stopTimeUpdate, column, task)
3704
+ );
3705
+ stopTimeStmt.run(values);
3706
+ }
3707
+ totalLineCount++;
3708
+ } catch (error) {
3709
+ task.logWarning(`Import error: ${error.message}`);
3710
+ }
3712
3711
  }
3713
- task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
3714
- }
3712
+ task.log(
3713
+ `Importing - GTFS-Realtime trip updates - ${totalLineCount} entries imported\r`,
3714
+ true
3715
+ );
3716
+ })();
3715
3717
  }
3716
3718
  async function processRealtimeVehiclePositions(db, gtfsRealtimeData, task) {
3717
- task.log(`Download successful`);
3718
3719
  let totalLineCount = 0;
3719
- for (const entity of gtfsRealtimeData.entity) {
3720
- const fieldValues = vehiclePositions.schema.map(
3721
- (column) => prepareRealtimeFieldValue(entity, column, task)
3722
- );
3723
- try {
3724
- db.prepare(
3725
- `REPLACE INTO ${vehiclePositions.filenameBase} (${vehiclePositions.schema.map((column) => column.name).join(", ")}) VALUES (${fieldValues.join(", ")})`
3726
- ).run();
3727
- } catch (error) {
3728
- task.logWarning(`Import error: ${error.message}`);
3720
+ const vehiclePositionStmt = db.prepare(
3721
+ `REPLACE INTO ${vehiclePositions.filenameBase} (${vehiclePositions.schema.map((column) => column.name).join(
3722
+ ", "
3723
+ )}) VALUES (${vehiclePositions.schema.map(() => "?").join(", ")})`
3724
+ );
3725
+ db.transaction(() => {
3726
+ for (const entity of gtfsRealtimeData.entity) {
3727
+ try {
3728
+ const fieldValues = vehiclePositions.schema.map((column) => prepareRealtimeFieldValue(entity, column, task));
3729
+ vehiclePositionStmt.run(fieldValues);
3730
+ totalLineCount++;
3731
+ } catch (error) {
3732
+ task.logWarning(`Import error: ${error.message}`);
3733
+ }
3729
3734
  }
3730
- task.log(`Importing - ${totalLineCount++} entries imported\r`, true);
3731
- }
3735
+ task.log(
3736
+ `Importing - GTFS-Realtime vehicle positions - ${totalLineCount} entries imported\r`,
3737
+ true
3738
+ );
3739
+ })();
3732
3740
  }
3733
3741
  async function updateGtfsRealtimeData(task) {
3734
3742
  if (task.realtimeAlerts === void 0 && task.realtimeTripUpdates === void 0 && task.realtimeVehiclePositions === void 0) {
@@ -3809,6 +3817,7 @@ async function updateGtfsRealtime(initialConfig) {
3809
3817
  gtfsRealtimeExpirationSeconds: config.gtfsRealtimeExpirationSeconds,
3810
3818
  ignoreErrors: config.ignoreErrors,
3811
3819
  sqlitePath: config.sqlitePath,
3820
+ prefix: agency2.prefix,
3812
3821
  currentTimestamp: Math.floor(Date.now() / 1e3),
3813
3822
  log: log(config),
3814
3823
  logWarning: logWarning(config),
@@ -4092,7 +4101,11 @@ var importGtfsFiles = (db, task) => mapSeries2(
4092
4101
  line
4093
4102
  ).map(([columnName, value]) => [
4094
4103
  columnName,
4095
- prefixedColumns.has(columnName) && value !== null ? `${task.prefix}${value}` : value
4104
+ applyPrefixToValue(
4105
+ value,
4106
+ prefixedColumns.has(columnName),
4107
+ task.prefix
4108
+ )
4096
4109
  ])
4097
4110
  );
4098
4111
  insert.run(prefixedLine);
@@ -4261,7 +4274,7 @@ import { writeFile as writeFile2 } from "node:fs/promises";
4261
4274
  import { without, compact as compact2 } from "lodash-es";
4262
4275
  import pluralize3 from "pluralize";
4263
4276
  import { stringify } from "csv-stringify";
4264
- import sqlString3 from "sqlstring-sqlite";
4277
+ import sqlString2 from "sqlstring-sqlite";
4265
4278
  import mapSeries3 from "promise-map-series";
4266
4279
  import untildify4 from "untildify";
4267
4280
  var getAgencies = (db, config) => {
@@ -4313,7 +4326,7 @@ var exportGtfs = async (initialConfig) => {
4313
4326
  exportPath,
4314
4327
  `${model.filenameBase}.${model.filenameExtension}`
4315
4328
  );
4316
- const tableName = sqlString3.escapeId(model.filenameBase);
4329
+ const tableName = sqlString2.escapeId(model.filenameBase);
4317
4330
  const lines = db.prepare(`SELECT * FROM ${tableName};`).all();
4318
4331
  if (!lines || lines.length === 0) {
4319
4332
  if (!model.nonstandard) {
@@ -4375,7 +4388,7 @@ var exportGtfs = async (initialConfig) => {
4375
4388
  };
4376
4389
 
4377
4390
  // src/lib/advancedQuery.ts
4378
- import sqlString4 from "sqlstring-sqlite";
4391
+ import sqlString3 from "sqlstring-sqlite";
4379
4392
  function advancedQuery(table, advancedQueryOptions) {
4380
4393
  const defaultOptions = {
4381
4394
  query: {},
@@ -4386,7 +4399,7 @@ function advancedQuery(table, advancedQueryOptions) {
4386
4399
  };
4387
4400
  const queryOptions = { ...defaultOptions, ...advancedQueryOptions };
4388
4401
  const db = queryOptions.options.db ?? openDb();
4389
- const tableName = sqlString4.escapeId(table);
4402
+ const tableName = sqlString3.escapeId(table);
4390
4403
  const selectClause = formatSelectClause(queryOptions.fields);
4391
4404
  const whereClause = formatWhereClauses(queryOptions.query);
4392
4405
  const joinClause = formatJoinClause(queryOptions.join);
@@ -4928,7 +4941,7 @@ function getStopsAsGeoJSON(query = {}, options = {}) {
4928
4941
 
4929
4942
  // src/lib/gtfs/stop-times.ts
4930
4943
  import { omit as omit6 } from "lodash-es";
4931
- import sqlString5 from "sqlstring-sqlite";
4944
+ import sqlString4 from "sqlstring-sqlite";
4932
4945
  function getStoptimes(query = {}, fields = [], orderBy2 = [], options = {}) {
4933
4946
  const db = options.db ?? openDb();
4934
4947
  const tableName = "stop_times";
@@ -4945,7 +4958,7 @@ function getStoptimes(query = {}, fields = [], orderBy2 = [], options = {}) {
4945
4958
  throw new Error("`date` must be a number in yyyymmdd format");
4946
4959
  }
4947
4960
  const serviceIds = getServiceIdsByDate(query.date);
4948
- const tripSubquery = `SELECT DISTINCT trip_id FROM trips WHERE service_id IN (${serviceIds.map((id) => sqlString5.escape(id)).join(",")})`;
4961
+ const tripSubquery = `SELECT DISTINCT trip_id FROM trips WHERE service_id IN (${serviceIds.map((id) => sqlString4.escape(id)).join(",")})`;
4949
4962
  whereClauses.push(`trip_id IN (${tripSubquery})`);
4950
4963
  }
4951
4964
  if (query.start_time) {