gtfs 4.10.1 → 4.10.3

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.
@@ -7,7 +7,7 @@ jobs:
7
7
  runs-on: ubuntu-latest
8
8
  strategy:
9
9
  matrix:
10
- node: [ 18, 20 ]
10
+ node: [ 20, 21 ]
11
11
  name: Use Node.js ${{ matrix.node }}
12
12
  steps:
13
13
  - uses: actions/checkout@v4
package/@types/index.d.ts CHANGED
@@ -160,6 +160,11 @@ export function openDb(config: DbConfig): Database.Database;
160
160
  */
161
161
  export function closeDb(db?: Database.Database): void;
162
162
 
163
+ /**
164
+ * Deletes the specified database.
165
+ */
166
+ export function deleteDb(db?: Database.Database): void;
167
+
163
168
  /**
164
169
  * Returns an array of agencies that match query parameters.
165
170
  */
package/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.10.3] - 2024-05-12
9
+
10
+ ### Added
11
+
12
+ - Additional GTFS-RT vehiclePosition fields
13
+ - deleteDb method
14
+
15
+ ### Updated
16
+
17
+ - Dependency updates
18
+
19
+ ## [4.10.2] - 2024-04-02
20
+
21
+ ### Added
22
+
23
+ - Better error message for `gtfsrealtime-update` command
24
+ - Support additional fields for vehiclePosition GTFS-Realtime data
25
+
26
+ ### Updated
27
+
28
+ - Dependency updates
29
+
8
30
  ## [4.10.1] - 2024-03-29
9
31
 
10
32
  ### Updated
package/README.md CHANGED
@@ -636,6 +636,20 @@ const db = openDb(config);
636
636
  closeDb(db);
637
637
  ```
638
638
 
639
+ ### Deleting a Database
640
+
641
+ You can use `deleteDb` to delete a sqlite3 database from the filesystem.
642
+
643
+ ```js
644
+ import { deleteDb, openDb } from 'gtfs';
645
+ const db = openDb(config);
646
+
647
+ // Do some stuff here
648
+
649
+ // Delete the database
650
+ deleteDb(db);
651
+ ```
652
+
639
653
  ### Examples
640
654
 
641
655
  For example, to get a list of all routes with just `route_id`, `route_short_name` and `route_color` sorted by `route_short_name`:
@@ -1338,11 +1352,13 @@ const timetableNotesReferences = getTimetableNotesReferences({
1338
1352
 
1339
1353
  ### GTFS-Realtime
1340
1354
 
1341
- In order to use GTFS-Realtime query methods, you must first configure GTFS Realtime import in node-gtfs
1355
+ In order to use GTFS-Realtime query methods, you must first run the [GTFS-Realtime update script or function](#gtfsrealtime-update-script) to pull data into your database.
1342
1356
 
1343
1357
  #### getServiceAlerts(query, fields, sortBy, options)
1344
1358
 
1345
- Returns an array of GTFS Realtime service alerts that match query parameters. [Details on Service Alerts](https://gtfs.org/realtime/feed-entities/service-alerts/)
1359
+ Returns an array of GTFS Realtime service alerts that match query parameters. Note that this does not refresh the data from GTFS-Realtime feeds, it only fetches what is stored in the database. In order to fetch the latest service alerts from GTFS-Realtime feeds and store in your database, use the [GTFS-Realtime update script or function](#gtfsrealtime-update-script).
1360
+
1361
+ [More details on Service Alerts](https://gtfs.org/realtime/feed-entities/service-alerts/)
1346
1362
 
1347
1363
  ```js
1348
1364
  import { getServiceAlerts } from 'gtfs';
@@ -1353,7 +1369,9 @@ const serviceAlerts = getServiceAlerts();
1353
1369
 
1354
1370
  #### getTripUpdates(query, fields, sortBy, options)
1355
1371
 
1356
- Returns an array of GTFS Realtime trip updates that match query parameters. [Details on Trip Updates](https://gtfs.org/realtime/feed-entities/trip-updates/)
1372
+ Returns an array of GTFS Realtime trip updates that match query parameters. Note that this does not refresh the data from GTFS-Realtime feeds, it only fetches what is stored in the database. In order to fetch the latest trip updates from GTFS-Realtime feeds and store in your database, use the [GTFS-Realtime update script or function](#gtfsrealtime-update-script).
1373
+
1374
+ [More details on Trip Updates](https://gtfs.org/realtime/feed-entities/trip-updates/)
1357
1375
 
1358
1376
  ```js
1359
1377
  import { getTripUpdates } from 'gtfs';
@@ -1364,7 +1382,9 @@ const tripUpdates = getTripUpdates();
1364
1382
 
1365
1383
  #### getStopTimeUpdates(query, fields, sortBy, options)
1366
1384
 
1367
- Returns an array of GTFS Realtime stop time updates that match query parameters. [Details on Stop Time Updates](https://gtfs.org/realtime/feed-entities/trip-updates/#stoptimeupdate)
1385
+ Returns an array of GTFS Realtime stop time updates that match query parameters. Note that this does not refresh the data from GTFS-Realtime feeds, it only fetches what is stored in the database. In order to fetch the latest stop time updates from GTFS-Realtime feeds and store in your database, use the [GTFS-Realtime update script or function](#gtfsrealtime-update-script).
1386
+
1387
+ [More details on Stop Time Updates](https://gtfs.org/realtime/feed-entities/trip-updates/#stoptimeupdate)
1368
1388
 
1369
1389
  ```js
1370
1390
  import { getStopTimeUpdates } from 'gtfs';
@@ -1375,7 +1395,9 @@ const stopTimeUpdates = getStopTimeUpdates();
1375
1395
 
1376
1396
  #### getVehiclePositions(query, fields, sortBy, options)
1377
1397
 
1378
- Returns an array of GTFS Realtime vehicle positions that match query parameters. [Details on Vehicle Positions](https://gtfs.org/realtime/feed-entities/vehicle-positions/)
1398
+ Returns an array of GTFS Realtime vehicle positions that match query parameters. Note that this does not refresh the data from GTFS-Realtime feeds, it only fetches what is stored in the database. In order to fetch the latest vehicle positions from GTFS-Realtime feeds and store in your database, use the [GTFS-Realtime update script or function](#gtfsrealtime-update-script).
1399
+
1400
+ [More details on Vehicle Positions](https://gtfs.org/realtime/feed-entities/vehicle-positions/)
1379
1401
 
1380
1402
  ```js
1381
1403
  import { getVehiclePositions } from 'gtfs';
package/lib/db.js CHANGED
@@ -1,3 +1,5 @@
1
+ import fs from 'fs';
2
+
1
3
  import Database from 'better-sqlite3';
2
4
  import untildify from 'untildify';
3
5
 
@@ -64,3 +66,27 @@ export function closeDb(db) {
64
66
  db.close();
65
67
  delete dbs[db.name];
66
68
  }
69
+
70
+ export function deleteDb(db) {
71
+ if (Object.keys(dbs).length === 0) {
72
+ throw new Error(
73
+ 'No database connection. Call `openDb(config)` before using any methods.',
74
+ );
75
+ }
76
+
77
+ if (!db) {
78
+ if (Object.keys(dbs).length > 1) {
79
+ throw new Error(
80
+ 'Multiple database connections. Pass the db you want to delete as a parameter to `deleteDb`.',
81
+ );
82
+ }
83
+
84
+ db = dbs[Object.keys(dbs)[0]];
85
+ }
86
+
87
+ db.close();
88
+
89
+ fs.unlinkSync(db.name);
90
+
91
+ delete dbs[db.name];
92
+ }
package/lib/gtfs.js CHANGED
@@ -67,7 +67,7 @@ import { getRunEvents } from './ods/run-events.js';
67
67
  import { getRunsPieces } from './ods/runs-pieces.js';
68
68
 
69
69
  // Expose database connection
70
- import { openDb, closeDb } from './db.js';
70
+ import { deleteDb, openDb, closeDb } from './db.js';
71
71
 
72
72
  // Advanced Query
73
73
  import { advancedQuery } from './advancedQuery.js';
@@ -238,6 +238,8 @@ const _openDb = openDb;
238
238
  export { _openDb as openDb };
239
239
  const _closeDb = closeDb;
240
240
  export { _closeDb as closeDb };
241
+ const _deleteDb = deleteDb;
242
+ export { _deleteDb as deleteDb };
241
243
 
242
244
  const _advancedQuery = advancedQuery;
243
245
  export { _advancedQuery as advancedQuery };
package/lib/import.js CHANGED
@@ -107,22 +107,39 @@ function getDescendantProp(obj, desc, defaultvalue) {
107
107
  return obj;
108
108
  }
109
109
 
110
- const markRealtimeDataStale = (config, log) => {
111
- const db = openDb(config);
110
+ const markRealtimeDataStale = (config) => {
111
+ const log = _log(config);
112
+ const logError = _logError(config);
112
113
 
113
- log(`Marking GTFS-Realtime data as stale..`);
114
- db.prepare(`UPDATE vehicle_positions SET is_updated=0`).run();
115
- db.prepare(`UPDATE trip_updates SET is_updated=0`).run();
116
- db.prepare(`UPDATE stop_time_updates SET is_updated=0`).run();
117
- db.prepare(`UPDATE service_alerts SET is_updated=0`).run();
118
- db.prepare(`UPDATE service_alert_targets SET is_updated=0`).run();
119
- log(`Marked GTFS-Realtime data as stale\r`, true);
114
+ try {
115
+ const db = openDb(config);
116
+
117
+ log(`Marking GTFS-Realtime data as stale`);
118
+ db.prepare(`UPDATE vehicle_positions SET is_updated=0`).run();
119
+ db.prepare(`UPDATE trip_updates SET is_updated=0`).run();
120
+ db.prepare(`UPDATE stop_time_updates SET is_updated=0`).run();
121
+ db.prepare(`UPDATE service_alerts SET is_updated=0`).run();
122
+ db.prepare(`UPDATE service_alert_targets SET is_updated=0`).run();
123
+ log(`Marked GTFS-Realtime data as stale\r`, true);
124
+ } catch (error) {
125
+ if (
126
+ error instanceof Error &&
127
+ error.code === 'SQLITE_ERROR' &&
128
+ error.message?.startsWith('no such table')
129
+ ) {
130
+ logError(
131
+ 'Run `gtfs-import` before running the `gtfsrealtime-update` command to set up tables.',
132
+ );
133
+ throw error;
134
+ }
135
+ }
120
136
  };
121
137
 
122
- const cleanStaleRealtimeData = (config, log) => {
138
+ const cleanStaleRealtimeData = (config) => {
139
+ const log = _log(config);
123
140
  const db = openDb(config);
124
141
 
125
- log(`Cleaning stale GTFS-RT data..`);
142
+ log(`Cleaning stale GTFS-RT data`);
126
143
  db.prepare(`DELETE FROM vehicle_positions WHERE is_updated=0`).run();
127
144
  db.prepare(`DELETE FROM trip_updates WHERE is_updated=0`).run();
128
145
  db.prepare(`DELETE FROM stop_time_updates WHERE is_updated=0`).run();
@@ -708,7 +725,7 @@ export async function updateGtfsRealtime(initialConfig) {
708
725
  )} using SQLite database at ${config.sqlitePath}`,
709
726
  );
710
727
 
711
- markRealtimeDataStale(config, log);
728
+ markRealtimeDataStale(config);
712
729
 
713
730
  await Promise.all(
714
731
  config.agencies.map(async (agency) => {
@@ -729,7 +746,7 @@ export async function updateGtfsRealtime(initialConfig) {
729
746
  }),
730
747
  );
731
748
 
732
- cleanStaleRealtimeData(config, log);
749
+ cleanStaleRealtimeData(config);
733
750
  log(
734
751
  `Completed GTFS-Realtime refresh for ${pluralize(
735
752
  'agencies',
@@ -39,6 +39,12 @@ const model = {
39
39
  source: 'vehicle.position.speed',
40
40
  default: null,
41
41
  },
42
+ {
43
+ name: 'current_stop_sequence',
44
+ type: 'integer',
45
+ source: 'vehicle.currentStopSequence',
46
+ default: null,
47
+ },
42
48
  {
43
49
  name: 'trip_id',
44
50
  type: 'varchar(255)',
@@ -46,6 +52,44 @@ const model = {
46
52
  source: 'vehicle.trip.tripId',
47
53
  default: null,
48
54
  },
55
+ {
56
+ name: 'trip_start_date',
57
+ type: 'varchar(255)',
58
+ index: true,
59
+ source: 'vehicle.trip.startDate',
60
+ default: null,
61
+ },
62
+ {
63
+ name: 'trip_start_time',
64
+ type: 'varchar(255)',
65
+ index: true,
66
+ source: 'vehicle.trip.startTime',
67
+ default: null,
68
+ },
69
+ {
70
+ name: 'congestion_level',
71
+ type: 'varchar(255)',
72
+ source: 'vehicle.congestionLevel',
73
+ default: null,
74
+ },
75
+ {
76
+ name: 'occupancy_status',
77
+ type: 'varchar(255)',
78
+ source: 'vehicle.occupancyStatus',
79
+ default: null,
80
+ },
81
+ {
82
+ name: 'occupancy_percentage',
83
+ type: 'integer',
84
+ source: 'vehicle.occupancyPercentage',
85
+ default: null,
86
+ },
87
+ {
88
+ name: 'vehicle_stop_status',
89
+ type: 'varchar(255)',
90
+ source: 'vehicle.vehicleStopStatus',
91
+ default: null,
92
+ },
49
93
  {
50
94
  name: 'vehicle_id',
51
95
  type: 'varchar(255)',
@@ -53,6 +97,24 @@ const model = {
53
97
  source: 'vehicle.vehicle.id',
54
98
  default: null,
55
99
  },
100
+ {
101
+ name: 'vehicle_label',
102
+ type: 'varchar(255)',
103
+ source: 'vehicle.vehicle.label',
104
+ default: null,
105
+ },
106
+ {
107
+ name: 'vehicle_license_plate',
108
+ type: 'varchar(255)',
109
+ source: 'vehicle.vehicle.licensePlate',
110
+ default: null,
111
+ },
112
+ {
113
+ name: 'vehicle_wheelchair_accessible',
114
+ type: 'varchar(255)',
115
+ source: 'vehicle.vehicle.wheelchairAccessible',
116
+ default: null,
117
+ },
56
118
  {
57
119
  name: 'timestamp',
58
120
  type: 'varchar(255)',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtfs",
3
- "version": "4.10.1",
3
+ "version": "4.10.3",
4
4
  "description": "Import GTFS transit data into SQLite and query routes, stops, times, fares and more",
5
5
  "keywords": [
6
6
  "transit",
@@ -77,7 +77,7 @@
77
77
  },
78
78
  "dependencies": {
79
79
  "@turf/helpers": "^6.5.0",
80
- "better-sqlite3": "^9.4.3",
80
+ "better-sqlite3": "^10.0.0",
81
81
  "csv-parse": "^5.5.5",
82
82
  "csv-stringify": "^6.4.6",
83
83
  "gtfs-realtime-bindings": "^1.1.1",
@@ -0,0 +1,62 @@
1
+ /* eslint-env mocha */
2
+
3
+ import fs from 'fs';
4
+
5
+ import config from '../test-config.js';
6
+ import { deleteDb, openDb, importGtfs } from '../../index.js';
7
+
8
+ const db2Config = {
9
+ agencies: [
10
+ {
11
+ ...config.agencies[0],
12
+ exclude: ['shapes'],
13
+ },
14
+ ],
15
+ verbose: false,
16
+ sqlitePath: './tmpdb2',
17
+ };
18
+
19
+ const db3Config = {
20
+ agencies: [
21
+ {
22
+ ...config.agencies[0],
23
+ exclude: ['shapes'],
24
+ },
25
+ ],
26
+ verbose: false,
27
+ sqlitePath: './tmpdb3',
28
+ };
29
+
30
+ describe('openDb():', () => {
31
+ before(async () => {});
32
+
33
+ after(() => {
34
+ // Delete extra databases
35
+ fs.rmSync(db2Config.sqlitePath, { force: true });
36
+ fs.rmSync(db3Config.sqlitePath, { force: true });
37
+ });
38
+
39
+ it('should allow deleting a database', async () => {
40
+ const db2 = openDb(db2Config);
41
+ await importGtfs(db2Config);
42
+
43
+ const db3 = openDb(db3Config);
44
+ await importGtfs(db3Config);
45
+
46
+ db2.name.should.equal('./tmpdb2');
47
+ db3.name.should.equal('./tmpdb3');
48
+
49
+ fs.existsSync(db2Config.sqlitePath).should.equal(true);
50
+ fs.existsSync(db3Config.sqlitePath).should.equal(true);
51
+
52
+ deleteDb(db2);
53
+
54
+ fs.existsSync(db2Config.sqlitePath).should.equal(false);
55
+ fs.existsSync(db3Config.sqlitePath).should.equal(true);
56
+
57
+ deleteDb(db3);
58
+
59
+ fs.existsSync(db2Config.sqlitePath).should.equal(false);
60
+ fs.existsSync(db3Config.sqlitePath).should.equal(false);
61
+ });
62
+ });