wlbot 1.1.4 → 1.1.5

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/LICENSE.txt CHANGED
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
package/README.md CHANGED
@@ -114,6 +114,8 @@ First, search open issues to see if a ticket has already been created for the is
114
114
 
115
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.**
116
116
 
117
+ If you are introducing new functionality, please add unit tests (UTs) to ensure the functionality of your contribution and its backwards compatibility. All UTs should be able to run locally. You will need to install the `devDependencies` to run the UTs.
118
+
117
119
  ## License
118
120
  Distributed under the MIT License. See `LICENSE.txt` for more information.
119
121
 
@@ -121,4 +123,4 @@ Distributed under the MIT License. See `LICENSE.txt` for more information.
121
123
  Below are several references that were used to help find inspiration for this project, get a starting point for the CLI, and serve as a resource for the WeatherLink API.
122
124
  - [WeatherLink Developer Portal](https://weatherlink.github.io)
123
125
  - [WeatherLink Portal](https://www.weatherlink.com)
124
- - [How to Build a Command Line Interface (CLI) Using Node.js](https://cheatcode.co/tutorials/how-to-build-a-command-line-interface-cli-using-node-js)
126
+ - [How to Build a Command Line Interface (CLI) Using Node.js](https://cheatcode.co/tutorials/how-to-build-a-command-line-interface-cli-using-node-js)
@@ -2,7 +2,7 @@ import chalk from 'chalk';
2
2
  import ora from 'ora';
3
3
 
4
4
  export default (options) => {
5
- const spinner = !options.raw ? ora('Reading Environment Variables').start() : undefined;
5
+ const spinner = ora('Reading Environment Variables').start();
6
6
 
7
7
  let evValues = {
8
8
  "WEATHER_LINK_API_KEY": process.env.WEATHER_LINK_API_KEY || "",
@@ -17,5 +17,6 @@ export default (options) => {
17
17
  }
18
18
 
19
19
  spinner.succeed(chalk.green.bold(`Environment Variables Retrieved`));
20
- return console.log(JSON.stringify(evValues, undefined, 2))
21
- };
20
+ console.log(JSON.stringify(evValues, undefined, 2));
21
+ return;
22
+ };
@@ -4,16 +4,17 @@ import ora from 'ora';
4
4
 
5
5
  import { buildWeatherLinkApiUrl, checkForRequired } from '../../lib/utils.js';
6
6
 
7
- export default (options) => {
7
+ export default async (options) => {
8
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) {
12
- if (spinner) {
13
- spinner.fail('Failed to Retrieve Catalog')
12
+ if (spinner) {
13
+ spinner.fail('Failed to Retrieve Catalog');
14
14
  }
15
-
16
- return console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
15
+
16
+ console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
17
+ return;
17
18
  }
18
19
 
19
20
  const API_KEY = process.env.WEATHER_LINK_API_KEY;
@@ -25,24 +26,30 @@ export default (options) => {
25
26
  );
26
27
 
27
28
  if (options.dryRun) {
28
- return console.log(urlToQuery);
29
+ console.log(urlToQuery);
30
+ return;
29
31
  }
30
32
 
31
- axios.get(urlToQuery)
32
- .then((response) => {
33
- if (options.raw) {
34
- return console.log(JSON.stringify(response.data));
35
- }
33
+ try {
34
+ const response = await axios.get(urlToQuery);
36
35
 
37
- spinner.succeed(chalk.green.bold(`Catalog Retrieved`));
38
- return console.dir(response.data, { depth: null })
39
- })
40
- .catch((error) => {
41
- if (options.raw) {
42
- return console.log(JSON.stringify(error.response.data));
43
- }
36
+ if (options.raw) {
37
+ console.log(JSON.stringify(response.data));
38
+ return response;
39
+ }
44
40
 
45
- spinner.fail('Failed to Retrieve Catalog');
46
- return console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
47
- })
48
- };
41
+ spinner.succeed(chalk.green.bold(`Catalog Retrieved`));
42
+ console.dir(response.data, { depth: null });
43
+ return response;
44
+
45
+ } catch (error) {
46
+ if (options.raw) {
47
+ console.log(JSON.stringify(error.response.data));
48
+ throw (error);
49
+ }
50
+
51
+ spinner.fail('Failed to Retrieve Catalog');
52
+ console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
53
+ throw (error);
54
+ }
55
+ };
@@ -4,16 +4,17 @@ import ora from 'ora';
4
4
 
5
5
  import { buildWeatherLinkApiUrl, checkForRequired } from '../../lib/utils.js';
6
6
 
7
- export default (options) => {
7
+ export default async (options) => {
8
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) {
12
- if (spinner) {
13
- spinner.fail('Failed to Retrieve Stations')
12
+ if (spinner) {
13
+ spinner.fail('Failed to Retrieve Stations');
14
14
  }
15
-
16
- return console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
15
+
16
+ console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
17
+ return;
17
18
  }
18
19
 
19
20
  const API_KEY = process.env.WEATHER_LINK_API_KEY;
@@ -25,30 +26,36 @@ export default (options) => {
25
26
  );
26
27
 
27
28
  if (options.dryRun) {
28
- return console.log(urlToQuery);
29
+ console.log(urlToQuery);
30
+ return;
29
31
  }
30
32
 
31
- axios.get(urlToQuery)
32
- .then((response) => {
33
-
34
- if (options.raw) {
35
- return console.log(JSON.stringify(response.data));
36
- }
37
-
38
- let stationIdList = [];
39
- response.data.stations.forEach(station => {
40
- stationIdList.push(station.station_id);
41
- });
42
-
43
- spinner.succeed(chalk.green.bold(`${stationIdList.length} Station(s) Found`));
44
- return console.log(stationIdList);
45
- })
46
- .catch((error) => {
47
- if (options.raw) {
48
- return console.log(JSON.stringify(error.response.data));
49
- }
50
-
51
- spinner.fail('Unable to Find Stations');
52
- return console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
53
- })
54
- };
33
+ try {
34
+ const response = await axios.get(urlToQuery);
35
+
36
+ if (options.raw) {
37
+ console.log(JSON.stringify(response.data));
38
+ return;
39
+ }
40
+
41
+ let stationIdList = [];
42
+ response.data.stations.forEach(station => {
43
+ stationIdList.push(station.station_id);
44
+ });
45
+
46
+ spinner.succeed(chalk.green.bold(`${stationIdList.length} Station(s) Found`));
47
+ console.dir(stationIdList, { depth: null });
48
+ return stationIdList;
49
+
50
+ } catch (error) {
51
+
52
+ if (options.raw) {
53
+ console.log(JSON.stringify(error.response.data));
54
+ throw (error);
55
+ }
56
+
57
+ spinner.fail('Unable to Find Stations');
58
+ console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
59
+ throw (error);
60
+ }
61
+ };
@@ -4,16 +4,17 @@ import ora from 'ora';
4
4
 
5
5
  import { buildWeatherLinkApiUrl, checkForRequired } from '../../lib/utils.js';
6
6
 
7
- export default (stationIds, options) => {
7
+ export default async (stationIds, options) => {
8
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) {
12
- if (spinner) {
13
- spinner.fail('Failed to Retrieve Stations')
12
+ if (spinner) {
13
+ spinner.fail('Failed to Retrieve Stations');
14
14
  }
15
15
 
16
- return console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
16
+ console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
17
+ return;
17
18
  }
18
19
 
19
20
  const API_KEY = process.env.WEATHER_LINK_API_KEY;
@@ -25,24 +26,31 @@ export default (stationIds, options) => {
25
26
  );
26
27
 
27
28
  if (options.dryRun) {
28
- return console.log(urlToQuery);
29
+ console.log(urlToQuery);
30
+ return;
29
31
  }
30
32
 
31
- axios.get(urlToQuery)
32
- .then((response) => {
33
- if (options.raw) {
34
- return console.log(JSON.stringify(response.data));
35
- }
36
-
37
- spinner.succeed(chalk.green.bold(`${response.data.stations.length} Station(s) Found`));
38
- return console.log(response.data);
39
- })
40
- .catch((error) => {
41
- if (options.raw) {
42
- return console.log(JSON.stringify(error.response.data));
43
- }
44
-
45
- spinner.fail('Unable to Find Stations');
46
- return console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
47
- })
48
- };
33
+ try {
34
+ const response = await axios.get(urlToQuery);
35
+
36
+ if (options.raw) {
37
+ console.log(JSON.stringify(response.data));
38
+ return response;
39
+ }
40
+
41
+ spinner.succeed(chalk.green.bold(`${response.data.stations.length} Station(s) Found`));
42
+ console.dir(response.data, { depth: null });
43
+ return response;
44
+
45
+ } catch (error) {
46
+
47
+ if (options.raw) {
48
+ console.log(JSON.stringify(error.response.data));
49
+ throw (error);
50
+ }
51
+
52
+ spinner.fail('Unable to Find Stations');
53
+ console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
54
+ throw (error);
55
+ }
56
+ };
@@ -1,39 +1,44 @@
1
1
  import axios from 'axios';
2
2
 
3
- export default function(service, options) {
3
+ export default async function (service, _) {
4
4
 
5
5
  // Mapping of wlbot's shorthand for service names to Davis Instrument's official names.
6
6
  const fullServiceName = {
7
- 'api' : 'APIs and Data Feeds',
8
- 'dataingest' : 'Data Ingestion',
9
- 'mobile' : 'Mobile Applications',
10
- 'syscomms' : 'System Communication',
11
- 'website' : 'WeatherLink Website'
7
+ 'api': 'APIs and Data Feeds',
8
+ 'dataingest': 'Data Ingestion',
9
+ 'mobile': 'Mobile Applications',
10
+ 'syscomms': 'System Communication',
11
+ 'website': 'WeatherLink Website'
12
12
  };
13
13
 
14
- return (
15
- axios.get(
16
- 'https://0886445102835570.hostedstatus.com/1.0/status/600712dea9c1290530967bc6'
17
- )
18
- .then((response) => {
19
-
20
- var requestedDavisServices = service === 'all' ?
21
- response.data.result.status
22
- :
23
- response.data.result.status.filter(davisService => {
24
- return davisService.name === fullServiceName[service];
25
- });
26
-
27
- return requestedDavisServices;
28
-
29
- })
30
- .catch((error) => {
31
- return ({
32
- 'error': {
33
- 'msg': `${error.response.data.message}`,
34
- 'status': `${error.response.status}`
35
- }
14
+ try {
15
+ const response = await axios.get('https://0886445102835570.hostedstatus.com/1.0/status/600712dea9c1290530967bc6');
16
+
17
+ if (!Array.isArray(response.data.result.status)) {
18
+ throw ({ response: { data: { message: 'Hosted Status returned in an unexpected format.' }, status: 999 } })
19
+ }
20
+
21
+ var requestedDavisServices = service === 'all' ?
22
+ response.data.result.status
23
+ :
24
+ response.data.result.status.filter(davisService => {
25
+ return davisService.name === fullServiceName[service];
36
26
  });
37
- })
38
- );
39
- };
27
+
28
+ requestedDavisServices.forEach((requestedService) => {
29
+ console.log(requestedService.name + ' is ' + requestedService.status + ' (Status Code: ' + requestedService.status_code + ')');
30
+ });
31
+
32
+ return requestedDavisServices;
33
+
34
+ } catch (error) {
35
+ console.log('Error: ' + error);
36
+
37
+ return ({
38
+ 'error': {
39
+ 'msg': `${error.response.data.message}`,
40
+ 'status': `${error.response.status}`
41
+ }
42
+ });
43
+ }
44
+ };
@@ -4,16 +4,17 @@ import ora from 'ora';
4
4
 
5
5
  import { buildWeatherLinkApiUrl, checkForRequired } from '../../lib/utils.js';
6
6
 
7
- export default (stationId, options) => {
7
+ export default async (stationId, options) => {
8
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) {
12
- if (spinner) {
13
- spinner.fail('Failed to Retrieve Current Weather Data')
12
+ if (spinner) {
13
+ spinner.fail('Failed to Retrieve Current Weather Data');
14
14
  }
15
15
 
16
- return console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
16
+ console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
17
+ return;
17
18
  }
18
19
 
19
20
  const API_KEY = process.env.WEATHER_LINK_API_KEY;
@@ -25,24 +26,29 @@ export default (stationId, options) => {
25
26
  );
26
27
 
27
28
  if (options.dryRun) {
28
- return console.log(urlToQuery);
29
+ console.log(urlToQuery);
30
+ return;
29
31
  }
30
32
 
31
- axios.get(urlToQuery)
32
- .then((response) => {
33
- if (options.raw) {
34
- return console.log(JSON.stringify(response.data));
35
- }
33
+ try {
34
+ const response = await axios.get(urlToQuery);
35
+ if (options.raw) {
36
+ console.log(JSON.stringify(response.data));
37
+ return response;
38
+ }
36
39
 
37
- spinner.succeed(chalk.green.bold(`Current Weather Data Retrieved`));
38
- return console.dir(response.data, { depth: null })
39
- })
40
- .catch((error) => {
41
- if (options.raw) {
42
- return console.log(JSON.stringify(error.response.data));
43
- }
40
+ spinner.succeed(chalk.green.bold(`Current Weather Data Retrieved`));
41
+ console.dir(response.data, { depth: null });
42
+ return response;
44
43
 
45
- spinner.fail('Failed to Retrieve Current Weather Data');
46
- return console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
47
- })
48
- };
44
+ } catch (error) {
45
+ if (options.raw) {
46
+ console.log(JSON.stringify(error.response.data));
47
+ throw error;
48
+ }
49
+
50
+ spinner.fail('Failed to Retrieve Current Weather Data');
51
+ console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
52
+ throw error;
53
+ }
54
+ };
@@ -4,22 +4,28 @@ import ora from 'ora';
4
4
 
5
5
  import { buildWeatherLinkApiUrl, checkForRequired, dateRangeIsValid } from '../../lib/utils.js';
6
6
 
7
- export default (stationId, startTimestamp, endTimestamp, options) => {
7
+ export default async (stationId, startTimestamp, endTimestamp, options) => {
8
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) {
12
- if (spinner) {
13
- spinner.fail('Failed to Retrieve Historic Weather Data')
12
+ if (spinner) {
13
+ spinner.fail('Failed to Retrieve Historic Weather Data');
14
14
  }
15
15
 
16
- return console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
16
+ console.log(`${chalk.red.bold(`Missing Environment Variable(s):`)} ${envVars.missing.join(", ")}`);
17
+ return;
17
18
  }
18
19
 
19
20
  const resultsOfDateRangeCheck = dateRangeIsValid(startTimestamp, endTimestamp);
20
21
 
21
22
  if (!resultsOfDateRangeCheck.isValid) {
22
- return console.log(`${chalk.red.bold(`Error:`)} ${resultsOfDateRangeCheck.msg}`);
23
+ if (spinner) {
24
+ spinner.fail(`${resultsOfDateRangeCheck.msg}`);
25
+ }
26
+
27
+ console.log(`${chalk.red.bold(`Error:`)} ${resultsOfDateRangeCheck.msg}`);
28
+ return;
23
29
  }
24
30
 
25
31
  const API_KEY = process.env.WEATHER_LINK_API_KEY;
@@ -31,24 +37,30 @@ export default (stationId, startTimestamp, endTimestamp, options) => {
31
37
  );
32
38
 
33
39
  if (options.dryRun) {
34
- return console.log(urlToQuery);
40
+ console.log(urlToQuery);
41
+ return
35
42
  }
36
43
 
37
- axios.get(urlToQuery)
38
- .then((response) => {
39
- if (options.raw) {
40
- return console.log(JSON.stringify(response.data));
41
- }
42
-
43
- spinner.succeed(chalk.green.bold(`Historical Weather Data Retrieved`));
44
- return console.dir(response.data, { depth: null })
45
- })
46
- .catch((error) => {
47
- if (options.raw) {
48
- return console.log(JSON.stringify(error.response.data));
49
- }
50
-
51
- spinner.fail('Failed to Retrieve Historical Weather Data');
52
- return console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
53
- })
54
- };
44
+ try {
45
+ const response = await axios.get(urlToQuery);
46
+
47
+ if (options.raw) {
48
+ console.log(JSON.stringify(response.data));
49
+ return response;
50
+ }
51
+
52
+ spinner.succeed(chalk.green.bold(`Historical Weather Data Retrieved`));
53
+ console.dir(response.data, { depth: null });
54
+ return response;
55
+
56
+ } catch (error) {
57
+ if (options.raw) {
58
+ console.log(JSON.stringify(error.response.data));
59
+ throw error;
60
+ }
61
+
62
+ spinner.fail('Failed to Retrieve Historical Weather Data');
63
+ console.log(`${chalk.red.bold(`Error ${error.response.status}:`)} ${error.response.data.message}`);
64
+ throw error;
65
+ }
66
+ };
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.4')
21
+ .version('1.1.5')
22
22
  .usage('<command>');
23
23
 
24
24
  const metadata = program.command("metadata")
@@ -70,17 +70,7 @@ program.command("config")
70
70
  program.command("status")
71
71
  .description("Retrieves the operational status(es) of Davis Instrument's services.")
72
72
  .addArgument(new Argument('[service]', 'The Davis Instrument service that you want to obtain the operational status of.').choices(['all', 'api', 'dataingest', 'mobile', 'syscomms', 'website']).default('all'))
73
- .action((service, options) => {
74
- status(service, options).then((result) => {
75
- if (!Array.isArray(result)) {
76
- console.log('Error: ' + result.error.msg);
77
- } else {
78
- result.forEach((requestedService) => {
79
- console.log(requestedService.name + ' is ' + requestedService.status + ' (Status Code: ' + requestedService.status_code + ')');
80
- });
81
- }
82
- });
83
- });
73
+ .action(status);
84
74
 
85
75
  program.commands.sort((a, b) => a._name.localeCompare(b._name));
86
- program.parse(process.argv);
76
+ program.parse(process.argv);
package/lib/utils.js CHANGED
@@ -14,7 +14,7 @@ export function buildWeatherLinkApiUrl(endpoint, signature_parameters, uri_param
14
14
 
15
15
  var apiSignature = "";
16
16
  for (const key in signature_parameters) {
17
- apiSignature = apiSignature + key + signature_parameters[key]
17
+ apiSignature = apiSignature + key + signature_parameters[key];
18
18
  }
19
19
 
20
20
  var hmac = crypto.createHmac('sha256', API_SECRET);
@@ -28,7 +28,7 @@ export function buildWeatherLinkApiUrl(endpoint, signature_parameters, uri_param
28
28
  apiRequestURL = apiRequestURL + "&" + key + "=" + uri_parameters[key];
29
29
  }
30
30
  });
31
-
31
+
32
32
  apiRequestURL = apiRequestURL + "&api-signature=" + hashedData;
33
33
  return apiRequestURL;
34
34
  }
@@ -43,16 +43,16 @@ export function checkForRequired(envVars) {
43
43
  let missingEnvVars = []
44
44
 
45
45
  for (const envVar of envVars) {
46
- if (!process.env[envVar]){
47
- missingEnvVars.push(envVar)
46
+ if (!process.env[envVar]) {
47
+ missingEnvVars.push(envVar);
48
48
  }
49
49
  }
50
50
 
51
51
  if (missingEnvVars.length != 0) {
52
- return {"exist": false, "missing": missingEnvVars};
52
+ return { "exist": false, "missing": missingEnvVars };
53
53
  }
54
54
 
55
- return {"exist": true, "missing": missingEnvVars};
55
+ return { "exist": true, "missing": missingEnvVars };
56
56
  }
57
57
 
58
58
  /**
@@ -63,12 +63,12 @@ export function checkForRequired(envVars) {
63
63
  */
64
64
  export function dateRangeIsValid(startTimestamp, endTimestamp) {
65
65
  if (startTimestamp <= 0 || endTimestamp <= 0) {
66
- return {isValid: false, msg:"start-timestamp and end-timestamp must be greater than 0."};
66
+ return { isValid: false, msg: "start-timestamp and end-timestamp must be greater than 0." };
67
67
  }
68
-
68
+
69
69
  if (startTimestamp >= endTimestamp) {
70
- return {isValid: false, msg:"start-timestamp must be less than end-timestamp."};
70
+ return { isValid: false, msg: "start-timestamp must be less than end-timestamp." };
71
71
  }
72
72
 
73
- return {isValid: true, msg:""};
74
- }
73
+ return { isValid: true, msg: "" };
74
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wlbot",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "A CLI for the WeatherLink Live API.",
5
5
  "keywords": [
6
6
  "Davis Instruments",
@@ -25,24 +25,26 @@
25
25
  "type": "module",
26
26
  "main": "./index.js",
27
27
  "bin": {
28
- "wlbot": "./index.js"
28
+ "wlbot": "index.js"
29
29
  },
30
30
  "repository": {
31
31
  "type": "git",
32
- "url": "https://github.com/mike-weiner/wlbot.git"
32
+ "url": "git+https://github.com/mike-weiner/wlbot.git"
33
33
  },
34
34
  "scripts": {
35
- "test": "mocha"
35
+ "pack:dry": "npm pack --dry-run",
36
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage"
36
37
  },
37
38
  "dependencies": {
38
39
  "axios": "^1.6.3",
39
40
  "chalk": "^5.3.0",
40
- "commander": "^11.1.0",
41
+ "commander": "^12.0.0",
41
42
  "ora": "^8.0.1"
42
43
  },
43
44
  "devDependencies": {
44
- "chai": "^5.0.0",
45
- "mocha": "^10.2.0"
45
+ "@babel/preset-env": "^7.23.7",
46
+ "@types/jest": "^29.5.11",
47
+ "jest": "^29.7.0"
46
48
  },
47
49
  "engines": {
48
50
  "node": ">=16"
@@ -1,108 +0,0 @@
1
- import { buildWeatherLinkApiUrl, checkForRequired, dateRangeIsValid } from '../lib/utils.js';
2
- import { expect } from 'chai';
3
-
4
- describe('buildWeatherLinkApiUrl', () => {
5
- beforeEach(() => {
6
- // Set the environment variables
7
- process.env.WEATHER_LINK_API_KEY = 'sampleKey';
8
- process.env.WEATHER_LINK_API_SECRET = 'sampleSecret';
9
- process.env.WEATHER_LINK_BASE_API_URL = 'https://api.weatherlink.com/v2/';
10
- });
11
-
12
- it('Endpoint: current/13', () => {
13
- expect(
14
- buildWeatherLinkApiUrl(
15
- `current/13`,
16
- {'api-key': process.env.WEATHER_LINK_API_KEY, 'station-id': String(13), 't': String(1660759469)},
17
- {'api-key': process.env.WEATHER_LINK_API_KEY, 't': String(1660759469)}
18
- )
19
- ).to.equal('https://api.weatherlink.com/v2/current/13?api-key=sampleKey&t=1660759469&api-signature=dcf2f0eafc43ec8b6d6a1a7acfc6faa44f9bc1045124d7d6416f2f486ff72e95')
20
- });
21
-
22
- it('Endpoint: stations', () => {
23
- expect(
24
- buildWeatherLinkApiUrl(
25
- 'stations',
26
- {'api-key': process.env.WEATHER_LINK_API_KEY, 't': String(1660757289)},
27
- {'api-key': process.env.WEATHER_LINK_API_KEY, 't': String(1660757289)}
28
- )
29
- ).to.equal('https://api.weatherlink.com/v2/stations?api-key=sampleKey&t=1660757289&api-signature=1663a50336ae4b7d975e322ad010e297d4ec487c5d3d9d4dad1d8a4a9e53d606')
30
- });
31
-
32
- it('Endpoint: stations/13,14,15', () => {
33
- expect(
34
- buildWeatherLinkApiUrl(
35
- `stations/13,14,15`,
36
- {'api-key': process.env.WEATHER_LINK_API_KEY, 'station-ids': '13,14,15', 't': String(1660759608)},
37
- {'api-key': process.env.WEATHER_LINK_API_KEY, 't': String(1660759608)}
38
- )
39
- ).to.equal('https://api.weatherlink.com/v2/stations/13,14,15?api-key=sampleKey&t=1660759608&api-signature=7accbcf70808449f944e5da9e3e06db0aae7362870e7ace8312d5d9e8103d274')
40
- });
41
- });
42
-
43
- describe('checkForRequired', () => {
44
-
45
- beforeEach(() => {
46
- // Set the environment variables
47
- process.env.WEATHER_LINK_API_KEY = 'sampleKey';
48
- process.env.WEATHER_LINK_API_SECRET = 'sampleSecret';
49
- process.env.WEATHER_LINK_BASE_API_URL = 'https://api.weatherlink.com/v2/';
50
- });
51
-
52
- it('Missing All Env Vars', () => {
53
- expect(
54
- checkForRequired(["WEATHER_LINK_VERY_FAKE_NONEXISTENT"])
55
- ).to.deep.equal({"exist": false, "missing": ["WEATHER_LINK_VERY_FAKE_NONEXISTENT"]})
56
- });
57
-
58
- it('All Env Vars Defined', () => {
59
- expect(
60
- checkForRequired(["WEATHER_LINK_API_KEY", "WEATHER_LINK_API_SECRET", "WEATHER_LINK_BASE_API_URL"])
61
- ).to.deep.equal({"exist": true, "missing": []})
62
- });
63
- });
64
-
65
- describe('dateRangeIsValid', () => {
66
-
67
- it('Start Timestamp is Before End Timestamp', () => {
68
- expect(
69
- dateRangeIsValid(1673472399, 1673494000).isValid
70
- ).to.equal(true)
71
- });
72
-
73
- it('Start Timestamp is the Same as End Timestamp', () => {
74
- expect(
75
- dateRangeIsValid(1673494000, 1673494000).isValid
76
- ).to.equal(false)
77
- });
78
-
79
- it('Start Timestamp is After End Timestamp', () => {
80
- expect(
81
- dateRangeIsValid(1673494010, 1673494000).isValid
82
- ).to.equal(false)
83
- });
84
-
85
- it('Start Timestamp is 0', () => {
86
- expect(
87
- dateRangeIsValid(0, 1673494000).isValid
88
- ).to.equal(false)
89
- });
90
-
91
- it('Start Timestamp is Negative', () => {
92
- expect(
93
- dateRangeIsValid(-10, 1673494000).isValid
94
- ).to.equal(false)
95
- });
96
-
97
- it('End Timestamp is 0', () => {
98
- expect(
99
- dateRangeIsValid(1673494010, 0).isValid
100
- ).to.equal(false)
101
- });
102
-
103
- it('End Timestamp is Negative', () => {
104
- expect(
105
- dateRangeIsValid(1673494010, -10).isValid
106
- ).to.equal(false)
107
- });
108
- });