gtfs 3.3.1 → 3.5.1

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/README.md CHANGED
@@ -21,13 +21,13 @@
21
21
 
22
22
  <hr>
23
23
 
24
- `node-GTFS` loads transit data in [GTFS format](https://developers.google.com/transit/) into a SQLite database and provides some methods to query for agencies, routes, stops, times, fares, calendars and other GTFS data. It also offers spatial queries to find nearby stops, routes and agencies and can convert stops and shapes to geoJSON format.
24
+ `node-GTFS` loads transit data in [GTFS format](https://developers.google.com/transit/) into a SQLite database and provides some methods to query for agencies, routes, stops, times, fares, calendars and other GTFS data. It also offers spatial queries to find nearby stops, routes and agencies and can convert stops and shapes to geoJSON format. Additionally, this library can export data from the SQLite database back into GTFS (csv) format.
25
25
 
26
- Additionally, this library can export data from the SQLite database back into GTFS (csv) format.
26
+ The library also supports importing GTFS-Realtime data into the same database. In order to keep the realtime database fresh, it uses `SQLITE REPLACE` which makes it very effective.
27
27
 
28
28
  You can use it as a [command-line tool](#command-line-examples) or as a [node.js module](#code-example).
29
29
 
30
- This library has three parts: the [GTFS import script](#gtfs-import-script), the [query methods](#query-methods) and the [GTFS export script](#gtfs-export-script)
30
+ This library has four parts: the [GTFS import script](#gtfs-import-script), [GTFS export script](#gtfs-export-script) and [GTFS-Realtime update script](#gtfsrealtime-update-script) and the [query methods](#query-methods)
31
31
 
32
32
  ## Installation
33
33
 
@@ -96,13 +96,13 @@ importGtfs(config)
96
96
  </tr>
97
97
  </table>
98
98
 
99
- ## Command Line Usage
99
+ ## Command-Line Usage
100
100
 
101
101
  The `gtfs-import` command-line utility will import GTFS into SQLite3.
102
102
 
103
103
  The `gtfs-export` command-line utility will create GTFS from data previously imported into SQLite3.
104
104
 
105
- ### gtfs-import Command-line options
105
+ ### gtfs-import Command-Line options
106
106
 
107
107
  `configPath`
108
108
 
@@ -219,6 +219,25 @@ API along with your API token.
219
219
  }
220
220
  ```
221
221
 
222
+ - Specify urls for GTFS-Realtime updates. `realtimeUrls` allows an array of GTFS-Realtime URLs. For example, a URL for trip updates, a URL for vehicle updates and a URL for service alerts. In addition, a `realtimeHeaders` parameter allows adding additional HTTP headers to the request.
223
+
224
+ ```json
225
+ {
226
+ "agencies": [
227
+ {
228
+ "url": "http://countyconnection.com/GTFS/google_transit.zip",
229
+ "realtimeUrls": [
230
+ "https://opendata.somewhere.com/gtfs-rt/VehicleUpdates.pb",
231
+ "https://opendata.somewhere.com/gtfs-rt/TripUpdates.pb"
232
+ ],
233
+ "realtimeHeaders": {
234
+ "Authorization": "bearer 1234567890"
235
+ }
236
+ }
237
+ ]
238
+ }
239
+ ```
240
+
222
241
  - Specify multiple agencies to be imported into the same database
223
242
 
224
243
  ```json
@@ -353,6 +372,39 @@ importGtfs(config)
353
372
  });
354
373
  ```
355
374
 
375
+ ## `gtfsrealtime-update` Script
376
+
377
+ The `gtfsrealtime-update` script requests GTFS-Realtime data and importings into a SQLite database. [GTFS-Realtime data](https://gtfs.org/realtime/reference/) can compliment GTFS Static data. [Read more about GTFS-Realtime configuration](#configuration).
378
+
379
+ ### Run the `gtfsrealtime-update` script from command-line
380
+
381
+ gtfsrealtime-update
382
+
383
+ By default, it will look for a `config.json` file in the project root. To specify a different path for the configuration file:
384
+
385
+ gtfsrealtime-update --configPath /path/to/your/custom-config.json
386
+
387
+ ### Use `updateGtfsRealtime` script in code
388
+
389
+ Use `updateGtfsRealtime()` in your code to run an update of a GTFS-Realtime data specified in a config.json file.
390
+
391
+ ```js
392
+ import { updateGtfsRealtime } from 'gtfs';
393
+ import { readFile } from 'fs/promises';
394
+
395
+ const config = JSON.parse(
396
+ await readFile(new URL('./config.json', import.meta.url))
397
+ );
398
+
399
+ updateGtfsRealtime(config)
400
+ .then(() => {
401
+ console.log('Update Successful');
402
+ })
403
+ .catch((err) => {
404
+ console.error(err);
405
+ });
406
+ ```
407
+
356
408
  ## `gtfs-export` Script
357
409
 
358
410
  The `gtfs-export` script reads from a JSON configuration file and exports data in GTFS format from a SQLite database. [Read more on setting up your configuration file](#configuration).
@@ -371,7 +423,7 @@ By default, it will look for a `config.json` file in the project root. To specif
371
423
 
372
424
  gtfs-export --configPath /path/to/your/custom-config.json
373
425
 
374
- ### Command Line options
426
+ ### Command-Line options
375
427
 
376
428
  #### Specify path to config JSON file
377
429
 
@@ -381,7 +433,7 @@ You can specify the path to a config file to be used by the export script.
381
433
 
382
434
  #### Show help
383
435
 
384
- Show all command line options
436
+ Show all command-line options
385
437
 
386
438
  gtfs-export --help
387
439
 
@@ -417,6 +469,8 @@ This library includes many methods you can use in your project to query GTFS dat
417
469
 
418
470
  Most methods accept three optional arguments: `query`, `fields` and `sortBy`.
419
471
 
472
+ More advanced methods include `advancedQuery`, `runRawQuery` and `execRawQuery`.
473
+
420
474
  #### Query
421
475
 
422
476
  For example, to get a list of all routes with just `route_id`, `route_short_name` and `route_color` sorted by `route_short_name`:
@@ -1011,6 +1065,114 @@ getTimetableNotesReferences({
1011
1065
  });
1012
1066
  ```
1013
1067
 
1068
+ ### getTripsDatedVehicleJourneys(query, fields, sortBy)
1069
+
1070
+ Queries trips_dated_vehicle_journey and returns a promise. The result of the promise is an array of trips_dated_vehicle_journey. These are from the non-standard `trips-dated-vehicle-journey.txt` file. See [documentation and examples of this file](https://www.trafiklab.se/api/trafiklab-apis/gtfs-regional/extra-files/).
1071
+
1072
+ ```js
1073
+ import { getTripsDatedVehicleJourneys } from 'gtfs';
1074
+
1075
+ // Get all timetable_stop_orders
1076
+ getTripsDatedVehicleJourneys();
1077
+ ```
1078
+
1079
+ ### getServiceAlerts(query, fields, sortBy)
1080
+
1081
+ Queries service alerts and returns a promise. The result of the promise is an array of service alerts.
1082
+ These are only valid if you use GTFS-Realtime and have imported Service Alert data.
1083
+
1084
+ ```js
1085
+ import { getServiceAlerts } from 'gtfs';
1086
+
1087
+ // Get service alerts
1088
+ getServiceAlerts();
1089
+ ```
1090
+
1091
+ ### getTripUpdates(query, fields, sortBy)
1092
+
1093
+ Queries trip alerts and returns a promise. The result of the promise is an array of trip updates.
1094
+ These are only valid if you use GTFS-Realtime and have imported Trip Update data.
1095
+
1096
+ ```js
1097
+ import { getTripUpdates } from 'gtfs';
1098
+
1099
+ // Get all trip updates
1100
+ getTripUpdates();
1101
+ ```
1102
+
1103
+ ### getStopTimesUpdates(query, fields, sortBy)
1104
+
1105
+ Queries stop times updates and returns a promise. The result of the promise is an array of stop times updates.
1106
+ These are only valid if you use GTFS-Realtime and have imported Trip Update data.
1107
+
1108
+ ```js
1109
+ import { getStopTimesUpdates } from 'gtfs';
1110
+
1111
+ // Get all stop times updates
1112
+ getStopTimesUpdates();
1113
+ ```
1114
+
1115
+ ### getVehiclePositions(query, fields, sortBy)
1116
+
1117
+ Queries vehicle positions and returns a promise. The result of the promise is an array of vehicle location data.
1118
+ These are only valid if you use GTFS-Realtime and have imported Vehicle Position data.
1119
+
1120
+ ```js
1121
+ import { getVehiclePositions } from 'gtfs';
1122
+
1123
+ // Get all vehicle position data
1124
+ getVehiclePositions();
1125
+ ```
1126
+
1127
+ ### advancedQuery(table, advancedQueryOptions)
1128
+
1129
+ Queries the database in a simple manner with support for table joins and custom tables. Returns a promise.
1130
+ The result of the promise is an array the selected data. Example shows joining stop_times with trips.
1131
+ Used for advanced scenarios.
1132
+
1133
+ ```js
1134
+ import { advancedQuery } from 'gtfs';
1135
+
1136
+ const advancedQueryOptions = {
1137
+ query: {
1138
+ 'stop_times.trip_id': tripId,
1139
+ },
1140
+ fields: ['stop_times.trip_id', 'arrival_time'],
1141
+ join: [
1142
+ {
1143
+ type: 'INNER',
1144
+ table: 'trips',
1145
+ on: 'stop_times.trip_id=trips.trip_id',
1146
+ },
1147
+ ],
1148
+ };
1149
+ // Perform a custom query
1150
+ advancedQuery('stop_times', advancedQueryOptions);
1151
+ ```
1152
+
1153
+ ### runRawQuery(query)
1154
+
1155
+ Queries the database using a raw sql statement. Returns a promise.
1156
+ The result of the promise is an array the selected data.
1157
+
1158
+ ```js
1159
+ import { runRawQuery } from 'gtfs';
1160
+
1161
+ // Perform a raw query
1162
+ runRawQuery('SELECT * FROM stop_times WHERE stop_sequence="1"');
1163
+ ```
1164
+
1165
+ ### execRawQuery(query)
1166
+
1167
+ Executes a statement. Returns a promise containing the result of the execute.
1168
+
1169
+ ```js
1170
+ import { execRawQuery } from 'gtfs';
1171
+
1172
+ // Purge trips table
1173
+ execRawQuery('DELETE FROM trips');
1174
+ ```
1175
+
1014
1176
  ## Contributing
1015
1177
 
1016
1178
  Pull requests are welcome, as is feedback and [reporting issues](https://github.com/blinktaginc/node-gtfs/issues).
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ import yargs from 'yargs';
4
+ import { hideBin } from 'yargs/helpers';
5
+
6
+ import { getConfig } from '../lib/file-utils.js';
7
+ import { formatError } from '../lib/log-utils.js';
8
+ import { updateGtfsRealtime } from '../lib/gtfs.js';
9
+
10
+ const { argv } = yargs(hideBin(process.argv))
11
+ .usage('Usage: $0 --configPath ./config.json')
12
+ .help()
13
+ .option('c', {
14
+ alias: 'configPath',
15
+ describe: 'Path to config file',
16
+ type: 'string',
17
+ });
18
+
19
+ const handleError = (error) => {
20
+ const text = error || 'Unknown Error';
21
+ process.stdout.write(`\n${formatError(text)}\n`);
22
+ console.error(error);
23
+ process.exit(1);
24
+ };
25
+
26
+ const setupImport = async () => {
27
+ const config = await getConfig(argv);
28
+ await updateGtfsRealtime(config);
29
+ process.exit();
30
+ };
31
+
32
+ setupImport().catch(handleError);
@@ -0,0 +1,28 @@
1
+ {
2
+ "agencies": [
3
+ {
4
+ "url": "http://www.bart.gov/dev/schedules/google_transit.zip",
5
+ "exclude": ["shapes"],
6
+ "realtimeUrls": [
7
+ "https://opendata.samtrafiken.se/gtfs-rt/sl/TripUpdates.pb?key=yourkey",
8
+ "https://opendata.samtrafiken.se/gtfs-rt/sl/VehiclePositions.pb?key=yourkey",
9
+ "https://opendata.samtrafiken.se/gtfs-rt/sl/ServiceAlerts.pb?key=yourkey"
10
+ ],
11
+ "realtimeHeaders": {
12
+ "X-CustomHeader": "MyCustomHeader"
13
+ },
14
+ "headers": {
15
+ "X-CustomHeader": "MyCustomHeader"
16
+ }
17
+ },
18
+ {
19
+ "path": "/path/to/gtfs.zip",
20
+ "exclude": ["stop_times", "shapes"]
21
+ }
22
+ ],
23
+ "csvOptions": {
24
+ "skip_lines_with_error": true
25
+ },
26
+ "sqlitePath": "/tmp/gtfs",
27
+ "exportPath": "~/path/to/export/gtfs"
28
+ }
@@ -0,0 +1,45 @@
1
+ import sqlString from 'sqlstring-sqlite';
2
+
3
+ import { getDb } from './db.js';
4
+
5
+ import {
6
+ formatOrderByClause,
7
+ formatSelectClause,
8
+ formatWhereClauses,
9
+ formatJoinClause,
10
+ } from './utils.js';
11
+
12
+ /*
13
+ * Returns an array of all agencies that match the query parameters.
14
+ */
15
+ export async function advancedQuery(table, advancedQueryOptions) {
16
+ const defaultOptions = {
17
+ query: {},
18
+ fields: [],
19
+ orderBy: [],
20
+ join: [],
21
+ options: {},
22
+ };
23
+ const queryOptions = { ...defaultOptions, ...advancedQueryOptions };
24
+
25
+ const db = queryOptions.options.db ?? (await getDb());
26
+ const tableName = sqlString.escapeId(table);
27
+ const selectClause = formatSelectClause(queryOptions.fields);
28
+ const whereClause = formatWhereClauses(queryOptions.query);
29
+ const joinClause = formatJoinClause(queryOptions.join);
30
+ const orderByClause = formatOrderByClause(queryOptions.orderBy);
31
+ const sqlStatement = `${selectClause} FROM ${tableName} ${joinClause} ${whereClause} ${orderByClause};`;
32
+ return db.all(sqlStatement).catch((error) => {
33
+ console.log(error);
34
+ });
35
+ }
36
+
37
+ export async function runRawQuery(sql, options = {}) {
38
+ const db = options.db ?? (await getDb());
39
+ return db.all(sql);
40
+ }
41
+
42
+ export async function execRawQuery(sql, options = {}) {
43
+ const db = options.db ?? (await getDb());
44
+ return db.exec(sql);
45
+ }
package/lib/db.js CHANGED
@@ -1,13 +1,14 @@
1
1
  import sqlite3 from 'sqlite3';
2
2
  import { open } from 'sqlite';
3
3
  import { setDefaultConfig } from './utils.js';
4
+ import untildify from 'untildify';
4
5
  const dbs = {};
5
6
 
6
7
  export async function openDb(initialConfig) {
7
8
  const config = setDefaultConfig(initialConfig);
8
9
  if (!dbs[config.sqlitePath]) {
9
10
  dbs[config.sqlitePath] = await open({
10
- filename: config.sqlitePath,
11
+ filename: untildify(config.sqlitePath),
11
12
  driver: sqlite3.Database,
12
13
  });
13
14
  }
@@ -0,0 +1,32 @@
1
+ import sqlString from 'sqlstring-sqlite';
2
+
3
+ import { getDb } from '../db.js';
4
+
5
+ import {
6
+ formatOrderByClause,
7
+ formatSelectClause,
8
+ formatWhereClauses,
9
+ } from '../utils.js';
10
+ import serviceAlerts from '../../models/gtfs-realtime/service-alerts.js';
11
+ import serviceAlertTargets from '../../models/gtfs-realtime/service-alert-targets.js';
12
+
13
+ /*
14
+ * Returns an array of all agencies that match the query parameters.
15
+ */
16
+ export async function getServiceAlerts(
17
+ query = {},
18
+ fields = [],
19
+ orderBy = [],
20
+ options = {}
21
+ ) {
22
+ const db = options.db ?? (await getDb());
23
+ const tableName = sqlString.escapeId(serviceAlerts.filenameBase);
24
+ const joinTable = sqlString.escapeId(serviceAlertTargets.filenameBase);
25
+ const selectClause = formatSelectClause(fields);
26
+ const whereClause = formatWhereClauses(query);
27
+ const orderByClause = formatOrderByClause(orderBy);
28
+
29
+ return db.all(
30
+ `${selectClause} FROM ${tableName} INNER JOIN ${joinTable} ON ${tableName}.id=${joinTable}.alert_id ${whereClause} ${orderByClause};`
31
+ );
32
+ }
@@ -0,0 +1,30 @@
1
+ import sqlString from 'sqlstring-sqlite';
2
+
3
+ import { getDb } from '../db.js';
4
+
5
+ import {
6
+ formatOrderByClause,
7
+ formatSelectClause,
8
+ formatWhereClauses,
9
+ } from '../utils.js';
10
+ import stopTimeUpdates from '../../models/gtfs-realtime/stop-times-updates.js';
11
+
12
+ /*
13
+ * Returns an array of all agencies that match the query parameters.
14
+ */
15
+ export async function getStopTimesUpdates(
16
+ query = {},
17
+ fields = [],
18
+ orderBy = [],
19
+ options = {}
20
+ ) {
21
+ const db = options.db ?? (await getDb());
22
+ const tableName = sqlString.escapeId(stopTimeUpdates.filenameBase);
23
+ const selectClause = formatSelectClause(fields);
24
+ const whereClause = formatWhereClauses(query);
25
+ const orderByClause = formatOrderByClause(orderBy);
26
+
27
+ return db.all(
28
+ `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
29
+ );
30
+ }
@@ -0,0 +1,30 @@
1
+ import sqlString from 'sqlstring-sqlite';
2
+
3
+ import { getDb } from '../db.js';
4
+
5
+ import {
6
+ formatOrderByClause,
7
+ formatSelectClause,
8
+ formatWhereClauses,
9
+ } from '../utils.js';
10
+ import tripUpdates from '../../models/gtfs-realtime/trip-updates.js';
11
+
12
+ /*
13
+ * Returns an array of all agencies that match the query parameters.
14
+ */
15
+ export async function getTripUpdates(
16
+ query = {},
17
+ fields = [],
18
+ orderBy = [],
19
+ options = {}
20
+ ) {
21
+ const db = options.db ?? (await getDb());
22
+ const tableName = sqlString.escapeId(tripUpdates.filenameBase);
23
+ const selectClause = formatSelectClause(fields);
24
+ const whereClause = formatWhereClauses(query);
25
+ const orderByClause = formatOrderByClause(orderBy);
26
+
27
+ return db.all(
28
+ `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
29
+ );
30
+ }
@@ -0,0 +1,30 @@
1
+ import sqlString from 'sqlstring-sqlite';
2
+
3
+ import { getDb } from '../db.js';
4
+
5
+ import {
6
+ formatOrderByClause,
7
+ formatSelectClause,
8
+ formatWhereClauses,
9
+ } from '../utils.js';
10
+ import vehiclePositions from '../../models/gtfs-realtime/vehicle-positions.js';
11
+
12
+ /*
13
+ * Returns an array of all agencies that match the query parameters.
14
+ */
15
+ export async function getVehiclePositions(
16
+ query = {},
17
+ fields = [],
18
+ orderBy = [],
19
+ options = {}
20
+ ) {
21
+ const db = options.db ?? (await getDb());
22
+ const tableName = sqlString.escapeId(vehiclePositions.filenameBase);
23
+ const selectClause = formatSelectClause(fields);
24
+ const whereClause = formatWhereClauses(query);
25
+ const orderByClause = formatOrderByClause(orderBy);
26
+
27
+ return db.all(
28
+ `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
29
+ );
30
+ }
package/lib/gtfs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // GTFS import script
2
- import importGtfs from './import.js';
2
+ import { importGtfs, updateGtfsRealtime } from './import.js';
3
3
 
4
4
  // GTFS export script
5
5
  import exportGtfs from './export.js';
@@ -31,6 +31,7 @@ import { getTimetableStopOrders } from './non-standard/timetable-stop-order.js';
31
31
  import { getTimetablePages } from './non-standard/timetable-pages.js';
32
32
  import { getTimetableNotes } from './non-standard/timetable-notes.js';
33
33
  import { getTimetableNotesReferences } from './non-standard/timetable-notes-references.js';
34
+ import { getTripsDatedVehicleJourneys } from './non-standard/trips-dated-vehicle-journey.js';
34
35
 
35
36
  // GTFS-ride Filenames
36
37
  import { getBoardAlights } from './gtfs-ride/board-alights.js';
@@ -39,9 +40,18 @@ import { getRiderTrips } from './gtfs-ride/rider-trips.js';
39
40
  import { getRiderships } from './gtfs-ride/riderships.js';
40
41
  import { getTripCapacities } from './gtfs-ride/trip-capacities.js';
41
42
 
43
+ // GTFS-Realtime Filenames
44
+ import { getStopTimesUpdates } from './gtfs-realtime/stop-times-updates.js';
45
+ import { getTripUpdates } from './gtfs-realtime/trip-updates.js';
46
+ import { getVehiclePositions } from './gtfs-realtime/vehicle-positions.js';
47
+ import { getServiceAlerts } from './gtfs-realtime/service-alerts.js';
48
+
42
49
  // Expose database connection
43
50
  import { openDb, closeDb, getDb } from './db.js';
44
51
 
52
+ // Advanced Query Support or Raw Query Support
53
+ import { runRawQuery, execRawQuery, advancedQuery } from './advancedQuery.js';
54
+
45
55
  const _importGtfs = importGtfs;
46
56
  export { _importGtfs as importGtfs };
47
57
  const _exportGtfs = exportGtfs;
@@ -123,6 +133,9 @@ export { _getTimetableNotes as getTimetableNotes };
123
133
  const _getTimetableNotesReferences = getTimetableNotesReferences;
124
134
  export { _getTimetableNotesReferences as getTimetableNotesReferences };
125
135
 
136
+ const _getTripsDatedVehicleJourneys = getTripsDatedVehicleJourneys;
137
+ export { _getTripsDatedVehicleJourneys as getTripsDatedVehicleJourneys };
138
+
126
139
  const _getBoardAlights = getBoardAlights;
127
140
  export { _getBoardAlights as getBoardAlights };
128
141
 
@@ -138,9 +151,31 @@ export { _getRiderships as getRiderships };
138
151
  const _getTripCapacities = getTripCapacities;
139
152
  export { _getTripCapacities as getTripCapacities };
140
153
 
154
+ const _updateGtfsRealtime = updateGtfsRealtime;
155
+ export { _updateGtfsRealtime as updateGtfsRealtime };
156
+
157
+ const _getStopTimesUpdates = getStopTimesUpdates;
158
+ export { _getStopTimesUpdates as getStopTimesUpdates };
159
+
160
+ const _getTripUpdates = getTripUpdates;
161
+ export { _getTripUpdates as getTripUpdates };
162
+
163
+ const _getVehiclePositions = getVehiclePositions;
164
+ export { _getVehiclePositions as getVehiclePositions };
165
+
166
+ const _getServiceAlerts = getServiceAlerts;
167
+ export { _getServiceAlerts as getServiceAlerts };
168
+
141
169
  const _openDb = openDb;
142
170
  export { _openDb as openDb };
143
171
  const _closeDb = closeDb;
144
172
  export { _closeDb as closeDb };
145
173
  const _getDb = getDb;
146
174
  export { _getDb as getDb };
175
+
176
+ const _advancedQuery = advancedQuery;
177
+ export { _advancedQuery as advancedQuery };
178
+ const _runRawQuery = runRawQuery;
179
+ export { _runRawQuery as runRawQuery };
180
+ const _execRawQuery = execRawQuery;
181
+ export { _execRawQuery as execRawQuery };