/
cli.js
executable file
·121 lines (106 loc) · 3.23 KB
/
cli.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/usr/bin/env node
'use strict';
const {
getStations,
getTravelDates,
getTimetable,
Type
} = require('./client');
const { getDateStr, formatDate, normalize } = require('./helpers');
const chalk = require('chalk');
const fuzzysearch = require('fuzzysearch');
const inquirer = require('inquirer');
const pkg = require('./package.json');
const print = require('./printer');
inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'));
const jsonify = obj => JSON.stringify(obj, null, 2);
const search = (needle, haystack) => {
return fuzzysearch(needle.toLowerCase(), haystack.toLowerCase());
};
const toDate = str => {
const [day, month, year] = str.split('.');
return new Date(Date.UTC(year, month - 1, day));
};
const name = Object.keys(pkg.bin)[0];
const help = chalk`
{bold ${name}} v${pkg.version}
Usage:
$ ${name}
Options:
-j, --json Output data in JSON format [boolean]
-h, --help Show help [boolean]
-v, --version Show version number [boolean]
Homepage: {green ${pkg.homepage}}
Report issue: {green ${pkg.bugs.url}}
`;
const options = require('minimist-options')({
help: { type: 'boolean', alias: 'h' },
version: { type: 'boolean', alias: 'v' },
json: { type: 'boolean', alias: 'j' }
});
const argv = require('minimist')(process.argv.slice(2), options);
program(argv).catch(err => { throw err; });
async function program(flags) {
if (flags.version) return console.log(pkg.version);
if (flags.help) return console.log(help);
const type = await selectType();
const [stations, travelDates] = await Promise.all([
getStations(type),
getTravelDates(type)
]);
const travelDate = await selectDate(travelDates);
const station = await selectStation(stations, type);
const timetable = await getTimetable(type, station, travelDate);
console.log();
if (flags.json) return console.log(jsonify(timetable));
print(timetable, type);
}
async function selectType() {
const { type } = await inquirer.prompt([{
type: 'list',
name: 'type',
message: 'Choose travel type',
choices: [{
name: 'Arrival',
value: Type.Arrival
}, {
name: 'Departure',
value: Type.Departure
}]
}]);
return type;
}
async function selectStation(stations, type) {
stations = stations.map(station => {
station.value = station;
station.normalizedName = normalize(station.name);
return station;
});
const message = 'Select ' + (type === Type.Arrival ? 'start' : 'destination');
const { city } = await inquirer.prompt([{
type: 'autocomplete',
name: 'city',
message,
pageSize: 10,
source: async (_, input) => {
if (!input) return stations;
return stations.filter(it => search(normalize(input), it.normalizedName));
}
}]);
return city;
}
async function selectDate(dates) {
const choices = dates.map(str => {
const date = toDate(str);
const name = formatDate(date);
return { name, value: getDateStr(date) };
});
choices.push(new inquirer.Separator());
const { date } = await inquirer.prompt([{
type: 'list',
name: 'date',
message: 'Choose travel date',
choices
}]);
return date;
}