diff --git a/.gitignore b/.gitignore index 301f74a..9497d32 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +# Playground +/dev.js + /node_modules /npm-debug.log -/package-lock.json /benchmark diff --git a/README.md b/README.md index 91f4f82..ca5c4a9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- Huejay + Huejay

# Huejay - Philips Hue client for Node.js @@ -36,6 +36,7 @@ Philips Hue API version supported: **1.19.0** - [Bridge Discovery](#bridge-discovery) - [Errors](#errors) - [Client Usage](#client-usage) + - [Remote API](#using-the-remote-api) - [Users](#users) - [Bridge](#bridge) - [Portal](#portal) @@ -133,6 +134,78 @@ client commands. The *timeout* option applies to bridge commands. The default value is 15000 milliseconds (or 15 seconds). +### Using the Remote API + +Philips provides a hosted API with an identical interface to that of the local bridge API. Using the Remote API allows for bridges and the devices controlling them to be on seperate networks. + +To use it, an OAuth token must be generated first. + +After [adding a new Remote Hue API app](https://developers.meethue.com/my-apps/), open + +`https://api.meethue.com/oauth2/auth?clientid=&appid=&deviceid=&devicename=&state=&response_type=code` + +in your browser to generate an authentication code. + +Parameters: + +| Parameter | Meaning | +|-------------|------------------------------------------------------------| +| client-id | Your app's client ID | +| app-id | Your app ID | +| device-id | Anything you want | +| device-name | Your app's name | +| state | Anything you want, will be passed back in the redirect URL | + +Once a code has been generated, run + +```javascript +const huejay = require('huejay'); + +(async () => { + const token = new huejay.OAuthToken({ + clientId: 'your-client-id', + clientSecret: 'your-client-secret' + }); + + await token.getByCode('your-auth-code'); + + console.log(JSON.stringify(token)) // => your OAuth token +})(); +``` + +to generate an OAuth token. + +You can then use the OAuth token in future requests like so: + +```javascript +const huejay = require('huejay'); + +(async () => { + const token = new huejay.OAuthToken({ + clientId: 'your-client-id', + clientSecret: 'your-client-secret', + accessToken: 'your-access-token', + refreshToken: 'your-refresh-token' + }); + + const client = new huejay.Client({ + remote: true, + oauthToken: token, + username: 'your-bridge-username' + }); + + // Refresh the access token + await token.refresh(); + + // Turn light `1` on + const light = await client.lights.getById(1); + + light.on = true; + + await client.lights.save(light); +})(); +``` + ### Users Huejay provides several commands for managing users on Philips Hue bridges. @@ -413,7 +486,7 @@ client.portal.get() ### Software Update Occasionally, Philips releases new updates for the bridge, lights, and devices. -You can use Huejay to facilitate downloading and installation of updates. +You can use Huejay to facilitate downloading and installation of updates. #### client.softwareUpdate.get - Get software update details @@ -1930,7 +2003,7 @@ Get bridge resource limits and timezones. Retrieve bridge light limits with the command `client.capabilities.lights`. This command will eventually return an object describe the limits of the bridge -around the light resource. +around the light resource. ```js client.capabilities.lights() diff --git a/lib/Action/ChangeGroupAction.js b/lib/Action/ChangeGroupAction.js index 8ef7411..9947f5c 100644 --- a/lib/Action/ChangeGroupAction.js +++ b/lib/Action/ChangeGroupAction.js @@ -63,7 +63,7 @@ class ChangeGroupAction extends AbstractAction { } if (!!withUsername) { - address = `/api/${client.username}${address}`; + address = `${client.username}${address}`; } return { diff --git a/lib/Action/ChangeLightState.js b/lib/Action/ChangeLightState.js index 4b639fe..9a25985 100644 --- a/lib/Action/ChangeLightState.js +++ b/lib/Action/ChangeLightState.js @@ -62,7 +62,7 @@ class ChangeLightState extends AbstractAction { } if (!!withUsername) { - address = `/api/${client.username}${address}`; + address = `${client.username}${address}`; } return { diff --git a/lib/Action/ChangeSensorState.js b/lib/Action/ChangeSensorState.js index 094ea1a..4313de8 100644 --- a/lib/Action/ChangeSensorState.js +++ b/lib/Action/ChangeSensorState.js @@ -46,7 +46,7 @@ class ChangeSensorState extends AbstractAction { } if (!!withUsername) { - address = `/api/${client.username}${address}`; + address = `${client.username}${address}`; } return { diff --git a/lib/Client.js b/lib/Client.js index 23e26b1..ee285c0 100644 --- a/lib/Client.js +++ b/lib/Client.js @@ -1,10 +1,14 @@ 'use strict'; +const OAuthToken = require('./OAuthToken'); + const DEFAULT_CONFIG = { - host: undefined, - port: 80, - username: undefined, - timeout: 15000, + host: undefined, + port: 80, + remote: false, + oauthToken: new OAuthToken(), + username: undefined, + timeout: 15000, }; /** @@ -59,6 +63,42 @@ class Client { this.config.port = Number(port); } + /** + * Get remote + * + * @return {boolean} Remote + */ + get remote() { + return this.config.remote; + } + + /** + * Set remote + * + * @param {boolean} remote Remote + */ + set remote(remote) { + this.config.remote = Boolean(remote); + } + + /** + * Get OAuthToken + * + * @return {string} OAuthToken + */ + get oauthToken() { + return this.config.oauthToken; + } + + /** + * Set OAuthToken + * + * @param {string} oauthToken OAuthToken + */ + set oauthToken(token) { + this.config.oauthToken = token; + } + /** * Get username * @@ -223,7 +263,7 @@ class Client { /** * Get capabilities accessor - * + * * @return {mixed} Capabilities accessor */ get capabilities() { diff --git a/lib/Command/Bridge/EnableLinkButton.js b/lib/Command/Bridge/EnableLinkButton.js index 6797d42..ba7466c 100644 --- a/lib/Command/Bridge/EnableLinkButton.js +++ b/lib/Command/Bridge/EnableLinkButton.js @@ -16,7 +16,7 @@ class EnableLinkButton { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/config`, + url: `${client.username}/config`, data: { 'linkbutton': true } diff --git a/lib/Command/Bridge/EnableTouchlink.js b/lib/Command/Bridge/EnableTouchlink.js index 7318049..1a650b8 100644 --- a/lib/Command/Bridge/EnableTouchlink.js +++ b/lib/Command/Bridge/EnableTouchlink.js @@ -16,7 +16,7 @@ class EnableTouchlink { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/config`, + url: `${client.username}/config`, data: { 'touchlink': true } diff --git a/lib/Command/Bridge/GetBridge.js b/lib/Command/Bridge/GetBridge.js index 87a72bc..d90d75e 100644 --- a/lib/Command/Bridge/GetBridge.js +++ b/lib/Command/Bridge/GetBridge.js @@ -18,8 +18,8 @@ class GetBridge { invoke(client) { let options = { url: client.username !== undefined - ? `api/${client.username}/config` - : 'api/config' + ? `${client.username}/config` + : 'config' }; return client.getTransport() diff --git a/lib/Command/Bridge/IsAuthenticated.js b/lib/Command/Bridge/IsAuthenticated.js index 954e45f..3a1fb6b 100644 --- a/lib/Command/Bridge/IsAuthenticated.js +++ b/lib/Command/Bridge/IsAuthenticated.js @@ -16,7 +16,7 @@ class IsAuthenticated { invoke(client) { let options = { // Time zone retrieval as it requires user and not resource intensive - url: `api/${client.username}/info/timezones` + url: `${client.username}/info/timezones` }; return client.getTransport() diff --git a/lib/Command/Bridge/Ping.js b/lib/Command/Bridge/Ping.js index 3db67d9..4ed5124 100644 --- a/lib/Command/Bridge/Ping.js +++ b/lib/Command/Bridge/Ping.js @@ -15,7 +15,7 @@ class Ping { */ invoke(client) { let options = { - url: 'api/config' + url: 'config' }; return client.getTransport() diff --git a/lib/Command/Bridge/SaveBridge.js b/lib/Command/Bridge/SaveBridge.js index 6e24db8..fe4dc8a 100644 --- a/lib/Command/Bridge/SaveBridge.js +++ b/lib/Command/Bridge/SaveBridge.js @@ -76,7 +76,7 @@ class SaveBridge { saveBridgeAttribute(client, attribute, value) { let options = { method: 'PUT', - url: `api/${client.username}/config`, + url: `${client.username}/config`, data: {} }; diff --git a/lib/Command/Capability/GetGroups.js b/lib/Command/Capability/GetGroups.js index def535b..452ff37 100644 --- a/lib/Command/Capability/GetGroups.js +++ b/lib/Command/Capability/GetGroups.js @@ -15,7 +15,7 @@ class GetGroups { */ invoke(client) { let options = { - url: `api/${client.username}/capabilities`, + url: `${client.username}/capabilities`, raw: true }; diff --git a/lib/Command/Capability/GetLights.js b/lib/Command/Capability/GetLights.js index f0096a7..7ecbdd8 100644 --- a/lib/Command/Capability/GetLights.js +++ b/lib/Command/Capability/GetLights.js @@ -15,7 +15,7 @@ class GetLights { */ invoke(client) { let options = { - url: `api/${client.username}/capabilities`, + url: `${client.username}/capabilities`, raw: true }; diff --git a/lib/Command/Capability/GetResourceLinks.js b/lib/Command/Capability/GetResourceLinks.js index 76754f1..0be85fa 100644 --- a/lib/Command/Capability/GetResourceLinks.js +++ b/lib/Command/Capability/GetResourceLinks.js @@ -15,7 +15,7 @@ class GetResourceLinks { */ invoke(client) { let options = { - url: `api/${client.username}/capabilities`, + url: `${client.username}/capabilities`, raw: true }; diff --git a/lib/Command/Capability/GetRules.js b/lib/Command/Capability/GetRules.js index 94870a2..f3f81fc 100644 --- a/lib/Command/Capability/GetRules.js +++ b/lib/Command/Capability/GetRules.js @@ -15,7 +15,7 @@ class GetRules { */ invoke(client) { let options = { - url: `api/${client.username}/capabilities`, + url: `${client.username}/capabilities`, raw: true }; diff --git a/lib/Command/Capability/GetScenes.js b/lib/Command/Capability/GetScenes.js index 67e74e5..a032759 100644 --- a/lib/Command/Capability/GetScenes.js +++ b/lib/Command/Capability/GetScenes.js @@ -15,7 +15,7 @@ class GetScenes { */ invoke(client) { let options = { - url: `api/${client.username}/capabilities`, + url: `${client.username}/capabilities`, raw: true }; diff --git a/lib/Command/Capability/GetSchedules.js b/lib/Command/Capability/GetSchedules.js index 3d4c760..6480d33 100644 --- a/lib/Command/Capability/GetSchedules.js +++ b/lib/Command/Capability/GetSchedules.js @@ -15,7 +15,7 @@ class GetSchedules { */ invoke(client) { let options = { - url: `api/${client.username}/capabilities`, + url: `${client.username}/capabilities`, raw: true }; diff --git a/lib/Command/Capability/GetSensors.js b/lib/Command/Capability/GetSensors.js index 38f9b4d..e3a90b8 100644 --- a/lib/Command/Capability/GetSensors.js +++ b/lib/Command/Capability/GetSensors.js @@ -15,7 +15,7 @@ class GetSensors { */ invoke(client) { let options = { - url: `api/${client.username}/capabilities`, + url: `${client.username}/capabilities`, raw: true }; diff --git a/lib/Command/Capability/GetTimeZones.js b/lib/Command/Capability/GetTimeZones.js index fee122b..7f13869 100644 --- a/lib/Command/Capability/GetTimeZones.js +++ b/lib/Command/Capability/GetTimeZones.js @@ -15,7 +15,7 @@ class GetTimeZones { */ invoke(client) { let options = { - url: `api/${client.username}/capabilities`, + url: `${client.username}/capabilities`, raw: true }; diff --git a/lib/Command/Group/CreateGroup.js b/lib/Command/Group/CreateGroup.js index d2ef001..e8e1e21 100644 --- a/lib/Command/Group/CreateGroup.js +++ b/lib/Command/Group/CreateGroup.js @@ -36,7 +36,7 @@ class CreateGroup { invoke(client) { let options = { method: 'POST', - url: `api/${client.username}/groups`, + url: `${client.username}/groups`, data: {} }; diff --git a/lib/Command/Group/DeleteGroup.js b/lib/Command/Group/DeleteGroup.js index 4ad424b..7d53bf8 100644 --- a/lib/Command/Group/DeleteGroup.js +++ b/lib/Command/Group/DeleteGroup.js @@ -25,7 +25,7 @@ class DeleteGroup { invoke(client) { let options = { method: 'DELETE', - url: `api/${client.username}/groups/${this.groupId}` + url: `${client.username}/groups/${this.groupId}` }; return client.getTransport() diff --git a/lib/Command/Group/GetGroup.js b/lib/Command/Group/GetGroup.js index 39fd236..2647274 100644 --- a/lib/Command/Group/GetGroup.js +++ b/lib/Command/Group/GetGroup.js @@ -26,7 +26,7 @@ class GetGroup { */ invoke(client) { let options = { - url: `api/${client.username}/groups/${this.groupId}` + url: `${client.username}/groups/${this.groupId}` }; return client.getTransport() diff --git a/lib/Command/Group/GetGroups.js b/lib/Command/Group/GetGroups.js index 5c63695..fc517b3 100644 --- a/lib/Command/Group/GetGroups.js +++ b/lib/Command/Group/GetGroups.js @@ -17,7 +17,7 @@ class GetGroups { */ invoke(client) { let options = { - url: `api/${client.username}/groups` + url: `${client.username}/groups` }; return client.getTransport() diff --git a/lib/Command/Group/SaveGroup.js b/lib/Command/Group/SaveGroup.js index aa3bc36..aec677f 100644 --- a/lib/Command/Group/SaveGroup.js +++ b/lib/Command/Group/SaveGroup.js @@ -34,7 +34,7 @@ class SaveGroup { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/groups/${this.group.id}`, + url: `${client.username}/groups/${this.group.id}`, data: {} }; diff --git a/lib/Command/Group/SaveGroupAction.js b/lib/Command/Group/SaveGroupAction.js index ffba11f..ec313cf 100644 --- a/lib/Command/Group/SaveGroupAction.js +++ b/lib/Command/Group/SaveGroupAction.js @@ -47,7 +47,7 @@ class SaveGroupAction { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/groups/${this.group.id}/action`, + url: `${client.username}/groups/${this.group.id}/action`, data: {}, multi: true }; diff --git a/lib/Command/InternetServices/GetInternetServices.js b/lib/Command/InternetServices/GetInternetServices.js index 340c56a..2708fb0 100644 --- a/lib/Command/InternetServices/GetInternetServices.js +++ b/lib/Command/InternetServices/GetInternetServices.js @@ -17,7 +17,7 @@ class GetInternetServices { */ invoke(client) { let options = { - url: `api/${client.username}/config` + url: `${client.username}/config` }; return client.getTransport() diff --git a/lib/Command/Light/DeleteLight.js b/lib/Command/Light/DeleteLight.js index f9e209a..94a5a2c 100644 --- a/lib/Command/Light/DeleteLight.js +++ b/lib/Command/Light/DeleteLight.js @@ -25,7 +25,7 @@ class DeleteLight { invoke(client) { let options = { method: 'DELETE', - url: `api/${client.username}/lights/${this.lightId}` + url: `${client.username}/lights/${this.lightId}` }; return client.getTransport() diff --git a/lib/Command/Light/GetLight.js b/lib/Command/Light/GetLight.js index 249e43d..80094de 100644 --- a/lib/Command/Light/GetLight.js +++ b/lib/Command/Light/GetLight.js @@ -26,7 +26,7 @@ class GetLight { */ invoke(client) { let options = { - url: `api/${client.username}/lights/${this.lightId}` + url: `${client.username}/lights/${this.lightId}` }; return client.getTransport() diff --git a/lib/Command/Light/GetLights.js b/lib/Command/Light/GetLights.js index 339c3ae..9a63570 100644 --- a/lib/Command/Light/GetLights.js +++ b/lib/Command/Light/GetLights.js @@ -17,7 +17,7 @@ class GetLights { */ invoke(client) { let options = { - url: `api/${client.username}/lights` + url: `${client.username}/lights` }; return client.getTransport() diff --git a/lib/Command/Light/GetNewLights.js b/lib/Command/Light/GetNewLights.js index 8d75b01..ba5c4b8 100644 --- a/lib/Command/Light/GetNewLights.js +++ b/lib/Command/Light/GetNewLights.js @@ -17,7 +17,7 @@ class GetNewLights { */ invoke(client) { let options = { - url: `api/${client.username}/lights/new` + url: `${client.username}/lights/new` }; return client.getTransport() diff --git a/lib/Command/Light/SaveLight.js b/lib/Command/Light/SaveLight.js index f778f24..990fa22 100644 --- a/lib/Command/Light/SaveLight.js +++ b/lib/Command/Light/SaveLight.js @@ -66,7 +66,7 @@ class SaveLight { saveLightAttribute(client, attribute, value) { let options = { method: 'PUT', - url: `api/${client.username}/lights/${this.light.id}`, + url: `${client.username}/lights/${this.light.id}`, data: {} }; diff --git a/lib/Command/Light/SaveLightState.js b/lib/Command/Light/SaveLightState.js index b28da89..7fb5273 100644 --- a/lib/Command/Light/SaveLightState.js +++ b/lib/Command/Light/SaveLightState.js @@ -46,7 +46,7 @@ class SaveLightState { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/lights/${this.light.id}/state`, + url: `${client.username}/lights/${this.light.id}/state`, data: {}, multi: true }; diff --git a/lib/Command/Light/StartLightScan.js b/lib/Command/Light/StartLightScan.js index 036f133..3865176 100644 --- a/lib/Command/Light/StartLightScan.js +++ b/lib/Command/Light/StartLightScan.js @@ -16,7 +16,7 @@ class StartLightScan { invoke(client) { let options = { method: 'POST', - url: `api/${client.username}/lights` + url: `${client.username}/lights` }; return client.getTransport() diff --git a/lib/Command/Portal/GetPortal.js b/lib/Command/Portal/GetPortal.js index fab9b6a..131b3ac 100644 --- a/lib/Command/Portal/GetPortal.js +++ b/lib/Command/Portal/GetPortal.js @@ -17,7 +17,7 @@ class GetPortal { */ invoke(client) { let options = { - url: `api/${client.username}/config` + url: `${client.username}/config` }; return client.getTransport() diff --git a/lib/Command/ResourceLinks/CreateResourceLink.js b/lib/Command/ResourceLinks/CreateResourceLink.js index ef82f13..3b2bab6 100644 --- a/lib/Command/ResourceLinks/CreateResourceLink.js +++ b/lib/Command/ResourceLinks/CreateResourceLink.js @@ -37,7 +37,7 @@ class CreateResourceLink { invoke(client) { let options = { method: 'POST', - url: `api/${client.username}/resourcelinks`, + url: `${client.username}/resourcelinks`, data: {} }; diff --git a/lib/Command/ResourceLinks/DeleteResourceLink.js b/lib/Command/ResourceLinks/DeleteResourceLink.js index 2946b22..f628ab2 100644 --- a/lib/Command/ResourceLinks/DeleteResourceLink.js +++ b/lib/Command/ResourceLinks/DeleteResourceLink.js @@ -25,7 +25,7 @@ class DeleteResourceLink { invoke(client) { let options = { method: 'DELETE', - url: `api/${client.username}/resourcelinks/${this.resourceLinkId}` + url: `${client.username}/resourcelinks/${this.resourceLinkId}` }; return client.getTransport() diff --git a/lib/Command/ResourceLinks/GetResourceLink.js b/lib/Command/ResourceLinks/GetResourceLink.js index de61993..f33184b 100644 --- a/lib/Command/ResourceLinks/GetResourceLink.js +++ b/lib/Command/ResourceLinks/GetResourceLink.js @@ -26,7 +26,7 @@ class GetResourceLink { */ invoke(client) { let options = { - url: `api/${client.username}/resourcelinks/${this.resourceLinkId}` + url: `${client.username}/resourcelinks/${this.resourceLinkId}` }; return client.getTransport() diff --git a/lib/Command/ResourceLinks/GetResourceLinks.js b/lib/Command/ResourceLinks/GetResourceLinks.js index b77f014..fc6332e 100644 --- a/lib/Command/ResourceLinks/GetResourceLinks.js +++ b/lib/Command/ResourceLinks/GetResourceLinks.js @@ -17,7 +17,7 @@ class GetResourceLinks { */ invoke(client) { let options = { - url: `api/${client.username}/resourcelinks` + url: `${client.username}/resourcelinks` }; return client.getTransport() diff --git a/lib/Command/ResourceLinks/SaveResourceLink.js b/lib/Command/ResourceLinks/SaveResourceLink.js index 31ee87b..358e77c 100644 --- a/lib/Command/ResourceLinks/SaveResourceLink.js +++ b/lib/Command/ResourceLinks/SaveResourceLink.js @@ -35,7 +35,7 @@ class SaveResourceLink { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/resourcelinks/${this.resourceLink.id}`, + url: `${client.username}/resourcelinks/${this.resourceLink.id}`, data: {} }; diff --git a/lib/Command/Rule/CreateRule.js b/lib/Command/Rule/CreateRule.js index 2974e2e..e04fef5 100644 --- a/lib/Command/Rule/CreateRule.js +++ b/lib/Command/Rule/CreateRule.js @@ -36,7 +36,7 @@ class CreateRule { invoke(client) { let options = { method: 'POST', - url: `api/${client.username}/rules`, + url: `${client.username}/rules`, data: {} }; diff --git a/lib/Command/Rule/DeleteRule.js b/lib/Command/Rule/DeleteRule.js index 391f350..550688b 100644 --- a/lib/Command/Rule/DeleteRule.js +++ b/lib/Command/Rule/DeleteRule.js @@ -25,7 +25,7 @@ class DeleteRule { invoke(client) { let options = { method: 'DELETE', - url: `api/${client.username}/rules/${this.ruleId}` + url: `${client.username}/rules/${this.ruleId}` }; return client.getTransport() diff --git a/lib/Command/Rule/GetRule.js b/lib/Command/Rule/GetRule.js index 4cb2656..5ee6d3b 100644 --- a/lib/Command/Rule/GetRule.js +++ b/lib/Command/Rule/GetRule.js @@ -26,7 +26,7 @@ class GetRule { */ invoke(client) { let options = { - url: `api/${client.username}/rules/${this.ruleId}` + url: `${client.username}/rules/${this.ruleId}` }; return client.getTransport() diff --git a/lib/Command/Rule/GetRules.js b/lib/Command/Rule/GetRules.js index 010f729..51d35c7 100644 --- a/lib/Command/Rule/GetRules.js +++ b/lib/Command/Rule/GetRules.js @@ -17,7 +17,7 @@ class GetRules { */ invoke(client) { let options = { - url: `api/${client.username}/rules` + url: `${client.username}/rules` }; return client.getTransport() diff --git a/lib/Command/Rule/SaveRule.js b/lib/Command/Rule/SaveRule.js index 3d78f77..04af5d2 100644 --- a/lib/Command/Rule/SaveRule.js +++ b/lib/Command/Rule/SaveRule.js @@ -36,7 +36,7 @@ class SaveRule { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/rules/${this.rule.id}`, + url: `${client.username}/rules/${this.rule.id}`, data: {} }; diff --git a/lib/Command/Scene/CreateScene.js b/lib/Command/Scene/CreateScene.js index a124498..e4fc436 100644 --- a/lib/Command/Scene/CreateScene.js +++ b/lib/Command/Scene/CreateScene.js @@ -37,7 +37,7 @@ class CreateScene { invoke(client) { let options = { method: 'POST', - url: `api/${client.username}/scenes`, + url: `${client.username}/scenes`, data: {} }; @@ -71,7 +71,7 @@ class CreateScene { reloadSceneAttributes(client) { return client.getTransport() .sendRequest({ - url: `api/${client.username}/scenes/${this.scene.id}` + url: `${client.username}/scenes/${this.scene.id}` }) .then(result => { this.scene.attributes.replace( diff --git a/lib/Command/Scene/DeleteScene.js b/lib/Command/Scene/DeleteScene.js index 4ec44c1..057c248 100644 --- a/lib/Command/Scene/DeleteScene.js +++ b/lib/Command/Scene/DeleteScene.js @@ -25,7 +25,7 @@ class DeleteScene { invoke(client) { let options = { method: 'DELETE', - url: `api/${client.username}/scenes/${this.sceneId}` + url: `${client.username}/scenes/${this.sceneId}` }; return client.getTransport() diff --git a/lib/Command/Scene/GetSceneById.js b/lib/Command/Scene/GetSceneById.js index c897c67..e1c9bde 100644 --- a/lib/Command/Scene/GetSceneById.js +++ b/lib/Command/Scene/GetSceneById.js @@ -26,7 +26,7 @@ class GetSceneById { */ invoke(client) { let options = { - url: `api/${client.username}/scenes/${this.sceneId}` + url: `${client.username}/scenes/${this.sceneId}` }; return client.getTransport() diff --git a/lib/Command/Scene/GetScenes.js b/lib/Command/Scene/GetScenes.js index 2ce0d30..b7dcb0b 100644 --- a/lib/Command/Scene/GetScenes.js +++ b/lib/Command/Scene/GetScenes.js @@ -17,7 +17,7 @@ class GetScenes { */ invoke(client) { let options = { - url: `api/${client.username}/scenes` + url: `${client.username}/scenes` }; return client.getTransport() diff --git a/lib/Command/Scene/RecallScene.js b/lib/Command/Scene/RecallScene.js index 1c7014c..e774805 100644 --- a/lib/Command/Scene/RecallScene.js +++ b/lib/Command/Scene/RecallScene.js @@ -25,7 +25,7 @@ class RecallScene { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/groups/0/action`, + url: `${client.username}/groups/0/action`, data: { scene: this.sceneId } diff --git a/lib/Command/Scene/SaveScene.js b/lib/Command/Scene/SaveScene.js index 583f43c..08ea7a9 100644 --- a/lib/Command/Scene/SaveScene.js +++ b/lib/Command/Scene/SaveScene.js @@ -38,7 +38,7 @@ class SaveScene { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/scenes/${this.scene.id}`, + url: `${client.username}/scenes/${this.scene.id}`, data: {} }; @@ -68,7 +68,7 @@ class SaveScene { reloadSceneAttributes(client) { return client.getTransport() .sendRequest({ - url: `api/${client.username}/scenes/${this.scene.id}` + url: `${client.username}/scenes/${this.scene.id}` }) .then(result => { this.scene.attributes.replace( diff --git a/lib/Command/Scene/SaveSceneLightState.js b/lib/Command/Scene/SaveSceneLightState.js index f4bc72d..de87359 100644 --- a/lib/Command/Scene/SaveSceneLightState.js +++ b/lib/Command/Scene/SaveSceneLightState.js @@ -65,7 +65,7 @@ class SaveSceneLightState { saveLightState(client, lightId, state) { let options = { method: 'PUT', - url: `api/${client.username}/scenes/${this.scene.id}/lightstates/${lightId}`, + url: `${client.username}/scenes/${this.scene.id}/lightstates/${lightId}`, data: {} }; diff --git a/lib/Command/Schedule/CreateSchedule.js b/lib/Command/Schedule/CreateSchedule.js index a8e0e5d..5c8a065 100644 --- a/lib/Command/Schedule/CreateSchedule.js +++ b/lib/Command/Schedule/CreateSchedule.js @@ -38,7 +38,7 @@ class CreateSchedule { invoke(client) { let options = { method: 'POST', - url: `api/${client.username}/schedules`, + url: `${client.username}/schedules`, data: {} }; diff --git a/lib/Command/Schedule/DeleteSchedule.js b/lib/Command/Schedule/DeleteSchedule.js index 62b5e15..5181802 100644 --- a/lib/Command/Schedule/DeleteSchedule.js +++ b/lib/Command/Schedule/DeleteSchedule.js @@ -25,7 +25,7 @@ class DeleteSchedule { invoke(client) { let options = { method: 'DELETE', - url: `api/${client.username}/schedules/${this.scheduleId}` + url: `${client.username}/schedules/${this.scheduleId}` }; return client.getTransport() diff --git a/lib/Command/Schedule/GetSchedule.js b/lib/Command/Schedule/GetSchedule.js index 81d6fde..3fc08b6 100644 --- a/lib/Command/Schedule/GetSchedule.js +++ b/lib/Command/Schedule/GetSchedule.js @@ -26,7 +26,7 @@ class GetSchedule { */ invoke(client) { let options = { - url: `api/${client.username}/schedules/${this.scheduleId}` + url: `${client.username}/schedules/${this.scheduleId}` }; return client.getTransport() diff --git a/lib/Command/Schedule/GetSchedules.js b/lib/Command/Schedule/GetSchedules.js index 1f9a257..ba45ab7 100644 --- a/lib/Command/Schedule/GetSchedules.js +++ b/lib/Command/Schedule/GetSchedules.js @@ -17,7 +17,7 @@ class GetSchedules { */ invoke(client) { let options = { - url: `api/${client.username}/schedules` + url: `${client.username}/schedules` }; return client.getTransport() diff --git a/lib/Command/Schedule/SaveSchedule.js b/lib/Command/Schedule/SaveSchedule.js index c938fde..8c85821 100644 --- a/lib/Command/Schedule/SaveSchedule.js +++ b/lib/Command/Schedule/SaveSchedule.js @@ -38,7 +38,7 @@ class SaveSchedule { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/schedules/${this.schedule.id}`, + url: `${client.username}/schedules/${this.schedule.id}`, data: {} }; diff --git a/lib/Command/Sensor/CreateSensor.js b/lib/Command/Sensor/CreateSensor.js index 002cce6..db117be 100644 --- a/lib/Command/Sensor/CreateSensor.js +++ b/lib/Command/Sensor/CreateSensor.js @@ -38,7 +38,7 @@ class CreateSensor { invoke(client) { let options = { method: 'POST', - url: `api/${client.username}/sensors`, + url: `${client.username}/sensors`, data: { config: this.sensor.config.attributes.getAll(), state: this.sensor.state.attributes.getAll() diff --git a/lib/Command/Sensor/DeleteSensor.js b/lib/Command/Sensor/DeleteSensor.js index 85f4ea5..28a0ec5 100644 --- a/lib/Command/Sensor/DeleteSensor.js +++ b/lib/Command/Sensor/DeleteSensor.js @@ -25,7 +25,7 @@ class DeleteSensor { invoke(client) { let options = { method: 'DELETE', - url: `api/${client.username}/sensors/${this.sensorId}` + url: `${client.username}/sensors/${this.sensorId}` }; return client.getTransport() diff --git a/lib/Command/Sensor/GetNewSensors.js b/lib/Command/Sensor/GetNewSensors.js index 570ddea..30edfcd 100644 --- a/lib/Command/Sensor/GetNewSensors.js +++ b/lib/Command/Sensor/GetNewSensors.js @@ -17,7 +17,7 @@ class GetNewSensors { */ invoke(client) { let options = { - url: `api/${client.username}/sensors/new` + url: `${client.username}/sensors/new` }; return client.getTransport() diff --git a/lib/Command/Sensor/GetSensor.js b/lib/Command/Sensor/GetSensor.js index 6d60058..d6491fb 100644 --- a/lib/Command/Sensor/GetSensor.js +++ b/lib/Command/Sensor/GetSensor.js @@ -26,7 +26,7 @@ class GetSensor { */ invoke(client) { let options = { - url: `api/${client.username}/sensors/${this.sensorId}` + url: `${client.username}/sensors/${this.sensorId}` }; return client.getTransport() diff --git a/lib/Command/Sensor/GetSensors.js b/lib/Command/Sensor/GetSensors.js index f608185..d2bdb18 100644 --- a/lib/Command/Sensor/GetSensors.js +++ b/lib/Command/Sensor/GetSensors.js @@ -17,7 +17,7 @@ class GetSensors { */ invoke(client) { let options = { - url: `api/${client.username}/sensors` + url: `${client.username}/sensors` }; return client.getTransport() diff --git a/lib/Command/Sensor/SaveSensor.js b/lib/Command/Sensor/SaveSensor.js index f906bf9..8c1880d 100644 --- a/lib/Command/Sensor/SaveSensor.js +++ b/lib/Command/Sensor/SaveSensor.js @@ -62,7 +62,7 @@ class SaveSensor { saveSensorAttribute(client, attribute, value) { let options = { method: 'PUT', - url: `api/${client.username}/sensors/${this.sensor.id}`, + url: `${client.username}/sensors/${this.sensor.id}`, data: {} }; diff --git a/lib/Command/Sensor/SaveSensorConfig.js b/lib/Command/Sensor/SaveSensorConfig.js index ddf6224..937a396 100644 --- a/lib/Command/Sensor/SaveSensorConfig.js +++ b/lib/Command/Sensor/SaveSensorConfig.js @@ -29,7 +29,7 @@ class SaveSensorConfig { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/sensors/${this.sensor.id}/config`, + url: `${client.username}/sensors/${this.sensor.id}/config`, data: this.sensor.config.attributes.getChanged() }; diff --git a/lib/Command/Sensor/SaveSensorState.js b/lib/Command/Sensor/SaveSensorState.js index 9aadea6..b0d5e9d 100644 --- a/lib/Command/Sensor/SaveSensorState.js +++ b/lib/Command/Sensor/SaveSensorState.js @@ -29,7 +29,7 @@ class SaveSensorState { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/sensors/${this.sensor.id}/state`, + url: `${client.username}/sensors/${this.sensor.id}/state`, data: this.sensor.state.attributes.getChanged() }; diff --git a/lib/Command/Sensor/StartSensorScan.js b/lib/Command/Sensor/StartSensorScan.js index 9e30550..6e10d23 100644 --- a/lib/Command/Sensor/StartSensorScan.js +++ b/lib/Command/Sensor/StartSensorScan.js @@ -16,7 +16,7 @@ class StartSensorScan { invoke(client) { let options = { method: 'POST', - url: `api/${client.username}/sensors` + url: `${client.username}/sensors` }; return client.getTransport() diff --git a/lib/Command/SoftwareUpdate/CheckForSoftwareUpdates.js b/lib/Command/SoftwareUpdate/CheckForSoftwareUpdates.js index 37a7628..22d22df 100644 --- a/lib/Command/SoftwareUpdate/CheckForSoftwareUpdates.js +++ b/lib/Command/SoftwareUpdate/CheckForSoftwareUpdates.js @@ -16,7 +16,7 @@ class CheckForSoftwareUpdates { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/config`, + url: `${client.username}/config`, data: { 'swupdate': { 'checkforupdate': true diff --git a/lib/Command/SoftwareUpdate/DisableInstallNotification.js b/lib/Command/SoftwareUpdate/DisableInstallNotification.js index e3ad24a..7c25096 100644 --- a/lib/Command/SoftwareUpdate/DisableInstallNotification.js +++ b/lib/Command/SoftwareUpdate/DisableInstallNotification.js @@ -16,7 +16,7 @@ class DisableInstallNotification { invoke(client) { let options = { method: 'PUT', - url: `api/${client.username}/config`, + url: `${client.username}/config`, data: { 'swupdate': { 'notify': false diff --git a/lib/Command/SoftwareUpdate/GetSoftwareUpdate.js b/lib/Command/SoftwareUpdate/GetSoftwareUpdate.js index b746f9e..ccefc9c 100644 --- a/lib/Command/SoftwareUpdate/GetSoftwareUpdate.js +++ b/lib/Command/SoftwareUpdate/GetSoftwareUpdate.js @@ -17,7 +17,7 @@ class GetSoftwareUpdate { */ invoke(client) { let options = { - url: `api/${client.username}/config` + url: `${client.username}/config` }; return client.getTransport() diff --git a/lib/Command/SoftwareUpdate/InstallSoftwareUpdates.js b/lib/Command/SoftwareUpdate/InstallSoftwareUpdates.js index ffc7197..66491e0 100644 --- a/lib/Command/SoftwareUpdate/InstallSoftwareUpdates.js +++ b/lib/Command/SoftwareUpdate/InstallSoftwareUpdates.js @@ -16,7 +16,7 @@ class InstallSoftwareUpdates { invoke(client) { let options = { method: 'PUT', - url : `api/${client.username}/config`, + url : `${client.username}/config`, data: { 'swupdate': { 'updatestate': 3 diff --git a/lib/Command/User/CreateUser.js b/lib/Command/User/CreateUser.js index bc1aacc..08e44c2 100644 --- a/lib/Command/User/CreateUser.js +++ b/lib/Command/User/CreateUser.js @@ -30,7 +30,7 @@ class CreateUser { invoke(client) { let options = { method: 'POST', - url: 'api', + url: '', data: { 'devicetype': this.user.deviceType } diff --git a/lib/Command/User/DeleteUser.js b/lib/Command/User/DeleteUser.js index 4d7b46a..7c40921 100644 --- a/lib/Command/User/DeleteUser.js +++ b/lib/Command/User/DeleteUser.js @@ -25,7 +25,7 @@ class DeleteUser { invoke(client) { let options = { method: 'DELETE', - url: `api/${client.username}/config/whitelist/${this.username}` + url: `${client.username}/config/whitelist/${this.username}` }; return client.getTransport() diff --git a/lib/Command/User/GetUser.js b/lib/Command/User/GetUser.js index 99a1daf..3b08b5c 100644 --- a/lib/Command/User/GetUser.js +++ b/lib/Command/User/GetUser.js @@ -27,7 +27,7 @@ class GetUser { */ invoke(client) { let options = { - url: `api/${client.username}/config` + url: `${client.username}/config` }; return client.getTransport() diff --git a/lib/Command/User/GetUsers.js b/lib/Command/User/GetUsers.js index c0fa586..3074125 100644 --- a/lib/Command/User/GetUsers.js +++ b/lib/Command/User/GetUsers.js @@ -17,7 +17,7 @@ class GetUsers { */ invoke(client) { let options = { - url: `api/${client.username}/config` + url: `${client.username}/config` }; return client.getTransport() diff --git a/lib/Huejay.js b/lib/Huejay.js index c24b80b..370a6b9 100644 --- a/lib/Huejay.js +++ b/lib/Huejay.js @@ -1,8 +1,9 @@ 'use strict'; module.exports = { - version: require('../package.json').version, - discover: require('./Discovery').discoverBridges, - Client: require('./Client'), - Error: require('./Error') + version: require('../package.json').version, + discover: require('./Discovery').discoverBridges, + Client: require('./Client'), + OAuthToken: require('./OAuthToken'), + Error: require('./Error') }; diff --git a/lib/OAuthToken.js b/lib/OAuthToken.js new file mode 100644 index 0000000..a464a34 --- /dev/null +++ b/lib/OAuthToken.js @@ -0,0 +1,154 @@ +'use strict'; + +const axios = require('axios'); +const qs = require('querystring'); +const HuejayError = require('./Error'); + +const DEFAULT_CONFIG = { + clientId: undefined, + clientSecret: undefined, + accessToken: undefined, + refreshToken: undefined, + accessTokenExpiryDate: undefined, + refreshTokenExpiryDate: undefined +}; + +/** + * OAuthToken + * + * Stores an OAuthToken to use when + * querying the remote API. + */ +class OAuthToken { + /** + * Constructor + * + * @param {Object} config Configuration + */ + constructor(config) { + this.config = Object.assign({}, DEFAULT_CONFIG, config); + } + + _expiresInSecondsToDate(seconds) { + return new Date(new Date().getTime() + Number(seconds) * 1000); + } + + _setTokenFromResponse(data) { + this.accessToken = data.access_token; + this.refreshToken = data.refresh_token; + + this.accessTokenExpiryDate = this._expiresInSecondsToDate(data.access_token_expires_in); + this.refreshTokenExpiryDate = this._expiresInSecondsToDate(data.refresh_token_expires_in); + } + + toJSON() { + return this.config; + } + + async refresh() { + try { + const res = await axios.post( + 'https://api.meethue.com/oauth2/refresh', + qs.stringify({ + refresh_token: this.config.refreshToken + }), + { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + auth: { + username: this.config.clientId, + password: this.config.clientSecret + }, + params: { + grant_type: 'refresh_token' + } + } + ); + + this._setTokenFromResponse(res.data); + + return this; + } catch (error) { + throw new HuejayError({ + message: error.message + }); + } + } + + async getByCode(code) { + try { + const res = await axios.post( + 'https://api.meethue.com/oauth2/token', {}, + { + auth: { + username: this.config.clientId, + password: this.config.clientSecret + }, + params: { + grant_type: 'authorization_code', + code + } + } + ); + + this._setTokenFromResponse(res.data); + + return this; + } catch (error) { + throw new HuejayError({ + message: error.message + }); + } + } + + get clientId() { + return this.config.clientId; + } + + set clientId(clientId) { + this.config.clientId = String(clientId); + } + + get clientSecret() { + return this.config.clientSecret; + } + + set clientSecret(clientSecret) { + this.config.clientSecret = String(clientSecret); + } + + get accessToken() { + return this.config.accessToken; + } + + set accessToken(token) { + this.config.accessToken = String(token); + } + + get refreshToken() { + return this.config.refreshToken; + } + + set refreshToken(token) { + this.config.refreshToken = String(token); + } + + get accessTokenExpiryDate() { + return this.config.accessTokenExpiryDate; + } + + set accessTokenExpiryDate(date) { + this.config.accessTokenExpiryDate = new Date(date); + } + + get refreshTokenExpiryDate() { + return this.config.refreshTokenExpiryDate; + } + + set refreshTokenExpiryDate(date) { + this.config.refreshTokenExpiryDate = new Date(date); + } +} + +module.exports = OAuthToken; diff --git a/lib/Transport.js b/lib/Transport.js index 1d0b568..4e3bfeb 100644 --- a/lib/Transport.js +++ b/lib/Transport.js @@ -1,7 +1,6 @@ 'use strict'; let axios = require('axios'); -let path = require('path'); let HuejayError = require('./Error'); /** @@ -25,8 +24,8 @@ class Transport { * @return {mixed} Axios http client */ getHttpClient() { - let httpClient = axios.create({ - baseURL: `http://${this.client.host}:${this.client.port}/`, + const clientOptions = { + baseURL: `http://${this.client.host}:${this.client.port}/api/`, headers: { 'Content-Type': 'application/json' }, @@ -37,9 +36,16 @@ class Transport { } ], responseType: 'json', - }); + }; - return httpClient; + if (this.client.remote) { + clientOptions.baseURL = `https://api.meethue.com/bridge/`; + + // Add authorization header + clientOptions.headers.Authorization = `Bearer ${this.client.oauthToken.accessToken}`; + } + + return axios.create(clientOptions); } /** diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..fc0d588 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1194 @@ +{ + "name": "huejay", + "version": "1.9.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@sinonjs/commons": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", + "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", + "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash": "^4.17.11" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } + } + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "requires": { + "check-error": "^1.0.2" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==" + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "lolex": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.2.0.tgz", + "integrity": "sha512-gKO5uExCXvSm6zbF562EvM+rd1kQDnB9AZBbiQVzf1ZmdDpxUSvpnAaVOP83N/31mRK8Ml8/VE8DMvsAZQ+7wg==", + "dev": true + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", + "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "mockery": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mockery/-/mockery-2.1.0.tgz", + "integrity": "sha512-9VkOmxKlWXoDO/h1jDZaS4lH33aWfRiJiNT/tKj+8OGzrcFDLo8d0syGdbsc3Bc4GvRXPb+NMMvojotmuGJTvA==", + "dev": true + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "nise": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.1.tgz", + "integrity": "sha512-edFWm0fsFG2n318rfEnKlTZTkjlbVOFF9XIA+fj+Ed+Qz1laYW2lobwavWoMzGrYDHH1EpiNJgDfvGnkZztR/g==", + "dev": true, + "requires": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^4.1.0", + "path-to-regexp": "^1.7.0" + } + }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sinon": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.4.1.tgz", + "integrity": "sha512-7s9buHGHN/jqoy/v4bJgmt0m1XEkCEd/tqdHXumpBp0JSujaT4Ng84JU5wDdK4E85ZMq78NuDe0I3NAqXY8TFg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.2", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.1", + "supports-color": "^5.5.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", + "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.11", + "yargs": "^12.0.5" + }, + "dependencies": { + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + } + } +} diff --git a/package.json b/package.json index d97e3fe..146f73b 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,9 @@ "test": "mocha" }, "dependencies": { - "moment": "^2.24.0", "axios": "^0.18.0", + "moment": "^2.24.0", + "querystring": "^0.2.0", "sprintf-js": "^1.1.2" }, "devDependencies": {