gtfs 3.1.3 → 3.1.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/.eslintrc.json +14 -19
- package/.husky/pre-commit +4 -0
- package/.prettierrc.js +4 -0
- package/CHANGELOG.md +156 -0
- package/README.md +113 -126
- package/bin/gtfs-export.js +4 -5
- package/bin/gtfs-import.js +6 -7
- package/config-sample-full.json +2 -7
- package/lib/db.js +4 -2
- package/lib/export.js +26 -9
- package/lib/file-utils.js +26 -9
- package/lib/geojson-utils.js +51 -38
- package/lib/gtfs/agencies.js +8 -2
- package/lib/gtfs/attributions.js +8 -2
- package/lib/gtfs/calendar-dates.js +8 -2
- package/lib/gtfs/calendars.js +8 -2
- package/lib/gtfs/fare-attributes.js +8 -2
- package/lib/gtfs/fare-rules.js +8 -2
- package/lib/gtfs/feed-info.js +8 -2
- package/lib/gtfs/frequencies.js +8 -2
- package/lib/gtfs/levels.js +8 -2
- package/lib/gtfs/pathways.js +8 -2
- package/lib/gtfs/routes.js +15 -4
- package/lib/gtfs/shapes.js +49 -18
- package/lib/gtfs/stop-times.js +8 -2
- package/lib/gtfs/stops.js +45 -16
- package/lib/gtfs/transfers.js +8 -2
- package/lib/gtfs/translations.js +8 -2
- package/lib/gtfs/trips.js +8 -2
- package/lib/gtfs-ride/board-alights.js +8 -2
- package/lib/gtfs-ride/ride-feed-infos.js +8 -2
- package/lib/gtfs-ride/rider-trips.js +8 -2
- package/lib/gtfs-ride/riderships.js +8 -2
- package/lib/gtfs-ride/trip-capacities.js +8 -2
- package/lib/import.js +198 -123
- package/lib/log-utils.js +8 -4
- package/lib/non-standard/directions.js +8 -2
- package/lib/non-standard/stop-attributes.js +8 -2
- package/lib/non-standard/timetable-notes-references.js +13 -3
- package/lib/non-standard/timetable-notes.js +8 -2
- package/lib/non-standard/timetable-pages.js +8 -2
- package/lib/non-standard/timetable-stop-order.js +13 -3
- package/lib/non-standard/timetables.js +8 -2
- package/lib/utils.js +22 -11
- package/models/gtfs/agency.js +11 -11
- package/models/gtfs/attributions.js +14 -14
- package/models/gtfs/calendar-dates.js +7 -7
- package/models/gtfs/calendar.js +12 -12
- package/models/gtfs/fare-attributes.js +9 -9
- package/models/gtfs/fare-rules.js +8 -8
- package/models/gtfs/feed-info.js +12 -12
- package/models/gtfs/frequencies.js +10 -10
- package/models/gtfs/levels.js +5 -5
- package/models/gtfs/pathways.js +14 -14
- package/models/gtfs/routes.js +14 -14
- package/models/gtfs/shapes.js +8 -8
- package/models/gtfs/stop-times.js +17 -17
- package/models/gtfs/stops.js +17 -17
- package/models/gtfs/transfers.js +7 -7
- package/models/gtfs/translations.js +10 -10
- package/models/gtfs/trips.js +12 -12
- package/models/gtfs-ride/board-alight.js +24 -24
- package/models/gtfs-ride/ride-feed-info.js +8 -8
- package/models/gtfs-ride/rider-trip.js +21 -21
- package/models/gtfs-ride/ridership.js +23 -23
- package/models/gtfs-ride/trip-capacity.js +10 -10
- package/models/models.js +1 -1
- package/models/non-standard/directions.js +6 -6
- package/models/non-standard/stop-attributes.js +5 -5
- package/models/non-standard/timetable-notes-references.js +9 -9
- package/models/non-standard/timetable-notes.js +5 -5
- package/models/non-standard/timetable-pages.js +5 -5
- package/models/non-standard/timetable-stop-order.js +6 -6
- package/models/non-standard/timetables.js +27 -27
- package/package.json +10 -2
- package/test/mocha/export-gtfs.js +63 -40
- package/test/mocha/get-agencies.js +11 -11
- package/test/mocha/get-attributions.js +1 -1
- package/test/mocha/get-board-alights.js +1 -1
- package/test/mocha/get-calendar-dates.js +22 -21
- package/test/mocha/get-calendars.js +8 -8
- package/test/mocha/get-db.js +9 -2
- package/test/mocha/get-directions.js +1 -1
- package/test/mocha/get-fare-attributes.js +3 -3
- package/test/mocha/get-fare-rules.js +8 -10
- package/test/mocha/get-feed-info.js +1 -1
- package/test/mocha/get-frequencies.js +1 -1
- package/test/mocha/get-levels.js +1 -1
- package/test/mocha/get-pathways.js +1 -1
- package/test/mocha/get-rider-trips.js +1 -1
- package/test/mocha/get-riderships.js +1 -1
- package/test/mocha/get-routes.js +9 -13
- package/test/mocha/get-shapes-as-geojson.js +3 -3
- package/test/mocha/get-shapes.js +28 -36
- package/test/mocha/get-stop-attributes.js +1 -1
- package/test/mocha/get-stops-as-geojson.js +2 -2
- package/test/mocha/get-stops.js +59 -48
- package/test/mocha/get-stoptimes.js +9 -7
- package/test/mocha/get-timetable-pages.js +1 -1
- package/test/mocha/get-timetable-stop-orders.js +1 -1
- package/test/mocha/get-timetables.js +1 -1
- package/test/mocha/get-transfers.js +1 -1
- package/test/mocha/get-translations.js +1 -1
- package/test/mocha/get-trip-capacities.js +1 -1
- package/test/mocha/get-trips.js +3 -3
- package/test/mocha/import-gtfs.js +59 -42
- package/test/test-config.js +9 -4
package/lib/export.js
CHANGED
|
@@ -17,7 +17,7 @@ import { setDefaultConfig } from './utils.js';
|
|
|
17
17
|
|
|
18
18
|
const stringify = promisify(csvStringify);
|
|
19
19
|
|
|
20
|
-
const exportGtfs = async initialConfig => {
|
|
20
|
+
const exportGtfs = async (initialConfig) => {
|
|
21
21
|
const config = setDefaultConfig(initialConfig);
|
|
22
22
|
const log = _log(config);
|
|
23
23
|
const logWarning = _logWarning(config);
|
|
@@ -26,20 +26,34 @@ const exportGtfs = async initialConfig => {
|
|
|
26
26
|
// Get agency name for export folder from first line of agency.txt
|
|
27
27
|
const agencies = await db.all('SELECT agency_name FROM agency;').catch(() => {
|
|
28
28
|
if (config.sqlitePath === ':memory:') {
|
|
29
|
-
throw new Error(
|
|
29
|
+
throw new Error(
|
|
30
|
+
'No agencies found in SQLite. You are using an in-memory database - if running this from command line be sure to specify a value for `sqlitePath` in config.json other than ":memory:".'
|
|
31
|
+
);
|
|
30
32
|
}
|
|
31
33
|
|
|
32
|
-
throw new Error(
|
|
34
|
+
throw new Error(
|
|
35
|
+
'No agencies found in SQLite. Be sure to first import data into SQLite using `gtfs-import` or `importGtfs(config);`'
|
|
36
|
+
);
|
|
33
37
|
});
|
|
34
38
|
|
|
35
39
|
const agencyCount = agencies.length;
|
|
36
40
|
if (agencyCount === 0) {
|
|
37
|
-
throw new Error(
|
|
41
|
+
throw new Error(
|
|
42
|
+
'No agencies found in SQLite. Be sure to first import data into SQLite using `gtfs-import` or `importGtfs(config);`'
|
|
43
|
+
);
|
|
38
44
|
} else if (agencyCount > 1) {
|
|
39
|
-
logWarning(
|
|
45
|
+
logWarning(
|
|
46
|
+
'More than one agency is defined in config.json. Export will merge all into one GTFS file.'
|
|
47
|
+
);
|
|
40
48
|
}
|
|
41
49
|
|
|
42
|
-
log(
|
|
50
|
+
log(
|
|
51
|
+
`Starting GTFS export for ${pluralize(
|
|
52
|
+
'agency',
|
|
53
|
+
agencyCount,
|
|
54
|
+
true
|
|
55
|
+
)} using SQLite database at ${config.sqlitePath}`
|
|
56
|
+
);
|
|
43
57
|
|
|
44
58
|
const folderName = generateFolderName(agencies[0].agency_name);
|
|
45
59
|
const defaultExportPath = path.join(process.cwd(), 'gtfs-export', folderName);
|
|
@@ -48,7 +62,7 @@ const exportGtfs = async initialConfig => {
|
|
|
48
62
|
await prepDirectory(exportPath);
|
|
49
63
|
|
|
50
64
|
// Loop through each GTFS file
|
|
51
|
-
const exportedFiles = await mapSeries(models, async model => {
|
|
65
|
+
const exportedFiles = await mapSeries(models, async (model) => {
|
|
52
66
|
const filepath = path.join(exportPath, `${model.filenameBase}.txt`);
|
|
53
67
|
const tableName = sqlString.escapeId(model.filenameBase);
|
|
54
68
|
const lines = await db.all(`SELECT * FROM ${tableName};`);
|
|
@@ -72,10 +86,13 @@ const exportGtfs = async initialConfig => {
|
|
|
72
86
|
'boarding_timestamp',
|
|
73
87
|
'alighting_timestamp',
|
|
74
88
|
'ridership_start_timestamp',
|
|
75
|
-
'ridership_end_timestamp'
|
|
89
|
+
'ridership_end_timestamp',
|
|
76
90
|
];
|
|
77
91
|
|
|
78
|
-
const columns = without(
|
|
92
|
+
const columns = without(
|
|
93
|
+
model.schema.map((column) => column.name),
|
|
94
|
+
...excludeColumns
|
|
95
|
+
);
|
|
79
96
|
const fileText = await stringify(lines, { columns, header: true });
|
|
80
97
|
await writeFile(filepath, fileText);
|
|
81
98
|
|
package/lib/file-utils.js
CHANGED
|
@@ -15,13 +15,24 @@ export async function getConfig(argv) {
|
|
|
15
15
|
if (argv.configPath) {
|
|
16
16
|
// If a `configPath` is specified, try to read it and throw error if it doesn't exist
|
|
17
17
|
try {
|
|
18
|
-
const data = await readFile(
|
|
19
|
-
|
|
18
|
+
const data = await readFile(
|
|
19
|
+
path.resolve(untildify(argv.configPath)),
|
|
20
|
+
'utf8'
|
|
21
|
+
).catch((error) => {
|
|
22
|
+
console.error(
|
|
23
|
+
new Error(
|
|
24
|
+
`Cannot find configuration file at \`${argv.configPath}\`. Use config-sample.json as a starting point, pass --configPath option.`
|
|
25
|
+
)
|
|
26
|
+
);
|
|
20
27
|
throw error;
|
|
21
28
|
});
|
|
22
29
|
config = Object.assign(JSON.parse(data), argv);
|
|
23
30
|
} catch (error) {
|
|
24
|
-
console.error(
|
|
31
|
+
console.error(
|
|
32
|
+
new Error(
|
|
33
|
+
`Cannot parse configuration file at \`${argv.configPath}\`. Check to ensure that it is valid JSON.`
|
|
34
|
+
)
|
|
35
|
+
);
|
|
25
36
|
throw error;
|
|
26
37
|
}
|
|
27
38
|
} else if (existsSync(path.resolve('./config.json'))) {
|
|
@@ -31,7 +42,11 @@ export async function getConfig(argv) {
|
|
|
31
42
|
config = Object.assign(JSON.parse(data), argv);
|
|
32
43
|
console.log('Using configuration from ./config.json');
|
|
33
44
|
} catch (error) {
|
|
34
|
-
console.error(
|
|
45
|
+
console.error(
|
|
46
|
+
new Error(
|
|
47
|
+
'Cannot parse configuration file at `./config.json`. Check to ensure that it is valid JSON.'
|
|
48
|
+
)
|
|
49
|
+
);
|
|
35
50
|
throw error;
|
|
36
51
|
}
|
|
37
52
|
} else if (argv.gtfsPath || argv.gtfsUrl) {
|
|
@@ -39,22 +54,24 @@ export async function getConfig(argv) {
|
|
|
39
54
|
const agencies = [];
|
|
40
55
|
if (argv.gtfsPath) {
|
|
41
56
|
agencies.push({
|
|
42
|
-
path: argv.gtfsPath
|
|
57
|
+
path: argv.gtfsPath,
|
|
43
58
|
});
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
if (argv.gtfsUrl) {
|
|
47
62
|
agencies.push({
|
|
48
|
-
url: argv.gtfsUrl
|
|
63
|
+
url: argv.gtfsUrl,
|
|
49
64
|
});
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
config = {
|
|
53
68
|
agencies,
|
|
54
|
-
...omit(argv, ['path', 'url'])
|
|
69
|
+
...omit(argv, ['path', 'url']),
|
|
55
70
|
};
|
|
56
71
|
} else {
|
|
57
|
-
const error = new Error(
|
|
72
|
+
const error = new Error(
|
|
73
|
+
'Cannot find configuration file. Use config-sample.json as a starting point, pass --configPath option.'
|
|
74
|
+
);
|
|
58
75
|
console.error(error);
|
|
59
76
|
throw error;
|
|
60
77
|
}
|
|
@@ -78,7 +95,7 @@ export function unzip(zipfilePath, exportPath) {
|
|
|
78
95
|
/* eslint-disable new-cap */
|
|
79
96
|
return createReadStream(zipfilePath)
|
|
80
97
|
.pipe(Extract({ path: exportPath }))
|
|
81
|
-
.on('entry', entry => entry.autodrain())
|
|
98
|
+
.on('entry', (entry) => entry.autodrain())
|
|
82
99
|
.promise();
|
|
83
100
|
/* eslint-enable new-cap */
|
|
84
101
|
}
|
package/lib/geojson-utils.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
cloneDeep,
|
|
3
|
+
filter,
|
|
4
|
+
groupBy,
|
|
5
|
+
last,
|
|
6
|
+
omit,
|
|
7
|
+
sortBy,
|
|
8
|
+
omitBy,
|
|
9
|
+
} from 'lodash-es';
|
|
2
10
|
import { feature, featureCollection } from '@turf/helpers';
|
|
3
11
|
|
|
4
12
|
function isValidLineString(lineString) {
|
|
@@ -11,7 +19,11 @@ function isValidLineString(lineString) {
|
|
|
11
19
|
}
|
|
12
20
|
|
|
13
21
|
// Reject linestrings with two identical points
|
|
14
|
-
if (
|
|
22
|
+
if (
|
|
23
|
+
lineString.length === 2 &&
|
|
24
|
+
lineString[0][0] === lineString[1][0] &&
|
|
25
|
+
lineString[0][1] === lineString[1][1]
|
|
26
|
+
) {
|
|
15
27
|
return false;
|
|
16
28
|
}
|
|
17
29
|
|
|
@@ -20,22 +32,18 @@ function isValidLineString(lineString) {
|
|
|
20
32
|
|
|
21
33
|
function consolidateShapes(shapes) {
|
|
22
34
|
const keys = new Set();
|
|
23
|
-
const segmentsArray = shapes.map(shape
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
[
|
|
27
|
-
shape[idx - 1].shape_pt_lon,
|
|
28
|
-
|
|
29
|
-
]
|
|
30
|
-
|
|
31
|
-
point.shape_pt_lon,
|
|
32
|
-
point.shape_pt_lat
|
|
33
|
-
]
|
|
34
|
-
]);
|
|
35
|
-
}
|
|
35
|
+
const segmentsArray = shapes.map((shape) =>
|
|
36
|
+
shape.reduce((memo, point, idx) => {
|
|
37
|
+
if (idx > 0) {
|
|
38
|
+
memo.push([
|
|
39
|
+
[shape[idx - 1].shape_pt_lon, shape[idx - 1].shape_pt_lat],
|
|
40
|
+
[point.shape_pt_lon, point.shape_pt_lat],
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
return memo;
|
|
45
|
+
}, [])
|
|
46
|
+
);
|
|
39
47
|
|
|
40
48
|
const consolidatedLineStrings = [];
|
|
41
49
|
|
|
@@ -75,42 +83,47 @@ function formatHexColor(color) {
|
|
|
75
83
|
|
|
76
84
|
function formatProperties(properties) {
|
|
77
85
|
const formattedProperties = {
|
|
78
|
-
...cloneDeep(omitBy(properties, value => value === null)),
|
|
86
|
+
...cloneDeep(omitBy(properties, (value) => value === null)),
|
|
79
87
|
route_color: formatHexColor(properties.route_color),
|
|
80
|
-
route_text_color: formatHexColor(properties.route_text_color)
|
|
88
|
+
route_text_color: formatHexColor(properties.route_text_color),
|
|
81
89
|
};
|
|
82
90
|
|
|
83
91
|
if (properties.routes) {
|
|
84
|
-
formattedProperties.routes = properties.routes.map(route =>
|
|
92
|
+
formattedProperties.routes = properties.routes.map((route) =>
|
|
93
|
+
formatProperties(route)
|
|
94
|
+
);
|
|
85
95
|
}
|
|
86
96
|
|
|
87
97
|
return formattedProperties;
|
|
88
98
|
}
|
|
89
99
|
|
|
90
100
|
export function shapesToGeoJSONFeatures(shapes, properties = {}) {
|
|
91
|
-
const shapeGroups = Object.values(groupBy(shapes, 'shape_id')).map(
|
|
101
|
+
const shapeGroups = Object.values(groupBy(shapes, 'shape_id')).map(
|
|
102
|
+
(shapeGroup) => sortBy(shapeGroup, 'shape_pt_sequence')
|
|
103
|
+
);
|
|
92
104
|
const lineStrings = consolidateShapes(shapeGroups);
|
|
93
105
|
|
|
94
|
-
return lineStrings.map(lineString =>
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
return lineStrings.map((lineString) =>
|
|
107
|
+
feature(
|
|
108
|
+
{
|
|
109
|
+
type: 'LineString',
|
|
110
|
+
coordinates: lineString,
|
|
111
|
+
},
|
|
112
|
+
formatProperties(properties)
|
|
113
|
+
)
|
|
114
|
+
);
|
|
101
115
|
}
|
|
102
116
|
|
|
103
117
|
export function stopsToGeoJSON(stops) {
|
|
104
|
-
const features = stops.map(stop =>
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
stop.stop_lon,
|
|
109
|
-
|
|
110
|
-
]
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
));
|
|
118
|
+
const features = stops.map((stop) =>
|
|
119
|
+
feature(
|
|
120
|
+
{
|
|
121
|
+
type: 'Point',
|
|
122
|
+
coordinates: [stop.stop_lon, stop.stop_lat],
|
|
123
|
+
},
|
|
124
|
+
formatProperties(omit(stop, ['stop_lat', 'stop_lon']))
|
|
125
|
+
)
|
|
126
|
+
);
|
|
114
127
|
|
|
115
128
|
return featureCollection(features);
|
|
116
129
|
}
|
package/lib/gtfs/agencies.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import agency from '../../models/gtfs/agency.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getAgencies(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
package/lib/gtfs/attributions.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import attributions from '../../models/gtfs/attributions.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getAttributions(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import calendarDates from '../../models/gtfs/calendar-dates.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getCalendarDates(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
package/lib/gtfs/calendars.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import calendars from '../../models/gtfs/calendar.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getCalendars(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import fareAttributes from '../../models/gtfs/fare-attributes.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getFareAttributes(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
package/lib/gtfs/fare-rules.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import fareRules from '../../models/gtfs/fare-rules.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getFareRules(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
package/lib/gtfs/feed-info.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import feedInfo from '../../models/gtfs/feed-info.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getFeedInfo(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
package/lib/gtfs/frequencies.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import frequencies from '../../models/gtfs/frequencies.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getFrequencies(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
package/lib/gtfs/levels.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import levels from '../../models/gtfs/levels.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getLevels(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
package/lib/gtfs/pathways.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import pathways from '../../models/gtfs/pathways.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getPathways(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|
package/lib/gtfs/routes.js
CHANGED
|
@@ -3,7 +3,12 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
3
3
|
|
|
4
4
|
import { getDb } from '../db.js';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
formatOrderByClause,
|
|
8
|
+
formatSelectClause,
|
|
9
|
+
formatWhereClause,
|
|
10
|
+
formatWhereClauses,
|
|
11
|
+
} from '../utils.js';
|
|
7
12
|
import routes from '../../models/gtfs/routes.js';
|
|
8
13
|
|
|
9
14
|
function buildStoptimeSubquery(query) {
|
|
@@ -12,7 +17,9 @@ function buildStoptimeSubquery(query) {
|
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
function buildTripSubquery(query) {
|
|
15
|
-
return `SELECT DISTINCT route_id FROM trips WHERE trip_id IN (${buildStoptimeSubquery(
|
|
20
|
+
return `SELECT DISTINCT route_id FROM trips WHERE trip_id IN (${buildStoptimeSubquery(
|
|
21
|
+
query
|
|
22
|
+
)})`;
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
/*
|
|
@@ -29,7 +36,9 @@ export async function getRoutes(query = {}, fields = [], orderBy = []) {
|
|
|
29
36
|
const routeQuery = omit(query, ['stop_id']);
|
|
30
37
|
const stoptimeQuery = pick(query, ['stop_id']);
|
|
31
38
|
|
|
32
|
-
const whereClauses = Object.entries(routeQuery).map(([key, value]) =>
|
|
39
|
+
const whereClauses = Object.entries(routeQuery).map(([key, value]) =>
|
|
40
|
+
formatWhereClause(key, value)
|
|
41
|
+
);
|
|
33
42
|
|
|
34
43
|
if (Object.values(stoptimeQuery).length > 0) {
|
|
35
44
|
whereClauses.push(`route_id IN (${buildTripSubquery(stoptimeQuery)})`);
|
|
@@ -39,5 +48,7 @@ export async function getRoutes(query = {}, fields = [], orderBy = []) {
|
|
|
39
48
|
whereClause = `WHERE ${whereClauses.join(' AND ')}`;
|
|
40
49
|
}
|
|
41
50
|
|
|
42
|
-
return db.all(
|
|
51
|
+
return db.all(
|
|
52
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
53
|
+
);
|
|
43
54
|
}
|
package/lib/gtfs/shapes.js
CHANGED
|
@@ -4,7 +4,12 @@ import { featureCollection } from '@turf/helpers';
|
|
|
4
4
|
|
|
5
5
|
import { getDb } from '../db.js';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
formatOrderByClause,
|
|
9
|
+
formatSelectClause,
|
|
10
|
+
formatWhereClause,
|
|
11
|
+
formatWhereClauses,
|
|
12
|
+
} from '../utils.js';
|
|
8
13
|
import { shapesToGeoJSONFeatures } from '../geojson-utils.js';
|
|
9
14
|
import shapes from '../../models/gtfs/shapes.js';
|
|
10
15
|
import { getAgencies } from './agencies.js';
|
|
@@ -28,10 +33,22 @@ export async function getShapes(query = {}, fields = [], orderBy = []) {
|
|
|
28
33
|
let whereClause = '';
|
|
29
34
|
const orderByClause = formatOrderByClause(orderBy);
|
|
30
35
|
|
|
31
|
-
const shapeQuery = omit(query, [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
const shapeQuery = omit(query, [
|
|
37
|
+
'route_id',
|
|
38
|
+
'trip_id',
|
|
39
|
+
'service_id',
|
|
40
|
+
'direction_id',
|
|
41
|
+
]);
|
|
42
|
+
const tripQuery = pick(query, [
|
|
43
|
+
'route_id',
|
|
44
|
+
'trip_id',
|
|
45
|
+
'service_id',
|
|
46
|
+
'direction_id',
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
const whereClauses = Object.entries(shapeQuery).map(([key, value]) =>
|
|
50
|
+
formatWhereClause(key, value)
|
|
51
|
+
);
|
|
35
52
|
|
|
36
53
|
if (Object.values(tripQuery).length > 0) {
|
|
37
54
|
whereClauses.push(`shape_id IN (${buildTripSubquery(tripQuery)})`);
|
|
@@ -41,7 +58,9 @@ export async function getShapes(query = {}, fields = [], orderBy = []) {
|
|
|
41
58
|
whereClause = `WHERE ${whereClauses.join(' AND ')}`;
|
|
42
59
|
}
|
|
43
60
|
|
|
44
|
-
return db.all(
|
|
61
|
+
return db.all(
|
|
62
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
63
|
+
);
|
|
45
64
|
}
|
|
46
65
|
|
|
47
66
|
/*
|
|
@@ -60,18 +79,30 @@ export async function getShapesAsGeoJSON(query = {}) {
|
|
|
60
79
|
const routes = await getRoutes(routeQuery);
|
|
61
80
|
const features = [];
|
|
62
81
|
|
|
63
|
-
await Promise.all(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
82
|
+
await Promise.all(
|
|
83
|
+
routes.map(async (route) => {
|
|
84
|
+
const shapeQuery = {
|
|
85
|
+
route_id: route.route_id,
|
|
86
|
+
...omit(query, 'route_id'),
|
|
87
|
+
};
|
|
88
|
+
const shapes = await getShapes(shapeQuery, [
|
|
89
|
+
'shape_id',
|
|
90
|
+
'shape_pt_sequence',
|
|
91
|
+
'shape_pt_lon',
|
|
92
|
+
'shape_pt_lat',
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
const agency = agencies.find(
|
|
96
|
+
(agency) => agency.agency_id === route.agency_id
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const routeProperties = {
|
|
100
|
+
agency_name: agency ? agency.agency_name : undefined,
|
|
101
|
+
...route,
|
|
102
|
+
};
|
|
103
|
+
features.push(...shapesToGeoJSONFeatures(shapes, routeProperties));
|
|
104
|
+
})
|
|
105
|
+
);
|
|
75
106
|
|
|
76
107
|
return featureCollection(features);
|
|
77
108
|
}
|
package/lib/gtfs/stop-times.js
CHANGED
|
@@ -2,7 +2,11 @@ import sqlString from 'sqlstring-sqlite';
|
|
|
2
2
|
|
|
3
3
|
import { getDb } from '../db.js';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
formatOrderByClause,
|
|
7
|
+
formatSelectClause,
|
|
8
|
+
formatWhereClauses,
|
|
9
|
+
} from '../utils.js';
|
|
6
10
|
import stopTimes from '../../models/gtfs/stop-times.js';
|
|
7
11
|
|
|
8
12
|
/*
|
|
@@ -15,5 +19,7 @@ export async function getStoptimes(query = {}, fields = [], orderBy = []) {
|
|
|
15
19
|
const whereClause = formatWhereClauses(query);
|
|
16
20
|
const orderByClause = formatOrderByClause(orderBy);
|
|
17
21
|
|
|
18
|
-
return db.all(
|
|
22
|
+
return db.all(
|
|
23
|
+
`${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
|
|
24
|
+
);
|
|
19
25
|
}
|