gtfs-to-html 2.9.2 → 2.9.4

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.d.ts CHANGED
@@ -7,8 +7,8 @@ interface IConfig {
7
7
  exclude?: string[];
8
8
  }[];
9
9
  coordinatePrecision?: number;
10
- outputType?: string;
11
10
  outputFormat?: string;
11
+ outputPath?: string;
12
12
  startDate?: string;
13
13
  endDate?: string;
14
14
  verbose?: boolean;
@@ -19,6 +19,6 @@ interface IConfig {
19
19
  logError: (text: string) => void;
20
20
  }
21
21
 
22
- declare const gtfsToHtml: (initialConfig: IConfig) => Promise<void>;
22
+ declare const gtfsToHtml: (initialConfig: IConfig) => Promise<string>;
23
23
 
24
24
  export { gtfsToHtml as default };
package/dist/index.js CHANGED
@@ -5,18 +5,26 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // src/lib/gtfs-to-html.ts
8
- import path2 from "node:path";
8
+ import path from "node:path";
9
9
  import { mkdir as mkdir2, writeFile } from "node:fs/promises";
10
10
  import { map } from "lodash-es";
11
11
  import { openDb as openDb2, importGtfs } from "gtfs";
12
12
  import sanitize2 from "sanitize-filename";
13
13
  import Timer from "timer-machine";
14
+ import untildify2 from "untildify";
14
15
 
15
16
  // src/lib/file-utils.ts
16
- import path from "node:path";
17
+ import { dirname, join, resolve } from "node:path";
17
18
  import { createWriteStream } from "node:fs";
18
19
  import { fileURLToPath } from "node:url";
19
- import { access, cp, copyFile, mkdir, readFile, rm } from "node:fs/promises";
20
+ import {
21
+ access,
22
+ cp,
23
+ copyFile,
24
+ mkdir,
25
+ readdir,
26
+ readFile
27
+ } from "node:fs/promises";
20
28
  import _ from "lodash-es";
21
29
  import archiver from "archiver";
22
30
  import beautify from "js-beautify";
@@ -325,7 +333,7 @@ function formatTripNameForCSV(trip, timetable) {
325
333
  }
326
334
 
327
335
  // package.json
328
- var version = "2.9.1";
336
+ var version = "2.9.3";
329
337
 
330
338
  // src/lib/utils.ts
331
339
  var isTimepoint = (stoptime) => {
@@ -1304,7 +1312,10 @@ function setDefaultConfig(initialConfig) {
1304
1312
  config.menuType = "none";
1305
1313
  }
1306
1314
  config.hasGtfsRealtime = config.agencies.some(
1307
- (agency) => agency.realtimeTripUpdates?.url || agency.realtimeVehiclePositions?.url
1315
+ (agency) => agency.realtimeTripUpdates?.url || agency.realtimeVehiclePositions?.url || agency.realtimeAlerts?.url
1316
+ );
1317
+ config.hasGtfsRealtimeAlerts = config.agencies.some(
1318
+ (agency) => agency.realtimeAlerts?.url
1308
1319
  );
1309
1320
  return config;
1310
1321
  }
@@ -1787,61 +1798,77 @@ function mergeTimetablesWithSameId(timetables) {
1787
1798
  }
1788
1799
 
1789
1800
  // src/lib/file-utils.ts
1790
- function getTemplatePath(templateFileName, config) {
1791
- let fullTemplateFileName = templateFileName;
1792
- if (config.noHead !== true) {
1793
- fullTemplateFileName += "_full";
1801
+ function getPathToViewsFolder(config) {
1802
+ if (config.templatePath) {
1803
+ return untildify(config.templatePath);
1804
+ }
1805
+ const __dirname = dirname(fileURLToPath(import.meta.url));
1806
+ let viewsFolderPath;
1807
+ if (__dirname.endsWith("/dist/bin") || __dirname.endsWith("/dist/app")) {
1808
+ viewsFolderPath = resolve(__dirname, "../../views/default");
1809
+ } else if (__dirname.endsWith("/dist")) {
1810
+ viewsFolderPath = resolve(__dirname, "../views/default");
1811
+ } else {
1812
+ viewsFolderPath = resolve(__dirname, "views/default");
1794
1813
  }
1795
- const templatePath = config.templatePath === void 0 ? path.join(fileURLToPath(import.meta.url), "../../../views/default") : untildify(config.templatePath);
1796
- return path.join(templatePath, `${fullTemplateFileName}.pug`);
1814
+ return viewsFolderPath;
1797
1815
  }
1798
- async function prepDirectory(exportPath) {
1799
- await rm(exportPath, { recursive: true, force: true });
1816
+ function getPathToTemplateFile(templateFileName, config) {
1817
+ const fullTemplateFileName = config.noHead !== true ? `${templateFileName}_full.pug` : `${templateFileName}.pug`;
1818
+ return join(getPathToViewsFolder(config), fullTemplateFileName);
1819
+ }
1820
+ async function prepDirectory(outputPath) {
1800
1821
  try {
1801
- await mkdir(exportPath, { recursive: true });
1822
+ await access(outputPath);
1802
1823
  } catch (error) {
1803
- if (error.code === "ENOENT") {
1804
- throw new Error(
1805
- `Unable to write to ${exportPath}. Try running this command from a writable directory.`
1806
- );
1824
+ try {
1825
+ await mkdir(outputPath, { recursive: true });
1826
+ } catch (error2) {
1827
+ if (error2?.code === "ENOENT") {
1828
+ throw new Error(
1829
+ `Unable to write to ${outputPath}. Try running this command from a writable directory.`
1830
+ );
1831
+ }
1832
+ throw error2;
1807
1833
  }
1808
- throw error;
1834
+ }
1835
+ const files = await readdir(outputPath);
1836
+ if (files.length > 0) {
1837
+ throw new Error(
1838
+ `Output directory ${outputPath} is not empty. Please specify an empty directory.`
1839
+ );
1809
1840
  }
1810
1841
  }
1811
- async function copyStaticAssets(config, exportPath) {
1812
- const staticAssetPath = config.templatePath === void 0 ? path.join(fileURLToPath(import.meta.url), "../../../views/default") : untildify(config.templatePath);
1842
+ async function copyStaticAssets(config, outputPath) {
1843
+ const viewsFolderPath = getPathToViewsFolder(config);
1813
1844
  const foldersToCopy = ["css", "js", "img"];
1814
1845
  for (const folder of foldersToCopy) {
1815
- if (await access(path.join(staticAssetPath, folder)).then(() => true).catch(() => false)) {
1816
- await cp(
1817
- path.join(staticAssetPath, folder),
1818
- path.join(exportPath, folder),
1819
- {
1820
- recursive: true
1821
- }
1822
- );
1846
+ if (await access(join(viewsFolderPath, folder)).then(() => true).catch(() => false)) {
1847
+ await cp(join(viewsFolderPath, folder), join(outputPath, folder), {
1848
+ recursive: true
1849
+ });
1823
1850
  }
1824
1851
  }
1825
1852
  if (config.hasGtfsRealtime) {
1826
1853
  await copyFile(
1827
1854
  "node_modules/pbf/dist/pbf.js",
1828
- path.join(exportPath, "js/pbf.js")
1855
+ join(outputPath, "js/pbf.js")
1829
1856
  );
1830
1857
  await copyFile(
1831
1858
  "node_modules/gtfs-realtime-pbf-js-module/gtfs-realtime.browser.proto.js",
1832
- path.join(exportPath, "js/gtfs-realtime.browser.proto.js")
1859
+ join(outputPath, "js/gtfs-realtime.browser.proto.js")
1833
1860
  );
1834
1861
  }
1835
1862
  }
1836
- function zipFolder(exportPath) {
1837
- const output = createWriteStream(path.join(exportPath, "timetables.zip"));
1863
+ function zipFolder(outputPath) {
1864
+ const output = createWriteStream(join(outputPath, "timetables.zip"));
1838
1865
  const archive = archiver("zip");
1839
- return new Promise((resolve, reject) => {
1840
- output.on("close", resolve);
1866
+ return new Promise((resolve2, reject) => {
1867
+ output.on("close", resolve2);
1841
1868
  archive.on("error", reject);
1842
1869
  archive.pipe(output);
1843
1870
  archive.glob("**/*.{txt,css,js,html}", {
1844
- cwd: exportPath
1871
+ cwd: outputPath
1845
1872
  });
1846
1873
  archive.finalize();
1847
1874
  });
@@ -1865,7 +1892,7 @@ function generateFolderName(timetablePage) {
1865
1892
  return sanitize(`${timetable.start_date}-${timetable.end_date}`);
1866
1893
  }
1867
1894
  async function renderTemplate(templateFileName, templateVars, config) {
1868
- const templatePath = getTemplatePath(templateFileName, config);
1895
+ const templatePath = getPathToTemplateFile(templateFileName, config);
1869
1896
  const html = await renderFile(templatePath, {
1870
1897
  _,
1871
1898
  md: (text) => insane(marked.parseInline(text)),
@@ -2075,8 +2102,8 @@ var gtfsToHtml = async (initialConfig) => {
2075
2102
  const agencyKey = config.agencies.map(
2076
2103
  (agency) => agency.agencyKey ?? agency.agency_key ?? "unknown"
2077
2104
  ).join("-");
2078
- const exportPath = path2.join(process.cwd(), "html", sanitize2(agencyKey));
2079
- const outputStats = {
2105
+ const outputPath = config.outputPath ? untildify2(config.outputPath) : path.join(process.cwd(), "html", sanitize2(agencyKey));
2106
+ const stats = {
2080
2107
  timetables: 0,
2081
2108
  timetablePages: 0,
2082
2109
  calendars: 0,
@@ -2090,9 +2117,9 @@ var gtfsToHtml = async (initialConfig) => {
2090
2117
  getTimetablePagesForAgency(config),
2091
2118
  "timetable_page_id"
2092
2119
  );
2093
- await prepDirectory(exportPath);
2120
+ await prepDirectory(outputPath);
2094
2121
  if (config.noHead !== true && ["html", "pdf"].includes(config.outputFormat)) {
2095
- await copyStaticAssets(config, exportPath);
2122
+ await copyStaticAssets(config, outputPath);
2096
2123
  }
2097
2124
  const bar = progressBar(
2098
2125
  `${agencyKey}: Generating ${config.outputFormat.toUpperCase()} timetables {bar} {value}/{total}`,
@@ -2107,7 +2134,7 @@ var gtfsToHtml = async (initialConfig) => {
2107
2134
  );
2108
2135
  for (const timetable of timetablePage.timetables) {
2109
2136
  for (const warning of timetable.warnings) {
2110
- outputStats.warnings.push(warning);
2137
+ stats.warnings.push(warning);
2111
2138
  bar?.interrupt(warning);
2112
2139
  }
2113
2140
  }
@@ -2116,20 +2143,20 @@ var gtfsToHtml = async (initialConfig) => {
2116
2143
  `No timetables found for timetable_page_id=${timetablePage.timetable_page_id}`
2117
2144
  );
2118
2145
  }
2119
- outputStats.timetables += timetablePage.consolidatedTimetables.length;
2120
- outputStats.timetablePages += 1;
2146
+ stats.timetables += timetablePage.consolidatedTimetables.length;
2147
+ stats.timetablePages += 1;
2121
2148
  const datePath = generateFolderName(timetablePage);
2122
- await mkdir2(path2.join(exportPath, datePath), { recursive: true });
2149
+ await mkdir2(path.join(outputPath, datePath), { recursive: true });
2123
2150
  config.assetPath = "../";
2124
- timetablePage.relativePath = path2.join(
2151
+ timetablePage.relativePath = path.join(
2125
2152
  datePath,
2126
2153
  sanitize2(timetablePage.filename)
2127
2154
  );
2128
2155
  if (config.outputFormat === "csv") {
2129
2156
  for (const timetable of timetablePage.consolidatedTimetables) {
2130
2157
  const csv = await generateTimetableCSV(timetable);
2131
- const csvPath = path2.join(
2132
- exportPath,
2158
+ const csvPath = path.join(
2159
+ outputPath,
2133
2160
  datePath,
2134
2161
  generateFileName(timetable, config, "csv")
2135
2162
  );
@@ -2137,8 +2164,8 @@ var gtfsToHtml = async (initialConfig) => {
2137
2164
  }
2138
2165
  } else {
2139
2166
  const html = await generateTimetableHTML(timetablePage, config);
2140
- const htmlPath = path2.join(
2141
- exportPath,
2167
+ const htmlPath = path.join(
2168
+ outputPath,
2142
2169
  datePath,
2143
2170
  sanitize2(timetablePage.filename)
2144
2171
  );
@@ -2149,12 +2176,12 @@ var gtfsToHtml = async (initialConfig) => {
2149
2176
  }
2150
2177
  timetablePages.push(timetablePage);
2151
2178
  const timetableStats = generateStats(timetablePage);
2152
- outputStats.stops += timetableStats.stops;
2153
- outputStats.routes += timetableStats.routes;
2154
- outputStats.trips += timetableStats.trips;
2155
- outputStats.calendars += timetableStats.calendars;
2179
+ stats.stops += timetableStats.stops;
2180
+ stats.routes += timetableStats.routes;
2181
+ stats.trips += timetableStats.trips;
2182
+ stats.calendars += timetableStats.calendars;
2156
2183
  } catch (error) {
2157
- outputStats.warnings.push(error?.message);
2184
+ stats.warnings.push(error?.message);
2158
2185
  bar?.interrupt(error.message);
2159
2186
  }
2160
2187
  bar?.increment();
@@ -2162,26 +2189,27 @@ var gtfsToHtml = async (initialConfig) => {
2162
2189
  if (config.outputFormat === "html") {
2163
2190
  config.assetPath = "";
2164
2191
  const html = await generateOverviewHTML(timetablePages, config);
2165
- await writeFile(path2.join(exportPath, "index.html"), html);
2192
+ await writeFile(path.join(outputPath, "index.html"), html);
2166
2193
  }
2167
- const logText = generateLogText(outputStats, config);
2168
- await writeFile(path2.join(exportPath, "log.txt"), logText);
2194
+ const logText = generateLogText(stats, config);
2195
+ await writeFile(path.join(outputPath, "log.txt"), logText);
2169
2196
  if (config.zipOutput) {
2170
- await zipFolder(exportPath);
2197
+ await zipFolder(outputPath);
2171
2198
  }
2172
- const fullExportPath = path2.join(
2173
- exportPath,
2199
+ const fullOutputPath = path.join(
2200
+ outputPath,
2174
2201
  config.zipOutput ? "/timetables.zip" : ""
2175
2202
  );
2176
2203
  config.log(
2177
- `${agencyKey}: ${config.outputFormat.toUpperCase()} timetables created at ${fullExportPath}`
2204
+ `${agencyKey}: ${config.outputFormat.toUpperCase()} timetables created at ${fullOutputPath}`
2178
2205
  );
2179
- logStats(outputStats, config);
2206
+ logStats(stats, config);
2180
2207
  const seconds = Math.round(timer.time() / 1e3);
2181
2208
  config.log(
2182
2209
  `${agencyKey}: ${config.outputFormat.toUpperCase()} timetable generation required ${seconds} seconds`
2183
2210
  );
2184
2211
  timer.stop();
2212
+ return fullOutputPath;
2185
2213
  };
2186
2214
  var gtfs_to_html_default = gtfsToHtml;
2187
2215
  export {