Skip to content

Commit

Permalink
Update to ES6 module
Browse files Browse the repository at this point in the history
Dependency updates
  • Loading branch information
brendannee committed May 23, 2021
1 parent 0adf3f5 commit 742cf16
Show file tree
Hide file tree
Showing 14 changed files with 1,457 additions and 2,500 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0] - 2021-05-23
### Breaking Changes
- Converted to ES Module
### Updated
- Dependency updates

## [0.0.5] - 2021-04-30
### Updated
- Dependency updates
Expand Down
37 changes: 20 additions & 17 deletions app/index.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
const path = require('path');
const gtfs = require('gtfs');
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { readFileSync } from 'node:fs';
import { openDb, getRoutes, getTrips, getDb, getStops } from 'gtfs';

const express = require('express');
const logger = require('morgan');
const toposort = require('toposort');
const { groupBy, last, uniqBy } = require('lodash');
import express from 'express';
import logger from 'morgan';
import toposort from 'toposort';
import { groupBy, last, uniqBy } from 'lodash-es';

const utils = require('../lib/utils');
const selectedConfig = require('../config');
import { setDefaultConfig } from '../lib/utils.js';

const app = express();
const router = new express.Router();

const config = utils.setDefaultConfig(selectedConfig);
const selectedConfig = JSON.parse(readFileSync(new URL('../config.json', import.meta.url)));

const config = setDefaultConfig(selectedConfig);
// Override noHead config option so full HTML pages are generated
config.assetPath = '/';
config.log = console.log;
config.logWarning = console.warn;
config.logError = console.error;

gtfs.openDb(config).catch(error => {
openDb(config).catch(error => {
if (error instanceof Error && error.code === 'SQLITE_CANTOPEN') {
config.logError(`Unable to open sqlite database "${config.sqlitePath}" defined as \`sqlitePath\` config.json. Ensure the parent directory exists or remove \`sqlitePath\` from config.json.`);
}
Expand All @@ -32,10 +35,10 @@ gtfs.openDb(config).catch(error => {
*/
router.get('/', async (request, response, next) => {
try {
const routes = await gtfs.getRoutes({}, ['route_id', 'route_short_name', 'route_long_name'], [['route_short_name', 'ASC']]);
const routes = await getRoutes({}, ['route_id', 'route_short_name', 'route_long_name'], [['route_short_name', 'ASC']]);

const routesWithDirections = await Promise.all(routes.map(async route => {
const trips = await gtfs.getTrips({
const trips = await getTrips({
route_id: route.route_id
}, [
'trip_headsign',
Expand All @@ -56,7 +59,7 @@ router.get('/', async (request, response, next) => {

router.get('/api/board-alights', async (request, response, next) => {
try {
const db = gtfs.getDb();
const db = getDb();
const values = [request.query.route_id];

let directionQuery = '';
Expand Down Expand Up @@ -100,7 +103,7 @@ router.get('/api/board-alights', async (request, response, next) => {

const routeStopOrder = toposort(stopGraph);

const stops = await gtfs.getStops({ stop_id: routeStopOrder }, ['stop_id', 'stop_name']);
const stops = await getStops({ stop_id: routeStopOrder }, ['stop_id', 'stop_name']);

return response.json({
routeStopOrder,
Expand All @@ -112,14 +115,14 @@ router.get('/api/board-alights', async (request, response, next) => {
}
});

app.set('views', path.join(__dirname, '..', 'views'));
app.set('views', path.join(fileURLToPath(import.meta.url), '../../views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.static(path.join(__dirname, '../public')));
app.use(express.static(path.join(fileURLToPath(import.meta.url), '../../public')));

app.use('/', router);
app.set('port', selectedConfig.port || process.env.PORT || 3000);
app.set('port', process.env.PORT || 3000);

const server = app.listen(app.get('port'), () => {
console.log(`Express server listening on port ${server.address().port}`);
Expand Down
23 changes: 13 additions & 10 deletions bin/gtfs-ride.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
#!/usr/bin/env node

// eslint-disable-next-line prefer-destructuring
const argv = require('yargs').usage('Usage: $0 --configPath ./config.json')
import yargs from 'yargs';
/* eslint-disable-next-line node/file-extension-in-import */
import { hideBin } from 'yargs/helpers';

import { getConfig } from '../lib/file-utils.js';
import { formatError } from '../lib/log-utils.js';
import gtfsRide from '../index.js';

const { argv } = yargs(hideBin(process.argv))
.usage('Usage: $0 --configPath ./config.json')
.help()
.option('c', {
alias: 'configPath',
Expand Down Expand Up @@ -33,22 +41,17 @@ const argv = require('yargs').usage('Usage: $0 --configPath ./config.json')
describe: 'Don’t import APC data.',
type: 'boolean'
})
.default('skipAPCImport', undefined)
.argv;

const fileUtils = require('../lib/file-utils');
const logUtils = require('../lib/log-utils');
const gtfsRide = require('..');
.default('skipAPCImport', undefined);

const handleError = error => {
const text = error || 'Unknown Error';
process.stdout.write(`\n${logUtils.formatError(text)}\n`);
process.stdout.write(`\n${formatError(text)}\n`);
console.error(error);
process.exit(1);
};

const setupImport = async () => {
const config = await fileUtils.getConfig(argv);
const config = await getConfig(argv);
await gtfsRide(config);
process.exit();
};
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = require('./lib/gtfs-ride');
export { default } from './lib/gtfs-ride.js';
40 changes: 21 additions & 19 deletions lib/file-utils.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
const path = require('path');

const fs = require('fs-extra');
const { snakeCase } = require('lodash');
const sanitize = require('sanitize-filename');
const untildify = require('untildify');
import path from 'node:path';
import { mkdir, readFile, rm } from 'node:fs/promises';
import { createReadStream, existsSync } from 'node:fs';
import { snakeCase } from 'lodash-es';
import sanitize from 'sanitize-filename';
import untildify from 'untildify';

/*
* Attempt to parse the specified config JSON file.
*/
exports.getConfig = async argv => {
export async function getConfig(argv) {
let config;

if (argv.configPath) {
// If a `configPath` is specified, try to read it and throw error if it doesn't exist
try {
const data = await fs.readFile(path.resolve(untildify(argv.configPath)), 'utf8').catch(error => {
const data = await readFile(path.resolve(untildify(argv.configPath)), 'utf8').catch(error => {
console.error(new Error(`Cannot find configuration file at \`${argv.configPath}\`. Use config-sample.json as a starting point, pass --configPath option`));
throw error;
});
Expand All @@ -23,10 +23,10 @@ exports.getConfig = async argv => {
console.error(new Error(`Cannot parse configuration file at \`${argv.configPath}\`. Check to ensure that it is valid JSON.`));
throw error;
}
} else if (fs.existsSync(path.resolve('./config.json'))) {
} else if (existsSync(path.resolve('./config.json'))) {
// Else if `config.json` exists, use config values read from it
try {
const data = await fs.readFile(path.resolve('./config.json'), 'utf8');
const data = await readFile(path.resolve('./config.json'), 'utf8');
config = Object.assign(JSON.parse(data), argv);
console.log('Using configuration from ./config.json');
} catch (error) {
Expand All @@ -39,24 +39,24 @@ exports.getConfig = async argv => {
}

return config;
};
}

/*
* Prepare the specified directory for saving HTML timetables by deleting
* everything and creating the expected folders.
*/
exports.prepDirectory = async exportPath => {
await fs.remove(exportPath);
await fs.ensureDir(exportPath);
};
export async function prepDirectory(exportPath) {
await rm(exportPath, { recursive: true, force: true });
await mkdir(exportPath, { recursive: true });
}

/*
* Count the number of lines in a file
*/
exports.countFileLines = async filePath => {
export async function countFileLines(filePath) {
return new Promise((resolve, reject) => {
let lineCount = 0;
fs.createReadStream(filePath)
createReadStream(filePath)
.on('data', buffer => {
let idx = -1;
lineCount--; // Because the loop will run once for idx=-1
Expand All @@ -68,9 +68,11 @@ exports.countFileLines = async filePath => {
resolve(lineCount);
}).on('error', reject);
});
};
}

/*
* Generate a folder name based on a string.
*/
exports.generateFolderName = folderName => snakeCase(sanitize(folderName));
export function generateFolderName(folderName) {
return snakeCase(sanitize(folderName));
}
6 changes: 3 additions & 3 deletions lib/formatters.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { pickBy } = require('lodash');
import { pickBy } from 'lodash-es';

/*
* Clean imported data
*/
exports.cleanLine = async ({ record, lineNumber }, model, config) => {
export async function cleanLine({ record, lineNumber }, model, config) {
return {
lineNumber,
record: pickBy(record, (value, fieldName) => {
Expand All @@ -23,4 +23,4 @@ exports.cleanLine = async ({ record, lineNumber }, model, config) => {
return true;
})
};
};
}
56 changes: 29 additions & 27 deletions lib/gtfs-ride.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
const path = require('path');

const { clone, omit } = require('lodash');
const fs = require('fs-extra');
const gtfs = require('gtfs');
const { DateTime } = require('luxon');
const open = require('open');
const Timer = require('timer-machine');
const untildify = require('untildify');

const { generateFolderName, prepDirectory } = require('./file-utils');
const logUtils = require('./log-utils');
const utils = require('./utils');
const importAPC = require('./import-apc');
const { generateSummaryHtml } = require('./summary');
import path from 'node:path';
import { writeFile } from 'node:fs/promises';

import { clone, omit } from 'lodash-es';
import { openDb, getDb, importGtfs, exportGtfs } from 'gtfs';
import { DateTime } from 'luxon';
import open from 'open';
import Timer from 'timer-machine';
import untildify from 'untildify';

import { generateFolderName, prepDirectory } from './file-utils.js';
import { log, logWarning, logError, logStats } from './log-utils.js';
import { setDefaultConfig } from './utils.js';
import importAPC from './import-apc.js';
import { generateSummaryHtml } from './summary.js';

/*
* Generate GTFS-Ride data
*/
module.exports = async initialConfig => {
const config = utils.setDefaultConfig(initialConfig);
config.log = logUtils.log(config);
config.logWarning = logUtils.logWarning(config);
config.logError = logUtils.logError(config);
const gtfsRide = async initialConfig => {
const config = setDefaultConfig(initialConfig);
config.log = log(config);
config.logWarning = logWarning(config);
config.logError = logError(config);

const issues = [];
config.recordIssue = issue => {
issues.push(issue);
};

await gtfs.openDb(config).catch(error => {
await openDb(config).catch(error => {
if (error instanceof Error && error.code === 'SQLITE_CANTOPEN') {
config.logError(`Unable to open sqlite database "${config.sqlitePath}" defined as \`sqlitePath\` config.json. Ensure the parent directory exists or remove \`sqlitePath\` from config.json.`);
}

throw error;
});

const db = gtfs.getDb();
const db = getDb();
const timer = new Timer();

timer.start();
Expand All @@ -55,7 +55,7 @@ module.exports = async initialConfig => {
}
];

await gtfs.import(gtfsImportConfig);
await importGtfs(gtfsImportConfig);
}

if (!config.skipAPCImport) {
Expand Down Expand Up @@ -85,13 +85,13 @@ module.exports = async initialConfig => {
// Export GTFS with GTFS-Ride included
config.log('Generating GTFS-Ride Data');

await gtfs.export({
await exportGtfs({
exportPath: path.join(exportPath, 'gtfs_ride'),
sqlitePath: config.sqlitePath
});

// Write log file of all issues
await fs.writeFile(path.join(exportPath, 'log.txt'), issues.join('\n'));
await writeFile(path.join(exportPath, 'log.txt'), issues.join('\n'));

timer.stop();

Expand Down Expand Up @@ -127,11 +127,13 @@ module.exports = async initialConfig => {
tripsWithoutData
};

logUtils.logStats(outputStats, config);
logStats(outputStats, config);

// Write summary html of output
const summaryHtmlPath = path.join(exportPath, 'summary.html');
const html = await generateSummaryHtml(outputStats);
await fs.writeFile(summaryHtmlPath, html);
await writeFile(summaryHtmlPath, html);
open(summaryHtmlPath);
};

export default gtfsRide;
Loading

0 comments on commit 742cf16

Please sign in to comment.