gtfs 4.15.4 → 4.15.6

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.
@@ -21,64 +21,49 @@ import StreamZip from "node-stream-zip";
21
21
  async function getConfig(argv2) {
22
22
  let config;
23
23
  let data;
24
- if (argv2.configPath) {
25
- try {
26
- data = await readFile(path.resolve(untildify(argv2.configPath)), "utf8");
27
- } catch (error) {
28
- throw new Error(
29
- `Cannot find configuration file at \`${argv2.configPath}\`. Use config-sample.json as a starting point.`
30
- );
31
- }
32
- try {
24
+ try {
25
+ if (argv2.configPath) {
26
+ const configPath = path.resolve(untildify(argv2.configPath));
27
+ data = await readFile(configPath, "utf8");
33
28
  config = Object.assign(JSON.parse(data), argv2);
34
- } catch (error) {
35
- throw new Error(
36
- `Cannot parse configuration file at \`${argv2.configPath}\`. Check to ensure that it is valid JSON.`
37
- );
38
- }
39
- } else if (argv2.gtfsPath || argv2.gtfsUrl || argv2.sqlitePath) {
40
- const agencies = [];
41
- if (argv2.gtfsPath) {
42
- agencies.push({
43
- path: argv2.gtfsPath
44
- });
45
- }
46
- if (argv2.gtfsUrl) {
47
- agencies.push({
48
- url: argv2.gtfsUrl
49
- });
50
- }
51
- config = {
52
- agencies,
53
- ...omit(argv2, ["path", "url"])
54
- };
55
- } else if (existsSync(path.resolve("./config.json"))) {
56
- try {
29
+ } else if (argv2.gtfsPath || argv2.gtfsUrl || argv2.sqlitePath) {
30
+ const agencies = [
31
+ ...argv2.gtfsPath ? [{ path: argv2.gtfsPath }] : [],
32
+ ...argv2.gtfsUrl ? [{ url: argv2.gtfsUrl }] : []
33
+ ];
34
+ config = {
35
+ agencies,
36
+ ...omit(argv2, ["path", "url"])
37
+ };
38
+ } else if (existsSync(path.resolve("./config.json"))) {
57
39
  data = await readFile(path.resolve("./config.json"), "utf8");
58
- } catch (error) {
40
+ config = Object.assign(JSON.parse(data), argv2);
41
+ console.log("Using configuration from ./config.json");
42
+ } else {
59
43
  throw new Error(
60
- `Cannot open configuration file at \`${path.resolve("./config.json")}\`. Check to ensure that it exists. Use config-sample.json as a starting point.`
44
+ "Cannot find configuration file. Use config-sample.json as a starting point, pass --configPath option."
61
45
  );
62
46
  }
63
- try {
64
- config = Object.assign(JSON.parse(data), argv2);
65
- console.log("Using configuration from ./config.json");
66
- } catch (error) {
47
+ return config;
48
+ } catch (error) {
49
+ if (error instanceof SyntaxError) {
67
50
  throw new Error(
68
- `Cannot parse configuration file at \`${path.resolve("./config.json")}\`. Check to ensure that it is valid JSON.`
51
+ `Cannot parse configuration file. Check to ensure that it is valid JSON. Error: ${error.message}`
69
52
  );
70
53
  }
71
- } else {
72
- throw new Error(
73
- "Cannot find configuration file. Use config-sample.json as a starting point, pass --configPath option."
74
- );
54
+ throw error;
75
55
  }
76
- return config;
77
56
  }
78
57
  async function unzip(zipfilePath, exportPath) {
79
- const zip = new StreamZip.async({ file: zipfilePath });
80
- await zip.extract(null, exportPath);
81
- await zip.close();
58
+ try {
59
+ const zip = new StreamZip.async({ file: zipfilePath });
60
+ await zip.extract(null, exportPath);
61
+ await zip.close();
62
+ } catch (error) {
63
+ throw new Error(
64
+ `Failed to extract zip file: ${error instanceof Error ? error.message : "Unknown error"}`
65
+ );
66
+ }
82
67
  }
83
68
 
84
69
  // src/lib/log-utils.ts
@@ -86,14 +71,14 @@ import { clearLine, cursorTo } from "node:readline";
86
71
  import { noop } from "lodash-es";
87
72
  import * as colors from "yoctocolors";
88
73
  function log(config) {
89
- if (config.verbose === false) {
74
+ if (!config.verbose) {
90
75
  return noop;
91
76
  }
92
77
  if (config.logFunction) {
93
78
  return config.logFunction;
94
79
  }
95
- return (text, overwrite) => {
96
- if (overwrite === true && process.stdout.isTTY) {
80
+ return (text, overwrite = false) => {
81
+ if (overwrite && process.stdout.isTTY) {
97
82
  clearLine(process.stdout, 0);
98
83
  cursorTo(process.stdout, 0);
99
84
  } else {
@@ -123,16 +108,12 @@ ${formatError(text)}
123
108
  };
124
109
  }
125
110
  function formatWarning(text) {
126
- const warningMessage = `${colors.underline("Warning")}: ${text}`;
127
- return colors.yellow(warningMessage);
111
+ return colors.yellow(`${colors.underline("Warning")}: ${text}`);
128
112
  }
129
113
  function formatError(error) {
130
114
  const messageText = error instanceof Error ? error.message : error;
131
- const errorMessage = `${colors.underline("Error")}: ${messageText.replace(
132
- "Error: ",
133
- ""
134
- )}`;
135
- return colors.red(errorMessage);
115
+ const cleanMessage = messageText.replace(/^Error:\s*/i, "");
116
+ return colors.red(`${colors.underline("Error")}: ${cleanMessage}`);
136
117
  }
137
118
 
138
119
  // src/lib/import-gtfs.ts
@@ -3291,10 +3272,10 @@ import { feature, featureCollection } from "@turf/helpers";
3291
3272
  function isValidJSON(string) {
3292
3273
  try {
3293
3274
  JSON.parse(string);
3275
+ return true;
3294
3276
  } catch (error) {
3295
3277
  return false;
3296
3278
  }
3297
- return true;
3298
3279
  }
3299
3280
 
3300
3281
  // src/lib/import-gtfs-realtime.ts
@@ -3333,14 +3314,17 @@ function setDefaultConfig(initialConfig) {
3333
3314
  }
3334
3315
  function convertLongTimeToDate(longDate) {
3335
3316
  const { high, low, unsigned } = longDate;
3336
- return new Date(new Long(low, high, unsigned).toInt() * 1e3).toISOString();
3317
+ return new Date(
3318
+ Long.fromBits(low, high, unsigned).toNumber() * 1e3
3319
+ ).toISOString();
3337
3320
  }
3338
3321
  function calculateSecondsFromMidnight(time) {
3339
- const split = time.split(":").map((d) => Number.parseInt(d, 10));
3340
- if (split.length !== 3) {
3322
+ if (!time || typeof time !== "string") return null;
3323
+ const [hours, minutes, seconds] = time.split(":").map(Number);
3324
+ if ([hours, minutes, seconds].some(isNaN) || hours >= 24 || minutes >= 60 || seconds >= 60) {
3341
3325
  return null;
3342
3326
  }
3343
- return split[0] * 3600 + split[1] * 60 + split[2];
3327
+ return hours * 3600 + minutes * 60 + seconds;
3344
3328
  }
3345
3329
  function padLeadingZeros(time) {
3346
3330
  const split = time.split(":").map((d) => String(Number(d)).padStart(2, "0"));
@@ -3793,6 +3777,9 @@ var importGtfsFiles = (db, task) => mapSeries2(
3793
3777
  task.log(`Importing - ${filename}\r`);
3794
3778
  const columns = model.schema.filter((column) => column.name !== "id");
3795
3779
  const placeholder = columns.map(({ name }) => `@${name}`).join(", ");
3780
+ const prefixedColumns = new Set(
3781
+ columns.filter((col) => col.prefix).map((col) => col.name)
3782
+ );
3796
3783
  const prepareStatement = `INSERT ${task.ignoreDuplicates ? "OR IGNORE" : ""} INTO ${model.filenameBase} (${columns.map((column) => column.name).join(", ")}) VALUES (${placeholder})`;
3797
3784
  const insert = db.prepare(prepareStatement);
3798
3785
  const insertLines = db.transaction((lines) => {
@@ -3806,7 +3793,7 @@ var importGtfsFiles = (db, task) => mapSeries2(
3806
3793
  line
3807
3794
  ).map(([columnName, value]) => [
3808
3795
  columnName,
3809
- columns.find((col) => col.name === columnName)?.prefix ? `${task.prefix}${value}` : value
3796
+ prefixedColumns.has(columnName) && value !== null ? `${task.prefix}${value}` : value
3810
3797
  ])
3811
3798
  );
3812
3799
  insert.run(prefixedLine);