From e5b8a4fb8a3b2b304471fb7a076d98e5f03703c7 Mon Sep 17 00:00:00 2001 From: Oliver Foster Date: Thu, 17 Mar 2022 09:37:26 +0000 Subject: [PATCH] Rewrite and added AAT API (#154) --- .eslintignore | 1 + .eslintrc.json | 14 + .gitignore | 4 +- README.md | 300 +- TODO.md | 36 + bin/adapt | 3 - bin/adapt.js | 3 + gruntfile.js | 18 - json/help-create.json | 3 +- json/help-create/question.json | 9 + lib/AdaptConsoleApplication.js | 19 - lib/CommandParser.js | 19 - lib/CommandTranslator.js | 16 - lib/ConsoleRenderer.js | 10 - lib/Constants.js | 68 - lib/JsonLoader.js | 40 - lib/JsonWriter.js | 21 - lib/PackageMeta.js | 41 - lib/Plugin.js | 53 - lib/PluginTypeResolver.js | 47 - lib/Project.js | 89 - lib/RendererHelpers.js | 41 - lib/RepositoryDownloader.js | 64 - lib/Slug.js | 5 - lib/VersionChecker.js | 7 - lib/api.js | 260 + lib/cli.js | 105 +- lib/commands/authenticate.js | 18 + lib/commands/create.js | 165 +- lib/commands/create/component.js | 127 +- lib/commands/create/course.js | 105 +- lib/commands/create/index.js | 6 - lib/commands/create/question.js | 18 + lib/commands/devinstall.js | 132 +- lib/commands/help.js | 83 +- lib/commands/index.js | 16 - lib/commands/install.js | 923 +-- lib/commands/install/InstallLog.js | 32 - lib/commands/install/InstallTarget.js | 259 - lib/commands/install/extend.js | 31 - lib/commands/ls.js | 33 +- lib/commands/register.js | 205 +- lib/commands/rename.js | 141 +- lib/commands/search.js | 38 +- lib/commands/uninstall.js | 145 +- lib/commands/unregister.js | 106 +- lib/commands/update.js | 879 +-- lib/commands/version.js | 26 +- lib/download.js | 101 - lib/errors.js | 58 - lib/integration/AdaptFramework.js | 19 + lib/integration/AdaptFramework/build.js | 39 + lib/integration/AdaptFramework/clone.js | 27 + .../AdaptFramework/deleteSrcCore.js | 9 + .../AdaptFramework/deleteSrcCourse.js | 9 + lib/integration/AdaptFramework/download.js | 21 + lib/integration/AdaptFramework/erase.js | 34 + .../AdaptFramework/getLatestVersion.js | 79 + lib/integration/AdaptFramework/npmInstall.js | 21 + lib/integration/Plugin.js | 403 + lib/integration/PluginManagement.js | 21 + .../PluginManagement/autenticate.js | 56 + lib/integration/PluginManagement/install.js | 222 + lib/integration/PluginManagement/print.js | 52 + lib/integration/PluginManagement/register.js | 130 + lib/integration/PluginManagement/rename.js | 101 + lib/integration/PluginManagement/schemas.js | 8 + lib/integration/PluginManagement/search.js | 46 + lib/integration/PluginManagement/uninstall.js | 141 + .../PluginManagement/unregister.js | 101 + lib/integration/PluginManagement/update.js | 224 + lib/integration/Project.js | 146 + lib/integration/Target.js | 296 + lib/integration/getBowerRegistryConfig.js | 34 + lib/logger.js | 28 + lib/promise/authenticate.js | 58 - lib/promise/build.js | 20 - lib/promise/cloneInstall.js | 35 - lib/promise/confirmBuild.js | 6 - lib/promise/exec.js | 39 - lib/promise/getRepository.js | 26 - lib/promise/highest.js | 109 - lib/promise/install.js | 31 - lib/promise/installAdaptDependencies.js | 30 - lib/promise/installNodeDependencies.js | 28 - lib/promise/removeTemporaryDownload.js | 8 - lib/promise/replaceTextContent.js | 10 - lib/promise/uninstallPackage.js | 15 - lib/promise/update.js | 33 - lib/promise/util.js | 16 - lib/util/JSONReadValidate.js | 34 + lib/util/constants.js | 38 + lib/util/createPromptTask.js | 7 + lib/util/download.js | 45 + lib/util/errors.js | 58 + lib/util/extract.js | 24 + lib/util/getDirNameFromImportMeta.js | 6 + lib/util/promises.js | 36 + package-lock.json | 6742 ++++------------- package.json | 49 +- test/fixtures/adapt-with-plugins.json | 6 - test/fixtures/adapt.json | 1 - test/specs/command_translation_concerns.js | 13 - test/specs/create_command_concerns.js | 22 - test/specs/create_concerns.js | 30 - test/specs/install_concerns.js | 31 - .../installing_compatible_plugins_concerns.js | 126 - ...nstalling_incompatible_plugins_concerns.js | 103 - test/specs/ls_concerns.js | 28 - test/specs/plugin_name_concerns.js | 82 - test/specs/project_concerns.js | 128 - test/specs/registration_concerns.js | 31 - test/specs/repository_downloader_concerns.js | 55 - test/specs/search_concerns.js | 30 - test/specs/type_resolution_concerns.js | 71 - test/specs/uninstall_command_concerns.js | 64 - test/specs/uninstall_concerns.js | 31 - 117 files changed, 5006 insertions(+), 10559 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 TODO.md delete mode 100755 bin/adapt create mode 100644 bin/adapt.js delete mode 100644 gruntfile.js create mode 100644 json/help-create/question.json delete mode 100644 lib/AdaptConsoleApplication.js delete mode 100644 lib/CommandParser.js delete mode 100644 lib/CommandTranslator.js delete mode 100644 lib/ConsoleRenderer.js delete mode 100644 lib/Constants.js delete mode 100644 lib/JsonLoader.js delete mode 100644 lib/JsonWriter.js delete mode 100644 lib/PackageMeta.js delete mode 100644 lib/Plugin.js delete mode 100644 lib/PluginTypeResolver.js delete mode 100644 lib/Project.js delete mode 100644 lib/RendererHelpers.js delete mode 100644 lib/RepositoryDownloader.js delete mode 100644 lib/Slug.js delete mode 100644 lib/VersionChecker.js create mode 100644 lib/api.js create mode 100644 lib/commands/authenticate.js delete mode 100644 lib/commands/create/index.js create mode 100644 lib/commands/create/question.js delete mode 100644 lib/commands/index.js delete mode 100644 lib/commands/install/InstallLog.js delete mode 100644 lib/commands/install/InstallTarget.js delete mode 100644 lib/commands/install/extend.js delete mode 100644 lib/download.js delete mode 100644 lib/errors.js create mode 100644 lib/integration/AdaptFramework.js create mode 100644 lib/integration/AdaptFramework/build.js create mode 100644 lib/integration/AdaptFramework/clone.js create mode 100644 lib/integration/AdaptFramework/deleteSrcCore.js create mode 100644 lib/integration/AdaptFramework/deleteSrcCourse.js create mode 100644 lib/integration/AdaptFramework/download.js create mode 100644 lib/integration/AdaptFramework/erase.js create mode 100644 lib/integration/AdaptFramework/getLatestVersion.js create mode 100644 lib/integration/AdaptFramework/npmInstall.js create mode 100644 lib/integration/Plugin.js create mode 100644 lib/integration/PluginManagement.js create mode 100644 lib/integration/PluginManagement/autenticate.js create mode 100644 lib/integration/PluginManagement/install.js create mode 100644 lib/integration/PluginManagement/print.js create mode 100644 lib/integration/PluginManagement/register.js create mode 100644 lib/integration/PluginManagement/rename.js create mode 100644 lib/integration/PluginManagement/schemas.js create mode 100644 lib/integration/PluginManagement/search.js create mode 100644 lib/integration/PluginManagement/uninstall.js create mode 100644 lib/integration/PluginManagement/unregister.js create mode 100644 lib/integration/PluginManagement/update.js create mode 100644 lib/integration/Project.js create mode 100644 lib/integration/Target.js create mode 100644 lib/integration/getBowerRegistryConfig.js create mode 100644 lib/logger.js delete mode 100644 lib/promise/authenticate.js delete mode 100644 lib/promise/build.js delete mode 100644 lib/promise/cloneInstall.js delete mode 100644 lib/promise/confirmBuild.js delete mode 100644 lib/promise/exec.js delete mode 100644 lib/promise/getRepository.js delete mode 100644 lib/promise/highest.js delete mode 100644 lib/promise/install.js delete mode 100644 lib/promise/installAdaptDependencies.js delete mode 100644 lib/promise/installNodeDependencies.js delete mode 100644 lib/promise/removeTemporaryDownload.js delete mode 100644 lib/promise/replaceTextContent.js delete mode 100644 lib/promise/uninstallPackage.js delete mode 100644 lib/promise/update.js delete mode 100644 lib/promise/util.js create mode 100644 lib/util/JSONReadValidate.js create mode 100644 lib/util/constants.js create mode 100644 lib/util/createPromptTask.js create mode 100644 lib/util/download.js create mode 100644 lib/util/errors.js create mode 100644 lib/util/extract.js create mode 100644 lib/util/getDirNameFromImportMeta.js create mode 100644 lib/util/promises.js delete mode 100644 test/fixtures/adapt-with-plugins.json delete mode 100644 test/fixtures/adapt.json delete mode 100644 test/specs/command_translation_concerns.js delete mode 100644 test/specs/create_command_concerns.js delete mode 100644 test/specs/create_concerns.js delete mode 100644 test/specs/install_concerns.js delete mode 100644 test/specs/installing_compatible_plugins_concerns.js delete mode 100644 test/specs/installing_incompatible_plugins_concerns.js delete mode 100644 test/specs/ls_concerns.js delete mode 100644 test/specs/plugin_name_concerns.js delete mode 100644 test/specs/project_concerns.js delete mode 100644 test/specs/registration_concerns.js delete mode 100644 test/specs/repository_downloader_concerns.js delete mode 100644 test/specs/search_concerns.js delete mode 100644 test/specs/type_resolution_concerns.js delete mode 100644 test/specs/uninstall_command_concerns.js delete mode 100644 test/specs/uninstall_concerns.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +node_modules diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..b56d919 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,14 @@ +{ + "env": { + "browser": false, + "node": true, + "commonjs": false, + "es2020": true + }, + "extends": [ + "standard" + ], + "parserOptions": { + "ecmaVersion": 2020 + } +} diff --git a/.gitignore b/.gitignore index feab0bc..617a1cf 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ src bower.json adapt.json .idea -.idea/workspace.xml \ No newline at end of file +.idea/workspace.xml +my-adapt-course +test-plugin diff --git a/README.md b/README.md index 1c4c3bd..0232bfe 100644 --- a/README.md +++ b/README.md @@ -1,266 +1,266 @@ Adapt Command Line Interface (CLI) ============================ -[![Build Status](https://travis-ci.org/adaptlearning/adapt-cli.png?branch=master)](https://travis-ci.org/adaptlearning/adapt-cli) [![Join the chat at https://gitter.im/adaptlearning/adapt-cli](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/adaptlearning/adapt-cli?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Build Status](https://travis-ci.org/adaptlearning/adapt-cli.png?branch=master)](https://travis-ci.org/adaptlearning/adapt-cli) [![Join the chat at https://gitter.im/adaptlearning/adapt-cli](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/adaptlearning/adapt-cli?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -The **Adapt CLI** is a command line interface for use with the [Adapt framework](https://github.com/adaptlearning/adapt_framework). Its primary usefulness is to install, update, and uninstall Adapt plug-ins. In doing so, it references the [Adapt Plugin Browser](https://www.adaptlearning.org/index.php/plugin-browser/). Consequently, the CLI includes several commands for working with this plug-in registry. +The **Adapt CLI** is a command line interface for use with the [Adapt framework](https://github.com/adaptlearning/adapt_framework). Its primary usefulness is to install, update, and uninstall Adapt plug-ins. In doing so, it references the [Adapt Plugin Browser](https://www.adaptlearning.org/index.php/plugin-browser/). Consequently, the CLI includes several commands for working with this plug-in registry. >IMPORTANT: The **Adapt CLI** is not intended to be used with courses in the [Adapt authoring tool](https://github.com/adaptlearning/adapt_authoring). The authoring tool tracks versions of plug-ins in its database. Using the CLI bypasses this tracking. ## Installation -Before installing the Adapt CLI, you must install [NodeJS](http://nodejs.org) and [git](http://git-scm.com/downloads). -To install the Adapt CLI globally, run the following command: +Before installing the Adapt CLI, you must install [NodeJS](http://nodejs.org) and [git](http://git-scm.com/downloads). +To install the Adapt CLI globally, run the following command: `npm install -g adapt-cli` Some systems may require elevated permissions in order to install a script globally. -## Commands +## Commands -### adapt version +### adapt version -##### Model: -`adapt version` +##### Model: +`adapt version` -This command reports both the version of the CLI and the version of the Adapt framework. The version of the framework is reported as "0.0.0" unless the command is run from the root directory of an installed framework. -
Back to Top
+This command reports both the version of the CLI and the version of the Adapt framework. The version of the framework is reported as "0.0.0" unless the command is run from the root directory of an installed framework. +
Back to Top
+ +### adapt help -### adapt help +##### Model: +`adapt help []` -##### Model: -`adapt help []` +**command**: A CLI command. -**command**: A CLI command. +##### Examples: -##### Examples: +1. To list all the CLI commands with a brief description of each: +`adapt help` -1. To list all the CLI commands with a brief description of each: -`adapt help` +1. To report a brief description of a specific command: +`adapt help create` -1. To report a brief description of a specific command: -`adapt help create` -
Back to Top
-### adapt create +### adapt create -##### Model: +##### Model: `adapt create [ ]` -**type**: What to create. Acceptable values are `course` and `component`. -**path**: The directory of the new course. Enclose in quotes if the path/name includes spaces. -**branch|tag**: The branch or tag name of the framework to be downloaded. This is optional. If not specified, the master branch will be used. +**type**: What to create. Acceptable values are `course` and `component`. +**path**: The directory of the new course. Enclose in quotes if the path/name includes spaces. +**branch|tag**: The branch or tag name of the framework to be downloaded. This is optional. If not specified, the master branch will be used. -##### Examples: +##### Examples: -1. To create an Adapt course *(do not use in conjunction with the Adapt authoring tool)*: -`adapt create course "My Course"` -This will create a new directory named "My Course" in your current working directory. It will download the Adapt framework from its master branch, including the default course, into the new directory. Before using the course, run: -`grunt build` +1. To create an Adapt course *(do not use in conjunction with the Adapt authoring tool)*: +`adapt create course "My Course"` +This will create a new directory named "My Course" in your current working directory. It will download the Adapt framework from its master branch, including the default course, into the new directory. Before using the course, run: +`grunt build` -1. To create an Adapt course from a specific branch: -`adapt create course "My Course" legacy` +1. To create an Adapt course from a specific branch: +`adapt create course "My Course" legacy` This is the same as example 1 except that the framework will be downloaded from the 'legacy' branch, not from the default master branch. -1. To create an Adapt course from a specific tag: +1. To create an Adapt course from a specific tag: `adapt create course "My Course" v3.5.1` This is the same as example 1 except that v3.5.1 of the framework will be downloaded, rather than the master branch. -1. To create an empty component: -`adapt create component "test-component"` -This command is useful for developing new components. It will create a new directory named "test-component" in the current working directory. It will populate the directory with files required for an Adapt component and insert "test-component" into the code where required. +1. To create an empty component: +`adapt create component "test-component"` +This command is useful for developing new components. It will create a new directory named "test-component" in the current working directory. It will populate the directory with files required for an Adapt component and insert "test-component" into the code where required. -### adapt search +### adapt search -##### Model: -`adapt search []` +##### Model: +`adapt search []` -**plug-in**: The optional name of the plug-in that you want to search for. Any part of the name may be used; multiple results may be returned if the partial name is not unique. +**plug-in**: The optional name of the plug-in that you want to search for. Any part of the name may be used; multiple results may be returned if the partial name is not unique. The **search** command searches within [Adapt Plugin Browser](https://www.adaptlearning.org/index.php/plugin-browser/). It will return the plug-in's complete name and its source repository only if the plug-in is registered. -##### Examples: -1. To view the name and repository of all plug-ins registered with the Adapt Plugin Browser: -`adapt search` +##### Examples: +1. To view the name and repository of all plug-ins registered with the Adapt Plugin Browser: +`adapt search` -1. To locate the repository of a known plug-in that is registered: -`adapt search adapt-contrib-pageLevelProgress` OR -`adapt search contrib-pageLevelProgress` OR -`adapt search pageLevel` +1. To locate the repository of a known plug-in that is registered: +`adapt search adapt-contrib-pageLevelProgress` OR +`adapt search contrib-pageLevelProgress` OR +`adapt search pageLevel` -### adapt install +### adapt install -##### Models: -`adapt install [#|@]` -`adapt install [--dry-run|--compatible]` +##### Models: +`adapt install [#|@]` +`adapt install [--dry-run|--compatible]` -**plug-in**: The name of the plug-in to be installed. The name may be fully qualified with "adapt-" or the prefix may be omitted. Parts of names are not acceptable. -**version**: A specific version number of the plug-in. This is optional. +**plug-in**: The name of the plug-in to be installed. The name may be fully qualified with "adapt-" or the prefix may be omitted. Parts of names are not acceptable. +**version**: A specific version number of the plug-in. This is optional. -##### Examples: -1. To install all plug-ins listed in *adapt.json*: +##### Examples: +1. To install all plug-ins listed in *adapt.json*: `adapt install` -This command must be run in the root directory of an Adapt framework installation. +This command must be run in the root directory of an Adapt framework installation. -1. To report the plug-ins that will be installed if `adapt install` is run: +1. To report the plug-ins that will be installed if `adapt install` is run: `adapt install --dry-run` -This command must be run in the root directory of an Adapt framework installation. +This command must be run in the root directory of an Adapt framework installation. -1. To install versions of all plug-ins listed in *adapt.json* that are compatible with the installed framework version. This overrides any incompatible settings provided on the command line or in *adapt.json*. +1. To install versions of all plug-ins listed in *adapt.json* that are compatible with the installed framework version. This overrides any incompatible settings provided on the command line or in *adapt.json*. `adapt install --compatible` This command must be run in the root directory of an Adapt framework installation. -1. To install a plug-in that has been registered with the [Adapt Plug-in Browser](https://www.adaptlearning.org/index.php/plugin-browser/) registry: -`adapt install adapt-contrib-pageLevelProgress` OR -`adapt install contrib-pageLevelProgress` - -1. To install a specific version of a registered plug-in: -`adapt install adapt-contrib-pageLevelProgress#1.1.0` OR -`adapt install adapt-contrib-pageLevelProgress@1.1.0` OR -`adapt install contrib-pageLevelProgress#1.1.0` OR -`adapt install contrib-pageLevelProgress@1.1.0` - -1. To use the CLI to install a plug-in that is not registered with [Adapt Plug-in Browser](https://www.adaptlearning.org/index.php/plugin-browser/) registry: - 1. Copy the uncompressed folder to the proper location for the type of plug-in. Components: *src/components*. Extensions: *src/extensions*. Menu: *src/menu*. Theme: *src/theme*. Note: The Adapt framework allows only one theme. Uninstall the current before replacing it with an alternative. More than one menu is allowed. - 1. Open *adapt.json* in an editor and add the full name of the new component to the list. - 1. Run the following command from the course root: - `adapt install` +1. To install a plug-in that has been registered with the [Adapt Plug-in Browser](https://www.adaptlearning.org/index.php/plugin-browser/) registry: +`adapt install adapt-contrib-pageLevelProgress` OR +`adapt install contrib-pageLevelProgress` + +1. To install a specific version of a registered plug-in: +`adapt install adapt-contrib-pageLevelProgress#1.1.0` OR +`adapt install adapt-contrib-pageLevelProgress@1.1.0` OR +`adapt install contrib-pageLevelProgress#1.1.0` OR +`adapt install contrib-pageLevelProgress@1.1.0` + +1. To use the CLI to install a plug-in that is not registered with [Adapt Plug-in Browser](https://www.adaptlearning.org/index.php/plugin-browser/) registry: + 1. Copy the uncompressed folder to the proper location for the type of plug-in. Components: *src/components*. Extensions: *src/extensions*. Menu: *src/menu*. Theme: *src/theme*. Note: The Adapt framework allows only one theme. Uninstall the current before replacing it with an alternative. More than one menu is allowed. + 1. Open *adapt.json* in an editor and add the full name of the new component to the list. + 1. Run the following command from the course root: + `adapt install` After installation, most CLI commands will operate on the plug-in with the exception of `adapt update`. Plug-ins must be registered with the [Adapt Plugin Browser](https://www.adaptlearning.org/index.php/plugin-browser/) for `adapt update` to succeed. -1. To update all registered plug-ins to their most recent public release: -`adapt update` -Since no plug-in name is specified in this command, all plug-ins listed in *adapt.json* are reinstalled. Whether the plug-in is updated will be determined by the compatible framework versions specified in *adapt.json*. If it includes a plug-in that is not registered, it will not be updated. -**Note to developers:** The CLI determines newest version by comparing release tags in the GitHub repo. Be sure to use a tag when you release a new version. - +1. To update all registered plug-ins to their most recent public release: +`adapt update` +Since no plug-in name is specified in this command, all plug-ins listed in *adapt.json* are reinstalled. Whether the plug-in is updated will be determined by the compatible framework versions specified in *adapt.json*. If it includes a plug-in that is not registered, it will not be updated. +**Note to developers:** The CLI determines newest version by comparing release tags in the GitHub repo. Be sure to use a tag when you release a new version. + -### adapt ls +### adapt ls -##### Model: -`adapt ls` +##### Model: +`adapt ls` -This command lists the name and version number of all plug-ins listed in the *adapt.json* file of the current directory. - +This command lists the name and version number of all plug-ins listed in the *adapt.json* file of the current directory. + -### adapt uninstall +### adapt uninstall -##### Model: -`adapt uninstall ` +##### Model: +`adapt uninstall ` -**plug-in**: The name of the plug-in to be installed. The name may be fully qualified with "adapt-" or the prefix may be omitted. Parts of names are not acceptable. +**plug-in**: The name of the plug-in to be installed. The name may be fully qualified with "adapt-" or the prefix may be omitted. Parts of names are not acceptable. -##### Examples: -1. To uninstall a plug-in: -`adapt uninstall adapt-contrib-pageLevelProgress` OR -`adapt uninstall contrib-pageLevelProgress` -Because the plug-in registry is not referenced during the uninstall process, this command will work whether or not the plug-in is registered with the Adapt Plugin Browser.. +##### Examples: +1. To uninstall a plug-in: +`adapt uninstall adapt-contrib-pageLevelProgress` OR +`adapt uninstall contrib-pageLevelProgress` +Because the plug-in registry is not referenced during the uninstall process, this command will work whether or not the plug-in is registered with the Adapt Plugin Browser.. ### adapt devinstall -##### Model: -`adapt devinstall [[#]]` +##### Model: +`adapt devinstall [[#]]` -**plug-in**: Name of the plug-in to be cloned. -**version**: Version of the plug-in to be installed. +**plug-in**: Name of the plug-in to be cloned. +**version**: Version of the plug-in to be installed. -##### Examples: +##### Examples: -1. To clone as git repositories the Adapt framework and all the plug-ins listed in *adapt.json* of the current directory: -`adapt devinstall` +1. To clone as git repositories the Adapt framework and all the plug-ins listed in *adapt.json* of the current directory: +`adapt devinstall` -1. To clone a specific plug-in listed in the *adapt.json*: -`adapt devinstall adapt-contrib-matching` +1. To clone a specific plug-in listed in the *adapt.json*: +`adapt devinstall adapt-contrib-matching` -1. To clone a specific version of a plug-in listed in the *adapt.json*: -`adapt devinstall adapt-contrib-matching#v2.2.0` +1. To clone a specific version of a plug-in listed in the *adapt.json*: +`adapt devinstall adapt-contrib-matching#v2.2.0` ### adapt update -##### Models: -`adapt update [[#|@]][--check]` +##### Models: +`adapt update [[#|@]][--check]` `adapt update [components|extensions|menu|theme|all][--check]` -**plug-in**: Name of the plug-in to be cloned. -**version**: Version of the plug-in to be installed. +**plug-in**: Name of the plug-in to be cloned. +**version**: Version of the plug-in to be installed. Before running the update command, ensure that there is no *bower.json* file in your project directory. -##### Examples: +##### Examples: -1. To report the latest compatible version for each plug-in in the current directory (plug-ins are not updated): -`adapt update --check` -Note: The `--check` option may be used to report on a specific plug-in or on a complete plug-in group (components, extensions, theme, menu): -`adapt update adapt-contrib-matching --check` -`adapt update extensions --check` +1. To report the latest compatible version for each plug-in in the current directory (plug-ins are not updated): +`adapt update --check` +Note: The `--check` option may be used to report on a specific plug-in or on a complete plug-in group (components, extensions, theme, menu): +`adapt update adapt-contrib-matching --check` +`adapt update extensions --check` -1. To update a registered plug-in: -`adapt update adapt-contrib-pageLevelProgress` OR -`adapt update contrib-pageLevelProgress` +1. To update a registered plug-in: +`adapt update adapt-contrib-pageLevelProgress` OR +`adapt update contrib-pageLevelProgress` -1. To update a specific version of a registered plug-in: -`adapt update adapt-contrib-pageLevelProgress#1.1.0` OR -`adapt update adapt-contrib-pageLevelProgress@1.1.0` OR -`adapt update contrib-pageLevelProgress#1.1.0` OR -`adapt update contrib-pageLevelProgress@1.1.0` +1. To update a specific version of a registered plug-in: +`adapt update adapt-contrib-pageLevelProgress#1.1.0` OR +`adapt update adapt-contrib-pageLevelProgress@1.1.0` OR +`adapt update contrib-pageLevelProgress#1.1.0` OR +`adapt update contrib-pageLevelProgress@1.1.0` -### adapt register +### adapt register -##### Command: -`adapt register` +##### Command: +`adapt register` -This command must be run from within the root directory of the plug-in you want to register. "name" and "repository" will be read from *bower.json* in the current directory. The plug-in name must be prefixed with "adapt-" and each word separated with a hyphen (-). Plug-in names are checked against those already registered to avoid duplicates. +This command must be run from within the root directory of the plug-in you want to register. "name" and "repository" will be read from *bower.json* in the current directory. The plug-in name must be prefixed with "adapt-" and each word separated with a hyphen (-). Plug-in names are checked against those already registered to avoid duplicates. -URL format must be of the form `git://github.com//.git` +URL format must be of the form `https://github.com//.git` -### adapt rename +### adapt rename -##### Command: -`adapt rename ` +##### Command: +`adapt rename ` -**current-name**: Name of the plug-in currently used in the plug-in registry. +**current-name**: Name of the plug-in currently used in the plug-in registry. **new-name**: Name proposed to replace the current plug-in name. -Please note that you must authenticate with GitHub to use **rename**. You must be a collaborator on the endpoint registered with the plug-in or a collaborator on the Adapt framework. Access to GitHub is for authentication only. +Please note that you must authenticate with GitHub to use **rename**. You must be a collaborator on the endpoint registered with the plug-in or a collaborator on the Adapt framework. Access to GitHub is for authentication only. -##### Example: +##### Example: -1. To rename a plug-in: -`adapt rename adapt-incorrectName adapt-betterName` +1. To rename a plug-in: +`adapt rename adapt-incorrectName adapt-betterName` -### adapt unregister +### adapt unregister -##### Command: -`adapt unregister []` +##### Command: +`adapt unregister []` -**plug-in**: Name of the plug-in currently used in the plug-in registry. +**plug-in**: Name of the plug-in currently used in the plug-in registry. -Please note that you must authenticate with GitHub to use **unregister**. You must be a collaborator on the endpoint registered with the plug-in or a collaborator on the Adapt framework. Access to GitHub is for authentication only. +Please note that you must authenticate with GitHub to use **unregister**. You must be a collaborator on the endpoint registered with the plug-in or a collaborator on the Adapt framework. Access to GitHub is for authentication only. -##### Examples: +##### Examples: -1. To unregister a plug-in while in the root directory of the plug-in: -`adapt unregister` +1. To unregister a plug-in while in the root directory of the plug-in: +`adapt unregister` -1. To unregister a plug-in by name: -`adapt unregister adapt-myMistake` +1. To unregister a plug-in by name: +`adapt unregister adapt-myMistake` The Plug-in Registry ------------------- -The Adapt community maintains the [Adapt Plugin Browser](https://www.adaptlearning.org/index.php/plugin-browser/) as a convenient registry of components, extensions, themes, and menus. The plug-in system is powered by [Bower](http://bower.io/): http://adapt-bower-repository.herokuapp.com/packages/. To register, a plug-in must be a valid bower package with *bower.json*, and have a unique name that is prefixed with "adapt-". +The Adapt community maintains the [Adapt Plugin Browser](https://www.adaptlearning.org/index.php/plugin-browser/) as a convenient registry of components, extensions, themes, and menus. The plug-in system is powered by [Bower](http://bower.io/): http://adapt-bower-repository.herokuapp.com/packages/. To register, a plug-in must be a valid bower package with *bower.json*, and have a unique name that is prefixed with "adapt-". -See [Developing plug-ins](https://github.com/adaptlearning/adapt_framework/wiki/Developing-plugins) for more information on defining your plug-in's package and on [registering your plug-in](https://github.com/adaptlearning/adapt_framework/wiki/Registering-a-plugin). - +See [Developing plug-ins](https://github.com/adaptlearning/adapt_framework/wiki/Developing-plugins) for more information on defining your plug-in's package and on [registering your plug-in](https://github.com/adaptlearning/adapt_framework/wiki/Registering-a-plugin). + ---------------------------- -adapt learning logo -**Author / maintainer:** Adapt Core Team with [contributors](https://github.com/adaptlearning/adapt-contrib-hotgraphic/graphs/contributors) +adapt learning logo +**Author / maintainer:** Adapt Core Team with [contributors](https://github.com/adaptlearning/adapt-contrib-hotgraphic/graphs/contributors) diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..665cb51 --- /dev/null +++ b/TODO.md @@ -0,0 +1,36 @@ +# TODO + +1. Isolate bower as best possible +2. Refactor + * ~~commands/build~~ + * ~~commands/help~~ + * ~~commands/uninstall~~ + * ~~commands/update~~ + * ~~commands/create/component~~ + * ~~commands/create/question~~ + * ~~commands/register~~ + * ~~commands/rename~~ + * ~~commands/search~~ + * ~~commands/unregister~~ + * ~~commands/install~~ + * ~~commands/create~~ + * ~~commands/create/course~~ + * ~~commands/devinstall~~ + * ~~commands/ls~~ + * ~~commands/version~~ +3. Final bits + * ~~Duplicates plugin names in install, update, uninstall~~ + * ~~Tests~~ + * ~~Bower config / multi registry search~~ + * ~~npm modules~~ +4. Ensure api is working + * ~~merge all Targets into Plugin~~ + * ~~rewrite update task to mirror install task code~~ + * ~~add path install to bower and clone install~~ + * ~~add schemas support~~ + * ~~add Plugin.fromPath()~~ + * create api functions + * non-interactive / interactivity + * json output is good + * good error output +5. ~~Get tests working against new code~~ diff --git a/bin/adapt b/bin/adapt deleted file mode 100755 index dd291df..0000000 --- a/bin/adapt +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node -var cli = require('../lib/cli'); -cli.withOptions().withPackage().execute(); diff --git a/bin/adapt.js b/bin/adapt.js new file mode 100644 index 0000000..ff33ba3 --- /dev/null +++ b/bin/adapt.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node +import cli from '../lib/cli.js' +cli.withOptions().execute() diff --git a/gruntfile.js b/gruntfile.js deleted file mode 100644 index 3a20075..0000000 --- a/gruntfile.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = function(grunt) { - require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); - - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - mochaTest: { - test: { - options: { - reporter: 'spec' - }, - src: ['test/specs/**/*.js'] - } - } - }); - - grunt.registerTask('default', ['mochaTest']); - grunt.registerTask('test', ['mochaTest']); -}; \ No newline at end of file diff --git a/json/help-create.json b/json/help-create.json index c3afb6b..4636fe5 100644 --- a/json/help-create.json +++ b/json/help-create.json @@ -6,6 +6,7 @@ ], "commands": { "course": "Create new adapt course", - "component": "Create new component using template adapt-component" + "component": "Create new component using template adapt-component", + "question": "Create new question component using template adapt-questionComponent" } } diff --git a/json/help-create/question.json b/json/help-create/question.json new file mode 100644 index 0000000..c9bf688 --- /dev/null +++ b/json/help-create/question.json @@ -0,0 +1,9 @@ +{ + "command": "create question", + "description": "create new question component", + "usage": [ + "create question", + "create question ", + "create question " + ] +} diff --git a/lib/AdaptConsoleApplication.js b/lib/AdaptConsoleApplication.js deleted file mode 100644 index 741f43e..0000000 --- a/lib/AdaptConsoleApplication.js +++ /dev/null @@ -1,19 +0,0 @@ -var AdaptConsoleApplication = function (commands, renderer) { - this.renderer = renderer || require('./ConsoleRenderer'); - this.commands = commands; -}; - -AdaptConsoleApplication.prototype.do = function (command, done) { - done = done || function () {}; - - if(!this.commands.hasOwnProperty(command.name)) { - var e = new Error('Unknown command "' + command.name + '", please check the documentation.'); - this.renderer.log(e.message); - done(e); - } - - var commandArguments = [this.renderer].concat(command.parameters).concat([done]); - this.commands[command.name].apply(this.commands, commandArguments); -}; - -module.exports = AdaptConsoleApplication; \ No newline at end of file diff --git a/lib/CommandParser.js b/lib/CommandParser.js deleted file mode 100644 index d99c0c4..0000000 --- a/lib/CommandParser.js +++ /dev/null @@ -1,19 +0,0 @@ - -var delimiter = ',', - CommandTranslator = require('./CommandTranslator'), - CommandParser = function (argv) { - argv = argv || ['node', 'path']; - this.parameters = CommandTranslator(argv.slice(2)); - if(this.parameters.length) { - this.name = String.prototype.toLowerCase.call(this.parameters.shift()); - } - }; - -CommandParser.prototype.param = function (index) { - if(index >= this.parameters.length) - return undefined; - - return this.parameters[index]; -}; - -module.exports = CommandParser; \ No newline at end of file diff --git a/lib/CommandTranslator.js b/lib/CommandTranslator.js deleted file mode 100644 index 8ba149f..0000000 --- a/lib/CommandTranslator.js +++ /dev/null @@ -1,16 +0,0 @@ -var _ = require('lodash'), - translationTable = [ - { pattern: /^-v$|^--version$/i, replacement: 'version' }, - { pattern: /^upgrade$/i, replacement: 'update' } - ], - CommandTranslator = function (parameters) { - parameters = Array.isArray(parameters) ? parameters : [parameters]; - return parameters.map(function (param) { - var translation = _.find(translationTable, function (item) { - return item.pattern.test(param); - }); - return translation ? translation.replacement : param; - }); - }; - -module.exports = CommandTranslator; diff --git a/lib/ConsoleRenderer.js b/lib/ConsoleRenderer.js deleted file mode 100644 index 1c93527..0000000 --- a/lib/ConsoleRenderer.js +++ /dev/null @@ -1,10 +0,0 @@ -var chalk = require('chalk'); - -module.exports = { - log: function () { - console.log.apply(this, arguments); - }, - error: function () { - console.error.apply(this, arguments); - } -}; \ No newline at end of file diff --git a/lib/Constants.js b/lib/Constants.js deleted file mode 100644 index c15c535..0000000 --- a/lib/Constants.js +++ /dev/null @@ -1,68 +0,0 @@ -var bower = require('bower'), - fs = require('fs'), - path = require('path'); - -module.exports = { - ManifestFilename: 'adapt.json', - FrameworkFilename: 'package.json', - DefaultProjectManifestPath: './adapt.json', - DefaultProjectFrameworkPath: './package.json', - DefaultCreateType : 'course', - DefaultTypeNames : { - 'course':'my-adapt-course', - 'component':'my-adapt-component' - }, - DefaultUserAgent: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36', - DefaultGitHubOrg: 'adaptlearning', - FrameworkRepository : process.env.ADAPT_FRAMEWORK || 'https://github.com/adaptlearning/adapt_framework', - FrameworkRepositoryName : 'adapt_framework', - ComponentRepository : process.env.ADAPT_COMPONENT || 'https://github.com/adaptlearning/adapt-component', - ComponentRepositoryName : 'adapt-component', - HomeDirectory : searchForHome(), - getRegistry:getRegistry, - setCwd: setCwd, - cwd: '.' -}; - -var registry = null; - -function searchForHome() { - var locations = [ - process.env.HOME, - (process.env.HOMEDRIVE + process.env.HOMEPATH), - process.env.USERPROFILE, - '/tmp', - '/temp', - ]; - var validLocations = locations.filter(fs.existsSync); - return validLocations[0]; -} - -function getRegistry() { - if (registry !== null) { - return registry; - } - - if (process.env.ADAPT_REGISTRY) { - registry = process.env.ADAPT_REGISTRY; - - } else if (fs.existsSync(path.join(this.cwd, './.bowerrc'))) { - // a manifest exists; let bower determine the registry - registry = undefined; - - } else { - // use the default Adapt registry - registry = 'http://adapt-bower-repository.herokuapp.com/'; - } - - return registry; -} - -function setCwd(cwd) { - if (!cwd) return; - - this.cwd = cwd; - - this.DefaultProjectManifestPath = path.join(this.cwd, this.ManifestFilename); - this.DefaultProjectFrameworkPath = path.join(this.cwd, this.FrameworkFilename); -} diff --git a/lib/JsonLoader.js b/lib/JsonLoader.js deleted file mode 100644 index b5b6f0c..0000000 --- a/lib/JsonLoader.js +++ /dev/null @@ -1,40 +0,0 @@ -var fs = require('fs'), - JSONLint = require('json-lint'); - -module.exports = { - existsSync: fs.existsSync, - - exists: fs.exists, - - readJSON: function (filepath, done) { - done = done || function () {}; - - fs.readFile(filepath, 'utf8', function (err, data) { - if(err) return done(err); - - try { - validateJSON(data, filepath); - done(null, JSON.parse(data)); - } catch (ex) { - done(ex.message); - } - }); - }, - - readJSONSync: function (filepath) { - var data = fs.readFileSync(filepath, 'utf-8'); - validateJSON(data, filepath); - return JSON.parse(data); - } -}; - -function validateJSON(jsonData, filepath) { - var lint = JSONLint(jsonData); - if (lint.error) { - var errorMessage = 'JSON parsing error: ' + lint.error + ', line: ' + lint.line + ', character: ' + lint.character; - if(filepath) { - errorMessage += ', file: \'' + filepath + '\''; - } - throw new Error(errorMessage); - } -} diff --git a/lib/JsonWriter.js b/lib/JsonWriter.js deleted file mode 100644 index 2ac3ddf..0000000 --- a/lib/JsonWriter.js +++ /dev/null @@ -1,21 +0,0 @@ -var fs = require('fs'); - -module.exports = { - existsSync: fs.existsSync, - - exists: fs.exists, - - writeJSON: function (filepath, values, done) { - done = done || function () {}; - - fs.writeFile(filepath, JSON.stringify(values, null, 4), { encoding: 'utf8' }, function (err) { - if(err) return done(err); - - done(); - }); - }, - - writeJSONSync: function (filepath, values) { - return fs.writeFileSync(filepath, JSON.stringify(values, null, 4), { encoding: 'utf8' }); - } -} diff --git a/lib/PackageMeta.js b/lib/PackageMeta.js deleted file mode 100644 index 6c4516c..0000000 --- a/lib/PackageMeta.js +++ /dev/null @@ -1,41 +0,0 @@ -var bower = require('bower'), - Q = require('q'); - -module.exports = { - getKeywords: function (plugin, config) { - var deferred = Q.defer(); - - bower.commands.info(plugin.toString(), 'keywords', config || {}) - .on('end', function(results) { - deferred.resolve(results); - }) - .on('error', function(err) { - deferred.reject(err); - }); - return deferred.promise; - }, - getFrameworkCompatibility: function (plugin, config) { - var deferred = Q.defer(); - var allVersions = '*'; - - bower.commands.info(plugin.toString(), 'framework', config || {}) - .on('end', function(results) { - deferred.resolve(results || allVersions); - }) - .on('error', function() { - deferred.resolve(allVersions); - }); - return deferred.promise; - }, - getRepositoryUrl: function (plugin, config) { - var deferred = Q.defer(); - bower.commands.lookup(plugin.name, config || {}) - .on('end', function(results) { - deferred.resolve(results); - }) - .on('error', function(err) { - deferred.reject(err); - }); - return deferred.promise; - } -}; diff --git a/lib/Plugin.js b/lib/Plugin.js deleted file mode 100644 index 60a39a3..0000000 --- a/lib/Plugin.js +++ /dev/null @@ -1,53 +0,0 @@ -var slug = require('./Slug'), - endpointParser = require('bower-endpoint-parser'), - zero = '0.0.0', - any = '*'; - - -var Plugin = function(name, versionOrIsContrib, isContrib) { - this.name = name; - - if(typeof isContrib === 'undefined') { - isContrib = false; - } - if(typeof versionOrIsContrib === 'undefined') { - isContrib = false; - this.version = any; - } else if(typeof versionOrIsContrib === 'boolean'){ - isContrib = versionOrIsContrib; - this.version = any; - } else { - this.version = versionOrIsContrib === zero ? any : versionOrIsContrib; - } - this.packageName = makePackageName(name, isContrib); - - Object.defineProperty(this, 'isContrib', { - get: function () { - return /^adapt-contrib/.test(this.packageName); - } - }); -}; - -Plugin.prototype.toString = function() { - var version = ''; - if(this.version !== any) { - version = '#'+ this.version; - } - return ''+this.packageName + version; -}; - -function makePackageName(name, isContrib) { - return (/^adapt-/i.test(name) ? '' : 'adapt-') + (!isContrib ? '' : 'contrib-') + slug(name); -} - -Plugin.parse = function (endpoint) { - var ep = endpointParser.decompose(endpoint), - version = /^\*$/.test(ep.target) ? any : ep.target; - return new Plugin(ep.name || ep.source, version); -}; - -Plugin.compose = function (endpoint) { - return Plugin.parse(endpointParser.compose(endpoint)); -}; - -module.exports = Plugin; \ No newline at end of file diff --git a/lib/PluginTypeResolver.js b/lib/PluginTypeResolver.js deleted file mode 100644 index 57e233e..0000000 --- a/lib/PluginTypeResolver.js +++ /dev/null @@ -1,47 +0,0 @@ -var PluginTypeResolver = function(types) { - this.types = types || [ - { - pattern: /^adapt-component$/, - typename: 'component', - belongsTo: 'components' - }, - { - pattern: /^adapt-extension$/, - typename: 'extension', - belongsTo: 'extensions' - }, - { - pattern: /^adapt-menu$/, - typename: 'menu', - belongsTo: 'menu' - }, - { - pattern: /^adapt-theme$/, - typename: 'theme', - belongsTo: 'theme' - } - ]; - this.defaultType = this.types[0]; -}; -PluginTypeResolver.prototype.resolve = function (keywords) { - keywords = Array.isArray(keywords) ? keywords : [keywords]; - - var types = keywords.map(toType(this.types)) - .filter(NonMatchingKeywords); - - return (types.length ? types[0] : this.defaultType); -}; -module.exports = PluginTypeResolver; - -function toType(types) { - return function (keyword) { - var typematches = types.filter(function (type) { - return type.pattern.test(keyword); - }); - if(typematches.length) return typematches[0]; - } -} - -function NonMatchingKeywords(item) { - return item !== undefined -} \ No newline at end of file diff --git a/lib/Project.js b/lib/Project.js deleted file mode 100644 index 1acc4a9..0000000 --- a/lib/Project.js +++ /dev/null @@ -1,89 +0,0 @@ -var Plugin = require('./Plugin'), - fs = require('fs'), - _ = require('lodash'), - JsonLoader = require('./JsonLoader'), - JsonWriter = require('./JsonWriter'), - chalk = require('chalk'), - renderer = require('./ConsoleRenderer'), - EmptyProject = function (){ - return { - dependencies: {} - }; - }; - EmptyPackage = function () { - return { "version": "0.0.0" }; - }; - -var Project = function (manifestFilePath, frameworkPackagePath) { - this.manifestFilePath = manifestFilePath; - this.frameworkPackagePath = frameworkPackagePath; - Object.defineProperty(this, 'plugins', { - get: function () { - var manifest = parse(this.manifestFilePath); - return _.toPairs(manifest.dependencies) - .map(function (pair) { - return new Plugin(pair[0], pair[1]); - }); - }.bind(this) - }); -}; - -Project.prototype.add = function (plugin) { - if(typeof Plugin !== 'object' && plugin.constructor !== Plugin) { - plugin = new Plugin(plugin); - } - var manifest; - if(this.isProjectContainsManifestFile()) { - manifest = parse(this.manifestFilePath); - } else { - manifest = EmptyProject(); - } - manifest.dependencies[plugin.packageName] = plugin.version; - save(this.manifestFilePath, manifest); -}; - -Project.prototype.remove = function (plugin) { - if(typeof Plugin !== 'object' && plugin.constructor !== Plugin) { - plugin = new Plugin(plugin); - } - var manifest = parse(this.manifestFilePath); - delete manifest.dependencies[plugin.packageName]; - save(this.manifestFilePath, manifest); -}; - -Project.prototype.getFrameworkVersion = function () { - return parsePackage(this.frameworkPackagePath).version; -}; - -Project.prototype.isProjectContainsManifestFile = function() { - return fs.existsSync(this.manifestFilePath); -}; - -function parse(manifestFilePath) { - if(!manifestFilePath) return EmptyProject(); - - return JsonLoader.readJSONSync(manifestFilePath); -} - -function parsePackage(frameworkPackagePath) { - var EmptyPackage = function () { - return { "version": "0.0.0" } - }; - - if(!frameworkPackagePath) return EmptyPackage(); - - try { - return JsonLoader.readJSONSync(frameworkPackagePath); - } - catch (ex) { - return EmptyPackage(); - } -} - -function save(manifestFilePath, manifest) { - if(manifestFilePath) { - JsonWriter.writeJSONSync(manifestFilePath, manifest); - } -} - -module.exports = Project; diff --git a/lib/RendererHelpers.js b/lib/RendererHelpers.js deleted file mode 100644 index 659ec38..0000000 --- a/lib/RendererHelpers.js +++ /dev/null @@ -1,41 +0,0 @@ -var chalk = require('chalk'), - inquirer = require('inquirer'), - Q = require('q'); - -module.exports = { - reportCompatibilityWarning : function (renderer, plugin) { - renderer.log(chalk.yellow('The plugin'), chalk.white(plugin), chalk.yellow('is not compatible with this version of Adapt.', 'Installing it may cause unexpected behaviour.')); - return confirm(plugin); - }, - reportFailure : function (renderer, done) { - return function (err) { - renderer.log(chalk.red('Oh dear, something went wrong.'), err.message); - done(err); - }; - }, - reportInvalidFrameworkDirectory : function (renderer, done) { - return function (err) { - renderer.log(chalk.red('Fatal error: please run above commands in adapt course directory.')); - done(err); - }; - }, -}; - -function confirm(plugin) { - var deferred = Q.defer(); - var schema = [ - { - name: 'continueWithInstall', - message: 'Install this plugin anyway?', - type: 'confirm', - default: false - } - ]; - inquirer.prompt(schema).then(properties => { - deferred.resolve({ - plugin: plugin, - continueWithInstall: properties.continueWithInstall - }); - }).catch(err => deferred.reject(err)); - return deferred.promise; -} diff --git a/lib/RepositoryDownloader.js b/lib/RepositoryDownloader.js deleted file mode 100644 index dd36e86..0000000 --- a/lib/RepositoryDownloader.js +++ /dev/null @@ -1,64 +0,0 @@ -var Constants = require('./Constants'), - urljoin = require('url-join'), - path = require('path'), - Q = require('q'); - -var RepositoryDownloader = function(options) { - if (!options.branch && !options.repository) - throw new Error('Repository details are required.'); - this.options = options; - - Object.defineProperty(this, 'url', { - get: function() { - return urljoin(this.options.repository, 'archive', this.options.branch + '.zip'); - } - }); -}; - -RepositoryDownloader.prototype.fetch = function(destination) { - var deferred = Q.defer(), - download = require('download'), - previousPercent = 0, - fileName = ''; - - download(this.url, destination, { - extract: true - }) - .on('response', function (response) { - fileName = getFileName(response.headers['content-disposition']); - }) - .on('downloadProgress', function(progress) { - var state = { - receivedSize: progress.transferred, - percent: Math.round(progress.transferred / progress.total * 100) - }; - - if(state.percent > previousPercent) { - previousPercent = state.percent; - deferred.notify(state, progress); - } - }) - .on('error', function(err) { - deferred.reject(err); - }) - .then(function() { - deferred.resolve(fileName); - }); - - return deferred.promise; -}; - -function getFileName(disposition) { - var fileName = ""; - if (disposition && disposition.indexOf('attachment') !== -1) { - var regex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; - var matches = regex.exec(disposition); - if (matches != null && matches[1]) { - fileName = matches[1].replace(/['"]/g, ''); - } - } - return fileName; -} - -module.exports = RepositoryDownloader; - diff --git a/lib/Slug.js b/lib/Slug.js deleted file mode 100644 index 85e474e..0000000 --- a/lib/Slug.js +++ /dev/null @@ -1,5 +0,0 @@ -var slug = require('speakingurl'); -module.exports = function (name) { - - return slug(name, { maintainCase: true }) -}; \ No newline at end of file diff --git a/lib/VersionChecker.js b/lib/VersionChecker.js deleted file mode 100644 index abad1f0..0000000 --- a/lib/VersionChecker.js +++ /dev/null @@ -1,7 +0,0 @@ -var semver = require('semver'); - -module.exports = { - assertVersionCompatibility: function (adaptVersion, compatibleVersionRange) { - return semver.satisfies(adaptVersion, compatibleVersionRange); - } -}; diff --git a/lib/api.js b/lib/api.js new file mode 100644 index 0000000..998be4c --- /dev/null +++ b/lib/api.js @@ -0,0 +1,260 @@ +import http from 'http' // api http import, to hold open process for testing +import { ADAPT_FRAMEWORK } from './util/constants.js' +import { + build, + download, + erase, + getLatestVersion, + npmInstall, + deleteSrcCourse, + deleteSrcCore +} from './integration/AdaptFramework.js' +import { + install, + uninstall, + update, + schemas +} from './integration/PluginManagement.js' +import Plugin from './integration/Plugin.js' +import Project from './integration/Project.js' +import fs from 'fs-extra' +import async from 'async' + +// TODO: api, check no interactivity, should be sorted, will fail silently if it absolutely cannot do what you've asked +// TODO: api, console and error output, error on fail when isInteractive: false? or something else? return Targets? +// TODO: api, figure out error translations, should probably error with codes? + +class API { + /** + * Installs a clean copy of the framework + * @param {Object} options + * @param {string} [options.version=null] Specific version of the framework to install + * @param {string} [options.repository] URL to github repo + * @param {string} [options.cwd=process.cwd()] Directory to install into + * @return {Promise} + */ + async installFramework ({ + version = null, + repository = ADAPT_FRAMEWORK, + cwd = process.cwd() + } = {}) { + if (!version) version = await getLatestVersion({ repository }) + await erase({ + isInteractive: false, + cwd + }) + await download({ + repository, + branch: version, + cwd + }) + await deleteSrcCourse({ + cwd + }) + await deleteSrcCore({ + cwd + }) + await npmInstall({ + cwd + }) + } + + /** + * @param {Object} options + * @param {Object} [options.repository=ADAPT_FRAMEWORK] The github repository url + * @returns {string} + */ + async getLatestFrameworkVersion ({ + repository = ADAPT_FRAMEWORK + } = {}) { + return getLatestVersion({ repository }) + } + + /** + * Runs build for a current course + * @param {Object} options + * @param {boolean} [options.sourceMaps=false] Whether to run the build with sourcemaps + * @param {boolean} [options.checkJSON=false] Whether to run without checking the json + * @param {boolean} [options.cache=true] Whether to clear build caches + * @param {string} [options.outputDir="build/"] Root path of the framework installation + * @param {string} [options.cachePath="build/.cache"] Path of compilation cache file + * @param {string} [options.cwd=process.cwd()] Root path of the framework installation + * @return {Promise} + */ + async buildCourse ({ + sourceMaps = false, + checkJSON = false, + cache = true, + outputDir = null, + cachePath = './build/.cache', + cwd = process.cwd() + } = {}) { + await build({ + sourceMaps, + checkJSON, + cache, + cwd, + outputDir, + cachePath + }) + } + + /** + * Installs multiple plugins + * Can install from source folder or bower registry + * @param {Object} options + * @param {[string]} [options.plugins=null] An array with name@version or name@path strings + * @param {string} [options.cwd=process.cwd()] Root path of the framework installation + * @return {Promise<[Target]>} + */ + async installPlugins ({ + plugins = null, + cwd = process.cwd() + } = {}) { + return await install({ + plugins, + isInteractive: false, + cwd + }) + } + + /** + * Uninstalls multiple plugins + * @param {Object} options + * @param {[string]} [options.plugins=null] An array with name@version or name@path strings + * @param {string} [options.cwd=process.cwd()] Root path of the framework installation + * @return {Promise<[Target]>} + */ + async uninstallPlugins ({ + plugins = null, + cwd = process.cwd() + } = {}) { + return await uninstall({ + plugins, + isInteractive: false, + cwd + }) + } + + /** + * Updates multiple plugins + * Can install from source folder or bower registry + * @param {Object} options + * @param {[string]} [options.plugins=null] An array with name@version or name@path strings + * @param {string} [options.cwd=process.cwd()] Root path of the framework installation + * @return {Promise<[Target]>} + */ + async updatePlugins ({ + plugins = null, + cwd = process.cwd() + } = {}) { + return await update({ + plugins, + isInteractive: false, + cwd + }) + } + + /** + * Retrieves all schemas defined in the project + * Clears schema cache + * @param {string} [options.cwd=process.cwd()] Root path of the framework installation + * @return {Promise<[string]>} Resolves with array of JSON schema filepaths + */ + async getSchemaPaths ({ + cwd = process.cwd() + } = {}) { + this._schemaPaths = await schemas({ cwd }) + this._schemas = {} + return this._schemaPaths + } + + /** + * Retrieves named schema + * Caches schemas for subsequent use + * Call getSchemaPaths to reset cache + * @param {string} options.name Schema filepath as returned from getSchemaPaths + * @return {Promise} Resolves with the JSON schema contents + */ + async getSchema ({ + name + } = {}) { + if (!this._schemaPaths) return new Error('Please run getSchemaPaths first') + if (!fs.existsSync(name) || !this._schemaPaths.includes(name)) throw new Error(`Schema does not exist: ${name}`) + return (this._schemas[name] = this._schemas[name] ?? await fs.readJSON(name)) + } + + /** + * Returns all installed plugins + * @return {Promise<[Plugin]>} + */ + async getInstalledPlugins ({ + cwd = process.cwd() + } = {}) { + const project = new Project({ cwd }) + if (!project.isAdaptDirectory) throw new Error(`Not in an adapt folder at: ${cwd}`) + const installedPlugins = await project.getInstalledPlugins() + for (const plugin of installedPlugins) { + await plugin.fetchProjectInfo() + } + return installedPlugins + } + + /** + * Gets the update information for installed and named plugins + * @param {Object} options + * @param {[string]} [options.plugins=null] An y of plugin names (if not specified, all plugins are checked) + * @param {string} [options.cwd=process.cwd()] Root path of the framework installation + * @return {Promise<[Plugin]>} + */ + async getPluginUpdateInfos ({ + plugins = null, + cwd = process.cwd() + } = {}) { + /** @type {Project} */ + const project = new Project({ cwd }) + if (!project.isAdaptDirectory) throw new Error(`Not in an adapt folder at: ${cwd}`) + const frameworkVersion = project.version + /** @type {[Plugin]} */ + const installedPlugins = await project.getInstalledPlugins() + const filteredPlugins = !plugins?.length + ? installedPlugins + : plugins + .map(name => installedPlugins.find(plugin => plugin.packageName === name)) + .filter(Boolean) + await async.eachOfLimit(filteredPlugins, 8, async plugin => { + await plugin.fetchProjectInfo() + await plugin.fetchBowerInfo() + await plugin.findCompatibleVersion(frameworkVersion) + }) + return filteredPlugins + } + + /** + * Returns an object representing the plugin at the path specified + * @returns {Plugin} + */ + async getPluginFromPath ({ + pluginPath, + cwd = null + } = {}) { + const project = cwd ? new Project({ cwd }) : null + return Plugin.fromPath({ pluginPath, project }) + } +} + +const api = new API() +export default api + +// debugging +if (process.argv.includes('--debug-wait')) { + // http server to hold open process for testing + const a = http.createServer((request, response) => { + response.writeHead(200, { 'Content-Type': 'text/plain' }) + response.end('test', 'utf-8') + }) + a.listen(999) + // make api global to debug more easily + global.api = api + console.log('API Ready') +} diff --git a/lib/cli.js b/lib/cli.js index 46a6209..6da9b76 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -1,52 +1,69 @@ -var path = require('path'), - _ = require('lodash'), - CommandParser = require('./CommandParser'), - AdaptConsoleApplication = require('./AdaptConsoleApplication'), - stdoutRenderer = { - log: _.bind(console.log, console), - write: _.bind(process.stdout.write, process.stdout) - }; +import authenticate from './commands/authenticate.js' +import create from './commands/create.js' +import devinstall from './commands/devinstall.js' +import help from './commands/help.js' +import install from './commands/install.js' +import ls from './commands/ls.js' +import register from './commands/register.js' +import rename from './commands/rename.js' +import search from './commands/search.js' +import uninstall from './commands/uninstall.js' +import unregister from './commands/unregister.js' +import update from './commands/update.js' +import version from './commands/version.js' +import logger from './logger.js' -function withPackage(pack) { - this.pkg = pack || require(path.join(__dirname, '..', 'package.json')); - return this; +const commands = { + authenticate, + create, + devinstall, + help, + install, + ls, + register, + rename, + search, + uninstall, + unregister, + update, + version } -function withOptions(argv) { - argv = argv || process.argv; - this.command = new CommandParser(argv); - return this; -} - -function execute() { - var commands = require('./commands'), - app = new AdaptConsoleApplication(commands, stdoutRenderer); - - app.do(this.command, function (err) { - process.exit(err ? 1: 0); - }); -} - -function getApi() { - var commands = require('./commands'); - var apiCommands = {}; +const translationTable = [ + { pattern: /^-v$|^--version$/i, replacement: 'version' }, + { pattern: /^upgrade$/i, replacement: 'update' } +] - _.each(commands, function(command, commandName) { - var prefix = 'api'; - if (commandName.startsWith(prefix)) { - apiCommands[commandName.split(prefix)[1]] = command; - } - }); +class CLI { + withOptions (argv = process.argv || ['node', 'path']) { + const parameters = argv.slice(2).map(param => { + const translation = translationTable.find(item => item.pattern.test(param)) + return translation ? translation.replacement : param + }) + const name = parameters.length + ? String.prototype.toLowerCase.call(parameters.shift()) + : '' + this.command = { + name, + parameters + } + return this + } - return { - commands:apiCommands + async execute () { + try { + if (!commands[this.command.name]) { + const e = new Error(`Unknown command "${this.command.name}", please check the documentation.`) + logger?.log(e.message) + throw e + } + const commandArguments = [logger].concat(this.command.parameters) + await commands[this.command.name](...commandArguments) + } catch (err) { + console.error(err) + process.exit(err ? 1 : 0) } + } } -module.exports = { - command: null, - withOptions: withOptions, - withPackage: withPackage, - execute: execute, - api: getApi() -}; +export default new CLI() diff --git a/lib/commands/authenticate.js b/lib/commands/authenticate.js new file mode 100644 index 0000000..4a405d4 --- /dev/null +++ b/lib/commands/authenticate.js @@ -0,0 +1,18 @@ +import chalk from 'chalk' +import { authenticate as pluginAuthenticate } from '../integration/PluginManagement.js' + +export default async function authenticate (logger, ...args) { + // strip flags + args = args.filter(arg => !String(arg).startsWith('--')) + try { + const confirmation = await pluginAuthenticate({ + logger, + cwd: process.cwd(), + pluginName: args[0] + }) + const { username, type, pluginName } = confirmation + logger?.log(chalk.green(`${username} authenticated as ${type} for ${pluginName}`)) + } catch (err) { + logger?.error('Authentication failed') + } +} diff --git a/lib/commands/create.js b/lib/commands/create.js index e2640a6..42418ee 100644 --- a/lib/commands/create.js +++ b/lib/commands/create.js @@ -1,90 +1,85 @@ -var bower = require('bower'), - chalk = require('chalk'), - inquirer = require('inquirer'), - path = require('path'), - Q = require('q'), - Constants = require('../Constants'), - Plugin = require('../Plugin'), - create = require('./create/index'), - highest = require('../promise/highest'), - _ = require('lodash'); +import inquirer from 'inquirer' +import component from './create/component.js' +import question from './create/question.js' +import course from './create/course.js' +import { ADAPT_FRAMEWORK } from '../util/constants.js' +import { getLatestVersion as getAdaptLatestVersion } from '../integration/AdaptFramework.js' -module.exports = { - create: function (renderer) { - var type = arguments.length >= 3 ? arguments[1] : Constants.DefaultCreateType, - localDir = arguments.length >= 4 ? arguments[2] : undefined, - branch = arguments.length >= 5 ? arguments[3] : undefined, - done = arguments[arguments.length-1]; - highest() - .then(function (tag) { - return confirm({ - type: type, - localDir: localDir, - branch: branch || tag, - renderer: renderer - }); - }) - .then(function (properties) { - var action = create[properties.type]; - if(!action) throw new Error('' + properties.type + ' is not a supported type'); - return action(properties); - }) - .then(function () { - done(); - }) - .fail(function (err) { - renderer.log(chalk.red("Oh dear, something went wrong. I'm terribly sorry."), err.message); - done(err); - }); - } -}; - -function confirm(properties) { - var deferred = Q.defer(), - renderer = properties.renderer; - - var typeSchema = [ - { - name: 'type', - choices: [ 'course', 'component' ], - type: 'list', - default: properties.type - } - ]; +const subTasks = { + component, + question, + course +} - inquirer.prompt(typeSchema).then(typeSchemaResults => { - var propertySchema = [ - { - name: 'localDir', - message: 'name', - type: 'input', - default: properties.localDir || Constants.DefaultTypeNames[typeSchemaResults.type] - }, - { - name: 'branch', - message: 'branch/tag', - type: 'input', - default: properties.branch || 'not specified' - }, - { - name: 'ready', - message: 'create now?', - type: 'confirm', - default: true - } - ]; +/** + * TODO: Change component name to camel case + */ +export const DEFAULT_TYPE_NAME = { + course: 'my-adapt-course', + component: 'myAdaptComponent', + question: 'myAdaptQuestion' +} - inquirer.prompt(propertySchema).then(propertySchemaResults => { - if(!propertySchemaResults.ready) deferred.reject(new Error('Aborted. Nothing has been created.')); +export default async function create (logger, type = 'course', name, branch) { + const options = await confirmOptions({ + type, + name, + branch, + logger + }) + const action = subTasks[options.type] + if (!action) throw new Error('' + options.type + ' is not a supported type') + try { + await action({ + name: options.name, + branch: options.branch, + cwd: process.cwd(), + logger + }) + } catch (err) { + logger?.error("Oh dear, something went wrong. I'm terribly sorry.", err.message) + throw err + } +} - var properties = _.extend({}, - typeSchemaResults, - propertySchemaResults, - { - renderer: renderer - }); - deferred.resolve(properties); - }).catch(err => deferred.reject(err)); - }).catch(err => deferred.reject(err)); - return deferred.promise; +async function confirmOptions ({ logger, type, name, branch }) { + const typeSchema = [ + { + name: 'type', + choices: ['course', 'component', 'question'], + type: 'list', + default: type + } + ] + const typeSchemaResults = await inquirer.prompt(typeSchema) + branch = branch || (typeSchemaResults.type === 'course') + ? await getAdaptLatestVersion({ repository: ADAPT_FRAMEWORK }) + : 'master' + const propertySchema = [ + { + name: 'name', + message: 'name', + type: 'input', + default: name || DEFAULT_TYPE_NAME[typeSchemaResults.type] + }, + { + name: 'branch', + message: 'branch/tag', + type: 'input', + default: branch || 'not specified' + }, + { + name: 'ready', + message: 'create now?', + type: 'confirm', + default: true + } + ] + const propertySchemaResults = await inquirer.prompt(propertySchema) + if (!propertySchemaResults.ready) throw new Error('Aborted. Nothing has been created.') + const finalProperties = { + ...typeSchemaResults, + ...propertySchemaResults + } + return finalProperties } diff --git a/lib/commands/create/component.js b/lib/commands/create/component.js index 65689d1..76eb077 100644 --- a/lib/commands/create/component.js +++ b/lib/commands/create/component.js @@ -1,81 +1,64 @@ -var chalk = require('chalk'), - Q = require('q'), - getRepository = require('../../promise/getRepository'), - removeTemporaryDownload = require('../../promise/removeTemporaryDownload'), - replaceTextContent = require('../../promise/replaceTextContent'), - slug = require('../../Slug'), - Constants = require('../../Constants'); +import fs from 'fs-extra' +import globs from 'globs' +import path from 'path' +import chalk from 'chalk' +import slug from 'speakingurl' +import Project from '../../integration/Project.js' +import downloader from '../../util/download.js' +import { ADAPT_COMPONENT } from '../../util/constants.js' -module.exports = function (properties) { - var fs = require('fs'), - path = require('path'); +export default async function component ({ + name, + repository = ADAPT_COMPONENT, + cwd, + branch, + logger +}) { + name = slug(name, { maintainCase: true }) - properties.component = { - name: slug(properties.localDir), - files: [] - }; - properties.relative = function (file) { - return path.join(this.localDir, file); - }; + const project = new Project({ cwd, logger }) + let pluginDir + if (project.containsManifestFile) { + const componentsDirectory = 'src/components' + pluginDir = path.join(cwd, componentsDirectory, 'adapt-' + name) + if (!fs.existsSync(componentsDirectory)) fs.mkdirSync(componentsDirectory) + } else { + pluginDir = path.join(cwd, name) + } - if(addComponentToCurrentCourse()) { - var componentsDirectory = 'src/components'; - properties.localDir = path.join(componentsDirectory, properties.localDir); - if(!fs.existsSync(componentsDirectory)) fs.mkdirSync(componentsDirectory); - } - properties.component.files.push(properties.relative('bower.json')); + await downloader({ + branch, + repository, + cwd: pluginDir, + logger + }) - return createComponent(properties) - .then(function (properties) { - properties.renderer.log('\n' + chalk.green(properties.localDir), 'has been created.\n'); + const files = await new Promise((resolve, reject) => { + globs('**', { cwd: pluginDir }, (err, matches) => { + if (err) return reject(err) + resolve(matches.map(match => path.join(pluginDir, match))) + }) + }) - if(addComponentToCurrentCourse()) { - properties.renderer.log(chalk.grey('To use this component in your course, use the registered name:') + chalk.yellow(properties.component.name)); - } - }); -}; + const filesRenamed = files.map(from => { + const to = from.replace(/((contrib-)?componentName)/g, name) + fs.renameSync(from, to) + return to + }) -function addComponentToCurrentCourse() { - var fs = require('fs'); - return fs.existsSync('./adapt.json'); -} - -function createComponent(properties) { - properties.repository = Constants.ComponentRepository; - properties.repositoryName = Constants.ComponentRepositoryName; - return getRepository(properties) - .then(removeTemporaryDownload) - .then(renameFiles) - .then(renameVariables); -} + await Promise.all(filesRenamed.map(async function (file) { + if (fs.statSync(file).isDirectory()) return + const lowerCaseName = name.toLowerCase() + const content = (await fs.readFile(file)).toString() + const modifiedContent = content + .replace(/((contrib-)?componentName)/g, name) + .replace(/((contrib-)?componentname)/g, lowerCaseName) + return fs.writeFile(file, modifiedContent) + })) -function renameFiles(properties) { - var fs = require('fs'), - path = require('path'); + logger?.log('\n' + chalk.green(pluginDir), 'has been created.\n') - var files = [ - { match: 'js/adapt-contrib-componentName.js', replace: /contrib-componentName/ }, - { match: 'less/componentName.less', replace: /componentName/ }, - { match: 'templates/componentName.hbs', replace: /componentName/ } - ]; - var renameFiles = files.map(function (file) { - return { - from: properties.relative(file.match), - to: properties.relative(file.match.replace(file.replace, properties.component.name)) - }; - }); - renameFiles.forEach(function (file) { - fs.renameSync(file.from, file.to); - properties.component.files.push(file.to); - }); - return properties; + if (fs.existsSync('./adapt.json')) { + logger?.log(chalk.grey('To use this component in your course, use the registered name:') + chalk.yellow(name)) + } } - -function renameVariables(properties) { - var renameFileContentPromises = properties.component.files.map(function (file) { - return replaceTextContent(file, (/((contrib-)?componentName)/g), properties.component.name); - }); - return Q.all(renameFileContentPromises).then(function () { - return properties; - }); -} \ No newline at end of file diff --git a/lib/commands/create/course.js b/lib/commands/create/course.js index dfca077..81fd973 100644 --- a/lib/commands/create/course.js +++ b/lib/commands/create/course.js @@ -1,81 +1,26 @@ -var bower = require('bower'), - chalk = require('chalk'), - inquirer = require('inquirer'), - path = require('path'), - Q = require('q'), - fs = require('q-io/fs'), - Plugin = require('../../Plugin'), - getRepository = require('../../promise/getRepository'), - removeTemporaryDownload = require('../../promise/removeTemporaryDownload'), - installNodeDependencies = require('../../promise/installNodeDependencies'), - installAdaptDependencies = require('../../promise/installAdaptDependencies'), - _ = require('lodash'); - -module.exports = function (properties) { - var progress = _.throttle(function () { - properties.renderer.write(chalk.grey('.')); - }, 300); - - return deleteExistingCourse(properties) - .then(function (properties) { - properties.renderer.write(chalk.cyan('downloading framework to', properties.localDir, '\t')); - return properties; - }) - .then(getRepository) - .progress(function (data) { - progress(); - return data; - }) - .then(function (properties) { - properties.renderer.log(' ', 'done!'); - return properties; - }) - .then(removeTemporaryDownload) - .then(installNodeDependencies) - .then(installAdaptDependencies) - .then(function (properties) { - properties.renderer.log('\n' + chalk.green(properties.localDir), 'has been created.\n'); - - properties.renderer.log(chalk.grey('To build the course, run:') + - '\n\tcd ' + properties.localDir + - '\n\tgrunt build\n'); - - properties.renderer.log(chalk.grey('Then to view the course, run:') + - '\n\tgrunt server\n'); - }); - -}; - -function deleteExistingCourse(properties) { - return fs.exists(properties.localDir) - .then(function (exists) { - if(exists) { - var deferred = Q.defer(); - - inquirer.prompt([ - { - name: 'overwrite existing course?', - type: 'confirm', - default: false - } - ]).then(results => { - if(results['overwrite existing course?']) { - fs.removeTree(properties.localDir) - .then(function (){ - deferred.resolve(properties); - }) - .fail(function (err) { - deferred.reject(err); - }); - } else { - deferred.reject(new Error('Course already exists and cannot overwrite.')); - } - }).catch(err => deferred.reject(err)); - - return deferred.promise; - } - }) - .then(function () { - return properties; - }); +import chalk from 'chalk' +import { + erase, + download, + npmInstall +} from '../../integration/AdaptFramework.js' +import path from 'path' +import { install as pluginsInstall } from '../../integration/PluginManagement.js' + +export default async function course ({ name, branch, cwd, logger }) { + cwd = path.join(cwd, name) + await erase({ logger, cwd }) + await download({ logger, cwd, branch }) + await npmInstall({ logger, cwd }) + await pluginsInstall({ logger, cwd }) + logger?.log(` +${chalk.green(name)} has been created. + +${chalk.grey('To build the course, run:')} + cd ${name} + grunt build + +${chalk.grey('Then to view the course, run:')} + grunt server +`) } diff --git a/lib/commands/create/index.js b/lib/commands/create/index.js deleted file mode 100644 index c5f7b5c..0000000 --- a/lib/commands/create/index.js +++ /dev/null @@ -1,6 +0,0 @@ -var chalk = require('chalk'); - -module.exports = { - "course": require('./course'), - "component": require('./component') -}; diff --git a/lib/commands/create/question.js b/lib/commands/create/question.js new file mode 100644 index 0000000..5f381ba --- /dev/null +++ b/lib/commands/create/question.js @@ -0,0 +1,18 @@ +import component from './component.js' +import { ADAPT_QUESTION } from '../../util/constants.js' + +export default async function question ({ + name, + repository = ADAPT_QUESTION, + cwd, + branch, + logger +}) { + return component({ + name, + repository, + cwd, + branch, + logger + }) +} diff --git a/lib/commands/devinstall.js b/lib/commands/devinstall.js index cf9139f..0bb3b65 100644 --- a/lib/commands/devinstall.js +++ b/lib/commands/devinstall.js @@ -1,97 +1,35 @@ -var promise = require('../promise/util'); - -module.exports = function (dependencies) { - - var chalk = dependencies.chalk || require('chalk'), - path = dependencies.path || require('path'), - Q = dependencies.Q || require('q'), - Constants = dependencies.Constants || require('../Constants'), - PluginTypeResolver = dependencies.PluginTypeResolver || require('../PluginTypeResolver'), - PackageMeta = dependencies.PackageMeta || require('../PackageMeta'), - Project = dependencies.Project || require('../Project'), - Plugin = dependencies.Plugin || require('../Plugin'), - RendererHelpers = dependencies.RendererHelpers || require('../RendererHelpers'), - VersionChecker = dependencies.VersionChecker || require('../VersionChecker'), - install = dependencies.install || require('../promise/install'), - cloneInstall = dependencies.cloneInstall || require('../promise/cloneInstall'), - mkdirp = require('mkdirp'), - exec = require('child_process').exec; - - function clonePlugins(localPath, renderer) { - renderer.log("Cloning Plugins"); - - var project = new Project( - path.resolve(localPath, Constants.DefaultProjectManifestPath), - path.resolve(localPath, Constants.DefaultProjectFrameworkPath) - ), - plugins = project.plugins; - - - - plugins.forEach(function(plugin, index, array) { - createInstallationTask(plugin, localPath, renderer); - }); - } - - - function createInstallationTask(plugin, localPath, renderer) { - return PackageMeta.getKeywords(plugin, { registry: Constants.getRegistry() }) - .then(function (keywords) { - var resolver = new PluginTypeResolver(), - pluginType = resolver.resolve(keywords); - - renderer.log(chalk.cyan(plugin.packageName), 'found.', 'Installing', pluginType.typename, '...'); - return cloneInstall(plugin, { - localPath: localPath, - directory: path.join('src', pluginType.belongsTo), - registry: Constants.getRegistry() - }); - }) - .then(function (installed) { - if (!installed) throw new Error('The plugin was found but failed to download and install.'); - renderer.log(chalk.green(plugin.packageName), 'has been installed successfully.'); - }) - .done(); - } - - return { - devinstall: function (renderer) { - - var repository = arguments.length >= 3 ? arguments[1] : Constants.FrameworkRepository, - localPath = path.resolve(Constants.FrameworkRepositoryName), - done = arguments[arguments.length-1] || function () {}; - - try { - // Are we inside an existing adapt_framework project. - var packageJson = require(process.cwd() + '/package.json'); - if (packageJson.name === 'adapt_framework') { - localPath = process.cwd(); - } - } catch (err) { - // Don't worry, we're not inside a framework directory. - } - - // we're trying to install a single plugin. - if (repository !== Constants.FrameworkRepository) { - return createInstallationTask(Plugin.parse(repository), localPath, renderer) - } - - function promiseFromChildProcess(child) { - return new Promise(function (resolve, reject) { - child.addListener("error", reject); - child.addListener("exit", resolve); - }); - } - var child = exec(`git clone ${repository} "${localPath}"`); - - // clone the framework and all the bundled plugins. - renderer.log("Cloning adapt_framework"); - promiseFromChildProcess(child) - .then(function(repo){ - renderer.log("Framework cloned."); - process.chdir(localPath); - clonePlugins(localPath, renderer, done); - }); - } - }; -}; +import { clone as adaptClone } from '../integration/AdaptFramework.js' +import { install as pluginsInstall } from '../integration/PluginManagement.js' +import { ADAPT_FRAMEWORK } from '../util/constants.js' +import path from 'path' +import Project from '../integration/Project.js' +import gh from 'parse-github-url' + +export default async function devinstall (logger, ...args) { + const NAME = gh(ADAPT_FRAMEWORK).repo + const isInAdapt = new Project().isAdaptDirectory + // In adapt folder or download adapt into adapt_framework folder + const cwd = isInAdapt + ? process.cwd() + : path.resolve(NAME) + // strip flags + const isClean = args.includes('--clean') + const isDryRun = args.includes('--dry-run') || args.includes('--check') + const isCompatibleEnabled = args.includes('--compatible') + args = args.filter(arg => !String(arg).startsWith('--')) + // always perform a clone on the adapt directory + if (!isInAdapt || args.includes(NAME)) { + await adaptClone({ logger, cwd }) + args = args.filter(arg => arg !== NAME) + } + const plugins = args + return await pluginsInstall({ + logger, + cwd, + isClean, + isDryRun, + isCompatibleEnabled, + dev: true, + plugins + }) +} diff --git a/lib/commands/help.js b/lib/commands/help.js index 9389f3a..75a1b41 100644 --- a/lib/commands/help.js +++ b/lib/commands/help.js @@ -1,52 +1,31 @@ -var fs = require('fs'), - path = require('path'), - chalk = require('chalk'), - _ = require('lodash'); - -module.exports = { - help: function (renderer) { - - var name = arguments.length >= 3 - ? arguments.length > 3 - ? Array.prototype.slice.apply(arguments, [1, arguments.length -1]).join(' ') - : arguments[1] - : ''; - var json; - - if (name) { - json = path.resolve(__dirname, '../../json/help-' + name.replace(/\s+/g, '/') + '.json'); - } else { - json = path.resolve(__dirname, '../../json/help.json'); - } - - fs.exists(json, function(exists) { - if (!exists) { - renderer.log('adapt ' + chalk.red(name) + ' Unknown command: ' + name); - } else { - - var jsonData = require(json); - - renderer.log('\nUsage: \n'); - _.each(jsonData.usage, function(usage) { - renderer.log(' ' + chalk.cyan('adapt') + ' ' + usage); - }); - - if(!_.isEmpty(jsonData.commands)) { - renderer.log('\n\nwhere is one of:\n'); - _.each(jsonData.commands, function(description, command) { - renderer.log(' ' + command + new Array(23 - command.length).join(' ') + description); - }); - } - - if(jsonData.description) { - renderer.log('\nDescription:\n\n ' + jsonData.description); - } - - if(!name) { - renderer.log('\nSee \'adapt help \' for more information on a specific command.\n'); - } - } - }); - - } -}; +import fs from 'fs-extra' +import path from 'path' +import chalk from 'chalk' +import getDirNameFromImportMeta from '../util/getDirNameFromImportMeta.js' +const __dirname = getDirNameFromImportMeta(import.meta) + +export default function help (logger, ...args) { + const name = args.join(' ') + const json = name + ? path.resolve(__dirname, `../../json/help-${name.replace(/\s+/g, '/')}.json`) + : path.resolve(__dirname, '../../json/help.json') + if (!fs.existsSync(json)) { + logger?.log(`adapt ${chalk.red(name)} Unknown command: ${name}`) + return + } + const jsonData = fs.readJSONSync(json) + logger?.log('\nUsage: \n') + jsonData.usage.forEach(usage => logger?.log(` ${chalk.cyan('adapt')} ${usage}`)) + if (jsonData.commands && Object.entries(jsonData.commands).length) { + logger?.log('\n\nwhere is one of:\n') + Object.entries(jsonData.commands).forEach(([command, description]) => { + logger?.log(` ${command}${new Array(23 - command.length).join(' ')}${description}`) + }) + } + if (jsonData.description) { + logger?.log(`\nDescription:\n\n ${jsonData.description}`) + } + if (!name) { + logger?.log('\nSee \'adapt help \' for more information on a specific command.\n') + } +} diff --git a/lib/commands/index.js b/lib/commands/index.js deleted file mode 100644 index 5bcd8c3..0000000 --- a/lib/commands/index.js +++ /dev/null @@ -1,16 +0,0 @@ -var _ = require('lodash'), - fs = require('fs'), - commands = {}, - files = fs.readdirSync(__dirname); - -module.exports = files.filter(excludeIndex).reduce(function (commands, filename) { - var useDefaultDependencies = {}, - command = require('./' + filename); - - if(typeof command === 'function') command = command(useDefaultDependencies); - return _.extend(commands, command); -}, {}); - -function excludeIndex (filename) { - return !/^index.js$/.test(filename); -} \ No newline at end of file diff --git a/lib/commands/install.js b/lib/commands/install.js index be4cf96..d7da52a 100644 --- a/lib/commands/install.js +++ b/lib/commands/install.js @@ -1,907 +1,16 @@ -// TODO -// - check promise chains - -var bower = require('bower'); -var chalk = require('chalk'); -var fs = require('fs'); -var inquirer = require('inquirer'); -var _ = require('lodash') -var path = require('path'); -var Q = require('q'); -var semver = require('semver'); -var Errors = require('../errors'); -var Constants = require('../Constants'); -var JsonLoader = require('../JsonLoader'); -var PackageMeta = require('../PackageMeta'); -var Plugin = require('../Plugin'); -var Project = require('../Project'); -var PluginTypeResolver = require('../PluginTypeResolver'); -var RendererHelpers = require('../RendererHelpers'); -var install = require('../promise/install'); -var promise = require('../promise/util'); -var InstallTarget = require('./install/InstallTarget'); -var InstallLog = require('./install/InstallLog'); - -module.exports = function (dependencies) { - - // standard output - var logger; - // a representation of the target Adapt project - var project; - // a list of plugin name/version pairs - var itinerary; - // the plugins to install (`Plugin` instances) - var plugins; - // whether to summarise installation without modifying anything - var isDryRun = false; - // whether to target the latest compatible version for all plugin installations (overrides constraints) - var isCompatibleEnabled = false; - // whether adapt.json is being used to compile the list of plugins to install - var isUsingManifest = false; - // whether this command is being performed on the command line - var isInteractive = true; - - return { - apiinstall: function(pluginName, cwd) { - isInteractive = false; - - Constants.setCwd(cwd); - - project = new Project(Constants.DefaultProjectManifestPath, Constants.DefaultProjectFrameworkPath); - - if(!project.isProjectContainsManifestFile()) { - return Q.reject({error:Errors.ERROR_COURSE_DIR}); - } - - itinerary = {}; - plugins = []; - - return init(pluginName ? [pluginName] : []) - .then(createPlugins) - .then(getInitialInfo) - .then(findCompatibleVersions) - .then(checkConstraints) - .then(createInstallationManifest) - .then(performInstallation) - .then(summariseInstallation); - }, - install: function(renderer) { - var args = [].slice.call(arguments, 1); - var done = args.pop() || function() {}; - - logger = renderer; - - project = new Project(Constants.DefaultProjectManifestPath, Constants.DefaultProjectFrameworkPath); - - if(!project.isProjectContainsManifestFile()) { - RendererHelpers.reportInvalidFrameworkDirectory(renderer, done)(true); - return; - } - - itinerary = {}; - plugins = []; - - var dryRunArgIndex = args.indexOf('--dry-run'); - var compatibleArgIndex = args.indexOf('--compatible'); - - if (dryRunArgIndex >= 0) { - args.splice(dryRunArgIndex, 1); - isDryRun = true; - } - - if (compatibleArgIndex >= 0) { - args.splice(compatibleArgIndex, 1); - isCompatibleEnabled = true; - } - - if (isDryRun) { - init(args) - .then(createPlugins) - .then(getInitialInfo) - .then(findCompatibleVersions) - .then(checkConstraints) - .then(createInstallationManifest) - .then(summariseDryRun) - .then(done) - .fail(function(){console.log('Error:', arguments)}); - } else { - init(args) - .then(createPlugins) - .then(getInitialInfo) - .then(findCompatibleVersions) - .then(checkConstraints) - .then(createInstallationManifest) - .then(performInstallation) - .then(updateManifest) - .then(summariseInstallation) - .then(done) - .fail(function(){console.log('Error:', arguments)}); - } - } - }; - - function init(args) { - if (args.length == 0) { - getItineraryFromManifest(); - } else { - getItineraryFromArguments(args); - } - - return Q.resolve(); - } - - function getItineraryFromManifest() { - isUsingManifest = true; - - itinerary = JsonLoader.readJSONSync(Constants.DefaultProjectManifestPath).dependencies; - } - - function getItineraryFromArguments(args) { - isUsingManifest = false; - - args.forEach(function(arg) { - var tokens = arg.split(/[#@]/); - var name = tokens[0]; - var version = tokens[1]; - - switch (tokens.length) { - case 1: itinerary[name] = '*'; break; - case 2: itinerary[name] = version; break; - default: return; - } - }); - } - - function createPlugins() { - Object.keys(itinerary).forEach(function(name) { - var plugin = new InstallTarget(name, itinerary[name], isCompatibleEnabled); - plugins.push(plugin); - }); - - return Q.resolve(); - } - - function getInitialInfo() { - //console.log('install::getInitialInfo'); - - var promises = []; - - for (var i=0, c=plugins.length; i')+' Getting plugin info '+Math.round(100*settled/total)+'% complete'); - } - - function conclude() { - InstallLog.logProgressConclusion(chalk.bold.cyan('')+' Getting plugin info 100% complete'); - return Q.resolve(); - } - } - - function findCompatibleVersions() { - //console.log('install::findCompatibleVersions'); - - var promises = []; - var present = plugins.filter(isPresent); - - for (var i=0, c=present.length; i')+' Finding compatible versions '+Math.round(100*settled/total)+'% complete'); - } - - function conclude() { - InstallLog.logProgressConclusion(chalk.bold.cyan('')+' Finding compatible versions 100% complete'); - return Q.resolve(); - } - } - - function checkConstraints() { - //console.log('install::checkConstraints'); - - var promises = []; - var present = plugins.filter(isPresent); - - for (var i=0, c=present.length; i')+' Checking constraints '+Math.round(100*settled/total)+'% complete'); - } - - function conclude() { - InstallLog.logProgressConclusion(chalk.bold.cyan('')+' Checking constraints 100% complete'); - return Q.resolve(); - } - } - - function createInstallationManifest() { - //console.log('install::createInstallationManifest'); - - var present = plugins.filter(isPresent); - - var verifiedForInstallation = present.filter(isVerifiedForInstallation); - - verifiedForInstallation.forEach(function(p) {p.markLatestCompatibleForInstallation();}); - - // there is no compatible version, but the user requested a valid version which is not the latest (prompt for (r)equested, (l)atest or (s)kip) - var incompatibleWithOldConstraint = present.filter(isIncompatibleWithOldConstraint); - // there is no compatible version, but the user requested the latest version (prompt for (l)atest or (s)kip) - var incompatibleWithLatestConstraint = present.filter(isIncompatibleWithLatestConstraint); - // there is no compatible version, but the user requested an invalid version (prompt for (l)atest or (s)kip) - var incompatibleWithBadConstraint = present.filter(isIncompatibleWithBadConstraint); - // there is no compatible version and no constraint was given (prompt for (l)atest or (s)kip) - var incompatibleWithNoConstraint = present.filter(isIncompatibleWithNoConstraint); - - // a compatible version exists but the user requested an older version that isn't compatible (prompt for (r)equested, (l)atest compatible or (s)kip) - var compatibleWithOldIncompatibleConstraint = present.filter(isCompatibleWithOldIncompatibleConstraint); - // a compatible version exists but the user requested an older version that is compatible (prompt for (r)equested, (l)atest compatible or (s)kip) - var compatibleWithOldCompatibleConstraint = present.filter(isCompatibleWithOldCompatibleConstraint); - // a compatible version exists but the user requested a newer version that is compatible (prompt for (r)equested, (l)atest compatible or (s)kip) - var compatibleWithNewCompatibleConstraint = present.filter(isCompatibleWithNewCompatibleConstraint); - // a compatible version exists but the user gave a bad constraint (prompt for (c)ompatible or (s)kip) - var compatibleWithBadConstraint = present.filter(isCompatibleWithBadConstraint); - // a compatible version exists but user has requested a valid version that is later than the latest compatible version (prompt for (r)equested, (l)atest compatible or (s)kip) - var compatibleWithUnmetConstraint = present.filter(isCompatibleWithUnmetConstraint); - - if (!isInteractive) { - - incompatibleWithOldConstraint.forEach(function(p) { - p._error = Errors.ERROR_INCOMPATIBLE_VALID_REQUEST; - }); - incompatibleWithLatestConstraint.forEach(function(p) { - p._error = Errors.ERROR_INCOMPATIBLE_VALID_REQUEST; - }); - incompatibleWithBadConstraint.forEach(function(p) { - p._error = Errors.ERROR_INCOMPATIBLE_BAD_REQUEST; - }); - incompatibleWithNoConstraint.forEach(function(p) { - p._error = Errors.ERROR_INCOMPATIBLE; - }); - compatibleWithOldIncompatibleConstraint.forEach(function(p) { - p._error = Errors.ERROR_COMPATIBLE_INC_REQUEST; - }); - compatibleWithBadConstraint.forEach(function(p) { - p._error = Errors.ERROR_COMPATIBLE_BAD_REQUEST; - }); - compatibleWithUnmetConstraint.forEach(function(p) { - p._error = Errors.ERROR_COMPATIBLE_INC_REQUEST; - }); - - compatibleWithOldCompatibleConstraint.forEach(function(p) { - p.markRequestedForInstallation(); - }); - - compatibleWithNewCompatibleConstraint.forEach(function(p) { - p.markRequestedForInstallation(); - }); - - return Q.resolve(); - } - - var allPromises = []; - - add(incompatibleWithOldConstraint, 'There is no compatible version of the following plugins:', getPrompt_incompatibleGeneric); - - add(incompatibleWithLatestConstraint, 'There is no compatible version of the following plugins:', getPrompt_incompatibleGeneric); - - add(incompatibleWithBadConstraint, 'An invalid constraint was given, but there is no compatible version of the following plugins:', getPrompt_incompatibleGeneric); - - add(incompatibleWithNoConstraint, 'There is no compatible version of the following plugins:', getPrompt_incompatibleGeneric); - - add(compatibleWithOldIncompatibleConstraint, 'An older incompatible version has been requested for the following plugins:', getPrompt_compatibleWithOldIncompatibleConstraint); - - add(compatibleWithOldCompatibleConstraint, 'A compatible but older version has been requested for the following plugins:', getPrompt_compatibleWithOldCompatibleConstraint); - - add(compatibleWithNewCompatibleConstraint, 'A compatible but newer version has been requested for the following plugins:', getPrompt_compatibleWithNewCompatibleConstraint); - - add(compatibleWithBadConstraint, 'An invalid constraint was given but a compatible version exists for the following plugins:', getPrompt_compatibleWithBadConstraint); - - add(compatibleWithUnmetConstraint, 'The requested version is incompatible but a compatible version exists for the following plugins:', getPrompt_compatibleWithUnmetConstraint); - - if (allPromises.length == 0) return Q.resolve(); - - return promise.serialise(allPromises, execute); - - function add(list, header, prompt) { - if (list.length > 0) { - allPromises.push({ - header: chalk.cyan(' ') + header, - list: list, - prompt: prompt - }); - } - } - - function execute(obj) { - console.log(obj.header); - return promise.serialise(obj.list, obj.prompt); - } - - function getPackageName(p) { - return p.packageName; - } - } - - function updateManifest() { - if (isUsingManifest) return Q.resolve(); - - return createPromptTask({ - message: chalk.white('Update the manifest (adapt.json)?'), - type: 'confirm', - default: true, - onlyRejectOnError: true - }) - .then(shouldUpdate => { - if (shouldUpdate) { - Object.keys(itinerary).forEach(function(name) { - project.add(new Plugin(name, itinerary[name])); - }); - } - - return Q.resolve(); - }); - } - - function getPrompt_incompatibleWithOldConstraint(p) { - return createPromptTask({ - message: chalk.reset(p.packageName), - choices: [ - { name: 'requested version', value: 'r' }, - { name: 'latest version', value: 'l' }, - { name: 'skip', value: 's' } - ], - type: 'list', - default: 's', - onlyRejectOnError: true - }) - .then(function (result) { - var installRequested = result === 'r'; - var installLatest = result === 'l'; - - if (installRequested) p.markRequestedForInstallation(); - if (installLatest) p.markLatestForInstallation(); - - return Q.resolve(); - }); - } - - function getPrompt_incompatibleGeneric(p) { - return createPromptTask({ - message: chalk.reset(p.packageName), - choices: [ - { name: 'latest version', value: 'l' }, - { name: 'skip', value: 's' } - ], - type: 'list', - default: 's', - onlyRejectOnError: true - }) - .then(function (result) { - var installLatest = result === 'l'; - - if (installLatest) p.markLatestForInstallation(); - - return Q.resolve(); - }); - } - - function getPrompt_compatibleWithOldIncompatibleConstraint(p) { - return createPromptTask({ - message: chalk.white(p.packageName), - choices: [ - { - name: `requested version [${semver.maxSatisfying(p._versions, p.version)}]`, - value: 'r' - }, - { - name: `latest compatible version [${p._latestCompatibleVersion}]`, - value: 'l' - }, - { - name: 'skip', - value: 's' - } - ], - type: 'list', - default: 's', - onlyRejectOnError: true - }) - .then(function (result) { - var installRequested = result === 'r'; - var installLatestCompatible = result === 'l'; - - if (installRequested) p.markRequestedForInstallation(); - if (installLatestCompatible) p.markLatestCompatibleForInstallation(); - - return Q.resolve(); - }); - } - - function getPrompt_compatibleWithOldCompatibleConstraint(p) { - return createPromptTask({ - message: chalk.white(p.packageName), - choices: [ - { - name: `requested version [${p._resolvedConstraint}]`, - value: 'r' - }, - { - name: `latest compatible version [${p._latestCompatibleVersion}]`, - value: 'l' - }, - { - name: 'skip', - value: 's' - } - ], - type: 'list', - default: 's', - onlyRejectOnError: true - }) - .then(function (result) { - var installRequested = result === 'r'; - var installLatestCompatible = result === 'l'; - - if (installRequested) p.markRequestedForInstallation(); - if (installLatestCompatible) p.markLatestCompatibleForInstallation(); - - return Q.resolve(); - }); - } - - function getPrompt_compatibleWithNewCompatibleConstraint(p) { - return createPromptTask({ - message: chalk.white(p.packageName), - choices: [ - { - name: `requested version [${p._resolvedConstraint}]`, - value: 'r' - }, - { - name: `latest compatible version [${p._latestCompatibleVersion}]`, - value: 'l' - }, - { - name: 'skip', - value: 's' - } - ], - type: 'list', - default: 's', - onlyRejectOnError: true - }) - .then(function (result) { - var installRequested = result === 'r'; - var installLatestCompatible = result === 'l'; - - if (installRequested) p.markRequestedForInstallation(); - if (installLatestCompatible) p.markLatestCompatibleForInstallation(); - - return Q.resolve(); - }); - } - - function getPrompt_compatibleWithBadConstraint(p) { - return createPromptTask({ - message: chalk.white(p.packageName), - type: 'list', - choices: [ - { - name: `compatible version [${p._latestCompatibleVersion}]`, - value: 'c' - }, - { - name: 'skip', - value: 's' - } - ], - default: 's', - onlyRejectOnError: true - }) - .then(function (result) { - var installLatestCompatible = result === 'c'; - - if (installLatestCompatible) p.markLatestCompatibleForInstallation(); - - return Q.resolve(); - }); - } - - function getPrompt_compatibleWithUnmetConstraint(p) { - return createPromptTask({ - message: chalk.white(p.packageName), - choices: [ - { - name: `requested version [${semver.maxSatisfying(p._versions, p.version)}]`, - value: 'r' - }, - { - name: `latest compatible version [${p._latestCompatibleVersion}]`, - value: 'l' - }, - { - name: 'skip', - value: 's' - } - ], - type: 'list', - default: 's', - onlyRejectOnError: true - }) - .then(function (result) { - var installRequested = result === 'r'; - var installLatestCompatible = result === 'l'; - - if (installRequested) p.markRequestedForInstallation(); - if (installLatestCompatible) p.markLatestCompatibleForInstallation(); - - return Q.resolve(); - }); - } - - function summariseDryRun() { - var toBeInstalled = plugins.filter(isToBeInstalled); - var toBeSkipped = plugins.filter(isSkipped); - var missing = plugins.filter(isMissing); - - summarise(toBeInstalled, toBeInstalledPrinter, 'The following plugins will be installed:'); - summarise(toBeSkipped, packageNamePrinter, 'The following plugins will be skipped:'); - summarise(missing, packageNamePrinter, 'There was a problem locating the following plugins:'); - - function summarise(list, iterator, header) { - if (!list || !iterator || list.length == 0) return; - - console.log(chalk.cyanBright(header)); - list.forEach(iterator); - } - - return Q.resolve(); - } - - function summariseInstallation() { - //console.log('install::summariseInstallation'); - - var installSucceeded = plugins.filter(isInstallSuccessful); - var installSkipped = plugins.filter(isSkipped); - var installErrored = plugins.filter(isInstallFailure); - var missing = plugins.filter(isMissing); - - var allSuccess = 'All requested plugins were successfully installed. Summary of installation:'; - var someSuccess = 'The following plugins were successfully installed:'; - var noSuccess = 'None of the requested plugins could be installed'; - var successMsg; - - if (!isInteractive) { - var report = []; - - if (plugins.length == 1) { - var p = plugins[0]; - - if (installSucceeded.length == 1) { - var bowerPath = path.join(Constants.cwd, 'src', p._belongsTo, p.packageName, 'bower.json'); - return Q.resolve(JsonLoader.readJSONSync(bowerPath)); - } - if (installSkipped.length == 1) { - return Q.reject(p._error); - } - if (installErrored.length == 1) { - var error = _.clone(Errors.ERROR_INSTALL_ERROR); - - if (p._installError) error.message = p._installError; - - return Q.reject(error); - } - return Q.reject(Errors.ERROR_NOT_FOUND); - } - - installSucceeded.forEach(function(p) { - var bowerPath = path.join(Constants.cwd, 'src', p._belongsTo, p.packageName, 'bower.json'); - report.push({ - name:p.packageName, - status:'fulfilled', - pluginData:JsonLoader.readJSONSync(bowerPath) - }); - }); - - installSkipped.forEach(function(p) { - report.push({ - name:p.packageName, - status:'rejected', - reason:p._error - }); - }); - - installErrored.forEach(function(p) { - var error = _.clone(Errors.ERROR_INSTALL_ERROR); - - if (p._installError) error.message = p._installError; - - report.push({ - name:p.packageName, - status:'rejected', - reason:error - }); - }); - - missing.forEach(function(p) { - report.push({ - name:p.packageName, - status:'rejected', - reason:Errors.ERROR_NOT_FOUND - }); - }); - - return Q.resolve(report); - } - - if (installErrored.length == 0 && missing.length == 0) successMsg = allSuccess; - else if (installSucceeded.length == 0) successMsg = noSuccess; - else successMsg = someSuccess; - - summarise(installSucceeded, installSucceededPrinter, successMsg); - summarise(installSkipped, packageNamePrinter, 'The following plugins were skipped:'); - summarise(installErrored, installErroredPrinter, 'The following plugins could not be installed:'); - summarise(missing, packageNamePrinter, 'There was a problem locating the following plugins:'); - - function summarise(list, iterator, header) { - if (!list || !iterator || list.length == 0) return; - - console.log(chalk.cyanBright(header)); - list.forEach(iterator); - } - - return Q.resolve(); - } - - function isToBeInstalled(p) { - return p._versionToInstall != undefined; - } - - function isInstallSuccessful(p) { - return p._versionToInstall != undefined && p._wasInstalled === true; - } - - function isInstallFailure(p) { - return p._versionToInstall != undefined && p._wasInstalled === false; - } - - function isSkipped(p) { - return !p._isMissingAtRepo && p._versionToInstall == undefined; - } - - // output formatting - - function highlight(str) { - var sub1 = 'adapt-contrib-'; - var sub2 = 'adapt-'; - - if (str.indexOf(sub1) == 0) { - return chalk.reset(sub1)+chalk.yellowBright(str.substring(sub1.length)); - } - - if (str.indexOf(sub2) == 0) { - return chalk.reset(sub2)+chalk.yellowBright(str.substring(sub2.length)); - } - - return str; - } - - function green(str) { - return chalk.greenBright(str); - } - - function greenIfEqual(v1, v2) { - var colourFunc = semver.satisfies(v1, v2) ? chalk.greenBright : chalk.magentaBright; - - return colourFunc(v2); - } - - function toBeInstalledPrinter(p) { - var v_i = p._versionToInstall, v_lc = p._latestCompatibleVersion; - - if (v_lc == '*') { - console.log(highlight(p.packageName), '(no version information)'); - } else { - console.log(highlight(p.packageName), '@'+green(v_i), '(latest compatible version is '+greenIfEqual(v_i, v_lc)+')'); - } - } - - function installSucceededPrinter(p) { - var v_i = p._versionToInstall, v_lc = p._latestCompatibleVersion; - - if (v_lc == '*') { - console.log(highlight(p.packageName), '(no version information)'); - } else { - console.log(highlight(p.packageName), '@'+green(v_i), '(latest compatible version is '+greenIfEqual(v_i, v_lc)+')'); - } - } - - function installErroredPrinter(p) { - console.log(highlight(p.packageName), p._installError ? '(error: ' + p._installError + ')' : '(unknown error)'); - } - - function packageNamePrinter(p) { - console.log(highlight(p.packageName)); - } - - // composite filter for when no user input is required to determine which version to install - - function isVerifiedForInstallation(p) { - return isCompatible(p) && (!isConstrained(p) || semver.satisfies(p._resolvedConstraint, p._latestCompatibleVersion)); - } - - // composite filters for when no compatible version exists - - function isIncompatibleWithOldConstraint(p) { - return !isCompatible(p) && isConstrained(p) && isGoodConstraint(p) && semver.lt(semver.maxSatisfying(p._versions, p.version), p._latestVersion); - } - - function isIncompatibleWithLatestConstraint(p) { - return !isCompatible(p) && isConstrained(p) && isGoodConstraint(p) && semver.satisfies(semver.maxSatisfying(p._versions, p.version), p._latestVersion); - } - - function isIncompatibleWithBadConstraint(p) { - return !isCompatible(p) && isConstrained(p) && isBadConstraint(p); - } - - function isIncompatibleWithNoConstraint(p) { - return !isCompatible(p) && !isConstrained(p); - } - - // composite filters for when a compatible version exists - - function isCompatibleWithOldCompatibleConstraint(p) { - return isCompatible(p) && isConstraintCompatible(p) && semver.lt(p._resolvedConstraint, p._latestCompatibleVersion); - } - - function isCompatibleWithBadConstraint(p) { - return isCompatible(p) && isBadConstraint(p); - } - - function isCompatibleWithOldIncompatibleConstraint(p) { - // when the following elements of the filter are true they imply: - // - // isCompatible(p) - there exists a compatible version - // isConstrained(p) - a constraint was given (i.e. not a wildcard '*') - // isGoodConstraint(p) - the constraint resolved to a version of the plugin - // !isConstraintCompatible(p) - the constraint did not resolve to a compatible version - // - // the last element determines if the constraint only specified version(s) less than the latest compatible version - return isCompatible(p) && isConstrained(p) && isGoodConstraint(p) && !isConstraintCompatible(p) && semver.lt(semver.maxSatisfying(p._versions, p.version), p._latestCompatibleVersion); - } - - function isCompatibleWithUnmetConstraint(p) { - // when the following elements of the filter are true they imply: - // - // isCompatible(p) - there exists a compatible version - // isConstrained(p) - a constraint was given (i.e. not a wildcard '*') - // isGoodConstraint(p) - the constraint resolved to a version of the plugin - // !isConstraintCompatible(p) - the constraint did not resolve to a compatible version - // - // the last element determines if the constraint specified version(s) greater than the latest compatible version - return isCompatible(p) && isConstrained(p) && isGoodConstraint(p) && !isConstraintCompatible(p) && semver.gt(semver.maxSatisfying(p._versions, p.version), p._latestCompatibleVersion); - } - - function isCompatibleWithNewCompatibleConstraint(p) { - return isCompatible(p) && isConstrained(p) && isGoodConstraint(p) && isConstraintCompatible(p) && semver.gt(semver.maxSatisfying(p._versions, p.version), p._latestCompatibleVersion); - } - - // simple filters - - function isConstraintCompatible(p) { - return p._resolvedConstraint != undefined && p._resolvedConstraint != null; - } - - function isCompatible(p) { - return p._latestCompatibleVersion != undefined && p._latestCompatibleVersion != null; - } - - function isConstrained(plugin) { - return plugin.version != '*'; - } - - function isGoodConstraint(plugin) { - return plugin._isBadConstraint === false; - } - - function isBadConstraint(plugin) { - return plugin._isBadConstraint === true; - } - - function isMissing(plugin) { - return plugin._isMissingAtRepo === true; - } - - function isPresent(plugin) { - return !isMissing(plugin); - } - - function createPromptTask(params) { - var deferred = Q.defer(); - var defaultConfig = { - name: 'question', - onlyRejectOnError: false - }; - var config = _.extend({}, defaultConfig, params); - var schema = [ config ]; - inquirer.prompt(schema).then(confirmation => { - if (!config.onlyRejectOnError && !confirmation.question) deferred.reject(new Error('Aborted. Nothing has been updated.')); - deferred.resolve(confirmation.question); - }).catch(err => deferred.reject(err)); - return deferred.promise; - } - - function performInstallation() { - if (isInteractive) { - return Q.all(plugins.filter(isToBeInstalled).map(createInstallationTask)).progress(progressUpdate).then(conclude); - } - - return Q.all(plugins.filter(isToBeInstalled).map(createInstallationTask)); - - function progressUpdate() { - var list = plugins.filter(isPresent).filter(isToBeInstalled); - var settled = list.filter(function(p) {return isInstallSuccessful(p) || isInstallFailure(p);}).length; - var total = list.length; - InstallLog.logProgress(chalk.bold.cyan('')+' Installing plugins '+Math.round(100*settled/total)+'% complete'); - } - - function conclude() { - InstallLog.logProgressConclusion(chalk.bold.cyan('')+' Installing plugins 100% complete'); - return Q.resolve(); - } - } - - function createInstallationTask(plugin) { - return PackageMeta.getKeywords(plugin, { registry: Constants.getRegistry(), cwd: Constants.cwd }).then(doInstall).then(conclude); - - function doInstall(keywords) { - var resolver = new PluginTypeResolver(), - pluginType = resolver.resolve(keywords); - - // this lookup should probably be moved InstallTarget - plugin._belongsTo = pluginType.belongsTo; - - return install(plugin, { - directory: path.join('src', pluginType.belongsTo), - registry: Constants.getRegistry(), - cwd: Constants.cwd - }); - } - - function conclude(result) { - plugin._wasInstalled = result._wasInstalled === true; - if (result.error) plugin._installError = result.error.code; - //renderUpdateProgress(); - } - } -}; +import { install as pluginsInstall } from '../integration/PluginManagement.js' + +export default async function install (logger, ...args) { + /** strip flags */ + const isClean = args.includes('--clean') + const isDryRun = args.includes('--dry-run') || args.includes('--check') + const isCompatibleEnabled = args.includes('--compatible') + const plugins = args.filter(arg => !String(arg).startsWith('--')) + await pluginsInstall({ + logger, + isClean, + isDryRun, + isCompatibleEnabled, + plugins + }) +} diff --git a/lib/commands/install/InstallLog.js b/lib/commands/install/InstallLog.js deleted file mode 100644 index c40c888..0000000 --- a/lib/commands/install/InstallLog.js +++ /dev/null @@ -1,32 +0,0 @@ -var readline = require('readline'); - -var isLoggingProgress = false; -var lastProgressStr = ''; - -module.exports = { - logProgress:function(str) { - lastProgressStr = str; - isLoggingProgress = true; - readline.cursorTo(process.stdout, 0); - process.stdout.write(str); - }, - - logProgressConclusion(str) { - lastProgressStr = str; - isLoggingProgress = false; - readline.cursorTo(process.stdout, 0); - process.stdout.write(str); - process.stdout.write('\n'); - }, - - log:function() { - if (isLoggingProgress) { - readline.clearLine(process.stdout, 0); - readline.cursorTo(process.stdout, 0); - console.log.apply(console, arguments); - this.logProgress(lastProgressStr); - } else { - console.log.apply(console, arguments); - } - } -} \ No newline at end of file diff --git a/lib/commands/install/InstallTarget.js b/lib/commands/install/InstallTarget.js deleted file mode 100644 index 3c7541e..0000000 --- a/lib/commands/install/InstallTarget.js +++ /dev/null @@ -1,259 +0,0 @@ -var bower = require('bower'), - _ = require('lodash'), - Q = require('q'), - readline = require('readline'), - endpointParser = require('bower-endpoint-parser'), - semver = require('semver'), - Plugin = require('../../Plugin'), - InstallLog = require('./InstallLog'), - Constants = require('../../Constants'), - extend = require('./extend'); - -var any = '*'; -var BOWER_MAX_TRY = 5; - -var InstallTarget = extend(Plugin, { - - constructor: function(name, requestedVersion, isCompatibleEnabled) { - var endpoint = name+'#'+(isCompatibleEnabled ? any : requestedVersion), - ep = endpointParser.decompose(endpoint), - version = /^\*$/.test(ep.target) ? any : ep.target, - proposal; - - Plugin.call(this, ep.name || ep.source, version); - - if (this.version !== any) { - proposal = this.version; - this._isConstrained = true; - this.version = semver.validRange(proposal); - - if (!this.version) { - throw new Error(this.packageName+' "'+proposal+'" is not a valid constraint'); - } - } - - // the constraint given by the user - this._requestedVersion = requestedVersion; - // the result of the current query to the server - this._rawInfo = undefined; - // information about a particular version of the plugin - this._versionInfo = undefined; - // the number of attempts made to query the server - this._bowerCmdCount = 0; - // a list of tags denoting the versions of the plugin - this._versions = undefined; - // an index denoting which version is being queried - this._versionIndex = 0; - // whether querying the server for plugin information failed at all - this._isMissingAtRepo = false; - // the most recent version of the plugin compatible with the given framework - this._latestCompatibleVersion = undefined; - // the most recent version of the plugin - this._latestVersion = undefined; - // whether the user supplied a constraint that is not supported by the plugin - this._isBadConstraint = false; - // whether the constraint has been checked for compatibility - this._constraintChecked = false; - // a non-wildcard constraint resolved to the highest version of the plugin that satisfies the constraint and is compatible with the framework - this._resolvedConstraint = undefined; - // the version to be installed - this._versionToInstall = undefined; - }, - - getInitialInfo: function() { - return this.getInfo().then(_.bind(processInfo, this)); - - function processInfo() { - if (!this._isMissingAtRepo) { - this._latestVersion = this._versionInfo.version; - - if (this._rawInfo.versions) { - this._versions = this._rawInfo.versions; - if (this._versions.length > 0) { - // check if the user supplied a constraint that cannot be met - this._isBadConstraint = semver.maxSatisfying(this._versions, this.version) === null; - } - } - } - } - }, - - getInfo: function(deferred) { - // presence of deferred signifies a retry - if (!deferred) this._bowerCmdCount = 0; - - deferred = deferred || Q.defer(); - - try { - var versionString = this._versions ? '#'+this._versions[this._versionIndex] : ''; - this._bowerCmdCount++; - bower.commands.info(this.packageName+versionString, null, {registry:Constants.getRegistry(), cwd: Constants.cwd}).on('end', _.bind(onSuccess, this)).on('error', _.bind(onFail, this)); - } catch(err) { - onFail.call(this, err); - } - - function onSuccess(results) { - this._rawInfo = results; - this._versionInfo = results.latest || results; - deferred.notify(); - deferred.resolve(results); - } - - function onFail() { - if (this._bowerCmdCount < BOWER_MAX_TRY) { - this.getInfo(deferred); - } else { - this._isMissingAtRepo = true; - deferred.notify(); - deferred.resolve(); - } - } - - return deferred.promise; - }, - - findCompatibleVersion: function(framework) { - if (this._isMissingAtRepo) return Q.resolve(); - - // check if the latest version is compatible - if (semver.satisfies(framework, this._versionInfo.framework)) { - this._latestCompatibleVersion = this._versionInfo.version || '*'; - return Q.resolve(); - } - - // if the plugin has no tags then there are no other versions to check - if (!this._versions || this._versions.length == 0) return Q.resolve(); - - this._versionIndex = 0; - - return this.checkProposedVersion(framework); - }, - - checkConstraint: function(framework) { - // check that the plugin exists - if (this._isMissingAtRepo) { - this._constraintChecked = true; - //InstallLog.log(this.packageName, 'cannot resolve constraint due to missing info'); - return Q.resolve(); - } - - // check that there are other versions to be considered - if (!this._versions || this._versions.length == 0) { - this._constraintChecked = true; - //InstallLog.log(this.packageName, 'cannot resolve constraint because there are no tags'); - return Q.resolve(); - } - - // check that a valid constraint exists - if (this.version == any || this._isBadConstraint) { - this._constraintChecked = true; - //InstallLog.log(this.packageName, 'cannot resolve constraint because a valid constraint has not been given'); - return Q.resolve(); - } - - this._versionIndex = 0; - - return this.getInfo().then(_.bind(function() { - return this.checkConstraintCompatibility(framework); - }, this)); - }, - - // find the highest version that satisfies the constraint and is compatible with the framework - checkConstraintCompatibility: function(framework, deferred) { - deferred = deferred || Q.defer(); - - // give up if there is any failure to obtain version info - if (this._isMissingAtRepo) { - this._constraintChecked = true; - //InstallLog.log(this.packageName, 'cannot resolve constraint due to missing info'); - deferred.notify(); - deferred.resolve(); - return deferred.promise; - } - - //InstallLog.log(this.packageName, 'checking', this._versionInfo.version, 'against', this.version, 'framework', framework); - - // check if the version satisfies the constraint and whether the version is compatible - if (semver.satisfies(this._versionInfo.version, this.version) && semver.satisfies(framework, this._versionInfo.framework)) { - this._resolvedConstraint = this._versionInfo.version; - this._constraintChecked = true; - //InstallLog.log(this.packageName, 'resolved constraint to', this._resolvedConstraint); - deferred.notify(); - deferred.resolve(); - } else { - if (this._versionIndex + 1 < this._versions.length) { - this._versionIndex++; - - this.getInfo().then(_.bind(function() { - return this.checkConstraintCompatibility(framework, deferred); - }, this)); - - } else { - this._resolvedConstraint = null; - this._constraintChecked = true; - //InstallLog.log(this.packageName, 'cannot resolve constraint'); - deferred.notify(); - deferred.resolve(); - } - } - - return deferred.promise; - }, - - // find the highest version that is compatible with the framework - checkProposedVersion: function(framework, deferred) { - deferred = deferred || Q.defer(); - - // give up if there is any failure to obtain version info - if (this._isMissingAtRepo) { - this._latestCompatibleVersion = null; - deferred.notify(); - deferred.resolve(); - return deferred.promise; - } - - // check that the proposed plugin is compatible with the installed framework - if (semver.satisfies(framework, this._versionInfo.framework)) { - this._latestCompatibleVersion = this._versionInfo.version; - deferred.notify(); - deferred.resolve(); - } else { - if (this._versionIndex + 1 < this._versions.length) { - this._versionIndex++; - - this.getInfo().then(_.bind(function() { - this.checkProposedVersion(framework, deferred); - }, this)); - - } else { - this._latestCompatibleVersion = null; - deferred.notify(); - deferred.resolve(); - } - } - - return deferred.promise; - }, - - markRequestedForInstallation:function() { - if (this._resolvedConstraint != undefined && this._resolvedConstraint != null) { - this._versionToInstall = this._resolvedConstraint; - } else { - this._versionToInstall = semver.maxSatisfying(this._versions, this.version); - } - }, - - markLatestCompatibleForInstallation:function() { - this._versionToInstall = this._latestCompatibleVersion; - }, - - markLatestForInstallation:function() { - this._versionToInstall = this._latestVersion; - }, - - logToConsole:function() { - console.log(this.packageName, this.version, this._versionInfo ? this._versionInfo.framework : 'missing'); - } -}); - -module.exports = InstallTarget; diff --git a/lib/commands/install/extend.js b/lib/commands/install/extend.js deleted file mode 100644 index a26cd5c..0000000 --- a/lib/commands/install/extend.js +++ /dev/null @@ -1,31 +0,0 @@ -// the Backbone extend function - -var _ = require('lodash'); - -module.exports = function(superClass, protoProps, staticProps) { - var parent = superClass; - var child; - - // The constructor function for the new subclass is either defined by you - // (the "constructor" property in your `extend` definition), or defaulted - // by us to simply call the parent constructor. - if (protoProps && _.has(protoProps, 'constructor')) { - child = protoProps.constructor; - } else { - child = function(){ return parent.apply(this, arguments); }; - } - - // Add static properties to the constructor function, if supplied. - _.extend(child, parent, staticProps); - - // Set the prototype chain to inherit from `parent`, without calling - // `parent`'s constructor function and add the prototype properties. - child.prototype = _.create(parent.prototype, protoProps); - child.prototype.constructor = child; - - // Set a convenience property in case the parent's prototype is needed - // later. - child.__super__ = parent.prototype; - - return child; -}; \ No newline at end of file diff --git a/lib/commands/ls.js b/lib/commands/ls.js index 8ae1f6b..9f6b544 100644 --- a/lib/commands/ls.js +++ b/lib/commands/ls.js @@ -1,24 +1,9 @@ -module.exports = function (dependencies) { - - var chalk = dependencies.chalk || require('chalk'), - Project = dependencies.Project || require('../Project'), - Constants = dependencies.Constants || require('../Constants'), - RendererHelpers = dependencies.RendererHelpers || require('../RendererHelpers'); - - return { - ls: function(renderer) { - var project = new Project(Constants.DefaultProjectManifestPath), - done = arguments[arguments.length -1]; - - if(project.isProjectContainsManifestFile()) { - project.plugins.forEach(function (p) { - renderer.log(chalk.cyan(p.name), p.version); - }); - done(); - } else { - RendererHelpers.reportInvalidFrameworkDirectory(renderer, done)(true); - } - } - }; - -}; +import chalk from 'chalk' +import Project from '../integration/Project.js' + +export default async function ls (logger) { + const project = new Project({ logger }) + project.tryThrowInvalidPath() + const installTargets = await project.getInstallTargets() + installTargets.forEach(p => logger?.log(`${chalk.cyan(p.name || p.sourcePath)} ${p.sourcePath || p.requestedVersion}`)) +} diff --git a/lib/commands/register.js b/lib/commands/register.js index 824ea32..4a544ac 100644 --- a/lib/commands/register.js +++ b/lib/commands/register.js @@ -1,196 +1,11 @@ -var bower = require('bower'), - chalk = require('chalk'), - inquirer = require('inquirer'), - path = require('path'), - _ = require('lodash'), - Q = require('q'), - Constants = require('../Constants'), - JsonLoader = require('../JsonLoader'), - JsonWriter = require('../JsonWriter'), - Project = require('../Project'), - Plugin = require('../Plugin'), - semver = require('semver'); - -module.exports = { - register: function (renderer) { - var done = arguments[arguments.length-1] || function () {}; - - //renderer.log(chalk.yellow('This will publish this plugin to', Constants.Registry)); - - loadPluginProperties('./bower.json', { - name: undefined, - repository: undefined, - framework: undefined - }) - .then(confirm) - .then(function (properties) { - savePluginProperties('./bower.json', properties); - return properties; - }) - .then(function (properties) { - // given a package name, create two Plugin representations - // if supplied name is adapt-contrib-myPackageName do a check against this name only - // if suppled name is adapt-myPackageName check against this name and adapt-contrib-myPackageName - // becase we don't want to allow adapt-myPackageName if adapt-contrib-myPackageName exists - var plugin = new Plugin(properties.name), - contribPlugin = new Plugin(properties.name, true), - searches = [exists(contribPlugin)]; - - if(!plugin.isContrib) { - searches.push(exists(plugin)); - } - - return Q.all(searches) - .spread(function (contribExists, pluginExists) { - if(contribExists) { - return reportExistence(contribPlugin, renderer); - } - if(pluginExists) { - return reportExistence(plugin, renderer); - } - return register(plugin, properties.repository); - }); - }) - .then(function (registered) { - if(!registered.result) throw new Error('The plugin was unable to register.'); - renderer.log(chalk.green(registered.plugin.packageName), 'has been registered successfully.'); - done(); - }) - .fail(function (err) { - renderer.log(chalk.red(err)); - done(err); - }) - .done(); - } -}; - -function loadPluginProperties(path, defaults) { - var deferred = Q.defer(); - - path = path || './bower.json'; - - if(!JsonLoader.existsSync(path)) { - deferred.reject(new Error('bower.json is not in the current working directory. Plugins must be a valid bower package.')); - } - JsonLoader.readJSON(path, function (error, data) { - if(error) { - deferred.reject(new Error(error)); - } else { - deferred.resolve(_.extend({}, defaults, data)); - } - }); - - return deferred.promise; -} - -function savePluginProperties(path, values) { - var deferred = Q.defer(); - - path = path || './bower.json'; - - if(!JsonWriter.existsSync(path)) { - deferred.reject(new Error('bower.json is not in the current working directory. Plugins must be a valid bower package.')); - } - JsonWriter.writeJSON(path, values, function () { - deferred.resolve(true); - }); - - return deferred.promise; -} - -function confirm(properties) { - var deferred = Q.defer(); - var plugin = new Plugin(properties.name), - schema = [ - { - name: 'name', - message: chalk.cyan('name'), - validate: v => { - return /^adapt-[\w|-]+?$/.test(v) || - `Name must prefixed with 'adapt' and each word separated with a hyphen(-)`; - }, - type: 'input', - default: plugin.toString() || 'not specified' - }, - { - name: 'repositoryUrl', - message: chalk.cyan('repository URL'), - validate: v => { - return /git:\/\/([\w\.@\:/\-~]+)(\.git)(\/)?/.test(v) || - 'Please provide a repository URL of the form git://.git'; - }, - type: 'input', - default: properties.repository ? properties.repository.url : undefined - }, - { - name: 'framework', - message: chalk.cyan('framework'), - validate: v => { - return semver.validRange(v) !== null || - 'Please provide a valid semver (see https://semver.org/)'; - }, - type: 'input', - default: properties.framework || '~2.0.0' - }, - { - name: 'ready', - message: chalk.cyan('Register now?'), - type: 'confirm', - default: true - } - ]; - inquirer.prompt(schema).then(confirmation => { - if(!confirmation.ready) deferred.reject(new Error('Aborted. Nothing has been registered.')); - - properties.name = confirmation.name; - properties.repository = {type:'git', url:confirmation.repositoryUrl}; - properties.framework = confirmation.framework; - - deferred.resolve(properties); - }).catch(err => deferred.reject(err)); - return deferred.promise; -} - -function register(plugin, repository) { - var deferred = Q.defer(); - - bower.commands.register(plugin.toString(), repository.url || repository, { registry: Constants.getRegistry() }) - .on('end', function(result) { - deferred.resolve({ result: result, plugin: plugin }); - }) - .on('error', function (err) { - deferred.reject(err); - }); - return deferred.promise; -} - -function exists(plugin) { - var deferred = Q.defer(); - - bower.commands.search(plugin.toString(), { registry: Constants.getRegistry() }) - .on('end', function(result) { - var matches = result.filter(exactMatch(plugin.toString())); - deferred.resolve(!!matches.length); - }) - .on('error', function (err) { - deferred.reject(err); - }); - return deferred.promise; -} - -function exactMatch(pattern) { - return function (item) { - if (typeof pattern === 'string') { - if (pattern.toLowerCase() === item.name.toLowerCase()) { - return true; - } - return false - } - var regexp = new RegExp(pattern, 'i'); - return regexp.test(item.name); - }; -} - -function reportExistence(plugin, renderer) { - renderer.log(chalk.yellow(plugin.toString()), chalk.cyan('has been previously registered. Plugin names must be unique. Try again with a different name.')); +import { register as pluginRegister } from '../integration/PluginManagement.js' + +export default async function register (logger, ...args) { + // strip flags + args = args.filter(arg => !String(arg).startsWith('--')) + return await pluginRegister({ + logger, + cwd: process.cwd(), + args + }) } diff --git a/lib/commands/rename.js b/lib/commands/rename.js index ffc3eb6..8f1a242 100644 --- a/lib/commands/rename.js +++ b/lib/commands/rename.js @@ -1,129 +1,14 @@ -var bower = require('bower'), - chalk = require('chalk'), - inquirer = require('inquirer'), - _ = require('lodash'), - Q = require('q'), - request = require('request'), - Constants = require('../Constants'), - Plugin = require('../Plugin'), - authenticate = require('../promise/authenticate'), - log; - -module.exports = { - rename: function (renderer) { - log = renderer.log; - - var done = arguments[arguments.length-1] || function () {}; - - if (arguments.length >= 4) { - var params = { - oldName:arguments[1], - newName:arguments[2] - }; - - // use Plugin to standardise name - params.newName = new Plugin(params.newName).packageName; - - log(chalk.yellow('Using registry at', Constants.getRegistry())); - log(chalk.yellow('Plugin will be renamed to', params.newName)); - - Q(params) - .then(checkPluginNameExists) - .then(checkNewPluginNameDoesNotExist) - .then(authenticate) - .then(confirm) - .then(rename) - .then(function() { - log(chalk.green('The plugin was successfully renamed.')); - done(); - }) - .catch(function (err) { - log(chalk.red(err)); - log('The plugin was not renamed.'); - done(err); - }) - .done(); - - } else { - log(chalk.red('You must call rename with the following arguments: ')); - done(); - } - } -}; - -function checkPluginNameExists(params) { - return exists(params.oldName).then(function(exists) { - return exists ? Q.resolve(params) : Q.reject('Plugin "'+params.oldName+'" does not exist'); - }); -} - -function checkNewPluginNameDoesNotExist(params) { - return exists(params.newName).then(function(exists) { - return exists ? Q.reject('Name "'+params.newName+'" already exists') : Q.resolve(params); - }); -} - -function confirm(params) { - var deferred = Q.defer(); - var schema = [ - { - name: 'ready', - message: chalk.cyan('Confirm rename now?'), - type: 'confirm', - default: true - } - ]; - inquirer.prompt(schema).then(confirmation => { - if(!confirmation.ready) deferred.reject(new Error('Aborted. Nothing has been renamed.')); - deferred.resolve(params); - }).catch(err => deferred.reject(err)); - return deferred.promise; -} - -function rename(params) { - var deferred = Q.defer(); - var path = 'packages/rename/'+params.username+'/'+params.oldName+'/'+params.newName; - var query = '?access_token='+params.token; - - request({ - url: Constants.getRegistry()+'/'+path+query, - method:'GET', - headers: {'User-Agent':'adapt-cli'}, - followRedirect:false - }, function(err, res, body) { - if (err) { - deferred.reject(err); - } else { - res.statusCode==201 ? deferred.resolve(params) : deferred.reject("The server responded with "+res.statusCode); - } - }); - - return deferred.promise; -} - -function exists(plugin) { - var deferred = Q.defer(); - - bower.commands.search(plugin.toString(), { registry: Constants.getRegistry() }) - .on('end', function(result) { - var matches = result.filter(exactMatch(plugin.toString())); - deferred.resolve(!!matches.length); - }) - .on('error', function (err) { - deferred.reject(err); - }); - return deferred.promise; -} - -function exactMatch(pattern) { - return function (item) { - if (typeof pattern === 'string') { - if (pattern.toLowerCase() === item.name.toLowerCase()) { - return true; - } - return false - } - var regexp = new RegExp(pattern, 'i'); - return regexp.test(item.name); - }; +import { rename as pluginRename } from '../integration/PluginManagement.js' + +export default async function rename (logger, ...args) { + /** strip flags */ + args = args.filter(arg => !String(arg).startsWith('--')) + const oldName = args[0] + const newName = args[1] + await pluginRename({ + logger, + cwd: process.cwd(), + oldName, + newName + }) } diff --git a/lib/commands/search.js b/lib/commands/search.js index 0d5dc3b..c92c50a 100644 --- a/lib/commands/search.js +++ b/lib/commands/search.js @@ -1,29 +1,11 @@ -var bower = require('bower'), - chalk = require('chalk'), - Constants = require('../Constants'), - Plugin = require('../Plugin'); +import { search as pluginsSearch } from '../integration/PluginManagement.js' - -module.exports = { - search: function(renderer) { - var searchTerm = arguments.length >= 3 ? arguments[1] : '', - done = arguments[arguments.length -1] || function () {}; - - var plugin = new Plugin(searchTerm); - - bower.commands.search(searchTerm, { registry: Constants.getRegistry() }) - .on('end', function(results) { - if(!results.length) { - renderer.log(chalk.yellow('no plugins found', plugin.toString())); - } - results.forEach(function (result) { - renderer.log(chalk.cyan(result.name) + ' ' + result.url); - }); - done(); - }) - .on('error', function (err) { - renderer.log(chalk.red("Oh dear, something went wrong. I'm terribly sorry."), err); - done(err); - }); - } -}; +export default async function search (logger, ...args) { + /** strip flags */ + args = args.filter(arg => !String(arg).startsWith('--')) + const searchTerm = (args[0] || '') + await pluginsSearch({ + logger, + searchTerm + }) +} diff --git a/lib/commands/uninstall.js b/lib/commands/uninstall.js index 899c588..1e73c82 100644 --- a/lib/commands/uninstall.js +++ b/lib/commands/uninstall.js @@ -1,136 +1,9 @@ -var chalk = require('chalk'), - fs = require('fs'), - path = require('path'), - rimraf = require('rimraf'), - Q = require('q'), - Constants = require('../Constants'), - PluginTypeResolver = require('../PluginTypeResolver'), - PackageMeta = require('../PackageMeta'), - Project = require('../Project'), - Plugin = require('../Plugin'), - RendererHelpers = require('../RendererHelpers'), - uninstallPackage = require('../promise/uninstallPackage'), - Errors = require('../errors'); - -module.exports = { - apiuninstall:function(pluginName, cwd) { - Constants.setCwd(cwd); - - var project = new Project(Constants.DefaultProjectManifestPath, Constants.DefaultProjectFrameworkPath); - - if(!project.isProjectContainsManifestFile()) { - return Q.reject(Errors.ERROR_COURSE_DIR); - } - - var plugin = Plugin.parse(pluginName); - var deferred = Q.defer(); - - PackageMeta.getKeywords(plugin, { registry: Constants.getRegistry() }) - .then(function (keywords) { - var resolver = new PluginTypeResolver(), - pluginType = resolver.resolve(keywords); - - return uninstallPackage(plugin, { - directory: path.join('src', pluginType.belongsTo), - cwd:Constants.cwd - }); - }) - .then(function () { - project.remove(plugin); - }) - .then(function () { - deferred.resolve(pluginName); - }) - .fail(function() { - // will fail if plugin has not been installed by Bower (i.e. the .bower.json manifest is missing) - // so just try and remove the directory (this is basically what Bower does anyway) - - var removePath; - - ['components', 'extensions', 'menu', 'theme'].forEach(function(pluginType) { - var pluginPath = path.join(Constants.cwd, 'src', pluginType, plugin.packageName); - - if (fs.existsSync(pluginPath)) { - removePath = pluginPath; - } - }); - - if (removePath) { - rimraf(removePath, function() { - if (fs.existsSync(removePath)) { - deferred.reject(Errors.ERROR_UNINSTALL); - } else { - project.remove(plugin); - deferred.resolve(pluginName); - } - }); - } else { - deferred.reject(Errors.ERROR_NOT_FOUND); - } - }); - - return deferred.promise; - }, - uninstall: function (renderer) { - - var packageName = arguments.length >= 3 ? arguments[1] : null, - done = arguments[arguments.length - 1]; - - if(!packageName) { - return renderer.log(chalk.red('Please specify a plugin to uninstall.')); - } - - var project = new Project(Constants.DefaultProjectManifestPath); - if (!project.isProjectContainsManifestFile()) { - return RendererHelpers.reportInvalidFrameworkDirectory(renderer, done)(true); - } - - var plugin = Plugin.parse(packageName); - - PackageMeta.getKeywords(plugin, { registry: Constants.getRegistry() }) - .then(function (keywords) { - var resolver = new PluginTypeResolver(), - pluginType = resolver.resolve(keywords); - - renderer.log(chalk.cyan(plugin.packageName), 'found.', 'Uninstalling', pluginType.typename, '...'); - return uninstallPackage(plugin, { - directory: path.join('src', pluginType.belongsTo), - cwd:Constants.cwd - }); - }) - .then(function () { - project.remove(plugin); - }) - .then(function () { - done(); - }) - .fail(function() { - // will fail if plugin has not been installed by Bower (i.e. the .bower.json manifest is missing) - // so just try and remove the directory (this is basically what Bower does anyway) - - var removePath; - - ['components', 'extensions', 'menu', 'theme'].forEach(function(pluginType) { - var pluginPath = path.join(Constants.cwd, 'src', pluginType, plugin.packageName); - - if (fs.existsSync(pluginPath)) { - removePath = pluginPath; - } - }); - - if (removePath) { - rimraf(removePath, function() { - if (fs.existsSync(removePath)) { - RendererHelpers.reportFailure(renderer, done); - } else { - project.remove(plugin); - done(); - } - }); - } else { - RendererHelpers.reportFailure(renderer, done); - } - }); - } - -}; +import { uninstall as pluginsUninstall } from '../integration/PluginManagement.js' + +export default async function uninstall (logger, ...args) { + const plugins = args.filter(arg => !String(arg).startsWith('--')) + await pluginsUninstall({ + logger, + plugins + }) +} diff --git a/lib/commands/unregister.js b/lib/commands/unregister.js index 04c7e31..725165b 100644 --- a/lib/commands/unregister.js +++ b/lib/commands/unregister.js @@ -1,96 +1,12 @@ -var bower = require('bower'), - chalk = require('chalk'), - inquirer = require('inquirer'), - _ = require('lodash'), - Q = require('q'), - request = require('request'), - Constants = require('../Constants'), - JsonLoader = require('../JsonLoader'), - authenticate = require('../promise/authenticate'), - log; - -module.exports = { - unregister: function (renderer) { - log = renderer.log; - - var done = arguments[arguments.length-1] || function () {}; - var pluginName; - - if (arguments.length >= 3) { - pluginName = arguments[1]; - } - - log(chalk.yellow('This will unregister the plugin at', Constants.getRegistry())); - - getProperties(pluginName) - .then(authenticate) - .then(confirm) - .then(unregister) - .then(function() { - log(chalk.green('The plugin was successfully unregistered.')); - done(); - }) - .catch(function (err) { - log(chalk.red(err)); - log('The plugin was not unregistered.'); - done(err); - }) - .done(); - } -}; - -function getProperties(pluginName) { - if (pluginName) { - return Q.resolve({name:pluginName}); - } - - return loadPluginProperties('./bower.json'); -} - -function loadPluginProperties(path, defaults) { - var deferred = Q.defer(); - - path = path || './bower.json'; - - if(!JsonLoader.existsSync(path)) { - deferred.reject(new Error('bower.json is not in the current working directory. Plugins must be a valid bower package.')); - } - JsonLoader.readJSON(path, function (data) { - deferred.resolve(_.extend({}, defaults, data)); - }); - - return deferred.promise; -} - -function confirm(properties) { - var deferred = Q.defer(); - var schema = [ - { - name: 'ready', - message: chalk.cyan('Confirm Unregister now?'), - type: 'confirm', - default: true - } - ]; - inquirer.prompt(schema).then(confirmation => { - if(!confirmation.ready) deferred.reject(new Error('Aborted. Nothing has been unregistered.')); - deferred.resolve(properties); - }).catch(err => deferred.reject(err)); - return deferred.promise; -} - -function unregister(properties) { - var deferred = Q.defer(); - - // user (username) with OAuth (token) wants to unregister the registered plugin (name) from registry - bower.commands.unregister(properties.username+'/'+properties.name, {token:properties.token, registry: Constants.getRegistry()}) - .on('end', function (result) { - //log('end', result); - deferred.resolve(); - }) - .on('error', function (err) { - //log('error', err); - deferred.reject(err); - }); - return deferred.promise; +import { unregister as pluginUnregister } from '../integration/PluginManagement.js' + +export default async function register (logger, ...args) { + // strip flags + args = args.filter(arg => !String(arg).startsWith('--')) + const pluginName = args[0] + return await pluginUnregister({ + logger, + cwd: process.cwd(), + pluginName + }) } diff --git a/lib/commands/update.js b/lib/commands/update.js index d9b6880..233c503 100644 --- a/lib/commands/update.js +++ b/lib/commands/update.js @@ -1,867 +1,12 @@ -var bower = require('bower'); -var chalk = require('chalk'); -var fs = require('fs'); -var inquirer = require('inquirer'); -var _ = require('lodash') -var path = require('path'); -var Q = require('q'); -var semver = require('semver'); -var Constants = require('../Constants'); -var JsonLoader = require('../JsonLoader'); -var JsonWriter = require('../JsonWriter'); -var PackageMeta = require('../PackageMeta'); -var Plugin = require('../Plugin'); -var Project = require('../Project'); -var PluginTypeResolver = require('../PluginTypeResolver'); -var RendererHelpers = require('../RendererHelpers'); -var VersionChecker = require('../VersionChecker') -var update = require('../promise/update'); -var promise = require('../promise/util'); -var Errors = require('../errors'); -var readline = require('readline'); - -module.exports = function() { - - // # Assumptions - - // All plugins are from Adapt ecosystem ("adapt-") - // As normal, .bowerrc will be read if present - this should point to a single Adapt registry - - // # Tasks - - // 1. Consider remove `project` and instead just store framework version - - // standard output - var logger; - // our temporary bower manifest - var bowerJson; - // a representation of the Adapt project we are going to update - var project; - // the plugins to update (`Plugin` instances) with the target version - var plugins; - // whether to summarise installed plugins without modifying anything - var isCheck = false; - // whether to output debugging information or not - var isDebuggingEnabled = false; - // when a bower command errors this is the maximum number of attempts the command will be repeated - var bowerCmdMaxTry = 5; - var installedPlugins; - // whether this command is being performed on the command line - var isInteractive = true; - - return { - apiupdate: function(pluginName, cwd) { - isInteractive = false; - - Constants.setCwd(cwd); - - clean(); - - bowerJson = {"name": "manifest", "dependencies":{}}; - project = new Project(Constants.DefaultProjectManifestPath, Constants.DefaultProjectFrameworkPath); - plugins = []; - installedPlugins = {}; - - if (!project.isProjectContainsManifestFile()) { - return Q.reject(Errors.ERROR_COURSE_DIR); - } - - args = pluginName ? [pluginName] : ['all']; - - discoverPlugins(); - - return Q(args) - .then(createManifestFromArguments) - .then(checkRedundancy) - .then(createPlugins) - .then(determineTargetVersions) - .then(checkIncompatible) - .then(performUpdates) - .then(verifyChanged) - .then(printUpdateSummary) - .finally(clean); - }, - update: function(renderer) { - var args = [].slice.call(arguments, 1); - var done = args.pop() || function() {}; - - logger = renderer; - - clean(); - - bowerJson = {"name": "manifest", "dependencies":{}}; - project = new Project(Constants.DefaultProjectManifestPath, Constants.DefaultProjectFrameworkPath); - plugins = []; - installedPlugins = {}; - - //bower.commands.info('adapt-contrib-media').on('end', function() {console.log(arguments)}) - - var checkArgIndex = args.indexOf('--check'); - var debugArgIndex = args.indexOf('--debug'); - - if (checkArgIndex >= 0) { - args.splice(checkArgIndex, 1); - isCheck = true; - } - - if (debugArgIndex >= 0) { - args.splice(checkArgIndex, 1); - isDebuggingEnabled = true; - } - - discoverPlugins(); - - if (isCheck) { - init(args) - .then(checkRedundancy) - .then(createPlugins) - .then(determineTargetVersions) - .then(printCheckSummary) - .then(done) - .fail(reportFailure(logger, done)) - } else { - init(args) - .then(checkRedundancy) - .then(createPlugins) - .then(determineTargetVersions) - .then(checkMissing) - .then(promptToUpdateIncompatible) - .then(performUpdates) - .then(verifyChanged) - .then(printUpdateSummary) - .then(done) - .fail(reportFailure(logger, done)) - .finally(clean); - } - } - } - - function discoverPlugins() { - - var components = discoverNamedGroup('components'); - var extensions = discoverNamedGroup('extensions'); - var menu = discoverNamedGroup('menu'); - var theme = discoverNamedGroup('theme'); - - function discoverNamedGroup(group) { - var srcpath = path.join(Constants.cwd, 'src', group); - - if (!fs.existsSync(srcpath)) return; - - var pluginNames = []; - - fs.readdirSync(srcpath).forEach(function(f) { - var pluginPath = path.join(srcpath, f); - var bowerPath = path.join(pluginPath, 'bower.json'); - var bowerManifest; - - if (fs.lstatSync(pluginPath).isDirectory() && fs.existsSync(bowerPath)) { - bowerManifest = JsonLoader.readJSONSync(bowerPath); - if (bowerManifest.name) { - installedPlugins[bowerManifest.name] = {manifest:bowerManifest, group:group}; - } - } - }); - } - } - - function addSelectedPlugins(arr) { - var groups = ['all', 'components', 'extensions', 'menu', 'theme']; - var selectedGroups = []; - - // record which groups are found and remove from list, taking care to avoid duplicates - arr = arr.filter(function(item) { - if (groups.indexOf(item) != -1) { - if (selectedGroups.indexOf(item) == -1) selectedGroups.push(item); - return false; - } - return true; - }); - - if (selectedGroups.indexOf('all') != -1) { - addAllPlugins(); - } else { - // add components, extensions, menus etc - selectedGroups.forEach(addPluginsFromGroup); - // add individual plugins - arr.forEach(addPlugin); - } - } - - function getPluginNames(group) { - return _.filter(_.keys(installedPlugins), function(k) { - return installedPlugins[k].group == group; - }); - } - - function addPlugin(arg) { - var tokens = arg.split(/[#@]/); - var name = tokens[0]; - var version = tokens[1]; - - if (!installedPlugins[name]) return; - - switch (tokens.length) { - case 1: bowerJson.dependencies[name] = '*'; break; - case 2: bowerJson.dependencies[name] = version; break; - default: return; - } - } - - function addPluginsFromGroup(group) { - var all = !group || group == 'all'; - - if (group == 'components' || all) getPluginNames('components').forEach(addPlugin); - if (group == 'extensions' || all) getPluginNames('extensions').forEach(addPlugin); - if (group == 'menu' || all) getPluginNames('menu').forEach(addPlugin); - if (group == 'theme' || all) getPluginNames('theme').forEach(addPlugin); - } - - function addAllPlugins() { - addPluginsFromGroup(); - } - - function createManifestFromArguments(args) { - addSelectedPlugins(args); - } - - function init(args) { - logger.log(); - - if (args.length == 0) { - if (isCheck) { - args = ['all']; - return Q(args).then(createManifestFromArguments); - } - - return createPromptTask({ - message: chalk.reset('This command will attempt to update all installed plugins. Do you wish to continue?'), - type: 'confirm' - }).then(function() { - args = ['all']; - return Q(args).then(createManifestFromArguments); - }); - } - // else process arguments - return Q(args).then(createManifestFromArguments); - } - - function checkRedundancy() { - if (Object.keys(bowerJson.dependencies).length == 0) { - if (isInteractive) { - return Q.reject({message:'No valid targets specified (please check spelling and case).'}); - } - return Q.reject(Errors.ERROR_NOTHING_TO_UPDATE); - } else { - return Q.resolve(); - } - } - - function createPlugins() { - debug('createPlugins'); - - Object.keys(bowerJson.dependencies).forEach(function(pluginName) { - var plugin = Plugin.parse(pluginName+'#'+bowerJson.dependencies[pluginName]); - plugin._installedVersion = installedPlugins[pluginName].manifest.version; - plugin._versionIndex = 0; - plugin._bowerCmdCount = 0; - plugin._belongsTo = installedPlugins[pluginName].group; - plugins.push(plugin); - }); - - var promiseToGetInfo = []; - - for (var i=0, c=plugins.length; i')+' Querying server '+Math.round(100*settled/total)+'% complete'); - }) - .then(function() { - process.stderr.write('\n'); - }); - } - - function determineTargetVersions() { - //console.log('determineTargetVersions'); - return Q.all(plugins.filter(isPresent).map(getTargetVersion)); - } - - function getTargetVersion(plugin) { - plugin._latestVersion = plugin._bowerInfo.version; - - // if the plugin has no tags then it is not possible to change version - if (!plugin._versions || plugin._versions.length == 0) return Q.resolve(); - - // if plugin already at latest version then nothing to do - if (semver.satisfies(plugin._installedVersion, plugin._bowerInfo.version)) { - //console.log('no update available for', plugin.packageName, plugin._bowerInfo.version); - plugin._isAtLatestVersion = true; - return Q.resolve(); - } - - //console.log('checking available updates for', plugin.packageName, 'with constraint', plugin.version, '(latest version is '+plugin._bowerInfo.version+')'); - - return checkProposedVersion(plugin); - } - - function checkProposedVersion(plugin, deferred) { - deferred = deferred || Q.defer(); - var adaptVersion = project.getFrameworkVersion(); - var satisfiesConstraint = semver.satisfies(plugin._bowerInfo.version, plugin.version); - - //console.log('getting target version for', plugin.packageName, ': checking', plugin._versions[plugin._versionIndex]); - - if (!plugin._isMissingAtRepo) { - //console.log('plugin not missing, plugin framework requirement is', plugin._bowerInfo.framework, 'installed framework', adaptVersion); - // check that the proposed plugin is compatible with the installed framework and that it also satisfies any user-provided constraint - if (semver.satisfies(adaptVersion, plugin._bowerInfo.framework) && - satisfiesConstraint) { - //console.log(plugin.packageName, chalk.green('can'), 'be updated from', plugin._installedVersion, 'to', plugin._bowerInfo.version, '(requires framework '+plugin._bowerInfo.framework+')'); - plugin._proposedVersion = plugin._bowerInfo.version; - plugin._shouldBeUpdated = true; - deferred.resolve(); - } else { - //console.log(plugin.packageName, chalk.red('cannot'), 'be updated to', plugin._bowerInfo.version, '(requires framework'+plugin._bowerInfo.framework+')'); - if (plugin._versionIndex + 1 < plugin._versions.length && semver.gt(plugin._versions[plugin._versionIndex + 1], plugin._installedVersion)) { - plugin._versionIndex++; - getInfo(plugin).then(function() { - checkProposedVersion(plugin, deferred); - }); - } else { - deferred.resolve(); - } - } - } else { - deferred.resolve(); - } - - return deferred.promise; - } - - function getInfo(plugin, deferred) { - // presence of deferred signifies a retry - if (!deferred) this._bowerCmdCount = 0; - - deferred = deferred || Q.defer(); - - function onSuccess(results) { - plugin._bowerInfo = results.latest || results; - if (results.versions) plugin._versions = results.versions; - deferred.notify(); - deferred.resolve(results); - } - - function onFail() { - reportError(); - - if (canRetry()) { - getInfo(plugin, deferred); - } else { - plugin._isMissingAtRepo = true; - deferred.notify(); - deferred.resolve(); - } - } - - try { - //console.log('Querying registry for', plugin.packageName, '(' + plugin.version + ')'); - var versionString = plugin._versions ? '#'+plugin._versions[plugin._versionIndex] : ''; - plugin._bowerCmdCount++; - bower.commands.info(plugin.packageName+versionString, null, {registry:Constants.getRegistry(), cwd:Constants.cwd}).on('end', onSuccess).on('error', onFail); - } catch(err) { - onFail(); - } - - function canRetry() { - return plugin._bowerCmdCount < bowerCmdMaxTry; - } - - function reportError() { - if (plugin._bowerCmdCount < bowerCmdMaxTry) { - debug(chalk.bold.magenta(''), 'Could not get info for', plugin.packageName+'.', 'Retrying.'); - } else { - debug(chalk.bold.magenta(''), 'Could not get info for', plugin.packageName+'.', 'Aborting.'); - } - } - - return deferred.promise; - } - - function checkMissing() { - var missing = plugins.filter(isMissing); - - if (missing.length == 0) { - return Q.resolve(); - } else if (missing.length == plugins.length) { - if (missing.length == 1) { - return Q.reject('The requested plugin was not found at the registry'); - } else { - return Q.reject('None of the requested plugins were found at the registry'); - } - } else { - return promptToListMissing().then(listMissingAndPromptToContinue); - } - } - - function promptToListMissing() { - return createPromptTask({ - message: chalk.cyan('Some plugins could not be found at the registry. Hit for list.'), - type: 'confirm' - }); - } - - function listMissingAndPromptToContinue() { - var missing = plugins.filter(isMissing); - - missing.forEach(function(plugin) { - logger.log(plugin.packageName); - }); - - return createPromptTask({ - message: chalk.cyan('Continue to update other plugins?'), - type: 'confirm', - default: true - }); - } - - function isMissing(plugin) { - return plugin._isMissingAtRepo === true; - } - - function isPresent(plugin) { - return !isMissing(plugin); - } - - function isIncompatible(plugin) { - return !semver.valid(plugin._proposedVersion); - } - - function isToBeUpdated(plugin) { - return plugin._shouldBeUpdated && !plugin._wasUpdated; - } - - function isConstrained(plugin) { - return plugin.version != '*'; - } - - function isUntagged(plugin) { - return !plugin._versions || plugin._versions.length == 0; - } - - function someOtherVersionSatisfiesConstraint(plugin) { - var maxSatisfying = semver.maxSatisfying(plugin._versions, plugin.version); - return maxSatisfying != null && !semver.satisfies(maxSatisfying, plugin._installedVersion); - } - - function checkIncompatible() { - var list = plugins.filter(isPresent).filter(isIncompatible).filter(isConstrained).filter(someOtherVersionSatisfiesConstraint); - - if (list.length == 0) return Q.resolve(); - - var names = list.map(function(p) { - return p.packageName; - }); - - return Q.reject(Errors.ERROR_UPDATE_INCOMPATIBLE); - } - - function promptToUpdateIncompatible() { - //console.log('promptToUpdateIncompatible'); - var adaptVersion = project.getFrameworkVersion(); - // if there are no compatible updates but the user has requested a specific version (or range) and a corresponding version exists then prompt - var list = plugins.filter(isPresent).filter(isIncompatible).filter(isConstrained).filter(someOtherVersionSatisfiesConstraint); - - if (list.length == 0) return Q.resolve(); - - logger.log(chalk.bgRed(''), ' Changes to the following plugins have been requested that will not use the latest compatible version in each case.'); - - return promise.serialise(list, function(plugin) { - // only prompt for plugins that have been requsted with a specific version constraint by the user - return createPromptTask({ - message: chalk.reset(`Change ${plugin.packageName} to ${semver.maxSatisfying(plugin._versions, plugin.version)}?`), - type: 'confirm', - default: false, - onlyRejectOnError: true - }) - .then(function(result) { - plugin._shouldBeUpdated = result; - }); - }); - } - - function performUpdates() { - var filtered = plugins.filter(isPresent).filter(isToBeUpdated); - var settled = 0, total = filtered.length; - - return promise.serialise(filtered, function(plugin) { - return createUpdateTask(plugin); - }) - .then(function() { - if (isInteractive) renderUpdateProgressFinished(); - }); - } - - function verifyChanged() { - plugins.filter(isPresent).forEach(function(plugin) { - if (!plugin._wasUpdated) return; - - var p = path.join(Constants.cwd, 'src', plugin._belongsTo, plugin.packageName, 'bower.json'); - - plugin._bowerInfo = JsonLoader.readJSONSync(p); - plugin._updatedVersion = plugin._bowerInfo.version; - }); - - return Q.resolve(); - } - - function highlight(str) { - var sub1 = 'adapt-contrib-'; - var sub2 = 'adapt-'; - - if (str.indexOf(sub1) == 0) { - return chalk.reset(sub1)+chalk.yellowBright(str.substring(sub1.length)); - } - - if (str.indexOf(sub2) == 0) { - return chalk.reset(sub2)+chalk.yellowBright(str.substring(sub2.length)); - } - - return str; - } - - function yellowIfEqual(v1, v2) { - var colourFunc = semver.satisfies(v1, v2) ? chalk.yellowBright : chalk.magentaBright; - - return colourFunc(v2); - } - - function greenIfEqual(v1, v2) { - var colourFunc = semver.satisfies(v1, v2) ? chalk.greenBright : chalk.magentaBright; - - return colourFunc(v2); - } - - function printCheckSummary() { - //console.log('printCheckSummary'); - - var present = plugins.filter(isPresent); - var missing = plugins.filter(isMissing); - var untagged = _.difference(present.filter(isUntagged), isMissing); - var latest = present.filter(function(plugin) {return plugin._isAtLatestVersion}); - var updateAvailable = present.filter(function(plugin){return plugin._proposedVersion}); - var updateNotAvailable = _.difference(present.filter(function(plugin){return !plugin._proposedVersion}), missing, untagged, latest); - - var byPackageName = function(a, b) { - if (a.packageName < b.packageName) return -1; - if (a.packageName > b.packageName) return 1; - return 0; - }; - - logger.log(); - - if (latest.length > 0) logger.log(chalk.whiteBright('The following plugins are using the latest version:')); - - latest.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.reset(highlight(plugin.packageName+' @'+plugin._installedVersion))); - }); - - if (latest.length > 0) logger.log(); - - // ************************************ - - if (updateAvailable.length > 0) logger.log(chalk.whiteBright('The following updates can be made:')); - - updateAvailable.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.reset(highlight(plugin.packageName), 'from', chalk.yellowBright(plugin._installedVersion), 'to', chalk.greenBright(plugin._proposedVersion), '(latest is '+greenIfEqual(plugin._proposedVersion, plugin._latestVersion)+')')); - }); - - if (updateAvailable.length > 0) logger.log(); - - // ************************************ - - if (updateNotAvailable.length > 0) logger.log(chalk.whiteBright('The following have no compatible updates:')); - - updateNotAvailable.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.reset(highlight(plugin.packageName+' @'+plugin._installedVersion)+' (latest is '+chalk.magentaBright(plugin._latestVersion)+')')); - }); - - if (updateNotAvailable.length > 0) logger.log(); - - // ************************************ - - untagged.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.redBright(plugin.packageName, 'has no version tags and so cannot be updated (use adapt install', plugin.packageName, 'to overwrite)')); - }); - - if (untagged.length > 0) logger.log(); - - // ************************************ - - missing.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.redBright(plugin.packageName, 'could not be found at the registry')); - }); - - if (missing.length > 0) logger.log(); - } - - function printUpdateSummary() { - if (isInteractive) logger.log(chalk.bold.cyan(''), 'Operation completed. Update summary:'); - - var present = plugins.filter(isPresent); - var missing = plugins.filter(isMissing); - var untagged = _.difference(present.filter(isUntagged), isMissing); - var errored = present.filter(function(plugin) {return plugin._shouldBeUpdated && !plugin._wasUpdated}); - var updated = present.filter(function(plugin) {return plugin._wasUpdated}); - var latest = present.filter(function(plugin) {return plugin._isAtLatestVersion}); - var userSkipped = _.difference(present.filter(isConstrained).filter(isIncompatible).filter(someOtherVersionSatisfiesConstraint), updated, errored); - var incompatibleConstrained = _.difference(present.filter(isIncompatible).filter(isConstrained), updated, untagged); - var incompatible = _.difference(present.filter(isIncompatible), missing, untagged, latest, updated, incompatibleConstrained); - - var byPackageName = function(a, b) { - if (a.packageName < b.packageName) return -1; - if (a.packageName > b.packageName) return 1; - return 0; - }; - - if (!isInteractive) { - var report = []; - - if (plugins.length == 1) { - var p = plugins[0]; - - if (latest.length == 1 || updated.length == 1) { - var bowerPath = path.join(Constants.cwd, 'src', p._belongsTo, p.packageName, 'bower.json'); - return Q.resolve(JsonLoader.readJSONSync(bowerPath)); - } - if (errored.length == 1) { - var error = _.clone(Errors.ERROR_UPDATE_ERROR); - - if (p._updateError) error.message = p._updateError; - - return Q.reject(error); - } - if (incompatible.length == 1) { - return Q.reject(Errors.ERROR_NO_UPDATE); - } - if (untagged.length == 1) { - return Q.reject(Errors.ERROR_NO_RELEASES); - } - - return Q.reject(Errors.ERROR_NOT_FOUND); - } - - latest.forEach(function(p) { - report.push({ - name: p.packageName, - status:'fulfilled', - pluginData: p._bowerInfo - }); - }); - - updated.forEach(function(p) { - report.push({ - name: p.packageName, - status:'fulfilled', - pluginData: p._bowerInfo - }); - }); - - // N.B. there will not be any incompatibleConstrained as this results in a rejected promise - - errored.forEach(function(p) { - var error = _.clone(Errors.ERROR_UPDATE_ERROR); - - if (p._updateError) error.message = p._updateError; - - report.push({ - name: p.packageName, - status:'rejected', - pluginData: p._bowerInfo, - reason: error - }); - }); - - incompatible.forEach(function(p) { - report.push({ - name: p.packageName, - status:'rejected', - pluginData: p._bowerInfo, - reason: Errors.ERROR_NO_UPDATE - }); - }); - - untagged.forEach(function(p) { - report.push({ - name: p.packageName, - status:'rejected', - pluginData: p._bowerInfo, - reason: Errors.ERROR_NO_RELEASES - }); - }); - - missing.forEach(function(p) { - report.push({ - name: p.packageName, - status:'rejected', - pluginData: p._bowerInfo, - reason: Errors.ERROR_NOT_FOUND - }); - }); - - return Q.resolve(report); - } - - logger.log(); - - if (latest.length > 0) logger.log(chalk.whiteBright('The following plugins are using the latest version:')); - - latest.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.reset(highlight(plugin.packageName+' @'+plugin._installedVersion))); - }); - - if (latest.length > 0) logger.log(); - - //*************************** - - if (incompatibleConstrained.length > 0) logger.log(chalk.whiteBright('The following plugins are using the requested version:')); - - incompatibleConstrained.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.reset(highlight(plugin.packageName+' @'+plugin._installedVersion)) + '. Latest is', chalk.magentaBright(plugin._latestVersion)); - }); - - if (incompatibleConstrained.length > 0) logger.log(); - - //*************************** - - if (incompatible.length > 0) logger.log(chalk.whiteBright('The following plugins are using the latest compatible version:')); - - incompatible.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.reset(highlight(plugin.packageName+' @'+plugin._installedVersion)) + '. Latest is', greenIfEqual(plugin._installedVersion, plugin._latestVersion)); - }); - - if (incompatible.length > 0) logger.log(); - - //*************************** - - if (updated.length > 0) logger.log(chalk.whiteBright('The following updates have been made:')); - - updated.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.reset(highlight(plugin.packageName)), 'from', chalk.yellowBright(plugin._installedVersion), 'to', chalk.greenBright(plugin._updatedVersion)+'.', 'Latest is', greenIfEqual(plugin._updatedVersion, plugin._latestVersion)); - }); - - if (updated.length > 0) logger.log(); - - //*************************** - - userSkipped.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.magenta(plugin.packageName, 'was skipped')); - }); - - if (userSkipped.length > 0) logger.log(); - - errored.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.bold.redBright(plugin.packageName, 'could not be updated', '(error code '+plugin._updateError+')')); - }); - - if (errored.length > 0) logger.log(); - - untagged.sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.redBright(plugin.packageName, 'has no version tags and so cannot be updated (use adapt install', plugin.packageName, 'to overwrite)')); - }); - - if (untagged.length > 0) logger.log(); - - missing.sort(byPackageName).sort(byPackageName).forEach(function(plugin) { - logger.log(chalk.redBright(plugin.packageName, 'could not be found at the registry')); - }); - - return Q.resolve(); - } - - function clean() { - if (fs.existsSync(path.join(Constants.cwd, 'bower.json'))) { - fs.unlinkSync(path.join(Constants.cwd, 'bower.json')); - } - return Q.resolve(); - } - - function createUpdateTask(plugin) { - //console.log(plugin.packageName, 'is missing', !!plugin._isMissingAtRepo, 'is ignored',!plugin._shouldBeUpdated); - - return Q.when(null, function() { - var deps = {}; - var manifest; - - // create bower.json with a single dependency, otherwise bower will install things incorrectly - deps[plugin.packageName] = plugin._proposedVersion || plugin.version; - manifest = _.extend({}, bowerJson, {dependencies:deps}); - - //console.log('manifest\n', JSON.stringify(manifest, null, 4)); - JsonWriter.writeJSONSync(path.join(Constants.cwd, 'bower.json'), manifest); - //console.log(JSON.stringify(JsonLoader.readJSONSync('bower.json'), null, 4)); - return update(plugin, null, { - directory: path.join('src', plugin._belongsTo), - registry: Constants.getRegistry(), - cwd:Constants.cwd, - force:true - }) - .then(function (result) { - //console.log(result.updated, result.error ? 'error code: '+result.error.code : 'no error') - plugin._wasUpdated = result.updated; - if (result.error) plugin._updateError = result.error.code; - if (isInteractive) renderUpdateProgress(); - }); - }) - - } - - function createPromptTask(params) { - var deferred = Q.defer(); - var defaultConfig = { - name: 'question', - onlyRejectOnError: false - }; - var config = _.extend({}, defaultConfig, params); - var schema = [ config ]; - inquirer.prompt(schema).then(confirmation => { - if (!config.onlyRejectOnError && !confirmation.question) deferred.reject(new Error('Aborted. Nothing has been updated.')); - deferred.resolve(confirmation.question); - }).catch(err => deferred.reject(err)); - return deferred.promise; - } - - function renderUpdateProgress() { - var list = plugins.filter(function(plugin) {return !plugin._isMissingAtRepo && plugin._shouldBeUpdated}); - var settled = plugins.filter(function(plugin) {return _.isBoolean(plugin._wasUpdated);}).length; - var total = list.length; - //console.log('progress', settled, total); - readline.cursorTo(process.stderr, 0); - process.stderr.write(chalk.bold.cyan('')+' Updates '+Math.round(100*settled/total)+'% complete'); - } - - function renderUpdateProgressFinished() { - process.stderr.write('\n'); - } - - function debug() { - if (isDebuggingEnabled) { - logger.debug.apply(logger, arguments); - } - } - - function reportFailure(renderer, done) { - return function (err) { - renderer.log(chalk.redBright(err.message)); - done(err); - }; - } -}; +import { update as pluginsUpdate } from '../integration/PluginManagement.js' + +export default async function update (logger, ...args) { + /** strip flags */ + const isDryRun = args.includes('--dry-run') || args.includes('--check') + const plugins = args.filter(arg => !String(arg).startsWith('--')) + await pluginsUpdate({ + logger, + plugins, + isDryRun + }) +} diff --git a/lib/commands/version.js b/lib/commands/version.js index 9a0dd23..6635adc 100644 --- a/lib/commands/version.js +++ b/lib/commands/version.js @@ -1,15 +1,13 @@ -var chalk = require('chalk'), - Constants = require('../Constants'), - Project = require('../Project'), - path = require('path'), - JsonLoader = require('../JsonLoader'); +import Project from '../integration/Project.js' +import path from 'path' +import { readValidateJSONSync } from '../util/JSONReadValidate.js' +import getDirNameFromImportMeta from '../util/getDirNameFromImportMeta.js' +const __dirname = getDirNameFromImportMeta(import.meta) -module.exports = { - version: function(renderer) { - var versionPath = path.join(__dirname, '../../package.json'); - var version = JsonLoader.readJSONSync(versionPath).version; - var project = new Project(Constants.DefaultProjectManifestPath, Constants.DefaultProjectFrameworkPath); - renderer.log('CLI: ' + version); - renderer.log('Framework: ' + project.getFrameworkVersion()); - } -}; +export default function version (logger) { + const cliVersionPath = path.join(__dirname, '../../package.json') + const cliVersion = readValidateJSONSync(cliVersionPath).version + const project = new Project() + logger?.log('CLI: ' + cliVersion) + logger?.log('Framework: ' + project.version) +} diff --git a/lib/download.js b/lib/download.js deleted file mode 100644 index 95beeca..0000000 --- a/lib/download.js +++ /dev/null @@ -1,101 +0,0 @@ -'use strict'; - -var decompress = require('decompress'); -var eachAsync = require('each-async'); -var fs = require('fs'); -var mkdir = require('mkdirp'); -var path = require('path'); -var request = require('request'); -var through = require('through2'); - -/** - * Download a file to a given destination - * - * Options: - * - * - `extract` Try extracting the file - * - `mode` Set mode on the downloaded files - * - `strip` Equivalent to --strip-components for tar - * - * @param {String|Array|Object} url - * @param {String} dest - * @param {Object} opts - * @api public - */ - -module.exports = function (url, dest, opts) { - url = Array.isArray(url) ? url : [url]; - opts = opts || {}; - - var stream = through(); - var strip = opts.strip || '0'; - var target; - - eachAsync(url, function (url, index, done) { - opts.url = url; - target = path.join(dest, path.basename(url)); - - if (url.url && url.name) { - target = path.join(dest, url.name); - opts.url = url.url; - } - - var req = request.get(opts) - .on('response', function (res) { - stream.emit('response', res); - }) - .on('data', function (data) { - stream.emit('data', data); - }) - .on('error', function (err) { - stream.emit('error', err); - }); - - req.on('response', function (res) { - var mime = res.headers['content-type']; - var status = res.statusCode; - var end; - - if (status < 200 || status >= 300) { - stream.emit('error', status); - return; - } - - if (opts.extract && decompress.canExtract(url, mime)) { - var ext; - - if (decompress.canExtract(url)) { - ext = url; - } else { - ext = mime; - } - - end = decompress.extract({ - ext: ext, - path: dest, - strip: strip - }); - } else { - if (!fs.existsSync(dest)) { - mkdir.sync(dest); - } - - end = fs.createWriteStream(target); - } - - req.pipe(end); - - end.on('close', function () { - if (!opts.extract && opts.mode) { - fs.chmodSync(target, opts.mode); - } - - done(); - }); - }); - }, function () { - stream.emit('close'); - }); - - return stream; -}; \ No newline at end of file diff --git a/lib/errors.js b/lib/errors.js deleted file mode 100644 index 03a65eb..0000000 --- a/lib/errors.js +++ /dev/null @@ -1,58 +0,0 @@ -module.exports = { - ERROR_COURSE_DIR: { - code: 0, - message: "Commands must be run in an Adapt project directory" - }, - ERROR_INCOMPATIBLE_VALID_REQUEST: { - code: 1, - message: "No compatible version exists (requested version is valid)" - }, - ERROR_INCOMPATIBLE_BAD_REQUEST: { - code: 2, - message: "No compatible version exists (requested version is invalid)" - }, - ERROR_INCOMPATIBLE: { - code: 3, - message: "No compatible version exists" - }, - ERROR_COMPATIBLE_INC_REQUEST: { - code: 4, - message: "Incompatible version requested (compatible version exists)" - }, - ERROR_COMPATIBLE_BAD_REQUEST: { - code: 5, - message: "Requested version is invalid" - }, - ERROR_UNINSTALL: { - code: 6, - message: "The plugin could not be uninstalled" - }, - ERROR_NOT_FOUND: { - code: 7, - message: "The plugin could not be found" - }, - ERROR_NOTHING_TO_UPDATE: { - code: 8, - message: "Could not resolve any plugins to update" - }, - ERROR_UPDATE_INCOMPATIBLE: { - code: 9, - message: "Incompatible update requested" - }, - ERROR_INSTALL_ERROR: { - code: 10, - message: "Unknown installation error" - }, - ERROR_UPDATE_ERROR: { - code: 11, - message: "Unknown update error" - }, - ERROR_NO_RELEASES: { - code: 12, - message: "No published releases" - }, - ERROR_NO_UPDATE: { - code: 13, - message: "No update available" - } -} \ No newline at end of file diff --git a/lib/integration/AdaptFramework.js b/lib/integration/AdaptFramework.js new file mode 100644 index 0000000..9f8d13f --- /dev/null +++ b/lib/integration/AdaptFramework.js @@ -0,0 +1,19 @@ +import build from './AdaptFramework/build.js' +import getLatestVersion from './AdaptFramework/getLatestVersion.js' +import clone from './AdaptFramework/clone.js' +import erase from './AdaptFramework/erase.js' +import download from './AdaptFramework/download.js' +import npmInstall from './AdaptFramework/npmInstall.js' +import deleteSrcCourse from './AdaptFramework/deleteSrcCourse.js' +import deleteSrcCore from './AdaptFramework/deleteSrcCore.js' + +export { + build, + getLatestVersion, + clone, + erase, + download, + npmInstall, + deleteSrcCourse, + deleteSrcCore +} diff --git a/lib/integration/AdaptFramework/build.js b/lib/integration/AdaptFramework/build.js new file mode 100644 index 0000000..cff4d5f --- /dev/null +++ b/lib/integration/AdaptFramework/build.js @@ -0,0 +1,39 @@ +import chalk from 'chalk' +import { exec } from 'child_process' +import Project from '../Project.js' +import path from 'path' + +export default async function adaptBuild ({ + sourceMaps = false, + checkJSON = false, + cache = true, + outputDir = null, + cachePath = null, + cwd = process.cwd(), + logger +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + const project = new Project({ cwd, logger }) + project.tryThrowInvalidPath() + logger?.log(chalk.cyan('running build')) + await new Promise((resolve, reject) => { + const cmd = [ + 'npx grunt', + !checkJSON + ? `server-build:${sourceMaps ? 'dev' : 'prod'}` // AAT + : `${sourceMaps ? 'diff' : 'build'}`, // Handbuilt + !cache && '--disable-cache', + outputDir && `--outputdir=${outputDir}`, + cachePath && `--cachepath=${cachePath}` + ].filter(Boolean).join(' '); + exec(cmd, { cwd }, (error, stdout, stderr) => { + if(error || stderr) { + const e = new Error('grunt tasks failed') + e.cmd = cmd; + e.raw = stdout.match(/>> Error:\s(.+)\s/)[1] + return reject(e) + } + resolve() + }) + }) +} diff --git a/lib/integration/AdaptFramework/clone.js b/lib/integration/AdaptFramework/clone.js new file mode 100644 index 0000000..1fb1004 --- /dev/null +++ b/lib/integration/AdaptFramework/clone.js @@ -0,0 +1,27 @@ +import chalk from 'chalk' +import { exec } from 'child_process' +import { ADAPT_FRAMEWORK } from '../../util/constants.js' +import path from 'path' + +export default async function clone ({ + repository = ADAPT_FRAMEWORK, + branch = 'master', + cwd = process.cwd(), + logger +} = {}) { + repository = repository.replace(/\.git/g, '') + cwd = path.resolve(process.cwd(), cwd) + if (!branch && !repository) throw new Error('Repository details are required.') + logger?.write(chalk.cyan('cloning framework to', cwd, '\t')) + await new Promise(function (resolve, reject) { + const child = exec(`git clone ${repository} "${cwd}"`) + child.addListener('error', reject) + child.addListener('exit', resolve) + }) + await new Promise(function (resolve, reject) { + const child = exec(`git checkout ${branch}`) + child.addListener('error', reject) + child.addListener('exit', resolve) + }) + logger?.log(' ', 'done!') +} diff --git a/lib/integration/AdaptFramework/deleteSrcCore.js b/lib/integration/AdaptFramework/deleteSrcCore.js new file mode 100644 index 0000000..23ee87c --- /dev/null +++ b/lib/integration/AdaptFramework/deleteSrcCore.js @@ -0,0 +1,9 @@ +import fs from 'fs-extra' +import path from 'path' + +export default function deleteSrcCore ({ + cwd = process.cwd() +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + return fs.rm(path.resolve(cwd, 'src/core'), { recursive: true, force: true }) +} diff --git a/lib/integration/AdaptFramework/deleteSrcCourse.js b/lib/integration/AdaptFramework/deleteSrcCourse.js new file mode 100644 index 0000000..9faf9ae --- /dev/null +++ b/lib/integration/AdaptFramework/deleteSrcCourse.js @@ -0,0 +1,9 @@ +import fs from 'fs-extra' +import path from 'path' + +export default function deleteSrcCourse ({ + cwd = process.cwd() +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + return fs.rm(path.resolve(cwd, 'src/course'), { recursive: true, force: true }) +} diff --git a/lib/integration/AdaptFramework/download.js b/lib/integration/AdaptFramework/download.js new file mode 100644 index 0000000..63e164f --- /dev/null +++ b/lib/integration/AdaptFramework/download.js @@ -0,0 +1,21 @@ +import downloader from '../../util/download.js' +import { ADAPT_FRAMEWORK } from '../../util/constants.js' +import path from 'path' + +export default async function download ({ + repository = ADAPT_FRAMEWORK, + branch, + tmp, + cwd, + logger +} = {}) { + repository = repository.replace(/\.git/g, '') + cwd = path.resolve(process.cwd(), cwd) + return downloader({ + repository, + branch, + tmp, + cwd, + logger + }) +} diff --git a/lib/integration/AdaptFramework/erase.js b/lib/integration/AdaptFramework/erase.js new file mode 100644 index 0000000..d4fcaff --- /dev/null +++ b/lib/integration/AdaptFramework/erase.js @@ -0,0 +1,34 @@ +import chalk from 'chalk' +import fs from 'fs-extra' +import inquirer from 'inquirer' +import globs from 'globs' +import path from 'path' + +export default async function erase ({ + isInteractive = true, + cwd, + logger +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + if (!fs.existsSync(cwd)) return + if (isInteractive) { + const results = await inquirer.prompt([{ + name: 'overwrite existing course?', + type: 'confirm', + default: false + }]) + if (!results['overwrite existing course?']) { + throw new Error('Course already exists and cannot overwrite.') + } + } + logger?.log(chalk.cyan('deleting existing course')) + const files = await new Promise((resolve, reject) => { + globs('**', { cwd }, (err, files) => { + if (err) return reject(err) + resolve(files) + }) + }) + for (const file of files) { + await fs.rm(file, { recursive: true }) + } +} diff --git a/lib/integration/AdaptFramework/getLatestVersion.js b/lib/integration/AdaptFramework/getLatestVersion.js new file mode 100644 index 0000000..7cda973 --- /dev/null +++ b/lib/integration/AdaptFramework/getLatestVersion.js @@ -0,0 +1,79 @@ +import request from 'request' +import semver from 'semver' +import gh from 'parse-github-url' +import { ADAPT_DEFAULT_USER_AGENT, ADAPT_FRAMEWORK, ADAPT_ALLOW_PRERELEASE } from '../../util/constants.js' +const semverOptions = { includePrerelease: ADAPT_ALLOW_PRERELEASE } + +export default async function getLatestVersion ({ versionLimit, repository = ADAPT_FRAMEWORK }) { + repository = repository.replace(/\.git/g, '') + const OWNER = gh(repository).owner + const NAME = gh(repository).name + // used in pagination + let nextPage = `https://api.github.com/repos/${OWNER}/${NAME}/releases` + // taken from https://gist.github.com/niallo/3109252 + const parseLinkHeader = header => { + if (!header || header.length === 0) { + return [] + } + const links = {} + // Parse each part into a named link + header.split(',').forEach(p => { + const section = p.split(';') + if (section.length !== 2) { + throw new Error("section could not be split on ';'") + } + const url = section[0].replace(/<(.*)>/, '$1').trim() + const name = section[1].replace(/rel="(.*)"/, '$1').trim() + links[name] = url + }) + return links + } + const processPage = async () => { + const [response, body] = await new Promise((resolve, reject) => { + request({ + headers: { + 'User-Agent': ADAPT_DEFAULT_USER_AGENT + }, + uri: nextPage, + method: 'GET' + }, (error, response, body) => { + if (error) return reject(error) + resolve([response, body]) + }) + }) + if (response?.statusCode === 403 && response?.headers['x-ratelimit-remaining'] === '0') { + // we've exceeded the API limit + const reqsReset = new Date(response.headers['x-ratelimit-reset'] * 1000) + throw new Error(`Couldn't check latest version of ${NAME}. You have exceeded GitHub's request limit of ${response.headers['x-ratelimit-limit']} requests per hour. Please wait until at least ${reqsReset.toTimeString()} before trying again.`) + } + if (response?.statusCode !== 200) { + throw new Error(`Couldn't check latest version of ${NAME}. GitubAPI did not respond with a 200 status code.`) + } + nextPage = parseLinkHeader(response.headers.link).next + let releases + try { + // parse and sort releases (newest first) + releases = JSON.parse(body).sort((a, b) => { + if (semver.lt(a.tag_name, b.tag_name, semverOptions)) return 1 + if (semver.gt(a.tag_name, b.tag_name, semverOptions)) return -1 + return 0 + }) + } catch (e) { + throw new Error(`Failed to parse GitHub release data\n${e}`) + } + const compatibleRelease = releases.find(release => { + const isFullRelease = !release.draft && !release.prerelease + const satisfiesVersion = !versionLimit || semver.satisfies(release.tag_name, versionLimit, semverOptions) + if (!isFullRelease || !satisfiesVersion) return false + return true + }) + if (!compatibleRelease && nextPage) { + return await processPage() + } + if (!compatibleRelease) { + throw new Error(`Couldn't find any releases compatible with specified framework version (${versionLimit}), please check that it is a valid version.`) + } + return compatibleRelease.tag_name + } + return await processPage() +} diff --git a/lib/integration/AdaptFramework/npmInstall.js b/lib/integration/AdaptFramework/npmInstall.js new file mode 100644 index 0000000..d1fd749 --- /dev/null +++ b/lib/integration/AdaptFramework/npmInstall.js @@ -0,0 +1,21 @@ +import chalk from 'chalk' +import { spawn } from 'child_process' +import path from 'path' + +export default async function npmInstall ({ + logger, + cwd +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + await new Promise((resolve, reject) => { + logger?.log(chalk.cyan('installing node dependencies')) + const npm = spawn((process.platform === 'win32' ? 'npm.cmd' : 'npm'), ['--unsafe-perm', 'install'], { + stdio: 'inherit', + cwd + }) + npm.on('close', code => { + if (code) return reject(new Error('npm install failed')) + resolve() + }) + }) +} diff --git a/lib/integration/Plugin.js b/lib/integration/Plugin.js new file mode 100644 index 0000000..6d924e3 --- /dev/null +++ b/lib/integration/Plugin.js @@ -0,0 +1,403 @@ +import slug from 'speakingurl' +import globs from 'globs' +import bower from 'bower' +import endpointParser from 'bower-endpoint-parser' +import semver from 'semver' +import fs from 'fs-extra' +import path from 'path' +import getBowerRegistryConfig from './getBowerRegistryConfig.js' +import { ADAPT_ALLOW_PRERELEASE, PLUGIN_TYPES, PLUGIN_TYPE_FOLDERS, PLUGIN_DEFAULT_TYPE } from '../util/constants.js' +/** @typedef {import("./Project.js").default} Project */ +const semverOptions = { includePrerelease: ADAPT_ALLOW_PRERELEASE } + +// when a bower command errors this is the maximum number of attempts the command will be repeated +const BOWER_MAX_TRY = 5 + +export default class Plugin { + /** + * @param {Object} options + * @param {string} options.name + * @param {string} options.requestedVersion + * @param {boolean} options.isContrib + * @param {boolean} options.isCompatibleEnabled whether to target the latest compatible version for all plugin installations (overrides requestedVersion) + * @param {Project} options.project + * @param {string} options.cwd + * @param {Object} options.logger + */ + constructor ({ + name, + requestedVersion = '*', + isContrib = false, + isCompatibleEnabled = false, + project, + cwd = (project?.cwd ?? process.cwd()), + logger + } = {}) { + this.logger = logger + /** @type {Project} */ + this.project = project + this.cwd = cwd + this.BOWER_REGISTRY_CONFIG = getBowerRegistryConfig({ cwd: this.cwd }) + const endpoint = name + '#' + (isCompatibleEnabled ? '*' : requestedVersion) + const ep = endpointParser.decompose(endpoint) + this.sourcePath = null + this.name = ep.name || ep.source + this.packageName = (/^adapt-/i.test(this.name) ? '' : 'adapt-') + (!isContrib ? '' : 'contrib-') + slug(this.name, { maintainCase: true }) + // the constraint given by the user + this.requestedVersion = requestedVersion + // the most recent version of the plugin compatible with the given framework + this.latestCompatibleSourceVersion = null + // a non-wildcard constraint resolved to the highest version of the plugin that satisfies the requestedVersion and is compatible with the framework + this.matchedVersion = null + // a flag describing if the plugin can be updated + this.canBeUpdated = null + + const isNameAPath = /\\|\//g.test(this.name) + const isVersionAPath = /\\|\//g.test(this.requestedVersion) + const isLocalPath = (isNameAPath || isVersionAPath) + if (isLocalPath) { + // wait to name the plugin until the local config file is loaded + this.sourcePath = isNameAPath ? this.name : this.requestedVersion + this.name = isVersionAPath ? this.packageName : '' + this.packageName = isNameAPath ? '' : this.packageName + this.requestedVersion = '*' + } + // the path of the source files + this.projectPath = null + // the project plugin .bower.json or bower.json + this._projectInfo = null + // the result of a query to the server or disk for source files + this._sourceInfo = null + // server given versions + this._versionsInfo = null + + Plugin.instances.push(this) + } + + /** + * the installed version is the latest version + * @returns {boolean|null} + */ + get isUpToDate () { + const canCheckSourceAgainstProject = (this.latestSourceVersion && this.projectVersion) + if (!canCheckSourceAgainstProject) return null + const isLatestVersion = (this.projectVersion === this.latestSourceVersion) + const isLatestMatchedVersion = (this.projectVersion === this.matchedVersion) + const isProjectVersionGreater = semver.gt(this.projectVersion, this.matchedVersion) + return (isLatestVersion || isLatestMatchedVersion || isProjectVersionGreater) + } + + /** + * the most recent version of the plugin + * @returns {string|null} + */ + get latestSourceVersion () { + return (this._sourceInfo?.version || null) + } + + /** + * the installed version of the plugin + * @returns {string|null} + */ + get projectVersion () { + return (this._projectInfo?.version || null) + } + + /** + * a list of tags denoting the source versions of the plugin + * @returns {[string]} + */ + get sourceVersions () { + return this._versionsInfo + } + + /** + * plugin will be or was installed from a local source + * @returns {boolean} + */ + get isLocalSource () { + return Boolean(this.sourcePath || this?._projectInfo?._wasInstalledFromPath) + } + + /** + * check if source path is a zip + * @returns {boolean} + */ + get isLocalSourceZip () { + return Boolean(this.isLocalSource && (this.sourcePath?.includes('.zip') || this._projectInfo?._source?.includes('.zip'))) + } + + /** @returns {boolean} */ + get isVersioned () { + return Boolean(this.sourceVersions?.length) + } + + /** + * is a contrib plugin + * @returns {boolean} + */ + get isContrib () { + return /^adapt-contrib/.test(this.packageName) + } + + /** + * whether querying the server or disk for plugin information worked + * @returns {boolean} + */ + get isPresent () { + return Boolean(this._projectInfo || this._sourceInfo) + } + + /** + * has user requested version + * @returns {boolean} + */ + get hasUserRequestVersion () { + return (this.requestedVersion !== '*') + } + + /** + * the supplied a constraint is valid and supported by the plugin + * @returns {boolean|null} + */ + get hasValidRequestVersion () { + return (this.latestSourceVersion) + ? semver.validRange(this.requestedVersion, semverOptions) && + (this.isVersioned + ? semver.maxSatisfying(this.sourceVersions, this.requestedVersion, semverOptions) !== null + : semver.satisfies(this.latestSourceVersion, this.requestedVersion) + ) + : null + } + + /** @returns {boolean} */ + get hasFrameworkCompatibleVersion () { + return (this.latestCompatibleSourceVersion !== null) + } + + async fetchSourceInfo () { + if (this.isLocalSource) return await this.fetchLocalSourceInfo() + await this.fetchBowerInfo() + } + + async fetchLocalSourceInfo () { + if (this._sourceInfo) return this._sourceInfo + this._sourceInfo = null + if (!this.isLocalSource) throw new Error('Plugin name or version must be a path to the source') + if (this.isLocalSourceZip) throw new Error('Cannot install from zip files') + this._sourceInfo = await new Promise((resolve, reject) => { + // get bower.json data + const paths = [ + path.resolve(this.cwd, `${this.sourcePath}/bower.json`) + ] + const bowerJSON = paths.reduce((bowerJSON, bowerJSONPath) => { + if (bowerJSON) return bowerJSON + if (!fs.existsSync(bowerJSONPath)) return null + return fs.readJSONSync(bowerJSONPath) + }, null) + resolve(bowerJSON) + }) + if (!this._sourceInfo) return + this.name = this._sourceInfo.name + this.matchedVersion = this.latestSourceVersion + this.packageName = this.name + } + + async fetchBowerInfo () { + if (this._sourceInfo) return this._sourceInfo + this._sourceInfo = null + if (this.isLocalSource) return + const perform = async (attemptCount = 0) => { + try { + return await new Promise((resolve, reject) => { + bower.commands.info(`${this.packageName}`, null, { cwd: this.cwd, registry: this.BOWER_REGISTRY_CONFIG }) + .on('end', resolve) + .on('error', reject) + }) + } catch (err) { + const isFinished = (err?.code === 'ENOTFOUND' || attemptCount >= BOWER_MAX_TRY) + if (isFinished) return null + return await perform(attemptCount++) + } + } + const info = await perform() + if (!info) return + this._sourceInfo = info.latest + this._versionsInfo = info.versions.filter(version => semverOptions.includePrerelease ? true : !semver.prerelease(version)) + } + + async fetchProjectInfo () { + if (this._projectInfo) return this._projectInfo + this._projectInfo = null + this._projectInfo = await new Promise((resolve, reject) => { + // get bower.json data + globs([ + `${this.cwd.replace(/\\/g, '/')}/src/*/${this.packageName}/.bower.json`, + `${this.cwd.replace(/\\/g, '/')}/src/*/${this.packageName}/bower.json` + ], (err, matches) => { + if (err) return resolve(null) + const tester = new RegExp(`/${this.packageName}/`, 'i') + const match = matches.find(match => tester.test(match)) + if (!match) { + // widen the search + globs([ + `${this.cwd.replace(/\\/g, '/')}/src/**/.bower.json`, + `${this.cwd.replace(/\\/g, '/')}/src/**/bower.json` + ], (err, matches) => { + if (err) return resolve(null) + const tester = new RegExp(`/${this.packageName}/`, 'i') + const match = matches.find(match => tester.test(match)) + if (!match) return resolve(null) + this.projectPath = path.resolve(match, '../') + resolve(fs.readJSONSync(match)) + }) + return + } + this.projectPath = path.resolve(match, '../') + resolve(fs.readJSONSync(match)) + }) + }) + if (!this._projectInfo) return + this.name = this._projectInfo.name + this.packageName = this.name + } + + async findCompatibleVersion (framework) { + const getBowerVersionInfo = async (version) => { + const perform = async (attemptCount = 0) => { + try { + return await new Promise((resolve, reject) => { + bower.commands.info(`${this.packageName}@${version}`, null, { cwd: this.cwd, registry: this.BOWER_REGISTRY_CONFIG }) + .on('end', resolve) + .on('error', reject) + }) + } catch (err) { + const isFinished = (err?.code === 'ENOTFOUND' || attemptCount >= BOWER_MAX_TRY) + if (isFinished) return null + return await perform(attemptCount++) + } + } + return await perform() + } + const getMatchingVersion = async () => { + if (this.isLocalSource) { + const info = this.projectVersion ? this._projectInfo : this._sourceInfo + const satisfiesConstraint = !this.hasValidRequestVersion || semver.satisfies(info.version, this.requestedVersion, semverOptions) + const satisfiesFramework = semver.satisfies(framework, info.framework) + if (satisfiesFramework && satisfiesConstraint) this.latestCompatibleSourceVersion = info.version + return info.version + } + + if (!this.isPresent) return null + + // check if the latest version is compatible + const satisfiesConstraint = !this.hasValidRequestVersion || semver.satisfies(this._sourceInfo.version, this.requestedVersion, semverOptions) + const satisfiesFramework = semver.satisfies(framework, this._sourceInfo.framework, semverOptions) + if (!this.latestCompatibleSourceVersion && satisfiesFramework) this.latestCompatibleSourceVersion = this.latestSourceVersion + if (satisfiesConstraint && satisfiesFramework) { + return this.latestSourceVersion + } + + if (!this.isVersioned) return null + + // find the highest version that is compatible with the framework and constraint + const searchVersionInfo = async (framework, versionIndex = 0) => { + const versioninfo = await getBowerVersionInfo(this.sourceVersions[versionIndex]) + // give up if there is any failure to obtain version info + if (!this.isPresent) return null + // check that the proposed plugin is compatible with the contraint and installed framework + const satisfiesConstraint = !this.hasValidRequestVersion || semver.satisfies(versioninfo.version, this.requestedVersion, semverOptions) + const satisfiesFramework = semver.satisfies(framework, versioninfo.framework, semverOptions) + if (!this.latestCompatibleSourceVersion && satisfiesFramework) this.latestCompatibleSourceVersion = versioninfo.version + const checkNext = (!satisfiesFramework || !satisfiesConstraint) + const hasNoMoreVersions = (versionIndex + 1 >= this.sourceVersions.length) + if (checkNext && hasNoMoreVersions) return null + if (checkNext) return await searchVersionInfo(framework, versionIndex + 1) + return versioninfo.version + } + return await searchVersionInfo(framework) + } + this.matchedVersion = await getMatchingVersion() + this.canBeUpdated = (this.projectVersion && this.matchedVersion) && (this.projectVersion !== this.matchedVersion) + } + + /** + * @returns {string} + */ + async getType () { + if (this._type) return this._type + const info = await this.getInfo() + const foundAttributeType = PLUGIN_TYPES.find(type => info[type]) + const foundKeywordType = info.keywords + .map(keyword => { + const typematches = PLUGIN_TYPES.filter(type => keyword?.toLowerCase()?.includes(type)) + return typematches.length ? typematches[0] : null + }) + .filter(Boolean)[0] + return (this._type = foundAttributeType || foundKeywordType || PLUGIN_DEFAULT_TYPE) + } + + async getTypeFolder () { + const type = await this.getType() + return PLUGIN_TYPE_FOLDERS[type] + } + + async getInfo () { + if (this._projectInfo) return this._projectInfo + if (!this._sourceInfo) await this.fetchSourceInfo() + return this._sourceInfo + } + + async getRepositoryUrl () { + if (this._repositoryUrl) return this._repositoryUrl + if (this.isLocalSource) return + const url = await new Promise((resolve, reject) => { + bower.commands.lookup(this.packageName, { cwd: this.cwd, registry: this.BOWER_REGISTRY_CONFIG }) + .on('end', resolve) + .on('error', reject) + }) + return (this._repositoryUrl = url) + } + + /** @returns {string} */ + toString () { + const isAny = (this.projectVersion === '*' || this.projectVersion === null) + return `${this.packageName}${isAny ? '' : `@${this.projectVersion}`}` + } + + async getSchemaPaths () { + if (this.isLocalSource) await this.fetchLocalSourceInfo() + else if (this.project) await this.fetchProjectInfo() + else throw new Error(`Cannot fetch schemas from remote plugin: ${this.name}`) + const pluginPath = this.projectPath ?? this.sourcePath + return new Promise((resolve, reject) => { + return globs(path.resolve(this.cwd, pluginPath, '**/*.schema.json'), (err, matches) => { + if (err) return reject(err) + resolve(matches) + }) + }) + } + + /** + * Read plugin data from pluginPath + * @param {Object} options + * @param {string} options.pluginPath Path to source directory + * @param {string} [options.projectPath=process.cwd()] Optional path to potential installation project + * @returns {Plugin} + */ + static async fromPath ({ + pluginPath, + projectPath = process.cwd() + }) { + const plugin = new Plugin({ + name: pluginPath, + cwd: projectPath + }) + await plugin.fetchLocalSourceInfo() + return plugin + } + + static get instances () { + return (Plugin._instances = Plugin._instances || []) + } +} diff --git a/lib/integration/PluginManagement.js b/lib/integration/PluginManagement.js new file mode 100644 index 0000000..8d12922 --- /dev/null +++ b/lib/integration/PluginManagement.js @@ -0,0 +1,21 @@ +import authenticate from './PluginManagement/autenticate.js' +import install from './PluginManagement/install.js' +import register from './PluginManagement/register.js' +import rename from './PluginManagement/rename.js' +import schemas from './PluginManagement/schemas.js' +import search from './PluginManagement/search.js' +import uninstall from './PluginManagement/uninstall.js' +import unregister from './PluginManagement/unregister.js' +import update from './PluginManagement/update.js' + +export { + authenticate, + install, + register, + rename, + schemas, + search, + uninstall, + unregister, + update +} diff --git a/lib/integration/PluginManagement/autenticate.js b/lib/integration/PluginManagement/autenticate.js new file mode 100644 index 0000000..8ee2d8e --- /dev/null +++ b/lib/integration/PluginManagement/autenticate.js @@ -0,0 +1,56 @@ +import chalk from 'chalk' +import inquirer from 'inquirer' +import request from 'request' +import getBowerRegistryConfig from '../getBowerRegistryConfig.js' +import path from 'path' + +export default async function authenticate ({ + pluginName, + cwd = process.cwd() +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + const BOWER_REGISTRY_CONFIG = getBowerRegistryConfig({ cwd }) + // check if github, do github device oauth workflow + // if not github, send request to repo anyway + const questions = [ + { + name: 'username', + message: chalk.cyan('GitHub username') + }, + { + name: 'token', + message: chalk.cyan('GitHub personal access token (with public_repo access)'), + type: 'password', + mask: '*' + } + ] + if (!pluginName) { + questions.unshift({ + name: 'pluginName', + message: chalk.cyan('Plugin name'), + default: pluginName + }) + } + const confirmation = await inquirer.prompt(questions) + if (!pluginName) { + ({ pluginName } = confirmation) + } + const { username, token } = confirmation + return new Promise((resolve, reject) => { + request({ + uri: `${BOWER_REGISTRY_CONFIG.register}authenticate/${username}/${pluginName}?access_token=${token}`, + method: 'GET', + headers: { 'User-Agent': 'adapt-cli' }, + followRedirect: false + }, (err, res, body) => { + if (err) return reject(err) + if (res.statusCode !== 200) reject(new Error(`The server responded with ${res.statusCode}`)) + try { + const bodyJSON = JSON.parse(body) + resolve({ username, token, pluginName, ...bodyJSON }) + } catch (err) { + reject(err) + } + }) + }) +} diff --git a/lib/integration/PluginManagement/install.js b/lib/integration/PluginManagement/install.js new file mode 100644 index 0000000..a5f3be7 --- /dev/null +++ b/lib/integration/PluginManagement/install.js @@ -0,0 +1,222 @@ +import chalk from 'chalk' +import { eachOfSeries } from 'async' +import { createPromptTask } from '../../util/createPromptTask.js' +import { errorPrinter, packageNamePrinter, versionPrinter } from './print.js' +import { eachOfLimitProgress, eachOfSeriesProgress } from '../../util/promises.js' +import Project from '../Project.js' +import Target from '../Target.js' +import bower from 'bower' +import { difference } from 'lodash-es' +import path from 'path' + +export default async function install ({ + plugins, + dev = false, + isInteractive = true, + isDryRun = false, // whether to summarise installation without modifying anything + isCompatibleEnabled = false, + isClean = false, + cwd = process.cwd(), + logger = null +}) { + cwd = path.resolve(process.cwd(), cwd) + isClean && await new Promise(resolve => bower.commands.cache.clean().on('end', resolve)) + const project = new Project({ cwd, logger }) + project.tryThrowInvalidPath() + + logger?.log(chalk.cyan(`${dev ? 'cloning' : 'installing'} adapt dependencies...`)) + + const targets = await getInstallTargets({ logger, project, plugins, isCompatibleEnabled }) + if (!targets?.length) return targets + + await loadPluginData({ logger, project, targets }) + await conflictResolution({ logger, targets, isInteractive, dev }) + if (isDryRun) { + await summariseDryRun({ logger, targets }) + return targets + } + const installTargetsToBeInstalled = targets.filter(target => target.isToBeInstalled) + if (installTargetsToBeInstalled.length) { + await eachOfSeriesProgress( + installTargetsToBeInstalled, + target => target.install({ clone: dev }), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Installing plugins ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Installing plugins 100% complete`) + const manifestDependencies = await project.getManifestDependencies() + await updateManifest({ logger, project, targets, manifestDependencies, isInteractive }) + } + await summariseInstallation({ logger, targets, dev }) + return targets +} + +/** + * @param {Object} options + * @param {Project} options.project + * @param {[string]} options.plugins + */ +async function getInstallTargets ({ logger, project, plugins, isCompatibleEnabled }) { + if (typeof plugins === 'string') plugins = [plugins] + /** whether adapt.json is being used to compile the list of plugins to install */ + const isEmpty = !plugins?.length + /** a list of plugin name/version pairs */ + const itinerary = isEmpty + ? await project.getManifestDependencies() + : plugins.reduce((itinerary, arg) => { + const [name, version = '*'] = arg.split(/[#@]/) + // Duplicates are removed by assigning to object properties + itinerary[name] = version + return itinerary + }, {}) + const pluginNames = Object.entries(itinerary).map(([name, version]) => `${name}#${version}`) + + /** + * @type {[Target]} + */ + const targets = pluginNames.length + ? pluginNames.map(nameVersion => { + const [name, requestedVersion] = nameVersion.split(/[#@]/) + return new Target({ name, requestedVersion, isCompatibleEnabled, project, logger }) + }) + : await project.getInstallTargets() + return targets +} + +/** + * @param {Object} options + * @param {Project} options.project + * @param {[Target]} options.targets + */ +async function loadPluginData ({ logger, project, targets }) { + const frameworkVersion = project.version + await eachOfLimitProgress( + targets, + target => target.fetchSourceInfo(), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Getting plugin info ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Getting plugin info 100% complete`) + await eachOfLimitProgress( + targets, + target => target.findCompatibleVersion(frameworkVersion), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Finding compatible source versions ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Finding compatible source versions 100% complete`) + await eachOfLimitProgress( + targets, + target => target.markInstallable(), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Marking installable ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Marking installable 100% complete`) +} + +/** + * @param {Object} options + * @param {[Target]} options.targets + */ +async function conflictResolution ({ logger, targets, isInteractive, dev }) { + /** @param {Target} target */ + async function checkVersion (target) { + const canApplyRequested = target.hasValidRequestVersion && + (target.hasFrameworkCompatibleVersion + ? (target.latestCompatibleSourceVersion !== target.matchedVersion) + : (target.latestSourceVersion !== target.matchedVersion)) + if (!isInteractive) { + if (canApplyRequested) return target.markRequestedForInstallation() + return target.markSkipped() + } + const choices = [ + dev && { name: 'master [master]', value: 'm' }, + canApplyRequested && { name: `requested version [${target.matchedVersion}]`, value: 'r' }, + target.hasFrameworkCompatibleVersion + ? { name: `latest compatible version [${target.latestCompatibleSourceVersion}]`, value: 'l' } + : { name: `latest version [${target.latestSourceVersion}]`, value: 'l' }, + { name: 'skip', value: 's' } + ].filter(Boolean) + const result = await createPromptTask({ message: chalk.reset(target.packageName), choices, type: 'list', default: 's' }) + const installMasterBranch = (result === 'm') + const installRequested = (result === 'r') + const installLatest = result === 'l' + const skipped = result === 's' + if (installMasterBranch) target.markMasterForInstallation() + if (installRequested) target.markRequestedForInstallation() + if (installLatest && target.hasFrameworkCompatibleVersion) target.markLatestCompatibleForInstallation() + if (installLatest && !target.hasFrameworkCompatibleVersion) target.markLatestForInstallation() + if (skipped) target.markSkipped() + } + function add (list, header, prompt) { + if (!list.length) return + return { + header: chalk.cyan(' ') + header, + list, + prompt + } + } + const allQuestions = [ + add(targets.filter(target => !target.hasFrameworkCompatibleVersion), 'There is no compatible version of the following plugins:', checkVersion), + add(targets.filter(target => target.hasFrameworkCompatibleVersion && !target.hasValidRequestVersion), 'The version requested is invalid, there are newer compatible versions of the following plugins:', checkVersion), + add(targets.filter(target => target.hasFrameworkCompatibleVersion && target.hasValidRequestVersion && !target.isApplyLatestCompatibleVersion), 'There are newer compatible versions of the following plugins:', checkVersion) + ].filter(Boolean) + if (allQuestions.length === 0) return + for (const question of allQuestions) { + logger?.log(question.header) + await eachOfSeries(question.list, question.prompt) + } +} + +/** + * @param {Object} options + * @param {Project} options.project + * @param {[Target]} options.targets + */ +async function updateManifest ({ project, targets, manifestDependencies, isInteractive }) { + if (targets.filter(target => target.isInstallSuccessful).length === 0) return + if (difference(targets.filter(target => target.isInstallSuccessful).map(target => target.packageName), Object.keys(manifestDependencies)).length === 0) return + if (isInteractive) { + const shouldUpdate = await createPromptTask({ + message: chalk.white('Update the manifest (adapt.json)?'), + type: 'confirm', + default: true + }) + if (!shouldUpdate) return + } + targets.forEach(target => target.isInstallSuccessful && project.add(target)) +} + +/** + * @param {Object} options + * @param {[Target]} options.targets + */ +function summariseDryRun ({ logger, targets }) { + const toBeInstalled = targets.filter(target => target.isToBeInstalled) + const toBeSkipped = targets.filter(target => !target.isToBeInstalled || target.isSkipped) + const missing = targets.filter(target => target.isMissing) + summarise(logger, toBeSkipped, packageNamePrinter, 'The following plugins will be skipped:') + summarise(logger, missing, packageNamePrinter, 'There was a problem locating the following plugins:') + summarise(logger, toBeInstalled, versionPrinter, 'The following plugins will be installed:') +} + +/** + * @param {Object} options + * @param {[Target]} options.targets + */ +function summariseInstallation ({ logger, targets, dev }) { + const installSucceeded = targets.filter(target => target.isInstallSuccessful) + const installSkipped = targets.filter(target => !target.isToBeInstalled || target.isSkipped) + const installErrored = targets.filter(target => target.isInstallFailure) + const missing = targets.filter(target => target.isMissing) + const noneInstalled = (installSucceeded.length === 0) + const allInstalledSuccessfully = (installErrored.length === 0 && missing.length === 0) + const someInstalledSuccessfully = (!noneInstalled && !allInstalledSuccessfully) + summarise(logger, installSkipped, packageNamePrinter, 'The following plugins were skipped:') + summarise(logger, missing, packageNamePrinter, 'There was a problem locating the following plugins:') + summarise(logger, installErrored, errorPrinter, 'The following plugins could not be installed:') + if (noneInstalled) logger?.log(chalk.cyanBright('None of the requested plugins could be installed')) + else if (allInstalledSuccessfully) summarise(logger, installSucceeded, dev ? packageNamePrinter : versionPrinter, 'All requested plugins were successfully installed. Summary of installation:') + else if (someInstalledSuccessfully) summarise(logger, installSucceeded, dev ? packageNamePrinter : versionPrinter, 'The following plugins were successfully installed:') +} + +function summarise (logger, list, iterator, header) { + if (!list || !iterator || list.length === 0) return + logger?.log(chalk.cyanBright(header)) + list.forEach(item => iterator(item, logger)) +} diff --git a/lib/integration/PluginManagement/print.js b/lib/integration/PluginManagement/print.js new file mode 100644 index 0000000..b2ace82 --- /dev/null +++ b/lib/integration/PluginManagement/print.js @@ -0,0 +1,52 @@ +import chalk from 'chalk' +import semver from 'semver' +import { ADAPT_ALLOW_PRERELEASE } from '../../util/constants.js' +const semverOptions = { includePrerelease: ADAPT_ALLOW_PRERELEASE } + +function highlight (pluginname) { + return ['adapt-contrib', 'adapt-'].reduce((output, prefix) => { + if (output || !pluginname.startsWith(prefix)) return output + return chalk.reset(prefix) + chalk.yellowBright(pluginname.substring(prefix.length)) + }, null) || pluginname +} + +function greenIfEqual (v1, v2) { + if (v1 === '*') return chalk.greenBright(v2) + return semver.satisfies(v1, v2, semverOptions) + ? chalk.greenBright(v2) + : chalk.magentaBright(v2) +} + +export function versionPrinter (plugin, logger) { + const { + versionToApply, + latestCompatibleSourceVersion + } = plugin + logger?.log(highlight(plugin.packageName), latestCompatibleSourceVersion === null + ? '(no version information)' + : `${chalk.greenBright(versionToApply)}${plugin.isLocalSource ? ' (local)' : ` (latest compatible version is ${greenIfEqual(versionToApply, latestCompatibleSourceVersion)})`}` + ) +} + +export function existingVersionPrinter (plugin, logger) { + const { + preUpdateProjectVersion, + projectVersion, + latestCompatibleSourceVersion + } = plugin + const fromTo = preUpdateProjectVersion !== null + ? `from ${chalk.greenBright(preUpdateProjectVersion)} to ${chalk.greenBright(projectVersion)}` + : `${chalk.greenBright(projectVersion)}` + logger?.log(highlight(plugin.packageName), latestCompatibleSourceVersion === null + ? fromTo + : `${fromTo}${plugin.isLocalSource ? ' (local)' : ` (latest compatible version is ${greenIfEqual(projectVersion, latestCompatibleSourceVersion)})`}` + ) +} + +export function errorPrinter (plugin, logger) { + logger?.log(highlight(plugin.packageName), plugin.installError ? '(error: ' + plugin.installError + ')' : '(unknown error)') +} + +export function packageNamePrinter (plugin, logger) { + logger?.log(highlight(plugin.packageName)) +} diff --git a/lib/integration/PluginManagement/register.js b/lib/integration/PluginManagement/register.js new file mode 100644 index 0000000..879e639 --- /dev/null +++ b/lib/integration/PluginManagement/register.js @@ -0,0 +1,130 @@ + +import getBowerRegistryConfig from '../getBowerRegistryConfig.js' +import fs from 'fs-extra' +import path from 'path' +import bower from 'bower' +import chalk from 'chalk' +import inquirer from 'inquirer' +import { readValidateJSON } from '../../util/JSONReadValidate.js' +import Plugin from '../Plugin.js' +import semver from 'semver' +import { ADAPT_ALLOW_PRERELEASE } from '../../util/constants.js' +const semverOptions = { includePrerelease: ADAPT_ALLOW_PRERELEASE } + +export default async function register ({ + logger, + cwd = process.cwd() +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + const BOWER_REGISTRY_CONFIG = getBowerRegistryConfig({ cwd }) + logger?.warn('Using registry at', BOWER_REGISTRY_CONFIG.register) + try { + const bowerJSONPath = path.join(cwd, 'bower.json') + const hasBowerJSON = fs.existsSync(bowerJSONPath) + + const bowerJSON = { + name: undefined, + repository: undefined, + framework: undefined, + ...(hasBowerJSON ? await readValidateJSON(bowerJSONPath) : {}) + } + const properties = await confirm(bowerJSON) + hasBowerJSON && await fs.writeJSON(bowerJSONPath, properties, { spaces: 2, replacer: null }) + + // given a package name, create two Plugin representations + // if supplied name is adapt-contrib-myPackageName do a check against this name only + // if suppled name is adapt-myPackageName check against this name and adapt-contrib-myPackageName + // becase we don't want to allow adapt-myPackageName if adapt-contrib-myPackageName exists + const plugin = new Plugin({ name: properties.name, logger }) + const contribPlugin = new Plugin({ name: properties.name, isContrib: true, logger }) + const contribExists = await exists(BOWER_REGISTRY_CONFIG, contribPlugin) + const pluginExists = await exists(BOWER_REGISTRY_CONFIG, plugin) + + if (contribExists || pluginExists) { + logger?.warn(plugin.toString(), 'has been previously registered. Plugin names must be unique. Try again with a different name.') + return + } + + const result = await registerWithBowerRepo(BOWER_REGISTRY_CONFIG, plugin, properties.repository) + if (!result) throw new Error('The plugin was unable to register.') + logger?.log(chalk.green(plugin.packageName), 'has been registered successfully.') + } catch (err) { + logger?.error(err) + } +} + +async function confirm (properties) { + const plugin = new Plugin({ name: properties.name }) + const schema = [ + { + name: 'name', + message: chalk.cyan('name'), + validate: v => { + return /^adapt-[\w|-]+?$/.test(v) || + 'Name must prefixed with \'adapt\' and each word separated with a hyphen(-)' + }, + type: 'input', + default: plugin.toString() || 'not specified' + }, + { + name: 'repositoryUrl', + message: chalk.cyan('repository URL'), + validate: v => { + return /https:\/\/([\w.@:/\-~]+)(\.git)(\/)?/.test(v) || + 'Please provide a repository URL of the form https://.git' + }, + type: 'input', + default: properties.repository ? properties.repository.url : undefined + }, + { + name: 'framework', + message: chalk.cyan('framework'), + validate: v => { + return semver.validRange(v, semverOptions) !== null || + 'Please provide a valid semver (see https://semver.org/)' + }, + type: 'input', + default: properties.framework || '>=5.15' + }, + { + name: 'ready', + message: chalk.cyan('Register now?'), + type: 'confirm', + default: true + } + ] + const confirmation = await inquirer.prompt(schema) + if (!confirmation.ready) throw new Error('Aborted. Nothing has been registered.') + properties.name = confirmation.name + properties.repository = { type: 'git', url: confirmation.repositoryUrl } + properties.framework = confirmation.framework + return properties +} + +/** + * @param {Plugin} plugin + * @returns {boolean} + */ +async function exists (BOWER_REGISTRY_CONFIG, plugin) { + const pluginName = plugin.toString().toLowerCase() + return new Promise((resolve, reject) => { + bower.commands.search(pluginName, { + registry: BOWER_REGISTRY_CONFIG.register + }) + .on('end', result => { + const matches = result.filter(({ name }) => name.toLowerCase() === pluginName) + resolve(Boolean(matches.length)) + }) + .on('error', reject) + }) +} + +async function registerWithBowerRepo (BOWER_REGISTRY_CONFIG, plugin, repository) { + return new Promise((resolve, reject) => { + bower.commands.register(plugin.toString(), repository.url || repository, { + registry: BOWER_REGISTRY_CONFIG + }) + .on('end', resolve) + .on('error', reject) + }) +} diff --git a/lib/integration/PluginManagement/rename.js b/lib/integration/PluginManagement/rename.js new file mode 100644 index 0000000..2869313 --- /dev/null +++ b/lib/integration/PluginManagement/rename.js @@ -0,0 +1,101 @@ +import getBowerRegistryConfig from '../getBowerRegistryConfig.js' +import authenticate from './autenticate.js' +import bower from 'bower' +import chalk from 'chalk' +import inquirer from 'inquirer' +import request from 'request' +import path from 'path' +import Plugin from '../Plugin.js' + +export default async function rename ({ + logger, + oldName, + newName, + cwd = process.cwd() +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + const BOWER_REGISTRY_CONFIG = getBowerRegistryConfig({ cwd }) + if (!oldName || !newName) { + logger?.error('You must call rename with the following arguments: ') + return + } + // use Plugin to standardise name + newName = new Plugin({ name: newName, logger }).packageName + oldName = new Plugin({ name: oldName, logger }).packageName + logger?.warn('Using registry at', BOWER_REGISTRY_CONFIG.register) + logger?.warn(`Plugin will be renamed from ${oldName} to ${newName}`) + try { + const oldExists = await exists(BOWER_REGISTRY_CONFIG, oldName) + if (!oldExists) throw new Error(`Plugin "${oldName}" does not exist`) + const newExists = await exists(BOWER_REGISTRY_CONFIG, newName) + if (newExists) throw new Error(`Name "${newName}" already exists`) + const { username, token, type } = await authenticate({ pluginName: oldName }) + logger?.log(`${username} authenticated as ${type}`) + await confirm() + await renameInBowerRepo({ + username, + token, + oldName, + newName, + BOWER_REGISTRY_CONFIG + }) + logger?.log(chalk.green('The plugin was successfully renamed.')) + } catch (err) { + logger?.error(err) + logger?.error('The plugin was not renamed.') + } +} + +async function confirm () { + const schema = [ + { + name: 'ready', + message: chalk.cyan('Confirm rename now?'), + type: 'confirm', + default: true + } + ] + const confirmation = await inquirer.prompt(schema) + if (!confirmation.ready) throw new Error('Aborted. Nothing has been renamed.') +} + +async function renameInBowerRepo ({ + username, + token, + oldName, + newName, + BOWER_REGISTRY_CONFIG +}) { + const path = 'packages/rename/' + username + '/' + oldName + '/' + newName + const query = '?access_token=' + token + return new Promise((resolve, reject) => { + request({ + url: BOWER_REGISTRY_CONFIG.register + path + query, + method: 'GET', + headers: { 'User-Agent': 'adapt-cli' }, + followRedirect: false + }, (err, res) => { + if (err) return reject(err) + if (res.statusCode !== 201) reject(new Error(`The server responded with ${res.statusCode}`)) + resolve() + }) + }) +} + +/** + * @param {Plugin} plugin + * @returns {boolean} + */ +async function exists (BOWER_REGISTRY_CONFIG, plugin) { + const pluginName = plugin.toString().toLowerCase() + return new Promise((resolve, reject) => { + bower.commands.search(pluginName, { + registry: BOWER_REGISTRY_CONFIG.register + }) + .on('end', result => { + const matches = result.filter(({ name }) => name.toLowerCase() === pluginName) + resolve(Boolean(matches.length)) + }) + .on('error', reject) + }) +} diff --git a/lib/integration/PluginManagement/schemas.js b/lib/integration/PluginManagement/schemas.js new file mode 100644 index 0000000..87895a8 --- /dev/null +++ b/lib/integration/PluginManagement/schemas.js @@ -0,0 +1,8 @@ +import Project from '../Project.js' +import path from 'path' + +export default async function schemas ({ cwd = process.cwd() } = {}) { + cwd = path.resolve(process.cwd(), cwd) + const project = new Project({ cwd }) + return await project.getSchemaPaths({ cwd }) +} diff --git a/lib/integration/PluginManagement/search.js b/lib/integration/PluginManagement/search.js new file mode 100644 index 0000000..c9b238d --- /dev/null +++ b/lib/integration/PluginManagement/search.js @@ -0,0 +1,46 @@ +import getBowerRegistryConfig from '../getBowerRegistryConfig.js' +import chalk from 'chalk' +import request from 'request' +import path from 'path' + +export default async function search ({ + logger, + searchTerm, + cwd = process.cwd() +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + const BOWER_REGISTRY_CONFIG = getBowerRegistryConfig({ cwd }) + try { + const uniqueResults = {} + for (const serverURI of BOWER_REGISTRY_CONFIG.search) { + try { + const immediateResults = await new Promise((resolve, reject) => { + request({ + uri: `${serverURI}packages/search/${searchTerm}`, + method: 'GET', + headers: { 'User-Agent': 'adapt-cli' }, + followRedirect: false + }, (err, res, body) => { + if (err) return reject(err) + if (res.statusCode !== 200) reject(new Error(`The server responded with ${res.statusCode}`)) + try { + resolve(JSON.parse(body)) + } catch (err) { + reject(err) + } + }) + }) + immediateResults?.forEach(result => (uniqueResults[result.name] = uniqueResults[result.name] ?? result)) + } catch (err) {} + } + const results = Object.values(uniqueResults) + if (!results.length) { + logger?.warn(`no plugins found containing: ${searchTerm}`) + } + results.forEach(function (result) { + logger?.log(chalk.cyan(result.name) + ' ' + result.url) + }) + } catch (err) { + logger?.error("Oh dear, something went wrong. I'm terribly sorry.", err) + } +} diff --git a/lib/integration/PluginManagement/uninstall.js b/lib/integration/PluginManagement/uninstall.js new file mode 100644 index 0000000..69a6bb8 --- /dev/null +++ b/lib/integration/PluginManagement/uninstall.js @@ -0,0 +1,141 @@ + +import chalk from 'chalk' +import Project from '../Project.js' +import Target from '../Target.js' +import { eachOfLimitProgress } from '../../util/promises.js' +import { createPromptTask } from '../../util/createPromptTask.js' +import { errorPrinter, packageNamePrinter } from './print.js' +import { intersection } from 'lodash-es' +import path from 'path' + +export default async function uninstall ({ + plugins, + isInteractive = true, + cwd = process.cwd(), + logger = null +}) { + cwd = path.resolve(process.cwd(), cwd) + const project = new Project({ cwd, logger }) + project.tryThrowInvalidPath() + + logger?.log(chalk.cyan('uninstalling adapt dependencies...')) + + const targets = await getUninstallTargets({ logger, project, plugins, isInteractive }) + if (!targets?.length) return targets + + await loadPluginData({ logger, targets }) + await eachOfLimitProgress( + targets.filter(target => target.isToBeUninstalled), + target => target.uninstall(), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Uninstalling plugins ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Uninstalling plugins 100% complete`) + const installedDependencies = await project.getInstalledDependencies() + await updateManifest({ project, targets, installedDependencies, isInteractive }) + await summariseUninstallation({ logger, targets }) + return targets +} + +/** + * @param {Object} options + * @param {Project} options.project + * @param {[Target]} options.targets + */ +async function getUninstallTargets ({ logger, project, plugins, isInteractive }) { + if (typeof plugins === 'string') plugins = [plugins] + /** whether adapt.json is being used to compile the list of targets to install */ + const isEmpty = !plugins?.length + if (isEmpty && isInteractive) { + const shouldContinue = await createPromptTask({ + message: chalk.reset('This command will attempt to uninstall all installed plugins. Do you wish to continue?'), + type: 'confirm' + }) + if (!shouldContinue) return + } + + /** a list of plugin name/version pairs */ + const itinerary = isEmpty + ? await project.getInstalledDependencies() + : plugins.reduce((itinerary, arg) => { + const [name, version = '*'] = arg.split(/[#@]/) + // Duplicates are removed by assigning to object properties + itinerary[name] = version + return itinerary + }, {}) + const pluginNames = Object.entries(itinerary).map(([name, version]) => `${name}@${version}`) + + /** @type {[Target]} */ + const targets = pluginNames + ? pluginNames.map(nameVersion => { + const [name] = nameVersion.split(/[#@]/) + return new Target({ name, project, logger }) + }) + : await project.getUninstallTargets() + return targets +} + +/** + * @param {Object} options + * @param {Project} options.project + * @param {[Target]} options.targets + */ +async function loadPluginData ({ logger, targets }) { + await eachOfLimitProgress( + targets, + target => target.fetchProjectInfo(), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Getting plugin info ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Getting plugin info 100% complete`) + await eachOfLimitProgress( + targets, + target => target.markUninstallable(), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Marking uninstallable ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Marking uninstallable 100% complete`) +} + +/** + * @param {Object} options + * @param {Project} options.project + * @param {[Target]} options.targets + * @returns + */ +async function updateManifest ({ project, targets, installedDependencies, isInteractive }) { + if (targets.filter(target => target.isToBeUninstalled).length === 0) return + if (intersection(Object.keys(installedDependencies), targets.map(target => target.packageName)).length) return + if (isInteractive) { + const shouldUpdate = await createPromptTask({ + message: chalk.white('Update the manifest (adapt.json)?'), + type: 'confirm', + default: true + }) + if (!shouldUpdate) return + } + targets.forEach(target => target.isToBeUninstalled && project.remove(target)) +} + +/** + * @param {Object} options + * @param {[Target]} options.targets + */ +function summariseUninstallation ({ logger, targets }) { + const uninstallSucceeded = targets.filter(target => target.isUninstallSuccessful) + const uninstallSkipped = targets.filter(target => !target.isToBeUninstalled || target.isSkipped) + const uninstallErrored = targets.filter(target => target.isUninstallFailure) + const missing = targets.filter(target => target.isMissing) + const noneUninstalled = (uninstallSucceeded.length === 0) + const allUninstalledSuccessfully = (uninstallErrored.length === 0 && missing.length === 0) + const someUninstalledSuccessfully = (!noneUninstalled && !allUninstalledSuccessfully) + summarise(logger, uninstallSkipped, packageNamePrinter, 'The following plugins were skipped:') + summarise(logger, missing, packageNamePrinter, 'There was a problem locating the following plugins:') + summarise(logger, uninstallErrored, errorPrinter, 'The following plugins could not be uninstalled:') + if (noneUninstalled) logger?.log(chalk.cyanBright('None of the requested plugins could be uninstalled')) + else if (allUninstalledSuccessfully) summarise(logger, uninstallSucceeded, packageNamePrinter, 'All requested plugins were successfully uninstalled. Summary of uninstallation:') + else if (someUninstalledSuccessfully) summarise(logger, uninstallSucceeded, packageNamePrinter, 'The following plugins were successfully uninstalled:') +} + +function summarise (logger, list, iterator, header) { + if (!list || !iterator || list.length === 0) return + logger?.log(chalk.cyanBright(header)) + list.forEach(item => iterator(item, logger)) +} diff --git a/lib/integration/PluginManagement/unregister.js b/lib/integration/PluginManagement/unregister.js new file mode 100644 index 0000000..e40c7ea --- /dev/null +++ b/lib/integration/PluginManagement/unregister.js @@ -0,0 +1,101 @@ +import getBowerRegistryConfig from '../getBowerRegistryConfig.js' +import authenticate from './autenticate.js' +import fs from 'fs-extra' +import path from 'path' +import chalk from 'chalk' +import inquirer from 'inquirer' +import { readValidateJSON } from '../../util/JSONReadValidate.js' +import Plugin from '../Plugin.js' +import request from 'request' + +export default async function unregister ({ + logger, + cwd = process.cwd(), + pluginName +} = {}) { + cwd = path.resolve(process.cwd(), cwd) + const BOWER_REGISTRY_CONFIG = getBowerRegistryConfig({ cwd }) + logger?.warn('Using registry at', BOWER_REGISTRY_CONFIG.register) + try { + const bowerJSONPath = path.join(cwd, 'bower.json') + const hasBowerJSON = fs.existsSync(bowerJSONPath) + const bowerJSON = hasBowerJSON ? await readValidateJSON(bowerJSONPath) : {} + if (pluginName) bowerJSON.name = pluginName + const props = await confirm(bowerJSON) + pluginName = props.pluginName + const repository = props.repository + const { username, token, type } = await authenticate({ repository, pluginName }) + logger?.log(`${username} authenticated as ${type}`) + await finalConfirm() + await unregisterInBowerRepo({ pluginName, username, token, BOWER_REGISTRY_CONFIG }) + logger?.log(chalk.green('The plugin was successfully unregistered.')) + } catch (err) { + logger?.error(err) + logger?.log('The plugin was not unregistered.') + } +} + +async function confirm (properties) { + const plugin = new Plugin({ name: properties.name }) + const schema = [ + { + name: 'pluginName', + message: chalk.cyan('name'), + validate: v => { + return /^adapt-[\w|-]+?$/.test(v) || + 'Name must prefixed with \'adapt\' and each word separated with a hyphen(-)' + }, + type: 'input', + default: plugin.toString() || 'not specified' + }, + { + name: 'repository', + message: chalk.cyan('repository URL'), + validate: v => { + return /https:\/\/([\w.@:/\-~]+)(\.git)(\/)?/.test(v) || + 'Please provide a repository URL of the form https://.git' + }, + type: 'input', + default: properties.repository ? properties.repository.url : undefined + } + ] + return await inquirer.prompt(schema) +} + +async function finalConfirm () { + const schema = [ + { + name: 'ready', + message: chalk.cyan('Confirm Unregister now?'), + type: 'confirm', + default: true + } + ] + const confirmation = await inquirer.prompt(schema) + if (!confirmation.ready) throw new Error('Aborted. Nothing has been unregistered.') +} + +async function unregisterInBowerRepo ({ + pluginName, + username, + token, + BOWER_REGISTRY_CONFIG +}) { + const uri = `${BOWER_REGISTRY_CONFIG.register}packages/${username}/${pluginName}?access_token=${token}` + return new Promise((resolve, reject) => { + request({ + uri, + method: 'DELETE', + headers: { 'User-Agent': 'adapt-cli' }, + followRedirect: false + }, (err, res, body) => { + if (err) return reject(err) + if (res.statusCode !== 204) reject(new Error(`The server responded with ${res.statusCode}`)) + try { + resolve() + } catch (err) { + reject(err) + } + }) + }) +} diff --git a/lib/integration/PluginManagement/update.js b/lib/integration/PluginManagement/update.js new file mode 100644 index 0000000..c89df22 --- /dev/null +++ b/lib/integration/PluginManagement/update.js @@ -0,0 +1,224 @@ +import chalk from 'chalk' +import { eachOfSeries } from 'async' +import path from 'path' +import Project from '../Project.js' +import { createPromptTask } from '../../util/createPromptTask.js' +import { errorPrinter, packageNamePrinter, versionPrinter, existingVersionPrinter } from './print.js' +import { eachOfLimitProgress, eachOfSeriesProgress } from '../../util/promises.js' +/** @typedef {import("../Target.js").default} Target */ + +export default async function update ({ + plugins, + // whether to summarise installed plugins without modifying anything + isDryRun = false, + isInteractive = true, + cwd = process.cwd(), + logger = null +}) { + cwd = path.resolve(process.cwd(), cwd) + const project = new Project({ cwd, logger }) + project.tryThrowInvalidPath() + + logger?.log(chalk.cyan('update adapt dependencies...')) + + const targets = await getUpdateTargets({ logger, project, plugins, isDryRun, isInteractive }) + if (!targets?.length) return targets + + await loadPluginData({ logger, project, targets }) + await conflictResolution({ logger, targets, isInteractive }) + if (isDryRun) { + await summariseDryRun({ logger, targets }) + return targets + } + const updateTargetsToBeUpdated = targets.filter(target => target.isToBeInstalled) + if (updateTargetsToBeUpdated.length) { + await eachOfSeriesProgress( + updateTargetsToBeUpdated, + target => target.update(), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Updating plugins ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Updating plugins 100% complete`) + } + await summariseUpdates({ logger, targets }) + return targets +} + +/** + * @param {Object} options + * @param {Project} options.project + * @param {[string]} options.plugins + */ +async function getUpdateTargets ({ project, plugins, isDryRun, isInteractive }) { + if (typeof plugins === 'string') plugins = [plugins] + if (!plugins) plugins = [] + const allowedTypes = ['all', 'components', 'extensions', 'menu', 'theme'] + const selectedTypes = [...new Set(plugins.filter(type => allowedTypes.includes(type)))] + const isEmpty = (!plugins.length) + const isAll = (isDryRun || isEmpty || selectedTypes.includes('all')) + const pluginNames = plugins + // remove types + .filter(arg => !allowedTypes.includes(arg)) + // split name/version + .map(arg => { + const [name, version = '*'] = arg.split(/[#@]/) + return [name, version] + }) + // make sure last applies + .reverse() + + /** @type {[Target]} */ + let targets = await project.getUpdateTargets() + for (const target of targets) { + await target.fetchProjectInfo() + } + if (!isDryRun && isEmpty && isInteractive) { + const shouldContinue = await createPromptTask({ + message: chalk.reset('This command will attempt to update all installed plugins. Do you wish to continue?'), + type: 'confirm' + }) + if (!shouldContinue) return + } + if (!isAll) { + const filtered = {} + for (const target of targets) { + const typeFolder = await target.getTypeFolder() + if (!typeFolder) continue + const lastSpecifiedPluginName = pluginNames.find(([name]) => target.isNameMatch(name)) + const isPluginNameIncluded = Boolean(lastSpecifiedPluginName) + const isTypeIncluded = selectedTypes.includes(typeFolder) + if (!isPluginNameIncluded && !isTypeIncluded) continue + // Resolve duplicates + filtered[target.packageName] = target + // Set requested version from name + target.requestedVersion = lastSpecifiedPluginName[1] || '*' + } + targets = Object.values(filtered) + } + return targets +} + +/** + * @param {Object} options + * @param {Project} options.project + * @param {[Target]} options.targets + */ +async function loadPluginData ({ logger, project, targets }) { + const frameworkVersion = project.version + await eachOfLimitProgress( + targets, + target => target.fetchSourceInfo(), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Getting plugin info ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Getting plugin info 100% complete`) + await eachOfLimitProgress( + targets, + target => target.findCompatibleVersion(frameworkVersion), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Finding compatible source versions ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Finding compatible source versions 100% complete`) + await eachOfLimitProgress( + targets, + target => target.markUpdateable(), + percentage => logger?.logProgress?.(`${chalk.bold.cyan('')} Marking updateable ${percentage}% complete`) + ) + logger?.log(`${chalk.bold.cyan('')} Marking updateable 100% complete`) +} + +/** + * @param {Object} options + * @param {[Target]} options.targets + */ +async function conflictResolution ({ logger, targets, isInteractive }) { + /** @param {Target} target */ + async function checkVersion (target) { + const canApplyRequested = target.hasValidRequestVersion && + (target.hasFrameworkCompatibleVersion + ? (target.latestCompatibleSourceVersion !== target.matchedVersion) + : (target.latestSourceVersion !== target.matchedVersion)) + if (!isInteractive) { + if (target.canApplyRequested) return target.markRequestedForInstallation() + return target.markSkipped() + } + const choices = [ + canApplyRequested && { name: `requested version [${target.matchedVersion}]`, value: 'r' }, + target.hasFrameworkCompatibleVersion + ? { name: `latest compatible version [${target.latestCompatibleSourceVersion}]`, value: 'l' } + : { name: `latest version [${target.latestSourceVersion}]`, value: 'l' }, + { name: 'skip', value: 's' } + ].filter(Boolean) + const result = await createPromptTask({ message: chalk.reset(target.packageName), choices, type: 'list', default: 's' }) + const installRequested = (result === 'r') + const installLatest = result === 'l' + const skipped = result === 's' + if (installRequested) target.markRequestedForInstallation() + if (installLatest && target.hasFrameworkCompatibleVersion) target.markLatestCompatibleForInstallation() + if (installLatest && !target.hasFrameworkCompatibleVersion) target.markLatestForInstallation() + if (skipped) target.markSkipped() + } + function add (list, header, prompt) { + if (!list.length) return + return { + header: chalk.bold.cyan(' ') + header, + list, + prompt + } + } + const preFilteredPlugins = targets.filter(target => !target.isLocalSource) + const allQuestions = [ + add(preFilteredPlugins.filter(target => !target.hasFrameworkCompatibleVersion), 'There is no compatible version of the following plugins:', checkVersion), + add(preFilteredPlugins.filter(target => target.hasFrameworkCompatibleVersion && !target.hasValidRequestVersion), 'The version requested is invalid, there are newer compatible versions of the following plugins:', checkVersion), + add(preFilteredPlugins.filter(target => target.hasFrameworkCompatibleVersion && target.hasValidRequestVersion && !target.isApplyLatestCompatibleVersion), 'There are newer compatible versions of the following plugins:', checkVersion) + ].filter(Boolean) + if (allQuestions.length === 0) return + for (const question of allQuestions) { + logger?.log(question.header) + await eachOfSeries(question.list, question.prompt) + } +} + +/** + * @param {Object} options + * @param {[Target]} options.targets + */ +function summariseDryRun ({ logger, targets }) { + const preFilteredPlugins = targets.filter(target => !target.isLocalSource) + const localSources = targets.filter(target => target.isLocalSource) + const toBeInstalled = preFilteredPlugins.filter(target => target.isToBeUpdated) + const toBeSkipped = preFilteredPlugins.filter(target => !target.isToBeUpdated || target.isSkipped) + const missing = preFilteredPlugins.filter(target => target.isMissing) + summarise(logger, localSources, packageNamePrinter, 'The following plugins were installed from a local source and cannot be updated:') + summarise(logger, toBeSkipped, packageNamePrinter, 'The following plugins will be skipped:') + summarise(logger, missing, packageNamePrinter, 'There was a problem locating the following plugins:') + summarise(logger, toBeInstalled, versionPrinter, 'The following plugins will be updated:') +} + +/** + * @param {Object} options + * @param {[Target]} options.targets + */ +function summariseUpdates ({ logger, targets }) { + const preFilteredPlugins = targets.filter(target => !target.isLocalSource) + const localSources = targets.filter(target => target.isLocalSource) + const installSucceeded = preFilteredPlugins.filter(target => target.isUpdateSuccessful) + const installSkipped = preFilteredPlugins.filter(target => target.isSkipped) + const noUpdateAvailable = preFilteredPlugins.filter(target => !target.isToBeUpdated && !target.isSkipped) + const installErrored = preFilteredPlugins.filter(target => target.isUpdateFailure) + const missing = preFilteredPlugins.filter(target => target.isMissing) + const noneInstalled = (installSucceeded.length === 0) + const allInstalledSuccessfully = (installErrored.length === 0 && missing.length === 0) + const someInstalledSuccessfully = (!noneInstalled && !allInstalledSuccessfully) + summarise(logger, localSources, existingVersionPrinter, 'The following plugins were installed from a local source and cannot be updated:') + summarise(logger, installSkipped, existingVersionPrinter, 'The following plugins were skipped:') + summarise(logger, noUpdateAvailable, existingVersionPrinter, 'The following plugins had no update available:') + summarise(logger, missing, packageNamePrinter, 'There was a problem locating the following plugins:') + summarise(logger, installErrored, errorPrinter, 'The following plugins could not be updated:') + if (noneInstalled) logger?.log(chalk.cyanBright('None of the requested plugins could be updated')) + else if (allInstalledSuccessfully) summarise(logger, installSucceeded, existingVersionPrinter, 'All requested plugins were successfully updated. Summary of installation:') + else if (someInstalledSuccessfully) summarise(logger, installSucceeded, existingVersionPrinter, 'The following plugins were successfully updated:') +} + +function summarise (logger, list, iterator, header) { + if (!list || !iterator || list.length === 0) return + logger?.log(chalk.cyanBright(header)) + list.forEach(item => iterator(item, logger)) +} diff --git a/lib/integration/Project.js b/lib/integration/Project.js new file mode 100644 index 0000000..528f4e0 --- /dev/null +++ b/lib/integration/Project.js @@ -0,0 +1,146 @@ +import fs from 'fs-extra' +import path from 'path' +import globs from 'globs' +import { readValidateJSON, readValidateJSONSync } from '../util/JSONReadValidate.js' +import Plugin from './Plugin.js' +import Target from './Target.js' +export const MANIFEST_FILENAME = 'adapt.json' +export const FRAMEWORK_FILENAME = 'package.json' + +/** + * A representation of the target Adapt Framework project + */ +export default class Project { + constructor ({ + cwd = process.cwd(), + logger + } = {}) { + this.logger = logger + this.cwd = cwd + this.manifestFilePath = path.resolve(this.cwd, MANIFEST_FILENAME) + this.frameworkPackagePath = path.resolve(this.cwd, FRAMEWORK_FILENAME) + } + + /** @returns {boolean} */ + get isAdaptDirectory () { + try { + // are we inside an existing adapt_framework project. + const packageJSON = fs.readJSONSync(this.cwd + '/package.json') + return (packageJSON.name === 'adapt_framework') + } catch (err) { + // don't worry, we're not inside a framework directory. + } + return false + } + + /** @returns {boolean} */ + get containsManifestFile () { + if (!this.isAdaptDirectory) return false + return fs.existsSync(this.manifestFilePath) + } + + /** @returns {string} */ + get version () { + try { + return readValidateJSONSync(this.frameworkPackagePath).version + } catch (ex) { + return null + } + } + + tryThrowInvalidPath () { + if (this.containsManifestFile) return + this.logger?.error('Fatal error: please run above commands in adapt course directory.') + throw new Error('Fatal error: please run above commands in adapt course directory.') + } + + /** @returns {[Target]} */ + async getInstallTargets () { + return Object.entries(await this.getManifestDependencies()).map(([name, requestedVersion]) => new Target({ name, requestedVersion, project: this, logger: this.logger })) + } + + /** @returns {[string]} */ + async getManifestDependencies () { + const manifest = await readValidateJSON(this.manifestFilePath) + return manifest.dependencies + } + + /** @returns {[Plugin]} */ + async getInstalledPlugins () { + return Object.entries(await this.getInstalledDependencies()).map(([name]) => new Plugin({ name, project: this, logger: this.logger })) + } + + /** @returns {[Target]} */ + async getUninstallTargets () { + return Object.entries(await this.getInstalledDependencies()).map(([name]) => new Target({ name, project: this, logger: this.logger })) + } + + /** @returns {[Target]} */ + async getUpdateTargets () { + return Object.entries(await this.getInstalledDependencies()).map(([name]) => new Target({ name, project: this, logger: this.logger })) + } + + async getInstalledDependencies () { + const getDependencyBowerJSONs = async () => { + const glob = `${this.cwd.replace(/\\/g, '/')}/src/**/bower.json` + const bowerJSONPaths = await new Promise((resolve, reject) => { + globs(glob, (err, matches) => { + if (err) return reject(err) + resolve(matches) + }) + }) + const bowerJSONs = [] + for (const bowerJSONPath of bowerJSONPaths) { + try { + bowerJSONs.push(await fs.readJSON(bowerJSONPath)) + } catch (err) {} + } + return bowerJSONs + } + const dependencies = (await getDependencyBowerJSONs()) + .filter(bowerJSON => bowerJSON?.name && bowerJSON?.version) + .reduce((dependencies, bowerJSON) => { + dependencies[bowerJSON.name] = bowerJSON.version + return dependencies + }, {}) + return dependencies + } + + async getSchemaPaths () { + const glob = `${this.cwd.replace(/\\/g, '/')}/src/**/*.schema.json` + const bowerJSONPaths = await new Promise((resolve, reject) => { + globs(glob, (err, matches) => { + if (err) return reject(err) + resolve(matches) + }) + }) + return bowerJSONPaths + } + + /** + * @param {Plugin} plugin + */ + add (plugin) { + if (typeof Plugin !== 'object' && !(plugin instanceof Plugin)) { + plugin = new Plugin({ name: plugin }) + } + let manifest = { version: '0.0.0', dependencies: {} } + if (this.containsManifestFile) { + manifest = readValidateJSONSync(this.manifestFilePath) + } + manifest.dependencies[plugin.packageName] = plugin.sourcePath || plugin.requestedVersion || plugin.version + fs.writeJSONSync(this.manifestFilePath, manifest, { spaces: 2, replacer: null }) + } + + /** + * @param {Plugin} plugin + */ + remove (plugin) { + if (typeof Plugin !== 'object' && !(plugin instanceof Plugin)) { + plugin = new Plugin({ name: plugin }) + } + const manifest = readValidateJSONSync(this.manifestFilePath) + delete manifest.dependencies[plugin.packageName] + fs.writeJSONSync(this.manifestFilePath, manifest, { spaces: 2, replacer: null }) + } +} diff --git a/lib/integration/Target.js b/lib/integration/Target.js new file mode 100644 index 0000000..ade01bb --- /dev/null +++ b/lib/integration/Target.js @@ -0,0 +1,296 @@ +import chalk from 'chalk' +import bower from 'bower' +import { exec } from 'child_process' +import semver from 'semver' +import fs from 'fs-extra' +import path from 'path' +import { ADAPT_ALLOW_PRERELEASE } from '../util/constants.js' +import Plugin from './Plugin.js' +/** @typedef {import("./Project.js").default} Project */ +const semverOptions = { includePrerelease: ADAPT_ALLOW_PRERELEASE } + +export default class Target extends Plugin { + /** + * @param {Object} options + * @param {string} options.name + * @param {string} options.requestedVersion + * @param {boolean} options.isContrib + * @param {boolean} options.isCompatibleEnabled whether to target the latest compatible version for all plugin installations (overrides requestedVersion) + * @param {Project} options.project + * @param {string} options.cwd + * @param {Object} options.logger + */ + constructor ({ + name, + requestedVersion = '*', + isContrib = false, + isCompatibleEnabled = false, + project, + cwd = (project?.cwd ?? process.cwd()), + logger + } = {}) { + super({ + name, + requestedVersion, + isContrib, + isCompatibleEnabled, + project, + cwd, + logger + }) + // The version to be installed + this.versionToApply = null + // Keep the project version preupdate + this.preUpdateProjectVersion = null + // Was explicitly skipped by the user + this._isSkipped = null + // Marks that this target was uninstalled, true, false and null + this._wasUninstalled = null + } + + /** + * Was explicitly skipped by the user + * @returns {boolean} + */ + get isSkipped () { + return Boolean(this._isSkipped) + } + + get isNoApply () { + return (this.isPresent && this.versionToApply === null) + } + + /** @returns {boolean} */ + get hasProposedVersion () { + return (this.matchedVersion !== null) + } + + /** @returns {boolean} */ + get isToBeInstalled () { + return (this.versionToApply !== null && !this._isSkipped) + } + + /** @returns {boolean} */ + get isInstallSuccessful () { + return (this.isToBeInstalled && this.isUpToDate) + } + + /** @returns {boolean} */ + get isInstallFailure () { + return (this.isToBeInstalled && !this.isUpToDate) + } + + /** @returns {boolean} */ + get isToBeUninstalled () { + return (this.versionToApply !== null && !this._isSkipped) + } + + /** @returns {boolean} */ + get isUninstallSuccessful () { + return (this.isToBeUninstalled && this._wasUninstalled) + } + + /** @returns {boolean} */ + get isUninstallFailure () { + return (this.isToBeUninstalled && !this._wasUninstalled) + } + + /** @returns {boolean} */ + get isToBeUpdated () { + return (this.versionToApply !== null && !this._isSkipped) + } + + /** @returns {boolean} */ + get isUpdateSuccessful () { + return (this.isToBeUpdated && this.isUpToDate) + } + + /** @returns {boolean} */ + get isUpdateFailure () { + return (this.isToBeUpdated && !this.isUpToDate) + } + + /** @returns {boolean} */ + get isApplyLatestCompatibleVersion () { + return (this.hasFrameworkCompatibleVersion && + semver.satisfies(this.latestCompatibleSourceVersion, this.matchedVersion, semverOptions)) + } + + markSkipped () { + this._isSkipped = true + } + + markInstallable () { + if (!this.isApplyLatestCompatibleVersion && !(this.isLocalSource && this.latestSourceVersion)) return + this.versionToApply = this.matchedVersion + } + + markUpdateable () { + if (!this.isPresent || this.isSkipped || !this.canBeUpdated) return + if (this.projectVersion === this.matchedVersion) return + this.versionToApply = this.matchedVersion + } + + markMasterForInstallation () { + this.versionToApply = '*' + } + + markRequestedForInstallation () { + this.matchedVersion = this.matchedVersion ?? semver.maxSatisfying(this.sourceVersions, this.requestedVersion, semverOptions) + if (this.projectVersion === this.matchedVersion) return + this.versionToApply = this.matchedVersion + } + + markLatestCompatibleForInstallation () { + if (this.projectVersion === this.latestCompatibleSourceVersion) return + this.versionToApply = this.latestCompatibleSourceVersion + } + + markLatestForInstallation () { + if (this.projectVersion === this.latestSourceVersion) return + this.versionToApply = this.latestSourceVersion + } + + markUninstallable () { + if (!this.isPresent) return + this.versionToApply = this.projectVersion + } + + async install ({ clone = false } = {}) { + const logger = this.logger + const pluginTypeFolder = await this.getTypeFolder() + if (this.isLocalSource) { + await fs.ensureDir(path.resolve(this.cwd, 'src', pluginTypeFolder)) + const pluginPath = path.resolve(this.cwd, 'src', pluginTypeFolder, this.name) + await fs.rm(pluginPath, { recursive: true, force: true }) + await fs.copy(this.sourcePath, pluginPath, { recursive: true }) + const bowerJSON = await fs.readJSON(path.join(pluginPath, 'bower.json')) + bowerJSON._source = this.sourcePath + bowerJSON._wasInstalledFromPath = true + await fs.writeJSON(path.join(pluginPath, '.bower.json'), bowerJSON, { spaces: 2, replacer: null }) + this._projectInfo = null + await this.fetchProjectInfo() + return + } + if (clone) { + // clone install + const repoDetails = await this.getRepositoryUrl() + if (!repoDetails) throw new Error('Error: Plugin repository url could not be found.') + await fs.ensureDir(path.resolve(this.cwd, 'src', pluginTypeFolder)) + const pluginPath = path.resolve(this.cwd, 'src', pluginTypeFolder, this.name) + await fs.rm(pluginPath, { recursive: true, force: true }) + const url = repoDetails.url.replace(/^git:\/\//, 'https://') + try { + const exitCode = await new Promise((resolve, reject) => { + try { + exec(`git clone ${url} "${pluginPath}"`, resolve) + } catch (err) { + reject(err) + } + }) + if (exitCode) throw new Error(`The plugin was found but failed to download and install. Exit code ${exitCode}`) + } catch (error) { + throw new Error(`The plugin was found but failed to download and install. Error ${error}`) + } + if (this.versionToApply !== '*') { + try { + await new Promise(resolve => exec(`git -C "${pluginPath}" checkout v${this.versionToApply}`, resolve)) + logger?.log(chalk.green(this.packageName), `is on branch "${this.versionToApply}".`) + } catch (err) { + throw new Error(chalk.yellow(this.packageName), `could not checkout branch "${this.versionToApply}".`) + } + } + this._projectInfo = null + await this.fetchProjectInfo() + return + } + // bower install + const outputPath = path.join(this.cwd, 'src', pluginTypeFolder) + const pluginPath = path.join(outputPath, this.name) + try { + await fs.rm(pluginPath, { recursive: true, force: true }) + } catch (err) { + throw new Error(`There was a problem writing to the target directory ${pluginPath}`) + } + await new Promise((resolve, reject) => { + const pluginNameVersion = `${this.packageName}@${this.versionToApply}` + bower.commands.install([pluginNameVersion], null, { + directory: outputPath, + cwd: this.cwd, + registry: this.BOWER_REGISTRY_CONFIG + }) + .on('end', resolve) + .on('error', err => { + err = new Error(`Bower reported ${err}`) + this._error = err + reject(err) + }) + }) + this._projectInfo = null + await this.fetchProjectInfo() + } + + async update () { + if (!this.isToBeUpdated) throw new Error() + const typeFolder = await this.getTypeFolder() + const outputPath = path.join(this.cwd, 'src', typeFolder) + const pluginPath = path.join(outputPath, this.name) + try { + await fs.rm(pluginPath, { recursive: true, force: true }) + } catch (err) { + throw new Error(`There was a problem writing to the target directory ${pluginPath}`) + } + await new Promise((resolve, reject) => { + const pluginNameVersion = `${this.packageName}@${this.matchedVersion}` + bower.commands.install([pluginNameVersion], null, { + directory: outputPath, + cwd: this.cwd, + registry: this.BOWER_REGISTRY_CONFIG + }) + .on('end', resolve) + .on('error', err => { + err = new Error(`Bower reported ${err}`) + this._error = err + reject(err) + }) + }) + this.preUpdateProjectVersion = this.projectVersion + this._projectInfo = null + await this.fetchProjectInfo() + } + + async uninstall () { + try { + if (!this.isToBeUninstalled) throw new Error() + await fs.rm(this.projectPath, { recursive: true, force: true }) + this._wasUninstalled = true + } catch (err) { + this._wasUninstalled = false + throw new Error(`There was a problem writing to the target directory ${this.projectPath}`) + } + } + + isNameMatch (name) { + const tester = new RegExp(`${name}$`, 'i') + return tester.test(this.packageName) + } + + /** + * Read plugin data from pluginPath + * @param {Object} options + * @param {string} options.pluginPath Path to source directory + * @param {string} [options.projectPath=process.cwd()] Optional path to potential installation project + * @returns {Target} + */ + static async fromPath ({ + pluginPath, + projectPath = process.cwd() + }) { + const target = new Target({ + name: pluginPath, + cwd: projectPath + }) + await target.fetchLocalSourceInfo() + return target + } +} diff --git a/lib/integration/getBowerRegistryConfig.js b/lib/integration/getBowerRegistryConfig.js new file mode 100644 index 0000000..5f8d791 --- /dev/null +++ b/lib/integration/getBowerRegistryConfig.js @@ -0,0 +1,34 @@ +import fs from 'fs-extra' +import { findUpSync } from 'find-up' + +export default function getBowerRegistryConfig ({ cwd = process.cwd() } = {}) { + function getConfig () { + if (process.env.ADAPT_REGISTRY) { + return process.env.ADAPT_REGISTRY + } + const configPath = findUpSync('.bowerrc', { cwd }) + if (configPath) { + // a manifest exists, load it + const config = fs.readJSONSync(configPath) + return config.registry + } + // use the default Adapt registry + return 'http://adapt-bower-repository.herokuapp.com/' + } + // normalize to https://github.com/bower/spec/blob/master/config.md + const config = getConfig() + let normalized = {} + switch (typeof config) { + case 'string': + normalized = { + register: config, + search: [config] + } + break + case 'object': + Object.assign(normalized, config) + break + } + if (typeof normalized.search === 'string') normalized.search = [normalized.search].filter(Boolean) + return normalized +} diff --git a/lib/logger.js b/lib/logger.js new file mode 100644 index 0000000..ace74ca --- /dev/null +++ b/lib/logger.js @@ -0,0 +1,28 @@ +import readline from 'readline' +import chalk from 'chalk' + +export default { + isLoggingProgress: false, + logProgress (...args) { + this.isLoggingProgress = true + readline.cursorTo(process.stdout, 0) + this.write(args.join(' ')) + }, + warn (...args) { + chalk.yellow(...args) + }, + error (...args) { + chalk.red(...args) + }, + log (...args) { + if (this.isLoggingProgress) { + this.isLoggingProgress = false + readline.cursorTo(process.stdout, 0) + this.write(args.join(' ')) + this.write('\n') + return + } + console.log.apply(console, args) + }, + write: process.stdout.write.bind(process.stdout) +} diff --git a/lib/promise/authenticate.js b/lib/promise/authenticate.js deleted file mode 100644 index 5f97692..0000000 --- a/lib/promise/authenticate.js +++ /dev/null @@ -1,58 +0,0 @@ -var bower = require('bower'), - chalk = require('chalk'), - inquirer = require('inquirer'), - Q = require('q'); - -module.exports = function(properties) { - return Q.fcall(ask, properties).then(login); -}; - -function ask(properties) { - var deferred = Q.defer(); - var schema = [ - { - name: 'username', - message: chalk.cyan('GitHub username') - }, - { - name: 'password', - message: chalk.cyan('GitHub password'), - type: 'password', - mask: '*' - } - ]; - inquirer.prompt(schema).then(confirmation => { - properties.username = confirmation.username; - properties.password = confirmation.password; - deferred.resolve(properties); - }).catch(err => deferred.reject(err)); - return deferred.promise; -} - -function login(properties) { - var deferred = Q.defer(); - - bower.commands.login(properties.repository, {interactive:true}) - .on('prompt', function (prompts, callback) { - callback({ - username:properties.username, - password:properties.password - }); - }) - .on('end', function (result) { - if (!result || !result.token) { - deferred.reject(); - } - else { - //log('end', result); - //log('token ',result.token); - properties.token = result.token; - deferred.resolve(properties); - } - }) - .on('error', function (err) { - //log('login:error', err); - deferred.reject(err); - }); - return deferred.promise; -} \ No newline at end of file diff --git a/lib/promise/build.js b/lib/promise/build.js deleted file mode 100644 index 70e8b8c..0000000 --- a/lib/promise/build.js +++ /dev/null @@ -1,20 +0,0 @@ -var Q = require('q'), - chalk = require('chalk'), - grunt = require('grunt'); - -module.exports = function build(properties) { - var deferred = Q.defer(), - cwd = process.cwd(); - - - - properties.renderer.log(chalk.cyan('running build')); - - grunt.loadTasks(properties.localDir); - - process.chdir(properties.localDir); - grunt.task.run(['build']); - process.chdir(cwd); - - return properties; -}; \ No newline at end of file diff --git a/lib/promise/cloneInstall.js b/lib/promise/cloneInstall.js deleted file mode 100644 index 3cd3a9f..0000000 --- a/lib/promise/cloneInstall.js +++ /dev/null @@ -1,35 +0,0 @@ -var Q = require('q'), - PackageMeta = require('../PackageMeta'), - path = require('path'), - Plugin = require('../Plugin'), - mkdirp = require('mkdirp'), - exec = require('child_process').exec; - -module.exports = function cloneInstall(plugin, options) { - var deferred = Q.defer(); - - PackageMeta.getRepositoryUrl(plugin, options) - .then(function(repoDetails) { - if (!repoDetails) { - console.log(plugin); - throw "Error: Plugin repository url could not be found."; - } - mkdirp(path.resolve(options.localPath, options.directory), function (err) { - if (err) { - return deferred.reject(err); - } - var pluginPath = path.resolve(options.localPath, options.directory, plugin.name); - - var url = repoDetails.url.replace(/^git:\/\//, 'https://'); - exec(`git clone ${url} "${pluginPath}"`); - }); - }) - .then(function(repo){ - deferred.resolve(plugin) - }) - .fail(function(err) { - deferred.reject(err); - }) - .done(); - return deferred.promise; -}; diff --git a/lib/promise/confirmBuild.js b/lib/promise/confirmBuild.js deleted file mode 100644 index 0d0c5c1..0000000 --- a/lib/promise/confirmBuild.js +++ /dev/null @@ -1,6 +0,0 @@ -var Q = requie('q'), - build = require('./build'); - -module.exports = function () { - -}; \ No newline at end of file diff --git a/lib/promise/exec.js b/lib/promise/exec.js deleted file mode 100644 index 9158be8..0000000 --- a/lib/promise/exec.js +++ /dev/null @@ -1,39 +0,0 @@ -var spawn = require("child_process").spawn; -var Q = require("q"); - -/** - * Wrap executing a command in a promise - * @param {string} command command to execute - * @param {Array} args Arguments to the command. - * @param {string} cwd The working directory to run the command in. - * @return {Promise} A promise for the completion of the command. - */ -module.exports = function exec(command, args, cwd) { - if (!command || !cwd) { - return Q.reject(new Error("Both command and working directory must be given, not " + command + " and " + cwd)); - } - if (args && !args.every(function (arg) { - var type = typeof arg; - return type === "boolean" || type === "string" || type === "number"; - })) { - return Q.reject(new Error("All arguments must be a boolean, string or number")); - } - - var deferred = Q.defer(); - - var proc = spawn(command, args, { - cwd: cwd, - stdio: global.DEBUG ? "inherit" : "ignore" - }); - proc.on("error", function (error) { - deferred.reject(new Error(command + " " + args.join(" ") + " in " + cwd + " encountered error " + error.message)); - }); - proc.on("exit", function(code) { - if (code !== 0) { - deferred.reject(new Error(command + " " + args.join(" ") + " in " + cwd + " exited with code " + code)); - } else { - deferred.resolve(); - } - }); - return deferred.promise; -}; \ No newline at end of file diff --git a/lib/promise/getRepository.js b/lib/promise/getRepository.js deleted file mode 100644 index f1537f7..0000000 --- a/lib/promise/getRepository.js +++ /dev/null @@ -1,26 +0,0 @@ -var RepositoryDownloader = require('../RepositoryDownloader'), - uuid = require('uuid'), - fs = require('q-io/fs'), - path = require('path'), - Constants = require('../Constants'); - -module.exports = function (properties) { - var downloader = new RepositoryDownloader({ - repository: properties.repository || Constants.FrameworkRepository, - branch : properties.branch - }), - tmp = properties.tmp = path.join(Constants.HomeDirectory, '.adapt', 'tmp', uuid.v1()); - - return downloader.fetch(tmp) - .then(function (fileName) { - return fs.copyTree(getDownloadedSourcePath(properties, fileName), properties.localDir) - .then(function () { - return properties; - }); - }); -}; - -function getDownloadedSourcePath(properties, fileName) { - var fName = fileName ? fs.base(fileName, fs.extension(fileName)) : ((properties.repositoryName || Constants.FrameworkRepositoryName) + '-' + properties.branch); - return path.join(properties.tmp, fName); -} diff --git a/lib/promise/highest.js b/lib/promise/highest.js deleted file mode 100644 index e40f79d..0000000 --- a/lib/promise/highest.js +++ /dev/null @@ -1,109 +0,0 @@ -var async = require('async'); -var Q = require('q'); -var request = require('request'); -var semver = require('semver'); -var Constants = require('../Constants'); -var _ = require('lodash'); - -module.exports = function () { - var deferred = Q.defer(); - - checkLatestAdaptRepoVersion(function (error, latestFrameworkTag) { - if (error) { - deferred.reject(error); - } else { - deferred.resolve(latestFrameworkTag); - } - }); - - return deferred.promise; -} - -function checkLatestAdaptRepoVersion(versionLimit, callback) { - if (typeof versionLimit === 'function') { - callback = versionLimit; - versionLimit = undefined; - } - // used in pagination - var nextPage = `https://api.github.com/repos/${Constants.DefaultGitHubOrg}/${Constants.FrameworkRepositoryName}/releases`; - - var _getReleases = function (done) { - request({ - headers: { - 'User-Agent': Constants.DefaultUserAgent - }, - uri: nextPage, - method: 'GET' - }, done); - }; - var _requestHandler = function (error, response, body) { - if (response) { - // we've exceeded the API limit - if (response.statusCode === 403 && response.headers['x-ratelimit-remaining'] === '0') { - var reqsReset = new Date(response.headers['x-ratelimit-reset'] * 1000); - error = `You have exceeded GitHub's request limit of ${response.headers['x-ratelimit-limit']} requests per hour. Please wait until at least ${reqsReset.toTimeString()} before trying again.`; - } - else if (response.statusCode !== 200) { - error = 'GitubAPI did not respond with a 200 status code.'; - } - } - if (error) { - return callback(new Error(`Couldn't check latest version of ${Constants.FrameworkRepositoryName}. ${error}`)); - } - nextPage = parseLinkHeader(response.headers.link).next; - try { - // parse and sort releases (newest first) - var releases = JSON.parse(body).sort((a, b) => { - if (semver.lt(a.tag_name, b.tag_name)) return 1; - if (semver.gt(a.tag_name, b.tag_name)) return -1; - return 0; - }); - } catch (e) { - return callback(new Error(`Failed to parse GitHub release data\n${e}`)); - } - var compatibleRelease; - async.someSeries(releases, function (release, cb) { - var isFullRelease = !release.draft && !release.prerelease; - var satisfiesVersion = !versionLimit || semver.satisfies(release.tag_name, versionLimit); - - if (!isFullRelease || !satisfiesVersion) { - return cb(null, false); - } - - compatibleRelease = release; - return cb(null, true); - }, function (error, satisfied) { - if (!satisfied) { - if (nextPage) { - return _getReleases(_requestHandler); - } - error = new Error(`Couldn't find any releases compatible with specified framework version (${versionLimit}), please check that it is a valid version.`); - } - if (error) { - return callback(error); - } - callback(error, compatibleRelease.tag_name); - }); - }; - // start recursion - _getReleases(_requestHandler); -} - -// taken from https://gist.github.com/niallo/3109252 -function parseLinkHeader(header) { - if (!header || header.length === 0) { - return []; - } - var links = {}; - // Parse each part into a named link - _.each(header.split(','), function (p) { - var section = p.split(';'); - if (section.length !== 2) { - throw new Error("section could not be split on ';'"); - } - var url = section[0].replace(/<(.*)>/, '$1').trim(); - var name = section[1].replace(/rel="(.*)"/, '$1').trim(); - links[name] = url; - }); - return links; -} \ No newline at end of file diff --git a/lib/promise/install.js b/lib/promise/install.js deleted file mode 100644 index fb726c7..0000000 --- a/lib/promise/install.js +++ /dev/null @@ -1,31 +0,0 @@ -var bower = require('bower'), - Q = require('q'), - path = require('path'), - rimraf = require('rimraf'), - Plugin = require('../Plugin'); - -module.exports = function install (plugin, config) { - var deferred = Q.defer(); - - // (reliably) remove the plugin first - rimraf(path.join(config.cwd || '.', config.directory, plugin.packageName), {disableGlob:true}, doInstall); - - function doInstall(err) { - if (err) { - deferred.notify(); - deferred.resolve({error:'There was a problem writing to the target directory'}); - } else { - bower.commands.install([plugin.packageName+'#'+plugin._versionToInstall], null, config) - .on('end', function() { - deferred.notify(); - deferred.resolve({_wasInstalled:true}); - }) - .on('error', function (err) { - deferred.notify(); - deferred.resolve({error:'Bower reported '+err}); - }); - } - } - - return deferred.promise; -} diff --git a/lib/promise/installAdaptDependencies.js b/lib/promise/installAdaptDependencies.js deleted file mode 100644 index 7ce6407..0000000 --- a/lib/promise/installAdaptDependencies.js +++ /dev/null @@ -1,30 +0,0 @@ -var chalk = require('chalk'), - Q = require('q'), - npm = require('npm'), - installCommand = invokeFactoryOrProvideObject(require('../commands/install')), - Constants = require('../Constants'), - path = require('path'); - -module.exports = function installAdaptDependencies (properties /* { renderer, localDir } */) { - var deferred = Q.defer(), - cwd = process.cwd(); - - properties.renderer.log(chalk.cyan('installing adapt dependencies')); - - if(path.relative(cwd, properties.localDir)) { - process.chdir(properties.localDir); - console.log(cwd, 'change to', process.cwd()); - } - installCommand.install(properties.renderer, function (err) { - if(err) deferred.reject(err); - - process.chdir(cwd); - deferred.resolve(properties); - }); - return deferred.promise; -}; - -function invokeFactoryOrProvideObject(factoryOrObject, dependencies) { - if(typeof factoryOrObject === 'function') return factoryOrObject(dependencies || {}); - return factoryOrObject; -} diff --git a/lib/promise/installNodeDependencies.js b/lib/promise/installNodeDependencies.js deleted file mode 100644 index 2d4804e..0000000 --- a/lib/promise/installNodeDependencies.js +++ /dev/null @@ -1,28 +0,0 @@ -var chalk = require('chalk'), - Q = require('q'), - npm = require('npm'), - Constants = require('../Constants'), - path = require('path'); - -module.exports = function installNodeDependencies (properties /* { renderer, localDir } */) { - var deferred = Q.defer(), - cwd = process.cwd(); - - properties.renderer.log(chalk.cyan('installing node dependencies')); - - if(path.relative(cwd, properties.localDir)) { - process.chdir(properties.localDir); - } - npm.load(function (err) { - if(err) deferred.reject(err); - - npm.commands.install(function () { - if(err) deferred.reject(err); - - process.chdir(cwd); - - deferred.resolve(properties); - }); - }); - return deferred.promise; -}; \ No newline at end of file diff --git a/lib/promise/removeTemporaryDownload.js b/lib/promise/removeTemporaryDownload.js deleted file mode 100644 index 629a984..0000000 --- a/lib/promise/removeTemporaryDownload.js +++ /dev/null @@ -1,8 +0,0 @@ -var fs = require('q-io/fs'); - -module.exports = function (properties) { - return fs.removeTree(properties.tmp) - .then(function () { - return properties; - }); -}; \ No newline at end of file diff --git a/lib/promise/replaceTextContent.js b/lib/promise/replaceTextContent.js deleted file mode 100644 index 156b33d..0000000 --- a/lib/promise/replaceTextContent.js +++ /dev/null @@ -1,10 +0,0 @@ -var Q = require('q'), - fs = require('q-io/fs'); - -module.exports = function (path, match, replacement) { - return fs.read(path) - .then(function (content) { - var modifiedContent = content.replace(match, replacement); - return fs.write(path, modifiedContent); - }); -}; \ No newline at end of file diff --git a/lib/promise/uninstallPackage.js b/lib/promise/uninstallPackage.js deleted file mode 100644 index a63a1eb..0000000 --- a/lib/promise/uninstallPackage.js +++ /dev/null @@ -1,15 +0,0 @@ -var bower = require('bower'), - Q = require('q'); - -module.exports = function uninstall (plugin, config) { - var deferred = Q.defer(); - - bower.commands.uninstall([plugin.toString()], {}, config) - .on('end', function(uninstalled) { - uninstalled.hasOwnProperty(plugin.toString()) ? deferred.resolve() : deferred.reject(); - }) - .on('error', function (err) { - deferred.reject(err); - }); - return deferred.promise; -}; diff --git a/lib/promise/update.js b/lib/promise/update.js deleted file mode 100644 index cbb9d02..0000000 --- a/lib/promise/update.js +++ /dev/null @@ -1,33 +0,0 @@ -var bower = require('bower'), - chalk = require('chalk'), - Q = require('q'); - -module.exports = function update (plugin, options, config) { - var deferred = Q.defer(); - - function onSuccess() { - //console.log('onSuccess'); - deferred.notify(); - deferred.resolve({updated:true}); - } - - function onFail(err) { - console.log('onFail', err); - deferred.notify(); - deferred.resolve({updated:false, error:err}); - } - - function onLog(obj) { - //console.log(chalk.cyan(obj.level), obj.id, obj.message); - } - - try { - //console.log('UPDATE', plugin.packageName, config); - bower.commands.update([plugin.packageName], options, config).on('end', onSuccess).on('error', onFail).on('log', onLog); - } catch(err) { - console.log('bower update threw error'); - onFail(err); - } - - return deferred.promise; -} \ No newline at end of file diff --git a/lib/promise/util.js b/lib/promise/util.js deleted file mode 100644 index a8de3d6..0000000 --- a/lib/promise/util.js +++ /dev/null @@ -1,16 +0,0 @@ -var Q = require('q'); - -module.exports = { - serialise: function (arr, iterator) { - // create a empty promise to start our series (so we can use `then`) - var currentPromise = Q(); - var promises = arr.map(function (el) { - return currentPromise = currentPromise.then(function () { - // execute the next function after the previous has resolved successfully - return iterator(el) - }) - }); - // group the results and return the group promise - return Q.all(promises) - } -}; \ No newline at end of file diff --git a/lib/util/JSONReadValidate.js b/lib/util/JSONReadValidate.js new file mode 100644 index 0000000..42e4111 --- /dev/null +++ b/lib/util/JSONReadValidate.js @@ -0,0 +1,34 @@ +import fs from 'fs-extra' +import JSONLint from 'json-lint' + +/** + * @param {string} filepath + * @param {function} [done] + * @returns {Promise} + */ +export async function readValidateJSON (filepath, done) { + try { + const data = await fs.readFile(filepath, 'utf8') + validateJSON(data, filepath) + done?.(null, JSON.parse(data)) + return JSON.parse(data) + } catch (err) { + done?.(err.message) + } +} + +export function readValidateJSONSync (filepath) { + const data = fs.readFileSync(filepath, 'utf-8') + validateJSON(data, filepath) + return JSON.parse(data) +} + +function validateJSON (jsonData, filepath) { + const lint = JSONLint(jsonData) + if (!lint.error) return + let errorMessage = 'JSON parsing error: ' + lint.error + ', line: ' + lint.line + ', character: ' + lint.character + if (filepath) { + errorMessage += ', file: \'' + filepath + '\'' + } + throw new Error(errorMessage) +} diff --git a/lib/util/constants.js b/lib/util/constants.js new file mode 100644 index 0000000..bbd4d23 --- /dev/null +++ b/lib/util/constants.js @@ -0,0 +1,38 @@ +import fs from 'fs-extra' + +export const ADAPT_ALLOW_PRERELEASE = process.env.ADAPT_ALLOW_PRERELEASE !== 'false' + +export const ADAPT_FRAMEWORK = process.env.ADAPT_FRAMEWORK || 'https://github.com/adaptlearning/adapt_framework' + +export const ADAPT_COMPONENT = process.env.ADAPT_COMPONENT || 'https://github.com/adaptlearning/adapt-component' + +export const ADAPT_QUESTION = process.env.ADAPT_QUESTION || 'https://github.com/adaptlearning/adapt-questionComponent' + +export const ADAPT_DEFAULT_USER_AGENT = process.env.ADAPT_DEFAULT_USER_AGENT || 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36' + +export const HOME_DIRECTORY = [ + process.env.HOME, + (process.env.HOMEDRIVE + process.env.HOMEPATH), + process.env.USERPROFILE, + '/tmp', + '/temp' +].filter(fs.existsSync)[0] + +/** @type {string} */ +export const PLUGIN_TYPES = [ + 'component', + 'extension', + 'menu', + 'theme' +] + +/** @type {Object} */ +export const PLUGIN_TYPE_FOLDERS = { + component: 'components', + extension: 'extensions', + menu: 'menu', + theme: 'theme' +} + +/** @type {string} */ +export const PLUGIN_DEFAULT_TYPE = PLUGIN_TYPES[0] diff --git a/lib/util/createPromptTask.js b/lib/util/createPromptTask.js new file mode 100644 index 0000000..f73ad26 --- /dev/null +++ b/lib/util/createPromptTask.js @@ -0,0 +1,7 @@ +import inquirer from 'inquirer' + +export async function createPromptTask (question) { + question = Object.assign({}, { name: 'question' }, question) + const confirmation = await inquirer.prompt([question]) + return confirmation.question +} diff --git a/lib/util/download.js b/lib/util/download.js new file mode 100644 index 0000000..ed432b1 --- /dev/null +++ b/lib/util/download.js @@ -0,0 +1,45 @@ +import chalk from 'chalk' +import uuid from 'uuid' +import fs from 'fs-extra' +import path from 'path' +import urljoin from 'url-join' +import fetch from 'download' +import { HOME_DIRECTORY } from './constants.js' +import gh from 'parse-github-url' + +export default async function download ({ + repository, + branch, + tmp, + cwd, + logger +} = {}) { + if (!branch && !repository) throw new Error('Repository details are required.') + const repositoryName = gh(repository).name + logger?.write(chalk.cyan(`downloading ${repositoryName} to ${cwd}\t`)) + tmp = (tmp || path.join(HOME_DIRECTORY, '.adapt', 'tmp', uuid.v1())) + const downloadFileName = await new Promise((resolve, reject) => { + let downloadFileName = '' + const url = urljoin(repository, 'archive', branch + '.zip') + fetch(url, tmp, { + extract: true + }) + .on('response', response => { + const disposition = response.headers['content-disposition'] + if (disposition?.indexOf('attachment') === -1) return + const regex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/ + const matches = regex.exec(disposition) + if (!matches?.[1]) return + downloadFileName = matches[1].replace(/['"]/g, '') + }) + .on('error', reject) + .then(() => resolve(downloadFileName)) + }) + const sourceFileName = downloadFileName + ? path.parse(downloadFileName).name + : `${repositoryName}-${branch}` + const sourcePath = path.join(tmp, sourceFileName) + await fs.copy(sourcePath, cwd) + await fs.rm(tmp, { recursive: true }) + logger?.log(' ', 'done!') +} diff --git a/lib/util/errors.js b/lib/util/errors.js new file mode 100644 index 0000000..8da0346 --- /dev/null +++ b/lib/util/errors.js @@ -0,0 +1,58 @@ +export default { + ERROR_COURSE_DIR: { + code: 0, + message: 'Commands must be run in an Adapt project directory' + }, + ERROR_INCOMPATIBLE_VALID_REQUEST: { + code: 1, + message: 'No compatible version exists (requested version is valid)' + }, + ERROR_INCOMPATIBLE_BAD_REQUEST: { + code: 2, + message: 'No compatible version exists (requested version is invalid)' + }, + ERROR_INCOMPATIBLE: { + code: 3, + message: 'No compatible version exists' + }, + ERROR_COMPATIBLE_INC_REQUEST: { + code: 4, + message: 'Incompatible version requested (compatible version exists)' + }, + ERROR_COMPATIBLE_BAD_REQUEST: { + code: 5, + message: 'Requested version is invalid' + }, + ERROR_UNINSTALL: { + code: 6, + message: 'The plugin could not be uninstalled' + }, + ERROR_NOT_FOUND: { + code: 7, + message: 'The plugin could not be found' + }, + ERROR_NOTHING_TO_UPDATE: { + code: 8, + message: 'Could not resolve any plugins to update' + }, + ERROR_UPDATE_INCOMPATIBLE: { + code: 9, + message: 'Incompatible update requested' + }, + ERROR_INSTALL_ERROR: { + code: 10, + message: 'Unknown installation error' + }, + ERROR_UPDATE_ERROR: { + code: 11, + message: 'Unknown update error' + }, + ERROR_NO_RELEASES: { + code: 12, + message: 'No published releases' + }, + ERROR_NO_UPDATE: { + code: 13, + message: 'No update available' + } +} diff --git a/lib/util/extract.js b/lib/util/extract.js new file mode 100644 index 0000000..937289a --- /dev/null +++ b/lib/util/extract.js @@ -0,0 +1,24 @@ +import uuid from 'uuid' +import path from 'path' +import decompress from 'decompress' +import { HOME_DIRECTORY } from './constants.js' + +export default async function extract ({ + sourcePath, + cwd +} = {}) { + const rootPath = path.join(HOME_DIRECTORY, '.adapt', 'tmp', uuid.v1()).replace(/\\/g, '/') + const files = await decompress(path.join(cwd, sourcePath), rootPath, { + filter: file => !file.path.endsWith('/') + }) + const rootDirectories = Object.keys(files.reduce((memo, file) => { memo[file.path.split(/\\|\//g)[0]] = true; return memo }, {})) + let copyPath = rootPath + if (rootDirectories.length === 1) { + const rootDirectory = files[0].path.split(/\\|\//g)[0] + copyPath = path.join(rootPath, rootDirectory) + } + return { + rootPath, + copyPath + } +} diff --git a/lib/util/getDirNameFromImportMeta.js b/lib/util/getDirNameFromImportMeta.js new file mode 100644 index 0000000..72d54f7 --- /dev/null +++ b/lib/util/getDirNameFromImportMeta.js @@ -0,0 +1,6 @@ +export default function getDirNameFromImportMeta (importMeta) { + const __dirname = (process.platform === 'win32') + ? new URL('.', importMeta.url).pathname.slice(1) + : new URL('.', import.meta.url).pathname + return __dirname +} diff --git a/lib/util/promises.js b/lib/util/promises.js new file mode 100644 index 0000000..a1e5909 --- /dev/null +++ b/lib/util/promises.js @@ -0,0 +1,36 @@ +import { eachOfLimit, eachOfSeries } from 'async' +/** + * Execute all promises in parallel, call progress at each promise to allow + * progress reporting + * @param {Array} array + * @param {function} iterator + * @param {function} progress + * @returns + */ +export async function eachOfLimitProgress (array, iterator, progress) { + let currentIndex = 0 + progress(0) + await eachOfLimit(array, 8, async item => { + currentIndex++ + progress(parseInt((currentIndex * 100) / array.length)) + return iterator(item) + }) +} + +/** + * Execute iterator against each item in the array waiting for the iterator returned + * to finish before continuing, calling progress as each stage + * @param {Array} array + * @param {function} iterator + * @param {function} progress + * @returns + */ +export async function eachOfSeriesProgress (array, iterator, progress) { + let currentIndex = 0 + progress(0) + await eachOfSeries(array, async item => { + currentIndex++ + progress(parseInt((currentIndex * 100) / array.length)) + return iterator(item) + }) +} diff --git a/package-lock.json b/package-lock.json index 6d3a47a..f5177f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,77 +1,121 @@ { "name": "adapt-cli", - "version": "2.1.14", + "version": "3.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { - "@sindresorhus/is": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", - "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } }, - "@sinonjs/commons": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.0.2.tgz", - "integrity": "sha512-WR3dlgqJP4QNrLC4iXN/5/2WaLQQ0VijOOkmflqFGVJ6wLEpbSjo7c0ZeGIdtY8Crk7xBBp87sM6+Mkerz7alw==", + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", "dev": true, "requires": { - "type-detect": "4.0.8" + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" } }, - "@sinonjs/formatio": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.0.0.tgz", - "integrity": "sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w==", + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, "requires": { - "@sinonjs/samsam": "2.1.0" - }, - "dependencies": { - "@sinonjs/samsam": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.0.tgz", - "integrity": "sha512-5x2kFgJYupaF1ns/RmharQ90lQkd2ELS8A9X0ymkAAdemYHGtI2KiUHG8nX2WU0T1qgnOU5YMqnBM2V7NUanNw==", - "dev": true, - "requires": { - "array-from": "^2.1.1" - } - } + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + } + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" } }, - "@sinonjs/samsam": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.1.2.tgz", - "integrity": "sha512-ZwTHAlC9akprWDinwEPD4kOuwaYZlyMwVJIANsKNC3QVp0AHB04m7RnB4eqeWfgmxw8MGTzS9uMaw93Z3QcZbw==", + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "requires": { - "type-fest": "^0.11.0" + "type-fest": "^0.21.3" } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "3.2.1", @@ -100,57 +144,39 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" - }, - "dependencies": { - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - } } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "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==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" - }, - "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 - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + "array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + } }, "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "requires": { "safer-buffer": "~2.1.0" } @@ -160,95 +186,41 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true }, "async": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", - "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, "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==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "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=", - "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==", - "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==", - "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==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", - "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -260,7 +232,7 @@ }, "bl": { "version": "1.2.3", - "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", "requires": { "readable-stream": "^2.3.5", @@ -268,9 +240,9 @@ } }, "bower": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.8.tgz", - "integrity": "sha512-1SrJnXnkP9soITHptSO+ahx3QKp3cVzn8poI6ujqc5SeOkg5iqM1pK9H+DSc2OQ8SnO0jC/NG4Ur/UIwy7574A==" + "version": "1.8.13", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.13.tgz", + "integrity": "sha512-8eWko16JlCTdaZZG70kddHPed17pHEbH8/IjfP4IFkQsfEqRsyNM09Dc8cDBFkSvtQ/2lTea7A+bMhRggG2a+Q==" }, "bower-endpoint-parser": { "version": "0.2.2", @@ -286,47 +258,13 @@ "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==", - "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=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "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": { - "version": "3.6.0", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz", - "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "requires": { - "base64-js": "0.0.8", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "buffer-alloc": { @@ -353,22 +291,6 @@ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "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" - } - }, "cacheable-request": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", @@ -383,6 +305,11 @@ "responselike": "1.0.2" }, "dependencies": { + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, "lowercase-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", @@ -390,6 +317,22 @@ } } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -407,9 +350,9 @@ } }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "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", @@ -421,27 +364,6 @@ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, - "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==", - "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=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -463,20 +385,6 @@ "mimic-response": "^1.0.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -490,31 +398,18 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" - }, "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "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" } }, "commander": { - "version": "2.8.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "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==" }, "concat-map": { "version": "0.0.1", @@ -522,35 +417,36 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "requires": { "ini": "^1.3.4", "proto-list": "~1.2.1" } }, "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } }, "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=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "requires": { - "es5-ext": "^0.10.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, "dashdash": { @@ -561,17 +457,13 @@ "assert-plus": "^1.0.0" } }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" - }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "decode-uri-component": { @@ -592,13 +484,6 @@ "make-dir": "^1.0.0", "pify": "^2.3.0", "strip-dirs": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } } }, "decompress-response": { @@ -617,13 +502,6 @@ "file-type": "^5.2.0", "is-stream": "^1.1.0", "tar-stream": "^1.5.2" - }, - "dependencies": { - "file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" - } } }, "decompress-tarbz2": { @@ -653,13 +531,6 @@ "decompress-tar": "^4.1.1", "file-type": "^5.2.0", "is-stream": "^1.1.0" - }, - "dependencies": { - "file-type": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", - "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" - } } }, "decompress-unzip": { @@ -677,58 +548,22 @@ "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" - }, - "get-stream": { - "version": "2.3.1", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", - "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", - "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" } } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { - "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==", - "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==", - "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==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "object-keys": "^1.0.12" } }, "delayed-stream": { @@ -736,16 +571,14 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } }, "download": { "version": "7.1.0", @@ -764,6 +597,23 @@ "make-dir": "^1.2.0", "p-event": "^2.1.0", "pify": "^3.0.0" + }, + "dependencies": { + "file-type": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } } }, "duplexer3": { @@ -786,52 +636,59 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "requires": { "once": "^1.4.0" } }, - "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" + "ansi-colors": "^4.1.1" } }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "es-abstract": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" } }, "escape-string-regexp": { @@ -839,87 +696,395 @@ "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==" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=" - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "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" + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "ms": "2.0.0" + "color-convert": "^2.0.1" } }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, - "extend-shallow": { + "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "is-extendable": "^0.1.0" + "color-name": "~1.1.4" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "eslint-config-standard": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", + "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-module-utils": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", + "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "find-up": "^2.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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" + } + }, + "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" + } + }, + "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" + } + }, + "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 + } + } + }, + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.25.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", + "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", + "dev": true, + "requires": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.2", + "has": "^1.0.3", + "is-core-module": "^2.8.0", + "is-glob": "^4.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.5", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.12.0" + }, + "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" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz", + "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } } }, - "expect.js": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", - "integrity": "sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s=", + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, "ext-list": { @@ -944,25 +1109,6 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "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==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, "external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -973,79 +1119,26 @@ "tmp": "^0.0.33" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "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=", - "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=", - "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==", - "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==", - "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==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "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=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "fd-slicer": { "version": "1.1.0", @@ -1063,10 +1156,19 @@ "escape-string-regexp": "^1.0.5" } }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "file-type": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", - "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" }, "filename-reserved-regex": { "version": "2.0.0", @@ -1083,78 +1185,30 @@ "trim-repeated": "^1.0.0" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "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=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "find-up": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.2.0.tgz", + "integrity": "sha512-yWHzMzXCaFoABSnFTCPKNFlYoq4mSga9QLRRKOCLSJ33hSkzROB14ITbAWW0QDQDyuzsPQ33S1DsOWQb/oW1yA==", "requires": { - "glob": "~5.0.0" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } + "locate-path": "^7.0.0", + "path-exists": "^5.0.0" } }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "requires": { - "for-in": "^1.0.1" - } + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true }, "forever-agent": { "version": "0.6.1", @@ -1171,14 +1225,6 @@ "mime-types": "^2.1.12" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -1193,6 +1239,16 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1201,9 +1257,27 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, - "get-proxy": { + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-proxy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", @@ -1212,19 +1286,23 @@ } }, "get-stream": { - "version": "3.0.0", - "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } }, - "getobject": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz", - "integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==" + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } }, "getpass": { "version": "0.1.7", @@ -1235,39 +1313,50 @@ } }, "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", - "dev": true, + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.2", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "is-glob": "^4.0.1" } }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "globals": { + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "globs": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globs/-/globs-0.1.4.tgz", + "integrity": "sha512-D23dWbOq48vlOraoSigbcQV4tWrnhwk+E/Um2cMuDS3/5dwGmdFeA7L/vAvDhLFlQOTDqHcXh35m/71g2A2WzQ==", + "requires": { + "glob": "^7.1.1" } }, "got": { @@ -1292,200 +1381,24 @@ "timed-out": "^4.0.1", "url-parse-lax": "^3.0.0", "url-to-options": "^1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "grunt": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.3.0.tgz", - "integrity": "sha512-6ILlMXv11/4cxuhSMfSU+SfvbxrPuqZrAtLN64+tZpQ3DAKfSQPQHRbTjSbdtxfyQhGZPtN0bDZJ/LdCM5WXXA==", - "requires": { - "dateformat": "~3.0.3", - "eventemitter2": "~0.4.13", - "exit": "~0.1.2", - "findup-sync": "~0.3.0", - "glob": "~7.1.6", - "grunt-cli": "~1.3.2", - "grunt-known-options": "~1.1.0", - "grunt-legacy-log": "~3.0.0", - "grunt-legacy-util": "~2.0.0", - "iconv-lite": "~0.4.13", - "js-yaml": "~3.14.0", - "minimatch": "~3.0.4", - "mkdirp": "~1.0.4", - "nopt": "~3.0.6", - "rimraf": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "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" - } - }, - "grunt-cli": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.2.tgz", - "integrity": "sha512-8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ==", - "requires": { - "grunt-known-options": "~1.1.0", - "interpret": "~1.1.0", - "liftoff": "~2.5.0", - "nopt": "~4.0.1", - "v8flags": "~3.1.1" - }, - "dependencies": { - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "grunt-known-options": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", - "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==" - }, - "grunt-legacy-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", - "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", - "requires": { - "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.1.0", - "hooker": "~0.2.3", - "lodash": "~4.17.19" - } - }, - "grunt-legacy-log-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", - "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", - "requires": { - "chalk": "~4.1.0", - "lodash": "~4.17.19" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "grunt-legacy-util": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", - "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", - "requires": { - "async": "~3.2.0", - "exit": "~0.1.2", - "getobject": "~1.0.0", - "hooker": "~0.2.3", - "lodash": "~4.17.21", - "underscore.string": "~3.3.5", - "which": "~2.0.2" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" } } }, - "grunt-mocha-test": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.13.3.tgz", - "integrity": "sha512-zQGEsi3d+ViPPi7/4jcj78afKKAKiAA5n61pknQYi25Ugik+aNOuRmiOkmb8mN2CeG8YxT+YdT1H1Q7B/eNkoQ==", - "dev": true, - "requires": { - "hooker": "^0.2.3", - "mkdirp": "^0.5.0" - } + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" }, "har-schema": { "version": "2.0.0", @@ -1493,11 +1406,11 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { - "ajv": "^5.3.0", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -1505,10 +1418,17 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -1519,6 +1439,12 @@ "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==" }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, "has-to-string-tag-x": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", @@ -1527,54 +1453,15 @@ "has-symbol-support-x": "^1.4.1" } }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { + "has-tostringtag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "has-symbols": "^1.0.2" } }, - "hooker": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", - "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=" - }, "http-cache-semantics": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", @@ -1599,9 +1486,31 @@ } }, "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "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", @@ -1613,14 +1522,14 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "inquirer": { "version": "7.3.3", @@ -1651,9 +1560,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1677,11 +1586,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -1692,104 +1596,74 @@ } } }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } }, "into-stream": { "version": "3.1.0", - "resolved": "http://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", "requires": { "from2": "^2.1.1", "p-is-promise": "^1.1.0" } }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "has-bigints": "^1.0.1" } }, - "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=", + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "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=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true }, "is-core-module": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", - "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, "requires": { "has": "^1.0.3" } }, - "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=", - "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=", - "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==", + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "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==" - } + "has-tostringtag": "^1.0.0" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", @@ -1797,11 +1671,12 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "^2.1.1" } }, "is-natural-number": { @@ -1809,78 +1684,89 @@ "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "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=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "has-tostringtag": "^1.0.0" } }, "is-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", - "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==" }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, - "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==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, "requires": { - "is-unc-path": "^1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" + }, + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, "requires": { - "unc-path-regex": "^0.1.2" + "call-bind": "^1.0.2" } }, - "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==" - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -1889,12 +1775,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -1910,10 +1792,17 @@ "is-object": "^1.0.1" } }, + "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.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1935,3509 +1824,201 @@ "integrity": "sha1-RbA/uobE8w8sbnCqc6kNP+GPmAM=" }, "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "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-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "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=", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "just-extend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-3.0.0.tgz", - "integrity": "sha512-Fu3T6pKBuxjWT/p4DkqGHFRsysc8OauWr4ZRTY9dIx07Y9O0RkoR5jcv28aeD1vuAwhm3nLkDurwLXoALp4DpQ==", - "dev": true - }, - "keyv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", - "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", - "requires": { - "json-buffer": "3.0.0" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - } - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lolex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-3.0.0.tgz", - "integrity": "sha512-hcnW80h3j2lbUfFdMArd5UPA/vxZJ+G8vobd+wg3nVEQA0EigStbYcrG030FJxL6xiDDPEkoMatV9xIh5OecQQ==", - "dev": true - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "requires": { - "pify": "^3.0.0" - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "^1.0.0" - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "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" - } - }, - "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.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" - }, - "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", - "requires": { - "mime-db": "~1.37.0" - } - }, - "mimeparse": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/mimeparse/-/mimeparse-0.1.4.tgz", - "integrity": "sha1-2vsCdSNw/SJgk64xUsJxrwGsJUo=" - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "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==", - "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=", - "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=" - } - } - }, - "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": "http://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" - } - }, - "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" - } - }, - "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" - } - } - } - }, - "mockery": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mockery/-/mockery-2.1.0.tgz", - "integrity": "sha512-9VkOmxKlWXoDO/h1jDZaS4lH33aWfRiJiNT/tKj+8OGzrcFDLo8d0syGdbsc3Bc4GvRXPb+NMMvojotmuGJTvA==", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "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-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" - } - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "nise": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.6.tgz", - "integrity": "sha512-1GedetLKzmqmgwabuMSqPsT7oumdR77SBpDfNNJhADRIeA3LN/2RVqR4fFqwvzhAqcTef6PPCzQwITE/YQ8S8A==", - "dev": true, - "requires": { - "@sinonjs/formatio": "3.0.0", - "just-extend": "^3.0.0", - "lolex": "^2.3.2", - "path-to-regexp": "^1.7.0", - "text-encoding": "^0.6.4" - }, - "dependencies": { - "lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "dev": true - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1" - } - }, - "normalize-url": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", - "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", - "requires": { - "prepend-http": "^2.0.0", - "query-string": "^5.0.1", - "sort-keys": "^2.0.0" - }, - "dependencies": { - "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "requires": { - "is-plain-obj": "^1.0.0" - } - } + "minimist": "^1.2.0" } - }, - "npm": { - "version": "6.14.6", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.6.tgz", - "integrity": "sha512-axnz6iHFK6WPE0js/+mRp+4IOwpHn5tJEw5KB6FiCU764zmffrhsYHbSHi2kKqNkRBt53XasXjngZfBD3FQzrQ==", - "requires": { - "JSONStream": "^1.3.5", - "abbrev": "~1.1.1", - "ansicolors": "~0.3.2", - "ansistyles": "~0.1.3", - "aproba": "^2.0.0", - "archy": "~1.0.0", - "bin-links": "^1.1.7", - "bluebird": "^3.5.5", - "byte-size": "^5.0.1", - "cacache": "^12.0.3", - "call-limit": "^1.1.1", - "chownr": "^1.1.4", - "ci-info": "^2.0.0", - "cli-columns": "^3.1.2", - "cli-table3": "^0.5.1", - "cmd-shim": "^3.0.3", - "columnify": "~1.5.4", - "config-chain": "^1.1.12", - "debuglog": "*", - "detect-indent": "~5.0.0", - "detect-newline": "^2.1.0", - "dezalgo": "~1.0.3", - "editor": "~1.0.0", - "figgy-pudding": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "fs-vacuum": "~1.2.10", - "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.3.0", - "glob": "^7.1.6", - "graceful-fs": "^4.2.4", - "has-unicode": "~2.0.1", - "hosted-git-info": "^2.8.8", - "iferr": "^1.0.2", - "imurmurhash": "*", - "infer-owner": "^1.0.4", - "inflight": "~1.0.6", - "inherits": "^2.0.4", - "ini": "^1.3.5", - "init-package-json": "^1.10.3", - "is-cidr": "^3.0.0", - "json-parse-better-errors": "^1.0.2", - "lazy-property": "~1.0.0", - "libcipm": "^4.0.7", - "libnpm": "^3.0.1", - "libnpmaccess": "^3.0.2", - "libnpmhook": "^5.0.3", - "libnpmorg": "^1.0.1", - "libnpmsearch": "^2.0.2", - "libnpmteam": "^1.0.2", - "libnpx": "^10.2.2", - "lock-verify": "^2.1.0", - "lockfile": "^1.0.4", - "lodash._baseindexof": "*", - "lodash._baseuniq": "~4.6.0", - "lodash._bindcallback": "*", - "lodash._cacheindexof": "*", - "lodash._createcache": "*", - "lodash._getnative": "*", - "lodash.clonedeep": "~4.5.0", - "lodash.restparam": "*", - "lodash.union": "~4.6.0", - "lodash.uniq": "~4.5.0", - "lodash.without": "~4.4.0", - "lru-cache": "^5.1.1", - "meant": "~1.0.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.5", - "move-concurrently": "^1.0.1", - "node-gyp": "^5.1.0", - "nopt": "^4.0.3", - "normalize-package-data": "^2.5.0", - "npm-audit-report": "^1.3.2", - "npm-cache-filename": "~1.0.2", - "npm-install-checks": "^3.0.2", - "npm-lifecycle": "^3.1.4", - "npm-package-arg": "^6.1.1", - "npm-packlist": "^1.4.8", - "npm-pick-manifest": "^3.0.2", - "npm-profile": "^4.0.4", - "npm-registry-fetch": "^4.0.5", - "npm-user-validate": "~1.0.0", - "npmlog": "~4.1.2", - "once": "~1.4.0", - "opener": "^1.5.1", - "osenv": "^0.1.5", - "pacote": "^9.5.12", - "path-is-inside": "~1.0.2", - "promise-inflight": "~1.0.1", - "qrcode-terminal": "^0.12.0", - "query-string": "^6.8.2", - "qw": "~1.0.1", - "read": "~1.0.7", - "read-cmd-shim": "^1.0.5", - "read-installed": "~4.0.3", - "read-package-json": "^2.1.1", - "read-package-tree": "^5.3.1", - "readable-stream": "^3.6.0", - "readdir-scoped-modules": "^1.1.0", - "request": "^2.88.0", - "retry": "^0.12.0", - "rimraf": "^2.7.1", - "safe-buffer": "^5.1.2", - "semver": "^5.7.1", - "sha": "^3.0.0", - "slide": "~1.1.6", - "sorted-object": "~2.0.1", - "sorted-union-stream": "~2.1.3", - "ssri": "^6.0.1", - "stringify-package": "^1.0.1", - "tar": "^4.4.13", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "uid-number": "0.0.6", - "umask": "~1.1.0", - "unique-filename": "^1.1.1", - "unpipe": "~1.0.0", - "update-notifier": "^2.5.0", - "uuid": "^3.3.3", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "~3.0.0", - "which": "^1.3.1", - "worker-farm": "^1.7.0", - "write-file-atomic": "^2.4.3" - }, - "dependencies": { - "JSONStream": { - "version": "1.3.5", - "bundled": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "bundled": true - }, - "agent-base": { - "version": "4.3.0", - "bundled": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "3.5.2", - "bundled": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "ajv": { - "version": "5.5.2", - "bundled": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ansi-align": { - "version": "2.0.0", - "bundled": true, - "requires": { - "string-width": "^2.0.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "ansi-styles": { - "version": "3.2.1", - "bundled": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansicolors": { - "version": "0.3.2", - "bundled": true - }, - "ansistyles": { - "version": "0.1.3", - "bundled": true - }, - "aproba": { - "version": "2.0.0", - "bundled": true - }, - "archy": { - "version": "1.0.0", - "bundled": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "asap": { - "version": "2.0.6", - "bundled": true - }, - "asn1": { - "version": "0.2.4", - "bundled": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "bundled": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true - }, - "aws-sign2": { - "version": "0.7.0", - "bundled": true - }, - "aws4": { - "version": "1.8.0", - "bundled": true - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bin-links": { - "version": "1.1.7", - "bundled": true, - "requires": { - "bluebird": "^3.5.3", - "cmd-shim": "^3.0.0", - "gentle-fs": "^2.3.0", - "graceful-fs": "^4.1.15", - "npm-normalize-package-bin": "^1.0.0", - "write-file-atomic": "^2.3.0" - } - }, - "bluebird": { - "version": "3.5.5", - "bundled": true - }, - "boxen": { - "version": "1.3.0", - "bundled": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer-from": { - "version": "1.0.0", - "bundled": true - }, - "builtins": { - "version": "1.0.3", - "bundled": true - }, - "byline": { - "version": "5.0.0", - "bundled": true - }, - "byte-size": { - "version": "5.0.1", - "bundled": true - }, - "cacache": { - "version": "12.0.3", - "bundled": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "call-limit": { - "version": "1.1.1", - "bundled": true - }, - "camelcase": { - "version": "4.1.0", - "bundled": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "bundled": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true - }, - "chalk": { - "version": "2.4.1", - "bundled": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chownr": { - "version": "1.1.4", - "bundled": true - }, - "ci-info": { - "version": "2.0.0", - "bundled": true - }, - "cidr-regex": { - "version": "2.0.10", - "bundled": true, - "requires": { - "ip-regex": "^2.1.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "bundled": true - }, - "cli-columns": { - "version": "3.1.2", - "bundled": true, - "requires": { - "string-width": "^2.0.0", - "strip-ansi": "^3.0.1" - } - }, - "cli-table3": { - "version": "0.5.1", - "bundled": true, - "requires": { - "colors": "^1.1.2", - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - } - }, - "cliui": { - "version": "4.1.0", - "bundled": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "bundled": true - }, - "cmd-shim": { - "version": "3.0.3", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "mkdirp": "~0.5.0" - } - }, - "co": { - "version": "4.6.0", - "bundled": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "color-convert": { - "version": "1.9.1", - "bundled": true, - "requires": { - "color-name": "^1.1.1" - } - }, - "color-name": { - "version": "1.1.3", - "bundled": true - }, - "colors": { - "version": "1.3.3", - "bundled": true, - "optional": true - }, - "columnify": { - "version": "1.5.4", - "bundled": true, - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - } - }, - "combined-stream": { - "version": "1.0.6", - "bundled": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "concat-stream": { - "version": "1.6.2", - "bundled": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "config-chain": { - "version": "1.1.12", - "bundled": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "configstore": { - "version": "3.1.2", - "bundled": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "copy-concurrently": { - "version": "1.0.5", - "bundled": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "create-error-class": { - "version": "3.0.2", - "bundled": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "bundled": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "bundled": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "bundled": true - } - } - }, - "crypto-random-string": { - "version": "1.0.0", - "bundled": true - }, - "cyclist": { - "version": "0.2.2", - "bundled": true - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "3.1.0", - "bundled": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "bundled": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "bundled": true - }, - "decamelize": { - "version": "1.2.0", - "bundled": true - }, - "decode-uri-component": { - "version": "0.2.0", - "bundled": true - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true - }, - "defaults": { - "version": "1.0.3", - "bundled": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.3", - "bundled": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true - }, - "detect-indent": { - "version": "5.0.0", - "bundled": true - }, - "detect-newline": { - "version": "2.1.0", - "bundled": true - }, - "dezalgo": { - "version": "1.0.3", - "bundled": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "dot-prop": { - "version": "4.2.0", - "bundled": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "dotenv": { - "version": "5.0.1", - "bundled": true - }, - "duplexer3": { - "version": "0.1.4", - "bundled": true - }, - "duplexify": { - "version": "3.6.0", - "bundled": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "bundled": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "editor": { - "version": "1.0.0", - "bundled": true - }, - "encoding": { - "version": "0.1.12", - "bundled": true, - "requires": { - "iconv-lite": "~0.4.13" - } - }, - "end-of-stream": { - "version": "1.4.1", - "bundled": true, - "requires": { - "once": "^1.4.0" - } - }, - "env-paths": { - "version": "2.2.0", - "bundled": true - }, - "err-code": { - "version": "1.1.2", - "bundled": true - }, - "errno": { - "version": "0.1.7", - "bundled": true, - "requires": { - "prr": "~1.0.1" - } - }, - "es-abstract": { - "version": "1.12.0", - "bundled": true, - "requires": { - "es-to-primitive": "^1.1.1", - "function-bind": "^1.1.1", - "has": "^1.0.1", - "is-callable": "^1.1.3", - "is-regex": "^1.0.4" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "bundled": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-promise": { - "version": "4.2.8", - "bundled": true - }, - "es6-promisify": { - "version": "5.0.0", - "bundled": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "bundled": true - }, - "execa": { - "version": "0.7.0", - "bundled": 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": { - "get-stream": { - "version": "3.0.0", - "bundled": true - } - } - }, - "extend": { - "version": "3.0.2", - "bundled": true - }, - "extsprintf": { - "version": "1.3.0", - "bundled": true - }, - "fast-deep-equal": { - "version": "1.1.0", - "bundled": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "bundled": true - }, - "figgy-pudding": { - "version": "3.5.1", - "bundled": true - }, - "find-npm-prefix": { - "version": "1.0.2", - "bundled": true - }, - "find-up": { - "version": "2.1.0", - "bundled": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "flush-write-stream": { - "version": "1.0.3", - "bundled": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true - }, - "form-data": { - "version": "2.3.2", - "bundled": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - }, - "from2": { - "version": "2.3.0", - "bundled": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "requires": { - "minipass": "^2.6.0" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "fs-vacuum": { - "version": "1.2.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "path-is-inside": "^1.0.1", - "rimraf": "^2.5.2" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - }, - "dependencies": { - "iferr": { - "version": "0.1.5", - "bundled": true - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "function-bind": { - "version": "1.1.1", - "bundled": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "genfun": { - "version": "5.0.0", - "bundled": true - }, - "gentle-fs": { - "version": "2.3.0", - "bundled": true, - "requires": { - "aproba": "^1.1.2", - "chownr": "^1.1.2", - "cmd-shim": "^3.0.3", - "fs-vacuum": "^1.2.10", - "graceful-fs": "^4.1.11", - "iferr": "^0.1.5", - "infer-owner": "^1.0.4", - "mkdirp": "^0.5.1", - "path-is-inside": "^1.0.2", - "read-cmd-shim": "^1.0.1", - "slide": "^1.1.6" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "iferr": { - "version": "0.1.5", - "bundled": true - } - } - }, - "get-caller-file": { - "version": "1.0.3", - "bundled": true - }, - "get-stream": { - "version": "4.1.0", - "bundled": true, - "requires": { - "pump": "^3.0.0" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": 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" - } - }, - "global-dirs": { - "version": "0.1.1", - "bundled": true, - "requires": { - "ini": "^1.3.4" - } - }, - "got": { - "version": "6.7.1", - "bundled": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - }, - "dependencies": { - "get-stream": { - "version": "3.0.0", - "bundled": true - } - } - }, - "graceful-fs": { - "version": "4.2.4", - "bundled": true - }, - "har-schema": { - "version": "2.0.0", - "bundled": true - }, - "har-validator": { - "version": "5.1.0", - "bundled": true, - "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "bundled": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "bundled": true - }, - "has-symbols": { - "version": "1.0.0", - "bundled": true - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true - }, - "hosted-git-info": { - "version": "2.8.8", - "bundled": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "bundled": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "bundled": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.2.0", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "bundled": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.23", - "bundled": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "iferr": { - "version": "1.0.2", - "bundled": true - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-lazy": { - "version": "2.1.0", - "bundled": true - }, - "imurmurhash": { - "version": "0.1.4", - "bundled": true - }, - "infer-owner": { - "version": "1.0.4", - "bundled": true - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true - }, - "ini": { - "version": "1.3.5", - "bundled": true - }, - "init-package-json": { - "version": "1.10.3", - "bundled": true, - "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" - } - }, - "invert-kv": { - "version": "2.0.0", - "bundled": true - }, - "ip": { - "version": "1.1.5", - "bundled": true - }, - "ip-regex": { - "version": "2.1.0", - "bundled": true - }, - "is-callable": { - "version": "1.1.4", - "bundled": true - }, - "is-ci": { - "version": "1.2.1", - "bundled": true, - "requires": { - "ci-info": "^1.5.0" - }, - "dependencies": { - "ci-info": { - "version": "1.6.0", - "bundled": true - } - } - }, - "is-cidr": { - "version": "3.0.0", - "bundled": true, - "requires": { - "cidr-regex": "^2.0.10" - } - }, - "is-date-object": { - "version": "1.0.1", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "bundled": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "bundled": true - }, - "is-obj": { - "version": "1.0.1", - "bundled": true - }, - "is-path-inside": { - "version": "1.0.1", - "bundled": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-redirect": { - "version": "1.0.0", - "bundled": true - }, - "is-regex": { - "version": "1.0.4", - "bundled": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-retry-allowed": { - "version": "1.2.0", - "bundled": true - }, - "is-stream": { - "version": "1.1.0", - "bundled": true - }, - "is-symbol": { - "version": "1.0.2", - "bundled": true, - "requires": { - "has-symbols": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "isexe": { - "version": "2.0.0", - "bundled": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "optional": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "bundled": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "bundled": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true - }, - "jsonparse": { - "version": "1.3.1", - "bundled": true - }, - "jsprim": { - "version": "1.4.1", - "bundled": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "latest-version": { - "version": "3.1.0", - "bundled": true, - "requires": { - "package-json": "^4.0.0" - } - }, - "lazy-property": { - "version": "1.0.0", - "bundled": true - }, - "lcid": { - "version": "2.0.0", - "bundled": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "libcipm": { - "version": "4.0.7", - "bundled": true, - "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.1", - "figgy-pudding": "^3.5.1", - "find-npm-prefix": "^1.0.2", - "graceful-fs": "^4.1.11", - "ini": "^1.3.5", - "lock-verify": "^2.0.2", - "mkdirp": "^0.5.1", - "npm-lifecycle": "^3.0.0", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "pacote": "^9.1.0", - "read-package-json": "^2.0.13", - "rimraf": "^2.6.2", - "worker-farm": "^1.6.0" - } - }, - "libnpm": { - "version": "3.0.1", - "bundled": true, - "requires": { - "bin-links": "^1.1.2", - "bluebird": "^3.5.3", - "find-npm-prefix": "^1.0.2", - "libnpmaccess": "^3.0.2", - "libnpmconfig": "^1.2.1", - "libnpmhook": "^5.0.3", - "libnpmorg": "^1.0.1", - "libnpmpublish": "^1.1.2", - "libnpmsearch": "^2.0.2", - "libnpmteam": "^1.0.2", - "lock-verify": "^2.0.2", - "npm-lifecycle": "^3.0.0", - "npm-logical-tree": "^1.2.1", - "npm-package-arg": "^6.1.0", - "npm-profile": "^4.0.2", - "npm-registry-fetch": "^4.0.0", - "npmlog": "^4.1.2", - "pacote": "^9.5.3", - "read-package-json": "^2.0.13", - "stringify-package": "^1.0.0" - } - }, - "libnpmaccess": { - "version": "3.0.2", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "get-stream": "^4.0.0", - "npm-package-arg": "^6.1.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmconfig": { - "version": "1.2.1", - "bundled": true, - "requires": { - "figgy-pudding": "^3.5.1", - "find-up": "^3.0.0", - "ini": "^1.3.5" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "bundled": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "bundled": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "2.2.0", - "bundled": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "bundled": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "bundled": true - } - } - }, - "libnpmhook": { - "version": "5.0.3", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmorg": { - "version": "1.0.1", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmpublish": { - "version": "1.1.2", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.0.0", - "lodash.clonedeep": "^4.5.0", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "npm-registry-fetch": "^4.0.0", - "semver": "^5.5.1", - "ssri": "^6.0.1" - } - }, - "libnpmsearch": { - "version": "2.0.2", - "bundled": true, - "requires": { - "figgy-pudding": "^3.5.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpmteam": { - "version": "1.0.2", - "bundled": true, - "requires": { - "aproba": "^2.0.0", - "figgy-pudding": "^3.4.1", - "get-stream": "^4.0.0", - "npm-registry-fetch": "^4.0.0" - } - }, - "libnpx": { - "version": "10.2.2", - "bundled": true, - "requires": { - "dotenv": "^5.0.1", - "npm-package-arg": "^6.0.0", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.0", - "update-notifier": "^2.3.0", - "which": "^1.3.0", - "y18n": "^4.0.0", - "yargs": "^11.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lock-verify": { - "version": "2.1.0", - "bundled": true, - "requires": { - "npm-package-arg": "^6.1.0", - "semver": "^5.4.1" - } - }, - "lockfile": { - "version": "1.0.4", - "bundled": true, - "requires": { - "signal-exit": "^3.0.2" - } - }, - "lodash._baseindexof": { - "version": "3.1.0", - "bundled": true - }, - "lodash._baseuniq": { - "version": "4.6.0", - "bundled": true, - "requires": { - "lodash._createset": "~4.0.0", - "lodash._root": "~3.0.0" - } - }, - "lodash._bindcallback": { - "version": "3.0.1", - "bundled": true - }, - "lodash._cacheindexof": { - "version": "3.0.2", - "bundled": true - }, - "lodash._createcache": { - "version": "3.1.2", - "bundled": true, - "requires": { - "lodash._getnative": "^3.0.0" - } - }, - "lodash._createset": { - "version": "4.0.3", - "bundled": true - }, - "lodash._getnative": { - "version": "3.9.1", - "bundled": true - }, - "lodash._root": { - "version": "3.0.1", - "bundled": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "bundled": true - }, - "lodash.restparam": { - "version": "3.6.1", - "bundled": true - }, - "lodash.union": { - "version": "4.6.0", - "bundled": true - }, - "lodash.uniq": { - "version": "4.5.0", - "bundled": true - }, - "lodash.without": { - "version": "4.4.0", - "bundled": true - }, - "lowercase-keys": { - "version": "1.0.1", - "bundled": true - }, - "lru-cache": { - "version": "5.1.1", - "bundled": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "1.3.0", - "bundled": true, - "requires": { - "pify": "^3.0.0" - } - }, - "make-fetch-happen": { - "version": "5.0.2", - "bundled": true, - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^12.0.0", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" - } - }, - "map-age-cleaner": { - "version": "0.1.3", - "bundled": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "meant": { - "version": "1.0.1", - "bundled": true - }, - "mem": { - "version": "4.3.0", - "bundled": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "dependencies": { - "mimic-fn": { - "version": "2.1.0", - "bundled": true - } - } - }, - "mime-db": { - "version": "1.35.0", - "bundled": true - }, - "mime-types": { - "version": "2.1.19", - "bundled": true, - "requires": { - "mime-db": "~1.35.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "requires": { - "minipass": "^2.9.0" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "mississippi": { - "version": "3.0.0", - "bundled": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mkdirp": { - "version": "0.5.5", - "bundled": true, - "requires": { - "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "bundled": true - } - } - }, - "move-concurrently": { - "version": "1.0.1", - "bundled": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - } - } - }, - "ms": { - "version": "2.1.1", - "bundled": true - }, - "mute-stream": { - "version": "0.0.7", - "bundled": true - }, - "nice-try": { - "version": "1.0.5", - "bundled": true - }, - "node-fetch-npm": { - "version": "2.0.2", - "bundled": true, - "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node-gyp": { - "version": "5.1.0", - "bundled": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.1.2", - "request": "^2.88.0", - "rimraf": "^2.6.3", - "semver": "^5.7.1", - "tar": "^4.4.12", - "which": "^1.3.1" - } - }, - "nopt": { - "version": "4.0.3", - "bundled": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "bundled": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.10.0", - "bundled": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "npm-audit-report": { - "version": "1.3.2", - "bundled": true, - "requires": { - "cli-table3": "^0.5.0", - "console-control-strings": "^1.1.0" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-cache-filename": { - "version": "1.0.2", - "bundled": true - }, - "npm-install-checks": { - "version": "3.0.2", - "bundled": true, - "requires": { - "semver": "^2.3.0 || 3.x || 4 || 5" - } - }, - "npm-lifecycle": { - "version": "3.1.4", - "bundled": true, - "requires": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.15", - "node-gyp": "^5.0.2", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", - "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" - } - }, - "npm-logical-tree": { - "version": "1.2.1", - "bundled": true - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true - }, - "npm-package-arg": { - "version": "6.1.1", - "bundled": true, - "requires": { - "hosted-git-info": "^2.7.1", - "osenv": "^0.1.5", - "semver": "^5.6.0", - "validate-npm-package-name": "^3.0.0" - } - }, - "npm-packlist": { - "version": "1.4.8", - "bundled": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-pick-manifest": { - "version": "3.0.2", - "bundled": true, - "requires": { - "figgy-pudding": "^3.5.1", - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" - } - }, - "npm-profile": { - "version": "4.0.4", - "bundled": true, - "requires": { - "aproba": "^1.1.2 || 2", - "figgy-pudding": "^3.4.1", - "npm-registry-fetch": "^4.0.0" - } - }, - "npm-registry-fetch": { - "version": "4.0.5", - "bundled": true, - "requires": { - "JSONStream": "^1.3.4", - "bluebird": "^3.5.1", - "figgy-pudding": "^3.4.1", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^5.0.0", - "npm-package-arg": "^6.1.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "bundled": true - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "bundled": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npm-user-validate": { - "version": "1.0.0", - "bundled": true - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "oauth-sign": { - "version": "0.9.0", - "bundled": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "object-keys": { - "version": "1.0.12", - "bundled": true - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "bundled": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "opener": { - "version": "1.5.1", - "bundled": true - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-locale": { - "version": "3.1.0", - "bundled": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "bundled": 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" - } - }, - "execa": { - "version": "1.0.0", - "bundled": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - } - } - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-defer": { - "version": "1.0.0", - "bundled": true - }, - "p-finally": { - "version": "1.0.0", - "bundled": true - }, - "p-is-promise": { - "version": "2.1.0", - "bundled": true - }, - "p-limit": { - "version": "1.2.0", - "bundled": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "bundled": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "bundled": true - }, - "package-json": { - "version": "4.0.1", - "bundled": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "pacote": { - "version": "9.5.12", - "bundled": true, - "requires": { - "bluebird": "^3.5.3", - "cacache": "^12.0.2", - "chownr": "^1.1.2", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.1.0", - "glob": "^7.1.3", - "infer-owner": "^1.0.4", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^5.0.0", - "minimatch": "^3.0.4", - "minipass": "^2.3.5", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.4.0", - "npm-normalize-package-bin": "^1.0.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.1.12", - "npm-pick-manifest": "^3.0.0", - "npm-registry-fetch": "^4.0.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.1", - "rimraf": "^2.6.2", - "safe-buffer": "^5.1.2", - "semver": "^5.6.0", - "ssri": "^6.0.1", - "tar": "^4.4.10", - "unique-filename": "^1.1.1", - "which": "^1.3.1" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "parallel-transform": { - "version": "1.1.0", - "bundled": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "path-exists": { - "version": "3.0.0", - "bundled": true - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "path-is-inside": { - "version": "1.0.2", - "bundled": true - }, - "path-key": { - "version": "2.0.1", - "bundled": true - }, - "path-parse": { - "version": "1.0.6", - "bundled": true - }, - "performance-now": { - "version": "2.1.0", - "bundled": true - }, - "pify": { - "version": "3.0.0", - "bundled": true - }, - "prepend-http": { - "version": "1.0.4", - "bundled": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true - }, - "promise-inflight": { - "version": "1.0.1", - "bundled": true - }, - "promise-retry": { - "version": "1.1.1", - "bundled": true, - "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" - }, - "dependencies": { - "retry": { - "version": "0.10.1", - "bundled": true - } - } - }, - "promzard": { - "version": "0.3.0", - "bundled": true, - "requires": { - "read": "1" - } - }, - "proto-list": { - "version": "1.2.4", - "bundled": true - }, - "protoduck": { - "version": "5.0.1", - "bundled": true, - "requires": { - "genfun": "^5.0.0" - } - }, - "prr": { - "version": "1.0.1", - "bundled": true - }, - "pseudomap": { - "version": "1.0.2", - "bundled": true - }, - "psl": { - "version": "1.1.29", - "bundled": true - }, - "pump": { - "version": "3.0.0", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "bundled": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "1.4.1", - "bundled": true - }, - "qrcode-terminal": { - "version": "0.12.0", - "bundled": true - }, - "qs": { - "version": "6.5.2", - "bundled": true - }, - "query-string": { - "version": "6.8.2", - "bundled": true, - "requires": { - "decode-uri-component": "^0.2.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, - "qw": { - "version": "1.0.1", - "bundled": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "bundled": true - } - } - }, - "read": { - "version": "1.0.7", - "bundled": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "1.0.5", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "read-installed": { - "version": "4.0.3", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "graceful-fs": "^4.1.2", - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "slide": "~1.1.3", - "util-extend": "^1.0.1" - } - }, - "read-package-json": { - "version": "2.1.1", - "bundled": true, - "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "npm-normalize-package-bin": "^1.0.0" - } - }, - "read-package-tree": { - "version": "5.3.1", - "bundled": true, - "requires": { - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "util-promisify": "^2.1.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "bundled": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdir-scoped-modules": { - "version": "1.1.0", - "bundled": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "registry-auth-token": { - "version": "3.4.0", - "bundled": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "bundled": true, - "requires": { - "rc": "^1.0.1" - } - }, - "request": { - "version": "2.88.0", - "bundled": true, - "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" - } - }, - "require-directory": { - "version": "2.1.1", - "bundled": true - }, - "require-main-filename": { - "version": "1.0.1", - "bundled": true - }, - "resolve-from": { - "version": "4.0.0", - "bundled": true - }, - "retry": { - "version": "0.12.0", - "bundled": true - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-queue": { - "version": "1.0.3", - "bundled": true, - "requires": { - "aproba": "^1.1.1" - }, - "dependencies": { - "aproba": { - "version": "1.2.0", - "bundled": true - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true - }, - "semver": { - "version": "5.7.1", - "bundled": true - }, - "semver-diff": { - "version": "2.1.0", - "bundled": true, - "requires": { - "semver": "^5.0.3" - } - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - }, - "sha": { - "version": "3.0.0", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "bundled": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "slide": { - "version": "1.1.6", - "bundled": true - }, - "smart-buffer": { - "version": "4.1.0", - "bundled": true - }, - "socks": { - "version": "2.3.3", - "bundled": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "bundled": true, - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "bundled": true, - "requires": { - "es6-promisify": "^5.0.0" - } - } - } - }, - "sorted-object": { - "version": "2.0.1", - "bundled": true - }, - "sorted-union-stream": { - "version": "2.1.3", - "bundled": true, - "requires": { - "from2": "^1.3.0", - "stream-iterate": "^1.1.0" - }, - "dependencies": { - "from2": { - "version": "1.3.0", - "bundled": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "~1.1.10" - } - }, - "isarray": { - "version": "0.0.1", - "bundled": true - }, - "readable-stream": { - "version": "1.1.14", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "bundled": true - } - } - }, - "spdx-correct": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "bundled": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "bundled": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "bundled": true - }, - "split-on-first": { - "version": "1.1.0", - "bundled": true - }, - "sshpk": { - "version": "1.14.2", - "bundled": true, - "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" - } - }, - "ssri": { - "version": "6.0.1", - "bundled": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "stream-each": { - "version": "1.2.2", - "bundled": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-iterate": { - "version": "1.2.0", - "bundled": true, - "requires": { - "readable-stream": "^2.1.5", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "stream-shift": { - "version": "1.0.0", - "bundled": true - }, - "strict-uri-encode": { - "version": "2.0.0", - "bundled": true - }, - "string-width": { - "version": "2.1.1", - "bundled": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "bundled": true - }, - "strip-ansi": { - "version": "4.0.0", - "bundled": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.3.0", - "bundled": true, - "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.0", - "bundled": true - } - } - }, - "stringify-package": { - "version": "1.0.1", - "bundled": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "bundled": true - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - }, - "supports-color": { - "version": "5.4.0", - "bundled": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - }, - "dependencies": { - "minipass": { - "version": "2.9.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - } - } - }, - "term-size": { - "version": "1.2.0", - "bundled": true, - "requires": { - "execa": "^0.7.0" - } - }, - "text-table": { - "version": "0.2.0", - "bundled": true - }, - "through": { - "version": "2.3.8", - "bundled": true - }, - "through2": { - "version": "2.0.3", - "bundled": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "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" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "timed-out": { - "version": "4.0.1", - "bundled": true - }, - "tiny-relative-date": { - "version": "1.3.0", - "bundled": true - }, - "tough-cookie": { - "version": "2.4.3", - "bundled": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "optional": true - }, - "typedarray": { - "version": "0.0.6", - "bundled": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true - }, - "umask": { - "version": "1.1.0", - "bundled": true - }, - "unique-filename": { - "version": "1.1.1", - "bundled": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.0", - "bundled": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-string": { - "version": "1.0.0", - "bundled": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "bundled": true - }, - "unzip-response": { - "version": "2.0.1", - "bundled": true - }, - "update-notifier": { - "version": "2.5.0", - "bundled": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "url-parse-lax": { - "version": "1.0.0", - "bundled": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "util-extend": { - "version": "1.0.3", - "bundled": true - }, - "util-promisify": { - "version": "2.1.0", - "bundled": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "uuid": { - "version": "3.3.3", - "bundled": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "bundled": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "locate-path": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.0.0.tgz", + "integrity": "sha512-+cg2yXqDUKfo4hsFxwa3G1cBJeA+gs1vD8FyV9/odWoUlQe/4syxHQ5DPtKjtfm6gnKbZzjCqzX03kXosvZB1w==", + "requires": { + "p-locate": "^6.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { "version": "3.0.0", - "bundled": true, - "requires": { - "builtins": "^1.0.3" - } - }, - "verror": { - "version": "1.10.0", - "bundled": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "bundled": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "1.3.1", - "bundled": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } + } + }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "requires": { + "mime-db": "1.51.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, + "dependencies": { + "sort-keys": { "version": "2.0.0", - "bundled": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "requires": { - "string-width": "^1.0.2" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "widest-line": { - "version": "2.0.1", - "bundled": true, - "requires": { - "string-width": "^2.1.1" - } - }, - "worker-farm": { - "version": "1.7.0", - "bundled": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "bundled": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": 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", - "bundled": true - }, - "write-file-atomic": { - "version": "2.4.3", - "bundled": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "bundled": true - }, - "xtend": { - "version": "4.0.1", - "bundled": true - }, - "y18n": { - "version": "4.0.0", - "bundled": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true - }, - "yargs": { - "version": "11.1.1", - "bundled": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.1.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": { - "y18n": { - "version": "3.2.1", - "bundled": true - } - } - }, - "yargs-parser": { - "version": "9.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", "requires": { - "camelcase": "^4.1.0" + "is-plain-obj": "^1.0.0" } } } @@ -5449,6 +2030,13 @@ "requires": { "config-chain": "^1.1.11", "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + } } }, "oauth-sign": { @@ -5461,68 +2049,39 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "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=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" - } + "object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "dev": true }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, "requires": { - "isobject": "^3.0.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" } }, "once": { @@ -5541,34 +2100,34 @@ "mimic-fn": "^2.1.0" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } }, "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=" }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "p-cancelable": { "version": "0.4.1", - "resolved": "http://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" }, "p-event": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.1.0.tgz", - "integrity": "sha512-sDEpDVnzLGlJj3k590uUdpfEUySP5yAYlvfTCu5hTDvSTXQVecYWKcEwdO49PrZlnJ5wkfAvtawnno/jyXeqvA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", "requires": { "p-timeout": "^2.0.1" } @@ -5580,9 +2139,25 @@ }, "p-is-promise": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "requires": { + "p-limit": "^4.0.0" + } + }, "p-timeout": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", @@ -5591,65 +2166,47 @@ "p-finally": "^1.0.0" } }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "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 + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "callsites": "^3.0.0" } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + "parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==" }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==" }, "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=" }, - "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-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "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-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "pend": { "version": "1.2.0", @@ -5662,9 +2219,9 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pinkie": { "version": "2.0.4", @@ -5679,10 +2236,11 @@ "pinkie": "^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=" + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true }, "prepend-http": { "version": "2.0.0", @@ -5690,9 +2248,15 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "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==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, "proto-list": { "version": "1.2.4", @@ -5700,48 +2264,23 @@ "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" }, "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" - }, - "q-io": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/q-io/-/q-io-1.13.6.tgz", - "integrity": "sha1-BFC9s54IfLiaX9SkFjfqM0fJhTg=", - "requires": { - "es6-set": "^0.1.1", - "mime": "^1.2.11", - "mimeparse": "^0.1.4", - "q": "^1.0.1", - "qs": "^1.2.1", - "url2": "^0.0.0" - }, - "dependencies": { - "qs": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", - "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=" - } - } + "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==" + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" }, "query-string": { "version": "5.1.1", - "resolved": "http://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", "requires": { "decode-uri-component": "^0.2.0", @@ -5750,50 +2289,36 @@ } }, "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==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "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" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "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==" + } } }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -5802,7 +2327,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -5812,33 +2337,33 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" } }, - "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - } + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true }, "responselike": { "version": "1.0.2", @@ -5857,18 +2382,13 @@ "signal-exit": "^3.0.2" } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "run-async": { @@ -5877,25 +2397,17 @@ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" }, "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "requires": { "tslib": "^1.9.0" } }, "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==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" - } + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -5903,168 +2415,86 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "seek-bzip": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", - "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", "requires": { - "commander": "~2.8.1" + "commander": "^2.8.1" } }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } }, - "set-value": { + "shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "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=", - "requires": { - "is-extendable": "^0.1.0" - } - } + "shebang-regex": "^3.0.0" } }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true }, - "sinon": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.1.0.tgz", - "integrity": "sha512-ffASxced8xr8eU0EGyfj9K++bRCtv/NyOFOxl7UBD86YH97oZjVxvecMhObwRlXe27GRUa6rVFEn67khPZ29rQ==", + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dev": true, "requires": { - "@sinonjs/commons": "^1.0.2", - "@sinonjs/formatio": "^3.0.0", - "@sinonjs/samsam": "^2.1.2", - "diff": "^3.5.0", - "lodash.get": "^4.4.2", - "lolex": "^3.0.0", - "nise": "^1.4.6", - "supports-color": "^5.5.0", - "type-detect": "^4.0.8" - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "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": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "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=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.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==", + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "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==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { - "kind-of": "^6.0.0" + "color-convert": "^2.0.1" } }, - "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==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { - "kind-of": "^6.0.0" + "color-name": "~1.1.4" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true } } }, @@ -6084,50 +2514,21 @@ "sort-keys": "^1.0.0" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "requires": { - "atob": "^2.1.1", - "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=" - }, "speakingurl": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==" }, - "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==", - "requires": { - "extend-shallow": "^3.0.0" - } - }, "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sshpk": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", - "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -6140,44 +2541,39 @@ "tweetnacl": "~0.14.0" } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "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=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string_decoder": { @@ -6186,16 +2582,29 @@ "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": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", @@ -6204,6 +2613,12 @@ "is-natural-number": "^4.0.1" } }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "strip-outer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", @@ -6220,6 +2635,45 @@ "has-flag": "^3.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ajv": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, "tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", @@ -6234,15 +2688,15 @@ "xtend": "^4.0.0" } }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "through": { "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "timed-out": { @@ -6263,51 +2717,13 @@ "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" }, - "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=", - "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=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "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=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, "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==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "^1.1.28", + "punycode": "^2.1.1" } }, "trim-repeated": { @@ -6318,6 +2734,18 @@ "escape-string-regexp": "^1.0.2" } }, + "tsconfig-paths": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -6336,117 +2764,58 @@ "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 - }, - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" - }, - "unbzip2-stream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz", - "integrity": "sha512-fIZnvdjblYs7Cru/xC6tCPVhz7JkYcVQQkePwMLyQELzYTds2Xn8QefPVnvdVhhZqubxNA1cASXEH5wcK0Bucw==", + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "requires": { - "buffer": "^3.0.1", - "through": "^2.3.6" + "prelude-ls": "^1.2.1" } }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" }, - "underscore.string": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", - "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, "requires": { - "sprintf-js": "^1.0.3", - "util-deprecate": "^1.0.2" + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" } }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "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=", - "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=", - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "buffer": "^5.2.1", + "through": "^2.3.8" } }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "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=", - "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=", - "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=" - } + "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, "url-join": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", - "integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" }, "url-parse-lax": { "version": "3.0.0", @@ -6461,33 +2830,21 @@ "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" }, - "url2": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/url2/-/url2-0.0.0.tgz", - "integrity": "sha1-Tqq9HVw6yQ1iq0SFyZhCKGWgSxo=" - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, "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.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, - "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "requires": { - "homedir-polyfill": "^1.0.1" - } + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true }, "verror": { "version": "1.10.0", @@ -6497,25 +2854,57 @@ "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" + }, + "dependencies": { + "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=" + } } }, "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yauzl": { "version": "2.10.0", @@ -6525,6 +2914,11 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==" } } } diff --git a/package.json b/package.json index bd31b72..64be37a 100644 --- a/package.json +++ b/package.json @@ -1,49 +1,40 @@ { "name": "adapt-cli", - "version": "2.1.14", + "version": "3.0.0", "description": "Command line tools for Adapt", - "main": "./lib/cli.js", - "directories": { - "test": "test" - }, + "main": "./lib/api.js", + "type": "module", "dependencies": { - "async": "^3.1.0", - "bower": "^1.8.4", + "async": "^3.2.3", + "bower": "^1.8.13", "bower-endpoint-parser": "^0.2.2", "chalk": "^2.4.1", - "debug": "^4.1.0", + "decompress": "^4.2.1", "download": "^7.1.0", - "grunt": "^1.0.3", + "find-up": "^6.2.0", + "fs-extra": "^10.0.0", + "globs": "^0.1.4", "inquirer": "^7.3.3", "json-lint": "^0.1.0", - "lodash": "^4.17.11", - "mkdirp": "^0.5.1", - "npm": "^6.4.1", - "q": "^1.5.1", - "q-io": "^1.13.6", + "lodash-es": "^4.17.21", + "parse-github-url": "^1.0.2", "request": "^2.88.0", - "semver": "^5.6.0", + "semver": "^7.3.5", "speakingurl": "^14.0.1", "url-join": "^4.0.0", "uuid": "^3.3.2" }, - "devDependencies": { - "expect.js": "^0.3.1", - "grunt-mocha-test": "^0.13.3", - "matchdep": "^2.0.0", - "mocha": "^5.2.0", - "mockery": "^2.1.0", - "rimraf": "^2.6.2", - "sinon": "^7.1.0" - }, - "scripts": { - "test": "grunt test" - }, - "author": "", "repository": "http://github.com/adaptlearning/adapt-cli", "license": "GPL-3.0", "preferGlobal": true, "bin": { - "adapt": "./bin/adapt" + "adapt": "./bin/adapt.js" + }, + "devDependencies": { + "eslint": "^7.31.0", + "eslint-config-standard": "^16.0.3", + "eslint-plugin-import": "^2.23.4", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^5.1.0" } } diff --git a/test/fixtures/adapt-with-plugins.json b/test/fixtures/adapt-with-plugins.json deleted file mode 100644 index 05d1cb4..0000000 --- a/test/fixtures/adapt-with-plugins.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "dependencies": { - "adapt-component" : "0.0.1", - "adapt-extension" : "0.0.2" - } -} \ No newline at end of file diff --git a/test/fixtures/adapt.json b/test/fixtures/adapt.json deleted file mode 100644 index e0f1805..0000000 --- a/test/fixtures/adapt.json +++ /dev/null @@ -1 +0,0 @@ -{"dependencies":{"adapt-component":"0.0.1","adapt-extension":"0.0.2"}} \ No newline at end of file diff --git a/test/specs/command_translation_concerns.js b/test/specs/command_translation_concerns.js deleted file mode 100644 index c02e0c2..0000000 --- a/test/specs/command_translation_concerns.js +++ /dev/null @@ -1,13 +0,0 @@ -var mockery = require('mockery'), - sinon = require('sinon'), - expect = require('expect.js'), - CommandTranslator = require('../../lib/CommandTranslator'); - -describe('Given I a list of parameters', function () { - describe('when I translate them', function () { - it('should translate -v to version', function () { - var parameters = [ '-v' ]; - expect(CommandTranslator(parameters)[0]).to.be('version'); - }); - }); -}); \ No newline at end of file diff --git a/test/specs/create_command_concerns.js b/test/specs/create_command_concerns.js deleted file mode 100644 index 21166f1..0000000 --- a/test/specs/create_command_concerns.js +++ /dev/null @@ -1,22 +0,0 @@ -var mockery = require('mockery'), - sinon = require('sinon'), - expect = require('expect.js'), - Q = require('q'), - Constants = require('../../lib/Constants'), - Project = require('../../lib/Project'), - Plugin = require('../../lib/Plugin'), - rimraf = require('rimraf'); - -/* mockery is just too slow to run as a unit test -describe('Given I have an create command', function () { - describe('when I create a course', function () { - it('should download the framework', function (done) { - var command = require('../../lib/commands/create'); - command.create(console, 'course', './downloaded-files', 'develop', function () { - expect(false).to.be(true); - done(); - }); - }); - }); -}); -*/ \ No newline at end of file diff --git a/test/specs/create_concerns.js b/test/specs/create_concerns.js deleted file mode 100644 index 8bf5a9b..0000000 --- a/test/specs/create_concerns.js +++ /dev/null @@ -1,30 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'); - -describe('Given I have an application', function () { - var AdaptConsoleApplication = require('../../lib/AdaptConsoleApplication'), - CommandParser = require('../../lib/CommandParser'), - createResult = { - success: true - }, - commands = { - create: sinon.stub().yields(null, createResult) - }, - outputDevice = { - log: sinon.stub() - }, - argsv = function () { - return ['node', 'create-concerns.js'].concat(Array.prototype.slice.call(arguments)); - }, - app = new AdaptConsoleApplication(commands, outputDevice); - - describe('when I execute a create command', function () { - it('should create the package', function (done) { - var create_command = new CommandParser(argsv('create', 'package-name')); - app.do(create_command, function (err, results) { - expect(commands.create.calledWith(outputDevice, 'package-name')).to.be(true); - done(); - }); - }); - }); -}); \ No newline at end of file diff --git a/test/specs/install_concerns.js b/test/specs/install_concerns.js deleted file mode 100644 index fbc74ee..0000000 --- a/test/specs/install_concerns.js +++ /dev/null @@ -1,31 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'); - -describe('Given I have an application', function () { - var AdaptConsoleApplication = require('../../lib/AdaptConsoleApplication'), - CommandParser = require('../../lib/CommandParser'), - installResult = { - success: true - }, - commands = { - install: sinon.stub().yields(null, installResult) - }, - outputDevice = { - log: sinon.stub() - }, - argsv = function () { - return ['node', 'search-concerns.js'].concat(Array.prototype.slice.call(arguments)); - }, - app = new AdaptConsoleApplication(commands, outputDevice); - - describe('when I execute an install command for an existing package', function () { - it('should install the package', function (done) { - var install_command = new CommandParser(argsv('install', 'package-name')); - app.do(install_command, function (err, results) { - expect(commands.install.calledWith(outputDevice, 'package-name')).to.be(true); - done(); - }); - }); - }); - -}); \ No newline at end of file diff --git a/test/specs/installing_compatible_plugins_concerns.js b/test/specs/installing_compatible_plugins_concerns.js deleted file mode 100644 index ce916c2..0000000 --- a/test/specs/installing_compatible_plugins_concerns.js +++ /dev/null @@ -1,126 +0,0 @@ -var fs = require('fs'), - sinon = require('sinon'), - expect = require('expect.js'), - Project = require('../../lib/Project'), - RendererHelpers = require('../../lib/RendererHelpers'), - Q = require('q'); - -describe('Given that I have Adapt Framework version 2', function () { - describe('When I install a plugin that is tagged as compatible with Adapt V2 framework version', function () { - before(function () { - fs.writeFileSync('./adapt.json', JSON.stringify(require('../fixtures/adapt.json'))); - }); - - it('should install it', function (done) { - - var context = createContext({ - pluginCompatibility: '~2.0.0', - frameworkVersion: '2.0.0' - }); - - var installCommand = require('../../lib/commands/install')(context); - - installCommand.install(context.renderer, 'plugin', function () { - expect(context.install.called).to.be(true); - done(); - }); - }); - - after(function() { - fs.unlinkSync('./adapt.json'); - Project.prototype.getFrameworkVersion.restore(); - RendererHelpers.reportCompatibilityWarning.restore(); - }); - }); -}); - -describe('Given that I have Adapt Framework version 1.1.1 or earlier', function () { - describe('When I install a plugin that is tagged as compatible with Adapt V1.1 framework version', function () { - before(function () { - fs.writeFileSync('./adapt.json', JSON.stringify(require('../fixtures/adapt.json'))); - }); - - it('should install it', function (done) { - - var context = createContext({ - pluginCompatibility: '1.1.1', - frameworkVersion: '1.1.1' - }); - - var installCommand = require('../../lib/commands/install')(context); - - installCommand.install(context.renderer, 'plugin', function (err) { - expect(context.install.called).to.be(true); - done(); - }); - }); - - after(function() { - fs.unlinkSync('./adapt.json'); - Project.prototype.getFrameworkVersion.restore(); - RendererHelpers.reportCompatibilityWarning.restore(); - }); - }); -}); - -describe('Given that I have Adapt Framework version 1.1.1 or earlier', function () { - describe('When I install a plugin that is NOT tagged', function () { - before(function () { - fs.writeFileSync('./adapt.json', JSON.stringify(require('../fixtures/adapt.json'))); - }); - - it('should install it', function (done) { - - var context = createContext({ - pluginCompatibility: '*', - frameworkVersion: '1.1.1' - }); - - var installCommand = require('../../lib/commands/install')(context); - - installCommand.install(context.renderer, 'plugin', function () { - expect(context.install.called).to.be(true); - done(); - }); - }); - - after(function() { - fs.unlinkSync('./adapt.json'); - Project.prototype.getFrameworkVersion.restore(); - RendererHelpers.reportCompatibilityWarning.restore(); - }); - }); -}); - -function createContext(values) { - var getKeywordsSuccessfully = Q.defer(), - getFrameworkCompatibilitySuccessfully = Q.defer(), - installSuccessfully = Q.defer(); - - getKeywordsSuccessfully.resolve('adapt-extension'); - getFrameworkCompatibilitySuccessfully.resolve(values.pluginCompatibility); - installSuccessfully.resolve(true); - - var warning = sinon.stub().yields(); - - var stubs = { - bower: { - commands: { - install: sinon.stub() - } - }, - renderer: values.renderer || { log: sinon.stub() }, - RendererHelpers: RendererHelpers, - Project: Project, - PackageMeta: { - getKeywords: sinon.stub().returns(getKeywordsSuccessfully.promise), - getFrameworkCompatibility: sinon.stub().returns(getFrameworkCompatibilitySuccessfully.promise) - }, - install: sinon.stub().returns(installSuccessfully.promise), - warning: warning - }; - - sinon.stub(stubs.RendererHelpers, 'reportCompatibilityWarning').returns(warning); - sinon.stub(stubs.Project.prototype, 'getFrameworkVersion').returns(values.frameworkVersion); - return stubs; -} diff --git a/test/specs/installing_incompatible_plugins_concerns.js b/test/specs/installing_incompatible_plugins_concerns.js deleted file mode 100644 index 90113f8..0000000 --- a/test/specs/installing_incompatible_plugins_concerns.js +++ /dev/null @@ -1,103 +0,0 @@ -var fs = require('fs'), - sinon = require('sinon'), - expect = require('expect.js'), - Project = require('../../lib/Project'), - RendererHelpers = require('../../lib/RendererHelpers'), - Q = require('q'); - -describe('Given that I have Adapt Framework version 2', function () { - describe('When I install a plugin that is tagged as incompatible with Adapt V2 framework version', function () { - before(function () { - fs.writeFileSync('./adapt.json', JSON.stringify(require('../fixtures/adapt.json'))); - }); - - it('should warn that the plugin is incompatible', function (done) { - - var context = createContext({ - frameworkVersion: '2.0.0', - pluginCompatibility: '1.1.1' - }); - - var installCommand = require('../../lib/commands/install')(context); - - installCommand.install(context.renderer, 'plugin', function (err) { - try { - expect(RendererHelpers.reportCompatibilityWarning.called).to.be(true); - done(); - } - catch(ex) { done(ex); } - }); - }); - - after(function() { - fs.unlinkSync('./adapt.json'); - Project.prototype.getFrameworkVersion.restore(); - RendererHelpers.reportCompatibilityWarning.restore(); - }); - }); -}); - -describe('Given that I have Adapt Framework version 1.1.1 or earlier', function () { - describe('When I install a plugin that is tagged as compatible with Adapt V2 framework version', function () { - before(function () { - fs.writeFileSync('./adapt.json', JSON.stringify(require('../fixtures/adapt.json'))); - }); - - it('should warn that the plugin is incompatible', function (done) { - - var context = createContext({ - frameworkVersion: '1.1.1', - pluginCompatibility: '>2.0.0' - }); - - var installCommand = require('../../lib/commands/install')(context); - - installCommand.install(context.renderer, 'plugin', function (err) { - try { - expect(RendererHelpers.reportCompatibilityWarning.called).to.be(true); - done(); - } - catch(ex) { done(ex); } - }); - }); - - after(function() { - fs.unlinkSync('./adapt.json'); - Project.prototype.getFrameworkVersion.restore(); - RendererHelpers.reportCompatibilityWarning.restore(); - }); - }); -}); - -function createContext(values) { - var getKeywordsSuccessfully = Q.defer(), - getFrameworkCompatibilitySuccessfully = Q.defer(), - userAbandonsInstallation = Q.defer(), - installSuccessfully = Q.defer(); - - getKeywordsSuccessfully.resolve('adapt-extension'); - getFrameworkCompatibilitySuccessfully.resolve(values.pluginCompatibility); - userAbandonsInstallation.resolve({ continueWithInstall: true }); - installSuccessfully.resolve(true); - - var stubs = { - bower: { - commands: { - install: sinon.stub() - } - }, - renderer: { log: sinon.stub() }, - RendererHelpers: RendererHelpers, - Project: Project, - PackageMeta: { - getKeywords: sinon.stub().returns(getKeywordsSuccessfully.promise), - getFrameworkCompatibility: sinon.stub().returns(getFrameworkCompatibilitySuccessfully.promise) - }, - install: sinon.stub().returns(installSuccessfully.promise) - }; - - sinon.stub(stubs.RendererHelpers, 'reportCompatibilityWarning').returns(userAbandonsInstallation.promise); - sinon.stub(stubs.Project.prototype, 'getFrameworkVersion').returns(values.frameworkVersion); - return stubs; -} - diff --git a/test/specs/ls_concerns.js b/test/specs/ls_concerns.js deleted file mode 100644 index 6767267..0000000 --- a/test/specs/ls_concerns.js +++ /dev/null @@ -1,28 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'); - -describe('Given I have an application', function () { - var AdaptConsoleApplication = require('../../lib/AdaptConsoleApplication'), - CommandParser = require('../../lib/CommandParser'), - commands = { - ls: sinon.stub().yields() - }, - outputDevice = { - log: sinon.stub() - }, - argsv = function () { - return ['node', 'search-concerns.js'].concat(Array.prototype.slice.call(arguments)); - }, - app = new AdaptConsoleApplication(commands, outputDevice); - - describe('when I execute an ls command for an existing package', function () { - it('should list the package', function (done) { - var ls_command = new CommandParser(argsv('ls')); - app.do(ls_command, function (err, results) { - expect(commands.ls.calledWith(outputDevice)).to.be(true); - done(); - }); - }); - }); - -}); \ No newline at end of file diff --git a/test/specs/plugin_name_concerns.js b/test/specs/plugin_name_concerns.js deleted file mode 100644 index aa22d9c..0000000 --- a/test/specs/plugin_name_concerns.js +++ /dev/null @@ -1,82 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'); - -describe('Given I have a name', function () { - var Plugin = require('../../lib/Plugin'); - - describe('when I create a plugin from a package name', function () { - it('should prefix the name with "adapt"', function () { - var plugin = new Plugin('myPackage'); - expect(plugin.packageName).to.match(/^adapt-myPackage$/); - }); - - it('should default the version to "*"', function () { - var plugin = new Plugin('package'); - expect(plugin.version).to.match(/^\*$/); - }); - - it('should stringify to the bower endpoint', function () { - var plugin = new Plugin('package'); - expect(plugin.toString()).to.match(/^adapt-package$/); - }); - }); - - describe('when I create a plugin from a multiple word package name', function () { - it('should convert the name to a suitable name with hyphens', function () { - var plugin = new Plugin('my adapt package'); - expect(plugin.packageName).to.match(/^adapt-my-adapt-package$/); - }); - }); - - describe('when I create a plugin from a specific version package name', function () { - it('should parse the correct version', function () { - var plugin = new Plugin('package' ,'1.0.0'); - expect(plugin.packageName).to.match(/^adapt-package$/); - expect(plugin.version).to.match(/^1.0.0$/); - }); - - it('should stringify to the bower endpoint', function () { - var plugin = new Plugin('package', '1.0.0'); - expect(plugin.toString()).to.match(/^adapt-package#1.0.0$/); - }); - }); - - describe('when I create a contrib plugin from a package name', function () { - it('should be contrib', function () { - var plugin = new Plugin('package', true); - expect(plugin.isContrib).to.be(true); - }); - - it('should prefix the name with "adapt-contrib"', function () { - var plugin = new Plugin('package', true); - expect(plugin.packageName).to.match(/^adapt-contrib-/); - }); - }); - - describe('when I create a specific version of a contrib plugin from a package name', function () { - it('should be contrib', function () { - var plugin = new Plugin('package', '1.0.0', true); - expect(plugin.isContrib).to.be(true); - }); - - it('should prefix the name with "adapt-contrib"', function () { - var plugin = new Plugin('package', '1.0.0', true); - expect(plugin.packageName).to.match(/^adapt-contrib-/); - }); - }); - - describe('when I create a plugin from a 0.0.0 version', function () { - it('should support any version', function () { - var plugin = new Plugin('package' ,'0.0.0'); - expect(plugin.packageName).to.match(/^adapt-package$/); - expect(plugin.version).to.match(/^\*$/); - }); - - it('should stringify to the bower endpoint for any version', function () { - var plugin = new Plugin('package', '0.0.0'); - expect(plugin.toString()).to.match(/^adapt-package$/); - }); - }); - - -}); \ No newline at end of file diff --git a/test/specs/project_concerns.js b/test/specs/project_concerns.js deleted file mode 100644 index e66302b..0000000 --- a/test/specs/project_concerns.js +++ /dev/null @@ -1,128 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'), - fs = require('fs'), - Project = require('../../lib/Project'), - Plugin = require('../../lib/Plugin'); - -describe('Given I have an adapt.json project file with no installed plugins', function () { - - describe('when I list all plugins', function () { - it('should provide an empty list', function () { - var project = new Project(); - expect(project.plugins).to.be.an(Array); - expect(project.plugins.length).to.be(0); - }); - }); - -}); - -describe('Given I have an adapt.json project file with plugins', function () { - - describe('when I list all plugins', function () { - before(function () { - fs.writeFileSync('./test/fixtures/adapt-when-i-list-plugins.json', JSON.stringify(require('../fixtures/adapt-with-plugins.json'))); - }); - - it('should provide a list of all plugins', function () { - var project = new Project('./test/fixtures/adapt-when-i-list-plugins.json'); - expect(project.plugins).to.be.an(Array); - expect(project.plugins.length).to.be(2); - expect(project.plugins[0].packageName).to.be('adapt-component'); - expect(project.plugins[0].version).to.be('0.0.1'); - expect(project.plugins[1].packageName).to.be('adapt-extension'); - expect(project.plugins[1].version).to.be('0.0.2'); - }); - - after(function () { - fs.unlinkSync('./test/fixtures/adapt-when-i-list-plugins.json'); - }); - }); - - describe('when I add a plugin', function () { - before(function () { - fs.writeFileSync('./test/fixtures/adapt-when-I-add-a-plugin.json', JSON.stringify(require('../fixtures/adapt-with-plugins.json'))); - }); - - it('should provide a list with the new plugins', function () { - var project = new Project('./test/fixtures/adapt-when-I-add-a-plugin.json'); - project.add(new Plugin('theme', '0.0.3')); - expect(project.plugins).to.be.an(Array); - expect(project.plugins.length).to.be(3); - expect(project.plugins[0].packageName).to.be('adapt-component'); - expect(project.plugins[0].version).to.be('0.0.1'); - expect(project.plugins[1].packageName).to.be('adapt-extension'); - expect(project.plugins[1].version).to.be('0.0.2'); - expect(project.plugins[2].packageName).to.be('adapt-theme'); - expect(project.plugins[2].version).to.be('0.0.3'); - }); - - after(function () { - fs.unlinkSync('./test/fixtures/adapt-when-I-add-a-plugin.json'); - }); - }); - - describe('when I remove a plugin', function () { - before(function () { - fs.writeFileSync('./test/fixtures/adapt-when-i-remove-a-plugin.json', JSON.stringify(require('../fixtures/adapt-with-plugins.json'))); - }); - - it('should no longer contain that plugin', function () { - var project = new Project('./test/fixtures/adapt-when-i-remove-a-plugin.json'); - project.remove(new Plugin('component')); - expect(project.plugins.length).to.be(1); - expect(project.plugins[0].packageName).to.be('adapt-extension'); - expect(project.plugins[0].version).to.be('0.0.2'); - }); - - after(function () { - fs.unlinkSync('./test/fixtures/adapt-when-i-remove-a-plugin.json'); - }); - }); - -}); - -describe('Given I have not got an adapt.json project file', function () { - - describe('when I add a plugin', function () { - before(function () { - if(fs.existsSync('./test/fixtures/adapt-missing.json')) { - fs.unlinkSync('./test/fixtures/adapt-missing.json'); - } - }); - - it('should create the file', function () { - var project = new Project('./test/fixtures/adapt-missing.json'); - project.add(new Plugin('theme', '0.0.3')); - - expect(fs.existsSync(project.manifestFilePath)).to.be(true); - - var created = new Project('./test/fixtures/adapt-missing.json') - expect(created.plugins.length).to.be(1); - expect(created.plugins[0].packageName).to.be('adapt-theme'); - expect(project.plugins[0].version).to.be('0.0.3'); - }); - - after(function () { - fs.unlinkSync('./test/fixtures/adapt-missing.json'); - }); - }); - -}); - -describe('Given I have a package.json file with a version number', function () { - describe('when I get the framework version', function () { - var version = "2.0.1"; - before(function () { - fs.writeFileSync('./test/fixtures/adapt-package-version.json', JSON.stringify({ "version": version })); - }); - - it('should provide the correct version number', function () { - var project = new Project(null, './test/fixtures/adapt-package-version.json') - expect(project.getFrameworkVersion()).to.be(version); - }); - - after(function () { - fs.unlinkSync('./test/fixtures/adapt-package-version.json'); - }); - }); -}); \ No newline at end of file diff --git a/test/specs/registration_concerns.js b/test/specs/registration_concerns.js deleted file mode 100644 index 8c34a6f..0000000 --- a/test/specs/registration_concerns.js +++ /dev/null @@ -1,31 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'); - -describe('Given I have an application', function () { - var AdaptConsoleApplication = require('../../lib/AdaptConsoleApplication'), - CommandParser = require('../../lib/CommandParser'), - registerResult = { - success: true - }, - commands = { - register: sinon.stub().yields(null, registerResult) - }, - outputDevice = { - log: sinon.stub() - }, - argsv = function () { - return ['node', 'register-concerns.js'].concat(Array.prototype.slice.call(arguments)); - }, - app = new AdaptConsoleApplication(commands, outputDevice); - - describe('when I execute a register command for a new package', function () { - it('should register the package', function (done) { - var register_command = new CommandParser(argsv('register', 'package-name', 'git-endpoint')); - app.do(register_command, function (err, results) { - expect(commands.register.calledWith(outputDevice, 'package-name', 'git-endpoint')).to.be(true); - done(); - }); - }); - }); - -}); \ No newline at end of file diff --git a/test/specs/repository_downloader_concerns.js b/test/specs/repository_downloader_concerns.js deleted file mode 100644 index 67ed594..0000000 --- a/test/specs/repository_downloader_concerns.js +++ /dev/null @@ -1,55 +0,0 @@ -var mockery = require('mockery'), - sinon = require('sinon'), - expect = require('expect.js'), - Q = require('q'), - Constants = require('../../lib/Constants'), - Project = require('../../lib/Project'), - Plugin = require('../../lib/Plugin'), - rimraf = require('rimraf'); - -describe('Given I have a repository downloader', function () { - describe('when fetch the repo', function () { - var location = './test/fixtures/downloaded-repo', - renderer = { - log: sinon.stub() - }, - eventEmitter = { - on: function (event, handler) { - if(event === 'close') { - setTimeout(handler, 100); - } - return eventEmitter; - }, - then: function(handler) { - setTimeout(handler, 100); - return this; - } - }, - download = sinon.stub().returns(eventEmitter); - - before(function () { - mockery.registerMock('download', download); - }); - - it('should download the repo to the target directory', function (done) { - mockery.enable({ warnOnUnregistered:false }); - var RepositoryDownloader = require('../../lib/RepositoryDownloader'), - downloader = new RepositoryDownloader({ - repository : 'https://github.com/adaptlearning/adapt-cli/', - branch : 'master' - }); - - downloader.fetch(location) - .then(function () { - expect(download.called).to.be(true); - done(); - }); - }); - - after(function () { - mockery.deregisterAll(); - mockery.disable(); - }); - }); - -}); \ No newline at end of file diff --git a/test/specs/search_concerns.js b/test/specs/search_concerns.js deleted file mode 100644 index 5290b29..0000000 --- a/test/specs/search_concerns.js +++ /dev/null @@ -1,30 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'); - -describe('Given I have an application', function () { - var AdaptConsoleApplication = require('../../lib/AdaptConsoleApplication'), - CommandParser = require('../../lib/CommandParser'), - searchResults = [ - "blah" - ], - commands = { - search: sinon.stub().yields(null, searchResults) - }, - outputDevice = { - log: sinon.stub() - }, - argsv = function () { - return ['node', 'search-concerns.js'].concat(Array.prototype.slice.call(arguments)); - }, - app = new AdaptConsoleApplication(commands, outputDevice); - - describe('when I execute a search command for a term', function () { - it('should perform a search for the term', function (done) { - var search_command = new CommandParser(argsv('search', 'term')); - app.do(search_command, function (err, results) { - expect(commands.search.calledWith(outputDevice, 'term')).to.be(true); - done(); - }); - }); - }); -}); \ No newline at end of file diff --git a/test/specs/type_resolution_concerns.js b/test/specs/type_resolution_concerns.js deleted file mode 100644 index 0ce2b16..0000000 --- a/test/specs/type_resolution_concerns.js +++ /dev/null @@ -1,71 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'); - -describe('Given I have a plugin type resolver', function () { - var PluginTypeResolver = require('../../lib/PluginTypeResolver'), - resolver = new PluginTypeResolver(); - - describe('when I resolve the keyword for a component', function () { - it('should provide a type of component', function () { - var keywords = ['adapt-component']; - - expect(resolver.resolve(keywords).typename).to.be('component'); - expect(resolver.resolve(keywords).belongsTo).to.be('components'); - }); - }); - - describe('when I resolve the keyword for an extension', function () { - it('should provide a type of extension', function () { - var keywords = ['adapt-extension']; - - expect(resolver.resolve(keywords).typename).to.be('extension'); - expect(resolver.resolve(keywords).belongsTo).to.be('extensions'); - }); - }); - - describe('when I resolve the keyword for a menu', function () { - it('should provide a type of menu', function () { - var keywords = ['adapt-menu']; - - expect(resolver.resolve(keywords).belongsTo).to.be('menu'); - expect(resolver.resolve(keywords).belongsTo).to.be('menu'); - }); - }); - - describe('when I resolve the keyword for a theme', function () { - it('should provide a type of theme', function () { - var keywords = ['adapt-theme']; - - expect(resolver.resolve(keywords).belongsTo).to.be('theme'); - expect(resolver.resolve(keywords).belongsTo).to.be('theme'); - }); - }); - - describe('when I have no keywords', function () { - it('should provide the default type', function () { - var keywords = undefined; - - expect(resolver.resolve(keywords).typename).to.be(resolver.defaultType.typename); - expect(resolver.resolve(keywords).belongsTo).to.be(resolver.defaultType.belongsTo); - }); - }); - - describe('when I have conflicting keywords', function () { - it('should provide the first matching type', function () { - var keywords = ['adapt-theme', 'adapt-extension']; - - expect(resolver.resolve(keywords).typename).to.be('theme'); - expect(resolver.resolve(keywords).belongsTo).to.be('theme'); - }); - }); - - describe('when I have an unknown keyword', function () { - it('should provide the first matching type', function () { - var keywords = ['unknown-keyword', 'adapt-theme']; - - expect(resolver.resolve(keywords).typename).to.be('theme'); - expect(resolver.resolve(keywords).belongsTo).to.be('theme'); - }); - }); - -}); \ No newline at end of file diff --git a/test/specs/uninstall_command_concerns.js b/test/specs/uninstall_command_concerns.js deleted file mode 100644 index d30b246..0000000 --- a/test/specs/uninstall_command_concerns.js +++ /dev/null @@ -1,64 +0,0 @@ -var fs = require('fs'), - mockery = require('mockery'), - sinon = require('sinon'), - expect = require('expect.js'), - Q = require('q'), - Project = require('../../lib/Project'), - Plugin = require('../../lib/Plugin'); - -describe('Given I have an uninstall command', function () { - describe('when I uninstall a plugin', function () { - var bower = { - commands: {} - }, - PackageMeta = { - }, - renderer = { - log: sinon.stub() - }; - - before(function () { - fs.writeFileSync('./adapt.json', JSON.stringify(require('../fixtures/adapt.json'))); - - mockery.enable(); - mockery.warnOnUnregistered(false); - - bower.commands.uninstall = sinon.stub().returns({ - on: function (event, done) { - if(event === 'end') { - setTimeout(done, 10, true); - } - return this; - } - }); - mockery.registerMock('bower', bower); - - PackageMeta.getKeywords = sinon.stub().returns(Q.fcall(function () { - return ['adapt-component']; - })); - mockery.registerMock('../PackageMeta', PackageMeta); - }); - - it('should get the keywords', function (done) { - var command = require('../../lib/commands/uninstall'); - command.uninstall(renderer, 'my-plugin', function () { - expect(PackageMeta.getKeywords.called).to.be(true); - done(); - }); - }); - - it('should invoke the bower uninstall command', function (done) { - var command = require('../../lib/commands/uninstall'); - command.uninstall(renderer, 'my-plugin', function () { - expect(bower.commands.uninstall.called).to.be(true); - done(); - }); - }); - - after(function () { - fs.unlinkSync('./adapt.json'); - mockery.disable(); - }); - }); - -}); diff --git a/test/specs/uninstall_concerns.js b/test/specs/uninstall_concerns.js deleted file mode 100644 index 084a802..0000000 --- a/test/specs/uninstall_concerns.js +++ /dev/null @@ -1,31 +0,0 @@ -var sinon = require('sinon'), - expect = require('expect.js'); - -describe('Given I have an application', function () { - var AdaptConsoleApplication = require('../../lib/AdaptConsoleApplication'), - CommandParser = require('../../lib/CommandParser'), - uninstallResult = { - success: true - }, - commands = { - uninstall: sinon.stub().yields(null, uninstallResult) - }, - outputDevice = { - log: sinon.stub() - }, - argsv = function () { - return ['node', 'search-concerns.js'].concat(Array.prototype.slice.call(arguments)); - }, - app = new AdaptConsoleApplication(commands, outputDevice); - - describe('when I execute an uninstall command for an existing package', function () { - it('should uninstall the package', function (done) { - var uninstall_command = new CommandParser(argsv('uninstall', 'package-name')); - app.do(uninstall_command, function (err, results) { - expect(commands.uninstall.calledWith(outputDevice, 'package-name')).to.be(true); - done(); - }); - }); - }); - -}); \ No newline at end of file