gtfs 3.3.0 → 3.3.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/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ 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
+ ## [3.3.1] - 2022-04-29
9
+
10
+ ### Added
11
+
12
+ - Add support for querying by shape_id
13
+
8
14
  ## [3.3.0] - 2022-04-26
9
15
 
10
16
  ### Changed
package/README.md CHANGED
@@ -569,7 +569,7 @@ getStops({
569
569
  `getStops` allows passing a `route_id` in the query and it will query trips and stoptimes to find all stops served by that `route_id`.
570
570
 
571
571
  ```js
572
- import { getRoutes } from 'gtfs';
572
+ import { getStops } from 'gtfs';
573
573
 
574
574
  // Get all stops for a specific route
575
575
  getStops({
@@ -580,7 +580,7 @@ getStops({
580
580
  `getStops` allows passing a `trip_id` in the query and it will query stoptimes to find all stops on that `trip_id`.
581
581
 
582
582
  ```js
583
- import { getRoutes } from 'gtfs';
583
+ import { getStops } from 'gtfs';
584
584
 
585
585
  // Get all stops for a specific trip
586
586
  getStops({
@@ -588,6 +588,17 @@ getStops({
588
588
  });
589
589
  ```
590
590
 
591
+ `getStops` allows passing a `shape_id` in the query and it will query trips and stoptimes to find all stops that use that `shape_id`.
592
+
593
+ ```js
594
+ import { getStops } from 'gtfs';
595
+
596
+ // Get all stops for a specific trip
597
+ getStops({
598
+ shape_id: 'cal_sf_tam',
599
+ });
600
+ ```
601
+
591
602
  ### getStopsAsGeoJSON(query)
592
603
 
593
604
  Queries stops and returns a promise. The result of the promise is an geoJSON object of stops. All valid queries for `getStops()` work for `getStopsAsGeoJSON()`.
@@ -718,23 +729,28 @@ Returns geoJSON of shapes.
718
729
  ```js
719
730
  import { getShapesAsGeoJSON } from 'gtfs';
720
731
 
721
- // Get geoJSON of all stops in an agency
732
+ // Get geoJSON of all routes in an agency
722
733
  getShapesAsGeoJSON();
723
734
 
724
- // Get geoJSON of stops along a specific route
735
+ // Get geoJSON of shapes for a specific route
725
736
  getShapesAsGeoJSON({
726
737
  route_id: 'Lo-16APR',
727
738
  });
728
739
 
729
- // Get geoJSON of stops for a specific trip
740
+ // Get geoJSON of shapes for a specific trip
730
741
  getShapesAsGeoJSON({
731
742
  trip_id: '37a',
732
743
  });
733
744
 
734
- // Get geoJSON of stops for a specific `service_id`
745
+ // Get geoJSON of shapes for a specific `service_id`
735
746
  getShapesAsGeoJSON({
736
747
  service_id: 'CT-16APR-Caltrain-Sunday-02',
737
748
  });
749
+
750
+ // Get geoJSON of shapes for a specific `shape_id`
751
+ getShapesAsGeoJSON({
752
+ shape_id: 'cal_sf_tam',
753
+ });
738
754
  ```
739
755
 
740
756
  ### getCalendars(query, fields, sortBy)
@@ -101,11 +101,12 @@ export async function getShapesAsGeoJSON(query = {}, options = {}) {
101
101
  (agency) => agency.agency_id === route.agency_id
102
102
  );
103
103
 
104
- const routeProperties = {
104
+ const geojsonProperties = {
105
105
  agency_name: agency ? agency.agency_name : undefined,
106
+ shape_id: query.shape_id,
106
107
  ...route,
107
108
  };
108
- features.push(...shapesToGeoJSONFeatures(shapes, routeProperties));
109
+ features.push(...shapesToGeoJSONFeatures(shapes, geojsonProperties));
109
110
  })
110
111
  );
111
112
 
package/lib/gtfs/stops.js CHANGED
@@ -47,12 +47,14 @@ export async function getStops(
47
47
  'trip_id',
48
48
  'service_id',
49
49
  'direction_id',
50
+ 'shape_id',
50
51
  ]);
51
52
  const tripQuery = pick(query, [
52
53
  'route_id',
53
54
  'trip_id',
54
55
  'service_id',
55
56
  'direction_id',
57
+ 'shape_id',
56
58
  ]);
57
59
 
58
60
  const whereClauses = Object.entries(stopQuery).map(([key, value]) =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtfs",
3
- "version": "3.3.0",
3
+ "version": "3.3.1",
4
4
  "description": "Import GTFS transit data into SQLite and query routes, stops, times, fares and more",
5
5
  "keywords": [
6
6
  "transit",
@@ -75,4 +75,19 @@ describe('getShapesAsGeoJSON():', () => {
75
75
  geojson.features[0].geometry.coordinates[0].length.should.equal(2);
76
76
  geojson.features[0].properties.route_color.should.startWith('#');
77
77
  });
78
+
79
+ it('should return geojson with shapes for a specific shapeId', async () => {
80
+ const shapeId = 'cal_sf_tam';
81
+
82
+ const geojson = await getShapesAsGeoJSON({
83
+ shape_id: shapeId,
84
+ });
85
+
86
+ should.exist(geojson);
87
+ geojson.type.should.equal('FeatureCollection');
88
+ geojson.features.length.should.equal(3);
89
+ should.exist(geojson.features[0].geometry.coordinates);
90
+ geojson.features[0].geometry.coordinates[0].length.should.equal(2);
91
+ geojson.features[0].properties.route_color.should.startWith('#');
92
+ });
78
93
  });
@@ -209,4 +209,32 @@ describe('getShapes():', () => {
209
209
  results.length.should.equal(713);
210
210
  results.should.containEql(expectedResult);
211
211
  });
212
+
213
+ it('should return array of shapes for specific shape_id', async () => {
214
+ const shapeId = 'cal_sf_tam';
215
+ const results = await getShapes(
216
+ {
217
+ shape_id: shapeId,
218
+ },
219
+ [
220
+ 'shape_id',
221
+ 'shape_pt_lat',
222
+ 'shape_pt_lon',
223
+ 'shape_pt_sequence',
224
+ 'shape_dist_traveled',
225
+ ]
226
+ );
227
+
228
+ const expectedResult = {
229
+ shape_id: 'cal_sf_tam',
230
+ shape_pt_lat: 37.682971245836484,
231
+ shape_pt_lon: -122.39507675170898,
232
+ shape_pt_sequence: 88,
233
+ shape_dist_traveled: null,
234
+ };
235
+
236
+ should.exist(results);
237
+ results.length.should.equal(401);
238
+ results.should.containEql(expectedResult);
239
+ });
212
240
  });
@@ -56,4 +56,18 @@ describe('getStopsAsGeoJSON(): ', () => {
56
56
  should.exist(geojson.features[0].geometry.coordinates);
57
57
  geojson.features[0].geometry.coordinates.length.should.equal(2);
58
58
  });
59
+
60
+ it('should return geojson with stops if they exist for a specific shapeId', async () => {
61
+ const shapeId = 'cal_sf_tam';
62
+
63
+ const geojson = await getStopsAsGeoJSON({
64
+ shape_id: shapeId,
65
+ });
66
+
67
+ should.exist(geojson);
68
+ geojson.type.should.equal('FeatureCollection');
69
+ geojson.features.length.should.equal(25);
70
+ should.exist(geojson.features[0].geometry.coordinates);
71
+ geojson.features[0].geometry.coordinates.length.should.equal(2);
72
+ });
59
73
  });
@@ -217,4 +217,53 @@ describe('getStops():', () => {
217
217
  );
218
218
  }
219
219
  });
220
+
221
+ it('should return array of stops if it exists for a specific shape_id', async () => {
222
+ const shapeId = 'cal_sf_tam';
223
+
224
+ const results = await getStops(
225
+ {
226
+ shape_id: shapeId,
227
+ },
228
+ [],
229
+ [['stop_id', 'ASC']]
230
+ );
231
+
232
+ const expectedStopIds = [
233
+ '70012',
234
+ '70021',
235
+ '70022',
236
+ '70032',
237
+ '70042',
238
+ '70052',
239
+ '70062',
240
+ '70082',
241
+ '70092',
242
+ '70102',
243
+ '70112',
244
+ '70122',
245
+ '70132',
246
+ '70142',
247
+ '70162',
248
+ '70172',
249
+ '70192',
250
+ '70202',
251
+ '70212',
252
+ '70222',
253
+ '70232',
254
+ '70242',
255
+ '70252',
256
+ '70262',
257
+ '70272',
258
+ ];
259
+
260
+ should.exist(results);
261
+ results.length.should.equal(25);
262
+ for (const [idx, stop] of results.entries()) {
263
+ expectedStopIds[idx].should.equal(
264
+ stop.stop_id,
265
+ 'The order of stops are expected to be the same'
266
+ );
267
+ }
268
+ });
220
269
  });