gtfs 4.1.0 → 4.2.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.
Files changed (37) hide show
  1. package/@types/index.d.ts +22 -0
  2. package/CHANGELOG.md +18 -0
  3. package/README.md +77 -41
  4. package/lib/gtfs/shapes.js +8 -0
  5. package/lib/gtfs/stops.js +7 -1
  6. package/lib/gtfs-plus/calendar-attributes.js +32 -0
  7. package/lib/{non-standard → gtfs-plus}/directions.js +1 -1
  8. package/lib/gtfs-plus/route-attributes.js +32 -0
  9. package/lib/{non-standard → gtfs-plus}/stop-attributes.js +1 -1
  10. package/lib/gtfs.js +12 -2
  11. package/lib/import.js +12 -2
  12. package/models/gtfs/agency.js +1 -5
  13. package/models/gtfs/attributions.js +1 -0
  14. package/models/gtfs/calendar-dates.js +2 -7
  15. package/models/gtfs/fare-leg-rules.js +4 -0
  16. package/models/gtfs/fare-products.js +5 -0
  17. package/models/gtfs/fare-rules.js +0 -5
  18. package/models/gtfs/fare-transfer-rules.js +6 -0
  19. package/models/gtfs/feed-info.js +0 -5
  20. package/models/gtfs/frequencies.js +2 -6
  21. package/models/gtfs/shapes.js +2 -6
  22. package/models/gtfs/stop-times.js +2 -7
  23. package/models/gtfs/transfers.js +7 -9
  24. package/models/gtfs/translations.js +6 -5
  25. package/models/gtfs-plus/calendar-attributes.js +20 -0
  26. package/models/{non-standard → gtfs-plus}/directions.js +3 -7
  27. package/models/gtfs-plus/route-attributes.js +32 -0
  28. package/models/{non-standard → gtfs-plus}/stop-attributes.js +14 -5
  29. package/models/gtfs-realtime/service-alert-targets.js +0 -1
  30. package/models/models.js +9 -4
  31. package/package.json +9 -9
  32. package/test/mocha/advanced-query.js +7 -7
  33. package/test/mocha/get-agencies.js +0 -2
  34. package/test/mocha/get-calendar-attributes.js +33 -0
  35. package/test/mocha/get-calendar-dates.js +0 -4
  36. package/test/mocha/get-route-attributes.js +33 -0
  37. package/test/mocha/open-db.js +0 -1
package/@types/index.d.ts CHANGED
@@ -383,6 +383,17 @@ export function getStopAreas(
383
383
  options?: QueryOptions
384
384
  ): SqlResults;
385
385
 
386
+ /**
387
+ * Returns an array of calendar_attributes that match query parameters.
388
+ * This is for the non-standard `calendar_attributes.txt` file.
389
+ */
390
+ export function getCalendarAttributes(
391
+ query?: SqlWhere,
392
+ fields?: SqlSelect,
393
+ sortBy?: SqlOrderBy,
394
+ options?: QueryOptions
395
+ ): SqlResults;
396
+
386
397
  /**
387
398
  * Returns an array of directions that match query parameters.
388
399
  * This is for the non-standard `directions.txt` file.
@@ -394,6 +405,17 @@ export function getDirections(
394
405
  options?: QueryOptions
395
406
  ): SqlResults;
396
407
 
408
+ /**
409
+ * Returns an array of route_attributes that match query parameters.
410
+ * This is for the non-standard `route_attributes.txt` file.
411
+ */
412
+ export function getRouteAttributes(
413
+ query?: SqlWhere,
414
+ fields?: SqlSelect,
415
+ sortBy?: SqlOrderBy,
416
+ options?: QueryOptions
417
+ ): SqlResults;
418
+
397
419
  /**
398
420
  * Returns an array of stop_attributes that match query parameters.
399
421
  * This is for the non-standard `stop_attributes.txt` file.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,24 @@ 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.2.0] - 2023-04-13
9
+
10
+ ### Updated
11
+
12
+ - Add route_attributes to getShapesAsGeoJSON() function as geojson properties
13
+ - Add stop_attributes to getStopsAsGeoJSON() function as geojson properties
14
+ - Support for multi-column primary keys
15
+
16
+ ## [4.1.1] - 2023-04-12
17
+
18
+ ### Added
19
+
20
+ - Support for GTFS+ Files
21
+
22
+ ### Updated
23
+
24
+ - Dependency updates
25
+
8
26
  ## [4.1.0] - 2023-02-25
9
27
 
10
28
  ### Added
package/README.md CHANGED
@@ -692,7 +692,7 @@ const stops = getStops({
692
692
 
693
693
  #### getStopsAsGeoJSON(query, options)
694
694
 
695
- Returns geoJSON object of stops that match query parameters. All valid queries for `getStops()` work for `getStopsAsGeoJSON()`.
695
+ 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
696
 
697
697
  ```js
698
698
  import { getStopsAsGeoJSON } from 'gtfs';
@@ -804,7 +804,7 @@ const shapes = getShapes({
804
804
 
805
805
  #### getShapesAsGeoJSON(query, options)
806
806
 
807
- Returns a geoJSON object of shapes that match query parameters. All valid queries for `getShapes()` work for `getShapesAsGeoJSON()`.
807
+ 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
808
 
809
809
  ```js
810
810
  import { getShapesAsGeoJSON } from 'gtfs';
@@ -1162,8 +1162,82 @@ import { getVehiclePositions } from 'gtfs';
1162
1162
  const vehiclePositions = getVehiclePositions();
1163
1163
  ```
1164
1164
 
1165
+ ### GTFS+ Files
1166
+
1167
+ #### getCalendarAttributes(query, fields, sortBy, options)
1168
+
1169
+ Returns an array of calendar_attributes that match query parameters.
1170
+
1171
+ ```js
1172
+ import { getCalendarAttributes } from 'gtfs';
1173
+
1174
+ // Get all calendar attributes
1175
+ const calendarAttributes = getCalendarAttributes();
1176
+
1177
+ // Get calendar attributes for specific service
1178
+ const calendarAttributes = getCalendarAttributes({
1179
+ service_id: '1234',
1180
+ });
1181
+ ```
1182
+
1183
+ #### getDirections(query, fields, sortBy, options)
1184
+
1185
+ Returns an array of directions that match query parameters.
1186
+
1187
+ ```js
1188
+ import { getDirections } from 'gtfs';
1189
+
1190
+ // Get all directions
1191
+ const directions = getDirections();
1192
+
1193
+ // Get directions for a specific route
1194
+ const directions = getDirections({
1195
+ route_id: '1234',
1196
+ });
1197
+
1198
+ // Get directions for a specific route and direction
1199
+ const directions = getDirections({
1200
+ route_id: '1234',
1201
+ direction_id: 1,
1202
+ });
1203
+ ```
1204
+
1205
+ #### getRouteAttributes(query, fields, sortBy, options)
1206
+
1207
+ Returns an array of route_attributes that match query parameters.
1208
+
1209
+ ```js
1210
+ import { getRouteAttributes } from 'gtfs';
1211
+
1212
+ // Get all route attributes
1213
+ const routeAttributes = getRouteAttributes();
1214
+
1215
+ // Get route attributes for specific route
1216
+ const routeAttributes = getRouteAttributes({
1217
+ route_id: '1234',
1218
+ });
1219
+ ```
1220
+
1221
+ #### getStopAttributes(query, fields, sortBy, options)
1222
+
1223
+ Returns an array of stop_attributes that match query parameters.
1224
+
1225
+ ```js
1226
+ import { getStopAttributes } from 'gtfs';
1227
+
1228
+ // Get all stop attributes
1229
+ const stopAttributes = getStopAttributes();
1230
+
1231
+ // Get stop attributes for specific stop
1232
+ const stopAttributes = getStopAttributes({
1233
+ stop_id: '1234',
1234
+ });
1235
+ ```
1236
+
1165
1237
  ### GTFS-Ride Files
1166
1238
 
1239
+ See full [documentation of GTFS Ride](https://gtfsride.org).
1240
+
1167
1241
  #### getBoardAlights(query, fields, sortBy, options)
1168
1242
 
1169
1243
  Returns an array of board_alight that match query parameters. [Details on board_alight.txt](http://gtfsride.org/specification#board_alighttxt)
@@ -1316,45 +1390,7 @@ const runEvents = runEvents({
1316
1390
  });
1317
1391
  ```
1318
1392
 
1319
- ### Non-standard GTFS Files
1320
-
1321
- #### getDirections(query, fields, sortBy, options)
1322
-
1323
- Returns an array of directions that match query parameters. This is for the non-standard `directions.txt` file. [Details on directions.txt](https://trilliumtransit.com/gtfs/reference/#directions)
1324
-
1325
- ```js
1326
- import { getDirections } from 'gtfs';
1327
-
1328
- // Get all directions
1329
- const directions = getDirections();
1330
-
1331
- // Get directions for a specific route
1332
- const directions = getDirections({
1333
- route_id: '1234',
1334
- });
1335
-
1336
- // Get directions for a specific route and direction
1337
- const directions = getDirections({
1338
- route_id: '1234',
1339
- direction_id: 1,
1340
- });
1341
- ```
1342
-
1343
- #### getStopAttributes(query, fields, sortBy, options)
1344
-
1345
- Returns an array of stop_attributes that match query parameters. This is for the non-standard `stop_attributes.txt` file. [Details on stop_attributes.txt](https://trilliumtransit.com/gtfs/reference/#stop_attributes)
1346
-
1347
- ```js
1348
- import { getStopAttributes } from 'gtfs';
1349
-
1350
- // Get all stop attributes
1351
- const stopAttributes = getStopAttributes();
1352
-
1353
- // Get stop attributes for specific stop
1354
- const stopAttributes = getStopAttributes({
1355
- stop_id: '1234',
1356
- });
1357
- ```
1393
+ ### Other Non-standard GTFS Files
1358
1394
 
1359
1395
  #### getTripsDatedVehicleJourneys(query, fields, sortBy, options)
1360
1396
 
@@ -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 stop;
100
+ return {
101
+ ...stop,
102
+ ...(stopAttributes?.[0] || []),
103
+ };
98
104
  });
99
105
 
100
106
  // Exclude stops not part of any route
@@ -0,0 +1,32 @@
1
+ import sqlString from 'sqlstring-sqlite';
2
+
3
+ import { openDb } from '../db.js';
4
+
5
+ import {
6
+ formatOrderByClause,
7
+ formatSelectClause,
8
+ formatWhereClauses,
9
+ } from '../utils.js';
10
+ import calendarAttributes from '../../models/gtfs-plus/calendar-attributes.js';
11
+
12
+ /*
13
+ * Returns an array of all calendar_attributes that match the query parameters.
14
+ */
15
+ export function getCalendarAttributes(
16
+ query = {},
17
+ fields = [],
18
+ orderBy = [],
19
+ options = {}
20
+ ) {
21
+ const db = options.db ?? openDb();
22
+ const tableName = sqlString.escapeId(calendarAttributes.filenameBase);
23
+ const selectClause = formatSelectClause(fields);
24
+ const whereClause = formatWhereClauses(query);
25
+ const orderByClause = formatOrderByClause(orderBy);
26
+
27
+ return db
28
+ .prepare(
29
+ `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
30
+ )
31
+ .all();
32
+ }
@@ -7,7 +7,7 @@ import {
7
7
  formatSelectClause,
8
8
  formatWhereClauses,
9
9
  } from '../utils.js';
10
- import directions from '../../models/non-standard/directions.js';
10
+ import directions from '../../models/gtfs-plus/directions.js';
11
11
 
12
12
  /*
13
13
  * Returns an array of all directions that match the query parameters.
@@ -0,0 +1,32 @@
1
+ import sqlString from 'sqlstring-sqlite';
2
+
3
+ import { openDb } from '../db.js';
4
+
5
+ import {
6
+ formatOrderByClause,
7
+ formatSelectClause,
8
+ formatWhereClauses,
9
+ } from '../utils.js';
10
+ import routeAttributes from '../../models/gtfs-plus/route-attributes.js';
11
+
12
+ /*
13
+ * Returns an array of all route_attributes that match the query parameters.
14
+ */
15
+ export function getRouteAttributes(
16
+ query = {},
17
+ fields = [],
18
+ orderBy = [],
19
+ options = {}
20
+ ) {
21
+ const db = options.db ?? openDb();
22
+ const tableName = sqlString.escapeId(routeAttributes.filenameBase);
23
+ const selectClause = formatSelectClause(fields);
24
+ const whereClause = formatWhereClauses(query);
25
+ const orderByClause = formatOrderByClause(orderBy);
26
+
27
+ return db
28
+ .prepare(
29
+ `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
30
+ )
31
+ .all();
32
+ }
@@ -7,7 +7,7 @@ import {
7
7
  formatSelectClause,
8
8
  formatWhereClauses,
9
9
  } from '../utils.js';
10
- import stopAttributes from '../../models/non-standard/stop-attributes.js';
10
+ import stopAttributes from '../../models/gtfs-plus/stop-attributes.js';
11
11
 
12
12
  /*
13
13
  * Returns an array of all stop attributes that match the query parameters.
package/lib/gtfs.js CHANGED
@@ -28,9 +28,13 @@ import { getTransfers } from './gtfs/transfers.js';
28
28
  import { getTranslations } from './gtfs/translations.js';
29
29
  import { getTrips } from './gtfs/trips.js';
30
30
 
31
+ // GTFS Plus Filenames
32
+ import { getCalendarAttributes } from './gtfs-plus/calendar-attributes.js';
33
+ import { getDirections } from './gtfs-plus/directions.js';
34
+ import { getRouteAttributes } from './gtfs-plus/route-attributes.js';
35
+ import { getStopAttributes } from './gtfs-plus/stop-attributes.js';
36
+
31
37
  // Non-standard GTFS Filenames
32
- import { getDirections } from './non-standard/directions.js';
33
- import { getStopAttributes } from './non-standard/stop-attributes.js';
34
38
  import { getTimetables } from './non-standard/timetables.js';
35
39
  import { getTimetableStopOrders } from './non-standard/timetable-stop-order.js';
36
40
  import { getTimetablePages } from './non-standard/timetable-pages.js';
@@ -139,9 +143,15 @@ export { _getTrips as getTrips };
139
143
  const _getTranslations = getTranslations;
140
144
  export { _getTranslations as getTranslations };
141
145
 
146
+ const _getCalendarAttributes = getCalendarAttributes;
147
+ export { _getCalendarAttributes as getCalendarAttributes };
148
+
142
149
  const _getDirections = getDirections;
143
150
  export { _getDirections as getDirections };
144
151
 
152
+ const _getRouteAttributes = getRouteAttributes;
153
+ export { _getRouteAttributes as getRouteAttributes };
154
+
145
155
  const _getStopAttributes = getStopAttributes;
146
156
  export { _getStopAttributes as getStopAttributes };
147
157
 
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} ${primary} ${required} ${columnDefault} ${columnCollation}`;
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(
@@ -1,14 +1,10 @@
1
1
  const model = {
2
2
  filenameBase: 'agency',
3
3
  schema: [
4
- {
5
- name: 'id',
6
- type: 'integer',
7
- primary: true,
8
- },
9
4
  {
10
5
  name: 'agency_id',
11
6
  type: 'varchar(255)',
7
+ primary: true,
12
8
  },
13
9
  {
14
10
  name: 'agency_name',
@@ -5,6 +5,7 @@ const model = {
5
5
  name: 'attribution_id',
6
6
  type: 'varchar(255)',
7
7
  primary: true,
8
+ required: true,
8
9
  },
9
10
  {
10
11
  name: 'agency_id',
@@ -1,22 +1,17 @@
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
- index: true,
8
+ primary: true,
14
9
  },
15
10
  {
16
11
  name: 'date',
17
12
  type: 'integer',
18
13
  required: true,
19
- index: true,
14
+ primary: true,
20
15
  },
21
16
  {
22
17
  name: 'exception_type',
@@ -8,19 +8,23 @@ const model = {
8
8
  {
9
9
  name: 'network_id',
10
10
  type: 'varchar(255)',
11
+ primary: true,
11
12
  },
12
13
  {
13
14
  name: 'from_area_id',
14
15
  type: 'varchar(255)',
16
+ primary: true,
15
17
  },
16
18
  {
17
19
  name: 'to_area_id',
18
20
  type: 'varchar(255)',
21
+ primary: true,
19
22
  },
20
23
  {
21
24
  name: 'fare_product_id',
22
25
  type: 'varchar(255)',
23
26
  required: true,
27
+ primary: true,
24
28
  },
25
29
  ],
26
30
  };
@@ -11,6 +11,11 @@ const model = {
11
11
  name: 'fare_product_name',
12
12
  type: 'varchar(255)',
13
13
  },
14
+ {
15
+ name: 'fare_media_id',
16
+ type: 'varchar(255)',
17
+ primary: true,
18
+ },
14
19
  {
15
20
  name: 'amount',
16
21
  type: 'real',
@@ -1,11 +1,6 @@
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)',
@@ -4,15 +4,18 @@ const model = {
4
4
  {
5
5
  name: 'from_leg_group_id',
6
6
  type: 'varchar(255)',
7
+ primary: true,
7
8
  },
8
9
  {
9
10
  name: 'to_leg_group_id',
10
11
  type: 'varchar(255)',
12
+ primary: true,
11
13
  },
12
14
  {
13
15
  name: 'transfer_count',
14
16
  type: 'integer',
15
17
  min: -1,
18
+ primary: true,
16
19
  },
17
20
  {
18
21
  name: 'transfer_id',
@@ -22,6 +25,7 @@ const model = {
22
25
  name: 'duration_limit',
23
26
  type: 'integer',
24
27
  min: 0,
28
+ primary: true,
25
29
  },
26
30
  {
27
31
  name: 'duration_limit_type',
@@ -34,10 +38,12 @@ const model = {
34
38
  type: 'integer',
35
39
  min: 0,
36
40
  max: 2,
41
+ required: true,
37
42
  },
38
43
  {
39
44
  name: 'fare_product_id',
40
45
  type: 'varchar(255)',
46
+ primary: true,
41
47
  },
42
48
  ],
43
49
  };
@@ -1,11 +1,6 @@
1
1
  const model = {
2
2
  filenameBase: 'feed_info',
3
3
  schema: [
4
- {
5
- name: 'id',
6
- type: 'integer',
7
- primary: true,
8
- },
9
4
  {
10
5
  name: 'feed_publisher_name',
11
6
  type: 'varchar(255)',
@@ -1,21 +1,17 @@
1
1
  const model = {
2
2
  filenameBase: 'frequencies',
3
3
  schema: [
4
- {
5
- name: 'id',
6
- type: 'integer',
7
- primary: true,
8
- },
9
4
  {
10
5
  name: 'trip_id',
11
6
  type: 'varchar(255)',
12
7
  required: true,
13
- index: true,
8
+ primary: true,
14
9
  },
15
10
  {
16
11
  name: 'start_time',
17
12
  type: 'varchar(255)',
18
13
  required: true,
14
+ primary: true,
19
15
  },
20
16
  {
21
17
  name: 'start_timestamp',
@@ -1,16 +1,11 @@
1
1
  const model = {
2
2
  filenameBase: 'shapes',
3
3
  schema: [
4
- {
5
- name: 'id',
6
- type: 'integer',
7
- primary: true,
8
- },
9
4
  {
10
5
  name: 'shape_id',
11
6
  type: 'varchar(255)',
12
7
  required: true,
13
- index: true,
8
+ primary: true,
14
9
  },
15
10
  {
16
11
  name: 'shape_pt_lat',
@@ -30,6 +25,7 @@ const model = {
30
25
  name: 'shape_pt_sequence',
31
26
  type: 'integer',
32
27
  required: true,
28
+ primary: true,
33
29
  min: 0,
34
30
  },
35
31
  {
@@ -1,16 +1,11 @@
1
1
  const model = {
2
2
  filenameBase: 'stop_times',
3
3
  schema: [
4
- {
5
- name: 'id',
6
- type: 'integer',
7
- primary: true,
8
- },
9
4
  {
10
5
  name: 'trip_id',
11
6
  type: 'varchar(255)',
12
7
  required: true,
13
- index: true,
8
+ primary: true,
14
9
  },
15
10
  {
16
11
  name: 'arrival_time',
@@ -39,8 +34,8 @@ const model = {
39
34
  name: 'stop_sequence',
40
35
  type: 'integer',
41
36
  required: true,
37
+ primary: true,
42
38
  min: 0,
43
- index: true,
44
39
  },
45
40
  {
46
41
  name: 'stop_headsign',
@@ -1,44 +1,42 @@
1
1
  const model = {
2
2
  filenameBase: 'transfers',
3
3
  schema: [
4
- {
5
- name: 'id',
6
- type: 'integer',
7
- primary: true,
8
- },
9
4
  {
10
5
  name: 'from_stop_id',
11
6
  type: 'varchar(255)',
12
- index: true,
7
+ primary: true,
13
8
  },
14
9
  {
15
10
  name: 'to_stop_id',
16
11
  type: 'varchar(255)',
17
- index: true,
12
+ primary: true,
18
13
  },
19
14
  {
20
15
  name: 'from_route_id',
21
16
  type: 'varchar(255)',
17
+ primary: true,
22
18
  },
23
19
  {
24
20
  name: 'to_route_id',
25
21
  type: 'varchar(255)',
22
+ primary: true,
26
23
  },
27
24
  {
28
25
  name: 'from_trip_id',
29
26
  type: 'varchar(255)',
27
+ primary: true,
30
28
  },
31
29
  {
32
30
  name: 'to_trip_id',
33
31
  type: 'varchar(255)',
32
+ primary: true,
34
33
  },
35
34
  {
36
35
  name: 'transfer_type',
37
36
  type: 'integer',
38
37
  min: 0,
39
38
  max: 5,
40
- required: false,
41
- default: 0
39
+ default: 0,
42
40
  },
43
41
  {
44
42
  name: 'min_transfer_time',
@@ -1,24 +1,22 @@
1
1
  const model = {
2
2
  filenameBase: 'translations',
3
3
  schema: [
4
- {
5
- name: 'id',
6
- type: 'integer',
7
- primary: true,
8
- },
9
4
  {
10
5
  name: 'table_name',
11
6
  type: 'varchar(255)',
7
+ primary: true,
12
8
  required: true,
13
9
  },
14
10
  {
15
11
  name: 'field_name',
16
12
  type: 'varchar(255)',
13
+ primary: true,
17
14
  required: true,
18
15
  },
19
16
  {
20
17
  name: 'language',
21
18
  type: 'varchar(255)',
19
+ primary: true,
22
20
  required: true,
23
21
  },
24
22
  {
@@ -29,14 +27,17 @@ const model = {
29
27
  {
30
28
  name: 'record_id',
31
29
  type: 'varchar(255)',
30
+ primary: true,
32
31
  },
33
32
  {
34
33
  name: 'record_sub_id',
35
34
  type: 'varchar(255)',
35
+ primary: true,
36
36
  },
37
37
  {
38
38
  name: 'field_value',
39
39
  type: 'varchar(2047)',
40
+ primary: true,
40
41
  },
41
42
  ],
42
43
  };
@@ -0,0 +1,20 @@
1
+ const model = {
2
+ filenameBase: 'calendar_attributes',
3
+ nonstandard: true,
4
+ extension: 'gtfs-plus',
5
+ schema: [
6
+ {
7
+ name: 'service_id',
8
+ type: 'varchar(255)',
9
+ primary: true,
10
+ },
11
+ {
12
+ name: 'service_description',
13
+ type: 'varchar(255)',
14
+ required: true,
15
+ nocase: true,
16
+ },
17
+ ],
18
+ };
19
+
20
+ export default model;
@@ -1,24 +1,20 @@
1
1
  const model = {
2
2
  filenameBase: 'directions',
3
3
  nonstandard: true,
4
+ extension: 'gtfs-plus',
4
5
  schema: [
5
- {
6
- name: 'id',
7
- type: 'integer',
8
- primary: true,
9
- },
10
6
  {
11
7
  name: 'route_id',
12
8
  type: 'varchar(255)',
13
9
  required: true,
14
- index: true,
10
+ primary: true,
15
11
  },
16
12
  {
17
13
  name: 'direction_id',
18
14
  type: 'integer',
19
15
  min: 0,
20
16
  max: 1,
21
- index: true,
17
+ primary: true,
22
18
  },
23
19
  {
24
20
  name: 'direction',
@@ -0,0 +1,32 @@
1
+ const model = {
2
+ filenameBase: 'route_attributes',
3
+ nonstandard: true,
4
+ extension: 'gtfs-plus',
5
+ schema: [
6
+ {
7
+ name: 'route_id',
8
+ type: 'varchar(255)',
9
+ primary: true,
10
+ },
11
+ {
12
+ name: 'category',
13
+ type: 'integer',
14
+ min: 0,
15
+ required: true,
16
+ },
17
+ {
18
+ name: 'subcategory',
19
+ type: 'integer',
20
+ min: 101,
21
+ required: true,
22
+ },
23
+ {
24
+ name: 'running_way',
25
+ type: 'integer',
26
+ min: 1,
27
+ required: true,
28
+ },
29
+ ],
30
+ };
31
+
32
+ export default model;
@@ -1,17 +1,26 @@
1
1
  const model = {
2
2
  filenameBase: 'stop_attributes',
3
3
  nonstandard: true,
4
+ extension: 'gtfs-plus',
4
5
  schema: [
5
6
  {
6
- name: 'id',
7
- type: 'integer',
7
+ name: 'stop_id',
8
+ type: 'varchar(255)',
9
+ required: true,
8
10
  primary: true,
9
11
  },
10
12
  {
11
- name: 'stop_id',
13
+ name: 'accessibility_id',
14
+ type: 'integer',
15
+ min: 0,
16
+ },
17
+ {
18
+ name: 'cardinal_direction',
19
+ type: 'varchar(255)',
20
+ },
21
+ {
22
+ name: 'relative_position',
12
23
  type: 'varchar(255)',
13
- required: true,
14
- index: true,
15
24
  },
16
25
  {
17
26
  name: 'stop_city',
@@ -7,7 +7,6 @@ const model = {
7
7
  type: 'varchar(255)',
8
8
  required: true,
9
9
  primary: true,
10
- index: true,
11
10
  source: 'parent.id',
12
11
  },
13
12
  {
package/models/models.js CHANGED
@@ -21,8 +21,6 @@ import transfers from '../models/gtfs/transfers.js';
21
21
  import translations from '../models/gtfs/translations.js';
22
22
  import trips from '../models/gtfs/trips.js';
23
23
 
24
- import directions from '../models/non-standard/directions.js';
25
- import stopAttributes from '../models/non-standard/stop-attributes.js';
26
24
  import timetables from '../models/non-standard/timetables.js';
27
25
  import timetablePages from '../models/non-standard/timetable-pages.js';
28
26
  import timetableStopOrder from '../models/non-standard/timetable-stop-order.js';
@@ -30,6 +28,11 @@ import timetableNotes from '../models/non-standard/timetable-notes.js';
30
28
  import timetableNotesReferences from '../models/non-standard/timetable-notes-references.js';
31
29
  import tripsDatedVehicleJourney from '../models/non-standard/trips-dated-vehicle-journey.js';
32
30
 
31
+ import calendarAttributes from '../models/gtfs-plus/calendar-attributes.js';
32
+ import directions from '../models/gtfs-plus/directions.js';
33
+ import routeAttributes from '../models/gtfs-plus/route-attributes.js';
34
+ import stopAttributes from '../models/gtfs-plus/stop-attributes.js';
35
+
33
36
  import boardAlight from '../models/gtfs-ride/board-alight.js';
34
37
  import riderTrip from '../models/gtfs-ride/rider-trip.js';
35
38
  import ridership from '../models/gtfs-ride/ridership.js';
@@ -71,14 +74,16 @@ const models = [
71
74
  transfers,
72
75
  translations,
73
76
  trips,
74
- directions,
75
- stopAttributes,
76
77
  timetables,
77
78
  timetablePages,
78
79
  timetableStopOrder,
79
80
  timetableNotes,
80
81
  timetableNotesReferences,
81
82
  tripsDatedVehicleJourney,
83
+ calendarAttributes,
84
+ directions,
85
+ routeAttributes,
86
+ stopAttributes,
82
87
  boardAlight,
83
88
  rideFeedInfo,
84
89
  riderTrip,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtfs",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Import GTFS transit data into SQLite and query routes, stops, times, fares and more",
5
5
  "keywords": [
6
6
  "transit",
@@ -74,13 +74,13 @@
74
74
  },
75
75
  "dependencies": {
76
76
  "@turf/helpers": "^6.5.0",
77
- "better-sqlite3": "^8.1.0",
78
- "csv-parse": "^5.3.5",
79
- "csv-stringify": "^6.2.4",
77
+ "better-sqlite3": "^8.3.0",
78
+ "csv-parse": "^5.3.6",
79
+ "csv-stringify": "^6.3.0",
80
80
  "gtfs-realtime-bindings": "^1.1.1",
81
81
  "lodash-es": "^4.17.21",
82
82
  "long": "^5.2.1",
83
- "node-fetch": "^3.3.0",
83
+ "node-fetch": "^3.3.1",
84
84
  "pluralize": "^8.0.0",
85
85
  "pretty-error": "^4.0.0",
86
86
  "promise-map-series": "^0.3.0",
@@ -95,14 +95,14 @@
95
95
  "yoctocolors": "^1.0.0"
96
96
  },
97
97
  "devDependencies": {
98
- "@types/better-sqlite3": "^7.6.3",
98
+ "@types/better-sqlite3": "^7.6.4",
99
99
  "dtslint": "^4.2.1",
100
- "eslint": "^8.34.0",
101
- "eslint-config-prettier": "^8.6.0",
100
+ "eslint": "^8.38.0",
101
+ "eslint-config-prettier": "^8.8.0",
102
102
  "eslint-config-xo": "^0.43.1",
103
103
  "husky": "^8.0.3",
104
104
  "mocha": "^10.2.0",
105
- "prettier": "^2.8.4",
105
+ "prettier": "^2.8.7",
106
106
  "pretty-quick": "^3.1.3",
107
107
  "should": "^13.2.3"
108
108
  },
@@ -57,14 +57,14 @@ describe('advancedQuery():', () => {
57
57
  const results = advancedQuery('stop_times', advancedQueryOptions);
58
58
 
59
59
  const expectedResults = [
60
- { trip_id: '329', arrival_time: '9:09:00' },
61
- { trip_id: '329', arrival_time: '8:52:00' },
62
- { trip_id: '329', arrival_time: '8:44:00' },
63
- { trip_id: '329', arrival_time: '8:35:00' },
64
- { trip_id: '329', arrival_time: '8:27:00' },
65
- { trip_id: '329', arrival_time: '8:16:00' },
66
- { trip_id: '329', arrival_time: '8:03:00' },
67
60
  { trip_id: '329', arrival_time: '7:56:00' },
61
+ { trip_id: '329', arrival_time: '8:03:00' },
62
+ { trip_id: '329', arrival_time: '8:16:00' },
63
+ { trip_id: '329', arrival_time: '8:27:00' },
64
+ { trip_id: '329', arrival_time: '8:35:00' },
65
+ { trip_id: '329', arrival_time: '8:44:00' },
66
+ { trip_id: '329', arrival_time: '8:52:00' },
67
+ { trip_id: '329', arrival_time: '9:09:00' },
68
68
  ];
69
69
 
70
70
  should.exist(results);
@@ -28,7 +28,6 @@ describe('getAgencies():', () => {
28
28
  const results = getAgencies();
29
29
 
30
30
  const expectedResult = {
31
- id: 1,
32
31
  agency_id: 'CT',
33
32
  agency_name: 'Caltrain',
34
33
  agency_url: 'http://www.caltrain.com',
@@ -54,7 +53,6 @@ describe('getAgencies():', () => {
54
53
  });
55
54
 
56
55
  const expectedResult = {
57
- id: 1,
58
56
  agency_id: 'CT',
59
57
  agency_name: 'Caltrain',
60
58
  agency_url: 'http://www.caltrain.com',
@@ -0,0 +1,33 @@
1
+ /* eslint-env mocha */
2
+
3
+ import should from 'should';
4
+
5
+ import config from '../test-config.js';
6
+ import {
7
+ openDb,
8
+ closeDb,
9
+ importGtfs,
10
+ getCalendarAttributes,
11
+ } from '../../index.js';
12
+
13
+ describe('getCalendarAttributes():', () => {
14
+ before(async () => {
15
+ openDb(config);
16
+ await importGtfs(config);
17
+ });
18
+
19
+ after(() => {
20
+ const db = openDb(config);
21
+ closeDb(db);
22
+ });
23
+
24
+ it('should return empty array if no calendar attributes', () => {
25
+ const serviceId = 'fake-service-id';
26
+
27
+ const results = getCalendarAttributes({
28
+ service_id: serviceId,
29
+ });
30
+ should.exists(results);
31
+ results.should.have.length(0);
32
+ });
33
+ });
@@ -38,28 +38,24 @@ describe('getCalendarDates():', () => {
38
38
 
39
39
  const expectedResults = [
40
40
  {
41
- id: 2,
42
41
  service_id: 'CT-16APR-Caltrain-Weekday-01',
43
42
  date: 20161124,
44
43
  exception_type: 2,
45
44
  holiday_name: null,
46
45
  },
47
46
  {
48
- id: 4,
49
47
  service_id: 'CT-16APR-Caltrain-Weekday-01',
50
48
  date: 20160905,
51
49
  exception_type: 2,
52
50
  holiday_name: null,
53
51
  },
54
52
  {
55
- id: 6,
56
53
  service_id: 'CT-16APR-Caltrain-Weekday-01',
57
54
  date: 20160704,
58
55
  exception_type: 2,
59
56
  holiday_name: null,
60
57
  },
61
58
  {
62
- id: 8,
63
59
  service_id: 'CT-16APR-Caltrain-Weekday-01',
64
60
  date: 20160530,
65
61
  exception_type: 2,
@@ -0,0 +1,33 @@
1
+ /* eslint-env mocha */
2
+
3
+ import should from 'should';
4
+
5
+ import config from '../test-config.js';
6
+ import {
7
+ openDb,
8
+ closeDb,
9
+ importGtfs,
10
+ getRouteAttributes,
11
+ } from '../../index.js';
12
+
13
+ describe('getRouteAttributes():', () => {
14
+ before(async () => {
15
+ openDb(config);
16
+ await importGtfs(config);
17
+ });
18
+
19
+ after(() => {
20
+ const db = openDb(config);
21
+ closeDb(db);
22
+ });
23
+
24
+ it('should return empty array if no route attributes', () => {
25
+ const routeId = 'fake-route-id';
26
+
27
+ const results = getRouteAttributes({
28
+ route_id: routeId,
29
+ });
30
+ should.exists(results);
31
+ results.should.have.length(0);
32
+ });
33
+ });
@@ -83,7 +83,6 @@ describe('openDb():', () => {
83
83
  );
84
84
 
85
85
  const expectedResult = {
86
- id: 1424,
87
86
  shape_id: 'cal_sf_tam',
88
87
  shape_pt_lat: 37.45375587083584,
89
88
  shape_pt_lon: -122.18063950538635,