From b5641a3aab59917d8edcf8f0e6cf7e832472ed7a Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Thu, 23 May 2019 22:27:59 -0700 Subject: [PATCH 01/29] interim --- packages/@aws-cdk/assert/lib/synth-utils.ts | 6 +- packages/@aws-cdk/assets/lib/staging.ts | 33 +-- packages/@aws-cdk/assets/test/test.asset.ts | 69 +++--- packages/@aws-cdk/cdk/lib/app.ts | 27 ++- packages/@aws-cdk/cdk/lib/stack.ts | 11 +- packages/@aws-cdk/cdk/lib/synthesis.ts | 242 ++----------------- packages/@aws-cdk/cdk/test/test.app.ts | 4 +- packages/@aws-cdk/cdk/test/test.synthesis.ts | 107 +++----- packages/@aws-cdk/cx-api/lib/cxapi.ts | 9 +- packages/aws-cdk/bin/cdk.ts | 52 ++-- packages/aws-cdk/lib/api/cxapp/exec.ts | 38 +-- packages/aws-cdk/lib/settings.ts | 13 +- 12 files changed, 177 insertions(+), 434 deletions(-) diff --git a/packages/@aws-cdk/assert/lib/synth-utils.ts b/packages/@aws-cdk/assert/lib/synth-utils.ts index 2d3e1d237dfff..c93d8d4a0395a 100644 --- a/packages/@aws-cdk/assert/lib/synth-utils.ts +++ b/packages/@aws-cdk/assert/lib/synth-utils.ts @@ -1,4 +1,6 @@ import { ISynthesisSession, Stack, SynthesisOptions, Synthesizer } from '@aws-cdk/cdk'; +import fs = require('fs'); +import path = require('path'); export class SynthUtils { public static toCloudFormation(stack: Stack, options: SynthesisOptions = { }): any { @@ -7,7 +9,9 @@ export class SynthUtils { } public static templateForStackName(session: ISynthesisSession, stackName: string): any { - return session.store.readJson(session.getArtifact(stackName).properties!.templateFile); + const fileName = session.getArtifact(stackName).properties!.templateFile; + const filePath = path.join(session.outdir, fileName); + return JSON.parse(fs.readFileSync(filePath, 'utf-8')); } public static synthesize(stack: Stack, options: SynthesisOptions): ISynthesisSession { diff --git a/packages/@aws-cdk/assets/lib/staging.ts b/packages/@aws-cdk/assets/lib/staging.ts index 05e465acb4227..6e215b19eed63 100644 --- a/packages/@aws-cdk/assets/lib/staging.ts +++ b/packages/@aws-cdk/assets/lib/staging.ts @@ -1,4 +1,4 @@ -import { Construct, Token } from '@aws-cdk/cdk'; +import { Construct, ISynthesisSession } from '@aws-cdk/cdk'; import cxapi = require('@aws-cdk/cx-api'); import fs = require('fs'); import path = require('path'); @@ -48,13 +48,7 @@ export class Staging extends Construct { private readonly copyOptions: CopyOptions; - /** - * The asset path after "prepare" is called. - * - * If staging is disabled, this will just be the original path. - * If staging is enabled it will be the staged path. - */ - private _preparedAssetPath?: string; + private readonly relativePath?: string; constructor(scope: Construct, id: string, props: StagingProps) { super(scope, id); @@ -62,23 +56,22 @@ export class Staging extends Construct { this.sourcePath = props.sourcePath; this.copyOptions = props; this.sourceHash = fingerprint(this.sourcePath, props); - this.stagedPath = new Token(() => this._preparedAssetPath).toString(); - } - protected prepare() { - const stagingDir = this.node.getContext(cxapi.ASSET_STAGING_DIR_CONTEXT); - if (!stagingDir) { - this._preparedAssetPath = this.sourcePath; - return; + const stagingDisabled = this.node.getContext(cxapi.DISABLE_ASSET_STAGING_CONTEXT); + if (stagingDisabled) { + this.stagedPath = this.sourcePath; + } else { + this.relativePath = `asset.` + this.sourceHash + path.extname(this.sourcePath); + this.stagedPath = this.relativePath; // always relative to outdir } + } - if (!fs.existsSync(stagingDir)) { - fs.mkdirSync(stagingDir); + protected synthesize(session: ISynthesisSession) { + if (!this.relativePath) { + return; } - const targetPath = path.join(stagingDir, this.sourceHash + path.extname(this.sourcePath)); - - this._preparedAssetPath = targetPath; + const targetPath = path.join(session.outdir, this.relativePath); // asset already staged if (fs.existsSync(targetPath)) { diff --git a/packages/@aws-cdk/assets/test/test.asset.ts b/packages/@aws-cdk/assets/test/test.asset.ts index bb92463bd7454..943945c230489 100644 --- a/packages/@aws-cdk/assets/test/test.asset.ts +++ b/packages/@aws-cdk/assets/test/test.asset.ts @@ -13,7 +13,12 @@ const SAMPLE_ASSET_DIR = path.join(__dirname, 'sample-asset-directory'); export = { 'simple use case'(test: Test) { - const stack = new cdk.Stack(); + const app = new cdk.App({ + context: { + [cxapi.DISABLE_ASSET_STAGING_CONTEXT]: 'true' + } + }); + const stack = new cdk.Stack(app, 'MyStack'); const asset = new ZipDirectoryAsset(stack, 'MyAsset', { path: SAMPLE_ASSET_DIR }); @@ -24,11 +29,11 @@ export = { test.ok(entry, 'found metadata entry'); // verify that now the template contains parameters for this asset - const template = SynthUtils.toCloudFormation(stack); + const session = app.run(); test.deepEqual(stack.node.resolve(entry!.data), { path: SAMPLE_ASSET_DIR, - id: 'MyAsset', + id: 'MyStackMyAssetBDDF29E3', packaging: 'zip', sourceHash: '6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', s3BucketParameter: 'MyAssetS3Bucket68C9B344', @@ -36,6 +41,7 @@ export = { artifactHashParameter: 'MyAssetArtifactHashF518BDDE', }); + const template = JSON.parse(fs.readFileSync(path.join(session.outdir, 'MyStack.template.json'), 'utf-8')); test.equal(template.Parameters.MyAssetS3Bucket68C9B344.Type, 'String'); test.equal(template.Parameters.MyAssetS3VersionKey68E1A45D.Type, 'String'); @@ -54,7 +60,7 @@ export = { const synth = app.synthesizeStack(stack.name); test.deepEqual(synth.metadata['/my-stack/MyAsset'][0].data, { - path: dirPath, + path: 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', id: "mystackMyAssetD6B1B593", packaging: "zip", sourceHash: '6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', @@ -77,7 +83,7 @@ export = { const template = SynthUtils.toCloudFormation(stack); test.deepEqual(stack.node.resolve(entry!.data), { - path: filePath, + path: 'asset.78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197.txt', packaging: 'file', id: 'MyAsset', sourceHash: '78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197', @@ -195,7 +201,7 @@ export = { // THEN expect(stack).to(haveResource('My::Resource::Type', { Metadata: { - "aws:asset:path": location, + "aws:asset:path": 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', "aws:asset:property": "PropName" } }, ResourcePart.CompleteDefinition)); @@ -225,14 +231,12 @@ export = { 'staging': { - 'copy file assets under .assets/${fingerprint}.ext'(test: Test) { + 'copy file assets under /${fingerprint}.ext'(test: Test) { const tempdir = mkdtempSync(); process.chdir(tempdir); // change current directory to somewhere in /tmp // GIVEN - const app = new App({ - context: { [cxapi.ASSET_STAGING_DIR_CONTEXT]: '.assets' } - }); + const app = new App({ outdir: tempdir }); const stack = new Stack(app, 'stack'); // WHEN @@ -246,9 +250,8 @@ export = { // THEN app.run(); - test.ok(fs.existsSync(path.join(tempdir, '.assets'))); - test.ok(fs.existsSync(path.join(tempdir, '.assets', 'a7a79cdf84b802ea8b198059ff899cffc095a1b9606e919f98e05bf80779756b.zip'))); - fs.readdirSync(path.join(tempdir, '.assets')); + test.ok(fs.existsSync(tempdir)); + test.ok(fs.existsSync(path.join(tempdir, 'asset.a7a79cdf84b802ea8b198059ff899cffc095a1b9606e919f98e05bf80779756b.zip'))); test.done(); }, @@ -257,9 +260,7 @@ export = { process.chdir(tempdir); // change current directory to somewhere in /tmp // GIVEN - const app = new App({ - context: { [cxapi.ASSET_STAGING_DIR_CONTEXT]: '.assets' } - }); + const app = new App({ outdir: tempdir }); const stack = new Stack(app, 'stack'); // WHEN @@ -269,11 +270,11 @@ export = { // THEN app.run(); - test.ok(fs.existsSync(path.join(tempdir, '.assets'))); - const hash = '6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2'; - test.ok(fs.existsSync(path.join(tempdir, '.assets', hash, 'sample-asset-file.txt'))); - test.ok(fs.existsSync(path.join(tempdir, '.assets', hash, 'sample-jar-asset.jar'))); - fs.readdirSync(path.join(tempdir, '.assets')); + test.ok(fs.existsSync(tempdir)); + const hash = 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2'; + test.ok(fs.existsSync(path.join(tempdir, hash, 'sample-asset-file.txt'))); + test.ok(fs.existsSync(path.join(tempdir, hash, 'sample-jar-asset.jar'))); + fs.readdirSync(tempdir); test.done(); }, @@ -284,8 +285,8 @@ export = { const staging = '.my-awesome-staging-directory'; const app = new App({ + outdir: staging, context: { - [cxapi.ASSET_STAGING_DIR_CONTEXT]: staging, [cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT]: 'true', } }); @@ -302,18 +303,19 @@ export = { const template = SynthUtils.templateForStackName(session, stack.name); test.deepEqual(template.Resources.MyResource.Metadata, { - "aws:asset:path": `.my-awesome-staging-directory/6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2`, + "aws:asset:path": `asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2`, "aws:asset:property": "PropName" }); test.done(); }, - 'if staging directory is absolute, asset path is absolute'(test: Test) { + 'if staging is disabled, asset path is absolute'(test: Test) { // GIVEN const staging = path.resolve(mkdtempSync()); const app = new App({ + outdir: staging, context: { - [cxapi.ASSET_STAGING_DIR_CONTEXT]: staging, + [cxapi.DISABLE_ASSET_STAGING_CONTEXT]: 'true', [cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT]: 'true', } }); @@ -330,7 +332,7 @@ export = { const template = SynthUtils.templateForStackName(session, stack.name); test.deepEqual(template.Resources.MyResource.Metadata, { - "aws:asset:path": `${staging}/6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2`, + "aws:asset:path": SAMPLE_ASSET_DIR, "aws:asset:property": "PropName" }); test.done(); @@ -338,19 +340,8 @@ export = { 'cdk metadata points to staged asset'(test: Test) { // GIVEN - const tempdir = mkdtempSync(); - process.chdir(tempdir); // change current directory to somewhere in /tmp - - const staging = '.stageme'; - - const app = new App({ - context: { - [cxapi.ASSET_STAGING_DIR_CONTEXT]: staging, - } - }); - + const app = new App(); const stack = new Stack(app, 'stack'); - new ZipDirectoryAsset(stack, 'MyAsset', { path: SAMPLE_ASSET_DIR }); // WHEN @@ -358,7 +349,7 @@ export = { const artifact = session.getArtifact(stack.name); const md = Object.values(artifact.metadata || {})[0][0].data; - test.deepEqual(md.path, '.stageme/6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2'); + test.deepEqual(md.path, 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2'); test.done(); } diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 45f0f43d51b84..346d8db21781e 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -1,6 +1,8 @@ import cxapi = require('@aws-cdk/cx-api'); +import fs = require('fs'); +import path = require('path'); import { Construct } from './construct'; -import { FileSystemStore, InMemoryStore, ISynthesisSession, Synthesizer } from './synthesis'; +import { ISynthesisSession, Synthesizer } from './synthesis'; /** * Custom construction properties for a CDK program @@ -15,6 +17,14 @@ export interface AppProps { */ readonly autoRun?: boolean; + /** + * The output directory into which to emit synthesized artifacts. + * + * @default - If this value is _not_ set, considers the environment variable `CDK_OUTDIR`. + * If `CDK_OUTDIR` is not defined, uses a temp directory. + */ + readonly outdir?: string; + /** * Additional context values for the application * @@ -30,6 +40,7 @@ export class App extends Construct { private _session?: ISynthesisSession; private readonly legacyManifest: boolean; private readonly runtimeInformation: boolean; + private readonly outdir?: string; /** * Initializes a CDK application. @@ -43,6 +54,7 @@ export class App extends Construct { // both are reverse logic this.legacyManifest = this.node.getContext(cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT) ? false : true; this.runtimeInformation = this.node.getContext(cxapi.DISABLE_VERSION_REPORTING) ? false : true; + this.outdir = props.outdir || process.env[cxapi.OUTDIR_ENV]; const autoRun = props.autoRun !== undefined ? props.autoRun : cxapi.OUTDIR_ENV in process.env; @@ -62,18 +74,10 @@ export class App extends Construct { return this._session; } - const outdir = process.env[cxapi.OUTDIR_ENV]; - let store; - if (outdir) { - store = new FileSystemStore({ outdir }); - } else { - store = new InMemoryStore(); - } - const synth = new Synthesizer(); this._session = synth.synthesize(this, { - store, + outdir: this.outdir, legacyManifest: this.legacyManifest, runtimeInformation: this.runtimeInformation }); @@ -92,7 +96,8 @@ export class App extends Construct { } const session = this.run(); - const legacy: cxapi.SynthesizeResponse = session.store.readJson(cxapi.OUTFILE_NAME); + const legacyManifestFile = path.join(session.outdir, cxapi.OUTFILE_NAME); + const legacy: cxapi.SynthesizeResponse = JSON.parse(fs.readFileSync(legacyManifestFile, 'utf-8')); const res = legacy.stacks.find(s => s.name === stackName); if (!res) { diff --git a/packages/@aws-cdk/cdk/lib/stack.ts b/packages/@aws-cdk/cdk/lib/stack.ts index 63b9d5f367311..8a97fee9f350d 100644 --- a/packages/@aws-cdk/cdk/lib/stack.ts +++ b/packages/@aws-cdk/cdk/lib/stack.ts @@ -1,4 +1,6 @@ import cxapi = require('@aws-cdk/cx-api'); +import fs = require('fs'); +import path = require('path'); import { App } from './app'; import { CfnParameter } from './cfn-parameter'; import { Construct, IConstruct, PATH_SEP } from './construct'; @@ -169,13 +171,13 @@ export class Stack extends Construct { * * @returns The Resource or undefined if not found */ - public findResource(path: string): CfnResource | undefined { - const r = this.node.findChild(path); + public findResource(constructPath: string): CfnResource | undefined { + const r = this.node.findChild(constructPath); if (!r) { return undefined; } // found an element, check if it's a resource (duck-type) if (!('resourceType' in r)) { - throw new Error(`Found a stack element for ${path} but it is not a resource: ${r.toString()}`); + throw new Error(`Found a stack element for ${constructPath} but it is not a resource: ${r.toString()}`); } return r as CfnResource; @@ -495,7 +497,8 @@ export class Stack extends Construct { const template = `${this.name}.template.json`; // write the CloudFormation template as a JSON file - session.store.writeJson(template, this._toCloudFormation()); + const outPath = path.join(session.outdir, template); + fs.writeFileSync(outPath, JSON.stringify(this._toCloudFormation(), undefined, 2)); const deps = this.dependencies().map(s => s.name); const meta = this.collectMetadata(); diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index 47d2cfdbd581e..580c295551284 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -11,7 +11,7 @@ export interface ISynthesizable { } export interface ISynthesisSession { - readonly store: ISessionStore; + readonly outdir: string; readonly manifest: cxapi.AssemblyManifest; addArtifact(id: string, droplet: cxapi.Artifact): void; addBuildStep(id: string, step: cxapi.BuildStep): void; @@ -22,9 +22,9 @@ export interface ISynthesisSession { export interface SynthesisOptions extends ManifestOptions { /** * The file store used for this session. - * @default InMemoryStore + * @default - creates a temporary directory */ - readonly store?: ISessionStore; + readonly outdir?: string; /** * Whether synthesis should skip the validation phase. @@ -74,14 +74,17 @@ export class SynthesisSession implements ISynthesisSession { return 'synthesize' in obj; } - public readonly store: ISessionStore; + public readonly outdir: string; private readonly artifacts: { [id: string]: cxapi.Artifact } = { }; private readonly buildSteps: { [id: string]: cxapi.BuildStep } = { }; private _manifest?: cxapi.AssemblyManifest; - constructor(options: SynthesisOptions) { - this.store = options.store || new InMemoryStore(); + constructor(options: SynthesisOptions = { }) { + this.outdir = options.outdir || fs.mkdtempSync(path.join(os.tmpdir(), 'cdk.out')); + if (!fs.existsSync(this.outdir)) { + fs.mkdirSync(this.outdir); + } } public get manifest() { @@ -126,7 +129,8 @@ export class SynthesisSession implements ISynthesisSession { runtime: runtimeInfo ? collectRuntimeInformation() : undefined }); - this.store.writeFile(cxapi.MANIFEST_FILE, JSON.stringify(manifest, undefined, 2)); + const manifestFilePath = path.join(this.outdir, cxapi.MANIFEST_FILE); + fs.writeFileSync(manifestFilePath, JSON.stringify(manifest, undefined, 2)); // write build manifest if we have build steps if (Object.keys(this.buildSteps).length > 0) { @@ -134,21 +138,21 @@ export class SynthesisSession implements ISynthesisSession { steps: this.buildSteps }; - this.store.writeFile(cxapi.BUILD_FILE, JSON.stringify(buildManifest, undefined, 2)); + const buildFilePath = path.join(this.outdir, cxapi.BUILD_FILE); + fs.writeFileSync(buildFilePath, JSON.stringify(buildManifest, undefined, 2)); } if (legacyManifest) { const legacy: cxapi.SynthesizeResponse = { ...manifest, - stacks: renderLegacyStacks(manifest, this.store) + stacks: renderLegacyStacks(manifest, this.outdir) }; // render the legacy manifest (cdk.out) which also contains a "stacks" attribute with all the rendered stacks. - this.store.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(legacy, undefined, 2)); + const legacyManifestPath = path.join(this.outdir, cxapi.OUTFILE_NAME); + fs.writeFileSync(legacyManifestPath, JSON.stringify(legacy, undefined, 2)); } - this.store.lock(); - return manifest; } } @@ -167,216 +171,7 @@ export interface ManifestOptions { readonly runtimeInformation?: boolean; } -export interface ISessionStore { - /** - * Creates a directory and returns it's full path. - * @param directoryName The name of the directory to create. - * @throws if a directory by that name already exists in the session or if the session has already been finalized. - */ - mkdir(directoryName: string): string; - - /** - * Returns the list of files in a directory. - * @param directoryName The name of the artifact - * @throws if there is no directory artifact under this name - */ - readdir(directoryName: string): string[]; - - /** - * Writes a file into the store. - * @param artifactName The name of the file. - * @param data The contents of the file. - */ - writeFile(artifactName: string, data: any): void; - - /** - * Writes a formatted JSON output file to the store - * @param artifactName the name of the artifact - * @param json the JSON object - */ - writeJson(artifactName: string, json: any): void; - - /** - * Reads a file from the store. - * @param fileName The name of the file. - * @throws if the file is not found - */ - readFile(fileName: string): any; - - /** - * Reads a JSON object from the store. - */ - readJson(fileName: string): any; - - /** - * @returns true if the file `fileName` exists in the store. - * @param name The name of the file or directory to look up. - */ - exists(name: string): boolean; - - /** - * List all top-level files that were emitted to the store. - */ - list(): string[]; - - /** - * Do not allow further writes into the store. - */ - lock(): void; -} - -export interface FileSystemStoreOptions { - /** - * The output directory for synthesis artifacts - */ - readonly outdir: string; -} - -/** - * Can be used to prepare and emit synthesis artifacts into an output directory. - */ -export class FileSystemStore implements ISessionStore { - private readonly outdir: string; - private locked = false; - - constructor(options: FileSystemStoreOptions) { - this.outdir = options.outdir; - return; - } - - public writeFile(fileName: string, data: any) { - this.canWrite(fileName); - - const p = this.pathForArtifact(fileName); - fs.writeFileSync(p, data); - } - - public writeJson(fileName: string, json: any) { - this.writeFile(fileName, JSON.stringify(json, undefined, 2)); - } - - public readFile(fileName: string): any { - const p = this.pathForArtifact(fileName); - if (!fs.existsSync(p)) { - throw new Error(`File not found: ${p}`); - } - - return fs.readFileSync(p); - } - - public readJson(fileName: string): any { - return JSON.parse(this.readFile(fileName).toString()); - } - - public exists(name: string): boolean { - const p = this.pathForArtifact(name); - return fs.existsSync(p); - } - - public mkdir(directoryName: string): string { - this.canWrite(directoryName); - const p = this.pathForArtifact(directoryName); - fs.mkdirSync(p); - return p; - } - - public readdir(directoryName: string): string[] { - if (!this.exists(directoryName)) { - throw new Error(`${directoryName} not found`); - } - - const p = this.pathForArtifact(directoryName); - return fs.readdirSync(p); - } - - public list(): string[] { - return fs.readdirSync(this.outdir).sort(); - } - - public lock() { - this.locked = true; - } - - private pathForArtifact(id: string) { - return path.join(this.outdir, id); - } - - private canWrite(artifactName: string) { - if (this.exists(artifactName)) { - throw new Error(`An artifact named ${artifactName} was already written to this session`); - } - if (this.locked) { - throw new Error('Session has already been finalized'); - } - } -} - -export class InMemoryStore implements ISessionStore { - private files: { [fileName: string]: any } = { }; - private dirs: { [dirName: string]: string } = { }; // value is path to a temporary directory - - private locked = false; - - public writeFile(fileName: string, data: any): void { - this.canWrite(fileName); - this.files[fileName] = data; - } - - public writeJson(fileName: string, json: any): void { - this.writeFile(fileName, JSON.stringify(json, undefined, 2)); - } - - public readFile(fileName: string) { - if (!(fileName in this.files)) { - throw new Error(`${fileName} not found`); - } - return this.files[fileName]; - } - - public readJson(fileName: string): any { - return JSON.parse(this.readFile(fileName).toString()); - } - - public exists(name: string) { - return name in this.files || name in this.dirs; - } - - public mkdir(directoryName: string): string { - this.canWrite(directoryName); - - const p = fs.mkdtempSync(path.join(os.tmpdir(), directoryName)); - this.dirs[directoryName] = p; - return p; - } - - public readdir(directoryName: string): string[] { - if (!this.exists(directoryName)) { - throw new Error(`${directoryName} not found`); - } - - const p = this.dirs[directoryName]; - return fs.readdirSync(p); - } - - public list(): string[] { - return [ ...Object.keys(this.files), ...Object.keys(this.dirs) ].sort(); - } - - public lock() { - this.locked = true; - } - - private canWrite(artifactName: string) { - if (this.exists(artifactName)) { - throw new Error(`An artifact named ${artifactName} was already written to this session`); - } - if (this.locked) { - throw new Error('Session has already been finalized'); - } - } -} - -export function renderLegacyStacks(manifest: cxapi.AssemblyManifest, store: ISessionStore) { +export function renderLegacyStacks(manifest: cxapi.AssemblyManifest, outdir: string) { // special case for backwards compat. build a list of stacks for the manifest const stacks = new Array(); const artifacts = manifest.artifacts || { }; @@ -387,7 +182,8 @@ export function renderLegacyStacks(manifest: cxapi.AssemblyManifest, store: ISes if (!templateFile) { throw new Error(`Invalid cloudformation artifact. Missing "template" property`); } - const template = store.readJson(templateFile); + const templateFilePath = path.join(outdir, templateFile); + const template = JSON.parse(fs.readFileSync(templateFilePath, 'utf-8')); const match = cxapi.AWS_ENV_REGEX.exec(artifact.environment); if (!match) { diff --git a/packages/@aws-cdk/cdk/test/test.app.ts b/packages/@aws-cdk/cdk/test/test.app.ts index 04c8995d0932b..d35cdd38ac6b0 100644 --- a/packages/@aws-cdk/cdk/test/test.app.ts +++ b/packages/@aws-cdk/cdk/test/test.app.ts @@ -1,5 +1,7 @@ import cxapi = require('@aws-cdk/cx-api'); +import fs = require('fs'); import { Test } from 'nodeunit'; +import path = require('path'); import { CfnResource, Construct, Stack, StackProps } from '../lib'; import { App } from '../lib/app'; @@ -11,7 +13,7 @@ function withApp(context: { [key: string]: any } | undefined, block: (app: App) const session = app.run(); // return the legacy manifest - return session.store.readJson(cxapi.OUTFILE_NAME); + return JSON.parse(fs.readFileSync(path.join(session.outdir, cxapi.OUTFILE_NAME), 'utf-8')); } function synth(context?: { [key: string]: any }): cxapi.SynthesizeResponse { diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index c360054a24546..63e1448fb629e 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -4,7 +4,7 @@ import { Test } from 'nodeunit'; import os = require('os'); import path = require('path'); import cdk = require('../lib'); -import { Construct, FileSystemStore, InMemoryStore, ISynthesisSession, SynthesisSession, Synthesizer } from '../lib'; +import { Construct, ISynthesisSession, SynthesisSession, Synthesizer } from '../lib'; const storeTestMatrix: any = {}; @@ -27,8 +27,8 @@ export = { // THEN test.same(app.run(), session); // same session if we run() again - test.deepEqual(session.store.list(), [ 'manifest.json' ]); - test.deepEqual(session.store.readJson('manifest.json').artifacts, {}); + test.deepEqual(list(session.outdir), [ 'manifest.json' ]); + test.deepEqual(readJson(session.outdir, 'manifest.json').artifacts, {}); test.done(); }, @@ -41,7 +41,7 @@ export = { const session = app.run(); // THEN - test.deepEqual(session.store.list(), [ + test.deepEqual(list(session.outdir), [ 'manifest.json', 'one-stack.template.json' ]); @@ -55,7 +55,7 @@ export = { class MyConstruct extends cdk.Construct implements cdk.ISynthesizable { public synthesize(s: cdk.ISynthesisSession) { - s.store.writeJson('foo.json', { bar: 123 }); + writeJson(s.outdir, 'foo.json', { bar: 123 }); s.addArtifact('my-random-construct', { type: cxapi.ArtifactType.AwsCloudFormationStack, environment: 'aws://12345/bar', @@ -72,12 +72,12 @@ export = { const session = app.run(); // THEN - test.deepEqual(session.store.list(), [ + test.deepEqual(list(session.outdir), [ 'foo.json', 'manifest.json', 'one-stack.template.json' ]); - test.deepEqual(session.store.readJson('foo.json'), { bar: 123 }); + test.deepEqual(readJson(session.outdir, 'foo.json'), { bar: 123 }); test.deepEqual(session.manifest, { version: '0.19.0', artifacts: { @@ -107,7 +107,7 @@ export = { // WHEN const session = app.run(); - const legacy: cxapi.SynthesizeResponse = session.store.readJson(cxapi.OUTFILE_NAME); + const legacy: cxapi.SynthesizeResponse = readJson(session.outdir, cxapi.OUTFILE_NAME); // THEN const t1 = legacy.stacks.find(s => s.name === 'stack1')!.template; @@ -152,17 +152,17 @@ export = { environment: 'aws://unknown-account/us-east-1' }); - session.store.writeJson('hey.json', { hello: 123 }); + writeJson(session.outdir, 'hey.json', { hello: 123 }); } } const root = new SynthesizeMe(); const synth = new Synthesizer(); - const result = synth.synthesize(root); + const result = synth.synthesize(root, { outdir: fs.mkdtempSync(path.join(os.tmpdir(), 'outdir')) }); test.deepEqual(calls, [ 'prepare', 'validate', 'synthesize' ]); - test.deepEqual(result.store.readJson('hey.json'), { hello: 123 }); + test.deepEqual(readJson(result.outdir, 'hey.json'), { hello: 123 }); test.deepEqual(result.manifest.artifacts!.art, { type: 'aws:ecr:image', environment: 'aws://unknown-account/us-east-1' @@ -177,63 +177,9 @@ export = { // all these tests will be executed for each type of store // const storeTests = { - 'writeFile()/readFile()'(test: Test, store: cdk.ISessionStore) { - // WHEN - store.writeFile('bla.txt', 'hello'); - store.writeFile('hey.txt', '1234'); - - // THEN - test.deepEqual(store.readFile('bla.txt').toString(), 'hello'); - test.deepEqual(store.readFile('hey.txt').toString(), '1234'); - test.throws(() => store.writeFile('bla.txt', 'override is forbidden')); - - // WHEN - store.lock(); - - // THEN - test.throws(() => store.writeFile('another.txt', 'locked!')); - test.done(); - }, - - 'exists() for files'(test: Test, store: cdk.ISessionStore) { - // WHEN - store.writeFile('A.txt', 'aaa'); - - // THEN - test.ok(store.exists('A.txt')); - test.ok(!store.exists('B.txt')); - test.done(); - }, - - 'mkdir'(test: Test, store: cdk.ISessionStore) { - // WHEN - const dir1 = store.mkdir('dir1'); - const dir2 = store.mkdir('dir2'); - - // THEN - test.ok(fs.statSync(dir1).isDirectory()); - test.ok(fs.statSync(dir2).isDirectory()); - test.throws(() => store.mkdir('dir1')); - - // WHEN - store.lock(); - test.throws(() => store.mkdir('dir3')); - test.done(); - }, - - 'list'(test: Test, store: cdk.ISessionStore) { - // WHEN - store.mkdir('dir1'); - store.writeFile('file1.txt', 'boom1'); - - // THEN - test.deepEqual(store.list(), ['dir1', 'file1.txt']); - test.done(); - }, - - 'SynthesisSession'(test: Test, store: cdk.ISessionStore) { + 'SynthesisSession'(test: Test, outdir: string) { // GIVEN - const session = new SynthesisSession({ store }); + const session = new SynthesisSession({ outdir }); const templateFile = 'foo.template.json'; // WHEN @@ -270,7 +216,7 @@ const storeTests = { } }); - session.store.writeJson(templateFile, { + writeJson(session.outdir, templateFile, { Resources: { MyTopic: { Type: 'AWS::S3::Topic' @@ -280,7 +226,7 @@ const storeTests = { session.close(); - const manifest = session.store.readJson(cxapi.MANIFEST_FILE); + const manifest = readJson(session.outdir, cxapi.MANIFEST_FILE); // THEN delete manifest.runtime; // deterministic tests @@ -314,7 +260,7 @@ const storeTests = { }); // verify we have a template file - test.deepEqual(session.store.readJson(templateFile), { + test.deepEqual(readJson(session.outdir, templateFile), { Resources: { MyTopic: { Type: 'AWS::S3::Topic' @@ -363,8 +309,8 @@ const storeTests = { // THEN const session = app.run(); - test.deepEqual(session.store.list(), [ 'build.json', 'manifest.json' ]); - test.deepEqual(session.store.readJson('build.json'), { + test.deepEqual(list(session.outdir), [ 'build.json', 'manifest.json' ]); + test.deepEqual(readJson(session.outdir, 'build.json'), { steps: { step_id: { type: 'build-step-type', parameters: { boom: 123 } } } @@ -375,8 +321,17 @@ const storeTests = { for (const [name, fn] of Object.entries(storeTests)) { const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'synthesis-tests')); - const fsStore = new FileSystemStore({ outdir }); - const memoryStore = new InMemoryStore(); - storeTestMatrix[`FileSystemStore - ${name}`] = (test: Test) => fn(test, fsStore); - storeTestMatrix[`InMemoryStore - ${name}`] = (test: Test) => fn(test, memoryStore); + storeTestMatrix[name] = (test: Test) => fn(test, outdir); +} + +function list(outdir: string) { + return fs.readdirSync(outdir).sort(); +} + +function readJson(outdir: string, file: string) { + return JSON.parse(fs.readFileSync(path.join(outdir, file), 'utf-8')); } + +function writeJson(outdir: string, file: string, data: any) { + fs.writeFileSync(path.join(outdir, file), JSON.stringify(data, undefined, 2)); +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/cxapi.ts b/packages/@aws-cdk/cx-api/lib/cxapi.ts index 459e3bee879e1..25801c004ea68 100644 --- a/packages/@aws-cdk/cx-api/lib/cxapi.ts +++ b/packages/@aws-cdk/cx-api/lib/cxapi.ts @@ -33,6 +33,9 @@ export const MANIFEST_FILE = 'manifest.json'; */ export const BUILD_FILE = 'build.json'; +// output directory into which to emit synthesis outputs. CDK doesn't allow outdir +// to be specified both through the CDK_OUTDIR environment variable and the through +// aws:cdk:outdir context. export const OUTDIR_ENV = 'CDK_OUTDIR'; export const CONTEXT_ENV = 'CDK_CONTEXT_JSON'; @@ -179,7 +182,7 @@ export const OUTFILE_NAME = 'cdk.out'; export const DISABLE_VERSION_REPORTING = 'aws:cdk:disable-version-reporting'; /** - * If this context key is set, the CDK will stage assets under the specified - * directory. Otherwise, assets will not be staged. + * If this is set, asset staging is disabled. This means that assets will not be copied to + * the output directory and will be referenced with absolute source paths. */ -export const ASSET_STAGING_DIR_CONTEXT = 'aws:cdk:asset-staging-dir'; +export const DISABLE_ASSET_STAGING_CONTEXT = 'aws:cdk:disable-asset-staging'; diff --git a/packages/aws-cdk/bin/cdk.ts b/packages/aws-cdk/bin/cdk.ts index 6d2b623e9bbf6..daf26b3a260e3 100644 --- a/packages/aws-cdk/bin/cdk.ts +++ b/packages/aws-cdk/bin/cdk.ts @@ -2,7 +2,6 @@ import 'source-map-support/register'; import colors = require('colors/safe'); -import fs = require('fs-extra'); import yargs = require('yargs'); import { bootstrapEnvironment, destroyStack, SDK } from '../lib'; @@ -10,12 +9,11 @@ import { environmentsFromDescriptors, globEnvironmentsFromStacks } from '../lib/ import { execProgram } from '../lib/api/cxapp/exec'; import { AppStacks, ExtendedStackSelection, listStackNames } from '../lib/api/cxapp/stacks'; import { CloudFormationDeploymentTarget, DEFAULT_TOOLKIT_STACK_NAME } from '../lib/api/deployment-target'; -import { leftPad } from '../lib/api/util/string-manipulation'; import { CdkToolkit } from '../lib/cdk-toolkit'; import { RequireApproval } from '../lib/diff'; import { availableInitLanguages, cliInit, printAvailableTemplates } from '../lib/init'; import { interactive } from '../lib/interactive'; -import { data, debug, error, highlight, print, setVerbose, success } from '../lib/logging'; +import { data, debug, error, print, setVerbose, success } from '../lib/logging'; import { PluginHost } from '../lib/plugin'; import { parseRenames } from '../lib/renames'; import { serializeStructure } from '../lib/serialize'; @@ -48,14 +46,13 @@ async function parseCommandLineArguments() { .option('asset-metadata', { type: 'boolean', desc: 'Include "aws:asset:*" CloudFormation metadata for resources that user assets (enabled by default)', default: true }) .option('role-arn', { type: 'string', alias: 'r', desc: 'ARN of Role to use when invoking CloudFormation', default: undefined, requiresArg: true }) .option('toolkit-stack-name', { type: 'string', desc: 'The name of the CDK toolkit stack', requiresArg: true }) - .option('staging', { type: 'string', desc: 'directory name for staging assets (use --no-asset-staging to disable)', default: '.cdk.staging' }) + .option('staging', { type: 'boolean', desc: 'copy assets to the output directory (use --no-staging to disable)', default: true }) + .option('output', { type: 'string', alias: 'o', desc: 'emits synthesis output into a directory (default: cdk.out)', requiresArg: true }) .command([ 'list', 'ls' ], 'Lists all stacks in the app', yargs => yargs .option('long', { type: 'boolean', default: false, alias: 'l', desc: 'display environment information for each stack' })) .command([ 'synthesize [STACKS..]', 'synth [STACKS..]' ], 'Synthesizes and prints the CloudFormation template for this stack', yargs => yargs .option('exclusively', { type: 'boolean', alias: 'e', desc: 'only deploy requested stacks, don\'t include dependencies' }) - .option('interactive', { type: 'boolean', alias: 'i', desc: 'interactively watch and show template updates' }) - .option('output', { type: 'string', alias: 'o', desc: 'write CloudFormation template for requested stacks to the given directory', requiresArg: true }) - .option('numbered', { type: 'boolean', alias: 'n', desc: 'prefix filenames with numbers to indicate deployment ordering' })) + .option('interactive', { type: 'boolean', alias: 'i', desc: 'interactively watch and show template updates' })) .command('bootstrap [ENVIRONMENTS..]', 'Deploys the CDK toolkit stack into an AWS environment', yargs => yargs .option('toolkit-bucket-name', { type: 'string', alias: 'b', desc: 'The name of the CDK toolkit bucket', default: undefined })) .command('deploy [STACKS..]', 'Deploys the stack(s) named STACKS into your AWS account', yargs => yargs @@ -211,7 +208,7 @@ async function initCommandLine() { case 'synthesize': case 'synth': - return await cliSynthesize(args.STACKS, args.exclusively, args.interactive, args.output, args.json, args.numbered); + return await cliSynthesize(args.STACKS, args.exclusively, args.interactive, configuration.settings); case 'metadata': return await cliMetadata(await findStack(args.STACK)); @@ -281,11 +278,9 @@ async function initCommandLine() { async function cliSynthesize(stackNames: string[], exclusively: boolean, doInteractive: boolean, - outputDir: string|undefined, - json: boolean, - numbered: boolean): Promise { + settings: Settings): Promise { // Only autoselect dependencies if it doesn't interfere with user request or output options - const autoSelectDependencies = !exclusively && outputDir !== undefined; + const autoSelectDependencies = !exclusively; const stacks = await appStacks.selectStacks(stackNames, autoSelectDependencies ? ExtendedStackSelection.Upstream : ExtendedStackSelection.None); @@ -296,6 +291,11 @@ async function initCommandLine() { return await interactive(stacks[0], argv.verbose, (stack) => appStacks.synthesizeStack(stack)); } + // if we have a single stack, print it to STDOUT + if (stacks.length === 1) { + return stacks[0].template; + } + // This is a slight hack; in integ mode we allow multiple stacks to be synthesized to stdout sequentially. // This is to make it so that we can support multi-stack integ test expectations, without so drastically // having to change the synthesis format that we have to rerun all integ tests. @@ -304,33 +304,11 @@ async function initCommandLine() { // the stack names), it's not exposed as a CLI flag. Instead, it's hidden // behind an environment variable. const isIntegMode = process.env.CDK_INTEG_MODE === '1'; - - if (stacks.length > 1 && outputDir == null && !isIntegMode) { - // tslint:disable-next-line:max-line-length - throw new Error(`Multiple stacks selected (${listStackNames(stacks)}), but output is directed to stdout. Either select one stack, or use --output to send templates to a directory.`); - } - - if (outputDir == null) { - // What we return here will be printed in 'main' - if (stacks.length > 1) { - // Only possible in integ mode - return stacks.map(s => s.template); - } - return stacks[0].template; - } - - fs.mkdirpSync(outputDir); - - let i = 0; - for (const stack of stacks) { - const prefix = numbered ? leftPad(`${i}`, 3, '0') + '.' : ''; - const fileName = `${outputDir}/${prefix}${stack.name}.template.${json ? 'json' : 'yaml'}`; - highlight(fileName); - await fs.writeFile(fileName, toJsonOrYaml(stack.template)); - i++; + if (isIntegMode) { + return stacks.map(s => s.template); } - return undefined; // Nothing to print + return settings.get(['output']); } async function cliList(options: { long?: boolean } = { }) { diff --git a/packages/aws-cdk/lib/api/cxapp/exec.ts b/packages/aws-cdk/lib/api/cxapp/exec.ts index 72d1412c367c6..cdde161d2fb58 100644 --- a/packages/aws-cdk/lib/api/cxapp/exec.ts +++ b/packages/aws-cdk/lib/api/cxapp/exec.ts @@ -1,7 +1,6 @@ import cxapi = require('@aws-cdk/cx-api'); import childProcess = require('child_process'); import fs = require('fs-extra'); -import os = require('os'); import path = require('path'); import semver = require('semver'); import { debug } from '../../logging'; @@ -42,8 +41,13 @@ export async function execProgram(aws: SDK, config: Configuration): Promise((ok, fail) => { // We use a slightly lower-level interface to: diff --git a/packages/aws-cdk/lib/settings.ts b/packages/aws-cdk/lib/settings.ts index 5f984f6e43fa7..4366916ea074d 100644 --- a/packages/aws-cdk/lib/settings.ts +++ b/packages/aws-cdk/lib/settings.ts @@ -20,7 +20,12 @@ export class Configuration { public settings = new Settings(); public context = new Context(); - private readonly defaultConfig = new Settings({ versionReporting: true, pathMetadata: true }); + public readonly defaultConfig = new Settings({ + versionReporting: true, + pathMetadata: true, + output: 'cdk.out' + }); + private readonly commandLineArguments: Settings; private readonly commandLineContext: Settings; private projectConfig: Settings; @@ -56,6 +61,8 @@ export class Configuration { .merge(this.commandLineArguments) .makeReadOnly(); + debug('merged settings:', this.settings.all); + this.loaded = true; return this; @@ -210,7 +217,8 @@ export class Settings { requireApproval: argv.requireApproval, toolkitStackName: argv.toolkitStackName, versionReporting: argv.versionReporting, - staging: argv.staging + staging: argv.staging, + output: argv.output, }); } @@ -255,6 +263,7 @@ export class Settings { } public merge(other: Settings): Settings { + debug('merging settings:', other.all); return new Settings(util.deepMerge(this.settings, other.settings)); } From 971957b0334244af4ba170e0791cfec807b24438 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Fri, 24 May 2019 10:41:52 -0700 Subject: [PATCH 02/29] feat(cli): cloud assembly - decouple synth and deploy formalize the concept of a cloud assembly to allow decoupling "synth" and "deploy". the main motivation is to allow "deploy" to run in a controlled environment without needing to execute the app for security purposes. "cdk synth" now produces a self-contained assembly in the output directory, which we call a "cloud assembly". this directory includes synthesized templates (similar to current behavior) but also a "manifest.json" file and the asset staging directories. "cdk deploy -a " will now skip synthesis and will directly deploy the assembly. to that end, we modified the behavior of asset staging such that all synth output always goes to the output directory, which is by default `cdk.out` (can be set with `--output`). if there's a single template, it is printed to stdout, otherwise the name of output directory is printed. BREAKING CHANGE: apps created with this version cannot be deployed using a previous version of the CLI and vice versa. Both have to be >= 0.32.0. - @aws-cdk/cdk.App member synthesizeStack has been removed - @aws-cdk/cdk.App member synthesizeStacks has been removed - @aws-cdk/cdk.FileSystemStore has been removed - @aws-cdk/cdk.InMemoryStore has been removed - @aws-cdk/cdk.SynthesisSession member addBuildStep has been removed - @aws-cdk/cdk.SynthesisSession member store has been removed - @aws-cdk/cdk.FileSystemStoreOptions has been removed - @aws-cdk/cdk.ISessionStore has been removed - @aws-cdk/cdk.ISynthesisSession member addBuildStep has been removed - @aws-cdk/cdk.ISynthesisSession member store has been removed - @aws-cdk/cdk.ManifestOptions member legacyManifest has been removed - @aws-cdk/cdk.ResolveContext has been removed - @aws-cdk/cdk.SynthesisOptions member legacyManifest has been removed - @aws-cdk/cdk.SynthesisOptions member store has been removed - @aws-cdk/cx-api.BuildManifest has been removed - @aws-cdk/cx-api.BuildStep has been removed - @aws-cdk/cx-api.SynthesizeResponse has been removed - @aws-cdk/cx-api.SynthesizedStack has been removed - @aws-cdk/cx-api.BuildStepType has been removed - --interactive has been removed - --numbered has been removed --- .gitignore | 2 + packages/@aws-cdk/assert/jest.ts | 8 +- packages/@aws-cdk/assert/lib/expect.ts | 12 +- packages/@aws-cdk/assert/lib/inspector.ts | 4 +- .../@aws-cdk/assert/test/test.assertions.ts | 13 +- .../assert/test/test.have-resource.ts | 11 +- packages/@aws-cdk/assets/test/test.asset.ts | 8 +- packages/@aws-cdk/cdk/lib/app.ts | 59 +- packages/@aws-cdk/cdk/lib/construct.ts | 6 +- packages/@aws-cdk/cdk/lib/stack.ts | 10 +- packages/@aws-cdk/cdk/lib/synthesis.ts | 71 - packages/@aws-cdk/cdk/test/test.app.ts | 457 +- packages/@aws-cdk/cdk/test/test.context.ts | 9 +- packages/@aws-cdk/cdk/test/test.synthesis.ts | 67 +- packages/@aws-cdk/cx-api/.gitignore | 5 +- packages/@aws-cdk/cx-api/jest.config.js | 180 + packages/@aws-cdk/cx-api/lib/artifacts.ts | 9 +- .../cx-api/lib/assembly/cloud-artifact.ts | 96 + .../cx-api/lib/assembly/cloud-assembly-api.ts | 55 + .../cx-api/lib/assembly/cloud-assembly.ts | 105 + .../lib/assembly/cloudformation-stack.ts | 57 + .../@aws-cdk/cx-api/lib/assembly/index.ts | 2 + .../cx-api/lib/assembly}/toposort.ts | 0 packages/@aws-cdk/cx-api/lib/build.ts | 16 - packages/@aws-cdk/cx-api/lib/cxapi.ts | 50 +- packages/@aws-cdk/cx-api/lib/environment.ts | 13 - packages/@aws-cdk/cx-api/lib/index.ts | 3 +- packages/@aws-cdk/cx-api/package-lock.json | 5060 ++++++++++++++++- packages/@aws-cdk/cx-api/package.json | 19 +- .../test/__snapshots__/deploy.test.js.snap | 61 + packages/@aws-cdk/cx-api/test/deploy.test.ts | 93 + .../test/fixtures/assets/asset-dir/foo.txt | 1 + .../fixtures/assets/docker-asset/Dockerfile | 1 + .../cx-api/test/fixtures/assets/manifest.json | 36 + .../cx-api/test/fixtures/assets/template.json | 7 + .../test/fixtures/depends/manifest.json | 35 + .../test/fixtures/depends/template.json | 7 + .../cx-api/test/fixtures/empty/manifest.json | 3 + .../invalid-artifact-type/manifest.json | 9 + .../fixtures/invalid-depends/manifest.json | 35 + .../fixtures/invalid-depends/template.json | 7 + .../fixtures/invalid-env-format/manifest.json | 12 + .../fixtures/logical-id-map/manifest.json | 21 + .../fixtures/logical-id-map/template.json | 7 + .../test/fixtures/messages/manifest.json | 22 + .../test/fixtures/messages/template.json | 7 + .../fixtures/missing-context/manifest.json | 26 + .../fixtures/missing-context/template.json | 7 + .../fixtures/multiple-stacks/manifest.json | 19 + .../fixtures/multiple-stacks/template.2.json | 7 + .../fixtures/multiple-stacks/template.json | 7 + .../test/fixtures/single-stack/manifest.json | 12 + .../test/fixtures/single-stack/template.json | 7 + .../stack-without-params/manifest.json | 9 + packages/aws-cdk/bin/cdk.ts | 25 +- .../aws-cdk/lib/api/bootstrap-environment.ts | 14 +- .../aws-cdk/lib/api/cxapp/environments.ts | 14 +- packages/aws-cdk/lib/api/cxapp/exec.ts | 55 +- packages/aws-cdk/lib/api/cxapp/stacks.ts | 125 +- packages/aws-cdk/lib/api/deploy-stack.ts | 8 +- packages/aws-cdk/lib/api/deployment-target.ts | 8 +- packages/aws-cdk/lib/api/toolkit-info.ts | 2 +- .../cloudformation/stack-activity-monitor.ts | 2 +- packages/aws-cdk/lib/api/util/sdk.ts | 8 +- packages/aws-cdk/lib/assets.ts | 28 +- packages/aws-cdk/lib/diff.ts | 28 +- .../app/csharp/.template.gitignore | 1 + .../app/fsharp/.template.gitignore | 1 + .../app/java/.template.gitignore | 1 + .../app/javascript/.template.gitignore | 1 + .../app/javascript/.template.npmignore | 1 + .../lib/init-templates/app/python/.gitignore | 1 + .../app/typescript/.template.gitignore | 1 + .../app/typescript/.template.npmignore | 1 + .../lib/typescript/.template.gitignore | 1 + .../lib/typescript/.template.npmignore | 1 + .../sample-app/javascript/.template.gitignore | 1 + .../sample-app/javascript/.template.npmignore | 1 + .../sample-app/python/.gitignore | 1 + .../sample-app/typescript/.template.gitignore | 1 + .../sample-app/typescript/.template.npmignore | 1 + packages/aws-cdk/lib/interactive.ts | 53 - packages/aws-cdk/lib/renames.ts | 2 +- packages/aws-cdk/package.json | 2 - .../aws-cdk/test/api/test.deploy-stack.ts | 11 +- packages/aws-cdk/test/api/test.stacks.ts | 80 +- packages/aws-cdk/test/test.assets.ts | 103 +- packages/aws-cdk/test/test.diff.ts | 32 +- 88 files changed, 6643 insertions(+), 837 deletions(-) create mode 100644 packages/@aws-cdk/cx-api/jest.config.js create mode 100644 packages/@aws-cdk/cx-api/lib/assembly/cloud-artifact.ts create mode 100644 packages/@aws-cdk/cx-api/lib/assembly/cloud-assembly-api.ts create mode 100644 packages/@aws-cdk/cx-api/lib/assembly/cloud-assembly.ts create mode 100644 packages/@aws-cdk/cx-api/lib/assembly/cloudformation-stack.ts create mode 100644 packages/@aws-cdk/cx-api/lib/assembly/index.ts rename packages/{aws-cdk/lib/api/util => @aws-cdk/cx-api/lib/assembly}/toposort.ts (100%) delete mode 100644 packages/@aws-cdk/cx-api/lib/build.ts delete mode 100644 packages/@aws-cdk/cx-api/lib/environment.ts create mode 100644 packages/@aws-cdk/cx-api/test/__snapshots__/deploy.test.js.snap create mode 100644 packages/@aws-cdk/cx-api/test/deploy.test.ts create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/assets/asset-dir/foo.txt create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/assets/docker-asset/Dockerfile create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/assets/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/assets/template.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/depends/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/depends/template.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/empty/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/invalid-artifact-type/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/invalid-depends/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/invalid-depends/template.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/invalid-env-format/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/logical-id-map/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/logical-id-map/template.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/messages/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/messages/template.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/missing-context/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/missing-context/template.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/template.2.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/template.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/single-stack/manifest.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/single-stack/template.json create mode 100644 packages/@aws-cdk/cx-api/test/fixtures/stack-without-params/manifest.json delete mode 100644 packages/aws-cdk/lib/interactive.ts diff --git a/.gitignore b/.gitignore index 6dda408d30db0..f48cdeb4f0a8c 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ coverage/ # CDK Context & Staging files cdk.context.json .cdk.staging/ +cdk.out/ + diff --git a/packages/@aws-cdk/assert/jest.ts b/packages/@aws-cdk/assert/jest.ts index 03c5778750ad3..9ffd93a6fd5af 100644 --- a/packages/@aws-cdk/assert/jest.ts +++ b/packages/@aws-cdk/assert/jest.ts @@ -1,5 +1,5 @@ import { Stack } from "@aws-cdk/cdk"; -import { SynthesizedStack } from "@aws-cdk/cx-api"; +import { ICloudFormationStackArtifact } from "@aws-cdk/cx-api"; import { HaveResourceAssertion, ResourcePart } from "./lib/assertions/have-resource"; import { expect as ourExpect } from './lib/expect'; @@ -19,7 +19,7 @@ declare global { expect.extend({ toHaveResource( - actual: SynthesizedStack | Stack, + actual: ICloudFormationStackArtifact | Stack, resourceType: string, properties?: any, comparison?: ResourcePart) { @@ -28,7 +28,7 @@ expect.extend({ return assertHaveResource(assertion, actual); }, toHaveResourceLike( - actual: SynthesizedStack | Stack, + actual: ICloudFormationStackArtifact | Stack, resourceType: string, properties?: any, comparison?: ResourcePart) { @@ -38,7 +38,7 @@ expect.extend({ } }); -function assertHaveResource(assertion: HaveResourceAssertion, actual: SynthesizedStack | Stack) { +function assertHaveResource(assertion: HaveResourceAssertion, actual: ICloudFormationStackArtifact | Stack) { const inspector = ourExpect(actual); const pass = assertion.assertUsing(inspector); if (pass) { diff --git a/packages/@aws-cdk/assert/lib/expect.ts b/packages/@aws-cdk/assert/lib/expect.ts index 9fca81ff8e2f3..f96249215750b 100644 --- a/packages/@aws-cdk/assert/lib/expect.ts +++ b/packages/@aws-cdk/assert/lib/expect.ts @@ -4,10 +4,10 @@ import api = require('@aws-cdk/cx-api'); import { StackInspector } from './inspector'; import { SynthUtils } from './synth-utils'; -export function expect(stack: api.SynthesizedStack | cdk.Stack, skipValidation = false): StackInspector { +export function expect(stack: api.ICloudFormationStackArtifact | cdk.Stack, skipValidation = false): StackInspector { // Can't use 'instanceof' here, that breaks if we have multiple copies // of this library. - let sstack: api.SynthesizedStack; + let sstack: api.ICloudFormationStackArtifact; if (cdk.Stack.isStack(stack)) { const session = SynthUtils.synthesize(stack, { @@ -16,6 +16,14 @@ export function expect(stack: api.SynthesizedStack | cdk.Stack, skipValidation = sstack = { name: stack.name, + originalName: stack.name, + id: stack.name, + assets: [], + logicalIdToPathMap: { }, + autoDeploy: true, + depends: [], + messages: [], + missing: { }, template: SynthUtils.templateForStackName(session, stack.name), metadata: collectStackMetadata(stack.node), environment: { diff --git a/packages/@aws-cdk/assert/lib/inspector.ts b/packages/@aws-cdk/assert/lib/inspector.ts index d5e3315bc80ed..b04558310eb2f 100644 --- a/packages/@aws-cdk/assert/lib/inspector.ts +++ b/packages/@aws-cdk/assert/lib/inspector.ts @@ -27,7 +27,7 @@ export abstract class Inspector { } export class StackInspector extends Inspector { - constructor(public readonly stack: api.SynthesizedStack) { + constructor(public readonly stack: api.ICloudFormationStackArtifact) { super(); } @@ -46,7 +46,7 @@ export class StackInspector extends Inspector { } export class StackPathInspector extends Inspector { - constructor(public readonly stack: api.SynthesizedStack, public readonly path: string) { + constructor(public readonly stack: api.ICloudFormationStackArtifact, public readonly path: string) { super(); } diff --git a/packages/@aws-cdk/assert/test/test.assertions.ts b/packages/@aws-cdk/assert/test/test.assertions.ts index c59a96114e6e0..7f64929baab29 100644 --- a/packages/@aws-cdk/assert/test/test.assertions.ts +++ b/packages/@aws-cdk/assert/test/test.assertions.ts @@ -5,6 +5,7 @@ import cx = require('@aws-cdk/cx-api'); import { Test } from 'nodeunit'; import { Stack } from '@aws-cdk/cdk'; +import { CloudAssembly } from '@aws-cdk/cx-api'; import { countResources, exist, expect, haveType, MatchStyle, matchTemplate } from '../lib/index'; passingExample('expect at to have ', () => { @@ -205,11 +206,19 @@ function failingExample(title: string, cb: (test: Test) => void) { }; } -function synthesizedStack(fn: (stack: cdk.Stack) => void): cx.SynthesizedStack { +function synthesizedStack(fn: (stack: cdk.Stack) => void): cx.ICloudFormationStackArtifact { const app = new cdk.App(); const stack = new cdk.Stack(app, 'TestStack'); fn(stack); - return app.synthesizeStack(stack.name); + + const session = app.run(); + + const assembly = new CloudAssembly(session.outdir); + const s = assembly.stacks.find(x => x.name === stack.name); + if (!s) { + throw new Error(`Cannot find stack ${stack.name}`); + } + return s; } interface TestResourceProps extends cdk.CfnResourceProps { diff --git a/packages/@aws-cdk/assert/test/test.have-resource.ts b/packages/@aws-cdk/assert/test/test.have-resource.ts index 888a8a3147b3d..2c760f457563a 100644 --- a/packages/@aws-cdk/assert/test/test.have-resource.ts +++ b/packages/@aws-cdk/assert/test/test.have-resource.ts @@ -1,3 +1,4 @@ +import { ICloudFormationStackArtifact } from '@aws-cdk/cx-api'; import { Test } from 'nodeunit'; import { expect, haveResource } from '../lib/index'; @@ -89,9 +90,17 @@ export = { }, }; -function mkStack(template: any) { +function mkStack(template: any): ICloudFormationStackArtifact { return { name: 'test', + id: 'test', + originalName: 'test', + assets: [], + logicalIdToPathMap: { }, + missing: { }, + depends: [], + autoDeploy: true, + messages: [], template, metadata: {}, environment: { diff --git a/packages/@aws-cdk/assets/test/test.asset.ts b/packages/@aws-cdk/assets/test/test.asset.ts index 943945c230489..e6b35f1411515 100644 --- a/packages/@aws-cdk/assets/test/test.asset.ts +++ b/packages/@aws-cdk/assets/test/test.asset.ts @@ -3,6 +3,7 @@ import iam = require('@aws-cdk/aws-iam'); import cdk = require('@aws-cdk/cdk'); import { App, Stack } from '@aws-cdk/cdk'; import cxapi = require('@aws-cdk/cx-api'); +import { CloudAssembly } from '@aws-cdk/cx-api'; import fs = require('fs'); import { Test } from 'nodeunit'; import os = require('os'); @@ -57,7 +58,12 @@ export = { path: dirPath }); - const synth = app.synthesizeStack(stack.name); + const assembly = new CloudAssembly(app.run().outdir); + const synth = assembly.stacks.find(x => x.name === stack.name); + + if (!synth) { + throw new Error(`cannot find stack`); + } test.deepEqual(synth.metadata['/my-stack/MyAsset'][0].data, { path: 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 346d8db21781e..d092cbb1ef768 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -1,6 +1,4 @@ import cxapi = require('@aws-cdk/cx-api'); -import fs = require('fs'); -import path = require('path'); import { Construct } from './construct'; import { ISynthesisSession, Synthesizer } from './synthesis'; @@ -25,6 +23,18 @@ export interface AppProps { */ readonly outdir?: string; + /** + * Include stack traces in construct metadata entries. + * @default true stack traces are included + */ + readonly stackTraces?: boolean; + + /** + * Include runtime versioning information in cloud assembly manifest + * @default true runtime info is included + */ + readonly runtimeInfo?: boolean; + /** * Additional context values for the application * @@ -38,7 +48,6 @@ export interface AppProps { */ export class App extends Construct { private _session?: ISynthesisSession; - private readonly legacyManifest: boolean; private readonly runtimeInformation: boolean; private readonly outdir?: string; @@ -51,8 +60,15 @@ export class App extends Construct { this.loadContext(props.context); + if (props.stackTraces === false) { + this.node.setContext(cxapi.DISABLE_METADATA_STACK_TRACE, true); + } + + if (props.runtimeInfo === false) { + this.node.setContext(cxapi.DISABLE_VERSION_REPORTING, true); + } + // both are reverse logic - this.legacyManifest = this.node.getContext(cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT) ? false : true; this.runtimeInformation = this.node.getContext(cxapi.DISABLE_VERSION_REPORTING) ? false : true; this.outdir = props.outdir || process.env[cxapi.OUTDIR_ENV]; @@ -78,47 +94,12 @@ export class App extends Construct { this._session = synth.synthesize(this, { outdir: this.outdir, - legacyManifest: this.legacyManifest, runtimeInformation: this.runtimeInformation }); return this._session; } - /** - * Synthesize and validate a single stack. - * @param stackName The name of the stack to synthesize - * @deprecated This method is going to be deprecated in a future version of the CDK - */ - public synthesizeStack(stackName: string): cxapi.SynthesizedStack { - if (!this.legacyManifest) { - throw new Error('No legacy manifest available, return an old-style stack output'); - } - - const session = this.run(); - const legacyManifestFile = path.join(session.outdir, cxapi.OUTFILE_NAME); - const legacy: cxapi.SynthesizeResponse = JSON.parse(fs.readFileSync(legacyManifestFile, 'utf-8')); - - const res = legacy.stacks.find(s => s.name === stackName); - if (!res) { - throw new Error(`Stack "${stackName}" not found`); - } - - return res; - } - - /** - * Synthesizes multiple stacks - * @deprecated This method is going to be deprecated in a future version of the CDK - */ - public synthesizeStacks(stackNames: string[]): cxapi.SynthesizedStack[] { - const ret: cxapi.SynthesizedStack[] = []; - for (const stackName of stackNames) { - ret.push(this.synthesizeStack(stackName)); - } - return ret; - } - private loadContext(defaults: { [key: string]: string } = { }) { // prime with defaults passed through constructor for (const [ k, v ] of Object.entries(defaults)) { diff --git a/packages/@aws-cdk/cdk/lib/construct.ts b/packages/@aws-cdk/cdk/lib/construct.ts index c771e05d9e8af..3cffa4e8ad649 100644 --- a/packages/@aws-cdk/cdk/lib/construct.ts +++ b/packages/@aws-cdk/cdk/lib/construct.ts @@ -279,7 +279,11 @@ export class ConstructNode { if (data == null) { return; } - const trace = createStackTrace(from || this.addMetadata); + + const trace = this.getContext(cxapi.DISABLE_METADATA_STACK_TRACE) + ? [] + : createStackTrace(from || this.addMetadata); + this._metadata.push({ type, data, trace }); } diff --git a/packages/@aws-cdk/cdk/lib/stack.ts b/packages/@aws-cdk/cdk/lib/stack.ts index 8a97fee9f350d..df76ba3423d85 100644 --- a/packages/@aws-cdk/cdk/lib/stack.ts +++ b/packages/@aws-cdk/cdk/lib/stack.ts @@ -503,14 +503,16 @@ export class Stack extends Construct { const deps = this.dependencies().map(s => s.name); const meta = this.collectMetadata(); + const properties: cxapi.AwsCloudFormationStackProperties = { + templateFile: template, + parameters: Object.keys(this.parameterValues).length > 0 ? this.node.resolve(this.parameterValues) : undefined + }; + // add an artifact that represents this stack session.addArtifact(this.name, { type: cxapi.ArtifactType.AwsCloudFormationStack, environment: this.environment, - properties: { - templateFile: template, - parameters: Object.keys(this.parameterValues).length > 0 ? this.node.resolve(this.parameterValues) : undefined - }, + properties, autoDeploy: this.autoDeploy ? undefined : false, dependencies: deps.length > 0 ? deps : undefined, metadata: Object.keys(meta).length > 0 ? meta : undefined, diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index 580c295551284..e14d9c3dd60fe 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -14,7 +14,6 @@ export interface ISynthesisSession { readonly outdir: string; readonly manifest: cxapi.AssemblyManifest; addArtifact(id: string, droplet: cxapi.Artifact): void; - addBuildStep(id: string, step: cxapi.BuildStep): void; tryGetArtifact(id: string): cxapi.Artifact | undefined; getArtifact(id: string): cxapi.Artifact; } @@ -77,7 +76,6 @@ export class SynthesisSession implements ISynthesisSession { public readonly outdir: string; private readonly artifacts: { [id: string]: cxapi.Artifact } = { }; - private readonly buildSteps: { [id: string]: cxapi.BuildStep } = { }; private _manifest?: cxapi.AssemblyManifest; constructor(options: SynthesisOptions = { }) { @@ -112,15 +110,7 @@ export class SynthesisSession implements ISynthesisSession { return artifact; } - public addBuildStep(id: string, step: cxapi.BuildStep) { - if (id in this.buildSteps) { - throw new Error(`Build step ${id} already exists`); - } - this.buildSteps[id] = filterUndefined(step); - } - public close(options: ManifestOptions = { }): cxapi.AssemblyManifest { - const legacyManifest = options.legacyManifest !== undefined ? options.legacyManifest : false; const runtimeInfo = options.runtimeInformation !== undefined ? options.runtimeInformation : true; const manifest: cxapi.AssemblyManifest = this._manifest = filterUndefined({ @@ -132,75 +122,14 @@ export class SynthesisSession implements ISynthesisSession { const manifestFilePath = path.join(this.outdir, cxapi.MANIFEST_FILE); fs.writeFileSync(manifestFilePath, JSON.stringify(manifest, undefined, 2)); - // write build manifest if we have build steps - if (Object.keys(this.buildSteps).length > 0) { - const buildManifest: cxapi.BuildManifest = { - steps: this.buildSteps - }; - - const buildFilePath = path.join(this.outdir, cxapi.BUILD_FILE); - fs.writeFileSync(buildFilePath, JSON.stringify(buildManifest, undefined, 2)); - } - - if (legacyManifest) { - const legacy: cxapi.SynthesizeResponse = { - ...manifest, - stacks: renderLegacyStacks(manifest, this.outdir) - }; - - // render the legacy manifest (cdk.out) which also contains a "stacks" attribute with all the rendered stacks. - const legacyManifestPath = path.join(this.outdir, cxapi.OUTFILE_NAME); - fs.writeFileSync(legacyManifestPath, JSON.stringify(legacy, undefined, 2)); - } - return manifest; } } export interface ManifestOptions { - /** - * Emit the legacy manifest (`cdk.out`) when the session is closed (alongside `manifest.json`). - * @default false - */ - readonly legacyManifest?: boolean; - /** * Include runtime information (module versions) in manifest. * @default true */ readonly runtimeInformation?: boolean; } - -export function renderLegacyStacks(manifest: cxapi.AssemblyManifest, outdir: string) { - // special case for backwards compat. build a list of stacks for the manifest - const stacks = new Array(); - const artifacts = manifest.artifacts || { }; - - for (const [ id, artifact ] of Object.entries(artifacts)) { - if (artifact.type === cxapi.ArtifactType.AwsCloudFormationStack) { - const templateFile = artifact.properties && artifact.properties.templateFile; - if (!templateFile) { - throw new Error(`Invalid cloudformation artifact. Missing "template" property`); - } - const templateFilePath = path.join(outdir, templateFile); - const template = JSON.parse(fs.readFileSync(templateFilePath, 'utf-8')); - - const match = cxapi.AWS_ENV_REGEX.exec(artifact.environment); - if (!match) { - throw new Error(`"environment" must match regex: ${cxapi.AWS_ENV_REGEX}`); - } - - stacks.push(filterUndefined({ - name: id, - environment: { name: artifact.environment.substr('aws://'.length), account: match[1], region: match[2] }, - template, - metadata: artifact.metadata || {}, - autoDeploy: artifact.autoDeploy, - dependsOn: artifact.dependencies && artifact.dependencies.length > 0 ? artifact.dependencies : undefined, - missing: artifact.missing - })); - } - } - - return stacks; -} diff --git a/packages/@aws-cdk/cdk/test/test.app.ts b/packages/@aws-cdk/cdk/test/test.app.ts index d35cdd38ac6b0..288f2636825a0 100644 --- a/packages/@aws-cdk/cdk/test/test.app.ts +++ b/packages/@aws-cdk/cdk/test/test.app.ts @@ -1,23 +1,23 @@ import cxapi = require('@aws-cdk/cx-api'); -import fs = require('fs'); import { Test } from 'nodeunit'; -import path = require('path'); import { CfnResource, Construct, Stack, StackProps } from '../lib'; -import { App } from '../lib/app'; +import { App, AppProps } from '../lib/app'; -function withApp(context: { [key: string]: any } | undefined, block: (app: App) => void): cxapi.SynthesizeResponse { - const app = new App({ context }); +function withApp(props: AppProps, block: (app: App) => void): cxapi.CloudAssembly { + const app = new App({ + runtimeInfo: false, + stackTraces: false, + ...props, + }); block(app); const session = app.run(); - - // return the legacy manifest - return JSON.parse(fs.readFileSync(path.join(session.outdir, cxapi.OUTFILE_NAME), 'utf-8')); + return new cxapi.CloudAssembly(session.outdir); } -function synth(context?: { [key: string]: any }): cxapi.SynthesizeResponse { - return withApp(context, app => { +function synth(context?: { [key: string]: any }): cxapi.CloudAssembly { + return withApp({ context }, app => { const stack1 = new Stack(app, 'stack1', { env: { account: '12345', region: 'us-east-1' } }); new CfnResource(stack1, 's1c1', { type: 'DummyResource', properties: { Prop1: 'Prop1' } }); const r2 = new CfnResource(stack1, 's1c2', { type: 'DummyResource', properties: { Foo: 123 } }); @@ -35,7 +35,7 @@ function synth(context?: { [key: string]: any }): cxapi.SynthesizeResponse { }); } -function synthStack(name: string, includeMetadata: boolean = false, context?: any): cxapi.SynthesizedStack { +function synthStack(name: string, includeMetadata: boolean = false, context?: any): cxapi.ICloudFormationStackArtifact { const response = synth(context); const stack = response.stacks.find(s => s.name === name); if (!stack) { @@ -52,289 +52,257 @@ function synthStack(name: string, includeMetadata: boolean = false, context?: an export = { 'synthesizes all stacks and returns synthesis result'(test: Test) { const response = synth(); + delete (response as any).dir; + + test.deepEqual(response.stacks.length, 2); + + const stack1 = response.stacks[0]; + test.deepEqual(stack1.name, 'stack1'); + test.deepEqual(stack1.environment.account, 12345); + test.deepEqual(stack1.environment.region, 'us-east-1'); + test.deepEqual(stack1.environment.name, 'aws://12345/us-east-1'); + test.deepEqual(stack1.template, { Resources: + { s1c1: { Type: 'DummyResource', Properties: { Prop1: 'Prop1' } }, + s1c2: { Type: 'DummyResource', Properties: { Foo: 123 } } } }); + test.deepEqual(stack1.metadata, { + '/stack1': [{ type: 'meta', data: 111, trace: [] }], + '/stack1/s1c1': [{ type: 'aws:cdk:logicalId', data: 's1c1', trace: [] }], + '/stack1/s1c2': + [{ type: 'aws:cdk:logicalId', data: 's1c2', trace: [] }, + { type: 'aws:cdk:warning', data: 'warning1', trace: [] }, + { type: 'aws:cdk:warning', data: 'warning2', trace: [] }], + '/': [{ type: 'applevel', data: 123, trace: [] }] + }); - // clean up metadata so assertion will be sane - response.stacks.forEach(s => delete (s as any).metadata); - delete (response as any).runtime; - delete (response as any).artifacts; - - test.deepEqual(response, { - version: '0.19.0', - stacks: - [ { name: 'stack1', - environment: - { name: '12345/us-east-1', - account: '12345', - region: 'us-east-1' }, - template: - { Resources: - { s1c1: { Type: 'DummyResource', Properties: { Prop1: 'Prop1' } }, - s1c2: { Type: 'DummyResource', Properties: { Foo: 123 } } } } }, - { name: 'stack2', - environment: - { name: 'unknown-account/unknown-region', - account: 'unknown-account', - region: 'unknown-region' }, - template: - { Resources: - { s2c1: { Type: 'DummyResource', Properties: { Prog2: 'Prog2' } }, - s1c2r1D1791C01: { Type: 'ResourceType1' }, - s1c2r25F685FFF: { Type: 'ResourceType2' } } } } ] }); - test.done(); - }, - - 'synth(name) can be used programmatically'(test: Test) { - const prog = new App(); - const stack = new Stack(prog, 'MyStack'); - new CfnResource(stack, 'MyResource', { type: 'MyResourceType' }); - - test.throws(() => prog.synthesizeStacks(['foo']), /foo/); - - test.deepEqual(prog.synthesizeStack('MyStack').template, - { Resources: { MyResource: { Type: 'MyResourceType' } } }); - test.done(); - }, - - 'synth(name) also collects metadata from all constructs in the stack'(test: Test) { - const stack = synthStack('stack1', true); - - const output = stack.metadata; - stripStackTraces(output); - - test.ok(output['/'], 'app-level metadata is included under "."'); - test.equal(output['/'][0].type, 'applevel'); - test.equal(output['/'][0].data, 123); - - test.ok(output['/stack1'], 'the construct "stack1" has metadata'); - test.equal(output['/stack1'][0].type, 'meta'); - test.equal(output['/stack1'][0].data, 111); - test.ok(output['/stack1'][0].trace.length > 0, 'trace contains multiple entries'); - - test.ok(output['/stack1/s1c2']); - test.equal(output['/stack1/s1c2'].length, 2, 'two entries'); - test.equal(output['/stack1/s1c2'][0].data, 'warning1'); - - const stack2 = synthStack('stack2', true); - const output2 = stack2.metadata; - - test.ok(output2['/stack2/s1c2']); - test.equal(output2['/stack2/s1c2'][0].type, 'meta'); - test.deepEqual(output2['/stack2/s1c2'][0].data, { key: 'value' }); - - test.done(); - }, - - 'context can be passed through CDK_CONTEXT'(test: Test) { - process.env[cxapi.CONTEXT_ENV] = JSON.stringify({ - key1: 'val1', - key2: 'val2' + const stack2 = response.stacks[1]; + test.deepEqual(stack2.name, 'stack2'); + test.deepEqual(stack2.environment.name, 'aws://unknown-account/unknown-region'); + test.deepEqual(stack2.template, { Resources: + { s2c1: { Type: 'DummyResource', Properties: { Prog2: 'Prog2' } }, + s1c2r1D1791C01: { Type: 'ResourceType1' }, + s1c2r25F685FFF: { Type: 'ResourceType2' } } }); + test.deepEqual(stack2.metadata, { + '/stack2/s2c1': [{ type: 'aws:cdk:logicalId', data: 's2c1', trace: [] }], + '/stack2/s1c2': [{ type: 'meta', data: { key: 'value' }, trace: [] }], + '/stack2/s1c2/r1': + [{ type: 'aws:cdk:logicalId', data: 's1c2r1D1791C01', trace: [] }], + '/stack2/s1c2/r2': + [{ type: 'aws:cdk:logicalId', data: 's1c2r25F685FFF', trace: [] }], + '/': [{ type: 'applevel', data: 123, trace: [] }] }); - const prog = new App(); - test.deepEqual(prog.node.getContext('key1'), 'val1'); - test.deepEqual(prog.node.getContext('key2'), 'val2'); - test.done(); - }, - 'context from the command line can be used when creating the stack'(test: Test) { - const output = synthStack('stack2', false, { ctx1: 'HELLO' }); + test.done(); +}, - test.deepEqual(output.template, { - Resources: { - s2c1: { +'context can be passed through CDK_CONTEXT'(test: Test) { + process.env[cxapi.CONTEXT_ENV] = JSON.stringify({ + key1: 'val1', + key2: 'val2' + }); + const prog = new App(); + test.deepEqual(prog.node.getContext('key1'), 'val1'); + test.deepEqual(prog.node.getContext('key2'), 'val2'); + test.done(); +}, + +'context from the command line can be used when creating the stack'(test: Test) { + const output = synthStack('stack2', false, { ctx1: 'HELLO' }); + + test.deepEqual(output.template, { + Resources: { + s2c1: { Type: "DummyResource", Properties: { Prog2: "Prog2" } - }, - s1c2r1D1791C01: { + }, + s1c2r1D1791C01: { Type: "ResourceType1" - }, - s1c2r25F685FFF: { + }, + s1c2r25F685FFF: { Type: "ResourceType2", Properties: { FromContext: "HELLO" } - } - } - }); - test.done(); - }, - - 'setContext(k,v) can be used to set context programmatically'(test: Test) { - const prog = new App(); - prog.node.setContext('foo', 'bar'); - test.deepEqual(prog.node.getContext('foo'), 'bar'); - test.done(); - }, - - 'setContext(k,v) cannot be called after stacks have been added because stacks may use the context'(test: Test) { - const prog = new App(); - new Stack(prog, 's1'); - test.throws(() => prog.node.setContext('foo', 'bar')); - test.done(); - }, - - 'app.synthesizeStack(stack) performs validation first (app.validateAll()) and if there are errors, it returns the errors'(test: Test) { - - class Child extends Construct { - protected validate() { - return [ `Error from ${this.node.id}` ]; } } + }); + test.done(); +}, + +'setContext(k,v) can be used to set context programmatically'(test: Test) { + const prog = new App(); + prog.node.setContext('foo', 'bar'); + test.deepEqual(prog.node.getContext('foo'), 'bar'); + test.done(); +}, + +'setContext(k,v) cannot be called after stacks have been added because stacks may use the context'(test: Test) { + const prog = new App(); + new Stack(prog, 's1'); + test.throws(() => prog.node.setContext('foo', 'bar')); + test.done(); +}, + +'app.run() performs validation first and if there are errors, it returns the errors'(test: Test) { + + class Child extends Construct { + protected validate() { + return [`Error from ${this.node.id}`]; + } + } - class Parent extends Stack { + class Parent extends Stack { - } + } - const app = new App(); + const app = new App(); - const parent = new Parent(app, 'Parent'); - new Child(parent, 'C1'); - new Child(parent, 'C2'); + const parent = new Parent(app, 'Parent'); + new Child(parent, 'C1'); + new Child(parent, 'C2'); - test.throws(() => { - app.synthesizeStacks(['Parent']); - }, /Validation failed with the following errors/); + test.throws(() => app.run(), /Validation failed with the following errors/); - test.done(); - }, - - 'app.synthesizeStack(stack) will return a list of missing contextual information'(test: Test) { - class MyStack extends Stack { - constructor(scope: App, id: string, props?: StackProps) { - super(scope, id, props); - - this.reportMissingContext('missing-context-key', { - provider: 'fake', - props: { - account: '12345689012', - region: 'ab-north-1', - }, - }, - ); - - this.reportMissingContext('missing-context-key-2', { - provider: 'fake2', - props: { - foo: 'bar', - account: '12345689012', - region: 'ab-south-1', - }, - }, - ); - } - } + test.done(); +}, - const response = withApp(undefined, app => { - new MyStack(app, 'MyStack'); - }); +'app.synthesizeStack(stack) will return a list of missing contextual information'(test: Test) { + class MyStack extends Stack { + constructor(scope: App, id: string, props?: StackProps) { + super(scope, id, props); - test.deepEqual(response.stacks[0].missing, { - "missing-context-key": { + this.reportMissingContext('missing-context-key', { provider: 'fake', props: { account: '12345689012', region: 'ab-north-1', }, }, - "missing-context-key-2": { + ); + + this.reportMissingContext('missing-context-key-2', { provider: 'fake2', props: { + foo: 'bar', account: '12345689012', region: 'ab-south-1', - foo: 'bar', }, }, - }); + ); + } + } - test.done(); - }, + const response = withApp({}, app => { + new MyStack(app, 'MyStack'); + }); - 'runtime library versions disabled'(test: Test) { - const context: any = {}; - context[cxapi.DISABLE_VERSION_REPORTING] = true; + test.deepEqual(response.stacks[0].missing, { + "missing-context-key": { + provider: 'fake', + props: { + account: '12345689012', + region: 'ab-north-1', + }, + }, + "missing-context-key-2": { + provider: 'fake2', + props: { + account: '12345689012', + region: 'ab-south-1', + foo: 'bar', + }, + }, + }); - const response = withApp(context, app => { - const stack = new Stack(app, 'stack1'); - new CfnResource(stack, 'MyResource', { type: 'Resource::Type' }); - }); + test.done(); +}, - test.equals(response.runtime, undefined); - test.done(); - }, +'runtime library versions disabled'(test: Test) { + const context: any = {}; + context[cxapi.DISABLE_VERSION_REPORTING] = true; - 'runtime library versions'(test: Test) { - const response = withApp({}, app => { - const stack = new Stack(app, 'stack1'); - new CfnResource(stack, 'MyResource', { type: 'Resource::Type' }); - }); + const response = withApp(context, app => { + const stack = new Stack(app, 'stack1'); + new CfnResource(stack, 'MyResource', { type: 'Resource::Type' }); + }); - const libs = (response.runtime && response.runtime.libraries) || { }; + test.deepEqual(response.runtime, { libraries: {} }); + test.done(); +}, - const version = require('../package.json').version; - test.deepEqual(libs['@aws-cdk/cdk'], version); - test.deepEqual(libs['@aws-cdk/cx-api'], version); - test.deepEqual(libs['jsii-runtime'], `node.js/${process.version}`); - test.done(); - }, +'runtime library versions'(test: Test) { + const response = withApp({ runtimeInfo: true }, app => { + const stack = new Stack(app, 'stack1'); + new CfnResource(stack, 'MyResource', { type: 'Resource::Type' }); + }); - 'jsii-runtime version loaded from JSII_AGENT'(test: Test) { - process.env.JSII_AGENT = 'Java/1.2.3.4'; + const libs = (response.runtime && response.runtime.libraries) || {}; - const response = withApp({}, app => { - const stack = new Stack(app, 'stack1'); - new CfnResource(stack, 'MyResource', { type: 'Resource::Type' }); - }); + const version = require('../package.json').version; + test.deepEqual(libs['@aws-cdk/cdk'], version); + test.deepEqual(libs['@aws-cdk/cx-api'], version); + test.deepEqual(libs['jsii-runtime'], `node.js/${process.version}`); + test.done(); +}, - const libs = (response.runtime && response.runtime.libraries) || { }; - test.deepEqual(libs['jsii-runtime'], `Java/1.2.3.4`); +'jsii-runtime version loaded from JSII_AGENT'(test: Test) { + process.env.JSII_AGENT = 'Java/1.2.3.4'; - delete process.env.JSII_AGENT; - test.done(); - }, + const response = withApp({ runtimeInfo: true }, app => { + const stack = new Stack(app, 'stack1'); + new CfnResource(stack, 'MyResource', { type: 'Resource::Type' }); + }); - 'version reporting includes only @aws-cdk, aws-cdk and jsii libraries'(test: Test) { - const response = withApp({}, app => { - const stack = new Stack(app, 'stack1'); - new CfnResource(stack, 'MyResource', { type: 'Resource::Type' }); - }); + const libs = (response.runtime && response.runtime.libraries) || {}; + test.deepEqual(libs['jsii-runtime'], `Java/1.2.3.4`); - const libs = (response.runtime && response.runtime.libraries) || { }; + delete process.env.JSII_AGENT; + test.done(); +}, - const version = require('../package.json').version; - test.deepEqual(libs, { - '@aws-cdk/cdk': version, - '@aws-cdk/cx-api': version, - 'jsii-runtime': `node.js/${process.version}` - }); +'version reporting includes only @aws-cdk, aws-cdk and jsii libraries'(test: Test) { + const response = withApp({ runtimeInfo: true }, app => { + const stack = new Stack(app, 'stack1'); + new CfnResource(stack, 'MyResource', { type: 'Resource::Type' }); + }); - test.done(); - }, + const libs = (response.runtime && response.runtime.libraries) || {}; - 'deep stack is shown and synthesized properly'(test: Test) { - // WHEN - const response = withApp(undefined, (app) => { - const topStack = new Stack(app, 'Stack'); - const topResource = new CfnResource(topStack, 'Res', { type: 'CDK::TopStack::Resource' }); + const version = require('../package.json').version; + test.deepEqual(libs, { + '@aws-cdk/cdk': version, + '@aws-cdk/cx-api': version, + 'jsii-runtime': `node.js/${process.version}` + }); - const bottomStack = new Stack(topResource, 'Stack'); - new CfnResource(bottomStack, 'Res', { type: 'CDK::BottomStack::Resource' }); - }); + test.done(); +}, - // THEN - test.deepEqual(response.stacks.map(s => ({ name: s.name, template: s.template })), [ - { - name: 'StackResStack7E4AFA86', - template: { Resources: { Res: { Type: 'CDK::BottomStack::Resource' } } }, - }, - { - name: 'Stack', - template: { Resources: { Res: { Type: 'CDK::TopStack::Resource' } } }, - } - ]); +'deep stack is shown and synthesized properly'(test: Test) { + // WHEN + const response = withApp({}, (app) => { + const topStack = new Stack(app, 'Stack'); + const topResource = new CfnResource(topStack, 'Res', { type: 'CDK::TopStack::Resource' }); - test.done(); - }, + const bottomStack = new Stack(topResource, 'Stack'); + new CfnResource(bottomStack, 'Res', { type: 'CDK::BottomStack::Resource' }); + }); + + // THEN + test.deepEqual(response.stacks.map(s => ({ name: s.name, template: s.template })), [ + { + name: 'Stack', + template: { Resources: { Res: { Type: 'CDK::TopStack::Resource' } } }, + }, + { + name: 'StackResStack7E4AFA86', + template: { Resources: { Res: { Type: 'CDK::BottomStack::Resource' } } }, + }, + ]); + + test.done(); +}, }; class MyConstruct extends Construct { @@ -345,12 +313,3 @@ class MyConstruct extends Construct { new CfnResource(this, 'r2', { type: 'ResourceType2', properties: { FromContext: this.node.getContext('ctx1') } }); } } - -/** - * Strip stack traces from metadata - */ -function stripStackTraces(meta: cxapi.StackMetadata) { - for (const key of Object.keys(meta)) { - meta[key] = meta[key].filter(entry => entry.type !== 'aws:cdk:logicalId'); - } -} diff --git a/packages/@aws-cdk/cdk/test/test.context.ts b/packages/@aws-cdk/cdk/test/test.context.ts index 20ccfd16a6ea5..4aee7d0d519eb 100644 --- a/packages/@aws-cdk/cdk/test/test.context.ts +++ b/packages/@aws-cdk/cdk/test/test.context.ts @@ -101,10 +101,11 @@ export = { test.deepEqual(new AvailabilityZoneProvider(stack).availabilityZones, [ 'dummy1a', 'dummy1b', 'dummy1c' ]); test.deepEqual(new SSMParameterProvider(child, {parameterName: 'foo'}).parameterValue(), 'dummy'); - const output = app.synthesizeStack(stack.name); - - const azError: MetadataEntry | undefined = output.metadata['/test-stack'].find(x => x.type === cxapi.ERROR_METADATA_KEY); - const ssmError: MetadataEntry | undefined = output.metadata['/test-stack/ChildConstruct'].find(x => x.type === cxapi.ERROR_METADATA_KEY); + const session = app.run(); + const output = session.getArtifact('test-stack'); + const metadata = output.metadata || { }; + const azError: MetadataEntry | undefined = metadata['/test-stack'].find(x => x.type === cxapi.ERROR_METADATA_KEY); + const ssmError: MetadataEntry | undefined = metadata['/test-stack/ChildConstruct'].find(x => x.type === cxapi.ERROR_METADATA_KEY); test.ok(azError && (azError.data as string).includes('Cannot determine scope for context provider availability-zones')); test.ok(ssmError && (ssmError.data as string).includes('Cannot determine scope for context provider ssm')); diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index 63e1448fb629e..e59e6959efde6 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -11,7 +11,6 @@ const storeTestMatrix: any = {}; function createModernApp() { return new cdk.App({ context: { - [cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT]: 'true', [cxapi.DISABLE_VERSION_REPORTING]: 'true', // for test reproducibility } }); @@ -79,7 +78,7 @@ export = { ]); test.deepEqual(readJson(session.outdir, 'foo.json'), { bar: 123 }); test.deepEqual(session.manifest, { - version: '0.19.0', + version: '0.31.0', artifacts: { 'my-random-construct': { type: 'aws:cloudformation:stack', @@ -96,37 +95,6 @@ export = { test.done(); }, - 'backwards compatibility: cdk.out contains all synthesized stacks'(test: Test) { - // GIVEN - const app = new cdk.App(); - const stack1 = new cdk.Stack(app, 'stack1'); - new cdk.CfnResource(stack1, 'Resource1', { type: 'AWS::CDK::Resource' }); - new cdk.CfnResource(stack1, 'Resource2', { type: 'AWS::CDK::Resource' }); - const stack2 = new cdk.Stack(app, 'stack2'); - new cdk.CfnResource(stack2, 'ResourceA', { type: 'AWS::CDK::Resource' }); - - // WHEN - const session = app.run(); - const legacy: cxapi.SynthesizeResponse = readJson(session.outdir, cxapi.OUTFILE_NAME); - - // THEN - const t1 = legacy.stacks.find(s => s.name === 'stack1')!.template; - const t2 = legacy.stacks.find(s => s.name === 'stack2')!.template; - - test.deepEqual(t1, { - Resources: { - Resource1: { Type: 'AWS::CDK::Resource' }, - Resource2: { Type: 'AWS::CDK::Resource' } - } - }); - test.deepEqual(t2, { - Resources: { - ResourceA: { Type: 'AWS::CDK::Resource' } - } - }); - test.done(); - }, - 'it should be possible to synthesize without an app'(test: Test) { const calls = new Array(); @@ -188,7 +156,7 @@ const storeTests = { environment: 'aws://1222344/us-east-1', dependencies: ['a', 'b'], metadata: { - foo: { bar: 123 } + foo: [ { data: 123, type: 'foo', trace: [] } ] }, properties: { templateFile, @@ -239,7 +207,7 @@ const storeTests = { type: 'aws:cloudformation:stack', environment: 'aws://1222344/us-east-1', dependencies: ['a', 'b'], - metadata: { foo: { bar: 123 } }, + metadata: { foo: [ { data: 123, type: 'foo', trace: [] } ] }, properties: { templateFile: 'foo.template.json', parameters: { @@ -288,35 +256,6 @@ const storeTests = { }); test.done(); }, - - 'addBuildStep can be used to produce build.json'(test: Test) { - // GIVEN - const app = createModernApp(); - - // WHEN - class BuildMe extends cdk.Construct implements cdk.ISynthesizable { - public synthesize(s: cdk.ISynthesisSession) { - s.addBuildStep('step_id', { - type: 'build-step-type', - parameters: { - boom: 123 - } - }); - } - } - - new BuildMe(app, 'hey'); - - // THEN - const session = app.run(); - test.deepEqual(list(session.outdir), [ 'build.json', 'manifest.json' ]); - test.deepEqual(readJson(session.outdir, 'build.json'), { - steps: { - step_id: { type: 'build-step-type', parameters: { boom: 123 } } - } - }); - test.done(); - } }; for (const [name, fn] of Object.entries(storeTests)) { diff --git a/packages/@aws-cdk/cx-api/.gitignore b/packages/@aws-cdk/cx-api/.gitignore index 7cc4e93cbf77b..aa27a447d1de9 100644 --- a/packages/@aws-cdk/cx-api/.gitignore +++ b/packages/@aws-cdk/cx-api/.gitignore @@ -9,4 +9,7 @@ tslint.json .LAST_BUILD .LAST_PACKAGE -*.snk \ No newline at end of file +*.snk +.nyc_output +coverage +.nycrc \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/jest.config.js b/packages/@aws-cdk/cx-api/jest.config.js new file mode 100644 index 0000000000000..31ffb09bc460e --- /dev/null +++ b/packages/@aws-cdk/cx-api/jest.config.js @@ -0,0 +1,180 @@ +// For a detailed explanation regarding each configuration property, visit: +// https://jestjs.io/docs/en/configuration.html + +module.exports = { + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // Respect "browser" field in package.json when resolving modules + // browser: false, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "/private/var/folders/n2/6v4_tbz97ws0h4bn5gbyvzb0m8vcjb/T/jest_b92skr", + + // Automatically clear mock calls and instances between every test + // clearMocks: false, + + // Indicates whether the coverage information should be collected while executing the test + // collectCoverage: false, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: null, + + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "/node_modules/" + // ], + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: null, + + // A path to a custom dependency extractor + // dependencyExtractor: null, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: null, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: null, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + moduleFileExtensions: [ + "js" + ], + + // A map from regular expressions to module names that allow to stub out resources with a single module + // moduleNameMapper: {}, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + // preset: null, + + // Run tests from one or more projects + // projects: null, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state between every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: null, + + // Automatically restore mock state between every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: null, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + testEnvironment: "node", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + // testMatch: [ + // "**/__tests__/**/*.[jt]s?(x)", + // "**/?(*.)+(spec|test).[tj]s?(x)" + // ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "/node_modules/" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: null, + + // This option allows use of a custom test runner + // testRunner: "jasmine2", + + // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href + // testURL: "http://localhost", + + // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" + // timers: "real", + + // A map from regular expressions to paths to transformers + // transform: null, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "/node_modules/" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: null, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; diff --git a/packages/@aws-cdk/cx-api/lib/artifacts.ts b/packages/@aws-cdk/cx-api/lib/artifacts.ts index ce59da7d077db..a178e00b572c2 100644 --- a/packages/@aws-cdk/cx-api/lib/artifacts.ts +++ b/packages/@aws-cdk/cx-api/lib/artifacts.ts @@ -1,3 +1,5 @@ +import { MetadataEntry } from './cxapi'; + export const AWS_ENV_REGEX = /aws\:\/\/([0-9]+|unknown-account)\/([a-z\-0-9]+)/; export enum ArtifactType { @@ -9,13 +11,18 @@ export enum ArtifactType { export interface Artifact { readonly type: ArtifactType; readonly environment: string; // format: aws://account/region - readonly metadata?: { [path: string]: any }; + readonly metadata?: { [path: string]: MetadataEntry[] }; readonly dependencies?: string[]; readonly missing?: { [key: string]: any }; readonly properties?: { [name: string]: any }; readonly autoDeploy?: boolean; } +export interface AwsCloudFormationStackProperties { + readonly templateFile: string; + readonly parameters?: { [id: string]: string }; +} + export function validateArtifact(artifcat: Artifact) { if (!AWS_ENV_REGEX.test(artifcat.environment)) { throw new Error(`Artifact "environment" must conform to ${AWS_ENV_REGEX}: ${artifcat.environment}`); diff --git a/packages/@aws-cdk/cx-api/lib/assembly/cloud-artifact.ts b/packages/@aws-cdk/cx-api/lib/assembly/cloud-artifact.ts new file mode 100644 index 0000000000000..362d11854a495 --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/assembly/cloud-artifact.ts @@ -0,0 +1,96 @@ +import { Artifact, ArtifactType } from '../artifacts'; +import { ERROR_METADATA_KEY, INFO_METADATA_KEY, MetadataEntry, MissingContext, WARNING_METADATA_KEY } from '../cxapi'; +import { CloudAssembly } from './cloud-assembly'; +import { Environment, ICloudArtifact, SynthesisMessage, SynthesisMessageLevel } from './cloud-assembly-api'; + +const ENVIRONMENT_PARSER = /aws:\/\/([0-9a-z\-]+)\/([a-z\-0-9]+)/; + +export class CloudArtifact implements ICloudArtifact { + public static from(assembly: CloudAssembly, name: string, artifact: Artifact): CloudArtifact { + switch (artifact.type) { + case ArtifactType.AwsCloudFormationStack: + return new CloudFormationStackArtifact(assembly, name, artifact); + + default: + throw new Error(`unsupported artifact type: ${artifact.type}`); + } + } + + public readonly missing: { [key: string]: MissingContext }; + public readonly autoDeploy: boolean; + public readonly messages: SynthesisMessage[]; + public readonly environment: Environment; + public readonly metadata: { [path: string]: MetadataEntry[] }; + public readonly dependsIDs: string[]; + + private _deps?: ICloudArtifact[]; // cache + + constructor(protected readonly assembly: CloudAssembly, public readonly id: string, artifact: Artifact) { + this.missing = artifact.missing || { }; + + this.environment = parseEnvironment(artifact.environment, id); + this.autoDeploy = artifact.autoDeploy === undefined ? true : artifact.autoDeploy; + this.metadata = artifact.metadata || { }; + this.messages = this.renderMessages(); + this.dependsIDs = artifact.dependencies || []; + } + + public get depends(): ICloudArtifact[] { + if (this._deps) { return this._deps; } + + this._deps = this.dependsIDs.map(id => { + const dep = this.assembly.artifacts.find(a => a.id === id); + if (!dep) { + throw new Error(`Artifact ${this.id} depends on non-existing artifact ${id}`); + } + return dep; + }); + + return this._deps; + } + + private renderMessages() { + const messages = new Array(); + + for (const [ id, metadata ] of Object.entries(this.metadata)) { + for (const entry of metadata) { + let level: SynthesisMessageLevel; + switch (entry.type) { + case WARNING_METADATA_KEY: + level = SynthesisMessageLevel.WARNING; + break; + case ERROR_METADATA_KEY: + level = SynthesisMessageLevel.ERROR; + break; + case INFO_METADATA_KEY: + level = SynthesisMessageLevel.INFO; + break; + default: + continue; + } + + messages.push({ level, entry, id }); + } + } + + return messages; + } +} + +function parseEnvironment(environment: string, artifactId: string): Environment { + const env = ENVIRONMENT_PARSER.exec(environment); + if (!env) { + throw new Error( + `Unable to parse environment specification "${environment}" for artifact ${artifactId}. ` + + `Expected format: aws://acount/region`); + } + + const [ , account, region ] = env; + if (!account || !region) { + throw new Error(`Invalid environment specification: ${environment}`); + } + + return { account, region, name: environment }; +} + +import { CloudFormationStackArtifact } from './cloudformation-stack'; diff --git a/packages/@aws-cdk/cx-api/lib/assembly/cloud-assembly-api.ts b/packages/@aws-cdk/cx-api/lib/assembly/cloud-assembly-api.ts new file mode 100644 index 0000000000000..622ecccd2d34f --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/assembly/cloud-assembly-api.ts @@ -0,0 +1,55 @@ +import { AppRuntime, MetadataEntry, MissingContext } from '../cxapi'; +import { AssetMetadataEntry } from '../metadata/assets'; + +export interface ICloudAssembly { + readonly directory: string; + readonly version: string; + readonly missing?: { [key: string]: MissingContext }; + readonly runtime: AppRuntime; + readonly artifacts: ICloudArtifact[]; + readonly stacks: ICloudFormationStackArtifact[]; +} + +export interface ICloudArtifact { + readonly id: string; + readonly environment: Environment; + readonly metadata: { [path: string]: MetadataEntry[] }; + readonly missing: { [key: string]: MissingContext }; + readonly autoDeploy: boolean; + readonly depends: ICloudArtifact[]; + readonly messages: SynthesisMessage[]; +} + +export interface SynthesisMessage { + readonly level: SynthesisMessageLevel; + readonly id: string; + readonly entry: MetadataEntry; +} + +export enum SynthesisMessageLevel { + INFO = 'info', + WARNING = 'warning', + ERROR = 'error' +} + +export interface ICloudFormationStackArtifact extends ICloudArtifact { + name: string; + readonly originalName: string; + readonly template: any; + readonly assets: AssetMetadataEntry[]; + readonly logicalIdToPathMap: { [logicalId: string]: string }; +} + +/** + * Models an AWS execution environment, for use within the CDK toolkit. + */ +export interface Environment { + /** The arbitrary name of this environment (user-set, or at least user-meaningful) */ + readonly name: string; + + /** The 12-digit AWS account ID for the account this environment deploys into */ + readonly account: string; + + /** The AWS region name where this environment deploys into */ + readonly region: string; +} diff --git a/packages/@aws-cdk/cx-api/lib/assembly/cloud-assembly.ts b/packages/@aws-cdk/cx-api/lib/assembly/cloud-assembly.ts new file mode 100644 index 0000000000000..2652d0214c08f --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/assembly/cloud-assembly.ts @@ -0,0 +1,105 @@ +import fs = require('fs'); +import path = require('path'); +import semver = require('semver'); +import { AppRuntime, AssemblyManifest, MANIFEST_FILE, MissingContext, PROTO_RESPONSE_VERSION } from '../cxapi'; +import { CloudArtifact } from './cloud-artifact'; +import { ICloudArtifact, ICloudAssembly, ICloudFormationStackArtifact } from './cloud-assembly-api'; +import { CloudFormationStackArtifact } from './cloudformation-stack'; +import { topologicalSort } from './toposort'; + +export class CloudAssembly implements ICloudAssembly { + public readonly artifacts: ICloudArtifact[]; + public readonly version: string; + public readonly missing?: { [key: string]: MissingContext }; + public readonly runtime: AppRuntime; + + private readonly manifest: AssemblyManifest; + + constructor(public readonly directory: string) { + this.manifest = this.readJson(MANIFEST_FILE); + + this.version = this.manifest.version; + verifyManifestVersion(this.manifest.version); + + this.artifacts = this.renderArtifacts(); + this.missing = this.renderMissing(); + this.runtime = this.manifest.runtime || { libraries: { } }; + + // force validation of deps by accessing 'depends' on all artifacts + this.validateDeps(); + } + + public readJson(filePath: string) { + return JSON.parse(fs.readFileSync(path.join(this.directory, filePath), 'utf-8')); + } + + public get stacks(): ICloudFormationStackArtifact[] { + const result = new Array(); + for (const a of this.artifacts) { + if (a instanceof CloudFormationStackArtifact) { + result.push(a); + } + } + return result; + } + + private validateDeps() { + for (const artifact of this.artifacts) { + ignore(artifact.depends); + } + } + + private renderArtifacts() { + const result = new Array(); + for (const [ name, artifact ] of Object.entries(this.manifest.artifacts || { })) { + result.push(CloudArtifact.from(this, name, artifact)); + } + + return topologicalSort(result, x => x.id, x => x.dependsIDs); + } + + private renderMissing() { + const missing: { [key: string]: MissingContext } = { }; + for (const artifact of this.artifacts) { + for (const [ key, m ] of Object.entries(artifact.missing)) { + missing[key] = m; + } + } + + return Object.keys(missing).length > 0 ? missing : undefined; + } +} + +/** + * Look at the type of response we get and upgrade it to the latest expected version + */ +function verifyManifestVersion(version?: string) { + if (!version) { + // tslint:disable-next-line:max-line-length + throw new Error(`CDK Framework >= ${PROTO_RESPONSE_VERSION} is required in order to interact with this version of the Toolkit.`); + } + + const frameworkVersion = semver.coerce(version); + const toolkitVersion = semver.coerce(PROTO_RESPONSE_VERSION); + + // Should not happen, but I don't trust this library 100% either, so let's check for it to be safe + if (!frameworkVersion || !toolkitVersion) { throw new Error('SemVer library could not parse versions'); } + + if (semver.gt(frameworkVersion, toolkitVersion)) { + throw new Error(`CDK Toolkit >= ${version} is required in order to interact with this program.`); + } + + if (semver.lt(frameworkVersion, toolkitVersion)) { + // Toolkit protocol is newer than the framework version, and we KNOW the + // version. This is a scenario in which we could potentially do some + // upgrading of the response in the future. + // + // For now though, we simply reject old responses. + throw new Error(`Cloud assembly created by CDK version ${frameworkVersion} but it must be >= ${PROTO_RESPONSE_VERSION} ` + + `in order to interact with this version of the toolkit (${toolkitVersion}).`); + } +} + +function ignore(_x: any) { + return; +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/lib/assembly/cloudformation-stack.ts b/packages/@aws-cdk/cx-api/lib/assembly/cloudformation-stack.ts new file mode 100644 index 0000000000000..587a0fb082c3d --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/assembly/cloudformation-stack.ts @@ -0,0 +1,57 @@ +import { Artifact, AwsCloudFormationStackProperties } from '../artifacts'; +import { ASSET_METADATA, AssetMetadataEntry } from '../metadata/assets'; +import { CloudArtifact } from './cloud-artifact'; +import { CloudAssembly } from './cloud-assembly'; +import { ICloudFormationStackArtifact } from './cloud-assembly-api'; + +export class CloudFormationStackArtifact extends CloudArtifact implements ICloudFormationStackArtifact { + public readonly template: any; + public readonly originalName: string; + public readonly logicalIdToPathMap: { [logicalId: string]: string }; + public readonly assets: AssetMetadataEntry[]; + + public name: string; + + constructor(assembly: CloudAssembly, name: string, artifact: Artifact) { + super(assembly, name, artifact); + + if (!artifact.properties) { + throw new Error(`Invalid CloudFormation stack artifact. Missing properties`); + } + + const properties = artifact.properties as AwsCloudFormationStackProperties; + this.template = this.assembly.readJson(properties.templateFile); + this.originalName = name; + this.name = this.originalName; + this.logicalIdToPathMap = this.buildLogicalToPathMap(); + this.assets = this.buildAssets(); + } + + private buildAssets() { + const assets = new Array(); + + for (const k of Object.keys(this.metadata)) { + for (const entry of this.metadata[k]) { + if (entry.type === ASSET_METADATA) { + assets.push(entry.data); + } + } + } + + return assets; + } + + private buildLogicalToPathMap() { + const map: { [id: string]: string } = {}; + for (const cpath of Object.keys(this.metadata)) { + const md = this.metadata[cpath]; + for (const e of md) { + if (e.type === 'aws:cdk:logicalId') { + const logical = e.data; + map[logical] = cpath; + } + } + } + return map; + } +} diff --git a/packages/@aws-cdk/cx-api/lib/assembly/index.ts b/packages/@aws-cdk/cx-api/lib/assembly/index.ts new file mode 100644 index 0000000000000..65f15e2b0323a --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/assembly/index.ts @@ -0,0 +1,2 @@ +export * from './cloud-assembly'; +export * from './cloud-assembly-api'; diff --git a/packages/aws-cdk/lib/api/util/toposort.ts b/packages/@aws-cdk/cx-api/lib/assembly/toposort.ts similarity index 100% rename from packages/aws-cdk/lib/api/util/toposort.ts rename to packages/@aws-cdk/cx-api/lib/assembly/toposort.ts diff --git a/packages/@aws-cdk/cx-api/lib/build.ts b/packages/@aws-cdk/cx-api/lib/build.ts deleted file mode 100644 index 4b5ec14188ed5..0000000000000 --- a/packages/@aws-cdk/cx-api/lib/build.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface BuildStep { - readonly type: string; - readonly depends?: string[]; - readonly parameters: { - [key: string]: any - }; -} - -export interface BuildManifest { - readonly steps: { [id: string]: BuildStep }; -} - -export enum BuildStepType { - CopyFile = 'copy-file', - ZipDirectory = 'zip-directory' -} diff --git a/packages/@aws-cdk/cx-api/lib/cxapi.ts b/packages/@aws-cdk/cx-api/lib/cxapi.ts index 25801c004ea68..55518dbde2c58 100644 --- a/packages/@aws-cdk/cx-api/lib/cxapi.ts +++ b/packages/@aws-cdk/cx-api/lib/cxapi.ts @@ -3,7 +3,6 @@ */ import { Artifact } from './artifacts'; -import { Environment } from './environment'; /** * Bump this to the library version if and only if the CX protocol changes. @@ -21,18 +20,13 @@ import { Environment } from './environment'; * updated (as the current verison in package.json has already been released!) * - The request does not have versioning yet, only the response. */ -export const PROTO_RESPONSE_VERSION = '0.19.0'; +export const PROTO_RESPONSE_VERSION = '0.31.0'; /** * The name of the root manifest file of the assembly. */ export const MANIFEST_FILE = 'manifest.json'; -/** - * The name of the root file with build instructions. - */ -export const BUILD_FILE = 'build.json'; - // output directory into which to emit synthesis outputs. CDK doesn't allow outdir // to be specified both through the CDK_OUTDIR environment variable and the through // aws:cdk:outdir context. @@ -68,30 +62,6 @@ export interface AssemblyManifest { readonly runtime?: AppRuntime; } -/** - * @deprecated use `AssemblyManifest` - */ -export interface SynthesizeResponse extends AssemblyManifest { - readonly stacks: SynthesizedStack[]; -} - -/** - * A complete synthesized stack - */ -export interface SynthesizedStack { - readonly name: string; - readonly environment: Environment; - readonly missing?: { [key: string]: MissingContext }; - readonly metadata: StackMetadata; - readonly template: any; - readonly autoDeploy?: boolean; - - /** - * Other stacks this stack depends on - */ - readonly dependsOn?: string[]; -} - /** * An metadata entry in the construct. */ @@ -163,19 +133,6 @@ export const PATH_METADATA_KEY = 'aws:cdk:path'; */ export const PATH_METADATA_ENABLE_CONTEXT = 'aws:cdk:enable-path-metadata'; -/** - * Disables the emission of `cdk.out` - */ -export const DISABLE_LEGACY_MANIFEST_CONTEXT = 'aws:cdk:disable-legacy-manifest'; - -/** - * The name of the pre 0.25.0 manifest file. Will only be emitted if - * aws:cdk:disable-legacy-manifest is not defined. - * - * @deprecated Use `MANIFEST_FILE` - */ -export const OUTFILE_NAME = 'cdk.out'; - /** * Disable the collection and reporting of version information. */ @@ -186,3 +143,8 @@ export const DISABLE_VERSION_REPORTING = 'aws:cdk:disable-version-reporting'; * the output directory and will be referenced with absolute source paths. */ export const DISABLE_ASSET_STAGING_CONTEXT = 'aws:cdk:disable-asset-staging'; + +/** + * Omits stack traces from construct metadata entries. + */ +export const DISABLE_METADATA_STACK_TRACE = 'aws:cdk:disable-stack-trace'; diff --git a/packages/@aws-cdk/cx-api/lib/environment.ts b/packages/@aws-cdk/cx-api/lib/environment.ts deleted file mode 100644 index 6dac39a141f27..0000000000000 --- a/packages/@aws-cdk/cx-api/lib/environment.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Models an AWS execution environment, for use within the CDK toolkit. - */ -export interface Environment { - /** The arbitrary name of this environment (user-set, or at least user-meaningful) */ - readonly name: string; - - /** The 12-digit AWS account ID for the account this environment deploys into */ - readonly account: string; - - /** The AWS region name where this environment deploys into */ - readonly region: string; -} diff --git a/packages/@aws-cdk/cx-api/lib/index.ts b/packages/@aws-cdk/cx-api/lib/index.ts index b3ebfaa8cf77a..4165f931c674e 100644 --- a/packages/@aws-cdk/cx-api/lib/index.ts +++ b/packages/@aws-cdk/cx-api/lib/index.ts @@ -1,9 +1,8 @@ export * from './cxapi'; -export * from './environment'; export * from './context/hosted-zone'; export * from './context/vpc'; export * from './context/ssm-parameter'; export * from './context/availability-zones'; export * from './metadata/assets'; export * from './artifacts'; -export * from './build'; +export * from './assembly'; diff --git a/packages/@aws-cdk/cx-api/package-lock.json b/packages/@aws-cdk/cx-api/package-lock.json index 8c1bb06151c08..172e521d70b18 100644 --- a/packages/@aws-cdk/cx-api/package-lock.json +++ b/packages/@aws-cdk/cx-api/package-lock.json @@ -1,5 +1,5061 @@ { "name": "@aws-cdk/cx-api", - "version": "0.28.0", - "lockfileVersion": 1 + "version": "0.31.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.5.tgz", + "integrity": "sha512-OvjIh6aqXtlsA8ujtGKfC7LYWksYSX8yQcM8Ay3LuvVeQ63lcOKgoZWVqcpFwkd29aYU9rVx7jxhfhiEDV9MZA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helpers": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.5", + "@babel/types": "^7.4.4", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.11", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz", + "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.11", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helpers": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz", + "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==", + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", + "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.5.tgz", + "integrity": "sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.4.4", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.4.5", + "@babel/types": "^7.4.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.11" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz", + "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + } + }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@jest/console": { + "version": "24.7.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz", + "integrity": "sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==", + "dev": true, + "requires": { + "@jest/source-map": "^24.3.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/core": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.8.0.tgz", + "integrity": "sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.8.0", + "jest-config": "^24.8.0", + "jest-haste-map": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-resolve-dependencies": "^24.8.0", + "jest-runner": "^24.8.0", + "jest-runtime": "^24.8.0", + "jest-snapshot": "^24.8.0", + "jest-util": "^24.8.0", + "jest-validate": "^24.8.0", + "jest-watcher": "^24.8.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "strip-ansi": "^5.0.0" + } + }, + "@jest/environment": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.8.0.tgz", + "integrity": "sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.8.0", + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "jest-mock": "^24.8.0" + } + }, + "@jest/fake-timers": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.8.0.tgz", + "integrity": "sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-mock": "^24.8.0" + } + }, + "@jest/reporters": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.8.0.tgz", + "integrity": "sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw==", + "dev": true, + "requires": { + "@jest/environment": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.1.1", + "jest-haste-map": "^24.8.0", + "jest-resolve": "^24.8.0", + "jest-runtime": "^24.8.0", + "jest-util": "^24.8.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.2.1", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + } + }, + "@jest/source-map": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.3.0.tgz", + "integrity": "sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.8.0.tgz", + "integrity": "sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/types": "^24.8.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz", + "integrity": "sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg==", + "dev": true, + "requires": { + "@jest/test-result": "^24.8.0", + "jest-haste-map": "^24.8.0", + "jest-runner": "^24.8.0", + "jest-runtime": "^24.8.0" + } + }, + "@jest/transform": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.8.0.tgz", + "integrity": "sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.8.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-util": "^24.8.0", + "micromatch": "^3.1.10", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + } + }, + "@jest/types": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.8.0.tgz", + "integrity": "sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^12.0.9" + } + }, + "@types/babel__core": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.2.tgz", + "integrity": "sha512-cfCCrFmiGY/yq0NuKNxIQvZFy9kY/1immpSpTngOnyIbD4+eJOG5mxphhHDv3CHL9GltO4GcKr54kGBg3RNdbg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", + "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.6.tgz", + "integrity": "sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", + "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "24.0.13", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.13.tgz", + "integrity": "sha512-3m6RPnO35r7Dg+uMLj1+xfZaOgIHHHut61djNjzwExXN4/Pm9has9C6I1KMYSfz7mahDhWUOVg4HW/nZdv5Pww==", + "dev": true, + "requires": { + "@types/jest-diff": "*" + } + }, + "@types/jest-diff": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz", + "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==", + "dev": true + }, + "@types/semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-OO0srjOGH99a4LUN2its3+r6CBYcplhJ466yLqs+zvAWgphCpS8hYZEZ797tRDP/QKcqTdb/YCN6ifASoAWkrQ==", + "dev": true + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/yargs": { + "version": "12.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz", + "integrity": "sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw==", + "dev": true + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", + "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "babel-jest": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.8.0.tgz", + "integrity": "sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw==", + "dev": true, + "requires": { + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.6.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz", + "integrity": "sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.6.0.tgz", + "integrity": "sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.6.0.tgz", + "integrity": "sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.6.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "bser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", + "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true, + "optional": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, + "cssom": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", + "dev": true + }, + "cssstyle": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", + "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "diff-sequences": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.3.0.tgz", + "integrity": "sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "exec-sh": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expect": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.8.0.tgz", + "integrity": "sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.8.0", + "jest-matcher-utils": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-regex-util": "^24.3.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "^2.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", + "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.12.1", + "node-pre-gyp": "^0.12.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": 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" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true, + "optional": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^4.1.0", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "yallist": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "handlebars": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "dev": true, + "requires": { + "handlebars": "^4.1.2" + } + }, + "jest": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.8.0.tgz", + "integrity": "sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.8.0" + }, + "dependencies": { + "jest-cli": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.8.0.tgz", + "integrity": "sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA==", + "dev": true, + "requires": { + "@jest/core": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.8.0", + "jest-util": "^24.8.0", + "jest-validate": "^24.8.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^12.0.2" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + } + } + }, + "jest-changed-files": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.8.0.tgz", + "integrity": "sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.8.0.tgz", + "integrity": "sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.8.0", + "@jest/types": "^24.8.0", + "babel-jest": "^24.8.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.8.0", + "jest-environment-node": "^24.8.0", + "jest-get-type": "^24.8.0", + "jest-jasmine2": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.8.0", + "jest-util": "^24.8.0", + "jest-validate": "^24.8.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.8.0", + "realpath-native": "^1.1.0" + } + }, + "jest-diff": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.8.0.tgz", + "integrity": "sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.3.0", + "jest-get-type": "^24.8.0", + "pretty-format": "^24.8.0" + } + }, + "jest-docblock": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.3.0.tgz", + "integrity": "sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.8.0.tgz", + "integrity": "sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.8.0", + "jest-util": "^24.8.0", + "pretty-format": "^24.8.0" + } + }, + "jest-environment-jsdom": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz", + "integrity": "sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ==", + "dev": true, + "requires": { + "@jest/environment": "^24.8.0", + "@jest/fake-timers": "^24.8.0", + "@jest/types": "^24.8.0", + "jest-mock": "^24.8.0", + "jest-util": "^24.8.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.8.0.tgz", + "integrity": "sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q==", + "dev": true, + "requires": { + "@jest/environment": "^24.8.0", + "@jest/fake-timers": "^24.8.0", + "@jest/types": "^24.8.0", + "jest-mock": "^24.8.0", + "jest-util": "^24.8.0" + } + }, + "jest-get-type": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.8.0.tgz", + "integrity": "sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ==", + "dev": true + }, + "jest-haste-map": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.8.0.tgz", + "integrity": "sha512-ZBPRGHdPt1rHajWelXdqygIDpJx8u3xOoLyUBWRW28r3tagrgoepPrzAozW7kW9HrQfhvmiv1tncsxqHJO1onQ==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.4.0", + "jest-util": "^24.8.0", + "jest-worker": "^24.6.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz", + "integrity": "sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.8.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.8.0", + "jest-matcher-utils": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-runtime": "^24.8.0", + "jest-snapshot": "^24.8.0", + "jest-util": "^24.8.0", + "pretty-format": "^24.8.0", + "throat": "^4.0.0" + } + }, + "jest-leak-detector": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz", + "integrity": "sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g==", + "dev": true, + "requires": { + "pretty-format": "^24.8.0" + } + }, + "jest-matcher-utils": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz", + "integrity": "sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.8.0", + "jest-get-type": "^24.8.0", + "pretty-format": "^24.8.0" + } + }, + "jest-message-util": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.8.0.tgz", + "integrity": "sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + } + }, + "jest-mock": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.8.0.tgz", + "integrity": "sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "dev": true + }, + "jest-regex-util": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.3.0.tgz", + "integrity": "sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg==", + "dev": true + }, + "jest-resolve": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.8.0.tgz", + "integrity": "sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-resolve-dependencies": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz", + "integrity": "sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.8.0" + } + }, + "jest-runner": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.8.0.tgz", + "integrity": "sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.8.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.8.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.8.0", + "jest-jasmine2": "^24.8.0", + "jest-leak-detector": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-resolve": "^24.8.0", + "jest-runtime": "^24.8.0", + "jest-util": "^24.8.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + } + }, + "jest-runtime": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.8.0.tgz", + "integrity": "sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.8.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.8.0", + "@jest/types": "^24.8.0", + "@types/yargs": "^12.0.2", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.8.0", + "jest-haste-map": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-mock": "^24.8.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.8.0", + "jest-snapshot": "^24.8.0", + "jest-util": "^24.8.0", + "jest-validate": "^24.8.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^12.0.2" + }, + "dependencies": { + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + } + } + }, + "jest-serializer": { + "version": "24.4.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.4.0.tgz", + "integrity": "sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q==", + "dev": true + }, + "jest-snapshot": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.8.0.tgz", + "integrity": "sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.8.0", + "chalk": "^2.0.1", + "expect": "^24.8.0", + "jest-diff": "^24.8.0", + "jest-matcher-utils": "^24.8.0", + "jest-message-util": "^24.8.0", + "jest-resolve": "^24.8.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.8.0", + "semver": "^5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, + "jest-util": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.8.0.tgz", + "integrity": "sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/fake-timers": "^24.8.0", + "@jest/source-map": "^24.3.0", + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + } + }, + "jest-validate": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.8.0.tgz", + "integrity": "sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "camelcase": "^5.0.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.8.0", + "leven": "^2.1.0", + "pretty-format": "^24.8.0" + } + }, + "jest-watcher": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.8.0.tgz", + "integrity": "sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw==", + "dev": true, + "requires": { + "@jest/test-result": "^24.8.0", + "@jest/types": "^24.8.0", + "@types/yargs": "^12.0.9", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.8.0", + "string-length": "^2.0.0" + } + }, + "jest-worker": { + "version": "24.6.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz", + "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", + "dev": true, + "requires": { + "merge-stream": "^1.0.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", + "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nwsapi": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + }, + "dependencies": { + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "pretty-format": { + "version": "24.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.8.0.tgz", + "integrity": "sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw==", + "dev": true, + "requires": { + "@jest/types": "^24.8.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "prompts": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.1.0.tgz", + "integrity": "sha512-+x5TozgqYdOwWsQFZizE/Tra3fKvAoy037kOyU6cgz84n8f6zxngLOV4O32kTwt9FcLCxAqw0P/c8rOr9y+Gfg==", + "dev": true, + "requires": { + "kleur": "^3.0.2", + "sisteransi": "^1.0.0" + } + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "resolve": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rsvp": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz", + "integrity": "sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "semver": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.0.tgz", + "integrity": "sha512-kCqEOOHoBcFs/2Ccuk4Xarm/KiWRSLEX9CAZF8xkJ6ZPlIoTZ8V5f7J16vYLJqDbR7KrxTJpR2lqjIEm2Qx9cQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sisteransi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.0.tgz", + "integrity": "sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "dev": true + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + } + }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "uglify-js": { + "version": "3.5.15", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.15.tgz", + "integrity": "sha512-fe7aYFotptIddkwcm6YuA0HmknBZ52ZzOsUxZEdhhkSsz7RfjHDX2QDxwKTiv4JQ5t5NhfmpgAK+J7LiDhKSqg==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } } diff --git a/packages/@aws-cdk/cx-api/package.json b/packages/@aws-cdk/cx-api/package.json index cb0e7c1f20ddb..ec8fff5371cf1 100644 --- a/packages/@aws-cdk/cx-api/package.json +++ b/packages/@aws-cdk/cx-api/package.json @@ -42,10 +42,24 @@ "url": "https://aws.amazon.com", "organization": true }, + "dependencies": { + "semver": "^6.0.0" + }, + "jest": { + "coverageThreshold": { + "global": { + "branches": 80, + "statements": 80 + } + } + }, "license": "Apache-2.0", "devDependencies": { "cdk-build-tools": "^0.31.0", - "pkglint": "^0.31.0" + "@types/jest": "^24.0.11", + "@types/semver": "^6.0.0", + "pkglint": "^0.31.0", + "jest": "^24.7.1" }, "repository": { "url": "https://github.com/awslabs/aws-cdk.git", @@ -57,6 +71,9 @@ "cdk" ], "homepage": "https://github.com/awslabs/aws-cdk", + "bundledDependencies": [ + "semver" + ], "engines": { "node": ">= 8.10.0" } diff --git a/packages/@aws-cdk/cx-api/test/__snapshots__/deploy.test.js.snap b/packages/@aws-cdk/cx-api/test/__snapshots__/deploy.test.js.snap new file mode 100644 index 0000000000000..8bf4506feca6e --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/__snapshots__/deploy.test.js.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`assembly with missing context 1`] = ` +Object { + "missing:context:key": Object { + "foo": 123, + }, + "missing:context:key2": Object { + "foo": 6688, + }, +} +`; + +exports[`assets 1`] = ` +Array [ + Object { + "id": "logical-id-of-the-asset", + "packaging": "zip", + "path": "asset-dir", + "sourceHash": "xoxoxox", + }, + Object { + "id": "logical-id-of-the-asset-x1234", + "packaging": "docker", + "path": "docker-asset", + "sourceHash": "docker-asset-source", + }, +] +`; + +exports[`messages 1`] = ` +Array [ + Object { + "entry": Object { + "data": "boom", + "trace": "bam", + "type": "aws:cdk:warning", + }, + "id": "foo", + "level": "warning", + }, + Object { + "entry": Object { + "data": "error!!", + "trace": "bam!Error", + "type": "aws:cdk:error", + }, + "id": "foo", + "level": "error", + }, + Object { + "entry": Object { + "data": "info?", + "trace": "bam!Error", + "type": "aws:cdk:info", + }, + "id": "bar", + "level": "info", + }, +] +`; diff --git a/packages/@aws-cdk/cx-api/test/deploy.test.ts b/packages/@aws-cdk/cx-api/test/deploy.test.ts new file mode 100644 index 0000000000000..67776e994d826 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/deploy.test.ts @@ -0,0 +1,93 @@ +import path = require('path'); +import { CloudAssembly } from '../lib'; + +const FIXTURES = path.join(__dirname, 'fixtures'); + +test('empty assembly', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'empty')); + expect(assembly.artifacts).toEqual([]); + expect(assembly.missing).toBeUndefined(); + expect(assembly.runtime).toEqual({ libraries: { } }); + expect(assembly.stacks).toEqual([]); + expect(assembly.version).toEqual('0.31.0'); +}); + +test('assembly a single cloudformation stack', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'single-stack')); + expect(assembly.artifacts).toHaveLength(1); + expect(assembly.stacks).toHaveLength(1); + expect(assembly.missing).toBeUndefined(); + expect(assembly.runtime).toEqual({ libraries: { } }); + expect(assembly.version).toEqual('0.31.0'); + expect(assembly.artifacts[0]).toEqual(assembly.stacks[0]); + + const stack = assembly.stacks[0]; + expect(stack.assets).toHaveLength(0); + expect(stack.autoDeploy).toBeTruthy(); + expect(stack.depends).toEqual([]); + expect(stack.environment).toEqual({ account: '37736633', region: 'us-region-1', name: 'aws://37736633/us-region-1' }); + expect(stack.template).toEqual({ Resources: { MyBucket: { Type: "AWS::S3::Bucket" } } }); + expect(stack.messages).toEqual([]); + expect(stack.metadata).toEqual({}); + expect(stack.missing).toEqual({}); + expect(stack.originalName).toEqual('MyStackName'); + expect(stack.name).toEqual('MyStackName'); + expect(stack.logicalIdToPathMap).toEqual({}); +}); + +test('assembly with missing context', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'missing-context')); + expect(assembly.missing).toMatchSnapshot(); +}); + +test('assembly with multiple stacks', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'multiple-stacks')); + expect(assembly.stacks).toHaveLength(2); + expect(assembly.artifacts).toHaveLength(2); +}); + +test('fails for invalid artifact type', () => { + expect(() => new CloudAssembly(path.join(FIXTURES, 'invalid-artifact-type'))) + .toThrow('unsupported artifact type: who:am:i'); +}); + +test('fails for invalid environment format', () => { + expect(() => new CloudAssembly(path.join(FIXTURES, 'invalid-env-format'))) + .toThrow('Unable to parse environment specification'); +}); + +test('fails if stack artifact does not have properties', () => { + expect(() => new CloudAssembly(path.join(FIXTURES, 'stack-without-params'))) + .toThrow('Invalid CloudFormation stack artifact. Missing properties'); +}); + +test('messages', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'messages')); + expect(assembly.stacks[0].messages).toMatchSnapshot(); +}); + +test('assets', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'assets')); + expect(assembly.stacks[0].assets).toMatchSnapshot(); +}); + +test('logical id to path map', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'logical-id-map')); + expect(assembly.stacks[0].logicalIdToPathMap).toEqual({ logicalIdOfFooBar: '/foo/bar' }); +}); + +test('dependencies', () => { + const assembly = new CloudAssembly(path.join(FIXTURES, 'depends')); + expect(assembly.stacks).toHaveLength(4); + + // expect stacks to be listed in topological order + expect(assembly.stacks.map(s => s.name)).toEqual([ 'StackA', 'StackD', 'StackC', 'StackB' ]); + expect(assembly.stacks[0].depends).toEqual([]); + expect(assembly.stacks[1].depends).toEqual([]); + expect(assembly.stacks[2].depends.map(x => x.id)).toEqual([ 'StackD' ]); + expect(assembly.stacks[3].depends.map(x => x.id)).toEqual([ 'StackC', 'StackD' ]); +}); + +test('fails for invalid dependencies', () => { + expect(() => new CloudAssembly(path.join(FIXTURES, 'invalid-depends'))).toThrow('Artifact StackC depends on non-existing artifact StackX'); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/assets/asset-dir/foo.txt b/packages/@aws-cdk/cx-api/test/fixtures/assets/asset-dir/foo.txt new file mode 100644 index 0000000000000..5783cb7e31483 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/assets/asset-dir/foo.txt @@ -0,0 +1 @@ +hello, assets! diff --git a/packages/@aws-cdk/cx-api/test/fixtures/assets/docker-asset/Dockerfile b/packages/@aws-cdk/cx-api/test/fixtures/assets/docker-asset/Dockerfile new file mode 100644 index 0000000000000..ceaf18ac05257 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/assets/docker-asset/Dockerfile @@ -0,0 +1 @@ +FROM ubuntu diff --git a/packages/@aws-cdk/cx-api/test/fixtures/assets/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/assets/manifest.json new file mode 100644 index 0000000000000..52cf5a8f17cab --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/assets/manifest.json @@ -0,0 +1,36 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyStackName": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "properties": { + "templateFile": "template.json" + }, + "metadata": { + "foo": [ + { + "type": "aws:cdk:asset", + "data": { + "packaging": "zip", + "id": "logical-id-of-the-asset", + "sourceHash": "xoxoxox", + "path": "asset-dir" + }, + "trace": "bam" + }, + { + "type": "aws:cdk:asset", + "data": { + "packaging": "docker", + "id": "logical-id-of-the-asset-x1234", + "sourceHash": "docker-asset-source", + "path": "docker-asset" + }, + "trace": "bam:ssss" + } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/assets/template.json b/packages/@aws-cdk/cx-api/test/fixtures/assets/template.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/assets/template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/depends/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/depends/manifest.json new file mode 100644 index 0000000000000..c00bbeb577aa6 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/depends/manifest.json @@ -0,0 +1,35 @@ +{ + "version": "0.31.0", + "artifacts": { + "StackA": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "properties": { + "templateFile": "template.json" + } + }, + "StackB": { + "type": "aws:cloudformation:stack", + "environment": "aws://1111/us-region-1", + "properties": { + "templateFile": "template.json" + }, + "dependencies": [ "StackC", "StackD" ] + }, + "StackC": { + "type": "aws:cloudformation:stack", + "environment": "aws://1111/us-region-1", + "properties": { + "templateFile": "template.json" + }, + "dependencies": [ "StackD" ] + }, + "StackD": { + "type": "aws:cloudformation:stack", + "environment": "aws://1111/us-region-1", + "properties": { + "templateFile": "template.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/depends/template.json b/packages/@aws-cdk/cx-api/test/fixtures/depends/template.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/depends/template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/empty/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/empty/manifest.json new file mode 100644 index 0000000000000..7366eb0b72921 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/empty/manifest.json @@ -0,0 +1,3 @@ +{ + "version": "0.31.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/invalid-artifact-type/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/invalid-artifact-type/manifest.json new file mode 100644 index 0000000000000..3980b2adf915d --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/invalid-artifact-type/manifest.json @@ -0,0 +1,9 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyArt": { + "type": "who:am:i", + "environment": "aws://37736633/us-region-1" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/invalid-depends/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/invalid-depends/manifest.json new file mode 100644 index 0000000000000..0bda25fbc37f3 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/invalid-depends/manifest.json @@ -0,0 +1,35 @@ +{ + "version": "0.31.0", + "artifacts": { + "StackA": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "properties": { + "templateFile": "template.json" + } + }, + "StackB": { + "type": "aws:cloudformation:stack", + "environment": "aws://1111/us-region-1", + "properties": { + "templateFile": "template.json" + }, + "dependencies": [ "StackC", "StackD" ] + }, + "StackC": { + "type": "aws:cloudformation:stack", + "environment": "aws://1111/us-region-1", + "properties": { + "templateFile": "template.json" + }, + "dependencies": [ "StackX" ] + }, + "StackD": { + "type": "aws:cloudformation:stack", + "environment": "aws://1111/us-region-1", + "properties": { + "templateFile": "template.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/invalid-depends/template.json b/packages/@aws-cdk/cx-api/test/fixtures/invalid-depends/template.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/invalid-depends/template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/invalid-env-format/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/invalid-env-format/manifest.json new file mode 100644 index 0000000000000..dc629aeb17c70 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/invalid-env-format/manifest.json @@ -0,0 +1,12 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyStackName": { + "type": "aws:cloudformation:stack", + "environment": "awsx://37736633/us-region-1", + "properties": { + "templateFile": "template.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/logical-id-map/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/logical-id-map/manifest.json new file mode 100644 index 0000000000000..555bbf0ae7d96 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/logical-id-map/manifest.json @@ -0,0 +1,21 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyStackName": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "properties": { + "templateFile": "template.json" + }, + "metadata": { + "/foo/bar": [ + { + "type": "aws:cdk:logicalId", + "data": "logicalIdOfFooBar", + "trace": "bam" + } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/logical-id-map/template.json b/packages/@aws-cdk/cx-api/test/fixtures/logical-id-map/template.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/logical-id-map/template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/messages/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/messages/manifest.json new file mode 100644 index 0000000000000..3ebade9ca9d44 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/messages/manifest.json @@ -0,0 +1,22 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyStackName": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "properties": { + "templateFile": "template.json" + }, + "metadata": { + "foo": [ + { "type": "aws:cdk:warning", "data": "boom", "trace": "bam" }, + { "type": "aws:cdk:error", "data": "error!!", "trace": "bam!Error" } + ], + "bar": [ + { "type": "aws:cdk:info", "data": "info?", "trace": "bam!Error" }, + { "type": "aws:foo", "data": "info?", "trace": "bam!Error" } + ] + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/messages/template.json b/packages/@aws-cdk/cx-api/test/fixtures/messages/template.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/messages/template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/missing-context/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/missing-context/manifest.json new file mode 100644 index 0000000000000..20cd3f71bdecf --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/missing-context/manifest.json @@ -0,0 +1,26 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyStackName": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "missing": { + "missing:context:key": { "foo": 123 } + }, + "properties": { + "templateFile": "template.json" + } + }, + "MyStackName1234": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "missing": { + "missing:context:key2": { "foo": 6688 } + }, + "properties": { + "templateFile": "template.json" + } + } + + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/missing-context/template.json b/packages/@aws-cdk/cx-api/test/fixtures/missing-context/template.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/missing-context/template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/manifest.json new file mode 100644 index 0000000000000..3e12e35d60355 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/manifest.json @@ -0,0 +1,19 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyStackName": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "properties": { + "templateFile": "template.json" + } + }, + "MyStackName1234": { + "type": "aws:cloudformation:stack", + "environment": "aws://1111/us-region-1", + "properties": { + "templateFile": "template.2.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/template.2.json b/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/template.2.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/template.2.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/template.json b/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/template.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/multiple-stacks/template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/single-stack/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/single-stack/manifest.json new file mode 100644 index 0000000000000..020886bf13984 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/single-stack/manifest.json @@ -0,0 +1,12 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyStackName": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1", + "properties": { + "templateFile": "template.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/single-stack/template.json b/packages/@aws-cdk/cx-api/test/fixtures/single-stack/template.json new file mode 100644 index 0000000000000..284fd64cffc21 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/single-stack/template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "MyBucket": { + "Type": "AWS::S3::Bucket" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cx-api/test/fixtures/stack-without-params/manifest.json b/packages/@aws-cdk/cx-api/test/fixtures/stack-without-params/manifest.json new file mode 100644 index 0000000000000..02d61f6d4f444 --- /dev/null +++ b/packages/@aws-cdk/cx-api/test/fixtures/stack-without-params/manifest.json @@ -0,0 +1,9 @@ +{ + "version": "0.31.0", + "artifacts": { + "MyStackName": { + "type": "aws:cloudformation:stack", + "environment": "aws://37736633/us-region-1" + } + } +} \ No newline at end of file diff --git a/packages/aws-cdk/bin/cdk.ts b/packages/aws-cdk/bin/cdk.ts index daf26b3a260e3..514ed9476de3f 100644 --- a/packages/aws-cdk/bin/cdk.ts +++ b/packages/aws-cdk/bin/cdk.ts @@ -7,12 +7,11 @@ import yargs = require('yargs'); import { bootstrapEnvironment, destroyStack, SDK } from '../lib'; import { environmentsFromDescriptors, globEnvironmentsFromStacks } from '../lib/api/cxapp/environments'; import { execProgram } from '../lib/api/cxapp/exec'; -import { AppStacks, ExtendedStackSelection, listStackNames } from '../lib/api/cxapp/stacks'; +import { AppStacks, ExtendedStackSelection } from '../lib/api/cxapp/stacks'; import { CloudFormationDeploymentTarget, DEFAULT_TOOLKIT_STACK_NAME } from '../lib/api/deployment-target'; import { CdkToolkit } from '../lib/cdk-toolkit'; import { RequireApproval } from '../lib/diff'; import { availableInitLanguages, cliInit, printAvailableTemplates } from '../lib/init'; -import { interactive } from '../lib/interactive'; import { data, debug, error, print, setVerbose, success } from '../lib/logging'; import { PluginHost } from '../lib/plugin'; import { parseRenames } from '../lib/renames'; @@ -29,7 +28,7 @@ async function parseCommandLineArguments() { return yargs .env('CDK') .usage('Usage: cdk -a COMMAND') - .option('app', { type: 'string', alias: 'a', desc: 'REQUIRED: Command-line for executing your CDK app (e.g. "node bin/my-app.js")', requiresArg: true }) + .option('app', { type: 'string', alias: 'a', desc: 'REQUIRED: command-line for executing your app or a cloud assembly directory (e.g. "node bin/my-app.js")', requiresArg: true }) .option('context', { type: 'array', alias: 'c', desc: 'Add contextual string parameter (KEY=VALUE)', nargs: 1, requiresArg: true }) .option('plugin', { type: 'array', alias: 'p', desc: 'Name or path of a node package that extend the CDK features. Can be specified multiple times', nargs: 1 }) .option('rename', { type: 'string', desc: 'Rename stack name if different from the one defined in the cloud executable ([ORIGINAL:]RENAMED)', requiresArg: true }) @@ -47,12 +46,11 @@ async function parseCommandLineArguments() { .option('role-arn', { type: 'string', alias: 'r', desc: 'ARN of Role to use when invoking CloudFormation', default: undefined, requiresArg: true }) .option('toolkit-stack-name', { type: 'string', desc: 'The name of the CDK toolkit stack', requiresArg: true }) .option('staging', { type: 'boolean', desc: 'copy assets to the output directory (use --no-staging to disable)', default: true }) - .option('output', { type: 'string', alias: 'o', desc: 'emits synthesis output into a directory (default: cdk.out)', requiresArg: true }) + .option('output', { type: 'string', alias: 'o', desc: 'emits the synthesized cloud assembly into a directory (default: cdk.out)', requiresArg: true }) .command([ 'list', 'ls' ], 'Lists all stacks in the app', yargs => yargs .option('long', { type: 'boolean', default: false, alias: 'l', desc: 'display environment information for each stack' })) .command([ 'synthesize [STACKS..]', 'synth [STACKS..]' ], 'Synthesizes and prints the CloudFormation template for this stack', yargs => yargs - .option('exclusively', { type: 'boolean', alias: 'e', desc: 'only deploy requested stacks, don\'t include dependencies' }) - .option('interactive', { type: 'boolean', alias: 'i', desc: 'interactively watch and show template updates' })) + .option('exclusively', { type: 'boolean', alias: 'e', desc: 'only deploy requested stacks, don\'t include dependencies' })) .command('bootstrap [ENVIRONMENTS..]', 'Deploys the CDK toolkit stack into an AWS environment', yargs => yargs .option('toolkit-bucket-name', { type: 'string', alias: 'b', desc: 'The name of the CDK toolkit bucket', default: undefined })) .command('deploy [STACKS..]', 'Deploys the stack(s) named STACKS into your AWS account', yargs => yargs @@ -208,7 +206,7 @@ async function initCommandLine() { case 'synthesize': case 'synth': - return await cliSynthesize(args.STACKS, args.exclusively, args.interactive, configuration.settings); + return await cliSynthesize(args.STACKS, args.exclusively); case 'metadata': return await cliMetadata(await findStack(args.STACK)); @@ -276,21 +274,12 @@ async function initCommandLine() { * should be supplied, where the templates will be written. */ async function cliSynthesize(stackNames: string[], - exclusively: boolean, - doInteractive: boolean, - settings: Settings): Promise { + exclusively: boolean): Promise { // Only autoselect dependencies if it doesn't interfere with user request or output options const autoSelectDependencies = !exclusively; const stacks = await appStacks.selectStacks(stackNames, autoSelectDependencies ? ExtendedStackSelection.Upstream : ExtendedStackSelection.None); - if (doInteractive) { - if (stacks.length !== 1) { - throw new Error(`When using interactive synthesis, must select exactly one stack. Got: ${listStackNames(stacks)}`); - } - return await interactive(stacks[0], argv.verbose, (stack) => appStacks.synthesizeStack(stack)); - } - // if we have a single stack, print it to STDOUT if (stacks.length === 1) { return stacks[0].template; @@ -308,7 +297,7 @@ async function initCommandLine() { return stacks.map(s => s.template); } - return settings.get(['output']); + return appStacks.assembly!.directory; } async function cliList(options: { long?: boolean } = { }) { diff --git a/packages/aws-cdk/lib/api/bootstrap-environment.ts b/packages/aws-cdk/lib/api/bootstrap-environment.ts index d2c751b36b6dc..a8c9001e9a800 100644 --- a/packages/aws-cdk/lib/api/bootstrap-environment.ts +++ b/packages/aws-cdk/lib/api/bootstrap-environment.ts @@ -1,4 +1,4 @@ -import { Environment, SynthesizedStack } from '@aws-cdk/cx-api'; +import { Environment, ICloudFormationStackArtifact } from '@aws-cdk/cx-api'; import { deployStack, DeployStackResult } from './deploy-stack'; import { SDK } from './util/sdk'; @@ -8,9 +8,15 @@ export const BUCKET_NAME_OUTPUT = 'BucketName'; export const BUCKET_DOMAIN_NAME_OUTPUT = 'BucketDomainName'; export async function bootstrapEnvironment(environment: Environment, aws: SDK, toolkitStackName: string, roleArn: string | undefined, toolkitBucketName: string | undefined): Promise { - const synthesizedStack: SynthesizedStack = { + const synthesizedStack: ICloudFormationStackArtifact = { + logicalIdToPathMap: { }, + messages: [], + depends: [], + autoDeploy: true, + metadata: { }, + missing: { }, environment, - metadata: {}, + assets: [], template: { Description: "The CDK Toolkit Stack. It was created by `cdk bootstrap` and manages resources necessary for managing your Cloud Applications with AWS CDK.", Resources: { @@ -33,7 +39,9 @@ export async function bootstrapEnvironment(environment: Environment, aws: SDK, t } } }, + id: toolkitStackName, name: toolkitStackName, + originalName: toolkitStackName }; if (toolkitBucketName) { synthesizedStack.template.Resources.StagingBucket.Properties.BucketName = toolkitBucketName; diff --git a/packages/aws-cdk/lib/api/cxapp/environments.ts b/packages/aws-cdk/lib/api/cxapp/environments.ts index ff63349b85e15..53b4366f04a85 100644 --- a/packages/aws-cdk/lib/api/cxapp/environments.ts +++ b/packages/aws-cdk/lib/api/cxapp/environments.ts @@ -1,15 +1,15 @@ -import cxapi = require('@aws-cdk/cx-api'); +import { Environment } from '@aws-cdk/cx-api'; import minimatch = require('minimatch'); import { AppStacks, ExtendedStackSelection } from './stacks'; -export async function globEnvironmentsFromStacks(appStacks: AppStacks, environmentGlobs: string[]): Promise { +export async function globEnvironmentsFromStacks(appStacks: AppStacks, environmentGlobs: string[]): Promise { if (environmentGlobs.length === 0) { environmentGlobs = [ '**' ]; // default to ALL } const stacks = await appStacks.selectStacks([], ExtendedStackSelection.None); const availableEnvironments = distinct(stacks.map(stack => stack.environment) - .filter(env => env !== undefined) as cxapi.Environment[]); + .filter(env => env !== undefined) as Environment[]); const environments = availableEnvironments.filter(env => environmentGlobs.find(glob => minimatch(env!.name, glob))); if (environments.length === 0) { const globs = JSON.stringify(environmentGlobs); @@ -23,12 +23,12 @@ export async function globEnvironmentsFromStacks(appStacks: AppStacks, environme /** * Given a set of "/" strings, construct environments for them */ -export function environmentsFromDescriptors(envSpecs: string[]): cxapi.Environment[] { +export function environmentsFromDescriptors(envSpecs: string[]): Environment[] { if (envSpecs.length === 0) { throw new Error(`Either specify an app with '--app', or specify an environment name like '123456789012/us-east-1'`); } - const ret = new Array(); + const ret = new Array(); for (const spec of envSpecs) { const parts = spec.split('/'); if (parts.length !== 2) { @@ -53,8 +53,8 @@ export function environmentsFromDescriptors(envSpecs: string[]): cxapi.Environme * * @return a de-duplicated list of environments. */ -function distinct(envs: cxapi.Environment[]): cxapi.Environment[] { - const unique: { [id: string]: cxapi.Environment } = {}; +function distinct(envs: Environment[]): Environment[] { + const unique: { [id: string]: Environment } = {}; for (const env of envs) { const id = `${env.account || 'default'}/${env.region || 'default'}`; if (id in unique) { continue; } diff --git a/packages/aws-cdk/lib/api/cxapp/exec.ts b/packages/aws-cdk/lib/api/cxapp/exec.ts index cdde161d2fb58..a80beb53e181b 100644 --- a/packages/aws-cdk/lib/api/cxapp/exec.ts +++ b/packages/aws-cdk/lib/api/cxapp/exec.ts @@ -2,13 +2,12 @@ import cxapi = require('@aws-cdk/cx-api'); import childProcess = require('child_process'); import fs = require('fs-extra'); import path = require('path'); -import semver = require('semver'); import { debug } from '../../logging'; import { Configuration, PROJECT_CONFIG, USER_DEFAULTS } from '../../settings'; import { SDK } from '../util/sdk'; /** Invokes the cloud executable and returns JSON output */ -export async function execProgram(aws: SDK, config: Configuration): Promise { +export async function execProgram(aws: SDK, config: Configuration): Promise { const env: { [key: string]: string } = { }; const context = config.context.all; @@ -50,7 +49,6 @@ export async function execProgram(aws: SDK, config: Configuration): Promise((ok, fail) => { @@ -105,7 +103,7 @@ export async function execProgram(aws: SDK, config: Configuration): Promise { if (code === 0) { - return ok(path.join(outdir, cxapi.OUTFILE_NAME)); + return ok(); } else { return fail(new Error(`Subprocess exited with error ${code}`)); } @@ -114,37 +112,6 @@ export async function execProgram(aws: SDK, config: Configuration): Promise= ${cxapi.PROTO_RESPONSE_VERSION} is required in order to interact with this version of the Toolkit.`); - } - - const frameworkVersion = semver.coerce(response.version); - const toolkitVersion = semver.coerce(cxapi.PROTO_RESPONSE_VERSION); - - // Should not happen, but I don't trust this library 100% either, so let's check for it to be safe - if (!frameworkVersion || !toolkitVersion) { throw new Error('SemVer library could not parse versions'); } - - if (semver.gt(frameworkVersion, toolkitVersion)) { - throw new Error(`CDK Toolkit >= ${response.version} is required in order to interact with this program.`); - } - - if (semver.lt(frameworkVersion, toolkitVersion)) { - // Toolkit protocol is newer than the framework version, and we KNOW the - // version. This is a scenario in which we could potentially do some - // upgrading of the response in the future. - // - // For now though, we simply reject old responses. - throw new Error(`CDK Framework >= ${cxapi.PROTO_RESPONSE_VERSION} is required in order to interact with this version of the Toolkit.`); - } - - return response; -} - /** * If we don't have region/account defined in context, we fall back to the default SDK behavior * where region is retreived from ~/.aws/config and account is based on default credentials provider diff --git a/packages/aws-cdk/lib/api/cxapp/stacks.ts b/packages/aws-cdk/lib/api/cxapp/stacks.ts index 7d913155e2a70..c1fbc7528d9df 100644 --- a/packages/aws-cdk/lib/api/cxapp/stacks.ts +++ b/packages/aws-cdk/lib/api/cxapp/stacks.ts @@ -6,11 +6,12 @@ import contextproviders = require('../../context-providers'); import { debug, error, print, warning } from '../../logging'; import { Renames } from '../../renames'; import { Configuration } from '../../settings'; -import cdkUtil = require('../../util'); import { SDK } from '../util/sdk'; -import { topologicalSort } from '../util/toposort'; -type Synthesizer = (aws: SDK, config: Configuration) => Promise; +/** + * @returns output directory + */ +type Synthesizer = (aws: SDK, config: Configuration) => Promise; export interface AppStacksProps { /** @@ -65,7 +66,8 @@ export class AppStacks { * Since app execution basically always synthesizes all the stacks, * we can invoke it once and cache the response for subsequent calls. */ - private cachedResponse?: cxapi.SynthesizeResponse; + public assembly?: cxapi.ICloudAssembly; + private readonly renames: Renames; constructor(private readonly props: AppStacksProps) { @@ -78,28 +80,29 @@ export class AppStacks { * It's an error if there are no stacks to select, or if one of the requested parameters * refers to a nonexistant stack. */ - public async selectStacks(selectors: string[], extendedSelection: ExtendedStackSelection): Promise { + public async selectStacks(selectors: string[], extendedSelection: ExtendedStackSelection): Promise { selectors = selectors.filter(s => s != null); // filter null/undefined - const stacks: cxapi.SynthesizedStack[] = await this.listStacks(); + const stacks = await this.listStacks(); if (stacks.length === 0) { throw new Error('This app contains no stacks'); } if (selectors.length === 0) { // remove non-auto deployed Stacks - const autoDeployedStacks = stacks.filter(s => s.autoDeploy !== false); + const autoDeployedStacks = stacks.filter(s => s.autoDeploy); debug('Stack name not specified, so defaulting to all available stacks: ' + listStackNames(autoDeployedStacks)); - return this.applyRenames(autoDeployedStacks); + this.applyRenames(autoDeployedStacks); + return autoDeployedStacks; } - const allStacks = new Map(); + const allStacks = new Map(); for (const stack of stacks) { allStacks.set(stack.name, stack); } // For every selector argument, pick stacks from the list. - const selectedStacks = new Map(); + const selectedStacks = new Map(); for (const pattern of selectors) { let found = false; @@ -129,7 +132,9 @@ export class AppStacks { // Only check selected stacks for errors this.processMessages(selectedList); - return this.applyRenames(selectedList); + this.applyRenames(selectedList); + + return selectedList; } /** @@ -142,42 +147,43 @@ export class AppStacks { * * Renames are *NOT* applied in list mode. */ - public async listStacks(): Promise { + public async listStacks(): Promise { const response = await this.synthesizeStacks(); - return topologicalSort(response.stacks, s => s.name, s => s.dependsOn || []); + return response.stacks; } /** * Synthesize a single stack */ - public async synthesizeStack(stackName: string): Promise { + public async synthesizeStack(stackName: string): Promise { const resp = await this.synthesizeStacks(); const stack = resp.stacks.find(s => s.name === stackName); if (!stack) { throw new Error(`Stack ${stackName} not found`); } - return this.applyRenames([stack])[0]; + this.applyRenames([stack]); + + return stack; } /** * Synthesize a set of stacks */ - public async synthesizeStacks(): Promise { - if (this.cachedResponse) { - return this.cachedResponse; + public async synthesizeStacks(): Promise { + if (this.assembly) { + return this.assembly; } const trackVersions: boolean = this.props.configuration.settings.get(['versionReporting']); // We may need to run the cloud executable multiple times in order to satisfy all missing context while (true) { - const response: cxapi.SynthesizeResponse = await this.props.synthesizer(this.props.aws, this.props.configuration); - const allMissing = cdkUtil.deepMerge(...response.stacks.map(s => s.missing)); + const assembly = await this.props.synthesizer(this.props.aws, this.props.configuration); - if (!cdkUtil.isEmpty(allMissing)) { + if (assembly.missing) { debug(`Some context information is missing. Fetching...`); - await contextproviders.provideContextValues(allMissing, this.props.configuration.context, this.props.aws); + await contextproviders.provideContextValues(assembly.missing, this.props.configuration.context, this.props.aws); // Cache the new context to disk await this.props.configuration.saveContext(); @@ -185,9 +191,9 @@ export class AppStacks { continue; } - if (trackVersions && response.runtime) { - const modules = formatModules(response.runtime); - for (const stack of response.stacks) { + if (trackVersions && assembly.runtime) { + const modules = formatModules(assembly.runtime); + for (const stack of assembly.stacks) { if (!stack.template.Resources) { stack.template.Resources = {}; } @@ -209,8 +215,8 @@ export class AppStacks { } // All good, return - this.cachedResponse = response; - return response; + this.assembly = assembly; + return assembly; function formatModules(runtime: cxapi.AppRuntime): string { const modules = new Array(); @@ -230,26 +236,24 @@ export class AppStacks { /** * Extracts 'aws:cdk:warning|info|error' metadata entries from the stack synthesis */ - private processMessages(stacks: cxapi.SynthesizedStack[]) { + private processMessages(stacks: cxapi.ICloudFormationStackArtifact[]) { let warnings = false; let errors = false; + for (const stack of stacks) { - for (const id of Object.keys(stack.metadata)) { - const metadata = stack.metadata[id]; - for (const entry of metadata) { - switch (entry.type) { - case cxapi.WARNING_METADATA_KEY: - warnings = true; - this.printMessage(warning, 'Warning', id, entry); - break; - case cxapi.ERROR_METADATA_KEY: - errors = true; - this.printMessage(error, 'Error', id, entry); - break; - case cxapi.INFO_METADATA_KEY: - this.printMessage(print, 'Info', id, entry); - break; - } + for (const message of stack.messages) { + switch (message.level) { + case cxapi.SynthesisMessageLevel.WARNING: + warnings = true; + this.printMessage(warning, 'Warning', message.id, message.entry); + break; + case cxapi.SynthesisMessageLevel.ERROR: + errors = true; + this.printMessage(error, 'Error', message.id, message.entry); + break; + case cxapi.SynthesisMessageLevel.INFO: + this.printMessage(print, 'Info', message.id, message.entry); + break; } } } @@ -271,26 +275,18 @@ export class AppStacks { } } - private applyRenames(stacks: cxapi.SynthesizedStack[]): SelectedStack[] { + private applyRenames(stacks: cxapi.ICloudFormationStackArtifact[]) { this.renames.validateSelectedStacks(stacks); - - const ret = []; for (const stack of stacks) { - ret.push({ - ...stack, - originalName: stack.name, - name: this.renames.finalName(stack.name), - }); + stack.name = this.renames.finalName(stack.name); } - - return ret; } } /** * Combine the names of a set of stacks using a comma */ -export function listStackNames(stacks: cxapi.SynthesizedStack[]): string { +export function listStackNames(stacks: cxapi.ICloudFormationStackArtifact[]): string { return stacks.map(s => s.name).join(', '); } @@ -319,7 +315,9 @@ export enum ExtendedStackSelection { * * Modifies `selectedStacks` in-place. */ -function includeDownstreamStacks(selectedStacks: Map, allStacks: Map) { +function includeDownstreamStacks( + selectedStacks: Map, + allStacks: Map) { const added = new Array(); let madeProgress = true; @@ -328,7 +326,7 @@ function includeDownstreamStacks(selectedStacks: Map selectedStacks.has(dependencyName))) { + if (!selectedStacks.has(name) && (stack.depends || []).some(dep => selectedStacks.has(dep.id))) { selectedStacks.set(name, stack); added.push(name); madeProgress = true; @@ -346,7 +344,9 @@ function includeDownstreamStacks(selectedStacks: Map, allStacks: Map) { +function includeUpstreamStacks( + selectedStacks: Map, + allStacks: Map) { const added = new Array(); let madeProgress = true; while (madeProgress) { @@ -354,7 +354,7 @@ function includeUpstreamStacks(selectedStacks: Map x.id)) { if (!selectedStacks.has(dependencyName) && allStacks.has(dependencyName)) { added.push(dependencyName); selectedStacks.set(dependencyName, allStacks.get(dependencyName)!); @@ -368,10 +368,3 @@ function includeUpstreamStacks(selectedStacks: Map { +async function makeBodyParameter(stack: cxapi.ICloudFormationStackArtifact, toolkitInfo?: ToolkitInfo): Promise { const templateJson = toYAML(stack.template); if (toolkitInfo) { const s3KeyPrefix = `cdk/${stack.name}/`; @@ -140,7 +140,7 @@ async function makeBodyParameter(stack: cxapi.SynthesizedStack, toolkitInfo?: To } export interface DestroyStackOptions { - stack: cxapi.SynthesizedStack; + stack: cxapi.ICloudFormationStackArtifact; sdk: SDK; roleArn?: string; deployName?: string; diff --git a/packages/aws-cdk/lib/api/deployment-target.ts b/packages/aws-cdk/lib/api/deployment-target.ts index 61dc56458fc42..a1058f818c3ca 100644 --- a/packages/aws-cdk/lib/api/deployment-target.ts +++ b/packages/aws-cdk/lib/api/deployment-target.ts @@ -1,4 +1,4 @@ -import cxapi = require('@aws-cdk/cx-api'); +import { ICloudFormationStackArtifact } from '@aws-cdk/cx-api'; import { debug } from '../logging'; import { deserializeStructure } from '../serialize'; import { Mode } from './aws-auth/credentials'; @@ -16,12 +16,12 @@ export type Template = { [key: string]: any }; * Provisioners apply templates to the cloud infrastructure. */ export interface IDeploymentTarget { - readCurrentTemplate(stack: cxapi.SynthesizedStack): Promise