From 9c0ff78cbe1fcf594a5ad13bac40086db29537fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ey=C3=BE=C3=B3r=20Magn=C3=BAsson?= Date: Tue, 29 May 2018 17:36:55 +0200 Subject: [PATCH 1/9] docs: add Gitbook config file --- .gitbook.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .gitbook.yaml diff --git a/.gitbook.yaml b/.gitbook.yaml new file mode 100644 index 0000000000..cc4ea460c9 --- /dev/null +++ b/.gitbook.yaml @@ -0,0 +1,3 @@ +structure: + readme: README.md + summary: docs/README.md From de58dd5e28d7f3051cd0e2338b9dbcc92e690d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ey=C3=BE=C3=B3r=20Magn=C3=BAsson?= Date: Wed, 30 May 2018 11:23:39 +0200 Subject: [PATCH 2/9] docs: add basic scaffolding --- docs/README.md | 14 ++++++++++++++ docs/examples/README.md | 1 + docs/getting-started.md | 4 ---- docs/getting-started/README.md | 25 +++++++++++++++++++++++++ docs/guides/README.md | 7 +++++++ docs/guides/commands.md | 1 + docs/guides/configuration.md | 1 + docs/guides/features.md | 1 + docs/{ => guides}/minikube.md | 0 docs/{ => guides}/remote-kubernetes.md | 0 docs/other/README.md | 5 +++++ docs/other/faq.md | 1 + docs/other/glossary.md | 1 + docs/other/troubleshooting.md | 1 + 14 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/examples/README.md delete mode 100644 docs/getting-started.md create mode 100644 docs/getting-started/README.md create mode 100644 docs/guides/README.md create mode 100644 docs/guides/commands.md create mode 100644 docs/guides/configuration.md create mode 100644 docs/guides/features.md rename docs/{ => guides}/minikube.md (100%) rename docs/{ => guides}/remote-kubernetes.md (100%) create mode 100644 docs/other/README.md create mode 100644 docs/other/faq.md create mode 100644 docs/other/glossary.md create mode 100644 docs/other/troubleshooting.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..71c07fbcfc --- /dev/null +++ b/docs/README.md @@ -0,0 +1,14 @@ +# Table of Contents + +* [Read Me](../README.md) +* [Getting Started](./getting-started/README.md) +* [Guides](./guides/README.md) + * [Configuration](./guides/configuration.md) + * [Features](./guides/features.md) + * [Commands](./guides/commands.md) + * [Using Garden with Minikube](./guides/minikube.md) + * [Remote Kubernetes](./guides/remote-kubernetes.md) +* [Other](./other/README.md) + * [FAQ](./other/faq.md) + * [Glossary](./other/glossary.md) + * [Troubleshooting](./other/troubleshooting.md) diff --git a/docs/examples/README.md b/docs/examples/README.md new file mode 100644 index 0000000000..0ffdd02fcb --- /dev/null +++ b/docs/examples/README.md @@ -0,0 +1 @@ +// TODO \ No newline at end of file diff --git a/docs/getting-started.md b/docs/getting-started.md deleted file mode 100644 index e97deb4ec8..0000000000 --- a/docs/getting-started.md +++ /dev/null @@ -1,4 +0,0 @@ -## Getting started with Garden - -TODO - diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md new file mode 100644 index 0000000000..2a90f3aab6 --- /dev/null +++ b/docs/getting-started/README.md @@ -0,0 +1,25 @@ +# Getting Started + +This guide will walk you through setting up, and installing the Garden framework. + +## Requirements + +You need to set up the following on your local machine to use garden: +* Node.js >= 8.x +* [Docker](https://docs.docker.com/) +* Git +* rsync +* [Watchman](https://facebook.github.io/watchman/docs/install.html) +* Local installation of Kubernetes + +## Install + +// TODO + +## Using the CLI + +// TODO + +## What's next + +// TODO \ No newline at end of file diff --git a/docs/guides/README.md b/docs/guides/README.md new file mode 100644 index 0000000000..c315fa45cb --- /dev/null +++ b/docs/guides/README.md @@ -0,0 +1,7 @@ +# Guides + +* [Configuration](./configuration.md) +* [Features](./features.md) +* [Commands](./commands.md) +* [Using Garden with Minikube](./minikube.md) +* [Remote Kubernetes](./remote-kubernetes.md) diff --git a/docs/guides/commands.md b/docs/guides/commands.md new file mode 100644 index 0000000000..8ad1dfb535 --- /dev/null +++ b/docs/guides/commands.md @@ -0,0 +1 @@ +//TODO diff --git a/docs/guides/configuration.md b/docs/guides/configuration.md new file mode 100644 index 0000000000..8ad1dfb535 --- /dev/null +++ b/docs/guides/configuration.md @@ -0,0 +1 @@ +//TODO diff --git a/docs/guides/features.md b/docs/guides/features.md new file mode 100644 index 0000000000..8ad1dfb535 --- /dev/null +++ b/docs/guides/features.md @@ -0,0 +1 @@ +//TODO diff --git a/docs/minikube.md b/docs/guides/minikube.md similarity index 100% rename from docs/minikube.md rename to docs/guides/minikube.md diff --git a/docs/remote-kubernetes.md b/docs/guides/remote-kubernetes.md similarity index 100% rename from docs/remote-kubernetes.md rename to docs/guides/remote-kubernetes.md diff --git a/docs/other/README.md b/docs/other/README.md new file mode 100644 index 0000000000..adc42029b6 --- /dev/null +++ b/docs/other/README.md @@ -0,0 +1,5 @@ +# Other + +* [FAQ](./faq.md) +* [Glossary](./glossary.md) +* [Troubleshooting](./troubleshooting.md) diff --git a/docs/other/faq.md b/docs/other/faq.md new file mode 100644 index 0000000000..8ad1dfb535 --- /dev/null +++ b/docs/other/faq.md @@ -0,0 +1 @@ +//TODO diff --git a/docs/other/glossary.md b/docs/other/glossary.md new file mode 100644 index 0000000000..8ad1dfb535 --- /dev/null +++ b/docs/other/glossary.md @@ -0,0 +1 @@ +//TODO diff --git a/docs/other/troubleshooting.md b/docs/other/troubleshooting.md new file mode 100644 index 0000000000..8ad1dfb535 --- /dev/null +++ b/docs/other/troubleshooting.md @@ -0,0 +1 @@ +//TODO From 42ee9a50a54ac9a8609bfd7ee30f1a8111011849 Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Tue, 29 May 2018 15:00:58 +0200 Subject: [PATCH 3/9] docs: added Features section in README --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b12486772..f9214005dd 100644 --- a/README.md +++ b/README.md @@ -16,13 +16,32 @@ All that said, Garden can already be highly useful if the following applies to y * **You're deploying to (or transitioning to) Kubernetes.** * **You develop on Mac or Linux.** -* **You work mostly with containers _today_ (but perhaps plan on adopting serverless platforms in the future).** +* **You work mostly with containers** _**today**_ _\(but perhaps plan on adopting serverless platforms in the future\)._ +* **You keep all your services in a single repository** _(multi-repo support coming soon!)._ * **You really don't want to spend your precious hours building your own developer tooling!** If that sounds right for you, please give it a go and don't hesitate to report issues or come right over to our [Gitter](https://gitter.im/garden-io/Lobby#) for a chat! +## Features + +With Garden, you can... + +* Configure and deploy a fleet of services to a local Kubernetes cluster using simple declarations. +* Use an integrated framework for building, testing and deploying services. +* Easily run end-to-end tests across multiple services without waiting for a slow CI pipeline. +* Automatically build, deploy and/or test when your code changes, using the `--watch` flag or the `garden dev` command. +* Manage build and runtime dependencies across all your services. +* Leverage a suite of commands and helpers to facilitate developing and running your stack. +* _Write code the way you want, and run your production system however suits you! Garden does not impose any new +libraries or languages aside from the config files._ + +Garden is also designed to be pluggable and modular, with Kubernetes being just one plugin (albeit an important one). +Over time we will add native support for a variety of platforms, including AWS (Lambda, ECS, Fargate and more), +GCP, Heroku, OpenFaaS... and the list will continue growing. + + ## Setup ### Dependencies From 2ff8fa24e969a303e1a2db28f464e0b934b7632c Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Wed, 30 May 2018 00:11:13 +0200 Subject: [PATCH 4/9] docs: add script to auto-generate CLI command reference --- docs/reference/commands.md | 300 +++++ gulpfile.ts | 41 +- package-lock.json | 1456 ++++++++++++++++--------- package.json | 3 + src/cli/cli.ts | 39 +- src/commands/base.ts | 33 +- src/commands/call.ts | 4 + src/commands/environment/configure.ts | 2 +- src/commands/index.ts | 42 + src/docs/generate.ts | 48 + src/docs/templates/commands.hbs | 49 + 11 files changed, 1472 insertions(+), 545 deletions(-) create mode 100644 docs/reference/commands.md create mode 100644 src/commands/index.ts create mode 100644 src/docs/generate.ts create mode 100644 src/docs/templates/commands.hbs diff --git a/docs/reference/commands.md b/docs/reference/commands.md new file mode 100644 index 0000000000..5ce504a003 --- /dev/null +++ b/docs/reference/commands.md @@ -0,0 +1,300 @@ +## Garden CLI commands + +Below is a list of Garden CLI commands and usage information. + +The commands should be run in a Garden project root, and are always scoped to that project. + +Note: You can get a list of commands in the CLI by running `garden -h/--help`, +and detailed help for each command using `garden -h/--help` + +##### Global options + +The following option flags can be used with any of the CLI commands: + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--root` | `-r` | string | override project root directory (defaults to working directory) + | `--silent` | `-s` | boolean | suppress log output + | `--env` | `-e` | string | The environment (and optionally namespace) to work against + | `--loglevel` | `-log` | `error` `warn` `info` `verbose` `debug` `silly` | set logger level + | `--output` | `-o` | `json` `yaml` | output command result in specified format (note: disables progress logging) + +### garden build + +Build your modules. + +##### Usage + + garden build [module] [options] + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | No | Specify module(s) to build. Use comma separator to specify multiple modules. + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force` | | boolean | Force rebuild of module(s) + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-build + +### garden call + +Call a service endpoint. + +This resolves the external endpoint for the given service and path, calls the given endpoint and outputs the result. +##### Usage + + garden call + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `serviceAndPath` | Yes | The name of the service(s) to call followed by the endpoint path (e.g. my-container/somepath) + +### garden config get + +Get a configuration variable. + +##### Usage + + garden config get + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `key` | Yes | The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested) + +### garden config set + +Set a configuration variable. + +##### Usage + + garden config set + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `key` | Yes | The key of the configuration variable. Separate with dots to set a nested key (e.g. key.nested) + | `value` | Yes | The value of the configuration variable + +### garden config delete + +Delete a configuration variable. + +##### Usage + + garden config delete + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `key` | Yes | The key of the configuration variable + +### garden deploy + +Deploy service(s) to the specified environment. + +##### Usage + + garden deploy [service] [options] + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `service` | No | The name of the service(s) to deploy (skip to deploy all services). Use comma as separator to specify multiple services. + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force` | | boolean | Force redeploy of service(s) + | `--force-build` | | boolean | Force rebuild of module(s) + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-deploy + +### garden dev + +Starts the garden development console. + +##### Usage + + garden dev + +### garden environment configure + +Configures your environment. + +##### Usage + + garden environment configure [options] + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force` | | boolean | Force reconfiguration of environment + +### garden environment destroy + +Destroy environment. + +##### Usage + + garden environment destroy + +### garden login + +Log into the Garden framework. + +##### Usage + + garden login + +### garden logout + +Log into the Garden framework. + +##### Usage + + garden logout + +### garden logs + +Retrieves the most recent logs for the specified service(s). + +##### Usage + + garden logs [service] [options] + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `service` | No | The name of the service(s) to logs (skip to logs all services). Use comma as separator to specify multiple services. + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--tail` | `-t` | boolean | Continuously stream new logs from the service(s) + +### garden push + +Build and push module(s) to remote registry. + +##### Usage + + garden push [module] [options] + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | No | The name of the module(s) to push (skip to push all modules). Use comma as separator to specify multiple modules. + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force-build` | | boolean | Force rebuild of module(s) before pushing + | `--allow-dirty` | | boolean | Allow pushing dirty builds (with untracked/uncommitted files) + +### garden run module + +Run the specified module. + +##### Usage + + garden run module [command] [options] + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | Yes | The name of the module to run + | `command` | No | The command to run in the module + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result + | `--force-build` | | boolean | Force rebuild of module + +### garden run service + +Run an ad-hoc instance of the specified service. + +##### Usage + + garden run service [options] + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `service` | Yes | The service to run + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result + | `--force-build` | | boolean | Force rebuild of module + +### garden run test + +Run the specified module test. + +##### Usage + + garden run test [options] + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | Yes | The name of the module to run + | `test` | Yes | The name of the test to run in the module + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result + | `--force-build` | | boolean | Force rebuild of module + +### garden scan + +Scans your project and outputs an overview of all modules. + +##### Usage + + garden scan + +### garden status + +Outputs the status of your environment. + +##### Usage + + garden status + +### garden test + +Test all or specified modules. + +##### Usage + + garden test [module] [options] + +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | No | The name of the module(s) to deploy (skip to test all modules). Use comma as separator to specify multiple modules. + +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--group` | `-g` | string | Only run tests with the specfied group (e.g. unit or integ) + | `--force` | `-f` | boolean | Force re-test of module(s) + | `--force-build` | | boolean | Force rebuild of module(s) + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-test + +### garden validate + +Check your garden configuration for errors. + +##### Usage + + garden validate + diff --git a/gulpfile.ts b/gulpfile.ts index 7b3d8ff3e5..aeb6ea7be5 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -7,6 +7,7 @@ import { join, relative, } from "path" +import { generateDocs } from "./src/docs/generate" const gulp = require("gulp") const cached = require("gulp-cached") @@ -114,6 +115,11 @@ gulp.task("check-licenses", (cb) => spawn("./bin/check-licenses", [], cb), ) +gulp.task("generate-docs", (cb) => { + generateDocs("docs") + cb() +}) + gulp.task("mocha", (cb) => spawn("node_modules/.bin/nyc", ["node_modules/.bin/mocha"], cb), ) @@ -164,18 +170,6 @@ gulp.task("tsfmt", (cb) => { spawn("node_modules/.bin/tsfmt", ["--verify"], cb) }) -gulp.task("tsfmt-watch", () => { - const verify = (path) => { - try { - _spawn("node_modules/.bin/tsfmt", ["--verify", path], { stdio: "inherit" }) - } catch (_) { } - } - - return gulp.watch([tsSources, testTsSources]) - .on("add", verify) - .on("change", verify) -}) - gulp.task("tslint", () => gulp.src(tsSources) .pipe(cached("tslint")) @@ -195,16 +189,27 @@ gulp.task("tslint-tests", () => .pipe(gulpTslint.report()), ) -gulp.task("tslint-watch", () => - gulp.watch([tsSources, testTsSources], gulp.parallel("tslint", "tslint-tests")), -) +gulp.task("watch-code", () => { + const verify = (path) => { + try { + _spawn("node_modules/.bin/tsfmt", ["--verify", path], { stdio: "inherit" }) + } catch (_) { } + } + + return gulp.watch([tsSources, testTsSources], gulp.parallel("generate-docs", "tslint", "tslint-tests")) + .on("add", verify) + .on("change", verify) +}) gulp.task("lint", gulp.parallel("check-licenses", "tslint", "tslint-tests", "tsfmt")) -gulp.task("build", gulp.series(gulp.parallel("pegjs", "static", "tsc"), "add-version-files")) +gulp.task("build", gulp.series( + gulp.parallel("generate-docs", "pegjs", "static", "tsc"), + "add-version-files", +)) gulp.task("dist", gulp.series((done) => { setDestDir("dist"); done() }, "lint", "build")) gulp.task("test", gulp.parallel("build", "lint", "mocha")) gulp.task("watch", gulp.series( "build", - gulp.parallel("pegjs-watch", "static-watch", "tsc-watch", "tsfmt-watch", "tslint-watch")), -) + gulp.parallel("pegjs-watch", "static-watch", "tsc-watch", "watch-code"), +)) gulp.task("default", gulp.series("watch")) diff --git a/package-lock.json b/package-lock.json index 8deb61c992..8e5d82016f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -140,6 +140,12 @@ "@types/vinyl-fs": "*" } }, + "@types/handlebars": { + "version": "4.0.37", + "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.37.tgz", + "integrity": "sha512-c/g99PQsJEFYdK3LT1qgPAZ61fu/oFOaEhov/6ZuUNMi1xQFbAOSThlX8fAQLf+QoGXtyv4S39OjIRXf3HkBtw==", + "dev": true + }, "@types/has-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/has-ansi/-/has-ansi-3.0.0.tgz", @@ -614,9 +620,9 @@ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" }, "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "dev": true, "requires": { "delegates": "^1.0.0", @@ -806,9 +812,9 @@ "dev": true }, "ast-types": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", - "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==" + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.3.tgz", + "integrity": "sha512-XA5o5dsNw8MhyW0Q7MWXJWc4oOzZKbdsEJq45h7c8q/d9DwWZ5F2ugUc1PuMLPGsUnphCt/cNDHu8JeBbxf1qA==" }, "async": { "version": "2.6.0", @@ -1016,9 +1022,9 @@ } }, "base64url": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.0.tgz", - "integrity": "sha512-LIVmqIrIWuiqTvn4RzcrwCOuHo2DD6tKmKBPXXlr4p4n4l6BZBkwFTIa3zu1XkX5MbZgro4a6BvPi+n2Mns5Gg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", + "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" }, "bcrypt-pbkdf": { "version": "1.0.1", @@ -1079,6 +1085,21 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.x.x" + }, + "dependencies": { + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + } + } + }, "bops": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/bops/-/bops-0.1.1.tgz", @@ -1239,8 +1260,7 @@ "capture-stack-trace": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", - "dev": true + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" }, "caseless": { "version": "0.12.0", @@ -2083,6 +2103,12 @@ "map-obj": "^1.0.0" } }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", @@ -2209,7 +2235,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, "requires": { "capture-stack-trace": "^1.0.0" } @@ -2229,23 +2254,52 @@ "resolved": "https://registry.npmjs.org/cryo/-/cryo-0.0.6.tgz", "integrity": "sha1-FoMyldLuFv85cR24QGF7euSvC6Q=" }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.x.x" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.x.x" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + } + } + }, "crypto-random-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" }, "css": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.3.tgz", - "integrity": "sha512-0W171WccAjQGGTKLhw4m2nnl0zPHUlTO/I8td4XzJgIB8Hg3ZZx71qT4G4eX8OVsSiaAKiUMy73E3nsbPlg2DQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", "dev": true, "requires": { "inherits": "^2.0.1", "source-map": "^0.1.38", - "source-map-resolve": "^0.5.1", + "source-map-resolve": "^0.3.0", "urix": "^0.1.0" }, "dependencies": { + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, "source-map": { "version": "0.1.43", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", @@ -2254,6 +2308,24 @@ "requires": { "amdefine": ">=0.0.4" } + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "~1.1.0", + "resolve-url": "~0.2.1", + "source-map-url": "~0.3.0", + "urix": "~0.1.0" + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true } } }, @@ -2396,9 +2468,9 @@ "dev": true }, "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", + "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", "dev": true }, "deep-is": { @@ -2782,9 +2854,9 @@ "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" }, "email-validator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", - "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.3.tgz", + "integrity": "sha1-M+UNZvUmuXzXLBcgWu+ux5yKKh4=" }, "enabled": { "version": "1.0.2", @@ -3153,15 +3225,6 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -3453,9 +3516,9 @@ } }, "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", "dev": true, "optional": true }, @@ -3566,6 +3629,13 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true, + "optional": true + }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -3775,13 +3845,13 @@ "optional": true }, "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz", + "integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=", "dev": true, "optional": true, "requires": { - "deep-extend": "^0.6.0", + "deep-extend": "~0.4.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" @@ -3893,6 +3963,13 @@ "ansi-regex": "^2.0.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "optional": true + }, "tar": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", @@ -3978,33 +4055,6 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": 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": { - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -4051,6 +4101,12 @@ "map-obj": "^1.0.0" } }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", @@ -4123,21 +4179,15 @@ "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", "dev": true }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "get-uri": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.2.tgz", - "integrity": "sha512-ZD325dMZOgerGqF/rF6vZXyFGTAay62svjQIT+X/oU2PtxYpFxvSkbsdi+oxIrsNxlZVd4y8wUDqkaExWTI/Cw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.1.tgz", + "integrity": "sha512-7aelVrYqCLuVjq2kEKRTH8fXPTC0xKTkM+G7UlFkEwCXY3sFbSxvY375JoFowOAYbkaU47SrBvOefUlLZZ+6QA==", "requires": { "data-uri-to-buffer": "1", "debug": "2", @@ -4940,6 +4990,24 @@ } } }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.x.x", + "cryptiles": "3.x.x", + "hoek": "4.x.x", + "sntp": "2.x.x" + }, + "dependencies": { + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + } + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -5725,14 +5793,14 @@ } }, "kubernetes-client": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/kubernetes-client/-/kubernetes-client-5.3.0.tgz", - "integrity": "sha512-i+sg7sk7iRVONnbmZLmUDtE82pc5CWjakMdKrf2h3JbPWjkLIhFJruLHJub8SGLLqDCYuC8KJOai6V5klsGJMA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/kubernetes-client/-/kubernetes-client-5.2.0.tgz", + "integrity": "sha512-PcbFsfSrCl3KOZKYCjvmbVYek9RRBIYFApRdm6L+eyqvVU8Qsrq3cRdMOXaZcnEpCMZ8++nUGgwFu8FhbMJoPQ==", "requires": { "async": "^2.6.0", "js-yaml": "^3.10.0", "lodash.merge": "^4.6.0", - "openid-client": "^2.0.0", + "openid-client": "^1.20.0", "promy": "^0.1.0", "request": "^2.83.0" } @@ -5896,6 +5964,15 @@ "strip-eof": "^1.0.0" } }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, "fs-extra": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", @@ -5907,6 +5984,53 @@ "universalify": "^0.1.0" } }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": 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": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", @@ -5947,6 +6071,18 @@ "strip-bom": "^3.0.0" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", @@ -6287,9 +6423,9 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, "lodash._basecopy": { "version": "3.0.1", @@ -6509,9 +6645,9 @@ } }, "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", + "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=" }, "longest": { "version": "1.0.1", @@ -7018,6 +7154,17 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + } } }, "strip-ansi": { @@ -7028,15 +7175,6 @@ "ansi-regex": "^2.0.0" } }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, "yargs": { "version": "3.32.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", @@ -7147,11 +7285,11 @@ "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" }, "node-jose": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-jose/-/node-jose-1.0.0.tgz", - "integrity": "sha512-RE3P8l60Rj9ELrpPmvw6sOQ1hSyYfmQdNUMCa4EN7nCE1ux5JVX+GfXv+mfUTEMhZwNMwxBtI0+X1CKKeukSVQ==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-jose/-/node-jose-0.11.0.tgz", + "integrity": "sha512-bWnCsBzFgfsxzNZ77Rdc+4pGxRV8NRre5yyGzjiTgZOFpi6n1tthXrMATMwzmUo0Nn45aUuQqYlN6URx8MFmFw==", "requires": { - "base64url": "^3.0.0", + "base64url": "^2.0.0", "es6-promise": "^4.0.5", "lodash.assign": "^4.0.8", "lodash.clone": "^4.3.2", @@ -7163,7 +7301,7 @@ "lodash.partialright": "^4.1.3", "lodash.pick": "^4.2.0", "lodash.uniq": "^4.2.1", - "long": "^4.0.0", + "long": "^3.1.0", "node-forge": "^0.7.1", "uuid": "^3.0.1" } @@ -7263,18 +7401,6 @@ "path-key": "^2.0.0" } }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": 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", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -7317,7 +7443,8 @@ "dependencies": { "align-text": { "version": "0.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { "kind-of": "^3.0.2", @@ -7327,22 +7454,26 @@ }, "amdefine": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", "dev": true }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "ansi-styles": { "version": "2.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, "append-transform": { "version": "0.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", "dev": true, "requires": { "default-require-extensions": "^1.0.0" @@ -7350,52 +7481,62 @@ }, "archy": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, "arr-diff": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, "arr-flatten": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "arr-union": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, "array-unique": { "version": "0.3.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "arrify": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "assign-symbols": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, "async": { "version": "1.5.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, "atob": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", "dev": true }, "babel-code-frame": { "version": "6.26.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { "chalk": "^1.1.3", @@ -7405,7 +7546,8 @@ }, "babel-generator": { "version": "6.26.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { "babel-messages": "^6.23.0", @@ -7420,7 +7562,8 @@ }, "babel-messages": { "version": "6.23.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", "dev": true, "requires": { "babel-runtime": "^6.22.0" @@ -7428,7 +7571,8 @@ }, "babel-runtime": { "version": "6.26.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { "core-js": "^2.4.0", @@ -7437,7 +7581,8 @@ }, "babel-template": { "version": "6.26.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", "dev": true, "requires": { "babel-runtime": "^6.26.0", @@ -7449,7 +7594,8 @@ }, "babel-traverse": { "version": "6.26.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", "dev": true, "requires": { "babel-code-frame": "^6.26.0", @@ -7465,7 +7611,8 @@ }, "babel-types": { "version": "6.26.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", "dev": true, "requires": { "babel-runtime": "^6.26.0", @@ -7476,17 +7623,20 @@ }, "babylon": { "version": "6.18.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, "balanced-match": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "base": { "version": "0.11.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -7500,7 +7650,8 @@ "dependencies": { "define-property": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { "is-descriptor": "^1.0.0" @@ -7508,7 +7659,8 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -7516,7 +7668,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -7524,7 +7677,8 @@ }, "is-descriptor": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -7534,19 +7688,22 @@ }, "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "kind-of": { "version": "6.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "brace-expansion": { "version": "1.1.11", - "bundled": true, + "resolved": false, + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -7555,7 +7712,8 @@ }, "braces": { "version": "2.3.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { "arr-flatten": "^1.1.0", @@ -7572,7 +7730,8 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -7582,12 +7741,14 @@ }, "builtin-modules": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, "cache-base": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -7603,14 +7764,16 @@ "dependencies": { "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "caching-transform": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-bb2y8g+Nj7znnz6U6dF0Lc31wKE=", "dev": true, "requires": { "md5-hex": "^1.2.0", @@ -7620,13 +7783,15 @@ }, "camelcase": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true, "optional": true }, "center-align": { "version": "0.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "optional": true, "requires": { @@ -7636,7 +7801,8 @@ }, "chalk": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { "ansi-styles": "^2.2.1", @@ -7648,7 +7814,8 @@ }, "class-utils": { "version": "0.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -7659,7 +7826,8 @@ "dependencies": { "define-property": { "version": "0.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" @@ -7667,14 +7835,16 @@ }, "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "cliui": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "optional": true, "requires": { @@ -7685,7 +7855,8 @@ "dependencies": { "wordwrap": { "version": "0.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true, "optional": true } @@ -7693,12 +7864,14 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "collection-visit": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { "map-visit": "^1.0.0", @@ -7707,37 +7880,44 @@ }, "commondir": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, "component-emitter": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "convert-source-map": { "version": "1.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", "dev": true }, "copy-descriptor": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, "core-js": { "version": "2.5.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==", "dev": true }, "cross-spawn": { "version": "4.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", "dev": true, "requires": { "lru-cache": "^4.0.1", @@ -7746,7 +7926,8 @@ }, "debug": { "version": "2.6.9", - "bundled": true, + "resolved": false, + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" @@ -7754,22 +7935,26 @@ }, "debug-log": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", "dev": true }, "decamelize": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decode-uri-component": { "version": "0.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, "default-require-extensions": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", "dev": true, "requires": { "strip-bom": "^2.0.0" @@ -7777,7 +7962,8 @@ }, "define-property": { "version": "2.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { "is-descriptor": "^1.0.2", @@ -7786,7 +7972,8 @@ "dependencies": { "is-accessor-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -7794,7 +7981,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -7802,7 +7990,8 @@ }, "is-descriptor": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -7812,19 +8001,22 @@ }, "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "kind-of": { "version": "6.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "detect-indent": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", "dev": true, "requires": { "repeating": "^2.0.0" @@ -7832,7 +8024,8 @@ }, "error-ex": { "version": "1.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { "is-arrayish": "^0.2.1" @@ -7840,17 +8033,20 @@ }, "escape-string-regexp": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, "esutils": { "version": "2.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, "execa": { "version": "0.7.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { "cross-spawn": "^5.0.1", @@ -7864,7 +8060,8 @@ "dependencies": { "cross-spawn": { "version": "5.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { "lru-cache": "^4.0.1", @@ -7876,7 +8073,8 @@ }, "expand-brackets": { "version": "2.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { "debug": "^2.3.3", @@ -7890,7 +8088,8 @@ "dependencies": { "define-property": { "version": "0.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" @@ -7898,7 +8097,8 @@ }, "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -7908,7 +8108,8 @@ }, "extend-shallow": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { "assign-symbols": "^1.0.0", @@ -7917,7 +8118,8 @@ "dependencies": { "is-extendable": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -7927,7 +8129,8 @@ }, "extglob": { "version": "2.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { "array-unique": "^0.3.2", @@ -7942,7 +8145,8 @@ "dependencies": { "define-property": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { "is-descriptor": "^1.0.0" @@ -7950,7 +8154,8 @@ }, "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -7958,7 +8163,8 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -7966,7 +8172,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -7974,7 +8181,8 @@ }, "is-descriptor": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -7984,14 +8192,16 @@ }, "kind-of": { "version": "6.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "fill-range": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -8002,7 +8212,8 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -8012,7 +8223,8 @@ }, "find-cache-dir": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", "dev": true, "requires": { "commondir": "^1.0.1", @@ -8022,7 +8234,8 @@ }, "find-up": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { "locate-path": "^2.0.0" @@ -8030,12 +8243,14 @@ }, "for-in": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, "foreground-child": { "version": "1.5.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", "dev": true, "requires": { "cross-spawn": "^4", @@ -8044,7 +8259,8 @@ }, "fragment-cache": { "version": "0.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { "map-cache": "^0.2.2" @@ -8052,27 +8268,32 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "get-caller-file": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, "get-stream": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, "get-value": { "version": "2.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, "glob": { "version": "7.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -8085,17 +8306,20 @@ }, "globals": { "version": "9.18.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, "graceful-fs": { "version": "4.1.11", - "bundled": true, + "resolved": false, + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, "handlebars": { "version": "4.0.11", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "dev": true, "requires": { "async": "^1.4.0", @@ -8106,7 +8330,8 @@ "dependencies": { "source-map": { "version": "0.4.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { "amdefine": ">=0.0.4" @@ -8116,7 +8341,8 @@ }, "has-ansi": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -8124,12 +8350,14 @@ }, "has-flag": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, "has-value": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { "get-value": "^2.0.6", @@ -8139,14 +8367,16 @@ "dependencies": { "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "has-values": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { "is-number": "^3.0.0", @@ -8155,7 +8385,8 @@ "dependencies": { "is-number": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -8163,7 +8394,8 @@ "dependencies": { "kind-of": { "version": "3.2.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" @@ -8173,7 +8405,8 @@ }, "kind-of": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { "is-buffer": "^1.1.5" @@ -8183,17 +8416,20 @@ }, "hosted-git-info": { "version": "2.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", "dev": true }, "imurmurhash": { "version": "0.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { "once": "^1.3.0", @@ -8202,12 +8438,14 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "invariant": { "version": "2.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { "loose-envify": "^1.0.0" @@ -8215,12 +8453,14 @@ }, "invert-kv": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, "is-accessor-descriptor": { "version": "0.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -8228,17 +8468,20 @@ }, "is-arrayish": { "version": "0.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-buffer": { "version": "1.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "is-builtin-module": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { "builtin-modules": "^1.0.0" @@ -8246,7 +8489,8 @@ }, "is-data-descriptor": { "version": "0.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -8254,7 +8498,8 @@ }, "is-descriptor": { "version": "0.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", @@ -8264,19 +8509,22 @@ "dependencies": { "kind-of": { "version": "5.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, "is-extendable": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, "is-finite": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { "number-is-nan": "^1.0.0" @@ -8284,12 +8532,14 @@ }, "is-fullwidth-code-point": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "is-number": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -8297,7 +8547,8 @@ }, "is-odd": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", "dev": true, "requires": { "is-number": "^4.0.0" @@ -8305,14 +8556,16 @@ "dependencies": { "is-number": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "dev": true } } }, "is-plain-object": { "version": "2.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { "isobject": "^3.0.1" @@ -8320,49 +8573,58 @@ "dependencies": { "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "is-stream": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "is-utf8": { "version": "0.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, "is-windows": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isexe": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "istanbul-lib-coverage": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", "dev": true }, "istanbul-lib-hook": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==", "dev": true, "requires": { "append-transform": "^0.4.0" @@ -8370,7 +8632,8 @@ }, "istanbul-lib-instrument": { "version": "1.10.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", "dev": true, "requires": { "babel-generator": "^6.18.0", @@ -8384,7 +8647,8 @@ }, "istanbul-lib-report": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-D4jVbMDtT2dPmloPJS/rmeP626N5Pr3Rp+SovrPn1+zPChGHcggd/0sL29jnbm4oK9W0wHjCRsdch9oLd7cm6g==", "dev": true, "requires": { "istanbul-lib-coverage": "^1.1.2", @@ -8395,7 +8659,8 @@ "dependencies": { "supports-color": { "version": "3.2.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { "has-flag": "^1.0.0" @@ -8405,7 +8670,8 @@ }, "istanbul-lib-source-maps": { "version": "1.2.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA==", "dev": true, "requires": { "debug": "^3.1.0", @@ -8417,7 +8683,8 @@ "dependencies": { "debug": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -8427,7 +8694,8 @@ }, "istanbul-reports": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-OPzVo1fPZ2H+owr8q/LYKLD+vquv9Pj4F+dj808MdHbuQLD7S4ACRjcX+0Tne5Vxt2lxXvdZaL7v+FOOAV281w==", "dev": true, "requires": { "handlebars": "^4.0.3" @@ -8435,17 +8703,20 @@ }, "js-tokens": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true }, "jsesc": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, "kind-of": { "version": "3.2.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" @@ -8453,13 +8724,15 @@ }, "lazy-cache": { "version": "1.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true, "optional": true }, "lcid": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { "invert-kv": "^1.0.0" @@ -8467,7 +8740,8 @@ }, "load-json-file": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -8479,7 +8753,8 @@ }, "locate-path": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { "p-locate": "^2.0.0", @@ -8488,24 +8763,28 @@ "dependencies": { "path-exists": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true } } }, "lodash": { "version": "4.17.10", - "bundled": true, + "resolved": false, + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", "dev": true }, "longest": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", "dev": true }, "loose-envify": { "version": "1.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "dev": true, "requires": { "js-tokens": "^3.0.0" @@ -8513,7 +8792,8 @@ }, "lru-cache": { "version": "4.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -8522,12 +8802,14 @@ }, "map-cache": { "version": "0.2.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-visit": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { "object-visit": "^1.0.0" @@ -8535,7 +8817,8 @@ }, "md5-hex": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-0sSv6YPENwZiF5uMrRRSGRNQRsQ=", "dev": true, "requires": { "md5-o-matic": "^0.1.1" @@ -8543,12 +8826,14 @@ }, "md5-o-matic": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", "dev": true }, "mem": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { "mimic-fn": "^1.0.0" @@ -8556,7 +8841,8 @@ }, "merge-source-map": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", "dev": true, "requires": { "source-map": "^0.6.1" @@ -8564,14 +8850,16 @@ "dependencies": { "source-map": { "version": "0.6.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } }, "micromatch": { "version": "3.1.10", - "bundled": true, + "resolved": false, + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -8591,19 +8879,22 @@ "dependencies": { "kind-of": { "version": "6.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "mimic-fn": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -8611,12 +8902,14 @@ }, "minimist": { "version": "0.0.8", - "bundled": true, + "resolved": false, + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "mixin-deep": { "version": "1.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -8625,7 +8918,8 @@ "dependencies": { "is-extendable": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { "is-plain-object": "^2.0.4" @@ -8635,7 +8929,8 @@ }, "mkdirp": { "version": "0.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { "minimist": "0.0.8" @@ -8643,12 +8938,14 @@ }, "ms": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "nanomatch": { "version": "1.2.9", - "bundled": true, + "resolved": false, + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -8667,24 +8964,28 @@ "dependencies": { "arr-diff": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, "array-unique": { "version": "0.3.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "kind-of": { "version": "6.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "normalize-package-data": { "version": "2.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", @@ -8695,7 +8996,8 @@ }, "npm-run-path": { "version": "2.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { "path-key": "^2.0.0" @@ -8703,17 +9005,20 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, "object-copy": { "version": "0.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { "copy-descriptor": "^0.1.0", @@ -8723,7 +9028,8 @@ "dependencies": { "define-property": { "version": "0.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" @@ -8733,7 +9039,8 @@ }, "object-visit": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { "isobject": "^3.0.0" @@ -8741,14 +9048,16 @@ "dependencies": { "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "object.pick": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { "isobject": "^3.0.1" @@ -8756,14 +9065,16 @@ "dependencies": { "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { "wrappy": "1" @@ -8771,7 +9082,8 @@ }, "optimist": { "version": "0.6.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { "minimist": "~0.0.1", @@ -8780,12 +9092,14 @@ }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { "execa": "^0.7.0", @@ -8795,12 +9109,14 @@ }, "p-finally": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, "p-limit": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", "dev": true, "requires": { "p-try": "^1.0.0" @@ -8808,7 +9124,8 @@ }, "p-locate": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { "p-limit": "^1.1.0" @@ -8816,12 +9133,14 @@ }, "p-try": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, "parse-json": { "version": "2.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { "error-ex": "^1.2.0" @@ -8829,12 +9148,14 @@ }, "pascalcase": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, "path-exists": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { "pinkie-promise": "^2.0.0" @@ -8842,22 +9163,26 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, "path-key": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { "version": "1.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", "dev": true }, "path-type": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -8867,17 +9192,20 @@ }, "pify": { "version": "2.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "pinkie": { "version": "2.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, "pinkie-promise": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { "pinkie": "^2.0.0" @@ -8885,7 +9213,8 @@ }, "pkg-dir": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { "find-up": "^1.0.0" @@ -8893,7 +9222,8 @@ "dependencies": { "find-up": { "version": "1.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { "path-exists": "^2.0.0", @@ -8904,17 +9234,20 @@ }, "posix-character-classes": { "version": "0.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, "pseudomap": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, "read-pkg": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { "load-json-file": "^1.0.0", @@ -8924,7 +9257,8 @@ }, "read-pkg-up": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { "find-up": "^1.0.0", @@ -8933,7 +9267,8 @@ "dependencies": { "find-up": { "version": "1.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { "path-exists": "^2.0.0", @@ -8944,12 +9279,14 @@ }, "regenerator-runtime": { "version": "0.11.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", "dev": true }, "regex-not": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { "extend-shallow": "^3.0.2", @@ -8958,17 +9295,20 @@ }, "repeat-element": { "version": "1.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", "dev": true }, "repeat-string": { "version": "1.6.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, "repeating": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { "is-finite": "^1.0.0" @@ -8976,32 +9316,38 @@ }, "require-directory": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, "resolve-from": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", "dev": true }, "resolve-url": { "version": "0.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, "ret": { "version": "0.1.15", - "bundled": true, + "resolved": false, + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, "right-align": { "version": "0.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "optional": true, "requires": { @@ -9010,7 +9356,8 @@ }, "rimraf": { "version": "2.6.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { "glob": "^7.0.5" @@ -9018,7 +9365,8 @@ }, "safe-regex": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { "ret": "~0.1.10" @@ -9026,17 +9374,20 @@ }, "semver": { "version": "5.5.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-value": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -9047,7 +9398,8 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -9057,7 +9409,8 @@ }, "shebang-command": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { "shebang-regex": "^1.0.0" @@ -9065,22 +9418,26 @@ }, "shebang-regex": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "slide": { "version": "1.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", "dev": true }, "snapdragon": { "version": "0.8.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { "base": "^0.11.1", @@ -9095,7 +9452,8 @@ "dependencies": { "define-property": { "version": "0.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" @@ -9103,7 +9461,8 @@ }, "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -9113,7 +9472,8 @@ }, "snapdragon-node": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { "define-property": "^1.0.0", @@ -9123,7 +9483,8 @@ "dependencies": { "define-property": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { "is-descriptor": "^1.0.0" @@ -9131,7 +9492,8 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -9139,7 +9501,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -9147,7 +9510,8 @@ }, "is-descriptor": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -9157,19 +9521,22 @@ }, "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "kind-of": { "version": "6.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "snapdragon-util": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -9177,12 +9544,14 @@ }, "source-map": { "version": "0.5.7", - "bundled": true, + "resolved": false, + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, "source-map-resolve": { "version": "0.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", "dev": true, "requires": { "atob": "^2.0.0", @@ -9194,12 +9563,14 @@ }, "source-map-url": { "version": "0.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, "spawn-wrap": { "version": "1.4.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", "dev": true, "requires": { "foreground-child": "^1.5.6", @@ -9212,7 +9583,8 @@ }, "spdx-correct": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -9221,12 +9593,14 @@ }, "spdx-exceptions": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, "spdx-expression-parse": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -9235,12 +9609,14 @@ }, "spdx-license-ids": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, "split-string": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -9248,7 +9624,8 @@ }, "static-extend": { "version": "0.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { "define-property": "^0.2.5", @@ -9257,7 +9634,8 @@ "dependencies": { "define-property": { "version": "0.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" @@ -9267,7 +9645,8 @@ }, "string-width": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", @@ -9276,12 +9655,14 @@ "dependencies": { "ansi-regex": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "strip-ansi": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { "ansi-regex": "^3.0.0" @@ -9291,7 +9672,8 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -9299,7 +9681,8 @@ }, "strip-bom": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { "is-utf8": "^0.2.0" @@ -9307,17 +9690,20 @@ }, "strip-eof": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, "supports-color": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, "test-exclude": { "version": "4.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ==", "dev": true, "requires": { "arrify": "^1.0.1", @@ -9329,17 +9715,20 @@ "dependencies": { "arr-diff": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, "array-unique": { "version": "0.3.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "braces": { "version": "2.3.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { "arr-flatten": "^1.1.0", @@ -9356,7 +9745,8 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -9366,7 +9756,8 @@ }, "expand-brackets": { "version": "2.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { "debug": "^2.3.3", @@ -9380,7 +9771,8 @@ "dependencies": { "define-property": { "version": "0.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { "is-descriptor": "^0.1.0" @@ -9388,7 +9780,8 @@ }, "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -9396,7 +9789,8 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -9404,7 +9798,8 @@ "dependencies": { "kind-of": { "version": "3.2.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" @@ -9414,7 +9809,8 @@ }, "is-data-descriptor": { "version": "0.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -9422,7 +9818,8 @@ "dependencies": { "kind-of": { "version": "3.2.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" @@ -9432,7 +9829,8 @@ }, "is-descriptor": { "version": "0.1.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", @@ -9442,14 +9840,16 @@ }, "kind-of": { "version": "5.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", "dev": true } } }, "extglob": { "version": "2.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { "array-unique": "^0.3.2", @@ -9464,7 +9864,8 @@ "dependencies": { "define-property": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { "is-descriptor": "^1.0.0" @@ -9472,7 +9873,8 @@ }, "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -9482,7 +9884,8 @@ }, "fill-range": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -9493,7 +9896,8 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -9503,7 +9907,8 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -9511,7 +9916,8 @@ }, "is-data-descriptor": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { "kind-of": "^6.0.0" @@ -9519,7 +9925,8 @@ }, "is-descriptor": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", @@ -9529,7 +9936,8 @@ }, "is-number": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -9537,7 +9945,8 @@ "dependencies": { "kind-of": { "version": "3.2.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { "is-buffer": "^1.1.5" @@ -9547,17 +9956,20 @@ }, "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, "kind-of": { "version": "6.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, "micromatch": { "version": "3.1.10", - "bundled": true, + "resolved": false, + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { "arr-diff": "^4.0.0", @@ -9579,12 +9991,14 @@ }, "to-fast-properties": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", "dev": true }, "to-object-path": { "version": "0.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -9592,7 +10006,8 @@ }, "to-regex": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { "define-property": "^2.0.2", @@ -9603,7 +10018,8 @@ }, "to-regex-range": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { "is-number": "^3.0.0", @@ -9612,7 +10028,8 @@ "dependencies": { "is-number": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { "kind-of": "^3.0.2" @@ -9622,12 +10039,14 @@ }, "trim-right": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, "uglify-js": { "version": "2.8.29", - "bundled": true, + "resolved": false, + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, "optional": true, "requires": { @@ -9638,7 +10057,8 @@ "dependencies": { "yargs": { "version": "3.10.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "optional": true, "requires": { @@ -9652,13 +10072,15 @@ }, "uglify-to-browserify": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "dev": true, "optional": true }, "union-value": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -9669,7 +10091,8 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { "is-extendable": "^0.1.0" @@ -9677,7 +10100,8 @@ }, "set-value": { "version": "0.4.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -9690,7 +10114,8 @@ }, "unset-value": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { "has-value": "^0.3.1", @@ -9699,7 +10124,8 @@ "dependencies": { "has-value": { "version": "0.3.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { "get-value": "^2.0.3", @@ -9709,7 +10135,8 @@ "dependencies": { "isobject": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { "isarray": "1.0.0" @@ -9719,24 +10146,28 @@ }, "has-values": { "version": "0.1.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true }, "isobject": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, "urix": { "version": "0.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, "use": { "version": "3.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", "dev": true, "requires": { "kind-of": "^6.0.2" @@ -9744,14 +10175,16 @@ "dependencies": { "kind-of": { "version": "6.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } }, "validate-npm-package-license": { "version": "3.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "dev": true, "requires": { "spdx-correct": "^3.0.0", @@ -9760,7 +10193,8 @@ }, "which": { "version": "1.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -9768,23 +10202,27 @@ }, "which-module": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "window-size": { "version": "0.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true, "optional": true }, "wordwrap": { "version": "0.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, "wrap-ansi": { "version": "2.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { "string-width": "^1.0.1", @@ -9793,7 +10231,8 @@ "dependencies": { "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { "number-is-nan": "^1.0.0" @@ -9801,7 +10240,8 @@ }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", @@ -9813,12 +10253,14 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "write-file-atomic": { "version": "1.3.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -9828,17 +10270,20 @@ }, "y18n": { "version": "3.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true }, "yallist": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, "yargs": { "version": "11.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "dev": true, "requires": { "cliui": "^4.0.0", @@ -9857,17 +10302,20 @@ "dependencies": { "ansi-regex": { "version": "3.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "camelcase": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "cliui": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { "string-width": "^2.1.1", @@ -9877,7 +10325,8 @@ }, "strip-ansi": { "version": "4.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { "ansi-regex": "^3.0.0" @@ -9885,7 +10334,8 @@ }, "yargs-parser": { "version": "9.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { "camelcase": "^4.1.0" @@ -9895,7 +10345,8 @@ }, "yargs-parser": { "version": "8.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", "dev": true, "requires": { "camelcase": "^4.1.0" @@ -9903,7 +10354,8 @@ "dependencies": { "camelcase": { "version": "4.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true } } @@ -10011,11 +10463,11 @@ } }, "oidc-token-hash": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-3.0.1.tgz", - "integrity": "sha512-oLnVSEcNZkw01sB5aFR+2iJmW4oyC1PIMJmd3FMBGDuPTy5ZtEuX5WNhKMRarJIMOq8NiOwIB6eJB9AhgYwBTg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-2.0.0.tgz", + "integrity": "sha512-XJwM41KOqU9OhRP0lo+OFiHaeSGKVL5+7NSid/lzfVm9e1oe1tUtxwo8n8fIStaU3j3HPxbwl/ddXsxJdHXZHA==", "requires": { - "base64url": "^3.0.0" + "base64url": "^2.0.0" } }, "once": { @@ -10049,28 +10501,18 @@ } }, "openid-client": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-2.1.0.tgz", - "integrity": "sha512-rYmoH0sXAJwvvmQiWj4TOpao20SJoRLIEHrs2ynBQIn7sE2G2oMEHActx0WkWl/VZf1y4RTGMYi9/etMqUgzFg==", - "requires": { - "base64url": "^3.0.0", - "got": "^8.3.1", - "lodash": "^4.17.10", - "lru-cache": "^4.1.3", - "node-jose": "^1.0.0", - "oidc-token-hash": "^3.0.1", - "uuid": "^3.2.1" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - } + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-1.20.0.tgz", + "integrity": "sha512-gkO9txUUDhpV5vfxhpaw0MY9CcofJaTCqkibWzjeNTy2Uy+HFHuyKbQgQ4Msl2q4gkAWU9rPcNSZbG2nX61sCg==", + "requires": { + "base64url": "^2.0.0", + "create-error-class": "^3.0.2", + "got": "^8.0.0", + "lodash": "^4.13.1", + "lru-cache": "^4.0.1", + "node-jose": "^0.11.0", + "oidc-token-hash": "^2.0.0", + "uuid": "^3.0.0" } }, "opn": { @@ -10762,12 +11204,12 @@ } }, "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", + "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", "dev": true, "requires": { - "deep-extend": "^0.6.0", + "deep-extend": "^0.5.1", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" @@ -11020,9 +11462,9 @@ } }, "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.6.0", @@ -11032,6 +11474,7 @@ "forever-agent": "~0.6.1", "form-data": "~2.3.1", "har-validator": "~5.0.3", + "hawk": "~6.0.2", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -11041,6 +11484,7 @@ "performance-now": "^2.1.0", "qs": "~6.5.1", "safe-buffer": "^5.1.1", + "stringstream": "~0.0.5", "tough-cookie": "~2.3.3", "tunnel-agent": "^0.6.0", "uuid": "^3.1.0" @@ -11437,10 +11881,25 @@ "kind-of": "^3.2.0" } }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.x.x" + }, + "dependencies": { + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + } + } + }, "snyk": { - "version": "1.82.0", - "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.82.0.tgz", - "integrity": "sha512-UZuGBdh3PSK6Va9Sos+hFUnLImIShluHfOSvF3UdM0jmjOaIRvIywkUrqT7J38xQ0VRmbVCoJlrYA1g7vD1CeA==", + "version": "1.80.0", + "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.80.0.tgz", + "integrity": "sha1-1hweYUzg5dZDeihDPXvhUILEzJw=", "requires": { "abbrev": "^1.1.1", "ansi-escapes": "^3.1.0", @@ -11458,14 +11917,14 @@ "recursive-readdir": "^2.2.2", "semver": "^5.5.0", "snyk-config": "2.1.0", - "snyk-go-plugin": "1.5.1", + "snyk-go-plugin": "1.5.0", "snyk-gradle-plugin": "1.3.0", "snyk-module": "1.8.2", "snyk-mvn-plugin": "1.2.0", - "snyk-nuget-plugin": "1.6.2", + "snyk-nuget-plugin": "1.6.1", "snyk-php-plugin": "1.5.1", "snyk-policy": "1.12.0", - "snyk-python-plugin": "1.6.1", + "snyk-python-plugin": "1.6.0", "snyk-resolve": "1.0.1", "snyk-resolve-deps": "3.1.0", "snyk-sbt-plugin": "1.3.0", @@ -11477,6 +11936,11 @@ "uuid": "^3.2.1" }, "dependencies": { + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -11519,6 +11983,11 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", @@ -11555,12 +12024,11 @@ } }, "snyk-go-plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/snyk-go-plugin/-/snyk-go-plugin-1.5.1.tgz", - "integrity": "sha512-8OPJOT05Z/UL5fFSXV6b/A6KjlS1Ahr2gpup1bhXtAGXlUUPyWidqkCIER9fexDXqYWgAoDAdn9YHIvmL/5bfw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/snyk-go-plugin/-/snyk-go-plugin-1.5.0.tgz", + "integrity": "sha512-H6CHhGqchCcQV/JhOiSbTI8JLYhQU7dZ/oLwHMfVEXSD3bWOp1evlohuaQQaqic/ZInitLsjkCLHG2x47ZgUgQ==", "requires": { "graphlib": "^2.1.1", - "tmp": "0.0.33", "toml": "^2.3.2" } }, @@ -11597,9 +12065,9 @@ "integrity": "sha512-ieTWhn1MB88gEQ6nUtGCeUKQ6Xoxm+u+QmD9u3zfP1QS5ep9fWt3YYDUQjgUiDTJJy7QyVQdZ/fsz3RECnOA7w==" }, "snyk-nuget-plugin": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/snyk-nuget-plugin/-/snyk-nuget-plugin-1.6.2.tgz", - "integrity": "sha512-8l8hS85esXyweTFgUFdwnGT94Ts42KcG5fdBX2wYosQkpUMePd+GTT9+64k/GvdH5hqcNt2OvtzW+Uf8JF+pbA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/snyk-nuget-plugin/-/snyk-nuget-plugin-1.6.1.tgz", + "integrity": "sha512-Hfml6WZbVPyTNRS569LL0yMFZUDYlPr8n/zTBZiSO3n0QBFQdTrXcBmGKGdh5xOgRf/hUKRaGCHYjeDOh7b6nw==", "requires": { "debug": "^3.1.0", "es6-promise": "^4.1.1", @@ -11615,6 +12083,11 @@ "requires": { "ms": "2.0.0" } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" } } }, @@ -11635,6 +12108,11 @@ "requires": { "ms": "2.0.0" } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" } } }, @@ -11670,12 +12148,9 @@ } }, "snyk-python-plugin": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/snyk-python-plugin/-/snyk-python-plugin-1.6.1.tgz", - "integrity": "sha512-6zr5jAB3p/bwMZQxZpdj+aPmioTgHB4DI6JMLInhZupss0x8Ome5YqzVzBbOvUKNrc3KaLtjGrJWcAuxDL6M/g==", - "requires": { - "tmp": "0.0.33" - } + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/snyk-python-plugin/-/snyk-python-plugin-1.6.0.tgz", + "integrity": "sha512-/9PcO6lvSY62qGpFjrRQ00NQdUulZnit6tOLMZp+91BnOjoiw4aKKr7uoky6rbwu64fEmK3sE+tcp8BXqH9kDQ==" }, "snyk-resolve": { "version": "1.0.1", @@ -12107,6 +12582,11 @@ "is-regexp": "^1.0.0" } }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/package.json b/package.json index a4219532ec..8428ef0d9a 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@types/dockerode": "^2.5.4", "@types/fs-extra": "^5.0.2", "@types/gulp": "^4.0.5", + "@types/handlebars": "^4.0.37", "@types/has-ansi": "^3.0.0", "@types/inquirer": "0.0.41", "@types/joi": "^13.0.8", @@ -91,6 +92,7 @@ "gulp-sourcemaps": "^2.6.4", "gulp-tslint": "^8.1.3", "gulp-typescript": "^4.0.2", + "handlebars": "^4.0.11", "husky": "^0.15.0-rc.13", "json-schema-to-typescript": "^5.5.0", "lerna": "^2.11.0", @@ -118,6 +120,7 @@ "dev": "gulp build && cd build && npm link && cd .. && gulp watch", "dist": "npm run clean && ./bin/check-if-clean && gulp dist", "fix-format": "node_modules/.bin/tslint -p . --fix && node_modules/.bin/tsfmt -r", + "generate-docs": "gulp generate-docs", "integ": "./test/integ/run", "lint": "gulp lint", "prepare": "npm run snyk-protect", diff --git a/src/cli/cli.ts b/src/cli/cli.ts index 138dba5825..fbbe6eeece 100644 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -10,6 +10,7 @@ import * as sywac from "sywac" import { merge, intersection } from "lodash" import { resolve } from "path" import { safeDump } from "js-yaml" +import { coreCommands } from "../commands" import stringify = require("json-stringify-safe") import { DeepPrimitiveMap } from "../types/common" @@ -34,22 +35,6 @@ import { } from "../exceptions" import { Garden } from "../garden" -import { BuildCommand } from "../commands/build" -import { CallCommand } from "../commands/call" -import { ConfigCommand } from "../commands/config" -import { DeployCommand } from "../commands/deploy" -import { DevCommand } from "../commands/dev" -import { EnvironmentCommand } from "../commands/environment/index" -import { PushCommand } from "../commands/push" -import { LoginCommand } from "../commands/login" -import { LogoutCommand } from "../commands/logout" -import { LogsCommand } from "../commands/logs" -import { RunCommand } from "../commands/run" -import { ScanCommand } from "../commands/scan" -import { StatusCommand } from "../commands/status" -import { TestCommand } from "../commands/test" -import { ValidateCommand } from "../commands/validate" - import { RootLogNode, getLogger } from "../logger" import { LogLevel, LoggerType } from "../logger/types" import { BasicTerminalWriter } from "../logger/writers/basic-terminal-writer" @@ -78,7 +63,7 @@ const OUTPUT_RENDERERS = { }, } -const GLOBAL_OPTIONS = { +export const GLOBAL_OPTIONS = { root: new StringParameter({ alias: "r", help: "override project root directory (defaults to working directory)", @@ -140,23 +125,7 @@ export class GardenCli { }) .style(styleConfig) - const commands = [ - new BuildCommand(), - new CallCommand(), - new ConfigCommand(), - new DeployCommand(), - new DevCommand(), - new EnvironmentCommand(), - new LoginCommand(), - new LogoutCommand(), - new LogsCommand(), - new PushCommand(), - new RunCommand(), - new ScanCommand(), - new StatusCommand(), - new TestCommand(), - new ValidateCommand(), - ] + const commands = coreCommands const globalOptions = Object.entries(GLOBAL_OPTIONS) @@ -185,7 +154,7 @@ export class GardenCli { arguments: args = {}, loggerType = DEFAULT_CLI_LOGGER_TYPE, options = {}, - subCommands = [], + subCommands, } = command const argKeys = getKeys(args) diff --git a/src/commands/base.ts b/src/commands/base.ts index 52e84252d4..e514708059 100644 --- a/src/commands/base.ts +++ b/src/commands/base.ts @@ -135,13 +135,15 @@ export abstract class Command l.trim()).join("\n") + : null + + return { + name, + fullName: this.getFullName(), + help, + description, + arguments: describeParameters(this.arguments), + options: describeParameters(this.options), + } + } + // Note: Due to a current TS limitation (apparently covered by https://github.com/Microsoft/TypeScript/issues/7011), // subclass implementations need to explicitly set the types in the implemented function signature. So for now we // can't enforce the types of `args` and `opts` automatically at the abstract class level and have to specify @@ -172,3 +190,12 @@ export async function handleTaskResults( return { result } } } + +export function describeParameters(args?: Parameters) { + if (!args) { return } + return Object.entries(args).map(([argName, arg]) => ({ + name: argName, + usageName: arg.required ? `<${argName}>` : `[${argName}]`, + ...arg, + })) +} diff --git a/src/commands/call.ts b/src/commands/call.ts index 41c4845875..7a3d0fbabb 100644 --- a/src/commands/call.ts +++ b/src/commands/call.ts @@ -35,6 +35,10 @@ export class CallCommand extends Command { name = "call" help = "Call a service endpoint" + description = ` + This resolves the external endpoint for the given service and path, calls the given endpoint and outputs the result. + ` + arguments = callArgs async action(ctx: PluginContext, args: Args): Promise { diff --git a/src/commands/environment/configure.ts b/src/commands/environment/configure.ts index 474a9a77d5..d4c6f5c5f1 100644 --- a/src/commands/environment/configure.ts +++ b/src/commands/environment/configure.ts @@ -16,7 +16,7 @@ import { } from "../base" export const options = { - force: new BooleanParameter({ help: "Force reconfiguration of module(s)" }), + force: new BooleanParameter({ help: "Force reconfiguration of environment" }), } export type Opts = ParameterValues diff --git a/src/commands/index.ts b/src/commands/index.ts new file mode 100644 index 0000000000..c3cf35a02b --- /dev/null +++ b/src/commands/index.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import { Command } from "./base" +import { BuildCommand } from "./build" +import { CallCommand } from "./call" +import { ConfigCommand } from "./config" +import { DeployCommand } from "./deploy" +import { DevCommand } from "./dev" +import { EnvironmentCommand } from "./environment" +import { LoginCommand } from "./login" +import { LogoutCommand } from "./logout" +import { LogsCommand } from "./logs" +import { PushCommand } from "./push" +import { RunCommand } from "./run" +import { ScanCommand } from "./scan" +import { StatusCommand } from "./status" +import { TestCommand } from "./test" +import { ValidateCommand } from "./validate" + +export const coreCommands: Command[] = [ + new BuildCommand(), + new CallCommand(), + new ConfigCommand(), + new DeployCommand(), + new DevCommand(), + new EnvironmentCommand(), + new LoginCommand(), + new LogoutCommand(), + new LogsCommand(), + new PushCommand(), + new RunCommand(), + new ScanCommand(), + new StatusCommand(), + new TestCommand(), + new ValidateCommand(), +] diff --git a/src/docs/generate.ts b/src/docs/generate.ts new file mode 100644 index 0000000000..009129551c --- /dev/null +++ b/src/docs/generate.ts @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +import { + readFileSync, + writeFileSync, +} from "fs" +import * as handlebars from "handlebars" +import { resolve } from "path" +import { GLOBAL_OPTIONS } from "../cli/cli" +import { coreCommands } from "../commands" +import { flatten } from "lodash" +import { describeParameters } from "../commands/base" + +function generateCommandReferenceDocs(docsRoot: string) { + const referenceDir = resolve(docsRoot, "reference") + const outputPath = resolve(referenceDir, "commands.md") + + const commands = flatten(coreCommands.map(cmd => { + if (cmd.subCommands && cmd.subCommands.length) { + return cmd.subCommands.map(subCommandCls => new subCommandCls(cmd).describe()) + } else { + return [cmd.describe()] + } + })) + + const globalOptions = describeParameters(GLOBAL_OPTIONS) + + const templatePath = resolve(__dirname, "templates", "commands.hbs") + handlebars.registerPartial( + "argType", + "{{#if choices}}{{#each choices}}`{{.}}` {{/each}}{{else}}{{type}}{{/if}}", + ) + const template = handlebars.compile(readFileSync(templatePath).toString()) + const markdown = template({ commands, globalOptions }) + + writeFileSync(outputPath, markdown) +} + +export function generateDocs(targetDir: string) { + const docsRoot = resolve(process.cwd(), targetDir) + generateCommandReferenceDocs(docsRoot) +} diff --git a/src/docs/templates/commands.hbs b/src/docs/templates/commands.hbs new file mode 100644 index 0000000000..60e2bcfeed --- /dev/null +++ b/src/docs/templates/commands.hbs @@ -0,0 +1,49 @@ +## Garden CLI commands + +Below is a list of Garden CLI commands and usage information. + +The commands should be run in a Garden project root, and are always scoped to that project. + +Note: You can get a list of commands in the CLI by running `garden -h/--help`, +and detailed help for each command using `garden -h/--help` + +##### Global options + +The following option flags can be used with any of the CLI commands: + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | +{{#each globalOptions}} + | `--{{name}}` | {{#if alias}}`-{{alias}}`{{/if}} | {{> argType}} | {{help}} +{{/each}} + +{{#each commands}} +### garden {{fullName}} + +{{help}}. + +{{#if description}}{{description}} +{{/if}} +##### Usage + + garden {{fullName}} {{#each arguments}}{{{usageName}}} {{/each}}{{#if options}}[options]{{/if}} + +{{#if arguments}} +##### Arguments +| Argument | Required | Description | +| -------- | -------- | ----------- | +{{#each arguments}} + | `{{name}}` | {{#if required}}Yes{{else}}No{{/if}} | {{help}} +{{/each}} + +{{/if}} +{{#if options}} +##### Options +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | +{{#each options}} + | `--{{name}}` | {{#if alias}}`-{{alias}}`{{/if}} | {{> argType}} | {{help}} +{{/each}} + +{{/if}} +{{/each}} From b6435f88d5bc4777aba9029a4d689a97063c0f63 Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Wed, 30 May 2018 02:51:05 +0200 Subject: [PATCH 5/9] docs: add description to every Joi schema (where applicable) --- src/commands/config/set.ts | 1 + src/config-store.ts | 18 +- src/plugins/container.ts | 108 ++++++++--- src/plugins/generic.ts | 19 +- src/plugins/google/google-cloud-functions.ts | 21 +- src/plugins/kubernetes/index.ts | 31 ++- src/plugins/kubernetes/local.ts | 18 +- src/types/common.ts | 12 +- src/types/config.ts | 10 +- src/types/module.ts | 81 +++++--- src/types/plugin/index.ts | 46 +++-- src/types/plugin/outputs.ts | 194 +++++++++++++------ src/types/project.ts | 56 ++++-- src/types/service.ts | 86 +++++--- src/types/test.ts | 32 ++- 15 files changed, 519 insertions(+), 214 deletions(-) diff --git a/src/commands/config/set.ts b/src/commands/config/set.ts index 836a70f766..f95fff3876 100644 --- a/src/commands/config/set.ts +++ b/src/commands/config/set.ts @@ -16,6 +16,7 @@ import { } from "../base" export const configSetArgs = { + // TODO: specify and validate config key schema here key: new StringParameter({ help: "The key of the configuration variable. Separate with dots to set a nested key (e.g. key.nested)", required: true, diff --git a/src/config-store.ts b/src/config-store.ts index d3a7c06937..63eea909f6 100644 --- a/src/config-store.ts +++ b/src/config-store.ts @@ -167,15 +167,19 @@ export interface LocalConfig { kubernetes?: KubernetesLocalConfig } -const kubernetesLocalConfigSchema = Joi.object().keys({ - username: joiIdentifier().allow("").optional(), - "previous-usernames": Joi.array().items(joiIdentifier()).optional(), -}) +const kubernetesLocalConfigSchema = Joi.object() + .keys({ + username: joiIdentifier().allow("").optional(), + "previous-usernames": Joi.array().items(joiIdentifier()).optional(), + }) + .meta({ internal: true }) // TODO: Dynamically populate schema with all possible provider keys? -const localConfigSchema = Joi.object().keys({ - kubernetes: kubernetesLocalConfigSchema, -}) +const localConfigSchema = Joi.object() + .keys({ + kubernetes: kubernetesLocalConfigSchema, + }) + .meta({ internal: true }) export class LocalConfigStore extends ConfigStore { diff --git a/src/plugins/container.ts b/src/plugins/container.ts index 4461c85886..60d9ae4906 100644 --- a/src/plugins/container.ts +++ b/src/plugins/container.ts @@ -95,47 +95,86 @@ export type ContainerServiceConfig = ServiceConfig const endpointSchema = Joi.object() .keys({ - paths: Joi.array().items(Joi.string().uri({ relativeOnly: true })), + paths: Joi.array() + .items(Joi.string().uri({ relativeOnly: true })) + .description("The paths which should be routed to the service."), // hostname: Joi.string(), - port: Joi.string().required(), + port: Joi.string() + .required() + .description("The name of the container port where the specified paths should be routed."), }) const healthCheckSchema = Joi.object() .keys({ - httpGet: Joi.object().keys({ - path: Joi.string().required(), - port: Joi.string().required(), - scheme: Joi.string().allow("HTTP", "HTTPS").default("HTTP"), - }), - command: Joi.array().items(Joi.string()), - tcpPort: Joi.string(), + httpGet: Joi.object() + .keys({ + path: Joi.string() + .uri({ relativeOnly: true }) + .required() + .description("The path of the service's health check endpoint."), + port: Joi.string() + .required() + .description("The name of the port where the service's health check endpoint should be available."), + scheme: Joi.string().allow("HTTP", "HTTPS").default("HTTP"), + }) + .description("Set this to check the service's health by making an HTTP request"), + command: Joi.array().items(Joi.string()) + .description("Set this to check the service's health by running a command in its container."), + tcpPort: Joi.string() + .description("Set this to check the service's health by checking if this TCP port is accepting connections."), }).xor("httpGet", "command", "tcpPort") const portSchema = Joi.object() .keys({ - name: joiIdentifier().required(), - protocol: Joi.string().allow("TCP", "UDP").default(DEFAULT_PORT_PROTOCOL), - containerPort: Joi.number().required(), - hostPort: Joi.number(), - nodePort: Joi.number(), + name: joiIdentifier() + .required() + .description("The name of the port (used when referencing the port elsewhere in the service configuration."), + protocol: Joi.string() + .allow("TCP", "UDP") + .default(DEFAULT_PORT_PROTOCOL) + .description("The protocol of the service container port."), + containerPort: Joi.number() + .required() + .description("The port number on the service container."), + hostPort: Joi.number() + .meta({ deprecated: true }), + nodePort: Joi.number() + .description( + "Set this to expose the service on the specified port on the host node " + + "(may not be supported by all providers).", + ), }) .required() const volumeSchema = Joi.object() .keys({ - name: joiIdentifier().required(), - containerPath: Joi.string().required(), - hostPath: Joi.string(), + name: joiIdentifier() + .required() + .description("The name of the allocated volume."), + containerPath: Joi.string() + .required() + .description("The path where the volume should be mounted in the container."), + hostPath: Joi.string() + .meta({ deprecated: true }), }) const serviceSchema = baseServiceSchema .keys({ - command: Joi.array().items(Joi.string()), - daemon: Joi.boolean().default(false), - endpoints: joiArray(endpointSchema), - healthCheck: healthCheckSchema, - ports: joiArray(portSchema).unique("name"), - volumes: joiArray(volumeSchema).unique("name"), + command: Joi.array().items(Joi.string()) + .description("The arguments to run the container with when starting the service."), + daemon: Joi.boolean() + .default(false) + .description("Whether to run the service as a daemon (to ensure only one runs per node)."), + endpoints: joiArray(endpointSchema) + .description("List of endpoints that the service exposes."), + healthCheck: healthCheckSchema + .description("Specify how the service's health should be checked after deploying."), + ports: joiArray(portSchema) + .unique("name") + .description("List of ports that the service container exposes."), + volumes: joiArray(volumeSchema) + .unique("name") + .description("List of volumes that should be mounted when deploying the container."), }) export interface ContainerModuleSpec extends GenericModuleSpec { @@ -146,11 +185,24 @@ export interface ContainerModuleSpec extends GenericModuleSpec { export type ContainerModuleConfig = ModuleConfig -export const containerModuleSpecSchema = genericModuleSpecSchema.keys({ - buildArgs: Joi.object().pattern(/.+/, joiPrimitive()).default(() => ({}), "{}"), - image: Joi.string(), - services: joiArray(serviceSchema).unique("name"), -}) +export const containerModuleSpecSchema = genericModuleSpecSchema + .keys({ + buildArgs: Joi.object() + .pattern(/.+/, joiPrimitive()) + .default(() => ({}), "{}") + .description("Specify build arguments when building the container image."), + // TODO: validate the image name format + image: Joi.string() + .description( + "Specify the image name for the container. Should be a valid docker image identifier. If specified and " + + "the module does not contain a Dockerfile, this image will be used to deploy the container services. " + + "If specified and the module does contain a Dockerfile, this identifier is used when pushing the built image.", + ), + services: joiArray(serviceSchema) + .unique("name") + .description("List of services to deploy from this container module."), + }) + .description("Configuration for a container module.") export class ContainerService extends Service { } diff --git a/src/plugins/generic.ts b/src/plugins/generic.ts index b9d9c185b6..d5a2f5476d 100644 --- a/src/plugins/generic.ts +++ b/src/plugins/generic.ts @@ -47,17 +47,24 @@ export interface GenericTestSpec extends BaseTestSpec { command: string[], } -export const genericTestSchema = baseTestSpecSchema.keys({ - command: Joi.array().items(Joi.string()), -}) +export const genericTestSchema = baseTestSpecSchema + .keys({ + command: Joi.array().items(Joi.string()) + .description("The command to run in the module build context in order to test it."), + }) + .description("The test specification of a generic module.") export interface GenericModuleSpec extends ModuleSpec { tests: GenericTestSpec[], } -export const genericModuleSpecSchema = Joi.object().keys({ - tests: joiArray(genericTestSchema), -}).unknown(false) +export const genericModuleSpecSchema = Joi.object() + .keys({ + tests: joiArray(genericTestSchema) + .description("A list of tests to run in the module."), + }) + .unknown(false) + .description("The module specification for a generic module.") export class GenericModule extends Module { } diff --git a/src/plugins/google/google-cloud-functions.ts b/src/plugins/google/google-cloud-functions.ts index cf544a9ad7..1367417ef0 100644 --- a/src/plugins/google/google-cloud-functions.ts +++ b/src/plugins/google/google-cloud-functions.ts @@ -50,11 +50,22 @@ export interface GcfServiceSpec extends GoogleCloudServiceSpec { path: string, } -export const gcfServicesSchema = joiArray(baseServiceSchema.keys({ - entrypoint: Joi.string(), - path: Joi.string().default("."), - project: Joi.string(), -})).unique("name") +const gcfServiceSchema = baseServiceSchema + .keys({ + entrypoint: Joi.string() + .description("The entrypoint for the function (exported name in the function's module)"), + path: Joi.string() + .default(".") + .description("The path of the module that contains the function."), + project: Joi.string() + .description("The Google Cloud project name of the function."), + }) + .description("Configuration for a Google Cloud Function.") + +export const gcfServicesSchema = joiArray(gcfServiceSchema) + .min(1) + .unique("name") + .description("List of configurations for one or more Google Cloud Functions.") export interface GcfModuleSpec extends ModuleSpec { functions: GcfServiceSpec[], diff --git a/src/plugins/kubernetes/index.ts b/src/plugins/kubernetes/index.ts index 49f31fc9b9..5ec02280d8 100644 --- a/src/plugins/kubernetes/index.ts +++ b/src/plugins/kubernetes/index.ts @@ -50,14 +50,29 @@ export interface KubernetesConfig extends ProviderConfig { export interface KubernetesProvider extends Provider { } -const configSchema = providerConfigBase.keys({ - context: Joi.string().required(), - ingressHostname: Joi.string().hostname().required(), - ingressPort: Joi.number().default(80), - ingressClass: Joi.string(), - forceSsl: Joi.boolean().default(true), - _system: Joi.any(), -}) +const kubernetesConfigBase = providerConfigBase + .keys({ + context: Joi.string() + .required() + .description("The kubectl context to use to connect to the Kubernetes cluster."), + ingressHostname: Joi.string() + .hostname() + .required() + .description("The external hostname of the cluster's ingress controller."), + }) + +const configSchema = kubernetesConfigBase + .keys({ + ingressPort: Joi.number() + .default(80) + .description("The external port of the cluster's ingress controller."), + ingressClass: Joi.string() + .description("The ingress class to use on configured Ingresses when deploying services."), + forceSsl: Joi.boolean() + .default(true) + .description("Whether to force use of SSL in configured Ingresses when deploying services."), + _system: Joi.any().meta({ internal: true }), + }) export function gardenPlugin({ config }: { config: KubernetesConfig }): GardenPlugin { config = validate(config, configSchema, { context: "kubernetes provider config" }) diff --git a/src/plugins/kubernetes/local.ts b/src/plugins/kubernetes/local.ts index 91db033fb3..436ae8328e 100644 --- a/src/plugins/kubernetes/local.ts +++ b/src/plugins/kubernetes/local.ts @@ -139,12 +139,18 @@ export interface LocalKubernetesConfig extends KubernetesConfig { _systemServices?: string[] } -const configSchema = providerConfigBase.keys({ - context: Joi.string(), - ingressHostname: Joi.string(), - _system: Joi.any(), - _systemServices: Joi.array().items(Joi.string()), -}) +const configSchema = providerConfigBase + .keys({ + context: Joi.string() + .description("The kubectl context to use to connect to the Kubernetes cluster."), + ingressHostname: Joi.string() + .description("The hostname of the cluster's ingress controller."), + _system: Joi.any().meta({ internal: true }), + _systemServices: Joi.array().items(Joi.string()) + .meta({ internal: true }) + .description("The system services which should be automatically deployed to the cluster."), + }) + .description("The provider configuration for the local-kubernetes plugin.") export const name = "local-kubernetes" diff --git a/src/types/common.ts b/src/types/common.ts index 1ac751e94c..bfba946100 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -27,6 +27,7 @@ export const enumToArray = Enum => ( ) export const joiPrimitive = () => Joi.alternatives().try(Joi.number(), Joi.string(), Joi.boolean()) + .description("Number, string or boolean") export const identifierRegex = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/ export const envVarRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/ @@ -34,25 +35,30 @@ export const envVarRegex = /^[a-zA-Z_][a-zA-Z0-9_]*$/ export const joiIdentifier = () => Joi .string().regex(identifierRegex) .description( - "may contain lowercase letters, numbers and dashes, must start with a letter, " + - "cannot contain consecutive dashes and cannot end with a dash", + "Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, " + + "and cannot end with a dash) and additionally cannot contain consecutive dashes", ) export const joiIdentifierMap = (valueSchema: JoiObject) => Joi .object().pattern(identifierRegex, valueSchema) .default(() => ({}), "{}") + .description("Key/value map, keys must be valid identifiers.") export const joiVariables = () => Joi .object().pattern(/[\w\d]+/i, joiPrimitive()) .default(() => ({}), "{}") + .description("Key/value map, keys may contain letters and numbers, and values must be primitives.") export const joiEnvVarName = () => Joi .string().regex(envVarRegex) - .description("may contain letters and numbers, cannot start with a number") + .description( + "Valid POSIX environment variable name (may contain letters, numbers and underscores and must start with a letter.", +) export const joiEnvVars = () => Joi .object().pattern(envVarRegex, joiPrimitive()) .default(() => ({}), "{}") + .description("Key/value map, keys must be valid POSIX environment variable names, and values must be primitives.") export const joiArray = (schema) => Joi .array().items(schema) diff --git a/src/types/config.ts b/src/types/config.ts index 0c53dbcb0f..6cf15c9552 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -33,14 +33,18 @@ export interface GardenConfig { export const configSchema = Joi.object() .keys({ // TODO: should this be called apiVersion? - version: Joi.string().default("0").only("0"), - dirname: Joi.string(), - path: Joi.string(), + version: Joi.string() + .default("0") + .only("0") + .description("The schema version of the config file (currently not used)."), + dirname: Joi.string().meta({ internal: true }), + path: Joi.string().meta({ internal: true }), module: baseModuleSpecSchema, project: projectSchema, }) .optionalKeys(["module", "project"]) .required() + .description("The garden.yml config file.") const baseModuleSchemaKeys = Object.keys(baseModuleSpecSchema.describe().children) diff --git a/src/types/module.ts b/src/types/module.ts index 2666e1344c..1e20fc2150 100644 --- a/src/types/module.ts +++ b/src/types/module.ts @@ -31,6 +31,7 @@ import { import { getNames } from "../util" import { TreeVersion } from "../vcs/base" import { + joiArray, joiEnvVars, joiIdentifier, joiVariables, @@ -55,11 +56,17 @@ export interface BuildCopySpec { } // TODO: allow : delimited string (e.g. some.file:some-dir/) -const copySchema = Joi.object().keys({ - // TODO: allow array of strings here - source: Joi.string().uri({ relativeOnly: true }).required(), - target: Joi.string().uri({ relativeOnly: true }).default(""), -}) +const copySchema = Joi.object() + .keys({ + // TODO: allow array of strings here + // TODO: disallow paths outside of the module root + source: Joi.string().uri({ relativeOnly: true }).required() + .description("POSIX-style path or filename of the directory or file(s) to copy to the target."), + target: Joi.string().uri({ relativeOnly: true }).default("") + .description( + "POSIX-style path or filename to copy the directory or file(s) to (defaults to same as source path).", + ), + }) export interface BuildDependencyConfig { name: string @@ -68,9 +75,13 @@ export interface BuildDependencyConfig { } export const buildDependencySchema = Joi.object().keys({ - name: joiIdentifier().required(), - plugin: joiIdentifier(), - copy: Joi.array().items(copySchema).default(() => [], "[]"), + name: joiIdentifier().required() + .description("Module name to build ahead of this module"), + plugin: joiIdentifier() + .meta({ internal: true }) + .description("The name of plugin that provides the build dependency."), + copy: joiArray(copySchema) + .description("Specify one or more files or directories to copy from the built dependency to this module."), }) export interface BuildConfig { @@ -79,11 +90,13 @@ export interface BuildConfig { dependencies: BuildDependencyConfig[], } -const versionFileSchema = Joi.object().keys({ - versionString: Joi.string().required(), - latestCommit: Joi.string().required(), - dirtyTimestamp: Joi.number().allow(null).required(), -}) +const versionFileSchema = Joi.object() + .keys({ + versionString: Joi.string().required(), + latestCommit: Joi.string().required(), + dirtyTimestamp: Joi.number().allow(null).required(), + }) + .meta({ internal: true }) export interface ModuleSpec { } @@ -97,27 +110,39 @@ export interface BaseModuleSpec { variables: PrimitiveMap } -export const baseModuleSpecSchema = Joi.object().keys({ - type: joiIdentifier().required(), - name: joiIdentifier(), - description: Joi.string(), - variables: joiVariables(), - allowPush: Joi.boolean() - .default(true, "Set to false to disable pushing this module to remote registries"), - build: Joi.object().keys({ - command: Joi.string(), - dependencies: Joi.array().items(buildDependencySchema).default(() => [], "[]"), - }).default(() => ({ dependencies: [] }), "{}"), -}).required().unknown(true) +export const baseModuleSpecSchema = Joi.object() + .keys({ + type: joiIdentifier().required().description("The type of this module (e.g. container)."), + name: joiIdentifier(), + description: Joi.string(), + variables: joiVariables() + .description("Variables that this module can reference and expose as environment variables."), + allowPush: Joi.boolean() + .default(true) + .description("Set to false to disable pushing this module to remote registries."), + build: Joi.object().keys({ + command: Joi.string() + .description("The command to run inside the module directory to perform the build."), + dependencies: joiArray(buildDependencySchema) + .description("A list of modules that must be built before this module is built."), + }).default(() => ({ dependencies: [] }), "{}"), + }) + .required() + .unknown(true) + .meta({ extendable: true }) export interface ModuleConfig extends BaseModuleSpec { // Plugins can add custom fields that are kept here spec: T } -export const moduleConfigSchema = baseModuleSpecSchema.keys({ - spec: Joi.object(), -}) +export const moduleConfigSchema = baseModuleSpecSchema + .keys({ + spec: Joi.object() + .meta({ extendable: true }) + .description("The module spec, as defined by the provider plugin."), + }) + .description("The configuration for a module.") export interface ModuleConstructor< M extends ModuleSpec = ModuleSpec, diff --git a/src/types/plugin/index.ts b/src/types/plugin/index.ts index 6ef4b06269..30b5aa2219 100644 --- a/src/types/plugin/index.ts +++ b/src/types/plugin/index.ts @@ -10,6 +10,7 @@ import * as Joi from "joi" import { mapValues } from "lodash" import { DeepPrimitiveMap, + joiArray, joiIdentifier, joiIdentifierMap, PrimitiveMap, @@ -171,16 +172,35 @@ export interface PluginFactory { } export type RegisterPluginParam = string | PluginFactory -export const pluginSchema = Joi.object().keys({ - config: Joi.object(), - modules: Joi.array().items(Joi.string()), - actions: Joi.object().keys(mapValues(pluginActionDescriptions, () => Joi.func())), - moduleActions: joiIdentifierMap( - Joi.object().keys(mapValues(moduleActionDescriptions, () => Joi.func())), - ), -}) - -export const pluginModuleSchema = Joi.object().keys({ - name: joiIdentifier(), - gardenPlugin: Joi.func().required(), -}).unknown(true) +export const pluginSchema = Joi.object() + .keys({ + config: Joi.object() + .meta({ extendable: true }) + .description( + "Plugins may use this key to override or augment their configuration " + + "(as specified in the garden.yml provider configuration.", + ), + modules: joiArray(Joi.string()) + .description( + "Plugins may optionally provide paths to Garden modules that are loaded as part of the plugin. " + + "This is useful, for example, to provide build dependencies for other modules " + + "or as part of the plugin operation.", + ), + // TODO: document plugin actions further + actions: Joi.object().keys(mapValues(pluginActionDescriptions, () => Joi.func())) + .description("A map of plugin action handlers provided by the plugin."), + moduleActions: joiIdentifierMap( + Joi.object().keys(mapValues(moduleActionDescriptions, () => Joi.func()), + ).description("A map of module names and module action handlers provided by the plugin."), + ), + }) + .description("The schema for Garden plugins.") + +export const pluginModuleSchema = Joi.object() + .keys({ + name: joiIdentifier(), + gardenPlugin: Joi.func().required() + .description("The initialization function for the plugin. Should return a valid Garden plugin object."), + }) + .unknown(true) + .description("A module containing a Garden plugin.") diff --git a/src/types/plugin/outputs.ts b/src/types/plugin/outputs.ts index d92f13ae5e..0ffa506715 100644 --- a/src/types/plugin/outputs.ts +++ b/src/types/plugin/outputs.ts @@ -27,10 +27,16 @@ export interface EnvironmentStatus { detail?: any } -export const environmentStatusSchema = Joi.object().keys({ - configured: Joi.boolean().required(), - detail: Joi.object(), -}) +export const environmentStatusSchema = Joi.object() + .keys({ + configured: Joi.boolean() + .required() + .description("Set to true if the environment is fully configured for a provider."), + detail: Joi.object() + .meta({ extendable: true }) + .description("Use this to include additional information that is specific to the provider."), + }) + .description("Description of an environment's status for a provider.") export type EnvironmentStatusMap = { [key: string]: EnvironmentStatus, @@ -48,9 +54,13 @@ export interface GetConfigResult { value: string | null } -export const getConfigResultSchema = Joi.object().keys({ - value: Joi.string().allow(null).required(), -}) +export const getConfigResultSchema = Joi.object() + .keys({ + value: Joi.string() + .allow(null) + .required() + .description("The config value found for the specified key (as string), or null if not found."), + }) export interface SetConfigResult { } @@ -60,17 +70,23 @@ export interface DeleteConfigResult { found: boolean } -export const deleteConfigResultSchema = Joi.object().keys({ - found: Joi.boolean().required(), -}) +export const deleteConfigResultSchema = Joi.object() + .keys({ + found: Joi.boolean() + .required() + .description("Set to true if the key was deleted, false if it was not found."), + }) export interface LoginStatus { loggedIn: boolean } -export const loginStatusSchema = Joi.object().keys({ - loggedIn: Joi.boolean().required(), -}) +export const loginStatusSchema = Joi.object() + .keys({ + loggedIn: Joi.boolean() + .required() + .description("Set to true if the user is already logged in, otherwise false."), + }) export interface LoginStatusMap { [key: string]: LoginStatus, @@ -83,12 +99,19 @@ export interface ExecInServiceResult { stderr?: string } -export const execInServiceResultSchema = Joi.object().keys({ - code: Joi.number().required(), - output: Joi.string().required(), - stdout: Joi.string(), - stderr: Joi.string(), -}) +export const execInServiceResultSchema = Joi.object() + .keys({ + code: Joi.number() + .required() + .description("The exit code of the command executed in the service container."), + output: Joi.string() + .required() + .description("The output of the executed command."), + stdout: Joi.string() + .description("The stdout output of the executed command (if available)."), + stderr: Joi.string() + .description("The stderr output of the executed command (if available)."), + }) export interface ServiceLogEntry { serviceName: string @@ -96,11 +119,19 @@ export interface ServiceLogEntry { msg: string } -export const serviceLogEntrySchema = Joi.object().keys({ - serviceName: Joi.string().required(), - timestamp: Joi.date().required(), - msg: Joi.string().required(), -}) +export const serviceLogEntrySchema = Joi.object() + .keys({ + serviceName: Joi.string() + .required() + .description("The name of the service the log entry originated from."), + timestamp: Joi.date() + .required() + .description("The time when the log entry was generated by the service."), + msg: Joi.string() + .required() + .description("The content of the log entry."), + }) + .description("A log entry returned by a getServiceLogs action handler.") export interface GetServiceLogsResult { } @@ -113,9 +144,15 @@ export interface ParseModuleResult { } export const parseModuleResultSchema = Joi.object().keys({ - module: moduleConfigSchema.required(), - services: joiArray(serviceConfigSchema).required(), - tests: joiArray(testConfigSchema).required(), + module: moduleConfigSchema + .required() + .description("The parsed module configuration."), + services: joiArray(serviceConfigSchema) + .required() + .description("List of deployable services provided by the module."), + tests: joiArray(testConfigSchema) + .required() + .description("List of tests defined by the module."), }) export interface BuildResult { @@ -126,23 +163,33 @@ export interface BuildResult { details?: any } -export const buildModuleResultSchema = Joi.object().keys({ - buildLog: Joi.string(), - fetched: Joi.boolean(), - fresh: Joi.boolean(), - version: Joi.string(), - details: Joi.object(), -}) +export const buildModuleResultSchema = Joi.object() + .keys({ + buildLog: Joi.string() + .description("The full log from the build."), + fetched: Joi.boolean() + .description("Set to true if the build was fetched from a remote registry."), + fresh: Joi.boolean() + .description("Set to true if the build was perfomed, false if it was already built, or fetched from a registry"), + version: Joi.string() + .description("The version that was built."), + details: Joi.object() + .description("Additional information, specific to the provider."), + }) export interface PushResult { pushed: boolean message?: string } -export const pushModuleResultSchema = Joi.object().keys({ - pushed: Joi.boolean().required(), - message: Joi.string(), -}) +export const pushModuleResultSchema = Joi.object() + .keys({ + pushed: Joi.boolean() + .required() + .description("Set to true if the module was pushed."), + message: Joi.string() + .description("Optional result message."), + }) export interface RunResult { moduleName: string @@ -154,29 +201,55 @@ export interface RunResult { output: string } -export const treeVersionSchema = Joi.object().keys({ - versionString: Joi.string().required(), - latestCommit: Joi.string().required(), - dirtyTimestamp: Joi.number().allow(null).required(), -}) - -export const runResultSchema = Joi.object().keys({ - moduleName: Joi.string(), - command: Joi.array().items(Joi.string()).required(), - version: treeVersionSchema, - success: Joi.boolean().required(), - startedAt: Joi.date().required(), - completedAt: Joi.date().required(), - output: Joi.string().required().allow(""), -}) +export const treeVersionSchema = Joi.object() + .keys({ + versionString: Joi.string() + .required() + .description("String representation of the module version."), + latestCommit: Joi.string() + .required() + .description("The latest commit hash of the module source."), + dirtyTimestamp: Joi.number() + .allow(null) + .required() + .description( + "Set to the last modified time (as UNIX timestamp) if the module contains uncommitted changes, otherwise null.", + ), + }) + +export const runResultSchema = Joi.object() + .keys({ + moduleName: Joi.string() + .description("The name of the module that was run."), + command: Joi.array().items(Joi.string()) + .required() + .description("The command that was run in the module."), + version: treeVersionSchema, + success: Joi.boolean() + .required() + .description("Whether the module was successfully run."), + startedAt: Joi.date() + .required() + .description("When the module run was started."), + completedAt: Joi.date() + .required() + .description("When the module run was completed."), + output: Joi.string() + .required() + .allow("") + .description("The output log from the run."), + }) export interface TestResult extends RunResult { testName: string } -export const testResultSchema = runResultSchema.keys({ - testName: Joi.string().required(), -}) +export const testResultSchema = runResultSchema + .keys({ + testName: Joi.string() + .required() + .description("The name of the test that was run."), + }) export const getTestResultSchema = testResultSchema.allow(null) @@ -184,9 +257,12 @@ export interface BuildStatus { ready: boolean } -export const buildStatusSchema = Joi.object().keys({ - ready: Joi.boolean().required(), -}) +export const buildStatusSchema = Joi.object() + .keys({ + ready: Joi.boolean() + .required() + .description("Whether an up-to-date build is ready for the module."), + }) export interface PluginActionOutputs { getEnvironmentStatus: Promise diff --git a/src/types/project.ts b/src/types/project.ts index 0679fdd353..2260c7643b 100644 --- a/src/types/project.ts +++ b/src/types/project.ts @@ -52,14 +52,27 @@ export const defaultEnvironments: EnvironmentConfig[] = [ }, ] -export const providerConfigBase = Joi.object().keys({ - name: joiIdentifier().required(), -}).unknown(true) +export const providerConfigBase = Joi.object() + .keys({ + name: joiIdentifier().required() + .description("The name of the provider plugin to configure.") + .example("local-kubernetes"), + }) + .unknown(true) + .meta({ extendable: true }) export const environmentSchema = Joi.object().keys({ - configurationHandler: joiIdentifier(), - providers: joiArray(providerConfigBase).unique("name"), - variables: joiVariables(), + configurationHandler: joiIdentifier() + .description( + "Specify the provider that should store configuration variables for this environment. " + + "Use this when you configure multiple providers that can manage configuration.", + ), + providers: joiArray(providerConfigBase) + .unique("name") + .description("A list of providers that should be used for this environment, and their configuration.") + .example(defaultProviders), + variables: joiVariables() + .description("A key/value map of variables that modules can reference when using this environment."), }) const defaultGlobal = { @@ -67,11 +80,26 @@ const defaultGlobal = { variables: {}, } -export const projectSchema = Joi.object().keys({ - name: joiIdentifier().required(), - defaultEnvironment: Joi.string().default("", ""), - global: environmentSchema.default(() => defaultGlobal, JSON.stringify(defaultGlobal)), - environments: joiArray(environmentSchema.keys({ name: joiIdentifier().required() })) - .unique("name") - .default(() => ({ ...defaultEnvironments }), JSON.stringify(defaultEnvironments)), -}).required() +export const projectSchema = Joi.object() + .keys({ + name: joiIdentifier() + .required() + .description("The name of the project."), + defaultEnvironment: Joi.string() + .default("", "") + .description("The default environment to use when calling commands without the `--env` parameter."), + global: environmentSchema + .default(() => defaultGlobal, JSON.stringify(defaultGlobal)) + .description( + "Default environment settings, that are inherited (but can be overridden) by each configured environment", + ), + environments: joiArray(environmentSchema.keys({ name: joiIdentifier().required() })) + .unique("name") + .default(() => ({ ...defaultEnvironments }), JSON.stringify(defaultEnvironments)) + .description("A list of environments to configure for the project.") + .example(defaultEnvironments), + }) + .required() + .description( + "The configuration for a Garden project. This should be specified in the garden.yml file in your project root.", +) diff --git a/src/types/service.ts b/src/types/service.ts index c12152f356..7350612998 100644 --- a/src/types/service.ts +++ b/src/types/service.ts @@ -25,7 +25,7 @@ import { } from "./common" import { Module } from "./module" -export type ServiceState = "ready" | "deploying" | "stopped" | "unhealthy" +export type ServiceState = "ready" | "deploying" | "stopped" | "unhealthy" | "unknown" export type ServiceProtocol = "http" | "https" | "tcp" | "udp" @@ -37,13 +37,25 @@ export interface ServiceEndpoint { paths?: string[] } -export const serviceEndpointSchema = Joi.object().keys({ - protocol: Joi.string().only("http", "https", "tcp", "udp").required(), - hostname: Joi.string().required(), - port: Joi.number(), - url: Joi.string().required(), - paths: Joi.array().items(Joi.string()), -}) +export const serviceEndpointSchema = Joi.object() + .keys({ + protocol: Joi.string() + .only("http", "https", "tcp", "udp") + .required() + .description("The protocol to use for the endpoint."), + hostname: Joi.string() + .required() + .description("The external hostname of the service endpoint."), + port: Joi.number() + .description("The port number that the service is exposed on."), + url: Joi.string() + .uri() + .required() + .description("The full URL of the service endpoint."), + paths: Joi.array().items(Joi.string()) + .description("The paths that are available on the service endpoint (defaults to any path)."), + }) + .description("A description of a deployed service endpoint.") export interface ServiceSpec { } @@ -58,19 +70,26 @@ export const serviceOutputsSchema = joiIdentifierMap(joiPrimitive()) export const baseServiceSchema = Joi.object() .keys({ name: joiIdentifier().required(), - dependencies: joiArray(joiIdentifier()), + dependencies: joiArray(joiIdentifier()) + .description("The names of services that this service depends on at runtime."), outputs: serviceOutputsSchema, }) .unknown(true) + .meta({ extendable: true }) + .description("The required attributes of a service. This is generally further defined by plugins.") export interface ServiceConfig extends BaseServiceSpec { // Plugins can add custom fields that are kept here spec: T } -export const serviceConfigSchema = baseServiceSchema.keys({ - spec: Joi.object(), -}) +export const serviceConfigSchema = baseServiceSchema + .keys({ + spec: Joi.object() + .meta({ extendable: true }) + .description("The service's specification, as defined by its provider plugin."), + }) + .description("The configuration for a module's service.") // TODO: revise this schema export interface ServiceStatus { @@ -87,19 +106,36 @@ export interface ServiceStatus { detail?: any } -export const serviceStatusSchema = Joi.object().keys({ - providerId: Joi.string(), - providerVersion: Joi.string(), - version: Joi.string(), - state: Joi.string(), - runningReplicas: Joi.number(), - endpoints: Joi.array().items(serviceEndpointSchema), - lastMessage: Joi.string().allow(""), - lastError: Joi.string(), - createdAt: Joi.string(), - updatedAt: Joi.string(), - detail: Joi.object(), -}) +export const serviceStatusSchema = Joi.object() + .keys({ + providerId: Joi.string() + .description("The ID used for the service by the provider (if not the same as the service name)."), + providerVersion: Joi.string() + .description("The provider version of the deployed service (if different from the Garden module version."), + version: Joi.string() + .description("The Garden module version of the deployed service."), + state: Joi.string() + .only("ready", "deploying", "stopped", "unhealthy", "unknown") + .default("unknown") + .description("The current deployment status of the service."), + runningReplicas: Joi.number() + .description("How many replicas of the service are currently running."), + endpoints: Joi.array() + .items(serviceEndpointSchema) + .description("List of currently deployed endpoints for the service."), + lastMessage: Joi.string() + .allow("") + .description("Latest status message of the service (if any)."), + lastError: Joi.string() + .description("Latest error status message of the service (if any)."), + createdAt: Joi.string() + .description("When the service was first deployed by the provider."), + updatedAt: Joi.string() + .description("When the service was last updated by the provider."), + detail: Joi.object() + .meta({ extendable: true }) + .description("Additional detail, specific to the provider."), + }) export type RuntimeContext = { envVars: PrimitiveMap diff --git a/src/types/test.ts b/src/types/test.ts index fa7210945c..cbb9fd2bfb 100644 --- a/src/types/test.ts +++ b/src/types/test.ts @@ -8,6 +8,7 @@ import * as Joi from "joi" import { + joiArray, joiIdentifier, joiVariables, PrimitiveMap, @@ -22,18 +23,31 @@ export interface BaseTestSpec extends TestSpec { timeout: number | null } -export const baseTestSpecSchema = Joi.object().keys({ - name: joiIdentifier().required(), - dependencies: Joi.array().items(Joi.string()).default(() => [], "[]"), - variables: joiVariables(), - timeout: Joi.number().allow(null).default(null), -}) +export const baseTestSpecSchema = Joi.object() + .keys({ + name: joiIdentifier() + .required() + .description("The name of the test."), + dependencies: joiArray(Joi.string()) + .description("The names of services that must be running before the test is run."), + variables: joiVariables() + .description("Map of key/value pairs that are available during the test execution."), + timeout: Joi.number() + .allow(null) + .default(null) + .description("Maximum duration (in seconds) of the test run."), + }) + .description("Required configuration for module tests.") export interface TestConfig extends BaseTestSpec { // Plugins can add custom fields that are kept here spec: T } -export const testConfigSchema = baseTestSpecSchema.keys({ - spec: Joi.object(), -}) +export const testConfigSchema = baseTestSpecSchema + .keys({ + spec: Joi.object() + .meta({ extendable: true }) + .description("The configuration for the test, as specified by its module's provider."), + }) + .description("Configuration for a module test.") From 2cab203980721af9b3cf99f161a574384bdada94 Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Wed, 30 May 2018 18:54:23 +0200 Subject: [PATCH 6/9] docs: add verbose descriptions to all commands --- docs/reference/commands.md | 267 +++++++++++++++++++++----- package-lock.json | 9 +- package.json | 2 + src/cli/cli.ts | 8 +- src/commands/base.ts | 5 +- src/commands/build.ts | 19 +- src/commands/call.ts | 17 +- src/commands/config/delete.ts | 14 +- src/commands/config/get.ts | 14 +- src/commands/config/set.ts | 18 +- src/commands/deploy.ts | 24 ++- src/commands/dev.ts | 13 +- src/commands/environment/configure.ts | 16 +- src/commands/environment/destroy.ts | 12 +- src/commands/exec.ts | 18 +- src/commands/login.ts | 11 +- src/commands/logout.ts | 9 +- src/commands/logs.ts | 15 +- src/commands/push.ts | 19 +- src/commands/run/module.ts | 21 +- src/commands/run/service.ts | 15 +- src/commands/run/test.ts | 20 +- src/commands/scan.ts | 2 +- src/commands/status.ts | 2 +- src/commands/test.ts | 34 +++- src/commands/validate.ts | 7 +- src/docs/templates/commands.hbs | 3 + src/task-graph.ts | 2 +- src/types/module.ts | 4 +- test/src/commands/run/service.ts | 2 +- test/src/commands/test.ts | 4 +- 31 files changed, 504 insertions(+), 122 deletions(-) diff --git a/docs/reference/commands.md b/docs/reference/commands.md index 5ce504a003..2ed6a43529 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -21,100 +21,176 @@ The following option flags can be used with any of the CLI commands: ### garden build -Build your modules. +Build your modules.. + +Builds all or specified modules, taking into account build dependency order. +Optionally stays running and automatically builds modules if their source (or their dependencies' sources) change. + +Examples: + + garden build # build all modules in the project + garden build my-module # only build my-module + garden build --force # force rebuild of modules + garden build --watch # watch for changes to code ##### Usage garden build [module] [options] ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | | `module` | No | Specify module(s) to build. Use comma separator to specify multiple modules. ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--force` | | boolean | Force rebuild of module(s) - | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-build + | `--force` | | boolean | Force rebuild of module(s). + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-build. ### garden call -Call a service endpoint. +Call a service endpoint.. + +This command resolves the deployed external endpoint for the given service and path, calls the given endpoint and +outputs the result. + +Examples: + + garden call my-container + garden call my-container/some-path + +Note: Currently only supports HTTP/HTTPS endpoints. -This resolves the external endpoint for the given service and path, calls the given endpoint and outputs the result. ##### Usage garden call ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | - | `serviceAndPath` | Yes | The name of the service(s) to call followed by the endpoint path (e.g. my-container/somepath) + | `serviceAndPath` | Yes | The name of the service(s) to call followed by the endpoint path (e.g. my-container/somepath). ### garden config get -Get a configuration variable. +Get a configuration variable from the environment.. + +Returns with an error if the provided key could not be found in the configuration. + +Examples: + + garden get somekey + garden get some.nested.key ##### Usage garden config get ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | - | `key` | Yes | The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested) + | `key` | Yes | The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested). ### garden config set -Set a configuration variable. +Set a configuration variable in the environment.. + +These configuration values can be referenced in module templates, for example as environment variables. + +_Note: The value is always stored as a string._ + +Examples: + + garden set somekey myvalue + garden set some.nested.key myvalue ##### Usage garden config set ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | - | `key` | Yes | The key of the configuration variable. Separate with dots to set a nested key (e.g. key.nested) - | `value` | Yes | The value of the configuration variable + | `key` | Yes | The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested). + | `value` | Yes | The value of the configuration variable. ### garden config delete -Delete a configuration variable. +Delete a configuration variable from the Garden environment.. + +Returns with an error if the provided key could not be found in the configuration. + +Examples: + + garden delete somekey + garden delete some.nested.key ##### Usage garden config delete ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | - | `key` | Yes | The key of the configuration variable + | `key` | Yes | The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested). ### garden deploy -Deploy service(s) to the specified environment. +Deploy service(s) to your environment.. + + + Deploys all or specified services, taking into account service dependency order. + Also builds modules and dependencies if needed. + + Optionally stays running and automatically re-builds and re-deploys services if their module source + (or their dependencies' sources) change. + + Examples: + + garden deploy # deploy all modules in the project + garden deploy my-service # only deploy my-service + garden deploy --force # force re-deploy of modules, even if they're already deployed + garden deploy --watch # watch for changes to code + garden deploy --env stage # deploy your services to an environment called stage + ##### Usage garden deploy [service] [options] ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | | `service` | No | The name of the service(s) to deploy (skip to deploy all services). Use comma as separator to specify multiple services. ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--force` | | boolean | Force redeploy of service(s) - | `--force-build` | | boolean | Force rebuild of module(s) - | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-deploy + | `--force` | | boolean | Force redeploy of service(s). + | `--force-build` | | boolean | Force rebuild of module(s). + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-deploy. ### garden dev -Starts the garden development console. +Starts the garden development console.. + + + The Garden dev console is a combination of the `build`, `deploy` and `test` commands. + It builds, deploys and tests all your modules and services, and re-builds, re-deploys and re-tests + as you modify the code. + + Examples: + + garden dev + ##### Usage @@ -122,20 +198,37 @@ Starts the garden development console. ### garden environment configure -Configures your environment. +Configures your environment.. + +Generally, environments are configured automatically as part of other commands that you run. +However, this command is useful if you want to make sure the environment is ready before running +another command, or if you need to force a reconfiguration using the --force flag. + +Examples: + + garden env configure + garden env configure --force ##### Usage garden environment configure [options] ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--force` | | boolean | Force reconfiguration of environment + | `--force` | | boolean | Force reconfiguration of environment, ignoring the environment status check. ### garden environment destroy -Destroy environment. +Destroy an environment.. + +Generally not as dramatic as it sounds :) This will trigger providers clear up any deployments in a +Garden environment and reset it. When you then run `garden env configure` or any deployment command, +the environment will be reconfigured. + +This can be useful if you find the environment to be in an inconsistent state, or need/want to free up +resources. ##### Usage @@ -143,7 +236,13 @@ Destroy environment. ### garden login -Log into the Garden framework. +Log into configured providers for this project and environment.. + +Executes the login flow for any provider that requires login (such as the `kubernetes` provider). + +Examples: + + garden login ##### Usage @@ -151,7 +250,11 @@ Log into the Garden framework. ### garden logout -Log into the Garden framework. +Log out of configured providers for this project and environment.. + +Examples: + + garden logout ##### Usage @@ -159,103 +262,152 @@ Log into the Garden framework. ### garden logs -Retrieves the most recent logs for the specified service(s). +Retrieves the most recent logs for the specified service(s).. + +Outputs logs for all or specified services, and optionally waits for news logs to come in. + +Examples: + + garden logs # prints latest logs from all services + garden logs my-service # prints latest logs for my-service + garden logs -t # keeps running and streams all incoming logs to the console ##### Usage garden logs [service] [options] ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | | `service` | No | The name of the service(s) to logs (skip to logs all services). Use comma as separator to specify multiple services. ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--tail` | `-t` | boolean | Continuously stream new logs from the service(s) + | `--tail` | `-t` | boolean | Continuously stream new logs from the service(s). ### garden push -Build and push module(s) to remote registry. +Build and push built module(s) to remote registry.. + +Pushes built module artifacts for all or specified modules. +Also builds modules and dependencies if needed. + +Examples: + + garden push # push artifacts for all modules in the project + garden push my-container # only push my-container + garden push --force-build # force re-build of modules before pushing artifacts + garden push --allow-dirty # allow pushing dirty builds (which usually triggers error) ##### Usage garden push [module] [options] ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | | `module` | No | The name of the module(s) to push (skip to push all modules). Use comma as separator to specify multiple modules. ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--force-build` | | boolean | Force rebuild of module(s) before pushing - | `--allow-dirty` | | boolean | Allow pushing dirty builds (with untracked/uncommitted files) + | `--force-build` | | boolean | Force rebuild of module(s) before pushing. + | `--allow-dirty` | | boolean | Allow pushing dirty builds (with untracked/uncommitted files). ### garden run module -Run the specified module. +Run an ad-hoc instance of a module.. + +This is useful for debugging or ad-hoc experimentation with modules. + +Examples: + + garden run module my-container # run an ad-hoc instance of a my-container container and attach to it + garden run module my-container /bin/sh # run an interactive shell in a new my-container container + garden run module my-container --i=false /some/script # execute a script in my-container and return the output ##### Usage garden run module [command] [options] ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | - | `module` | Yes | The name of the module to run - | `command` | No | The command to run in the module + | `module` | Yes | The name of the module to run. + | `command` | No | The command to run in the module. ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result - | `--force-build` | | boolean | Force rebuild of module + | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result. + | `--force-build` | | boolean | Force rebuild of module before running. ### garden run service Run an ad-hoc instance of the specified service. +This can be useful for debugging or ad-hoc experimentation with services. + +Examples: + + garden run service my-service # run an ad-hoc instance of a my-service and attach to it + ##### Usage garden run service [options] ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | | `service` | Yes | The service to run ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result | `--force-build` | | boolean | Force rebuild of module ### garden run test -Run the specified module test. +Run the specified module test.. + +This can be useful for debugging tests, particularly integration/end-to-end tests. + +Examples: + + garden run test my-module integ # run the test named 'integ' in my-module + garden run test my-module integ --i=false # do not attach to the test run, just output results when completed ##### Usage garden run test [options] ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | - | `module` | Yes | The name of the module to run - | `test` | Yes | The name of the test to run in the module + | `module` | Yes | The name of the module to run. + | `test` | Yes | The name of the test to run in the module. ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result - | `--force-build` | | boolean | Force rebuild of module + | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result. + | `--force-build` | | boolean | Force rebuild of module before running. ### garden scan -Scans your project and outputs an overview of all modules. +Scans your project and outputs an overview of all modules.. + ##### Usage @@ -263,7 +415,8 @@ Scans your project and outputs an overview of all modules. ### garden status -Outputs the status of your environment. +Outputs the status of your environment.. + ##### Usage @@ -271,28 +424,48 @@ Outputs the status of your environment. ### garden test -Test all or specified modules. +Test all or specified modules.. + + + Runs all or specified tests defined in the project. Also builds modules and dependencies, + and deploy service dependencies if needed. + + Optionally stays running and automatically re-runs tests if their module source + (or their dependencies' sources) change. + + Examples: + + garden test # run all tests in the project + garden test my-module # run all tests in the my-module module + garden test -n integ # run all tests with the name 'integ' in the project + garden test --force # force tests to be re-run, even if they're already run successfully + garden test --watch # watch for changes to code + ##### Usage garden test [module] [options] ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | | `module` | No | The name of the module(s) to deploy (skip to test all modules). Use comma as separator to specify multiple modules. ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--group` | `-g` | string | Only run tests with the specfied group (e.g. unit or integ) - | `--force` | `-f` | boolean | Force re-test of module(s) - | `--force-build` | | boolean | Force rebuild of module(s) - | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-test + | `--name` | `-n` | string | Only run tests with the specfied name (e.g. unit or integ). + | `--force` | `-f` | boolean | Force re-test of module(s). + | `--force-build` | | boolean | Force rebuild of module(s). + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-test. ### garden validate -Check your garden configuration for errors. +Check your garden configuration for errors.. + +Throws an error and exits with code 1 if something's not right in your garden.yml files. ##### Usage diff --git a/package-lock.json b/package-lock.json index 8e5d82016f..2129f59cc8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -77,6 +77,12 @@ "commander": "*" } }, + "@types/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@types/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-EGlKlgMhnLt/cM4DbUSafFdrkeJoC9Mvnj0PUCU7tFmTjMjNRT957kXCx0wYm3JuEq4o4ZsS5vG+NlkM2DMd2A==", + "dev": true + }, "@types/dockerode": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-2.5.4.tgz", @@ -2449,8 +2455,7 @@ "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" }, "deep-eql": { "version": "3.0.1", diff --git a/package.json b/package.json index 8428ef0d9a..fd0acc8e00 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "cli-cursor": "^2.1.0", "cli-highlight": "^2.0.0", "cryo": "0.0.6", + "dedent": "^0.7.0", "deep-map": "^1.5.0", "dockerode": "^2.5.5", "elegant-spinner": "^1.0.1", @@ -63,6 +64,7 @@ "devDependencies": { "@types/bluebird": "^3.5.20", "@types/chai": "^4.1.3", + "@types/dedent": "^0.7.0", "@types/dockerode": "^2.5.4", "@types/fs-extra": "^5.0.2", "@types/gulp": "^4.0.5", diff --git a/src/cli/cli.ts b/src/cli/cli.ts index fbbe6eeece..85e61179ae 100644 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -66,25 +66,25 @@ const OUTPUT_RENDERERS = { export const GLOBAL_OPTIONS = { root: new StringParameter({ alias: "r", - help: "override project root directory (defaults to working directory)", + help: "Override project root directory (defaults to working directory).", defaultValue: process.cwd(), }), silent: new BooleanParameter({ alias: "s", - help: "suppress log output", + help: "Suppress log output.", defaultValue: false, }), env: new EnvironmentOption(), loglevel: new ChoicesParameter({ alias: "log", choices: enumToArray(LogLevel), - help: "set logger level", + help: "Set logger level.", defaultValue: LogLevel[LogLevel.info], }), output: new ChoicesParameter({ alias: "o", choices: Object.keys(OUTPUT_RENDERERS), - help: "output command result in specified format (note: disables progress logging)", + help: "Output command result in specified format (note: disables progress logging).", }), } const GLOBAL_OPTIONS_GROUP_NAME = "Global options" diff --git a/src/commands/base.ts b/src/commands/base.ts index e514708059..d9a4ddf9db 100644 --- a/src/commands/base.ts +++ b/src/commands/base.ts @@ -152,10 +152,7 @@ export abstract class Command l.trim()).join("\n") - : null + const { name, help, description } = this return { name, diff --git a/src/commands/build.ts b/src/commands/build.ts index d1c7b3f5d8..0c1aa5548c 100644 --- a/src/commands/build.ts +++ b/src/commands/build.ts @@ -17,6 +17,7 @@ import { } from "./base" import { BuildTask } from "../tasks/build" import { TaskResults } from "../task-graph" +import dedent = require("dedent") export const buildArguments = { module: new StringParameter({ @@ -25,8 +26,8 @@ export const buildArguments = { } export const buildOptions = { - force: new BooleanParameter({ help: "Force rebuild of module(s)" }), - watch: new BooleanParameter({ help: "Watch for changes in module(s) and auto-build", alias: "w" }), + force: new BooleanParameter({ help: "Force rebuild of module(s)." }), + watch: new BooleanParameter({ help: "Watch for changes in module(s) and auto-build.", alias: "w" }), } export type BuildArguments = ParameterValues @@ -34,7 +35,19 @@ export type BuildOptions = ParameterValues export class BuildCommand extends Command { name = "build" - help = "Build your modules" + help = "Build your modules." + + description = dedent` + Builds all or specified modules, taking into account build dependency order. + Optionally stays running and automatically builds modules if their source (or their dependencies' sources) change. + + Examples: + + garden build # build all modules in the project + garden build my-module # only build my-module + garden build --force # force rebuild of modules + garden build --watch # watch for changes to code + ` arguments = buildArguments options = buildOptions diff --git a/src/commands/call.ts b/src/commands/call.ts index 7a3d0fbabb..0ba1dafa53 100644 --- a/src/commands/call.ts +++ b/src/commands/call.ts @@ -21,10 +21,11 @@ import { ParameterError, RuntimeError } from "../exceptions" import { EntryStyle } from "../logger/types" import { pick } from "lodash" import { PluginContext } from "../plugin-context" +import dedent = require("dedent") export const callArgs = { serviceAndPath: new StringParameter({ - help: "The name of the service(s) to call followed by the endpoint path (e.g. my-container/somepath)", + help: "The name of the service(s) to call followed by the endpoint path (e.g. my-container/somepath).", required: true, }), } @@ -33,10 +34,18 @@ export type Args = ParameterValues export class CallCommand extends Command { name = "call" - help = "Call a service endpoint" + help = "Call a service endpoint." - description = ` - This resolves the external endpoint for the given service and path, calls the given endpoint and outputs the result. + description = dedent` + This command resolves the deployed external endpoint for the given service and path, calls the given endpoint and + outputs the result. + + Examples: + + garden call my-container + garden call my-container/some-path + + Note: Currently only supports HTTP/HTTPS endpoints. ` arguments = callArgs diff --git a/src/commands/config/delete.ts b/src/commands/config/delete.ts index 221344e5f3..96a9a1e794 100644 --- a/src/commands/config/delete.ts +++ b/src/commands/config/delete.ts @@ -15,10 +15,11 @@ import { StringParameter, } from "../base" import { NotFoundError } from "../../exceptions" +import dedent = require("dedent") export const configDeleteArgs = { key: new StringParameter({ - help: "The key of the configuration variable", + help: "The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested).", required: true, }), } @@ -30,7 +31,16 @@ export type DeleteArgs = ParameterValues export class ConfigDeleteCommand extends Command { name = "delete" alias = "del" - help = "Delete a configuration variable" + help = "Delete a configuration variable from the Garden environment." + + description = dedent` + Returns with an error if the provided key could not be found in the configuration. + + Examples: + + garden delete somekey + garden delete some.nested.key + ` arguments = configDeleteArgs diff --git a/src/commands/config/get.ts b/src/commands/config/get.ts index 0c501f606b..ee2b95a5d6 100644 --- a/src/commands/config/get.ts +++ b/src/commands/config/get.ts @@ -14,10 +14,11 @@ import { ParameterValues, StringParameter, } from "../base" +import dedent = require("dedent") export const configGetArgs = { key: new StringParameter({ - help: "The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested)", + help: "The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested).", required: true, }), } @@ -28,7 +29,16 @@ export type GetArgs = ParameterValues export class ConfigGetCommand extends Command { name = "get" - help = "Get a configuration variable" + help = "Get a configuration variable from the environment." + + description = dedent` + Returns with an error if the provided key could not be found in the configuration. + + Examples: + + garden get somekey + garden get some.nested.key + ` arguments = configGetArgs diff --git a/src/commands/config/set.ts b/src/commands/config/set.ts index f95fff3876..e2c01ee46d 100644 --- a/src/commands/config/set.ts +++ b/src/commands/config/set.ts @@ -14,15 +14,16 @@ import { ParameterValues, StringParameter, } from "../base" +import dedent = require("dedent") export const configSetArgs = { // TODO: specify and validate config key schema here key: new StringParameter({ - help: "The key of the configuration variable. Separate with dots to set a nested key (e.g. key.nested)", + help: "The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested).", required: true, }), value: new StringParameter({ - help: "The value of the configuration variable", + help: "The value of the configuration variable.", required: true, }), } @@ -33,7 +34,18 @@ export type SetArgs = ParameterValues export class ConfigSetCommand extends Command { name = "set" - help = "Set a configuration variable" + help = "Set a configuration variable in the environment." + + description = dedent` + These configuration values can be referenced in module templates, for example as environment variables. + + _Note: The value is always stored as a string._ + + Examples: + + garden set somekey myvalue + garden set some.nested.key myvalue + ` arguments = configSetArgs diff --git a/src/commands/deploy.ts b/src/commands/deploy.ts index cbe6a9e72f..9abe396927 100644 --- a/src/commands/deploy.ts +++ b/src/commands/deploy.ts @@ -26,9 +26,9 @@ export const deployArgs = { } export const deployOpts = { - force: new BooleanParameter({ help: "Force redeploy of service(s)" }), - "force-build": new BooleanParameter({ help: "Force rebuild of module(s)" }), - watch: new BooleanParameter({ help: "Watch for changes in module(s) and auto-deploy", alias: "w" }), + force: new BooleanParameter({ help: "Force redeploy of service(s)." }), + "force-build": new BooleanParameter({ help: "Force rebuild of module(s)." }), + watch: new BooleanParameter({ help: "Watch for changes in module(s) and auto-deploy.", alias: "w" }), } export type Args = ParameterValues @@ -36,7 +36,23 @@ export type Opts = ParameterValues export class DeployCommand extends Command { name = "deploy" - help = "Deploy service(s) to the specified environment" + help = "Deploy service(s) to your environment." + + description = ` + Deploys all or specified services, taking into account service dependency order. + Also builds modules and dependencies if needed. + + Optionally stays running and automatically re-builds and re-deploys services if their module source + (or their dependencies' sources) change. + + Examples: + + garden deploy # deploy all modules in the project + garden deploy my-service # only deploy my-service + garden deploy --force # force re-deploy of modules, even if they're already deployed + garden deploy --watch # watch for changes to code + garden deploy --env stage # deploy your services to an environment called stage + ` arguments = deployArgs options = deployOpts diff --git a/src/commands/dev.ts b/src/commands/dev.ts index 5ef13f030e..89bdeb22d7 100644 --- a/src/commands/dev.ts +++ b/src/commands/dev.ts @@ -22,9 +22,20 @@ import moment = require("moment") const imgcatPath = join(STATIC_DIR, "imgcat") const bannerPath = join(STATIC_DIR, "garden-banner-1-half.png") +// TODO: allow limiting to certain modules and/or services export class DevCommand extends Command { name = "dev" - help = "Starts the garden development console" + help = "Starts the garden development console." + + description = ` + The Garden dev console is a combination of the \`build\`, \`deploy\` and \`test\` commands. + It builds, deploys and tests all your modules and services, and re-builds, re-deploys and re-tests + as you modify the code. + + Examples: + + garden dev + ` async action(ctx: PluginContext): Promise { try { diff --git a/src/commands/environment/configure.ts b/src/commands/environment/configure.ts index d4c6f5c5f1..6434434987 100644 --- a/src/commands/environment/configure.ts +++ b/src/commands/environment/configure.ts @@ -14,9 +14,10 @@ import { CommandResult, ParameterValues, } from "../base" +import dedent = require("dedent") export const options = { - force: new BooleanParameter({ help: "Force reconfiguration of environment" }), + force: new BooleanParameter({ help: "Force reconfiguration of environment, ignoring the environment status check." }), } export type Opts = ParameterValues @@ -24,7 +25,18 @@ export type Opts = ParameterValues export class EnvironmentConfigureCommand extends Command { name = "configure" alias = "config" - help = "Configures your environment" + help = "Configures your environment." + + description = dedent` + Generally, environments are configured automatically as part of other commands that you run. + However, this command is useful if you want to make sure the environment is ready before running + another command, or if you need to force a reconfiguration using the --force flag. + + Examples: + + garden env configure + garden env configure --force + ` options = options diff --git a/src/commands/environment/destroy.ts b/src/commands/environment/destroy.ts index d486d7695a..f393960c3d 100644 --- a/src/commands/environment/destroy.ts +++ b/src/commands/environment/destroy.ts @@ -13,11 +13,21 @@ import { CommandResult, } from "../base" import { EnvironmentStatusMap } from "../../types/plugin/outputs" +import dedent = require("dedent") export class EnvironmentDestroyCommand extends Command { name = "destroy" alias = "d" - help = "Destroy environment" + help = "Destroy an environment." + + description = dedent` + Generally not as dramatic as it sounds :) This will trigger providers clear up any deployments in a + Garden environment and reset it. When you then run \`garden env configure\` or any deployment command, + the environment will be reconfigured. + + This can be useful if you find the environment to be in an inconsistent state, or need/want to free up + resources. + ` async action(ctx: PluginContext): Promise> { const { name } = ctx.getEnvironment() diff --git a/src/commands/exec.ts b/src/commands/exec.ts index f61d605b86..c56aa7ad96 100644 --- a/src/commands/exec.ts +++ b/src/commands/exec.ts @@ -17,14 +17,15 @@ import { ParameterValues, StringParameter, } from "./base" +import dedent = require("dedent") export const runArgs = { service: new StringParameter({ - help: "The service to exec the command in", + help: "The service to exec the command in.", required: true, }), command: new StringParameter({ - help: "The command to run", + help: "The command to run.", required: true, }), } @@ -42,7 +43,18 @@ export type Args = ParameterValues export class ExecCommand extends Command { name = "exec" alias = "e" - help = "Executes a command (such as an interactive shell) in a running service" + help = "Executes a command (such as an interactive shell) in a running service." + + description = dedent` + Finds an active container for a deployed service and executes the given command within the container. + Supports interactive shells. + + _NOTE: This command may not be supported for all module types. + + Examples: + + garden exec my-service /bin/sh # runs a shell in the my-service container + ` arguments = runArgs options = runOpts diff --git a/src/commands/login.ts b/src/commands/login.ts index 32bd7b559a..454a8140a7 100644 --- a/src/commands/login.ts +++ b/src/commands/login.ts @@ -13,10 +13,19 @@ import { import { EntryStyle } from "../logger/types" import { PluginContext } from "../plugin-context" import { LoginStatusMap } from "../types/plugin/outputs" +import dedent = require("dedent") export class LoginCommand extends Command { name = "login" - help = "Log into the Garden framework" + help = "Log into configured providers for this project and environment." + + description = dedent` + Executes the login flow for any provider that requires login (such as the \`kubernetes\` provider). + + Examples: + + garden login + ` async action(ctx: PluginContext): Promise> { ctx.log.header({ emoji: "unlock", command: "Login" }) diff --git a/src/commands/logout.ts b/src/commands/logout.ts index 4c5217f33d..dc425ae346 100644 --- a/src/commands/logout.ts +++ b/src/commands/logout.ts @@ -13,10 +13,17 @@ import { import { EntryStyle } from "../logger/types" import { PluginContext } from "../plugin-context" import { LoginStatusMap } from "../types/plugin/outputs" +import dedent = require("dedent") export class LogoutCommand extends Command { name = "logout" - help = "Log into the Garden framework" + help = "Log out of configured providers for this project and environment." + + description = dedent` + Examples: + + garden logout + ` async action(ctx: PluginContext): Promise> { diff --git a/src/commands/logs.ts b/src/commands/logs.ts index b0be664b58..470f6095f1 100644 --- a/src/commands/logs.ts +++ b/src/commands/logs.ts @@ -20,6 +20,7 @@ import Bluebird = require("bluebird") import { Service } from "../types/service" import Stream from "ts-stream" import { LoggerType } from "../logger/types" +import dedent = require("dedent") export const logsArgs = { service: new StringParameter({ @@ -29,7 +30,7 @@ export const logsArgs = { } export const logsOpts = { - tail: new BooleanParameter({ help: "Continuously stream new logs from the service(s)", alias: "t" }), + tail: new BooleanParameter({ help: "Continuously stream new logs from the service(s).", alias: "t" }), // TODO // since: new MomentParameter({ help: "Retrieve logs from the specified point onwards" }), } @@ -39,7 +40,17 @@ export type Opts = ParameterValues export class LogsCommand extends Command { name = "logs" - help = "Retrieves the most recent logs for the specified service(s)" + help = "Retrieves the most recent logs for the specified service(s)." + + description = dedent` + Outputs logs for all or specified services, and optionally waits for news logs to come in. + + Examples: + + garden logs # prints latest logs from all services + garden logs my-service # prints latest logs for my-service + garden logs -t # keeps running and streams all incoming logs to the console + ` arguments = logsArgs options = logsOpts diff --git a/src/commands/push.ts b/src/commands/push.ts index 486c8876af..a11ed5d0cf 100644 --- a/src/commands/push.ts +++ b/src/commands/push.ts @@ -19,6 +19,7 @@ import { Module } from "../types/module" import { PushTask } from "../tasks/push" import { RuntimeError } from "../exceptions" import { TaskResults } from "../task-graph" +import dedent = require("dedent") export const pushArgs = { module: new StringParameter({ @@ -29,10 +30,10 @@ export const pushArgs = { export const pushOpts = { "force-build": new BooleanParameter({ - help: "Force rebuild of module(s) before pushing", + help: "Force rebuild of module(s) before pushing.", }), "allow-dirty": new BooleanParameter({ - help: "Allow pushing dirty builds (with untracked/uncommitted files)", + help: "Allow pushing dirty builds (with untracked/uncommitted files).", }), } @@ -41,7 +42,19 @@ export type Opts = ParameterValues export class PushCommand extends Command { name = "push" - help = "Build and push module(s) to remote registry" + help = "Build and push built module(s) to remote registry." + + description = dedent` + Pushes built module artifacts for all or specified modules. + Also builds modules and dependencies if needed. + + Examples: + + garden push # push artifacts for all modules in the project + garden push my-container # only push my-container + garden push --force-build # force re-build of modules before pushing artifacts + garden push --allow-dirty # allow pushing dirty builds (which usually triggers error) + ` arguments = pushArgs options = pushOpts diff --git a/src/commands/run/module.ts b/src/commands/run/module.ts index 007dec6b2a..656cc61d97 100644 --- a/src/commands/run/module.ts +++ b/src/commands/run/module.ts @@ -22,15 +22,16 @@ import { flatten, } from "lodash" import { printRuntimeContext } from "./index" +import dedent = require("dedent") export const runArgs = { module: new StringParameter({ - help: "The name of the module to run", + help: "The name of the module to run.", required: true, }), // TODO: make this a variadic arg command: new StringParameter({ - help: "The command to run in the module", + help: "The command to run in the module.", }), } @@ -38,10 +39,10 @@ export const runOpts = { // TODO: we could provide specific parameters like this by adding commands for specific modules, via plugins //entrypoint: new StringParameter({ help: "Override default entrypoint in module" }), interactive: new BooleanParameter({ - help: "Set to false to skip interactive mode and just output the command result", + help: "Set to false to skip interactive mode and just output the command result.", defaultValue: true, }), - "force-build": new BooleanParameter({ help: "Force rebuild of module" }), + "force-build": new BooleanParameter({ help: "Force rebuild of module before running." }), } export type Args = ParameterValues @@ -50,7 +51,17 @@ export type Opts = ParameterValues export class RunModuleCommand extends Command { name = "module" alias = "m" - help = "Run the specified module" + help = "Run an ad-hoc instance of a module." + + description = dedent` + This is useful for debugging or ad-hoc experimentation with modules. + + Examples: + + garden run module my-container # run an ad-hoc instance of a my-container container and attach to it + garden run module my-container /bin/sh # run an interactive shell in a new my-container container + garden run module my-container --i=false /some/script # execute a script in my-container and return the output + ` arguments = runArgs options = runOpts diff --git a/src/commands/run/service.ts b/src/commands/run/service.ts index ac2f93884f..1d93615c6c 100644 --- a/src/commands/run/service.ts +++ b/src/commands/run/service.ts @@ -18,6 +18,7 @@ import { StringParameter, } from "../base" import { printRuntimeContext } from "./index" +import dedent = require("dedent") export const runArgs = { service: new StringParameter({ @@ -27,10 +28,6 @@ export const runArgs = { } export const runOpts = { - interactive: new BooleanParameter({ - help: "Set to false to skip interactive mode and just output the command result", - defaultValue: true, - }), "force-build": new BooleanParameter({ help: "Force rebuild of module" }), } @@ -42,6 +39,14 @@ export class RunServiceCommand extends Command { alias = "s" help = "Run an ad-hoc instance of the specified service" + description = dedent` + This can be useful for debugging or ad-hoc experimentation with services. + + Examples: + + garden run service my-service # run an ad-hoc instance of a my-service and attach to it + ` + arguments = runArgs options = runOpts @@ -66,7 +71,7 @@ export class RunServiceCommand extends Command { printRuntimeContext(ctx, runtimeContext) - const result = await ctx.runService({ serviceName, runtimeContext, silent: false, interactive: opts.interactive }) + const result = await ctx.runService({ serviceName, runtimeContext, silent: false, interactive: true }) return { result } } diff --git a/src/commands/run/test.ts b/src/commands/run/test.ts index 58c1db2155..c944fb403b 100644 --- a/src/commands/run/test.ts +++ b/src/commands/run/test.ts @@ -23,24 +23,25 @@ import { StringParameter, } from "../base" import { printRuntimeContext } from "./index" +import dedent = require("dedent") export const runArgs = { module: new StringParameter({ - help: "The name of the module to run", + help: "The name of the module to run.", required: true, }), test: new StringParameter({ - help: "The name of the test to run in the module", + help: "The name of the test to run in the module.", required: true, }), } export const runOpts = { interactive: new BooleanParameter({ - help: "Set to false to skip interactive mode and just output the command result", + help: "Set to false to skip interactive mode and just output the command result.", defaultValue: true, }), - "force-build": new BooleanParameter({ help: "Force rebuild of module" }), + "force-build": new BooleanParameter({ help: "Force rebuild of module before running." }), } export type Args = ParameterValues @@ -49,7 +50,16 @@ export type Opts = ParameterValues export class RunTestCommand extends Command { name = "test" alias = "t" - help = "Run the specified module test" + help = "Run the specified module test." + + description = dedent` + This can be useful for debugging tests, particularly integration/end-to-end tests. + + Examples: + + garden run test my-module integ # run the test named 'integ' in my-module + garden run test my-module integ --i=false # do not attach to the test run, just output results when completed + ` arguments = runArgs options = runOpts diff --git a/src/commands/scan.ts b/src/commands/scan.ts index 8b48925279..4f2dd1ea53 100644 --- a/src/commands/scan.ts +++ b/src/commands/scan.ts @@ -21,7 +21,7 @@ import { export class ScanCommand extends Command { name = "scan" - help = "Scans your project and outputs an overview of all modules" + help = "Scans your project and outputs an overview of all modules." async action(ctx: PluginContext): Promise> { const modules = await ctx.getModules() diff --git a/src/commands/status.ts b/src/commands/status.ts index bacab3d34b..b90f211c65 100644 --- a/src/commands/status.ts +++ b/src/commands/status.ts @@ -20,7 +20,7 @@ import { highlightYaml } from "../util" export class StatusCommand extends Command { name = "status" alias = "s" - help = "Outputs the status of your environment" + help = "Outputs the status of your environment." async action(ctx: PluginContext): Promise> { const status = await ctx.getStatus() diff --git a/src/commands/test.ts b/src/commands/test.ts index 32febe9186..2e7dc1c87c 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -25,13 +25,13 @@ export const testArgs = { } export const testOpts = { - group: new StringParameter({ - help: "Only run tests with the specfied group (e.g. unit or integ)", - alias: "g", + name: new StringParameter({ + help: "Only run tests with the specfied name (e.g. unit or integ).", + alias: "n", }), - force: new BooleanParameter({ help: "Force re-test of module(s)", alias: "f" }), - "force-build": new BooleanParameter({ help: "Force rebuild of module(s)" }), - watch: new BooleanParameter({ help: "Watch for changes in module(s) and auto-test", alias: "w" }), + force: new BooleanParameter({ help: "Force re-test of module(s).", alias: "f" }), + "force-build": new BooleanParameter({ help: "Force rebuild of module(s)." }), + watch: new BooleanParameter({ help: "Watch for changes in module(s) and auto-test.", alias: "w" }), } export type Args = ParameterValues @@ -39,7 +39,23 @@ export type Opts = ParameterValues export class TestCommand extends Command { name = "test" - help = "Test all or specified modules" + help = "Test all or specified modules." + + description = ` + Runs all or specified tests defined in the project. Also builds modules and dependencies, + and deploy service dependencies if needed. + + Optionally stays running and automatically re-runs tests if their module source + (or their dependencies' sources) change. + + Examples: + + garden test # run all tests in the project + garden test my-module # run all tests in the my-module module + garden test -n integ # run all tests with the name 'integ' in the project + garden test --force # force tests to be re-run, even if they're already run successfully + garden test --watch # watch for changes to code + ` arguments = testArgs options = testOpts @@ -55,14 +71,14 @@ export class TestCommand extends Command { await ctx.configureEnvironment({}) - const group = opts.group + const name = opts.name const force = opts.force const forceBuild = opts["force-build"] const results = await ctx.processModules({ modules, watch: opts.watch, - process: async (module) => module.getTestTasks({ group, force, forceBuild }), + process: async (module) => module.getTestTasks({ name, force, forceBuild }), }) return handleTaskResults(ctx, "test", results) diff --git a/src/commands/validate.ts b/src/commands/validate.ts index ab43ed33c1..b6c7832c3a 100644 --- a/src/commands/validate.ts +++ b/src/commands/validate.ts @@ -11,10 +11,15 @@ import { Command, CommandResult, } from "./base" +import dedent = require("dedent") export class ValidateCommand extends Command { name = "validate" - help = "Check your garden configuration for errors" + help = "Check your garden configuration for errors." + + description = dedent` + Throws an error and exits with code 1 if something's not right in your garden.yml files. + ` async action(ctx: PluginContext): Promise { diff --git a/src/docs/templates/commands.hbs b/src/docs/templates/commands.hbs index 60e2bcfeed..94bc628ca3 100644 --- a/src/docs/templates/commands.hbs +++ b/src/docs/templates/commands.hbs @@ -24,12 +24,14 @@ The following option flags can be used with any of the CLI commands: {{#if description}}{{description}} {{/if}} + ##### Usage garden {{fullName}} {{#each arguments}}{{{usageName}}} {{/each}}{{#if options}}[options]{{/if}} {{#if arguments}} ##### Arguments + | Argument | Required | Description | | -------- | -------- | ----------- | {{#each arguments}} @@ -39,6 +41,7 @@ The following option flags can be used with any of the CLI commands: {{/if}} {{#if options}} ##### Options + | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | {{#each options}} diff --git a/src/task-graph.ts b/src/task-graph.ts index 63a36a447b..3016344b2b 100644 --- a/src/task-graph.ts +++ b/src/task-graph.ts @@ -35,7 +35,7 @@ export interface TaskResults { interface LogEntryMap { [key: string]: LogEntry } -const DEFAULT_CONCURRENCY = 4 +export const DEFAULT_CONCURRENCY = 4 const taskStyle = chalk.cyan.bold diff --git a/src/types/module.ts b/src/types/module.ts index 1e20fc2150..f63504f1f0 100644 --- a/src/types/module.ts +++ b/src/types/module.ts @@ -304,12 +304,12 @@ export class Module< } async getTestTasks( - { group, force = false, forceBuild = false }: { group?: string, force?: boolean, forceBuild?: boolean }, + { name, force = false, forceBuild = false }: { name?: string, force?: boolean, forceBuild?: boolean }, ) { const tasks: Promise[] = [] for (const test of this.tests) { - if (group && test.name !== group) { + if (name && test.name !== name) { continue } tasks.push(TestTask.factory({ diff --git a/test/src/commands/run/service.ts b/test/src/commands/run/service.ts index fcad2f2008..ea307085ce 100644 --- a/test/src/commands/run/service.ts +++ b/test/src/commands/run/service.ts @@ -23,7 +23,7 @@ describe("RunServiceCommand", () => { const { result } = await cmd.action( ctx, { service: "testService" }, - { interactive: false, "force-build": false }, + { "force-build": false }, ) const expected: RunResult = { diff --git a/test/src/commands/test.ts b/test/src/commands/test.ts index 508e0535be..60031f8346 100644 --- a/test/src/commands/test.ts +++ b/test/src/commands/test.ts @@ -14,7 +14,7 @@ describe("commands.test", () => { const { result } = await command.action( ctx, { module: undefined }, - { group: undefined, force: true, "force-build": true, watch: false }, + { name: undefined, force: true, "force-build": true, watch: false }, ) expect(isSubset(taskResultOutputs(result!), { @@ -49,7 +49,7 @@ describe("commands.test", () => { const { result } = await command.action( ctx, { module: "module-a" }, - { group: undefined, force: true, "force-build": true, watch: false }, + { name: undefined, force: true, "force-build": true, watch: false }, ) expect(isSubset(taskResultOutputs(result!), { From 325b6072c5f98955dcf94429285c17d98c60074e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ey=C3=BE=C3=B3r=20Magn=C3=BAsson?= Date: Wed, 30 May 2018 18:31:14 +0200 Subject: [PATCH 7/9] docs: add getting-started section --- docs/getting-started/README.md | 81 +++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index 2a90f3aab6..a1e9502a21 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -1,10 +1,10 @@ # Getting Started -This guide will walk you through setting up, and installing the Garden framework. +This guide will walk you through setting up the Garden framework. -## Requirements +## Install dependencies -You need to set up the following on your local machine to use garden: +You need the following dependencies on your local machine to use Garden: * Node.js >= 8.x * [Docker](https://docs.docker.com/) * Git @@ -12,14 +12,81 @@ You need to set up the following on your local machine to use garden: * [Watchman](https://facebook.github.io/watchman/docs/install.html) * Local installation of Kubernetes -## Install +### OSX -// TODO +#### Step 1: Docker and local Kubernetes +To install Docker and Kubernetes, we recommend [Docker for Mac (edge version)](https://docs.docker.com/engine/installation/). + +_Note: you need to install the _edge version_ of Docker for Mac in +order to enable Kubernetes support._ + +Once installed, open the +Docker preferences, go to the Kubernetes section, tick `Enable Kubernetes` and +save. + +Alternatively, you can use [Minikube](../guides/minikube.md) on any supported platform. + +#### Step 2: Other dependencies +For installing the other dependencies, we recommend using Homebrew. + +### Linux + +#### Step 1: Docker +To install Docker, please follow the instructions in the [official documentation](https://docs.docker.com/install/linux/docker-ce/ubuntu/). + +#### Step 2: Local Kubernetes +For local Kubernetes, you can use Minikube. Please see the +[official installation guide](https://github.com/kubernetes/minikube#installation) for instructions. + +You'll likely also need to install a driver to run the Minikube VM. Please follow the +[instructions here](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver), +and note the name of the driver. + +Once Minikube and the appropriate driver for your OS is installed, you can start it by running: + + minikube start --vm-driver= # e.g. hyperkit on macOS + +Finally, you will need to configure a [kubectl context](https://kubernetes.io/docs/reference/kubectl/cheatsheet/#kubectl-context-and-configuration) +to point to your local instance. + + + +Check out our [Minikube guide](../guides/minikube.md) for further information on using Garden with Minikube. + +#### Step 3: Other dependencies +Other dependencies can be installed with the package manager of your choice + +## Install the Garden CLI + +Once you have the dependencies set up, simply run: + + npm install -g garden-cli ## Using the CLI -// TODO +With the CLI installed, we can now try out a few commands using the [hello-world](https://github.com/garden-io/garden/tree/master/examples/hello-world) example from this repository. The example consists of a container service that runs an [Express](http://expressjs.com/) app, a serverless function, and an npm library package. + +_Note: check if Kubernetes is running with `kubectl version`. You should see both a `Client Version` and a `Server Version` in the response. If not, please start it up before proceeding._ + +Clone the repo and change into the `examples/hello-world` directory: + + git clone https://github.com/garden-io/garden.git && + cd garden/examples/hello-world + +First, let's check the environment status by running the following from the project root: + + garden status + +The response tells us how the environment is configured and the status of the providers. Next, we'll deploy the services with: + + garden deploy + +And that's it! The services are now running on the Garden framework. You can see for yourself by querying the `/hello` endpoint of the container with: + + garden call hello-container/hello + +Check out our [Commands](../guides/commands.md) guide for other features like auto-reload, streaming service logs, running tests, and lots more. ## What's next -// TODO \ No newline at end of file +Kick the tires of our [examples](https://github.com/garden-io/garden/tree/master/examples/hello-world) to get a feel for how projects are configured, or head to the [Guides](../guides/README.md) section for a deep dive into the Garden framework. From 6b2a311740fec856b4009b3894016b0fc3a2fce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ey=C3=BE=C3=B3r=20Magn=C3=BAsson?= Date: Thu, 31 May 2018 15:58:48 +0200 Subject: [PATCH 8/9] docs: remove empty --- docs/README.md | 10 +++------- docs/examples/README.md | 1 - docs/guides/README.md | 5 ++--- docs/guides/commands.md | 1 - docs/guides/configuration.md | 1 - docs/guides/features.md | 1 - docs/other/README.md | 5 ----- docs/other/faq.md | 1 - docs/other/glossary.md | 1 - docs/other/troubleshooting.md | 1 - docs/reference/README.md | 3 +++ docs/reference/commands.md | 8 ++++---- 12 files changed, 12 insertions(+), 26 deletions(-) delete mode 100644 docs/examples/README.md delete mode 100644 docs/guides/commands.md delete mode 100644 docs/guides/configuration.md delete mode 100644 docs/guides/features.md delete mode 100644 docs/other/README.md delete mode 100644 docs/other/faq.md delete mode 100644 docs/other/glossary.md delete mode 100644 docs/other/troubleshooting.md create mode 100644 docs/reference/README.md diff --git a/docs/README.md b/docs/README.md index 71c07fbcfc..66d4cad11a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,12 +3,8 @@ * [Read Me](../README.md) * [Getting Started](./getting-started/README.md) * [Guides](./guides/README.md) - * [Configuration](./guides/configuration.md) - * [Features](./guides/features.md) - * [Commands](./guides/commands.md) * [Using Garden with Minikube](./guides/minikube.md) * [Remote Kubernetes](./guides/remote-kubernetes.md) -* [Other](./other/README.md) - * [FAQ](./other/faq.md) - * [Glossary](./other/glossary.md) - * [Troubleshooting](./other/troubleshooting.md) +* [Reference](./reference/README.md) + * [Commands](./reference/commands.md) + diff --git a/docs/examples/README.md b/docs/examples/README.md deleted file mode 100644 index 0ffdd02fcb..0000000000 --- a/docs/examples/README.md +++ /dev/null @@ -1 +0,0 @@ -// TODO \ No newline at end of file diff --git a/docs/guides/README.md b/docs/guides/README.md index c315fa45cb..e165d313be 100644 --- a/docs/guides/README.md +++ b/docs/guides/README.md @@ -1,7 +1,6 @@ # Guides -* [Configuration](./configuration.md) -* [Features](./features.md) -* [Commands](./commands.md) * [Using Garden with Minikube](./minikube.md) * [Remote Kubernetes](./remote-kubernetes.md) + + diff --git a/docs/guides/commands.md b/docs/guides/commands.md deleted file mode 100644 index 8ad1dfb535..0000000000 --- a/docs/guides/commands.md +++ /dev/null @@ -1 +0,0 @@ -//TODO diff --git a/docs/guides/configuration.md b/docs/guides/configuration.md deleted file mode 100644 index 8ad1dfb535..0000000000 --- a/docs/guides/configuration.md +++ /dev/null @@ -1 +0,0 @@ -//TODO diff --git a/docs/guides/features.md b/docs/guides/features.md deleted file mode 100644 index 8ad1dfb535..0000000000 --- a/docs/guides/features.md +++ /dev/null @@ -1 +0,0 @@ -//TODO diff --git a/docs/other/README.md b/docs/other/README.md deleted file mode 100644 index adc42029b6..0000000000 --- a/docs/other/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Other - -* [FAQ](./faq.md) -* [Glossary](./glossary.md) -* [Troubleshooting](./troubleshooting.md) diff --git a/docs/other/faq.md b/docs/other/faq.md deleted file mode 100644 index 8ad1dfb535..0000000000 --- a/docs/other/faq.md +++ /dev/null @@ -1 +0,0 @@ -//TODO diff --git a/docs/other/glossary.md b/docs/other/glossary.md deleted file mode 100644 index 8ad1dfb535..0000000000 --- a/docs/other/glossary.md +++ /dev/null @@ -1 +0,0 @@ -//TODO diff --git a/docs/other/troubleshooting.md b/docs/other/troubleshooting.md deleted file mode 100644 index 8ad1dfb535..0000000000 --- a/docs/other/troubleshooting.md +++ /dev/null @@ -1 +0,0 @@ -//TODO diff --git a/docs/reference/README.md b/docs/reference/README.md new file mode 100644 index 0000000000..c0e31a5d0c --- /dev/null +++ b/docs/reference/README.md @@ -0,0 +1,3 @@ +# Reference + +* [Commands](./commands.md) diff --git a/docs/reference/commands.md b/docs/reference/commands.md index 2ed6a43529..e0a38bec61 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -13,11 +13,11 @@ The following option flags can be used with any of the CLI commands: | Argument | Alias | Type | Description | | -------- | ----- | ---- | ----------- | - | `--root` | `-r` | string | override project root directory (defaults to working directory) - | `--silent` | `-s` | boolean | suppress log output + | `--root` | `-r` | string | Override project root directory (defaults to working directory). + | `--silent` | `-s` | boolean | Suppress log output. | `--env` | `-e` | string | The environment (and optionally namespace) to work against - | `--loglevel` | `-log` | `error` `warn` `info` `verbose` `debug` `silly` | set logger level - | `--output` | `-o` | `json` `yaml` | output command result in specified format (note: disables progress logging) + | `--loglevel` | `-log` | `error` `warn` `info` `verbose` `debug` `silly` | Set logger level. + | `--output` | `-o` | `json` `yaml` | Output command result in specified format (note: disables progress logging). ### garden build From f7d3953eb5bde62e86e6ca08636d00f29b6610d3 Mon Sep 17 00:00:00 2001 From: Thorarinn Sigurdsson Date: Sun, 27 May 2018 22:03:15 +0200 Subject: [PATCH 9/9] docs: configuration guide and glossary. --- docs/guides/configuration.md | 243 +++++++++++++++++++++++++++++++++++ docs/other/glossary.md | 46 +++++++ 2 files changed, 289 insertions(+) create mode 100644 docs/guides/configuration.md create mode 100644 docs/other/glossary.md diff --git a/docs/guides/configuration.md b/docs/guides/configuration.md new file mode 100644 index 0000000000..89f6d47d81 --- /dev/null +++ b/docs/guides/configuration.md @@ -0,0 +1,243 @@ +## Configuration + +Garden is configured via `garden.yml` configuration files. + +The [project-wide](#project) `garden.yml` file should be located in the top-level directory of the project's Git +repository. + +In addition, each of the project's [modules](../other/glossary#module)' `garden.yml` should be located in that module's +top-level +directory. + +Currently, Garden projects assume that all their modules are rooted in subdirectories of the same Git repository. +In a future release, this mono-repo structure will be made optional. + +To get started, create a `garden.yml` file in the top-level directory of your repository, and a `garden.yml` file +in the top-level directory of each of the modules you'd like do define for your project. + +To decide how to split your project up into modules, it's useful to consider what parts of it are built as a single +step, and what the dependency relationships are between your build steps. For example, each container and each +serverless function should be represented by its own module + +Then, you can configure each module's endpoints via the [`services` directive](#services) in its `garden.yml`. + +Below, we'll be using examples from the +[hello-world example project](https://github.com/garden-io/garden/tree/528b141717f718ebe304d2ebde87b85d0c6c5e50/examples/hello-world). + +### Project Configuration +[Github link](https://github.com/garden-io/garden/blob/528b141717f718ebe304d2ebde87b85d0c6c5e50/examples/hello-world/garden.yml) +```yaml +# examples/hello-world/garden.yml +project: + name: hello-world + global: + providers: + - name: container + - name: npm-package + variables: + my-variable: hello-variable + environments: + - name: local + providers: + - name: local-kubernetes + - name: local-google-cloud-functions + - name: dev + providers: + - name: google-app-engine + - name: google-cloud-functions + default-project: garden-hello-world +``` +The project-wide `garden.yml` defines the project's name, the default providers used for each +[plugin](../other/glossary#plugin) the project requires (via the `global` directive), and +[environment](../other/glossary#environment)-specific provider overrides as is appropriate for each of the project's +configured environments (`local` and `dev` under the `environments` directive above). + +Here, project-wide configuration variables can also be specified (global, and/or environment-specific). These are +then available for interpolation in any string scalar value in any module's `garden.yml`. + + For example, assuming the above project configuration, `"foo-${variables.my-variable}-bar"` would evaluate to + `"foo-hello-variable-bar"` when used as a scalar string value in a module's `garden.yml`. + +### Module Configuration +Below, we'll use the module configurations of `hello-function` and `hello-container` from the +[hello-world example project](https://github.com/garden-io/garden/tree/528b141717f718ebe304d2ebde87b85d0c6c5e50/examples/hello-world) +as examples to illustrate some of the primary module-level configuration options. + +The following is a snippet from [`hello-function`'s module config](#hello-function-module-configuration): +```yaml +module: + description: Hello world serverless function + type: google-cloud-function + name: hello-function + ... + build: + dependencies: + - name: hello-npm-package + copy: + - source: "./" + target: libraries/hello-npm-package/ +``` + +#### name +The module's name, used e.g. when referring to it from another module's configuration as a +[build dependency](#build-configuration), or when building specific modules with `garden build`. + +Note that module names must be unique within a given project. An error will be thrown in any Garden CLI command if two +modules use the same name. + +#### type +A [module](../other/glossary.md#module)'s `type` specifies its plugin type. Garden interprets this according to the +active environment's configured provider for the specified plugin type. + +For example, +[`hello-container`](#hello-container-module-configuration)'s `type` is set to `container`, which the +[project configuration](#project-configuration) above interprets as `local-kubernetes` (a Docker container managed +via a local Kubernetes installation), assuming that the `local` environment is being used. + +#### build +A module's build configuration is specified via the `build` directive. + +Under `build`, the `command` subdirective sets the CLI command run during builds. A module's build command is executed +with its working directory set to a copy of the module's top-level directory, located at +`[project-root]/.garden/build/[module-name]`. This internal directory is referred to as the module's +[build directory](../other/glossary.md#build-directory). + +The `.garden` directory should not be modified by users, since this may lead to unexpected errors when the Garden CLI +tools are used in the project. + +##### Build Dependencies +The `dependencies` subdirective lists the module's build dependencies. `name` is the required module's name, and +`copy` indicates what files/folders, if any, should be copied from the required module's build directory to the +module in question after the required module is built (`source`), and where they should be copied (`target). + +#### Services +The following is a snippet from [`hello-container's`'s module config](#hello-container-module-configuration): +```yaml +module: + description: Hello world container service + type: container + services: + - name: hello-container + command: [npm, start] + ports: + - name: http + containerPort: 8080 + endpoints: + - paths: [/hello] + port: http + healthCheck: + httpGet: + path: /_ah/health + port: http + dependencies: + - hello-function + ... +``` +The `services` directive defines the services exposed by the module. + +##### name +The service's name, used e.g. when referring to it as a dependency of another service, or when deploying +specific services with `garden deploy`. Service names must be unique across all modules within a given project. An +error will be thrown in any Garden CLI command if two services use the same name. + +##### command +The CLI command to be executed (after the module is built) to make the service's endpoints available. + +##### ports +Names each port exposed by the service. + +##### endpoints +Enumerates the functional endpoints exposed by the service, defining the relative path and port to associate with +each of them. + +##### healthcheck +Defines the endpoint used to query the service's availability. + +##### dependencies +Lists the names of the services that must be deployed before the service in question (the `hello-container` service, in +this case) is deployed. + +##### tests +A list of named test configurations for the module. + +Following is another snippet from [`hello-container`'s module config](#hello-container-module-configuration): +```yaml +module: + description: Hello world container service + type: container + ... + tests: + - name: unit + command: [npm, test] + - name: integ + command: [npm, run, integ] + dependencies: + - hello-function +``` +Test groups can be run by `name` via `garden test`. `command` is the CLI command to run the specified tests, and +`dependencies` lists (by name) the services (if any) that must be deployed before the test group in question is run. + +#### Functions (experimental) +For modules defining serverless functions, the `functions` directive specifies the names and entry points of the +functions the module exposes. Note that serverless functionality is still experimental and under active development. + +This section is currently only included to clarify the `functions` directive in +[`hello-function`'s module config](#hello-function-module-configuration), since it's used as an example here. + +### Examples + +#### hello-function Module Configuration +[Github link](https://github.com/garden-io/garden/blob/528b141717f718ebe304d2ebde87b85d0c6c5e50/examples/hello-world/services/hello-function/garden.yml) +````yaml +# examples/hello-world/services/hello-function/garden.yml +module: + description: Hello world serverless function + name: hello-function + type: google-cloud-function + functions: + - name: hello-function + entrypoint: helloFunction + tests: + - name: unit + command: [npm, test] + build: + dependencies: + - name: hello-npm-package + copy: + - source: "./" + target: libraries/hello-npm-package/ +```` + +#### hello-container Module Configuration +[Github link](https://github.com/garden-io/garden/blob/528b141717f718ebe304d2ebde87b85d0c6c5e50/examples/hello-world/services/hello-container/garden.yml) +```yaml +# examples/hello-world/services/hello-container/garden.yml +module: + description: Hello world container service + type: container + services: + - name: hello-container + command: [npm, start] + ports: + - name: http + containerPort: 8080 + endpoints: + - paths: [/hello] + port: http + healthCheck: + httpGet: + path: /_ah/health + port: http + dependencies: + - hello-function + build: + dependencies: + - hello-npm-package + tests: + - name: unit + command: [npm, test] + - name: integ + command: [npm, run, integ] + dependencies: + - hello-function +``` diff --git a/docs/other/glossary.md b/docs/other/glossary.md new file mode 100644 index 0000000000..eba5c38978 --- /dev/null +++ b/docs/other/glossary.md @@ -0,0 +1,46 @@ +## Glossary + +#### Environment +Represents the current configuration and status of any running services in the [project](#project), which may be +inspected and modified via the Garden CLI's `environment` command. + +Several named environment configurations may be defined (e.g. _dev_, _testing_, ...) in the [project's +`garden.yml`](../guides/configuration.md#projects). + +#### Module +The basic unit of configuration in Garden. A module is defined by its +[`garden.yml` configuration file](../guides/configuration.md#module-configuration), located in the module's top-level +directory, +which +is a subdirectory of the [project](#project) repository's top-level directory. + +Each module has a [plugin](#plugin) type, and may define one or more [services](#sevice). + +Essentially, a project is organized into modules at the granularity of its *build* steps. A module's build step may +depend on one or more other modules, as specified in its `garden.yml`, in which case those modules will be built +first, and their build output made available to the requiring module's build step. + +#### Plugin +A [module's](#module) plugin type defines its behavior when it is built, deployed, run and tested. Currently, +`container` is the only stable plugin type, but plugin types for serverless functions and for build-only use cases +(such as NPM modules) are under development. + +#### Project +The top-level unit of organization in Garden. A project consists of one or more [modules](#modules), along with a +project-level [`garden.yml` configuration file](../guides/configuration.md#project-configuration). + +Garden CLI commands are run in the context of a project, and are aware of all its modules and services. + +Currently, Garden projects assume that all their modules are rooted in subdirectories of the same Git repository, with +the project-level `garden.yml` located in the repository's top-level directory. In a future release, this mono-repo +structure will be made optional. + +#### Provider +An implementation of a [plugin type](#plugin) (e.g. `local-kubernetes` for the `container` plugin). + +#### Service +The unit of deployment in Garden. Services are defined in their parent [module](#module)'s `garden.yml`, each +exposing [one or more endpoints](../guides/configuration.md#services). + +Services may depend on services defined in other modules, in which case those services will be deployed first, and +their deployment output made available to the requiring service's deploy step.