Skip to content

Commit 0d46b34

Browse files
Merge pull request #63 from linkedconnections/development
v2.0.1
2 parents 1646a58 + f655deb commit 0d46b34

File tree

5 files changed

+78
-46
lines changed

5 files changed

+78
-46
lines changed

lib/GtfsIndex.js

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ const { URL } = require('url');
22
const { request } = require('undici');
33
const util = require('util');
44
const fs = require('fs');
5-
const unzip = require('unzipper');
65
const csv = require('fast-csv');
76
const del = require('del');
87
const childProcess = require('child_process');
98
const { Level } = require('level');
9+
const Utils = require('./Utils');
1010

1111
const exec = util.promisify(childProcess.exec);
1212

@@ -17,60 +17,48 @@ class GtfsIndex {
1717
this._headers = options.headers || {};
1818
}
1919

20-
getIndexes(options) {
21-
return new Promise(async (resolve, reject) => {
22-
try {
23-
await this.cleanUp();
24-
// Download or load from disk static GTFS feed
25-
if (this.path.startsWith('http') || this.path.startsWith('https')) {
26-
const downloadURL = new URL(this.path);
27-
if (!downloadURL.protocol) {
28-
reject('Please provide a valid URL or a path to a GTFS feed');
29-
return;
30-
} else {
31-
await this.download(this.path, this.headers);
32-
}
20+
async getIndexes(options) {
21+
try {
22+
await this.cleanUp();
23+
// Download or load from disk static GTFS feed
24+
if (this.path.startsWith('http') || this.path.startsWith('https')) {
25+
const downloadURL = new URL(this.path);
26+
if (!downloadURL.protocol) {
27+
throw new Error('Please provide a valid URL or a path to a GTFS feed');
3328
} else {
34-
if (!fs.existsSync(this.path)) {
35-
reject('Please provide a valid url or a path to a GTFS feed');
36-
return;
37-
} else {
29+
await this.download(this.path, this.headers);
30+
}
31+
} else {
32+
if (!fs.existsSync(this.path)) {
33+
throw new Error('Please provide a valid url or a path to a GTFS feed');
34+
} else {
35+
if (this.path.endsWith('.zip')) {
3836
await this.unzip(fs.createReadStream(this.path));
37+
} else {
38+
this.auxPath = this.path;
3939
}
4040
}
41-
42-
resolve(this.createIndexes(options.store, options.trips, options.deduce));
43-
} catch (err) {
44-
await this.cleanUp();
45-
reject(err);
4641
}
47-
});
42+
43+
return this.createIndexes(options.store, options.trips, options.deduce);
44+
} catch (err) {
45+
await this.cleanUp();
46+
throw err;
47+
}
4848
}
4949

5050
async download(url, headers) {
5151
const res = await request(url, { method: 'GET', headers });
5252

53-
if(res.statusCode === 200) {
53+
if (res.statusCode === 200) {
5454
await this.unzip(await res.body);
5555
} else {
5656
throw new Error(`Error on HTTP request: ${url}, Message: ${await res.body.text()}`);
5757
}
5858
}
5959

60-
unzip(res) {
61-
return new Promise((resolve, reject) => {
62-
if (!fs.existsSync(this.auxPath)) {
63-
fs.mkdirSync(this.auxPath);
64-
}
65-
res.pipe(unzip.Extract({ path: this.auxPath }))
66-
.on('error', async err => {
67-
await this.cleanUp();
68-
reject(err);
69-
})
70-
.on('close', () => {
71-
resolve();
72-
});
73-
});
60+
unzip(stream) {
61+
return Utils.unzipStream(stream, this.auxPath);
7462
}
7563

7664
async createIndexes(store, uTrips, deduce) {
@@ -88,7 +76,7 @@ class GtfsIndex {
8876
let cdp = null;
8977

9078

91-
if(deduce) {
79+
if (deduce) {
9280
tripsByRoute = new Map();
9381
firstStops = new Map();
9482
calendar = new Map();
@@ -147,7 +135,7 @@ class GtfsIndex {
147135
let sp = this.createIndex(this.auxPath + '/stops.txt', stops_index, 'stop_id');
148136
let rp = this.createIndex(this.auxPath + '/routes.txt', routes_index, 'route_id');
149137

150-
if(deduce) {
138+
if (deduce) {
151139
cp = this.createIndex(this.auxPath + '/calendar.txt', calendar, 'service_id');
152140
cdp = this.processCalendarDates(this.auxPath + '/calendar_dates.txt', calendarDates);
153141
}
@@ -317,6 +305,10 @@ class GtfsIndex {
317305
return this._auxPath;
318306
}
319307

308+
set auxPath(path) {
309+
this._auxPath = path;
310+
}
311+
320312
get headers() {
321313
return this._headers;
322314
}

lib/Utils.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const fs = require('fs');
2+
const unzip = require('unzipper');
3+
4+
function unzipStream(stream, outPath) {
5+
return new Promise((resolve, reject) => {
6+
if (!fs.existsSync(outPath)) {
7+
fs.mkdirSync(outPath);
8+
}
9+
stream.pipe(unzip.Extract({ path: outPath }))
10+
.on('error', async err => {
11+
await this.cleanUp();
12+
reject(err);
13+
})
14+
.on('close', () => {
15+
resolve();
16+
});
17+
});
18+
}
19+
20+
module.exports = {
21+
unzipStream
22+
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gtfsrt2lc",
3-
"version": "2.0.0",
3+
"version": "2.0.1",
44
"description": "Converts the GTFS-RT to Linked Connections",
55
"main": "./Gtfsrt2LC.js",
66
"bin": {

test/gtfsrt2lc.test.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
const fs = require('fs');
12
const GtfsIndex = require('../lib/GtfsIndex');
23
const Gtfsrt2lc = require('../lib/Gtfsrt2LC');
4+
const Utils = require('../lib/Utils');
35

46
const static_path = './test/data/static_rawdata.zip';
57
const rt_path = './test/data/realtime_rawdata';
@@ -24,7 +26,7 @@ var grepConnections = [];
2426
var levelConnections = [];
2527

2628

27-
// Make sure travis-ci does not crash due to timeouts
29+
// Make sure test process does not crash due to timeouts
2830
jest.setTimeout(180000);
2931

3032
test('Obtain the list of trips to be updated from GTFS-RT data', async () => {
@@ -77,7 +79,7 @@ test('Extract all indexes from sample static GTFS data (test/data/static_rawdata
7779
});
7880

7981
test('Extract all indexes from sample static GTFS data (test/data/static_rawdata.zip) using LevelStore', async () => {
80-
let gti = new GtfsIndex({ path: static_path });
82+
const gti = new GtfsIndex({ path: static_path });
8183
expect.assertions(4);
8284
levelIndexes = await gti.getIndexes({ store: 'LevelStore' });
8385

@@ -92,6 +94,22 @@ test('Extract all indexes from sample static GTFS data (test/data/static_rawdata
9294
expect(levelStop_times).toBeDefined();
9395
});
9496

97+
test('Extract all indexes when source is given as decompressed folder', async () => {
98+
// First decompress GTFS zip file
99+
const fileStream = fs.createReadStream(static_path);
100+
const sourcePath = './test/data/decompressed';
101+
await Utils.unzipStream(fileStream, sourcePath);
102+
// Extract indexes
103+
expect.assertions(4);
104+
const gti = new GtfsIndex({ path: sourcePath });
105+
const indexes = await gti.getIndexes({ store: 'MemStore' });
106+
107+
expect(indexes.routes).toBeDefined();
108+
expect(indexes.trips).toBeDefined();
109+
expect(indexes.stops).toBeDefined();
110+
expect(indexes.stop_times).toBeDefined();
111+
});
112+
95113
test('Check all parsed connections are consistent regarding departure and arrival times', async () => {
96114
grt.setIndexes(memIndexes);
97115
let connStream = await grt.parse({ format: 'json' });

0 commit comments

Comments
 (0)