gtfs 4.15.6 → 4.15.8

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
@@ -152,7 +152,8 @@ var attributions = {
152
152
  {
153
153
  name: "attribution_id",
154
154
  type: "text",
155
- prefix: true
155
+ prefix: true,
156
+ primary: true
156
157
  },
157
158
  {
158
159
  name: "agency_id",
@@ -585,26 +586,31 @@ var fareRules = {
585
586
  name: "fare_id",
586
587
  type: "text",
587
588
  required: true,
589
+ primary: true,
588
590
  prefix: true
589
591
  },
590
592
  {
591
593
  name: "route_id",
592
594
  type: "text",
595
+ primary: true,
593
596
  prefix: true
594
597
  },
595
598
  {
596
599
  name: "origin_id",
597
600
  type: "text",
601
+ primary: true,
598
602
  prefix: true
599
603
  },
600
604
  {
601
605
  name: "destination_id",
602
606
  type: "text",
607
+ primary: true,
603
608
  prefix: true
604
609
  },
605
610
  {
606
611
  name: "contains_id",
607
612
  type: "text",
613
+ primary: true,
608
614
  prefix: true
609
615
  }
610
616
  ]
@@ -811,14 +817,16 @@ var locationGroupStops = {
811
817
  type: "text",
812
818
  prefix: true,
813
819
  index: true,
814
- required: true
820
+ required: true,
821
+ primary: true
815
822
  },
816
823
  {
817
824
  name: "stop_id",
818
825
  type: "text",
819
826
  required: true,
820
827
  prefix: true,
821
- index: true
828
+ index: true,
829
+ primary: true
822
830
  }
823
831
  ]
824
832
  };
@@ -1079,12 +1087,14 @@ var stopAreas = {
1079
1087
  name: "area_id",
1080
1088
  type: "text",
1081
1089
  required: true,
1090
+ primary: true,
1082
1091
  prefix: true
1083
1092
  },
1084
1093
  {
1085
1094
  name: "stop_id",
1086
1095
  type: "text",
1087
1096
  required: true,
1097
+ primary: true,
1088
1098
  prefix: true
1089
1099
  }
1090
1100
  ]
@@ -1308,16 +1318,19 @@ var timeframes = {
1308
1318
  },
1309
1319
  {
1310
1320
  name: "start_time",
1311
- type: "text"
1321
+ type: "text",
1322
+ primary: true
1312
1323
  },
1313
1324
  {
1314
1325
  name: "end_time",
1315
- type: "text"
1326
+ type: "text",
1327
+ primary: true
1316
1328
  },
1317
1329
  {
1318
1330
  name: "service_id",
1319
1331
  type: "text",
1320
1332
  required: true,
1333
+ primary: true,
1321
1334
  index: true,
1322
1335
  prefix: true
1323
1336
  }
@@ -1504,21 +1517,19 @@ var timetables = {
1504
1517
  filenameExtension: "txt",
1505
1518
  nonstandard: true,
1506
1519
  schema: [
1507
- {
1508
- name: "id",
1509
- type: "integer",
1510
- primary: true,
1511
- prefix: true
1512
- },
1513
1520
  {
1514
1521
  name: "timetable_id",
1515
1522
  type: "text",
1516
- prefix: true
1523
+ prefix: true,
1524
+ required: true,
1525
+ primary: true
1517
1526
  },
1518
1527
  {
1519
1528
  name: "route_id",
1520
1529
  type: "text",
1521
- prefix: true
1530
+ prefix: true,
1531
+ required: true,
1532
+ primary: true
1522
1533
  },
1523
1534
  {
1524
1535
  name: "direction_id",
@@ -1652,6 +1663,7 @@ var timetablePages = {
1652
1663
  name: "timetable_page_id",
1653
1664
  type: "text",
1654
1665
  primary: true,
1666
+ required: true,
1655
1667
  prefix: true
1656
1668
  },
1657
1669
  {
@@ -1671,28 +1683,28 @@ var timetableStopOrder = {
1671
1683
  filenameExtension: "txt",
1672
1684
  nonstandard: true,
1673
1685
  schema: [
1674
- {
1675
- name: "id",
1676
- type: "integer",
1677
- primary: true,
1678
- prefix: true
1679
- },
1680
1686
  {
1681
1687
  name: "timetable_id",
1682
1688
  type: "text",
1683
1689
  index: true,
1684
- prefix: true
1690
+ prefix: true,
1691
+ required: true,
1692
+ primary: true
1685
1693
  },
1686
1694
  {
1687
1695
  name: "stop_id",
1688
1696
  type: "text",
1689
- prefix: true
1697
+ prefix: true,
1698
+ required: true,
1699
+ primary: true
1690
1700
  },
1691
1701
  {
1692
1702
  name: "stop_sequence",
1693
1703
  type: "integer",
1694
1704
  min: 0,
1695
- index: true
1705
+ index: true,
1706
+ required: true,
1707
+ primary: true
1696
1708
  }
1697
1709
  ]
1698
1710
  };
@@ -1707,7 +1719,8 @@ var timetableNotes = {
1707
1719
  name: "note_id",
1708
1720
  type: "text",
1709
1721
  primary: true,
1710
- prefix: true
1722
+ prefix: true,
1723
+ required: true
1711
1724
  },
1712
1725
  {
1713
1726
  name: "symbol",
@@ -1716,7 +1729,8 @@ var timetableNotes = {
1716
1729
  {
1717
1730
  name: "note",
1718
1731
  type: "text",
1719
- nocase: true
1732
+ nocase: true,
1733
+ required: true
1720
1734
  }
1721
1735
  ]
1722
1736
  };
@@ -1730,37 +1744,39 @@ var timetableNotesReferences = {
1730
1744
  {
1731
1745
  name: "note_id",
1732
1746
  type: "text",
1733
- prefix: true
1747
+ prefix: true,
1748
+ required: true,
1749
+ primary: true
1734
1750
  },
1735
1751
  {
1736
1752
  name: "timetable_id",
1737
1753
  type: "text",
1738
- index: true,
1739
- prefix: true
1754
+ prefix: true,
1755
+ primary: true
1740
1756
  },
1741
1757
  {
1742
1758
  name: "route_id",
1743
1759
  type: "text",
1744
- index: true,
1745
- prefix: true
1760
+ prefix: true,
1761
+ primary: true
1746
1762
  },
1747
1763
  {
1748
1764
  name: "trip_id",
1749
1765
  type: "text",
1750
- index: true,
1751
- prefix: true
1766
+ prefix: true,
1767
+ primary: true
1752
1768
  },
1753
1769
  {
1754
1770
  name: "stop_id",
1755
1771
  type: "text",
1756
- index: true,
1757
- prefix: true
1772
+ prefix: true,
1773
+ primary: true
1758
1774
  },
1759
1775
  {
1760
1776
  name: "stop_sequence",
1761
1777
  type: "integer",
1762
1778
  min: 0,
1763
- index: true
1779
+ primary: true
1764
1780
  },
1765
1781
  {
1766
1782
  name: "show_on_stoptime",
@@ -2394,7 +2410,7 @@ var tripUpdates = {
2394
2410
  extension: "gtfs-realtime",
2395
2411
  schema: [
2396
2412
  {
2397
- name: "update_id",
2413
+ name: "id",
2398
2414
  type: "text",
2399
2415
  required: true,
2400
2416
  primary: true,
@@ -2558,7 +2574,7 @@ var vehiclePositions = {
2558
2574
  extension: "gtfs-realtime",
2559
2575
  schema: [
2560
2576
  {
2561
- name: "update_id",
2577
+ name: "id",
2562
2578
  type: "text",
2563
2579
  required: true,
2564
2580
  primary: true,
@@ -2797,17 +2813,12 @@ var deadheadTimes = {
2797
2813
  nonstandard: true,
2798
2814
  extension: "ods",
2799
2815
  schema: [
2800
- {
2801
- name: "id",
2802
- type: "integer",
2803
- primary: true,
2804
- prefix: true
2805
- },
2806
2816
  {
2807
2817
  name: "deadhead_id",
2808
2818
  type: "text",
2809
2819
  required: true,
2810
2820
  index: true,
2821
+ primary: true,
2811
2822
  prefix: true
2812
2823
  },
2813
2824
  {
@@ -2844,6 +2855,7 @@ var deadheadTimes = {
2844
2855
  name: "location_sequence",
2845
2856
  type: "integer",
2846
2857
  required: true,
2858
+ primary: true,
2847
2859
  min: 0,
2848
2860
  index: true
2849
2861
  },
@@ -3170,6 +3182,58 @@ import { omit, snakeCase } from "lodash-es";
3170
3182
  import sanitize from "sanitize-filename";
3171
3183
  import untildify2 from "untildify";
3172
3184
  import StreamZip from "node-stream-zip";
3185
+
3186
+ // src/lib/log-utils.ts
3187
+ import { clearLine, cursorTo } from "node:readline";
3188
+ import { noop } from "lodash-es";
3189
+ import * as colors from "yoctocolors";
3190
+ function log(config) {
3191
+ if (config.verbose === false) {
3192
+ return noop;
3193
+ }
3194
+ if (config.logFunction) {
3195
+ return config.logFunction;
3196
+ }
3197
+ return (text, overwrite = false) => {
3198
+ if (overwrite && process.stdout.isTTY) {
3199
+ clearLine(process.stdout, 0);
3200
+ cursorTo(process.stdout, 0);
3201
+ } else {
3202
+ process.stdout.write("\n");
3203
+ }
3204
+ process.stdout.write(text);
3205
+ };
3206
+ }
3207
+ function logWarning(config) {
3208
+ if (config.logFunction) {
3209
+ return config.logFunction;
3210
+ }
3211
+ return (text) => {
3212
+ process.stdout.write(`
3213
+ ${formatWarning(text)}
3214
+ `);
3215
+ };
3216
+ }
3217
+ function logError(config) {
3218
+ if (config.logFunction) {
3219
+ return config.logFunction;
3220
+ }
3221
+ return (text) => {
3222
+ process.stdout.write(`
3223
+ ${formatError(text)}
3224
+ `);
3225
+ };
3226
+ }
3227
+ function formatWarning(text) {
3228
+ return colors.yellow(`${colors.underline("Warning")}: ${text}`);
3229
+ }
3230
+ function formatError(error) {
3231
+ const messageText = error instanceof Error ? error.message : error;
3232
+ const cleanMessage = messageText.replace(/^Error:\s*/i, "");
3233
+ return colors.red(`${colors.underline("Error")}: ${cleanMessage}`);
3234
+ }
3235
+
3236
+ // src/lib/file-utils.ts
3173
3237
  async function prepDirectory(exportPath) {
3174
3238
  await rm(exportPath, { recursive: true, force: true });
3175
3239
  await mkdir(exportPath, { recursive: true });
@@ -3317,56 +3381,6 @@ import GtfsRealtimeBindings from "gtfs-realtime-bindings";
3317
3381
  import sqlString2 from "sqlstring-sqlite";
3318
3382
  import mapSeries from "promise-map-series";
3319
3383
 
3320
- // src/lib/log-utils.ts
3321
- import { clearLine, cursorTo } from "node:readline";
3322
- import { noop } from "lodash-es";
3323
- import * as colors from "yoctocolors";
3324
- function log(config) {
3325
- if (!config.verbose) {
3326
- return noop;
3327
- }
3328
- if (config.logFunction) {
3329
- return config.logFunction;
3330
- }
3331
- return (text, overwrite = false) => {
3332
- if (overwrite && process.stdout.isTTY) {
3333
- clearLine(process.stdout, 0);
3334
- cursorTo(process.stdout, 0);
3335
- } else {
3336
- process.stdout.write("\n");
3337
- }
3338
- process.stdout.write(text);
3339
- };
3340
- }
3341
- function logWarning(config) {
3342
- if (config.logFunction) {
3343
- return config.logFunction;
3344
- }
3345
- return (text) => {
3346
- process.stdout.write(`
3347
- ${formatWarning(text)}
3348
- `);
3349
- };
3350
- }
3351
- function logError(config) {
3352
- if (config.logFunction) {
3353
- return config.logFunction;
3354
- }
3355
- return (text) => {
3356
- process.stdout.write(`
3357
- ${formatError(text)}
3358
- `);
3359
- };
3360
- }
3361
- function formatWarning(text) {
3362
- return colors.yellow(`${colors.underline("Warning")}: ${text}`);
3363
- }
3364
- function formatError(error) {
3365
- const messageText = error instanceof Error ? error.message : error;
3366
- const cleanMessage = messageText.replace(/^Error:\s*/i, "");
3367
- return colors.red(`${colors.underline("Error")}: ${cleanMessage}`);
3368
- }
3369
-
3370
3384
  // src/lib/utils.ts
3371
3385
  import sqlString from "sqlstring-sqlite";
3372
3386
  import Long from "long";
@@ -3388,7 +3402,8 @@ function setDefaultConfig(initialConfig) {
3388
3402
  sqlitePath: ":memory:",
3389
3403
  ignoreDuplicates: false,
3390
3404
  ignoreErrors: false,
3391
- gtfsRealtimeExpirationSeconds: 0
3405
+ gtfsRealtimeExpirationSeconds: 0,
3406
+ verbose: true
3392
3407
  };
3393
3408
  return {
3394
3409
  ...defaults,
@@ -3511,6 +3526,15 @@ function getDayOfWeekFromDate(date) {
3511
3526
  }
3512
3527
  return DAYS_OF_WEEK[dateObj.getDay()];
3513
3528
  }
3529
+ function formatCurrency(value, currency) {
3530
+ const parts = new Intl.NumberFormat(void 0, {
3531
+ style: "currency",
3532
+ currency
3533
+ }).formatToParts(value);
3534
+ const integerPart = parts.find((part) => part.type === "integer")?.value ?? "0";
3535
+ const fractionPart = parts.find((part) => part.type === "fraction")?.value ?? "";
3536
+ return `${integerPart}${fractionPart !== "" ? `.${fractionPart}` : ""}`;
3537
+ }
3514
3538
 
3515
3539
  // src/lib/import-gtfs-realtime.ts
3516
3540
  function getNestedProperty(obj, defaultValue, path3) {
@@ -3907,18 +3931,31 @@ var createGtfsTables = (db) => {
3907
3931
  return;
3908
3932
  }
3909
3933
  const columns = model.schema.map((column) => {
3910
- let check = "";
3934
+ const checks = [];
3911
3935
  if (column.min !== void 0 && column.max) {
3912
- check = `CHECK( ${column.name} >= ${column.min} AND ${column.name} <= ${column.max} )`;
3936
+ checks.push(
3937
+ `${column.name} >= ${column.min} AND ${column.name} <= ${column.max}`
3938
+ );
3913
3939
  } else if (column.min) {
3914
- check = `CHECK( ${column.name} >= ${column.min} )`;
3940
+ checks.push(`${column.name} >= ${column.min}`);
3915
3941
  } else if (column.max) {
3916
- check = `CHECK( ${column.name} <= ${column.max} )`;
3942
+ checks.push(`${column.name} <= ${column.max}`);
3943
+ }
3944
+ if (column.type === "integer") {
3945
+ checks.push(
3946
+ `(TYPEOF(${column.name}) = 'integer' OR ${column.name} IS NULL)`
3947
+ );
3948
+ }
3949
+ if (column.type === "real") {
3950
+ checks.push(
3951
+ `(TYPEOF(${column.name}) = 'real' OR ${column.name} IS NULL)`
3952
+ );
3917
3953
  }
3918
3954
  const required = column.required ? "NOT NULL" : "";
3919
3955
  const columnDefault = column.default ? "DEFAULT " + column.default : "";
3920
3956
  const columnCollation = column.nocase ? "COLLATE NOCASE" : "";
3921
- return `${column.name} ${column.type} ${check} ${required} ${columnDefault} ${columnCollation}`;
3957
+ const checkClause = checks.length > 0 ? `CHECK(${checks.join(" AND ")})` : "";
3958
+ return `${column.name} ${column.type} ${checkClause} ${required} ${columnDefault} ${columnCollation}`;
3922
3959
  });
3923
3960
  const primaryColumns = model.schema.filter((column) => column.primary);
3924
3961
  if (primaryColumns.length > 0) {
@@ -3961,38 +3998,15 @@ var formatGtfsLine = (line, model, totalLineCount) => {
3961
3998
  }
3962
3999
  continue;
3963
4000
  }
3964
- switch (type) {
3965
- case "date":
3966
- value = value.replace(/-/g, "");
3967
- if (value.length !== 8) {
3968
- throw new Error(
3969
- `Invalid date in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`
3970
- );
3971
- }
3972
- value = parseInt(value, 10);
3973
- break;
3974
- case "integer":
3975
- value = parseInt(value, 10);
3976
- break;
3977
- case "real":
3978
- value = parseFloat(value);
3979
- break;
3980
- }
3981
- if (Number.isNaN(value)) {
3982
- formattedLine[name] = null;
3983
- continue;
4001
+ if (type === "date") {
4002
+ value = value.replace(/-/g, "");
4003
+ if (value.length !== 8) {
4004
+ throw new Error(
4005
+ `Invalid date in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}.`
4006
+ );
4007
+ }
3984
4008
  }
3985
4009
  formattedLine[name] = value;
3986
- if (min !== void 0 && value < min) {
3987
- throw new Error(
3988
- `Invalid value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}: below minimum value of ${min}.`
3989
- );
3990
- }
3991
- if (max !== void 0 && value > max) {
3992
- throw new Error(
3993
- `Invalid value in ${filenameBase}.${filenameExtension} for ${name} on line ${lineNumber}: above maximum value of ${max}.`
3994
- );
3995
- }
3996
4010
  }
3997
4011
  for (const [timeColumnName, timestampColumnName] of TIME_COLUMN_PAIRS) {
3998
4012
  const value = formattedLine[timeColumnName];
@@ -4028,12 +4042,11 @@ var importGtfsFiles = (db, task) => mapSeries2(
4028
4042
  return;
4029
4043
  }
4030
4044
  task.log(`Importing - ${filename}\r`);
4031
- const columns = model.schema.filter((column) => column.name !== "id");
4032
- const placeholder = columns.map(({ name }) => `@${name}`).join(", ");
4045
+ const placeholder = model.schema.map(({ name }) => `@${name}`).join(", ");
4033
4046
  const prefixedColumns = new Set(
4034
- columns.filter((col) => col.prefix).map((col) => col.name)
4047
+ model.schema.filter((column) => column.prefix).map((column) => column.name)
4035
4048
  );
4036
- const prepareStatement = `INSERT ${task.ignoreDuplicates ? "OR IGNORE" : ""} INTO ${model.filenameBase} (${columns.map((column) => column.name).join(", ")}) VALUES (${placeholder})`;
4049
+ const prepareStatement = `INSERT ${task.ignoreDuplicates ? "OR IGNORE" : ""} INTO ${model.filenameBase} (${model.schema.map((column) => column.name).join(", ")}) VALUES (${placeholder})`;
4037
4050
  const insert = db.prepare(prepareStatement);
4038
4051
  const insertLines = db.transaction((lines) => {
4039
4052
  for (const [rowNumber, line] of Object.entries(lines)) {
@@ -4061,7 +4074,7 @@ var importGtfsFiles = (db, task) => mapSeries2(
4061
4074
  );
4062
4075
  }
4063
4076
  task.logWarning(
4064
- `Check ${filename} for invalid data on row ${rowNumber}.`
4077
+ `Check ${filename} for invalid data on line ${rowNumber + 1}.`
4065
4078
  );
4066
4079
  throw error;
4067
4080
  }
@@ -4279,7 +4292,6 @@ var exportGtfs = async (initialConfig) => {
4279
4292
  }
4280
4293
  if (model.filenameExtension === "txt") {
4281
4294
  const excludeColumns = [
4282
- "id",
4283
4295
  "arrival_timestamp",
4284
4296
  "departure_timestamp",
4285
4297
  "start_timestamp",
@@ -4298,6 +4310,14 @@ var exportGtfs = async (initialConfig) => {
4298
4310
  if (!routesWithAgencyId || routesWithAgencyId.length === 0) {
4299
4311
  excludeColumns.push("agency_id");
4300
4312
  }
4313
+ } else if (model.filenameBase === "fare_attributes") {
4314
+ for (const line of lines) {
4315
+ line.price = formatCurrency(line.price, line.currency_type);
4316
+ }
4317
+ } else if (model.filenameBase === "fare_products") {
4318
+ for (const line of lines) {
4319
+ line.price = formatCurrency(line.amount, line.currency);
4320
+ }
4301
4321
  }
4302
4322
  const columns = without(
4303
4323
  model.schema.map((column) => column.name),