gtfs 4.17.0 → 4.17.2

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