gtfs 4.1.1 → 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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ 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
+
8
16
  ## [4.1.1] - 2023-04-12
9
17
 
10
18
  ### 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';
@@ -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
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
  };
@@ -3,23 +3,18 @@ const model = {
3
3
  nonstandard: true,
4
4
  extension: 'gtfs-plus',
5
5
  schema: [
6
- {
7
- name: 'id',
8
- type: 'integer',
9
- primary: true,
10
- },
11
6
  {
12
7
  name: 'route_id',
13
8
  type: 'varchar(255)',
14
9
  required: true,
15
- index: true,
10
+ primary: true,
16
11
  },
17
12
  {
18
13
  name: 'direction_id',
19
14
  type: 'integer',
20
15
  min: 0,
21
16
  max: 1,
22
- index: true,
17
+ primary: true,
23
18
  },
24
19
  {
25
20
  name: 'direction',
@@ -3,16 +3,11 @@ const model = {
3
3
  nonstandard: true,
4
4
  extension: 'gtfs-plus',
5
5
  schema: [
6
- {
7
- name: 'id',
8
- type: 'integer',
9
- primary: true,
10
- },
11
6
  {
12
7
  name: 'stop_id',
13
8
  type: 'varchar(255)',
14
9
  required: true,
15
- index: true,
10
+ primary: true,
16
11
  },
17
12
  {
18
13
  name: 'accessibility_id',
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtfs",
3
- "version": "4.1.1",
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",
@@ -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',
@@ -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,
@@ -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,