wlbot 1.1.2 → 1.1.4
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/README.md +17 -1
- package/commands/metadata/catalog.js +12 -8
- package/commands/metadata/mine.js +12 -8
- package/commands/metadata/stations.js +12 -8
- package/commands/weather/current.js +12 -8
- package/commands/weather/historic.js +12 -8
- package/index.js +6 -1
- package/package.json +7 -7
- package/test/utils.test.js +13 -13
package/README.md
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
- [Install npm Packages](#install-npm-packages)
|
|
13
13
|
- [Installing CLI Globally](#installing-cli-globally)
|
|
14
14
|
- [Calling the CLI](#calling-the-cli)
|
|
15
|
+
- [Upgrading `wlbot` via `npm`](#upgrading-wlbot-via-npm)
|
|
15
16
|
- [Contributing](#contributing)
|
|
16
17
|
- [License](#license)
|
|
17
18
|
- [References](#references)
|
|
@@ -95,8 +96,23 @@ There are several commands that you will probably call more frequently than othe
|
|
|
95
96
|
- `wlbot metadata mine`: This command will return an array of `station-id` numbers for the weather station's that your WeatherLink account has permission to view data for.
|
|
96
97
|
- `wlbot weather current <station-id>`: This command will return the current weather record for the station whose station id matches `<station-id>`.
|
|
97
98
|
|
|
99
|
+
## Upgrading `wlbot` via `npm`
|
|
100
|
+
If you installed `wlbot` via `npm`, you can quickly get an updated version via the command line.
|
|
101
|
+
|
|
102
|
+
To see what version of `wlbot` you currently have installed:
|
|
103
|
+
1. Open a command line window and run `wlbot -V`.
|
|
104
|
+
|
|
105
|
+
To upgrade your installed version of `wlbot`:
|
|
106
|
+
1. Open a command line window and run `npm update -g wlbot`.
|
|
107
|
+
|
|
108
|
+
Downloading the upgrade may take a minute or two based on your internet connection.
|
|
109
|
+
|
|
98
110
|
## Contributing
|
|
99
|
-
All contributions are welcome!
|
|
111
|
+
All contributions are welcome!
|
|
112
|
+
|
|
113
|
+
First, search open issues to see if a ticket has already been created for the issue or feature request that you have. If a ticket does not already exist, open an issue to discuss what contributions you would like to make.
|
|
114
|
+
|
|
115
|
+
**All contributions should be developed in a `feature/` branch off of the `development` branch as a PR will be required before any changes are merged back into the `development` branch.**
|
|
100
116
|
|
|
101
117
|
## License
|
|
102
118
|
Distributed under the MIT License. See `LICENSE.txt` for more information.
|
|
@@ -5,7 +5,7 @@ import ora from 'ora';
|
|
|
5
5
|
import { buildWeatherLinkApiUrl, checkForRequired } from '../../lib/utils.js';
|
|
6
6
|
|
|
7
7
|
export default (options) => {
|
|
8
|
-
const spinner = !options.raw ? ora('Retrieving Sensor Catalog').start() : undefined;
|
|
8
|
+
const spinner = !options.raw && !options.dryRun ? ora('Retrieving Sensor Catalog').start() : undefined;
|
|
9
9
|
|
|
10
10
|
const envVars = checkForRequired(["WEATHER_LINK_API_KEY", "WEATHER_LINK_API_SECRET", "WEATHER_LINK_BASE_API_URL"])
|
|
11
11
|
if (!envVars.exist) {
|
|
@@ -18,13 +18,17 @@ export default (options) => {
|
|
|
18
18
|
|
|
19
19
|
const API_KEY = process.env.WEATHER_LINK_API_KEY;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
21
|
+
const urlToQuery = buildWeatherLinkApiUrl(
|
|
22
|
+
`sensor-catalog`,
|
|
23
|
+
{ "api-key": API_KEY, "t": String(Math.round(Date.now() / 1000)) },
|
|
24
|
+
{ "api-key": API_KEY, "t": String(Math.round(Date.now() / 1000)) }
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (options.dryRun) {
|
|
28
|
+
return console.log(urlToQuery);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
axios.get(urlToQuery)
|
|
28
32
|
.then((response) => {
|
|
29
33
|
if (options.raw) {
|
|
30
34
|
return console.log(JSON.stringify(response.data));
|
|
@@ -5,7 +5,7 @@ import ora from 'ora';
|
|
|
5
5
|
import { buildWeatherLinkApiUrl, checkForRequired } from '../../lib/utils.js';
|
|
6
6
|
|
|
7
7
|
export default (options) => {
|
|
8
|
-
const spinner = !options.raw ? ora('Searching for Stations').start() : undefined;
|
|
8
|
+
const spinner = !options.raw && !options.dryRun ? ora('Searching for Stations').start() : undefined;
|
|
9
9
|
|
|
10
10
|
const envVars = checkForRequired(["WEATHER_LINK_API_KEY", "WEATHER_LINK_API_SECRET", "WEATHER_LINK_BASE_API_URL"])
|
|
11
11
|
if (!envVars.exist) {
|
|
@@ -18,13 +18,17 @@ export default (options) => {
|
|
|
18
18
|
|
|
19
19
|
const API_KEY = process.env.WEATHER_LINK_API_KEY;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
21
|
+
const urlToQuery = buildWeatherLinkApiUrl(
|
|
22
|
+
'stations',
|
|
23
|
+
{ "api-key": API_KEY, "t": String(Math.round(Date.now() / 1000)) },
|
|
24
|
+
{ "api-key": API_KEY, "t": String(Math.round(Date.now() / 1000)) }
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (options.dryRun) {
|
|
28
|
+
return console.log(urlToQuery);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
axios.get(urlToQuery)
|
|
28
32
|
.then((response) => {
|
|
29
33
|
|
|
30
34
|
if (options.raw) {
|
|
@@ -5,7 +5,7 @@ import ora from 'ora';
|
|
|
5
5
|
import { buildWeatherLinkApiUrl, checkForRequired } from '../../lib/utils.js';
|
|
6
6
|
|
|
7
7
|
export default (stationIds, options) => {
|
|
8
|
-
const spinner = !options.raw ? ora('Searching for Stations').start() : undefined;
|
|
8
|
+
const spinner = !options.raw && !options.dryRun ? ora('Searching for Stations').start() : undefined;
|
|
9
9
|
|
|
10
10
|
const envVars = checkForRequired(["WEATHER_LINK_API_KEY", "WEATHER_LINK_API_SECRET", "WEATHER_LINK_BASE_API_URL"])
|
|
11
11
|
if (!envVars.exist) {
|
|
@@ -18,13 +18,17 @@ export default (stationIds, options) => {
|
|
|
18
18
|
|
|
19
19
|
const API_KEY = process.env.WEATHER_LINK_API_KEY;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
21
|
+
const urlToQuery = buildWeatherLinkApiUrl(
|
|
22
|
+
`stations/${stationIds}`,
|
|
23
|
+
{ "api-key": API_KEY, "station-ids": String(stationIds), "t": String(Math.round(Date.now() / 1000)) },
|
|
24
|
+
{ "api-key": API_KEY, "t": String(Math.round(Date.now() / 1000)) }
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (options.dryRun) {
|
|
28
|
+
return console.log(urlToQuery);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
axios.get(urlToQuery)
|
|
28
32
|
.then((response) => {
|
|
29
33
|
if (options.raw) {
|
|
30
34
|
return console.log(JSON.stringify(response.data));
|
|
@@ -5,7 +5,7 @@ import ora from 'ora';
|
|
|
5
5
|
import { buildWeatherLinkApiUrl, checkForRequired } from '../../lib/utils.js';
|
|
6
6
|
|
|
7
7
|
export default (stationId, options) => {
|
|
8
|
-
const spinner = !options.raw ? ora('Retrieving Current Weather Data').start() : undefined;
|
|
8
|
+
const spinner = !options.raw && !options.dryRun ? ora('Retrieving Current Weather Data').start() : undefined;
|
|
9
9
|
|
|
10
10
|
const envVars = checkForRequired(["WEATHER_LINK_API_KEY", "WEATHER_LINK_API_SECRET", "WEATHER_LINK_BASE_API_URL"])
|
|
11
11
|
if (!envVars.exist) {
|
|
@@ -18,13 +18,17 @@ export default (stationId, options) => {
|
|
|
18
18
|
|
|
19
19
|
const API_KEY = process.env.WEATHER_LINK_API_KEY;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
)
|
|
21
|
+
const urlToQuery = buildWeatherLinkApiUrl(
|
|
22
|
+
`current/${stationId}`,
|
|
23
|
+
{ "api-key": API_KEY, "station-id": String(stationId), "t": String(Math.round(Date.now() / 1000)) },
|
|
24
|
+
{ "api-key": API_KEY, "t": String(Math.round(Date.now() / 1000)) }
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (options.dryRun) {
|
|
28
|
+
return console.log(urlToQuery);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
axios.get(urlToQuery)
|
|
28
32
|
.then((response) => {
|
|
29
33
|
if (options.raw) {
|
|
30
34
|
return console.log(JSON.stringify(response.data));
|
|
@@ -5,7 +5,7 @@ import ora from 'ora';
|
|
|
5
5
|
import { buildWeatherLinkApiUrl, checkForRequired, dateRangeIsValid } from '../../lib/utils.js';
|
|
6
6
|
|
|
7
7
|
export default (stationId, startTimestamp, endTimestamp, options) => {
|
|
8
|
-
const spinner = !options.raw ? ora('Retrieving Historical Weather Data').start() : undefined;
|
|
8
|
+
const spinner = !options.raw && !options.dryRun ? ora('Retrieving Historical Weather Data').start() : undefined;
|
|
9
9
|
|
|
10
10
|
const envVars = checkForRequired(["WEATHER_LINK_API_KEY", "WEATHER_LINK_API_SECRET", "WEATHER_LINK_BASE_API_URL"])
|
|
11
11
|
if (!envVars.exist) {
|
|
@@ -24,13 +24,17 @@ export default (stationId, startTimestamp, endTimestamp, options) => {
|
|
|
24
24
|
|
|
25
25
|
const API_KEY = process.env.WEATHER_LINK_API_KEY;
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
27
|
+
const urlToQuery = buildWeatherLinkApiUrl(
|
|
28
|
+
`historic/${stationId}`,
|
|
29
|
+
{ "api-key": API_KEY, "end-timestamp": endTimestamp, "start-timestamp": startTimestamp, "station-id": String(stationId), "t": String(Math.round(Date.now() / 1000)) },
|
|
30
|
+
{ "api-key": API_KEY, "end-timestamp": endTimestamp, "start-timestamp": startTimestamp, "t": String(Math.round(Date.now() / 1000)) }
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (options.dryRun) {
|
|
34
|
+
return console.log(urlToQuery);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
axios.get(urlToQuery)
|
|
34
38
|
.then((response) => {
|
|
35
39
|
if (options.raw) {
|
|
36
40
|
return console.log(JSON.stringify(response.data));
|
package/index.js
CHANGED
|
@@ -18,7 +18,7 @@ const program = new Command();
|
|
|
18
18
|
program
|
|
19
19
|
.description("A CLI for the WeatherLink Live API.")
|
|
20
20
|
.name("wlbot")
|
|
21
|
-
.version('1.1.
|
|
21
|
+
.version('1.1.4')
|
|
22
22
|
.usage('<command>');
|
|
23
23
|
|
|
24
24
|
const metadata = program.command("metadata")
|
|
@@ -26,17 +26,20 @@ const metadata = program.command("metadata")
|
|
|
26
26
|
|
|
27
27
|
metadata.command("catalog")
|
|
28
28
|
.description("Get a catalog of all available sensor types and the data reported by each sensor.")
|
|
29
|
+
.option("-d, --dry-run", "Checks for the necessary environmental variables and outputs the URL that would be queried.")
|
|
29
30
|
.option("-r, --raw", "Display the raw response from the WeatherLink API.")
|
|
30
31
|
.action(catalog);
|
|
31
32
|
|
|
32
33
|
metadata.command("mine")
|
|
33
34
|
.description("Returns an array of Weather Station Id(s) that are associated with your WeatherLink API Key.")
|
|
35
|
+
.option("-d, --dry-run", "Checks for the necessary environmental variables and outputs the URL that would be queried.")
|
|
34
36
|
.option("-r, --raw", "Display the raw response from the WeatherLink API.")
|
|
35
37
|
.action(mine);
|
|
36
38
|
|
|
37
39
|
metadata.command("stations")
|
|
38
40
|
.description("Returns all available information about 1 or more weather stations associated with your WeatherLink API Key.")
|
|
39
41
|
.argument('<station-ids>', 'A comma-separated list of Weather Station Id(s) that you want information about.')
|
|
42
|
+
.option("-d, --dry-run", "Checks for the necessary environmental variables and outputs the URL that would be queried.")
|
|
40
43
|
.option("-r, --raw", "Display the raw response from the WeatherLink API.")
|
|
41
44
|
.action(stations);
|
|
42
45
|
|
|
@@ -46,6 +49,7 @@ const weather = program.command("weather")
|
|
|
46
49
|
weather.command("current")
|
|
47
50
|
.description("Get the current weather data for 1 weather station associated with your WeatherLink API Key.")
|
|
48
51
|
.argument('<station-id>', 'The Station ID of the weather station that you want current weather data for.')
|
|
52
|
+
.option("-d, --dry-run", "Checks for the necessary environmental variables and outputs the URL that would be queried.")
|
|
49
53
|
.option("-r, --raw", "Display the raw response from the WeatherLink API.")
|
|
50
54
|
.action(current);
|
|
51
55
|
|
|
@@ -54,6 +58,7 @@ weather.command("historic")
|
|
|
54
58
|
.argument('<station-id>', 'The Station ID of the weather station that you want current weather data for.')
|
|
55
59
|
.argument('<start-timestamp>', 'A Unix timestamp marking the beginning of the historical period (must be earlier than end-timestamp but not more than 24 hours earlier).')
|
|
56
60
|
.argument('<end-timestamp>', 'A Unix timestamp marking the end of the historical period (must be later than start-timestamp but not more than 24 hours later).')
|
|
61
|
+
.option("-d, --dry-run", "Checks for the necessary environmental variables and outputs the URL that would be queried.")
|
|
57
62
|
.option("-r, --raw", "Display the raw response from the WeatherLink API.")
|
|
58
63
|
.action(historic);
|
|
59
64
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wlbot",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "A CLI for the WeatherLink Live API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Davis Instruments",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"test": "mocha"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"axios": "^
|
|
39
|
-
"chalk": "^5.0
|
|
40
|
-
"commander": "^
|
|
41
|
-
"ora": "^
|
|
38
|
+
"axios": "^1.6.3",
|
|
39
|
+
"chalk": "^5.3.0",
|
|
40
|
+
"commander": "^11.1.0",
|
|
41
|
+
"ora": "^8.0.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"chai": "^
|
|
45
|
-
"mocha": "^10.
|
|
44
|
+
"chai": "^5.0.0",
|
|
45
|
+
"mocha": "^10.2.0"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|
|
48
48
|
"node": ">=16"
|
package/test/utils.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { buildWeatherLinkApiUrl, checkForRequired, dateRangeIsValid } from '../lib/utils.js';
|
|
2
|
-
import
|
|
2
|
+
import { expect } from 'chai';
|
|
3
3
|
|
|
4
4
|
describe('buildWeatherLinkApiUrl', () => {
|
|
5
5
|
beforeEach(() => {
|
|
@@ -10,7 +10,7 @@ describe('buildWeatherLinkApiUrl', () => {
|
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
it('Endpoint: current/13', () => {
|
|
13
|
-
|
|
13
|
+
expect(
|
|
14
14
|
buildWeatherLinkApiUrl(
|
|
15
15
|
`current/13`,
|
|
16
16
|
{'api-key': process.env.WEATHER_LINK_API_KEY, 'station-id': String(13), 't': String(1660759469)},
|
|
@@ -20,7 +20,7 @@ describe('buildWeatherLinkApiUrl', () => {
|
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
it('Endpoint: stations', () => {
|
|
23
|
-
|
|
23
|
+
expect(
|
|
24
24
|
buildWeatherLinkApiUrl(
|
|
25
25
|
'stations',
|
|
26
26
|
{'api-key': process.env.WEATHER_LINK_API_KEY, 't': String(1660757289)},
|
|
@@ -30,7 +30,7 @@ describe('buildWeatherLinkApiUrl', () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
it('Endpoint: stations/13,14,15', () => {
|
|
33
|
-
|
|
33
|
+
expect(
|
|
34
34
|
buildWeatherLinkApiUrl(
|
|
35
35
|
`stations/13,14,15`,
|
|
36
36
|
{'api-key': process.env.WEATHER_LINK_API_KEY, 'station-ids': '13,14,15', 't': String(1660759608)},
|
|
@@ -50,13 +50,13 @@ describe('checkForRequired', () => {
|
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
it('Missing All Env Vars', () => {
|
|
53
|
-
|
|
53
|
+
expect(
|
|
54
54
|
checkForRequired(["WEATHER_LINK_VERY_FAKE_NONEXISTENT"])
|
|
55
55
|
).to.deep.equal({"exist": false, "missing": ["WEATHER_LINK_VERY_FAKE_NONEXISTENT"]})
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
it('All Env Vars Defined', () => {
|
|
59
|
-
|
|
59
|
+
expect(
|
|
60
60
|
checkForRequired(["WEATHER_LINK_API_KEY", "WEATHER_LINK_API_SECRET", "WEATHER_LINK_BASE_API_URL"])
|
|
61
61
|
).to.deep.equal({"exist": true, "missing": []})
|
|
62
62
|
});
|
|
@@ -65,43 +65,43 @@ describe('checkForRequired', () => {
|
|
|
65
65
|
describe('dateRangeIsValid', () => {
|
|
66
66
|
|
|
67
67
|
it('Start Timestamp is Before End Timestamp', () => {
|
|
68
|
-
|
|
68
|
+
expect(
|
|
69
69
|
dateRangeIsValid(1673472399, 1673494000).isValid
|
|
70
70
|
).to.equal(true)
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
it('Start Timestamp is the Same as End Timestamp', () => {
|
|
74
|
-
|
|
74
|
+
expect(
|
|
75
75
|
dateRangeIsValid(1673494000, 1673494000).isValid
|
|
76
76
|
).to.equal(false)
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
it('Start Timestamp is After End Timestamp', () => {
|
|
80
|
-
|
|
80
|
+
expect(
|
|
81
81
|
dateRangeIsValid(1673494010, 1673494000).isValid
|
|
82
82
|
).to.equal(false)
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
it('Start Timestamp is 0', () => {
|
|
86
|
-
|
|
86
|
+
expect(
|
|
87
87
|
dateRangeIsValid(0, 1673494000).isValid
|
|
88
88
|
).to.equal(false)
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
it('Start Timestamp is Negative', () => {
|
|
92
|
-
|
|
92
|
+
expect(
|
|
93
93
|
dateRangeIsValid(-10, 1673494000).isValid
|
|
94
94
|
).to.equal(false)
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
it('End Timestamp is 0', () => {
|
|
98
|
-
|
|
98
|
+
expect(
|
|
99
99
|
dateRangeIsValid(1673494010, 0).isValid
|
|
100
100
|
).to.equal(false)
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
it('End Timestamp is Negative', () => {
|
|
104
|
-
|
|
104
|
+
expect(
|
|
105
105
|
dateRangeIsValid(1673494010, -10).isValid
|
|
106
106
|
).to.equal(false)
|
|
107
107
|
});
|