transit-departures-widget 2.1.1 → 2.2.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,26 @@ 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
+ ## [2.2.1] - 2024-04-08
9
+
10
+ ## Fixed
11
+
12
+ - allow query param in config gtfsRtTripupdatesUrl
13
+
14
+ ## Updated
15
+
16
+ - Dependency updates
17
+
18
+ ## [2.2.0] - 2024-03-07
19
+
20
+ ## Added
21
+
22
+ - startDate and endDate config params
23
+
24
+ ## Updated
25
+
26
+ - Dependency updates
27
+
8
28
  ## [2.1.1] - 2023-12-04
9
29
 
10
30
  ## Fixed
package/README.md CHANGED
@@ -89,17 +89,19 @@ Copy `config-sample.json` to `config.json` and then add your projects configurat
89
89
 
90
90
  cp config-sample.json config.json
91
91
 
92
- | option | type | description |
93
- | --------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------- |
94
- | [`agency`](#agency) | object | Information about the GTFS and GTFS-RT to be used. |
95
- | [`beautify`](#beautify) | boolean | Whether or not to beautify the HTML output. |
96
- | [`locale`](#locale) | string | The 2-letter code of the language to use for the interface. |
97
- | [`noHead`](#nohead) | boolean | Whether or not to skip the header and footer of the HTML document. |
98
- | [`refreshIntervalSeconds`](#refreshIntervalSeconds) | integer | How often the widget should refresh departure data in seconds. Optional, defaults to 20 seconds. |
99
- | [`skipImport`](#skipimport) | boolean | Whether or not to skip importing GTFS data into SQLite. |
100
- | [`sqlitePath`](#sqlitepath) | string | A path to an SQLite database. Optional, defaults to using an in-memory database. |
101
- | [`templatePath`](#templatepath) | string | Path to custom pug template for rendering widget. |
102
- | [`timeFormat`](#timeFormat) | string | The format (12hour or 24hour) for the "as of" display. |
92
+ | option | type | description |
93
+ | --------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------- |
94
+ | [`agency`](#agency) | object | Information about the GTFS and GTFS-RT to be used. |
95
+ | [`beautify`](#beautify) | boolean | Whether or not to beautify the HTML output. |
96
+ | [`endDate`](#enddate) | string | A date in YYYYMMDD format to use to filter calendar.txt service. Optional, defaults to using all service in specified GTFS. |
97
+ | [`locale`](#locale) | string | The 2-letter code of the language to use for the interface. |
98
+ | [`noHead`](#nohead) | boolean | Whether or not to skip the header and footer of the HTML document. |
99
+ | [`refreshIntervalSeconds`](#refreshIntervalSeconds) | integer | How often the widget should refresh departure data in seconds. Optional, defaults to 20 seconds. |
100
+ | [`skipImport`](#skipimport) | boolean | Whether or not to skip importing GTFS data into SQLite. |
101
+ | [`sqlitePath`](#sqlitepath) | string | A path to an SQLite database. Optional, defaults to using an in-memory database. |
102
+ | [`startDate`](#startdate) | string | A date in YYYYMMDD format to use to filter calendar.txt service. Optional, defaults to using all service in specified GTFS. |
103
+ | [`templatePath`](#templatepath) | string | Path to custom pug template for rendering widget. |
104
+ | [`timeFormat`](#timeFormat) | string | The format (12hour or 24hour) for the "as of" display. |
103
105
 
104
106
  ### agency
105
107
 
@@ -157,6 +159,14 @@ Copy `config-sample.json` to `config.json` and then add your projects configurat
157
159
  "beautify": false
158
160
  ```
159
161
 
162
+ ### endDate
163
+
164
+ {String} A date in YYYYMMDD format to use to filter service_ids in calendar.txt. Useful in combination with `startDate` configuration option. Optional, if not specified, all services in GTFS will be used.
165
+
166
+ ```
167
+ "endDate": "20240401"
168
+ ```
169
+
160
170
  ### locale
161
171
 
162
172
  {String} The 2-letter language code of the language to use for the interface. Current languages supported are Polish (`pl`) and English (`en`). Pull Requests welcome for translations to other languages. Defaults to `en` (English).
@@ -189,6 +199,14 @@ Copy `config-sample.json` to `config.json` and then add your projects configurat
189
199
  "skipImport": false
190
200
  ```
191
201
 
202
+ ### startDate
203
+
204
+ {String} A date in YYYYMMDD format to use to filter service_ids in calendar.txt. Useful in combination with `endDate` configuration option. Optional, if not specified, all services in GTFS will be used.
205
+
206
+ ```
207
+ "startDate": "20240301"
208
+ ```
209
+
192
210
  ### sqlitePath
193
211
 
194
212
  {String} A path to an SQLite database. Optional, defaults to using an in-memory database.
@@ -5,9 +5,11 @@
5
5
  "gtfs_rt_tripupdates_url": "https://marintransit.net/gtfs-rt/tripupdates"
6
6
  },
7
7
  "beautify": true,
8
+ "endDate": "20240331",
8
9
  "locale": "en",
9
10
  "noHead": false,
10
11
  "refreshIntervalSeconds": 20,
11
12
  "templatePath": "views/widget",
12
- "timeFormat": "12hour"
13
+ "timeFormat": "12hour",
14
+ "startDate": "20240301"
13
15
  }
package/lib/utils.js CHANGED
@@ -7,6 +7,29 @@ import sqlString from 'sqlstring-sqlite'
7
7
  import toposort from 'toposort'
8
8
  import i18n from 'i18n'
9
9
 
10
+ /*
11
+ * Get calendars for a specified date range
12
+ */
13
+ const getCalendarsForDateRange = (config) => {
14
+ const db = openDb(config)
15
+ let whereClause = ''
16
+ const whereClauses = []
17
+
18
+ if (config.endDate) {
19
+ whereClauses.push(`start_date <= ${sqlString.escape(config.endDate)}`)
20
+ }
21
+
22
+ if (config.startDate) {
23
+ whereClauses.push(`end_date >= ${sqlString.escape(config.startDate)}`)
24
+ }
25
+
26
+ if (whereClauses.length > 0) {
27
+ whereClause = `WHERE ${whereClauses.join(' AND ')}`
28
+ }
29
+
30
+ return db.prepare(`SELECT * FROM calendar ${whereClause}`).all()
31
+ }
32
+
10
33
  /*
11
34
  * Format a route name.
12
35
  */
@@ -40,11 +63,15 @@ function getDirectionsForRoute(route, config) {
40
63
  'direction',
41
64
  ])
42
65
 
66
+ const calendars = getCalendarsForDateRange(config)
67
+
43
68
  // Else use the most common headsigns as directions from trips.txt file
44
69
  if (directions.length === 0) {
45
70
  const headsigns = db
46
71
  .prepare(
47
- 'SELECT direction_id, trip_headsign, count(*) AS count FROM trips WHERE route_id = ? GROUP BY direction_id, trip_headsign',
72
+ `SELECT direction_id, trip_headsign, count(*) AS count FROM trips WHERE route_id = ? AND service_id IN (${calendars
73
+ .map((calendar) => `'${calendar.service_id}'`)
74
+ .join(', ')}) GROUP BY direction_id, trip_headsign`,
48
75
  )
49
76
  .all(route.route_id)
50
77
 
@@ -105,9 +132,11 @@ function sortStopIdsBySequence(stoptimes) {
105
132
  */
106
133
  function getStopsForDirection(route, direction, config) {
107
134
  const db = openDb(config)
135
+ const calendars = getCalendarsForDateRange(config)
108
136
  const whereClause = formatWhereClauses({
109
137
  direction_id: direction.direction_id,
110
138
  route_id: route.route_id,
139
+ service_id: calendars.map((calendar) => calendar.service_id),
111
140
  })
112
141
  const stoptimes = db
113
142
  .prepare(
@@ -155,6 +184,8 @@ export function generateTransitDeparturesWidgetHtml(config) {
155
184
  updateFiles: false,
156
185
  })
157
186
 
187
+ const calendars = getCalendarsForDateRange(config)
188
+
158
189
  for (const route of routes) {
159
190
  route.route_full_name = formatRouteName(route)
160
191
 
@@ -174,7 +205,11 @@ export function generateTransitDeparturesWidgetHtml(config) {
174
205
  direction.stopIds = directionStops.map((stop) => stop.stop_id)
175
206
 
176
207
  const trips = getTrips(
177
- { route_id: route.route_id, direction_id: direction.direction_id },
208
+ {
209
+ route_id: route.route_id,
210
+ direction_id: direction.direction_id,
211
+ service_id: calendars.map((calendar) => calendar.service_id),
212
+ },
178
213
  ['trip_id'],
179
214
  )
180
215
  direction.tripIds = trips.map((trip) => trip.trip_id)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "transit-departures-widget",
3
3
  "description": "Build a realtime transit departures tool from GTFS and GTFS-Realtime.",
4
- "version": "2.1.1",
4
+ "version": "2.2.1",
5
5
  "keywords": [
6
6
  "transit",
7
7
  "gtfs",
@@ -16,7 +16,8 @@
16
16
  },
17
17
  "repository": "git://github.com/BlinkTagInc/transit-departures-widget",
18
18
  "contributors": [
19
- "Wojciech Kulesza <wojciech.kulesza@goeuropa.eu>"
19
+ "Wojciech Kulesza <wojciech.kulesza@goeuropa.eu>",
20
+ "eMerzh"
20
21
  ],
21
22
  "license": "MIT",
22
23
  "scripts": {
@@ -30,10 +31,10 @@
30
31
  "main": "index.js",
31
32
  "dependencies": {
32
33
  "copy-dir": "^1.3.0",
33
- "express": "^4.18.2",
34
- "gtfs": "^4.5.1",
34
+ "express": "^4.19.2",
35
+ "gtfs": "^4.10.2",
35
36
  "i18n": "^0.15.1",
36
- "js-beautify": "^1.14.11",
37
+ "js-beautify": "^1.15.1",
37
38
  "lodash-es": "^4.17.21",
38
39
  "morgan": "^1.10.0",
39
40
  "pretty-error": "^4.0.0",
@@ -44,12 +45,12 @@
44
45
  "toposort": "^2.0.2",
45
46
  "untildify": "^5.0.0",
46
47
  "yargs": "^17.7.2",
47
- "yoctocolors": "^1.0.0"
48
+ "yoctocolors": "^2.0.0"
48
49
  },
49
50
  "devDependencies": {
50
- "husky": "^8.0.3",
51
- "lint-staged": "^15.2.0",
52
- "prettier": "^3.1.0"
51
+ "husky": "^9.0.11",
52
+ "lint-staged": "^15.2.2",
53
+ "prettier": "^3.2.5"
53
54
  },
54
55
  "engines": {
55
56
  "node": ">= 14.15.4"
@@ -6,6 +6,7 @@ function setupTransitDeparturesWidget(routes, stops, config) {
6
6
  let departuresTimeout
7
7
  let initialStop
8
8
  let selectedParameters
9
+ let url = new URL(config.gtfsRtTripupdatesUrl)
9
10
 
10
11
  function updateUrlWithStop(stop) {
11
12
  const url = new URL(window.location.origin + window.location.pathname)
@@ -15,7 +16,7 @@ function setupTransitDeparturesWidget(routes, stops, config) {
15
16
  }
16
17
 
17
18
  async function fetchTripUpdates() {
18
- const url = `${config.gtfsRtTripupdatesUrl}?cacheBust=${Date.now()}`
19
+ url.searchParams.append('cacheBust', Date.now())
19
20
  const response = await fetch(url)
20
21
  if (response.ok) {
21
22
  const bufferResponse = await response.arrayBuffer()