gtfs 4.1.1 → 4.3.0
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/.github/workflows/nodejs.yml +3 -3
- package/CHANGELOG.md +19 -0
- package/README.md +64 -15
- package/lib/db.js +14 -15
- package/lib/file-utils.js +7 -9
- package/lib/gtfs/shapes.js +8 -0
- package/lib/gtfs/stops.js +7 -1
- package/lib/import.js +28 -8
- package/models/gtfs/agency.js +2 -5
- package/models/gtfs/areas.js +1 -0
- package/models/gtfs/attributions.js +6 -1
- package/models/gtfs/calendar-dates.js +3 -7
- package/models/gtfs/calendar.js +1 -0
- package/models/gtfs/fare-attributes.js +2 -0
- package/models/gtfs/fare-leg-rules.js +9 -0
- package/models/gtfs/fare-products.js +7 -0
- package/models/gtfs/fare-rules.js +5 -5
- package/models/gtfs/fare-transfer-rules.js +10 -0
- package/models/gtfs/feed-info.js +0 -5
- package/models/gtfs/frequencies.js +3 -6
- package/models/gtfs/levels.js +1 -0
- package/models/gtfs/pathways.js +3 -0
- package/models/gtfs/routes.js +3 -0
- package/models/gtfs/shapes.js +3 -6
- package/models/gtfs/stop-areas.js +2 -0
- package/models/gtfs/stop-times.js +4 -7
- package/models/gtfs/stops.js +3 -0
- package/models/gtfs/transfers.js +13 -9
- package/models/gtfs/translations.js +8 -5
- package/models/gtfs/trips.js +5 -0
- package/models/gtfs-plus/calendar-attributes.js +1 -0
- package/models/gtfs-plus/directions.js +3 -7
- package/models/gtfs-plus/route-attributes.js +1 -0
- package/models/gtfs-plus/stop-attributes.js +2 -6
- package/models/gtfs-realtime/service-alert-targets.js +0 -1
- package/models/gtfs-ride/board-alight.js +2 -0
- package/models/gtfs-ride/rider-trip.js +5 -0
- package/models/gtfs-ride/ridership.js +5 -0
- package/models/gtfs-ride/trip-capacity.js +2 -0
- package/models/non-standard/timetable-notes-references.js +5 -0
- package/models/non-standard/timetable-notes.js +1 -0
- package/models/non-standard/timetable-pages.js +1 -0
- package/models/non-standard/timetable-stop-order.js +3 -0
- package/models/non-standard/timetables.js +3 -0
- package/models/non-standard/trips-dated-vehicle-journey.js +1 -0
- package/models/ods/deadhead-times.js +4 -0
- package/models/ods/deadheads.js +8 -0
- package/models/ods/ops-locations.js +1 -0
- package/models/ods/run-events.js +4 -0
- package/package.json +7 -7
- package/test/mocha/advanced-query.js +7 -7
- package/test/mocha/export-gtfs.js +6 -1
- package/test/mocha/get-agencies.js +0 -2
- package/test/mocha/get-calendar-dates.js +0 -4
- package/test/mocha/import-gtfs.js +32 -5
- package/test/mocha/open-db.js +0 -1
|
@@ -8,12 +8,12 @@ jobs:
|
|
|
8
8
|
|
|
9
9
|
strategy:
|
|
10
10
|
matrix:
|
|
11
|
-
node-version: [
|
|
11
|
+
node-version: [16.x, 18.x, 20.x]
|
|
12
12
|
|
|
13
13
|
steps:
|
|
14
|
-
- uses: actions/checkout@
|
|
14
|
+
- uses: actions/checkout@v3
|
|
15
15
|
- name: Use Node.js ${{ matrix.node-version }}
|
|
16
|
-
uses: actions/setup-node@
|
|
16
|
+
uses: actions/setup-node@v3
|
|
17
17
|
with:
|
|
18
18
|
node-version: ${{ matrix.node-version }}
|
|
19
19
|
- name: npm install and test
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ 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.3.0] - 2023-05-04
|
|
9
|
+
|
|
10
|
+
### Updated
|
|
11
|
+
|
|
12
|
+
- Updated Readme to add closeDb documentation
|
|
13
|
+
- Use node-stream-zip instead of unzipper
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Support for prefixes when importing multiple GTFS files
|
|
18
|
+
|
|
19
|
+
## [4.2.0] - 2023-04-13
|
|
20
|
+
|
|
21
|
+
### Updated
|
|
22
|
+
|
|
23
|
+
- Add route_attributes to getShapesAsGeoJSON() function as geojson properties
|
|
24
|
+
- Add stop_attributes to getStopsAsGeoJSON() function as geojson properties
|
|
25
|
+
- Support for multi-column primary keys
|
|
26
|
+
|
|
8
27
|
## [4.1.1] - 2023-04-12
|
|
9
28
|
|
|
10
29
|
### Added
|
package/README.md
CHANGED
|
@@ -176,11 +176,21 @@ Copy `config-sample.json` to `config.json` and then add your projects configurat
|
|
|
176
176
|
|
|
177
177
|
For GTFS files that contain more than one agency, you only need to list each GTFS file once in the `agencies` array, not once per agency that it contains.
|
|
178
178
|
|
|
179
|
-
To find an agency's GTFS file, visit [transitfeeds.com](http://transitfeeds.com).
|
|
180
|
-
URL from the agency's website or you can use a URL generated from the transitfeeds.com
|
|
181
|
-
API along with your API token.
|
|
179
|
+
To find an agency's GTFS file, visit [transitfeeds.com](http://transitfeeds.com).
|
|
182
180
|
|
|
183
|
-
|
|
181
|
+
#### agencies options
|
|
182
|
+
|
|
183
|
+
| option | type | description |
|
|
184
|
+
| ----------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
185
|
+
| `url` | string | The URL to a zipped GTFS file. Required if `path` not present. |
|
|
186
|
+
| `path` | string | A path to a zipped GTFS file or a directory of unzipped .txt files. Required if `url` is not present. |
|
|
187
|
+
| `headers` | object | An object of HTTP headers in key:value format to use when fetching GTFS from the `url` specified. Optional. |
|
|
188
|
+
| `prefix` | string | A prefix to be added to every ID field maintain uniqueness when importing multiple GTFS from multiple agencies. Optional. |
|
|
189
|
+
| `exclude` | array | An array of GTFS file names (without `.txt`) to exclude when importing. Optional. |
|
|
190
|
+
| `realtimeUrls` | array | An array of GTFS-Realtime urls to import. Optional. |
|
|
191
|
+
| `realtimeHeaders` | array | An object of HTTP headers in key:value format to use when fetching GTFS-Realtime data from the `realtimeUrls` specified. Optional. |
|
|
192
|
+
|
|
193
|
+
- Specify a `url` to download GTFS:
|
|
184
194
|
|
|
185
195
|
```json
|
|
186
196
|
{
|
|
@@ -192,7 +202,7 @@ API along with your API token.
|
|
|
192
202
|
}
|
|
193
203
|
```
|
|
194
204
|
|
|
195
|
-
- Specify a download URL with custom headers:
|
|
205
|
+
- Specify a download URL with custom headers using the `headers` field:
|
|
196
206
|
|
|
197
207
|
```json
|
|
198
208
|
{
|
|
@@ -208,7 +218,7 @@ API along with your API token.
|
|
|
208
218
|
}
|
|
209
219
|
```
|
|
210
220
|
|
|
211
|
-
- Specify a path to a zipped GTFS file:
|
|
221
|
+
- Specify a `path` to a zipped GTFS file:
|
|
212
222
|
|
|
213
223
|
```json
|
|
214
224
|
{
|
|
@@ -220,7 +230,7 @@ API along with your API token.
|
|
|
220
230
|
}
|
|
221
231
|
```
|
|
222
232
|
|
|
223
|
-
- Specify a path to an unzipped GTFS file:
|
|
233
|
+
- Specify a `path` to an unzipped GTFS file:
|
|
224
234
|
|
|
225
235
|
```json
|
|
226
236
|
{
|
|
@@ -232,7 +242,7 @@ API along with your API token.
|
|
|
232
242
|
}
|
|
233
243
|
```
|
|
234
244
|
|
|
235
|
-
-
|
|
245
|
+
- If you don't want all GTFS files to be imported, you can specify an array of files to `exclude`. This can save a lot of time for larger GTFS.
|
|
236
246
|
|
|
237
247
|
```json
|
|
238
248
|
{
|
|
@@ -279,6 +289,23 @@ API along with your API token.
|
|
|
279
289
|
}
|
|
280
290
|
```
|
|
281
291
|
|
|
292
|
+
- When importing multiple agencies their IDs may overlap. Specify a `prefix` to be added to every ID field to maintain uniqueness.
|
|
293
|
+
|
|
294
|
+
```json
|
|
295
|
+
{
|
|
296
|
+
"agencies": [
|
|
297
|
+
{
|
|
298
|
+
"path": "/path/to/the/gtfs.zip",
|
|
299
|
+
"prefix": "A"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"path": "/path/to/the/othergtfs.zip",
|
|
303
|
+
"prefix": 10000
|
|
304
|
+
}
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
282
309
|
### csvOptions
|
|
283
310
|
|
|
284
311
|
{Object} Add options to be passed to [`csv-parse`](https://csv.js.org/parse/) with the key `csvOptions`. This is an optional parameter.
|
|
@@ -506,13 +533,29 @@ Most query methods accept three optional arguments: `query`, `fields`, `sortBy`
|
|
|
506
533
|
|
|
507
534
|
For more advanced queries, you can use `advancedQuery` or raw SQL queries using query method from [better-sqlite3](#raw-sqlite-query).
|
|
508
535
|
|
|
509
|
-
### Setup
|
|
536
|
+
### Database Setup
|
|
510
537
|
|
|
511
|
-
To use any of the query methods, first open the database before making any queries:
|
|
538
|
+
To use any of the query methods, first open the database using `openDb` before making any queries:
|
|
512
539
|
|
|
513
540
|
```js
|
|
514
541
|
import { openDb } from 'gtfs';
|
|
542
|
+
import { readFile } from 'fs/promises';
|
|
543
|
+
const config = JSON.parse(
|
|
544
|
+
await readFile(new URL('./config.json', import.meta.url))
|
|
545
|
+
);
|
|
546
|
+
const db = openDb(config);
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
If you no longer need a database (especially if using an in-memory database) you can use `closeDb`:
|
|
550
|
+
|
|
551
|
+
```js
|
|
552
|
+
import { closeDb, openDb } from 'gtfs';
|
|
515
553
|
const db = openDb(config);
|
|
554
|
+
|
|
555
|
+
// Do some stuff here
|
|
556
|
+
|
|
557
|
+
// Close database connection when done.
|
|
558
|
+
closeDb(db);
|
|
516
559
|
```
|
|
517
560
|
|
|
518
561
|
### Examples
|
|
@@ -520,7 +563,7 @@ const db = openDb(config);
|
|
|
520
563
|
For example, to get a list of all routes with just `route_id`, `route_short_name` and `route_color` sorted by `route_short_name`:
|
|
521
564
|
|
|
522
565
|
```js
|
|
523
|
-
import { openDb, getRoutes } from 'gtfs';
|
|
566
|
+
import { closeDb, openDb, getRoutes } from 'gtfs';
|
|
524
567
|
import { readFile } from 'fs/promises';
|
|
525
568
|
const config = JSON.parse(
|
|
526
569
|
await readFile(new URL('./config.json', import.meta.url))
|
|
@@ -533,12 +576,14 @@ const routes = getRoutes(
|
|
|
533
576
|
[['route_short_name', 'ASC']], // Sort by this field and direction
|
|
534
577
|
{ db: db } // Options for the query. Can specify which database to use if more than one are open
|
|
535
578
|
);
|
|
579
|
+
|
|
580
|
+
closeDb(db);
|
|
536
581
|
```
|
|
537
582
|
|
|
538
583
|
To get a list of all trip_ids for a specific route:
|
|
539
584
|
|
|
540
585
|
```js
|
|
541
|
-
import { openDb, getTrips } from 'gtfs';
|
|
586
|
+
import { closeDb, openDb, getTrips } from 'gtfs';
|
|
542
587
|
import { readFile } from 'fs/promises';
|
|
543
588
|
const config = JSON.parse(
|
|
544
589
|
await readFile(new URL('./config.json', import.meta.url))
|
|
@@ -551,12 +596,14 @@ const trips = getTrips(
|
|
|
551
596
|
},
|
|
552
597
|
['trip_id']
|
|
553
598
|
);
|
|
599
|
+
|
|
600
|
+
closeDb(db);
|
|
554
601
|
```
|
|
555
602
|
|
|
556
603
|
To get a few stops by specific stop_ids:
|
|
557
604
|
|
|
558
605
|
```js
|
|
559
|
-
import { openDb, getStops } from 'gtfs';
|
|
606
|
+
import { closeDb, openDb, getStops } from 'gtfs';
|
|
560
607
|
import { readFile } from 'fs/promises';
|
|
561
608
|
const config = JSON.parse(await readFile(new URL('./config.json', import.meta.url)));
|
|
562
609
|
|
|
@@ -570,6 +617,8 @@ const stops = getStops(
|
|
|
570
617
|
]
|
|
571
618
|
}
|
|
572
619
|
);
|
|
620
|
+
|
|
621
|
+
closeDb(db);
|
|
573
622
|
```
|
|
574
623
|
|
|
575
624
|
### Static GTFS Files
|
|
@@ -692,7 +741,7 @@ const stops = getStops({
|
|
|
692
741
|
|
|
693
742
|
#### getStopsAsGeoJSON(query, options)
|
|
694
743
|
|
|
695
|
-
Returns geoJSON object of stops that match query parameters. All valid queries for `getStops()` work for `getStopsAsGeoJSON()`.
|
|
744
|
+
Returns geoJSON object of stops that match query parameters. Stops will include all properties of each stop from stops.txt and stop_attributes.txt if present. All valid queries for `getStops()` work for `getStopsAsGeoJSON()`.
|
|
696
745
|
|
|
697
746
|
```js
|
|
698
747
|
import { getStopsAsGeoJSON } from 'gtfs';
|
|
@@ -804,7 +853,7 @@ const shapes = getShapes({
|
|
|
804
853
|
|
|
805
854
|
#### getShapesAsGeoJSON(query, options)
|
|
806
855
|
|
|
807
|
-
Returns a geoJSON object of shapes that match query parameters. All valid queries for `getShapes()` work for `getShapesAsGeoJSON()`.
|
|
856
|
+
Returns a geoJSON object of shapes that match query parameters. Shapes will include all properties of each route from routes.txt and route_attributes.txt if present. All valid queries for `getShapes()` work for `getShapesAsGeoJSON()`.
|
|
808
857
|
|
|
809
858
|
```js
|
|
810
859
|
import { getShapesAsGeoJSON } from 'gtfs';
|
package/lib/db.js
CHANGED
|
@@ -4,21 +4,26 @@ import untildify from 'untildify';
|
|
|
4
4
|
import { setDefaultConfig } from './utils.js';
|
|
5
5
|
const dbs = {};
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
if (dbs[sqlitePath]) {
|
|
9
|
-
return dbs[sqlitePath];
|
|
10
|
-
}
|
|
11
|
-
|
|
7
|
+
function setupDb(sqlitePath) {
|
|
12
8
|
const db = new Database(untildify(sqlitePath));
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
db.pragma('journal_mode = OFF');
|
|
10
|
+
db.pragma('synchronous = OFF');
|
|
11
|
+
db.pragma('temp_store = MEMORY');
|
|
15
12
|
dbs[sqlitePath] = db;
|
|
13
|
+
|
|
16
14
|
return db;
|
|
17
|
-
}
|
|
15
|
+
}
|
|
18
16
|
|
|
19
17
|
export function openDb(config) {
|
|
18
|
+
// If config is passed, use that to open or return db
|
|
20
19
|
if (config) {
|
|
21
|
-
|
|
20
|
+
const { sqlitePath } = setDefaultConfig(config);
|
|
21
|
+
|
|
22
|
+
if (dbs[sqlitePath]) {
|
|
23
|
+
return dbs[sqlitePath];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return setupDb(sqlitePath);
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
// If only one db connection already exists, use it
|
|
@@ -36,12 +41,6 @@ export function openDb(config) {
|
|
|
36
41
|
throw new Error('Unable to find database connection.');
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
export function setupDb(db) {
|
|
40
|
-
db.pragma('journal_mode = OFF');
|
|
41
|
-
db.pragma('synchronous = OFF');
|
|
42
|
-
db.pragma('temp_store = MEMORY');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
44
|
export function closeDb(db) {
|
|
46
45
|
if (Object.keys(dbs).length === 0) {
|
|
47
46
|
throw new Error(
|
package/lib/file-utils.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
3
|
import { mkdir, readFile, rm } from 'node:fs/promises';
|
|
4
4
|
import { omit, snakeCase } from 'lodash-es';
|
|
5
5
|
import sanitize from 'sanitize-filename';
|
|
6
6
|
import untildify from 'untildify';
|
|
7
|
-
import
|
|
7
|
+
import StreamZip from 'node-stream-zip';
|
|
8
8
|
|
|
9
9
|
/*
|
|
10
10
|
* Attempt to parse any config JSON file and read values from CLI.
|
|
@@ -91,13 +91,11 @@ export async function prepDirectory(exportPath) {
|
|
|
91
91
|
/*
|
|
92
92
|
* Unzip a zipfile into a specified directory
|
|
93
93
|
*/
|
|
94
|
-
export function unzip(zipfilePath, exportPath) {
|
|
95
|
-
/* eslint-disable new-cap */
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.promise();
|
|
100
|
-
/* eslint-enable new-cap */
|
|
94
|
+
export async function unzip(zipfilePath, exportPath) {
|
|
95
|
+
/* eslint-disable-next-line new-cap */
|
|
96
|
+
const zip = new StreamZip.async({ file: zipfilePath });
|
|
97
|
+
await zip.extract(null, exportPath);
|
|
98
|
+
await zip.close();
|
|
101
99
|
}
|
|
102
100
|
|
|
103
101
|
/*
|
package/lib/gtfs/shapes.js
CHANGED
|
@@ -14,6 +14,7 @@ import { shapesToGeoJSONFeatures } from '../geojson-utils.js';
|
|
|
14
14
|
import shapes from '../../models/gtfs/shapes.js';
|
|
15
15
|
import { getAgencies } from './agencies.js';
|
|
16
16
|
import { getRoutes } from './routes.js';
|
|
17
|
+
import { getRouteAttributes } from '../gtfs-plus/route-attributes.js';
|
|
17
18
|
|
|
18
19
|
function buildTripSubquery(query) {
|
|
19
20
|
const whereClause = formatWhereClauses(query);
|
|
@@ -92,6 +93,12 @@ export function getShapesAsGeoJSON(query = {}, options = {}) {
|
|
|
92
93
|
[],
|
|
93
94
|
options
|
|
94
95
|
);
|
|
96
|
+
const routeAttributes = getRouteAttributes(
|
|
97
|
+
{ route_id: route.route_id },
|
|
98
|
+
[],
|
|
99
|
+
[],
|
|
100
|
+
options
|
|
101
|
+
);
|
|
95
102
|
|
|
96
103
|
const agency = agencies.find(
|
|
97
104
|
(agency) => agency.agency_id === route.agency_id
|
|
@@ -101,6 +108,7 @@ export function getShapesAsGeoJSON(query = {}, options = {}) {
|
|
|
101
108
|
agency_name: agency ? agency.agency_name : undefined,
|
|
102
109
|
shape_id: query.shape_id,
|
|
103
110
|
...route,
|
|
111
|
+
...(routeAttributes?.[0] || []),
|
|
104
112
|
};
|
|
105
113
|
features.push(...shapesToGeoJSONFeatures(shapes, geojsonProperties));
|
|
106
114
|
}
|
package/lib/gtfs/stops.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { stopsToGeoJSON } from '../geojson-utils.js';
|
|
13
13
|
import stops from '../../models/gtfs/stops.js';
|
|
14
14
|
import { getAgencies } from './agencies.js';
|
|
15
|
+
import { getStopAttributes } from '../gtfs-plus/stop-attributes.js';
|
|
15
16
|
|
|
16
17
|
function buildTripSubquery(query) {
|
|
17
18
|
const whereClause = formatWhereClauses(query);
|
|
@@ -89,12 +90,17 @@ export function getStopsAsGeoJSON(query = {}, options = {}) {
|
|
|
89
90
|
.prepare(`SELECT * FROM routes WHERE route_id IN (${routeSubquery})`)
|
|
90
91
|
.all(stop.stop_id);
|
|
91
92
|
|
|
93
|
+
const stopAttributes = getStopAttributes({ stop_id: stop.stop_id });
|
|
94
|
+
|
|
92
95
|
stop.routes = orderBy(routes, (route) =>
|
|
93
96
|
Number.parseInt(route.route_short_name, 10)
|
|
94
97
|
);
|
|
95
98
|
stop.agency_name = agencies[0].agency_name;
|
|
96
99
|
|
|
97
|
-
return
|
|
100
|
+
return {
|
|
101
|
+
...stop,
|
|
102
|
+
...(stopAttributes?.[0] || []),
|
|
103
|
+
};
|
|
98
104
|
});
|
|
99
105
|
|
|
100
106
|
// Exclude stops not part of any route
|
package/lib/import.js
CHANGED
|
@@ -329,13 +329,23 @@ const createTables = (db) => {
|
|
|
329
329
|
check = `CHECK( ${column.name} <= ${column.max} )`;
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
-
const primary = column.primary ? 'PRIMARY KEY' : '';
|
|
333
332
|
const required = column.required ? 'NOT NULL' : '';
|
|
334
333
|
const columnDefault = column.default ? 'DEFAULT ' + column.default : '';
|
|
335
334
|
const columnCollation = column.nocase ? 'COLLATE NOCASE' : '';
|
|
336
|
-
return `${column.name} ${column.type} ${check} ${
|
|
335
|
+
return `${column.name} ${column.type} ${check} ${required} ${columnDefault} ${columnCollation}`;
|
|
337
336
|
});
|
|
338
337
|
|
|
338
|
+
// Find Primary Key fields
|
|
339
|
+
const primaryColumns = model.schema.filter((column) => column.primary);
|
|
340
|
+
|
|
341
|
+
if (primaryColumns.length > 0) {
|
|
342
|
+
columns.push(
|
|
343
|
+
`PRIMARY KEY (${primaryColumns
|
|
344
|
+
.map((column) => column.name)
|
|
345
|
+
.join(', ')})`
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
339
349
|
db.prepare(`DROP TABLE IF EXISTS ${model.filenameBase};`).run();
|
|
340
350
|
|
|
341
351
|
db.prepare(
|
|
@@ -436,23 +446,32 @@ const importLines = (task, lines, model, totalLineCount) => {
|
|
|
436
446
|
}
|
|
437
447
|
|
|
438
448
|
const linesToImportCount = lines.length;
|
|
439
|
-
const
|
|
440
|
-
.filter((column) => column.name !== 'id')
|
|
441
|
-
.map((column) => column.name);
|
|
449
|
+
const columns = model.schema.filter((column) => column.name !== 'id');
|
|
442
450
|
const placeholders = [];
|
|
443
451
|
const values = [];
|
|
444
452
|
|
|
445
453
|
while (lines.length > 0) {
|
|
446
454
|
const line = lines.pop();
|
|
447
|
-
placeholders.push(`(${
|
|
448
|
-
values.push(
|
|
455
|
+
placeholders.push(`(${columns.map(() => '?').join(', ')})`);
|
|
456
|
+
values.push(
|
|
457
|
+
...columns.map((column) => {
|
|
458
|
+
if (task.prefix !== undefined && column.prefix === true) {
|
|
459
|
+
// Add prefixes to field values if needed
|
|
460
|
+
return `${task.prefix}${line[column.name]}`;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return line[column.name];
|
|
464
|
+
})
|
|
465
|
+
);
|
|
449
466
|
}
|
|
450
467
|
|
|
451
468
|
try {
|
|
452
469
|
db.prepare(
|
|
453
470
|
`INSERT ${task.ignoreDuplicates ? 'OR IGNORE' : ''} INTO ${
|
|
454
471
|
model.filenameBase
|
|
455
|
-
} (${
|
|
472
|
+
} (${columns
|
|
473
|
+
.map((column) => column.name)
|
|
474
|
+
.join(', ')}) VALUES ${placeholders.join(',')}`
|
|
456
475
|
).run(...values);
|
|
457
476
|
} catch (error) {
|
|
458
477
|
task.warn(
|
|
@@ -578,6 +597,7 @@ export async function importGtfs(initialConfig) {
|
|
|
578
597
|
csvOptions: config.csvOptions || {},
|
|
579
598
|
ignoreDuplicates: config.ignoreDuplicates,
|
|
580
599
|
sqlitePath: config.sqlitePath,
|
|
600
|
+
prefix: agency.prefix,
|
|
581
601
|
log,
|
|
582
602
|
warn: logWarning,
|
|
583
603
|
error: logError,
|
package/models/gtfs/agency.js
CHANGED
package/models/gtfs/areas.js
CHANGED
|
@@ -5,18 +5,23 @@ const model = {
|
|
|
5
5
|
name: 'attribution_id',
|
|
6
6
|
type: 'varchar(255)',
|
|
7
7
|
primary: true,
|
|
8
|
+
required: true,
|
|
9
|
+
prefix: true,
|
|
8
10
|
},
|
|
9
11
|
{
|
|
10
12
|
name: 'agency_id',
|
|
11
|
-
type: 'varchar(255)',
|
|
13
|
+
type: 'varchar(255)',
|
|
14
|
+
prefix: true,
|
|
12
15
|
},
|
|
13
16
|
{
|
|
14
17
|
name: 'route_id',
|
|
15
18
|
type: 'varchar(255)',
|
|
19
|
+
prefix: true,
|
|
16
20
|
},
|
|
17
21
|
{
|
|
18
22
|
name: 'trip_id',
|
|
19
23
|
type: 'varchar(255)',
|
|
24
|
+
prefix: true,
|
|
20
25
|
},
|
|
21
26
|
{
|
|
22
27
|
name: 'organization_name',
|
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
const model = {
|
|
2
2
|
filenameBase: 'calendar_dates',
|
|
3
3
|
schema: [
|
|
4
|
-
{
|
|
5
|
-
name: 'id',
|
|
6
|
-
type: 'integer',
|
|
7
|
-
primary: true,
|
|
8
|
-
},
|
|
9
4
|
{
|
|
10
5
|
name: 'service_id',
|
|
11
6
|
type: 'varchar(255)',
|
|
12
7
|
required: true,
|
|
13
|
-
|
|
8
|
+
primary: true,
|
|
9
|
+
prefix: true,
|
|
14
10
|
},
|
|
15
11
|
{
|
|
16
12
|
name: 'date',
|
|
17
13
|
type: 'integer',
|
|
18
14
|
required: true,
|
|
19
|
-
|
|
15
|
+
primary: true,
|
|
20
16
|
},
|
|
21
17
|
{
|
|
22
18
|
name: 'exception_type',
|
package/models/gtfs/calendar.js
CHANGED
|
@@ -6,6 +6,7 @@ const model = {
|
|
|
6
6
|
type: 'varchar(255)',
|
|
7
7
|
required: true,
|
|
8
8
|
primary: true,
|
|
9
|
+
prefix: true,
|
|
9
10
|
},
|
|
10
11
|
{
|
|
11
12
|
name: 'price',
|
|
@@ -33,6 +34,7 @@ const model = {
|
|
|
33
34
|
{
|
|
34
35
|
name: 'agency_id',
|
|
35
36
|
type: 'varchar(255)',
|
|
37
|
+
prefix: true,
|
|
36
38
|
},
|
|
37
39
|
{
|
|
38
40
|
name: 'transfer_duration',
|
|
@@ -4,23 +4,32 @@ const model = {
|
|
|
4
4
|
{
|
|
5
5
|
name: 'leg_group_id',
|
|
6
6
|
type: 'varchar(255)',
|
|
7
|
+
prefix: true,
|
|
7
8
|
},
|
|
8
9
|
{
|
|
9
10
|
name: 'network_id',
|
|
10
11
|
type: 'varchar(255)',
|
|
12
|
+
primary: true,
|
|
13
|
+
prefix: true,
|
|
11
14
|
},
|
|
12
15
|
{
|
|
13
16
|
name: 'from_area_id',
|
|
14
17
|
type: 'varchar(255)',
|
|
18
|
+
primary: true,
|
|
19
|
+
prefix: true,
|
|
15
20
|
},
|
|
16
21
|
{
|
|
17
22
|
name: 'to_area_id',
|
|
18
23
|
type: 'varchar(255)',
|
|
24
|
+
primary: true,
|
|
25
|
+
prefix: true,
|
|
19
26
|
},
|
|
20
27
|
{
|
|
21
28
|
name: 'fare_product_id',
|
|
22
29
|
type: 'varchar(255)',
|
|
23
30
|
required: true,
|
|
31
|
+
primary: true,
|
|
32
|
+
prefix: true,
|
|
24
33
|
},
|
|
25
34
|
],
|
|
26
35
|
};
|
|
@@ -6,11 +6,18 @@ const model = {
|
|
|
6
6
|
type: 'varchar(255)',
|
|
7
7
|
required: true,
|
|
8
8
|
primary: true,
|
|
9
|
+
prefix: true,
|
|
9
10
|
},
|
|
10
11
|
{
|
|
11
12
|
name: 'fare_product_name',
|
|
12
13
|
type: 'varchar(255)',
|
|
13
14
|
},
|
|
15
|
+
{
|
|
16
|
+
name: 'fare_media_id',
|
|
17
|
+
type: 'varchar(255)',
|
|
18
|
+
primary: true,
|
|
19
|
+
prefix: true,
|
|
20
|
+
},
|
|
14
21
|
{
|
|
15
22
|
name: 'amount',
|
|
16
23
|
type: 'real',
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
const model = {
|
|
2
2
|
filenameBase: 'fare_rules',
|
|
3
3
|
schema: [
|
|
4
|
-
{
|
|
5
|
-
name: 'id',
|
|
6
|
-
type: 'integer',
|
|
7
|
-
primary: true,
|
|
8
|
-
},
|
|
9
4
|
{
|
|
10
5
|
name: 'fare_id',
|
|
11
6
|
type: 'varchar(255)',
|
|
12
7
|
required: true,
|
|
8
|
+
prefix: true,
|
|
13
9
|
},
|
|
14
10
|
{
|
|
15
11
|
name: 'route_id',
|
|
16
12
|
type: 'varchar(255)',
|
|
13
|
+
prefix: true,
|
|
17
14
|
},
|
|
18
15
|
{
|
|
19
16
|
name: 'origin_id',
|
|
20
17
|
type: 'varchar(255)',
|
|
18
|
+
prefix: true,
|
|
21
19
|
},
|
|
22
20
|
{
|
|
23
21
|
name: 'destination_id',
|
|
24
22
|
type: 'varchar(255)',
|
|
23
|
+
prefix: true,
|
|
25
24
|
},
|
|
26
25
|
{
|
|
27
26
|
name: 'contains_id',
|
|
28
27
|
type: 'varchar(255)',
|
|
28
|
+
prefix: true,
|
|
29
29
|
},
|
|
30
30
|
],
|
|
31
31
|
};
|
|
@@ -4,24 +4,31 @@ const model = {
|
|
|
4
4
|
{
|
|
5
5
|
name: 'from_leg_group_id',
|
|
6
6
|
type: 'varchar(255)',
|
|
7
|
+
primary: true,
|
|
8
|
+
prefix: true,
|
|
7
9
|
},
|
|
8
10
|
{
|
|
9
11
|
name: 'to_leg_group_id',
|
|
10
12
|
type: 'varchar(255)',
|
|
13
|
+
primary: true,
|
|
14
|
+
prefix: true,
|
|
11
15
|
},
|
|
12
16
|
{
|
|
13
17
|
name: 'transfer_count',
|
|
14
18
|
type: 'integer',
|
|
15
19
|
min: -1,
|
|
20
|
+
primary: true,
|
|
16
21
|
},
|
|
17
22
|
{
|
|
18
23
|
name: 'transfer_id',
|
|
19
24
|
type: 'varchar(255)',
|
|
25
|
+
prefix: true,
|
|
20
26
|
},
|
|
21
27
|
{
|
|
22
28
|
name: 'duration_limit',
|
|
23
29
|
type: 'integer',
|
|
24
30
|
min: 0,
|
|
31
|
+
primary: true,
|
|
25
32
|
},
|
|
26
33
|
{
|
|
27
34
|
name: 'duration_limit_type',
|
|
@@ -34,10 +41,13 @@ const model = {
|
|
|
34
41
|
type: 'integer',
|
|
35
42
|
min: 0,
|
|
36
43
|
max: 2,
|
|
44
|
+
required: true,
|
|
37
45
|
},
|
|
38
46
|
{
|
|
39
47
|
name: 'fare_product_id',
|
|
40
48
|
type: 'varchar(255)',
|
|
49
|
+
primary: true,
|
|
50
|
+
prefix: true,
|
|
41
51
|
},
|
|
42
52
|
],
|
|
43
53
|
};
|