-
Notifications
You must be signed in to change notification settings - Fork 0
/
cli.js
executable file
·113 lines (99 loc) · 3.62 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
#!/usr/bin/env node
'use strict';
const { getCities, getPollenData } = require('./client');
const { URL } = require('url');
const chalk = require('chalk');
const diacritics = require('diacritics');
const flowers = require('./flowers');
const fuzzysearch = require('fuzzysearch');
const inquirer = require('inquirer');
const Lines = require('./lines');
const opn = require('opn');
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 removeDiacritics = str => diacritics.remove(str.replace(/đ/g, 'dj'));
const normalize = str => removeDiacritics(str.toLowerCase().trim());
const compare = (str1, str2) => normalize(str1) === normalize(str2);
const openUrl = url => opn(url, { wait: false });
const name = Object.keys(pkg.bin)[0];
const help = chalk`
{bold ${name}} v${pkg.version}
Usage:
$ ${name} [city]
$ ${name} -c <city>
Options:
-c, --city Select city [string]
-j, --json Output data in JSON format [boolean]
-x, --xml Output data in XML format [boolean]
-w, --web Show data using web browser [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' },
city: { type: 'string', alias: 'c' },
json: { type: 'boolean', alias: 'j' },
xml: { type: 'boolean', alias: 'x' },
web: { type: 'boolean', alias: 'w' }
});
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 outputHelp(help, flowers);
const cities = await getCities();
const city = flags.city ? { name: flags.city } : await selectCity(cities);
let url;
if (city.url) ({ url } = city);
else ({ url } = cities.find(({ name }) => compare(name, city.name)) || {});
if (!url) {
const msg = chalk`Odabrani grad nije pronadjen: {blue ${city.name}}`;
console.error(chalk`{bgRed.whiteBright Error} ${msg}`);
process.exit(1);
}
if (flags.web) return openUrl(webpage(url));
const data = await getPollenData(url);
if (flags.json) return console.log(jsonify(data, null, 2));
if (flags.xml) return console.log(data.toXML());
return print(data);
}
async function selectCity(cities) {
cities = cities.map(city => {
city.value = city;
city.normalizedName = normalize(city.name);
return city;
});
const { city } = await inquirer.prompt([{
type: 'autocomplete',
name: 'city',
message: 'Select city',
pageSize: 10,
source: async (_, input) => {
if (!input) return cities;
const needle = normalize(input);
return cities.filter(city => fuzzysearch(needle, city.normalizedName));
}
}]);
return city;
}
function outputHelp(help, logo, margin = 66) {
const output = new Lines();
help.split('\n').forEach((line, row) => {
output.write(line);
const logoLine = logo[row];
if (!logoLine) return output.next();
output.restartLine(margin).write(logoLine);
output.next();
});
console.log(output.toString());
}
function webpage(url) {
const urlObj = new URL(url);
urlObj.search = '';
return urlObj.href;
}