diff --git a/.eslintrc.json b/.eslintrc.json index 9369a59..436a2b2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,42 +1,42 @@ -{ - "env": { - "browser": true, - "commonjs": true, - "node": true, - "es6": true, - "mocha": true - }, - "extends": "eslint:recommended", - "parserOptions": { - "sourceType": "module", - "ecmaVersion": 6 - }, - "rules": { - "indent": [ - "warn", - 4 - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "warn", - "double" - ], - "semi": [ - "warn", - "always" - ], - "no-unused-vars": [ - "warn" - ], - "no-var": 2, - "require-yield": [ - 0 - ], - "no-cond-assign": [ - 0 - ] - } +{ + "env": { + "browser": true, + "commonjs": true, + "node": true, + "es6": true, + "mocha": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "sourceType": "module", + "ecmaVersion": 6 + }, + "rules": { + "indent": [ + "warn", + 4 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "warn", + "double" + ], + "semi": [ + "warn", + "always" + ], + "no-unused-vars": [ + "warn" + ], + "no-var": 2, + "require-yield": [ + 0 + ], + "no-cond-assign": [ + 0 + ] + } } \ No newline at end of file diff --git a/.gitignore b/.gitignore index dd849a7..a7b4881 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ -node_modules -.vscode -coverage -typings -.nyc_output -*.map -.env -.DS_Store -.idea +node_modules +.vscode +coverage +typings +.nyc_output +*.map +.env +.DS_Store +.idea *.markdownlint* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d1c1326..5fc1589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,172 +1,172 @@ -# CHANGELOG - -## [2.6.0] - 2019/11/19 -- Fix search user by username or email on`kata invite-member` and `kata impersonate`command ([#133](https://github.com/kata-ai/kata-cli/pull/133), [#139](https://github.com/kata-ai/kata-cli/pull/139)) - -## [2.5.0] - 2019/09/02 -- Fix bug when switch to team during in impersonate mode ([#126](https://github.com/kata-ai/kata-cli/pull/126)) -- Add feature to select project name inline ([#127](https://github.com/kata-ai/kata-cli/pull/127)) -- Add handler to display notification message when error happened, instead of letting string quotes `''` pop up ([#128](https://github.com/kata-ai/kata-cli/pull/128)) - -## [2.4.0] - 2019/07/12 -- Add missing feature so that Kata-CLI is aligned with Platform. (#122) - - For the sake of consistency, we renamed several commands, such as: - - `kata add-channel` to `kata create-channel` - - `kata edit-channel` to `kata update-channel` - - `kata config-view` to `kata view-config` - - `kata add-member` to `kata invite-member` -- Add feature: impersonate user when logging in as administrator (#121) - -## [2.3.0] - 2019/04/16 -- Improved user experience for update-environment command (#120) - -## [2.2.0] - 2019/03/20 -- Improved user experience for update-environment command (#114) -- Add 20 character limit validation for environment URL and project name (#115) -- Improved error message for missing NLU.yml (#117) -- Fixed bug on create-deployment command not choosing the correct NLU revision (#118) - -## [2.1.1] - 2019/03/01 -- Change analytics message (#119) - -## [2.1.0] - 2019/02/14 -### Fixed : -- Change endpoint API for command `push` (#109) -- Check job training status on command `nl-train` (#108) -- Add training error detail for command `nl-train` (#107) -- Fix endpoint API for command `nl-snapshot` (#106) -- Add Google Analytics for command tracking (#105) - -## [2.0.11] - 2019/01/03 -### Fixed : -- Create new revision on push (#102) -- Fix get latest revision (#101) -- Limit new entity name to 20 chars and add detailed error messages (#98) -- Set substring to 7 (#97) - -## [2.0.8] - 2018/12/20 -### Fixed : -- Fix nl-pull for entity type dictionary -- Latest bot, nlu, and cms revision endpoint -- Remove yarn.lock - -## [2.0.6] - 2018/12/20 -### Fixed : -- Remove warning http2 - -## [2.0.5] - 2018/12/20 -### Fixed : -- Restrict create-environment when name exist -- Change Project Push endpoint - -### Added : -- NL docs on README -- Move CONTRIBUTING to README - -## [2.0.4] - 2018/12/13 -### Fixed : -- Remove *.yml from .gitignore - -## [2.0.3] - 2018/12/13 -### Fixed : -- Fix vulnerabilities - -## [2.0.2] - 2018/12/13 -### Fixed : -- Switch team error -- Create team error namespace -- Add or remove member to team - -### Added : -- Pull with revision -- Version type when create-deployment - -## [2.0.1] - 2018/12/05 -### Fixed : -- Fix .gitignore - -## [2.0.0] - 2018/12/05 -### Added : -- Kata CLI v2.0 - -## [1.4.0] - 2018/08/16 -### Added : -- Add twitter channel type - -### Fixed : -- Switch team method - -## [1.3.2] - 2018/07/12 -### Added : -- Add config-view command - -### Fixed -- Integrate function 'versions' to new bot version object - -## [1.3.1] - 2018/02/12 -### Fixed -- Fix undefined context and state in flow spec - -## [1.3.0] - 2018/02/05 -### Added : -- Kata pull bot - -### Fixed -- Fix version still increment when failed push bot - -## [1.2.4] - 2017/01/08 -### Fixed : -- Handle kata console error when no bot.yml in directory - -## [1.2.3] - 2017/12/27 -### Fixed : -- Fix bug on kata deploy and kata nl-push command - -## [1.2.1] - 2017/12/21 -### Changed : -- Update kata init command - -## [1.2.0] - 2017/12/06 -### Added : -- Add discard and update draft -- Add new version information when pushing bot -- Generate challenge token for fbmessenger channel type - -### Changed : -- Change kata init output message - -### Fixed : -- Fix proper handling for kata versions - -## [1.1.0] - 2017/11/28 -### Added : -- Handle NLU Management - -### Fixed : -- Fix wrong username and password -- Fix invalid user command input - -## 1.0.0 - 2017/10/26 -### Added : -- Handle Bot Management -- Handle Deployment Management -- Handle User & Team Management - -[2.0.11]: https://github.com/kata-ai/kata-cli/compare/v2.0.8...v2.0.11 -[2.0.8]: https://github.com/kata-ai/kata-cli/compare/v2.0.6...v2.0.8 -[2.0.6]: https://github.com/kata-ai/kata-cli/compare/v2.0.5...v2.0.6 -[2.0.5]: https://github.com/kata-ai/kata-cli/compare/v2.0.4...v2.0.5 -[2.0.4]: https://github.com/kata-ai/kata-cli/compare/v2.0.3...v2.0.4 -[2.0.3]: https://github.com/kata-ai/kata-cli/compare/v2.0.2...v2.0.3 -[2.0.2]: https://github.com/kata-ai/kata-cli/compare/v2.0.1...v2.0.2 -[2.0.1]: https://github.com/kata-ai/kata-cli/compare/v2.0.0...v2.0.1 -[2.0.0]: https://github.com/kata-ai/kata-cli/compare/v1.4.0...v2.0.0 -[1.4.0]: https://github.com/kata-ai/kata-cli/compare/v1.3.2...v1.4.0 -[1.3.2]: https://github.com/kata-ai/kata-cli/compare/v1.3.1...v1.3.2 -[1.3.1]: https://github.com/kata-ai/kata-cli/compare/v1.3.0...v1.3.1 -[1.3.0]: https://github.com/kata-ai/kata-cli/compare/v1.2.4...v1.3.0 -[1.2.4]: https://github.com/kata-ai/kata-cli/compare/v1.2.3...v1.2.4 -[1.2.3]: https://github.com/kata-ai/kata-cli/compare/v1.2.1...v1.2.3 -[1.2.1]: https://github.com/kata-ai/kata-cli/compare/v1.2.0...v1.2.1 -[1.2.0]: https://github.com/kata-ai/kata-cli/compare/v1.1.0...v1.2.0 -[1.1.0]: https://github.com/kata-ai/kata-cli/compare/v1.0.0...v1.1.0 +# CHANGELOG + +## [2.6.0] - 2019/11/19 +- Fix search user by username or email on`kata invite-member` and `kata impersonate`command ([#133](https://github.com/kata-ai/kata-cli/pull/133), [#139](https://github.com/kata-ai/kata-cli/pull/139)) + +## [2.5.0] - 2019/09/02 +- Fix bug when switch to team during in impersonate mode ([#126](https://github.com/kata-ai/kata-cli/pull/126)) +- Add feature to select project name inline ([#127](https://github.com/kata-ai/kata-cli/pull/127)) +- Add handler to display notification message when error happened, instead of letting string quotes `''` pop up ([#128](https://github.com/kata-ai/kata-cli/pull/128)) + +## [2.4.0] - 2019/07/12 +- Add missing feature so that Kata-CLI is aligned with Platform. (#122) + - For the sake of consistency, we renamed several commands, such as: + - `kata add-channel` to `kata create-channel` + - `kata edit-channel` to `kata update-channel` + - `kata config-view` to `kata view-config` + - `kata add-member` to `kata invite-member` +- Add feature: impersonate user when logging in as administrator (#121) + +## [2.3.0] - 2019/04/16 +- Improved user experience for update-environment command (#120) + +## [2.2.0] - 2019/03/20 +- Improved user experience for update-environment command (#114) +- Add 20 character limit validation for environment URL and project name (#115) +- Improved error message for missing NLU.yml (#117) +- Fixed bug on create-deployment command not choosing the correct NLU revision (#118) + +## [2.1.1] - 2019/03/01 +- Change analytics message (#119) + +## [2.1.0] - 2019/02/14 +### Fixed : +- Change endpoint API for command `push` (#109) +- Check job training status on command `nl-train` (#108) +- Add training error detail for command `nl-train` (#107) +- Fix endpoint API for command `nl-snapshot` (#106) +- Add Google Analytics for command tracking (#105) + +## [2.0.11] - 2019/01/03 +### Fixed : +- Create new revision on push (#102) +- Fix get latest revision (#101) +- Limit new entity name to 20 chars and add detailed error messages (#98) +- Set substring to 7 (#97) + +## [2.0.8] - 2018/12/20 +### Fixed : +- Fix nl-pull for entity type dictionary +- Latest bot, nlu, and cms revision endpoint +- Remove yarn.lock + +## [2.0.6] - 2018/12/20 +### Fixed : +- Remove warning http2 + +## [2.0.5] - 2018/12/20 +### Fixed : +- Restrict create-environment when name exist +- Change Project Push endpoint + +### Added : +- NL docs on README +- Move CONTRIBUTING to README + +## [2.0.4] - 2018/12/13 +### Fixed : +- Remove *.yml from .gitignore + +## [2.0.3] - 2018/12/13 +### Fixed : +- Fix vulnerabilities + +## [2.0.2] - 2018/12/13 +### Fixed : +- Switch team error +- Create team error namespace +- Add or remove member to team + +### Added : +- Pull with revision +- Version type when create-deployment + +## [2.0.1] - 2018/12/05 +### Fixed : +- Fix .gitignore + +## [2.0.0] - 2018/12/05 +### Added : +- Kata CLI v2.0 + +## [1.4.0] - 2018/08/16 +### Added : +- Add twitter channel type + +### Fixed : +- Switch team method + +## [1.3.2] - 2018/07/12 +### Added : +- Add config-view command + +### Fixed +- Integrate function 'versions' to new bot version object + +## [1.3.1] - 2018/02/12 +### Fixed +- Fix undefined context and state in flow spec + +## [1.3.0] - 2018/02/05 +### Added : +- Kata pull bot + +### Fixed +- Fix version still increment when failed push bot + +## [1.2.4] - 2017/01/08 +### Fixed : +- Handle kata console error when no bot.yml in directory + +## [1.2.3] - 2017/12/27 +### Fixed : +- Fix bug on kata deploy and kata nl-push command + +## [1.2.1] - 2017/12/21 +### Changed : +- Update kata init command + +## [1.2.0] - 2017/12/06 +### Added : +- Add discard and update draft +- Add new version information when pushing bot +- Generate challenge token for fbmessenger channel type + +### Changed : +- Change kata init output message + +### Fixed : +- Fix proper handling for kata versions + +## [1.1.0] - 2017/11/28 +### Added : +- Handle NLU Management + +### Fixed : +- Fix wrong username and password +- Fix invalid user command input + +## 1.0.0 - 2017/10/26 +### Added : +- Handle Bot Management +- Handle Deployment Management +- Handle User & Team Management + +[2.0.11]: https://github.com/kata-ai/kata-cli/compare/v2.0.8...v2.0.11 +[2.0.8]: https://github.com/kata-ai/kata-cli/compare/v2.0.6...v2.0.8 +[2.0.6]: https://github.com/kata-ai/kata-cli/compare/v2.0.5...v2.0.6 +[2.0.5]: https://github.com/kata-ai/kata-cli/compare/v2.0.4...v2.0.5 +[2.0.4]: https://github.com/kata-ai/kata-cli/compare/v2.0.3...v2.0.4 +[2.0.3]: https://github.com/kata-ai/kata-cli/compare/v2.0.2...v2.0.3 +[2.0.2]: https://github.com/kata-ai/kata-cli/compare/v2.0.1...v2.0.2 +[2.0.1]: https://github.com/kata-ai/kata-cli/compare/v2.0.0...v2.0.1 +[2.0.0]: https://github.com/kata-ai/kata-cli/compare/v1.4.0...v2.0.0 +[1.4.0]: https://github.com/kata-ai/kata-cli/compare/v1.3.2...v1.4.0 +[1.3.2]: https://github.com/kata-ai/kata-cli/compare/v1.3.1...v1.3.2 +[1.3.1]: https://github.com/kata-ai/kata-cli/compare/v1.3.0...v1.3.1 +[1.3.0]: https://github.com/kata-ai/kata-cli/compare/v1.2.4...v1.3.0 +[1.2.4]: https://github.com/kata-ai/kata-cli/compare/v1.2.3...v1.2.4 +[1.2.3]: https://github.com/kata-ai/kata-cli/compare/v1.2.1...v1.2.3 +[1.2.1]: https://github.com/kata-ai/kata-cli/compare/v1.2.0...v1.2.1 +[1.2.0]: https://github.com/kata-ai/kata-cli/compare/v1.1.0...v1.2.0 +[1.1.0]: https://github.com/kata-ai/kata-cli/compare/v1.0.0...v1.1.0 diff --git a/README.md b/README.md index 72341d2..c922767 100644 --- a/README.md +++ b/README.md @@ -1,388 +1,388 @@ -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5445d7e1a31740f8a4659e4774a168d9)](https://www.codacy.com?utm_source=git@bitbucket.org&utm_medium=referral&utm_content=yesboss/Kata-CLI&utm_campaign=Badge_Grade) -[![Known Vulnerabilities](https://snyk.io/test/github/kata-ai/kata-cli/badge.svg)](https://snyk.io/test/github/kata-ai/kata-cli) -[![NPM version](https://img.shields.io/npm/v/kata-cli.svg?style=flat)](https://www.npmjs.com/package/kata-cli) -[![NPM downloads](https://img.shields.io/npm/dm/kata-cli.svg?style=flat)](https://www.npmjs.com/package/kata-cli) - -# Kata-CLI Overview and Command Reference -Kata Command Line Interface (Kata CLI) is a tool for creating bot with Kata Markup Language (Kata ML) and helps managing the bots with command line/shell of various operating systems. - -## Installing Kata-CLI -Install Kata-CLI using the npm package manager. - -```shell -npm install -g kata-cli -``` - -This is the preferred method to install Kata-CLI in a global mode, as it will always install the most recent stable release. - -### Changelog -For details about changes between versions, and information about updating from previous releases, see the [Changelog](CHANGELOG.md) - -### Upgrade Kata-CLI version -To check your installed Kata-CLI version, use this command: - - ```shell - ➜ kata --version - ``` - -Please refer to the full descriptions on [Changelog](CHANGELOG.md) to check the latest version. *Make sure to update Kata-CLI to the latest stable version before doing some fun with your Bot with this command*: - - ```shell - ➜ npm i -g kata-cli@x.y.z - ``` - -you can add `@version-number` to be exact. - -## Command Overview - -Use `kata --help` into your command line to find out the list of commands offered by Kata-CLI with a short description. The new command in Kata-CLI is that with asterisk (*). - -### User Management -The list of command below is accessible by user with role as **user** : - -Commands | Functionalities ---------------------- | ------------------------------------------------------------------------------------------- -`kata login [options]` | the parameter `options` can be `user` or `team` -`kata whoami` | to see the current user login informations -`kata change-password` | to change user's password -`kata create-team ` | to create team -`kata logout` | to logout from the platform -(*) `kata forgot-password ` | to set new password when user forgot -(*) `kata list-team` | to list user's team -(*) `kata list-team-user [teamName]` | to list user's team member - -This command is accessible by user with role as **admin** : - -Commands | Functionalities ---------------------- | ------------------------------------------------------------------------------------------- -`kata create-user` | to set spesific role and create user - -Command as **team** : - -Commands | Functionalities ---------------------- | ------------------------------------------------------------------------------------------- -`kata add-member [options] --admin` | to assign user as the teammember -`kata remove-member ` | to remove member from the team -`kata switch [userName or teamName]` | to switch between `user` and `team` role. Parameter must be `user` or `team`. - -### Project Management Command - -The new commands (on version 2.4.0) to manage Project are those with asterisk (*). - -Commands | Functionalities ---------------------- | ------------------------------------------------------------------------------------------- -`kata create-project` | to create a project -`kata list-project` | to display current projects that you have -`kata select-project` | to select project that you want to use, any bot operation will be related to that project -(*) `kata delete-project [projectName]` | to delete project -(*) `kata update-project [projectName]` | to update project details - -### Bot, Deployment, Environment and Channel Management Command - -#### Bot Management Command - -Here are list of commands to manage Bot, those with asterisk (*) are the the new commands on version 2.4.0 - -Commands | Functionalities ---------------------- | ------------------------------------------------------------------------------------------- -(*) `kata view-config` | to view user configurations -`kata init ` | to initialize the bot -`kata revisions` | to list the revisions of the bot -`kata list-bots` | to list the bots -`kata push` | to push the bot revision -`kata pull [revision]` | to pull the bot with specified name and version -`kata remove-bot` | to delete selected bot -`kata test [fileName]` | to run a test for the bot -`kata console [revision]` | to converse with the bot, updated features: user can choose certain environment console -`kata drop ` | to drop bot -`kata set ` | to set configuration setting on Kata-CLI -(*) `kata errors` | to list error log from a bot - -#### Deployment Management Command - -Here are list of commands to manage Deployment, those with asterisk (*) are the the new commands on version 2.4.0 - -Commands | Functionalities ---------------------- | ------------------------------------------------------------------------------------------- -`kata create-deployment` | to create a deployment -`kata list-deployment` | to list deployments -(*) `kata rollback-deployment ` | to rollback to certain deployment - -#### Environment Management Command - -Here are list of commands to manage Environment, those with asterisk (*) are the the new commands on version 2.4.0 - -Commands | Functionalities ---------------------- | ------------------------------------------------------------------------------------------- -`kata create-environment ` | Create an environment on the selected project -`kata list-environment` | List environments of the selected project -`kata update-environment ` | Update an environment of the selected project - -#### Channel Management Command - -Here are list of commands to manage Channel, those with asterisk (*) are the the new commands on version 2.4.0 - -Commands | Functionalities ---------------------- | ------------------------------------------------------------------------------------------- -(*) `kata add-channel [options] ` | Create a channel with channelName on the selected environment -(*) `kata update-channel [options] ` | Update a channel on the selected environment -`kata list-channel` | List channels of the selected environment -`kata remove-channel ` | Remove the channel named channelName from the selected environment - -### NLU Related Command - -Here are list of commands to manage NLU, those with asterisk (*) are the the new commands on version 2.4.0 - -Commands | Functionalities ----------|----------------- -`kata nl-init` | to initialize nl definition -`kata nl-push` | to push nl changes -`kata nl-pull` | to pull nl changes from remote -`kata nl-train [options]` | to train a sentence or a batch of sentences. `[options]` can be `-f ` -`kata nl-predict [options]` | to predict a sentence. `[options]` can be `[-f ]` -`kata list-profiles` | to list all profiles -`kata nl-snapshot` | to save the nlu snapshot -(*) `kata nl-list-training --page=` | to list the training sentences -(*) `kata nl-list-prediction --page=` | to list the prediction log -(*) `kata nl-list-revision` | to list the revision -(*) `kata nl-issue-token` | to (re-)issue token - -### Outdated Commands on Kata-CLI - -Here are the list of outdated commands on version 2.4.0, please refer to [Changelog](CHANGELOG.md) for the details. - -_List of Deprecated Command:_ -- `kata add-channel ` -- `kata edit-channel ` -- `kata config-view` -- `kata add-member` - -_List of Permanently Deleted Command:_ -- `kata deploy [version]` -- `kata session-get [deploymentId]` -- `kata session-create [deploymentId]` -- `kata session-update [deploymentId]` -- `kata session-delete [deploymentId]` -- `kata timestamp` - - -## Workflow - -We hope that you can get a smooth experience in working with Kata-CLI by following several best practice steps: - -### Project Workspace - -In Kata-CLI upto 2.0 version, we introduce Project Environment on the top of the Bots, Deployment, Environment, NLU and CMS. Hence, before running Kata-CLI main command, such as: `kata init`,`kata push`, `kata console`., user have to initiate and define the Project that they are going to work on. - -#### 1. Create the Project - -Welcome to your project workspace. In this documentation, you may find the term `project` and `bot` is used interchangeably, since a bot belongs to a project. - -For the first step, create folder where we're going to wrap our project in. Then let's create our first project, where a bot, deployments, environments and channels are attached to. - - ```shell - ➜ kata create-project - ? Project name: your-project-name - ? Timezone (UTC) 7 - ? Project description: your-project-desc - ? NLU Language id - ? Is private Nlu? Yes - Project "your-project-name" (5c9ea2b9-ab79-4aa8-aaa0-a831bbb175de) is successfully created - ``` - -Voila, your first project is there. - -If you already have an existing project that you're gonna be working on, you have to select the project first. To show the list of your project, run this command: - - ```shell - ➜ kata select-project - ``` - -#### 2. Create the Bot - -Once the project is selected, it is the time to build the bot using this command: - - ```shell - ➜ kata init - ``` - -This command will generate a `bot.yml` under the project. This file contains a simple `hi-bot` template written in Kata Markup Language (Kata-ML) schema, as the first revision of your bot. - -Run this command to see the list of bot revisions: - - ```shell - ➜ kata revisions - ``` - -#### 3. Push your bot changes - -Customize your bot schema on `bot.yml` file, then push the bot to apply the changes: - - ```shell - ➜ kata push - Push Bot Success. Revision : 6bb61b7 - ``` - -#### 4. Test a conversation with your bot - -Once you pushed the latest revision of your bot, meaning that you are ready to test a conversation with the bot. Run this command on your terminal: - - ```shell - ➜ kata console - ``` - -We'll enter the virtual environment (node shell) to do a chatting simulation with the bot. - - ```shell - your-bot-name>text("hi") - { messages: - [ { type: 'text', - content: 'hi', - id: 'd5a1a010-fb60-42cf-96c8-c648fc557443', - intent: 'greeting', - attributes: {} } ], - responses: - [ { type: 'text', - content: 'hialo!', - action: 'text', - id: '1f7caf54-ee6f-4aa6-9696-bdcced9e406a', - refId: 'd5a1a010-fb60-42cf-96c8-c648fc557443', - flow: 'hello', - intent: 'greeting' } ], - session: - { id: 'test~from~console', - states: {}, - contexes: {}, - history: [], - current: null, - meta: { lastFlow: 'hello', lastState: 'greet', end: true }, - timestamp: 0, - data: {} }, - duration: 86 } - your-bot-name> - (To exit, press ^C again or type .exit) - ``` - -Kata-CLI will create a session that alive along the conversation and generate a `.katasession` file in your home directory for further debugging (if needed). - -To view your current session, you can either run this command: - - ```shell - ➜ cat ~/.katasession - {"id":"test~from~console","states":{},"contexes":{},"history":[],"current":null,"meta":{"lastFlow":"hello","lastState":"other","end":true},"timestamp":0,"data":{}}% - ``` - -or this command, for a better JSON alignment: - - ```shell - ➜ kata console - your-bot-name>current() - { - id: 'test~from~console', - states: {}, - contexes: {}, - history: [], - current: null, - meta: { lastFlow: 'hello', lastState: 'other', end: true }, - timestamp: 0, - data: {} - } - ``` - -Congratulations that you finish your first revision of the bot. Now it is the time to deploy your bot. - -### Deploy your Project - -Follow these following steps to deploy your project to messaging channels. - -#### 1. Create a Deployment - -Create a new deployment version using these command. If you do not specificy the deployment types (`major`/`minor`/`patch`), it will automatically create a deployment with patch. - - ```shell - ➜ kata create-deployment [deploymentType] - ``` - -#### 2. Create and Update Environment -After having the deployment, we need to create an environment. Environment works like tier in which a your bot is deployed and executed. We provide three stages of environments: `Development`, `Staging`, `Production`. - - ```shell - ➜ kata create-environment - ``` - -Your freshly created environment will auto-select the latest deployment version. - -If you already have environment, you can just simply update it with the newer deployment version using this command: - - ```shell - ➜ kata update-environment - ``` - -#### 3. Create Channel -Let's create messaging channel under environment. The steps are: type the command to create channel below, then choose the environment where it belongs to. - - ```shell - ➜ kata create-channel - ``` - -(*) Notes: -Previously, the command to create channel is: -`kata add-channel ` -From this version above, the command is changed to: -`kata create-channel ` - -### Integrate with NLU - -An NLU must be under a project. Therefore, we need to define a project, before we create an NLU. - -#### 1. Initialize NLU Project - -It would create a new file `nlu.yml` in which the nlu structure can be defined. - - ```shell - # initialize a nlu project - ➜ kata nl-init - ``` - -#### 2. Push NLU - -To use push command to create and update the NLU - - ```shell - # push current nlu project - ➜ kata nl-push - ``` - -#### 3. List Profiles - -To list all profiles - - ```shell - ➜ kata list-profiles - ``` - -#### 4. Train NLU - -To train a nlu. - - ```shell - ➜ kata nl-train [-f ] - ➜ kata nl-train [-s ] - ``` - -#### 5. Predict Sentences with NLU - - ```shell - ➜ kata nl-predict [-f ] - ➜ kata nl-predict [-s ] - ``` - -## Contributing - -Is something missing/incorrect? Please let us know by contacting support@kata.ai. If you know how to fix it straight away, don’t hesitate to create a pull request on this documentation’s GitHub repository by following these steps: -1. Fork this repository -2. Name your branch with prefix `feature/` if you added new feature, `hotfix/` if you fixed some bugs -3. Code, and dont forget to add test after added new feature -4. Commit your branch and pull request to base `develop` branch - -Happy contributing :) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5445d7e1a31740f8a4659e4774a168d9)](https://www.codacy.com?utm_source=git@bitbucket.org&utm_medium=referral&utm_content=yesboss/Kata-CLI&utm_campaign=Badge_Grade) +[![Known Vulnerabilities](https://snyk.io/test/github/kata-ai/kata-cli/badge.svg)](https://snyk.io/test/github/kata-ai/kata-cli) +[![NPM version](https://img.shields.io/npm/v/kata-cli.svg?style=flat)](https://www.npmjs.com/package/kata-cli) +[![NPM downloads](https://img.shields.io/npm/dm/kata-cli.svg?style=flat)](https://www.npmjs.com/package/kata-cli) + +# Kata-CLI Overview and Command Reference +Kata Command Line Interface (Kata CLI) is a tool for creating bot with Kata Markup Language (Kata ML) and helps managing the bots with command line/shell of various operating systems. + +## Installing Kata-CLI +Install Kata-CLI using the npm package manager. + +```shell +npm install -g kata-cli +``` + +This is the preferred method to install Kata-CLI in a global mode, as it will always install the most recent stable release. + +### Changelog +For details about changes between versions, and information about updating from previous releases, see the [Changelog](CHANGELOG.md) + +### Upgrade Kata-CLI version +To check your installed Kata-CLI version, use this command: + + ```shell + ➜ kata --version + ``` + +Please refer to the full descriptions on [Changelog](CHANGELOG.md) to check the latest version. *Make sure to update Kata-CLI to the latest stable version before doing some fun with your Bot with this command*: + + ```shell + ➜ npm i -g kata-cli@x.y.z + ``` + +you can add `@version-number` to be exact. + +## Command Overview + +Use `kata --help` into your command line to find out the list of commands offered by Kata-CLI with a short description. The new command in Kata-CLI is that with asterisk (*). + +### User Management +The list of command below is accessible by user with role as **user** : + +Commands | Functionalities +--------------------- | ------------------------------------------------------------------------------------------- +`kata login [options]` | the parameter `options` can be `user` or `team` +`kata whoami` | to see the current user login informations +`kata change-password` | to change user's password +`kata create-team ` | to create team +`kata logout` | to logout from the platform +(*) `kata forgot-password ` | to set new password when user forgot +(*) `kata list-team` | to list user's team +(*) `kata list-team-user [teamName]` | to list user's team member + +This command is accessible by user with role as **admin** : + +Commands | Functionalities +--------------------- | ------------------------------------------------------------------------------------------- +`kata create-user` | to set spesific role and create user + +Command as **team** : + +Commands | Functionalities +--------------------- | ------------------------------------------------------------------------------------------- +`kata add-member [options] --admin` | to assign user as the teammember +`kata remove-member ` | to remove member from the team +`kata switch [userName or teamName]` | to switch between `user` and `team` role. Parameter must be `user` or `team`. + +### Project Management Command + +The new commands (on version 2.4.0) to manage Project are those with asterisk (*). + +Commands | Functionalities +--------------------- | ------------------------------------------------------------------------------------------- +`kata create-project` | to create a project +`kata list-project` | to display current projects that you have +`kata select-project` | to select project that you want to use, any bot operation will be related to that project +(*) `kata delete-project [projectName]` | to delete project +(*) `kata update-project [projectName]` | to update project details + +### Bot, Deployment, Environment and Channel Management Command + +#### Bot Management Command + +Here are list of commands to manage Bot, those with asterisk (*) are the the new commands on version 2.4.0 + +Commands | Functionalities +--------------------- | ------------------------------------------------------------------------------------------- +(*) `kata view-config` | to view user configurations +`kata init ` | to initialize the bot +`kata revisions` | to list the revisions of the bot +`kata list-bots` | to list the bots +`kata push` | to push the bot revision +`kata pull [revision]` | to pull the bot with specified name and version +`kata remove-bot` | to delete selected bot +`kata test [fileName]` | to run a test for the bot +`kata console [revision]` | to converse with the bot, updated features: user can choose certain environment console +`kata drop ` | to drop bot +`kata set ` | to set configuration setting on Kata-CLI +(*) `kata errors` | to list error log from a bot + +#### Deployment Management Command + +Here are list of commands to manage Deployment, those with asterisk (*) are the the new commands on version 2.4.0 + +Commands | Functionalities +--------------------- | ------------------------------------------------------------------------------------------- +`kata create-deployment` | to create a deployment +`kata list-deployment` | to list deployments +(*) `kata rollback-deployment ` | to rollback to certain deployment + +#### Environment Management Command + +Here are list of commands to manage Environment, those with asterisk (*) are the the new commands on version 2.4.0 + +Commands | Functionalities +--------------------- | ------------------------------------------------------------------------------------------- +`kata create-environment ` | Create an environment on the selected project +`kata list-environment` | List environments of the selected project +`kata update-environment ` | Update an environment of the selected project + +#### Channel Management Command + +Here are list of commands to manage Channel, those with asterisk (*) are the the new commands on version 2.4.0 + +Commands | Functionalities +--------------------- | ------------------------------------------------------------------------------------------- +(*) `kata add-channel [options] ` | Create a channel with channelName on the selected environment +(*) `kata update-channel [options] ` | Update a channel on the selected environment +`kata list-channel` | List channels of the selected environment +`kata remove-channel ` | Remove the channel named channelName from the selected environment + +### NLU Related Command + +Here are list of commands to manage NLU, those with asterisk (*) are the the new commands on version 2.4.0 + +Commands | Functionalities +---------|----------------- +`kata nl-init` | to initialize nl definition +`kata nl-push` | to push nl changes +`kata nl-pull` | to pull nl changes from remote +`kata nl-train [options]` | to train a sentence or a batch of sentences. `[options]` can be `-f ` +`kata nl-predict [options]` | to predict a sentence. `[options]` can be `[-f ]` +`kata list-profiles` | to list all profiles +`kata nl-snapshot` | to save the nlu snapshot +(*) `kata nl-list-training --page=` | to list the training sentences +(*) `kata nl-list-prediction --page=` | to list the prediction log +(*) `kata nl-list-revision` | to list the revision +(*) `kata nl-issue-token` | to (re-)issue token + +### Outdated Commands on Kata-CLI + +Here are the list of outdated commands on version 2.4.0, please refer to [Changelog](CHANGELOG.md) for the details. + +_List of Deprecated Command:_ +- `kata add-channel ` +- `kata edit-channel ` +- `kata config-view` +- `kata add-member` + +_List of Permanently Deleted Command:_ +- `kata deploy [version]` +- `kata session-get [deploymentId]` +- `kata session-create [deploymentId]` +- `kata session-update [deploymentId]` +- `kata session-delete [deploymentId]` +- `kata timestamp` + + +## Workflow + +We hope that you can get a smooth experience in working with Kata-CLI by following several best practice steps: + +### Project Workspace + +In Kata-CLI upto 2.0 version, we introduce Project Environment on the top of the Bots, Deployment, Environment, NLU and CMS. Hence, before running Kata-CLI main command, such as: `kata init`,`kata push`, `kata console`., user have to initiate and define the Project that they are going to work on. + +#### 1. Create the Project + +Welcome to your project workspace. In this documentation, you may find the term `project` and `bot` is used interchangeably, since a bot belongs to a project. + +For the first step, create folder where we're going to wrap our project in. Then let's create our first project, where a bot, deployments, environments and channels are attached to. + + ```shell + ➜ kata create-project + ? Project name: your-project-name + ? Timezone (UTC) 7 + ? Project description: your-project-desc + ? NLU Language id + ? Is private Nlu? Yes + Project "your-project-name" (5c9ea2b9-ab79-4aa8-aaa0-a831bbb175de) is successfully created + ``` + +Voila, your first project is there. + +If you already have an existing project that you're gonna be working on, you have to select the project first. To show the list of your project, run this command: + + ```shell + ➜ kata select-project + ``` + +#### 2. Create the Bot + +Once the project is selected, it is the time to build the bot using this command: + + ```shell + ➜ kata init + ``` + +This command will generate a `bot.yml` under the project. This file contains a simple `hi-bot` template written in Kata Markup Language (Kata-ML) schema, as the first revision of your bot. + +Run this command to see the list of bot revisions: + + ```shell + ➜ kata revisions + ``` + +#### 3. Push your bot changes + +Customize your bot schema on `bot.yml` file, then push the bot to apply the changes: + + ```shell + ➜ kata push + Push Bot Success. Revision : 6bb61b7 + ``` + +#### 4. Test a conversation with your bot + +Once you pushed the latest revision of your bot, meaning that you are ready to test a conversation with the bot. Run this command on your terminal: + + ```shell + ➜ kata console + ``` + +We'll enter the virtual environment (node shell) to do a chatting simulation with the bot. + + ```shell + your-bot-name>text("hi") + { messages: + [ { type: 'text', + content: 'hi', + id: 'd5a1a010-fb60-42cf-96c8-c648fc557443', + intent: 'greeting', + attributes: {} } ], + responses: + [ { type: 'text', + content: 'hialo!', + action: 'text', + id: '1f7caf54-ee6f-4aa6-9696-bdcced9e406a', + refId: 'd5a1a010-fb60-42cf-96c8-c648fc557443', + flow: 'hello', + intent: 'greeting' } ], + session: + { id: 'test~from~console', + states: {}, + contexes: {}, + history: [], + current: null, + meta: { lastFlow: 'hello', lastState: 'greet', end: true }, + timestamp: 0, + data: {} }, + duration: 86 } + your-bot-name> + (To exit, press ^C again or type .exit) + ``` + +Kata-CLI will create a session that alive along the conversation and generate a `.katasession` file in your home directory for further debugging (if needed). + +To view your current session, you can either run this command: + + ```shell + ➜ cat ~/.katasession + {"id":"test~from~console","states":{},"contexes":{},"history":[],"current":null,"meta":{"lastFlow":"hello","lastState":"other","end":true},"timestamp":0,"data":{}}% + ``` + +or this command, for a better JSON alignment: + + ```shell + ➜ kata console + your-bot-name>current() + { + id: 'test~from~console', + states: {}, + contexes: {}, + history: [], + current: null, + meta: { lastFlow: 'hello', lastState: 'other', end: true }, + timestamp: 0, + data: {} + } + ``` + +Congratulations that you finish your first revision of the bot. Now it is the time to deploy your bot. + +### Deploy your Project + +Follow these following steps to deploy your project to messaging channels. + +#### 1. Create a Deployment + +Create a new deployment version using these command. If you do not specificy the deployment types (`major`/`minor`/`patch`), it will automatically create a deployment with patch. + + ```shell + ➜ kata create-deployment [deploymentType] + ``` + +#### 2. Create and Update Environment +After having the deployment, we need to create an environment. Environment works like tier in which a your bot is deployed and executed. We provide three stages of environments: `Development`, `Staging`, `Production`. + + ```shell + ➜ kata create-environment + ``` + +Your freshly created environment will auto-select the latest deployment version. + +If you already have environment, you can just simply update it with the newer deployment version using this command: + + ```shell + ➜ kata update-environment + ``` + +#### 3. Create Channel +Let's create messaging channel under environment. The steps are: type the command to create channel below, then choose the environment where it belongs to. + + ```shell + ➜ kata create-channel + ``` + +(*) Notes: +Previously, the command to create channel is: +`kata add-channel ` +From this version above, the command is changed to: +`kata create-channel ` + +### Integrate with NLU + +An NLU must be under a project. Therefore, we need to define a project, before we create an NLU. + +#### 1. Initialize NLU Project + +It would create a new file `nlu.yml` in which the nlu structure can be defined. + + ```shell + # initialize a nlu project + ➜ kata nl-init + ``` + +#### 2. Push NLU + +To use push command to create and update the NLU + + ```shell + # push current nlu project + ➜ kata nl-push + ``` + +#### 3. List Profiles + +To list all profiles + + ```shell + ➜ kata list-profiles + ``` + +#### 4. Train NLU + +To train a nlu. + + ```shell + ➜ kata nl-train [-f ] + ➜ kata nl-train [-s ] + ``` + +#### 5. Predict Sentences with NLU + + ```shell + ➜ kata nl-predict [-f ] + ➜ kata nl-predict [-s ] + ``` + +## Contributing + +Is something missing/incorrect? Please let us know by contacting support@kata.ai. If you know how to fix it straight away, don’t hesitate to create a pull request on this documentation’s GitHub repository by following these steps: +1. Fork this repository +2. Name your branch with prefix `feature/` if you added new feature, `hotfix/` if you fixed some bugs +3. Code, and dont forget to add test after added new feature +4. Commit your branch and pull request to base `develop` branch + +Happy contributing :) diff --git a/bin/coverage.sh b/bin/coverage.sh index 645d2ee..2349e2e 100644 --- a/bin/coverage.sh +++ b/bin/coverage.sh @@ -1,6 +1,6 @@ -#!bin/bash - -NODE_ENV=test nyc npm t -NODE_ENV=test nyc report --reporter=text-summary -NODE_ENV=test nyc report --reporter=lcov +#!bin/bash + +NODE_ENV=test nyc npm t +NODE_ENV=test nyc report --reporter=text-summary +NODE_ENV=test nyc report --reporter=lcov cat ./coverage/lcov.info | ./node_modules/.bin/codacy-coverage && rm -rf ./coverage \ No newline at end of file diff --git a/bin/kata.js b/bin/kata.js index 8130134..018d7d9 100755 --- a/bin/kata.js +++ b/bin/kata.js @@ -1,12 +1,12 @@ -#!/usr/bin/env node -"use strict"; - -let boot = require("../index.js"); - -try { - boot.start(); -} -catch (e) { - console.log(e.stack); - process.exit(); +#!/usr/bin/env node +"use strict"; + +let boot = require("../index.js"); + +try { + boot.start(); +} +catch (e) { + console.log(e.stack); + process.exit(); } \ No newline at end of file diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index 641a6f7..6f6886a 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -1,38 +1,38 @@ -image: node:6.9.4 - -pipelines: - - default: - - step: - caches: - - node - script: - - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.18.1 - - export PATH=$HOME/.yarn/bin:$PATH - - yarn - - npm run cover - - tags: - '*': - - step: - caches: - - node - script: - - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.18.1 - - export PATH=$HOME/.yarn/bin:$PATH - - yarn - - npm run cover - - branches: - develop: - - step: - caches: - - node - script: - - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.18.1 - - export PATH=$HOME/.yarn/bin:$PATH - - yarn - - npm run cover - -options: +image: node:6.9.4 + +pipelines: + + default: + - step: + caches: + - node + script: + - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.18.1 + - export PATH=$HOME/.yarn/bin:$PATH + - yarn + - npm run cover + + tags: + '*': + - step: + caches: + - node + script: + - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.18.1 + - export PATH=$HOME/.yarn/bin:$PATH + - yarn + - npm run cover + + branches: + develop: + - step: + caches: + - node + script: + - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.18.1 + - export PATH=$HOME/.yarn/bin:$PATH + - yarn + - npm run cover + +options: docker: true \ No newline at end of file diff --git a/components/api/api.ts b/components/api/api.ts index 831e365..70bed08 100644 --- a/components/api/api.ts +++ b/components/api/api.ts @@ -1,48 +1,48 @@ - -import { JsonObject, Component } from "merapi"; -import { IHelper } from "interfaces/main"; - -export default class Api extends Component { - private draftApi: any; - private apiClient: any; - private bearer: any; - private botApi: any; - private authApi: any; - private userApi: any; - private teamApi: any; - public deploymentApi: any; - private sessionApi: any; - private cachesApi: any; - private utilApi: any; - public nluApi: any; - public projectApi: any; - - constructor( - private helper: IHelper, - private zaun: any - ) { - super(); - - this.apiClient = this.zaun.ApiClient.instance; - let basePath = this.helper.getProp("zaunUrl") || "https://api.kata.ai"; - - this.apiClient.basePath = basePath; - this.bearer = this.apiClient.authentications.Bearer; - const currentLogin = this.helper.getProp("current_login") as string || "user"; - const tokenObj = this.helper.getProp("token") as JsonObject || {}; - this.bearer.apiKey = `Bearer ${tokenObj[currentLogin]}`; - - this.botApi = new this.zaun.BotApi(); - this.authApi = new this.zaun.AuthApi(); - this.userApi = new this.zaun.UserApi(); - this.teamApi = new this.zaun.TeamApi(); - this.deploymentApi = new this.zaun.DeploymentApi(); - this.projectApi = new zaun.ProjectApi(); - // this.draftApi = new this.zaun.DraftApi(); - // this.channelApi = new this.zaun.ChannelApi(); - // this.sessionApi = new this.zaun.SessionApi(); - // this.cachesApi = new this.zaun.CacheApi(); - // this.utilApi = new this.zaun.UtilApi(); - this.nluApi = new this.zaun.NluApi(); - } -} + +import { JsonObject, Component } from "merapi"; +import { IHelper } from "interfaces/main"; + +export default class Api extends Component { + private draftApi: any; + private apiClient: any; + private bearer: any; + private botApi: any; + private authApi: any; + private userApi: any; + private teamApi: any; + public deploymentApi: any; + private sessionApi: any; + private cachesApi: any; + private utilApi: any; + public nluApi: any; + public projectApi: any; + + constructor( + private helper: IHelper, + private zaun: any + ) { + super(); + + this.apiClient = this.zaun.ApiClient.instance; + let basePath = this.helper.getProp("zaunUrl") || "https://api.kata.ai"; + + this.apiClient.basePath = basePath; + this.bearer = this.apiClient.authentications.Bearer; + const currentLogin = this.helper.getProp("current_login") as string || "user"; + const tokenObj = this.helper.getProp("token") as JsonObject || {}; + this.bearer.apiKey = `Bearer ${tokenObj[currentLogin]}`; + + this.botApi = new this.zaun.BotApi(); + this.authApi = new this.zaun.AuthApi(); + this.userApi = new this.zaun.UserApi(); + this.teamApi = new this.zaun.TeamApi(); + this.deploymentApi = new this.zaun.DeploymentApi(); + this.projectApi = new zaun.ProjectApi(); + // this.draftApi = new this.zaun.DraftApi(); + // this.channelApi = new this.zaun.ChannelApi(); + // this.sessionApi = new this.zaun.SessionApi(); + // this.cachesApi = new this.zaun.CacheApi(); + // this.utilApi = new this.zaun.UtilApi(); + this.nluApi = new this.zaun.NluApi(); + } +} diff --git a/components/api/zaun.ts b/components/api/zaun.ts index 0c1c996..05331a0 100644 --- a/components/api/zaun.ts +++ b/components/api/zaun.ts @@ -1,6 +1,6 @@ - -import { Component } from "merapi"; - -export default function() { - return require("zaun"); -} + +import { Component } from "merapi"; + +export default function() { + return require("zaun"); +} diff --git a/components/bots/bot.ts b/components/bots/bot.ts index 1cf1861..ac84349 100644 --- a/components/bots/bot.ts +++ b/components/bots/bot.ts @@ -1,653 +1,653 @@ - -import { ICompile, IHelper, ITester } from "interfaces/main"; -import { Component, Config, IHash, JsonObject } from "merapi"; -import { v4 as uuid } from "uuid"; -import { CatchError } from "../scripts/helper"; -import { isDate } from "util"; -import inquirer = require("inquirer"); -const Table = require("cli-table"); - -const colors = require("colors"); -const repl = require("repl"); -const util = require("util"); -const os = require("os"); -const fs = require("fs"); -const deasync = require("deasync"); - -export default class Bot extends Component { - constructor(private compile: ICompile, private helper: IHelper, private tester: ITester, private api: any) { - super(); - } - - public init(name: string, options: JsonObject) { - const botDesc = { - schema: "kata.ai/schema/kata-ml/1.0", - name, - desc: "My First Bot", - flows: { - hello: { - fallback: true, - intents: { - greeting: { - initial: true, - condition: "content == 'hi'" - }, - fallback: { - fallback: true - } - }, - states: { - init: { - initial: true, - transitions: { - greet: { - condition: "intent == \"greeting\"" - }, - other: { - fallback: true - } - } - }, - greet: { - end: true, - action: { - name: "text", - options: { - text: "hi!" - } - } - }, - other: { - end: true, - action: { - name: "text", - options: { - text: "sorry!" - } - } - } - } - } - } - }; - - this.helper.dumpYaml("./bot.yml", botDesc); - - console.log(`Initialized ${name} successfully`); - } - - public async revisions(options: JsonObject) { - try { - const projectId = this.getProject(); - const { data, response } = await this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsGet, projectId); - const result = data; - if (result && result.data) { - console.log("Bot Revision : "); - result.data.forEach((hist: JsonObject) => { - console.log(`- ${hist.revision}`); - }); - } else { - console.log("You must push at least 1 bot to acquire revisions"); - } - } catch (e) { - if (e.code === "ENOENT") { - console.log("kata versions must be executed in bot directory with bot.yml"); - } else { - console.log(this.helper.wrapError(e)); - } - } - } - - public async test(file: string, options: JsonObject) { - const testFiles = file ? [file] : this.helper.getFiles("./test", ".spec.yml"); - const botId = this.helper.getProjectId(); - - if (!botId) { - throw new Error("BOT ID HAS NOT DEFINED"); - } - - const results: JsonObject = {}; - - for (let i = 0; i < testFiles.length; i++) { - const yaml = this.helper.loadYaml(testFiles[i]); - let res; - - switch (yaml.schema) { - case "kata.ai/schema/kata-ml/1.0/test/intents": - res = await this.tester.execIntentTest(yaml, this.api.botApi, botId, console.log); - if (this.hasErrors(res)) { - results[testFiles[i]] = res; - } - break; - case "kata.ai/schema/kata-ml/1.0/test/states": - res = await this.tester.execStateTest(yaml, this.api.botApi, botId, console.log); - if (this.hasErrors(res)) { - results[testFiles[i]] = res; - } - break; - case "kata.ai/schema/kata-ml/1.0/test/actions": - res = await this.tester.execActionsTest(yaml, this.api.botApi, botId, console.log); - if (this.hasErrors(res)) { - results[testFiles[i]] = res; - } - break; - case "kata.ai/schema/kata-ml/1.0/test/flow": - res = await this.tester.execFlowTest(yaml, this.api.botApi, botId, console.log); - if (this.hasErrors(res)) { - results[testFiles[i]] = res; - } - break; - } - } - - this.printResult(results as IHash>); - } - - private hasErrors(res: any) { - return Object.keys(res).some((key) => (res[key] && res[key].length) || res[key] === null); - } - - private printResult(results: IHash> = {}) { - if (Object.keys(results).length) { - console.log(colors.red("Errors:")); - for (const i in results) { - console.log(` ${i}:`); - for (const j in results[i]) { - if (!results[i][j]) { - console.log(` ${colors.red(j + ":")}`); - console.log(` diaenne returns ${colors.red("null")}`); - continue; - } - if (results[i][j].length) { - console.log(` ${colors.red(j + ":")}`); - - results[i][j].forEach((res) => { - console.log(` expecting ${res.field} to be ${colors.green(res.expect)} but got ${colors.red(res.result)}`); - }); - } - } - } - } - } - - @CatchError - public async push(options: JsonObject) { - const desc = this.helper.loadYaml("./bot.yml"); - desc.tag = options.tag || null; - - let bot = Config.create(desc, { left: "${", right: "}" }); - bot = this.compile.execDirectives(bot, process.cwd()); - bot.resolve(); - - const botDesc = bot.get(); - botDesc.name = botDesc.name || "bot"; - - if (options.draft) { - await this.updateDraft(botDesc, desc); - return; - } - - const projectId = this.getProject(); - - botDesc.id = projectId; - - let latestBotRevision; - try { - const { response: { body: data } } = await this.helper.toPromise( - this.api.projectApi, - this.api.projectApi.projectsProjectIdBotGet, botDesc.id - ); - - if (data.revision) { - latestBotRevision = data.revision; - - const { data: newBot } = await this.helper.toPromise( - this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsRevisionPut, - projectId, latestBotRevision, botDesc - ); - const { data: project } = await this.helper.toPromise( - this.api.projectApi, - this.api.projectApi.projectsProjectIdGet, projectId - ); - - console.log(`Updated bot ${colors.green(project.name)} with revision: ${newBot.revision.substring(0, 7)}`); - - } else { - throw Error("Could not find latest bot revision from this project."); - } - } catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - - this.helper.dumpYaml("./bot.yml", desc); - } - - public async discardDraft(botDesc: JsonObject, desc: JsonObject): Promise { - try { - desc.tag = null; - await this.helper.toPromise(this.api.draftApi, this.api.draftApi.botsBotIdDraftDelete, botDesc.id); - console.log("Draft discarded."); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - this.helper.dumpYaml("./bot.yml", desc); - } - - public async discard(options: JsonObject): Promise { - const desc = this.helper.loadYaml("./bot.yml"); - - let bot = Config.create(desc, { left: "${", right: "}" }); - bot = this.compile.execDirectives(bot, process.cwd()); - bot.resolve(); - - const botDesc = bot.get(); - - if (options.draft) { - await this.discardDraft(botDesc, desc); - return; - } - return; - } - - public async updateDraft(botDesc: JsonObject, desc: JsonObject): Promise { - botDesc.id = botDesc.id || uuid(); - - try { - await this.helper.toPromise(this.api.draftApi, this.api.draftApi.botsBotIdDraftPost, botDesc.id, botDesc); - desc.tag = "draft"; - botDesc.tag = "draft"; - console.log("Draft updated."); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - - this.helper.dumpYaml("./bot.yml", desc); - } - - public async delete(options: JsonObject) { - const answer = await this.helper.inquirerPrompt([ - { - type: "confirm", - name: "confirmation", - message: "Are you sure to delete this bot?", - default: false - } - ]); - - if (!answer.confirmation) { - return; - } - - const botId = this.helper.getProjectId(); - - try { - const { data } = await this.helper.toPromise(this.api.botApi, this.api.botApi.botsBotIdDelete, botId); - - console.log("REMOVE BOT SUCCESSFULLY"); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - public async console(options: JsonObject) { - let projectId: string; - let botDesc; - try { - projectId = this.getProject() as string; - botDesc = this.helper.loadYaml("./bot.yml"); - } catch (error) { - console.log(this.helper.wrapError(error)); - return; - } - - const dataEnvironments = await this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet , projectId, null); - const environments: object[] = dataEnvironments.response.body.data; - const choicesEnvironment = environments.map((environment: any) => ({ name: environment.name, value: environment.name })); - choicesEnvironment.push({ name: 'No Environment', value: null }) - - let { environment } = await inquirer.prompt([ - { - type: "list", - name: "environment", - message: "Environment:", - choices: choicesEnvironment - } - ]); - - const con = repl.start({ - prompt: botDesc.name + ">", - writer(obj: any) { - return util.inspect(obj, false, null, true); - } - }); - - con.context.text = function text(str: string) { - let currentSession = this.getLocalSession(); - const message = { - type: "text", - content: str - }; - - const body = { - environmentName: environment, - session: currentSession, - message - }; - if (!body.environmentName) delete body.environmentName - - try { - return this.converse(projectId, body); - } catch (e) { - return this.helper.wrapError(e); - } - }.bind(this); - - con.context.button = function button(op: JsonObject, obj: JsonObject = {}) { - let currentSession = this.getLocalSession(); - obj.op = op; - const message = { - type: "data", - payload: obj - }; - const body = { - environmentName: environment, - session: currentSession, - message - }; - if (!body.environmentName) delete body.environmentName - - try { - return this.converse(projectId, body); - } catch (e) { - return this.helper.wrapError(e); - } - }.bind(this); - - con.context.command = function command(command: string, obj: JsonObject = {}) { - let currentSession = this.getLocalSession(); - const message = { - type: "command", - content: command, - payload: obj - }; - const body = { - environmentName: environment, - session: currentSession, - message - }; - if (!body.environmentName) delete body.environmentName - - try { - return this.converse(projectId, body); - } catch (e) { - return this.helper.wrapError(e); - } - }.bind(this); - - con.context.current = () => this.getLocalSession(); - con.context.clear = () => this.resetSession(); - - con.context.clearCaches = function clearCaches(num: number = 20) { - try { - for (let i = 0; i < num; i++) { - this.sync(this.helper.toPromise(this.api.cachesApi, this.api.cachesApi.cachesDelete)); - } - } catch (e) { - return this.helper.wrapError(e); - } - }.bind(this); - } - - private sync(promise: any) { - if (promise && typeof promise.then === "function") { - let done = false; - let error: Error = null; - let result; - - promise.then((res: any) => { - if (res.data !== "") { - done = true; - result = res; - } else { - error = new Error("Error found. Please check your bot."); - } - }).catch((e: Error) => { - error = e; - }); - - deasync.loopWhile(() => { - return !done && !error; - }); - - if (error) { - throw error; - } - - return result; - } - - - throw new Error("Sync only accept promises"); - } - - public async pull(revision: string, options: JsonObject) { - - let projectId; - let bots; - let botDesc; - - try { - projectId = this.getProject(); - } catch (e) { - console.log(this.helper.wrapError(e)); - return; - } - try { - const { response: { body } } = await this.helper.toPromise( - this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsGet, projectId); - bots = body.data; - - } catch (e) { - console.log("INVALID PROJECT"); - return; - } - try { - if (!revision) { - revision = bots[0].revision; - } - const { response: { body } } = await this.helper.toPromise( - this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsRevisionGet, projectId, revision); - botDesc = body; - - } catch (e) { - console.log("INVALID PROJECT REVISION"); - return; - } - - // remove data - delete botDesc.id; - delete botDesc.revision; - delete botDesc.changelog; - for (const flow in botDesc.flows) { - if (botDesc.flows[flow]) { - for (const state in botDesc.flows[flow].states) { - if (botDesc.flows[flow].states[state]) { - delete botDesc.flows[flow].states[state].style; - } - } - } - } - - console.log(`Pull bot revision ${revision.substring(0, 6)} to bot.yml`); - this.helper.dumpYaml("./bot.yml", botDesc); - - return; - } - - private getProject() { - const projectId = this.helper.getProp("projectId") - - if (!projectId || projectId === "") { - throw Error("Error : You must specify a Project first, execute kata list-project to list your projects."); - } - - return projectId; - } - - private converse(projectId: string, body: Object) { - const { data } = this.sync(this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotConversePost, projectId, body)) as any; - const { session } = data; - this.setLocalSession(session); - return data; - } - - private setLocalSession(session: Object) { - const jsonPath = `${os.homedir()}/.katasession`; - try { - if (session) { - fs.writeFileSync(jsonPath, JSON.stringify(session), "utf8"); - } - } catch (error) { - console.log(this.helper.wrapError(`Error set local session : ${error.message}`)); - } - - } - - private getLocalSession() { - const jsonPath = `${os.homedir()}/.katasession`; - - if (fs.existsSync(jsonPath)) { - return JSON.parse(fs.readFileSync(jsonPath, "utf8")); - } else { - // default session - return { - "channel_id" : "console-channel", - "environment_id" : "console-environment", - "states" : {}, - "contexes" : {}, - "history" : [ ], - "current" : null, - "meta" : null, - "timestamp" : Date.now(), - "data" : {}, - "created_at" : Date.now(), - "updated_at" : Date.now(), - "session_start" : Date.now(), - "session_id" : "test~from~console", - "id" : "test~from~console" - }; - } - } - - private resetSession() { - const jsonPath = `${os.homedir()}/.katasession`; - - if (fs.existsSync(jsonPath)) { - fs.unlinkSync(jsonPath); - return true; - } - } - - public async errors() { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const dataEnvironments = await this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet , projectId, null); - if (dataEnvironments && dataEnvironments.response && dataEnvironments.response.body && dataEnvironments.response.body.data && dataEnvironments.response.body.data.length > 0) { - const environments: object[] = dataEnvironments.response.body.data; - const choicesEnvironment = environments.map((environment: any) => ({ - name: environment.name, - value: environment.id - })); - - let { environmentId } = await inquirer.prompt([ - { - type: "list", - name: "environmentId", - message: "Environment:", - choices: choicesEnvironment - } - ]); - - const dataChannels = await this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet , projectId, environmentId, null); - const channels: object[] = dataChannels.response.body; - const choicesChannel = channels.map((channel: any) => ({ - name: channel.name, - value: channel.id - })); - - let { channelId } = await inquirer.prompt([ - { - type: "list", - name: "channelId", - message: "Channel:", - choices: choicesChannel - } - ]); - - let { start, end, error } = await inquirer.prompt([ - { - type: "text", - name: "start", - message: "Date Start (yyyy-mm-dd):" - }, - { - type: "text", - name: "end", - message: "Date End (yyyy-mm-dd):" - }, - { - type: "list", - name: "error", - message: "Error Group:", - choices: [ - { - name: "User Error", - value: {"group": 1000, "code":"1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100"} - }, - { - name: "System Error", - value: {"group": 4000, "code":"4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100"} - } - ] - }, - ]); - - if (isDate(start) == false) { - start = new Date().setHours(0,0,0) - } else { - start = new Date(start).setHours(0,0,0) - } - if (isDate(end) == false) { - end = new Date().setHours(23,59,59) - } else { - end = new Date(end).setHours(23,59,59) - } - - const errorGroup = error.group - const errorCode = error.code - - const { response } = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdErrorsGet , projectId, environmentId, channelId, errorGroup, errorCode, new Date(start).toISOString(), new Date(end).toISOString()); - - if (response && response.body && response.body.data) { - const table = new Table({ - head: ["Time", "Error Code", "Error Message"], - colWidths: [25, 15, 75] - }); - response.body.data.forEach((project: JsonObject) => { - table.push([project.timestamp, project.errorCode, project.errorMessage]); - }); - console.log(table.toString()); - } - } else { - console.log("Failed to get Environment list"); - } - } else { - console.log("Please select Project first"); - } - } catch (e) { - console.error(this.helper.wrapError(e)); - } - } -} + +import { ICompile, IHelper, ITester } from "interfaces/main"; +import { Component, Config, IHash, JsonObject } from "merapi"; +import { v4 as uuid } from "uuid"; +import { CatchError } from "../scripts/helper"; +import { isDate } from "util"; +import inquirer = require("inquirer"); +const Table = require("cli-table"); + +const colors = require("colors"); +const repl = require("repl"); +const util = require("util"); +const os = require("os"); +const fs = require("fs"); +const deasync = require("deasync"); + +export default class Bot extends Component { + constructor(private compile: ICompile, private helper: IHelper, private tester: ITester, private api: any) { + super(); + } + + public init(name: string, options: JsonObject) { + const botDesc = { + schema: "kata.ai/schema/kata-ml/1.0", + name, + desc: "My First Bot", + flows: { + hello: { + fallback: true, + intents: { + greeting: { + initial: true, + condition: "content == 'hi'" + }, + fallback: { + fallback: true + } + }, + states: { + init: { + initial: true, + transitions: { + greet: { + condition: "intent == \"greeting\"" + }, + other: { + fallback: true + } + } + }, + greet: { + end: true, + action: { + name: "text", + options: { + text: "hi!" + } + } + }, + other: { + end: true, + action: { + name: "text", + options: { + text: "sorry!" + } + } + } + } + } + } + }; + + this.helper.dumpYaml("./bot.yml", botDesc); + + console.log(`Initialized ${name} successfully`); + } + + public async revisions(options: JsonObject) { + try { + const projectId = this.getProject(); + const { data, response } = await this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsGet, projectId); + const result = data; + if (result && result.data) { + console.log("Bot Revision : "); + result.data.forEach((hist: JsonObject) => { + console.log(`- ${hist.revision}`); + }); + } else { + console.log("You must push at least 1 bot to acquire revisions"); + } + } catch (e) { + if (e.code === "ENOENT") { + console.log("kata versions must be executed in bot directory with bot.yml"); + } else { + console.log(this.helper.wrapError(e)); + } + } + } + + public async test(file: string, options: JsonObject) { + const testFiles = file ? [file] : this.helper.getFiles("./test", ".spec.yml"); + const botId = this.helper.getProjectId(); + + if (!botId) { + throw new Error("BOT ID HAS NOT DEFINED"); + } + + const results: JsonObject = {}; + + for (let i = 0; i < testFiles.length; i++) { + const yaml = this.helper.loadYaml(testFiles[i]); + let res; + + switch (yaml.schema) { + case "kata.ai/schema/kata-ml/1.0/test/intents": + res = await this.tester.execIntentTest(yaml, this.api.botApi, botId, console.log); + if (this.hasErrors(res)) { + results[testFiles[i]] = res; + } + break; + case "kata.ai/schema/kata-ml/1.0/test/states": + res = await this.tester.execStateTest(yaml, this.api.botApi, botId, console.log); + if (this.hasErrors(res)) { + results[testFiles[i]] = res; + } + break; + case "kata.ai/schema/kata-ml/1.0/test/actions": + res = await this.tester.execActionsTest(yaml, this.api.botApi, botId, console.log); + if (this.hasErrors(res)) { + results[testFiles[i]] = res; + } + break; + case "kata.ai/schema/kata-ml/1.0/test/flow": + res = await this.tester.execFlowTest(yaml, this.api.botApi, botId, console.log); + if (this.hasErrors(res)) { + results[testFiles[i]] = res; + } + break; + } + } + + this.printResult(results as IHash>); + } + + private hasErrors(res: any) { + return Object.keys(res).some((key) => (res[key] && res[key].length) || res[key] === null); + } + + private printResult(results: IHash> = {}) { + if (Object.keys(results).length) { + console.log(colors.red("Errors:")); + for (const i in results) { + console.log(` ${i}:`); + for (const j in results[i]) { + if (!results[i][j]) { + console.log(` ${colors.red(j + ":")}`); + console.log(` diaenne returns ${colors.red("null")}`); + continue; + } + if (results[i][j].length) { + console.log(` ${colors.red(j + ":")}`); + + results[i][j].forEach((res) => { + console.log(` expecting ${res.field} to be ${colors.green(res.expect)} but got ${colors.red(res.result)}`); + }); + } + } + } + } + } + + @CatchError + public async push(options: JsonObject) { + const desc = this.helper.loadYaml("./bot.yml"); + desc.tag = options.tag || null; + + let bot = Config.create(desc, { left: "${", right: "}" }); + bot = this.compile.execDirectives(bot, process.cwd()); + bot.resolve(); + + const botDesc = bot.get(); + botDesc.name = botDesc.name || "bot"; + + if (options.draft) { + await this.updateDraft(botDesc, desc); + return; + } + + const projectId = this.getProject(); + + botDesc.id = projectId; + + let latestBotRevision; + try { + const { response: { body: data } } = await this.helper.toPromise( + this.api.projectApi, + this.api.projectApi.projectsProjectIdBotGet, botDesc.id + ); + + if (data.revision) { + latestBotRevision = data.revision; + + const { data: newBot } = await this.helper.toPromise( + this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsRevisionPut, + projectId, latestBotRevision, botDesc + ); + const { data: project } = await this.helper.toPromise( + this.api.projectApi, + this.api.projectApi.projectsProjectIdGet, projectId + ); + + console.log(`Updated bot ${colors.green(project.name)} with revision: ${newBot.revision.substring(0, 7)}`); + + } else { + throw Error("Could not find latest bot revision from this project."); + } + } catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + + this.helper.dumpYaml("./bot.yml", desc); + } + + public async discardDraft(botDesc: JsonObject, desc: JsonObject): Promise { + try { + desc.tag = null; + await this.helper.toPromise(this.api.draftApi, this.api.draftApi.botsBotIdDraftDelete, botDesc.id); + console.log("Draft discarded."); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + this.helper.dumpYaml("./bot.yml", desc); + } + + public async discard(options: JsonObject): Promise { + const desc = this.helper.loadYaml("./bot.yml"); + + let bot = Config.create(desc, { left: "${", right: "}" }); + bot = this.compile.execDirectives(bot, process.cwd()); + bot.resolve(); + + const botDesc = bot.get(); + + if (options.draft) { + await this.discardDraft(botDesc, desc); + return; + } + return; + } + + public async updateDraft(botDesc: JsonObject, desc: JsonObject): Promise { + botDesc.id = botDesc.id || uuid(); + + try { + await this.helper.toPromise(this.api.draftApi, this.api.draftApi.botsBotIdDraftPost, botDesc.id, botDesc); + desc.tag = "draft"; + botDesc.tag = "draft"; + console.log("Draft updated."); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + + this.helper.dumpYaml("./bot.yml", desc); + } + + public async delete(options: JsonObject) { + const answer = await this.helper.inquirerPrompt([ + { + type: "confirm", + name: "confirmation", + message: "Are you sure to delete this bot?", + default: false + } + ]); + + if (!answer.confirmation) { + return; + } + + const botId = this.helper.getProjectId(); + + try { + const { data } = await this.helper.toPromise(this.api.botApi, this.api.botApi.botsBotIdDelete, botId); + + console.log("REMOVE BOT SUCCESSFULLY"); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + public async console(options: JsonObject) { + let projectId: string; + let botDesc; + try { + projectId = this.getProject() as string; + botDesc = this.helper.loadYaml("./bot.yml"); + } catch (error) { + console.log(this.helper.wrapError(error)); + return; + } + + const dataEnvironments = await this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet , projectId, null); + const environments: object[] = dataEnvironments.response.body.data; + const choicesEnvironment = environments.map((environment: any) => ({ name: environment.name, value: environment.name })); + choicesEnvironment.push({ name: 'No Environment', value: null }) + + let { environment } = await inquirer.prompt([ + { + type: "list", + name: "environment", + message: "Environment:", + choices: choicesEnvironment + } + ]); + + const con = repl.start({ + prompt: botDesc.name + ">", + writer(obj: any) { + return util.inspect(obj, false, null, true); + } + }); + + con.context.text = function text(str: string) { + let currentSession = this.getLocalSession(); + const message = { + type: "text", + content: str + }; + + const body = { + environmentName: environment, + session: currentSession, + message + }; + if (!body.environmentName) delete body.environmentName + + try { + return this.converse(projectId, body); + } catch (e) { + return this.helper.wrapError(e); + } + }.bind(this); + + con.context.button = function button(op: JsonObject, obj: JsonObject = {}) { + let currentSession = this.getLocalSession(); + obj.op = op; + const message = { + type: "data", + payload: obj + }; + const body = { + environmentName: environment, + session: currentSession, + message + }; + if (!body.environmentName) delete body.environmentName + + try { + return this.converse(projectId, body); + } catch (e) { + return this.helper.wrapError(e); + } + }.bind(this); + + con.context.command = function command(command: string, obj: JsonObject = {}) { + let currentSession = this.getLocalSession(); + const message = { + type: "command", + content: command, + payload: obj + }; + const body = { + environmentName: environment, + session: currentSession, + message + }; + if (!body.environmentName) delete body.environmentName + + try { + return this.converse(projectId, body); + } catch (e) { + return this.helper.wrapError(e); + } + }.bind(this); + + con.context.current = () => this.getLocalSession(); + con.context.clear = () => this.resetSession(); + + con.context.clearCaches = function clearCaches(num: number = 20) { + try { + for (let i = 0; i < num; i++) { + this.sync(this.helper.toPromise(this.api.cachesApi, this.api.cachesApi.cachesDelete)); + } + } catch (e) { + return this.helper.wrapError(e); + } + }.bind(this); + } + + private sync(promise: any) { + if (promise && typeof promise.then === "function") { + let done = false; + let error: Error = null; + let result; + + promise.then((res: any) => { + if (res.data !== "") { + done = true; + result = res; + } else { + error = new Error("Error found. Please check your bot."); + } + }).catch((e: Error) => { + error = e; + }); + + deasync.loopWhile(() => { + return !done && !error; + }); + + if (error) { + throw error; + } + + return result; + } + + + throw new Error("Sync only accept promises"); + } + + public async pull(revision: string, options: JsonObject) { + + let projectId; + let bots; + let botDesc; + + try { + projectId = this.getProject(); + } catch (e) { + console.log(this.helper.wrapError(e)); + return; + } + try { + const { response: { body } } = await this.helper.toPromise( + this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsGet, projectId); + bots = body.data; + + } catch (e) { + console.log("INVALID PROJECT"); + return; + } + try { + if (!revision) { + revision = bots[0].revision; + } + const { response: { body } } = await this.helper.toPromise( + this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsRevisionGet, projectId, revision); + botDesc = body; + + } catch (e) { + console.log("INVALID PROJECT REVISION"); + return; + } + + // remove data + delete botDesc.id; + delete botDesc.revision; + delete botDesc.changelog; + for (const flow in botDesc.flows) { + if (botDesc.flows[flow]) { + for (const state in botDesc.flows[flow].states) { + if (botDesc.flows[flow].states[state]) { + delete botDesc.flows[flow].states[state].style; + } + } + } + } + + console.log(`Pull bot revision ${revision.substring(0, 6)} to bot.yml`); + this.helper.dumpYaml("./bot.yml", botDesc); + + return; + } + + private getProject() { + const projectId = this.helper.getProp("projectId") + + if (!projectId || projectId === "") { + throw Error("Error : You must specify a Project first, execute kata list-project to list your projects."); + } + + return projectId; + } + + private converse(projectId: string, body: Object) { + const { data } = this.sync(this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotConversePost, projectId, body)) as any; + const { session } = data; + this.setLocalSession(session); + return data; + } + + private setLocalSession(session: Object) { + const jsonPath = `${os.homedir()}/.katasession`; + try { + if (session) { + fs.writeFileSync(jsonPath, JSON.stringify(session), "utf8"); + } + } catch (error) { + console.log(this.helper.wrapError(`Error set local session : ${error.message}`)); + } + + } + + private getLocalSession() { + const jsonPath = `${os.homedir()}/.katasession`; + + if (fs.existsSync(jsonPath)) { + return JSON.parse(fs.readFileSync(jsonPath, "utf8")); + } else { + // default session + return { + "channel_id" : "console-channel", + "environment_id" : "console-environment", + "states" : {}, + "contexes" : {}, + "history" : [ ], + "current" : null, + "meta" : null, + "timestamp" : Date.now(), + "data" : {}, + "created_at" : Date.now(), + "updated_at" : Date.now(), + "session_start" : Date.now(), + "session_id" : "test~from~console", + "id" : "test~from~console" + }; + } + } + + private resetSession() { + const jsonPath = `${os.homedir()}/.katasession`; + + if (fs.existsSync(jsonPath)) { + fs.unlinkSync(jsonPath); + return true; + } + } + + public async errors() { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const dataEnvironments = await this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet , projectId, null); + if (dataEnvironments && dataEnvironments.response && dataEnvironments.response.body && dataEnvironments.response.body.data && dataEnvironments.response.body.data.length > 0) { + const environments: object[] = dataEnvironments.response.body.data; + const choicesEnvironment = environments.map((environment: any) => ({ + name: environment.name, + value: environment.id + })); + + let { environmentId } = await inquirer.prompt([ + { + type: "list", + name: "environmentId", + message: "Environment:", + choices: choicesEnvironment + } + ]); + + const dataChannels = await this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet , projectId, environmentId, null); + const channels: object[] = dataChannels.response.body; + const choicesChannel = channels.map((channel: any) => ({ + name: channel.name, + value: channel.id + })); + + let { channelId } = await inquirer.prompt([ + { + type: "list", + name: "channelId", + message: "Channel:", + choices: choicesChannel + } + ]); + + let { start, end, error } = await inquirer.prompt([ + { + type: "text", + name: "start", + message: "Date Start (yyyy-mm-dd):" + }, + { + type: "text", + name: "end", + message: "Date End (yyyy-mm-dd):" + }, + { + type: "list", + name: "error", + message: "Error Group:", + choices: [ + { + name: "User Error", + value: {"group": 1000, "code":"1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100"} + }, + { + name: "System Error", + value: {"group": 4000, "code":"4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100"} + } + ] + }, + ]); + + if (isDate(start) == false) { + start = new Date().setHours(0,0,0) + } else { + start = new Date(start).setHours(0,0,0) + } + if (isDate(end) == false) { + end = new Date().setHours(23,59,59) + } else { + end = new Date(end).setHours(23,59,59) + } + + const errorGroup = error.group + const errorCode = error.code + + const { response } = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdErrorsGet , projectId, environmentId, channelId, errorGroup, errorCode, new Date(start).toISOString(), new Date(end).toISOString()); + + if (response && response.body && response.body.data) { + const table = new Table({ + head: ["Time", "Error Code", "Error Message"], + colWidths: [25, 15, 75] + }); + response.body.data.forEach((project: JsonObject) => { + table.push([project.timestamp, project.errorCode, project.errorMessage]); + }); + console.log(table.toString()); + } + } else { + console.log("Failed to get Environment list"); + } + } else { + console.log("Please select Project first"); + } + } catch (e) { + console.error(this.helper.wrapError(e)); + } + } +} diff --git a/components/bots/channel.ts b/components/bots/channel.ts index 705c806..49c778a 100644 --- a/components/bots/channel.ts +++ b/components/bots/channel.ts @@ -1,312 +1,312 @@ - -import { IHelper } from "interfaces/main"; -import { Config, JsonObject } from "merapi"; -import Environment from "./environment"; -import inquirer = require("inquirer"); -const Table = require("cli-table"); - -export default class Channel { - constructor( - private helper: IHelper, - private api: any, - private config: Config, - private environment: Environment, - ) { } - - public async addChannel(channelName: string, options: JsonObject) { - const projectId = this.helper.getProjectId(); - const environmentId = await this.environment.askEnvironmentId(); - - try { - const { response: { body: channelsBody } } = await this.helper.toPromise( - this.api.deploymentApi, - this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, - projectId, environmentId, {}, - ); - - const channels: { name: string; id: string }[] = channelsBody; - const channelWithSameName = channels.find((row) => row.name === channelName); - if (channelWithSameName) { - throw new Error("CHANNEL NAME HAS BEEN USED"); - } - - if (!options.data) { - options.data = "{}"; - } - - let channelData = JSON.parse(options.data as string) as JsonObject; - channelData.name = channelName; - channelData = await this.inquireChannelData(channelData); - - const result = await this.helper.toPromise( - this.api.deploymentApi, - this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsPost, - projectId, - environmentId, - channelData, - ); - console.log(result.response.body); - const channel = result.response.body; - - - console.log("CHANNEL ADDED SUCCESSFULLY"); - console.log(`Paste this url to ${channelData.type} webhook : ${channel.webhook}`); - if (channelData.type === "fbmessenger") { - const channelOptions = JSON.parse(channel.options as string) as JsonObject; - console.log(`And also this token : ${channelOptions.challenge} to your FB Challenge token.`); - } - - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - - public async list() { - const projectId = this.helper.getProjectId(); - const environmentId = await this.environment.askEnvironmentId(); - - try { - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, - projectId, environmentId, {} - ); - - if (!body) { - throw Error("Failed to list Channels for this environment."); - } - - const table = new Table({ - head: ["Channel Name", "Channel Type", "Channel ID"], - colWidths: [30, 30, 42] - }); - - body.forEach((channel: JsonObject) => { - table.push([channel.name, channel.type, channel.id]); - }); - console.log(table.toString()); - - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - - public async removeChannel( - channelName: string, options: JsonObject - ) { - const projectId = this.helper.getProjectId(); - const environmentId = await this.environment.askEnvironmentId(); - - try { - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdGet, - environmentId, projectId, - ); - const deployment = body; - const channels: { name: string; id: string }[] = deployment.channels; - - const channel = channels.find((row) => row.name === channelName); - if (!channel) { - throw new Error("CHANNEL NOT FOUND"); - } - console.log(channel); - - await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsChannelIdDelete, - projectId, environmentId, channel.id - ); - - console.log("CHANNEL REMOVED SUCCESSFULLY"); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - private async inquireChannelData(data: JsonObject): Promise { - const { id, name, type, token, refreshToken, secret, url, additionalOptions } = data; - const channelType = this.config.default("config.channels.type", []); - const channelUrl = this.config.default("config.channels.url", []); - const answer = await inquirer.prompt([ - { - type: "list", - name: "type", - message: `channel type : `, - choices: channelType, - when: () => !type, - validate: (type: string) => { - if (!type) { - return "Channel type cannot be empty"; - } - return true; - }, - filter: (type: string) => { - return type.toLowerCase(); - } - }, - { - type: "input", - name: "options.token", - message: "channel token: ", - when: () => !token, - filter(token: string) { - if (!token || token.length === 0) { - return null; - } - - return token; - } - }, - { - type: "input", - name: "options.refreshToken", - message: "channel refresh token: ", - when: () => !refreshToken, - filter(refreshToken: string) { - if (!refreshToken || refreshToken.length === 0) { - return null; - } - - return refreshToken; - } - }, - { - type: "input", - name: "options.secret", - message: "channel secret key: ", - when() { return !secret; }, - filter(secret: string) { - if (!secret || secret.length === 0) { - return null; - } - - return secret; - } - }, - { - type: "input", - name: "additionalOptions", - message: "channel additional options: ", - when() { return !additionalOptions; }, - filter(additionalOptions: string): JsonObject { - if (!additionalOptions || additionalOptions.length === 0) { - return null; - } - try { - const result = JSON.parse(additionalOptions); - if (typeof result === "object") { - return result; - } else { - return { error: true }; - } - } catch (error) { - return { error }; - } - }, - validate(additionalOptions: JsonObject) { - if (!additionalOptions) { - return true; - } - if (additionalOptions.error) { - return "Channel options must be a JSON Format"; - } else { - return true; - } - } - }, - { - type: "input", - name: "url", - message(answer: JsonObject) { - if (answer.type !== "generic") { - return `channel api url (default: ${channelUrl[answer.type as any]}) :`; - } - - return "channel api url : "; - }, - when() { return !url; }, - validate(url: string, answer: JsonObject) { - if (!url && answer.type === "generic") { - return "Channel api url cannot be empty"; - } - - return true; - }, - default: (answer: JsonObject) => { - return channelUrl[answer.type as any]; - } - } - - ]); - - let options = { token, refreshToken, secret, }; - - if (additionalOptions) { - options = { ...options, ...additionalOptions as JsonObject }; - } - - const res = { id, name, type, options, url }; - try { - answer.options = Object.assign(answer.options, answer.additionalOptions); - answer.additionalOptions = undefined; - } catch (error) { - // - } - return { ...res, ...answer }; - } - - public async updateChannel(channelName: string, options: JsonObject) { - try { - const projectId = this.helper.getProjectId(); - if (!projectId) { - throw new Error("Please select project first"); - } - - const environmentId = await this.environment.askEnvironmentId(); - - const { response: { body: channelsBody } } = await this.helper.toPromise( - this.api.deploymentApi, - this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, - projectId, environmentId, {}, - ); - - const channels: { name: string; id: string }[] = channelsBody; - if (channels.length == 0) { - throw new Error("Channel not found"); - } - - const channelFound = channels.find((row) => row.name === channelName); - if (!channelFound) { - throw new Error("Channel not found"); - } - - if (!options.data) { - options.data = "{}"; - } - - let channelData = JSON.parse(options.data as string) as JsonObject; - channelData.name = channelName; - channelData = await this.inquireChannelData(channelData); - - const result = await this.helper.toPromise( - this.api.deploymentApi, - this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsChannelIdPut, - projectId, - environmentId, - channelFound.id, - channelData, - ); - console.log(result.response.body); - const channel = result.response.body; - - console.log("Channel added successfully"); - console.log(`Paste this url to ${channelData.type} webhook : ${channel.webhook}`); - if (channelData.type === "fbmessenger") { - const channelOptions = JSON.parse(channel.options as string) as JsonObject; - console.log(`And also this token : ${channelOptions.challenge} to your FB Challenge token.`); - } - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } -} + +import { IHelper } from "interfaces/main"; +import { Config, JsonObject } from "merapi"; +import Environment from "./environment"; +import inquirer = require("inquirer"); +const Table = require("cli-table"); + +export default class Channel { + constructor( + private helper: IHelper, + private api: any, + private config: Config, + private environment: Environment, + ) { } + + public async addChannel(channelName: string, options: JsonObject) { + const projectId = this.helper.getProjectId(); + const environmentId = await this.environment.askEnvironmentId(); + + try { + const { response: { body: channelsBody } } = await this.helper.toPromise( + this.api.deploymentApi, + this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, + projectId, environmentId, {}, + ); + + const channels: { name: string; id: string }[] = channelsBody; + const channelWithSameName = channels.find((row) => row.name === channelName); + if (channelWithSameName) { + throw new Error("CHANNEL NAME HAS BEEN USED"); + } + + if (!options.data) { + options.data = "{}"; + } + + let channelData = JSON.parse(options.data as string) as JsonObject; + channelData.name = channelName; + channelData = await this.inquireChannelData(channelData); + + const result = await this.helper.toPromise( + this.api.deploymentApi, + this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsPost, + projectId, + environmentId, + channelData, + ); + console.log(result.response.body); + const channel = result.response.body; + + + console.log("CHANNEL ADDED SUCCESSFULLY"); + console.log(`Paste this url to ${channelData.type} webhook : ${channel.webhook}`); + if (channelData.type === "fbmessenger") { + const channelOptions = JSON.parse(channel.options as string) as JsonObject; + console.log(`And also this token : ${channelOptions.challenge} to your FB Challenge token.`); + } + + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + + public async list() { + const projectId = this.helper.getProjectId(); + const environmentId = await this.environment.askEnvironmentId(); + + try { + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, + projectId, environmentId, {} + ); + + if (!body) { + throw Error("Failed to list Channels for this environment."); + } + + const table = new Table({ + head: ["Channel Name", "Channel Type", "Channel ID"], + colWidths: [30, 30, 42] + }); + + body.forEach((channel: JsonObject) => { + table.push([channel.name, channel.type, channel.id]); + }); + console.log(table.toString()); + + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + + public async removeChannel( + channelName: string, options: JsonObject + ) { + const projectId = this.helper.getProjectId(); + const environmentId = await this.environment.askEnvironmentId(); + + try { + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdGet, + environmentId, projectId, + ); + const deployment = body; + const channels: { name: string; id: string }[] = deployment.channels; + + const channel = channels.find((row) => row.name === channelName); + if (!channel) { + throw new Error("CHANNEL NOT FOUND"); + } + console.log(channel); + + await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsChannelIdDelete, + projectId, environmentId, channel.id + ); + + console.log("CHANNEL REMOVED SUCCESSFULLY"); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + private async inquireChannelData(data: JsonObject): Promise { + const { id, name, type, token, refreshToken, secret, url, additionalOptions } = data; + const channelType = this.config.default("config.channels.type", []); + const channelUrl = this.config.default("config.channels.url", []); + const answer = await inquirer.prompt([ + { + type: "list", + name: "type", + message: `channel type : `, + choices: channelType, + when: () => !type, + validate: (type: string) => { + if (!type) { + return "Channel type cannot be empty"; + } + return true; + }, + filter: (type: string) => { + return type.toLowerCase(); + } + }, + { + type: "input", + name: "options.token", + message: "channel token: ", + when: () => !token, + filter(token: string) { + if (!token || token.length === 0) { + return null; + } + + return token; + } + }, + { + type: "input", + name: "options.refreshToken", + message: "channel refresh token: ", + when: () => !refreshToken, + filter(refreshToken: string) { + if (!refreshToken || refreshToken.length === 0) { + return null; + } + + return refreshToken; + } + }, + { + type: "input", + name: "options.secret", + message: "channel secret key: ", + when() { return !secret; }, + filter(secret: string) { + if (!secret || secret.length === 0) { + return null; + } + + return secret; + } + }, + { + type: "input", + name: "additionalOptions", + message: "channel additional options: ", + when() { return !additionalOptions; }, + filter(additionalOptions: string): JsonObject { + if (!additionalOptions || additionalOptions.length === 0) { + return null; + } + try { + const result = JSON.parse(additionalOptions); + if (typeof result === "object") { + return result; + } else { + return { error: true }; + } + } catch (error) { + return { error }; + } + }, + validate(additionalOptions: JsonObject) { + if (!additionalOptions) { + return true; + } + if (additionalOptions.error) { + return "Channel options must be a JSON Format"; + } else { + return true; + } + } + }, + { + type: "input", + name: "url", + message(answer: JsonObject) { + if (answer.type !== "generic") { + return `channel api url (default: ${channelUrl[answer.type as any]}) :`; + } + + return "channel api url : "; + }, + when() { return !url; }, + validate(url: string, answer: JsonObject) { + if (!url && answer.type === "generic") { + return "Channel api url cannot be empty"; + } + + return true; + }, + default: (answer: JsonObject) => { + return channelUrl[answer.type as any]; + } + } + + ]); + + let options = { token, refreshToken, secret, }; + + if (additionalOptions) { + options = { ...options, ...additionalOptions as JsonObject }; + } + + const res = { id, name, type, options, url }; + try { + answer.options = Object.assign(answer.options, answer.additionalOptions); + answer.additionalOptions = undefined; + } catch (error) { + // + } + return { ...res, ...answer }; + } + + public async updateChannel(channelName: string, options: JsonObject) { + try { + const projectId = this.helper.getProjectId(); + if (!projectId) { + throw new Error("Please select project first"); + } + + const environmentId = await this.environment.askEnvironmentId(); + + const { response: { body: channelsBody } } = await this.helper.toPromise( + this.api.deploymentApi, + this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, + projectId, environmentId, {}, + ); + + const channels: { name: string; id: string }[] = channelsBody; + if (channels.length == 0) { + throw new Error("Channel not found"); + } + + const channelFound = channels.find((row) => row.name === channelName); + if (!channelFound) { + throw new Error("Channel not found"); + } + + if (!options.data) { + options.data = "{}"; + } + + let channelData = JSON.parse(options.data as string) as JsonObject; + channelData.name = channelName; + channelData = await this.inquireChannelData(channelData); + + const result = await this.helper.toPromise( + this.api.deploymentApi, + this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsChannelIdPut, + projectId, + environmentId, + channelFound.id, + channelData, + ); + console.log(result.response.body); + const channel = result.response.body; + + console.log("Channel added successfully"); + console.log(`Paste this url to ${channelData.type} webhook : ${channel.webhook}`); + if (channelData.type === "fbmessenger") { + const channelOptions = JSON.parse(channel.options as string) as JsonObject; + console.log(`And also this token : ${channelOptions.challenge} to your FB Challenge token.`); + } + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } +} diff --git a/components/bots/deployment.ts b/components/bots/deployment.ts index 9a510bb..5d61b91 100644 --- a/components/bots/deployment.ts +++ b/components/bots/deployment.ts @@ -1,186 +1,186 @@ - -import { IHelper } from "interfaces/main"; -import { JsonObject } from "merapi"; -const Table = require("cli-table"); -import inquirer = require("inquirer"); - -export default class Deployment { - constructor(private helper: IHelper, private api: any) { - } - - public async create(versionType?: string) { - const projectId = this.helper.getProjectId(); - const { response: { body: project } } = await this.helper.toPromise( - this.api.projectApi, this.api.projectApi.projectsProjectIdGet, - projectId - ); - // TODO: {page:1, limit:1} - let botRevision: string; - let nluRevision: string; - let cmsRevision: string; - - try { - const { response: { body: data } } = await this.helper.toPromise( - this.api.projectApi, - this.api.projectApi.projectsProjectIdBotGet, projectId - ); - - if (data.revision) { - botRevision = data.revision; - } - } catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - - try { - const { response: {body: data} } = await this.helper.toPromise(this.api.projectApi, - this.api.projectApi.projectsProjectIdNluRevisionsGet, projectId); - - if (data.data[0] && data.data[0].revision) { - nluRevision = data.data[0].revision; - } - } catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - - try { - const { response: {body: data} } = await this.helper.toPromise(this.api.projectApi, - this.api.projectApi.projectsProjectIdCmsGet, projectId); - if (data.revision) { - cmsRevision = data.revision; - } - } catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - - let targetVersion; - - try { - // get previous deployment version - const { response: { body: latestDeployment } } = await this.helper.toPromise(this.api.projectApi, - this.api.projectApi.projectsProjectIdDeploymentGet, projectId); - const prevVersion = latestDeployment.version; - let [major, minor, patch] = prevVersion.split("."); - - if (versionType === "major") { - major = Number(major) + 1; - minor = 0; - patch = 0; - } else if (versionType === "minor") { - minor = Number(minor) + 1; - patch = 0; - } else { - patch = Number(patch) + 1; - } - targetVersion = `${major}.${minor}.${patch}`; - - } catch (e) { - targetVersion = "0.0.1"; - } - - try { - const postBody = { - version: targetVersion, - botRevision, - nluRevision, - cmsRevision, - modules: (null as any), - }; - - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsPost, - postBody, projectId, - ); - - - console.log(`Bot Revision: ${botRevision.substring(0, 7)}`); - console.log(`NLU Revision: ${nluRevision.substring(0, 7)}`); - console.log(`CMS Revision: ${cmsRevision.substring(0, 7)}`); - console.log(`Succesfully create Deployment to version ${targetVersion}`); - } catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - } - - public async list(options: JsonObject) { - const projectId = this.helper.getProjectId(); - - try { - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, {} - ); - - if (body && body.data) { - const table = new Table({ - head: ["Deployment Name", "Deployment Version", "Bot Revision"], - colWidths: [30, 30, 42] - }); - body.data.forEach((deployment: JsonObject) => { - table.push([deployment.name, deployment.version, deployment.botRevision]); - }); - - console.log(table.toString()); - } - } catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - } - - public async rollback(version: string) { - try { - const projectId = this.helper.getProjectId(); - const author = this.helper.getProp("current_login"); - - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { limit: 1000000, page: 1} - ); - - if (body && body.data) { - const deployments: object[] = body.data; - const versionData: any = deployments.find((deployment: any) => deployment.version === version); - if (!versionData) { - throw new Error("Version not found"); - } - - let { changelog, confirm } = await inquirer.prompt([ - { - type: "text", - name: "changelog", - message: "Changelog:", - }, - { - type: "confirm", - name: "confirm", - message: `IMPORTANT: Existing NL training data will also be rolled back to version ${versionData.version}`, - default: true, - } - ]); - - const requestBody = { - author, - changelog, - version: versionData.version - } - - if (confirm) { - const { response } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.deploymentsDeploymentIdRollbackPost, versionData.id, requestBody - ); - - if (response && response.body) { - console.log(`Successfully rolled back to version ${versionData.version}`) - } else { - console.log(`Error when trying to rollback to version ${versionData.version}`) - } - } - } - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } -} + +import { IHelper } from "interfaces/main"; +import { JsonObject } from "merapi"; +const Table = require("cli-table"); +import inquirer = require("inquirer"); + +export default class Deployment { + constructor(private helper: IHelper, private api: any) { + } + + public async create(versionType?: string) { + const projectId = this.helper.getProjectId(); + const { response: { body: project } } = await this.helper.toPromise( + this.api.projectApi, this.api.projectApi.projectsProjectIdGet, + projectId + ); + // TODO: {page:1, limit:1} + let botRevision: string; + let nluRevision: string; + let cmsRevision: string; + + try { + const { response: { body: data } } = await this.helper.toPromise( + this.api.projectApi, + this.api.projectApi.projectsProjectIdBotGet, projectId + ); + + if (data.revision) { + botRevision = data.revision; + } + } catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + + try { + const { response: {body: data} } = await this.helper.toPromise(this.api.projectApi, + this.api.projectApi.projectsProjectIdNluRevisionsGet, projectId); + + if (data.data[0] && data.data[0].revision) { + nluRevision = data.data[0].revision; + } + } catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + + try { + const { response: {body: data} } = await this.helper.toPromise(this.api.projectApi, + this.api.projectApi.projectsProjectIdCmsGet, projectId); + if (data.revision) { + cmsRevision = data.revision; + } + } catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + + let targetVersion; + + try { + // get previous deployment version + const { response: { body: latestDeployment } } = await this.helper.toPromise(this.api.projectApi, + this.api.projectApi.projectsProjectIdDeploymentGet, projectId); + const prevVersion = latestDeployment.version; + let [major, minor, patch] = prevVersion.split("."); + + if (versionType === "major") { + major = Number(major) + 1; + minor = 0; + patch = 0; + } else if (versionType === "minor") { + minor = Number(minor) + 1; + patch = 0; + } else { + patch = Number(patch) + 1; + } + targetVersion = `${major}.${minor}.${patch}`; + + } catch (e) { + targetVersion = "0.0.1"; + } + + try { + const postBody = { + version: targetVersion, + botRevision, + nluRevision, + cmsRevision, + modules: (null as any), + }; + + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsPost, + postBody, projectId, + ); + + + console.log(`Bot Revision: ${botRevision.substring(0, 7)}`); + console.log(`NLU Revision: ${nluRevision.substring(0, 7)}`); + console.log(`CMS Revision: ${cmsRevision.substring(0, 7)}`); + console.log(`Succesfully create Deployment to version ${targetVersion}`); + } catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + } + + public async list(options: JsonObject) { + const projectId = this.helper.getProjectId(); + + try { + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, {} + ); + + if (body && body.data) { + const table = new Table({ + head: ["Deployment Name", "Deployment Version", "Bot Revision"], + colWidths: [30, 30, 42] + }); + body.data.forEach((deployment: JsonObject) => { + table.push([deployment.name, deployment.version, deployment.botRevision]); + }); + + console.log(table.toString()); + } + } catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + } + + public async rollback(version: string) { + try { + const projectId = this.helper.getProjectId(); + const author = this.helper.getProp("current_login"); + + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { limit: 1000000, page: 1} + ); + + if (body && body.data) { + const deployments: object[] = body.data; + const versionData: any = deployments.find((deployment: any) => deployment.version === version); + if (!versionData) { + throw new Error("Version not found"); + } + + let { changelog, confirm } = await inquirer.prompt([ + { + type: "text", + name: "changelog", + message: "Changelog:", + }, + { + type: "confirm", + name: "confirm", + message: `IMPORTANT: Existing NL training data will also be rolled back to version ${versionData.version}`, + default: true, + } + ]); + + const requestBody = { + author, + changelog, + version: versionData.version + } + + if (confirm) { + const { response } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.deploymentsDeploymentIdRollbackPost, versionData.id, requestBody + ); + + if (response && response.body) { + console.log(`Successfully rolled back to version ${versionData.version}`) + } else { + console.log(`Error when trying to rollback to version ${versionData.version}`) + } + } + } + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } +} diff --git a/components/bots/environment.ts b/components/bots/environment.ts index 230140a..f7dff0d 100644 --- a/components/bots/environment.ts +++ b/components/bots/environment.ts @@ -1,197 +1,197 @@ - -import { IHelper } from "interfaces/main"; -import inquirer = require("inquirer"); -const Table = require("cli-table"); - -export default class Environment { - constructor( - private helper: IHelper, - private api: any, - ) { } - - public async create(slug: string) { - const projectId = this.helper.getProjectId(); - - if (slug.length > 20) { - console.error("error: Namespace length can not exceed 20 characters"); - return; - } - - try { - const deployment = await this.getLatestDeployment(); - if (!deployment) { - throw Error("Deployment not found"); - } - - const name = await this.askPredefinedEnvironmentName(); - - const existEnvs = await this.listEnvironment(); - for (const existEnv of existEnvs) { - if ((existEnv.name as string).toLowerCase() === name.toLowerCase()) { - throw new Error( - "Can not create environment with same name. " + - "Please use command update-environment."); - } - } - - const postBody = { - depId: projectId, - depVersion: deployment.version, - name, slug, - }; - - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsPost, - projectId, postBody, - ); - - console.log(body); - console.log("ENVIRONMENT CREATED SUCCESSFULLY"); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - - public async list() { - try { - const environmentList = await this.listEnvironment(); - - const table = new Table({ - head: ["Environment Name", "Environment Slug", "Environment ID", "Deployment Version"], - colWidths: [30, 30, 42, 30] - }); - environmentList.forEach((environment) => { - table.push([environment.name, String(environment.slug), environment.id, environment.depVersion]); - }); - - console.log(table.toString()); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - private async askDeploymentId(prop: { message?: string } = {}): Promise { - const projectId = this.helper.getProjectId(); - - let page = 1; - while (true) { - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { - page - } - ); - const choices = body.data.map((row: any) => ({ name: `(${row.version})`, value: row.version })); - - if (body.total > body.page * body.limit) { - choices.push({name: "Load More", value: -1}); - } - - const { deploymentVersion } = await inquirer.prompt([ - { - type: "list", - name: "deploymentVersion", - message: prop.message || "Select Deployment:", - paginated: false, - choices - }, - ]); - if (deploymentVersion === -1) { - page++; - continue; - } - return deploymentVersion; - } - } - - public async update(newDeploymentVersion: string) { - const projectId = this.helper.getProjectId(); - if (!newDeploymentVersion) { - newDeploymentVersion = await this.askDeploymentId(); - } - if (!/[0-9]+\.[0-9]+\.[0-9]+/.test(newDeploymentVersion)) { - console.error("error: Deployment version must be in the format of <0-9>.<0-9>.<0-9>"); - return; - } - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { limit: 1000000 } - ); - if (!body.data.find((data: any) => data.version === newDeploymentVersion)) { - console.error(`error: There are no deployment with version ${newDeploymentVersion}`); - return; - } - - try { - const environmentId = await this.askEnvironmentId({ - message: "Select which Environment to update: " - }); - - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdPut, - environmentId, projectId, { depVersion: newDeploymentVersion } - ); - - if (!body) { - throw Error("Error updating Environment"); - } - - return console.log(body); - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async askEnvironmentId(prop: { message?: string } = {}): Promise { - const environmentList = await this.listEnvironment(); - const choices = environmentList.map((row: any) => ({ name: `${row.name} (${row.depVersion})`, value: row.id })); - - const { environmentId } = await inquirer.prompt([ - { - type: "list", - name: "environmentId", - message: prop.message || "Select Environment:", - paginated: false, - choices - }, - ]); - return environmentId; - } - - private async askPredefinedEnvironmentName(): Promise { - const environmentNames = ["Development", "Production", "Staging"]; - const choices = environmentNames.map((name) => ({ name, value: name })); - - const { environmentName } = await inquirer.prompt([ - { - type: "list", - name: "environmentName", - message: "Which Environment to create?", - paginated: false, - choices - }, - ]); - - return environmentName; - } - - private async getLatestDeployment() { - const projectId = this.helper.getProjectId(); - - const { response } = await this.helper.toPromise( - this.api.projectApi, this.api.projectApi.projectsProjectIdDeploymentGet, projectId - ); - - return response && response.body; - } - - private async listEnvironment(): Promise { - const projectId = this.helper.getProp("projectId"); - const { response: { body } } = await this.helper.toPromise( - this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet, projectId, {} - ); - if (!body || !body.data) { - throw Error("Failed to list environments."); - } - return body.data; - } -} + +import { IHelper } from "interfaces/main"; +import inquirer = require("inquirer"); +const Table = require("cli-table"); + +export default class Environment { + constructor( + private helper: IHelper, + private api: any, + ) { } + + public async create(slug: string) { + const projectId = this.helper.getProjectId(); + + if (slug.length > 20) { + console.error("error: Namespace length can not exceed 20 characters"); + return; + } + + try { + const deployment = await this.getLatestDeployment(); + if (!deployment) { + throw Error("Deployment not found"); + } + + const name = await this.askPredefinedEnvironmentName(); + + const existEnvs = await this.listEnvironment(); + for (const existEnv of existEnvs) { + if ((existEnv.name as string).toLowerCase() === name.toLowerCase()) { + throw new Error( + "Can not create environment with same name. " + + "Please use command update-environment."); + } + } + + const postBody = { + depId: projectId, + depVersion: deployment.version, + name, slug, + }; + + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsPost, + projectId, postBody, + ); + + console.log(body); + console.log("ENVIRONMENT CREATED SUCCESSFULLY"); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + + public async list() { + try { + const environmentList = await this.listEnvironment(); + + const table = new Table({ + head: ["Environment Name", "Environment Slug", "Environment ID", "Deployment Version"], + colWidths: [30, 30, 42, 30] + }); + environmentList.forEach((environment) => { + table.push([environment.name, String(environment.slug), environment.id, environment.depVersion]); + }); + + console.log(table.toString()); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + private async askDeploymentId(prop: { message?: string } = {}): Promise { + const projectId = this.helper.getProjectId(); + + let page = 1; + while (true) { + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { + page + } + ); + const choices = body.data.map((row: any) => ({ name: `(${row.version})`, value: row.version })); + + if (body.total > body.page * body.limit) { + choices.push({name: "Load More", value: -1}); + } + + const { deploymentVersion } = await inquirer.prompt([ + { + type: "list", + name: "deploymentVersion", + message: prop.message || "Select Deployment:", + paginated: false, + choices + }, + ]); + if (deploymentVersion === -1) { + page++; + continue; + } + return deploymentVersion; + } + } + + public async update(newDeploymentVersion: string) { + const projectId = this.helper.getProjectId(); + if (!newDeploymentVersion) { + newDeploymentVersion = await this.askDeploymentId(); + } + if (!/[0-9]+\.[0-9]+\.[0-9]+/.test(newDeploymentVersion)) { + console.error("error: Deployment version must be in the format of <0-9>.<0-9>.<0-9>"); + return; + } + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { limit: 1000000 } + ); + if (!body.data.find((data: any) => data.version === newDeploymentVersion)) { + console.error(`error: There are no deployment with version ${newDeploymentVersion}`); + return; + } + + try { + const environmentId = await this.askEnvironmentId({ + message: "Select which Environment to update: " + }); + + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdPut, + environmentId, projectId, { depVersion: newDeploymentVersion } + ); + + if (!body) { + throw Error("Error updating Environment"); + } + + return console.log(body); + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async askEnvironmentId(prop: { message?: string } = {}): Promise { + const environmentList = await this.listEnvironment(); + const choices = environmentList.map((row: any) => ({ name: `${row.name} (${row.depVersion})`, value: row.id })); + + const { environmentId } = await inquirer.prompt([ + { + type: "list", + name: "environmentId", + message: prop.message || "Select Environment:", + paginated: false, + choices + }, + ]); + return environmentId; + } + + private async askPredefinedEnvironmentName(): Promise { + const environmentNames = ["Development", "Production", "Staging"]; + const choices = environmentNames.map((name) => ({ name, value: name })); + + const { environmentName } = await inquirer.prompt([ + { + type: "list", + name: "environmentName", + message: "Which Environment to create?", + paginated: false, + choices + }, + ]); + + return environmentName; + } + + private async getLatestDeployment() { + const projectId = this.helper.getProjectId(); + + const { response } = await this.helper.toPromise( + this.api.projectApi, this.api.projectApi.projectsProjectIdDeploymentGet, projectId + ); + + return response && response.body; + } + + private async listEnvironment(): Promise { + const projectId = this.helper.getProp("projectId"); + const { response: { body } } = await this.helper.toPromise( + this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet, projectId, {} + ); + if (!body || !body.data) { + throw Error("Failed to list environments."); + } + return body.data; + } +} diff --git a/components/bots/session.ts b/components/bots/session.ts index 57d6c29..557701b 100644 --- a/components/bots/session.ts +++ b/components/bots/session.ts @@ -1,98 +1,98 @@ - -import { IHelper } from "interfaces/main"; -import { Component, JsonObject } from "merapi"; - -export default class Session extends Component { - private defaultDeploymentId = "f223c9e0-6ba1-434d-8313-a9f18ca364bd"; - - constructor(private helper : IHelper, private api : any) { - super(); - } - - public async get(id : string, deploymentId : string, options : JsonObject) { - const botId = this.helper.getBotId(); - - try { - deploymentId = deploymentId || this.defaultDeploymentId; - const {data} = await this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdGet, botId, deploymentId, id, ""); - - console.dir(data, { depth: null }); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - public async create(id : string, deploymentId : string, options : JsonObject) { - const botId = this.helper.getBotId(); - - try { - let session : JsonObject; - - if (options.data) { - session = JSON.parse(options.data as string); - } else if (options.file) { - session = this.helper.loadYamlOrJsonFile(options.file as string); - } - - if (id && !session.id) { - session.id = id; - } - - deploymentId = deploymentId || this.defaultDeploymentId; - - const {data} = await this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsPost, botId, deploymentId, session); - - console.log(data); - console.log("Session created successfully"); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - public async update(id : string, deploymentId : string, options : JsonObject) { - const botId = this.helper.getBotId(); - - try { - let session : JsonObject; - - if (options.data) { - session = JSON.parse(options.data as string); - } else if (options.file) { - session = this.helper.loadYamlOrJsonFile(options.file as string); - } - - if (!session.id) { - session.id = id; - } - - deploymentId = deploymentId || this.defaultDeploymentId; - - const {data} = await this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdPut, botId, deploymentId, id, session); - - console.log(data); - console.log("Session updated successfully"); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - public async delete(id : string, deploymentId : string, options : JsonObject) { - const botId = this.helper.getBotId(); - - try { - deploymentId = deploymentId || this.defaultDeploymentId; - const {data} = await this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdDelete, botId, deploymentId, id); - - console.dir(data, { depth: null }); - console.log("Session deleted successfully"); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - public async timestamp() { - const { response } = await this.helper.toPromise(this.api.utilApi, this.api.utilApi.timestampGet); - - console.log(`Current server timestamp: ${response.text}`); - } -} + +import { IHelper } from "interfaces/main"; +import { Component, JsonObject } from "merapi"; + +export default class Session extends Component { + private defaultDeploymentId = "f223c9e0-6ba1-434d-8313-a9f18ca364bd"; + + constructor(private helper : IHelper, private api : any) { + super(); + } + + public async get(id : string, deploymentId : string, options : JsonObject) { + const botId = this.helper.getBotId(); + + try { + deploymentId = deploymentId || this.defaultDeploymentId; + const {data} = await this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdGet, botId, deploymentId, id, ""); + + console.dir(data, { depth: null }); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + public async create(id : string, deploymentId : string, options : JsonObject) { + const botId = this.helper.getBotId(); + + try { + let session : JsonObject; + + if (options.data) { + session = JSON.parse(options.data as string); + } else if (options.file) { + session = this.helper.loadYamlOrJsonFile(options.file as string); + } + + if (id && !session.id) { + session.id = id; + } + + deploymentId = deploymentId || this.defaultDeploymentId; + + const {data} = await this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsPost, botId, deploymentId, session); + + console.log(data); + console.log("Session created successfully"); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + public async update(id : string, deploymentId : string, options : JsonObject) { + const botId = this.helper.getBotId(); + + try { + let session : JsonObject; + + if (options.data) { + session = JSON.parse(options.data as string); + } else if (options.file) { + session = this.helper.loadYamlOrJsonFile(options.file as string); + } + + if (!session.id) { + session.id = id; + } + + deploymentId = deploymentId || this.defaultDeploymentId; + + const {data} = await this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdPut, botId, deploymentId, id, session); + + console.log(data); + console.log("Session updated successfully"); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + public async delete(id : string, deploymentId : string, options : JsonObject) { + const botId = this.helper.getBotId(); + + try { + deploymentId = deploymentId || this.defaultDeploymentId; + const {data} = await this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdDelete, botId, deploymentId, id); + + console.dir(data, { depth: null }); + console.log("Session deleted successfully"); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + public async timestamp() { + const { response } = await this.helper.toPromise(this.api.utilApi, this.api.utilApi.timestampGet); + + console.log(`Current server timestamp: ${response.text}`); + } +} diff --git a/components/deprecated/deprecated.ts b/components/deprecated/deprecated.ts index 4746d79..4111402 100644 --- a/components/deprecated/deprecated.ts +++ b/components/deprecated/deprecated.ts @@ -1,19 +1,19 @@ -import { Component } from "merapi"; - -export default class Deprecated extends Component { - public addChannel() { - console.log("This command is deprecated, please use create-channel"); - } - - public removeChannel() { - console.log("This command is deprecated, please use delete-channel"); - } - - public configView() { - console.log("This command is deprecated, please use view-config"); - } - - public addMember() { - console.log("This command is deprecated, please use invite-member"); - } -} +import { Component } from "merapi"; + +export default class Deprecated extends Component { + public addChannel() { + console.log("This command is deprecated, please use create-channel"); + } + + public removeChannel() { + console.log("This command is deprecated, please use delete-channel"); + } + + public configView() { + console.log("This command is deprecated, please use view-config"); + } + + public addMember() { + console.log("This command is deprecated, please use invite-member"); + } +} diff --git a/components/main.ts b/components/main.ts index 1f5cd8d..ff73294 100644 --- a/components/main.ts +++ b/components/main.ts @@ -1,122 +1,122 @@ -import { Command, CommandDescriptor, CommandList, IHelper } from "interfaces/main"; -import { Component, IConfigReader, IInjector, Json, JsonObject } from "merapi"; - -const commander = require("commander"); - -export default class Main extends Component { - - constructor( - private config : IConfigReader, - private injector : IInjector, - private helper : IHelper - ) { - super(); - } - - async start(argv:string[]) { - let commands = this.config.get("commands"); - commander.version(`Kata CLI version ${this.config.default("version", "1.0.0")}`); - await this.compile(commands, commander); - commander.parse(argv); - const validCommands = commander.commands.map((x:any) => x.name()); - if (argv.length === 2 || validCommands.indexOf(argv[2]) === -1) { - commander.parse([argv[0], argv[1], '-h']); - } - - this.sendNotificationTracking() - this.sendDataAnalytics(argv) - this.saveCommandSession(argv) - } - - async compile(commands: CommandList, program: Command, currKey : string = "") { - for (let key in commands) { - let command = commands[key]; - - if (command.type === "group") { - await this.compileGroup(`${currKey}${key}`, command, program); - } - else if (command.type === "alias") { - this.compileAlias(key, command, program); - } - else { - await this.compileCommand(`${currKey}${key}`, command, program); - } - } - } - - async compileGroup(key: string, command: CommandDescriptor, program: Command) { - await this.compile(command.subcommands, program, `${key}-`); - } - - compileAlias(key: string, command: CommandDescriptor, program: Command) { - program.command(key).action((self) => { - let args = self._args; - commander.parse(command.alias.split(/\s+/).concat(args)); - }); - } - - async compileCommand(key: string, command: CommandDescriptor, program: Command) { - let subcommand; - let commandKey = command.alias ? command.alias : key; - - if (command.args) { - subcommand = program.command(`${commandKey} ${command.args}`) - } - else { - subcommand = program.command(commandKey); - } - - if (command.params) { - for (let i in command.params) { - let param = command.params[i]; - let flag = param.short ? `-${param.short}, --${i}` : `--${i}`; - if (param.value !== undefined) - subcommand.option(`${flag} `, param.desc || "", param.value); - else if(param.bool) - subcommand.option(flag, param.desc || ""); - else - subcommand.option(`${flag} [value]`, param.desc || ""); - } - } - - subcommand.action(await this.createAction(command.handler, command.middleware)); - } - - async createAction(handler:string, middleware : string[] = []) : Promise<(...args:any[]) => void> { - let methods : any[] = []; - for (let i=0; i { - for (let i=0; i("commands"); + commander.version(`Kata CLI version ${this.config.default("version", "1.0.0")}`); + await this.compile(commands, commander); + commander.parse(argv); + const validCommands = commander.commands.map((x:any) => x.name()); + if (argv.length === 2 || validCommands.indexOf(argv[2]) === -1) { + commander.parse([argv[0], argv[1], '-h']); + } + + this.sendNotificationTracking() + this.sendDataAnalytics(argv) + this.saveCommandSession(argv) + } + + async compile(commands: CommandList, program: Command, currKey : string = "") { + for (let key in commands) { + let command = commands[key]; + + if (command.type === "group") { + await this.compileGroup(`${currKey}${key}`, command, program); + } + else if (command.type === "alias") { + this.compileAlias(key, command, program); + } + else { + await this.compileCommand(`${currKey}${key}`, command, program); + } + } + } + + async compileGroup(key: string, command: CommandDescriptor, program: Command) { + await this.compile(command.subcommands, program, `${key}-`); + } + + compileAlias(key: string, command: CommandDescriptor, program: Command) { + program.command(key).action((self) => { + let args = self._args; + commander.parse(command.alias.split(/\s+/).concat(args)); + }); + } + + async compileCommand(key: string, command: CommandDescriptor, program: Command) { + let subcommand; + let commandKey = command.alias ? command.alias : key; + + if (command.args) { + subcommand = program.command(`${commandKey} ${command.args}`) + } + else { + subcommand = program.command(commandKey); + } + + if (command.params) { + for (let i in command.params) { + let param = command.params[i]; + let flag = param.short ? `-${param.short}, --${i}` : `--${i}`; + if (param.value !== undefined) + subcommand.option(`${flag} `, param.desc || "", param.value); + else if(param.bool) + subcommand.option(flag, param.desc || ""); + else + subcommand.option(`${flag} [value]`, param.desc || ""); + } + } + + subcommand.action(await this.createAction(command.handler, command.middleware)); + } + + async createAction(handler:string, middleware : string[] = []) : Promise<(...args:any[]) => void> { + let methods : any[] = []; + for (let i=0; i { + for (let i=0; i 20) { - console.log(`Failed to create ${key}. Entity name must not be longer than 20 characters.`); - continue; - } - await this.helper.toPromise(this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameEntitiesPost, - projectId, nluDesc.name, { ...nluDesc.entities[key], name: key }); - } - } - } - - const remoteDiff = this.helper.difference(entities, nluDesc.entities); - if (remoteDiff) { - for (const key in remoteDiff) { - if (!nluDesc.entities[key]) { - // delete remote entity - await this.helper.toPromise(this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameDelete, - projectId, nluDesc.name, key); - } - } - } - } - - if (!nluDesc.entities && entities) { - for (const key in entities) { - if (entities[key]) { - // delete remote entity - await this.helper.toPromise(this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameDelete, - projectId, nluDesc.name, key); - } - } - } - - if (nluDesc.entities && !entities) { - for (const key in nluDesc.entities) { - if (nluDesc.entities[key]) { - // create new entity - if ((key as string).length > 20) { - console.log(`Failed to create ${key}. Entity name must not be longer than 20 characters.`); - continue; - } - await this.helper.toPromise(this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameEntitiesPost, - projectId, nluDesc.name, { ...nluDesc.entities[key], name: key }); - } - } - } - } - - console.log(`NLU ${nluDesc.name} Updated !`); - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async train(options: JsonObject) { - const projectId = this.helper.getProp("projectId"); - let nluDesc; - try { - nluDesc = this.helper.loadYaml("./nlu.yml"); - } catch (e) { - console.log("Missing nlu.yml"); - return; - } - const nluName = nluDesc.name; - if (!nluName) { - console.log("Missing name in nlu.yml"); - return; - } - // check training job - const result = await this.helper.toPromise(this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameHasActiveJobGet, projectId, nluName); - if (result.data) { - console.log("Sorry, your previous training is still running. " + - "Give it another try in a few minutes."); - return; - } - try { - let opts: any = {}; - if (options.file) { - console.log(`Training.. (input file: ${options.file})`); - opts = { - file: fs.createReadStream(options.file) - }; - } else if (options.sentence) { - console.log(`Training.. (input: ${options.sentence})`); - opts = { - sentence: options.sentence - }; - } - - const { response: { body } } = await this.helper.toPromise(this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameTrainPost, projectId, nluName, opts); - const trainResult = body; - - // Print result - const count = trainResult.count; - const successCount = trainResult.rowIds ? trainResult.rowIds.length : 0; - if (successCount) { - console.log(`Success: ${successCount} data trained !`); - } - - // Write error to file - const errorCount = trainResult.errRows ? trainResult.errRows.length : 0; - if (errorCount) { - if (options.file) { - const rawData = fs.readFileSync(options.file).toString("utf8"); - const trainingData = rawData.split("\n"); - let errData = ""; - for (const i of trainResult.errRows) { - errData += trainingData[i] + "\n"; - } - fs.writeFile(errorFileLog, errData, (err: any) => { - if (err) { throw err; } - console.log(`Error training ${errorCount} data. See details on ${errorFileLog}`); - }); - } else if (options.sentence) { - console.log(`Error training data`); - } - } - - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async predict(options: JsonObject) { - const projectId = this.helper.getProp("projectId"); - let nluDesc; - try { - nluDesc = this.helper.loadYaml("./nlu.yml"); - } catch (e) { - console.log("Missing nlu.yml"); - return; - } - const nluName = nluDesc.name; - if (!nluName) { - console.log("Missing name in nlu.yml"); - return; - } - try { - let opts = {}; - if (options.file) { - console.log(`Predict.. (input file: ${options.file})`); - opts = { - file: fs.createReadStream(options.file) - }; - - } else if (options.sentence) { - console.log(`Predict.. (input: ${options.sentence})`); - opts = { - sentence: options.sentence - }; - - } else { - throw new Error("Please input sentence or file to predict"); - } - - const { response: { body } } = await this.helper.toPromise( - this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNamePredictPost, projectId, nluName, opts - ); - console.log(`Success, result : `); - let i = 0; - body.result.forEach((x: any) => { - console.log(`${++i}. Input: ${x.input}`); - console.log(` Result: ${JSON.stringify(x.output)}`); - - }); - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async listProfiles() { - try { - const profiles = await this.helper.toPromise(this.api.nluApi, this.api.nluApi.nlusProfilesGet); - if (profiles && profiles.data) { - const table = new Table({ - head: ["Type", "Name", "Desc"] - , colWidths: [10, 10, 40] - }); - profiles.data.forEach((profile: { type: string, name: string, desc: string }) => { - table.push([profile.type, profile.name, profile.desc]); - }); - console.log(table.toString()); - } - } catch (error) { - console.log(error); - } - } - - // deprecated soon - private async listNlus(page?: number, limit?: number) { - try { - page = page || 1; - limit = limit || 10; - - const projectId = this.helper.getProp("projectId"); - const nlus = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluGet, projectId, { page, limit }); - if (nlus && nlus.data) { - const table = new Table({ - head: ["Name", "Language", "Visibility"] - , colWidths: [20, 20, 20] - }); - nlus.data.items.forEach((nlus: { name: string, lang: string, visibility: string }) => { - table.push([nlus.name, nlus.lang, nlus.visibility]); - }); - console.log(table.toString()); - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async snapshot() { - const projectId = this.helper.getProp("projectId"); - try { - const nluDesc: any = this.helper.loadYaml("./nlu.yml"); - const result = await this.helper.toPromise(this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameSnapshotGet, projectId, nluDesc.name); - - console.log(`Snapshot captured!`); - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async listTraining(params?:any) { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const projectName = this.helper.getProp("projectName"); - const username = this.helper.getProp("current_login"); - - const { response } = await this.helper.toPromise( - this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameTrainingDataGet, - projectId, - `${username}:${projectName}`, - { page: params.page || 1 } - ); - - if (response && response.body && response.body.data) { - const table = new Table({ - head: ["Train Data", "Entities"], - colWidths: [50, 50] - }); - - response.body.data.forEach((data: any) => { - const entities: JsonArray = data.entities.map((e:any) => { - return `(${e.entity}:${e.label}) ${e.value}` - }) - table.push([data.input, entities.join("\n")]); - }); - console.log(table.toString()); - } else { - console.log("Failed when trying list train data") - } - } else { - console.log("Please select project first") - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async listPrediction(params?:any) { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const projectName = this.helper.getProp("projectName"); - const username = this.helper.getProp("current_login"); - - const { response } = await this.helper.toPromise( - this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameLogGet, - projectId, - `${username}:${projectName}`, - { page: params.page || 1, limit: 10 } - ); - - if (response && response.body && response.body.result) { - const table = new Table({ - head: ["Prediction Log", "Entities"] - }); - - response.body.result.forEach((data: any) => { - const entities: JsonArray = data.corrected.entities.map((e:any) => { - return `(${e.entity}:${e.label}) ${e.value}` - }) - - table.push([data.corrected.input, entities.join("\n")]); - }); - console.log(table.toString()); - } else { - console.log("Failed when trying list prediction log") - } - } else { - console.log("Please select project first") - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async listRevision() { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const { response } = await this.helper.toPromise( - this.api.projectApi, - this.api.projectApi.projectsProjectIdNluRevisionsGet, - projectId - ); - - if (response && response.body && response.body.data) { - const table = new Table({ - head: ["Snapshot", "Date"], - colWidths: [50, 25] - }); - - response.body.data.forEach((data: any) => { - table.push([data.revision, new Date(data.created_at).toLocaleString()]); - }); - console.log(table.toString()); - } else { - console.log("Failed when trying get revision list") - } - } else { - console.log("Please select project first") - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async detail() { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const { response } = await this.helper.toPromise( - this.api.nluApi, - this.api.nluApi.projectsProjectIdNluGet, - projectId - ); - - if (response && response.body) { - const table = new Table({ - head: ["NLU Name", "NLU ID", "Language", "Token"] - }); - - const language = (response.body.lang == "id") ? "Bahasa Indonesia" : "English" - - table.push([response.body.name, response.body.id, language, response.body.token]); - - console.log(table.toString()); - } else { - console.log("Failed when trying get NL detail") - } - } else { - console.log("Please select project first") - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async issueToken() { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const projectName = this.helper.getProp("projectName"); - const username = this.helper.getProp("current_login"); - - const { response } = await this.helper.toPromise( - this.api.nluApi, - this.api.nluApi.projectsProjectIdNlusNluNameIssueTokenGet, - projectId, - `${username}:${projectName}` - ); - - if (response && response.body) { - console.log(response.body.toString()) - } else { - console.log("Failed when trying issue token") - } - } else { - console.log("Please select project first") - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } -} +import { IHelper } from "interfaces/main"; +import { Component, JsonObject, JsonArray } from "merapi"; +const Table = require("cli-table"); +const fs = require("fs"); +const yaml = require("js-yaml"); + +const template: any = { + default: { + name: "kata", + lang: "id", + entities: { + location: { + type: "phrase", + profile: "location" + }, + person: { + type: "phrase", + profile: "name" + } + } + }, + email: { + name: "email", + lang: "id", + entities: { + email: { + type: "phrase", + profile: "email" + } + } + }, + locationlabel: { + name: "location_kata", + lang: "id", + entities: { + location: { + type: "phrase", + profile: "location", + labels: [ + "common", + "places", + "city", + "street", + "country", + "airport" + ], + resolver: "location" + } + } + }, + location: { + name: "location", + lang: "id", + entities: { + location: { + type: "phrase", + profile: "location" + } + } + }, + name: { + name: "person", + lang: "id", + entities: { + person: { + type: "phrase", + profile: "name" + } + } + }, + sentiment: { + name: "sentiment", + lang: "id", + entities: { + sentiment: { + type: "trait", + profile: "sentiment", + labels: [ + "positive", + "negative", + "neutral" + ] + } + } + } +}; + +const errorFileLog = "training.error.log"; + +export default class Nlu extends Component { + + constructor(private helper: IHelper, private api: any) { + super(); + } + + public async init(name: string, sandbox?: string) { + try { + const sandboxName: any = sandbox || "default"; + const nluDesc: any = template[sandboxName]; + + nluDesc.name = name; + this.helper.dumpYaml("./nlu.yml", nluDesc); + console.log(`Init NLU ${name}`); + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async pull() { + + const projectId = this.helper.getProp("projectId"); + let nluDesc; + + try { + const { response: { body } } = await this.helper.toPromise(this.api.projectApi, + this.api.projectApi.projectsProjectIdNluGet, projectId); + const {name, lang, visibility, entities} = body; + nluDesc = {name, lang, visibility, entities}; + } catch (error) { + console.log("Error: ", this.helper.wrapError(error)); + return; + } + for (const entity in nluDesc.entities) { + if (nluDesc.entities[entity] && nluDesc.entities[entity].type === "dict") { + // get dictionary + try { + const { response: { body } } = await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameGet, + projectId, nluDesc.name, entity); + if (body.dictionary) { + nluDesc.entities[entity].dictionary = body.dictionary; + } + } catch (error) { + console.log("Error: ", this.helper.wrapError(error)); + return; + } + } + } + + const nluYml = yaml.dump(nluDesc); + console.log("Writing to nlu.yml..."); + fs.writeFileSync("nlu.yml", nluYml); + } + + public async push() { + + const projectId = this.helper.getProp("projectId"); + let nluDesc: any = null; + try { + nluDesc = this.helper.loadYaml("./nlu.yml"); + } catch (error) { + if (error.code === "ENOENT") { + console.log( + "error: NLU file 'nlu.yml' does not exist, try calling 'kata nl-pull' to fetch 'nlu.yml' from the server" + ); + } + return; + } + + let nlu; + let entities; + + try { + const { response: { body } } = await this.helper.toPromise(this.api.projectApi, + this.api.projectApi.projectsProjectIdNluGet, projectId); + nlu = body; + } catch (error) { + console.log(this.helper.wrapError(error)); + return; + } + try { + const { response: { body } } = await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameEntitiesGet, projectId, nluDesc.name); + entities = body; + } catch (error) { + console.log(this.helper.wrapError(error)); + return; + } + + + try { + if (nlu) { + let { lang, visibility } = nluDesc; + visibility = visibility || "private"; + // await this.helper.toPromise(this.api.nluApi, this.api.nluApi.nlusNluNamePut, + // nluDesc.name, { lang, visibility }); + + if (nluDesc.entities && entities) { + const localDiff = this.helper.difference(nluDesc.entities, entities); + + if (localDiff) { + for (const key in localDiff) { + if (entities[key]) { + // Update remote entity + if (!nluDesc.entities[key].inherit) { + await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNamePut, + projectId, nluDesc.name, key, { ...nluDesc.entities[key], name: key }); + } + } else { + // Create new entity + if ((key as string).length > 20) { + console.log(`Failed to create ${key}. Entity name must not be longer than 20 characters.`); + continue; + } + await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameEntitiesPost, + projectId, nluDesc.name, { ...nluDesc.entities[key], name: key }); + } + } + } + + const remoteDiff = this.helper.difference(entities, nluDesc.entities); + if (remoteDiff) { + for (const key in remoteDiff) { + if (!nluDesc.entities[key]) { + // delete remote entity + await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameDelete, + projectId, nluDesc.name, key); + } + } + } + } + + if (!nluDesc.entities && entities) { + for (const key in entities) { + if (entities[key]) { + // delete remote entity + await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameDelete, + projectId, nluDesc.name, key); + } + } + } + + if (nluDesc.entities && !entities) { + for (const key in nluDesc.entities) { + if (nluDesc.entities[key]) { + // create new entity + if ((key as string).length > 20) { + console.log(`Failed to create ${key}. Entity name must not be longer than 20 characters.`); + continue; + } + await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameEntitiesPost, + projectId, nluDesc.name, { ...nluDesc.entities[key], name: key }); + } + } + } + } + + console.log(`NLU ${nluDesc.name} Updated !`); + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async train(options: JsonObject) { + const projectId = this.helper.getProp("projectId"); + let nluDesc; + try { + nluDesc = this.helper.loadYaml("./nlu.yml"); + } catch (e) { + console.log("Missing nlu.yml"); + return; + } + const nluName = nluDesc.name; + if (!nluName) { + console.log("Missing name in nlu.yml"); + return; + } + + // handle when training job checking is failed + const hasActiveJobErrMsg = "Sorry, your previous training is still running. Give it another try in a few minutes."; + try { + // check training job + const result = await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameHasActiveJobGet, projectId, nluName); + if (result.data) { + console.log(hasActiveJobErrMsg); + return; + } + } catch (error) { + console.log(hasActiveJobErrMsg); + return; + } + + try { + let opts: any = {}; + if (options.file) { + console.log(`Training.. (input file: ${options.file})`); + opts = { + file: fs.createReadStream(options.file) + }; + } else if (options.sentence) { + console.log(`Training.. (input: ${options.sentence})`); + opts = { + sentence: options.sentence + }; + } + + // saat proses training lama, misal 30k data, proses training berhenti/reject ada balikan error tapi tidak dihandle. + try { + const { response: { body } } = await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameTrainPost, projectId, nluName, opts); + const trainResult = body; + + // Print result + const count = trainResult.count; + const successCount = trainResult.rowIds ? trainResult.rowIds.length : 0; + if (successCount) { + console.log(`Success: ${successCount} data trained !`); + } + + // Write error to file + const errorCount = trainResult.errRows ? trainResult.errRows.length : 0; + if (errorCount) { + if (options.file) { + const rawData = fs.readFileSync(options.file).toString("utf8"); + const trainingData = rawData.split("\n"); + let errData = ""; + for (const i of trainResult.errRows) { + errData += trainingData[i] + "\n"; + } + fs.writeFile(errorFileLog, errData, (err: any) => { + if (err) { throw err; } + console.log(`Error training ${errorCount} data. See details on ${errorFileLog}`); + }); + } else if (options.sentence) { + console.log(`Error training data`); + } + } + } catch (error) { + console.log(`Process training data is rejected. Error details : ${JSON.stringify(error)}`); + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async predict(options: JsonObject) { + const projectId = this.helper.getProp("projectId"); + let nluDesc; + try { + nluDesc = this.helper.loadYaml("./nlu.yml"); + } catch (e) { + console.log("Missing nlu.yml"); + return; + } + const nluName = nluDesc.name; + if (!nluName) { + console.log("Missing name in nlu.yml"); + return; + } + try { + let opts = {}; + if (options.file) { + console.log(`Predict.. (input file: ${options.file})`); + opts = { + file: fs.createReadStream(options.file) + }; + + } else if (options.sentence) { + console.log(`Predict.. (input: ${options.sentence})`); + opts = { + sentence: options.sentence + }; + + } else { + throw new Error("Please input sentence or file to predict"); + } + + const { response: { body } } = await this.helper.toPromise( + this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNamePredictPost, projectId, nluName, opts + ); + console.log(`Success, result : `); + let i = 0; + body.result.forEach((x: any) => { + console.log(`${++i}. Input: ${x.input}`); + console.log(` Result: ${JSON.stringify(x.output)}`); + + }); + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async listProfiles() { + try { + const profiles = await this.helper.toPromise(this.api.nluApi, this.api.nluApi.nlusProfilesGet); + if (profiles && profiles.data) { + const table = new Table({ + head: ["Type", "Name", "Desc"] + , colWidths: [10, 10, 40] + }); + profiles.data.forEach((profile: { type: string, name: string, desc: string }) => { + table.push([profile.type, profile.name, profile.desc]); + }); + console.log(table.toString()); + } + } catch (error) { + console.log(error); + } + } + + // deprecated soon + private async listNlus(page?: number, limit?: number) { + try { + page = page || 1; + limit = limit || 10; + + const projectId = this.helper.getProp("projectId"); + const nlus = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluGet, projectId, { page, limit }); + if (nlus && nlus.data) { + const table = new Table({ + head: ["Name", "Language", "Visibility"] + , colWidths: [20, 20, 20] + }); + nlus.data.items.forEach((nlus: { name: string, lang: string, visibility: string }) => { + table.push([nlus.name, nlus.lang, nlus.visibility]); + }); + console.log(table.toString()); + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async snapshot() { + const projectId = this.helper.getProp("projectId"); + try { + const nluDesc: any = this.helper.loadYaml("./nlu.yml"); + const result = await this.helper.toPromise(this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameSnapshotGet, projectId, nluDesc.name); + + console.log(`Snapshot captured!`); + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async listTraining(params?:any) { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const projectName = this.helper.getProp("projectName"); + const username = this.helper.getProp("current_login"); + + const { response } = await this.helper.toPromise( + this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameTrainingDataGet, + projectId, + `${username}:${projectName}`, + { page: params.page || 1 } + ); + + if (response && response.body && response.body.data) { + const table = new Table({ + head: ["Train Data", "Entities"], + colWidths: [50, 50] + }); + + response.body.data.forEach((data: any) => { + const entities: JsonArray = data.entities.map((e:any) => { + return `(${e.entity}:${e.label}) ${e.value}` + }) + table.push([data.input, entities.join("\n")]); + }); + console.log(table.toString()); + } else { + console.log("Failed when trying list train data") + } + } else { + console.log("Please select project first") + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async listPrediction(params?:any) { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const projectName = this.helper.getProp("projectName"); + const username = this.helper.getProp("current_login"); + + const { response } = await this.helper.toPromise( + this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameLogGet, + projectId, + `${username}:${projectName}`, + { page: params.page || 1, limit: 10 } + ); + + if (response && response.body && response.body.result) { + const table = new Table({ + head: ["Prediction Log", "Entities"] + }); + + response.body.result.forEach((data: any) => { + const entities: JsonArray = data.corrected.entities.map((e:any) => { + return `(${e.entity}:${e.label}) ${e.value}` + }) + + table.push([data.corrected.input, entities.join("\n")]); + }); + console.log(table.toString()); + } else { + console.log("Failed when trying list prediction log") + } + } else { + console.log("Please select project first") + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async listRevision() { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const { response } = await this.helper.toPromise( + this.api.projectApi, + this.api.projectApi.projectsProjectIdNluRevisionsGet, + projectId + ); + + if (response && response.body && response.body.data) { + const table = new Table({ + head: ["Snapshot", "Date"], + colWidths: [50, 25] + }); + + response.body.data.forEach((data: any) => { + table.push([data.revision, new Date(data.created_at).toLocaleString()]); + }); + console.log(table.toString()); + } else { + console.log("Failed when trying get revision list") + } + } else { + console.log("Please select project first") + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async detail() { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const { response } = await this.helper.toPromise( + this.api.nluApi, + this.api.nluApi.projectsProjectIdNluGet, + projectId + ); + + if (response && response.body) { + const table = new Table({ + head: ["NLU Name", "NLU ID", "Language", "Token"] + }); + + const language = (response.body.lang == "id") ? "Bahasa Indonesia" : "English" + + table.push([response.body.name, response.body.id, language, response.body.token]); + + console.log(table.toString()); + } else { + console.log("Failed when trying get NL detail") + } + } else { + console.log("Please select project first") + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async issueToken() { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const projectName = this.helper.getProp("projectName"); + const username = this.helper.getProp("current_login"); + + const { response } = await this.helper.toPromise( + this.api.nluApi, + this.api.nluApi.projectsProjectIdNlusNluNameIssueTokenGet, + projectId, + `${username}:${projectName}` + ); + + if (response && response.body) { + console.log(response.body.toString()) + } else { + console.log("Failed when trying issue token") + } + } else { + console.log("Please select project first") + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } +} diff --git a/components/projects/project.ts b/components/projects/project.ts index 5a2df6d..f1f33f6 100644 --- a/components/projects/project.ts +++ b/components/projects/project.ts @@ -1,293 +1,293 @@ - -import Api from "components/api/api"; -import { IHelper } from "interfaces/main"; -import { JsonObject } from "merapi"; -import inquirer = require("inquirer"); -const Table = require("cli-table"); -const colors = require("colors/safe"); - -export default class Project { - constructor( - private api: Api, - private helper: IHelper, - ) { } - - public async create() { - let projectData: Record = {name : ""}; - while (true) { - projectData = await this.helper.inquirerPrompt([ - { - type: "text", - name: "name", - message: "Project name:", - }, - ]); - if (projectData.name.length > 20) { - console.error("error: Project name length can not exceed 20 characters"); - } - else if (!/^[A-Za-z][A-Za-z0-9_-]*[A-Za-z0-9]$/.test(projectData.name)) { - console.error("error: Project name must start with alphabet characters and contains only aplhanumeric character, dash, or underscore"); - } - else { - break; - } - } - const inquiredOptions = await this.helper.inquirerPrompt([ - { - type: "number", - name: "timezone", - message: "Timezone (UTC)", - default: 7, - }, - { - type: "text", - name: "description", - message: "Project description:", - }, - ]); - const options = { bot: true, cms: true, nlu: true, ...inquiredOptions }; - - let nluOptions: any = {}; - if (options.nlu) { - nluOptions = await this.helper.inquirerPrompt([ - { - type: "text", - name: "nluLang", - message: "NLU Language", - default: "id", - }, - { - type: "confirm", - name: "privateNlu", - message: "Is private Nlu?", - default: true, - }, - ]); - nluOptions.nluVisibility = nluOptions.privateNlu ? "private" : "public"; - delete nluOptions.privateNlu; - } - - const requestBody = { ...projectData, options: { ...options, ...nluOptions } }; - - try { - const { response } = await this.helper.toPromise( - this.api.projectApi, this.api.projectApi.projectsPost, requestBody - ); - - if (response && response.body && response.body.id) { - const project = response.body; - const projectId = project.id; - this.helper.setProp("projectId", projectId); - console.log(colors.green(`Project "${project.name}" (${projectId}) is successfully created`)); - return; - } - - } catch (e) { - console.error(this.helper.wrapError(e)); - } - } - - public async update(projectName?:string) { - let chosen = null - - if (projectName) { - chosen = await this.getDataByName(projectName) - } else { - chosen = await this.choose() - } - - if (chosen) { - const { description, privateNlu } = await this.helper.inquirerPrompt([ - { - type: "text", - name: "description", - message: "Project description:", - }, - { - type: "confirm", - name: "privateNlu", - message: "Is private Nlu?", - default: true, - } - ]); - - const nluVisibility = privateNlu ? 'private' : 'public'; - - const requestBody = { - id: chosen.id, - name: chosen.name, - description: description, - options: { - timezone: chosen.options.timezone, - nluLang: chosen.options.nluLang, - nluVisibility: nluVisibility, - nluId: chosen.options.nluId - } - } - - const { response } = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdPut, chosen.id, requestBody); - if (response && response.body) { - console.log(`Project ${chosen.name} has been updated.`) - } else { - console.log("Failed when trying update project") - } - } else { - console.log(`Project ${projectName} is not found`) - } - } - - public async list() { - try { - const { response } = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, {}); - - if (response && response.body && response.body.data) { - const table = new Table({ - head: ["Project ID", "Project Name"], - colWidths: [38, 32] - }); - response.body.data.forEach((project: JsonObject) => { - table.push([project.id, project.name]); - }); - console.log(table.toString()); - } - } catch (e) { - console.error(this.helper.wrapError(e)); - } - } - - private async getDataByName(projectName: string) { - const { response } = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, {}); - - if (response && response.body && response.body.data) { - const projects = response.body.data - const sameName = projects.find((project: any) => project.name === projectName); - if (sameName) { - return sameName - } - } - } - - private async choose(){ - try { - let page = 1; - const pageLimit = 10; - while (true) { - const { response } = await this.helper.toPromise( - this.api.projectApi, - this.api.projectApi.projectsGet, - { limit: pageLimit, page} - ); - - if (response && response.body && response.body.data) { - - const maxPage = Math.ceil(response.body.total / pageLimit); - - const projectList: object[] = response.body.data; - const choices = projectList.map((projectRow: any) => ({ - name: projectRow.name, - value: projectRow - })); - - const body = response.body; - - if (body.total > body.page * body.limit) { - choices.push({name: "(Load More)", value: -1}); - } - - const { project } = await inquirer.prompt([ - { - type: "list", - name: "project", - message: `Select project (page ${ page } / ${ maxPage })`, - paginated: false, - pageSize: pageLimit + 1, - choices - }, - ]); - - if (project === -1) { - page++; - continue; - } - - return project; - } - console.error("Failed to list projects"); - } - } catch (e) { - console.error(this.helper.wrapError(e)); - } - } - - public async select(projectName?: string) { - let chosen: any; - if (typeof projectName === "string") { - chosen = await this.getDataByName(projectName); - if (chosen !== undefined) { - // project name found - this.helper.setProp("projectId", chosen.id); - this.helper.setProp("projectName", chosen.name); - } else { - // project name not found, select through inquirer - console.log( - `Project with name ${colors.green(projectName)} is not found. ` + - `Please choose listed project name below:`); - chosen = await this.choose() - if (chosen) { - this.helper.setProp("projectId", chosen.id); - this.helper.setProp("projectName", chosen.name); - } - } - } else { - // projectName is empty - chosen = await this.choose() - if (chosen) { - this.helper.setProp("projectId", chosen.id); - this.helper.setProp("projectName", chosen.name); - } - } - console.log(colors.green(`Project "${ chosen.name }" (${ chosen.id }) is successfully selected`)); - - if (!chosen || chosen === undefined) { - chosen = await this.choose() - if (chosen) { - this.helper.setProp("projectId", chosen.id); - this.helper.setProp("projectName", chosen.name); - console.log(colors.green(`Project "${ chosen.name }" (${ chosen.id }) is successfully selected`)); - } - } - - - } - - public async delete(projectName?: string) { - try { - const chosen = projectName ? await this.getDataByName(projectName) : await this.choose() - if (chosen) { - const { yes } = await inquirer.prompt([ - { - type: "confirm", - name: "yes", - message: "Are you sure want to delete this project ?", - default: true, - } - ]); - - if (yes) { - const deleteProject = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdDelete, chosen.id); - if (deleteProject && deleteProject.response && deleteProject.response.body) { - if (deleteProject.response.body) { - console.log("Project has been deleted.") - } else { - console.log("Failed when trying delete project") - } - } - } - } else { - console.log(`Project ${projectName} is not found`) - } - } catch (e) { - console.error(this.helper.wrapError(e)); - } - } -} + +import Api from "components/api/api"; +import { IHelper } from "interfaces/main"; +import { JsonObject } from "merapi"; +import inquirer = require("inquirer"); +const Table = require("cli-table"); +const colors = require("colors/safe"); + +export default class Project { + constructor( + private api: Api, + private helper: IHelper, + ) { } + + public async create() { + let projectData: Record = {name : ""}; + while (true) { + projectData = await this.helper.inquirerPrompt([ + { + type: "text", + name: "name", + message: "Project name:", + }, + ]); + if (projectData.name.length > 20) { + console.error("error: Project name length can not exceed 20 characters"); + } + else if (!/^[A-Za-z][A-Za-z0-9_-]*[A-Za-z0-9]$/.test(projectData.name)) { + console.error("error: Project name must start with alphabet characters and contains only aplhanumeric character, dash, or underscore"); + } + else { + break; + } + } + const inquiredOptions = await this.helper.inquirerPrompt([ + { + type: "number", + name: "timezone", + message: "Timezone (UTC)", + default: 7, + }, + { + type: "text", + name: "description", + message: "Project description:", + }, + ]); + const options = { bot: true, cms: true, nlu: true, ...inquiredOptions }; + + let nluOptions: any = {}; + if (options.nlu) { + nluOptions = await this.helper.inquirerPrompt([ + { + type: "text", + name: "nluLang", + message: "NLU Language", + default: "id", + }, + { + type: "confirm", + name: "privateNlu", + message: "Is private Nlu?", + default: true, + }, + ]); + nluOptions.nluVisibility = nluOptions.privateNlu ? "private" : "public"; + delete nluOptions.privateNlu; + } + + const requestBody = { ...projectData, options: { ...options, ...nluOptions } }; + + try { + const { response } = await this.helper.toPromise( + this.api.projectApi, this.api.projectApi.projectsPost, requestBody + ); + + if (response && response.body && response.body.id) { + const project = response.body; + const projectId = project.id; + this.helper.setProp("projectId", projectId); + console.log(colors.green(`Project "${project.name}" (${projectId}) is successfully created`)); + return; + } + + } catch (e) { + console.error(this.helper.wrapError(e)); + } + } + + public async update(projectName?:string) { + let chosen = null + + if (projectName) { + chosen = await this.getDataByName(projectName) + } else { + chosen = await this.choose() + } + + if (chosen) { + const { description, privateNlu } = await this.helper.inquirerPrompt([ + { + type: "text", + name: "description", + message: "Project description:", + }, + { + type: "confirm", + name: "privateNlu", + message: "Is private Nlu?", + default: true, + } + ]); + + const nluVisibility = privateNlu ? 'private' : 'public'; + + const requestBody = { + id: chosen.id, + name: chosen.name, + description: description, + options: { + timezone: chosen.options.timezone, + nluLang: chosen.options.nluLang, + nluVisibility: nluVisibility, + nluId: chosen.options.nluId + } + } + + const { response } = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdPut, chosen.id, requestBody); + if (response && response.body) { + console.log(`Project ${chosen.name} has been updated.`) + } else { + console.log("Failed when trying update project") + } + } else { + console.log(`Project ${projectName} is not found`) + } + } + + public async list() { + try { + const { response } = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, {}); + + if (response && response.body && response.body.data) { + const table = new Table({ + head: ["Project ID", "Project Name"], + colWidths: [38, 32] + }); + response.body.data.forEach((project: JsonObject) => { + table.push([project.id, project.name]); + }); + console.log(table.toString()); + } + } catch (e) { + console.error(this.helper.wrapError(e)); + } + } + + private async getDataByName(projectName: string) { + const { response } = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, {}); + + if (response && response.body && response.body.data) { + const projects = response.body.data + const sameName = projects.find((project: any) => project.name === projectName); + if (sameName) { + return sameName + } + } + } + + private async choose(){ + try { + let page = 1; + const pageLimit = 10; + while (true) { + const { response } = await this.helper.toPromise( + this.api.projectApi, + this.api.projectApi.projectsGet, + { limit: pageLimit, page} + ); + + if (response && response.body && response.body.data) { + + const maxPage = Math.ceil(response.body.total / pageLimit); + + const projectList: object[] = response.body.data; + const choices = projectList.map((projectRow: any) => ({ + name: projectRow.name, + value: projectRow + })); + + const body = response.body; + + if (body.total > body.page * body.limit) { + choices.push({name: "(Load More)", value: -1}); + } + + const { project } = await inquirer.prompt([ + { + type: "list", + name: "project", + message: `Select project (page ${ page } / ${ maxPage })`, + paginated: false, + pageSize: pageLimit + 1, + choices + }, + ]); + + if (project === -1) { + page++; + continue; + } + + return project; + } + console.error("Failed to list projects"); + } + } catch (e) { + console.error(this.helper.wrapError(e)); + } + } + + public async select(projectName?: string) { + let chosen: any; + if (typeof projectName === "string") { + chosen = await this.getDataByName(projectName); + if (chosen !== undefined) { + // project name found + this.helper.setProp("projectId", chosen.id); + this.helper.setProp("projectName", chosen.name); + } else { + // project name not found, select through inquirer + console.log( + `Project with name ${colors.green(projectName)} is not found. ` + + `Please choose listed project name below:`); + chosen = await this.choose() + if (chosen) { + this.helper.setProp("projectId", chosen.id); + this.helper.setProp("projectName", chosen.name); + } + } + } else { + // projectName is empty + chosen = await this.choose() + if (chosen) { + this.helper.setProp("projectId", chosen.id); + this.helper.setProp("projectName", chosen.name); + } + } + console.log(colors.green(`Project "${ chosen.name }" (${ chosen.id }) is successfully selected`)); + + if (!chosen || chosen === undefined) { + chosen = await this.choose() + if (chosen) { + this.helper.setProp("projectId", chosen.id); + this.helper.setProp("projectName", chosen.name); + console.log(colors.green(`Project "${ chosen.name }" (${ chosen.id }) is successfully selected`)); + } + } + + + } + + public async delete(projectName?: string) { + try { + const chosen = projectName ? await this.getDataByName(projectName) : await this.choose() + if (chosen) { + const { yes } = await inquirer.prompt([ + { + type: "confirm", + name: "yes", + message: "Are you sure want to delete this project ?", + default: true, + } + ]); + + if (yes) { + const deleteProject = await this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdDelete, chosen.id); + if (deleteProject && deleteProject.response && deleteProject.response.body) { + if (deleteProject.response.body) { + console.log("Project has been deleted.") + } else { + console.log("Failed when trying delete project") + } + } + } + } else { + console.log(`Project ${projectName} is not found`) + } + } catch (e) { + console.error(this.helper.wrapError(e)); + } + } +} diff --git a/components/scripts/compile.ts b/components/scripts/compile.ts index e93f950..1834932 100644 --- a/components/scripts/compile.ts +++ b/components/scripts/compile.ts @@ -1,45 +1,45 @@ - -import { IConfig, IHash, Component } from "merapi"; -import { ICompile, IHelper } from "interfaces/main"; - -const { Config } = require("merapi"); -const path = require("path"); -const fs = require("fs"); -const yaml = require("js-yaml"); - -export default class Compile extends Component implements ICompile { - private directives : any = { - include(file: string, basepath: string, helper: IHelper) { - let ext = path.extname(file); - if (ext === ".yml" || ext === ".yaml") - return helper.loadYaml(path.resolve(basepath, file)); - else if(ext === ".json") - return require(path.resolve(basepath, file)); - else - return fs.readFileSync(path.resolve(basepath, file)).toString(); - } - }; - - constructor(private helper: IHelper) { - super(); - } - - execDirective(name : string, directive: any, dict : IHash, basepath : string) { - for (let i in dict) { - if (typeof dict[i] !== "string") - continue; - let val = dict[i].trim(); - if (val.indexOf("$"+name+"(") === 0 && val.charAt(val.length-1) === ")") { - dict[i] = directive(dict[i].substring(2+name.length, dict[i].length-1), basepath, this.helper); - } - } - } - - execDirectives(config : IConfig, basepath : string) : IConfig { - let flattened = config.flatten(); - for (let i in this.directives) { - this.execDirective(i, this.directives[i], flattened, basepath); - } - return config.create(flattened); - } + +import { IConfig, IHash, Component } from "merapi"; +import { ICompile, IHelper } from "interfaces/main"; + +const { Config } = require("merapi"); +const path = require("path"); +const fs = require("fs"); +const yaml = require("js-yaml"); + +export default class Compile extends Component implements ICompile { + private directives : any = { + include(file: string, basepath: string, helper: IHelper) { + let ext = path.extname(file); + if (ext === ".yml" || ext === ".yaml") + return helper.loadYaml(path.resolve(basepath, file)); + else if(ext === ".json") + return require(path.resolve(basepath, file)); + else + return fs.readFileSync(path.resolve(basepath, file)).toString(); + } + }; + + constructor(private helper: IHelper) { + super(); + } + + execDirective(name : string, directive: any, dict : IHash, basepath : string) { + for (let i in dict) { + if (typeof dict[i] !== "string") + continue; + let val = dict[i].trim(); + if (val.indexOf("$"+name+"(") === 0 && val.charAt(val.length-1) === ")") { + dict[i] = directive(dict[i].substring(2+name.length, dict[i].length-1), basepath, this.helper); + } + } + } + + execDirectives(config : IConfig, basepath : string) : IConfig { + let flattened = config.flatten(); + for (let i in this.directives) { + this.execDirective(i, this.directives[i], flattened, basepath); + } + return config.create(flattened); + } } \ No newline at end of file diff --git a/components/scripts/helper.ts b/components/scripts/helper.ts index 1d4b276..1abe1de 100644 --- a/components/scripts/helper.ts +++ b/components/scripts/helper.ts @@ -1,314 +1,314 @@ - -import { Component, JsonObject, Json, IConfig } from "merapi"; -import * as _ from "lodash"; - -const Catch = require("catch-decorator"); -const yaml = require("js-yaml"); -const fs = require("fs"); -const os = require("os"); -const path = require("path"); -const inquirer = require("inquirer"); -const analytics = require("universal-analytics"); - -function wrapError(error: any) { - let errorMessage; - - if (error.response && error.response.body && error.response.body.message) { - errorMessage = error.response.body.message; - } else if (error.response && error.response.body) { - errorMessage = error.response.body; - } else { - errorMessage = error.message; - } - - return errorMessage; -} - -export const CatchError = Catch(Error, (error: any) => { - console.log("Error"); - console.error(wrapError(error)); -}); - - -export default class Helper extends Component { - constructor(private config : IConfig) { - super(); - } - - public getFiles(dir : string, ending : string) : string[] { - const fileList = fs.readdirSync(dir); - const res = []; - for (let i = 0; i < fileList.length; i++) { - const stat = fs.statSync(path.resolve(dir, fileList[i])); - if (stat.isDirectory()) { - res.push(...this.getFiles(dir + "/" + fileList[i], ending)); - } else if (stat.isFile() && fileList[i].endsWith(ending)) { - res.push(dir + "/" + fileList[i]); - } - } - return res; - } - - public loadYaml(file : string) : JsonObject { - return yaml.safeLoad(fs.readFileSync(file, "utf8")); - } - - public dumpYaml(file : string, object : JsonObject) : void { - fs.writeFileSync(file, yaml.safeDump(object, { indent: 4, lineWidth: 150 }), "utf8"); - } - - public compareTestResult(result : Json, expect : Json) : { field : string, expect : any, result : any }[] { - if (!result) { return null; } - const errors = []; - const expected = this.config.create(expect).flatten(); - const res = this.config.create(result); - for (const i in expected) { - const value = res.get(i); - if (value !== expected[i]) { - errors.push({ field: i, expect: expected[i], result: value }); - } - } - return errors; - } - - public setProp(prop : string, value : string, options? : JsonObject) : void { - const jsonPath = `${os.homedir()}/.katajson`; - let jsonProp; - - if (fs.existsSync(jsonPath)) { - jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - } else { - jsonProp = {}; - } - - jsonProp[prop] = value; - - fs.writeFileSync(jsonPath, JSON.stringify(jsonProp), "utf8"); - } - - public getProp(prop : string, options? : JsonObject) : Json { - const jsonPath = `${os.homedir()}/.katajson`; - let jsonProp; - - if (fs.existsSync(jsonPath)) { - jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - } else { - jsonProp = {}; - } - - return jsonProp[prop]; - } - - public delete() : Boolean { - const jsonPath = `${os.homedir()}/.katajson`; - - if (fs.existsSync(jsonPath)) { - fs.unlinkSync(jsonPath); - return true; - } - - return false; - } - - public deleteKeyToken(userName: string) { - const jsonPath = `${os.homedir()}/.katajson`; - let jsonProp; - - if (fs.existsSync(jsonPath)) { - jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - // if userName token exist - if (userName in jsonProp.token) { - jsonProp.current_login = "admin"; - delete jsonProp.token[userName]; - delete jsonProp.projectId; - delete jsonProp.projectName; - delete jsonProp.isImpersonate; - } else { - return new Error(`Failed to unimpersonate ${(userName)}`); - } - } else { - jsonProp = {}; - } - fs.writeFileSync(jsonPath, JSON.stringify(jsonProp), "utf8"); - return jsonProp; - } - - public toPromise(ctx : any, func : any, ...args : any[]) : Promise { - return new Promise((resolve, reject) => { - args.push((error : Error, data : any, response : Response) => { - if (error) { - reject(error); - } else { - resolve({ data, response }); - } - }); - - func.apply(ctx, args); - }); - } - - public getBotId() : string { - const desc = this.loadYaml("./bot.yml"); - - return desc.id as string; - } - - public getProjectId(): string { - return this.getProp("projectId") as string; - } - - public createDirectory(dirPath: string, mode?: number) { - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath, mode); - } - } - - public getCurrentToken() : JsonObject { - const currentLogin = this.getProp("current_login") as string || ""; - const tokenProp = (this.getProp("token") || {}) as JsonObject; - - return { - currentLogin, - token: tokenProp[currentLogin] - }; - } - public loadYamlOrJsonFile(filePath : string) { - if (!fs.existsSync(filePath)) { - return new Error("FILE NOT FOUND"); - } - - const fileExt = path.extname(filePath); - - if (fileExt === ".json") { - return JSON.parse(fs.readFileSync(filePath, "utf8")); - } else if (fileExt === ".yml" || fileExt === ".yaml") { - return this.loadYaml(filePath); - } else if (fileExt === ".txt") { - return fs.readFileSync(filePath, "utf8"); - } else { - return new Error("UNSUPPORTED FILE TYPE"); - } - } - - public async inquirerPrompt(questions : JsonObject[]) : Promise { - return inquirer.prompt(questions); - } - - public wrapError(error: any) { - const errorMessage: string = wrapError(error); - - const commands: JsonObject[] = this.getCommandSession(); - // Note: error might happen even after clearCommandSession is called - // this might results in an empty command, we do not want to track empty command error - if (commands.length > 0) { - const lastCommand: string = commands[commands.length - 1].command as string; - const mainCommand: string = lastCommand.split(" ")[0]; - - this.sendGoogleAnalytics("debug", mainCommand, lastCommand, commands, errorMessage); - this.clearCommandSession(); - } - - return errorMessage; - } - - public difference(object: any, base: any) { - function changes(object: any, base: any) { - return _.transform(object, function(result: any, value, key) { - if (!_.isEqual(value, base[key])) { - result[key] = (_.isObject(value) && _.isObject(base[key])) ? changes(value, base[key]) : value; - } - }); - } - - return changes(object, base); - } - - public viewConfig() : void { - const jsonPath = `${os.homedir()}/.katajson`; - let jsonProp; - - if (fs.existsSync(jsonPath)) { - jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - delete jsonProp.first_login; - } else { - jsonProp = ".katajson file not found"; - } - - console.log(jsonProp); - } - - public checkNotificationStatus(): Boolean { - const jsonPath = `${os.homedir()}/.katanotif`; - - if (fs.existsSync(jsonPath)) { - return true - } else { - fs.writeFileSync(jsonPath, "true", "utf8"); - return false - } - } - - public addCommandSession(command:string): void { - const jsonPath = `${os.homedir()}/.katacommand`; - let jsonData:JsonObject[] = []; - - if (fs.existsSync(jsonPath)) jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - - if (jsonData.length > 0) { - const lastData:JsonObject = jsonData[jsonData.length - 1] - const diff:number = Math.abs(Number(lastData.timestamp) - new Date().getTime()) / 36e5; - - if (diff >= 1) jsonData = [] //Lebih dari 1 jam ? - } - - jsonData.push({ timestamp: new Date().getTime(), command: command }) - - fs.writeFileSync(jsonPath, JSON.stringify(jsonData), "utf8"); - } - - public getCommandSession(): JsonObject[] { - const jsonPath = `${os.homedir()}/.katacommand`; - let jsonData:JsonObject[] = []; - - if (fs.existsSync(jsonPath)) jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - - return jsonData - } - - public clearCommandSession(): void { - const jsonPath = `${os.homedir()}/.katacommand`; - - fs.writeFileSync(jsonPath, "[]", "utf8"); - } - - public sendGoogleAnalytics(event:string, action:string, command:string, lastSession?:JsonObject[], errorMessage?:string): void { - let firstLogin = this.getProp("first_login") as JsonObject; - let projectId = this.getProp("projectId") as string; - let projectName = this.getProp("projectName") as string; - - if (!firstLogin) firstLogin = { id: null, username: null, type: null } - if (!projectId) projectId = null - if (!projectName) projectName = null - - const version = this.config.default("version", "1.0.0") - const google = analytics(this.config.default("config.trackingId", "UA-131926842-1"), firstLogin.id); - - const data:JsonObject = { - userId: firstLogin.id, - username: firstLogin.username, - currentUserType: firstLogin.type, - activeProjectId: projectId, - activeProjectName: projectName, - command: command, - versionCLI: version, - timestamp: new Date().getTime() - } - - if (lastSession) data.lastSession = lastSession - if (errorMessage) data.errorMessage = errorMessage - - google.event(event, action, JSON.stringify(data), (err:any) => { - if (err) console.log(this.wrapError(err)); - }) - } -} + +import { Component, JsonObject, Json, IConfig } from "merapi"; +import * as _ from "lodash"; + +const Catch = require("catch-decorator"); +const yaml = require("js-yaml"); +const fs = require("fs"); +const os = require("os"); +const path = require("path"); +const inquirer = require("inquirer"); +const analytics = require("universal-analytics"); + +function wrapError(error: any) { + let errorMessage; + + if (error.response && error.response.body && error.response.body.message) { + errorMessage = error.response.body.message; + } else if (error.response && error.response.body) { + errorMessage = error.response.body; + } else { + errorMessage = error.message; + } + + return errorMessage; +} + +export const CatchError = Catch(Error, (error: any) => { + console.log("Error"); + console.error(wrapError(error)); +}); + + +export default class Helper extends Component { + constructor(private config : IConfig) { + super(); + } + + public getFiles(dir : string, ending : string) : string[] { + const fileList = fs.readdirSync(dir); + const res = []; + for (let i = 0; i < fileList.length; i++) { + const stat = fs.statSync(path.resolve(dir, fileList[i])); + if (stat.isDirectory()) { + res.push(...this.getFiles(dir + "/" + fileList[i], ending)); + } else if (stat.isFile() && fileList[i].endsWith(ending)) { + res.push(dir + "/" + fileList[i]); + } + } + return res; + } + + public loadYaml(file : string) : JsonObject { + return yaml.safeLoad(fs.readFileSync(file, "utf8")); + } + + public dumpYaml(file : string, object : JsonObject) : void { + fs.writeFileSync(file, yaml.safeDump(object, { indent: 4, lineWidth: 150 }), "utf8"); + } + + public compareTestResult(result : Json, expect : Json) : { field : string, expect : any, result : any }[] { + if (!result) { return null; } + const errors = []; + const expected = this.config.create(expect).flatten(); + const res = this.config.create(result); + for (const i in expected) { + const value = res.get(i); + if (value !== expected[i]) { + errors.push({ field: i, expect: expected[i], result: value }); + } + } + return errors; + } + + public setProp(prop : string, value : string, options? : JsonObject) : void { + const jsonPath = `${os.homedir()}/.katajson`; + let jsonProp; + + if (fs.existsSync(jsonPath)) { + jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + } else { + jsonProp = {}; + } + + jsonProp[prop] = value; + + fs.writeFileSync(jsonPath, JSON.stringify(jsonProp), "utf8"); + } + + public getProp(prop : string, options? : JsonObject) : Json { + const jsonPath = `${os.homedir()}/.katajson`; + let jsonProp; + + if (fs.existsSync(jsonPath)) { + jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + } else { + jsonProp = {}; + } + + return jsonProp[prop]; + } + + public delete() : Boolean { + const jsonPath = `${os.homedir()}/.katajson`; + + if (fs.existsSync(jsonPath)) { + fs.unlinkSync(jsonPath); + return true; + } + + return false; + } + + public deleteKeyToken(userName: string) { + const jsonPath = `${os.homedir()}/.katajson`; + let jsonProp; + + if (fs.existsSync(jsonPath)) { + jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + // if userName token exist + if (userName in jsonProp.token) { + jsonProp.current_login = "admin"; + delete jsonProp.token[userName]; + delete jsonProp.projectId; + delete jsonProp.projectName; + delete jsonProp.isImpersonate; + } else { + return new Error(`Failed to unimpersonate ${(userName)}`); + } + } else { + jsonProp = {}; + } + fs.writeFileSync(jsonPath, JSON.stringify(jsonProp), "utf8"); + return jsonProp; + } + + public toPromise(ctx : any, func : any, ...args : any[]) : Promise { + return new Promise((resolve, reject) => { + args.push((error : Error, data : any, response : Response) => { + if (error) { + reject(error); + } else { + resolve({ data, response }); + } + }); + + func.apply(ctx, args); + }); + } + + public getBotId() : string { + const desc = this.loadYaml("./bot.yml"); + + return desc.id as string; + } + + public getProjectId(): string { + return this.getProp("projectId") as string; + } + + public createDirectory(dirPath: string, mode?: number) { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, mode); + } + } + + public getCurrentToken() : JsonObject { + const currentLogin = this.getProp("current_login") as string || ""; + const tokenProp = (this.getProp("token") || {}) as JsonObject; + + return { + currentLogin, + token: tokenProp[currentLogin] + }; + } + public loadYamlOrJsonFile(filePath : string) { + if (!fs.existsSync(filePath)) { + return new Error("FILE NOT FOUND"); + } + + const fileExt = path.extname(filePath); + + if (fileExt === ".json") { + return JSON.parse(fs.readFileSync(filePath, "utf8")); + } else if (fileExt === ".yml" || fileExt === ".yaml") { + return this.loadYaml(filePath); + } else if (fileExt === ".txt") { + return fs.readFileSync(filePath, "utf8"); + } else { + return new Error("UNSUPPORTED FILE TYPE"); + } + } + + public async inquirerPrompt(questions : JsonObject[]) : Promise { + return inquirer.prompt(questions); + } + + public wrapError(error: any) { + const errorMessage: string = wrapError(error); + + const commands: JsonObject[] = this.getCommandSession(); + // Note: error might happen even after clearCommandSession is called + // this might results in an empty command, we do not want to track empty command error + if (commands.length > 0) { + const lastCommand: string = commands[commands.length - 1].command as string; + const mainCommand: string = lastCommand.split(" ")[0]; + + this.sendGoogleAnalytics("debug", mainCommand, lastCommand, commands, errorMessage); + this.clearCommandSession(); + } + + return errorMessage; + } + + public difference(object: any, base: any) { + function changes(object: any, base: any) { + return _.transform(object, function(result: any, value, key) { + if (!_.isEqual(value, base[key])) { + result[key] = (_.isObject(value) && _.isObject(base[key])) ? changes(value, base[key]) : value; + } + }); + } + + return changes(object, base); + } + + public viewConfig() : void { + const jsonPath = `${os.homedir()}/.katajson`; + let jsonProp; + + if (fs.existsSync(jsonPath)) { + jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + delete jsonProp.first_login; + } else { + jsonProp = ".katajson file not found"; + } + + console.log(jsonProp); + } + + public checkNotificationStatus(): Boolean { + const jsonPath = `${os.homedir()}/.katanotif`; + + if (fs.existsSync(jsonPath)) { + return true + } else { + fs.writeFileSync(jsonPath, "true", "utf8"); + return false + } + } + + public addCommandSession(command:string): void { + const jsonPath = `${os.homedir()}/.katacommand`; + let jsonData:JsonObject[] = []; + + if (fs.existsSync(jsonPath)) jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + + if (jsonData.length > 0) { + const lastData:JsonObject = jsonData[jsonData.length - 1] + const diff:number = Math.abs(Number(lastData.timestamp) - new Date().getTime()) / 36e5; + + if (diff >= 1) jsonData = [] //Lebih dari 1 jam ? + } + + jsonData.push({ timestamp: new Date().getTime(), command: command }) + + fs.writeFileSync(jsonPath, JSON.stringify(jsonData), "utf8"); + } + + public getCommandSession(): JsonObject[] { + const jsonPath = `${os.homedir()}/.katacommand`; + let jsonData:JsonObject[] = []; + + if (fs.existsSync(jsonPath)) jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + + return jsonData + } + + public clearCommandSession(): void { + const jsonPath = `${os.homedir()}/.katacommand`; + + fs.writeFileSync(jsonPath, "[]", "utf8"); + } + + public sendGoogleAnalytics(event:string, action:string, command:string, lastSession?:JsonObject[], errorMessage?:string): void { + let firstLogin = this.getProp("first_login") as JsonObject; + let projectId = this.getProp("projectId") as string; + let projectName = this.getProp("projectName") as string; + + if (!firstLogin) firstLogin = { id: null, username: null, type: null } + if (!projectId) projectId = null + if (!projectName) projectName = null + + const version = this.config.default("version", "1.0.0") + const google = analytics(this.config.default("config.trackingId", "UA-131926842-1"), firstLogin.id); + + const data:JsonObject = { + userId: firstLogin.id, + username: firstLogin.username, + currentUserType: firstLogin.type, + activeProjectId: projectId, + activeProjectName: projectName, + command: command, + versionCLI: version, + timestamp: new Date().getTime() + } + + if (lastSession) data.lastSession = lastSession + if (errorMessage) data.errorMessage = errorMessage + + google.event(event, action, JSON.stringify(data), (err:any) => { + if (err) console.log(this.wrapError(err)); + }) + } +} diff --git a/components/scripts/tester.ts b/components/scripts/tester.ts index 3d9d82e..b75f68d 100644 --- a/components/scripts/tester.ts +++ b/components/scripts/tester.ts @@ -1,133 +1,133 @@ -import { Component, IConfig, JsonObject, IHash } from "merapi"; -import { IHelper } from "interfaces/main"; - -let colors = require("colors/safe"); - -export default class Tester extends Component { - constructor(private config: IConfig, private helper: IHelper) { - super(); - } - - async execIntentTest(yaml: any, botApi: any, botId: string, print = function(text: string){}) : Promise> { - let flow = yaml.flow; - let context = yaml.context || {}; - let data = yaml.data || {}; - let result : IHash<{field: string, expect: any, result: any}[]> = {}; - print(yaml.desc); - let tab = " "; - - for (let name in yaml.test) { - let test = yaml.test[name]; - let testIntent = test.intent || null; - let testContext = Object.assign({}, context, test.context || {}); - let testData = Object.assign({}, data, test.data || {}); - let testMessage = Object.assign({type:"text", content:"", payload:{}}, test.message || {}); - - let body = { - flow, - "intent": testIntent, - "message": testMessage, - "context": testContext, - "data": testData - }; - - let execResult = await this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "intent", body); - result[name] = this.helper.compareTestResult(execResult.data, test.expect); - print(tab+name+": "+ (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); - } - - return result; - } - - async execStateTest(yaml: any, botApi: any, botId: string, print = function(text: string){}) : Promise> { - let flow = yaml.flow; - let context = yaml.context || {}; - let data = yaml.data || {}; - let result : IHash<{field: string, expect: any, result: any}[]> = {}; - print(yaml.desc); - let tab = " "; - - for (let name in yaml.test) { - let test = yaml.test[name]; - let testState = test.state; - let testContext = Object.assign({}, context, test.context || {}); - let testData = Object.assign({}, data, test.data || {}); - let testMessage = Object.assign({type:"text", content:"", payload:{}}, test.message || {} - , {intent:test.intent, attributes:test.attributes}); - - let body = { - flow, - state: testState, - message: testMessage, - context: testContext, - data: testData - }; - - let execResult = await this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "state-mapper", body); - result[name] = this.helper.compareTestResult(execResult.data, test.expect); - print(tab+name+": "+ (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); - } - - return result; - } - - async execActionsTest(yaml: any, botApi: any, botId: string, print = function(text: string){}) : Promise> { - let flow = yaml.flow; - let context = yaml.context || {}; - let data = yaml.data || {}; - let result : IHash<{field: string, expect: any, result: any}[]> = {}; - print(yaml.desc); - let tab = " "; - - for (let name in yaml.test) { - let test = yaml.test[name]; - let testState = test.state; - let testContext = Object.assign({}, context, test.context || {}); - let testData = Object.assign({}, data, test.data || {}); - let testMessage = Object.assign({type:"text", content:"", payload:{}}, test.message || {} - , {intent:test.intent, attributes:test.attributes}); - - let body = { - flow, - state: testState, - message: testMessage, - context: testContext, - data: testData - }; - - let execResult = await this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "action", body); - result[name] = this.helper.compareTestResult(execResult.data, test.expect); - print(tab+name+": "+ (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); - } - - return result; - } - - async execFlowTest(yaml: any, botApi: any, botId: string, print = function(text: string){}) : Promise> { - let flow = yaml.flow; - let state = yaml.state || null; - let context = yaml.context || {}; - let data = yaml.data || {}; - let result : IHash<{field: string, expect: any, result: any}[]> = {}; - print(yaml.desc); - let tab = " "; - - for (let name in yaml.test) { - let test = yaml.test[name]; - let message = Object.assign({type:"text", content:"", payload:{}}, test.message || {} - , {intent:test.intent, attributes:test.attributes}); - - let body = { flow, state, message, context, data }; - - let execResult = await this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "flow", body); - result[name] = this.helper.compareTestResult(execResult.data, test.expect); - print(tab+name+": "+ (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); - if (!execResult) break; - state = execResult.data.state; - context = execResult.data.context; - data = execResult.data; - } - - return result; - } -} +import { Component, IConfig, JsonObject, IHash } from "merapi"; +import { IHelper } from "interfaces/main"; + +let colors = require("colors/safe"); + +export default class Tester extends Component { + constructor(private config: IConfig, private helper: IHelper) { + super(); + } + + async execIntentTest(yaml: any, botApi: any, botId: string, print = function(text: string){}) : Promise> { + let flow = yaml.flow; + let context = yaml.context || {}; + let data = yaml.data || {}; + let result : IHash<{field: string, expect: any, result: any}[]> = {}; + print(yaml.desc); + let tab = " "; + + for (let name in yaml.test) { + let test = yaml.test[name]; + let testIntent = test.intent || null; + let testContext = Object.assign({}, context, test.context || {}); + let testData = Object.assign({}, data, test.data || {}); + let testMessage = Object.assign({type:"text", content:"", payload:{}}, test.message || {}); + + let body = { + flow, + "intent": testIntent, + "message": testMessage, + "context": testContext, + "data": testData + }; + + let execResult = await this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "intent", body); + result[name] = this.helper.compareTestResult(execResult.data, test.expect); + print(tab+name+": "+ (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); + } + + return result; + } + + async execStateTest(yaml: any, botApi: any, botId: string, print = function(text: string){}) : Promise> { + let flow = yaml.flow; + let context = yaml.context || {}; + let data = yaml.data || {}; + let result : IHash<{field: string, expect: any, result: any}[]> = {}; + print(yaml.desc); + let tab = " "; + + for (let name in yaml.test) { + let test = yaml.test[name]; + let testState = test.state; + let testContext = Object.assign({}, context, test.context || {}); + let testData = Object.assign({}, data, test.data || {}); + let testMessage = Object.assign({type:"text", content:"", payload:{}}, test.message || {} + , {intent:test.intent, attributes:test.attributes}); + + let body = { + flow, + state: testState, + message: testMessage, + context: testContext, + data: testData + }; + + let execResult = await this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "state-mapper", body); + result[name] = this.helper.compareTestResult(execResult.data, test.expect); + print(tab+name+": "+ (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); + } + + return result; + } + + async execActionsTest(yaml: any, botApi: any, botId: string, print = function(text: string){}) : Promise> { + let flow = yaml.flow; + let context = yaml.context || {}; + let data = yaml.data || {}; + let result : IHash<{field: string, expect: any, result: any}[]> = {}; + print(yaml.desc); + let tab = " "; + + for (let name in yaml.test) { + let test = yaml.test[name]; + let testState = test.state; + let testContext = Object.assign({}, context, test.context || {}); + let testData = Object.assign({}, data, test.data || {}); + let testMessage = Object.assign({type:"text", content:"", payload:{}}, test.message || {} + , {intent:test.intent, attributes:test.attributes}); + + let body = { + flow, + state: testState, + message: testMessage, + context: testContext, + data: testData + }; + + let execResult = await this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "action", body); + result[name] = this.helper.compareTestResult(execResult.data, test.expect); + print(tab+name+": "+ (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); + } + + return result; + } + + async execFlowTest(yaml: any, botApi: any, botId: string, print = function(text: string){}) : Promise> { + let flow = yaml.flow; + let state = yaml.state || null; + let context = yaml.context || {}; + let data = yaml.data || {}; + let result : IHash<{field: string, expect: any, result: any}[]> = {}; + print(yaml.desc); + let tab = " "; + + for (let name in yaml.test) { + let test = yaml.test[name]; + let message = Object.assign({type:"text", content:"", payload:{}}, test.message || {} + , {intent:test.intent, attributes:test.attributes}); + + let body = { flow, state, message, context, data }; + + let execResult = await this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "flow", body); + result[name] = this.helper.compareTestResult(execResult.data, test.expect); + print(tab+name+": "+ (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); + if (!execResult) break; + state = execResult.data.state; + context = execResult.data.context; + data = execResult.data; + } + + return result; + } +} diff --git a/components/users/team.ts b/components/users/team.ts index 15923f9..7f5008c 100644 --- a/components/users/team.ts +++ b/components/users/team.ts @@ -1,150 +1,150 @@ -import { IHelper } from "interfaces/main"; -import { Component, JsonObject } from "merapi"; - -export default class Team extends Component { - - constructor(private helper: IHelper, private api: any) { - super(); - } - - public async addMember(username: string, options?: JsonObject) { - try { - const role = options.admin ? "teamAdmin" : "teamMember"; - let firstLogin = this.helper.getProp("first_login") as JsonObject; - - const { userInfo, teamInfo, teamMember, currentLogin } = await this.getInfo( - username, - (firstLogin.username).toString() - ); - - if (userInfo && userInfo.id) { - if (this.checkUser(userInfo.id, teamMember)) { - throw new Error(`User ${username} already on this team`); - } - const { response } = await this.helper.toPromise( - this.api.teamApi, - this.api.teamApi.teamsTeamIdUsersUserIdPost, - teamInfo.teamId, - userInfo.username, - { - roleId: role - }); - if (!response.body) { - throw new Error("Error adding user to team: invalid roleId"); - } - console.log(`Success register ${username} to ${currentLogin}`); - } else { - console.log(`User ${username} not found`); - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async removeMember(username: string) { - const answer = await this.helper.inquirerPrompt([ - { - type: "confirm", - name: "confirmation", - message: `Do you want to remove ${username} ?`, - default: false - } - ]); - - if (!answer.confirmation) { - return; - } - - try { - const { userInfo, teamInfo, teamMember, currentLogin } = await this.getInfo(username); - if (userInfo && userInfo.id) { - if (!this.checkUser(userInfo.id, teamMember)) { - throw new Error(`User ${username} not a member of this team`); - } - - const { response } = await this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersUserIdDelete, teamInfo.id, userInfo.id); - - console.log(`Success remove ${username} from ${currentLogin}`); - } else { - console.log(`User ${username} not found`); - } - - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - private async getInfo(username: string, firstLoginUsername?: string) { - const currentLogin = this.helper.getProp("current_login") as string; - const currentUserType = this.helper.getProp("current_user_type") as string; - - if (currentUserType !== "team") { - throw new Error("Must be on team to do this operation"); - } - - const requestTeamData = - await this.helper.toPromise( - this.api.userApi, - this.api.userApi.usersUserIdTeamsGet, - firstLoginUsername - ); - - let teamInfo: any; - if (requestTeamData.response && requestTeamData.response.body) { - const filterTeamBasedOnCurrentTeam = (requestTeamData.response.body).filter( - (singleTeam: any) => ( singleTeam.username == currentLogin )); - teamInfo = filterTeamBasedOnCurrentTeam[0]; - } else { - throw new Error("Cannot add user to team"); - } - // console.log('teamInfo ', teamInfo); - - const requestUserData = - await this.helper.toPromise( - this.api.userApi, - this.api.userApi.usersGetInfoKeyGet, - username - ); - - // console.log('requestUserData ', requestUserData); - let userInfo: any; - if (requestUserData && requestUserData.response) { - userInfo = requestUserData.response.body; - } else { - throw new Error("Cannot add user to team"); - } - - // console.log('userInfo ', userInfo); - const requestTeamMember = - await this.helper.toPromise( - this.api.teamApi, - this.api.teamApi.teamsTeamIdUsersGet, - teamInfo.teamId - ); - - let teamMember: any[]; - if (requestTeamMember && requestTeamMember.response) { - teamMember = requestTeamMember.response.body; - } else { - throw new Error("Cannot add user to team"); - } - - // console.log('teamMember ', teamMember); - return { - teamInfo, - userInfo, - teamMember, - currentLogin - }; - } - - private checkUser(userId: string, member: any[]): boolean { - const teamMember = member.map((x: JsonObject) => x.userId); - if (teamMember.indexOf(userId) > -1) { - return true; - } - - return false; - } - -} +import { IHelper } from "interfaces/main"; +import { Component, JsonObject } from "merapi"; + +export default class Team extends Component { + + constructor(private helper: IHelper, private api: any) { + super(); + } + + public async addMember(username: string, options?: JsonObject) { + try { + const role = options.admin ? "teamAdmin" : "teamMember"; + let firstLogin = this.helper.getProp("first_login") as JsonObject; + + const { userInfo, teamInfo, teamMember, currentLogin } = await this.getInfo( + username, + (firstLogin.username).toString() + ); + + if (userInfo && userInfo.id) { + if (this.checkUser(userInfo.id, teamMember)) { + throw new Error(`User ${username} already on this team`); + } + const { response } = await this.helper.toPromise( + this.api.teamApi, + this.api.teamApi.teamsTeamIdUsersUserIdPost, + teamInfo.teamId, + userInfo.username, + { + roleId: role + }); + if (!response.body) { + throw new Error("Error adding user to team: invalid roleId"); + } + console.log(`Success register ${username} to ${currentLogin}`); + } else { + console.log(`User ${username} not found`); + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async removeMember(username: string) { + const answer = await this.helper.inquirerPrompt([ + { + type: "confirm", + name: "confirmation", + message: `Do you want to remove ${username} ?`, + default: false + } + ]); + + if (!answer.confirmation) { + return; + } + + try { + const { userInfo, teamInfo, teamMember, currentLogin } = await this.getInfo(username); + if (userInfo && userInfo.id) { + if (!this.checkUser(userInfo.id, teamMember)) { + throw new Error(`User ${username} not a member of this team`); + } + + const { response } = await this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersUserIdDelete, teamInfo.id, userInfo.id); + + console.log(`Success remove ${username} from ${currentLogin}`); + } else { + console.log(`User ${username} not found`); + } + + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + private async getInfo(username: string, firstLoginUsername?: string) { + const currentLogin = this.helper.getProp("current_login") as string; + const currentUserType = this.helper.getProp("current_user_type") as string; + + if (currentUserType !== "team") { + throw new Error("Must be on team to do this operation"); + } + + const requestTeamData = + await this.helper.toPromise( + this.api.userApi, + this.api.userApi.usersUserIdTeamsGet, + firstLoginUsername + ); + + let teamInfo: any; + if (requestTeamData.response && requestTeamData.response.body) { + const filterTeamBasedOnCurrentTeam = (requestTeamData.response.body).filter( + (singleTeam: any) => ( singleTeam.username == currentLogin )); + teamInfo = filterTeamBasedOnCurrentTeam[0]; + } else { + throw new Error("Cannot add user to team"); + } + // console.log('teamInfo ', teamInfo); + + const requestUserData = + await this.helper.toPromise( + this.api.userApi, + this.api.userApi.usersGetInfoKeyGet, + username + ); + + // console.log('requestUserData ', requestUserData); + let userInfo: any; + if (requestUserData && requestUserData.response) { + userInfo = requestUserData.response.body; + } else { + throw new Error("Cannot add user to team"); + } + + // console.log('userInfo ', userInfo); + const requestTeamMember = + await this.helper.toPromise( + this.api.teamApi, + this.api.teamApi.teamsTeamIdUsersGet, + teamInfo.teamId + ); + + let teamMember: any[]; + if (requestTeamMember && requestTeamMember.response) { + teamMember = requestTeamMember.response.body; + } else { + throw new Error("Cannot add user to team"); + } + + // console.log('teamMember ', teamMember); + return { + teamInfo, + userInfo, + teamMember, + currentLogin + }; + } + + private checkUser(userId: string, member: any[]): boolean { + const teamMember = member.map((x: JsonObject) => x.userId); + if (teamMember.indexOf(userId) > -1) { + return true; + } + + return false; + } + +} diff --git a/components/users/user.ts b/components/users/user.ts index 791cdf0..3f0e93b 100644 --- a/components/users/user.ts +++ b/components/users/user.ts @@ -1,548 +1,548 @@ -import { Component, JsonObject } from "merapi"; -import { IHelper } from "interfaces/main"; -const inquirer = require("inquirer"); -const Table = require("cli-table"); -const colors = require("colors"); - -export default class User extends Component { - - constructor(private helper: IHelper, private api: any) { - super(); - } - - public async login(options: JsonObject) { - try { - let currToken = this.helper.getCurrentToken().token; - if (options.token) { - if (!currToken) { - currToken = options.token as string; - } - - this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currToken}`; - let result = await this.helper.toPromise(this.api.authApi, this.api.authApi.tokensTokenIdGet, options.token); - const tokenObj = result.data; - - if (tokenObj.type === "user") { - this.setToken({ name: "user", type: tokenObj.type }, options.token as string); - } else if (tokenObj.type === "team") { - result = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, tokenObj.teamId); - const team = result.data; - - this.setToken({ name: team.username, type: tokenObj.type }, options.token as string); - } else { - throw new Error("Invalid token"); - } - } else { - let user = (options.user ? options.user : "") as string; - let pass = (options.password ? options.password : "") as string; - - const answer = await inquirer.prompt([ - { - type: "input", - name: "user", - message: "username: ", - when() { - return !user; - }, - validate(user: string) { - if (!user) { - return "Username cannot be empty"; - } - - return true; - } - }, - { - type: "password", - name: "password", - message: "password: ", - mask: "*", - when() { - return !pass; - }, - validate(password: string) { - if (!password) { - return "Password cannot be empty"; - } - - return true; - } - } - ]); - - user = answer.user || user; - pass = answer.password || pass; - - const result = await this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: user, password: pass }); - if (!result.data.isLoggedIn && !result.data.id) { - console.log(`username or password is incorrect`); - } else { - const token = result.data.id; - - this.helper.setProp("first_login", { type: "user", username: user, id: result.data.userId }); - this.setToken({ name: user, type: "user", namespace: "platform" }, token); - - console.log(`Logged in as ${colors.green(user)}`); - } - } - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - public async logout() { - const answer = await this.helper.inquirerPrompt([ - { - type: "confirm", - name: "confirmation", - message: "Do you want to log out ?", - default: false - } - ]); - - if (!answer.confirmation) { - return; - } - - try { - const result = await this.helper.delete(); - if (result) { - console.log("Logged out"); - } else { - console.log("Please log in first"); - } - - this.helper.clearCommandSession(); - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - public async switch(type: string, name?: string) { - try { - const firstLogin = this.helper.getProp("first_login") as JsonObject; - const currentType = this.helper.getProp("current_user_type"); - const currentLogin = this.helper.getProp("current_login"); - const username = name ? name : currentLogin; - - if (currentType === type && username === currentLogin) { - throw new Error(`Unable to switch : already on ${colors.green(currentLogin)} as ${colors.green(type)}`); - } - - const isImpersonate = this.helper.getProp("isImpersonate"); - if (type === "team") { - let userId: string; - if (isImpersonate === true) { - const currentLoginName = this.helper.getProp("current_login").toString(); - userId = (await this.getUserInfo(currentLoginName)).id; - } else { - userId = firstLogin.id.toString(); - } - const { response } = await this.helper.toPromise( - this.api.userApi, - this.api.userApi.usersUserIdGet, - userId - ); - - - if (!response) { - throw new Error(`Unable to switch team: ${colors.green(name)}`); - } - - const teams = response && response.body ? - response.body.teams.filter((team: any) => team.username === name) : []; - - if (teams.length > 0) { - const result = await this.helper.toPromise( - this.api.authApi, - this.api.authApi.tokensPost, - { - type: "team", - teamId: teams[0].teamId - } - ); - const token = result.data.id; - this.setToken({ name, type: "team" }, token); - this.helper.setProp("current_login", name); - this.helper.setProp("current_user_type", "team"); - console.log(`Switched to team: ${colors.green(name)}`); - } else { - console.log(`Invalid team name. Unable to switch to team: ${colors.red(name)}`); - } - } else if (type === "user") { - if (isImpersonate === true) { - // TODO: jika user login sbg admin, impersonate dewi, switch ke team, lalu mau switch ke user yg non-user tsb - const userTokenInfo = this.getUserTokenInfo(name); - if (!userTokenInfo || userTokenInfo === undefined) { - throw new Error(`${colors.red(name)}'s token is not found.`); - } else if ( userTokenInfo.userName === "admin") { - throw new Error(`Cannot switch to ${colors.red(name)}. Use unimpersonate.`); - } else { - if (name === userTokenInfo.userName) { - this.helper.setProp("current_login", name); - this.helper.setProp("current_user_type", "user"); - console.log(`Switched to user ${colors.green(name)}`); - } else { - throw new Error(`Unable to switch to user ${colors.red(name)}.`); - } - } - } else { - this.helper.setProp("current_login", firstLogin.username); - this.helper.setProp("current_user_type", "user"); - console.log(`Switched to user ${colors.green(firstLogin.username)}`); - } - } - - } catch (e) { - console.log(this.helper.wrapError(e)); - } - } - - public async changePassword() { - try { - const passObj = await this.getNewPasswordData(); - if (passObj.newPass !== passObj.rePass) { - throw new Error("Invalid retype password"); - } - - const currentUser = this.helper.getProp("current_login") as string; - const { data } = await this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: currentUser, password: passObj.oldPass }); - if (data) { - const result = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdPut, currentUser, { password: passObj.newPass }); - console.log("Password changed"); - } else { - console.log("Invalid password"); - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - - public whoami(options: JsonObject) { - const currentLogin = this.helper.getProp("current_login") as string; - const currentType = this.helper.getProp("current_user_type") as string; - console.log(`Current login: ${colors.green(currentLogin)}, login type: ${colors.green(currentType)}`); - } - - public async createTeam(name: string) { - try { - const currentLogin = this.helper.getProp("current_login") as string; - const currentUserType = this.helper.getProp("current_user_type") as string; - - if (currentUserType !== "user") { - throw new Error("Must be on user to do this operation"); - } - - const { response } = await this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsPost, { username: name, password: "", roleId: "teamAdmin" }); - - if (response && response.body.id) { - console.log(`Team ${colors.green(name)} created !`); - } else { - console.log(`Team ${colors.red(name)} exist !`); - } - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async createUser(username: string, options?: JsonObject) { - const password = await this.helper.inquirerPrompt([ - { - type: "password", - name: "answer", - message: "password: ", - mask: "*", - default: null - }]); - - const confirmPassword = await this.helper.inquirerPrompt([ - { - type: "password", - name: "answer", - message: "retype password: ", - mask: "*", - default: null - } - ]); - try { - - if (password.answer !== confirmPassword.answer) { - throw new Error("Invalid retype password"); - } - - let role: string; - if (options.admin) { - role = "admin"; - } else if (options.internal) { - role = "internalUser"; - } else { - role = "user"; - } - - const { data } = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, username); - - if (data.id) { - throw new Error(`Username ${username} exist !`); - } - - const newUser = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersPost, { username, password: password.answer, roleId: role }); - - console.log(`New user ${colors.green(newUser.data.username)} created !`); - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - public async impersonate(userName: string) { - // TODO : dibuat seperti login, pake inquirer. - try { - const currentLogin: string = this.helper.getProp("current_login").toString(); - if (currentLogin !== "admin") { - throw new Error(`Your login status is not superadmin. You are not authorized to impersonate a user`); - } - - // set currentToken header bearer token - const currentToken: string = this.helper.getCurrentToken().token.toString(); - this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`; - - // get admin token - this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`; - - // get user id from username - const id: string = (await this.getUserInfo(userName)).id; - const name: string = (await this.getUserInfo(userName)).name; - const email: string = (await this.getUserInfo(userName)).email; - - if ( name && email ) { - // userName is user collected input - if ( userName !== name && userName !== email ) { - throw new Error(`Sorry, username is not exist.`); - } - } else { - throw new Error(`Sorry, username is not valid.`); - } - - - // impersonate function - const result = await this.helper.toPromise( - this.api.authApi, this.api.authApi.impersonatePost, - { - userId: id, - namespace: "platform" - } - ); - - // set value on .katajson - const impersonateToken: string = result.data.id.toString(); - const type: string = result.data.type.toString(); - this.helper.setProp("isImpersonate", true); - this.setToken({ name, type }, impersonateToken); - - console.log(`Succesfully impersonate as ${colors.green(name)}`); - - } catch (error) { - console.log(this.helper.wrapError(error)); - - } - } - - // unimpersonate command - public async unimpersonate() { - try { - const userName: string = this.helper.getProp("current_login").toString(); - this.helper.deleteKeyToken(userName); - const currentLogin: string = this.helper.getProp("current_login").toString(); - console.log(`Succesfully unimpersonate user. Now your current login is ${colors.green(currentLogin)}`); - } catch (error) { - console.log(this.helper.wrapError(error)); - } - } - - - private setToken(userInfo: JsonObject, token: string) { - this.helper.setProp("current_login", userInfo.name); - this.helper.setProp("current_user_type", userInfo.type); - this.helper.setProp("namespace", userInfo.namespace); - const tokenProp = (this.helper.getProp("token") || {}) as JsonObject; - tokenProp[userInfo.name as string] = token; - this.helper.setProp("token", tokenProp); - } - - private getUserTokenInfo(name: string) { - const tokenProp = (this.helper.getProp("token") || {}) as JsonObject; - if (name in tokenProp) { - const userName: string = name.toString(); - const token: string = tokenProp[name as string].toString(); - return { - userName, - token - }; - } - } - - private async getUserInfo(userName: string) { - // get userId from currentlogin - const { response } = await this.helper.toPromise( - this.api.userApi, - this.api.userApi.usersGetInfoKeyGet, - userName, - ); - const user = response.body; - const email: string = user.email ? user.email.toString() : ""; - const name: string = user.username.toString(); - const id: string = user.userId.toString(); - return { - id, - name, - email, - }; - } - - private async getNewPasswordData(): Promise { - let oldPass : string; - let newPass : string; - let rePass : string; - - const answer = await inquirer.prompt([ - { - type: "password", - name: "oldPass", - message: "current password: ", - mask: "*", - when() { - return !oldPass; - }, - validate(user : string) { - if (!user) { - return "Password cannot be empty"; - } - return true; - } - }, - { - type: "password", - name: "newPass", - message: "new password: ", - mask: "*", - when() { - return !newPass; - }, - validate(password: string) { - if (!password) { - return "Password cannot be empty"; - } - - return true; - } - }, - { - type: "password", - name: "rePass", - message: "retype new password: ", - mask: "*", - when() { - return !rePass; - }, - validate(password: string, answer: JsonObject) { - if (!password) { - return "Password cannot be empty"; - } - - if (password !== answer.newPass) { - return "Invalid retype password"; - } - - return true; - } - }, - ]); - - return answer; - } - - public async forgot(username: string) { - try { - const current_login = this.helper.getProp("current_login") - if (!current_login) { - const { response } = await this.helper.toPromise(this.api.authApi, this.api.authApi.forgotPost, { username }); - if (response && response.body && response.body.message) { - console.log("Please check your email to reset your password."); - } - } else { - console.log(`Please log out first`); - } - } catch (e) { - console.error(this.helper.wrapError(e)); - } - } - - public async listTeam() { - try { - const current_login = this.helper.getProp("current_login") - if (current_login) { - const { response } = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login); - const table = new Table({ - head: ["Team Name", "Projects", "Members", "Bots"], - colWidths: [50, 15, 15, 15] - }); - response.body.forEach((team: JsonObject) => { - table.push([team.username, team.projects, team.members, team.bots]); - }); - console.log(table.toString()); - } else { - console.log("Please log in first"); - } - } catch (e) { - console.error(this.helper.wrapError(e)); - } - } - - public async listTeamUser(teamName?: string) { - try { - const current_login = this.helper.getProp("current_login") - if (current_login) { - const dataTeams = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login); - const teams: object[] = dataTeams.response.body; - const choices = teams.map((team: any) => ({ - name: team.username, - value: team.teamId - })); - let teamId = null - - if (teamName) { - const sameName = choices.find((choice: any) => choice.name === teamName); - if (sameName) { - teamId = sameName.value - } - } else { - const choice = await inquirer.prompt([ - { - type: "list", - name: "teamId", - message: "Team:", - choices: choices - } - ]); - - teamId = choice.teamId - } - - - const { response } = await this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersGet, teamId); - const table = new Table({ - head: ["Username", "Role"], - colWidths: [50, 25] - }); - response.body.forEach((user: JsonObject) => { - table.push([user.username, user.roleName]); - }); - console.log(table.toString()); - } else { - console.log("Please log in first"); - } - } catch (e) { - console.error(this.helper.wrapError(e)); - } - } -} +import { Component, JsonObject } from "merapi"; +import { IHelper } from "interfaces/main"; +const inquirer = require("inquirer"); +const Table = require("cli-table"); +const colors = require("colors"); + +export default class User extends Component { + + constructor(private helper: IHelper, private api: any) { + super(); + } + + public async login(options: JsonObject) { + try { + let currToken = this.helper.getCurrentToken().token; + if (options.token) { + if (!currToken) { + currToken = options.token as string; + } + + this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currToken}`; + let result = await this.helper.toPromise(this.api.authApi, this.api.authApi.tokensTokenIdGet, options.token); + const tokenObj = result.data; + + if (tokenObj.type === "user") { + this.setToken({ name: "user", type: tokenObj.type }, options.token as string); + } else if (tokenObj.type === "team") { + result = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, tokenObj.teamId); + const team = result.data; + + this.setToken({ name: team.username, type: tokenObj.type }, options.token as string); + } else { + throw new Error("Invalid token"); + } + } else { + let user = (options.user ? options.user : "") as string; + let pass = (options.password ? options.password : "") as string; + + const answer = await inquirer.prompt([ + { + type: "input", + name: "user", + message: "username: ", + when() { + return !user; + }, + validate(user: string) { + if (!user) { + return "Username cannot be empty"; + } + + return true; + } + }, + { + type: "password", + name: "password", + message: "password: ", + mask: "*", + when() { + return !pass; + }, + validate(password: string) { + if (!password) { + return "Password cannot be empty"; + } + + return true; + } + } + ]); + + user = answer.user || user; + pass = answer.password || pass; + + const result = await this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: user, password: pass }); + if (!result.data.isLoggedIn && !result.data.id) { + console.log(`username or password is incorrect`); + } else { + const token = result.data.id; + + this.helper.setProp("first_login", { type: "user", username: user, id: result.data.userId }); + this.setToken({ name: user, type: "user", namespace: "platform" }, token); + + console.log(`Logged in as ${colors.green(user)}`); + } + } + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + public async logout() { + const answer = await this.helper.inquirerPrompt([ + { + type: "confirm", + name: "confirmation", + message: "Do you want to log out ?", + default: false + } + ]); + + if (!answer.confirmation) { + return; + } + + try { + const result = await this.helper.delete(); + if (result) { + console.log("Logged out"); + } else { + console.log("Please log in first"); + } + + this.helper.clearCommandSession(); + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + public async switch(type: string, name?: string) { + try { + const firstLogin = this.helper.getProp("first_login") as JsonObject; + const currentType = this.helper.getProp("current_user_type"); + const currentLogin = this.helper.getProp("current_login"); + const username = name ? name : currentLogin; + + if (currentType === type && username === currentLogin) { + throw new Error(`Unable to switch : already on ${colors.green(currentLogin)} as ${colors.green(type)}`); + } + + const isImpersonate = this.helper.getProp("isImpersonate"); + if (type === "team") { + let userId: string; + if (isImpersonate === true) { + const currentLoginName = this.helper.getProp("current_login").toString(); + userId = (await this.getUserInfo(currentLoginName)).id; + } else { + userId = firstLogin.id.toString(); + } + const { response } = await this.helper.toPromise( + this.api.userApi, + this.api.userApi.usersUserIdGet, + userId + ); + + + if (!response) { + throw new Error(`Unable to switch team: ${colors.green(name)}`); + } + + const teams = response && response.body ? + response.body.teams.filter((team: any) => team.username === name) : []; + + if (teams.length > 0) { + const result = await this.helper.toPromise( + this.api.authApi, + this.api.authApi.tokensPost, + { + type: "team", + teamId: teams[0].teamId + } + ); + const token = result.data.id; + this.setToken({ name, type: "team" }, token); + this.helper.setProp("current_login", name); + this.helper.setProp("current_user_type", "team"); + console.log(`Switched to team: ${colors.green(name)}`); + } else { + console.log(`Invalid team name. Unable to switch to team: ${colors.red(name)}`); + } + } else if (type === "user") { + if (isImpersonate === true) { + // TODO: jika user login sbg admin, impersonate dewi, switch ke team, lalu mau switch ke user yg non-user tsb + const userTokenInfo = this.getUserTokenInfo(name); + if (!userTokenInfo || userTokenInfo === undefined) { + throw new Error(`${colors.red(name)}'s token is not found.`); + } else if ( userTokenInfo.userName === "admin") { + throw new Error(`Cannot switch to ${colors.red(name)}. Use unimpersonate.`); + } else { + if (name === userTokenInfo.userName) { + this.helper.setProp("current_login", name); + this.helper.setProp("current_user_type", "user"); + console.log(`Switched to user ${colors.green(name)}`); + } else { + throw new Error(`Unable to switch to user ${colors.red(name)}.`); + } + } + } else { + this.helper.setProp("current_login", firstLogin.username); + this.helper.setProp("current_user_type", "user"); + console.log(`Switched to user ${colors.green(firstLogin.username)}`); + } + } + + } catch (e) { + console.log(this.helper.wrapError(e)); + } + } + + public async changePassword() { + try { + const passObj = await this.getNewPasswordData(); + if (passObj.newPass !== passObj.rePass) { + throw new Error("Invalid retype password"); + } + + const currentUser = this.helper.getProp("current_login") as string; + const { data } = await this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: currentUser, password: passObj.oldPass }); + if (data) { + const result = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdPut, currentUser, { password: passObj.newPass }); + console.log("Password changed"); + } else { + console.log("Invalid password"); + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + + public whoami(options: JsonObject) { + const currentLogin = this.helper.getProp("current_login") as string; + const currentType = this.helper.getProp("current_user_type") as string; + console.log(`Current login: ${colors.green(currentLogin)}, login type: ${colors.green(currentType)}`); + } + + public async createTeam(name: string) { + try { + const currentLogin = this.helper.getProp("current_login") as string; + const currentUserType = this.helper.getProp("current_user_type") as string; + + if (currentUserType !== "user") { + throw new Error("Must be on user to do this operation"); + } + + const { response } = await this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsPost, { username: name, password: "", roleId: "teamAdmin" }); + + if (response && response.body.id) { + console.log(`Team ${colors.green(name)} created !`); + } else { + console.log(`Team ${colors.red(name)} exist !`); + } + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async createUser(username: string, options?: JsonObject) { + const password = await this.helper.inquirerPrompt([ + { + type: "password", + name: "answer", + message: "password: ", + mask: "*", + default: null + }]); + + const confirmPassword = await this.helper.inquirerPrompt([ + { + type: "password", + name: "answer", + message: "retype password: ", + mask: "*", + default: null + } + ]); + try { + + if (password.answer !== confirmPassword.answer) { + throw new Error("Invalid retype password"); + } + + let role: string; + if (options.admin) { + role = "admin"; + } else if (options.internal) { + role = "internalUser"; + } else { + role = "user"; + } + + const { data } = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, username); + + if (data.id) { + throw new Error(`Username ${username} exist !`); + } + + const newUser = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersPost, { username, password: password.answer, roleId: role }); + + console.log(`New user ${colors.green(newUser.data.username)} created !`); + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + public async impersonate(userName: string) { + // TODO : dibuat seperti login, pake inquirer. + try { + const currentLogin: string = this.helper.getProp("current_login").toString(); + if (currentLogin !== "admin") { + throw new Error(`Your login status is not superadmin. You are not authorized to impersonate a user`); + } + + // set currentToken header bearer token + const currentToken: string = this.helper.getCurrentToken().token.toString(); + this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`; + + // get admin token + this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`; + + // get user id from username + const id: string = (await this.getUserInfo(userName)).id; + const name: string = (await this.getUserInfo(userName)).name; + const email: string = (await this.getUserInfo(userName)).email; + + if ( name && email ) { + // userName is user collected input + if ( userName !== name && userName !== email ) { + throw new Error(`Sorry, username is not exist.`); + } + } else { + throw new Error(`Sorry, username is not valid.`); + } + + + // impersonate function + const result = await this.helper.toPromise( + this.api.authApi, this.api.authApi.impersonatePost, + { + userId: id, + namespace: "platform" + } + ); + + // set value on .katajson + const impersonateToken: string = result.data.id.toString(); + const type: string = result.data.type.toString(); + this.helper.setProp("isImpersonate", true); + this.setToken({ name, type }, impersonateToken); + + console.log(`Succesfully impersonate as ${colors.green(name)}`); + + } catch (error) { + console.log(this.helper.wrapError(error)); + + } + } + + // unimpersonate command + public async unimpersonate() { + try { + const userName: string = this.helper.getProp("current_login").toString(); + this.helper.deleteKeyToken(userName); + const currentLogin: string = this.helper.getProp("current_login").toString(); + console.log(`Succesfully unimpersonate user. Now your current login is ${colors.green(currentLogin)}`); + } catch (error) { + console.log(this.helper.wrapError(error)); + } + } + + + private setToken(userInfo: JsonObject, token: string) { + this.helper.setProp("current_login", userInfo.name); + this.helper.setProp("current_user_type", userInfo.type); + this.helper.setProp("namespace", userInfo.namespace); + const tokenProp = (this.helper.getProp("token") || {}) as JsonObject; + tokenProp[userInfo.name as string] = token; + this.helper.setProp("token", tokenProp); + } + + private getUserTokenInfo(name: string) { + const tokenProp = (this.helper.getProp("token") || {}) as JsonObject; + if (name in tokenProp) { + const userName: string = name.toString(); + const token: string = tokenProp[name as string].toString(); + return { + userName, + token + }; + } + } + + private async getUserInfo(userName: string) { + // get userId from currentlogin + const { response } = await this.helper.toPromise( + this.api.userApi, + this.api.userApi.usersGetInfoKeyGet, + userName, + ); + const user = response.body; + const email: string = user.email ? user.email.toString() : ""; + const name: string = user.username.toString(); + const id: string = user.userId.toString(); + return { + id, + name, + email, + }; + } + + private async getNewPasswordData(): Promise { + let oldPass : string; + let newPass : string; + let rePass : string; + + const answer = await inquirer.prompt([ + { + type: "password", + name: "oldPass", + message: "current password: ", + mask: "*", + when() { + return !oldPass; + }, + validate(user : string) { + if (!user) { + return "Password cannot be empty"; + } + return true; + } + }, + { + type: "password", + name: "newPass", + message: "new password: ", + mask: "*", + when() { + return !newPass; + }, + validate(password: string) { + if (!password) { + return "Password cannot be empty"; + } + + return true; + } + }, + { + type: "password", + name: "rePass", + message: "retype new password: ", + mask: "*", + when() { + return !rePass; + }, + validate(password: string, answer: JsonObject) { + if (!password) { + return "Password cannot be empty"; + } + + if (password !== answer.newPass) { + return "Invalid retype password"; + } + + return true; + } + }, + ]); + + return answer; + } + + public async forgot(username: string) { + try { + const current_login = this.helper.getProp("current_login") + if (!current_login) { + const { response } = await this.helper.toPromise(this.api.authApi, this.api.authApi.forgotPost, { username }); + if (response && response.body && response.body.message) { + console.log("Please check your email to reset your password."); + } + } else { + console.log(`Please log out first`); + } + } catch (e) { + console.error(this.helper.wrapError(e)); + } + } + + public async listTeam() { + try { + const current_login = this.helper.getProp("current_login") + if (current_login) { + const { response } = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login); + const table = new Table({ + head: ["Team Name", "Projects", "Members", "Bots"], + colWidths: [50, 15, 15, 15] + }); + response.body.forEach((team: JsonObject) => { + table.push([team.username, team.projects, team.members, team.bots]); + }); + console.log(table.toString()); + } else { + console.log("Please log in first"); + } + } catch (e) { + console.error(this.helper.wrapError(e)); + } + } + + public async listTeamUser(teamName?: string) { + try { + const current_login = this.helper.getProp("current_login") + if (current_login) { + const dataTeams = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login); + const teams: object[] = dataTeams.response.body; + const choices = teams.map((team: any) => ({ + name: team.username, + value: team.teamId + })); + let teamId = null + + if (teamName) { + const sameName = choices.find((choice: any) => choice.name === teamName); + if (sameName) { + teamId = sameName.value + } + } else { + const choice = await inquirer.prompt([ + { + type: "list", + name: "teamId", + message: "Team:", + choices: choices + } + ]); + + teamId = choice.teamId + } + + + const { response } = await this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersGet, teamId); + const table = new Table({ + head: ["Username", "Role"], + colWidths: [50, 25] + }); + response.body.forEach((user: JsonObject) => { + table.push([user.username, user.roleName]); + }); + console.log(table.toString()); + } else { + console.log("Please log in first"); + } + } catch (e) { + console.error(this.helper.wrapError(e)); + } + } +} diff --git a/index.js b/index.js index 175bcf5..70e2f8a 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,13 @@ -"use strict"; -const path = require("path"); -const merapi = require("merapi"); -const yaml = require("js-yaml"); -const fs = require("fs"); -const config = yaml.safeLoad(fs.readFileSync(`${__dirname}/service.yml`, "utf8")); -config.package = require(`${__dirname}/package`); - -module.exports = merapi({ - basepath: path.resolve(__dirname, "lib"), - config: config, - delimiters: {left: "${", right: "}"} -}); +"use strict"; +const path = require("path"); +const merapi = require("merapi"); +const yaml = require("js-yaml"); +const fs = require("fs"); +const config = yaml.safeLoad(fs.readFileSync(`${__dirname}/service.yml`, "utf8")); +config.package = require(`${__dirname}/package`); + +module.exports = merapi({ + basepath: path.resolve(__dirname, "lib"), + config: config, + delimiters: {left: "${", right: "}"} +}); diff --git a/interfaces/main.ts b/interfaces/main.ts index f0d40bd..19ecb0d 100644 --- a/interfaces/main.ts +++ b/interfaces/main.ts @@ -1,316 +1,316 @@ -import { Json, IConfig, IHash, JsonObject } from "merapi"; - -export interface CommandOptions { - noHelp?: boolean; - isDefault?: boolean; - } - -export interface ParseOptionsResult { - args: string[]; - unknown: string[]; -} - -export interface Option { - flags: string; - required: boolean; - optional: boolean; - bool: boolean; - short?: string; - long: string; - description: string; -} - -export interface Command extends NodeJS.EventEmitter { - args: string[]; - - /** - * Set the program version to `str`. - * - * This method auto-registers the "-V, --version" flag - * which will print the version number when passed. - * - * @param {string} str - * @param {string} [flags] - * @returns {Command} for chaining - */ - version(str: string, flags?: string): Command; - - /** - * Add command `name`. - * - * The `.action()` callback is invoked when the - * command `name` is specified via __ARGV__, - * and the remaining arguments are applied to the - * function for access. - * - * When the `name` is "*" an un-matched command - * will be passed as the first arg, followed by - * the rest of __ARGV__ remaining. - * - * @example - * program - * .version('0.0.1') - * .option('-C, --chdir ', 'change the working directory') - * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') - * .option('-T, --no-tests', 'ignore test hook') - * - * program - * .command('setup') - * .description('run remote setup commands') - * .action(function() { - * console.log('setup'); - * }); - * - * program - * .command('exec ') - * .description('run the given remote command') - * .action(function(cmd) { - * console.log('exec "%s"', cmd); - * }); - * - * program - * .command('teardown [otherDirs...]') - * .description('run teardown commands') - * .action(function(dir, otherDirs) { - * console.log('dir "%s"', dir); - * if (otherDirs) { - * otherDirs.forEach(function (oDir) { - * console.log('dir "%s"', oDir); - * }); - * } - * }); - * - * program - * .command('*') - * .description('deploy the given env') - * .action(function(env) { - * console.log('deploying "%s"', env); - * }); - * - * program.parse(process.argv); - * - * @param {string} name - * @param {string} [desc] for git-style sub-commands - * @param {CommandOptions} [opts] command options - * @returns {Command} the new command - */ - command(name: string, desc?: string, opts?: CommandOptions): Command; - - - /** - * Define argument syntax for the top-level command. - * - * @param {string} desc - * @returns {Command} for chaining - */ - arguments(desc: string): Command; - - /** - * Parse expected `args`. - * - * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. - * - * @param {string[]} args - * @returns {Command} for chaining - */ - parseExpectedArgs(args: string[]): Command; - /** - * Register callback `fn` for the command. - * - * @example - * program - * .command('help') - * .description('display verbose help') - * .action(function() { - * // output help here - * }); - * - * @param {(...args: any[]) => void} fn - * @returns {Command} for chaining - */ - action(fn: (...args: any[]) => void): Command; - - /** - * Define option with `flags`, `description` and optional - * coercion `fn`. - * - * The `flags` string should contain both the short and long flags, - * separated by comma, a pipe or space. The following are all valid - * all will output this way when `--help` is used. - * - * "-p, --pepper" - * "-p|--pepper" - * "-p --pepper" - * - *@example - * // simple boolean defaulting to false - * program.option('-p, --pepper', 'add pepper'); - * - * --pepper - * program.pepper - * // => Boolean - * - * // simple boolean defaulting to true - * program.option('-C, --no-cheese', 'remove cheese'); - * - * program.cheese - * // => true - * - * --no-cheese - * program.cheese - * // => false - * - * // required argument - * program.option('-C, --chdir ', 'change the working directory'); - * - * --chdir /tmp - * program.chdir - * // => "/tmp" - * - * // optional argument - * program.option('-c, --cheese [type]', 'add cheese [marble]'); - * - * @param {string} flags - * @param {string} [description] - * @param {((arg1: any, arg2: any) => void) | RegExp} [fn] function or default - * @param {*} [defaultValue] - * @returns {Command} for chaining - */ - option(flags: string, description?: string, fn?: ((arg1: any, arg2: any) => void) | RegExp, defaultValue?: any): Command; - option(flags: string, description?: string, defaultValue?: any): Command; - - /** - * Allow unknown options on the command line. - * - * @param {boolean} [arg] if `true` or omitted, no error will be thrown for unknown options. - * @returns {Command} for chaining - */ - allowUnknownOption(arg?: boolean): Command; - - /** - * Parse `argv`, settings options and invoking commands when defined. - * - * @param {string[]} argv - * @returns {Command} for chaining - */ - parse(argv: string[]): Command; - - /** - * Parse options from `argv` returning `argv` void of these options. - * - * @param {string[]} argv - * @returns {ParseOptionsResult} - */ - parseOptions(argv: string[]): ParseOptionsResult; - - /** - * Return an object containing options as key-value pairs - * - * @returns {{[key: string]: string}} - */ - opts(): { [key: string]: string }; - - /** - * Set the description to `str`. - * - * @param {string} str - * @return {(Command | string)} - */ - description(str: string): Command; - description(): string; - - /** - * Set an alias for the command. - * - * @param {string} alias - * @return {(Command | string)} - */ - alias(alias: string): Command; - alias(): string; - - /** - * Set or get the command usage. - * - * @param {string} str - * @return {(Command | string)} - */ - usage(str: string): Command; - usage(): string; - - /** - * Get the name of the command. - * - * @return {string} - */ - name(): string; - - /** - * Output help information for this command. - * - * @param {() => void} [cb] Callback method - */ - outputHelp(cb?: () => void): void; - - /** Output help information and exit. */ - help(): void; -} - -export interface CommandList { - [name: string] : CommandDescriptor; -} - -export interface CommandDescriptor { - type?: "group" | "command" | "alias"; - desc?: string; - middleware?: string[]; - subcommands?: CommandList; - args?: string; - params?: { - [param: string]: { - type: string, - desc?: string, - short?: string, - bool?: boolean, - value?: Json - } - }; - handler?: string; - alias?: string; -} - -export interface ICompile { - execDirectives(config: IConfig, basepath: string) : IConfig; - execDirective(name: string, directive: any, dict: IHash, basepath: string) : void -} - -export interface IHelper { - getFiles(dir: string, ending: string) : string[]; - loadYaml(file: string) : JsonObject; - dumpYaml(file: string, object: JsonObject) : void; - compareTestResult(result: Json, expect: Json) : {field: string, expect: any, result: any}[]; - setProp(prop: string, value: Json, options?: JsonObject) : void; - getProp(prop: string, options?: JsonObject): Json; - toPromise(ctx: any, func: any, ...args: any[]): Promise; - getBotId(): string; - getProjectId(): string; - createDirectory(path: string, mode?: number) : void; - getCurrentToken() : JsonObject; - loadYamlOrJsonFile(filePath: string) : JsonObject; - inquirerPrompt(questions: JsonObject[]): Promise; - delete() : Boolean; - deleteKeyToken(username: string): JsonObject; - wrapError(error : any) : string; - difference(object: any, base: any): Object; - checkNotificationStatus() : Boolean; - addCommandSession(command:string): void; - getCommandSession(): JsonObject[]; - clearCommandSession(): void; - sendGoogleAnalytics(event:string, action:string, data:string): void; -} - -export interface ITester { - execIntentTest(yaml: any, botApi: any, botId: string, print: (text: string) => void) : Promise>; - execStateTest(yaml: any, botApi: any, botId: string, print: (text: string) => void) : Promise>; - execActionsTest(yaml: any, botApi: any, botId: string, print: (text: string) => void) : Promise>; - execFlowTest(yaml: any, botApi: any, botId: string, print: (text: string) => void) : Promise>; -} +import { Json, IConfig, IHash, JsonObject } from "merapi"; + +export interface CommandOptions { + noHelp?: boolean; + isDefault?: boolean; + } + +export interface ParseOptionsResult { + args: string[]; + unknown: string[]; +} + +export interface Option { + flags: string; + required: boolean; + optional: boolean; + bool: boolean; + short?: string; + long: string; + description: string; +} + +export interface Command extends NodeJS.EventEmitter { + args: string[]; + + /** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {string} str + * @param {string} [flags] + * @returns {Command} for chaining + */ + version(str: string, flags?: string): Command; + + /** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * @example + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function() { + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd) { + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('teardown [otherDirs...]') + * .description('run teardown commands') + * .action(function(dir, otherDirs) { + * console.log('dir "%s"', dir); + * if (otherDirs) { + * otherDirs.forEach(function (oDir) { + * console.log('dir "%s"', oDir); + * }); + * } + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env) { + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {string} name + * @param {string} [desc] for git-style sub-commands + * @param {CommandOptions} [opts] command options + * @returns {Command} the new command + */ + command(name: string, desc?: string, opts?: CommandOptions): Command; + + + /** + * Define argument syntax for the top-level command. + * + * @param {string} desc + * @returns {Command} for chaining + */ + arguments(desc: string): Command; + + /** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {string[]} args + * @returns {Command} for chaining + */ + parseExpectedArgs(args: string[]): Command; + /** + * Register callback `fn` for the command. + * + * @example + * program + * .command('help') + * .description('display verbose help') + * .action(function() { + * // output help here + * }); + * + * @param {(...args: any[]) => void} fn + * @returns {Command} for chaining + */ + action(fn: (...args: any[]) => void): Command; + + /** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + *@example + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to true + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => false + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {string} flags + * @param {string} [description] + * @param {((arg1: any, arg2: any) => void) | RegExp} [fn] function or default + * @param {*} [defaultValue] + * @returns {Command} for chaining + */ + option(flags: string, description?: string, fn?: ((arg1: any, arg2: any) => void) | RegExp, defaultValue?: any): Command; + option(flags: string, description?: string, defaultValue?: any): Command; + + /** + * Allow unknown options on the command line. + * + * @param {boolean} [arg] if `true` or omitted, no error will be thrown for unknown options. + * @returns {Command} for chaining + */ + allowUnknownOption(arg?: boolean): Command; + + /** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {string[]} argv + * @returns {Command} for chaining + */ + parse(argv: string[]): Command; + + /** + * Parse options from `argv` returning `argv` void of these options. + * + * @param {string[]} argv + * @returns {ParseOptionsResult} + */ + parseOptions(argv: string[]): ParseOptionsResult; + + /** + * Return an object containing options as key-value pairs + * + * @returns {{[key: string]: string}} + */ + opts(): { [key: string]: string }; + + /** + * Set the description to `str`. + * + * @param {string} str + * @return {(Command | string)} + */ + description(str: string): Command; + description(): string; + + /** + * Set an alias for the command. + * + * @param {string} alias + * @return {(Command | string)} + */ + alias(alias: string): Command; + alias(): string; + + /** + * Set or get the command usage. + * + * @param {string} str + * @return {(Command | string)} + */ + usage(str: string): Command; + usage(): string; + + /** + * Get the name of the command. + * + * @return {string} + */ + name(): string; + + /** + * Output help information for this command. + * + * @param {() => void} [cb] Callback method + */ + outputHelp(cb?: () => void): void; + + /** Output help information and exit. */ + help(): void; +} + +export interface CommandList { + [name: string] : CommandDescriptor; +} + +export interface CommandDescriptor { + type?: "group" | "command" | "alias"; + desc?: string; + middleware?: string[]; + subcommands?: CommandList; + args?: string; + params?: { + [param: string]: { + type: string, + desc?: string, + short?: string, + bool?: boolean, + value?: Json + } + }; + handler?: string; + alias?: string; +} + +export interface ICompile { + execDirectives(config: IConfig, basepath: string) : IConfig; + execDirective(name: string, directive: any, dict: IHash, basepath: string) : void +} + +export interface IHelper { + getFiles(dir: string, ending: string) : string[]; + loadYaml(file: string) : JsonObject; + dumpYaml(file: string, object: JsonObject) : void; + compareTestResult(result: Json, expect: Json) : {field: string, expect: any, result: any}[]; + setProp(prop: string, value: Json, options?: JsonObject) : void; + getProp(prop: string, options?: JsonObject): Json; + toPromise(ctx: any, func: any, ...args: any[]): Promise; + getBotId(): string; + getProjectId(): string; + createDirectory(path: string, mode?: number) : void; + getCurrentToken() : JsonObject; + loadYamlOrJsonFile(filePath: string) : JsonObject; + inquirerPrompt(questions: JsonObject[]): Promise; + delete() : Boolean; + deleteKeyToken(username: string): JsonObject; + wrapError(error : any) : string; + difference(object: any, base: any): Object; + checkNotificationStatus() : Boolean; + addCommandSession(command:string): void; + getCommandSession(): JsonObject[]; + clearCommandSession(): void; + sendGoogleAnalytics(event:string, action:string, data:string): void; +} + +export interface ITester { + execIntentTest(yaml: any, botApi: any, botId: string, print: (text: string) => void) : Promise>; + execStateTest(yaml: any, botApi: any, botId: string, print: (text: string) => void) : Promise>; + execActionsTest(yaml: any, botApi: any, botId: string, print: (text: string) => void) : Promise>; + execFlowTest(yaml: any, botApi: any, botId: string, print: (text: string) => void) : Promise>; +} diff --git a/lib/components/api/api.js b/lib/components/api/api.js index 514250c..aa34f70 100644 --- a/lib/components/api/api.js +++ b/lib/components/api/api.js @@ -1,31 +1,31 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -class Api extends merapi_1.Component { - constructor(helper, zaun) { - super(); - this.helper = helper; - this.zaun = zaun; - this.apiClient = this.zaun.ApiClient.instance; - let basePath = this.helper.getProp("zaunUrl") || "https://api.kata.ai"; - this.apiClient.basePath = basePath; - this.bearer = this.apiClient.authentications.Bearer; - const currentLogin = this.helper.getProp("current_login") || "user"; - const tokenObj = this.helper.getProp("token") || {}; - this.bearer.apiKey = `Bearer ${tokenObj[currentLogin]}`; - this.botApi = new this.zaun.BotApi(); - this.authApi = new this.zaun.AuthApi(); - this.userApi = new this.zaun.UserApi(); - this.teamApi = new this.zaun.TeamApi(); - this.deploymentApi = new this.zaun.DeploymentApi(); - this.projectApi = new zaun.ProjectApi(); - // this.draftApi = new this.zaun.DraftApi(); - // this.channelApi = new this.zaun.ChannelApi(); - // this.sessionApi = new this.zaun.SessionApi(); - // this.cachesApi = new this.zaun.CacheApi(); - // this.utilApi = new this.zaun.UtilApi(); - this.nluApi = new this.zaun.NluApi(); - } -} -exports.default = Api; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +class Api extends merapi_1.Component { + constructor(helper, zaun) { + super(); + this.helper = helper; + this.zaun = zaun; + this.apiClient = this.zaun.ApiClient.instance; + let basePath = this.helper.getProp("zaunUrl") || "https://api.kata.ai"; + this.apiClient.basePath = basePath; + this.bearer = this.apiClient.authentications.Bearer; + const currentLogin = this.helper.getProp("current_login") || "user"; + const tokenObj = this.helper.getProp("token") || {}; + this.bearer.apiKey = `Bearer ${tokenObj[currentLogin]}`; + this.botApi = new this.zaun.BotApi(); + this.authApi = new this.zaun.AuthApi(); + this.userApi = new this.zaun.UserApi(); + this.teamApi = new this.zaun.TeamApi(); + this.deploymentApi = new this.zaun.DeploymentApi(); + this.projectApi = new zaun.ProjectApi(); + // this.draftApi = new this.zaun.DraftApi(); + // this.channelApi = new this.zaun.ChannelApi(); + // this.sessionApi = new this.zaun.SessionApi(); + // this.cachesApi = new this.zaun.CacheApi(); + // this.utilApi = new this.zaun.UtilApi(); + this.nluApi = new this.zaun.NluApi(); + } +} +exports.default = Api; //# sourceMappingURL=api.js.map \ No newline at end of file diff --git a/lib/components/api/zaun.js b/lib/components/api/zaun.js index 1bf248b..90f1b29 100644 --- a/lib/components/api/zaun.js +++ b/lib/components/api/zaun.js @@ -1,7 +1,7 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function default_1() { - return require("zaun"); -} -exports.default = default_1; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function default_1() { + return require("zaun"); +} +exports.default = default_1; //# sourceMappingURL=zaun.js.map \ No newline at end of file diff --git a/lib/components/bots/bot.js b/lib/components/bots/bot.js index 84e64bd..6f4ab53 100644 --- a/lib/components/bots/bot.js +++ b/lib/components/bots/bot.js @@ -1,630 +1,630 @@ -"use strict"; -var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -}; -var __metadata = (this && this.__metadata) || function (k, v) { - if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -const uuid_1 = require("uuid"); -const helper_1 = require("../scripts/helper"); -const util_1 = require("util"); -const inquirer = require("inquirer"); -const Table = require("cli-table"); -const colors = require("colors"); -const repl = require("repl"); -const util = require("util"); -const os = require("os"); -const fs = require("fs"); -const deasync = require("deasync"); -class Bot extends merapi_1.Component { - constructor(compile, helper, tester, api) { - super(); - this.compile = compile; - this.helper = helper; - this.tester = tester; - this.api = api; - } - init(name, options) { - const botDesc = { - schema: "kata.ai/schema/kata-ml/1.0", - name, - desc: "My First Bot", - flows: { - hello: { - fallback: true, - intents: { - greeting: { - initial: true, - condition: "content == 'hi'" - }, - fallback: { - fallback: true - } - }, - states: { - init: { - initial: true, - transitions: { - greet: { - condition: "intent == \"greeting\"" - }, - other: { - fallback: true - } - } - }, - greet: { - end: true, - action: { - name: "text", - options: { - text: "hi!" - } - } - }, - other: { - end: true, - action: { - name: "text", - options: { - text: "sorry!" - } - } - } - } - } - } - }; - this.helper.dumpYaml("./bot.yml", botDesc); - console.log(`Initialized ${name} successfully`); - } - revisions(options) { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.getProject(); - const { data, response } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsGet, projectId); - const result = data; - if (result && result.data) { - console.log("Bot Revision : "); - result.data.forEach((hist) => { - console.log(`- ${hist.revision}`); - }); - } - else { - console.log("You must push at least 1 bot to acquire revisions"); - } - } - catch (e) { - if (e.code === "ENOENT") { - console.log("kata versions must be executed in bot directory with bot.yml"); - } - else { - console.log(this.helper.wrapError(e)); - } - } - }); - } - test(file, options) { - return __awaiter(this, void 0, void 0, function* () { - const testFiles = file ? [file] : this.helper.getFiles("./test", ".spec.yml"); - const botId = this.helper.getProjectId(); - if (!botId) { - throw new Error("BOT ID HAS NOT DEFINED"); - } - const results = {}; - for (let i = 0; i < testFiles.length; i++) { - const yaml = this.helper.loadYaml(testFiles[i]); - let res; - switch (yaml.schema) { - case "kata.ai/schema/kata-ml/1.0/test/intents": - res = yield this.tester.execIntentTest(yaml, this.api.botApi, botId, console.log); - if (this.hasErrors(res)) { - results[testFiles[i]] = res; - } - break; - case "kata.ai/schema/kata-ml/1.0/test/states": - res = yield this.tester.execStateTest(yaml, this.api.botApi, botId, console.log); - if (this.hasErrors(res)) { - results[testFiles[i]] = res; - } - break; - case "kata.ai/schema/kata-ml/1.0/test/actions": - res = yield this.tester.execActionsTest(yaml, this.api.botApi, botId, console.log); - if (this.hasErrors(res)) { - results[testFiles[i]] = res; - } - break; - case "kata.ai/schema/kata-ml/1.0/test/flow": - res = yield this.tester.execFlowTest(yaml, this.api.botApi, botId, console.log); - if (this.hasErrors(res)) { - results[testFiles[i]] = res; - } - break; - } - } - this.printResult(results); - }); - } - hasErrors(res) { - return Object.keys(res).some((key) => (res[key] && res[key].length) || res[key] === null); - } - printResult(results = {}) { - if (Object.keys(results).length) { - console.log(colors.red("Errors:")); - for (const i in results) { - console.log(` ${i}:`); - for (const j in results[i]) { - if (!results[i][j]) { - console.log(` ${colors.red(j + ":")}`); - console.log(` diaenne returns ${colors.red("null")}`); - continue; - } - if (results[i][j].length) { - console.log(` ${colors.red(j + ":")}`); - results[i][j].forEach((res) => { - console.log(` expecting ${res.field} to be ${colors.green(res.expect)} but got ${colors.red(res.result)}`); - }); - } - } - } - } - } - push(options) { - return __awaiter(this, void 0, void 0, function* () { - const desc = this.helper.loadYaml("./bot.yml"); - desc.tag = options.tag || null; - let bot = merapi_1.Config.create(desc, { left: "${", right: "}" }); - bot = this.compile.execDirectives(bot, process.cwd()); - bot.resolve(); - const botDesc = bot.get(); - botDesc.name = botDesc.name || "bot"; - if (options.draft) { - yield this.updateDraft(botDesc, desc); - return; - } - const projectId = this.getProject(); - botDesc.id = projectId; - let latestBotRevision; - try { - const { response: { body: data } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdBotGet, botDesc.id); - if (data.revision) { - latestBotRevision = data.revision; - const { data: newBot } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsRevisionPut, projectId, latestBotRevision, botDesc); - const { data: project } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdGet, projectId); - console.log(`Updated bot ${colors.green(project.name)} with revision: ${newBot.revision.substring(0, 7)}`); - } - else { - throw Error("Could not find latest bot revision from this project."); - } - } - catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - this.helper.dumpYaml("./bot.yml", desc); - }); - } - discardDraft(botDesc, desc) { - return __awaiter(this, void 0, void 0, function* () { - try { - desc.tag = null; - yield this.helper.toPromise(this.api.draftApi, this.api.draftApi.botsBotIdDraftDelete, botDesc.id); - console.log("Draft discarded."); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - this.helper.dumpYaml("./bot.yml", desc); - }); - } - discard(options) { - return __awaiter(this, void 0, void 0, function* () { - const desc = this.helper.loadYaml("./bot.yml"); - let bot = merapi_1.Config.create(desc, { left: "${", right: "}" }); - bot = this.compile.execDirectives(bot, process.cwd()); - bot.resolve(); - const botDesc = bot.get(); - if (options.draft) { - yield this.discardDraft(botDesc, desc); - return; - } - return; - }); - } - updateDraft(botDesc, desc) { - return __awaiter(this, void 0, void 0, function* () { - botDesc.id = botDesc.id || uuid_1.v4(); - try { - yield this.helper.toPromise(this.api.draftApi, this.api.draftApi.botsBotIdDraftPost, botDesc.id, botDesc); - desc.tag = "draft"; - botDesc.tag = "draft"; - console.log("Draft updated."); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - this.helper.dumpYaml("./bot.yml", desc); - }); - } - delete(options) { - return __awaiter(this, void 0, void 0, function* () { - const answer = yield this.helper.inquirerPrompt([ - { - type: "confirm", - name: "confirmation", - message: "Are you sure to delete this bot?", - default: false - } - ]); - if (!answer.confirmation) { - return; - } - const botId = this.helper.getProjectId(); - try { - const { data } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.botsBotIdDelete, botId); - console.log("REMOVE BOT SUCCESSFULLY"); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - console(options) { - return __awaiter(this, void 0, void 0, function* () { - let projectId; - let botDesc; - try { - projectId = this.getProject(); - botDesc = this.helper.loadYaml("./bot.yml"); - } - catch (error) { - console.log(this.helper.wrapError(error)); - return; - } - const dataEnvironments = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet, projectId, null); - const environments = dataEnvironments.response.body.data; - const choicesEnvironment = environments.map((environment) => ({ name: environment.name, value: environment.name })); - choicesEnvironment.push({ name: 'No Environment', value: null }); - let { environment } = yield inquirer.prompt([ - { - type: "list", - name: "environment", - message: "Environment:", - choices: choicesEnvironment - } - ]); - const con = repl.start({ - prompt: botDesc.name + ">", - writer(obj) { - return util.inspect(obj, false, null, true); - } - }); - con.context.text = function text(str) { - let currentSession = this.getLocalSession(); - const message = { - type: "text", - content: str - }; - const body = { - environmentName: environment, - session: currentSession, - message - }; - if (!body.environmentName) - delete body.environmentName; - try { - return this.converse(projectId, body); - } - catch (e) { - return this.helper.wrapError(e); - } - }.bind(this); - con.context.button = function button(op, obj = {}) { - let currentSession = this.getLocalSession(); - obj.op = op; - const message = { - type: "data", - payload: obj - }; - const body = { - environmentName: environment, - session: currentSession, - message - }; - if (!body.environmentName) - delete body.environmentName; - try { - return this.converse(projectId, body); - } - catch (e) { - return this.helper.wrapError(e); - } - }.bind(this); - con.context.command = function command(command, obj = {}) { - let currentSession = this.getLocalSession(); - const message = { - type: "command", - content: command, - payload: obj - }; - const body = { - environmentName: environment, - session: currentSession, - message - }; - if (!body.environmentName) - delete body.environmentName; - try { - return this.converse(projectId, body); - } - catch (e) { - return this.helper.wrapError(e); - } - }.bind(this); - con.context.current = () => this.getLocalSession(); - con.context.clear = () => this.resetSession(); - con.context.clearCaches = function clearCaches(num = 20) { - try { - for (let i = 0; i < num; i++) { - this.sync(this.helper.toPromise(this.api.cachesApi, this.api.cachesApi.cachesDelete)); - } - } - catch (e) { - return this.helper.wrapError(e); - } - }.bind(this); - }); - } - sync(promise) { - if (promise && typeof promise.then === "function") { - let done = false; - let error = null; - let result; - promise.then((res) => { - if (res.data !== "") { - done = true; - result = res; - } - else { - error = new Error("Error found. Please check your bot."); - } - }).catch((e) => { - error = e; - }); - deasync.loopWhile(() => { - return !done && !error; - }); - if (error) { - throw error; - } - return result; - } - throw new Error("Sync only accept promises"); - } - pull(revision, options) { - return __awaiter(this, void 0, void 0, function* () { - let projectId; - let bots; - let botDesc; - try { - projectId = this.getProject(); - } - catch (e) { - console.log(this.helper.wrapError(e)); - return; - } - try { - const { response: { body } } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsGet, projectId); - bots = body.data; - } - catch (e) { - console.log("INVALID PROJECT"); - return; - } - try { - if (!revision) { - revision = bots[0].revision; - } - const { response: { body } } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsRevisionGet, projectId, revision); - botDesc = body; - } - catch (e) { - console.log("INVALID PROJECT REVISION"); - return; - } - // remove data - delete botDesc.id; - delete botDesc.revision; - delete botDesc.changelog; - for (const flow in botDesc.flows) { - if (botDesc.flows[flow]) { - for (const state in botDesc.flows[flow].states) { - if (botDesc.flows[flow].states[state]) { - delete botDesc.flows[flow].states[state].style; - } - } - } - } - console.log(`Pull bot revision ${revision.substring(0, 6)} to bot.yml`); - this.helper.dumpYaml("./bot.yml", botDesc); - return; - }); - } - getProject() { - const projectId = this.helper.getProp("projectId"); - if (!projectId || projectId === "") { - throw Error("Error : You must specify a Project first, execute kata list-project to list your projects."); - } - return projectId; - } - converse(projectId, body) { - const { data } = this.sync(this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotConversePost, projectId, body)); - const { session } = data; - this.setLocalSession(session); - return data; - } - setLocalSession(session) { - const jsonPath = `${os.homedir()}/.katasession`; - try { - if (session) { - fs.writeFileSync(jsonPath, JSON.stringify(session), "utf8"); - } - } - catch (error) { - console.log(this.helper.wrapError(`Error set local session : ${error.message}`)); - } - } - getLocalSession() { - const jsonPath = `${os.homedir()}/.katasession`; - if (fs.existsSync(jsonPath)) { - return JSON.parse(fs.readFileSync(jsonPath, "utf8")); - } - else { - // default session - return { - "channel_id": "console-channel", - "environment_id": "console-environment", - "states": {}, - "contexes": {}, - "history": [], - "current": null, - "meta": null, - "timestamp": Date.now(), - "data": {}, - "created_at": Date.now(), - "updated_at": Date.now(), - "session_start": Date.now(), - "session_id": "test~from~console", - "id": "test~from~console" - }; - } - } - resetSession() { - const jsonPath = `${os.homedir()}/.katasession`; - if (fs.existsSync(jsonPath)) { - fs.unlinkSync(jsonPath); - return true; - } - } - errors() { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const dataEnvironments = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet, projectId, null); - if (dataEnvironments && dataEnvironments.response && dataEnvironments.response.body && dataEnvironments.response.body.data && dataEnvironments.response.body.data.length > 0) { - const environments = dataEnvironments.response.body.data; - const choicesEnvironment = environments.map((environment) => ({ - name: environment.name, - value: environment.id - })); - let { environmentId } = yield inquirer.prompt([ - { - type: "list", - name: "environmentId", - message: "Environment:", - choices: choicesEnvironment - } - ]); - const dataChannels = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, projectId, environmentId, null); - const channels = dataChannels.response.body; - const choicesChannel = channels.map((channel) => ({ - name: channel.name, - value: channel.id - })); - let { channelId } = yield inquirer.prompt([ - { - type: "list", - name: "channelId", - message: "Channel:", - choices: choicesChannel - } - ]); - let { start, end, error } = yield inquirer.prompt([ - { - type: "text", - name: "start", - message: "Date Start (yyyy-mm-dd):" - }, - { - type: "text", - name: "end", - message: "Date End (yyyy-mm-dd):" - }, - { - type: "list", - name: "error", - message: "Error Group:", - choices: [ - { - name: "User Error", - value: { "group": 1000, "code": "1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100" } - }, - { - name: "System Error", - value: { "group": 4000, "code": "4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100" } - } - ] - }, - ]); - if (util_1.isDate(start) == false) { - start = new Date().setHours(0, 0, 0); - } - else { - start = new Date(start).setHours(0, 0, 0); - } - if (util_1.isDate(end) == false) { - end = new Date().setHours(23, 59, 59); - } - else { - end = new Date(end).setHours(23, 59, 59); - } - const errorGroup = error.group; - const errorCode = error.code; - const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdErrorsGet, projectId, environmentId, channelId, errorGroup, errorCode, new Date(start).toISOString(), new Date(end).toISOString()); - if (response && response.body && response.body.data) { - const table = new Table({ - head: ["Time", "Error Code", "Error Message"], - colWidths: [25, 15, 75] - }); - response.body.data.forEach((project) => { - table.push([project.timestamp, project.errorCode, project.errorMessage]); - }); - console.log(table.toString()); - } - } - else { - console.log("Failed to get Environment list"); - } - } - else { - console.log("Please select Project first"); - } - } - catch (e) { - console.error(this.helper.wrapError(e)); - } - }); - } -} -__decorate([ - helper_1.CatchError, - __metadata("design:type", Function), - __metadata("design:paramtypes", [Object]), - __metadata("design:returntype", Promise) -], Bot.prototype, "push", null); -exports.default = Bot; +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +const uuid_1 = require("uuid"); +const helper_1 = require("../scripts/helper"); +const util_1 = require("util"); +const inquirer = require("inquirer"); +const Table = require("cli-table"); +const colors = require("colors"); +const repl = require("repl"); +const util = require("util"); +const os = require("os"); +const fs = require("fs"); +const deasync = require("deasync"); +class Bot extends merapi_1.Component { + constructor(compile, helper, tester, api) { + super(); + this.compile = compile; + this.helper = helper; + this.tester = tester; + this.api = api; + } + init(name, options) { + const botDesc = { + schema: "kata.ai/schema/kata-ml/1.0", + name, + desc: "My First Bot", + flows: { + hello: { + fallback: true, + intents: { + greeting: { + initial: true, + condition: "content == 'hi'" + }, + fallback: { + fallback: true + } + }, + states: { + init: { + initial: true, + transitions: { + greet: { + condition: "intent == \"greeting\"" + }, + other: { + fallback: true + } + } + }, + greet: { + end: true, + action: { + name: "text", + options: { + text: "hi!" + } + } + }, + other: { + end: true, + action: { + name: "text", + options: { + text: "sorry!" + } + } + } + } + } + } + }; + this.helper.dumpYaml("./bot.yml", botDesc); + console.log(`Initialized ${name} successfully`); + } + revisions(options) { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.getProject(); + const { data, response } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsGet, projectId); + const result = data; + if (result && result.data) { + console.log("Bot Revision : "); + result.data.forEach((hist) => { + console.log(`- ${hist.revision}`); + }); + } + else { + console.log("You must push at least 1 bot to acquire revisions"); + } + } + catch (e) { + if (e.code === "ENOENT") { + console.log("kata versions must be executed in bot directory with bot.yml"); + } + else { + console.log(this.helper.wrapError(e)); + } + } + }); + } + test(file, options) { + return __awaiter(this, void 0, void 0, function* () { + const testFiles = file ? [file] : this.helper.getFiles("./test", ".spec.yml"); + const botId = this.helper.getProjectId(); + if (!botId) { + throw new Error("BOT ID HAS NOT DEFINED"); + } + const results = {}; + for (let i = 0; i < testFiles.length; i++) { + const yaml = this.helper.loadYaml(testFiles[i]); + let res; + switch (yaml.schema) { + case "kata.ai/schema/kata-ml/1.0/test/intents": + res = yield this.tester.execIntentTest(yaml, this.api.botApi, botId, console.log); + if (this.hasErrors(res)) { + results[testFiles[i]] = res; + } + break; + case "kata.ai/schema/kata-ml/1.0/test/states": + res = yield this.tester.execStateTest(yaml, this.api.botApi, botId, console.log); + if (this.hasErrors(res)) { + results[testFiles[i]] = res; + } + break; + case "kata.ai/schema/kata-ml/1.0/test/actions": + res = yield this.tester.execActionsTest(yaml, this.api.botApi, botId, console.log); + if (this.hasErrors(res)) { + results[testFiles[i]] = res; + } + break; + case "kata.ai/schema/kata-ml/1.0/test/flow": + res = yield this.tester.execFlowTest(yaml, this.api.botApi, botId, console.log); + if (this.hasErrors(res)) { + results[testFiles[i]] = res; + } + break; + } + } + this.printResult(results); + }); + } + hasErrors(res) { + return Object.keys(res).some((key) => (res[key] && res[key].length) || res[key] === null); + } + printResult(results = {}) { + if (Object.keys(results).length) { + console.log(colors.red("Errors:")); + for (const i in results) { + console.log(` ${i}:`); + for (const j in results[i]) { + if (!results[i][j]) { + console.log(` ${colors.red(j + ":")}`); + console.log(` diaenne returns ${colors.red("null")}`); + continue; + } + if (results[i][j].length) { + console.log(` ${colors.red(j + ":")}`); + results[i][j].forEach((res) => { + console.log(` expecting ${res.field} to be ${colors.green(res.expect)} but got ${colors.red(res.result)}`); + }); + } + } + } + } + } + push(options) { + return __awaiter(this, void 0, void 0, function* () { + const desc = this.helper.loadYaml("./bot.yml"); + desc.tag = options.tag || null; + let bot = merapi_1.Config.create(desc, { left: "${", right: "}" }); + bot = this.compile.execDirectives(bot, process.cwd()); + bot.resolve(); + const botDesc = bot.get(); + botDesc.name = botDesc.name || "bot"; + if (options.draft) { + yield this.updateDraft(botDesc, desc); + return; + } + const projectId = this.getProject(); + botDesc.id = projectId; + let latestBotRevision; + try { + const { response: { body: data } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdBotGet, botDesc.id); + if (data.revision) { + latestBotRevision = data.revision; + const { data: newBot } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsRevisionPut, projectId, latestBotRevision, botDesc); + const { data: project } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdGet, projectId); + console.log(`Updated bot ${colors.green(project.name)} with revision: ${newBot.revision.substring(0, 7)}`); + } + else { + throw Error("Could not find latest bot revision from this project."); + } + } + catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + this.helper.dumpYaml("./bot.yml", desc); + }); + } + discardDraft(botDesc, desc) { + return __awaiter(this, void 0, void 0, function* () { + try { + desc.tag = null; + yield this.helper.toPromise(this.api.draftApi, this.api.draftApi.botsBotIdDraftDelete, botDesc.id); + console.log("Draft discarded."); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + this.helper.dumpYaml("./bot.yml", desc); + }); + } + discard(options) { + return __awaiter(this, void 0, void 0, function* () { + const desc = this.helper.loadYaml("./bot.yml"); + let bot = merapi_1.Config.create(desc, { left: "${", right: "}" }); + bot = this.compile.execDirectives(bot, process.cwd()); + bot.resolve(); + const botDesc = bot.get(); + if (options.draft) { + yield this.discardDraft(botDesc, desc); + return; + } + return; + }); + } + updateDraft(botDesc, desc) { + return __awaiter(this, void 0, void 0, function* () { + botDesc.id = botDesc.id || uuid_1.v4(); + try { + yield this.helper.toPromise(this.api.draftApi, this.api.draftApi.botsBotIdDraftPost, botDesc.id, botDesc); + desc.tag = "draft"; + botDesc.tag = "draft"; + console.log("Draft updated."); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + this.helper.dumpYaml("./bot.yml", desc); + }); + } + delete(options) { + return __awaiter(this, void 0, void 0, function* () { + const answer = yield this.helper.inquirerPrompt([ + { + type: "confirm", + name: "confirmation", + message: "Are you sure to delete this bot?", + default: false + } + ]); + if (!answer.confirmation) { + return; + } + const botId = this.helper.getProjectId(); + try { + const { data } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.botsBotIdDelete, botId); + console.log("REMOVE BOT SUCCESSFULLY"); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + console(options) { + return __awaiter(this, void 0, void 0, function* () { + let projectId; + let botDesc; + try { + projectId = this.getProject(); + botDesc = this.helper.loadYaml("./bot.yml"); + } + catch (error) { + console.log(this.helper.wrapError(error)); + return; + } + const dataEnvironments = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet, projectId, null); + const environments = dataEnvironments.response.body.data; + const choicesEnvironment = environments.map((environment) => ({ name: environment.name, value: environment.name })); + choicesEnvironment.push({ name: 'No Environment', value: null }); + let { environment } = yield inquirer.prompt([ + { + type: "list", + name: "environment", + message: "Environment:", + choices: choicesEnvironment + } + ]); + const con = repl.start({ + prompt: botDesc.name + ">", + writer(obj) { + return util.inspect(obj, false, null, true); + } + }); + con.context.text = function text(str) { + let currentSession = this.getLocalSession(); + const message = { + type: "text", + content: str + }; + const body = { + environmentName: environment, + session: currentSession, + message + }; + if (!body.environmentName) + delete body.environmentName; + try { + return this.converse(projectId, body); + } + catch (e) { + return this.helper.wrapError(e); + } + }.bind(this); + con.context.button = function button(op, obj = {}) { + let currentSession = this.getLocalSession(); + obj.op = op; + const message = { + type: "data", + payload: obj + }; + const body = { + environmentName: environment, + session: currentSession, + message + }; + if (!body.environmentName) + delete body.environmentName; + try { + return this.converse(projectId, body); + } + catch (e) { + return this.helper.wrapError(e); + } + }.bind(this); + con.context.command = function command(command, obj = {}) { + let currentSession = this.getLocalSession(); + const message = { + type: "command", + content: command, + payload: obj + }; + const body = { + environmentName: environment, + session: currentSession, + message + }; + if (!body.environmentName) + delete body.environmentName; + try { + return this.converse(projectId, body); + } + catch (e) { + return this.helper.wrapError(e); + } + }.bind(this); + con.context.current = () => this.getLocalSession(); + con.context.clear = () => this.resetSession(); + con.context.clearCaches = function clearCaches(num = 20) { + try { + for (let i = 0; i < num; i++) { + this.sync(this.helper.toPromise(this.api.cachesApi, this.api.cachesApi.cachesDelete)); + } + } + catch (e) { + return this.helper.wrapError(e); + } + }.bind(this); + }); + } + sync(promise) { + if (promise && typeof promise.then === "function") { + let done = false; + let error = null; + let result; + promise.then((res) => { + if (res.data !== "") { + done = true; + result = res; + } + else { + error = new Error("Error found. Please check your bot."); + } + }).catch((e) => { + error = e; + }); + deasync.loopWhile(() => { + return !done && !error; + }); + if (error) { + throw error; + } + return result; + } + throw new Error("Sync only accept promises"); + } + pull(revision, options) { + return __awaiter(this, void 0, void 0, function* () { + let projectId; + let bots; + let botDesc; + try { + projectId = this.getProject(); + } + catch (e) { + console.log(this.helper.wrapError(e)); + return; + } + try { + const { response: { body } } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsGet, projectId); + bots = body.data; + } + catch (e) { + console.log("INVALID PROJECT"); + return; + } + try { + if (!revision) { + revision = bots[0].revision; + } + const { response: { body } } = yield this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotRevisionsRevisionGet, projectId, revision); + botDesc = body; + } + catch (e) { + console.log("INVALID PROJECT REVISION"); + return; + } + // remove data + delete botDesc.id; + delete botDesc.revision; + delete botDesc.changelog; + for (const flow in botDesc.flows) { + if (botDesc.flows[flow]) { + for (const state in botDesc.flows[flow].states) { + if (botDesc.flows[flow].states[state]) { + delete botDesc.flows[flow].states[state].style; + } + } + } + } + console.log(`Pull bot revision ${revision.substring(0, 6)} to bot.yml`); + this.helper.dumpYaml("./bot.yml", botDesc); + return; + }); + } + getProject() { + const projectId = this.helper.getProp("projectId"); + if (!projectId || projectId === "") { + throw Error("Error : You must specify a Project first, execute kata list-project to list your projects."); + } + return projectId; + } + converse(projectId, body) { + const { data } = this.sync(this.helper.toPromise(this.api.botApi, this.api.botApi.projectsProjectIdBotConversePost, projectId, body)); + const { session } = data; + this.setLocalSession(session); + return data; + } + setLocalSession(session) { + const jsonPath = `${os.homedir()}/.katasession`; + try { + if (session) { + fs.writeFileSync(jsonPath, JSON.stringify(session), "utf8"); + } + } + catch (error) { + console.log(this.helper.wrapError(`Error set local session : ${error.message}`)); + } + } + getLocalSession() { + const jsonPath = `${os.homedir()}/.katasession`; + if (fs.existsSync(jsonPath)) { + return JSON.parse(fs.readFileSync(jsonPath, "utf8")); + } + else { + // default session + return { + "channel_id": "console-channel", + "environment_id": "console-environment", + "states": {}, + "contexes": {}, + "history": [], + "current": null, + "meta": null, + "timestamp": Date.now(), + "data": {}, + "created_at": Date.now(), + "updated_at": Date.now(), + "session_start": Date.now(), + "session_id": "test~from~console", + "id": "test~from~console" + }; + } + } + resetSession() { + const jsonPath = `${os.homedir()}/.katasession`; + if (fs.existsSync(jsonPath)) { + fs.unlinkSync(jsonPath); + return true; + } + } + errors() { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const dataEnvironments = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet, projectId, null); + if (dataEnvironments && dataEnvironments.response && dataEnvironments.response.body && dataEnvironments.response.body.data && dataEnvironments.response.body.data.length > 0) { + const environments = dataEnvironments.response.body.data; + const choicesEnvironment = environments.map((environment) => ({ + name: environment.name, + value: environment.id + })); + let { environmentId } = yield inquirer.prompt([ + { + type: "list", + name: "environmentId", + message: "Environment:", + choices: choicesEnvironment + } + ]); + const dataChannels = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, projectId, environmentId, null); + const channels = dataChannels.response.body; + const choicesChannel = channels.map((channel) => ({ + name: channel.name, + value: channel.id + })); + let { channelId } = yield inquirer.prompt([ + { + type: "list", + name: "channelId", + message: "Channel:", + choices: choicesChannel + } + ]); + let { start, end, error } = yield inquirer.prompt([ + { + type: "text", + name: "start", + message: "Date Start (yyyy-mm-dd):" + }, + { + type: "text", + name: "end", + message: "Date End (yyyy-mm-dd):" + }, + { + type: "list", + name: "error", + message: "Error Group:", + choices: [ + { + name: "User Error", + value: { "group": 1000, "code": "1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100" } + }, + { + name: "System Error", + value: { "group": 4000, "code": "4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100" } + } + ] + }, + ]); + if (util_1.isDate(start) == false) { + start = new Date().setHours(0, 0, 0); + } + else { + start = new Date(start).setHours(0, 0, 0); + } + if (util_1.isDate(end) == false) { + end = new Date().setHours(23, 59, 59); + } + else { + end = new Date(end).setHours(23, 59, 59); + } + const errorGroup = error.group; + const errorCode = error.code; + const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdErrorsGet, projectId, environmentId, channelId, errorGroup, errorCode, new Date(start).toISOString(), new Date(end).toISOString()); + if (response && response.body && response.body.data) { + const table = new Table({ + head: ["Time", "Error Code", "Error Message"], + colWidths: [25, 15, 75] + }); + response.body.data.forEach((project) => { + table.push([project.timestamp, project.errorCode, project.errorMessage]); + }); + console.log(table.toString()); + } + } + else { + console.log("Failed to get Environment list"); + } + } + else { + console.log("Please select Project first"); + } + } + catch (e) { + console.error(this.helper.wrapError(e)); + } + }); + } +} +__decorate([ + helper_1.CatchError, + __metadata("design:type", Function), + __metadata("design:paramtypes", [Object]), + __metadata("design:returntype", Promise) +], Bot.prototype, "push", null); +exports.default = Bot; //# sourceMappingURL=bot.js.map \ No newline at end of file diff --git a/lib/components/bots/channel.js b/lib/components/bots/channel.js index 4afeaae..4345cdc 100644 --- a/lib/components/bots/channel.js +++ b/lib/components/bots/channel.js @@ -1,264 +1,264 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const inquirer = require("inquirer"); -const Table = require("cli-table"); -class Channel { - constructor(helper, api, config, environment) { - this.helper = helper; - this.api = api; - this.config = config; - this.environment = environment; - } - addChannel(channelName, options) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - const environmentId = yield this.environment.askEnvironmentId(); - try { - const { response: { body: channelsBody } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, projectId, environmentId, {}); - const channels = channelsBody; - const channelWithSameName = channels.find((row) => row.name === channelName); - if (channelWithSameName) { - throw new Error("CHANNEL NAME HAS BEEN USED"); - } - if (!options.data) { - options.data = "{}"; - } - let channelData = JSON.parse(options.data); - channelData.name = channelName; - channelData = yield this.inquireChannelData(channelData); - const result = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsPost, projectId, environmentId, channelData); - console.log(result.response.body); - const channel = result.response.body; - console.log("CHANNEL ADDED SUCCESSFULLY"); - console.log(`Paste this url to ${channelData.type} webhook : ${channel.webhook}`); - if (channelData.type === "fbmessenger") { - const channelOptions = JSON.parse(channel.options); - console.log(`And also this token : ${channelOptions.challenge} to your FB Challenge token.`); - } - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - list() { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - const environmentId = yield this.environment.askEnvironmentId(); - try { - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, projectId, environmentId, {}); - if (!body) { - throw Error("Failed to list Channels for this environment."); - } - const table = new Table({ - head: ["Channel Name", "Channel Type", "Channel ID"], - colWidths: [30, 30, 42] - }); - body.forEach((channel) => { - table.push([channel.name, channel.type, channel.id]); - }); - console.log(table.toString()); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - removeChannel(channelName, options) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - const environmentId = yield this.environment.askEnvironmentId(); - try { - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdGet, environmentId, projectId); - const deployment = body; - const channels = deployment.channels; - const channel = channels.find((row) => row.name === channelName); - if (!channel) { - throw new Error("CHANNEL NOT FOUND"); - } - console.log(channel); - yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsChannelIdDelete, projectId, environmentId, channel.id); - console.log("CHANNEL REMOVED SUCCESSFULLY"); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - inquireChannelData(data) { - return __awaiter(this, void 0, void 0, function* () { - const { id, name, type, token, refreshToken, secret, url, additionalOptions } = data; - const channelType = this.config.default("config.channels.type", []); - const channelUrl = this.config.default("config.channels.url", []); - const answer = yield inquirer.prompt([ - { - type: "list", - name: "type", - message: `channel type : `, - choices: channelType, - when: () => !type, - validate: (type) => { - if (!type) { - return "Channel type cannot be empty"; - } - return true; - }, - filter: (type) => { - return type.toLowerCase(); - } - }, - { - type: "input", - name: "options.token", - message: "channel token: ", - when: () => !token, - filter(token) { - if (!token || token.length === 0) { - return null; - } - return token; - } - }, - { - type: "input", - name: "options.refreshToken", - message: "channel refresh token: ", - when: () => !refreshToken, - filter(refreshToken) { - if (!refreshToken || refreshToken.length === 0) { - return null; - } - return refreshToken; - } - }, - { - type: "input", - name: "options.secret", - message: "channel secret key: ", - when() { return !secret; }, - filter(secret) { - if (!secret || secret.length === 0) { - return null; - } - return secret; - } - }, - { - type: "input", - name: "additionalOptions", - message: "channel additional options: ", - when() { return !additionalOptions; }, - filter(additionalOptions) { - if (!additionalOptions || additionalOptions.length === 0) { - return null; - } - try { - const result = JSON.parse(additionalOptions); - if (typeof result === "object") { - return result; - } - else { - return { error: true }; - } - } - catch (error) { - return { error }; - } - }, - validate(additionalOptions) { - if (!additionalOptions) { - return true; - } - if (additionalOptions.error) { - return "Channel options must be a JSON Format"; - } - else { - return true; - } - } - }, - { - type: "input", - name: "url", - message(answer) { - if (answer.type !== "generic") { - return `channel api url (default: ${channelUrl[answer.type]}) :`; - } - return "channel api url : "; - }, - when() { return !url; }, - validate(url, answer) { - if (!url && answer.type === "generic") { - return "Channel api url cannot be empty"; - } - return true; - }, - default: (answer) => { - return channelUrl[answer.type]; - } - } - ]); - let options = { token, refreshToken, secret, }; - if (additionalOptions) { - options = Object.assign({}, options, additionalOptions); - } - const res = { id, name, type, options, url }; - try { - answer.options = Object.assign(answer.options, answer.additionalOptions); - answer.additionalOptions = undefined; - } - catch (error) { - // - } - return Object.assign({}, res, answer); - }); - } - updateChannel(channelName, options) { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.helper.getProjectId(); - if (!projectId) { - throw new Error("Please select project first"); - } - const environmentId = yield this.environment.askEnvironmentId(); - const { response: { body: channelsBody } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, projectId, environmentId, {}); - const channels = channelsBody; - if (channels.length == 0) { - throw new Error("Channel not found"); - } - const channelFound = channels.find((row) => row.name === channelName); - if (!channelFound) { - throw new Error("Channel not found"); - } - if (!options.data) { - options.data = "{}"; - } - let channelData = JSON.parse(options.data); - channelData.name = channelName; - channelData = yield this.inquireChannelData(channelData); - const result = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsChannelIdPut, projectId, environmentId, channelFound.id, channelData); - console.log(result.response.body); - const channel = result.response.body; - console.log("Channel added successfully"); - console.log(`Paste this url to ${channelData.type} webhook : ${channel.webhook}`); - if (channelData.type === "fbmessenger") { - const channelOptions = JSON.parse(channel.options); - console.log(`And also this token : ${channelOptions.challenge} to your FB Challenge token.`); - } - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } -} -exports.default = Channel; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const inquirer = require("inquirer"); +const Table = require("cli-table"); +class Channel { + constructor(helper, api, config, environment) { + this.helper = helper; + this.api = api; + this.config = config; + this.environment = environment; + } + addChannel(channelName, options) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + const environmentId = yield this.environment.askEnvironmentId(); + try { + const { response: { body: channelsBody } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, projectId, environmentId, {}); + const channels = channelsBody; + const channelWithSameName = channels.find((row) => row.name === channelName); + if (channelWithSameName) { + throw new Error("CHANNEL NAME HAS BEEN USED"); + } + if (!options.data) { + options.data = "{}"; + } + let channelData = JSON.parse(options.data); + channelData.name = channelName; + channelData = yield this.inquireChannelData(channelData); + const result = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsPost, projectId, environmentId, channelData); + console.log(result.response.body); + const channel = result.response.body; + console.log("CHANNEL ADDED SUCCESSFULLY"); + console.log(`Paste this url to ${channelData.type} webhook : ${channel.webhook}`); + if (channelData.type === "fbmessenger") { + const channelOptions = JSON.parse(channel.options); + console.log(`And also this token : ${channelOptions.challenge} to your FB Challenge token.`); + } + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + list() { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + const environmentId = yield this.environment.askEnvironmentId(); + try { + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, projectId, environmentId, {}); + if (!body) { + throw Error("Failed to list Channels for this environment."); + } + const table = new Table({ + head: ["Channel Name", "Channel Type", "Channel ID"], + colWidths: [30, 30, 42] + }); + body.forEach((channel) => { + table.push([channel.name, channel.type, channel.id]); + }); + console.log(table.toString()); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + removeChannel(channelName, options) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + const environmentId = yield this.environment.askEnvironmentId(); + try { + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdGet, environmentId, projectId); + const deployment = body; + const channels = deployment.channels; + const channel = channels.find((row) => row.name === channelName); + if (!channel) { + throw new Error("CHANNEL NOT FOUND"); + } + console.log(channel); + yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsChannelIdDelete, projectId, environmentId, channel.id); + console.log("CHANNEL REMOVED SUCCESSFULLY"); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + inquireChannelData(data) { + return __awaiter(this, void 0, void 0, function* () { + const { id, name, type, token, refreshToken, secret, url, additionalOptions } = data; + const channelType = this.config.default("config.channels.type", []); + const channelUrl = this.config.default("config.channels.url", []); + const answer = yield inquirer.prompt([ + { + type: "list", + name: "type", + message: `channel type : `, + choices: channelType, + when: () => !type, + validate: (type) => { + if (!type) { + return "Channel type cannot be empty"; + } + return true; + }, + filter: (type) => { + return type.toLowerCase(); + } + }, + { + type: "input", + name: "options.token", + message: "channel token: ", + when: () => !token, + filter(token) { + if (!token || token.length === 0) { + return null; + } + return token; + } + }, + { + type: "input", + name: "options.refreshToken", + message: "channel refresh token: ", + when: () => !refreshToken, + filter(refreshToken) { + if (!refreshToken || refreshToken.length === 0) { + return null; + } + return refreshToken; + } + }, + { + type: "input", + name: "options.secret", + message: "channel secret key: ", + when() { return !secret; }, + filter(secret) { + if (!secret || secret.length === 0) { + return null; + } + return secret; + } + }, + { + type: "input", + name: "additionalOptions", + message: "channel additional options: ", + when() { return !additionalOptions; }, + filter(additionalOptions) { + if (!additionalOptions || additionalOptions.length === 0) { + return null; + } + try { + const result = JSON.parse(additionalOptions); + if (typeof result === "object") { + return result; + } + else { + return { error: true }; + } + } + catch (error) { + return { error }; + } + }, + validate(additionalOptions) { + if (!additionalOptions) { + return true; + } + if (additionalOptions.error) { + return "Channel options must be a JSON Format"; + } + else { + return true; + } + } + }, + { + type: "input", + name: "url", + message(answer) { + if (answer.type !== "generic") { + return `channel api url (default: ${channelUrl[answer.type]}) :`; + } + return "channel api url : "; + }, + when() { return !url; }, + validate(url, answer) { + if (!url && answer.type === "generic") { + return "Channel api url cannot be empty"; + } + return true; + }, + default: (answer) => { + return channelUrl[answer.type]; + } + } + ]); + let options = { token, refreshToken, secret, }; + if (additionalOptions) { + options = Object.assign({}, options, additionalOptions); + } + const res = { id, name, type, options, url }; + try { + answer.options = Object.assign(answer.options, answer.additionalOptions); + answer.additionalOptions = undefined; + } + catch (error) { + // + } + return Object.assign({}, res, answer); + }); + } + updateChannel(channelName, options) { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.helper.getProjectId(); + if (!projectId) { + throw new Error("Please select project first"); + } + const environmentId = yield this.environment.askEnvironmentId(); + const { response: { body: channelsBody } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsGet, projectId, environmentId, {}); + const channels = channelsBody; + if (channels.length == 0) { + throw new Error("Channel not found"); + } + const channelFound = channels.find((row) => row.name === channelName); + if (!channelFound) { + throw new Error("Channel not found"); + } + if (!options.data) { + options.data = "{}"; + } + let channelData = JSON.parse(options.data); + channelData.name = channelName; + channelData = yield this.inquireChannelData(channelData); + const result = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdChannelsChannelIdPut, projectId, environmentId, channelFound.id, channelData); + console.log(result.response.body); + const channel = result.response.body; + console.log("Channel added successfully"); + console.log(`Paste this url to ${channelData.type} webhook : ${channel.webhook}`); + if (channelData.type === "fbmessenger") { + const channelOptions = JSON.parse(channel.options); + console.log(`And also this token : ${channelOptions.challenge} to your FB Challenge token.`); + } + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } +} +exports.default = Channel; //# sourceMappingURL=channel.js.map \ No newline at end of file diff --git a/lib/components/bots/deployment.js b/lib/components/bots/deployment.js index df7c194..0e7bfeb 100644 --- a/lib/components/bots/deployment.js +++ b/lib/components/bots/deployment.js @@ -1,169 +1,169 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const Table = require("cli-table"); -const inquirer = require("inquirer"); -class Deployment { - constructor(helper, api) { - this.helper = helper; - this.api = api; - } - create(versionType) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - const { response: { body: project } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdGet, projectId); - // TODO: {page:1, limit:1} - let botRevision; - let nluRevision; - let cmsRevision; - try { - const { response: { body: data } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdBotGet, projectId); - if (data.revision) { - botRevision = data.revision; - } - } - catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - try { - const { response: { body: data } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluRevisionsGet, projectId); - if (data.data[0] && data.data[0].revision) { - nluRevision = data.data[0].revision; - } - } - catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - try { - const { response: { body: data } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdCmsGet, projectId); - if (data.revision) { - cmsRevision = data.revision; - } - } - catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - let targetVersion; - try { - // get previous deployment version - const { response: { body: latestDeployment } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdDeploymentGet, projectId); - const prevVersion = latestDeployment.version; - let [major, minor, patch] = prevVersion.split("."); - if (versionType === "major") { - major = Number(major) + 1; - minor = 0; - patch = 0; - } - else if (versionType === "minor") { - minor = Number(minor) + 1; - patch = 0; - } - else { - patch = Number(patch) + 1; - } - targetVersion = `${major}.${minor}.${patch}`; - } - catch (e) { - targetVersion = "0.0.1"; - } - try { - const postBody = { - version: targetVersion, - botRevision, - nluRevision, - cmsRevision, - modules: null, - }; - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsPost, postBody, projectId); - console.log(`Bot Revision: ${botRevision.substring(0, 7)}`); - console.log(`NLU Revision: ${nluRevision.substring(0, 7)}`); - console.log(`CMS Revision: ${cmsRevision.substring(0, 7)}`); - console.log(`Succesfully create Deployment to version ${targetVersion}`); - } - catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - }); - } - list(options) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - try { - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, {}); - if (body && body.data) { - const table = new Table({ - head: ["Deployment Name", "Deployment Version", "Bot Revision"], - colWidths: [30, 30, 42] - }); - body.data.forEach((deployment) => { - table.push([deployment.name, deployment.version, deployment.botRevision]); - }); - console.log(table.toString()); - } - } - catch (e) { - console.error("Error"); - console.log(this.helper.wrapError(e)); - } - }); - } - rollback(version) { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.helper.getProjectId(); - const author = this.helper.getProp("current_login"); - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { limit: 1000000, page: 1 }); - if (body && body.data) { - const deployments = body.data; - const versionData = deployments.find((deployment) => deployment.version === version); - if (!versionData) { - throw new Error("Version not found"); - } - let { changelog, confirm } = yield inquirer.prompt([ - { - type: "text", - name: "changelog", - message: "Changelog:", - }, - { - type: "confirm", - name: "confirm", - message: `IMPORTANT: Existing NL training data will also be rolled back to version ${versionData.version}`, - default: true, - } - ]); - const requestBody = { - author, - changelog, - version: versionData.version - }; - if (confirm) { - const { response } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.deploymentsDeploymentIdRollbackPost, versionData.id, requestBody); - if (response && response.body) { - console.log(`Successfully rolled back to version ${versionData.version}`); - } - else { - console.log(`Error when trying to rollback to version ${versionData.version}`); - } - } - } - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } -} -exports.default = Deployment; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Table = require("cli-table"); +const inquirer = require("inquirer"); +class Deployment { + constructor(helper, api) { + this.helper = helper; + this.api = api; + } + create(versionType) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + const { response: { body: project } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdGet, projectId); + // TODO: {page:1, limit:1} + let botRevision; + let nluRevision; + let cmsRevision; + try { + const { response: { body: data } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdBotGet, projectId); + if (data.revision) { + botRevision = data.revision; + } + } + catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + try { + const { response: { body: data } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluRevisionsGet, projectId); + if (data.data[0] && data.data[0].revision) { + nluRevision = data.data[0].revision; + } + } + catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + try { + const { response: { body: data } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdCmsGet, projectId); + if (data.revision) { + cmsRevision = data.revision; + } + } + catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + let targetVersion; + try { + // get previous deployment version + const { response: { body: latestDeployment } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdDeploymentGet, projectId); + const prevVersion = latestDeployment.version; + let [major, minor, patch] = prevVersion.split("."); + if (versionType === "major") { + major = Number(major) + 1; + minor = 0; + patch = 0; + } + else if (versionType === "minor") { + minor = Number(minor) + 1; + patch = 0; + } + else { + patch = Number(patch) + 1; + } + targetVersion = `${major}.${minor}.${patch}`; + } + catch (e) { + targetVersion = "0.0.1"; + } + try { + const postBody = { + version: targetVersion, + botRevision, + nluRevision, + cmsRevision, + modules: null, + }; + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsPost, postBody, projectId); + console.log(`Bot Revision: ${botRevision.substring(0, 7)}`); + console.log(`NLU Revision: ${nluRevision.substring(0, 7)}`); + console.log(`CMS Revision: ${cmsRevision.substring(0, 7)}`); + console.log(`Succesfully create Deployment to version ${targetVersion}`); + } + catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + }); + } + list(options) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + try { + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, {}); + if (body && body.data) { + const table = new Table({ + head: ["Deployment Name", "Deployment Version", "Bot Revision"], + colWidths: [30, 30, 42] + }); + body.data.forEach((deployment) => { + table.push([deployment.name, deployment.version, deployment.botRevision]); + }); + console.log(table.toString()); + } + } + catch (e) { + console.error("Error"); + console.log(this.helper.wrapError(e)); + } + }); + } + rollback(version) { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.helper.getProjectId(); + const author = this.helper.getProp("current_login"); + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { limit: 1000000, page: 1 }); + if (body && body.data) { + const deployments = body.data; + const versionData = deployments.find((deployment) => deployment.version === version); + if (!versionData) { + throw new Error("Version not found"); + } + let { changelog, confirm } = yield inquirer.prompt([ + { + type: "text", + name: "changelog", + message: "Changelog:", + }, + { + type: "confirm", + name: "confirm", + message: `IMPORTANT: Existing NL training data will also be rolled back to version ${versionData.version}`, + default: true, + } + ]); + const requestBody = { + author, + changelog, + version: versionData.version + }; + if (confirm) { + const { response } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.deploymentsDeploymentIdRollbackPost, versionData.id, requestBody); + if (response && response.body) { + console.log(`Successfully rolled back to version ${versionData.version}`); + } + else { + console.log(`Error when trying to rollback to version ${versionData.version}`); + } + } + } + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } +} +exports.default = Deployment; //# sourceMappingURL=deployment.js.map \ No newline at end of file diff --git a/lib/components/bots/environment.js b/lib/components/bots/environment.js index 6d3e4b1..482a6a2 100644 --- a/lib/components/bots/environment.js +++ b/lib/components/bots/environment.js @@ -1,180 +1,180 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const inquirer = require("inquirer"); -const Table = require("cli-table"); -class Environment { - constructor(helper, api) { - this.helper = helper; - this.api = api; - } - create(slug) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - if (slug.length > 20) { - console.error("error: Namespace length can not exceed 20 characters"); - return; - } - try { - const deployment = yield this.getLatestDeployment(); - if (!deployment) { - throw Error("Deployment not found"); - } - const name = yield this.askPredefinedEnvironmentName(); - const existEnvs = yield this.listEnvironment(); - for (const existEnv of existEnvs) { - if (existEnv.name.toLowerCase() === name.toLowerCase()) { - throw new Error("Can not create environment with same name. " + - "Please use command update-environment."); - } - } - const postBody = { - depId: projectId, - depVersion: deployment.version, - name, slug, - }; - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsPost, projectId, postBody); - console.log(body); - console.log("ENVIRONMENT CREATED SUCCESSFULLY"); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - list() { - return __awaiter(this, void 0, void 0, function* () { - try { - const environmentList = yield this.listEnvironment(); - const table = new Table({ - head: ["Environment Name", "Environment Slug", "Environment ID", "Deployment Version"], - colWidths: [30, 30, 42, 30] - }); - environmentList.forEach((environment) => { - table.push([environment.name, String(environment.slug), environment.id, environment.depVersion]); - }); - console.log(table.toString()); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - askDeploymentId(prop = {}) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - let page = 1; - while (true) { - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { - page - }); - const choices = body.data.map((row) => ({ name: `(${row.version})`, value: row.version })); - if (body.total > body.page * body.limit) { - choices.push({ name: "Load More", value: -1 }); - } - const { deploymentVersion } = yield inquirer.prompt([ - { - type: "list", - name: "deploymentVersion", - message: prop.message || "Select Deployment:", - paginated: false, - choices - }, - ]); - if (deploymentVersion === -1) { - page++; - continue; - } - return deploymentVersion; - } - }); - } - update(newDeploymentVersion) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - if (!newDeploymentVersion) { - newDeploymentVersion = yield this.askDeploymentId(); - } - if (!/[0-9]+\.[0-9]+\.[0-9]+/.test(newDeploymentVersion)) { - console.error("error: Deployment version must be in the format of <0-9>.<0-9>.<0-9>"); - return; - } - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { limit: 1000000 }); - if (!body.data.find((data) => data.version === newDeploymentVersion)) { - console.error(`error: There are no deployment with version ${newDeploymentVersion}`); - return; - } - try { - const environmentId = yield this.askEnvironmentId({ - message: "Select which Environment to update: " - }); - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdPut, environmentId, projectId, { depVersion: newDeploymentVersion }); - if (!body) { - throw Error("Error updating Environment"); - } - return console.log(body); - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - askEnvironmentId(prop = {}) { - return __awaiter(this, void 0, void 0, function* () { - const environmentList = yield this.listEnvironment(); - const choices = environmentList.map((row) => ({ name: `${row.name} (${row.depVersion})`, value: row.id })); - const { environmentId } = yield inquirer.prompt([ - { - type: "list", - name: "environmentId", - message: prop.message || "Select Environment:", - paginated: false, - choices - }, - ]); - return environmentId; - }); - } - askPredefinedEnvironmentName() { - return __awaiter(this, void 0, void 0, function* () { - const environmentNames = ["Development", "Production", "Staging"]; - const choices = environmentNames.map((name) => ({ name, value: name })); - const { environmentName } = yield inquirer.prompt([ - { - type: "list", - name: "environmentName", - message: "Which Environment to create?", - paginated: false, - choices - }, - ]); - return environmentName; - }); - } - getLatestDeployment() { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProjectId(); - const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdDeploymentGet, projectId); - return response && response.body; - }); - } - listEnvironment() { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProp("projectId"); - const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet, projectId, {}); - if (!body || !body.data) { - throw Error("Failed to list environments."); - } - return body.data; - }); - } -} -exports.default = Environment; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const inquirer = require("inquirer"); +const Table = require("cli-table"); +class Environment { + constructor(helper, api) { + this.helper = helper; + this.api = api; + } + create(slug) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + if (slug.length > 20) { + console.error("error: Namespace length can not exceed 20 characters"); + return; + } + try { + const deployment = yield this.getLatestDeployment(); + if (!deployment) { + throw Error("Deployment not found"); + } + const name = yield this.askPredefinedEnvironmentName(); + const existEnvs = yield this.listEnvironment(); + for (const existEnv of existEnvs) { + if (existEnv.name.toLowerCase() === name.toLowerCase()) { + throw new Error("Can not create environment with same name. " + + "Please use command update-environment."); + } + } + const postBody = { + depId: projectId, + depVersion: deployment.version, + name, slug, + }; + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsPost, projectId, postBody); + console.log(body); + console.log("ENVIRONMENT CREATED SUCCESSFULLY"); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + list() { + return __awaiter(this, void 0, void 0, function* () { + try { + const environmentList = yield this.listEnvironment(); + const table = new Table({ + head: ["Environment Name", "Environment Slug", "Environment ID", "Deployment Version"], + colWidths: [30, 30, 42, 30] + }); + environmentList.forEach((environment) => { + table.push([environment.name, String(environment.slug), environment.id, environment.depVersion]); + }); + console.log(table.toString()); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + askDeploymentId(prop = {}) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + let page = 1; + while (true) { + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { + page + }); + const choices = body.data.map((row) => ({ name: `(${row.version})`, value: row.version })); + if (body.total > body.page * body.limit) { + choices.push({ name: "Load More", value: -1 }); + } + const { deploymentVersion } = yield inquirer.prompt([ + { + type: "list", + name: "deploymentVersion", + message: prop.message || "Select Deployment:", + paginated: false, + choices + }, + ]); + if (deploymentVersion === -1) { + page++; + continue; + } + return deploymentVersion; + } + }); + } + update(newDeploymentVersion) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + if (!newDeploymentVersion) { + newDeploymentVersion = yield this.askDeploymentId(); + } + if (!/[0-9]+\.[0-9]+\.[0-9]+/.test(newDeploymentVersion)) { + console.error("error: Deployment version must be in the format of <0-9>.<0-9>.<0-9>"); + return; + } + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdDeploymentVersionsGet, projectId, { limit: 1000000 }); + if (!body.data.find((data) => data.version === newDeploymentVersion)) { + console.error(`error: There are no deployment with version ${newDeploymentVersion}`); + return; + } + try { + const environmentId = yield this.askEnvironmentId({ + message: "Select which Environment to update: " + }); + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsEnvironmentIdPut, environmentId, projectId, { depVersion: newDeploymentVersion }); + if (!body) { + throw Error("Error updating Environment"); + } + return console.log(body); + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + askEnvironmentId(prop = {}) { + return __awaiter(this, void 0, void 0, function* () { + const environmentList = yield this.listEnvironment(); + const choices = environmentList.map((row) => ({ name: `${row.name} (${row.depVersion})`, value: row.id })); + const { environmentId } = yield inquirer.prompt([ + { + type: "list", + name: "environmentId", + message: prop.message || "Select Environment:", + paginated: false, + choices + }, + ]); + return environmentId; + }); + } + askPredefinedEnvironmentName() { + return __awaiter(this, void 0, void 0, function* () { + const environmentNames = ["Development", "Production", "Staging"]; + const choices = environmentNames.map((name) => ({ name, value: name })); + const { environmentName } = yield inquirer.prompt([ + { + type: "list", + name: "environmentName", + message: "Which Environment to create?", + paginated: false, + choices + }, + ]); + return environmentName; + }); + } + getLatestDeployment() { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProjectId(); + const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdDeploymentGet, projectId); + return response && response.body; + }); + } + listEnvironment() { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProp("projectId"); + const { response: { body } } = yield this.helper.toPromise(this.api.deploymentApi, this.api.deploymentApi.projectsProjectIdEnvironmentsGet, projectId, {}); + if (!body || !body.data) { + throw Error("Failed to list environments."); + } + return body.data; + }); + } +} +exports.default = Environment; //# sourceMappingURL=environment.js.map \ No newline at end of file diff --git a/lib/components/bots/session.js b/lib/components/bots/session.js index 306cb87..3788f62 100644 --- a/lib/components/bots/session.js +++ b/lib/components/bots/session.js @@ -1,102 +1,102 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -class Session extends merapi_1.Component { - constructor(helper, api) { - super(); - this.helper = helper; - this.api = api; - this.defaultDeploymentId = "f223c9e0-6ba1-434d-8313-a9f18ca364bd"; - } - get(id, deploymentId, options) { - return __awaiter(this, void 0, void 0, function* () { - const botId = this.helper.getBotId(); - try { - deploymentId = deploymentId || this.defaultDeploymentId; - const { data } = yield this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdGet, botId, deploymentId, id, ""); - console.dir(data, { depth: null }); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - create(id, deploymentId, options) { - return __awaiter(this, void 0, void 0, function* () { - const botId = this.helper.getBotId(); - try { - let session; - if (options.data) { - session = JSON.parse(options.data); - } - else if (options.file) { - session = this.helper.loadYamlOrJsonFile(options.file); - } - if (id && !session.id) { - session.id = id; - } - deploymentId = deploymentId || this.defaultDeploymentId; - const { data } = yield this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsPost, botId, deploymentId, session); - console.log(data); - console.log("Session created successfully"); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - update(id, deploymentId, options) { - return __awaiter(this, void 0, void 0, function* () { - const botId = this.helper.getBotId(); - try { - let session; - if (options.data) { - session = JSON.parse(options.data); - } - else if (options.file) { - session = this.helper.loadYamlOrJsonFile(options.file); - } - if (!session.id) { - session.id = id; - } - deploymentId = deploymentId || this.defaultDeploymentId; - const { data } = yield this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdPut, botId, deploymentId, id, session); - console.log(data); - console.log("Session updated successfully"); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - delete(id, deploymentId, options) { - return __awaiter(this, void 0, void 0, function* () { - const botId = this.helper.getBotId(); - try { - deploymentId = deploymentId || this.defaultDeploymentId; - const { data } = yield this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdDelete, botId, deploymentId, id); - console.dir(data, { depth: null }); - console.log("Session deleted successfully"); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - timestamp() { - return __awaiter(this, void 0, void 0, function* () { - const { response } = yield this.helper.toPromise(this.api.utilApi, this.api.utilApi.timestampGet); - console.log(`Current server timestamp: ${response.text}`); - }); - } -} -exports.default = Session; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +class Session extends merapi_1.Component { + constructor(helper, api) { + super(); + this.helper = helper; + this.api = api; + this.defaultDeploymentId = "f223c9e0-6ba1-434d-8313-a9f18ca364bd"; + } + get(id, deploymentId, options) { + return __awaiter(this, void 0, void 0, function* () { + const botId = this.helper.getBotId(); + try { + deploymentId = deploymentId || this.defaultDeploymentId; + const { data } = yield this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdGet, botId, deploymentId, id, ""); + console.dir(data, { depth: null }); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + create(id, deploymentId, options) { + return __awaiter(this, void 0, void 0, function* () { + const botId = this.helper.getBotId(); + try { + let session; + if (options.data) { + session = JSON.parse(options.data); + } + else if (options.file) { + session = this.helper.loadYamlOrJsonFile(options.file); + } + if (id && !session.id) { + session.id = id; + } + deploymentId = deploymentId || this.defaultDeploymentId; + const { data } = yield this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsPost, botId, deploymentId, session); + console.log(data); + console.log("Session created successfully"); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + update(id, deploymentId, options) { + return __awaiter(this, void 0, void 0, function* () { + const botId = this.helper.getBotId(); + try { + let session; + if (options.data) { + session = JSON.parse(options.data); + } + else if (options.file) { + session = this.helper.loadYamlOrJsonFile(options.file); + } + if (!session.id) { + session.id = id; + } + deploymentId = deploymentId || this.defaultDeploymentId; + const { data } = yield this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdPut, botId, deploymentId, id, session); + console.log(data); + console.log("Session updated successfully"); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + delete(id, deploymentId, options) { + return __awaiter(this, void 0, void 0, function* () { + const botId = this.helper.getBotId(); + try { + deploymentId = deploymentId || this.defaultDeploymentId; + const { data } = yield this.helper.toPromise(this.api.sessionApi, this.api.sessionApi.botsBotIdDeploymentsDeploymentIdSessionsSessionIdDelete, botId, deploymentId, id); + console.dir(data, { depth: null }); + console.log("Session deleted successfully"); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + timestamp() { + return __awaiter(this, void 0, void 0, function* () { + const { response } = yield this.helper.toPromise(this.api.utilApi, this.api.utilApi.timestampGet); + console.log(`Current server timestamp: ${response.text}`); + }); + } +} +exports.default = Session; //# sourceMappingURL=session.js.map \ No newline at end of file diff --git a/lib/components/deprecated/deprecated.js b/lib/components/deprecated/deprecated.js index c489aff..55f0196 100644 --- a/lib/components/deprecated/deprecated.js +++ b/lib/components/deprecated/deprecated.js @@ -1,19 +1,19 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -class Deprecated extends merapi_1.Component { - addChannel() { - console.log("This command is deprecated, please use create-channel"); - } - removeChannel() { - console.log("This command is deprecated, please use delete-channel"); - } - configView() { - console.log("This command is deprecated, please use view-config"); - } - addMember() { - console.log("This command is deprecated, please use invite-member"); - } -} -exports.default = Deprecated; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +class Deprecated extends merapi_1.Component { + addChannel() { + console.log("This command is deprecated, please use create-channel"); + } + removeChannel() { + console.log("This command is deprecated, please use delete-channel"); + } + configView() { + console.log("This command is deprecated, please use view-config"); + } + addMember() { + console.log("This command is deprecated, please use invite-member"); + } +} +exports.default = Deprecated; //# sourceMappingURL=deprecated.js.map \ No newline at end of file diff --git a/lib/components/main.js b/lib/components/main.js index 6e7ccce..0689545 100644 --- a/lib/components/main.js +++ b/lib/components/main.js @@ -1,120 +1,120 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -const commander = require("commander"); -class Main extends merapi_1.Component { - constructor(config, injector, helper) { - super(); - this.config = config; - this.injector = injector; - this.helper = helper; - } - start(argv) { - return __awaiter(this, void 0, void 0, function* () { - let commands = this.config.get("commands"); - commander.version(`Kata CLI version ${this.config.default("version", "1.0.0")}`); - yield this.compile(commands, commander); - commander.parse(argv); - const validCommands = commander.commands.map((x) => x.name()); - if (argv.length === 2 || validCommands.indexOf(argv[2]) === -1) { - commander.parse([argv[0], argv[1], '-h']); - } - this.sendNotificationTracking(); - this.sendDataAnalytics(argv); - this.saveCommandSession(argv); - }); - } - compile(commands, program, currKey = "") { - return __awaiter(this, void 0, void 0, function* () { - for (let key in commands) { - let command = commands[key]; - if (command.type === "group") { - yield this.compileGroup(`${currKey}${key}`, command, program); - } - else if (command.type === "alias") { - this.compileAlias(key, command, program); - } - else { - yield this.compileCommand(`${currKey}${key}`, command, program); - } - } - }); - } - compileGroup(key, command, program) { - return __awaiter(this, void 0, void 0, function* () { - yield this.compile(command.subcommands, program, `${key}-`); - }); - } - compileAlias(key, command, program) { - program.command(key).action((self) => { - let args = self._args; - commander.parse(command.alias.split(/\s+/).concat(args)); - }); - } - compileCommand(key, command, program) { - return __awaiter(this, void 0, void 0, function* () { - let subcommand; - let commandKey = command.alias ? command.alias : key; - if (command.args) { - subcommand = program.command(`${commandKey} ${command.args}`); - } - else { - subcommand = program.command(commandKey); - } - if (command.params) { - for (let i in command.params) { - let param = command.params[i]; - let flag = param.short ? `-${param.short}, --${i}` : `--${i}`; - if (param.value !== undefined) - subcommand.option(`${flag} `, param.desc || "", param.value); - else if (param.bool) - subcommand.option(flag, param.desc || ""); - else - subcommand.option(`${flag} [value]`, param.desc || ""); - } - } - subcommand.action(yield this.createAction(command.handler, command.middleware)); - }); - } - createAction(handler, middleware = []) { - return __awaiter(this, void 0, void 0, function* () { - let methods = []; - for (let i = 0; i < middleware.length; i++) { - methods.push(yield this.injector.resolveMethod(middleware[i])); - } - let handlerMethod = yield this.injector.resolveMethod(handler); - return (...args) => { - for (let i = 0; i < methods.length; i++) - args = methods[i](...args); - handlerMethod(...args); - }; - }); - } - sendDataAnalytics(argv) { - const command = Object.assign([], argv); - this.helper.sendGoogleAnalytics("track", argv[2], command.splice(2).join(" ")); - } - sendNotificationTracking() { - const status = this.helper.checkNotificationStatus(); - if (!status) { - console.log("\n[NOTICE]" + - "\nStarting from Kata CLI v2.1.0, " + - "we added analytics that tracks your CLI usage to improve user experience. " + - "Please contact support@kata.ai if you have any questions.\n"); - } - } - saveCommandSession(argv) { - const command = Object.assign([], argv); - this.helper.addCommandSession(command.splice(2).join(" ")); - } -} -exports.default = Main; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +const commander = require("commander"); +class Main extends merapi_1.Component { + constructor(config, injector, helper) { + super(); + this.config = config; + this.injector = injector; + this.helper = helper; + } + start(argv) { + return __awaiter(this, void 0, void 0, function* () { + let commands = this.config.get("commands"); + commander.version(`Kata CLI version ${this.config.default("version", "1.0.0")}`); + yield this.compile(commands, commander); + commander.parse(argv); + const validCommands = commander.commands.map((x) => x.name()); + if (argv.length === 2 || validCommands.indexOf(argv[2]) === -1) { + commander.parse([argv[0], argv[1], '-h']); + } + this.sendNotificationTracking(); + this.sendDataAnalytics(argv); + this.saveCommandSession(argv); + }); + } + compile(commands, program, currKey = "") { + return __awaiter(this, void 0, void 0, function* () { + for (let key in commands) { + let command = commands[key]; + if (command.type === "group") { + yield this.compileGroup(`${currKey}${key}`, command, program); + } + else if (command.type === "alias") { + this.compileAlias(key, command, program); + } + else { + yield this.compileCommand(`${currKey}${key}`, command, program); + } + } + }); + } + compileGroup(key, command, program) { + return __awaiter(this, void 0, void 0, function* () { + yield this.compile(command.subcommands, program, `${key}-`); + }); + } + compileAlias(key, command, program) { + program.command(key).action((self) => { + let args = self._args; + commander.parse(command.alias.split(/\s+/).concat(args)); + }); + } + compileCommand(key, command, program) { + return __awaiter(this, void 0, void 0, function* () { + let subcommand; + let commandKey = command.alias ? command.alias : key; + if (command.args) { + subcommand = program.command(`${commandKey} ${command.args}`); + } + else { + subcommand = program.command(commandKey); + } + if (command.params) { + for (let i in command.params) { + let param = command.params[i]; + let flag = param.short ? `-${param.short}, --${i}` : `--${i}`; + if (param.value !== undefined) + subcommand.option(`${flag} `, param.desc || "", param.value); + else if (param.bool) + subcommand.option(flag, param.desc || ""); + else + subcommand.option(`${flag} [value]`, param.desc || ""); + } + } + subcommand.action(yield this.createAction(command.handler, command.middleware)); + }); + } + createAction(handler, middleware = []) { + return __awaiter(this, void 0, void 0, function* () { + let methods = []; + for (let i = 0; i < middleware.length; i++) { + methods.push(yield this.injector.resolveMethod(middleware[i])); + } + let handlerMethod = yield this.injector.resolveMethod(handler); + return (...args) => { + for (let i = 0; i < methods.length; i++) + args = methods[i](...args); + handlerMethod(...args); + }; + }); + } + sendDataAnalytics(argv) { + const command = Object.assign([], argv); + this.helper.sendGoogleAnalytics("track", argv[2], command.splice(2).join(" ")); + } + sendNotificationTracking() { + const status = this.helper.checkNotificationStatus(); + if (!status) { + console.log("\n[NOTICE]" + + "\nStarting from Kata CLI v2.1.0, " + + "we added analytics that tracks your CLI usage to improve user experience. " + + "Please contact support@kata.ai if you have any questions.\n"); + } + } + saveCommandSession(argv) { + const command = Object.assign([], argv); + this.helper.addCommandSession(command.splice(2).join(" ")); + } +} +exports.default = Main; //# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/lib/components/nlus/nlu.js b/lib/components/nlus/nlu.js index 00874ad..046b65c 100644 --- a/lib/components/nlus/nlu.js +++ b/lib/components/nlus/nlu.js @@ -1,568 +1,568 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -const Table = require("cli-table"); -const fs = require("fs"); -const yaml = require("js-yaml"); -const template = { - default: { - name: "kata", - lang: "id", - entities: { - location: { - type: "phrase", - profile: "location" - }, - person: { - type: "phrase", - profile: "name" - } - } - }, - email: { - name: "email", - lang: "id", - entities: { - email: { - type: "phrase", - profile: "email" - } - } - }, - locationlabel: { - name: "location_kata", - lang: "id", - entities: { - location: { - type: "phrase", - profile: "location", - labels: [ - "common", - "places", - "city", - "street", - "country", - "airport" - ], - resolver: "location" - } - } - }, - location: { - name: "location", - lang: "id", - entities: { - location: { - type: "phrase", - profile: "location" - } - } - }, - name: { - name: "person", - lang: "id", - entities: { - person: { - type: "phrase", - profile: "name" - } - } - }, - sentiment: { - name: "sentiment", - lang: "id", - entities: { - sentiment: { - type: "trait", - profile: "sentiment", - labels: [ - "positive", - "negative", - "neutral" - ] - } - } - } -}; -const errorFileLog = "training.error.log"; -class Nlu extends merapi_1.Component { - constructor(helper, api) { - super(); - this.helper = helper; - this.api = api; - } - init(name, sandbox) { - return __awaiter(this, void 0, void 0, function* () { - try { - const sandboxName = sandbox || "default"; - const nluDesc = template[sandboxName]; - nluDesc.name = name; - this.helper.dumpYaml("./nlu.yml", nluDesc); - console.log(`Init NLU ${name}`); - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - pull() { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProp("projectId"); - let nluDesc; - try { - const { response: { body } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluGet, projectId); - const { name, lang, visibility, entities } = body; - nluDesc = { name, lang, visibility, entities }; - } - catch (error) { - console.log("Error: ", this.helper.wrapError(error)); - return; - } - for (const entity in nluDesc.entities) { - if (nluDesc.entities[entity] && nluDesc.entities[entity].type === "dict") { - // get dictionary - try { - const { response: { body } } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameGet, projectId, nluDesc.name, entity); - if (body.dictionary) { - nluDesc.entities[entity].dictionary = body.dictionary; - } - } - catch (error) { - console.log("Error: ", this.helper.wrapError(error)); - return; - } - } - } - const nluYml = yaml.dump(nluDesc); - console.log("Writing to nlu.yml..."); - fs.writeFileSync("nlu.yml", nluYml); - }); - } - push() { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProp("projectId"); - let nluDesc = null; - try { - nluDesc = this.helper.loadYaml("./nlu.yml"); - } - catch (error) { - if (error.code === "ENOENT") { - console.log("error: NLU file 'nlu.yml' does not exist, try calling 'kata nl-pull' to fetch 'nlu.yml' from the server"); - } - return; - } - let nlu; - let entities; - try { - const { response: { body } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluGet, projectId); - nlu = body; - } - catch (error) { - console.log(this.helper.wrapError(error)); - return; - } - try { - const { response: { body } } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesGet, projectId, nluDesc.name); - entities = body; - } - catch (error) { - console.log(this.helper.wrapError(error)); - return; - } - try { - if (nlu) { - let { lang, visibility } = nluDesc; - visibility = visibility || "private"; - // await this.helper.toPromise(this.api.nluApi, this.api.nluApi.nlusNluNamePut, - // nluDesc.name, { lang, visibility }); - if (nluDesc.entities && entities) { - const localDiff = this.helper.difference(nluDesc.entities, entities); - if (localDiff) { - for (const key in localDiff) { - if (entities[key]) { - // Update remote entity - if (!nluDesc.entities[key].inherit) { - yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNamePut, projectId, nluDesc.name, key, Object.assign({}, nluDesc.entities[key], { name: key })); - } - } - else { - // Create new entity - if (key.length > 20) { - console.log(`Failed to create ${key}. Entity name must not be longer than 20 characters.`); - continue; - } - yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesPost, projectId, nluDesc.name, Object.assign({}, nluDesc.entities[key], { name: key })); - } - } - } - const remoteDiff = this.helper.difference(entities, nluDesc.entities); - if (remoteDiff) { - for (const key in remoteDiff) { - if (!nluDesc.entities[key]) { - // delete remote entity - yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameDelete, projectId, nluDesc.name, key); - } - } - } - } - if (!nluDesc.entities && entities) { - for (const key in entities) { - if (entities[key]) { - // delete remote entity - yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameDelete, projectId, nluDesc.name, key); - } - } - } - if (nluDesc.entities && !entities) { - for (const key in nluDesc.entities) { - if (nluDesc.entities[key]) { - // create new entity - if (key.length > 20) { - console.log(`Failed to create ${key}. Entity name must not be longer than 20 characters.`); - continue; - } - yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesPost, projectId, nluDesc.name, Object.assign({}, nluDesc.entities[key], { name: key })); - } - } - } - } - console.log(`NLU ${nluDesc.name} Updated !`); - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - train(options) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProp("projectId"); - let nluDesc; - try { - nluDesc = this.helper.loadYaml("./nlu.yml"); - } - catch (e) { - console.log("Missing nlu.yml"); - return; - } - const nluName = nluDesc.name; - if (!nluName) { - console.log("Missing name in nlu.yml"); - return; - } - // check training job - const result = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameHasActiveJobGet, projectId, nluName); - if (result.data) { - console.log("Sorry, your previous training is still running. " + - "Give it another try in a few minutes."); - return; - } - try { - let opts = {}; - if (options.file) { - console.log(`Training.. (input file: ${options.file})`); - opts = { - file: fs.createReadStream(options.file) - }; - } - else if (options.sentence) { - console.log(`Training.. (input: ${options.sentence})`); - opts = { - sentence: options.sentence - }; - } - const { response: { body } } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameTrainPost, projectId, nluName, opts); - const trainResult = body; - // Print result - const count = trainResult.count; - const successCount = trainResult.rowIds ? trainResult.rowIds.length : 0; - if (successCount) { - console.log(`Success: ${successCount} data trained !`); - } - // Write error to file - const errorCount = trainResult.errRows ? trainResult.errRows.length : 0; - if (errorCount) { - if (options.file) { - const rawData = fs.readFileSync(options.file).toString("utf8"); - const trainingData = rawData.split("\n"); - let errData = ""; - for (const i of trainResult.errRows) { - errData += trainingData[i] + "\n"; - } - fs.writeFile(errorFileLog, errData, (err) => { - if (err) { - throw err; - } - console.log(`Error training ${errorCount} data. See details on ${errorFileLog}`); - }); - } - else if (options.sentence) { - console.log(`Error training data`); - } - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - predict(options) { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProp("projectId"); - let nluDesc; - try { - nluDesc = this.helper.loadYaml("./nlu.yml"); - } - catch (e) { - console.log("Missing nlu.yml"); - return; - } - const nluName = nluDesc.name; - if (!nluName) { - console.log("Missing name in nlu.yml"); - return; - } - try { - let opts = {}; - if (options.file) { - console.log(`Predict.. (input file: ${options.file})`); - opts = { - file: fs.createReadStream(options.file) - }; - } - else if (options.sentence) { - console.log(`Predict.. (input: ${options.sentence})`); - opts = { - sentence: options.sentence - }; - } - else { - throw new Error("Please input sentence or file to predict"); - } - const { response: { body } } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNamePredictPost, projectId, nluName, opts); - console.log(`Success, result : `); - let i = 0; - body.result.forEach((x) => { - console.log(`${++i}. Input: ${x.input}`); - console.log(` Result: ${JSON.stringify(x.output)}`); - }); - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - listProfiles() { - return __awaiter(this, void 0, void 0, function* () { - try { - const profiles = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.nlusProfilesGet); - if (profiles && profiles.data) { - const table = new Table({ - head: ["Type", "Name", "Desc"], - colWidths: [10, 10, 40] - }); - profiles.data.forEach((profile) => { - table.push([profile.type, profile.name, profile.desc]); - }); - console.log(table.toString()); - } - } - catch (error) { - console.log(error); - } - }); - } - // deprecated soon - listNlus(page, limit) { - return __awaiter(this, void 0, void 0, function* () { - try { - page = page || 1; - limit = limit || 10; - const projectId = this.helper.getProp("projectId"); - const nlus = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluGet, projectId, { page, limit }); - if (nlus && nlus.data) { - const table = new Table({ - head: ["Name", "Language", "Visibility"], - colWidths: [20, 20, 20] - }); - nlus.data.items.forEach((nlus) => { - table.push([nlus.name, nlus.lang, nlus.visibility]); - }); - console.log(table.toString()); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - snapshot() { - return __awaiter(this, void 0, void 0, function* () { - const projectId = this.helper.getProp("projectId"); - try { - const nluDesc = this.helper.loadYaml("./nlu.yml"); - const result = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameSnapshotGet, projectId, nluDesc.name); - console.log(`Snapshot captured!`); - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - listTraining(params) { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const projectName = this.helper.getProp("projectName"); - const username = this.helper.getProp("current_login"); - const { response } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameTrainingDataGet, projectId, `${username}:${projectName}`, { page: params.page || 1 }); - if (response && response.body && response.body.data) { - const table = new Table({ - head: ["Train Data", "Entities"], - colWidths: [50, 50] - }); - response.body.data.forEach((data) => { - const entities = data.entities.map((e) => { - return `(${e.entity}:${e.label}) ${e.value}`; - }); - table.push([data.input, entities.join("\n")]); - }); - console.log(table.toString()); - } - else { - console.log("Failed when trying list train data"); - } - } - else { - console.log("Please select project first"); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - listPrediction(params) { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const projectName = this.helper.getProp("projectName"); - const username = this.helper.getProp("current_login"); - const { response } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameLogGet, projectId, `${username}:${projectName}`, { page: params.page || 1, limit: 10 }); - if (response && response.body && response.body.result) { - const table = new Table({ - head: ["Prediction Log", "Entities"] - }); - response.body.result.forEach((data) => { - const entities = data.corrected.entities.map((e) => { - return `(${e.entity}:${e.label}) ${e.value}`; - }); - table.push([data.corrected.input, entities.join("\n")]); - }); - console.log(table.toString()); - } - else { - console.log("Failed when trying list prediction log"); - } - } - else { - console.log("Please select project first"); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - listRevision() { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluRevisionsGet, projectId); - if (response && response.body && response.body.data) { - const table = new Table({ - head: ["Snapshot", "Date"], - colWidths: [50, 25] - }); - response.body.data.forEach((data) => { - table.push([data.revision, new Date(data.created_at).toLocaleString()]); - }); - console.log(table.toString()); - } - else { - console.log("Failed when trying get revision list"); - } - } - else { - console.log("Please select project first"); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - detail() { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const { response } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNluGet, projectId); - if (response && response.body) { - const table = new Table({ - head: ["NLU Name", "NLU ID", "Language", "Token"] - }); - const language = (response.body.lang == "id") ? "Bahasa Indonesia" : "English"; - table.push([response.body.name, response.body.id, language, response.body.token]); - console.log(table.toString()); - } - else { - console.log("Failed when trying get NL detail"); - } - } - else { - console.log("Please select project first"); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - issueToken() { - return __awaiter(this, void 0, void 0, function* () { - try { - const projectId = this.helper.getProp("projectId"); - if (projectId) { - const projectName = this.helper.getProp("projectName"); - const username = this.helper.getProp("current_login"); - const { response } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameIssueTokenGet, projectId, `${username}:${projectName}`); - if (response && response.body) { - console.log(response.body.toString()); - } - else { - console.log("Failed when trying issue token"); - } - } - else { - console.log("Please select project first"); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } -} -exports.default = Nlu; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +const Table = require("cli-table"); +const fs = require("fs"); +const yaml = require("js-yaml"); +const template = { + default: { + name: "kata", + lang: "id", + entities: { + location: { + type: "phrase", + profile: "location" + }, + person: { + type: "phrase", + profile: "name" + } + } + }, + email: { + name: "email", + lang: "id", + entities: { + email: { + type: "phrase", + profile: "email" + } + } + }, + locationlabel: { + name: "location_kata", + lang: "id", + entities: { + location: { + type: "phrase", + profile: "location", + labels: [ + "common", + "places", + "city", + "street", + "country", + "airport" + ], + resolver: "location" + } + } + }, + location: { + name: "location", + lang: "id", + entities: { + location: { + type: "phrase", + profile: "location" + } + } + }, + name: { + name: "person", + lang: "id", + entities: { + person: { + type: "phrase", + profile: "name" + } + } + }, + sentiment: { + name: "sentiment", + lang: "id", + entities: { + sentiment: { + type: "trait", + profile: "sentiment", + labels: [ + "positive", + "negative", + "neutral" + ] + } + } + } +}; +const errorFileLog = "training.error.log"; +class Nlu extends merapi_1.Component { + constructor(helper, api) { + super(); + this.helper = helper; + this.api = api; + } + init(name, sandbox) { + return __awaiter(this, void 0, void 0, function* () { + try { + const sandboxName = sandbox || "default"; + const nluDesc = template[sandboxName]; + nluDesc.name = name; + this.helper.dumpYaml("./nlu.yml", nluDesc); + console.log(`Init NLU ${name}`); + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + pull() { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProp("projectId"); + let nluDesc; + try { + const { response: { body } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluGet, projectId); + const { name, lang, visibility, entities } = body; + nluDesc = { name, lang, visibility, entities }; + } + catch (error) { + console.log("Error: ", this.helper.wrapError(error)); + return; + } + for (const entity in nluDesc.entities) { + if (nluDesc.entities[entity] && nluDesc.entities[entity].type === "dict") { + // get dictionary + try { + const { response: { body } } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameGet, projectId, nluDesc.name, entity); + if (body.dictionary) { + nluDesc.entities[entity].dictionary = body.dictionary; + } + } + catch (error) { + console.log("Error: ", this.helper.wrapError(error)); + return; + } + } + } + const nluYml = yaml.dump(nluDesc); + console.log("Writing to nlu.yml..."); + fs.writeFileSync("nlu.yml", nluYml); + }); + } + push() { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProp("projectId"); + let nluDesc = null; + try { + nluDesc = this.helper.loadYaml("./nlu.yml"); + } + catch (error) { + if (error.code === "ENOENT") { + console.log("error: NLU file 'nlu.yml' does not exist, try calling 'kata nl-pull' to fetch 'nlu.yml' from the server"); + } + return; + } + let nlu; + let entities; + try { + const { response: { body } } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluGet, projectId); + nlu = body; + } + catch (error) { + console.log(this.helper.wrapError(error)); + return; + } + try { + const { response: { body } } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesGet, projectId, nluDesc.name); + entities = body; + } + catch (error) { + console.log(this.helper.wrapError(error)); + return; + } + try { + if (nlu) { + let { lang, visibility } = nluDesc; + visibility = visibility || "private"; + // await this.helper.toPromise(this.api.nluApi, this.api.nluApi.nlusNluNamePut, + // nluDesc.name, { lang, visibility }); + if (nluDesc.entities && entities) { + const localDiff = this.helper.difference(nluDesc.entities, entities); + if (localDiff) { + for (const key in localDiff) { + if (entities[key]) { + // Update remote entity + if (!nluDesc.entities[key].inherit) { + yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNamePut, projectId, nluDesc.name, key, Object.assign({}, nluDesc.entities[key], { name: key })); + } + } + else { + // Create new entity + if (key.length > 20) { + console.log(`Failed to create ${key}. Entity name must not be longer than 20 characters.`); + continue; + } + yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesPost, projectId, nluDesc.name, Object.assign({}, nluDesc.entities[key], { name: key })); + } + } + } + const remoteDiff = this.helper.difference(entities, nluDesc.entities); + if (remoteDiff) { + for (const key in remoteDiff) { + if (!nluDesc.entities[key]) { + // delete remote entity + yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameDelete, projectId, nluDesc.name, key); + } + } + } + } + if (!nluDesc.entities && entities) { + for (const key in entities) { + if (entities[key]) { + // delete remote entity + yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesEntityNameDelete, projectId, nluDesc.name, key); + } + } + } + if (nluDesc.entities && !entities) { + for (const key in nluDesc.entities) { + if (nluDesc.entities[key]) { + // create new entity + if (key.length > 20) { + console.log(`Failed to create ${key}. Entity name must not be longer than 20 characters.`); + continue; + } + yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameEntitiesPost, projectId, nluDesc.name, Object.assign({}, nluDesc.entities[key], { name: key })); + } + } + } + } + console.log(`NLU ${nluDesc.name} Updated !`); + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + train(options) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProp("projectId"); + let nluDesc; + try { + nluDesc = this.helper.loadYaml("./nlu.yml"); + } + catch (e) { + console.log("Missing nlu.yml"); + return; + } + const nluName = nluDesc.name; + if (!nluName) { + console.log("Missing name in nlu.yml"); + return; + } + // check training job + const result = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameHasActiveJobGet, projectId, nluName); + if (result.data) { + console.log("Sorry, your previous training is still running. " + + "Give it another try in a few minutes."); + return; + } + try { + let opts = {}; + if (options.file) { + console.log(`Training.. (input file: ${options.file})`); + opts = { + file: fs.createReadStream(options.file) + }; + } + else if (options.sentence) { + console.log(`Training.. (input: ${options.sentence})`); + opts = { + sentence: options.sentence + }; + } + const { response: { body } } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameTrainPost, projectId, nluName, opts); + const trainResult = body; + // Print result + const count = trainResult.count; + const successCount = trainResult.rowIds ? trainResult.rowIds.length : 0; + if (successCount) { + console.log(`Success: ${successCount} data trained !`); + } + // Write error to file + const errorCount = trainResult.errRows ? trainResult.errRows.length : 0; + if (errorCount) { + if (options.file) { + const rawData = fs.readFileSync(options.file).toString("utf8"); + const trainingData = rawData.split("\n"); + let errData = ""; + for (const i of trainResult.errRows) { + errData += trainingData[i] + "\n"; + } + fs.writeFile(errorFileLog, errData, (err) => { + if (err) { + throw err; + } + console.log(`Error training ${errorCount} data. See details on ${errorFileLog}`); + }); + } + else if (options.sentence) { + console.log(`Error training data`); + } + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + predict(options) { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProp("projectId"); + let nluDesc; + try { + nluDesc = this.helper.loadYaml("./nlu.yml"); + } + catch (e) { + console.log("Missing nlu.yml"); + return; + } + const nluName = nluDesc.name; + if (!nluName) { + console.log("Missing name in nlu.yml"); + return; + } + try { + let opts = {}; + if (options.file) { + console.log(`Predict.. (input file: ${options.file})`); + opts = { + file: fs.createReadStream(options.file) + }; + } + else if (options.sentence) { + console.log(`Predict.. (input: ${options.sentence})`); + opts = { + sentence: options.sentence + }; + } + else { + throw new Error("Please input sentence or file to predict"); + } + const { response: { body } } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNamePredictPost, projectId, nluName, opts); + console.log(`Success, result : `); + let i = 0; + body.result.forEach((x) => { + console.log(`${++i}. Input: ${x.input}`); + console.log(` Result: ${JSON.stringify(x.output)}`); + }); + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + listProfiles() { + return __awaiter(this, void 0, void 0, function* () { + try { + const profiles = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.nlusProfilesGet); + if (profiles && profiles.data) { + const table = new Table({ + head: ["Type", "Name", "Desc"], + colWidths: [10, 10, 40] + }); + profiles.data.forEach((profile) => { + table.push([profile.type, profile.name, profile.desc]); + }); + console.log(table.toString()); + } + } + catch (error) { + console.log(error); + } + }); + } + // deprecated soon + listNlus(page, limit) { + return __awaiter(this, void 0, void 0, function* () { + try { + page = page || 1; + limit = limit || 10; + const projectId = this.helper.getProp("projectId"); + const nlus = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluGet, projectId, { page, limit }); + if (nlus && nlus.data) { + const table = new Table({ + head: ["Name", "Language", "Visibility"], + colWidths: [20, 20, 20] + }); + nlus.data.items.forEach((nlus) => { + table.push([nlus.name, nlus.lang, nlus.visibility]); + }); + console.log(table.toString()); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + snapshot() { + return __awaiter(this, void 0, void 0, function* () { + const projectId = this.helper.getProp("projectId"); + try { + const nluDesc = this.helper.loadYaml("./nlu.yml"); + const result = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameSnapshotGet, projectId, nluDesc.name); + console.log(`Snapshot captured!`); + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + listTraining(params) { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const projectName = this.helper.getProp("projectName"); + const username = this.helper.getProp("current_login"); + const { response } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameTrainingDataGet, projectId, `${username}:${projectName}`, { page: params.page || 1 }); + if (response && response.body && response.body.data) { + const table = new Table({ + head: ["Train Data", "Entities"], + colWidths: [50, 50] + }); + response.body.data.forEach((data) => { + const entities = data.entities.map((e) => { + return `(${e.entity}:${e.label}) ${e.value}`; + }); + table.push([data.input, entities.join("\n")]); + }); + console.log(table.toString()); + } + else { + console.log("Failed when trying list train data"); + } + } + else { + console.log("Please select project first"); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + listPrediction(params) { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const projectName = this.helper.getProp("projectName"); + const username = this.helper.getProp("current_login"); + const { response } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameLogGet, projectId, `${username}:${projectName}`, { page: params.page || 1, limit: 10 }); + if (response && response.body && response.body.result) { + const table = new Table({ + head: ["Prediction Log", "Entities"] + }); + response.body.result.forEach((data) => { + const entities = data.corrected.entities.map((e) => { + return `(${e.entity}:${e.label}) ${e.value}`; + }); + table.push([data.corrected.input, entities.join("\n")]); + }); + console.log(table.toString()); + } + else { + console.log("Failed when trying list prediction log"); + } + } + else { + console.log("Please select project first"); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + listRevision() { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdNluRevisionsGet, projectId); + if (response && response.body && response.body.data) { + const table = new Table({ + head: ["Snapshot", "Date"], + colWidths: [50, 25] + }); + response.body.data.forEach((data) => { + table.push([data.revision, new Date(data.created_at).toLocaleString()]); + }); + console.log(table.toString()); + } + else { + console.log("Failed when trying get revision list"); + } + } + else { + console.log("Please select project first"); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + detail() { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const { response } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNluGet, projectId); + if (response && response.body) { + const table = new Table({ + head: ["NLU Name", "NLU ID", "Language", "Token"] + }); + const language = (response.body.lang == "id") ? "Bahasa Indonesia" : "English"; + table.push([response.body.name, response.body.id, language, response.body.token]); + console.log(table.toString()); + } + else { + console.log("Failed when trying get NL detail"); + } + } + else { + console.log("Please select project first"); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + issueToken() { + return __awaiter(this, void 0, void 0, function* () { + try { + const projectId = this.helper.getProp("projectId"); + if (projectId) { + const projectName = this.helper.getProp("projectName"); + const username = this.helper.getProp("current_login"); + const { response } = yield this.helper.toPromise(this.api.nluApi, this.api.nluApi.projectsProjectIdNlusNluNameIssueTokenGet, projectId, `${username}:${projectName}`); + if (response && response.body) { + console.log(response.body.toString()); + } + else { + console.log("Failed when trying issue token"); + } + } + else { + console.log("Please select project first"); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } +} +exports.default = Nlu; //# sourceMappingURL=nlu.js.map \ No newline at end of file diff --git a/lib/components/projects/project.js b/lib/components/projects/project.js index d16bd54..8316887 100644 --- a/lib/components/projects/project.js +++ b/lib/components/projects/project.js @@ -1,287 +1,287 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const inquirer = require("inquirer"); -const Table = require("cli-table"); -const colors = require("colors/safe"); -class Project { - constructor(api, helper) { - this.api = api; - this.helper = helper; - } - create() { - return __awaiter(this, void 0, void 0, function* () { - let projectData = { name: "" }; - while (true) { - projectData = yield this.helper.inquirerPrompt([ - { - type: "text", - name: "name", - message: "Project name:", - }, - ]); - if (projectData.name.length > 20) { - console.error("error: Project name length can not exceed 20 characters"); - } - else if (!/^[A-Za-z][A-Za-z0-9_-]*[A-Za-z0-9]$/.test(projectData.name)) { - console.error("error: Project name must start with alphabet characters and contains only aplhanumeric character, dash, or underscore"); - } - else { - break; - } - } - const inquiredOptions = yield this.helper.inquirerPrompt([ - { - type: "number", - name: "timezone", - message: "Timezone (UTC)", - default: 7, - }, - { - type: "text", - name: "description", - message: "Project description:", - }, - ]); - const options = Object.assign({ bot: true, cms: true, nlu: true }, inquiredOptions); - let nluOptions = {}; - if (options.nlu) { - nluOptions = yield this.helper.inquirerPrompt([ - { - type: "text", - name: "nluLang", - message: "NLU Language", - default: "id", - }, - { - type: "confirm", - name: "privateNlu", - message: "Is private Nlu?", - default: true, - }, - ]); - nluOptions.nluVisibility = nluOptions.privateNlu ? "private" : "public"; - delete nluOptions.privateNlu; - } - const requestBody = Object.assign({}, projectData, { options: Object.assign({}, options, nluOptions) }); - try { - const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsPost, requestBody); - if (response && response.body && response.body.id) { - const project = response.body; - const projectId = project.id; - this.helper.setProp("projectId", projectId); - console.log(colors.green(`Project "${project.name}" (${projectId}) is successfully created`)); - return; - } - } - catch (e) { - console.error(this.helper.wrapError(e)); - } - }); - } - update(projectName) { - return __awaiter(this, void 0, void 0, function* () { - let chosen = null; - if (projectName) { - chosen = yield this.getDataByName(projectName); - } - else { - chosen = yield this.choose(); - } - if (chosen) { - const { description, privateNlu } = yield this.helper.inquirerPrompt([ - { - type: "text", - name: "description", - message: "Project description:", - }, - { - type: "confirm", - name: "privateNlu", - message: "Is private Nlu?", - default: true, - } - ]); - const nluVisibility = privateNlu ? 'private' : 'public'; - const requestBody = { - id: chosen.id, - name: chosen.name, - description: description, - options: { - timezone: chosen.options.timezone, - nluLang: chosen.options.nluLang, - nluVisibility: nluVisibility, - nluId: chosen.options.nluId - } - }; - const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdPut, chosen.id, requestBody); - if (response && response.body) { - console.log(`Project ${chosen.name} has been updated.`); - } - else { - console.log("Failed when trying update project"); - } - } - else { - console.log(`Project ${projectName} is not found`); - } - }); - } - list() { - return __awaiter(this, void 0, void 0, function* () { - try { - const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, {}); - if (response && response.body && response.body.data) { - const table = new Table({ - head: ["Project ID", "Project Name"], - colWidths: [38, 32] - }); - response.body.data.forEach((project) => { - table.push([project.id, project.name]); - }); - console.log(table.toString()); - } - } - catch (e) { - console.error(this.helper.wrapError(e)); - } - }); - } - getDataByName(projectName) { - return __awaiter(this, void 0, void 0, function* () { - const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, {}); - if (response && response.body && response.body.data) { - const projects = response.body.data; - const sameName = projects.find((project) => project.name === projectName); - if (sameName) { - return sameName; - } - } - }); - } - choose() { - return __awaiter(this, void 0, void 0, function* () { - try { - let page = 1; - const pageLimit = 10; - while (true) { - const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, { limit: pageLimit, page }); - if (response && response.body && response.body.data) { - const maxPage = Math.ceil(response.body.total / pageLimit); - const projectList = response.body.data; - const choices = projectList.map((projectRow) => ({ - name: projectRow.name, - value: projectRow - })); - const body = response.body; - if (body.total > body.page * body.limit) { - choices.push({ name: "(Load More)", value: -1 }); - } - const { project } = yield inquirer.prompt([ - { - type: "list", - name: "project", - message: `Select project (page ${page} / ${maxPage})`, - paginated: false, - pageSize: pageLimit + 1, - choices - }, - ]); - if (project === -1) { - page++; - continue; - } - return project; - } - console.error("Failed to list projects"); - } - } - catch (e) { - console.error(this.helper.wrapError(e)); - } - }); - } - select(projectName) { - return __awaiter(this, void 0, void 0, function* () { - let chosen; - if (typeof projectName === "string") { - chosen = yield this.getDataByName(projectName); - if (chosen !== undefined) { - // project name found - this.helper.setProp("projectId", chosen.id); - this.helper.setProp("projectName", chosen.name); - } - else { - // project name not found, select through inquirer - console.log(`Project with name ${colors.green(projectName)} is not found. ` + - `Please choose listed project name below:`); - chosen = yield this.choose(); - if (chosen) { - this.helper.setProp("projectId", chosen.id); - this.helper.setProp("projectName", chosen.name); - } - } - } - else { - // projectName is empty - chosen = yield this.choose(); - if (chosen) { - this.helper.setProp("projectId", chosen.id); - this.helper.setProp("projectName", chosen.name); - } - } - console.log(colors.green(`Project "${chosen.name}" (${chosen.id}) is successfully selected`)); - if (!chosen || chosen === undefined) { - chosen = yield this.choose(); - if (chosen) { - this.helper.setProp("projectId", chosen.id); - this.helper.setProp("projectName", chosen.name); - console.log(colors.green(`Project "${chosen.name}" (${chosen.id}) is successfully selected`)); - } - } - }); - } - delete(projectName) { - return __awaiter(this, void 0, void 0, function* () { - try { - const chosen = projectName ? yield this.getDataByName(projectName) : yield this.choose(); - if (chosen) { - const { yes } = yield inquirer.prompt([ - { - type: "confirm", - name: "yes", - message: "Are you sure want to delete this project ?", - default: true, - } - ]); - if (yes) { - const deleteProject = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdDelete, chosen.id); - if (deleteProject && deleteProject.response && deleteProject.response.body) { - if (deleteProject.response.body) { - console.log("Project has been deleted."); - } - else { - console.log("Failed when trying delete project"); - } - } - } - } - else { - console.log(`Project ${projectName} is not found`); - } - } - catch (e) { - console.error(this.helper.wrapError(e)); - } - }); - } -} -exports.default = Project; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const inquirer = require("inquirer"); +const Table = require("cli-table"); +const colors = require("colors/safe"); +class Project { + constructor(api, helper) { + this.api = api; + this.helper = helper; + } + create() { + return __awaiter(this, void 0, void 0, function* () { + let projectData = { name: "" }; + while (true) { + projectData = yield this.helper.inquirerPrompt([ + { + type: "text", + name: "name", + message: "Project name:", + }, + ]); + if (projectData.name.length > 20) { + console.error("error: Project name length can not exceed 20 characters"); + } + else if (!/^[A-Za-z][A-Za-z0-9_-]*[A-Za-z0-9]$/.test(projectData.name)) { + console.error("error: Project name must start with alphabet characters and contains only aplhanumeric character, dash, or underscore"); + } + else { + break; + } + } + const inquiredOptions = yield this.helper.inquirerPrompt([ + { + type: "number", + name: "timezone", + message: "Timezone (UTC)", + default: 7, + }, + { + type: "text", + name: "description", + message: "Project description:", + }, + ]); + const options = Object.assign({ bot: true, cms: true, nlu: true }, inquiredOptions); + let nluOptions = {}; + if (options.nlu) { + nluOptions = yield this.helper.inquirerPrompt([ + { + type: "text", + name: "nluLang", + message: "NLU Language", + default: "id", + }, + { + type: "confirm", + name: "privateNlu", + message: "Is private Nlu?", + default: true, + }, + ]); + nluOptions.nluVisibility = nluOptions.privateNlu ? "private" : "public"; + delete nluOptions.privateNlu; + } + const requestBody = Object.assign({}, projectData, { options: Object.assign({}, options, nluOptions) }); + try { + const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsPost, requestBody); + if (response && response.body && response.body.id) { + const project = response.body; + const projectId = project.id; + this.helper.setProp("projectId", projectId); + console.log(colors.green(`Project "${project.name}" (${projectId}) is successfully created`)); + return; + } + } + catch (e) { + console.error(this.helper.wrapError(e)); + } + }); + } + update(projectName) { + return __awaiter(this, void 0, void 0, function* () { + let chosen = null; + if (projectName) { + chosen = yield this.getDataByName(projectName); + } + else { + chosen = yield this.choose(); + } + if (chosen) { + const { description, privateNlu } = yield this.helper.inquirerPrompt([ + { + type: "text", + name: "description", + message: "Project description:", + }, + { + type: "confirm", + name: "privateNlu", + message: "Is private Nlu?", + default: true, + } + ]); + const nluVisibility = privateNlu ? 'private' : 'public'; + const requestBody = { + id: chosen.id, + name: chosen.name, + description: description, + options: { + timezone: chosen.options.timezone, + nluLang: chosen.options.nluLang, + nluVisibility: nluVisibility, + nluId: chosen.options.nluId + } + }; + const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdPut, chosen.id, requestBody); + if (response && response.body) { + console.log(`Project ${chosen.name} has been updated.`); + } + else { + console.log("Failed when trying update project"); + } + } + else { + console.log(`Project ${projectName} is not found`); + } + }); + } + list() { + return __awaiter(this, void 0, void 0, function* () { + try { + const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, {}); + if (response && response.body && response.body.data) { + const table = new Table({ + head: ["Project ID", "Project Name"], + colWidths: [38, 32] + }); + response.body.data.forEach((project) => { + table.push([project.id, project.name]); + }); + console.log(table.toString()); + } + } + catch (e) { + console.error(this.helper.wrapError(e)); + } + }); + } + getDataByName(projectName) { + return __awaiter(this, void 0, void 0, function* () { + const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, {}); + if (response && response.body && response.body.data) { + const projects = response.body.data; + const sameName = projects.find((project) => project.name === projectName); + if (sameName) { + return sameName; + } + } + }); + } + choose() { + return __awaiter(this, void 0, void 0, function* () { + try { + let page = 1; + const pageLimit = 10; + while (true) { + const { response } = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsGet, { limit: pageLimit, page }); + if (response && response.body && response.body.data) { + const maxPage = Math.ceil(response.body.total / pageLimit); + const projectList = response.body.data; + const choices = projectList.map((projectRow) => ({ + name: projectRow.name, + value: projectRow + })); + const body = response.body; + if (body.total > body.page * body.limit) { + choices.push({ name: "(Load More)", value: -1 }); + } + const { project } = yield inquirer.prompt([ + { + type: "list", + name: "project", + message: `Select project (page ${page} / ${maxPage})`, + paginated: false, + pageSize: pageLimit + 1, + choices + }, + ]); + if (project === -1) { + page++; + continue; + } + return project; + } + console.error("Failed to list projects"); + } + } + catch (e) { + console.error(this.helper.wrapError(e)); + } + }); + } + select(projectName) { + return __awaiter(this, void 0, void 0, function* () { + let chosen; + if (typeof projectName === "string") { + chosen = yield this.getDataByName(projectName); + if (chosen !== undefined) { + // project name found + this.helper.setProp("projectId", chosen.id); + this.helper.setProp("projectName", chosen.name); + } + else { + // project name not found, select through inquirer + console.log(`Project with name ${colors.green(projectName)} is not found. ` + + `Please choose listed project name below:`); + chosen = yield this.choose(); + if (chosen) { + this.helper.setProp("projectId", chosen.id); + this.helper.setProp("projectName", chosen.name); + } + } + } + else { + // projectName is empty + chosen = yield this.choose(); + if (chosen) { + this.helper.setProp("projectId", chosen.id); + this.helper.setProp("projectName", chosen.name); + } + } + console.log(colors.green(`Project "${chosen.name}" (${chosen.id}) is successfully selected`)); + if (!chosen || chosen === undefined) { + chosen = yield this.choose(); + if (chosen) { + this.helper.setProp("projectId", chosen.id); + this.helper.setProp("projectName", chosen.name); + console.log(colors.green(`Project "${chosen.name}" (${chosen.id}) is successfully selected`)); + } + } + }); + } + delete(projectName) { + return __awaiter(this, void 0, void 0, function* () { + try { + const chosen = projectName ? yield this.getDataByName(projectName) : yield this.choose(); + if (chosen) { + const { yes } = yield inquirer.prompt([ + { + type: "confirm", + name: "yes", + message: "Are you sure want to delete this project ?", + default: true, + } + ]); + if (yes) { + const deleteProject = yield this.helper.toPromise(this.api.projectApi, this.api.projectApi.projectsProjectIdDelete, chosen.id); + if (deleteProject && deleteProject.response && deleteProject.response.body) { + if (deleteProject.response.body) { + console.log("Project has been deleted."); + } + else { + console.log("Failed when trying delete project"); + } + } + } + } + else { + console.log(`Project ${projectName} is not found`); + } + } + catch (e) { + console.error(this.helper.wrapError(e)); + } + }); + } +} +exports.default = Project; //# sourceMappingURL=project.js.map \ No newline at end of file diff --git a/lib/components/scripts/compile.js b/lib/components/scripts/compile.js index fde0b47..1403213 100644 --- a/lib/components/scripts/compile.js +++ b/lib/components/scripts/compile.js @@ -1,43 +1,43 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -const { Config } = require("merapi"); -const path = require("path"); -const fs = require("fs"); -const yaml = require("js-yaml"); -class Compile extends merapi_1.Component { - constructor(helper) { - super(); - this.helper = helper; - this.directives = { - include(file, basepath, helper) { - let ext = path.extname(file); - if (ext === ".yml" || ext === ".yaml") - return helper.loadYaml(path.resolve(basepath, file)); - else if (ext === ".json") - return require(path.resolve(basepath, file)); - else - return fs.readFileSync(path.resolve(basepath, file)).toString(); - } - }; - } - execDirective(name, directive, dict, basepath) { - for (let i in dict) { - if (typeof dict[i] !== "string") - continue; - let val = dict[i].trim(); - if (val.indexOf("$" + name + "(") === 0 && val.charAt(val.length - 1) === ")") { - dict[i] = directive(dict[i].substring(2 + name.length, dict[i].length - 1), basepath, this.helper); - } - } - } - execDirectives(config, basepath) { - let flattened = config.flatten(); - for (let i in this.directives) { - this.execDirective(i, this.directives[i], flattened, basepath); - } - return config.create(flattened); - } -} -exports.default = Compile; +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +const { Config } = require("merapi"); +const path = require("path"); +const fs = require("fs"); +const yaml = require("js-yaml"); +class Compile extends merapi_1.Component { + constructor(helper) { + super(); + this.helper = helper; + this.directives = { + include(file, basepath, helper) { + let ext = path.extname(file); + if (ext === ".yml" || ext === ".yaml") + return helper.loadYaml(path.resolve(basepath, file)); + else if (ext === ".json") + return require(path.resolve(basepath, file)); + else + return fs.readFileSync(path.resolve(basepath, file)).toString(); + } + }; + } + execDirective(name, directive, dict, basepath) { + for (let i in dict) { + if (typeof dict[i] !== "string") + continue; + let val = dict[i].trim(); + if (val.indexOf("$" + name + "(") === 0 && val.charAt(val.length - 1) === ")") { + dict[i] = directive(dict[i].substring(2 + name.length, dict[i].length - 1), basepath, this.helper); + } + } + } + execDirectives(config, basepath) { + let flattened = config.flatten(); + for (let i in this.directives) { + this.execDirective(i, this.directives[i], flattened, basepath); + } + return config.create(flattened); + } +} +exports.default = Compile; //# sourceMappingURL=compile.js.map \ No newline at end of file diff --git a/lib/components/scripts/helper.js b/lib/components/scripts/helper.js index a8e234b..f9f94ef 100644 --- a/lib/components/scripts/helper.js +++ b/lib/components/scripts/helper.js @@ -1,290 +1,290 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -const _ = require("lodash"); -const Catch = require("catch-decorator"); -const yaml = require("js-yaml"); -const fs = require("fs"); -const os = require("os"); -const path = require("path"); -const inquirer = require("inquirer"); -const analytics = require("universal-analytics"); -function wrapError(error) { - let errorMessage; - if (error.response && error.response.body && error.response.body.message) { - errorMessage = error.response.body.message; - } - else if (error.response && error.response.body) { - errorMessage = error.response.body; - } - else { - errorMessage = error.message; - } - return errorMessage; -} -exports.CatchError = Catch(Error, (error) => { - console.log("Error"); - console.error(wrapError(error)); -}); -class Helper extends merapi_1.Component { - constructor(config) { - super(); - this.config = config; - } - getFiles(dir, ending) { - const fileList = fs.readdirSync(dir); - const res = []; - for (let i = 0; i < fileList.length; i++) { - const stat = fs.statSync(path.resolve(dir, fileList[i])); - if (stat.isDirectory()) { - res.push(...this.getFiles(dir + "/" + fileList[i], ending)); - } - else if (stat.isFile() && fileList[i].endsWith(ending)) { - res.push(dir + "/" + fileList[i]); - } - } - return res; - } - loadYaml(file) { - return yaml.safeLoad(fs.readFileSync(file, "utf8")); - } - dumpYaml(file, object) { - fs.writeFileSync(file, yaml.safeDump(object, { indent: 4, lineWidth: 150 }), "utf8"); - } - compareTestResult(result, expect) { - if (!result) { - return null; - } - const errors = []; - const expected = this.config.create(expect).flatten(); - const res = this.config.create(result); - for (const i in expected) { - const value = res.get(i); - if (value !== expected[i]) { - errors.push({ field: i, expect: expected[i], result: value }); - } - } - return errors; - } - setProp(prop, value, options) { - const jsonPath = `${os.homedir()}/.katajson`; - let jsonProp; - if (fs.existsSync(jsonPath)) { - jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - } - else { - jsonProp = {}; - } - jsonProp[prop] = value; - fs.writeFileSync(jsonPath, JSON.stringify(jsonProp), "utf8"); - } - getProp(prop, options) { - const jsonPath = `${os.homedir()}/.katajson`; - let jsonProp; - if (fs.existsSync(jsonPath)) { - jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - } - else { - jsonProp = {}; - } - return jsonProp[prop]; - } - delete() { - const jsonPath = `${os.homedir()}/.katajson`; - if (fs.existsSync(jsonPath)) { - fs.unlinkSync(jsonPath); - return true; - } - return false; - } - deleteKeyToken(userName) { - const jsonPath = `${os.homedir()}/.katajson`; - let jsonProp; - if (fs.existsSync(jsonPath)) { - jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - // if userName token exist - if (userName in jsonProp.token) { - jsonProp.current_login = "admin"; - delete jsonProp.token[userName]; - delete jsonProp.projectId; - delete jsonProp.projectName; - delete jsonProp.isImpersonate; - } - else { - return new Error(`Failed to unimpersonate ${(userName)}`); - } - } - else { - jsonProp = {}; - } - fs.writeFileSync(jsonPath, JSON.stringify(jsonProp), "utf8"); - return jsonProp; - } - toPromise(ctx, func, ...args) { - return new Promise((resolve, reject) => { - args.push((error, data, response) => { - if (error) { - reject(error); - } - else { - resolve({ data, response }); - } - }); - func.apply(ctx, args); - }); - } - getBotId() { - const desc = this.loadYaml("./bot.yml"); - return desc.id; - } - getProjectId() { - return this.getProp("projectId"); - } - createDirectory(dirPath, mode) { - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath, mode); - } - } - getCurrentToken() { - const currentLogin = this.getProp("current_login") || ""; - const tokenProp = (this.getProp("token") || {}); - return { - currentLogin, - token: tokenProp[currentLogin] - }; - } - loadYamlOrJsonFile(filePath) { - if (!fs.existsSync(filePath)) { - return new Error("FILE NOT FOUND"); - } - const fileExt = path.extname(filePath); - if (fileExt === ".json") { - return JSON.parse(fs.readFileSync(filePath, "utf8")); - } - else if (fileExt === ".yml" || fileExt === ".yaml") { - return this.loadYaml(filePath); - } - else if (fileExt === ".txt") { - return fs.readFileSync(filePath, "utf8"); - } - else { - return new Error("UNSUPPORTED FILE TYPE"); - } - } - inquirerPrompt(questions) { - return __awaiter(this, void 0, void 0, function* () { - return inquirer.prompt(questions); - }); - } - wrapError(error) { - const errorMessage = wrapError(error); - const commands = this.getCommandSession(); - // Note: error might happen even after clearCommandSession is called - // this might results in an empty command, we do not want to track empty command error - if (commands.length > 0) { - const lastCommand = commands[commands.length - 1].command; - const mainCommand = lastCommand.split(" ")[0]; - this.sendGoogleAnalytics("debug", mainCommand, lastCommand, commands, errorMessage); - this.clearCommandSession(); - } - return errorMessage; - } - difference(object, base) { - function changes(object, base) { - return _.transform(object, function (result, value, key) { - if (!_.isEqual(value, base[key])) { - result[key] = (_.isObject(value) && _.isObject(base[key])) ? changes(value, base[key]) : value; - } - }); - } - return changes(object, base); - } - viewConfig() { - const jsonPath = `${os.homedir()}/.katajson`; - let jsonProp; - if (fs.existsSync(jsonPath)) { - jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - delete jsonProp.first_login; - } - else { - jsonProp = ".katajson file not found"; - } - console.log(jsonProp); - } - checkNotificationStatus() { - const jsonPath = `${os.homedir()}/.katanotif`; - if (fs.existsSync(jsonPath)) { - return true; - } - else { - fs.writeFileSync(jsonPath, "true", "utf8"); - return false; - } - } - addCommandSession(command) { - const jsonPath = `${os.homedir()}/.katacommand`; - let jsonData = []; - if (fs.existsSync(jsonPath)) - jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - if (jsonData.length > 0) { - const lastData = jsonData[jsonData.length - 1]; - const diff = Math.abs(Number(lastData.timestamp) - new Date().getTime()) / 36e5; - if (diff >= 1) - jsonData = []; //Lebih dari 1 jam ? - } - jsonData.push({ timestamp: new Date().getTime(), command: command }); - fs.writeFileSync(jsonPath, JSON.stringify(jsonData), "utf8"); - } - getCommandSession() { - const jsonPath = `${os.homedir()}/.katacommand`; - let jsonData = []; - if (fs.existsSync(jsonPath)) - jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); - return jsonData; - } - clearCommandSession() { - const jsonPath = `${os.homedir()}/.katacommand`; - fs.writeFileSync(jsonPath, "[]", "utf8"); - } - sendGoogleAnalytics(event, action, command, lastSession, errorMessage) { - let firstLogin = this.getProp("first_login"); - let projectId = this.getProp("projectId"); - let projectName = this.getProp("projectName"); - if (!firstLogin) - firstLogin = { id: null, username: null, type: null }; - if (!projectId) - projectId = null; - if (!projectName) - projectName = null; - const version = this.config.default("version", "1.0.0"); - const google = analytics(this.config.default("config.trackingId", "UA-131926842-1"), firstLogin.id); - const data = { - userId: firstLogin.id, - username: firstLogin.username, - currentUserType: firstLogin.type, - activeProjectId: projectId, - activeProjectName: projectName, - command: command, - versionCLI: version, - timestamp: new Date().getTime() - }; - if (lastSession) - data.lastSession = lastSession; - if (errorMessage) - data.errorMessage = errorMessage; - google.event(event, action, JSON.stringify(data), (err) => { - if (err) - console.log(this.wrapError(err)); - }); - } -} -exports.default = Helper; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +const _ = require("lodash"); +const Catch = require("catch-decorator"); +const yaml = require("js-yaml"); +const fs = require("fs"); +const os = require("os"); +const path = require("path"); +const inquirer = require("inquirer"); +const analytics = require("universal-analytics"); +function wrapError(error) { + let errorMessage; + if (error.response && error.response.body && error.response.body.message) { + errorMessage = error.response.body.message; + } + else if (error.response && error.response.body) { + errorMessage = error.response.body; + } + else { + errorMessage = error.message; + } + return errorMessage; +} +exports.CatchError = Catch(Error, (error) => { + console.log("Error"); + console.error(wrapError(error)); +}); +class Helper extends merapi_1.Component { + constructor(config) { + super(); + this.config = config; + } + getFiles(dir, ending) { + const fileList = fs.readdirSync(dir); + const res = []; + for (let i = 0; i < fileList.length; i++) { + const stat = fs.statSync(path.resolve(dir, fileList[i])); + if (stat.isDirectory()) { + res.push(...this.getFiles(dir + "/" + fileList[i], ending)); + } + else if (stat.isFile() && fileList[i].endsWith(ending)) { + res.push(dir + "/" + fileList[i]); + } + } + return res; + } + loadYaml(file) { + return yaml.safeLoad(fs.readFileSync(file, "utf8")); + } + dumpYaml(file, object) { + fs.writeFileSync(file, yaml.safeDump(object, { indent: 4, lineWidth: 150 }), "utf8"); + } + compareTestResult(result, expect) { + if (!result) { + return null; + } + const errors = []; + const expected = this.config.create(expect).flatten(); + const res = this.config.create(result); + for (const i in expected) { + const value = res.get(i); + if (value !== expected[i]) { + errors.push({ field: i, expect: expected[i], result: value }); + } + } + return errors; + } + setProp(prop, value, options) { + const jsonPath = `${os.homedir()}/.katajson`; + let jsonProp; + if (fs.existsSync(jsonPath)) { + jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + } + else { + jsonProp = {}; + } + jsonProp[prop] = value; + fs.writeFileSync(jsonPath, JSON.stringify(jsonProp), "utf8"); + } + getProp(prop, options) { + const jsonPath = `${os.homedir()}/.katajson`; + let jsonProp; + if (fs.existsSync(jsonPath)) { + jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + } + else { + jsonProp = {}; + } + return jsonProp[prop]; + } + delete() { + const jsonPath = `${os.homedir()}/.katajson`; + if (fs.existsSync(jsonPath)) { + fs.unlinkSync(jsonPath); + return true; + } + return false; + } + deleteKeyToken(userName) { + const jsonPath = `${os.homedir()}/.katajson`; + let jsonProp; + if (fs.existsSync(jsonPath)) { + jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + // if userName token exist + if (userName in jsonProp.token) { + jsonProp.current_login = "admin"; + delete jsonProp.token[userName]; + delete jsonProp.projectId; + delete jsonProp.projectName; + delete jsonProp.isImpersonate; + } + else { + return new Error(`Failed to unimpersonate ${(userName)}`); + } + } + else { + jsonProp = {}; + } + fs.writeFileSync(jsonPath, JSON.stringify(jsonProp), "utf8"); + return jsonProp; + } + toPromise(ctx, func, ...args) { + return new Promise((resolve, reject) => { + args.push((error, data, response) => { + if (error) { + reject(error); + } + else { + resolve({ data, response }); + } + }); + func.apply(ctx, args); + }); + } + getBotId() { + const desc = this.loadYaml("./bot.yml"); + return desc.id; + } + getProjectId() { + return this.getProp("projectId"); + } + createDirectory(dirPath, mode) { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, mode); + } + } + getCurrentToken() { + const currentLogin = this.getProp("current_login") || ""; + const tokenProp = (this.getProp("token") || {}); + return { + currentLogin, + token: tokenProp[currentLogin] + }; + } + loadYamlOrJsonFile(filePath) { + if (!fs.existsSync(filePath)) { + return new Error("FILE NOT FOUND"); + } + const fileExt = path.extname(filePath); + if (fileExt === ".json") { + return JSON.parse(fs.readFileSync(filePath, "utf8")); + } + else if (fileExt === ".yml" || fileExt === ".yaml") { + return this.loadYaml(filePath); + } + else if (fileExt === ".txt") { + return fs.readFileSync(filePath, "utf8"); + } + else { + return new Error("UNSUPPORTED FILE TYPE"); + } + } + inquirerPrompt(questions) { + return __awaiter(this, void 0, void 0, function* () { + return inquirer.prompt(questions); + }); + } + wrapError(error) { + const errorMessage = wrapError(error); + const commands = this.getCommandSession(); + // Note: error might happen even after clearCommandSession is called + // this might results in an empty command, we do not want to track empty command error + if (commands.length > 0) { + const lastCommand = commands[commands.length - 1].command; + const mainCommand = lastCommand.split(" ")[0]; + this.sendGoogleAnalytics("debug", mainCommand, lastCommand, commands, errorMessage); + this.clearCommandSession(); + } + return errorMessage; + } + difference(object, base) { + function changes(object, base) { + return _.transform(object, function (result, value, key) { + if (!_.isEqual(value, base[key])) { + result[key] = (_.isObject(value) && _.isObject(base[key])) ? changes(value, base[key]) : value; + } + }); + } + return changes(object, base); + } + viewConfig() { + const jsonPath = `${os.homedir()}/.katajson`; + let jsonProp; + if (fs.existsSync(jsonPath)) { + jsonProp = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + delete jsonProp.first_login; + } + else { + jsonProp = ".katajson file not found"; + } + console.log(jsonProp); + } + checkNotificationStatus() { + const jsonPath = `${os.homedir()}/.katanotif`; + if (fs.existsSync(jsonPath)) { + return true; + } + else { + fs.writeFileSync(jsonPath, "true", "utf8"); + return false; + } + } + addCommandSession(command) { + const jsonPath = `${os.homedir()}/.katacommand`; + let jsonData = []; + if (fs.existsSync(jsonPath)) + jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + if (jsonData.length > 0) { + const lastData = jsonData[jsonData.length - 1]; + const diff = Math.abs(Number(lastData.timestamp) - new Date().getTime()) / 36e5; + if (diff >= 1) + jsonData = []; //Lebih dari 1 jam ? + } + jsonData.push({ timestamp: new Date().getTime(), command: command }); + fs.writeFileSync(jsonPath, JSON.stringify(jsonData), "utf8"); + } + getCommandSession() { + const jsonPath = `${os.homedir()}/.katacommand`; + let jsonData = []; + if (fs.existsSync(jsonPath)) + jsonData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + return jsonData; + } + clearCommandSession() { + const jsonPath = `${os.homedir()}/.katacommand`; + fs.writeFileSync(jsonPath, "[]", "utf8"); + } + sendGoogleAnalytics(event, action, command, lastSession, errorMessage) { + let firstLogin = this.getProp("first_login"); + let projectId = this.getProp("projectId"); + let projectName = this.getProp("projectName"); + if (!firstLogin) + firstLogin = { id: null, username: null, type: null }; + if (!projectId) + projectId = null; + if (!projectName) + projectName = null; + const version = this.config.default("version", "1.0.0"); + const google = analytics(this.config.default("config.trackingId", "UA-131926842-1"), firstLogin.id); + const data = { + userId: firstLogin.id, + username: firstLogin.username, + currentUserType: firstLogin.type, + activeProjectId: projectId, + activeProjectName: projectName, + command: command, + versionCLI: version, + timestamp: new Date().getTime() + }; + if (lastSession) + data.lastSession = lastSession; + if (errorMessage) + data.errorMessage = errorMessage; + google.event(event, action, JSON.stringify(data), (err) => { + if (err) + console.log(this.wrapError(err)); + }); + } +} +exports.default = Helper; //# sourceMappingURL=helper.js.map \ No newline at end of file diff --git a/lib/components/scripts/tester.js b/lib/components/scripts/tester.js index ceb814a..3a13aad 100644 --- a/lib/components/scripts/tester.js +++ b/lib/components/scripts/tester.js @@ -1,130 +1,130 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -let colors = require("colors/safe"); -class Tester extends merapi_1.Component { - constructor(config, helper) { - super(); - this.config = config; - this.helper = helper; - } - execIntentTest(yaml, botApi, botId, print = function (text) { }) { - return __awaiter(this, void 0, void 0, function* () { - let flow = yaml.flow; - let context = yaml.context || {}; - let data = yaml.data || {}; - let result = {}; - print(yaml.desc); - let tab = " "; - for (let name in yaml.test) { - let test = yaml.test[name]; - let testIntent = test.intent || null; - let testContext = Object.assign({}, context, test.context || {}); - let testData = Object.assign({}, data, test.data || {}); - let testMessage = Object.assign({ type: "text", content: "", payload: {} }, test.message || {}); - let body = { - flow, - "intent": testIntent, - "message": testMessage, - "context": testContext, - "data": testData - }; - let execResult = yield this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "intent", body); - result[name] = this.helper.compareTestResult(execResult.data, test.expect); - print(tab + name + ": " + (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); - } - return result; - }); - } - execStateTest(yaml, botApi, botId, print = function (text) { }) { - return __awaiter(this, void 0, void 0, function* () { - let flow = yaml.flow; - let context = yaml.context || {}; - let data = yaml.data || {}; - let result = {}; - print(yaml.desc); - let tab = " "; - for (let name in yaml.test) { - let test = yaml.test[name]; - let testState = test.state; - let testContext = Object.assign({}, context, test.context || {}); - let testData = Object.assign({}, data, test.data || {}); - let testMessage = Object.assign({ type: "text", content: "", payload: {} }, test.message || {}, { intent: test.intent, attributes: test.attributes }); - let body = { - flow, - state: testState, - message: testMessage, - context: testContext, - data: testData - }; - let execResult = yield this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "state-mapper", body); - result[name] = this.helper.compareTestResult(execResult.data, test.expect); - print(tab + name + ": " + (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); - } - return result; - }); - } - execActionsTest(yaml, botApi, botId, print = function (text) { }) { - return __awaiter(this, void 0, void 0, function* () { - let flow = yaml.flow; - let context = yaml.context || {}; - let data = yaml.data || {}; - let result = {}; - print(yaml.desc); - let tab = " "; - for (let name in yaml.test) { - let test = yaml.test[name]; - let testState = test.state; - let testContext = Object.assign({}, context, test.context || {}); - let testData = Object.assign({}, data, test.data || {}); - let testMessage = Object.assign({ type: "text", content: "", payload: {} }, test.message || {}, { intent: test.intent, attributes: test.attributes }); - let body = { - flow, - state: testState, - message: testMessage, - context: testContext, - data: testData - }; - let execResult = yield this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "action", body); - result[name] = this.helper.compareTestResult(execResult.data, test.expect); - print(tab + name + ": " + (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); - } - return result; - }); - } - execFlowTest(yaml, botApi, botId, print = function (text) { }) { - return __awaiter(this, void 0, void 0, function* () { - let flow = yaml.flow; - let state = yaml.state || null; - let context = yaml.context || {}; - let data = yaml.data || {}; - let result = {}; - print(yaml.desc); - let tab = " "; - for (let name in yaml.test) { - let test = yaml.test[name]; - let message = Object.assign({ type: "text", content: "", payload: {} }, test.message || {}, { intent: test.intent, attributes: test.attributes }); - let body = { flow, state, message, context, data }; - let execResult = yield this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "flow", body); - result[name] = this.helper.compareTestResult(execResult.data, test.expect); - print(tab + name + ": " + (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); - if (!execResult) - break; - state = execResult.data.state; - context = execResult.data.context; - data = execResult.data; - } - return result; - }); - } -} -exports.default = Tester; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +let colors = require("colors/safe"); +class Tester extends merapi_1.Component { + constructor(config, helper) { + super(); + this.config = config; + this.helper = helper; + } + execIntentTest(yaml, botApi, botId, print = function (text) { }) { + return __awaiter(this, void 0, void 0, function* () { + let flow = yaml.flow; + let context = yaml.context || {}; + let data = yaml.data || {}; + let result = {}; + print(yaml.desc); + let tab = " "; + for (let name in yaml.test) { + let test = yaml.test[name]; + let testIntent = test.intent || null; + let testContext = Object.assign({}, context, test.context || {}); + let testData = Object.assign({}, data, test.data || {}); + let testMessage = Object.assign({ type: "text", content: "", payload: {} }, test.message || {}); + let body = { + flow, + "intent": testIntent, + "message": testMessage, + "context": testContext, + "data": testData + }; + let execResult = yield this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "intent", body); + result[name] = this.helper.compareTestResult(execResult.data, test.expect); + print(tab + name + ": " + (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); + } + return result; + }); + } + execStateTest(yaml, botApi, botId, print = function (text) { }) { + return __awaiter(this, void 0, void 0, function* () { + let flow = yaml.flow; + let context = yaml.context || {}; + let data = yaml.data || {}; + let result = {}; + print(yaml.desc); + let tab = " "; + for (let name in yaml.test) { + let test = yaml.test[name]; + let testState = test.state; + let testContext = Object.assign({}, context, test.context || {}); + let testData = Object.assign({}, data, test.data || {}); + let testMessage = Object.assign({ type: "text", content: "", payload: {} }, test.message || {}, { intent: test.intent, attributes: test.attributes }); + let body = { + flow, + state: testState, + message: testMessage, + context: testContext, + data: testData + }; + let execResult = yield this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "state-mapper", body); + result[name] = this.helper.compareTestResult(execResult.data, test.expect); + print(tab + name + ": " + (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); + } + return result; + }); + } + execActionsTest(yaml, botApi, botId, print = function (text) { }) { + return __awaiter(this, void 0, void 0, function* () { + let flow = yaml.flow; + let context = yaml.context || {}; + let data = yaml.data || {}; + let result = {}; + print(yaml.desc); + let tab = " "; + for (let name in yaml.test) { + let test = yaml.test[name]; + let testState = test.state; + let testContext = Object.assign({}, context, test.context || {}); + let testData = Object.assign({}, data, test.data || {}); + let testMessage = Object.assign({ type: "text", content: "", payload: {} }, test.message || {}, { intent: test.intent, attributes: test.attributes }); + let body = { + flow, + state: testState, + message: testMessage, + context: testContext, + data: testData + }; + let execResult = yield this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "action", body); + result[name] = this.helper.compareTestResult(execResult.data, test.expect); + print(tab + name + ": " + (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); + } + return result; + }); + } + execFlowTest(yaml, botApi, botId, print = function (text) { }) { + return __awaiter(this, void 0, void 0, function* () { + let flow = yaml.flow; + let state = yaml.state || null; + let context = yaml.context || {}; + let data = yaml.data || {}; + let result = {}; + print(yaml.desc); + let tab = " "; + for (let name in yaml.test) { + let test = yaml.test[name]; + let message = Object.assign({ type: "text", content: "", payload: {} }, test.message || {}, { intent: test.intent, attributes: test.attributes }); + let body = { flow, state, message, context, data }; + let execResult = yield this.helper.toPromise(botApi, botApi.botsBotIdExecObjectPost, botId, "flow", body); + result[name] = this.helper.compareTestResult(execResult.data, test.expect); + print(tab + name + ": " + (result[name] && !result[name].length ? colors.green("passed") : colors.red("not passing"))); + if (!execResult) + break; + state = execResult.data.state; + context = execResult.data.context; + data = execResult.data; + } + return result; + }); + } +} +exports.default = Tester; //# sourceMappingURL=tester.js.map \ No newline at end of file diff --git a/lib/components/users/team.js b/lib/components/users/team.js index 2f368ad..4e21261 100644 --- a/lib/components/users/team.js +++ b/lib/components/users/team.js @@ -1,129 +1,129 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -class Team extends merapi_1.Component { - constructor(helper, api) { - super(); - this.helper = helper; - this.api = api; - } - addMember(username, options) { - return __awaiter(this, void 0, void 0, function* () { - try { - const role = options.admin ? "teamAdmin" : "teamMember"; - let firstLogin = this.helper.getProp("first_login"); - const { userInfo, teamInfo, teamMember, currentLogin } = yield this.getInfo(username, (firstLogin.username).toString()); - if (userInfo && userInfo.id) { - if (this.checkUser(userInfo.id, teamMember)) { - throw new Error(`User ${username} already on this team`); - } - const { response } = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersUserIdPost, teamInfo.teamId, userInfo.username, { - roleId: role - }); - if (!response.body) { - throw new Error("Error adding user to team: invalid roleId"); - } - console.log(`Success register ${username} to ${currentLogin}`); - } - else { - console.log(`User ${username} not found`); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - removeMember(username) { - return __awaiter(this, void 0, void 0, function* () { - const answer = yield this.helper.inquirerPrompt([ - { - type: "confirm", - name: "confirmation", - message: `Do you want to remove ${username} ?`, - default: false - } - ]); - if (!answer.confirmation) { - return; - } - try { - const { userInfo, teamInfo, teamMember, currentLogin } = yield this.getInfo(username); - if (userInfo && userInfo.id) { - if (!this.checkUser(userInfo.id, teamMember)) { - throw new Error(`User ${username} not a member of this team`); - } - const { response } = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersUserIdDelete, teamInfo.id, userInfo.id); - console.log(`Success remove ${username} from ${currentLogin}`); - } - else { - console.log(`User ${username} not found`); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - getInfo(username, firstLoginUsername) { - return __awaiter(this, void 0, void 0, function* () { - const currentLogin = this.helper.getProp("current_login"); - const currentUserType = this.helper.getProp("current_user_type"); - if (currentUserType !== "team") { - throw new Error("Must be on team to do this operation"); - } - const requestTeamData = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, firstLoginUsername); - let teamInfo; - if (requestTeamData.response && requestTeamData.response.body) { - const filterTeamBasedOnCurrentTeam = (requestTeamData.response.body).filter((singleTeam) => (singleTeam.username == currentLogin)); - teamInfo = filterTeamBasedOnCurrentTeam[0]; - } - else { - throw new Error("Cannot add user to team"); - } - // console.log('teamInfo ', teamInfo); - const requestUserData = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersGetInfoKeyGet, username); - // console.log('requestUserData ', requestUserData); - let userInfo; - if (requestUserData && requestUserData.response) { - userInfo = requestUserData.response.body; - } - else { - throw new Error("Cannot add user to team"); - } - // console.log('userInfo ', userInfo); - const requestTeamMember = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersGet, teamInfo.teamId); - let teamMember; - if (requestTeamMember && requestTeamMember.response) { - teamMember = requestTeamMember.response.body; - } - else { - throw new Error("Cannot add user to team"); - } - // console.log('teamMember ', teamMember); - return { - teamInfo, - userInfo, - teamMember, - currentLogin - }; - }); - } - checkUser(userId, member) { - const teamMember = member.map((x) => x.userId); - if (teamMember.indexOf(userId) > -1) { - return true; - } - return false; - } -} -exports.default = Team; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +class Team extends merapi_1.Component { + constructor(helper, api) { + super(); + this.helper = helper; + this.api = api; + } + addMember(username, options) { + return __awaiter(this, void 0, void 0, function* () { + try { + const role = options.admin ? "teamAdmin" : "teamMember"; + let firstLogin = this.helper.getProp("first_login"); + const { userInfo, teamInfo, teamMember, currentLogin } = yield this.getInfo(username, (firstLogin.username).toString()); + if (userInfo && userInfo.id) { + if (this.checkUser(userInfo.id, teamMember)) { + throw new Error(`User ${username} already on this team`); + } + const { response } = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersUserIdPost, teamInfo.teamId, userInfo.username, { + roleId: role + }); + if (!response.body) { + throw new Error("Error adding user to team: invalid roleId"); + } + console.log(`Success register ${username} to ${currentLogin}`); + } + else { + console.log(`User ${username} not found`); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + removeMember(username) { + return __awaiter(this, void 0, void 0, function* () { + const answer = yield this.helper.inquirerPrompt([ + { + type: "confirm", + name: "confirmation", + message: `Do you want to remove ${username} ?`, + default: false + } + ]); + if (!answer.confirmation) { + return; + } + try { + const { userInfo, teamInfo, teamMember, currentLogin } = yield this.getInfo(username); + if (userInfo && userInfo.id) { + if (!this.checkUser(userInfo.id, teamMember)) { + throw new Error(`User ${username} not a member of this team`); + } + const { response } = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersUserIdDelete, teamInfo.id, userInfo.id); + console.log(`Success remove ${username} from ${currentLogin}`); + } + else { + console.log(`User ${username} not found`); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + getInfo(username, firstLoginUsername) { + return __awaiter(this, void 0, void 0, function* () { + const currentLogin = this.helper.getProp("current_login"); + const currentUserType = this.helper.getProp("current_user_type"); + if (currentUserType !== "team") { + throw new Error("Must be on team to do this operation"); + } + const requestTeamData = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, firstLoginUsername); + let teamInfo; + if (requestTeamData.response && requestTeamData.response.body) { + const filterTeamBasedOnCurrentTeam = (requestTeamData.response.body).filter((singleTeam) => (singleTeam.username == currentLogin)); + teamInfo = filterTeamBasedOnCurrentTeam[0]; + } + else { + throw new Error("Cannot add user to team"); + } + // console.log('teamInfo ', teamInfo); + const requestUserData = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersGetInfoKeyGet, username); + // console.log('requestUserData ', requestUserData); + let userInfo; + if (requestUserData && requestUserData.response) { + userInfo = requestUserData.response.body; + } + else { + throw new Error("Cannot add user to team"); + } + // console.log('userInfo ', userInfo); + const requestTeamMember = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersGet, teamInfo.teamId); + let teamMember; + if (requestTeamMember && requestTeamMember.response) { + teamMember = requestTeamMember.response.body; + } + else { + throw new Error("Cannot add user to team"); + } + // console.log('teamMember ', teamMember); + return { + teamInfo, + userInfo, + teamMember, + currentLogin + }; + }); + } + checkUser(userId, member) { + const teamMember = member.map((x) => x.userId); + if (teamMember.indexOf(userId) > -1) { + return true; + } + return false; + } +} +exports.default = Team; //# sourceMappingURL=team.js.map \ No newline at end of file diff --git a/lib/components/users/user.js b/lib/components/users/user.js index a4d2bc2..7221064 100644 --- a/lib/components/users/user.js +++ b/lib/components/users/user.js @@ -1,535 +1,535 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const merapi_1 = require("merapi"); -const inquirer = require("inquirer"); -const Table = require("cli-table"); -const colors = require("colors"); -class User extends merapi_1.Component { - constructor(helper, api) { - super(); - this.helper = helper; - this.api = api; - } - login(options) { - return __awaiter(this, void 0, void 0, function* () { - try { - let currToken = this.helper.getCurrentToken().token; - if (options.token) { - if (!currToken) { - currToken = options.token; - } - this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currToken}`; - let result = yield this.helper.toPromise(this.api.authApi, this.api.authApi.tokensTokenIdGet, options.token); - const tokenObj = result.data; - if (tokenObj.type === "user") { - this.setToken({ name: "user", type: tokenObj.type }, options.token); - } - else if (tokenObj.type === "team") { - result = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, tokenObj.teamId); - const team = result.data; - this.setToken({ name: team.username, type: tokenObj.type }, options.token); - } - else { - throw new Error("Invalid token"); - } - } - else { - let user = (options.user ? options.user : ""); - let pass = (options.password ? options.password : ""); - const answer = yield inquirer.prompt([ - { - type: "input", - name: "user", - message: "username: ", - when() { - return !user; - }, - validate(user) { - if (!user) { - return "Username cannot be empty"; - } - return true; - } - }, - { - type: "password", - name: "password", - message: "password: ", - mask: "*", - when() { - return !pass; - }, - validate(password) { - if (!password) { - return "Password cannot be empty"; - } - return true; - } - } - ]); - user = answer.user || user; - pass = answer.password || pass; - const result = yield this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: user, password: pass }); - if (!result.data.isLoggedIn && !result.data.id) { - console.log(`username or password is incorrect`); - } - else { - const token = result.data.id; - this.helper.setProp("first_login", { type: "user", username: user, id: result.data.userId }); - this.setToken({ name: user, type: "user", namespace: "platform" }, token); - console.log(`Logged in as ${colors.green(user)}`); - } - } - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - logout() { - return __awaiter(this, void 0, void 0, function* () { - const answer = yield this.helper.inquirerPrompt([ - { - type: "confirm", - name: "confirmation", - message: "Do you want to log out ?", - default: false - } - ]); - if (!answer.confirmation) { - return; - } - try { - const result = yield this.helper.delete(); - if (result) { - console.log("Logged out"); - } - else { - console.log("Please log in first"); - } - this.helper.clearCommandSession(); - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - switch(type, name) { - return __awaiter(this, void 0, void 0, function* () { - try { - const firstLogin = this.helper.getProp("first_login"); - const currentType = this.helper.getProp("current_user_type"); - const currentLogin = this.helper.getProp("current_login"); - const username = name ? name : currentLogin; - if (currentType === type && username === currentLogin) { - throw new Error(`Unable to switch : already on ${colors.green(currentLogin)} as ${colors.green(type)}`); - } - const isImpersonate = this.helper.getProp("isImpersonate"); - if (type === "team") { - let userId; - if (isImpersonate === true) { - const currentLoginName = this.helper.getProp("current_login").toString(); - userId = (yield this.getUserInfo(currentLoginName)).id; - } - else { - userId = firstLogin.id.toString(); - } - const { response } = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, userId); - if (!response) { - throw new Error(`Unable to switch team: ${colors.green(name)}`); - } - const teams = response && response.body ? - response.body.teams.filter((team) => team.username === name) : []; - if (teams.length > 0) { - const result = yield this.helper.toPromise(this.api.authApi, this.api.authApi.tokensPost, { - type: "team", - teamId: teams[0].teamId - }); - const token = result.data.id; - this.setToken({ name, type: "team" }, token); - this.helper.setProp("current_login", name); - this.helper.setProp("current_user_type", "team"); - console.log(`Switched to team: ${colors.green(name)}`); - } - else { - console.log(`Invalid team name. Unable to switch to team: ${colors.red(name)}`); - } - } - else if (type === "user") { - if (isImpersonate === true) { - // TODO: jika user login sbg admin, impersonate dewi, switch ke team, lalu mau switch ke user yg non-user tsb - const userTokenInfo = this.getUserTokenInfo(name); - if (!userTokenInfo || userTokenInfo === undefined) { - throw new Error(`${colors.red(name)}'s token is not found.`); - } - else if (userTokenInfo.userName === "admin") { - throw new Error(`Cannot switch to ${colors.red(name)}. Use unimpersonate.`); - } - else { - if (name === userTokenInfo.userName) { - this.helper.setProp("current_login", name); - this.helper.setProp("current_user_type", "user"); - console.log(`Switched to user ${colors.green(name)}`); - } - else { - throw new Error(`Unable to switch to user ${colors.red(name)}.`); - } - } - } - else { - this.helper.setProp("current_login", firstLogin.username); - this.helper.setProp("current_user_type", "user"); - console.log(`Switched to user ${colors.green(firstLogin.username)}`); - } - } - } - catch (e) { - console.log(this.helper.wrapError(e)); - } - }); - } - changePassword() { - return __awaiter(this, void 0, void 0, function* () { - try { - const passObj = yield this.getNewPasswordData(); - if (passObj.newPass !== passObj.rePass) { - throw new Error("Invalid retype password"); - } - const currentUser = this.helper.getProp("current_login"); - const { data } = yield this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: currentUser, password: passObj.oldPass }); - if (data) { - const result = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdPut, currentUser, { password: passObj.newPass }); - console.log("Password changed"); - } - else { - console.log("Invalid password"); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - whoami(options) { - const currentLogin = this.helper.getProp("current_login"); - const currentType = this.helper.getProp("current_user_type"); - console.log(`Current login: ${colors.green(currentLogin)}, login type: ${colors.green(currentType)}`); - } - createTeam(name) { - return __awaiter(this, void 0, void 0, function* () { - try { - const currentLogin = this.helper.getProp("current_login"); - const currentUserType = this.helper.getProp("current_user_type"); - if (currentUserType !== "user") { - throw new Error("Must be on user to do this operation"); - } - const { response } = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsPost, { username: name, password: "", roleId: "teamAdmin" }); - if (response && response.body.id) { - console.log(`Team ${colors.green(name)} created !`); - } - else { - console.log(`Team ${colors.red(name)} exist !`); - } - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - createUser(username, options) { - return __awaiter(this, void 0, void 0, function* () { - const password = yield this.helper.inquirerPrompt([ - { - type: "password", - name: "answer", - message: "password: ", - mask: "*", - default: null - } - ]); - const confirmPassword = yield this.helper.inquirerPrompt([ - { - type: "password", - name: "answer", - message: "retype password: ", - mask: "*", - default: null - } - ]); - try { - if (password.answer !== confirmPassword.answer) { - throw new Error("Invalid retype password"); - } - let role; - if (options.admin) { - role = "admin"; - } - else if (options.internal) { - role = "internalUser"; - } - else { - role = "user"; - } - const { data } = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, username); - if (data.id) { - throw new Error(`Username ${username} exist !`); - } - const newUser = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersPost, { username, password: password.answer, roleId: role }); - console.log(`New user ${colors.green(newUser.data.username)} created !`); - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - impersonate(userName) { - return __awaiter(this, void 0, void 0, function* () { - // TODO : dibuat seperti login, pake inquirer. - try { - const currentLogin = this.helper.getProp("current_login").toString(); - if (currentLogin !== "admin") { - throw new Error(`Your login status is not superadmin. You are not authorized to impersonate a user`); - } - // set currentToken header bearer token - const currentToken = this.helper.getCurrentToken().token.toString(); - this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`; - // get admin token - this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`; - // get user id from username - const id = (yield this.getUserInfo(userName)).id; - const name = (yield this.getUserInfo(userName)).name; - const email = (yield this.getUserInfo(userName)).email; - if (name && email) { - // userName is user collected input - if (userName !== name && userName !== email) { - throw new Error(`Sorry, username is not exist.`); - } - } - else { - throw new Error(`Sorry, username is not valid.`); - } - // impersonate function - const result = yield this.helper.toPromise(this.api.authApi, this.api.authApi.impersonatePost, { - userId: id, - namespace: "platform" - }); - // set value on .katajson - const impersonateToken = result.data.id.toString(); - const type = result.data.type.toString(); - this.helper.setProp("isImpersonate", true); - this.setToken({ name, type }, impersonateToken); - console.log(`Succesfully impersonate as ${colors.green(name)}`); - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - // unimpersonate command - unimpersonate() { - return __awaiter(this, void 0, void 0, function* () { - try { - const userName = this.helper.getProp("current_login").toString(); - this.helper.deleteKeyToken(userName); - const currentLogin = this.helper.getProp("current_login").toString(); - console.log(`Succesfully unimpersonate user. Now your current login is ${colors.green(currentLogin)}`); - } - catch (error) { - console.log(this.helper.wrapError(error)); - } - }); - } - setToken(userInfo, token) { - this.helper.setProp("current_login", userInfo.name); - this.helper.setProp("current_user_type", userInfo.type); - this.helper.setProp("namespace", userInfo.namespace); - const tokenProp = (this.helper.getProp("token") || {}); - tokenProp[userInfo.name] = token; - this.helper.setProp("token", tokenProp); - } - getUserTokenInfo(name) { - const tokenProp = (this.helper.getProp("token") || {}); - if (name in tokenProp) { - const userName = name.toString(); - const token = tokenProp[name].toString(); - return { - userName, - token - }; - } - } - getUserInfo(userName) { - return __awaiter(this, void 0, void 0, function* () { - // get userId from currentlogin - const { response } = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersGetInfoKeyGet, userName); - const user = response.body; - const email = user.email ? user.email.toString() : ""; - const name = user.username.toString(); - const id = user.userId.toString(); - return { - id, - name, - email, - }; - }); - } - getNewPasswordData() { - return __awaiter(this, void 0, void 0, function* () { - let oldPass; - let newPass; - let rePass; - const answer = yield inquirer.prompt([ - { - type: "password", - name: "oldPass", - message: "current password: ", - mask: "*", - when() { - return !oldPass; - }, - validate(user) { - if (!user) { - return "Password cannot be empty"; - } - return true; - } - }, - { - type: "password", - name: "newPass", - message: "new password: ", - mask: "*", - when() { - return !newPass; - }, - validate(password) { - if (!password) { - return "Password cannot be empty"; - } - return true; - } - }, - { - type: "password", - name: "rePass", - message: "retype new password: ", - mask: "*", - when() { - return !rePass; - }, - validate(password, answer) { - if (!password) { - return "Password cannot be empty"; - } - if (password !== answer.newPass) { - return "Invalid retype password"; - } - return true; - } - }, - ]); - return answer; - }); - } - forgot(username) { - return __awaiter(this, void 0, void 0, function* () { - try { - const current_login = this.helper.getProp("current_login"); - if (!current_login) { - const { response } = yield this.helper.toPromise(this.api.authApi, this.api.authApi.forgotPost, { username }); - if (response && response.body && response.body.message) { - console.log("Please check your email to reset your password."); - } - } - else { - console.log(`Please log out first`); - } - } - catch (e) { - console.error(this.helper.wrapError(e)); - } - }); - } - listTeam() { - return __awaiter(this, void 0, void 0, function* () { - try { - const current_login = this.helper.getProp("current_login"); - if (current_login) { - const { response } = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login); - const table = new Table({ - head: ["Team Name", "Projects", "Members", "Bots"], - colWidths: [50, 15, 15, 15] - }); - response.body.forEach((team) => { - table.push([team.username, team.projects, team.members, team.bots]); - }); - console.log(table.toString()); - } - else { - console.log("Please log in first"); - } - } - catch (e) { - console.error(this.helper.wrapError(e)); - } - }); - } - listTeamUser(teamName) { - return __awaiter(this, void 0, void 0, function* () { - try { - const current_login = this.helper.getProp("current_login"); - if (current_login) { - const dataTeams = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login); - const teams = dataTeams.response.body; - const choices = teams.map((team) => ({ - name: team.username, - value: team.teamId - })); - let teamId = null; - if (teamName) { - const sameName = choices.find((choice) => choice.name === teamName); - if (sameName) { - teamId = sameName.value; - } - } - else { - const choice = yield inquirer.prompt([ - { - type: "list", - name: "teamId", - message: "Team:", - choices: choices - } - ]); - teamId = choice.teamId; - } - const { response } = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersGet, teamId); - const table = new Table({ - head: ["Username", "Role"], - colWidths: [50, 25] - }); - response.body.forEach((user) => { - table.push([user.username, user.roleName]); - }); - console.log(table.toString()); - } - else { - console.log("Please log in first"); - } - } - catch (e) { - console.error(this.helper.wrapError(e)); - } - }); - } -} -exports.default = User; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const merapi_1 = require("merapi"); +const inquirer = require("inquirer"); +const Table = require("cli-table"); +const colors = require("colors"); +class User extends merapi_1.Component { + constructor(helper, api) { + super(); + this.helper = helper; + this.api = api; + } + login(options) { + return __awaiter(this, void 0, void 0, function* () { + try { + let currToken = this.helper.getCurrentToken().token; + if (options.token) { + if (!currToken) { + currToken = options.token; + } + this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currToken}`; + let result = yield this.helper.toPromise(this.api.authApi, this.api.authApi.tokensTokenIdGet, options.token); + const tokenObj = result.data; + if (tokenObj.type === "user") { + this.setToken({ name: "user", type: tokenObj.type }, options.token); + } + else if (tokenObj.type === "team") { + result = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, tokenObj.teamId); + const team = result.data; + this.setToken({ name: team.username, type: tokenObj.type }, options.token); + } + else { + throw new Error("Invalid token"); + } + } + else { + let user = (options.user ? options.user : ""); + let pass = (options.password ? options.password : ""); + const answer = yield inquirer.prompt([ + { + type: "input", + name: "user", + message: "username: ", + when() { + return !user; + }, + validate(user) { + if (!user) { + return "Username cannot be empty"; + } + return true; + } + }, + { + type: "password", + name: "password", + message: "password: ", + mask: "*", + when() { + return !pass; + }, + validate(password) { + if (!password) { + return "Password cannot be empty"; + } + return true; + } + } + ]); + user = answer.user || user; + pass = answer.password || pass; + const result = yield this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: user, password: pass }); + if (!result.data.isLoggedIn && !result.data.id) { + console.log(`username or password is incorrect`); + } + else { + const token = result.data.id; + this.helper.setProp("first_login", { type: "user", username: user, id: result.data.userId }); + this.setToken({ name: user, type: "user", namespace: "platform" }, token); + console.log(`Logged in as ${colors.green(user)}`); + } + } + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + logout() { + return __awaiter(this, void 0, void 0, function* () { + const answer = yield this.helper.inquirerPrompt([ + { + type: "confirm", + name: "confirmation", + message: "Do you want to log out ?", + default: false + } + ]); + if (!answer.confirmation) { + return; + } + try { + const result = yield this.helper.delete(); + if (result) { + console.log("Logged out"); + } + else { + console.log("Please log in first"); + } + this.helper.clearCommandSession(); + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + switch(type, name) { + return __awaiter(this, void 0, void 0, function* () { + try { + const firstLogin = this.helper.getProp("first_login"); + const currentType = this.helper.getProp("current_user_type"); + const currentLogin = this.helper.getProp("current_login"); + const username = name ? name : currentLogin; + if (currentType === type && username === currentLogin) { + throw new Error(`Unable to switch : already on ${colors.green(currentLogin)} as ${colors.green(type)}`); + } + const isImpersonate = this.helper.getProp("isImpersonate"); + if (type === "team") { + let userId; + if (isImpersonate === true) { + const currentLoginName = this.helper.getProp("current_login").toString(); + userId = (yield this.getUserInfo(currentLoginName)).id; + } + else { + userId = firstLogin.id.toString(); + } + const { response } = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, userId); + if (!response) { + throw new Error(`Unable to switch team: ${colors.green(name)}`); + } + const teams = response && response.body ? + response.body.teams.filter((team) => team.username === name) : []; + if (teams.length > 0) { + const result = yield this.helper.toPromise(this.api.authApi, this.api.authApi.tokensPost, { + type: "team", + teamId: teams[0].teamId + }); + const token = result.data.id; + this.setToken({ name, type: "team" }, token); + this.helper.setProp("current_login", name); + this.helper.setProp("current_user_type", "team"); + console.log(`Switched to team: ${colors.green(name)}`); + } + else { + console.log(`Invalid team name. Unable to switch to team: ${colors.red(name)}`); + } + } + else if (type === "user") { + if (isImpersonate === true) { + // TODO: jika user login sbg admin, impersonate dewi, switch ke team, lalu mau switch ke user yg non-user tsb + const userTokenInfo = this.getUserTokenInfo(name); + if (!userTokenInfo || userTokenInfo === undefined) { + throw new Error(`${colors.red(name)}'s token is not found.`); + } + else if (userTokenInfo.userName === "admin") { + throw new Error(`Cannot switch to ${colors.red(name)}. Use unimpersonate.`); + } + else { + if (name === userTokenInfo.userName) { + this.helper.setProp("current_login", name); + this.helper.setProp("current_user_type", "user"); + console.log(`Switched to user ${colors.green(name)}`); + } + else { + throw new Error(`Unable to switch to user ${colors.red(name)}.`); + } + } + } + else { + this.helper.setProp("current_login", firstLogin.username); + this.helper.setProp("current_user_type", "user"); + console.log(`Switched to user ${colors.green(firstLogin.username)}`); + } + } + } + catch (e) { + console.log(this.helper.wrapError(e)); + } + }); + } + changePassword() { + return __awaiter(this, void 0, void 0, function* () { + try { + const passObj = yield this.getNewPasswordData(); + if (passObj.newPass !== passObj.rePass) { + throw new Error("Invalid retype password"); + } + const currentUser = this.helper.getProp("current_login"); + const { data } = yield this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: currentUser, password: passObj.oldPass }); + if (data) { + const result = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdPut, currentUser, { password: passObj.newPass }); + console.log("Password changed"); + } + else { + console.log("Invalid password"); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + whoami(options) { + const currentLogin = this.helper.getProp("current_login"); + const currentType = this.helper.getProp("current_user_type"); + console.log(`Current login: ${colors.green(currentLogin)}, login type: ${colors.green(currentType)}`); + } + createTeam(name) { + return __awaiter(this, void 0, void 0, function* () { + try { + const currentLogin = this.helper.getProp("current_login"); + const currentUserType = this.helper.getProp("current_user_type"); + if (currentUserType !== "user") { + throw new Error("Must be on user to do this operation"); + } + const { response } = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsPost, { username: name, password: "", roleId: "teamAdmin" }); + if (response && response.body.id) { + console.log(`Team ${colors.green(name)} created !`); + } + else { + console.log(`Team ${colors.red(name)} exist !`); + } + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + createUser(username, options) { + return __awaiter(this, void 0, void 0, function* () { + const password = yield this.helper.inquirerPrompt([ + { + type: "password", + name: "answer", + message: "password: ", + mask: "*", + default: null + } + ]); + const confirmPassword = yield this.helper.inquirerPrompt([ + { + type: "password", + name: "answer", + message: "retype password: ", + mask: "*", + default: null + } + ]); + try { + if (password.answer !== confirmPassword.answer) { + throw new Error("Invalid retype password"); + } + let role; + if (options.admin) { + role = "admin"; + } + else if (options.internal) { + role = "internalUser"; + } + else { + role = "user"; + } + const { data } = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, username); + if (data.id) { + throw new Error(`Username ${username} exist !`); + } + const newUser = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersPost, { username, password: password.answer, roleId: role }); + console.log(`New user ${colors.green(newUser.data.username)} created !`); + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + impersonate(userName) { + return __awaiter(this, void 0, void 0, function* () { + // TODO : dibuat seperti login, pake inquirer. + try { + const currentLogin = this.helper.getProp("current_login").toString(); + if (currentLogin !== "admin") { + throw new Error(`Your login status is not superadmin. You are not authorized to impersonate a user`); + } + // set currentToken header bearer token + const currentToken = this.helper.getCurrentToken().token.toString(); + this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`; + // get admin token + this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`; + // get user id from username + const id = (yield this.getUserInfo(userName)).id; + const name = (yield this.getUserInfo(userName)).name; + const email = (yield this.getUserInfo(userName)).email; + if (name && email) { + // userName is user collected input + if (userName !== name && userName !== email) { + throw new Error(`Sorry, username is not exist.`); + } + } + else { + throw new Error(`Sorry, username is not valid.`); + } + // impersonate function + const result = yield this.helper.toPromise(this.api.authApi, this.api.authApi.impersonatePost, { + userId: id, + namespace: "platform" + }); + // set value on .katajson + const impersonateToken = result.data.id.toString(); + const type = result.data.type.toString(); + this.helper.setProp("isImpersonate", true); + this.setToken({ name, type }, impersonateToken); + console.log(`Succesfully impersonate as ${colors.green(name)}`); + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + // unimpersonate command + unimpersonate() { + return __awaiter(this, void 0, void 0, function* () { + try { + const userName = this.helper.getProp("current_login").toString(); + this.helper.deleteKeyToken(userName); + const currentLogin = this.helper.getProp("current_login").toString(); + console.log(`Succesfully unimpersonate user. Now your current login is ${colors.green(currentLogin)}`); + } + catch (error) { + console.log(this.helper.wrapError(error)); + } + }); + } + setToken(userInfo, token) { + this.helper.setProp("current_login", userInfo.name); + this.helper.setProp("current_user_type", userInfo.type); + this.helper.setProp("namespace", userInfo.namespace); + const tokenProp = (this.helper.getProp("token") || {}); + tokenProp[userInfo.name] = token; + this.helper.setProp("token", tokenProp); + } + getUserTokenInfo(name) { + const tokenProp = (this.helper.getProp("token") || {}); + if (name in tokenProp) { + const userName = name.toString(); + const token = tokenProp[name].toString(); + return { + userName, + token + }; + } + } + getUserInfo(userName) { + return __awaiter(this, void 0, void 0, function* () { + // get userId from currentlogin + const { response } = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersGetInfoKeyGet, userName); + const user = response.body; + const email = user.email ? user.email.toString() : ""; + const name = user.username.toString(); + const id = user.userId.toString(); + return { + id, + name, + email, + }; + }); + } + getNewPasswordData() { + return __awaiter(this, void 0, void 0, function* () { + let oldPass; + let newPass; + let rePass; + const answer = yield inquirer.prompt([ + { + type: "password", + name: "oldPass", + message: "current password: ", + mask: "*", + when() { + return !oldPass; + }, + validate(user) { + if (!user) { + return "Password cannot be empty"; + } + return true; + } + }, + { + type: "password", + name: "newPass", + message: "new password: ", + mask: "*", + when() { + return !newPass; + }, + validate(password) { + if (!password) { + return "Password cannot be empty"; + } + return true; + } + }, + { + type: "password", + name: "rePass", + message: "retype new password: ", + mask: "*", + when() { + return !rePass; + }, + validate(password, answer) { + if (!password) { + return "Password cannot be empty"; + } + if (password !== answer.newPass) { + return "Invalid retype password"; + } + return true; + } + }, + ]); + return answer; + }); + } + forgot(username) { + return __awaiter(this, void 0, void 0, function* () { + try { + const current_login = this.helper.getProp("current_login"); + if (!current_login) { + const { response } = yield this.helper.toPromise(this.api.authApi, this.api.authApi.forgotPost, { username }); + if (response && response.body && response.body.message) { + console.log("Please check your email to reset your password."); + } + } + else { + console.log(`Please log out first`); + } + } + catch (e) { + console.error(this.helper.wrapError(e)); + } + }); + } + listTeam() { + return __awaiter(this, void 0, void 0, function* () { + try { + const current_login = this.helper.getProp("current_login"); + if (current_login) { + const { response } = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login); + const table = new Table({ + head: ["Team Name", "Projects", "Members", "Bots"], + colWidths: [50, 15, 15, 15] + }); + response.body.forEach((team) => { + table.push([team.username, team.projects, team.members, team.bots]); + }); + console.log(table.toString()); + } + else { + console.log("Please log in first"); + } + } + catch (e) { + console.error(this.helper.wrapError(e)); + } + }); + } + listTeamUser(teamName) { + return __awaiter(this, void 0, void 0, function* () { + try { + const current_login = this.helper.getProp("current_login"); + if (current_login) { + const dataTeams = yield this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login); + const teams = dataTeams.response.body; + const choices = teams.map((team) => ({ + name: team.username, + value: team.teamId + })); + let teamId = null; + if (teamName) { + const sameName = choices.find((choice) => choice.name === teamName); + if (sameName) { + teamId = sameName.value; + } + } + else { + const choice = yield inquirer.prompt([ + { + type: "list", + name: "teamId", + message: "Team:", + choices: choices + } + ]); + teamId = choice.teamId; + } + const { response } = yield this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersGet, teamId); + const table = new Table({ + head: ["Username", "Role"], + colWidths: [50, 25] + }); + response.body.forEach((user) => { + table.push([user.username, user.roleName]); + }); + console.log(table.toString()); + } + else { + console.log("Please log in first"); + } + } + catch (e) { + console.error(this.helper.wrapError(e)); + } + }); + } +} +exports.default = User; //# sourceMappingURL=user.js.map \ No newline at end of file diff --git a/lib/interfaces/main.js b/lib/interfaces/main.js index 700adff..9cc9880 100644 --- a/lib/interfaces/main.js +++ b/lib/interfaces/main.js @@ -1,3 +1,3 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); //# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c253eaf..8f0c50a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5386 +1,5386 @@ -{ - "name": "kata-cli", - "version": "2.6.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@sinonjs/commons": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz", - "integrity": "sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "@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 - }, - "@types/inquirer": { - "version": "0.0.43", - "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-0.0.43.tgz", - "integrity": "sha512-xgyfKZVMFqE8aIKy1xfFVsX2MxyXUNgjgmbF6dRbR3sL+ZM5K4ka/9L4mmTwX8eTeVYtduyXu0gUVwVJa1HbNw==", - "dev": true, - "requires": { - "@types/rx": "*", - "@types/through": "*" - } - }, - "@types/js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==", - "dev": true - }, - "@types/lodash": { - "version": "4.14.149", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", - "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", - "dev": true - }, - "@types/mocha": { - "version": "5.2.7", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", - "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", - "dev": true - }, - "@types/node": { - "version": "7.10.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-7.10.9.tgz", - "integrity": "sha512-usSpgoUsRtO5xNV5YEPU8PPnHisFx8u0rokj1BPVn/hDF7zwUDzVLiuKZM38B7z8V2111Fj6kd4rGtQFUZpNOw==", - "dev": true - }, - "@types/rx": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@types/rx/-/rx-4.1.1.tgz", - "integrity": "sha1-WY/JSla67ZdfGUV04PVy/Y5iekg=", - "dev": true, - "requires": { - "@types/rx-core": "*", - "@types/rx-core-binding": "*", - "@types/rx-lite": "*", - "@types/rx-lite-aggregates": "*", - "@types/rx-lite-async": "*", - "@types/rx-lite-backpressure": "*", - "@types/rx-lite-coincidence": "*", - "@types/rx-lite-experimental": "*", - "@types/rx-lite-joinpatterns": "*", - "@types/rx-lite-testing": "*", - "@types/rx-lite-time": "*", - "@types/rx-lite-virtualtime": "*" - } - }, - "@types/rx-core": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-core/-/rx-core-4.0.3.tgz", - "integrity": "sha1-CzNUsSOM7b4rdPYybxOdvHpZHWA=", - "dev": true - }, - "@types/rx-core-binding": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/rx-core-binding/-/rx-core-binding-4.0.4.tgz", - "integrity": "sha512-5pkfxnC4w810LqBPUwP5bg7SFR/USwhMSaAeZQQbEHeBp57pjKXRlXmqpMrLJB4y1oglR/c2502853uN0I+DAQ==", - "dev": true, - "requires": { - "@types/rx-core": "*" - } - }, - "@types/rx-lite": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/rx-lite/-/rx-lite-4.0.6.tgz", - "integrity": "sha512-oYiDrFIcor9zDm0VDUca1UbROiMYBxMLMaM6qzz4ADAfOmA9r1dYEcAFH+2fsPI5BCCjPvV9pWC3X3flbrvs7w==", - "dev": true, - "requires": { - "@types/rx-core": "*", - "@types/rx-core-binding": "*" - } - }, - "@types/rx-lite-aggregates": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-aggregates/-/rx-lite-aggregates-4.0.3.tgz", - "integrity": "sha512-MAGDAHy8cRatm94FDduhJF+iNS5//jrZ/PIfm+QYw9OCeDgbymFHChM8YVIvN2zArwsRftKgE33QfRWvQk4DPg==", - "dev": true, - "requires": { - "@types/rx-lite": "*" - } - }, - "@types/rx-lite-async": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/rx-lite-async/-/rx-lite-async-4.0.2.tgz", - "integrity": "sha512-vTEv5o8l6702ZwfAM5aOeVDfUwBSDOs+ARoGmWAKQ6LOInQ8J4/zjM7ov12fuTpktUKdMQjkeCp07Vd73mPkxw==", - "dev": true, - "requires": { - "@types/rx-lite": "*" - } - }, - "@types/rx-lite-backpressure": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-backpressure/-/rx-lite-backpressure-4.0.3.tgz", - "integrity": "sha512-Y6aIeQCtNban5XSAF4B8dffhIKu6aAy/TXFlScHzSxh6ivfQBQw6UjxyEJxIOt3IT49YkS+siuayM2H/Q0cmgA==", - "dev": true, - "requires": { - "@types/rx-lite": "*" - } - }, - "@types/rx-lite-coincidence": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-coincidence/-/rx-lite-coincidence-4.0.3.tgz", - "integrity": "sha512-1VNJqzE9gALUyMGypDXZZXzR0Tt7LC9DdAZQ3Ou/Q0MubNU35agVUNXKGHKpNTba+fr8GdIdkC26bRDqtCQBeQ==", - "dev": true, - "requires": { - "@types/rx-lite": "*" - } - }, - "@types/rx-lite-experimental": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/rx-lite-experimental/-/rx-lite-experimental-4.0.1.tgz", - "integrity": "sha1-xTL1y98/LBXaFt7Ykw0bKYQCPL0=", - "dev": true, - "requires": { - "@types/rx-lite": "*" - } - }, - "@types/rx-lite-joinpatterns": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/rx-lite-joinpatterns/-/rx-lite-joinpatterns-4.0.1.tgz", - "integrity": "sha1-9w/jcFGKhDLykVjMkv+1a05K/D4=", - "dev": true, - "requires": { - "@types/rx-lite": "*" - } - }, - "@types/rx-lite-testing": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/rx-lite-testing/-/rx-lite-testing-4.0.1.tgz", - "integrity": "sha1-IbGdEfTf1v/vWp0WSOnIh5v+Iek=", - "dev": true, - "requires": { - "@types/rx-lite-virtualtime": "*" - } - }, - "@types/rx-lite-time": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-time/-/rx-lite-time-4.0.3.tgz", - "integrity": "sha512-ukO5sPKDRwCGWRZRqPlaAU0SKVxmWwSjiOrLhoQDoWxZWg6vyB9XLEZViKOzIO6LnTIQBlk4UylYV0rnhJLxQw==", - "dev": true, - "requires": { - "@types/rx-lite": "*" - } - }, - "@types/rx-lite-virtualtime": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-virtualtime/-/rx-lite-virtualtime-4.0.3.tgz", - "integrity": "sha512-3uC6sGmjpOKatZSVHI2xB1+dedgml669ZRvqxy+WqmGJDVusOdyxcKfyzjW0P3/GrCiN4nmRkLVMhPwHCc5QLg==", - "dev": true, - "requires": { - "@types/rx-lite": "*" - } - }, - "@types/sinon": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-2.3.7.tgz", - "integrity": "sha512-w+LjztaZbgZWgt/y/VMP5BUAWLtSyoIJhXyW279hehLPyubDoBNwvhcj3WaSptcekuKYeTCVxrq60rdLc6ImJA==", - "dev": true - }, - "@types/through": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.29.tgz", - "integrity": "sha512-9a7C5VHh+1BKblaYiq+7Tfc+EOmjMdZaD1MYtkQjSoxgB69tBjW98ry6SKsi4zEIWztLOMRuL87A3bdT/Fc/4w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/uuid": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.6.tgz", - "integrity": "sha512-cCdlC/1kGEZdEglzOieLDYBxHsvEOIg7kp/2FYyVR9Pxakq+Qf/inL3RKQ+PA8gOlI/NnL+fXmQH12nwcGzsHw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "ajv": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.1.tgz", - "integrity": "sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "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==", - "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==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" - }, - "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 - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "requires": { - "lodash": "^4.17.11" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "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 - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "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" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bluebird": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" - }, - "bluebird-co": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bluebird-co/-/bluebird-co-2.2.0.tgz", - "integrity": "sha1-4KSeY7axfjTJH0izk0t2mjd/vtc=" - }, - "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 - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "catch-decorator": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/catch-decorator/-/catch-decorator-2.0.0.tgz", - "integrity": "sha512-Y4cmIy7zsYKOoYxY6U0qNxzzQiwjJuI4gdVJGcH0lKb7BZO3P/qZKWJZcE0bGICBzzGRTl7VL0R1dBiOjc5u8w==" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-table": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", - "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "requires": { - "colors": "1.0.3" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" - }, - "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" - } - }, - "codacy-coverage": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/codacy-coverage/-/codacy-coverage-2.1.1.tgz", - "integrity": "sha512-MGMkPS5d9AqQEXTZ4grn/syl/7VvOehgWTeU2B41E22q767QolclfdfadKAndL287cIPEOEdwh9JBqCwQJLtFw==", - "dev": true, - "requires": { - "bluebird": "^3.5.x", - "commander": "^2.x", - "joi": "^12.x", - "lcov-parse": "^1.x", - "lodash": "^4.17.4", - "log-driver": "^1.x", - "request": "^2.83.0", - "request-promise": "^4.x" - } - }, - "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==", - "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=" - }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-exists": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", - "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==" - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "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 - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" - }, - "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "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" - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "requires": { - "array-find-index": "^1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - }, - "deasync": { - "version": "0.1.16", - "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.16.tgz", - "integrity": "sha512-FNCjDwxGbhK+Ye8fmE3p2ahIjERhkbuwX+WVGZPtSbAh9LfE1Saa2p0l+f0t11sIlk9D8W+Bym+cDp6r5yghAQ==", - "requires": { - "bindings": "^1.5.0", - "node-addon-api": "^1.7.1" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "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=" - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.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" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", - "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "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 - }, - "get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=" - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "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" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", - "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "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 - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" - }, - "http-basic": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-2.5.1.tgz", - "integrity": "sha1-jORHvbW2xXf4pj4/p4BW7Eu02/s=", - "requires": { - "caseless": "~0.11.0", - "concat-stream": "^1.4.6", - "http-response-object": "^1.0.0" - }, - "dependencies": { - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" - } - } - }, - "http-response-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-1.1.0.tgz", - "integrity": "sha1-p8TnWq6C87tJBOT0P2FWc7TVGMM=" - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "requires": { - "repeating": "^2.0.0" - } - }, - "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==" - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-class": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz", - "integrity": "sha1-4FdFFwW7NOOePjNZjJOpg3KWtzY=" - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "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=" - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "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-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isemail": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", - "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", - "dev": true, - "requires": { - "punycode": "2.x.x" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } - }, - "joi": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-12.0.0.tgz", - "integrity": "sha512-z0FNlV4NGgjQN1fdtHYXf5kmgludM65fG/JlXzU6+rwkt9U5UWuXVYnXa2FpK0u6+qBuCmrm5byPNuiiddAHvQ==", - "dev": true, - "requires": { - "hoek": "4.x.x", - "isemail": "3.x.x", - "topo": "2.x.x" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.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": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lcov-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", - "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", - "dev": true - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "dependencies": { - "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 - } - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - }, - "log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true - }, - "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 - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, - "merapi": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/merapi/-/merapi-0.17.2.tgz", - "integrity": "sha1-Fi7IMQhiQ80vZYEykFdyLhoXVaA=", - "requires": { - "bluebird": "^3.5.0", - "bluebird-co": "^2.2.0", - "colors": "^1.1.2", - "dateformat": "^1.0.12", - "esprima": "^2.7.2", - "is-class": "0.0.4", - "lodash": "^4.1.0", - "to-snake-case": "^1.0.0" - }, - "dependencies": { - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" - } - } - }, - "merapi-proxy": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/merapi-proxy/-/merapi-proxy-0.1.8.tgz", - "integrity": "sha512-7GoXcKB4dov/yGr4I3qAdElTlQdXqaOS6m0icPzau6uBhioz30prgtQunBaQvKR5U2L+G2gc5iu7adaEmwNtSw==", - "requires": { - "async": "^2.6.0", - "bluebird": "^3.5.0", - "request": "^2.81.0", - "request-promise": "^4.2.0", - "sleep-promise": "^2.0.0", - "sync-request": "^4.0.1", - "to-camel-case": "^1.0.0", - "to-snake-case": "^1.0.0" - } - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "requires": { - "mime-db": "1.40.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" - }, - "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": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, - "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" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "mocha-lcov-reporter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mocha-lcov-reporter/-/mocha-lcov-reporter-1.3.0.tgz", - "integrity": "sha1-Rpve9PivyaEWBW8HnfYYLQr7A4Q=", - "dev": true - }, - "mocha-typescript": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/mocha-typescript/-/mocha-typescript-1.1.17.tgz", - "integrity": "sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA==", - "dev": true, - "requires": { - "@types/mocha": "^5.2.0", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "yargs": "^11.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "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.2", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", - "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", - "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-addon-api": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.1.tgz", - "integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==" - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "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=" - }, - "nyc": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.9.0.tgz", - "integrity": "sha512-w8OdJAhXL5izerzZMdqzYKMj/pgHJyY3qEPYBjLLxrhcVoHEY9pU5ENIiZyCgG9OR7x3VcUMoD40o6PtVpfR4g==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "arrify": "^1.0.1", - "caching-transform": "^1.0.0", - "convert-source-map": "^1.5.1", - "debug-log": "^1.0.1", - "default-require-extensions": "^1.0.0", - "find-cache-dir": "^0.1.1", - "find-up": "^2.1.0", - "foreground-child": "^1.5.3", - "glob": "^7.0.6", - "istanbul-lib-coverage": "^1.1.2", - "istanbul-lib-hook": "^1.1.0", - "istanbul-lib-instrument": "^1.10.0", - "istanbul-lib-report": "^1.1.3", - "istanbul-lib-source-maps": "^1.2.3", - "istanbul-reports": "^1.4.0", - "md5-hex": "^1.2.0", - "merge-source-map": "^1.1.0", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.0", - "resolve-from": "^2.0.0", - "rimraf": "^2.6.2", - "signal-exit": "^3.0.1", - "spawn-wrap": "^1.4.2", - "test-exclude": "^4.2.0", - "yargs": "11.1.0", - "yargs-parser": "^8.0.0" - }, - "dependencies": { - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "append-transform": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", - "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "atob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "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" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "caching-transform": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-1.0.1.tgz", - "integrity": "sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE=", - "dev": true, - "requires": { - "md5-hex": "^1.2.0", - "mkdirp": "^0.5.1", - "write-file-atomic": "^1.1.4" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - } - } - }, - "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 - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "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 - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "debug-log": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", - "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "default-require-extensions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", - "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", - "dev": true, - "requires": { - "strip-bom": "^2.0.0" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.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" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "mkdirp": "^0.5.1", - "pkg-dir": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", - "dev": true, - "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "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" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, - "requires": { - "async": "^1.4.0", - "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "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.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "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-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-odd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "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-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "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 - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", - "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", - "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==", - "dev": true, - "requires": { - "append-transform": "^0.4.0" - } - }, - "istanbul-lib-report": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", - "integrity": "sha512-D4jVbMDtT2dPmloPJS/rmeP626N5Pr3Rp+SovrPn1+zPChGHcggd/0sL29jnbm4oK9W0wHjCRsdch9oLd7cm6g==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^1.1.2", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" - }, - "dependencies": { - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", - "integrity": "sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.1.2", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "istanbul-reports": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.4.0.tgz", - "integrity": "sha512-OPzVo1fPZ2H+owr8q/LYKLD+vquv9Pj4F+dj808MdHbuQLD7S4ACRjcX+0Tne5Vxt2lxXvdZaL7v+FOOAV281w==", - "dev": true, - "requires": { - "handlebars": "^4.0.3" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "dependencies": { - "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 - } - } - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "md5-hex": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-1.3.0.tgz", - "integrity": "sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ=", - "dev": true, - "requires": { - "md5-o-matic": "^0.1.1" - } - }, - "md5-o-matic": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz", - "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", - "dev": true - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "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 - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "nanomatch": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-odd": "^2.0.0", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "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-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "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-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "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-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - } - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "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": "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 - }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "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 - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "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 - }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", - "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", - "dev": true, - "requires": { - "atob": "^2.0.0", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "spawn-wrap": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", - "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", - "dev": true, - "requires": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", - "signal-exit": "^3.0.2", - "which": "^1.3.0" - } - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "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" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "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-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" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.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 - }, - "test-exclude": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.1.tgz", - "integrity": "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "micromatch": "^3.1.8", - "object-assign": "^4.1.0", - "read-pkg-up": "^1.0.1", - "require-main-filename": "^1.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - } - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", - "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "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 - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - }, - "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": { - "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" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write-file-atomic": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", - "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "slide": "^1.1.5" - } - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", - "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.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", - "yargs-parser": "^9.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "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" - } - }, - "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" - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", - "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - } - } - } - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "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-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "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-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "~2.0.3" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", - "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "request-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", - "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", - "requires": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } - }, - "request-promise-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", - "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "requires": { - "lodash": "^4.17.11" - } - }, - "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": "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 - }, - "resolve": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", - "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "requires": { - "is-promise": "^2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "requires": { - "rx-lite": "*" - } - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" - }, - "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=" - }, - "sinon": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", - "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.4.0", - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/samsam": "^3.3.3", - "diff": "^3.5.0", - "lolex": "^4.2.0", - "nise": "^1.5.2", - "supports-color": "^5.5.0" - } - }, - "sleep-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sleep-promise/-/sleep-promise-2.0.0.tgz", - "integrity": "sha1-5+eY3+VsBE2oWILXbSKpmARmPEE=" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.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-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "requires": { - "get-stdin": "^4.0.1" - } - }, - "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 - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "sync-request": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-4.1.0.tgz", - "integrity": "sha512-iFbOBWYaznBNbheIKaMkj+3EabpEsXbuwcTVuYkRjoav+Om5L8VXXLIXms0cHxkouXMRCQaSfhfau9/HyIbM2Q==", - "requires": { - "command-exists": "^1.2.2", - "concat-stream": "^1.6.0", - "get-port": "^3.1.0", - "http-response-object": "^1.1.0", - "then-request": "^2.2.0" - } - }, - "then-request": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/then-request/-/then-request-2.2.0.tgz", - "integrity": "sha1-ZnizL6DKIY/laZgbvYhxtZQGDYE=", - "requires": { - "caseless": "~0.11.0", - "concat-stream": "^1.4.7", - "http-basic": "^2.5.1", - "http-response-object": "^1.1.0", - "promise": "^7.1.1", - "qs": "^6.1.0" - }, - "dependencies": { - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-camel-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz", - "integrity": "sha1-GlYFSy+daWKYzmamCJcyK29CPkY=", - "requires": { - "to-space-case": "^1.0.0" - } - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-no-case": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", - "integrity": "sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo=" - }, - "to-snake-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-snake-case/-/to-snake-case-1.0.0.tgz", - "integrity": "sha1-znRpE4l5RgGah+Yu366upMYIq4w=", - "requires": { - "to-space-case": "^1.0.0" - } - }, - "to-space-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", - "integrity": "sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc=", - "requires": { - "to-no-case": "^1.0.0" - } - }, - "topo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "ts-node": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-3.3.0.tgz", - "integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "chalk": "^2.0.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.0", - "tsconfig": "^6.0.0", - "v8flags": "^3.0.0", - "yn": "^2.0.0" - } - }, - "tsconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz", - "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", - "dev": true, - "requires": { - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true - }, - "tslint": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", - "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "diff": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", - "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", - "dev": true - } - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "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 - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "typescript": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", - "integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==", - "dev": true - }, - "universal-analytics": { - "version": "0.4.20", - "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.20.tgz", - "integrity": "sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw==", - "requires": { - "debug": "^3.0.0", - "request": "^2.88.0", - "uuid": "^3.0.0" - } - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" - }, - "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "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 - }, - "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": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", - "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.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", - "yargs-parser": "^9.0.2" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - } - } - }, - "yn": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", - "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", - "dev": true - }, - "zaun": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/zaun/-/zaun-2.4.0.tgz", - "integrity": "sha512-yg2FIUBacwSKIwlvAVPfAfU2MSzIHs2c0oB2ErExqfxfKQg2nWF5zjjnLkJpNeM5E/4gnYBe2u+F+VO9uS4v6w==", - "requires": { - "superagent": "3.8.3" - } - } - } -} +{ + "name": "kata-cli", + "version": "2.6.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@sinonjs/commons": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.6.0.tgz", + "integrity": "sha512-w4/WHG7C4WWFyE5geCieFJF6MZkbW4VAriol5KlmQXpAQdxvV0p26sqNZOW6Qyw6Y0l9K4g+cHvvczR2sEEpqg==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "@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 + }, + "@types/inquirer": { + "version": "0.0.43", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-0.0.43.tgz", + "integrity": "sha512-xgyfKZVMFqE8aIKy1xfFVsX2MxyXUNgjgmbF6dRbR3sL+ZM5K4ka/9L4mmTwX8eTeVYtduyXu0gUVwVJa1HbNw==", + "dev": true, + "requires": { + "@types/rx": "*", + "@types/through": "*" + } + }, + "@types/js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", + "dev": true + }, + "@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "@types/node": { + "version": "7.10.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-7.10.9.tgz", + "integrity": "sha512-usSpgoUsRtO5xNV5YEPU8PPnHisFx8u0rokj1BPVn/hDF7zwUDzVLiuKZM38B7z8V2111Fj6kd4rGtQFUZpNOw==", + "dev": true + }, + "@types/rx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/rx/-/rx-4.1.1.tgz", + "integrity": "sha1-WY/JSla67ZdfGUV04PVy/Y5iekg=", + "dev": true, + "requires": { + "@types/rx-core": "*", + "@types/rx-core-binding": "*", + "@types/rx-lite": "*", + "@types/rx-lite-aggregates": "*", + "@types/rx-lite-async": "*", + "@types/rx-lite-backpressure": "*", + "@types/rx-lite-coincidence": "*", + "@types/rx-lite-experimental": "*", + "@types/rx-lite-joinpatterns": "*", + "@types/rx-lite-testing": "*", + "@types/rx-lite-time": "*", + "@types/rx-lite-virtualtime": "*" + } + }, + "@types/rx-core": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-core/-/rx-core-4.0.3.tgz", + "integrity": "sha1-CzNUsSOM7b4rdPYybxOdvHpZHWA=", + "dev": true + }, + "@types/rx-core-binding": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/rx-core-binding/-/rx-core-binding-4.0.4.tgz", + "integrity": "sha512-5pkfxnC4w810LqBPUwP5bg7SFR/USwhMSaAeZQQbEHeBp57pjKXRlXmqpMrLJB4y1oglR/c2502853uN0I+DAQ==", + "dev": true, + "requires": { + "@types/rx-core": "*" + } + }, + "@types/rx-lite": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/rx-lite/-/rx-lite-4.0.6.tgz", + "integrity": "sha512-oYiDrFIcor9zDm0VDUca1UbROiMYBxMLMaM6qzz4ADAfOmA9r1dYEcAFH+2fsPI5BCCjPvV9pWC3X3flbrvs7w==", + "dev": true, + "requires": { + "@types/rx-core": "*", + "@types/rx-core-binding": "*" + } + }, + "@types/rx-lite-aggregates": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-aggregates/-/rx-lite-aggregates-4.0.3.tgz", + "integrity": "sha512-MAGDAHy8cRatm94FDduhJF+iNS5//jrZ/PIfm+QYw9OCeDgbymFHChM8YVIvN2zArwsRftKgE33QfRWvQk4DPg==", + "dev": true, + "requires": { + "@types/rx-lite": "*" + } + }, + "@types/rx-lite-async": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/rx-lite-async/-/rx-lite-async-4.0.2.tgz", + "integrity": "sha512-vTEv5o8l6702ZwfAM5aOeVDfUwBSDOs+ARoGmWAKQ6LOInQ8J4/zjM7ov12fuTpktUKdMQjkeCp07Vd73mPkxw==", + "dev": true, + "requires": { + "@types/rx-lite": "*" + } + }, + "@types/rx-lite-backpressure": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-backpressure/-/rx-lite-backpressure-4.0.3.tgz", + "integrity": "sha512-Y6aIeQCtNban5XSAF4B8dffhIKu6aAy/TXFlScHzSxh6ivfQBQw6UjxyEJxIOt3IT49YkS+siuayM2H/Q0cmgA==", + "dev": true, + "requires": { + "@types/rx-lite": "*" + } + }, + "@types/rx-lite-coincidence": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-coincidence/-/rx-lite-coincidence-4.0.3.tgz", + "integrity": "sha512-1VNJqzE9gALUyMGypDXZZXzR0Tt7LC9DdAZQ3Ou/Q0MubNU35agVUNXKGHKpNTba+fr8GdIdkC26bRDqtCQBeQ==", + "dev": true, + "requires": { + "@types/rx-lite": "*" + } + }, + "@types/rx-lite-experimental": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/rx-lite-experimental/-/rx-lite-experimental-4.0.1.tgz", + "integrity": "sha1-xTL1y98/LBXaFt7Ykw0bKYQCPL0=", + "dev": true, + "requires": { + "@types/rx-lite": "*" + } + }, + "@types/rx-lite-joinpatterns": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/rx-lite-joinpatterns/-/rx-lite-joinpatterns-4.0.1.tgz", + "integrity": "sha1-9w/jcFGKhDLykVjMkv+1a05K/D4=", + "dev": true, + "requires": { + "@types/rx-lite": "*" + } + }, + "@types/rx-lite-testing": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/rx-lite-testing/-/rx-lite-testing-4.0.1.tgz", + "integrity": "sha1-IbGdEfTf1v/vWp0WSOnIh5v+Iek=", + "dev": true, + "requires": { + "@types/rx-lite-virtualtime": "*" + } + }, + "@types/rx-lite-time": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-time/-/rx-lite-time-4.0.3.tgz", + "integrity": "sha512-ukO5sPKDRwCGWRZRqPlaAU0SKVxmWwSjiOrLhoQDoWxZWg6vyB9XLEZViKOzIO6LnTIQBlk4UylYV0rnhJLxQw==", + "dev": true, + "requires": { + "@types/rx-lite": "*" + } + }, + "@types/rx-lite-virtualtime": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-virtualtime/-/rx-lite-virtualtime-4.0.3.tgz", + "integrity": "sha512-3uC6sGmjpOKatZSVHI2xB1+dedgml669ZRvqxy+WqmGJDVusOdyxcKfyzjW0P3/GrCiN4nmRkLVMhPwHCc5QLg==", + "dev": true, + "requires": { + "@types/rx-lite": "*" + } + }, + "@types/sinon": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-2.3.7.tgz", + "integrity": "sha512-w+LjztaZbgZWgt/y/VMP5BUAWLtSyoIJhXyW279hehLPyubDoBNwvhcj3WaSptcekuKYeTCVxrq60rdLc6ImJA==", + "dev": true + }, + "@types/through": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.29.tgz", + "integrity": "sha512-9a7C5VHh+1BKblaYiq+7Tfc+EOmjMdZaD1MYtkQjSoxgB69tBjW98ry6SKsi4zEIWztLOMRuL87A3bdT/Fc/4w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/uuid": { + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.6.tgz", + "integrity": "sha512-cCdlC/1kGEZdEglzOieLDYBxHsvEOIg7kp/2FYyVR9Pxakq+Qf/inL3RKQ+PA8gOlI/NnL+fXmQH12nwcGzsHw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "ajv": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.1.tgz", + "integrity": "sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "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==", + "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==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "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 + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "requires": { + "lodash": "^4.17.11" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "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 + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "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" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" + }, + "bluebird-co": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bluebird-co/-/bluebird-co-2.2.0.tgz", + "integrity": "sha1-4KSeY7axfjTJH0izk0t2mjd/vtc=" + }, + "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 + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "catch-decorator": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/catch-decorator/-/catch-decorator-2.0.0.tgz", + "integrity": "sha512-Y4cmIy7zsYKOoYxY6U0qNxzzQiwjJuI4gdVJGcH0lKb7BZO3P/qZKWJZcE0bGICBzzGRTl7VL0R1dBiOjc5u8w==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "requires": { + "colors": "1.0.3" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + }, + "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" + } + }, + "codacy-coverage": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/codacy-coverage/-/codacy-coverage-2.1.1.tgz", + "integrity": "sha512-MGMkPS5d9AqQEXTZ4grn/syl/7VvOehgWTeU2B41E22q767QolclfdfadKAndL287cIPEOEdwh9JBqCwQJLtFw==", + "dev": true, + "requires": { + "bluebird": "^3.5.x", + "commander": "^2.x", + "joi": "^12.x", + "lcov-parse": "^1.x", + "lodash": "^4.17.4", + "log-driver": "^1.x", + "request": "^2.83.0", + "request-promise": "^4.x" + } + }, + "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==", + "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=" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "command-exists": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz", + "integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw==" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "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 + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" + }, + "core-js": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "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" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "deasync": { + "version": "0.1.16", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.16.tgz", + "integrity": "sha512-FNCjDwxGbhK+Ye8fmE3p2ahIjERhkbuwX+WVGZPtSbAh9LfE1Saa2p0l+f0t11sIlk9D8W+Bym+cDp6r5yghAQ==", + "requires": { + "bindings": "^1.5.0", + "node-addon-api": "^1.7.1" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "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=" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.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" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", + "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "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 + }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz", + "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg==" + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "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 + } + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-basic": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-2.5.1.tgz", + "integrity": "sha1-jORHvbW2xXf4pj4/p4BW7Eu02/s=", + "requires": { + "caseless": "~0.11.0", + "concat-stream": "^1.4.6", + "http-response-object": "^1.0.0" + }, + "dependencies": { + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" + } + } + }, + "http-response-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-1.1.0.tgz", + "integrity": "sha1-p8TnWq6C87tJBOT0P2FWc7TVGMM=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "^2.0.0" + } + }, + "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==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-class": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz", + "integrity": "sha1-4FdFFwW7NOOePjNZjJOpg3KWtzY=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "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=" + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "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-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "dev": true, + "requires": { + "punycode": "2.x.x" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "joi": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-12.0.0.tgz", + "integrity": "sha512-z0FNlV4NGgjQN1fdtHYXf5kmgludM65fG/JlXzU6+rwkt9U5UWuXVYnXa2FpK0u6+qBuCmrm5byPNuiiddAHvQ==", + "dev": true, + "requires": { + "hoek": "4.x.x", + "isemail": "3.x.x", + "topo": "2.x.x" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.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": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "dev": true + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "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 + } + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true + }, + "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 + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "merapi": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/merapi/-/merapi-0.17.2.tgz", + "integrity": "sha1-Fi7IMQhiQ80vZYEykFdyLhoXVaA=", + "requires": { + "bluebird": "^3.5.0", + "bluebird-co": "^2.2.0", + "colors": "^1.1.2", + "dateformat": "^1.0.12", + "esprima": "^2.7.2", + "is-class": "0.0.4", + "lodash": "^4.1.0", + "to-snake-case": "^1.0.0" + }, + "dependencies": { + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + } + } + }, + "merapi-proxy": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/merapi-proxy/-/merapi-proxy-0.1.8.tgz", + "integrity": "sha512-7GoXcKB4dov/yGr4I3qAdElTlQdXqaOS6m0icPzau6uBhioz30prgtQunBaQvKR5U2L+G2gc5iu7adaEmwNtSw==", + "requires": { + "async": "^2.6.0", + "bluebird": "^3.5.0", + "request": "^2.81.0", + "request-promise": "^4.2.0", + "sleep-promise": "^2.0.0", + "sync-request": "^4.0.1", + "to-camel-case": "^1.0.0", + "to-snake-case": "^1.0.0" + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "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": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "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" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "mocha-lcov-reporter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mocha-lcov-reporter/-/mocha-lcov-reporter-1.3.0.tgz", + "integrity": "sha1-Rpve9PivyaEWBW8HnfYYLQr7A4Q=", + "dev": true + }, + "mocha-typescript": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/mocha-typescript/-/mocha-typescript-1.1.17.tgz", + "integrity": "sha512-Ge6pCQkZumkkhxVNdAf3JxunskShgaynCb30HYD7TT1Yhog/7NW2+6w5RcRHI+nuQrCMTX6z1+qf2pD8qwCoQA==", + "dev": true, + "requires": { + "@types/mocha": "^5.2.0", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "yargs": "^11.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "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.2", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.2.tgz", + "integrity": "sha512-/6RhOUlicRCbE9s+94qCUsyE+pKlVJ5AhIv+jEE7ESKwnbXqulKZ1FYU+XAtHHWE9TinYvAxDUJAb912PwPoWA==", + "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-addon-api": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.1.tgz", + "integrity": "sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "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=" + }, + "nyc": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.9.0.tgz", + "integrity": "sha512-w8OdJAhXL5izerzZMdqzYKMj/pgHJyY3qEPYBjLLxrhcVoHEY9pU5ENIiZyCgG9OR7x3VcUMoD40o6PtVpfR4g==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "arrify": "^1.0.1", + "caching-transform": "^1.0.0", + "convert-source-map": "^1.5.1", + "debug-log": "^1.0.1", + "default-require-extensions": "^1.0.0", + "find-cache-dir": "^0.1.1", + "find-up": "^2.1.0", + "foreground-child": "^1.5.3", + "glob": "^7.0.6", + "istanbul-lib-coverage": "^1.1.2", + "istanbul-lib-hook": "^1.1.0", + "istanbul-lib-instrument": "^1.10.0", + "istanbul-lib-report": "^1.1.3", + "istanbul-lib-source-maps": "^1.2.3", + "istanbul-reports": "^1.4.0", + "md5-hex": "^1.2.0", + "merge-source-map": "^1.1.0", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.0", + "resolve-from": "^2.0.0", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.1", + "spawn-wrap": "^1.4.2", + "test-exclude": "^4.2.0", + "yargs": "11.1.0", + "yargs-parser": "^8.0.0" + }, + "dependencies": { + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "atob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "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" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "caching-transform": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-1.0.1.tgz", + "integrity": "sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE=", + "dev": true, + "requires": { + "md5-hex": "^1.2.0", + "mkdirp": "^0.5.1", + "write-file-atomic": "^1.1.4" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + } + } + }, + "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 + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "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 + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "^2.0.0" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.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" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "mkdirp": "^0.5.1", + "pkg-dir": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "dev": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "^1.4.0", + "optimist": "^0.6.1", + "source-map": "^0.4.4", + "uglify-js": "^2.6" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hosted-git-info": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "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.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "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-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "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-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "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 + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz", + "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==", + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz", + "integrity": "sha512-D4jVbMDtT2dPmloPJS/rmeP626N5Pr3Rp+SovrPn1+zPChGHcggd/0sL29jnbm4oK9W0wHjCRsdch9oLd7cm6g==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.1.2", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, + "dependencies": { + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz", + "integrity": "sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.1.2", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "istanbul-reports": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.4.0.tgz", + "integrity": "sha512-OPzVo1fPZ2H+owr8q/LYKLD+vquv9Pj4F+dj808MdHbuQLD7S4ACRjcX+0Tne5Vxt2lxXvdZaL7v+FOOAV281w==", + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "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 + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5-hex": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-1.3.0.tgz", + "integrity": "sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ=", + "dev": true, + "requires": { + "md5-o-matic": "^0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz", + "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "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 + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-odd": "^2.0.0", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "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-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "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-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "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-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + } + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "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": "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 + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "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 + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "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 + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, + "requires": { + "atob": "^2.0.0", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spawn-wrap": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", + "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", + "dev": true, + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "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" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "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-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" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.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 + }, + "test-exclude": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.1.tgz", + "integrity": "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "micromatch": "^3.1.8", + "object-assign": "^4.1.0", + "read-pkg-up": "^1.0.1", + "require-main-filename": "^1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "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 + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "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": { + "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" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.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", + "yargs-parser": "^9.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "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" + } + }, + "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" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + } + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "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-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "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-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.2.0.tgz", + "integrity": "sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", + "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "requires": { + "lodash": "^4.17.11" + } + }, + "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": "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 + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "requires": { + "is-promise": "^2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "requires": { + "rx-lite": "*" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + }, + "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=" + }, + "sinon": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.5.0.tgz", + "integrity": "sha512-AoD0oJWerp0/rY9czP/D6hDTTUYGpObhZjMpd7Cl/A6+j0xBE+ayL/ldfggkBXUs0IkvIiM1ljM8+WkOc5k78Q==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.3", + "diff": "^3.5.0", + "lolex": "^4.2.0", + "nise": "^1.5.2", + "supports-color": "^5.5.0" + } + }, + "sleep-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sleep-promise/-/sleep-promise-2.0.0.tgz", + "integrity": "sha1-5+eY3+VsBE2oWILXbSKpmARmPEE=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.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-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "^4.0.1" + } + }, + "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 + }, + "superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "sync-request": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-4.1.0.tgz", + "integrity": "sha512-iFbOBWYaznBNbheIKaMkj+3EabpEsXbuwcTVuYkRjoav+Om5L8VXXLIXms0cHxkouXMRCQaSfhfau9/HyIbM2Q==", + "requires": { + "command-exists": "^1.2.2", + "concat-stream": "^1.6.0", + "get-port": "^3.1.0", + "http-response-object": "^1.1.0", + "then-request": "^2.2.0" + } + }, + "then-request": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-2.2.0.tgz", + "integrity": "sha1-ZnizL6DKIY/laZgbvYhxtZQGDYE=", + "requires": { + "caseless": "~0.11.0", + "concat-stream": "^1.4.7", + "http-basic": "^2.5.1", + "http-response-object": "^1.1.0", + "promise": "^7.1.1", + "qs": "^6.1.0" + }, + "dependencies": { + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=" + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-camel-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz", + "integrity": "sha1-GlYFSy+daWKYzmamCJcyK29CPkY=", + "requires": { + "to-space-case": "^1.0.0" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-no-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", + "integrity": "sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo=" + }, + "to-snake-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-snake-case/-/to-snake-case-1.0.0.tgz", + "integrity": "sha1-znRpE4l5RgGah+Yu366upMYIq4w=", + "requires": { + "to-space-case": "^1.0.0" + } + }, + "to-space-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", + "integrity": "sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc=", + "requires": { + "to-no-case": "^1.0.0" + } + }, + "topo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "dev": true, + "requires": { + "hoek": "4.x.x" + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "ts-node": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-3.3.0.tgz", + "integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "chalk": "^2.0.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.0", + "tsconfig": "^6.0.0", + "v8flags": "^3.0.0", + "yn": "^2.0.0" + } + }, + "tsconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz", + "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "tslint": { + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^4.0.1", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + }, + "dependencies": { + "diff": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", + "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", + "dev": true + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "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 + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typescript": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", + "integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==", + "dev": true + }, + "universal-analytics": { + "version": "0.4.20", + "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.20.tgz", + "integrity": "sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw==", + "requires": { + "debug": "^3.0.0", + "request": "^2.88.0", + "uuid": "^3.0.0" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + }, + "v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "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 + }, + "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": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.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", + "yargs-parser": "^9.0.2" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + } + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + }, + "zaun": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/zaun/-/zaun-2.4.0.tgz", + "integrity": "sha512-yg2FIUBacwSKIwlvAVPfAfU2MSzIHs2c0oB2ErExqfxfKQg2nWF5zjjnLkJpNeM5E/4gnYBe2u+F+VO9uS4v6w==", + "requires": { + "superagent": "3.8.3" + } + } + } +} diff --git a/package.json b/package.json index 4a00073..7b7977f 100644 --- a/package.json +++ b/package.json @@ -1,80 +1,80 @@ -{ - "name": "kata-cli", - "version": "2.6.0", - "description": "Kata AI Command Line Tools", - "main": "index.js", - "bin": { - "kata": "./bin/kata.js" - }, - "directories": { - "test": "test" - }, - "scripts": { - "clean": "rm -rf ./lib", - "build": "tsc", - "test": "NODE_ENV=test mocha --recursive --compilers ts:ts-node/register --bail", - "cover": "sh bin/coverage.sh" - }, - "repository": { - "type": "git", - "url": "https://github.com/kata-ai/kata-cli.git" - }, - "keywords": [ - "cli" - ], - "nyc": { - "include": [ - "components/**/*.ts", - "components/*.ts", - "interfaces/*.ts" - ], - "exclude": [ - "node_modules" - ], - "extension": [ - ".ts" - ], - "require": [ - "ts-node/register" - ], - "reporter": [ - "json", - "html" - ], - "all": true - }, - "author": "Febry Antonius, Yoga Aliarham", - "license": "ISC", - "homepage": "https://github.com/kata-ai/kata-cli#readme", - "dependencies": { - "catch-decorator": "^2.0.0", - "cli-table": "^0.3.1", - "commander": "^2.20.3", - "deasync": "^0.1.16", - "inquirer": "^3.0.6", - "js-yaml": "^3.12.0", - "lodash": "^4.17.15", - "merapi": "^0.17.1", - "merapi-proxy": "^0.1.7", - "universal-analytics": "^0.4.20", - "uuid": "^3.3.3", - "zaun": "^2.4.0" - }, - "devDependencies": { - "@types/inquirer": "0.0.43", - "@types/js-yaml": "^3.9.0", - "@types/lodash": "^4.14.149", - "@types/node": "^7.10.9", - "@types/sinon": "^2.3.3", - "@types/uuid": "^3.4.6", - "codacy-coverage": "^2.1.1", - "mocha": "^5.2.0", - "mocha-lcov-reporter": "^1.3.0", - "mocha-typescript": "^1.1.17", - "nyc": "^11.9.0", - "sinon": "^7.5.0", - "ts-node": "^3.3.0", - "tslint": "^5.20.1", - "typescript": "^3.7.2" - } -} +{ + "name": "kata-cli", + "version": "2.6.0", + "description": "Kata AI Command Line Tools", + "main": "index.js", + "bin": { + "kata": "./bin/kata.js" + }, + "directories": { + "test": "test" + }, + "scripts": { + "clean": "rm -rf ./lib", + "build": "tsc", + "test": "NODE_ENV=test mocha --recursive --compilers ts:ts-node/register --bail", + "cover": "sh bin/coverage.sh" + }, + "repository": { + "type": "git", + "url": "https://github.com/kata-ai/kata-cli.git" + }, + "keywords": [ + "cli" + ], + "nyc": { + "include": [ + "components/**/*.ts", + "components/*.ts", + "interfaces/*.ts" + ], + "exclude": [ + "node_modules" + ], + "extension": [ + ".ts" + ], + "require": [ + "ts-node/register" + ], + "reporter": [ + "json", + "html" + ], + "all": true + }, + "author": "Febry Antonius, Yoga Aliarham", + "license": "ISC", + "homepage": "https://github.com/kata-ai/kata-cli#readme", + "dependencies": { + "catch-decorator": "^2.0.0", + "cli-table": "^0.3.1", + "commander": "^2.20.3", + "deasync": "^0.1.16", + "inquirer": "^3.0.6", + "js-yaml": "^3.12.0", + "lodash": "^4.17.15", + "merapi": "^0.17.1", + "merapi-proxy": "^0.1.7", + "universal-analytics": "^0.4.20", + "uuid": "^3.3.3", + "zaun": "^2.4.0" + }, + "devDependencies": { + "@types/inquirer": "0.0.43", + "@types/js-yaml": "^3.9.0", + "@types/lodash": "^4.14.149", + "@types/node": "^7.10.9", + "@types/sinon": "^2.3.3", + "@types/uuid": "^3.4.6", + "codacy-coverage": "^2.1.1", + "mocha": "^5.2.0", + "mocha-lcov-reporter": "^1.3.0", + "mocha-typescript": "^1.1.17", + "nyc": "^11.9.0", + "sinon": "^7.5.0", + "ts-node": "^3.3.0", + "tslint": "^5.20.1", + "typescript": "^3.7.2" + } +} diff --git a/service.yml b/service.yml index c989420..c52feb6 100644 --- a/service.yml +++ b/service.yml @@ -1,414 +1,414 @@ -schema: kata.ai/schema/merapi/1.0 - -name: ${package.name} -version: ${package.version} - -components: - # main - main: Main - - # bot management - bot: bots/Bot - channel: bots/Channel - deployment: bots/Deployment - environment: bots/Environment - session: bots/Session - - # Project managements - project: projects/Project - - # user management - user: users/User - team: users/Team - - # nlu management - nlu: nlus/Nlu - - # helper - compile: scripts/Compile - helper: scripts/Helper - tester: scripts/Tester - - # command deprecated - deprecated: deprecated/Deprecated - - # api - api: api/Api - zaun: api/Zaun - - -config: - trackingId: "UA-131926842-1" - channels: - type: - - line - - slack - - generic - - fbmessenger - - telegram - - qiscus - - twitter - - url: - line: https://api.line.me - telegram: https://api.telegram.org - fbmessenger: https://graph.facebook.com/v2.6/me/messages - slack: https://slack.com/api - qiscus: https://.qiscus.com - twitter: https://api.twitter.com - -commands: - bot: - type: group - desc: Commands for bot management - subcommands: - init: - desc: Initialize new bot.yml file - args: "" - params: - config: - type: string - desc: Parameter string - handler: bot.init - alias: init - revisions: - desc: Get list bot revision - handler: bot.revisions - alias: revisions - push: - desc: Push and update reversion bot - params: - tag: - type: string - desc: Tag version for deployment - handler: bot.push - alias: push - pull: - desc: Pull bot with specific revision - args: "[revision]" - handler: bot.pull - alias: pull - discard: - desc: Discard bot - params: - draft: - type: string - handler: bot.discard - alias: discard - console: - desc: Interactive command - params: - session: - type: string - desc: Session id to use in console - short: s - handler: bot.console - alias: console - errors: - desc: Get list error log - handler: bot.errors - alias: errors - deployment: - type: group - desc: Commands for deployment bot - subcommands: - create: - desc: Create a Deployment of the selected project - args: "[versionType]" - handler: deployment.create - alias: create-deployment - list: - desc: Get List deployment - handler: deployment.list - alias: list-deployment - rollback: - desc: Rollback deployment by bot version - args: "" - handler: deployment.rollback - alias: rollback-deployment - environment: - type: group - desc: Commands for environment bot - subcommands: - create: - desc: Create an environment on the selected project - args: "" - handler: environment.create - alias: create-environment - list: - desc: List environments of the selected project - handler: environment.list - alias: list-environment - update: - desc: Update an environment of the selected project - args: "[newDeploymentVersion]" - handler: environment.update - alias: update-environment - channels: - type: group - desc: Commands for channel - subcommands: - create: - args: "" - desc: Create a channel on the selected environment - params: - data: - type: json - desc: Channel json data - short: d - handler: channel.addChannel - alias: create-channel - list: - desc: Get list channels of the selected environment - handler: channel.list - alias: list-channel - delete: - desc: Delete a channel from the selected environment - args: "" - handler: channel.removeChannel - alias: delete-channel - update: - desc: Update a channel from selected environment - args: "" - params: - data: - type: json - desc: Channel json data - short: d - handler: channel.updateChannel - alias: update-channel - project: - type: group - desc: Commands for bot projects - subcommands: - create: - desc: Create a project - handler: project.create - alias: create-project - select: - desc: Select a project - handler: project.select - alias: select-project - list: - desc: Get list project - handler: project.list - alias: list-project - delete: - desc: Delete project by project id - args: "[projectName]" - handler: project.delete - alias: delete-project - update: - desc: Update project by project id - args: "[projectName]" - handler: project.update - alias: update-project - config: - type: group - desc: Command for config management - subcommands: - view: - desc: View config stored in .katajson file - handler: helper.viewConfig - alias: view-config - set: - type: command - desc: Command for set property value - args: " " - handler: helper.setProp - user: - type: group - desc: Commands for user management - subcommands: - createUser: - desc: Create new user - args: "" - params: - admin: - type: boolean - desc: Label admin - short: a - internal: - type: boolean - desc: Label internal - short: i - handler: user.createUser - alias: create-user - switch: - desc: Switch between team and user - args: " [name]" - handler: user.switch - alias: switch - login: - desc: Login to kata - params: - user: - type: string - desc: Username login - short: u - password: - type: string - desc: Password login - short: p - token: - type: string - desc: Token login - short: t - handler: user.login - alias: login - logout: - desc: Logout from kata - handler: user.logout - alias: logout - forgotpassword: - desc: Forgot password - args: "" - handler: user.forgot - alias: forgot-password - whoami: - desc: Identify current user - handler: user.whoami - alias: whoami - changePassword: - desc: Change current user password - handler: user.changePassword - alias: change-password - listTeam: - desc: Get list all team - handler: user.listTeam - alias: list-team - listTeamUser: - desc: Get list all team user - args: "[teamName]" - handler: user.listTeamUser - alias: list-team-user - createTeam: - desc: Create team - args: "" - handler: user.createTeam - alias: create-team - inviteMember: - desc: Invite member to team - args: "" - handler: team.addMember - params: - admin: - type: boolean - desc: Admin label for new member - short: a - alias: invite-member - impersonate: - desc: Impersonate as certain user - args: "" - handler: user.impersonate - alias: impersonate - unimpersonate: - desc: Unimpersonate current user, set back to admin - handler: user.unimpersonate - alias: unimpersonate - nlu: - type: group - desc: Command for nlu management - subcommands: - pull: - desc: Pull nlu from server - handler: nlu.pull - alias: nl-pull - push: - desc: Create or update nlu - handler: nlu.push - alias: nl-push - init: - desc: Init nlu file - handler: nlu.pull - alias: nl-init - train: - desc: Train nlu - handler: nlu.train - params: - file: - type: string - desc: File path contain data training - short: f - sentence: - type: string - desc: String to train - short: s - alias: nl-train - predict: - desc: Predict NL - handler: nlu.predict - params: - file: - type: string - desc: File path contain data to predict - short: f - sentence: - type: string - desc: String to predict - short: s - nlu: - type: string - desc: NLU to use - short: nlu - alias: nl-predict - listProfiles: - desc: Get list default profiles - handler: nlu.listProfiles - alias: list-profiles - snapshot: - desc: Snapshot profiles - handler: nlu.snapshot - alias: nl-snapshot - listTraining: - desc: Get list training - handler: nlu.listTraining - params: - page: - type: number - desc: Number page - short: p - alias: nl-list-training - listPrediction: - desc: Get list prediction log - handler: nlu.listPrediction - params: - page: - type: number - desc: Number page - short: p - alias: nl-list-prediction - listRevision: - desc: Get list revision - handler: nlu.listRevision - alias: nl-list-revision - issueToken: - desc: Issue token - handler: nlu.issueToken - alias: nl-issue-token - detail: - desc: Get NL detail - handler: nlu.detail - alias: nl-detail - deprecated: - type: group - desc: Command for deprecated management - subcommands: - addChannel: - desc: This command is deprecated, please use create-channel - handler: deprecated.addChannel - alias: add-channel - removeChannel: - desc: This command is deprecated, please use delete-channel - handler: deprecated.removeChannel - alias: remove-channel - configView: - desc: This command is deprecated, please use view-config - handler: deprecated.configView - alias: config-view - addMember: - desc: This command is deprecated, please use invite-member - handler: deprecated.addMember - alias: add-member -# entry point -main: main +schema: kata.ai/schema/merapi/1.0 + +name: ${package.name} +version: ${package.version} + +components: + # main + main: Main + + # bot management + bot: bots/Bot + channel: bots/Channel + deployment: bots/Deployment + environment: bots/Environment + session: bots/Session + + # Project managements + project: projects/Project + + # user management + user: users/User + team: users/Team + + # nlu management + nlu: nlus/Nlu + + # helper + compile: scripts/Compile + helper: scripts/Helper + tester: scripts/Tester + + # command deprecated + deprecated: deprecated/Deprecated + + # api + api: api/Api + zaun: api/Zaun + + +config: + trackingId: "UA-131926842-1" + channels: + type: + - line + - slack + - generic + - fbmessenger + - telegram + - qiscus + - twitter + + url: + line: https://api.line.me + telegram: https://api.telegram.org + fbmessenger: https://graph.facebook.com/v2.6/me/messages + slack: https://slack.com/api + qiscus: https://.qiscus.com + twitter: https://api.twitter.com + +commands: + bot: + type: group + desc: Commands for bot management + subcommands: + init: + desc: Initialize new bot.yml file + args: "" + params: + config: + type: string + desc: Parameter string + handler: bot.init + alias: init + revisions: + desc: Get list bot revision + handler: bot.revisions + alias: revisions + push: + desc: Push and update reversion bot + params: + tag: + type: string + desc: Tag version for deployment + handler: bot.push + alias: push + pull: + desc: Pull bot with specific revision + args: "[revision]" + handler: bot.pull + alias: pull + discard: + desc: Discard bot + params: + draft: + type: string + handler: bot.discard + alias: discard + console: + desc: Interactive command + params: + session: + type: string + desc: Session id to use in console + short: s + handler: bot.console + alias: console + errors: + desc: Get list error log + handler: bot.errors + alias: errors + deployment: + type: group + desc: Commands for deployment bot + subcommands: + create: + desc: Create a Deployment of the selected project + args: "[versionType]" + handler: deployment.create + alias: create-deployment + list: + desc: Get List deployment + handler: deployment.list + alias: list-deployment + rollback: + desc: Rollback deployment by bot version + args: "" + handler: deployment.rollback + alias: rollback-deployment + environment: + type: group + desc: Commands for environment bot + subcommands: + create: + desc: Create an environment on the selected project + args: "" + handler: environment.create + alias: create-environment + list: + desc: List environments of the selected project + handler: environment.list + alias: list-environment + update: + desc: Update an environment of the selected project + args: "[newDeploymentVersion]" + handler: environment.update + alias: update-environment + channels: + type: group + desc: Commands for channel + subcommands: + create: + args: "" + desc: Create a channel on the selected environment + params: + data: + type: json + desc: Channel json data + short: d + handler: channel.addChannel + alias: create-channel + list: + desc: Get list channels of the selected environment + handler: channel.list + alias: list-channel + delete: + desc: Delete a channel from the selected environment + args: "" + handler: channel.removeChannel + alias: delete-channel + update: + desc: Update a channel from selected environment + args: "" + params: + data: + type: json + desc: Channel json data + short: d + handler: channel.updateChannel + alias: update-channel + project: + type: group + desc: Commands for bot projects + subcommands: + create: + desc: Create a project + handler: project.create + alias: create-project + select: + desc: Select a project + handler: project.select + alias: select-project + list: + desc: Get list project + handler: project.list + alias: list-project + delete: + desc: Delete project by project id + args: "[projectName]" + handler: project.delete + alias: delete-project + update: + desc: Update project by project id + args: "[projectName]" + handler: project.update + alias: update-project + config: + type: group + desc: Command for config management + subcommands: + view: + desc: View config stored in .katajson file + handler: helper.viewConfig + alias: view-config + set: + type: command + desc: Command for set property value + args: " " + handler: helper.setProp + user: + type: group + desc: Commands for user management + subcommands: + createUser: + desc: Create new user + args: "" + params: + admin: + type: boolean + desc: Label admin + short: a + internal: + type: boolean + desc: Label internal + short: i + handler: user.createUser + alias: create-user + switch: + desc: Switch between team and user + args: " [name]" + handler: user.switch + alias: switch + login: + desc: Login to kata + params: + user: + type: string + desc: Username login + short: u + password: + type: string + desc: Password login + short: p + token: + type: string + desc: Token login + short: t + handler: user.login + alias: login + logout: + desc: Logout from kata + handler: user.logout + alias: logout + forgotpassword: + desc: Forgot password + args: "" + handler: user.forgot + alias: forgot-password + whoami: + desc: Identify current user + handler: user.whoami + alias: whoami + changePassword: + desc: Change current user password + handler: user.changePassword + alias: change-password + listTeam: + desc: Get list all team + handler: user.listTeam + alias: list-team + listTeamUser: + desc: Get list all team user + args: "[teamName]" + handler: user.listTeamUser + alias: list-team-user + createTeam: + desc: Create team + args: "" + handler: user.createTeam + alias: create-team + inviteMember: + desc: Invite member to team + args: "" + handler: team.addMember + params: + admin: + type: boolean + desc: Admin label for new member + short: a + alias: invite-member + impersonate: + desc: Impersonate as certain user + args: "" + handler: user.impersonate + alias: impersonate + unimpersonate: + desc: Unimpersonate current user, set back to admin + handler: user.unimpersonate + alias: unimpersonate + nlu: + type: group + desc: Command for nlu management + subcommands: + pull: + desc: Pull nlu from server + handler: nlu.pull + alias: nl-pull + push: + desc: Create or update nlu + handler: nlu.push + alias: nl-push + init: + desc: Init nlu file + handler: nlu.pull + alias: nl-init + train: + desc: Train nlu + handler: nlu.train + params: + file: + type: string + desc: File path contain data training + short: f + sentence: + type: string + desc: String to train + short: s + alias: nl-train + predict: + desc: Predict NL + handler: nlu.predict + params: + file: + type: string + desc: File path contain data to predict + short: f + sentence: + type: string + desc: String to predict + short: s + nlu: + type: string + desc: NLU to use + short: nlu + alias: nl-predict + listProfiles: + desc: Get list default profiles + handler: nlu.listProfiles + alias: list-profiles + snapshot: + desc: Snapshot profiles + handler: nlu.snapshot + alias: nl-snapshot + listTraining: + desc: Get list training + handler: nlu.listTraining + params: + page: + type: number + desc: Number page + short: p + alias: nl-list-training + listPrediction: + desc: Get list prediction log + handler: nlu.listPrediction + params: + page: + type: number + desc: Number page + short: p + alias: nl-list-prediction + listRevision: + desc: Get list revision + handler: nlu.listRevision + alias: nl-list-revision + issueToken: + desc: Issue token + handler: nlu.issueToken + alias: nl-issue-token + detail: + desc: Get NL detail + handler: nlu.detail + alias: nl-detail + deprecated: + type: group + desc: Command for deprecated management + subcommands: + addChannel: + desc: This command is deprecated, please use create-channel + handler: deprecated.addChannel + alias: add-channel + removeChannel: + desc: This command is deprecated, please use delete-channel + handler: deprecated.removeChannel + alias: remove-channel + configView: + desc: This command is deprecated, please use view-config + handler: deprecated.configView + alias: config-view + addMember: + desc: This command is deprecated, please use invite-member + handler: deprecated.addMember + alias: add-member +# entry point +main: main diff --git a/start.js b/start.js index 2688afa..8441f1d 100644 --- a/start.js +++ b/start.js @@ -1,11 +1,11 @@ -"use strict"; - -let boot = require("./index.js"); - -try { - boot.start(); -} -catch (e) { - console.log(e.stack); - process.exit(); +"use strict"; + +let boot = require("./index.js"); + +try { + boot.start(); +} +catch (e) { + console.log(e.stack); + process.exit(); } \ No newline at end of file diff --git a/test/bots/bot.spec.ts b/test/bots/bot.spec.ts index 52eb0ce..00e391d 100644 --- a/test/bots/bot.spec.ts +++ b/test/bots/bot.spec.ts @@ -1,270 +1,270 @@ -import { IConfig, Config } from "merapi"; -import { suite, test } from "mocha-typescript"; -import { safeLoad } from "js-yaml"; -import { readFileSync } from "fs"; -import { execSync } from "child_process"; -import { IHelper, ICompile, ITester } from "../../interfaces/main"; -import { stub, SinonStub, assert } from "sinon"; -import { deepEqual } from "assert"; -import Api from "../../components/api/api"; -import Bot from "../../components/bots/bot"; -import Helper from "../../components/scripts/helper"; -import Compile from "../../components/scripts/compile"; -import Tester from "../../components/scripts/tester"; -import Zaun from "../../components/api/zaun"; - -@suite class BotTest { - private config : IConfig; - private helper : IHelper; - private compile : ICompile; - private tester : ITester; - private api : any; - private bot : any; - private botDesc = { - schema: "kata.ai/schema/kata-ml/1.0", - name: "Bot Name", - desc: "My First Bot", - flows: { - hello: { - fallback: true, - intents: { - greeting: { - initial: true, - condition: "content == 'hi'" - }, - fallback: { - fallback: true - } - }, - states: { - init: { - initial: true, - transitions: { - greet: { - condition: "intent == \"greeting\"" - }, - other: { - fallback: true - } - } - }, - greet: { - end: true, - action: { - name: "text", - options: { - text: "hi!" - } - } - }, - other: { - end: true, - action: { - name: "text", - options: { - text: "sorry!" - } - } - } - } - } - }, - id: "botId" - }; - - constructor() { - const configJson = safeLoad(readFileSync("./service.yml", "utf8")); - const zaun = Zaun(); - this.config = Config.create(configJson); - this.helper = new Helper(this.config); - this.compile = new Compile(this.helper); - this.tester = new Tester(this.config, this.helper); - this.api = new Api(this.helper, zaun); - this.bot = new Bot(this.compile, this.helper, this.tester, this.api); - } - - @test public async "should call init bot successfully"() { - const createDirStub = stub(this.helper, "createDirectory"); - const dumpYamlStub = stub(this.helper, "dumpYaml"); - const consoleLogStub = stub(console, "log"); - - this.bot.init(this.botDesc.name, {}); - - const bot = Object.assign({}, this.botDesc); - delete bot.id; - - createDirStub.restore(); - dumpYamlStub.restore(); - consoleLogStub.restore(); - assert.callCount(dumpYamlStub, 1); - assert.calledWith(dumpYamlStub, "./bot.yml", bot); - assert.calledWith(consoleLogStub, "Initialized Bot Name successfully"); - } - - - @test public async "should call bot revisions successfully"() { - const consoleLogStub = stub(console, "log"); - const botApiVersions = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake(function fakeFn(botId, callback) { - callback(); - }); - - await this.bot.revisions(); - - consoleLogStub.restore(); - botApiVersions.restore(); - assert.calledOnce(botApiVersions); - } - - // TODO - @test public async "function test should call intents, states, actions, and flow test api"() { - const getFileStub = stub(this.helper, "getFiles").returns(["data1"]); - let loadYamlStub = stub(this.helper, "loadYaml").returns({ schema: "kata.ai/schema/kata-ml/1.0/test/intents" }); - const getBotIdStub = stub(this.helper, "getBotId").returns("testBotId"); - - const execIntentTestStub = stub(this.tester, "execIntentTest").returns({ results: { intents: { field: "intentsA", expect: "true", result: "true" } } }); - await this.bot.test(); - - loadYamlStub.restore(); - loadYamlStub = stub(this.helper, "loadYaml").returns({ schema: "kata.ai/schema/kata-ml/1.0/test/states" }); - const execStateTestStub = stub(this.tester, "execStateTest").returns({ results: { intents: { field: "statesA", expect: "true", result: "true" } } }); - await this.bot.test(); - - loadYamlStub.restore(); - loadYamlStub = stub(this.helper, "loadYaml").returns({ schema: "kata.ai/schema/kata-ml/1.0/test/actions" }); - const execActionsTestStub = stub(this.tester, "execActionsTest").returns({ results: { intents: { field: "actionsA", expect: "true", result: "true" } } }); - await this.bot.test(); - - loadYamlStub.restore(); - loadYamlStub = stub(this.helper, "loadYaml").returns({ schema: "kata.ai/schema/kata-ml/1.0/test/flow" }); - const execFlowTestStub = stub(this.tester, "execFlowTest").returns({ results: { intents: { field: "flowsA", expect: "true", result: "true" } } }); - await this.bot.test(); - - getBotIdStub.restore(); - getFileStub.restore(); - loadYamlStub.restore(); - execIntentTestStub.restore(); - execStateTestStub.restore(); - execActionsTestStub.restore(); - execFlowTestStub.restore(); - - - assert.calledWith(getFileStub, "./test", ".spec.yml"); - assert.calledOnce(execIntentTestStub); - assert.calledOnce(execStateTestStub); - assert.calledOnce(execActionsTestStub); - assert.calledOnce(execFlowTestStub); - } - - // @test public async "should call list bots"() { - // const botsGetStub = stub(this.api.botApi, "botsGet").callsFake(function fakeFn(opts, callback) { - // callback(); - // }); - // const consoleLogStub = stub(console, "log"); - - // await this.bot.list(); - - // botsGetStub.restore(); - // consoleLogStub.restore(); - // assert.calledOnce(botsGetStub); - // } - - @test public async "function bot push should create bot"() { - const bot = Object.assign({}, this.botDesc); - delete bot.id; - - const botObj = { - resolve: () => { }, - get: () => bot - }; - const configCreateStub = stub(Config, "create").returns({}); - const loadYamlStub = stub(this.helper, "loadYaml").returns(bot); - const getProjectStubn = stub(this.helper, "getProp").returns(bot); - const execDirectiveStub = stub(this.compile, "execDirectives").returns(botObj); - const createBotStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsPost").callsFake(function fakeFn(body, callback) { - callback(null, { revision: "aaaabbbbccccdddddeeee" }); - }); - const dumpYamlStub = stub(this.helper, "dumpYaml"); - const consoleLogStub = stub(console, "log"); - - await this.bot.push({}); - - configCreateStub.restore(); - loadYamlStub.restore(); - execDirectiveStub.restore(); - createBotStub.restore(); - dumpYamlStub.restore(); - consoleLogStub.restore(); - assert.calledOnce(createBotStub); - assert.calledWith(createBotStub, bot); - assert.calledWith(dumpYamlStub, "./bot.yml", bot); - } - - // @test public async "function bot update should call update bot api"() { - // const botObj = { - // resolve: () => { }, - // get: () => this.botDesc - // }; - // const updatedVersion = "2.0.0"; - // const configCreateStub = stub(Config, "create").returns({}); - // const loadYamlStub = stub(this.helper, "loadYaml").returns(this.botDesc); - // const execDirectiveStub = stub(this.compile, "execDirectives").returns(botObj); - // const updateBotStub = stub(this.api.botApi, "botsBotIdPut").callsFake((botId, body, opts, callback) => { - // callback(null, { version: updatedVersion }); - // }); - // const dumpYamlStub = stub(this.helper, "dumpYaml"); - // const consoleLogStub = stub(console, "log"); - - // await this.bot.update({ rev: "major" }); - - // configCreateStub.restore(); - // loadYamlStub.restore(); - // execDirectiveStub.restore(); - // updateBotStub.restore(); - // dumpYamlStub.restore(); - // consoleLogStub.restore(); - // assert.calledOnce(updateBotStub); - // assert.calledWith(configCreateStub, { ...this.botDesc, version: updatedVersion }); - // assert.calledWith(updateBotStub, this.botDesc.id, this.botDesc, {}); - // assert.calledWith(dumpYamlStub, "./bot.yml", { ...this.botDesc, version: updatedVersion }); - // } - - // @test public async "function bot delete should call delete bot api"() { - // const inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }); - // const getBotIdStub = stub(this.helper, "getBotId").returns(this.botDesc.id); - // const deleteBotStub = stub(this.api.botApi, "botsBotIdDelete").callsFake((botId, callback) => { - // callback(null, {}); - // }); - // const consoleLogStub = stub(console, "log"); - - // await this.bot.delete(); - - // inquirerPromptStub.restore(); - // getBotIdStub.restore(); - // deleteBotStub.restore(); - // consoleLogStub.restore(); - // assert.calledOnce(deleteBotStub); - // assert.calledWith(deleteBotStub, this.botDesc.id); - // } - - // @test public async "should pull bot with valid bot name"() { - // const dumpYamlStub = stub(this.helper, "dumpYaml"); - // const botsGetStub = stub(this.api.botApi, "botsGet").callsFake((body, callback) => { - // callback(null, { items: [this.botDesc] }); - // }); - // const botsBotIdGet = stub(this.api.botApi, "botsBotIdGet").callsFake((botId, callback) => { - // callback(null, this.botDesc); - // }); - // const consoleLogStub = stub(console, "log"); - - // await this.bot.pull(this.botDesc.name, this.botDesc.version, {}); - - // dumpYamlStub.restore(); - // botsGetStub.restore(); - // botsBotIdGet.restore(); - // consoleLogStub.restore(); - // assert.calledOnce(botsGetStub); - // assert.callCount(dumpYamlStub, 1); - // assert.calledWith(dumpYamlStub, "./bot.yml", this.botDesc); - // assert.calledWith(consoleLogStub, `SUCCESS PULL BOT ${this.botDesc.name} WITH VERSION ${this.botDesc.version}`); - // } -} +import { IConfig, Config } from "merapi"; +import { suite, test } from "mocha-typescript"; +import { safeLoad } from "js-yaml"; +import { readFileSync } from "fs"; +import { execSync } from "child_process"; +import { IHelper, ICompile, ITester } from "../../interfaces/main"; +import { stub, SinonStub, assert } from "sinon"; +import { deepEqual } from "assert"; +import Api from "../../components/api/api"; +import Bot from "../../components/bots/bot"; +import Helper from "../../components/scripts/helper"; +import Compile from "../../components/scripts/compile"; +import Tester from "../../components/scripts/tester"; +import Zaun from "../../components/api/zaun"; + +@suite class BotTest { + private config : IConfig; + private helper : IHelper; + private compile : ICompile; + private tester : ITester; + private api : any; + private bot : any; + private botDesc = { + schema: "kata.ai/schema/kata-ml/1.0", + name: "Bot Name", + desc: "My First Bot", + flows: { + hello: { + fallback: true, + intents: { + greeting: { + initial: true, + condition: "content == 'hi'" + }, + fallback: { + fallback: true + } + }, + states: { + init: { + initial: true, + transitions: { + greet: { + condition: "intent == \"greeting\"" + }, + other: { + fallback: true + } + } + }, + greet: { + end: true, + action: { + name: "text", + options: { + text: "hi!" + } + } + }, + other: { + end: true, + action: { + name: "text", + options: { + text: "sorry!" + } + } + } + } + } + }, + id: "botId" + }; + + constructor() { + const configJson = safeLoad(readFileSync("./service.yml", "utf8")); + const zaun = Zaun(); + this.config = Config.create(configJson); + this.helper = new Helper(this.config); + this.compile = new Compile(this.helper); + this.tester = new Tester(this.config, this.helper); + this.api = new Api(this.helper, zaun); + this.bot = new Bot(this.compile, this.helper, this.tester, this.api); + } + + @test public async "should call init bot successfully"() { + const createDirStub = stub(this.helper, "createDirectory"); + const dumpYamlStub = stub(this.helper, "dumpYaml"); + const consoleLogStub = stub(console, "log"); + + this.bot.init(this.botDesc.name, {}); + + const bot = Object.assign({}, this.botDesc); + delete bot.id; + + createDirStub.restore(); + dumpYamlStub.restore(); + consoleLogStub.restore(); + assert.callCount(dumpYamlStub, 1); + assert.calledWith(dumpYamlStub, "./bot.yml", bot); + assert.calledWith(consoleLogStub, "Initialized Bot Name successfully"); + } + + + @test public async "should call bot revisions successfully"() { + const consoleLogStub = stub(console, "log"); + const botApiVersions = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake(function fakeFn(botId, callback) { + callback(); + }); + + await this.bot.revisions(); + + consoleLogStub.restore(); + botApiVersions.restore(); + assert.calledOnce(botApiVersions); + } + + // TODO + @test public async "function test should call intents, states, actions, and flow test api"() { + const getFileStub = stub(this.helper, "getFiles").returns(["data1"]); + let loadYamlStub = stub(this.helper, "loadYaml").returns({ schema: "kata.ai/schema/kata-ml/1.0/test/intents" }); + const getBotIdStub = stub(this.helper, "getBotId").returns("testBotId"); + + const execIntentTestStub = stub(this.tester, "execIntentTest").returns({ results: { intents: { field: "intentsA", expect: "true", result: "true" } } }); + await this.bot.test(); + + loadYamlStub.restore(); + loadYamlStub = stub(this.helper, "loadYaml").returns({ schema: "kata.ai/schema/kata-ml/1.0/test/states" }); + const execStateTestStub = stub(this.tester, "execStateTest").returns({ results: { intents: { field: "statesA", expect: "true", result: "true" } } }); + await this.bot.test(); + + loadYamlStub.restore(); + loadYamlStub = stub(this.helper, "loadYaml").returns({ schema: "kata.ai/schema/kata-ml/1.0/test/actions" }); + const execActionsTestStub = stub(this.tester, "execActionsTest").returns({ results: { intents: { field: "actionsA", expect: "true", result: "true" } } }); + await this.bot.test(); + + loadYamlStub.restore(); + loadYamlStub = stub(this.helper, "loadYaml").returns({ schema: "kata.ai/schema/kata-ml/1.0/test/flow" }); + const execFlowTestStub = stub(this.tester, "execFlowTest").returns({ results: { intents: { field: "flowsA", expect: "true", result: "true" } } }); + await this.bot.test(); + + getBotIdStub.restore(); + getFileStub.restore(); + loadYamlStub.restore(); + execIntentTestStub.restore(); + execStateTestStub.restore(); + execActionsTestStub.restore(); + execFlowTestStub.restore(); + + + assert.calledWith(getFileStub, "./test", ".spec.yml"); + assert.calledOnce(execIntentTestStub); + assert.calledOnce(execStateTestStub); + assert.calledOnce(execActionsTestStub); + assert.calledOnce(execFlowTestStub); + } + + // @test public async "should call list bots"() { + // const botsGetStub = stub(this.api.botApi, "botsGet").callsFake(function fakeFn(opts, callback) { + // callback(); + // }); + // const consoleLogStub = stub(console, "log"); + + // await this.bot.list(); + + // botsGetStub.restore(); + // consoleLogStub.restore(); + // assert.calledOnce(botsGetStub); + // } + + @test public async "function bot push should create bot"() { + const bot = Object.assign({}, this.botDesc); + delete bot.id; + + const botObj = { + resolve: () => { }, + get: () => bot + }; + const configCreateStub = stub(Config, "create").returns({}); + const loadYamlStub = stub(this.helper, "loadYaml").returns(bot); + const getProjectStubn = stub(this.helper, "getProp").returns(bot); + const execDirectiveStub = stub(this.compile, "execDirectives").returns(botObj); + const createBotStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsPost").callsFake(function fakeFn(body, callback) { + callback(null, { revision: "aaaabbbbccccdddddeeee" }); + }); + const dumpYamlStub = stub(this.helper, "dumpYaml"); + const consoleLogStub = stub(console, "log"); + + await this.bot.push({}); + + configCreateStub.restore(); + loadYamlStub.restore(); + execDirectiveStub.restore(); + createBotStub.restore(); + dumpYamlStub.restore(); + consoleLogStub.restore(); + assert.calledOnce(createBotStub); + assert.calledWith(createBotStub, bot); + assert.calledWith(dumpYamlStub, "./bot.yml", bot); + } + + // @test public async "function bot update should call update bot api"() { + // const botObj = { + // resolve: () => { }, + // get: () => this.botDesc + // }; + // const updatedVersion = "2.0.0"; + // const configCreateStub = stub(Config, "create").returns({}); + // const loadYamlStub = stub(this.helper, "loadYaml").returns(this.botDesc); + // const execDirectiveStub = stub(this.compile, "execDirectives").returns(botObj); + // const updateBotStub = stub(this.api.botApi, "botsBotIdPut").callsFake((botId, body, opts, callback) => { + // callback(null, { version: updatedVersion }); + // }); + // const dumpYamlStub = stub(this.helper, "dumpYaml"); + // const consoleLogStub = stub(console, "log"); + + // await this.bot.update({ rev: "major" }); + + // configCreateStub.restore(); + // loadYamlStub.restore(); + // execDirectiveStub.restore(); + // updateBotStub.restore(); + // dumpYamlStub.restore(); + // consoleLogStub.restore(); + // assert.calledOnce(updateBotStub); + // assert.calledWith(configCreateStub, { ...this.botDesc, version: updatedVersion }); + // assert.calledWith(updateBotStub, this.botDesc.id, this.botDesc, {}); + // assert.calledWith(dumpYamlStub, "./bot.yml", { ...this.botDesc, version: updatedVersion }); + // } + + // @test public async "function bot delete should call delete bot api"() { + // const inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }); + // const getBotIdStub = stub(this.helper, "getBotId").returns(this.botDesc.id); + // const deleteBotStub = stub(this.api.botApi, "botsBotIdDelete").callsFake((botId, callback) => { + // callback(null, {}); + // }); + // const consoleLogStub = stub(console, "log"); + + // await this.bot.delete(); + + // inquirerPromptStub.restore(); + // getBotIdStub.restore(); + // deleteBotStub.restore(); + // consoleLogStub.restore(); + // assert.calledOnce(deleteBotStub); + // assert.calledWith(deleteBotStub, this.botDesc.id); + // } + + // @test public async "should pull bot with valid bot name"() { + // const dumpYamlStub = stub(this.helper, "dumpYaml"); + // const botsGetStub = stub(this.api.botApi, "botsGet").callsFake((body, callback) => { + // callback(null, { items: [this.botDesc] }); + // }); + // const botsBotIdGet = stub(this.api.botApi, "botsBotIdGet").callsFake((botId, callback) => { + // callback(null, this.botDesc); + // }); + // const consoleLogStub = stub(console, "log"); + + // await this.bot.pull(this.botDesc.name, this.botDesc.version, {}); + + // dumpYamlStub.restore(); + // botsGetStub.restore(); + // botsBotIdGet.restore(); + // consoleLogStub.restore(); + // assert.calledOnce(botsGetStub); + // assert.callCount(dumpYamlStub, 1); + // assert.calledWith(dumpYamlStub, "./bot.yml", this.botDesc); + // assert.calledWith(consoleLogStub, `SUCCESS PULL BOT ${this.botDesc.name} WITH VERSION ${this.botDesc.version}`); + // } +} diff --git a/test/bots/deployment.spec.ts b/test/bots/deployment.spec.ts index ad2bb38..c147b1f 100644 --- a/test/bots/deployment.spec.ts +++ b/test/bots/deployment.spec.ts @@ -1,203 +1,203 @@ -import { IConfigReader, ILogger, Config, IConfig } from "merapi"; -import { suite, test } from "mocha-typescript"; -import { stub, spy, assert } from "sinon"; -import { IHelper } from "../../interfaces/main"; -import { readFileSync } from "fs"; -import { safeLoad } from "js-yaml"; -import Helper from "../../components/scripts/helper"; -import Api from "../../components/api/api"; -import Deployment from "../../components/bots/deployment"; -import Zaun from "../../components/api/zaun"; -import { v4 as uuid } from "uuid"; -const Table = require("cli-table"); - -@suite class DeploymentTest { - private config: IConfig; - private helper: IHelper; - private api: any; - private deployment: any; - private emptyDeploymentObj = { - name: "test", - botId: "739b5e9f-d5e1-44b1-93a8-954d291df170", - botVersion: "1.0.5", - channels: {} - }; - private deploymentObj = { - name: "test", - botId: "739b5e9f-d5e1-44b1-93a8-954d291df170", - botVersion: "1.0.5", - channels: { - fb: "a22867dd-ce49-4afe-b7d1-3199c01e1c51", - line: "b02eb207-8f8a-480d-8c32-606b0fa7dfe7" - } - }; - private channelObj = { - name: "fb", - id: this.deploymentObj.channels.fb, - type: "messenger", - token: "tokenChannel", - refreshToken: "refreshToken", - secret: "secretKey", - url: "http://url", - webhook: "https://urlwebhook" - }; - - private channelObjWithOptions = { - name: "fb", - id: this.deploymentObj.channels.fb, - type: "messenger", - token: "tokenChannel", - refreshToken: "refreshToken", - secret: "secretKey", - url: "http://url", - additionalOptions: { botEmail: "test@test.com" }, - webhook: "https://urlwebhook" - }; - private webhook = "https://kanal.katalabs.io"; - - constructor() { - const configJson = safeLoad(readFileSync("./service.yml", "utf8")); - const zaun = Zaun(); - this.config = Config.create(configJson); - this.helper = new Helper(this.config); - this.api = new Api(this.helper, zaun); - this.deployment = new Deployment(this.helper, this.api); - } - - @test public async "function create deployment should create deployment successfully"() { - const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); - const projectId = "projectId1"; - const projectApiStub = stub(this.api.projectApi, "projectsProjectIdGet").callsFake((projectId, callback) => { - callback(null, null, { body: { project: { nluRevision: "nlurev1", botRevision: "botrev1", cmsRevision: "cmsrev1", } } }) - }); - const botRevApiStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "botrev1"} ] } }); - }); - const nluRevApiStub = stub(this.api.projectApi, "projectsProjectIdNluRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "nlurev1"} ] } }); - }); - const cmsRevApiStub = stub(this.api.projectApi, "projectsProjectIdCmsRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "cmsrev1"} ] } }); - }); - const prevDeplymentStub = stub(this.api.projectApi, "projectsProjectIdDeploymentGet").callsFake((projectId, callback) => { - callback(null, null, { body: { version: "0.0.1" } }); - }); - const deploymentApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsPost").callsFake(({}, projectId, callback) => { - callback(null, null, { body: { result: "ok" }}); - }); - - const consoleLogStub = stub(console, "log"); - - await this.deployment.create(); - - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Succesfully create Deployment to version 0.0.2"); - } - - @test public async "function create deployment with patch version should create deployment successfully"() { - const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); - const projectId = "projectId1"; - const projectApiStub = stub(this.api.projectApi, "projectsProjectIdGet").callsFake((projectId, callback) => { - callback(null, null, { body: { project: { nluRevision: "nlurev1", botRevision: "botrev1", cmsRevision: "cmsrev1", } } }) - }); - const botRevApiStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "botrev1"} ] } }); - }); - const nluRevApiStub = stub(this.api.projectApi, "projectsProjectIdNluRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "nlurev1"} ] } }); - }); - const cmsRevApiStub = stub(this.api.projectApi, "projectsProjectIdCmsRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "cmsrev1"} ] } }); - }); - const prevDeplymentStub = stub(this.api.projectApi, "projectsProjectIdDeploymentGet").callsFake((projectId, callback) => { - callback(null, null, { body: { version: "0.0.1" } }); - }); - const deploymentApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsPost").callsFake(({}, projectId, callback) => { - callback(null, null, { body: { result: "ok" }}); - }); - - const consoleLogStub = stub(console, "log"); - - await this.deployment.create("patch"); - - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Succesfully create Deployment to version 0.0.2"); - } - - @test public async "function create deployment with minor version should create deployment successfully"() { - const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); - const projectId = "projectId1"; - const projectApiStub = stub(this.api.projectApi, "projectsProjectIdGet").callsFake((projectId, callback) => { - callback(null, null, { body: { project: { nluRevision: "nlurev1", botRevision: "botrev1", cmsRevision: "cmsrev1", } } }) - }); - const botRevApiStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "botrev1"} ] } }); - }); - const nluRevApiStub = stub(this.api.projectApi, "projectsProjectIdNluRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "nlurev1"} ] } }); - }); - const cmsRevApiStub = stub(this.api.projectApi, "projectsProjectIdCmsRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "cmsrev1"} ] } }); - }); - const prevDeplymentStub = stub(this.api.projectApi, "projectsProjectIdDeploymentGet").callsFake((projectId, callback) => { - callback(null, null, { body: { version: "0.0.1" } }); - }); - const deploymentApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsPost").callsFake(({}, projectId, callback) => { - callback(null, null, { body: { result: "ok" }}); - }); - - const consoleLogStub = stub(console, "log"); - - await this.deployment.create("minor"); - - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Succesfully create Deployment to version 0.1.0"); - } - - @test public async "function create deployment with major version should create deployment successfully"() { - const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); - const projectId = "projectId1"; - const projectApiStub = stub(this.api.projectApi, "projectsProjectIdGet").callsFake((projectId, callback) => { - callback(null, null, { body: { project: { nluRevision: "nlurev1", botRevision: "botrev1", cmsRevision: "cmsrev1", } } }) - }); - const botRevApiStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "botrev1"} ] } }); - }); - const nluRevApiStub = stub(this.api.projectApi, "projectsProjectIdNluRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "nlurev1"} ] } }); - }); - const cmsRevApiStub = stub(this.api.projectApi, "projectsProjectIdCmsRevisionsGet").callsFake((projectId, callback) => { - callback(null, null, { body: { data: [ {revision: "cmsrev1"} ] } }); - }); - const prevDeplymentStub = stub(this.api.projectApi, "projectsProjectIdDeploymentGet").callsFake((projectId, callback) => { - callback(null, null, { body: { version: "0.0.1" } }); - }); - const deploymentApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsPost").callsFake(({}, projectId, callback) => { - callback(null, null, { body: { result: "ok" }}); - }); - - const consoleLogStub = stub(console, "log"); - - await this.deployment.create("major"); - - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Succesfully create Deployment to version 1.0.0"); - } - - @test public async "function list deployment should list deployment successfully"() { - const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); - const projectId = "projectId1"; - const projectApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsGet").callsFake((projectId, {}, callback) => { - callback(null, null, { body: { data: [{ name: "depl01", version: "0.0.1", botRevision: "ah42das", }] } }) - }); - - const consoleErrorStub = stub(console, "error"); - const consoleLogStub = stub(console, "log"); - await this.deployment.list(); - consoleErrorStub.restore(); - consoleLogStub.restore(); - assert.notCalled(consoleErrorStub); - } - - -} +import { IConfigReader, ILogger, Config, IConfig } from "merapi"; +import { suite, test } from "mocha-typescript"; +import { stub, spy, assert } from "sinon"; +import { IHelper } from "../../interfaces/main"; +import { readFileSync } from "fs"; +import { safeLoad } from "js-yaml"; +import Helper from "../../components/scripts/helper"; +import Api from "../../components/api/api"; +import Deployment from "../../components/bots/deployment"; +import Zaun from "../../components/api/zaun"; +import { v4 as uuid } from "uuid"; +const Table = require("cli-table"); + +@suite class DeploymentTest { + private config: IConfig; + private helper: IHelper; + private api: any; + private deployment: any; + private emptyDeploymentObj = { + name: "test", + botId: "739b5e9f-d5e1-44b1-93a8-954d291df170", + botVersion: "1.0.5", + channels: {} + }; + private deploymentObj = { + name: "test", + botId: "739b5e9f-d5e1-44b1-93a8-954d291df170", + botVersion: "1.0.5", + channels: { + fb: "a22867dd-ce49-4afe-b7d1-3199c01e1c51", + line: "b02eb207-8f8a-480d-8c32-606b0fa7dfe7" + } + }; + private channelObj = { + name: "fb", + id: this.deploymentObj.channels.fb, + type: "messenger", + token: "tokenChannel", + refreshToken: "refreshToken", + secret: "secretKey", + url: "http://url", + webhook: "https://urlwebhook" + }; + + private channelObjWithOptions = { + name: "fb", + id: this.deploymentObj.channels.fb, + type: "messenger", + token: "tokenChannel", + refreshToken: "refreshToken", + secret: "secretKey", + url: "http://url", + additionalOptions: { botEmail: "test@test.com" }, + webhook: "https://urlwebhook" + }; + private webhook = "https://kanal.katalabs.io"; + + constructor() { + const configJson = safeLoad(readFileSync("./service.yml", "utf8")); + const zaun = Zaun(); + this.config = Config.create(configJson); + this.helper = new Helper(this.config); + this.api = new Api(this.helper, zaun); + this.deployment = new Deployment(this.helper, this.api); + } + + @test public async "function create deployment should create deployment successfully"() { + const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); + const projectId = "projectId1"; + const projectApiStub = stub(this.api.projectApi, "projectsProjectIdGet").callsFake((projectId, callback) => { + callback(null, null, { body: { project: { nluRevision: "nlurev1", botRevision: "botrev1", cmsRevision: "cmsrev1", } } }) + }); + const botRevApiStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "botrev1"} ] } }); + }); + const nluRevApiStub = stub(this.api.projectApi, "projectsProjectIdNluRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "nlurev1"} ] } }); + }); + const cmsRevApiStub = stub(this.api.projectApi, "projectsProjectIdCmsRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "cmsrev1"} ] } }); + }); + const prevDeplymentStub = stub(this.api.projectApi, "projectsProjectIdDeploymentGet").callsFake((projectId, callback) => { + callback(null, null, { body: { version: "0.0.1" } }); + }); + const deploymentApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsPost").callsFake(({}, projectId, callback) => { + callback(null, null, { body: { result: "ok" }}); + }); + + const consoleLogStub = stub(console, "log"); + + await this.deployment.create(); + + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Succesfully create Deployment to version 0.0.2"); + } + + @test public async "function create deployment with patch version should create deployment successfully"() { + const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); + const projectId = "projectId1"; + const projectApiStub = stub(this.api.projectApi, "projectsProjectIdGet").callsFake((projectId, callback) => { + callback(null, null, { body: { project: { nluRevision: "nlurev1", botRevision: "botrev1", cmsRevision: "cmsrev1", } } }) + }); + const botRevApiStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "botrev1"} ] } }); + }); + const nluRevApiStub = stub(this.api.projectApi, "projectsProjectIdNluRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "nlurev1"} ] } }); + }); + const cmsRevApiStub = stub(this.api.projectApi, "projectsProjectIdCmsRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "cmsrev1"} ] } }); + }); + const prevDeplymentStub = stub(this.api.projectApi, "projectsProjectIdDeploymentGet").callsFake((projectId, callback) => { + callback(null, null, { body: { version: "0.0.1" } }); + }); + const deploymentApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsPost").callsFake(({}, projectId, callback) => { + callback(null, null, { body: { result: "ok" }}); + }); + + const consoleLogStub = stub(console, "log"); + + await this.deployment.create("patch"); + + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Succesfully create Deployment to version 0.0.2"); + } + + @test public async "function create deployment with minor version should create deployment successfully"() { + const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); + const projectId = "projectId1"; + const projectApiStub = stub(this.api.projectApi, "projectsProjectIdGet").callsFake((projectId, callback) => { + callback(null, null, { body: { project: { nluRevision: "nlurev1", botRevision: "botrev1", cmsRevision: "cmsrev1", } } }) + }); + const botRevApiStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "botrev1"} ] } }); + }); + const nluRevApiStub = stub(this.api.projectApi, "projectsProjectIdNluRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "nlurev1"} ] } }); + }); + const cmsRevApiStub = stub(this.api.projectApi, "projectsProjectIdCmsRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "cmsrev1"} ] } }); + }); + const prevDeplymentStub = stub(this.api.projectApi, "projectsProjectIdDeploymentGet").callsFake((projectId, callback) => { + callback(null, null, { body: { version: "0.0.1" } }); + }); + const deploymentApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsPost").callsFake(({}, projectId, callback) => { + callback(null, null, { body: { result: "ok" }}); + }); + + const consoleLogStub = stub(console, "log"); + + await this.deployment.create("minor"); + + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Succesfully create Deployment to version 0.1.0"); + } + + @test public async "function create deployment with major version should create deployment successfully"() { + const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); + const projectId = "projectId1"; + const projectApiStub = stub(this.api.projectApi, "projectsProjectIdGet").callsFake((projectId, callback) => { + callback(null, null, { body: { project: { nluRevision: "nlurev1", botRevision: "botrev1", cmsRevision: "cmsrev1", } } }) + }); + const botRevApiStub = stub(this.api.botApi, "projectsProjectIdBotRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "botrev1"} ] } }); + }); + const nluRevApiStub = stub(this.api.projectApi, "projectsProjectIdNluRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "nlurev1"} ] } }); + }); + const cmsRevApiStub = stub(this.api.projectApi, "projectsProjectIdCmsRevisionsGet").callsFake((projectId, callback) => { + callback(null, null, { body: { data: [ {revision: "cmsrev1"} ] } }); + }); + const prevDeplymentStub = stub(this.api.projectApi, "projectsProjectIdDeploymentGet").callsFake((projectId, callback) => { + callback(null, null, { body: { version: "0.0.1" } }); + }); + const deploymentApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsPost").callsFake(({}, projectId, callback) => { + callback(null, null, { body: { result: "ok" }}); + }); + + const consoleLogStub = stub(console, "log"); + + await this.deployment.create("major"); + + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Succesfully create Deployment to version 1.0.0"); + } + + @test public async "function list deployment should list deployment successfully"() { + const projectIdStub = stub(this.helper, "getProjectId").returns("projectId1"); + const projectId = "projectId1"; + const projectApiStub = stub(this.api.deploymentApi, "projectsProjectIdDeploymentVersionsGet").callsFake((projectId, {}, callback) => { + callback(null, null, { body: { data: [{ name: "depl01", version: "0.0.1", botRevision: "ah42das", }] } }) + }); + + const consoleErrorStub = stub(console, "error"); + const consoleLogStub = stub(console, "log"); + await this.deployment.list(); + consoleErrorStub.restore(); + consoleLogStub.restore(); + assert.notCalled(consoleErrorStub); + } + + +} diff --git a/test/users/team.spec.ts b/test/users/team.spec.ts index 6277c8b..a6d2210 100644 --- a/test/users/team.spec.ts +++ b/test/users/team.spec.ts @@ -1,232 +1,232 @@ -import { IConfigReader, IConfig, Config } from "merapi"; -import { suite, test } from "mocha-typescript"; -import { spy, stub, assert } from "sinon"; -import { IHelper } from "../../interfaces/main"; -import { readFileSync } from "fs"; -import { safeLoad } from "js-yaml"; -import Helper from "../../components/scripts/helper"; -import Zaun from "../../components/api/zaun"; -import Api from "../../components/api/api"; -import Team from "../../components/users/team"; - -@suite class TeamTest { - private config: IConfig; - private helper: IHelper; - private api: any; - private session: any; - private team: any; - - private userTokenObj = { - id: '84330d2b-f2f8-499c-adee-99d2c533e7d5', - type: 'user', - label: 'dashboard', - userId: '5c0a78c2-3a2c-447a-80d2-069761be3ef9', - teamId: null, - botId: null, - roleId: 'ccd9b640-93c4-43b6-8523-f324f89faad6', - expire: 1503789662 - }; - private teamTokenObj = { - id: 'ea43b3b6-3c7f-4bd8-98f3-e58ee699b5b3', - type: 'team', - label: null, - userId: '8a62686d-695c-44f0-a57c-4ca19f5bf78b', - teamId: 'e563ec87-dae9-45f0-a2b3-515a069fb2b0', - botId: null, - roleId: '81b179bc-fa56-4c27-92db-a1602abe48c2', - expire: 1506907823 - }; - private userObj = { - id: '9ad603b7-5c33-432c-9752-2f4816b6bd9f', - type: 'user2', - label: 'dashboard', - userId: '05c7f7a7-fba6-437a-8e6d-72c9f71c6352', - roleId: 'b3941608-1494-4983-9b64-af746b601190', - expire: 1506915325 - } - private teamObj = { - id: 'e563ec87-dae9-45f0-a2b3-515a069fb2b0', - username: 'team1', - password: 'password', - type: 'team', - email: null, - profile: null, - roleId: '55f7d797-a938-4f59-9c6a-cf6cd8a01d08', - created_at: '2017-06-18T01:46:13.000Z', - updated_at: '2017-06-18T01:46:13.000Z' - } - - constructor() { - let zaun = Zaun(); - let configJson = safeLoad(readFileSync("./service.yml", "utf8")); - this.config = Config.create(configJson); - this.helper = new Helper(this.config); - this.api = new Api(this.helper, zaun); - this.team = new Team(this.helper, this.api); - } - - @test async "function add member should add member successfully"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); - let teamPostStub = stub(this.api.teamApi, "teamsTeamIdUsersUserIdPost"); - let teamGetStub = stub(this.api.teamApi, "teamsTeamIdUsersGet"); - - getPropStub.withArgs("current_login").returns("team1"); - getPropStub.withArgs("current_user_type").returns("team"); - getUserInfoStub.withArgs("team1").callsFake((userId, callback) => { - callback(null, this.teamObj, { body: this.teamObj }); - }); - getUserInfoStub.withArgs("user2").callsFake((userId, callback) => { - callback(null, this.userObj, { body: this.userObj }); - }); - teamGetStub.callsFake((teamId, callback) => { - callback(null, null, {body: [{userId: "anotherUserId"}]}); - }); - teamPostStub.callsFake((teamId, userId, roleId, callback) => { - callback(null, null, {body: {team: this.teamObj}}); - }) - - await this.team.addMember("user2", "roleId-test"); - - setPropStub.restore(); - getPropStub.restore(); - getUserInfoStub.restore(); - teamGetStub.restore(); - teamPostStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Success register user2 to team1"); - } - - @test async "function add member should throw error when current login is user"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - - getPropStub.withArgs("current_login").returns("user1"); - getPropStub.withArgs("current_user_type").returns("user"); - - await this.team.addMember("user2", "roleId-test"); - - setPropStub.restore(); - getPropStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Must be on team to do this operation"); - } - - @test async "function add member should throw error when username is already in team"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); - let teamGetStub = stub(this.api.teamApi, "teamsTeamIdUsersGet"); - - getPropStub.withArgs("current_login").returns("team1"); - getPropStub.withArgs("current_user_type").returns("team"); - getUserInfoStub.withArgs("team1").callsFake((userId, callback) => { - callback(null, this.teamObj, { body: this.teamObj }); - }); - getUserInfoStub.withArgs("user2").callsFake((userId, callback) => { - callback(null, this.userObj, { body: this.userObj }); - }); - teamGetStub.callsFake((teamId, callback) => { - callback(null, null, {body: [{userId: this.userObj.id}]}); - }); - - await this.team.addMember("user2", "roleId-test"); - - setPropStub.restore(); - getPropStub.restore(); - getUserInfoStub.restore(); - teamGetStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "User user2 already on this team"); - } - - @test async "function remove member should remove member successfully"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); - let teamDeleteStub = stub(this.api.teamApi, "teamsTeamIdUsersUserIdDelete"); - let teamGetStub = stub(this.api.teamApi, "teamsTeamIdUsersGet"); - let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }) - - getPropStub.withArgs("current_login").returns("team1"); - getPropStub.withArgs("current_user_type").returns("team"); - getUserInfoStub.withArgs("team1").callsFake((userId, callback) => { - callback(null, this.teamObj, { body: this.teamObj }); - }); - getUserInfoStub.withArgs("user2").callsFake((userId, callback) => { - callback(null, this.userObj, { body: this.userObj }); - }); - teamGetStub.callsFake((teamId, callback) => { - callback(null, null, {body: [{userId: this.userObj.id}]}); - }); - teamDeleteStub.callsFake((teamId, userId, callback) => { - callback(null, null, {body: {team: this.teamObj}}); - }) - - await this.team.removeMember("user2"); - - setPropStub.restore(); - getPropStub.restore(); - getUserInfoStub.restore(); - teamGetStub.restore(); - teamDeleteStub.restore(); - consoleLogStub.restore(); - inquirerPromptStub.restore(); - assert.calledWith(consoleLogStub, "Success remove user2 from team1"); - } - - @test async "function remove member should throw error when current login is user"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }) - - getPropStub.withArgs("current_login").returns("user1"); - getPropStub.withArgs("current_user_type").returns("user"); - - await this.team.removeMember("user2"); - - setPropStub.restore(); - getPropStub.restore(); - consoleLogStub.restore(); - inquirerPromptStub.restore(); - assert.calledWith(consoleLogStub, "Must be on team to do this operation"); - } - - @test async "function remove member should throw error when username is not member of the team"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); - let teamGetStub = stub(this.api.teamApi, "teamsTeamIdUsersGet"); - let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }) - - getPropStub.withArgs("current_login").returns("team1"); - getPropStub.withArgs("current_user_type").returns("team"); - getUserInfoStub.withArgs("team1").callsFake((userId, callback) => { - callback(null, this.teamObj, { body: this.teamObj }); - }); - getUserInfoStub.withArgs("user2").callsFake((userId, callback) => { - callback(null, this.userObj, { body: this.userObj }); - }); - teamGetStub.callsFake((teamId, callback) => { - callback(null, null, {body: [{userId: "anotherUserId"}]}); - }); - - await this.team.removeMember("user2"); - - setPropStub.restore(); - getPropStub.restore(); - getUserInfoStub.restore(); - teamGetStub.restore(); - consoleLogStub.restore(); - inquirerPromptStub.restore(); - assert.calledWith(consoleLogStub, "User user2 not a member of this team"); - } - +import { IConfigReader, IConfig, Config } from "merapi"; +import { suite, test } from "mocha-typescript"; +import { spy, stub, assert } from "sinon"; +import { IHelper } from "../../interfaces/main"; +import { readFileSync } from "fs"; +import { safeLoad } from "js-yaml"; +import Helper from "../../components/scripts/helper"; +import Zaun from "../../components/api/zaun"; +import Api from "../../components/api/api"; +import Team from "../../components/users/team"; + +@suite class TeamTest { + private config: IConfig; + private helper: IHelper; + private api: any; + private session: any; + private team: any; + + private userTokenObj = { + id: '84330d2b-f2f8-499c-adee-99d2c533e7d5', + type: 'user', + label: 'dashboard', + userId: '5c0a78c2-3a2c-447a-80d2-069761be3ef9', + teamId: null, + botId: null, + roleId: 'ccd9b640-93c4-43b6-8523-f324f89faad6', + expire: 1503789662 + }; + private teamTokenObj = { + id: 'ea43b3b6-3c7f-4bd8-98f3-e58ee699b5b3', + type: 'team', + label: null, + userId: '8a62686d-695c-44f0-a57c-4ca19f5bf78b', + teamId: 'e563ec87-dae9-45f0-a2b3-515a069fb2b0', + botId: null, + roleId: '81b179bc-fa56-4c27-92db-a1602abe48c2', + expire: 1506907823 + }; + private userObj = { + id: '9ad603b7-5c33-432c-9752-2f4816b6bd9f', + type: 'user2', + label: 'dashboard', + userId: '05c7f7a7-fba6-437a-8e6d-72c9f71c6352', + roleId: 'b3941608-1494-4983-9b64-af746b601190', + expire: 1506915325 + } + private teamObj = { + id: 'e563ec87-dae9-45f0-a2b3-515a069fb2b0', + username: 'team1', + password: 'password', + type: 'team', + email: null, + profile: null, + roleId: '55f7d797-a938-4f59-9c6a-cf6cd8a01d08', + created_at: '2017-06-18T01:46:13.000Z', + updated_at: '2017-06-18T01:46:13.000Z' + } + + constructor() { + let zaun = Zaun(); + let configJson = safeLoad(readFileSync("./service.yml", "utf8")); + this.config = Config.create(configJson); + this.helper = new Helper(this.config); + this.api = new Api(this.helper, zaun); + this.team = new Team(this.helper, this.api); + } + + @test async "function add member should add member successfully"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); + let teamPostStub = stub(this.api.teamApi, "teamsTeamIdUsersUserIdPost"); + let teamGetStub = stub(this.api.teamApi, "teamsTeamIdUsersGet"); + + getPropStub.withArgs("current_login").returns("team1"); + getPropStub.withArgs("current_user_type").returns("team"); + getUserInfoStub.withArgs("team1").callsFake((userId, callback) => { + callback(null, this.teamObj, { body: this.teamObj }); + }); + getUserInfoStub.withArgs("user2").callsFake((userId, callback) => { + callback(null, this.userObj, { body: this.userObj }); + }); + teamGetStub.callsFake((teamId, callback) => { + callback(null, null, {body: [{userId: "anotherUserId"}]}); + }); + teamPostStub.callsFake((teamId, userId, roleId, callback) => { + callback(null, null, {body: {team: this.teamObj}}); + }) + + await this.team.addMember("user2", "roleId-test"); + + setPropStub.restore(); + getPropStub.restore(); + getUserInfoStub.restore(); + teamGetStub.restore(); + teamPostStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Success register user2 to team1"); + } + + @test async "function add member should throw error when current login is user"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + + getPropStub.withArgs("current_login").returns("user1"); + getPropStub.withArgs("current_user_type").returns("user"); + + await this.team.addMember("user2", "roleId-test"); + + setPropStub.restore(); + getPropStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Must be on team to do this operation"); + } + + @test async "function add member should throw error when username is already in team"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); + let teamGetStub = stub(this.api.teamApi, "teamsTeamIdUsersGet"); + + getPropStub.withArgs("current_login").returns("team1"); + getPropStub.withArgs("current_user_type").returns("team"); + getUserInfoStub.withArgs("team1").callsFake((userId, callback) => { + callback(null, this.teamObj, { body: this.teamObj }); + }); + getUserInfoStub.withArgs("user2").callsFake((userId, callback) => { + callback(null, this.userObj, { body: this.userObj }); + }); + teamGetStub.callsFake((teamId, callback) => { + callback(null, null, {body: [{userId: this.userObj.id}]}); + }); + + await this.team.addMember("user2", "roleId-test"); + + setPropStub.restore(); + getPropStub.restore(); + getUserInfoStub.restore(); + teamGetStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "User user2 already on this team"); + } + + @test async "function remove member should remove member successfully"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); + let teamDeleteStub = stub(this.api.teamApi, "teamsTeamIdUsersUserIdDelete"); + let teamGetStub = stub(this.api.teamApi, "teamsTeamIdUsersGet"); + let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }) + + getPropStub.withArgs("current_login").returns("team1"); + getPropStub.withArgs("current_user_type").returns("team"); + getUserInfoStub.withArgs("team1").callsFake((userId, callback) => { + callback(null, this.teamObj, { body: this.teamObj }); + }); + getUserInfoStub.withArgs("user2").callsFake((userId, callback) => { + callback(null, this.userObj, { body: this.userObj }); + }); + teamGetStub.callsFake((teamId, callback) => { + callback(null, null, {body: [{userId: this.userObj.id}]}); + }); + teamDeleteStub.callsFake((teamId, userId, callback) => { + callback(null, null, {body: {team: this.teamObj}}); + }) + + await this.team.removeMember("user2"); + + setPropStub.restore(); + getPropStub.restore(); + getUserInfoStub.restore(); + teamGetStub.restore(); + teamDeleteStub.restore(); + consoleLogStub.restore(); + inquirerPromptStub.restore(); + assert.calledWith(consoleLogStub, "Success remove user2 from team1"); + } + + @test async "function remove member should throw error when current login is user"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }) + + getPropStub.withArgs("current_login").returns("user1"); + getPropStub.withArgs("current_user_type").returns("user"); + + await this.team.removeMember("user2"); + + setPropStub.restore(); + getPropStub.restore(); + consoleLogStub.restore(); + inquirerPromptStub.restore(); + assert.calledWith(consoleLogStub, "Must be on team to do this operation"); + } + + @test async "function remove member should throw error when username is not member of the team"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); + let teamGetStub = stub(this.api.teamApi, "teamsTeamIdUsersGet"); + let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }) + + getPropStub.withArgs("current_login").returns("team1"); + getPropStub.withArgs("current_user_type").returns("team"); + getUserInfoStub.withArgs("team1").callsFake((userId, callback) => { + callback(null, this.teamObj, { body: this.teamObj }); + }); + getUserInfoStub.withArgs("user2").callsFake((userId, callback) => { + callback(null, this.userObj, { body: this.userObj }); + }); + teamGetStub.callsFake((teamId, callback) => { + callback(null, null, {body: [{userId: "anotherUserId"}]}); + }); + + await this.team.removeMember("user2"); + + setPropStub.restore(); + getPropStub.restore(); + getUserInfoStub.restore(); + teamGetStub.restore(); + consoleLogStub.restore(); + inquirerPromptStub.restore(); + assert.calledWith(consoleLogStub, "User user2 not a member of this team"); + } + } \ No newline at end of file diff --git a/test/users/user.spec.ts b/test/users/user.spec.ts index ad36c93..f4e8283 100644 --- a/test/users/user.spec.ts +++ b/test/users/user.spec.ts @@ -1,368 +1,368 @@ -// tslint:disable:member-access -import { readFileSync } from "fs"; -import { safeLoad } from "js-yaml"; -import { Config, IConfig } from "merapi"; -import { suite, test } from "mocha-typescript"; -import { assert, stub } from "sinon"; -import Api from "../../components/api/api"; -import Zaun from "../../components/api/zaun"; -import Helper from "../../components/scripts/helper"; -import User from "../../components/users/user"; -import { IHelper } from "../../interfaces/main"; - -@suite class UserTest { - private config: IConfig; - private helper: IHelper; - private api: any; - private user: any; - - private userTokenObj = { - id: '84330d2b-f2f8-499c-adee-99d2c533e7d5', - type: 'user', - label: 'dashboard', - userId: '5c0a78c2-3a2c-447a-80d2-069761be3ef9', - teamId: null, - botId: null, - roleId: 'ccd9b640-93c4-43b6-8523-f324f89faad6', - expire: 1503789662 - }; - private teamTokenObj = { - id: 'ea43b3b6-3c7f-4bd8-98f3-e58ee699b5b3', - type: 'team', - label: null, - userId: '8a62686d-695c-44f0-a57c-4ca19f5bf78b', - teamId: 'e563ec87-dae9-45f0-a2b3-515a069fb2b0', - botId: null, - roleId: '81b179bc-fa56-4c27-92db-a1602abe48c2', - expire: 1506907823 - }; - private userObj = { - id: '9ad603b7-5c33-432c-9752-2f4816b6bd9f', - type: 'user', - label: 'dashboard', - userId: '05c7f7a7-fba6-437a-8e6d-72c9f71c6352', - roleId: 'b3941608-1494-4983-9b64-af746b601190', - expire: 1506915325 - } - private teamObj = { - id: "e563ec87-dae9-45f0-a2b3-515a069fb2b0", - username: "user1", - password: "password", - type: "team", - email: null as string, - profile: null as string, - roleId: "55f7d797-a938-4f59-9c6a-cf6cd8a01d08", - created_at: "2017-06-18T01:46:13.000Z", - updated_at: "2017-06-18T01:46:13.000Z", - teams: [{ teamId: "e563ec87-dae9-45f0-a2b3-515a069fb2b0", username: "team1" }] as any[] - }; - - constructor() { - let zaun = Zaun(); - let configJson = safeLoad(readFileSync("./service.yml", "utf8")); - this.config = Config.create(configJson); - this.helper = new Helper(this.config); - this.api = new Api(this.helper, zaun); - this.user = new User(this.helper, this.api); - } - - @test async "function login should call login api successfully with user token"() { - let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); - let getTokenInfoStub = stub(this.api.authApi, "tokensTokenIdGet").callsFake((tokenId, callback) => { - callback(null, this.userTokenObj); - }); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp").returns({}); - - await this.user.login({ token: "userToken" }); - - getTokenStub.restore(); - getTokenInfoStub.restore(); - setPropStub.restore(); - getPropStub.restore(); - assert.calledWith(setPropStub, "current_login", "user"); - assert.calledWith(setPropStub, "token", { user: "userToken" }); - } - - @test async "function whoami should print current user login"() { - let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); - let getTokenInfoStub = stub(this.api.authApi, "tokensTokenIdGet").callsFake((tokenId, callback) => { - callback(null, this.userTokenObj); - }); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp").returns("user"); - let consoleLogStub = stub(console, "log"); - - await this.user.login({ token: "userToken" }); - this.user.whoami(); - consoleLogStub.restore(); - getTokenStub.restore(); - getTokenInfoStub.restore(); - setPropStub.restore(); - getPropStub.restore(); - - assert.calledWith(getPropStub, "current_login"); - assert.calledWith(getPropStub, "current_user_type"); - assert.calledWith(consoleLogStub, "Current login: user, login type: user"); - } - - @test async "function login should call login api successfully with team token"() { - let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); - let getTokenInfoStub = stub(this.api.authApi, "tokensTokenIdGet").callsFake((tokenId, callback) => { - callback(null, this.teamTokenObj); - }); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((userId, callback) => { - callback(null, this.teamObj); - }); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp").returns({}); - - await this.user.login({ token: "teamToken" }); - - getTokenStub.restore(); - getTokenInfoStub.restore(); - setPropStub.restore(); - getPropStub.restore(); - assert.calledWith(setPropStub, "current_login", this.teamObj.username); - assert.calledWith(setPropStub, "token", { "user1": "teamToken" }); - } - - @test async "function login should throw error if token type not user and not team"() { - let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); - let getTokenInfoStub = stub(this.api.authApi, "tokensTokenIdGet").callsFake((tokenId, callback) => { - callback(null, {}); - }); - let consoleLogStub = stub(console, "log"); - - await this.user.login({ token: "userToken" }); - - getTokenStub.restore(); - getTokenInfoStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Invalid token"); - } - - @test async "function login should call login api successfully with username & password"() { - let consoleLogStub = stub(console, "log"); - let authObj = { - user: "user1", - password: "pass1" - }; - let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); - let loginStub = stub(this.api.authApi, "loginPost").callsFake((body, callback) => { - callback(null, this.userObj); - }); - let userInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((body, callback) => { - callback(null, {data: {id: "test", type: "user"}}); - }); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp").returns({}); - - await this.user.login({ user: "user1", password: "pass1" }); - - getTokenStub.restore(); - loginStub.restore(); - setPropStub.restore(); - getPropStub.restore(); - consoleLogStub.restore(); - assert.calledWith(setPropStub, "current_login", authObj.user); - assert.calledWith(setPropStub, "token", { "user1": this.userObj.id }); - } - - @test async "function switch should switch team successfully with team name"() { - const getTokenStub = stub(this.helper, "getCurrentToken").returns({ token: "token" }); - const getUserInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((userId, callback) => { - callback(null, this.teamObj, { body: this.teamObj }); - }); - const createTokenTeamStub = stub(this.api.authApi, "tokensPost").callsFake((body, callback) => { - callback(null, this.teamTokenObj), { body: this.teamTokenObj }; - }); - const setPropStub = stub(this.helper, "setProp"); - const getPropStub = stub(this.helper, "getProp"); - - getPropStub.withArgs("first_login").returns({ user: "user1", type: "user" }); - getPropStub.withArgs("current_user_type").returns("user"); - - await this.user.switch("team", "team1"); - - getTokenStub.restore(); - getUserInfoStub.restore(); - createTokenTeamStub.restore(); - setPropStub.restore(); - getPropStub.restore(); - // consoleLogStub.restore(); - assert.calledWith(setPropStub, "current_login", "team1"); - assert.calledWith(setPropStub, "token", { "team1": this.teamTokenObj.id }); - } - - @test async "function switch should switch user successfully from team"() { - let consoleLogStub = stub(console, "log"); - - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - - getPropStub.withArgs("first_login").returns({username: "user1", type: "user"}); - getPropStub.withArgs("current_user_type").returns("team"); - getPropStub.withArgs("current_login").returns("user1"); - - await this.user.switch("user"); - - setPropStub.restore(); - getPropStub.restore(); - consoleLogStub.restore(); - assert.calledWith(setPropStub, "current_login", "user1"); - assert.calledWith(setPropStub, "current_user_type", "user"); - } - - @test async "function switch should throw error when switch to current login type"() { - let consoleLogStub = stub(console, "log"); - - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - - getPropStub.withArgs("first_login").returns({user: "user1", type: "user"}); - getPropStub.withArgs("current_login").returns("user1"); - getPropStub.withArgs("current_user_type").returns("user"); - - - await this.user.switch("user"); - - setPropStub.restore(); - getPropStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Unable to switch : already on user1 user"); - } - - @test async "function logout should logout successfully"() { - let consoleLogStub = stub(console, "log"); - let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }) - let sDeleteStub = stub(this.helper, "delete").returns(true); - - await this.user.logout(); - - consoleLogStub.restore(); - inquirerPromptStub.restore(); - sDeleteStub.restore(); - assert.called(sDeleteStub); - } - - @test async "function create team should create user successfully"() { - let newUser = "newUser"; - let consoleLogStub = stub(console, "log"); - let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({answer: "password"}); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((userId, callback) => { - callback(null, {teams: []}), { body: {teams:[]} }; - });; - let createUserStub = stub(this.api.userApi, "usersPost"); - createUserStub.callsFake((body, callback) => { - callback(null, {username: newUser}, { body: { username: newUser } }); - }); - - - await this.user.createUser(newUser, {}); - - getUserInfoStub.restore(); - createUserStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, `New user ${newUser} created !`); - } - - @test async "function create team should throw error when user exists"() { - let newUser = "newUser"; - let consoleLogStub = stub(console, "log"); - let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({answer: "password"}); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((userId, callback) => { - callback(null, {id: "test-id", teams: []}, { body: {id: "test-id", teams: []} } ); - });; - let createUserStub = stub(this.api.userApi, "usersPost"); - createUserStub.callsFake((body, callback) => { - callback(null, {username: newUser}, { body: {username: newUser} }); - }); - - - await this.user.createUser(newUser, {}); - - getUserInfoStub.restore(); - createUserStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, `Username ${newUser} exist !`); - } - - @test async "function create team should create team successfully"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); - let createTeamStub = stub(this.api.teamApi, "teamsPost"); - let teamPostStub = stub(this.api.teamApi, "teamsTeamIdUsersUserIdPost"); - - getPropStub.withArgs("current_login").returns("user1"); - getPropStub.withArgs("current_user_type").returns("user"); - createTeamStub.callsFake((teamObj, callback) => { - callback(null, null, {body: {id: "team1"}}) - }) - getUserInfoStub.callsFake((userId, callback) => { - callback(null, this.userObj, { body: this.userObj }); - }); - teamPostStub.callsFake((teamId, userId, roleId, callback) => { - callback(null, null, {body: {team: this.teamObj}}); - }); - - await this.user.createTeam("team1"); - - setPropStub.restore(); - getPropStub.restore(); - getUserInfoStub.restore(); - teamPostStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Team team1 created !"); - } - - @test async "function create team should throw error when current login is team"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - - getPropStub.withArgs("current_login").returns("team1"); - getPropStub.withArgs("current_user_type").returns("team"); - - await this.user.createTeam("team1"); - - setPropStub.restore(); - getPropStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Must be on user to do this operation"); - } - - @test async "function create team should throw error when team name exist"() { - let consoleLogStub = stub(console, "log"); - let setPropStub = stub(this.helper, "setProp"); - let getPropStub = stub(this.helper, "getProp"); - let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); - let createTeamStub = stub(this.api.teamApi, "teamsPost"); - let teamPostStub = stub(this.api.teamApi, "teamsTeamIdUsersUserIdPost"); - - getPropStub.withArgs("current_login").returns("user1"); - getPropStub.withArgs("current_user_type").returns("user"); - createTeamStub.callsFake((teamObj, callback) => { - callback(null, null, false); - }) - getUserInfoStub.callsFake((userId, callback) => { - callback(null, this.userObj, { body: this.userObj }); - }); - teamPostStub.callsFake((teamId, userId, roleId, callback) => { - callback(null, null, {body: {team: this.teamObj}}); - }); - - await this.user.createTeam("team1"); - - setPropStub.restore(); - getPropStub.restore(); - getUserInfoStub.restore(); - teamPostStub.restore(); - consoleLogStub.restore(); - assert.calledWith(consoleLogStub, "Team team1 exist !"); - } - - +// tslint:disable:member-access +import { readFileSync } from "fs"; +import { safeLoad } from "js-yaml"; +import { Config, IConfig } from "merapi"; +import { suite, test } from "mocha-typescript"; +import { assert, stub } from "sinon"; +import Api from "../../components/api/api"; +import Zaun from "../../components/api/zaun"; +import Helper from "../../components/scripts/helper"; +import User from "../../components/users/user"; +import { IHelper } from "../../interfaces/main"; + +@suite class UserTest { + private config: IConfig; + private helper: IHelper; + private api: any; + private user: any; + + private userTokenObj = { + id: '84330d2b-f2f8-499c-adee-99d2c533e7d5', + type: 'user', + label: 'dashboard', + userId: '5c0a78c2-3a2c-447a-80d2-069761be3ef9', + teamId: null, + botId: null, + roleId: 'ccd9b640-93c4-43b6-8523-f324f89faad6', + expire: 1503789662 + }; + private teamTokenObj = { + id: 'ea43b3b6-3c7f-4bd8-98f3-e58ee699b5b3', + type: 'team', + label: null, + userId: '8a62686d-695c-44f0-a57c-4ca19f5bf78b', + teamId: 'e563ec87-dae9-45f0-a2b3-515a069fb2b0', + botId: null, + roleId: '81b179bc-fa56-4c27-92db-a1602abe48c2', + expire: 1506907823 + }; + private userObj = { + id: '9ad603b7-5c33-432c-9752-2f4816b6bd9f', + type: 'user', + label: 'dashboard', + userId: '05c7f7a7-fba6-437a-8e6d-72c9f71c6352', + roleId: 'b3941608-1494-4983-9b64-af746b601190', + expire: 1506915325 + } + private teamObj = { + id: "e563ec87-dae9-45f0-a2b3-515a069fb2b0", + username: "user1", + password: "password", + type: "team", + email: null as string, + profile: null as string, + roleId: "55f7d797-a938-4f59-9c6a-cf6cd8a01d08", + created_at: "2017-06-18T01:46:13.000Z", + updated_at: "2017-06-18T01:46:13.000Z", + teams: [{ teamId: "e563ec87-dae9-45f0-a2b3-515a069fb2b0", username: "team1" }] as any[] + }; + + constructor() { + let zaun = Zaun(); + let configJson = safeLoad(readFileSync("./service.yml", "utf8")); + this.config = Config.create(configJson); + this.helper = new Helper(this.config); + this.api = new Api(this.helper, zaun); + this.user = new User(this.helper, this.api); + } + + @test async "function login should call login api successfully with user token"() { + let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); + let getTokenInfoStub = stub(this.api.authApi, "tokensTokenIdGet").callsFake((tokenId, callback) => { + callback(null, this.userTokenObj); + }); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp").returns({}); + + await this.user.login({ token: "userToken" }); + + getTokenStub.restore(); + getTokenInfoStub.restore(); + setPropStub.restore(); + getPropStub.restore(); + assert.calledWith(setPropStub, "current_login", "user"); + assert.calledWith(setPropStub, "token", { user: "userToken" }); + } + + @test async "function whoami should print current user login"() { + let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); + let getTokenInfoStub = stub(this.api.authApi, "tokensTokenIdGet").callsFake((tokenId, callback) => { + callback(null, this.userTokenObj); + }); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp").returns("user"); + let consoleLogStub = stub(console, "log"); + + await this.user.login({ token: "userToken" }); + this.user.whoami(); + consoleLogStub.restore(); + getTokenStub.restore(); + getTokenInfoStub.restore(); + setPropStub.restore(); + getPropStub.restore(); + + assert.calledWith(getPropStub, "current_login"); + assert.calledWith(getPropStub, "current_user_type"); + assert.calledWith(consoleLogStub, "Current login: user, login type: user"); + } + + @test async "function login should call login api successfully with team token"() { + let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); + let getTokenInfoStub = stub(this.api.authApi, "tokensTokenIdGet").callsFake((tokenId, callback) => { + callback(null, this.teamTokenObj); + }); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((userId, callback) => { + callback(null, this.teamObj); + }); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp").returns({}); + + await this.user.login({ token: "teamToken" }); + + getTokenStub.restore(); + getTokenInfoStub.restore(); + setPropStub.restore(); + getPropStub.restore(); + assert.calledWith(setPropStub, "current_login", this.teamObj.username); + assert.calledWith(setPropStub, "token", { "user1": "teamToken" }); + } + + @test async "function login should throw error if token type not user and not team"() { + let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); + let getTokenInfoStub = stub(this.api.authApi, "tokensTokenIdGet").callsFake((tokenId, callback) => { + callback(null, {}); + }); + let consoleLogStub = stub(console, "log"); + + await this.user.login({ token: "userToken" }); + + getTokenStub.restore(); + getTokenInfoStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Invalid token"); + } + + @test async "function login should call login api successfully with username & password"() { + let consoleLogStub = stub(console, "log"); + let authObj = { + user: "user1", + password: "pass1" + }; + let getTokenStub = stub(this.helper, "getCurrentToken").returns({token: "token"}); + let loginStub = stub(this.api.authApi, "loginPost").callsFake((body, callback) => { + callback(null, this.userObj); + }); + let userInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((body, callback) => { + callback(null, {data: {id: "test", type: "user"}}); + }); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp").returns({}); + + await this.user.login({ user: "user1", password: "pass1" }); + + getTokenStub.restore(); + loginStub.restore(); + setPropStub.restore(); + getPropStub.restore(); + consoleLogStub.restore(); + assert.calledWith(setPropStub, "current_login", authObj.user); + assert.calledWith(setPropStub, "token", { "user1": this.userObj.id }); + } + + @test async "function switch should switch team successfully with team name"() { + const getTokenStub = stub(this.helper, "getCurrentToken").returns({ token: "token" }); + const getUserInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((userId, callback) => { + callback(null, this.teamObj, { body: this.teamObj }); + }); + const createTokenTeamStub = stub(this.api.authApi, "tokensPost").callsFake((body, callback) => { + callback(null, this.teamTokenObj), { body: this.teamTokenObj }; + }); + const setPropStub = stub(this.helper, "setProp"); + const getPropStub = stub(this.helper, "getProp"); + + getPropStub.withArgs("first_login").returns({ user: "user1", type: "user" }); + getPropStub.withArgs("current_user_type").returns("user"); + + await this.user.switch("team", "team1"); + + getTokenStub.restore(); + getUserInfoStub.restore(); + createTokenTeamStub.restore(); + setPropStub.restore(); + getPropStub.restore(); + // consoleLogStub.restore(); + assert.calledWith(setPropStub, "current_login", "team1"); + assert.calledWith(setPropStub, "token", { "team1": this.teamTokenObj.id }); + } + + @test async "function switch should switch user successfully from team"() { + let consoleLogStub = stub(console, "log"); + + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + + getPropStub.withArgs("first_login").returns({username: "user1", type: "user"}); + getPropStub.withArgs("current_user_type").returns("team"); + getPropStub.withArgs("current_login").returns("user1"); + + await this.user.switch("user"); + + setPropStub.restore(); + getPropStub.restore(); + consoleLogStub.restore(); + assert.calledWith(setPropStub, "current_login", "user1"); + assert.calledWith(setPropStub, "current_user_type", "user"); + } + + @test async "function switch should throw error when switch to current login type"() { + let consoleLogStub = stub(console, "log"); + + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + + getPropStub.withArgs("first_login").returns({user: "user1", type: "user"}); + getPropStub.withArgs("current_login").returns("user1"); + getPropStub.withArgs("current_user_type").returns("user"); + + + await this.user.switch("user"); + + setPropStub.restore(); + getPropStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Unable to switch : already on user1 user"); + } + + @test async "function logout should logout successfully"() { + let consoleLogStub = stub(console, "log"); + let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({ confirmation: true }) + let sDeleteStub = stub(this.helper, "delete").returns(true); + + await this.user.logout(); + + consoleLogStub.restore(); + inquirerPromptStub.restore(); + sDeleteStub.restore(); + assert.called(sDeleteStub); + } + + @test async "function create team should create user successfully"() { + let newUser = "newUser"; + let consoleLogStub = stub(console, "log"); + let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({answer: "password"}); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((userId, callback) => { + callback(null, {teams: []}), { body: {teams:[]} }; + });; + let createUserStub = stub(this.api.userApi, "usersPost"); + createUserStub.callsFake((body, callback) => { + callback(null, {username: newUser}, { body: { username: newUser } }); + }); + + + await this.user.createUser(newUser, {}); + + getUserInfoStub.restore(); + createUserStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, `New user ${newUser} created !`); + } + + @test async "function create team should throw error when user exists"() { + let newUser = "newUser"; + let consoleLogStub = stub(console, "log"); + let inquirerPromptStub = stub(this.helper, "inquirerPrompt").returns({answer: "password"}); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet").callsFake((userId, callback) => { + callback(null, {id: "test-id", teams: []}, { body: {id: "test-id", teams: []} } ); + });; + let createUserStub = stub(this.api.userApi, "usersPost"); + createUserStub.callsFake((body, callback) => { + callback(null, {username: newUser}, { body: {username: newUser} }); + }); + + + await this.user.createUser(newUser, {}); + + getUserInfoStub.restore(); + createUserStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, `Username ${newUser} exist !`); + } + + @test async "function create team should create team successfully"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); + let createTeamStub = stub(this.api.teamApi, "teamsPost"); + let teamPostStub = stub(this.api.teamApi, "teamsTeamIdUsersUserIdPost"); + + getPropStub.withArgs("current_login").returns("user1"); + getPropStub.withArgs("current_user_type").returns("user"); + createTeamStub.callsFake((teamObj, callback) => { + callback(null, null, {body: {id: "team1"}}) + }) + getUserInfoStub.callsFake((userId, callback) => { + callback(null, this.userObj, { body: this.userObj }); + }); + teamPostStub.callsFake((teamId, userId, roleId, callback) => { + callback(null, null, {body: {team: this.teamObj}}); + }); + + await this.user.createTeam("team1"); + + setPropStub.restore(); + getPropStub.restore(); + getUserInfoStub.restore(); + teamPostStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Team team1 created !"); + } + + @test async "function create team should throw error when current login is team"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + + getPropStub.withArgs("current_login").returns("team1"); + getPropStub.withArgs("current_user_type").returns("team"); + + await this.user.createTeam("team1"); + + setPropStub.restore(); + getPropStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Must be on user to do this operation"); + } + + @test async "function create team should throw error when team name exist"() { + let consoleLogStub = stub(console, "log"); + let setPropStub = stub(this.helper, "setProp"); + let getPropStub = stub(this.helper, "getProp"); + let getUserInfoStub = stub(this.api.userApi, "usersUserIdGet"); + let createTeamStub = stub(this.api.teamApi, "teamsPost"); + let teamPostStub = stub(this.api.teamApi, "teamsTeamIdUsersUserIdPost"); + + getPropStub.withArgs("current_login").returns("user1"); + getPropStub.withArgs("current_user_type").returns("user"); + createTeamStub.callsFake((teamObj, callback) => { + callback(null, null, false); + }) + getUserInfoStub.callsFake((userId, callback) => { + callback(null, this.userObj, { body: this.userObj }); + }); + teamPostStub.callsFake((teamId, userId, roleId, callback) => { + callback(null, null, {body: {team: this.teamObj}}); + }); + + await this.user.createTeam("team1"); + + setPropStub.restore(); + getPropStub.restore(); + getUserInfoStub.restore(); + teamPostStub.restore(); + consoleLogStub.restore(); + assert.calledWith(consoleLogStub, "Team team1 exist !"); + } + + } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index d572dda..5e2582a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,24 @@ -{ - "compileOnSave": true, - "compilerOptions": { - "target": "es6", - "module": "commonjs", - "baseUrl": "./", - "sourceMap": true, - "sourceRoot": "./", - "noImplicitAny": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "outDir": "./lib" - }, - - "include": [ - "components/**/*.ts", - "components/*.ts", - "interfaces/*.ts" - ], - - "exclude": [ - "node_modules" - ] +{ + "compileOnSave": true, + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "baseUrl": "./", + "sourceMap": true, + "sourceRoot": "./", + "noImplicitAny": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "outDir": "./lib" + }, + + "include": [ + "components/**/*.ts", + "components/*.ts", + "interfaces/*.ts" + ], + + "exclude": [ + "node_modules" + ] } \ No newline at end of file diff --git a/tslint.json b/tslint.json index 9f2d389..c464f67 100644 --- a/tslint.json +++ b/tslint.json @@ -1,23 +1,23 @@ -{ - "defaultSeverity": "error", - "extends": [ - "tslint:recommended" - ], - "jsRules": {}, - "rules": { - "member-ordering": [false], - "align": [false], - "object-literal-sort-keys": [false], - "new-parens": true, - "no-arg": true, - "no-bitwise": true, - "array-type": [false], - "trailing-comma": [false], - "ordered-imports": [false], - "no-trailing-whitespace": [false], - "no-conditional-assignment": true, - "no-consecutive-blank-lines": false, - "no-console": [false] - }, - "rulesDirectory": [] +{ + "defaultSeverity": "error", + "extends": [ + "tslint:recommended" + ], + "jsRules": {}, + "rules": { + "member-ordering": [false], + "align": [false], + "object-literal-sort-keys": [false], + "new-parens": true, + "no-arg": true, + "no-bitwise": true, + "array-type": [false], + "trailing-comma": [false], + "ordered-imports": [false], + "no-trailing-whitespace": [false], + "no-conditional-assignment": true, + "no-consecutive-blank-lines": false, + "no-console": [false] + }, + "rulesDirectory": [] } \ No newline at end of file