From af3c695949925d368fd76a3491d4940a9ae17001 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 12:14:26 +0200 Subject: [PATCH 01/24] feat(core): democratize synthesis This change enables each construct in the tree to participate in synthesis by overriding the "synthesize" method and emitting files to the session directory. It is a small step towards generalizing how synthesis artifacts are being produced, built and deployed by the CDK. This change moves the code that synthesizes a CloudFormation template from a CDK stack to the `Stack` class and emits a `.template.json` file for each stack. The CLI hasn't been changed to work with these new files yet, so the output of this file is ALSO included in the main manifest (defined `cxapi.OUTFILE_NAME`), which is the only file currently being read by the CLI. --- packages/@aws-cdk/cdk/lib/app.ts | 115 ++++++------------ .../@aws-cdk/cdk/lib/cloudformation/stack.ts | 59 ++++++++- packages/@aws-cdk/cdk/lib/core/construct.ts | 52 ++++++-- packages/@aws-cdk/cdk/lib/index.ts | 2 + packages/@aws-cdk/cdk/lib/synthesis.ts | 98 +++++++++++++++ packages/@aws-cdk/cdk/test/test.app.ts | 16 +-- 6 files changed, 241 insertions(+), 101 deletions(-) create mode 100644 packages/@aws-cdk/cdk/lib/synthesis.ts diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index f7f2994f8c393..3c0e89e6f9794 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -1,14 +1,13 @@ import cxapi = require('@aws-cdk/cx-api'); -import fs = require('fs'); -import path = require('path'); import { Stack } from './cloudformation/stack'; -import { IConstruct, MetadataEntry, PATH_SEP, Root } from './core/construct'; +import { Root } from './core/construct'; +import { InMemorySynthesisSession, ISynthesisSession, SynthesisSession } from './synthesis'; /** * Represents a CDK program. */ export class App extends Root { - private prepared = false; + private _session?: ISynthesisSession; /** * Initializes a CDK application. @@ -34,23 +33,32 @@ export class App extends Root { /** * Runs the program. Output is written to output directory as specified in the request. */ - public run(): void { + public run(): ISynthesisSession { + // this app has already been executed, no-op for you + if (this._session) { + return this._session; + } + const outdir = process.env[cxapi.OUTDIR_ENV]; - if (!outdir) { - process.stderr.write(`ERROR: The environment variable "${cxapi.OUTDIR_ENV}" is not defined\n`); - process.stderr.write('AWS CDK Toolkit (>= 0.11.0) is required in order to interact with this program.\n'); - process.exit(1); - return; + if (outdir) { + this._session = new SynthesisSession({ outdir }); + } else { + this._session = new InMemorySynthesisSession(); } - const result: cxapi.SynthesizeResponse = { - version: cxapi.PROTO_RESPONSE_VERSION, - stacks: this.synthesizeStacks(Object.keys(this.stacks)), - runtime: this.collectRuntimeInformation() - }; + // the three holy phases of synthesis: validate, prepare and synthesize + const errors = this.node.validateTree(); + if (errors.length > 0) { + const errorList = errors.map(e => `[${e.source.node.path}] ${e.message}`).join('\n '); + throw new Error(`Validation failed with the following errors:\n ${errorList}`); + } - const outfile = path.join(outdir, cxapi.OUTFILE_NAME); - fs.writeFileSync(outfile, JSON.stringify(result, undefined, 2)); + this.node.prepareTree(); + this.node.synthesizeTree(this.run()); + + this._session.finalize(); // lock session - cannot emit more artifacts + + return this._session; } /** @@ -58,49 +66,16 @@ export class App extends Root { * @param stackName The name of the stack to synthesize */ public synthesizeStack(stackName: string): cxapi.SynthesizedStack { - const stack = this.getStack(stackName); - - if (!this.prepared) { - // Maintain the existing contract that the tree will be prepared even if - // 'synthesizeStack' is called by itself. But only prepare the tree once. - this.node.prepareTree(); - this.prepared = true; - } - - // first, validate this stack and stop if there are errors. - const errors = stack.node.validateTree(); - if (errors.length > 0) { - const errorList = errors.map(e => `[${e.source.node.path}] ${e.message}`).join('\n '); - throw new Error(`Stack validation failed with the following errors:\n ${errorList}`); - } - - const account = stack.env.account || 'unknown-account'; - const region = stack.env.region || 'unknown-region'; + this.getStack(stackName); // just make sure stack exists - const environment: cxapi.Environment = { - name: `${account}/${region}`, - account, - region - }; - - const missing = Object.keys(stack.missingContext).length ? stack.missingContext : undefined; - return { - name: stack.node.id, - environment, - missing, - template: stack.toCloudFormation(), - metadata: this.collectMetadata(stack), - dependsOn: noEmptyArray(stack.dependencies().map(s => s.node.id)), - }; + const artifact = this.run().readFile(Stack.artifactIdForStack(stackName)); + return JSON.parse(artifact); } /** * Synthesizes multiple stacks */ public synthesizeStacks(stackNames: string[]): cxapi.SynthesizedStack[] { - this.node.prepareTree(); - this.prepared = true; - const ret: cxapi.SynthesizedStack[] = []; for (const stackName of stackNames) { ret.push(this.synthesizeStack(stackName)); @@ -109,30 +84,16 @@ export class App extends Root { } /** - * Returns metadata for all constructs in the stack. + * Synthesize the app manifest (the root file which the toolkit reads) */ - public collectMetadata(stack: Stack) { - const output: { [id: string]: MetadataEntry[] } = { }; - - visit(stack); - - // add app-level metadata under "." - if (this.node.metadata.length > 0) { - output[PATH_SEP] = this.node.metadata; - } - - return output; - - function visit(node: IConstruct) { - if (node.node.metadata.length > 0) { - // Make the path absolute - output[PATH_SEP + node.node.path] = node.node.metadata.map(md => node.node.resolve(md) as MetadataEntry); - } + protected synthesize(session: ISynthesisSession) { + const manifest: cxapi.SynthesizeResponse = { + version: cxapi.PROTO_RESPONSE_VERSION, + stacks: this.synthesizeStacks(Object.keys(this.stacks)), + runtime: this.collectRuntimeInformation() + }; - for (const child of node.node.children) { - visit(child); - } - } + session.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(manifest, undefined, 2)); } private collectRuntimeInformation(): cxapi.AppRuntime { @@ -239,7 +200,3 @@ function getJsiiAgentVersion() { return jsiiAgent; } - -function noEmptyArray(xs: T[]): T[] | undefined { - return xs.length > 0 ? xs : undefined; -} diff --git a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts index 4f5e38e1f27b8..1e079140a99c4 100644 --- a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts +++ b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts @@ -1,7 +1,8 @@ import cxapi = require('@aws-cdk/cx-api'); import { App } from '../app'; -import { Construct, IConstruct } from '../core/construct'; +import { Construct, IConstruct, PATH_SEP } from '../core/construct'; import { Environment } from '../environment'; +import { ISynthesisSession } from '../synthesis'; import { CfnReference } from './cfn-tokens'; import { HashedAddressingScheme, IAddressingScheme, LogicalIDs } from './logical-id'; @@ -48,6 +49,10 @@ export class Stack extends Construct { return (construct as any)._isStack; } + public static artifactIdForStack(stackName: string) { + return `${stackName}.template.json`; + } + private static readonly VALID_STACK_NAME_REGEX = /^[A-Za-z][A-Za-z0-9-]*$/; /** @@ -125,6 +130,54 @@ export class Stack extends Construct { return r as Resource; } + public synthesize(session: ISynthesisSession): void { + const account = this.env.account || 'unknown-account'; + const region = this.env.region || 'unknown-region'; + + const environment: cxapi.Environment = { + name: `${account}/${region}`, + account, + region + }; + + const missing = Object.keys(this.missingContext).length ? this.missingContext : undefined; + + const output: cxapi.SynthesizedStack = { + name: this.node.id, + template: this.toCloudFormation(), + environment, + missing, + metadata: this.collectMetadata(), + dependsOn: noEmptyArray(this.dependencies().map(s => s.node.id)), + }; + + session.writeFile(Stack.artifactIdForStack(this.node.id), JSON.stringify(output, undefined, 2)); + } + + public collectMetadata() { + const output: { [id: string]: cxapi.MetadataEntry[] } = { }; + + visit(this); + + const app = this.parentApp(); + if (app && app.node.metadata.length > 0) { + output[PATH_SEP] = app.node.metadata; + } + + return output; + + function visit(node: IConstruct) { + if (node.node.metadata.length > 0) { + // Make the path absolute + output[PATH_SEP + node.node.path] = node.node.metadata.map(md => node.node.resolve(md) as cxapi.MetadataEntry); + } + + for (const child of node.node.children) { + visit(child); + } + } + } + /** * Returns the CloudFormation template for this stack by traversing * the tree and invoking toCloudFormation() on all Entity objects. @@ -530,3 +583,7 @@ function findResources(roots: Iterable): Resource[] { } return ret; } + +function noEmptyArray(xs: T[]): T[] | undefined { + return xs.length > 0 ? xs : undefined; +} diff --git a/packages/@aws-cdk/cdk/lib/core/construct.ts b/packages/@aws-cdk/cdk/lib/core/construct.ts index 0a4a12cf7fef5..dfd9c89e70102 100644 --- a/packages/@aws-cdk/cdk/lib/core/construct.ts +++ b/packages/@aws-cdk/cdk/lib/core/construct.ts @@ -1,10 +1,12 @@ import cxapi = require('@aws-cdk/cx-api'); import { IAspect } from '../aspects/aspect'; import { CloudFormationJSON } from '../cloudformation/cloudformation-json'; +import { ISynthesisSession } from '../synthesis'; import { makeUniqueId } from '../util/uniqueid'; import { IDependable } from './dependency'; import { Token, unresolved } from './tokens'; import { resolve } from './tokens/resolve'; + export const PATH_SEP = '/'; /** @@ -190,15 +192,22 @@ export class ConstructNode { */ public findAll(order: ConstructOrder = ConstructOrder.DepthFirst): IConstruct[] { const ret = new Array(); - const queue: IConstruct[] = [this.host]; + visit(this.host); + return ret; - while (queue.length > 0) { - const next = order === ConstructOrder.BreadthFirst ? queue.splice(0, 1)[0] : queue.pop()!; - ret.push(next); - queue.push(...next.node.children); - } + function visit(node: IConstruct) { + if (order === ConstructOrder.BreadthFirst) { + ret.push(node); + } - return ret; + for (const child of node.node.children) { + visit(child); + } + + if (order === ConstructOrder.DepthFirst) { + ret.push(node); + } + } } /** @@ -332,6 +341,19 @@ export class ConstructNode { } } + /** + * Synthesizes the entire subtree by writing artifacts into a synthesis session. + */ + public synthesizeTree(session: ISynthesisSession) { + const constructs = this.host.node.findAll(ConstructOrder.DepthFirst); + + for (const construct of constructs) { + if (Construct.isConstruct(construct)) { + (construct as any).synthesize(session); + } + } + } + /** * Applies the aspect to this Constructs node */ @@ -626,9 +648,23 @@ export class Construct implements IConstruct { * understand the implications. */ protected prepare(): void { - // Intentionally left blank + return; } + /** + * Synthesizes this construct into artifacts. + * + * This method can be overloaded by any construct that wishes to emit artifacts during + * the tree synthesis. For example, the `Stack` construct overrides this and produces + * CloudFormation templates, `Asset` overrides this to produce asset artifacts, etc. + * + * To emit artifacts, use the API of the `Session` argument. + * + * @param _session synthesis session + */ + protected synthesize(_session: ISynthesisSession): void { + return; + } } /** diff --git a/packages/@aws-cdk/cdk/lib/index.ts b/packages/@aws-cdk/cdk/lib/index.ts index 49ffef7cdb7bf..6b4e11a8fb43a 100644 --- a/packages/@aws-cdk/cdk/lib/index.ts +++ b/packages/@aws-cdk/cdk/lib/index.ts @@ -32,3 +32,5 @@ export * from './context'; export * from './environment'; export * from './runtime'; + +export * from './synthesis'; \ No newline at end of file diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts new file mode 100644 index 0000000000000..3d3d03e7c3cd5 --- /dev/null +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -0,0 +1,98 @@ +import fs = require('fs'); +import path = require('path'); + +export interface ISynthesisSession { + /** + * Writes a file into the synthesis session directory. + * @param fileName The name of the file. + * @param data The contents of the file. + */ + writeFile(fileName: string, data: any): void; + + /** + * Reads a file from the synthesis session directory. + * @param fileName The name of the file. + * @throws if the file is not found + */ + readFile(fileName: string): any; + + /** + * Finalizes the session. After this is called, the session will be locked for + * writing. + */ + finalize(): void; +} + +export interface SynthesisSessionOptions { + /** + * The output directory for synthesis artifacts + */ + outdir: string; +} + +/** + * Can be used to prepare and emit synthesis artifacts into an output directory. + */ +export class SynthesisSession implements ISynthesisSession { + private readonly outdir: string; + private locked = false; + + constructor(options: SynthesisSessionOptions) { + this.outdir = options.outdir; + return; + } + + public writeFile(fileName: string, data: any) { + if (this.locked) { + throw new Error('Session has already been finalized'); + } + const p = this.pathForArtifact(fileName); + if (fs.existsSync(p)) { + throw new Error(`File ${p} already exists`); + } + fs.writeFileSync(p, data); + } + + 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 finalize() { + this.locked = true; + } + + private pathForArtifact(id: string) { + return path.join(this.outdir, id); + } +} + +export class InMemorySynthesisSession implements ISynthesisSession { + private store: { [fileName: string]: any } = { }; + private locked = false; + + public writeFile(fileName: string, data: any): void { + if (this.locked) { + throw new Error(`Session has already been finalized`); + } + if (fileName in this.store) { + throw new Error(`${fileName} already exists`); + } + this.store[fileName] = data; + } + + public readFile(fileName: string) { + if (!(fileName in this.store)) { + throw new Error(`${fileName} not found`); + } + return this.store[fileName]; + } + + public finalize() { + this.locked = true; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cdk/test/test.app.ts b/packages/@aws-cdk/cdk/test/test.app.ts index b0e5edff50db5..2bc831ccdde76 100644 --- a/packages/@aws-cdk/cdk/test/test.app.ts +++ b/packages/@aws-cdk/cdk/test/test.app.ts @@ -1,15 +1,9 @@ import cxapi = require('@aws-cdk/cx-api'); -import fs = require('fs'); import { Test } from 'nodeunit'; -import os = require('os'); -import path = require('path'); import { Construct, Resource, Stack, StackProps } from '../lib'; import { App } from '../lib/app'; function withApp(context: { [key: string]: any } | undefined, block: (app: App) => void) { - const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-app-test')); - process.env[cxapi.OUTDIR_ENV] = outdir; - if (context) { process.env[cxapi.CONTEXT_ENV] = JSON.stringify(context); } else { @@ -20,13 +14,9 @@ function withApp(context: { [key: string]: any } | undefined, block: (app: App) block(app); - app.run(); + const session = app.run(); - const outfile = path.join(outdir, cxapi.OUTFILE_NAME); - const response = JSON.parse(fs.readFileSync(outfile).toString()); - fs.unlinkSync(outfile); - fs.rmdirSync(outdir); - return response; + return JSON.parse(session.readFile(cxapi.OUTFILE_NAME)); } function synth(context?: { [key: string]: any }): cxapi.SynthesizeResponse { @@ -212,7 +202,7 @@ export = { test.throws(() => { app.synthesizeStacks(['Parent']); - }, /Stack validation failed with the following errors/); + }, /Validation failed with the following errors/); test.done(); }, From f00f5afa05c8415ac0f67cda815ad9b47c2cbac3 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 14:20:42 +0200 Subject: [PATCH 02/24] move "prepare" before "validate" --- packages/@aws-cdk/cdk/lib/app.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 3c0e89e6f9794..142b6ec1ee097 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -46,17 +46,23 @@ export class App extends Root { this._session = new InMemorySynthesisSession(); } - // the three holy phases of synthesis: validate, prepare and synthesize + // the three holy phases of synthesis: prepare, validate and synthesize + + // prepare + this.node.prepareTree(); + + // validate const errors = this.node.validateTree(); if (errors.length > 0) { const errorList = errors.map(e => `[${e.source.node.path}] ${e.message}`).join('\n '); throw new Error(`Validation failed with the following errors:\n ${errorList}`); } - this.node.prepareTree(); - this.node.synthesizeTree(this.run()); + // synthesize + this.node.synthesizeTree(this._session); - this._session.finalize(); // lock session - cannot emit more artifacts + // lock session - cannot emit more artifacts + this._session.finalize(); return this._session; } From c23f0c6460973668aeecec84f0a20d3b25daa560 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 14:20:58 +0200 Subject: [PATCH 03/24] Use stack's uniqueId as artifact name instead of just id --- packages/@aws-cdk/cdk/lib/app.ts | 5 ++--- packages/@aws-cdk/cdk/lib/cloudformation/stack.ts | 13 ++++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 142b6ec1ee097..d3c2c547ac578 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -72,9 +72,8 @@ export class App extends Root { * @param stackName The name of the stack to synthesize */ public synthesizeStack(stackName: string): cxapi.SynthesizedStack { - this.getStack(stackName); // just make sure stack exists - - const artifact = this.run().readFile(Stack.artifactIdForStack(stackName)); + const stack = this.getStack(stackName); + const artifact = this.run().readFile(stack.artifactName); return JSON.parse(artifact); } diff --git a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts index 1e079140a99c4..25942a2925a3e 100644 --- a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts +++ b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts @@ -49,10 +49,6 @@ export class Stack extends Construct { return (construct as any)._isStack; } - public static artifactIdForStack(stackName: string) { - return `${stackName}.template.json`; - } - private static readonly VALID_STACK_NAME_REGEX = /^[A-Za-z][A-Za-z0-9-]*$/; /** @@ -82,6 +78,11 @@ export class Stack extends Construct { */ public readonly name: string; + /** + * The name of the CDK artifact produced by this stack. + */ + public readonly artifactName: string; + /* * Used to determine if this construct is a stack. */ @@ -111,6 +112,8 @@ export class Stack extends Construct { this.logicalIds = new LogicalIDs(props && props.namingScheme ? props.namingScheme : new HashedAddressingScheme()); this.name = this.node.id; + + this.artifactName = `${this.node.uniqueId}.stack.json`; } /** @@ -151,7 +154,7 @@ export class Stack extends Construct { dependsOn: noEmptyArray(this.dependencies().map(s => s.node.id)), }; - session.writeFile(Stack.artifactIdForStack(this.node.id), JSON.stringify(output, undefined, 2)); + session.writeFile(this.artifactName, JSON.stringify(output, undefined, 2)); } public collectMetadata() { From 25a96f94963a9a08d7f427dba75260b8ea295d85 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 17:06:20 +0200 Subject: [PATCH 04/24] Move manifest creation to `run` and don't use synthesizeStacks --- packages/@aws-cdk/cdk/lib/app.ts | 52 ++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index d3c2c547ac578..4d82ca5d99f13 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -1,6 +1,6 @@ import cxapi = require('@aws-cdk/cx-api'); import { Stack } from './cloudformation/stack'; -import { Root } from './core/construct'; +import { IConstruct, Root } from './core/construct'; import { InMemorySynthesisSession, ISynthesisSession, SynthesisSession } from './synthesis'; /** @@ -20,14 +20,18 @@ export class App extends Root { private get stacks() { const out: { [name: string]: Stack } = { }; - for (const child of this.node.children) { - if (!Stack.isStack(child)) { - throw new Error(`The child ${child.toString()} of App must be a Stack`); - } + collectStacks(this); + return out; + + function collectStacks(c: IConstruct) { + for (const child of c.node.children) { + if (Stack.isStack(child)) { + out[child.node.uniqueId] = child; + } - out[child.node.id] = child as Stack; + collectStacks(child); + } } - return out; } /** @@ -46,6 +50,8 @@ export class App extends Root { this._session = new InMemorySynthesisSession(); } + const session = this._session; + // the three holy phases of synthesis: prepare, validate and synthesize // prepare @@ -59,17 +65,29 @@ export class App extends Root { } // synthesize - this.node.synthesizeTree(this._session); + this.node.synthesizeTree(session); + + // write the entrypoint/manifest of this app. It includes a *copy* of the + // synthesized stack output for backwards compatibility + + const manifest: cxapi.SynthesizeResponse = { + version: cxapi.PROTO_RESPONSE_VERSION, + stacks: Object.values(this.stacks).map(s => session.readFile(s.artifactName)), + runtime: this.collectRuntimeInformation() + }; + + session.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(manifest, undefined, 2)); // lock session - cannot emit more artifacts - this._session.finalize(); + session.finalize(); - return this._session; + return 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 { const stack = this.getStack(stackName); @@ -79,6 +97,7 @@ export class App extends Root { /** * 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[] = []; @@ -88,19 +107,6 @@ export class App extends Root { return ret; } - /** - * Synthesize the app manifest (the root file which the toolkit reads) - */ - protected synthesize(session: ISynthesisSession) { - const manifest: cxapi.SynthesizeResponse = { - version: cxapi.PROTO_RESPONSE_VERSION, - stacks: this.synthesizeStacks(Object.keys(this.stacks)), - runtime: this.collectRuntimeInformation() - }; - - session.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(manifest, undefined, 2)); - } - private collectRuntimeInformation(): cxapi.AppRuntime { const libraries: { [name: string]: string } = {}; From 1920c9b5db1e3937986cf3d606deee3678365ab6 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 17:06:44 +0200 Subject: [PATCH 05/24] fix visibility modifiers of Stack methods --- .../@aws-cdk/cdk/lib/cloudformation/stack.ts | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts index 25942a2925a3e..8879f20c4f9ec 100644 --- a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts +++ b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts @@ -133,54 +133,6 @@ export class Stack extends Construct { return r as Resource; } - public synthesize(session: ISynthesisSession): void { - const account = this.env.account || 'unknown-account'; - const region = this.env.region || 'unknown-region'; - - const environment: cxapi.Environment = { - name: `${account}/${region}`, - account, - region - }; - - const missing = Object.keys(this.missingContext).length ? this.missingContext : undefined; - - const output: cxapi.SynthesizedStack = { - name: this.node.id, - template: this.toCloudFormation(), - environment, - missing, - metadata: this.collectMetadata(), - dependsOn: noEmptyArray(this.dependencies().map(s => s.node.id)), - }; - - session.writeFile(this.artifactName, JSON.stringify(output, undefined, 2)); - } - - public collectMetadata() { - const output: { [id: string]: cxapi.MetadataEntry[] } = { }; - - visit(this); - - const app = this.parentApp(); - if (app && app.node.metadata.length > 0) { - output[PATH_SEP] = app.node.metadata; - } - - return output; - - function visit(node: IConstruct) { - if (node.node.metadata.length > 0) { - // Make the path absolute - output[PATH_SEP + node.node.path] = node.node.metadata.map(md => node.node.resolve(md) as cxapi.MetadataEntry); - } - - for (const child of node.node.children) { - visit(child); - } - } - } - /** * Returns the CloudFormation template for this stack by traversing * the tree and invoking toCloudFormation() on all Entity objects. @@ -473,6 +425,30 @@ export class Stack extends Construct { } } + protected synthesize(session: ISynthesisSession): void { + const account = this.env.account || 'unknown-account'; + const region = this.env.region || 'unknown-region'; + + const environment: cxapi.Environment = { + name: `${account}/${region}`, + account, + region + }; + + const missing = Object.keys(this.missingContext).length ? this.missingContext : undefined; + + const output: cxapi.SynthesizedStack = { + name: this.node.id, + template: this.toCloudFormation(), + environment, + missing, + metadata: this.collectMetadata(), + dependsOn: noEmptyArray(this.dependencies().map(s => s.node.id)), + }; + + session.writeFile(this.artifactName, JSON.stringify(output, undefined, 2)); + } + /** * Applied defaults to environment attributes. */ @@ -503,6 +479,30 @@ export class Stack extends Construct { } return false; } + + private collectMetadata() { + const output: { [id: string]: cxapi.MetadataEntry[] } = { }; + + visit(this); + + const app = this.parentApp(); + if (app && app.node.metadata.length > 0) { + output[PATH_SEP] = app.node.metadata; + } + + return output; + + function visit(node: IConstruct) { + if (node.node.metadata.length > 0) { + // Make the path absolute + output[PATH_SEP + node.node.path] = node.node.metadata.map(md => node.node.resolve(md) as cxapi.MetadataEntry); + } + + for (const child of node.node.children) { + visit(child); + } + } + } } function merge(template: any, part: any) { From 89827fdd2036f83eca02a7fbc09e0c88ca76739d Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 17:08:53 +0200 Subject: [PATCH 06/24] add "mkdir", "readdir", "exists" and "list" to synth session and add unit tests --- packages/@aws-cdk/cdk/lib/synthesis.ts | 123 +++++++++++++++--- packages/@aws-cdk/cdk/test/test.synthesis.ts | 130 +++++++++++++++++++ 2 files changed, 235 insertions(+), 18 deletions(-) create mode 100644 packages/@aws-cdk/cdk/test/test.synthesis.ts diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index 3d3d03e7c3cd5..b824d970529f5 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -1,13 +1,28 @@ import fs = require('fs'); +import os = require('os'); import path = require('path'); export interface ISynthesisSession { + /** + * Creates a directory under the session 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 synthesis session directory. - * @param fileName The name of the file. + * @param artifactName The name of the file. * @param data The contents of the file. */ - writeFile(fileName: string, data: any): void; + writeFile(artifactName: string, data: any): void; /** * Reads a file from the synthesis session directory. @@ -16,6 +31,17 @@ export interface ISynthesisSession { */ readFile(fileName: string): any; + /** + * @returns true if the file `fileName` exists in the session directory. + * @param name The name of the file or directory to look up. + */ + exists(name: string): boolean; + + /** + * List all artifacts that were emitted to the session. + */ + list(): string[]; + /** * Finalizes the session. After this is called, the session will be locked for * writing. @@ -43,13 +69,9 @@ export class SynthesisSession implements ISynthesisSession { } public writeFile(fileName: string, data: any) { - if (this.locked) { - throw new Error('Session has already been finalized'); - } + this.canWrite(fileName); + const p = this.pathForArtifact(fileName); - if (fs.existsSync(p)) { - throw new Error(`File ${p} already exists`); - } fs.writeFileSync(p, data); } @@ -62,6 +84,31 @@ export class SynthesisSession implements ISynthesisSession { return fs.readFileSync(p); } + 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 finalize() { this.locked = true; } @@ -69,30 +116,70 @@ export class SynthesisSession implements ISynthesisSession { 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 InMemorySynthesisSession implements ISynthesisSession { - private store: { [fileName: string]: any } = { }; + 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 { - if (this.locked) { - throw new Error(`Session has already been finalized`); - } - if (fileName in this.store) { - throw new Error(`${fileName} already exists`); - } - this.store[fileName] = data; + this.canWrite(fileName); + this.files[fileName] = data; } public readFile(fileName: string) { - if (!(fileName in this.store)) { + if (!(fileName in this.files)) { throw new Error(`${fileName} not found`); } - return this.store[fileName]; + return this.files[fileName]; + } + + 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 finalize() { 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'); + } + } } \ No newline at end of file diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts new file mode 100644 index 0000000000000..9befcda084c6e --- /dev/null +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -0,0 +1,130 @@ +import fs = require('fs'); +import { Test } from 'nodeunit'; +import os = require('os'); +import path = require('path'); +import cdk = require('../lib'); +import { InMemorySynthesisSession, SynthesisSession } from '../lib'; + +const sessionTestMatix: any = { }; + +export = { + 'constructs that implement "synthesize" can emit artifacts during synthesis'(test: Test) { + // GIVEN + const app = new cdk.App(); + new Synthesizer1(app, 'synthe1'); + const s2 = new Synthesizer2(app, 'synthe2'); + new Synthesizer3(s2, 'synthe3'); + + // WHEN + const session = app.run(); + + // THEN + test.deepEqual(session.readFile('s1.txt'), 'hello, s1'); + test.deepEqual(session.readFile('s2.txt'), 'hello, s2'); + + test.deepEqual(session.list(), [ + 'cdk.out', + 's1.txt', + 's2.txt', + 'synthe2Group0512C945A.txt', + 'synthe2Group181E95665.txt', + 'synthe2Group20BD1A3CD.txt', + 'synthe2synthe30CE80559.txt' + ]); + + test.done(); + }, + + 'session': sessionTestMatix +}; + +const sessionTests = { + 'writeFile()/readFile()'(test: Test, session: cdk.ISynthesisSession) { + // WHEN + session.writeFile('bla.txt', 'hello'); + session.writeFile('hey.txt', '1234'); + + // THEN + test.deepEqual(session.readFile('bla.txt').toString(), 'hello'); + test.deepEqual(session.readFile('hey.txt').toString(), '1234'); + test.throws(() => session.writeFile('bla.txt', 'override is forbidden')); + + // WHEN + session.finalize(); + + // THEN + test.throws(() => session.writeFile('another.txt', 'locked!')); + test.done(); + }, + + 'exists() for files'(test: Test, session: cdk.ISynthesisSession) { + // WHEN + session.writeFile('A.txt', 'aaa'); + + // THEN + test.ok(session.exists('A.txt')); + test.ok(!session.exists('B.txt')); + test.done(); + }, + + 'mkdir'(test: Test, session: cdk.ISynthesisSession) { + // WHEN + const dir1 = session.mkdir('dir1'); + const dir2 = session.mkdir('dir2'); + + // THEN + test.ok(fs.statSync(dir1).isDirectory()); + test.ok(fs.statSync(dir2).isDirectory()); + test.throws(() => session.mkdir('dir1')); + + // WHEN + session.finalize(); + test.throws(() => session.mkdir('dir3')); + test.done(); + }, + + 'list'(test: Test, session: cdk.ISynthesisSession) { + // WHEN + session.mkdir('dir1'); + session.writeFile('file1.txt', 'boom1'); + + // THEN + test.deepEqual(session.list(), [ 'dir1', 'file1.txt' ]); + test.done(); + } +}; + +for (const [ name, fn ] of Object.entries(sessionTests)) { + const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'synthesis-tests')); + const fsSession = new SynthesisSession({ outdir }); + const memorySession = new InMemorySynthesisSession(); + sessionTestMatix[`SynthesisSession - ${name}`] = (test: Test) => fn(test, fsSession); + sessionTestMatix[`InMemorySession - ${name}`] = (test: Test) => fn(test, memorySession); +} + +class Synthesizer1 extends cdk.Construct { + public synthesize(s: cdk.ISynthesisSession) { + s.writeFile('s1.txt', 'hello, s1'); + } +} + +class Synthesizer2 extends cdk.Construct { + constructor(scope: cdk.Construct, id: string) { + super(scope, id); + + const group = new cdk.Construct(this, 'Group'); + for (let i = 0; i < 3; ++i) { + new Synthesizer3(group, `${i}`); + } + } + + public synthesize(s: cdk.ISynthesisSession) { + s.writeFile('s2.txt', 'hello, s2'); + } +} + +class Synthesizer3 extends cdk.Construct { + public synthesize(s: cdk.ISynthesisSession) { + s.writeFile(this.node.uniqueId + '.txt', 'hello, s3'); + } +} From 7a35a9898d30f07bf7148e492ed9fc003ab9d16f Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 17:22:38 +0200 Subject: [PATCH 07/24] read synthesized stacks in a uniform way --- packages/@aws-cdk/cdk/lib/app.ts | 10 ++++-- packages/@aws-cdk/cdk/test/test.synthesis.ts | 38 ++++++++++++++++++-- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 4d82ca5d99f13..87c20b99ac42f 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -72,7 +72,7 @@ export class App extends Root { const manifest: cxapi.SynthesizeResponse = { version: cxapi.PROTO_RESPONSE_VERSION, - stacks: Object.values(this.stacks).map(s => session.readFile(s.artifactName)), + stacks: Object.values(this.stacks).map(s => this.readSynthesizedStack(session, s.artifactName)), runtime: this.collectRuntimeInformation() }; @@ -91,8 +91,8 @@ export class App extends Root { */ public synthesizeStack(stackName: string): cxapi.SynthesizedStack { const stack = this.getStack(stackName); - const artifact = this.run().readFile(stack.artifactName); - return JSON.parse(artifact); + const session = this.run(); + return this.readSynthesizedStack(session, stack.artifactName); } /** @@ -107,6 +107,10 @@ export class App extends Root { return ret; } + private readSynthesizedStack(session: ISynthesisSession, artifactName: string) { + return JSON.parse(session.readFile(artifactName).toString()); + } + private collectRuntimeInformation(): cxapi.AppRuntime { const libraries: { [name: string]: string } = {}; diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index 9befcda084c6e..637149a25be68 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -1,3 +1,4 @@ +import cxapi = require('@aws-cdk/cx-api'); import fs = require('fs'); import { Test } from 'nodeunit'; import os = require('os'); @@ -5,7 +6,7 @@ import path = require('path'); import cdk = require('../lib'); import { InMemorySynthesisSession, SynthesisSession } from '../lib'; -const sessionTestMatix: any = { }; +const sessionTestMatix: any = {}; export = { 'constructs that implement "synthesize" can emit artifacts during synthesis'(test: Test) { @@ -35,6 +36,37 @@ export = { test.done(); }, + 'cdk.out contains all synthesized stacks'(test: Test) { + // GIVEN + const app = new cdk.App(); + const stack1 = new cdk.Stack(app, 'stack1'); + new cdk.Resource(stack1, 'Resource1', { type: 'AWS::CDK::Resource' }); + new cdk.Resource(stack1, 'Resource2', { type: 'AWS::CDK::Resource' }); + const stack2 = new cdk.Stack(app, 'stack2'); + new cdk.Resource(stack2, 'ResourceA', { type: 'AWS::CDK::Resource' }); + + // WHEN + const session = app.run(); + const manifest: cxapi.SynthesizeResponse = JSON.parse(session.readFile(cxapi.OUTFILE_NAME).toString()); + + // THEN + const t1 = manifest.stacks.find(s => s.name === 'stack1')!.template; + const t2 = manifest.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(); + }, + 'session': sessionTestMatix }; @@ -89,12 +121,12 @@ const sessionTests = { session.writeFile('file1.txt', 'boom1'); // THEN - test.deepEqual(session.list(), [ 'dir1', 'file1.txt' ]); + test.deepEqual(session.list(), ['dir1', 'file1.txt']); test.done(); } }; -for (const [ name, fn ] of Object.entries(sessionTests)) { +for (const [name, fn] of Object.entries(sessionTests)) { const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'synthesis-tests')); const fsSession = new SynthesisSession({ outdir }); const memorySession = new InMemorySynthesisSession(); From 82622e7454be4fa3a879da1b360d6bbbf125ba9d Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 17:23:14 +0200 Subject: [PATCH 08/24] fix applet tests --- packages/@aws-cdk/applet-js/test/test.applets.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/applet-js/test/test.applets.ts b/packages/@aws-cdk/applet-js/test/test.applets.ts index 7d8f67ad03807..1e0cd80f67fc8 100644 --- a/packages/@aws-cdk/applet-js/test/test.applets.ts +++ b/packages/@aws-cdk/applet-js/test/test.applets.ts @@ -80,16 +80,17 @@ function synthesizeApplet(yamlFile: string, direct = false) { const command = direct ? yamlFile : 'cdk-applet-js'; const args = direct ? [] : [yamlFile]; + const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-applet-tests')); child_process.execFileSync(command, args, { env: { ...process.env, - CDK_OUTDIR: os.tmpdir(), + CDK_OUTDIR: outdir, PATH: 'bin:' + process.env.PATH } }); - return JSON.parse(fs.readFileSync(path.join(os.tmpdir(), 'cdk.out'), { encoding: 'utf-8' })); + return JSON.parse(fs.readFileSync(path.join(outdir, 'cdk.out'), { encoding: 'utf-8' })); } function getStack(stackName: string, allStacks: any) { From 6aea527bcd1b9c73b4cf65cbccf004be81f68731 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 17:49:03 +0200 Subject: [PATCH 09/24] identify stacks by id and not uniqueid (for now) --- packages/@aws-cdk/cdk/lib/app.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 87c20b99ac42f..28d1402c7b886 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -26,7 +26,7 @@ export class App extends Root { function collectStacks(c: IConstruct) { for (const child of c.node.children) { if (Stack.isStack(child)) { - out[child.node.uniqueId] = child; + out[child.node.id] = child; // TODO: this should probably be changed to uniqueId } collectStacks(child); @@ -140,6 +140,7 @@ export class App extends Root { } const stack = this.stacks[stackname]; + if (!stack) { throw new Error(`Cannot find stack ${stackname}`); } From ab0daa31d0323cce703831d6abe57cc9f5775c0e Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 18:20:44 +0200 Subject: [PATCH 10/24] change findAll API to PreOrder/PostOrder instead of Depth/Breadth --- packages/@aws-cdk/cdk/lib/core/construct.ts | 18 +++++++++--------- .../@aws-cdk/cdk/test/core/test.construct.ts | 17 ++++++++++++++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/core/construct.ts b/packages/@aws-cdk/cdk/lib/core/construct.ts index dfd9c89e70102..9daf54c1bd2f8 100644 --- a/packages/@aws-cdk/cdk/lib/core/construct.ts +++ b/packages/@aws-cdk/cdk/lib/core/construct.ts @@ -190,13 +190,13 @@ export class ConstructNode { /** * Return this construct and all of its children in the given order */ - public findAll(order: ConstructOrder = ConstructOrder.DepthFirst): IConstruct[] { + public findAll(order: ConstructOrder = ConstructOrder.PreOrder): IConstruct[] { const ret = new Array(); visit(this.host); return ret; function visit(node: IConstruct) { - if (order === ConstructOrder.BreadthFirst) { + if (order === ConstructOrder.PreOrder) { ret.push(node); } @@ -204,7 +204,7 @@ export class ConstructNode { visit(child); } - if (order === ConstructOrder.DepthFirst) { + if (order === ConstructOrder.PostOrder) { ret.push(node); } } @@ -328,7 +328,7 @@ export class ConstructNode { * Run 'prepare()' on all constructs in the tree */ public prepareTree() { - const constructs = this.host.node.findAll(ConstructOrder.BreadthFirst); + const constructs = this.host.node.findAll(ConstructOrder.PreOrder); // Aspects are applied root to leaf for (const construct of constructs) { construct.node.invokeAspects(); @@ -345,7 +345,7 @@ export class ConstructNode { * Synthesizes the entire subtree by writing artifacts into a synthesis session. */ public synthesizeTree(session: ISynthesisSession) { - const constructs = this.host.node.findAll(ConstructOrder.DepthFirst); + const constructs = this.host.node.findAll(ConstructOrder.PostOrder); for (const construct of constructs) { if (Construct.isConstruct(construct)) { @@ -725,14 +725,14 @@ function createStackTrace(below: Function): string[] { */ export enum ConstructOrder { /** - * Breadth first + * Depth-first, pre-order */ - BreadthFirst, + PreOrder, /** - * Depth first + * Depth-first, post-order (leaf nodes first) */ - DepthFirst + PostOrder } /** diff --git a/packages/@aws-cdk/cdk/test/core/test.construct.ts b/packages/@aws-cdk/cdk/test/core/test.construct.ts index 851d179a53200..a711efa001360 100644 --- a/packages/@aws-cdk/cdk/test/core/test.construct.ts +++ b/packages/@aws-cdk/cdk/test/core/test.construct.ts @@ -1,6 +1,6 @@ import cxapi = require('@aws-cdk/cx-api'); import { Test } from 'nodeunit'; -import { ArnComponents, Construct, Root, Stack, Token } from '../../lib'; +import { ArnComponents, Construct, ConstructOrder, Root, Stack, Token } from '../../lib'; // tslint:disable:variable-name // tslint:disable:max-line-length @@ -446,6 +446,21 @@ export = { new Construct(c1a, 'c1aZ'); new Construct(c1b, 'c1bZ'); + test.done(); + }, + + 'findAll returns a list of all children in either DFS or BFS'(test: Test) { + // GIVEN + const c1 = new Construct(undefined as any, '1'); + const c2 = new Construct(c1, '2'); + new Construct(c1, '3'); + new Construct(c2, '4'); + new Construct(c2, '5'); + + // THEN + test.deepEqual(c1.node.findAll().map(x => x.node.id), c1.node.findAll(ConstructOrder.PreOrder).map(x => x.node.id)); // default is PreOrder + test.deepEqual(c1.node.findAll(ConstructOrder.PreOrder).map(x => x.node.id), [ '1', '2', '4', '5', '3' ]); + test.deepEqual(c1.node.findAll(ConstructOrder.PostOrder).map(x => x.node.id), [ '4', '5', '2', '3', '1' ]); test.done(); } }; From 3912e28fc7f1a1b3762be5fbdded193b41d5cd5e Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 19:16:32 +0200 Subject: [PATCH 11/24] remove unused bundled deps --- packages/@aws-cdk/cdk/package-lock.json | 11306 +++++++++++++++++++++- packages/@aws-cdk/cdk/package.json | 8 +- 2 files changed, 11198 insertions(+), 116 deletions(-) diff --git a/packages/@aws-cdk/cdk/package-lock.json b/packages/@aws-cdk/cdk/package-lock.json index ae37325b5aad3..f65537671951a 100644 --- a/packages/@aws-cdk/cdk/package-lock.json +++ b/packages/@aws-cdk/cdk/package-lock.json @@ -1,111 +1,11199 @@ { - "name": "@aws-cdk/cdk", - "version": "0.23.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/js-base64": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-2.3.1.tgz", - "integrity": "sha512-4RKbhIDGC87s4EBy2Cp2/5S2O6kmCRcZnD5KRCq1q9z2GhBte1+BdsfVKCpG8yKpDGNyEE2G6IqFIh6W2YwWPA==", - "dev": true - }, - "@types/lodash": { - "version": "4.14.120", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.120.tgz", - "integrity": "sha512-jQ21kQ120mo+IrDs1nFNVm/AsdFxIx2+vZ347DbogHJPd/JzKNMOqU6HCYin1W6v8l5R9XSO2/e9cxmn7HAnVw==", - "dev": true - }, - "cli-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.1.7.tgz", - "integrity": "sha1-rcMgD6RxzCEbDaf1ZrcemLnWc0c=", - "requires": { - "es5-ext": "0.8.x" - } - }, - "difflib": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", - "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=", - "requires": { - "heap": ">= 0.2.0" - } - }, - "dreamopt": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.6.0.tgz", - "integrity": "sha1-2BPM2sjTnYrVJndVFKE92mZNa0s=", - "requires": { - "wordwrap": ">=0.0.2" - } - }, - "es5-ext": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.8.2.tgz", - "integrity": "sha1-q6jZ4ZQ6iVrJaDemKjmz9V7NlKs=" - }, - "fast-check": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-1.10.0.tgz", - "integrity": "sha512-6MoIj+RsnMWNX1cB5IY79Jlt6FPyQ0b7ur+sbJVaQ8F+xWz2E0vyS/HZzhDwrq5ZFxQF95HZdDaRLwFTiAy9Bg==", - "dev": true, - "requires": { - "lorem-ipsum": "~1.0.6", - "pure-rand": "^1.6.2" - } - }, - "heap": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", - "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" - }, - "js-base64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==" - }, - "json-diff": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.3.1.tgz", - "integrity": "sha1-bbw64tJeB1p/1xvNmHRFhmb7aBs=", - "requires": { - "cli-color": "~0.1.6", - "difflib": "~0.2.1", - "dreamopt": "~0.6.0" - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "lorem-ipsum": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-1.0.6.tgz", - "integrity": "sha512-Rx4XH8X4KSDCKAVvWGYlhAfNqdUP5ZdT4rRyf0jjrvWgtViZimDIlopWNfn/y3lGM5K4uuiAoY28TaD+7YKFrQ==", - "dev": true, - "requires": { - "minimist": "~1.2.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "pure-rand": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-1.6.2.tgz", - "integrity": "sha512-HNwHOH63m7kCxe0kWEe5jSLwJiL2N83RUUN8POniFuZS+OsbFcMWlvXgxIU2nwKy2zYG2bQan40WBNK4biYPRg==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - } - } + "name": "@aws-cdk/cdk", + "version": "0.24.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@aws-cdk/cx-api": { + "version": "0.24.1", + "dependencies": { + "cdk-build-tools": { + "bundled": true, + "requires": { + "awslint": "^0.24.1", + "fs-extra": "^7.0.0", + "jsii": "^0.7.13", + "jsii-pacmak": "^0.7.13", + "nodeunit": "^0.11.3", + "nyc": "^13.0.1", + "typescript": "^3.1.2", + "yargs": "^9.0.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "bundled": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.3.2", + "bundled": true, + "requires": { + "@babel/types": "^7.3.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "bundled": 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", + "bundled": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "bundled": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "bundled": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.3.2", + "bundled": true + }, + "@babel/template": { + "version": "7.2.2", + "bundled": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "bundled": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "@babel/types": { + "version": "7.3.2", + "bundled": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ajv": { + "version": "6.8.1", + "bundled": 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-regex": { + "version": "3.0.0", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arg": { + "version": "4.1.0", + "bundled": true + }, + "argparse": { + "version": "1.0.10", + "bundled": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1": { + "version": "0.2.4", + "bundled": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "async": { + "version": "2.6.1", + "bundled": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true + }, + "aws4": { + "version": "1.8.0", + "bundled": true + }, + "awslint": { + "version": "0.24.1", + "bundled": true, + "requires": { + "colors": "^1.3.3", + "fs-extra": "^7.0.1", + "jsii-reflect": "^0.7.12", + "yargs": "^12.0.5" + }, + "dependencies": { + "@types/colors": { + "version": "https://registry.npmjs.org/@types/colors/-/colors-1.2.1.tgz", + "bundled": true, + "requires": { + "colors": "*" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/jest": { + "version": "https://registry.npmjs.org/@types/jest/-/jest-23.3.14.tgz", + "bundled": true + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.8.tgz", + "bundled": true + }, + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true + }, + "argparse": { + "version": "1.0.10", + "bundled": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "bundled": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "5.0.0", + "bundled": true + }, + "chalk": { + "version": "2.4.2", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "supports-color": { + "version": "5.5.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "commander": { + "version": "2.19.0", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "diff": { + "version": "3.5.0", + "bundled": true + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "esprima": { + "version": "4.0.1", + "bundled": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "js-tokens": { + "version": "3.0.2", + "bundled": true + }, + "js-yaml": { + "version": "3.12.1", + "bundled": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsii-reflect": { + "version": "0.7.14", + "bundled": true, + "requires": { + "colors": "^1.3.3", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "oo-ascii-tree": "^0.7.14", + "yargs": "^12.0.5" + } + }, + "jsii-spec": { + "version": "0.7.14", + "bundled": true, + "requires": { + "jsonschema": "^1.2.4" + } + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonschema": { + "version": "1.2.4", + "bundled": true + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "4.1.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "oo-ascii-tree": { + "version": "0.7.14", + "bundled": true + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "2.0.0", + "bundled": true + }, + "p-limit": { + "version": "2.1.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "bundled": true + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-parse": { + "version": "1.0.6", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve": { + "version": "1.10.0", + "bundled": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sprintf-js": { + "version": "1.0.3", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "supports-color": { + "version": "2.0.0", + "bundled": true + }, + "tslib": { + "version": "1.9.3", + "bundled": true + }, + "tslint": { + "version": "https://registry.npmjs.org/tslint/-/tslint-5.12.1.tgz", + "bundled": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + } + }, + "tsutils": { + "version": "2.29.0", + "bundled": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "typescript": { + "version": "https://registry.npmjs.org/typescript/-/typescript-3.3.1.tgz", + "bundled": true + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yargs": { + "version": "12.0.5", + "bundled": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bind-obj-methods": { + "version": "2.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "bundled": true + }, + "buffer-from": { + "version": "1.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "5.0.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.2", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "clean-yaml-object": { + "version": "0.1.0", + "bundled": true + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "codemaker": { + "version": "0.7.14", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^2.0.0", + "fs-extra": "^7.0.1" + }, + "dependencies": { + "decamelize": { + "version": "2.0.0", + "bundled": true, + "requires": { + "xregexp": "4.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "color-support": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "combined-stream": { + "version": "1.0.7", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "coveralls": { + "version": "3.0.2", + "bundled": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.11.0", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.85.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-format": { + "version": "2.0.0", + "bundled": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "deep-equal": { + "version": "1.0.1", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "diff": { + "version": "1.4.0", + "bundled": true + }, + "domain-browser": { + "version": "1.2.0", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "bundled": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ejs": { + "version": "2.6.1", + "bundled": true + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "esm": { + "version": "3.2.1", + "bundled": true + }, + "esprima": { + "version": "4.0.1", + "bundled": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true + }, + "events-to-array": { + "version": "1.1.2", + "bundled": true + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flatted": { + "version": "2.0.0", + "bundled": true + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.3.3", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-exists-cached": { + "version": "1.0.0", + "bundled": true + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "function-loop": { + "version": "1.0.1", + "bundled": true + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.10.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "growl": { + "version": "1.10.5", + "bundled": true + }, + "har-schema": { + "version": "2.0.0", + "bundled": true + }, + "har-validator": { + "version": "5.1.3", + "bundled": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "bundled": true + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "bundled": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "bundled": true + }, + "js-yaml": { + "version": "3.12.1", + "bundled": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true + }, + "jsesc": { + "version": "2.5.2", + "bundled": true + }, + "jsii": { + "version": "0.7.14", + "bundled": true, + "requires": { + "case": "^1.6.1", + "colors": "^1.3.3", + "deep-equal": "^1.0.1", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "log4js": "^4.0.1", + "semver": "^5.6.0", + "sort-json": "^2.0.0", + "spdx-license-list": "^5.0.0", + "typescript": "^3.2.4", + "yargs": "^12.0.5" + }, + "dependencies": { + "yargs": { + "version": "12.0.5", + "bundled": 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" + } + } + } + }, + "jsii-pacmak": { + "version": "0.7.14", + "bundled": true, + "requires": { + "clone": "^2.1.2", + "codemaker": "^0.7.14", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "spdx-license-list": "^5.0.0", + "xmlbuilder": "^10.1.1", + "yargs": "^12.0.5" + }, + "dependencies": { + "yargs": { + "version": "12.0.5", + "bundled": 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" + } + } + } + }, + "jsii-spec": { + "version": "0.7.14", + "bundled": true, + "requires": { + "jsonschema": "^1.2.4" + } + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonschema": { + "version": "1.2.4", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "lcov-parse": { + "version": "0.0.10", + "bundled": true + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "bundled": true + }, + "log-driver": { + "version": "1.2.7", + "bundled": true + }, + "log4js": { + "version": "4.0.2", + "bundled": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^3.1.0", + "flatted": "^2.0.0", + "rfdc": "^1.1.2", + "streamroller": "^1.0.1" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-error": { + "version": "1.3.5", + "bundled": true + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "4.1.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mime-db": { + "version": "1.37.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.21", + "bundled": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.0.3", + "bundled": true + } + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "nodeunit": { + "version": "0.11.3", + "bundled": true, + "requires": { + "ejs": "^2.5.2", + "tap": "^12.0.1" + } + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "nyc": { + "version": "13.2.0", + "bundled": true, + "requires": { + "archy": "^1.0.0", + "arrify": "^1.0.1", + "caching-transform": "^3.0.1", + "convert-source-map": "^1.6.0", + "find-cache-dir": "^2.0.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-hook": "^2.0.3", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.2", + "istanbul-reports": "^2.1.0", + "make-dir": "^1.3.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.1.0", + "uuid": "^3.3.2", + "yargs": "^12.0.5", + "yargs-parser": "^11.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "append-transform": { + "version": "1.0.0", + "bundled": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "archy": { + "version": "1.0.0", + "bundled": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true + }, + "async": { + "version": "2.6.1", + "bundled": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "caching-transform": { + "version": "3.0.1", + "bundled": true, + "requires": { + "hasha": "^3.0.0", + "make-dir": "^1.3.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.3.0" + } + }, + "camelcase": { + "version": "5.0.0", + "bundled": true + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "commander": { + "version": "2.17.1", + "bundled": true, + "optional": true + }, + "commondir": { + "version": "1.0.1", + "bundled": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "convert-source-map": { + "version": "1.6.0", + "bundled": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cross-spawn": { + "version": "4.0.2", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "debug": { + "version": "4.1.1", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "default-require-extensions": { + "version": "2.0.0", + "bundled": true, + "requires": { + "strip-bom": "^3.0.0" + } + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es6-error": { + "version": "4.1.1", + "bundled": true + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "find-cache-dir": { + "version": "2.0.0", + "bundled": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "handlebars": { + "version": "4.0.12", + "bundled": true, + "requires": { + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true + } + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "hasha": { + "version": "3.0.0", + "bundled": true, + "requires": { + "is-stream": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "bundled": true + }, + "istanbul-lib-hook": { + "version": "2.0.3", + "bundled": true, + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.4", + "bundled": true, + "requires": { + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "supports-color": "^6.0.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.2", + "bundled": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "rimraf": "^2.6.2", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true + } + } + }, + "istanbul-reports": { + "version": "2.1.0", + "bundled": true, + "requires": { + "handlebars": "^4.0.11" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "bundled": true + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "bundled": 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", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "bundled": true + }, + "lodash.flattendeep": { + "version": "4.4.0", + "bundled": true + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "1.3.0", + "bundled": true, + "requires": { + "pify": "^3.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "4.0.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^1.1.0" + } + }, + "merge-source-map": { + "version": "1.1.0", + "bundled": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.10", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "bundled": true + } + } + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "1.1.0", + "bundled": true + }, + "p-limit": { + "version": "2.1.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "bundled": true + }, + "package-hash": { + "version": "3.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "bundled": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "3.0.0", + "bundled": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "bundled": true + }, + "pkg-dir": { + "version": "3.0.0", + "bundled": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "read-pkg": { + "version": "3.0.0", + "bundled": 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", + "bundled": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "release-zalgo": { + "version": "1.0.0", + "bundled": true, + "requires": { + "es6-error": "^4.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "resolve-from": { + "version": "4.0.0", + "bundled": true + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "spawn-wrap": { + "version": "1.4.2", + "bundled": true, + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "test-exclude": { + "version": "5.1.0", + "bundled": true, + "requires": { + "arrify": "^1.0.1", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^1.0.1" + } + }, + "uglify-js": { + "version": "3.4.9", + "bundled": true, + "optional": true, + "requires": { + "commander": "~2.17.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true, + "optional": true + } + } + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.4.2", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "12.0.5", + "bundled": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "oauth-sign": { + "version": "0.9.0", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.1", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "own-or": { + "version": "1.0.0", + "bundled": true + }, + "own-or-env": { + "version": "1.0.1", + "bundled": true, + "requires": { + "own-or": "^1.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "2.0.0", + "bundled": true + }, + "p-limit": { + "version": "2.1.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "bundled": true + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pkglint": { + "bundled": true, + "requires": { + "case": "^1.5.5", + "colors": "^1.3.2", + "fs-extra": "^7.0.0", + "semver": "^5.6.0", + "yargs": "^9.0.1" + }, + "dependencies": { + "@types/colors": { + "version": "https://registry.npmjs.org/@types/colors/-/colors-1.2.1.tgz", + "bundled": true, + "requires": { + "colors": "*" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.8.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/semver": { + "version": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "cliui": { + "version": "3.2.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.3.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "psl": { + "version": "1.1.31", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "bundled": true + }, + "qs": { + "version": "6.5.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": 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" + } + }, + "request": { + "version": "2.88.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "rfdc": { + "version": "1.1.2", + "bundled": true + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sort-json": { + "version": "2.0.0", + "bundled": true, + "requires": { + "detect-indent": "^5.0.0", + "detect-newline": "^2.1.0", + "minimist": "^1.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true + }, + "source-map-support": { + "version": "0.5.10", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true + } + } + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "spdx-license-list": { + "version": "5.0.0", + "bundled": true + }, + "sprintf-js": { + "version": "1.0.3", + "bundled": true + }, + "sshpk": { + "version": "1.16.1", + "bundled": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-utils": { + "version": "1.0.2", + "bundled": true + }, + "streamroller": { + "version": "1.0.1", + "bundled": true, + "requires": { + "async": "^2.6.1", + "date-format": "^2.0.0", + "debug": "^3.1.0", + "fs-extra": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "supports-color": { + "version": "5.5.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap": { + "version": "12.5.1", + "bundled": true, + "requires": { + "bind-obj-methods": "^2.0.0", + "browser-process-hrtime": "^1.0.0", + "capture-stack-trace": "^1.0.0", + "clean-yaml-object": "^0.1.0", + "color-support": "^1.1.0", + "coveralls": "^3.0.2", + "domain-browser": "^1.2.0", + "esm": "^3.1.4", + "foreground-child": "^1.3.3", + "fs-exists-cached": "^1.0.0", + "function-loop": "^1.0.1", + "glob": "^7.1.3", + "isexe": "^2.0.0", + "js-yaml": "^3.12.1", + "minipass": "^2.3.5", + "mkdirp": "^0.5.1", + "nyc": "^13.1.0", + "opener": "^1.5.1", + "os-homedir": "^1.0.2", + "own-or": "^1.0.0", + "own-or-env": "^1.0.1", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.0", + "source-map-support": "^0.5.10", + "stack-utils": "^1.0.2", + "tap-mocha-reporter": "^3.0.7", + "tap-parser": "^7.0.0", + "tmatch": "^4.0.0", + "trivial-deferred": "^1.0.1", + "ts-node": "^8.0.1", + "tsame": "^2.0.1", + "typescript": "^3.2.4", + "write-file-atomic": "^2.3.0", + "yapool": "^1.0.0" + } + }, + "tap-mocha-reporter": { + "version": "3.0.7", + "bundled": true, + "requires": { + "color-support": "^1.1.0", + "debug": "^2.1.3", + "diff": "^1.3.2", + "escape-string-regexp": "^1.0.3", + "glob": "^7.0.5", + "js-yaml": "^3.3.1", + "readable-stream": "^2.1.5", + "tap-parser": "^5.1.0", + "unicode-length": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "tap-parser": { + "version": "5.4.0", + "bundled": true, + "requires": { + "events-to-array": "^1.0.1", + "js-yaml": "^3.2.7", + "readable-stream": "^2" + } + } + } + }, + "tap-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "events-to-array": "^1.0.1", + "js-yaml": "^3.2.7", + "minipass": "^2.2.0" + } + }, + "tmatch": { + "version": "4.0.0", + "bundled": true + }, + "to-fast-properties": { + "version": "2.0.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.4.3", + "bundled": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "bundled": true + } + } + }, + "trim-right": { + "version": "1.0.1", + "bundled": true + }, + "trivial-deferred": { + "version": "1.0.1", + "bundled": true + }, + "ts-node": { + "version": "8.0.2", + "bundled": true, + "requires": { + "arg": "^4.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "bundled": true + } + } + }, + "tsame": { + "version": "2.0.1", + "bundled": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true + }, + "typescript": { + "version": "3.3.1", + "bundled": true + }, + "unicode-length": { + "version": "1.0.3", + "bundled": true, + "requires": { + "punycode": "^1.3.2", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "uri-js": { + "version": "4.2.2", + "bundled": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.4.2", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xmlbuilder": { + "version": "10.1.1", + "bundled": true + }, + "xregexp": { + "version": "4.0.0", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yapool": { + "version": "1.0.0", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "cliui": { + "version": "3.2.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true + }, + "yargs-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "11.1.1", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yn": { + "version": "3.0.0", + "bundled": true + } + } + }, + "pkglint": { + "bundled": true, + "requires": { + "case": "^1.5.5", + "colors": "^1.3.2", + "fs-extra": "^7.0.0", + "semver": "^5.6.0", + "yargs": "^9.0.1" + }, + "dependencies": { + "@types/colors": { + "version": "https://registry.npmjs.org/@types/colors/-/colors-1.2.1.tgz", + "bundled": true, + "requires": { + "colors": "*" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.8.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/semver": { + "version": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "cliui": { + "version": "3.2.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": {} + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.3.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": {} + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "y18n": { + "version": "3.2.1", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + } + } + }, + "@types/js-base64": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-2.3.1.tgz", + "integrity": "sha512-4RKbhIDGC87s4EBy2Cp2/5S2O6kmCRcZnD5KRCq1q9z2GhBte1+BdsfVKCpG8yKpDGNyEE2G6IqFIh6W2YwWPA==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.120", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.120.tgz", + "integrity": "sha512-jQ21kQ120mo+IrDs1nFNVm/AsdFxIx2+vZ347DbogHJPd/JzKNMOqU6HCYin1W6v8l5R9XSO2/e9cxmn7HAnVw==", + "dev": true + }, + "cdk-build-tools": { + "version": "0.24.1", + "dev": true, + "requires": { + "awslint": "^0.24.1", + "fs-extra": "^7.0.0", + "jsii": "^0.7.13", + "jsii-pacmak": "^0.7.13", + "nodeunit": "^0.11.3", + "nyc": "^13.0.1", + "typescript": "^3.1.2", + "yargs": "^9.0.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "bundled": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.3.2", + "bundled": true, + "requires": { + "@babel/types": "^7.3.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "bundled": 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", + "bundled": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "bundled": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "bundled": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.3.2", + "bundled": true + }, + "@babel/template": { + "version": "7.2.2", + "bundled": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "bundled": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": {} + }, + "@babel/types": { + "version": "7.3.2", + "bundled": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ajv": { + "version": "6.8.1", + "bundled": 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-regex": { + "version": "3.0.0", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arg": { + "version": "4.1.0", + "bundled": true + }, + "argparse": { + "version": "1.0.10", + "bundled": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1": { + "version": "0.2.4", + "bundled": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "async": { + "version": "2.6.1", + "bundled": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true + }, + "aws4": { + "version": "1.8.0", + "bundled": true + }, + "awslint": { + "version": "0.24.1", + "bundled": true, + "requires": { + "colors": "^1.3.3", + "fs-extra": "^7.0.1", + "jsii-reflect": "^0.7.12", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bind-obj-methods": { + "version": "2.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "bundled": true + }, + "buffer-from": { + "version": "1.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "5.0.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.2", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "clean-yaml-object": { + "version": "0.1.0", + "bundled": true + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "codemaker": { + "version": "0.7.14", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^2.0.0", + "fs-extra": "^7.0.1" + }, + "dependencies": {} + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "color-support": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "combined-stream": { + "version": "1.0.7", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "coveralls": { + "version": "3.0.2", + "bundled": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.11.0", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.85.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-format": { + "version": "2.0.0", + "bundled": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "deep-equal": { + "version": "1.0.1", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "diff": { + "version": "1.4.0", + "bundled": true + }, + "domain-browser": { + "version": "1.2.0", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "bundled": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ejs": { + "version": "2.6.1", + "bundled": true + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "esm": { + "version": "3.2.1", + "bundled": true + }, + "esprima": { + "version": "4.0.1", + "bundled": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true + }, + "events-to-array": { + "version": "1.1.2", + "bundled": true + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flatted": { + "version": "2.0.0", + "bundled": true + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": {} + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.3.3", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-exists-cached": { + "version": "1.0.0", + "bundled": true + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "function-loop": { + "version": "1.0.1", + "bundled": true + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.10.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "growl": { + "version": "1.10.5", + "bundled": true + }, + "har-schema": { + "version": "2.0.0", + "bundled": true + }, + "har-validator": { + "version": "5.1.3", + "bundled": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "bundled": true + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "bundled": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "bundled": true + }, + "js-yaml": { + "version": "3.12.1", + "bundled": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true + }, + "jsesc": { + "version": "2.5.2", + "bundled": true + }, + "jsii": { + "version": "0.7.14", + "bundled": true, + "requires": { + "case": "^1.6.1", + "colors": "^1.3.3", + "deep-equal": "^1.0.1", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "log4js": "^4.0.1", + "semver": "^5.6.0", + "sort-json": "^2.0.0", + "spdx-license-list": "^5.0.0", + "typescript": "^3.2.4", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "jsii-pacmak": { + "version": "0.7.14", + "bundled": true, + "requires": { + "clone": "^2.1.2", + "codemaker": "^0.7.14", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "spdx-license-list": "^5.0.0", + "xmlbuilder": "^10.1.1", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "jsii-spec": { + "version": "0.7.14", + "bundled": true, + "requires": { + "jsonschema": "^1.2.4" + } + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonschema": { + "version": "1.2.4", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "lcov-parse": { + "version": "0.0.10", + "bundled": true + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "bundled": true + }, + "log-driver": { + "version": "1.2.7", + "bundled": true + }, + "log4js": { + "version": "4.0.2", + "bundled": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^3.1.0", + "flatted": "^2.0.0", + "rfdc": "^1.1.2", + "streamroller": "^1.0.1" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-error": { + "version": "1.3.5", + "bundled": true + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "4.1.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mime-db": { + "version": "1.37.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.21", + "bundled": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": {} + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": {} + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "nodeunit": { + "version": "0.11.3", + "bundled": true, + "requires": { + "ejs": "^2.5.2", + "tap": "^12.0.1" + } + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "nyc": { + "version": "13.2.0", + "bundled": true, + "requires": { + "archy": "^1.0.0", + "arrify": "^1.0.1", + "caching-transform": "^3.0.1", + "convert-source-map": "^1.6.0", + "find-cache-dir": "^2.0.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-hook": "^2.0.3", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.2", + "istanbul-reports": "^2.1.0", + "make-dir": "^1.3.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.1.0", + "uuid": "^3.3.2", + "yargs": "^12.0.5", + "yargs-parser": "^11.1.1" + }, + "dependencies": {} + }, + "oauth-sign": { + "version": "0.9.0", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.1", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "own-or": { + "version": "1.0.0", + "bundled": true + }, + "own-or-env": { + "version": "1.0.1", + "bundled": true, + "requires": { + "own-or": "^1.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "2.0.0", + "bundled": true + }, + "p-limit": { + "version": "2.1.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "bundled": true + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pkglint": { + "bundled": true, + "requires": { + "case": "^1.5.5", + "colors": "^1.3.2", + "fs-extra": "^7.0.0", + "semver": "^5.6.0", + "yargs": "^9.0.1" + }, + "dependencies": {} + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "psl": { + "version": "1.1.31", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "bundled": true + }, + "qs": { + "version": "6.5.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": {} + }, + "readable-stream": { + "version": "2.3.6", + "bundled": 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" + } + }, + "request": { + "version": "2.88.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "rfdc": { + "version": "1.1.2", + "bundled": true + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sort-json": { + "version": "2.0.0", + "bundled": true, + "requires": { + "detect-indent": "^5.0.0", + "detect-newline": "^2.1.0", + "minimist": "^1.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true + }, + "source-map-support": { + "version": "0.5.10", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": {} + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "spdx-license-list": { + "version": "5.0.0", + "bundled": true + }, + "sprintf-js": { + "version": "1.0.3", + "bundled": true + }, + "sshpk": { + "version": "1.16.1", + "bundled": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-utils": { + "version": "1.0.2", + "bundled": true + }, + "streamroller": { + "version": "1.0.1", + "bundled": true, + "requires": { + "async": "^2.6.1", + "date-format": "^2.0.0", + "debug": "^3.1.0", + "fs-extra": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "supports-color": { + "version": "5.5.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap": { + "version": "12.5.1", + "bundled": true, + "requires": { + "bind-obj-methods": "^2.0.0", + "browser-process-hrtime": "^1.0.0", + "capture-stack-trace": "^1.0.0", + "clean-yaml-object": "^0.1.0", + "color-support": "^1.1.0", + "coveralls": "^3.0.2", + "domain-browser": "^1.2.0", + "esm": "^3.1.4", + "foreground-child": "^1.3.3", + "fs-exists-cached": "^1.0.0", + "function-loop": "^1.0.1", + "glob": "^7.1.3", + "isexe": "^2.0.0", + "js-yaml": "^3.12.1", + "minipass": "^2.3.5", + "mkdirp": "^0.5.1", + "nyc": "^13.1.0", + "opener": "^1.5.1", + "os-homedir": "^1.0.2", + "own-or": "^1.0.0", + "own-or-env": "^1.0.1", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.0", + "source-map-support": "^0.5.10", + "stack-utils": "^1.0.2", + "tap-mocha-reporter": "^3.0.7", + "tap-parser": "^7.0.0", + "tmatch": "^4.0.0", + "trivial-deferred": "^1.0.1", + "ts-node": "^8.0.1", + "tsame": "^2.0.1", + "typescript": "^3.2.4", + "write-file-atomic": "^2.3.0", + "yapool": "^1.0.0" + } + }, + "tap-mocha-reporter": { + "version": "3.0.7", + "bundled": true, + "requires": { + "color-support": "^1.1.0", + "debug": "^2.1.3", + "diff": "^1.3.2", + "escape-string-regexp": "^1.0.3", + "glob": "^7.0.5", + "js-yaml": "^3.3.1", + "readable-stream": "^2.1.5", + "tap-parser": "^5.1.0", + "unicode-length": "^1.0.0" + }, + "dependencies": {} + }, + "tap-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "events-to-array": "^1.0.1", + "js-yaml": "^3.2.7", + "minipass": "^2.2.0" + } + }, + "tmatch": { + "version": "4.0.0", + "bundled": true + }, + "to-fast-properties": { + "version": "2.0.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.4.3", + "bundled": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": {} + }, + "trim-right": { + "version": "1.0.1", + "bundled": true + }, + "trivial-deferred": { + "version": "1.0.1", + "bundled": true + }, + "ts-node": { + "version": "8.0.2", + "bundled": true, + "requires": { + "arg": "^4.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + }, + "dependencies": {} + }, + "tsame": { + "version": "2.0.1", + "bundled": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true + }, + "typescript": { + "version": "3.3.1", + "bundled": true + }, + "unicode-length": { + "version": "1.0.3", + "bundled": true, + "requires": { + "punycode": "^1.3.2", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "uri-js": { + "version": "4.2.2", + "bundled": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.4.2", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xmlbuilder": { + "version": "10.1.1", + "bundled": true + }, + "xregexp": { + "version": "4.0.0", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yapool": { + "version": "1.0.0", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": {} + }, + "yargs-parser": { + "version": "11.1.1", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yn": { + "version": "3.0.0", + "bundled": true + } + } + }, + "cfn2ts": { + "version": "0.24.1", + "dev": true, + "requires": { + "@aws-cdk/cfnspec": "^0.24.1", + "codemaker": "^0.6.4", + "fast-json-patch": "^2.0.6", + "fs-extra": "^7.0.0", + "yargs": "^9.0.1" + }, + "dependencies": { + "@aws-cdk/cfnspec": { + "version": "0.24.1", + "bundled": true, + "dev": true, + "requires": { + "md5": "^2.2.1" + }, + "dependencies": { + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/md5": { + "version": "https://registry.npmjs.org/@types/md5/-/md5-2.1.33.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "cdk-build-tools": { + "bundled": true, + "requires": { + "awslint": "^0.24.1", + "fs-extra": "^7.0.0", + "jsii": "^0.7.13", + "jsii-pacmak": "^0.7.13", + "nodeunit": "^0.11.3", + "nyc": "^13.0.1", + "typescript": "^3.1.2", + "yargs": "^9.0.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "bundled": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.3.2", + "bundled": true, + "requires": { + "@babel/types": "^7.3.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "bundled": 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", + "bundled": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "bundled": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "bundled": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.3.2", + "bundled": true + }, + "@babel/template": { + "version": "7.2.2", + "bundled": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "bundled": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": {} + }, + "@babel/types": { + "version": "7.3.2", + "bundled": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ajv": { + "version": "6.8.1", + "bundled": 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-regex": { + "version": "3.0.0", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arg": { + "version": "4.1.0", + "bundled": true + }, + "argparse": { + "version": "1.0.10", + "bundled": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1": { + "version": "0.2.4", + "bundled": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "async": { + "version": "2.6.1", + "bundled": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true + }, + "aws4": { + "version": "1.8.0", + "bundled": true + }, + "awslint": { + "version": "0.24.1", + "bundled": true, + "requires": { + "colors": "^1.3.3", + "fs-extra": "^7.0.1", + "jsii-reflect": "^0.7.12", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bind-obj-methods": { + "version": "2.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "bundled": true + }, + "buffer-from": { + "version": "1.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "5.0.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.2", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "clean-yaml-object": { + "version": "0.1.0", + "bundled": true + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "codemaker": { + "version": "0.7.14", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^2.0.0", + "fs-extra": "^7.0.1" + }, + "dependencies": {} + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "color-support": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "combined-stream": { + "version": "1.0.7", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "coveralls": { + "version": "3.0.2", + "bundled": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.11.0", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.85.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-format": { + "version": "2.0.0", + "bundled": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "deep-equal": { + "version": "1.0.1", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "diff": { + "version": "1.4.0", + "bundled": true + }, + "domain-browser": { + "version": "1.2.0", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "bundled": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ejs": { + "version": "2.6.1", + "bundled": true + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "esm": { + "version": "3.2.1", + "bundled": true + }, + "esprima": { + "version": "4.0.1", + "bundled": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true + }, + "events-to-array": { + "version": "1.1.2", + "bundled": true + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flatted": { + "version": "2.0.0", + "bundled": true + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": {} + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.3.3", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-exists-cached": { + "version": "1.0.0", + "bundled": true + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "function-loop": { + "version": "1.0.1", + "bundled": true + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.10.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "growl": { + "version": "1.10.5", + "bundled": true + }, + "har-schema": { + "version": "2.0.0", + "bundled": true + }, + "har-validator": { + "version": "5.1.3", + "bundled": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "bundled": true + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "bundled": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "bundled": true + }, + "js-yaml": { + "version": "3.12.1", + "bundled": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true + }, + "jsesc": { + "version": "2.5.2", + "bundled": true + }, + "jsii": { + "version": "0.7.14", + "bundled": true, + "requires": { + "case": "^1.6.1", + "colors": "^1.3.3", + "deep-equal": "^1.0.1", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "log4js": "^4.0.1", + "semver": "^5.6.0", + "sort-json": "^2.0.0", + "spdx-license-list": "^5.0.0", + "typescript": "^3.2.4", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "jsii-pacmak": { + "version": "0.7.14", + "bundled": true, + "requires": { + "clone": "^2.1.2", + "codemaker": "^0.7.14", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "spdx-license-list": "^5.0.0", + "xmlbuilder": "^10.1.1", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "jsii-spec": { + "version": "0.7.14", + "bundled": true, + "requires": { + "jsonschema": "^1.2.4" + } + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonschema": { + "version": "1.2.4", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "lcov-parse": { + "version": "0.0.10", + "bundled": true + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "bundled": true + }, + "log-driver": { + "version": "1.2.7", + "bundled": true + }, + "log4js": { + "version": "4.0.2", + "bundled": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^3.1.0", + "flatted": "^2.0.0", + "rfdc": "^1.1.2", + "streamroller": "^1.0.1" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-error": { + "version": "1.3.5", + "bundled": true + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "4.1.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mime-db": { + "version": "1.37.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.21", + "bundled": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": {} + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": {} + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "nodeunit": { + "version": "0.11.3", + "bundled": true, + "requires": { + "ejs": "^2.5.2", + "tap": "^12.0.1" + } + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "nyc": { + "version": "13.2.0", + "bundled": true, + "requires": { + "archy": "^1.0.0", + "arrify": "^1.0.1", + "caching-transform": "^3.0.1", + "convert-source-map": "^1.6.0", + "find-cache-dir": "^2.0.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-hook": "^2.0.3", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.2", + "istanbul-reports": "^2.1.0", + "make-dir": "^1.3.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.1.0", + "uuid": "^3.3.2", + "yargs": "^12.0.5", + "yargs-parser": "^11.1.1" + }, + "dependencies": {} + }, + "oauth-sign": { + "version": "0.9.0", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.1", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "own-or": { + "version": "1.0.0", + "bundled": true + }, + "own-or-env": { + "version": "1.0.1", + "bundled": true, + "requires": { + "own-or": "^1.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "2.0.0", + "bundled": true + }, + "p-limit": { + "version": "2.1.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "bundled": true + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pkglint": { + "bundled": true, + "requires": { + "case": "^1.5.5", + "colors": "^1.3.2", + "fs-extra": "^7.0.0", + "semver": "^5.6.0", + "yargs": "^9.0.1" + }, + "dependencies": {} + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "psl": { + "version": "1.1.31", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "bundled": true + }, + "qs": { + "version": "6.5.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": {} + }, + "readable-stream": { + "version": "2.3.6", + "bundled": 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" + } + }, + "request": { + "version": "2.88.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "rfdc": { + "version": "1.1.2", + "bundled": true + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sort-json": { + "version": "2.0.0", + "bundled": true, + "requires": { + "detect-indent": "^5.0.0", + "detect-newline": "^2.1.0", + "minimist": "^1.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true + }, + "source-map-support": { + "version": "0.5.10", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": {} + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "spdx-license-list": { + "version": "5.0.0", + "bundled": true + }, + "sprintf-js": { + "version": "1.0.3", + "bundled": true + }, + "sshpk": { + "version": "1.16.1", + "bundled": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-utils": { + "version": "1.0.2", + "bundled": true + }, + "streamroller": { + "version": "1.0.1", + "bundled": true, + "requires": { + "async": "^2.6.1", + "date-format": "^2.0.0", + "debug": "^3.1.0", + "fs-extra": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "supports-color": { + "version": "5.5.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap": { + "version": "12.5.1", + "bundled": true, + "requires": { + "bind-obj-methods": "^2.0.0", + "browser-process-hrtime": "^1.0.0", + "capture-stack-trace": "^1.0.0", + "clean-yaml-object": "^0.1.0", + "color-support": "^1.1.0", + "coveralls": "^3.0.2", + "domain-browser": "^1.2.0", + "esm": "^3.1.4", + "foreground-child": "^1.3.3", + "fs-exists-cached": "^1.0.0", + "function-loop": "^1.0.1", + "glob": "^7.1.3", + "isexe": "^2.0.0", + "js-yaml": "^3.12.1", + "minipass": "^2.3.5", + "mkdirp": "^0.5.1", + "nyc": "^13.1.0", + "opener": "^1.5.1", + "os-homedir": "^1.0.2", + "own-or": "^1.0.0", + "own-or-env": "^1.0.1", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.0", + "source-map-support": "^0.5.10", + "stack-utils": "^1.0.2", + "tap-mocha-reporter": "^3.0.7", + "tap-parser": "^7.0.0", + "tmatch": "^4.0.0", + "trivial-deferred": "^1.0.1", + "ts-node": "^8.0.1", + "tsame": "^2.0.1", + "typescript": "^3.2.4", + "write-file-atomic": "^2.3.0", + "yapool": "^1.0.0" + } + }, + "tap-mocha-reporter": { + "version": "3.0.7", + "bundled": true, + "requires": { + "color-support": "^1.1.0", + "debug": "^2.1.3", + "diff": "^1.3.2", + "escape-string-regexp": "^1.0.3", + "glob": "^7.0.5", + "js-yaml": "^3.3.1", + "readable-stream": "^2.1.5", + "tap-parser": "^5.1.0", + "unicode-length": "^1.0.0" + }, + "dependencies": {} + }, + "tap-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "events-to-array": "^1.0.1", + "js-yaml": "^3.2.7", + "minipass": "^2.2.0" + } + }, + "tmatch": { + "version": "4.0.0", + "bundled": true + }, + "to-fast-properties": { + "version": "2.0.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.4.3", + "bundled": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": {} + }, + "trim-right": { + "version": "1.0.1", + "bundled": true + }, + "trivial-deferred": { + "version": "1.0.1", + "bundled": true + }, + "ts-node": { + "version": "8.0.2", + "bundled": true, + "requires": { + "arg": "^4.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + }, + "dependencies": {} + }, + "tsame": { + "version": "2.0.1", + "bundled": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true + }, + "typescript": { + "version": "3.3.1", + "bundled": true + }, + "unicode-length": { + "version": "1.0.3", + "bundled": true, + "requires": { + "punycode": "^1.3.2", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "uri-js": { + "version": "4.2.2", + "bundled": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.4.2", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xmlbuilder": { + "version": "10.1.1", + "bundled": true + }, + "xregexp": { + "version": "4.0.0", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yapool": { + "version": "1.0.0", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": {} + }, + "yargs-parser": { + "version": "11.1.1", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yn": { + "version": "3.0.0", + "bundled": true + } + } + }, + "charenc": { + "version": "0.0.2", + "bundled": true, + "dev": true + }, + "cli-color": { + "version": "0.1.7", + "bundled": true, + "requires": { + "es5-ext": "0.8.x" + } + }, + "crypt": { + "version": "0.0.2", + "bundled": true, + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "difflib": { + "version": "0.2.4", + "bundled": true, + "requires": { + "heap": ">= 0.2.0" + } + }, + "dreamopt": { + "version": "0.6.0", + "bundled": true, + "requires": { + "wordwrap": ">=0.0.2" + } + }, + "es5-ext": { + "version": "0.8.2", + "bundled": true + }, + "fast-json-patch": { + "version": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.0.7.tgz", + "bundled": true, + "requires": { + "deep-equal": "^1.0.1" + } + }, + "fs-extra": { + "version": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "heap": { + "version": "0.2.6", + "bundled": true + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "json-diff": { + "version": "https://registry.npmjs.org/json-diff/-/json-diff-0.3.1.tgz", + "bundled": true, + "requires": { + "cli-color": "~0.1.6", + "difflib": "~0.2.1", + "dreamopt": "~0.6.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "md5": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "pkglint": { + "bundled": true, + "requires": { + "case": "^1.5.5", + "colors": "^1.3.2", + "fs-extra": "^7.0.0", + "semver": "^5.6.0", + "yargs": "^9.0.1" + }, + "dependencies": { + "@types/colors": { + "version": "https://registry.npmjs.org/@types/colors/-/colors-1.2.1.tgz", + "bundled": true, + "requires": { + "colors": "*" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.8.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/semver": { + "version": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "cliui": { + "version": "3.2.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": {} + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.3.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": {} + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "y18n": { + "version": "3.2.1", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "sort-json": { + "version": "https://registry.npmjs.org/sort-json/-/sort-json-2.0.0.tgz", + "bundled": true, + "requires": { + "detect-indent": "^5.0.0", + "detect-newline": "^2.1.0", + "minimist": "^1.2.0" + } + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "wordwrap": { + "version": "1.0.0", + "bundled": true + } + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "cdk-build-tools": { + "bundled": true, + "requires": { + "awslint": "^0.24.1", + "fs-extra": "^7.0.0", + "jsii": "^0.7.13", + "jsii-pacmak": "^0.7.13", + "nodeunit": "^0.11.3", + "nyc": "^13.0.1", + "typescript": "^3.1.2", + "yargs": "^9.0.1" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "bundled": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.3.2", + "bundled": true, + "requires": { + "@babel/types": "^7.3.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "bundled": 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", + "bundled": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "bundled": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "bundled": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.3.2", + "bundled": true + }, + "@babel/template": { + "version": "7.2.2", + "bundled": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "bundled": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": {} + }, + "@babel/types": { + "version": "7.3.2", + "bundled": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.4.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ajv": { + "version": "6.8.1", + "bundled": 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-regex": { + "version": "3.0.0", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arg": { + "version": "4.1.0", + "bundled": true + }, + "argparse": { + "version": "1.0.10", + "bundled": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1": { + "version": "0.2.4", + "bundled": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "bundled": true + }, + "async": { + "version": "2.6.1", + "bundled": true, + "requires": { + "lodash": "^4.17.10" + } + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.7.0", + "bundled": true + }, + "aws4": { + "version": "1.8.0", + "bundled": true + }, + "awslint": { + "version": "0.24.1", + "bundled": true, + "requires": { + "colors": "^1.3.3", + "fs-extra": "^7.0.1", + "jsii-reflect": "^0.7.12", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "bundled": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bind-obj-methods": { + "version": "2.0.0", + "bundled": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "bundled": true + }, + "buffer-from": { + "version": "1.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "5.0.0", + "bundled": true + }, + "capture-stack-trace": { + "version": "1.0.1", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "chalk": { + "version": "2.4.2", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "clean-yaml-object": { + "version": "0.1.0", + "bundled": true + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "2.1.2", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "codemaker": { + "version": "0.7.14", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^2.0.0", + "fs-extra": "^7.0.1" + }, + "dependencies": {} + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "color-support": { + "version": "1.1.3", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "combined-stream": { + "version": "1.0.7", + "bundled": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "coveralls": { + "version": "3.0.2", + "bundled": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.11.0", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.85.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-format": { + "version": "2.0.0", + "bundled": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "deep-equal": { + "version": "1.0.1", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "detect-indent": { + "version": "5.0.0", + "bundled": true + }, + "detect-newline": { + "version": "2.1.0", + "bundled": true + }, + "diff": { + "version": "1.4.0", + "bundled": true + }, + "domain-browser": { + "version": "1.2.0", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "bundled": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ejs": { + "version": "2.6.1", + "bundled": true + }, + "end-of-stream": { + "version": "1.4.1", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true + }, + "esm": { + "version": "3.2.1", + "bundled": true + }, + "esprima": { + "version": "4.0.1", + "bundled": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true + }, + "events-to-array": { + "version": "1.1.2", + "bundled": true + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "extend": { + "version": "3.0.2", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "bundled": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "bundled": true + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "flatted": { + "version": "2.0.0", + "bundled": true + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": {} + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.3.3", + "bundled": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-exists-cached": { + "version": "1.0.0", + "bundled": true + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "function-loop": { + "version": "1.0.1", + "bundled": true + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "pump": "^3.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "bundled": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.10.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "growl": { + "version": "1.10.5", + "bundled": true + }, + "har-schema": { + "version": "2.0.0", + "bundled": true + }, + "har-validator": { + "version": "5.1.3", + "bundled": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "http-signature": { + "version": "1.2.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "bundled": true + }, + "istanbul-lib-instrument": { + "version": "3.1.0", + "bundled": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "bundled": true + }, + "js-yaml": { + "version": "3.12.1", + "bundled": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true + }, + "jsesc": { + "version": "2.5.2", + "bundled": true + }, + "jsii": { + "version": "0.7.14", + "bundled": true, + "requires": { + "case": "^1.6.1", + "colors": "^1.3.3", + "deep-equal": "^1.0.1", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "log4js": "^4.0.1", + "semver": "^5.6.0", + "sort-json": "^2.0.0", + "spdx-license-list": "^5.0.0", + "typescript": "^3.2.4", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "jsii-pacmak": { + "version": "0.7.14", + "bundled": true, + "requires": { + "clone": "^2.1.2", + "codemaker": "^0.7.14", + "fs-extra": "^7.0.1", + "jsii-spec": "^0.7.14", + "spdx-license-list": "^5.0.0", + "xmlbuilder": "^10.1.1", + "yargs": "^12.0.5" + }, + "dependencies": {} + }, + "jsii-spec": { + "version": "0.7.14", + "bundled": true, + "requires": { + "jsonschema": "^1.2.4" + } + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "bundled": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonschema": { + "version": "1.2.4", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "lcov-parse": { + "version": "0.0.10", + "bundled": true + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "bundled": true + }, + "log-driver": { + "version": "1.2.7", + "bundled": true + }, + "log4js": { + "version": "4.0.2", + "bundled": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^3.1.0", + "flatted": "^2.0.0", + "rfdc": "^1.1.2", + "streamroller": "^1.0.1" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-error": { + "version": "1.3.5", + "bundled": true + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "4.1.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mime-db": { + "version": "1.37.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.21", + "bundled": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "bundled": true + }, + "minipass": { + "version": "2.3.5", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": {} + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": {} + }, + "ms": { + "version": "2.1.1", + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "nodeunit": { + "version": "0.11.3", + "bundled": true, + "requires": { + "ejs": "^2.5.2", + "tap": "^12.0.1" + } + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "nyc": { + "version": "13.2.0", + "bundled": true, + "requires": { + "archy": "^1.0.0", + "arrify": "^1.0.1", + "caching-transform": "^3.0.1", + "convert-source-map": "^1.6.0", + "find-cache-dir": "^2.0.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-hook": "^2.0.3", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.2", + "istanbul-reports": "^2.1.0", + "make-dir": "^1.3.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.1.0", + "uuid": "^3.3.2", + "yargs": "^12.0.5", + "yargs-parser": "^11.1.1" + }, + "dependencies": {} + }, + "oauth-sign": { + "version": "0.9.0", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.5.1", + "bundled": true + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "own-or": { + "version": "1.0.0", + "bundled": true + }, + "own-or-env": { + "version": "1.0.1", + "bundled": true, + "requires": { + "own-or": "^1.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "2.0.0", + "bundled": true + }, + "p-limit": { + "version": "2.1.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "bundled": true + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pkglint": { + "bundled": true, + "requires": { + "case": "^1.5.5", + "colors": "^1.3.2", + "fs-extra": "^7.0.0", + "semver": "^5.6.0", + "yargs": "^9.0.1" + }, + "dependencies": {} + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "psl": { + "version": "1.1.31", + "bundled": true + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "bundled": true + }, + "qs": { + "version": "6.5.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": {} + }, + "readable-stream": { + "version": "2.3.6", + "bundled": 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" + } + }, + "request": { + "version": "2.88.0", + "bundled": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "rfdc": { + "version": "1.1.2", + "bundled": true + }, + "rimraf": { + "version": "2.6.3", + "bundled": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sort-json": { + "version": "2.0.0", + "bundled": true, + "requires": { + "detect-indent": "^5.0.0", + "detect-newline": "^2.1.0", + "minimist": "^1.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true + }, + "source-map-support": { + "version": "0.5.10", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": {} + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "spdx-license-list": { + "version": "5.0.0", + "bundled": true + }, + "sprintf-js": { + "version": "1.0.3", + "bundled": true + }, + "sshpk": { + "version": "1.16.1", + "bundled": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-utils": { + "version": "1.0.2", + "bundled": true + }, + "streamroller": { + "version": "1.0.1", + "bundled": true, + "requires": { + "async": "^2.6.1", + "date-format": "^2.0.0", + "debug": "^3.1.0", + "fs-extra": "^7.0.0", + "lodash": "^4.17.10" + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "supports-color": { + "version": "5.5.0", + "bundled": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tap": { + "version": "12.5.1", + "bundled": true, + "requires": { + "bind-obj-methods": "^2.0.0", + "browser-process-hrtime": "^1.0.0", + "capture-stack-trace": "^1.0.0", + "clean-yaml-object": "^0.1.0", + "color-support": "^1.1.0", + "coveralls": "^3.0.2", + "domain-browser": "^1.2.0", + "esm": "^3.1.4", + "foreground-child": "^1.3.3", + "fs-exists-cached": "^1.0.0", + "function-loop": "^1.0.1", + "glob": "^7.1.3", + "isexe": "^2.0.0", + "js-yaml": "^3.12.1", + "minipass": "^2.3.5", + "mkdirp": "^0.5.1", + "nyc": "^13.1.0", + "opener": "^1.5.1", + "os-homedir": "^1.0.2", + "own-or": "^1.0.0", + "own-or-env": "^1.0.1", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.0", + "source-map-support": "^0.5.10", + "stack-utils": "^1.0.2", + "tap-mocha-reporter": "^3.0.7", + "tap-parser": "^7.0.0", + "tmatch": "^4.0.0", + "trivial-deferred": "^1.0.1", + "ts-node": "^8.0.1", + "tsame": "^2.0.1", + "typescript": "^3.2.4", + "write-file-atomic": "^2.3.0", + "yapool": "^1.0.0" + } + }, + "tap-mocha-reporter": { + "version": "3.0.7", + "bundled": true, + "requires": { + "color-support": "^1.1.0", + "debug": "^2.1.3", + "diff": "^1.3.2", + "escape-string-regexp": "^1.0.3", + "glob": "^7.0.5", + "js-yaml": "^3.3.1", + "readable-stream": "^2.1.5", + "tap-parser": "^5.1.0", + "unicode-length": "^1.0.0" + }, + "dependencies": {} + }, + "tap-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "events-to-array": "^1.0.1", + "js-yaml": "^3.2.7", + "minipass": "^2.2.0" + } + }, + "tmatch": { + "version": "4.0.0", + "bundled": true + }, + "to-fast-properties": { + "version": "2.0.0", + "bundled": true + }, + "tough-cookie": { + "version": "2.4.3", + "bundled": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": {} + }, + "trim-right": { + "version": "1.0.1", + "bundled": true + }, + "trivial-deferred": { + "version": "1.0.1", + "bundled": true + }, + "ts-node": { + "version": "8.0.2", + "bundled": true, + "requires": { + "arg": "^4.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + }, + "dependencies": {} + }, + "tsame": { + "version": "2.0.1", + "bundled": true + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true + }, + "typescript": { + "version": "3.3.1", + "bundled": true + }, + "unicode-length": { + "version": "1.0.3", + "bundled": true, + "requires": { + "punycode": "^1.3.2", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "uri-js": { + "version": "4.2.2", + "bundled": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "uuid": { + "version": "3.3.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "write-file-atomic": { + "version": "2.4.2", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "xmlbuilder": { + "version": "10.1.1", + "bundled": true + }, + "xregexp": { + "version": "4.0.0", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yapool": { + "version": "1.0.0", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + }, + "dependencies": {} + }, + "yargs-parser": { + "version": "11.1.1", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yn": { + "version": "3.0.0", + "bundled": true + } + } + }, + "cliui": { + "version": "3.2.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "codemaker": { + "version": "0.6.4", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "decamelize": "^1.2.0", + "fs-extra": "^4.0.3" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } + } + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "deep-equal": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "fast-json-patch": { + "version": "2.0.7", + "bundled": true, + "dev": true, + "requires": { + "deep-equal": "^1.0.1" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true, + "dev": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true, + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "pkglint": { + "bundled": true, + "requires": { + "case": "^1.5.5", + "colors": "^1.3.2", + "fs-extra": "^7.0.0", + "semver": "^5.6.0", + "yargs": "^9.0.1" + }, + "dependencies": { + "@types/colors": { + "version": "https://registry.npmjs.org/@types/colors/-/colors-1.2.1.tgz", + "bundled": true, + "requires": { + "colors": "*" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.8.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/semver": { + "version": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "cliui": { + "version": "3.2.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": {} + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.3.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": {} + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "y18n": { + "version": "3.2.1", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.6.0", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true, + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true, + "dev": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "universalify": { + "version": "0.1.2", + "bundled": true, + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true, + "dev": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "fast-check": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-1.10.0.tgz", + "integrity": "sha512-6MoIj+RsnMWNX1cB5IY79Jlt6FPyQ0b7ur+sbJVaQ8F+xWz2E0vyS/HZzhDwrq5ZFxQF95HZdDaRLwFTiAy9Bg==", + "dev": true, + "requires": { + "lorem-ipsum": "~1.0.6", + "pure-rand": "^1.6.2" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lorem-ipsum": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-1.0.6.tgz", + "integrity": "sha512-Rx4XH8X4KSDCKAVvWGYlhAfNqdUP5ZdT4rRyf0jjrvWgtViZimDIlopWNfn/y3lGM5K4uuiAoY28TaD+7YKFrQ==", + "dev": true, + "requires": { + "minimist": "~1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "pkglint": { + "version": "0.24.1", + "dev": true, + "requires": { + "case": "^1.5.5", + "colors": "^1.3.2", + "fs-extra": "^7.0.0", + "semver": "^5.6.0", + "yargs": "^9.0.1" + }, + "dependencies": { + "@types/colors": { + "version": "https://registry.npmjs.org/@types/colors/-/colors-1.2.1.tgz", + "bundled": true, + "requires": { + "colors": "*" + } + }, + "@types/fs-extra": { + "version": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.8.tgz", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "10.12.21", + "bundled": true + }, + "@types/semver": { + "version": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "bundled": true + }, + "@types/yargs": { + "version": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true + }, + "case": { + "version": "1.6.1", + "bundled": true + }, + "cliui": { + "version": "3.2.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": {} + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "colors": { + "version": "1.3.3", + "bundled": true + }, + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "error-ex": { + "version": "1.3.2", + "bundled": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "bundled": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true + }, + "graceful-fs": { + "version": "4.1.15", + "bundled": true + }, + "hosted-git-info": { + "version": "2.7.1", + "bundled": true + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "jsonfile": { + "version": "4.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "bundled": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "bundled": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true + }, + "normalize-package-data": { + "version": "2.4.2", + "bundled": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-limit": { + "version": "1.3.0", + "bundled": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "path-type": { + "version": "2.0.0", + "bundled": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true + }, + "read-pkg": { + "version": "2.0.0", + "bundled": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "bundled": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true + }, + "semver": { + "version": "5.6.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "spdx-correct": { + "version": "3.1.0", + "bundled": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "bundled": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "bundled": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": {} + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "bundled": true + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "universalify": { + "version": "0.1.2", + "bundled": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": {} + }, + "y18n": { + "version": "3.2.1", + "bundled": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true + }, + "yargs": { + "version": "9.0.1", + "bundled": true, + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "bundled": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "pure-rand": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-1.6.2.tgz", + "integrity": "sha512-HNwHOH63m7kCxe0kWEe5jSLwJiL2N83RUUN8POniFuZS+OsbFcMWlvXgxIU2nwKy2zYG2bQan40WBNK4biYPRg==", + "dev": true + } + } } diff --git a/packages/@aws-cdk/cdk/package.json b/packages/@aws-cdk/cdk/package.json index a38d52df4c953..36161b46b50e3 100644 --- a/packages/@aws-cdk/cdk/package.json +++ b/packages/@aws-cdk/cdk/package.json @@ -70,14 +70,8 @@ "pkglint": "^0.24.1" }, "dependencies": { - "@aws-cdk/cx-api": "^0.24.1", - "js-base64": "^2.4.5", - "json-diff": "^0.3.1" + "@aws-cdk/cx-api": "^0.24.1" }, - "bundledDependencies": [ - "json-diff", - "js-base64" - ], "homepage": "https://github.com/awslabs/aws-cdk", "peerDependencies": { "@aws-cdk/cx-api": "^0.24.1" From 297b66b06cdf553651329f7903d75f4b5e0f6435 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Tue, 26 Feb 2019 19:26:23 +0200 Subject: [PATCH 12/24] fix assert test --- packages/@aws-cdk/assert/lib/expect.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/assert/lib/expect.ts b/packages/@aws-cdk/assert/lib/expect.ts index a983da0d96cd3..fa50a36088f47 100644 --- a/packages/@aws-cdk/assert/lib/expect.ts +++ b/packages/@aws-cdk/assert/lib/expect.ts @@ -41,7 +41,7 @@ function isStackClassInstance(x: api.SynthesizedStack | cdk.Stack): x is cdk.Sta function collectStackMetadata(root: cdk.ConstructNode): api.StackMetadata { const result: api.StackMetadata = {}; - for (const construct of root.findAll(cdk.ConstructOrder.DepthFirst)) { + for (const construct of root.findAll(cdk.ConstructOrder.PreOrder)) { const path = `/${root.id}/${construct.node.path}`; for (const entry of construct.node.metadata) { result[path] = result[path] || []; From dca97c62fd28a5d243e9bc2043a950451b89dee8 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Wed, 27 Feb 2019 17:11:25 +0200 Subject: [PATCH 13/24] start establishing the concept of "artifacts" Start moving towards the cloud-assembly specification where an output of a CDK program is a bunch of artifacts and those are processed by the toolkit. Related https://github.com/awslabs/aws-cdk/issues/956 Related https://github.com/awslabs/aws-cdk/issues/233 Related https://github.com/awslabs/aws-cdk/pull/1119 --- design/cloud-assembly.md | 473 ++++++++++++++++++ packages/@aws-cdk/cdk/lib/app.ts | 150 +----- .../@aws-cdk/cdk/lib/cloudformation/stack.ts | 35 +- packages/@aws-cdk/cdk/lib/runtime-info.ts | 85 ++++ packages/@aws-cdk/cdk/lib/synthesis.ts | 150 +++++- packages/@aws-cdk/cdk/test/test.app.ts | 17 +- packages/@aws-cdk/cdk/test/test.synthesis.ts | 229 +++++---- packages/@aws-cdk/cx-api/lib/artifacts.ts | 27 + packages/@aws-cdk/cx-api/lib/cxapi.ts | 32 +- packages/@aws-cdk/cx-api/lib/index.ts | 1 + 10 files changed, 932 insertions(+), 267 deletions(-) create mode 100644 design/cloud-assembly.md create mode 100644 packages/@aws-cdk/cdk/lib/runtime-info.ts create mode 100644 packages/@aws-cdk/cx-api/lib/artifacts.ts diff --git a/design/cloud-assembly.md b/design/cloud-assembly.md new file mode 100644 index 0000000000000..63d8d808ceda1 --- /dev/null +++ b/design/cloud-assembly.md @@ -0,0 +1,473 @@ +# Cloud Assembly Specification, Version 1.0 + +The key words **MUST**, **MUST NOT**, **REQUIRED**, **SHALL**, **SHALL NOT**, **SHOULD**, **SHOULD NOT**, +**RECOMMENDED**, **MAY**, and **OPTIONAL** in this document are to be interpreted as described in [RFC 2119] when they +are spelled out in bold, capital letters (as they are shown here). + +## Introduction +A *Cloud Assembly* is a self-contained document container designed to hold the components of *cloud applications*, +including all the parts that are needed in order to deploy those to a *cloud* provider. This document is the +specification of the *Cloud Assembly* format as well as requirements imposed on *Cloud Assemblers* and *Cloud Runtimes*. + +### Design Goals +The design goals for the *Cloud Assembly Specification* are the following: +* The *Cloud Assembly Specification* is extensible. +* The *Cloud Assembly Specification* is cloud-agnostic. +* The *Cloud Assembly Specification* is easy to implement and use. +* The *Cloud Assembly Specification* supports authenticity and integrity guarantees. +* A *Cloud Assembly* is self-contained, making deployments reproductible. + +## Specification +A *Cloud Assembly* is a ZIP archive that **SHOULD** conform to the [ISO/IEC 21320-1:2015] *Document Container File* +standard. *Cloud Assembly* files **SHOULD** use the `.cloud` extension in order to make them easier to recognize by +users. + +Documents in the archive can be stored with any name and directory structure, however the following entries at the root +of the archive are reserved for special use: +* `manifest.json` **MUST** be present and contains the [manifest document](#manifest-document) for the *Cloud Assembly*. +* `signature.asc`, when present, **MUST** contain the [digital signature](#digital-signature) of the *Cloud Assembly*. + +### Manifest Document +The `manifest.json` file is the entry point of the *Cloud Assembly*. It **MUST** be a valid [JSON] document composed of +a single `object` that conforms to the following schema: + +Key |Type |Required|Description +--------------|---------------------|:------:|----------- +`schema` |`string` |Required|The schema for the document. **MUST** be `cloud-assembly/1.0`. +`droplets` |`Map` |Required|A mapping of [*Logical ID*](#logical-id) to [Droplet](#droplet). +`missing` |`Map`| |A mapping of context keys to [missing information](#missing). + +The [JSON] specification allows for keys to be specified multiple times in a given `object`. However, *Cloud Assembly* +consumers **MAY** assume keys are unique, and *Cloud Assemblers* **SHOULD** avoid generating duplicate keys. If +duplicate keys are present and the manifest parser permits it, the latest specified value **SHOULD** be preferred. + +### Logical ID +*Logical IDs* are `string`s that uniquely identify [Droplet](#droplet)s in the context of a *Cloud Assembly*. +* A *Logical ID* **MUST NOT** be empty. +* A *Logical ID* **SHOULD NOT** exceed `256` characters. +* A *Logical ID* **MUST** be composed of only the following ASCII printable characters: + + Upper-case letters: `A` (`0x41`) through `Z` (`0x5A`) + + Lower-case letters: `a` (`0x61`) through `z` (`0x7A`) + + Numeric characters: `0` (`0x30`) through `9` (`0x39`) + + Plus: `+` (`0x2B`) + + Minus: `-` (`0x2D`) + + Forward-slash: `/` (`0x2F`) + + Underscore: `_` (`0x5F`) +* A *Logical ID* **MUST NOT** contain the `.` (`0x2E`) character as it is used in the string substitution pattern for + cross-droplet references to separate the *Logical ID* from the *attribute* name. + +In other words, *Logical IDs* are expected to match the following regular expression: +```js +/^[A-Za-z0-9+\/_-]{1,256}$/ +``` + +### Droplet +Clouds are made of Droplets. Thet are the building blocks of *Cloud Assemblies*. They model a part of the +*cloud application* that can be deployed independently, provided its dependencies are fulfilled. Droplets are specified +using [JSON] objects that **MUST** conform to the following schema: + +Key |Type |Required|Description +-------------|----------------------|:------:|----------- +`type` |`string` |Required|The [*Droplet Type*](#droplet-type) specifier of this Droplet. +`environment`|`string` |required|The target [environment](#environment) in which Droplet is deployed. +`dependsOn` |`string[]` | |*Logical IDs* of other Droplets that must be deployed before this one. +`metadata` |`Map`| |Arbitrary named [metadata](#metadata) associated with this Droplet. +`properties` |`Map` | |The properties of this Droplet as documented by its maintainers. + +Each [Droplet Type](#droplet-type) can produce output strings that allow Droplets to provide informations that other +[Droplets](#droplet) can use when composing the *cloud application*. Each Droplet implementer is responsible to document +the output attributes it supports. References to these outputs are modeled using special `string` tokens within entries +of the `properties` section of Droplets: + +``` +${LogicalId.attributeName} + ╰───┬───╯ ╰─────┬─────╯ + │ └─ The name of the output attribute + └───────────── The Logical ID of the Droplet +``` + +The following escape sequences are valid: +* `\\` encodes the `\` literal +* `\${` encodes the `${` literal + +Deployment systems **SHOULD** return an error upon encountering an occurrence of the `\` literal that is not part of a +valid escape sequence. + +Droplets **MUST NOT** cause circular dependencies. Deployment systems **SHOULD** detect cycles and fail upon discovering +one. + +#### Droplet Type +Every Droplet has a type specifier, which allows *Cloud Assembly* consumers to know how to deploy it. The type +specifiers are `string`s that use an URI-like syntax (`protocol://path`), providing the coordinates to a reference +implementation for the Droplet behavior. + +Deployment systems **MUST** support at least one protocol, and **SHOULD** support all the protocols specified in +the following sub-sections. + +##### The `npm` protocol +Type specifiers using the `npm` protocol have the following format: +``` +npm://[@namespace/]package/ClassName[@version] +╰┬╯ ╰────┬────╯ ╰──┬──╯ ╰───┬───╯ ╰──┬──╯ + │ │ │ │ └─ Optional version specifier + │ │ │ └─────────── Fully qualified name of the Handler class + │ │ └──────────────────── Name of the NPM package + │ └────────────────────────────── Optional NPM namespace + └───────────────────────────────────────── NPM protocol specifier +``` + +#### Environment +Environments help Deployment systems determine where to deploy a particular Droplet. They are referenced by `string`s +that use an URI-like syntax (`protocol://path`). + +Deployment systems **MUST** support at least one protocol, and **SHOULD** support all the protocols specified in the +following sub-sections. + +##### The `aws` protocol +Environments using the `aws` protocol have the following format: +``` +aws://account/region +╰┬╯ ╰──┬──╯ ╰──┬─╯ + │ │ └─ The name of an AWS region (e.g: eu-west-1) + │ └───────── An AWS account ID (e.g: 123456789012) + └───────────────── AWS protocol specifier +``` + +### Metadata +Metadata can be attached to [Droplets](#droplet) to allow tools that work with *Cloud Assemblies* to share additional +information about the *cloud application*. Metadata **SHOULD NOT** be used to convey data that is necessary for +correctly process the *Cloud Assembly*, since any tool that consumes a *Cloud Assembly* **MAY** choose to ignore any or +all Metadata. + +Key |Type |Required|Description +-------|--------|:------:|----------- +`kind` |`string`|Required|A token identifying the kind of metadata. +`value`|`any` |Required|The value associated with this metadata. + +A common use-case for Metadata is reporting warning or error messages that were emitted during the creation of the +*Cloud Assembly*, so that deployment systems can present this information to users or logs. Warning and error messages +**SHOULD** set the `kind` field to `warning` and `error` respectively, and the `value` field **SHOULD** contain a single +`string`. Deployment systems **MAY** reject *Cloud Assemblies* that include [Droplets](#droplet) that carry one or more +`error` Metadata entries, and they **SHOULD** surface `warning` messages, either directly through their user interface, +or in the execution log. + +### Missing +[Droplets](#droplet) may require contextual information to be available in order to correctly participate in a +*Cloud Assembly*. When information is missing, *Cloud Assembly* producers report the missing information by adding +entries to the `missing` section of the [manifest document](#manifest-document). The values are [JSON] `object`s that +**MUST** conform to the following schema: + +Key |Type |Required|Description +---------------|-----------------|:------:|----------- +`provider` |`string` |Required|A tag that identifies the entity that should provide the information. +`props` |`Map`|Required|Properties that are required in order to obtain the missing information. + +### Digital Signature +#### Signing +*Cloud Assemblers* **SHOULD** support digital signature of *Cloud Assemblies*. When support for digital signature is +present, *Cloud Assemblers*: +* **MUST** require configuration of the [PGP][RFC 4880] key that will be used for signing. + +##### Signing Algorithm +The digital signature of *Cloud Assemblies* starts by establishing an attestation document that provides cryptographic +summary information about the contents of the signed assembly. It is a [JSON] document composed of a single `object` +with the following fields: + +Field |Type |Description +-----------|----------------------|----------- +`timestamp`|`string` |The [ISO 8601] timestamp of the attestation document creation time +`algorithm`|`string` |The hashing algorithm used to derive the `FileData` hashes. +`nonce` |`string` |The nonce used when deriving the `FileData` hashes. +`items` |`Map`|Summary information about the attested files. + +The `algorithm` field **MUST** be set to the standard identifier of a standard hashing algorithm, such as `SHA256`. +Algorithms that are vulnerable to known collision attacks **SHOULD** not be used. + +The `nonce` field **MUST** be set to a byte array generated using a cryptographically secure random number generator. A +`nonce` **MUST NOT** be re-used. It **MUST** be composed of at least `32` bytes, and **SHOULD** be the same length or +larger than the size of the output of the chosen `algorithm`. + +The `items` field **MUST** contain one entry for each file in the *Cloud Assembly*, keyed on the relative path to the +file within the container document, with a value that contains the following keys: +Key |Type |Description +------|--------|----------- +`size`|`string`|The decimal representation of the file size in bytes. +`hash`|`string`|The base-64 encoded result of hashing the file's content appended with the `nonce` using the `algorithm`. + +Here is a schematic example: +```js +{ + // When this attestation doucment was created + "timestamp": "2018-11-15T11:08:52", + // The hashing algorithm for the attestation is SHA256 + "algorithm": "SHA256", + // 32 bytes of cryptographically-secure randomness + "nonce": "2tDLdIoy1VtzLFjfzXVqzsNJHa9862y/WQgqKzC9+xs=", + "items": { + "data/data.bin": { + // The file is really 1024 times the character 'a' + "size": "1024", + // SHA256( + ) + "hash": "HIKJYDnT92EKILbFt2SOzA8dWF0YMEBHS72xLSw4lok=" + }, + /* ...other files of the assembly... */ + } +} +``` + +Once the attestation is ready, it is digitally *signed* using the configured [PGP][RFC 4880] key. The key **MUST** be +valid as of the `timestamp` field included in the attestation. The siganture **MUST** not be detached, and is +**RECOMMENDED** to use the *cleartext signature framework* described in section 7 of [RFC 4880] so the attestation can +be read by a human. + +#### Verifying +Deployment systems **SHOULD** support verifying signed *Cloud Assemblies*. If support for signature verification is not +present, a warning **MUST** be emitted when processing a *Cloud Assembly* that contains the `signature.asc` file. + +Deployment systems that support verifying signed *Cloud Assemblies*: +* **SHOULD** be configurable to *require* that an assembly is signed. When this requirement is active, an error **MUST** + be returned when attempting to deploy an un-signed *Cloud Assembly*. +* **MUST** verify the integrity and authenticity of signed *Cloud Assemblies* prior to attempting to load any file + included in it, except for `signature.asc`. + * An error **MUST** be raised if the *Cloud Assembly*'s integirty is not verified by the signature. + * An error **MUST** be raised if the [PGP][RFC 4880] key has expired according to the signature timestamp. + * An error **MUST** be raised if the [PGP][RFC 4880] key is known to have been revoked. Deployment systems **MAY** + trust locally available information pertaining to the key's validity. +* **SHOULD** allow configuration of a list of trusted [PGP][RFC 4880] keys. + +## Annex +### Examples of Droplets for the AWS Cloud +The Droplet specifications provided in this section are for illustration purpose only. + +#### `@aws-cdk/aws-cloudformation.StackDroplet` +A [*CloudFormation* stack][CFN Stack]. + +##### Properties +Property |Type |Required|Description +-------------|--------------------|:------:|----------- +`stackName` |`string` |Required|The name of the *CloudFormation* stack once deployed. +`template` |`string` |Required|The assembly-relative path to the *CloudFormation* template document. +`parameters` |`Map`| |Parameters to be passed to the [stack][CFN Stack] upon deployment. +`stackPolicy`|`string` | |The assembly-relative path to the [Stack Policy][CFN Stack Policy]. + +##### Output Attributes +Attribute |Type |Description +---------------|--------------------|----------- +`output.`|`string`|Data returned by the [*CloudFormation* Outputs][CFN Output] named `` of the stack. +`stackArn` |`string`|The ARN of the [stack][CFN Stack]. + +##### Example +```json +{ + "type": "npm://@aws-cdk/aws-cloudformation.StackDroplet", + "environment": "aws://000000000000/bermuda-triangle-1", + "properties": { + "template": "my-stack/template.yml", + "parameters": { + "bucketName": "${helperStack.output.bucketName}", + "objectKey": "${helperStack.output.objectKey}" + }, + "stackPolicy": "my-stack/policy.json" + } +} +``` + +[CFN Stack]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html +[CFN Stack Policy]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/protect-stack-resources.html +[CFN Outputs]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/outputs-section-structure.html + +#### `@aws-cdk/assets.FileDroplet` +A file that needs to be uploaded to an *S3* bucket. + +##### Properties +Property |Type |Required|Description +------------|--------|:------:|----------- +`file` |`string`|Required|The assembly-relative path to the file that will be uploaded. +`bucketName`|`string`|Required|The name of the bucket where this file will be uploaded. +`objectKey` |`string`|Required|The key at which to place the object in the bucket. + +##### Output Attributes +Attribute |Type |Description +------------|--------|----------- +`bucketName`|`string`|The name of the bucket where the file was uploaded. +`objectKey` |`string`|The key at which the file was uploaded in the bucket. + +##### Example +```json +{ + "type": "npm://@aws-cdk/assets.FileDroplet", + "environment": "aws://000000000000/bermuda-triangle-1", + "properties": { + "file": "assets/file.bin", + "bucket": "${helperStack.outputs.bucketName}", + "objectKey": "assets/da39a3ee5e6b4b0d3255bfef95601890afd80709/nifty-asset.png" + } +} +``` + +#### `@aws-cdk/aws-ecr.DockerImageDroplet` +A Docker image to be published to an *ECR* registry. + +##### Properties +Property |Type |Required|Description +------------|--------|:------:|----------- +`savedImage`|`string`|Required|The assembly-relative path to the tar archive obtained from `docker image save`. +`pushTarget`|`string`|Required|Where the image should be pushed to (e.g: `.dkr.ecr..amazon.com/`). +`tagName` |`string`| |The name of the tag to use when pushing the image (default: `latest`). + +##### Output Attributes +Attribute |Type |Description +--------------|--------|----------- +`exactImageId`|`string`|An absolute reference to the published image version (`imageName@DIGEST`). +`imageName` |`string`|The full tagged image name (`imageName:tagName`). + +##### Example +```json +{ + "type": "npm://@aws-cdk/aws-ecr.DockerImageDroplet", + "environment": "aws://000000000000/bermuda-triangle-1", + "properties": { + "savedImage": "docker/37e6de0b24fa.tar", + "imageName": "${helperStack.output.ecrImageName}", + "tagName": "latest" + } +} +``` + +### Example +Here is an example the contents of a complete *Cloud Assembly* that deploys AWS resources: +``` +☁️ my-assembly.cloud +├─ manifest.json Cloud Assembly manifest +├─ stacks +│ ├─ PipelineStack.yml CloudFormation template +│ ├─ ServiceStack-beta.yml CloudFormation template +│ ├─ ServiceStack-beta.stack-policy.json CloudFormation stack policy +│ ├─ ServiceStack-prod.yml CloudFormation template +│ └─ ServiceStack-prod.stack-policy.json CloudFormation stack policy +├─ docker +│ └─ docker-image.tar Saved Docker image (docker image save) +├─ assets +│ └─ static-website Files for a static website +│ ├─ index.html +│ └─ style.css +└─ signature.asc Cloud Assembly digital signature +``` + +#### `manifest.json` +```json +{ + "schema": "cloud-assembly/1.0", + "droplets": { + "PipelineStack": { + "type": "npm://@aws-cdk/aws-cloudformation.StackDroplet", + "environment": "aws://123456789012/eu-west-1", + "properties": { + "template": "stacks/PipelineStack.yml" + } + }, + "ServiceStack-beta": { + "type": "npm://@aws-cdk/aws-cloudformation.StackDroplet", + "environment": "aws://123456789012/eu-west-1", + "properties": { + "template": "stacks/ServiceStack-beta.yml", + "stackPolicy": "stacks/ServiceStack-beta.stack-policy.json", + "parameters": { + "image": "${DockerImage.exactImageId}", + "websiteFilesBucket": "${StaticFiles.bucketName}", + "websiteFilesKeyPrefix": "${StaticFiles.keyPrefix}", + } + } + }, + "ServiceStack-prod": { + "type": "npm://@aws-cdk/aws-cloudformation.StackDroplet", + "environment": "aws://123456789012/eu-west-1", + "properties": { + "template": "stacks/ServiceStack-prod.yml", + "stackPolicy": "stacks/ServiceStack-prod.stack-policy.json", + "parameters": { + "image": "${DockerImage.exactImageId}", + "websiteFilesBucket": "${StaticFiles.bucketName}", + "websiteFilesKeyPrefix": "${StaticFiles.keyPrefix}", + } + } + }, + "DockerImage": { + "type": "npm://@aws-cdk/aws-ecr.DockerImageDroplet", + "environment": "aws://123456789012/eu-west-1", + "properties": { + "savedImage": "docker/docker-image.tar", + "imageName": "${PipelineStack.output.ecrImageName}" + } + }, + "StaticFiles": { + "type": "npm://@aws-cdk/assets.DirectoryDroplet", + "environment": "aws://123456789012/eu-west-1", + "properties": { + "directory": "assets/static-website", + "bucketName": "${PipelineStack.output.stagingBucket}" + } + } + } +} +``` + +#### `signature.asc` +```pgp +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +{ + "algorithm": "SHA-256", + "items": { + "assets/static-website/index.html": { + "size": ..., + "hash": "..." + }, + "assets/static-website/style.css": { + "size": ..., + "hash": "..." + }, + "docker/docker-image.tar": { + "size": ..., + "hash": "..." + }, + "manifest.json": { + "size": ..., + "hash": "..." + }, + "stacks/PipelineStack.yml": { + "size": ..., + "hash": "..." + }, + "stacks/ServiceStack-beta.stack-policy.json": { + "size": ..., + "hash": "..." + }, + "stacks/ServiceStack-beta.yml": { + "size": ..., + "hash": "..." + }, + "stacks/ServiceStack-prod.stack-policy.json": { + "size": ..., + "hash": "..." + }, + "stacks/ServiceStack-prod.yml": { + "size": ..., + "hash": "..." + }, + }, + "nonce": "mUz0aYEhMlVmhJLNr5sizPKlJx1Kv38ApBc12NW6wPE=", + "timestamp": "2018-11-06T14:56:23Z" +} +-----BEGIN PGP SIGNATURE----- +[...] +-----END PGP SIGNATURE----- +``` + + +[RFC 2119]: https://tools.ietf.org/html/rfc2119 +[ISO/IEC 21320-1:2015]: https://www.iso.org/standard/60101.html +[JSON]: https://www.json.org +[RFC 4880]: https://tools.ietf.org/html/rfc4880 +[ISO 8601]: https://www.iso.org/standard/40874.html \ No newline at end of file diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 28d1402c7b886..dce46f89e828d 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -1,7 +1,6 @@ import cxapi = require('@aws-cdk/cx-api'); -import { Stack } from './cloudformation/stack'; -import { IConstruct, Root } from './core/construct'; -import { InMemorySynthesisSession, ISynthesisSession, SynthesisSession } from './synthesis'; +import { Root } from './core/construct'; +import { FileSystemStore, InMemoryStore, ISynthesisSession, SynthesisSession } from './synthesis'; /** * Represents a CDK program. @@ -18,22 +17,6 @@ export class App extends Root { this.loadContext(); } - private get stacks() { - const out: { [name: string]: Stack } = { }; - collectStacks(this); - return out; - - function collectStacks(c: IConstruct) { - for (const child of c.node.children) { - if (Stack.isStack(child)) { - out[child.node.id] = child; // TODO: this should probably be changed to uniqueId - } - - collectStacks(child); - } - } - } - /** * Runs the program. Output is written to output directory as specified in the request. */ @@ -44,13 +27,14 @@ export class App extends Root { } const outdir = process.env[cxapi.OUTDIR_ENV]; + let store; if (outdir) { - this._session = new SynthesisSession({ outdir }); + store = new FileSystemStore({ outdir }); } else { - this._session = new InMemorySynthesisSession(); + store = new InMemoryStore(); } - const session = this._session; + const session = this._session = new SynthesisSession(store); // the three holy phases of synthesis: prepare, validate and synthesize @@ -67,18 +51,7 @@ export class App extends Root { // synthesize this.node.synthesizeTree(session); - // write the entrypoint/manifest of this app. It includes a *copy* of the - // synthesized stack output for backwards compatibility - - const manifest: cxapi.SynthesizeResponse = { - version: cxapi.PROTO_RESPONSE_VERSION, - stacks: Object.values(this.stacks).map(s => this.readSynthesizedStack(session, s.artifactName)), - runtime: this.collectRuntimeInformation() - }; - - session.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(manifest, undefined, 2)); - - // lock session - cannot emit more artifacts + // write session manifest and lock store session.finalize(); return session; @@ -90,9 +63,13 @@ export class App extends Root { * @deprecated This method is going to be deprecated in a future version of the CDK */ public synthesizeStack(stackName: string): cxapi.SynthesizedStack { - const stack = this.getStack(stackName); const session = this.run(); - return this.readSynthesizedStack(session, stack.artifactName); + const res = session.manifest.stacks.find(s => s.name === stackName); + if (!res) { + throw new Error(`Stack "${stackName}" not found`); + } + + return res; } /** @@ -107,46 +84,6 @@ export class App extends Root { return ret; } - private readSynthesizedStack(session: ISynthesisSession, artifactName: string) { - return JSON.parse(session.readFile(artifactName).toString()); - } - - private collectRuntimeInformation(): cxapi.AppRuntime { - const libraries: { [name: string]: string } = {}; - - for (const fileName of Object.keys(require.cache)) { - const pkg = findNpmPackage(fileName); - if (pkg && !pkg.private) { - libraries[pkg.name] = pkg.version; - } - } - - // include only libraries that are in the @aws-cdk npm scope - for (const name of Object.keys(libraries)) { - if (!name.startsWith('@aws-cdk/')) { - delete libraries[name]; - } - } - - // add jsii runtime version - libraries['jsii-runtime'] = getJsiiAgentVersion(); - - return { libraries }; - } - - private getStack(stackname: string) { - if (stackname == null) { - throw new Error('Stack name must be defined'); - } - - const stack = this.stacks[stackname]; - - if (!stack) { - throw new Error(`Cannot find stack ${stackname}`); - } - return stack; - } - private loadContext() { const contextJson = process.env[cxapi.CONTEXT_ENV]; const context = !contextJson ? { } : JSON.parse(contextJson); @@ -155,64 +92,3 @@ export class App extends Root { } } } - -/** - * Determines which NPM module a given loaded javascript file is from. - * - * The only infromation that is available locally is a list of Javascript files, - * and every source file is associated with a search path to resolve the further - * ``require`` calls made from there, which includes its own directory on disk, - * and parent directories - for example: - * - * [ '...repo/packages/aws-cdk-resources/lib/cfn/node_modules', - * '...repo/packages/aws-cdk-resources/lib/node_modules', - * '...repo/packages/aws-cdk-resources/node_modules', - * '...repo/packages/node_modules', - * // etc... - * ] - * - * We are looking for ``package.json`` that is anywhere in the tree, except it's - * in the parent directory, not in the ``node_modules`` directory. For this - * reason, we strip the ``/node_modules`` suffix off each path and use regular - * module resolution to obtain a reference to ``package.json``. - * - * @param fileName a javascript file name. - * @returns the NPM module infos (aka ``package.json`` contents), or - * ``undefined`` if the lookup was unsuccessful. - */ -function findNpmPackage(fileName: string): { name: string, version: string, private?: boolean } | undefined { - const mod = require.cache[fileName]; - const paths = mod.paths.map(stripNodeModules); - - try { - const packagePath = require.resolve('package.json', { paths }); - return require(packagePath); - } catch (e) { - return undefined; - } - - /** - * @param s a path. - * @returns ``s`` with any terminating ``/node_modules`` - * (or ``\\node_modules``) stripped off.) - */ - function stripNodeModules(s: string): string { - if (s.endsWith('/node_modules') || s.endsWith('\\node_modules')) { - // /node_modules is 13 characters - return s.substr(0, s.length - 13); - } - return s; - } -} - -function getJsiiAgentVersion() { - let jsiiAgent = process.env.JSII_AGENT; - - // if JSII_AGENT is not specified, we will assume this is a node.js runtime - // and plug in our node.js version - if (!jsiiAgent) { - jsiiAgent = `node.js/${process.version}`; - } - - return jsiiAgent; -} diff --git a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts index 8879f20c4f9ec..ca2275447f4f4 100644 --- a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts +++ b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts @@ -78,11 +78,6 @@ export class Stack extends Construct { */ public readonly name: string; - /** - * The name of the CDK artifact produced by this stack. - */ - public readonly artifactName: string; - /* * Used to determine if this construct is a stack. */ @@ -112,8 +107,6 @@ export class Stack extends Construct { this.logicalIds = new LogicalIDs(props && props.namingScheme ? props.namingScheme : new HashedAddressingScheme()); this.name = this.node.id; - - this.artifactName = `${this.node.uniqueId}.stack.json`; } /** @@ -428,25 +421,21 @@ export class Stack extends Construct { protected synthesize(session: ISynthesisSession): void { const account = this.env.account || 'unknown-account'; const region = this.env.region || 'unknown-region'; - - const environment: cxapi.Environment = { - name: `${account}/${region}`, - account, - region - }; - const missing = Object.keys(this.missingContext).length ? this.missingContext : undefined; + const template = `${this.node.id}.template.json`; - const output: cxapi.SynthesizedStack = { - name: this.node.id, - template: this.toCloudFormation(), - environment, - missing, - metadata: this.collectMetadata(), - dependsOn: noEmptyArray(this.dependencies().map(s => s.node.id)), - }; + // write the CloudFormation template as a JSON file + session.store.writeJson(template, this.toCloudFormation()); - session.writeFile(this.artifactName, JSON.stringify(output, undefined, 2)); + // add an artifact that represents this stack + session.addArtifact(this.node.id, { + type: cxapi.ArtifactType.CloudFormationStack, + dependencies: noEmptyArray(this.dependencies().map(s => s.node.id)), + environment: `aws://${account}/${region}`, + metadata: this.collectMetadata(), + missing, + properties: { template } + }); } /** diff --git a/packages/@aws-cdk/cdk/lib/runtime-info.ts b/packages/@aws-cdk/cdk/lib/runtime-info.ts new file mode 100644 index 0000000000000..863788302abd7 --- /dev/null +++ b/packages/@aws-cdk/cdk/lib/runtime-info.ts @@ -0,0 +1,85 @@ +import cxapi = require('@aws-cdk/cx-api'); + +export function collectRuntimeInformation(): cxapi.AppRuntime { + const libraries: { [name: string]: string } = {}; + + for (const fileName of Object.keys(require.cache)) { + const pkg = findNpmPackage(fileName); + if (pkg && !pkg.private) { + libraries[pkg.name] = pkg.version; + } + } + + // include only libraries that are in the @aws-cdk npm scope + for (const name of Object.keys(libraries)) { + if (!name.startsWith('@aws-cdk/')) { + delete libraries[name]; + } + } + + // add jsii runtime version + libraries['jsii-runtime'] = getJsiiAgentVersion(); + + return { libraries }; +} + +/** + * Determines which NPM module a given loaded javascript file is from. + * + * The only infromation that is available locally is a list of Javascript files, + * and every source file is associated with a search path to resolve the further + * ``require`` calls made from there, which includes its own directory on disk, + * and parent directories - for example: + * + * [ '...repo/packages/aws-cdk-resources/lib/cfn/node_modules', + * '...repo/packages/aws-cdk-resources/lib/node_modules', + * '...repo/packages/aws-cdk-resources/node_modules', + * '...repo/packages/node_modules', + * // etc... + * ] + * + * We are looking for ``package.json`` that is anywhere in the tree, except it's + * in the parent directory, not in the ``node_modules`` directory. For this + * reason, we strip the ``/node_modules`` suffix off each path and use regular + * module resolution to obtain a reference to ``package.json``. + * + * @param fileName a javascript file name. + * @returns the NPM module infos (aka ``package.json`` contents), or + * ``undefined`` if the lookup was unsuccessful. + */ +function findNpmPackage(fileName: string): { name: string, version: string, private?: boolean } | undefined { + const mod = require.cache[fileName]; + const paths = mod.paths.map(stripNodeModules); + + try { + const packagePath = require.resolve('package.json', { paths }); + return require(packagePath); + } catch (e) { + return undefined; + } + + /** + * @param s a path. + * @returns ``s`` with any terminating ``/node_modules`` + * (or ``\\node_modules``) stripped off.) + */ + function stripNodeModules(s: string): string { + if (s.endsWith('/node_modules') || s.endsWith('\\node_modules')) { + // /node_modules is 13 characters + return s.substr(0, s.length - 13); + } + return s; + } +} + +function getJsiiAgentVersion() { + let jsiiAgent = process.env.JSII_AGENT; + + // if JSII_AGENT is not specified, we will assume this is a node.js runtime + // and plug in our node.js version + if (!jsiiAgent) { + jsiiAgent = `node.js/${process.version}`; + } + + return jsiiAgent; +} diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index b824d970529f5..ab58471303776 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -1,10 +1,67 @@ +import cxapi = require('@aws-cdk/cx-api'); import fs = require('fs'); import os = require('os'); import path = require('path'); +import { collectRuntimeInformation } from './runtime-info'; export interface ISynthesisSession { + readonly store: ISessionStore; + readonly manifest: cxapi.AssemblyManifest; + addArtifact(id: string, droplet: cxapi.Artifact): void; + tryGetArtifact(id: string): cxapi.Artifact | undefined; +} + +export class SynthesisSession implements ISynthesisSession { + private readonly artifacts: { [id: string]: cxapi.Artifact } = { }; + private _manifest?: cxapi.AssemblyManifest; + + constructor(public readonly store: ISessionStore) { + + } + + public get manifest() { + if (!this._manifest) { + throw new Error(`Cannot read assembly manifest before the session has been finalized`); + } + + return this._manifest; + } + + public addArtifact(id: string, artifact: cxapi.Artifact): void { + cxapi.validateArtifact(artifact); + this.store.writeFile(id, JSON.stringify(artifact, undefined, 2)); + this.artifacts[id] = artifact; + } + + public tryGetArtifact(id: string): cxapi.Artifact | undefined { + if (!this.store.exists(id)) { + return undefined; + } + + return JSON.parse(this.store.readFile(id).toString()); + } + + public finalize(): cxapi.AssemblyManifest { + const manifest: cxapi.SynthesizeResponse = this._manifest = { + version: cxapi.PROTO_RESPONSE_VERSION, + artifacts: this.artifacts, + runtime: collectRuntimeInformation(), + + // for backwards compatbility + stacks: renderLegacyStacks(this.artifacts, this.store), + }; + + // write the manifest (under both legacy and new name) + this.store.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(manifest, undefined, 2)); + this.store.writeFile(cxapi.MANIFEST_FILE, JSON.stringify(manifest, undefined, 2)); + + return manifest; + } +} + +export interface ISessionStore { /** - * Creates a directory under the session directory and returns it's full path. + * 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. */ @@ -18,38 +75,56 @@ export interface ISynthesisSession { readdir(directoryName: string): string[]; /** - * Writes a file into the synthesis session directory. + * 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; /** - * Reads a file from the synthesis session directory. + * 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; /** - * @returns true if the file `fileName` exists in the session directory. + * 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 artifacts that were emitted to the session. + * List all top-level files that were emitted to the store. */ list(): string[]; /** - * Finalizes the session. After this is called, the session will be locked for - * writing. + * Do not allow further writes into the store. */ finalize(): void; } export interface SynthesisSessionOptions { + /** + * Where to store the + */ + store: ISessionStore; +} + +export interface FileSystemStoreOptions { /** * The output directory for synthesis artifacts */ @@ -59,11 +134,11 @@ export interface SynthesisSessionOptions { /** * Can be used to prepare and emit synthesis artifacts into an output directory. */ -export class SynthesisSession implements ISynthesisSession { +export class FileSystemStore implements ISessionStore { private readonly outdir: string; private locked = false; - constructor(options: SynthesisSessionOptions) { + constructor(options: FileSystemStoreOptions) { this.outdir = options.outdir; return; } @@ -75,6 +150,10 @@ export class SynthesisSession implements ISynthesisSession { 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)) { @@ -84,6 +163,10 @@ export class SynthesisSession implements ISynthesisSession { 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); @@ -127,7 +210,7 @@ export class SynthesisSession implements ISynthesisSession { } } -export class InMemorySynthesisSession implements ISynthesisSession { +export class InMemoryStore implements ISessionStore { private files: { [fileName: string]: any } = { }; private dirs: { [dirName: string]: string } = { }; // value is path to a temporary directory @@ -138,6 +221,10 @@ export class InMemorySynthesisSession implements ISynthesisSession { 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`); @@ -145,6 +232,10 @@ export class InMemorySynthesisSession implements ISynthesisSession { 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; } @@ -182,4 +273,43 @@ export class InMemorySynthesisSession implements ISynthesisSession { throw new Error('Session has already been finalized'); } } +} + +function renderLegacyStacks(artifacts: { [id: string]: cxapi.Artifact }, store: ISessionStore) { + // special case for backwards compat. build a list of stacks for the manifest + const stacks = new Array(); + + for (const [ id, artifact ] of Object.entries(artifacts)) { + if (artifact.type === cxapi.ArtifactType.CloudFormationStack) { + const templateFile = (artifact.properties || {}).template; + if (!templateFile) { + throw new Error(`Invalid cloudformation artifact. Missing "template" property`); + } + const template = store.readJson(templateFile); + + const match = cxapi.AWS_ENV_REGEX.exec(artifact.environment); + if (!match) { + throw new Error(`"environment" must match regex: ${cxapi.AWS_ENV_REGEX}`); + } + + const synthStack: cxapi.SynthesizedStack = { + name: id, + environment: { name: artifact.environment.substr('aws://'.length), account: match[1], region: match[2] }, + template, + metadata: artifact.metadata || {}, + }; + + if (artifact.dependencies && artifact.dependencies.length > 0) { + synthStack.dependsOn = artifact.dependencies; + } + + if (artifact.missing) { + synthStack.missing = artifact.missing; + } + + stacks.push(synthStack); + } + } + + return stacks; } \ No newline at end of file diff --git a/packages/@aws-cdk/cdk/test/test.app.ts b/packages/@aws-cdk/cdk/test/test.app.ts index 2bc831ccdde76..25106b825b7e0 100644 --- a/packages/@aws-cdk/cdk/test/test.app.ts +++ b/packages/@aws-cdk/cdk/test/test.app.ts @@ -16,7 +16,7 @@ function withApp(context: { [key: string]: any } | undefined, block: (app: App) const session = app.run(); - return JSON.parse(session.readFile(cxapi.OUTFILE_NAME)); + return session.manifest; } function synth(context?: { [key: string]: any }): cxapi.SynthesizeResponse { @@ -59,6 +59,7 @@ export = { // clean up metadata so assertion will be sane response.stacks.forEach(s => delete s.metadata); delete response.runtime; + delete response.artifacts; test.deepEqual(response, { version: '0.19.0', @@ -90,13 +91,7 @@ export = { const stack = new Stack(prog, 'MyStack'); new Resource(stack, 'MyResource', { type: 'MyResourceType' }); - let throws; - try { - prog.synthesizeStacks(['foo']); - } catch (e) { - throws = e.message; - } - test.ok(throws.indexOf('Cannot find stack foo') !== -1); + test.throws(() => prog.synthesizeStacks(['foo']), /foo/); test.deepEqual(prog.synthesizeStack('MyStack').template, { Resources: { MyResource: { Type: 'MyResourceType' } } }); @@ -264,7 +259,7 @@ export = { new Resource(stack, 'MyResource', { type: 'Resource::Type' }); }); - const libs = response.runtime.libraries; + const libs = (response.runtime && response.runtime.libraries) || { }; const version = require('../package.json').version; test.deepEqual(libs['@aws-cdk/cdk'], version); @@ -281,7 +276,7 @@ export = { new Resource(stack, 'MyResource', { type: 'Resource::Type' }); }); - const libs = response.runtime.libraries; + const libs = (response.runtime && response.runtime.libraries) || { }; test.deepEqual(libs['jsii-runtime'], `Java/1.2.3.4`); delete process.env.JSII_AGENT; @@ -294,7 +289,7 @@ export = { new Resource(stack, 'MyResource', { type: 'Resource::Type' }); }); - const libs = response.runtime.libraries; + const libs = (response.runtime && response.runtime.libraries) || { }; const version = require('../package.json').version; test.deepEqual(libs, { diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index 637149a25be68..d97c87feb4c02 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -4,39 +4,12 @@ import { Test } from 'nodeunit'; import os = require('os'); import path = require('path'); import cdk = require('../lib'); -import { InMemorySynthesisSession, SynthesisSession } from '../lib'; +import { FileSystemStore, InMemoryStore, SynthesisSession } from '../lib'; -const sessionTestMatix: any = {}; +const storeTestMatrix: any = {}; export = { - 'constructs that implement "synthesize" can emit artifacts during synthesis'(test: Test) { - // GIVEN - const app = new cdk.App(); - new Synthesizer1(app, 'synthe1'); - const s2 = new Synthesizer2(app, 'synthe2'); - new Synthesizer3(s2, 'synthe3'); - - // WHEN - const session = app.run(); - - // THEN - test.deepEqual(session.readFile('s1.txt'), 'hello, s1'); - test.deepEqual(session.readFile('s2.txt'), 'hello, s2'); - - test.deepEqual(session.list(), [ - 'cdk.out', - 's1.txt', - 's2.txt', - 'synthe2Group0512C945A.txt', - 'synthe2Group181E95665.txt', - 'synthe2Group20BD1A3CD.txt', - 'synthe2synthe30CE80559.txt' - ]); - - test.done(); - }, - - 'cdk.out contains all synthesized stacks'(test: Test) { + 'backwards compatibility: cdk.out contains all synthesized stacks'(test: Test) { // GIVEN const app = new cdk.App(); const stack1 = new cdk.Stack(app, 'stack1'); @@ -47,7 +20,7 @@ export = { // WHEN const session = app.run(); - const manifest: cxapi.SynthesizeResponse = JSON.parse(session.readFile(cxapi.OUTFILE_NAME).toString()); + const manifest = session.manifest; // THEN const t1 = manifest.stacks.find(s => s.name === 'stack1')!.template; @@ -67,96 +40,184 @@ export = { test.done(); }, - 'session': sessionTestMatix + 'store': storeTestMatrix }; -const sessionTests = { - 'writeFile()/readFile()'(test: Test, session: cdk.ISynthesisSession) { +// +// all these tests will be executed for each type of store +// +const storeTests = { + 'writeFile()/readFile()'(test: Test, store: cdk.ISessionStore) { // WHEN - session.writeFile('bla.txt', 'hello'); - session.writeFile('hey.txt', '1234'); + store.writeFile('bla.txt', 'hello'); + store.writeFile('hey.txt', '1234'); // THEN - test.deepEqual(session.readFile('bla.txt').toString(), 'hello'); - test.deepEqual(session.readFile('hey.txt').toString(), '1234'); - test.throws(() => session.writeFile('bla.txt', 'override is forbidden')); + 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 - session.finalize(); + store.finalize(); // THEN - test.throws(() => session.writeFile('another.txt', 'locked!')); + test.throws(() => store.writeFile('another.txt', 'locked!')); test.done(); }, - 'exists() for files'(test: Test, session: cdk.ISynthesisSession) { + 'exists() for files'(test: Test, store: cdk.ISessionStore) { // WHEN - session.writeFile('A.txt', 'aaa'); + store.writeFile('A.txt', 'aaa'); // THEN - test.ok(session.exists('A.txt')); - test.ok(!session.exists('B.txt')); + test.ok(store.exists('A.txt')); + test.ok(!store.exists('B.txt')); test.done(); }, - 'mkdir'(test: Test, session: cdk.ISynthesisSession) { + 'mkdir'(test: Test, store: cdk.ISessionStore) { // WHEN - const dir1 = session.mkdir('dir1'); - const dir2 = session.mkdir('dir2'); + 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(() => session.mkdir('dir1')); + test.throws(() => store.mkdir('dir1')); // WHEN - session.finalize(); - test.throws(() => session.mkdir('dir3')); + store.finalize(); + test.throws(() => store.mkdir('dir3')); test.done(); }, - 'list'(test: Test, session: cdk.ISynthesisSession) { + 'list'(test: Test, store: cdk.ISessionStore) { // WHEN - session.mkdir('dir1'); - session.writeFile('file1.txt', 'boom1'); + store.mkdir('dir1'); + store.writeFile('file1.txt', 'boom1'); // THEN - test.deepEqual(session.list(), ['dir1', 'file1.txt']); + test.deepEqual(store.list(), ['dir1', 'file1.txt']); test.done(); - } -}; + }, -for (const [name, fn] of Object.entries(sessionTests)) { - const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'synthesis-tests')); - const fsSession = new SynthesisSession({ outdir }); - const memorySession = new InMemorySynthesisSession(); - sessionTestMatix[`SynthesisSession - ${name}`] = (test: Test) => fn(test, fsSession); - sessionTestMatix[`InMemorySession - ${name}`] = (test: Test) => fn(test, memorySession); -} + 'SynthesisSession'(test: Test, store: cdk.ISessionStore) { + // GIVEN + const session = new SynthesisSession(store); + const templateFile = 'foo.template.json'; -class Synthesizer1 extends cdk.Construct { - public synthesize(s: cdk.ISynthesisSession) { - s.writeFile('s1.txt', 'hello, s1'); - } -} + // WHEN + session.addArtifact('my-first-artifact', { + type: cxapi.ArtifactType.CloudFormationStack, + environment: 'aws://1222344/us-east-1', + dependencies: ['a', 'b'], + metadata: { + foo: { bar: 123 } + }, + properties: { + template: templateFile, + prop1: 1234, + prop2: 555 + }, + missing: { + foo: { + provider: 'context-provider', + props: { + a: 'A', + b: 2 + } + } + } + }); -class Synthesizer2 extends cdk.Construct { - constructor(scope: cdk.Construct, id: string) { - super(scope, id); + session.addArtifact('minimal-artifact', { + type: cxapi.ArtifactType.CloudFormationStack, + environment: 'aws://111/helo-world', + properties: { + template: templateFile + } + }); - const group = new cdk.Construct(this, 'Group'); - for (let i = 0; i < 3; ++i) { - new Synthesizer3(group, `${i}`); - } - } + session.store.writeJson(templateFile, { + Resources: { + MyTopic: { + Type: 'AWS::S3::Topic' + } + } + }); - public synthesize(s: cdk.ISynthesisSession) { - s.writeFile('s2.txt', 'hello, s2'); - } -} + session.finalize(); -class Synthesizer3 extends cdk.Construct { - public synthesize(s: cdk.ISynthesisSession) { - s.writeFile(this.node.uniqueId + '.txt', 'hello, s3'); + // THEN + delete session.manifest.stacks; // remove legacy + delete session.manifest.runtime; // deterministic tests + + // verify the manifest looks right + test.deepEqual(session.manifest, { + version: cxapi.PROTO_RESPONSE_VERSION, + artifacts: { + 'my-first-artifact': { + type: 'aws:cloudformation:stack', + environment: 'aws://1222344/us-east-1', + dependencies: ['a', 'b'], + metadata: { foo: { bar: 123 } }, + properties: { template: 'foo.template.json', prop1: 1234, prop2: 555 }, + missing: { + foo: { provider: 'context-provider', props: { a: 'A', b: 2 } } + } + }, + 'minimal-artifact': { + type: 'aws:cloudformation:stack', + environment: 'aws://111/helo-world', + properties: { template: 'foo.template.json' } + } + } + }); + + // verify we have a template file + test.deepEqual(session.store.readJson(templateFile), { + Resources: { + MyTopic: { + Type: 'AWS::S3::Topic' + } + } + }); + + test.done(); } +}; + +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); } + +// class Synthesizer1 extends cdk.Construct { +// public synthesize(s: cdk.ISynthesisSession) { +// s.writeFile('s1.txt', 'hello, s1'); +// } +// } + +// class Synthesizer2 extends cdk.Construct { +// constructor(scope: cdk.Construct, id: string) { +// super(scope, id); + +// const group = new cdk.Construct(this, 'Group'); +// for (let i = 0; i < 3; ++i) { +// new Synthesizer3(group, `${i}`); +// } +// } + +// public synthesize(s: cdk.ISynthesisSession) { +// s.writeFile('s2.txt', 'hello, s2'); +// } +// } + +// class Synthesizer3 extends cdk.Construct { +// public synthesize(s: cdk.ISynthesisSession) { +// s.writeFile(this.node.uniqueId + '.txt', 'hello, s3'); +// } +// } diff --git a/packages/@aws-cdk/cx-api/lib/artifacts.ts b/packages/@aws-cdk/cx-api/lib/artifacts.ts new file mode 100644 index 0000000000000..4d222d5a3f8a2 --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/artifacts.ts @@ -0,0 +1,27 @@ +export const AWS_ENV_REGEX = /aws\:\/\/([0-9]+|unknown-account)\/([a-z\-0-9]+)/; + +export enum ArtifactType { + CloudFormationStack = 'aws:cloudformation:stack', + DockerImage = 'aws:docker', + File = 'aws:file' +} + +export interface Artifact { + type: ArtifactType; + environment: string; // format: aws://account/region + properties?: { [name: string]: any }; + metadata?: { [path: string]: any }; + dependencies?: string[]; + missing?: { [key: string]: any }; + + /** + * Build instructions for this artifact (for example, lambda-builders, zip directory, docker build, etc) + */ + build?: any; +} + +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}`); + } +} \ 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 867fd4a1af323..c6cd373ee1235 100644 --- a/packages/@aws-cdk/cx-api/lib/cxapi.ts +++ b/packages/@aws-cdk/cx-api/lib/cxapi.ts @@ -2,6 +2,7 @@ * File with definitions for the interface between the Cloud Executable and the CDK toolkit. */ +import { Artifact } from './artifacts'; import { Environment } from './environment'; /** @@ -22,7 +23,16 @@ import { Environment } from './environment'; */ export const PROTO_RESPONSE_VERSION = '0.19.0'; +/** + * @deprecated Use `MANIFEST_FILE` + */ export const OUTFILE_NAME = 'cdk.out'; + +/** + * The name of the root manifest file of the assembly. + */ +export const MANIFEST_FILE = "manifest.json"; + export const OUTDIR_ENV = 'CDK_OUTDIR'; export const CONTEXT_ENV = 'CDK_CONTEXT_JSON'; @@ -38,15 +48,33 @@ export interface MissingContext { }; } -export interface SynthesizeResponse { +export interface AssemblyManifest { /** * Protocol version */ version: string; - stacks: SynthesizedStack[]; + + /** + * The set of artifacts in this assembly. + */ + artifacts?: { [id: string]: Artifact }; + + /** + * Runtime information. + */ runtime?: AppRuntime; + + /** + * @deprecated stacks should be read from `Artifacts`. + */ + stacks: SynthesizedStack[]; } +/** + * @deprecated use `AssemblyManifest` + */ +export type SynthesizeResponse = AssemblyManifest; + /** * A complete synthesized stack */ diff --git a/packages/@aws-cdk/cx-api/lib/index.ts b/packages/@aws-cdk/cx-api/lib/index.ts index 8be9dc02a8bd7..b2bf7536b9c3a 100644 --- a/packages/@aws-cdk/cx-api/lib/index.ts +++ b/packages/@aws-cdk/cx-api/lib/index.ts @@ -5,3 +5,4 @@ export * from './context/vpc'; export * from './context/ssm-parameter'; export * from './context/availability-zones'; export * from './metadata/assets'; +export * from './artifacts'; From b4b3847efc99d310960d1ea5a4c5405021777437 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Wed, 27 Feb 2019 17:31:41 +0200 Subject: [PATCH 14/24] only write "stacks" in legacy cdk.out --- packages/@aws-cdk/cdk/lib/synthesis.ts | 10 +++--- packages/@aws-cdk/cdk/test/test.synthesis.ts | 35 +++----------------- 2 files changed, 10 insertions(+), 35 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index ab58471303776..eb1c083443730 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -46,15 +46,15 @@ export class SynthesisSession implements ISynthesisSession { version: cxapi.PROTO_RESPONSE_VERSION, artifacts: this.artifacts, runtime: collectRuntimeInformation(), - - // for backwards compatbility - stacks: renderLegacyStacks(this.artifacts, this.store), + stacks: [], // this is required }; - // write the manifest (under both legacy and new name) - this.store.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(manifest, undefined, 2)); this.store.writeFile(cxapi.MANIFEST_FILE, JSON.stringify(manifest, undefined, 2)); + // render the legacy manifest (cdk.out) which also contains a "stacks" attribute with all the rendered stacks. + manifest.stacks = renderLegacyStacks(this.artifacts, this.store); + this.store.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(manifest, undefined, 2)); + return manifest; } } diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index d97c87feb4c02..32f8e14b0bbc9 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -148,13 +148,15 @@ const storeTests = { session.finalize(); + const manifest = session.store.readJson(cxapi.MANIFEST_FILE); + // THEN - delete session.manifest.stacks; // remove legacy - delete session.manifest.runtime; // deterministic tests + delete manifest.runtime; // deterministic tests // verify the manifest looks right - test.deepEqual(session.manifest, { + test.deepEqual(manifest, { version: cxapi.PROTO_RESPONSE_VERSION, + stacks: [], // here for legacy reasons artifacts: { 'my-first-artifact': { type: 'aws:cloudformation:stack', @@ -194,30 +196,3 @@ for (const [name, fn] of Object.entries(storeTests)) { storeTestMatrix[`FileSystemStore - ${name}`] = (test: Test) => fn(test, fsStore); storeTestMatrix[`InMemoryStore - ${name}`] = (test: Test) => fn(test, memoryStore); } - -// class Synthesizer1 extends cdk.Construct { -// public synthesize(s: cdk.ISynthesisSession) { -// s.writeFile('s1.txt', 'hello, s1'); -// } -// } - -// class Synthesizer2 extends cdk.Construct { -// constructor(scope: cdk.Construct, id: string) { -// super(scope, id); - -// const group = new cdk.Construct(this, 'Group'); -// for (let i = 0; i < 3; ++i) { -// new Synthesizer3(group, `${i}`); -// } -// } - -// public synthesize(s: cdk.ISynthesisSession) { -// s.writeFile('s2.txt', 'hello, s2'); -// } -// } - -// class Synthesizer3 extends cdk.Construct { -// public synthesize(s: cdk.ISynthesisSession) { -// s.writeFile(this.node.uniqueId + '.txt', 'hello, s3'); -// } -// } From 362faa5de74651c4b605ccba94a8b105c1eef7c3 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Wed, 27 Feb 2019 17:49:57 +0200 Subject: [PATCH 15/24] ISynthesizable Instead of an empty protected method, use an interface to discover if a construct is synthesizable. --- packages/@aws-cdk/cdk/lib/app.ts | 10 ++++--- packages/@aws-cdk/cdk/lib/core/construct.ts | 29 --------------------- packages/@aws-cdk/cdk/lib/synthesis.ts | 11 ++++++++ 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index dce46f89e828d..13455da837ba1 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -1,5 +1,5 @@ import cxapi = require('@aws-cdk/cx-api'); -import { Root } from './core/construct'; +import { ConstructOrder, Root } from './core/construct'; import { FileSystemStore, InMemoryStore, ISynthesisSession, SynthesisSession } from './synthesis'; /** @@ -48,8 +48,12 @@ export class App extends Root { throw new Error(`Validation failed with the following errors:\n ${errorList}`); } - // synthesize - this.node.synthesizeTree(session); + // synthesize (leaves first) + for (const c of this.node.findAll(ConstructOrder.PostOrder)) { + if (SynthesisSession.isSynthesizable(c)) { + c.synthesize(session); + } + } // write session manifest and lock store session.finalize(); diff --git a/packages/@aws-cdk/cdk/lib/core/construct.ts b/packages/@aws-cdk/cdk/lib/core/construct.ts index 9daf54c1bd2f8..7892adc9b7f66 100644 --- a/packages/@aws-cdk/cdk/lib/core/construct.ts +++ b/packages/@aws-cdk/cdk/lib/core/construct.ts @@ -1,7 +1,6 @@ import cxapi = require('@aws-cdk/cx-api'); import { IAspect } from '../aspects/aspect'; import { CloudFormationJSON } from '../cloudformation/cloudformation-json'; -import { ISynthesisSession } from '../synthesis'; import { makeUniqueId } from '../util/uniqueid'; import { IDependable } from './dependency'; import { Token, unresolved } from './tokens'; @@ -341,19 +340,6 @@ export class ConstructNode { } } - /** - * Synthesizes the entire subtree by writing artifacts into a synthesis session. - */ - public synthesizeTree(session: ISynthesisSession) { - const constructs = this.host.node.findAll(ConstructOrder.PostOrder); - - for (const construct of constructs) { - if (Construct.isConstruct(construct)) { - (construct as any).synthesize(session); - } - } - } - /** * Applies the aspect to this Constructs node */ @@ -650,21 +636,6 @@ export class Construct implements IConstruct { protected prepare(): void { return; } - - /** - * Synthesizes this construct into artifacts. - * - * This method can be overloaded by any construct that wishes to emit artifacts during - * the tree synthesis. For example, the `Stack` construct overrides this and produces - * CloudFormation templates, `Asset` overrides this to produce asset artifacts, etc. - * - * To emit artifacts, use the API of the `Session` argument. - * - * @param _session synthesis session - */ - protected synthesize(_session: ISynthesisSession): void { - return; - } } /** diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index eb1c083443730..ea500fe138f32 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -4,6 +4,10 @@ import os = require('os'); import path = require('path'); import { collectRuntimeInformation } from './runtime-info'; +export interface ISynthesizable { + synthesize(session: ISynthesisSession): void; +} + export interface ISynthesisSession { readonly store: ISessionStore; readonly manifest: cxapi.AssemblyManifest; @@ -12,6 +16,13 @@ export interface ISynthesisSession { } export class SynthesisSession implements ISynthesisSession { + /** + * @returns true if `obj` implements `ISynthesizable`. + */ + public static isSynthesizable(obj: any): obj is ISynthesizable { + return 'synthesize' in obj; + } + private readonly artifacts: { [id: string]: cxapi.Artifact } = { }; private _manifest?: cxapi.AssemblyManifest; From d8a7e95931c43c380fcd4106179bd7c536493525 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Wed, 27 Feb 2019 18:05:57 +0200 Subject: [PATCH 16/24] Rename "finalize" to "close", because Java --- packages/@aws-cdk/cdk/lib/app.ts | 2 +- packages/@aws-cdk/cdk/lib/synthesis.ts | 2 +- packages/@aws-cdk/cdk/test/test.synthesis.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 13455da837ba1..0db451bb0ec41 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -56,7 +56,7 @@ export class App extends Root { } // write session manifest and lock store - session.finalize(); + session.close(); return session; } diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index ea500fe138f32..935cec97f6ca0 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -52,7 +52,7 @@ export class SynthesisSession implements ISynthesisSession { return JSON.parse(this.store.readFile(id).toString()); } - public finalize(): cxapi.AssemblyManifest { + public close(): cxapi.AssemblyManifest { const manifest: cxapi.SynthesizeResponse = this._manifest = { version: cxapi.PROTO_RESPONSE_VERSION, artifacts: this.artifacts, diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index 32f8e14b0bbc9..0d4016d361613 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -146,7 +146,7 @@ const storeTests = { } }); - session.finalize(); + session.close(); const manifest = session.store.readJson(cxapi.MANIFEST_FILE); From 9536a173bf4e607ba00d5fb0073d6d85023670d5 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Wed, 27 Feb 2019 21:51:52 +0200 Subject: [PATCH 17/24] allow disabling legacy manifest in new versions --- packages/@aws-cdk/cdk/lib/app.ts | 43 +++++++-- .../@aws-cdk/cdk/lib/cloudformation/stack.ts | 30 +++--- packages/@aws-cdk/cdk/lib/synthesis.ts | 56 ++++++++--- packages/@aws-cdk/cdk/test/test.app.ts | 13 +-- packages/@aws-cdk/cdk/test/test.synthesis.ts | 92 +++++++++++++++++-- packages/@aws-cdk/cx-api/lib/cxapi.ts | 33 ++++--- 6 files changed, 207 insertions(+), 60 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 0db451bb0ec41..f24b774781b92 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -7,14 +7,20 @@ import { FileSystemStore, InMemoryStore, ISynthesisSession, SynthesisSession } f */ export class App extends Root { private _session?: ISynthesisSession; + private readonly legacyManifest: boolean; + private readonly runtimeInformation: boolean; /** * Initializes a CDK application. * @param request Optional toolkit request (e.g. for tests) */ - constructor() { + constructor(context?: { [key: string]: string }) { super(); - this.loadContext(); + this.loadContext(context); + + // both are reverse logic + this.legacyManifest = this.node.getContext(cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT) === 'true' ? false : true; + this.runtimeInformation = this.node.getContext(cxapi.DISABLE_RUNTIME_INFO_CONTEXT) === 'true' ? false : true; } /** @@ -34,7 +40,11 @@ export class App extends Root { store = new InMemoryStore(); } - const session = this._session = new SynthesisSession(store); + const session = this._session = new SynthesisSession({ + store, + legacyManifest: this.legacyManifest, + runtimeInformation: this.runtimeInformation + }); // the three holy phases of synthesis: prepare, validate and synthesize @@ -62,13 +72,19 @@ export class App extends Root { } /** - * Synthesize and validate a single stack + * 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 res = session.manifest.stacks.find(s => s.name === stackName); + const legacy: cxapi.SynthesizeResponse = session.store.readJson(cxapi.OUTFILE_NAME); + + const res = legacy.stacks.find(s => s.name === stackName); if (!res) { throw new Error(`Stack "${stackName}" not found`); } @@ -88,11 +104,20 @@ export class App extends Root { return ret; } - private loadContext() { + private loadContext(defaults: { [key: string]: string } = { }) { + // primve with defaults passed through constructor + for (const [ k, v ] of Object.entries(defaults)) { + this.node.setContext(k, v); + } + + // read from environment const contextJson = process.env[cxapi.CONTEXT_ENV]; - const context = !contextJson ? { } : JSON.parse(contextJson); - for (const key of Object.keys(context)) { - this.node.setContext(key, context[key]); + const contextFromEnvironment = contextJson + ? JSON.parse(contextJson) + : { }; + + for (const [ k, v ] of Object.entries(contextFromEnvironment)) { + this.node.setContext(k, v); } } } diff --git a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts index ca2275447f4f4..fb0b779989e33 100644 --- a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts +++ b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts @@ -421,21 +421,33 @@ export class Stack extends Construct { protected synthesize(session: ISynthesisSession): void { const account = this.env.account || 'unknown-account'; const region = this.env.region || 'unknown-region'; - const missing = Object.keys(this.missingContext).length ? this.missingContext : undefined; const template = `${this.node.id}.template.json`; // write the CloudFormation template as a JSON file session.store.writeJson(template, this.toCloudFormation()); - // add an artifact that represents this stack - session.addArtifact(this.node.id, { + const artifact: cxapi.Artifact = { type: cxapi.ArtifactType.CloudFormationStack, - dependencies: noEmptyArray(this.dependencies().map(s => s.node.id)), environment: `aws://${account}/${region}`, - metadata: this.collectMetadata(), - missing, properties: { template } - }); + }; + + const deps = this.dependencies().map(s => s.node.id); + if (deps.length > 0) { + artifact.dependencies = deps; + } + + const meta = this.collectMetadata(); + if (Object.keys(meta).length > 0) { + artifact.metadata = meta; + } + + if (this.missingContext && Object.keys(this.missingContext).length > 0) { + artifact.missing = this.missingContext; + } + + // add an artifact that represents this stack + session.addArtifact(this.node.id, artifact); } /** @@ -575,7 +587,3 @@ function findResources(roots: Iterable): Resource[] { } return ret; } - -function noEmptyArray(xs: T[]): T[] | undefined { - return xs.length > 0 ? xs : undefined; -} diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index 935cec97f6ca0..82a3047ffafff 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -15,6 +15,25 @@ export interface ISynthesisSession { tryGetArtifact(id: string): cxapi.Artifact | undefined; } +export interface SynthesisSessionOptions { + /** + * The file store used for this session. + */ + store: ISessionStore; + + /** + * Emit the legacy manifest (`cdk.out`) when the session is closed (alongside `manifest.json`). + * @default false + */ + legacyManifest?: boolean; + + /** + * Include runtime information (module versions) in manifest. + * @default true + */ + runtimeInformation?: boolean; +} + export class SynthesisSession implements ISynthesisSession { /** * @returns true if `obj` implements `ISynthesizable`. @@ -23,11 +42,17 @@ export class SynthesisSession implements ISynthesisSession { return 'synthesize' in obj; } + public readonly store: ISessionStore; + private readonly artifacts: { [id: string]: cxapi.Artifact } = { }; private _manifest?: cxapi.AssemblyManifest; + private readonly legacyManifest: boolean; + private readonly runtimeInfo: boolean; - constructor(public readonly store: ISessionStore) { - + constructor(options: SynthesisSessionOptions) { + this.store = options.store; + this.legacyManifest = options.legacyManifest !== undefined ? options.legacyManifest : false; + this.runtimeInfo = options.runtimeInformation !== undefined ? options.runtimeInformation : true; } public get manifest() { @@ -40,31 +65,34 @@ export class SynthesisSession implements ISynthesisSession { public addArtifact(id: string, artifact: cxapi.Artifact): void { cxapi.validateArtifact(artifact); - this.store.writeFile(id, JSON.stringify(artifact, undefined, 2)); this.artifacts[id] = artifact; } public tryGetArtifact(id: string): cxapi.Artifact | undefined { - if (!this.store.exists(id)) { - return undefined; - } - - return JSON.parse(this.store.readFile(id).toString()); + return this.artifacts[id]; } public close(): cxapi.AssemblyManifest { - const manifest: cxapi.SynthesizeResponse = this._manifest = { + const manifest: cxapi.AssemblyManifest = this._manifest = { version: cxapi.PROTO_RESPONSE_VERSION, artifacts: this.artifacts, - runtime: collectRuntimeInformation(), - stacks: [], // this is required }; + if (this.runtimeInfo) { + manifest.runtime = collectRuntimeInformation(); + } + this.store.writeFile(cxapi.MANIFEST_FILE, JSON.stringify(manifest, undefined, 2)); - // render the legacy manifest (cdk.out) which also contains a "stacks" attribute with all the rendered stacks. - manifest.stacks = renderLegacyStacks(this.artifacts, this.store); - this.store.writeFile(cxapi.OUTFILE_NAME, JSON.stringify(manifest, undefined, 2)); + if (this.legacyManifest) { + const legacy: cxapi.SynthesizeResponse = { + ...manifest, + stacks: renderLegacyStacks(this.artifacts, this.store) + }; + + // 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)); + } return manifest; } diff --git a/packages/@aws-cdk/cdk/test/test.app.ts b/packages/@aws-cdk/cdk/test/test.app.ts index 25106b825b7e0..bf8dbcc487d82 100644 --- a/packages/@aws-cdk/cdk/test/test.app.ts +++ b/packages/@aws-cdk/cdk/test/test.app.ts @@ -3,20 +3,15 @@ import { Test } from 'nodeunit'; import { Construct, Resource, Stack, StackProps } from '../lib'; import { App } from '../lib/app'; -function withApp(context: { [key: string]: any } | undefined, block: (app: App) => void) { - if (context) { - process.env[cxapi.CONTEXT_ENV] = JSON.stringify(context); - } else { - delete process.env[cxapi.CONTEXT_ENV]; - } - - const app = new App(); +function withApp(context: { [key: string]: any } | undefined, block: (app: App) => void): cxapi.SynthesizeResponse { + const app = new App(context); block(app); const session = app.run(); - return session.manifest; + // return the legacy manifest + return session.store.readJson(cxapi.OUTFILE_NAME); } 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 0d4016d361613..cd3875d7c8eae 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -8,7 +8,88 @@ import { FileSystemStore, InMemoryStore, SynthesisSession } from '../lib'; const storeTestMatrix: any = {}; +function createModernApp() { + return new cdk.App({ + [cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT]: 'true', + [cxapi.DISABLE_RUNTIME_INFO_CONTEXT]: 'true', // for test reproducibility + }); +} + export = { + 'synthesis with an empty app'(test: Test) { + // GIVEN + const app = createModernApp(); + + // WHEN + const session = app.run(); + + // 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.done(); + }, + + 'single empty stack'(test: Test) { + // GIVEN + const app = createModernApp(); + new cdk.Stack(app, 'one-stack'); + + // WHEN + const session = app.run(); + + // THEN + test.deepEqual(session.store.list(), [ + 'manifest.json', + 'one-stack.template.json' + ]); + test.done(); + }, + + 'some random construct implements "synthesize"'(test: Test) { + // GIVEN + const app = createModernApp(); + const stack = new cdk.Stack(app, 'one-stack'); + + class MyConstruct extends cdk.Construct implements cdk.ISynthesizable { + public synthesize(s: cdk.ISynthesisSession) { + s.store.writeJson('foo.json', { bar: 123 }); + s.addArtifact('my-random-construct', { + type: cxapi.ArtifactType.CloudFormationStack, + environment: 'aws://12345/bar', + }); + } + } + + new MyConstruct(stack, 'MyConstruct'); + + // WHEN + const session = app.run(); + + // THEN + test.deepEqual(session.store.list(), [ + 'foo.json', + 'manifest.json', + 'one-stack.template.json' + ]); + test.deepEqual(session.store.readJson('foo.json'), { bar: 123 }); + test.deepEqual(session.manifest, { + version: '0.19.0', + artifacts: { + 'my-random-construct': { + type: 'aws:cloudformation:stack', + environment: 'aws://12345/bar' + }, + 'one-stack': { + type: 'aws:cloudformation:stack', + environment: 'aws://unknown-account/unknown-region', + properties: { template: 'one-stack.template.json' } + } + }, + }); + test.done(); + }, + 'backwards compatibility: cdk.out contains all synthesized stacks'(test: Test) { // GIVEN const app = new cdk.App(); @@ -20,11 +101,11 @@ export = { // WHEN const session = app.run(); - const manifest = session.manifest; + const legacy: cxapi.SynthesizeResponse = session.store.readJson(cxapi.OUTFILE_NAME); // THEN - const t1 = manifest.stacks.find(s => s.name === 'stack1')!.template; - const t2 = manifest.stacks.find(s => s.name === 'stack2')!.template; + const t1 = legacy.stacks.find(s => s.name === 'stack1')!.template; + const t2 = legacy.stacks.find(s => s.name === 'stack2')!.template; test.deepEqual(t1, { Resources: { @@ -103,7 +184,7 @@ const storeTests = { 'SynthesisSession'(test: Test, store: cdk.ISessionStore) { // GIVEN - const session = new SynthesisSession(store); + const session = new SynthesisSession({ store }); const templateFile = 'foo.template.json'; // WHEN @@ -156,7 +237,6 @@ const storeTests = { // verify the manifest looks right test.deepEqual(manifest, { version: cxapi.PROTO_RESPONSE_VERSION, - stacks: [], // here for legacy reasons artifacts: { 'my-first-artifact': { type: 'aws:cloudformation:stack', @@ -186,7 +266,7 @@ const storeTests = { }); test.done(); - } + }, }; for (const [name, fn] of Object.entries(storeTests)) { diff --git a/packages/@aws-cdk/cx-api/lib/cxapi.ts b/packages/@aws-cdk/cx-api/lib/cxapi.ts index c6cd373ee1235..1845421876984 100644 --- a/packages/@aws-cdk/cx-api/lib/cxapi.ts +++ b/packages/@aws-cdk/cx-api/lib/cxapi.ts @@ -23,11 +23,6 @@ import { Environment } from './environment'; */ export const PROTO_RESPONSE_VERSION = '0.19.0'; -/** - * @deprecated Use `MANIFEST_FILE` - */ -export const OUTFILE_NAME = 'cdk.out'; - /** * The name of the root manifest file of the assembly. */ @@ -63,17 +58,14 @@ export interface AssemblyManifest { * Runtime information. */ runtime?: AppRuntime; - - /** - * @deprecated stacks should be read from `Artifacts`. - */ - stacks: SynthesizedStack[]; } /** * @deprecated use `AssemblyManifest` */ -export type SynthesizeResponse = AssemblyManifest; +export interface SynthesizeResponse extends AssemblyManifest { + stacks: SynthesizedStack[]; +} /** * A complete synthesized stack @@ -161,3 +153,22 @@ export const PATH_METADATA_KEY = 'aws:cdk:path'; * Enables the embedding of the "aws:cdk:path" in CloudFormation template metadata. */ 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. + * By default, synthesis output includes inforamtion about module versions. + */ +export const DISABLE_RUNTIME_INFO_CONTEXT = "aws:cdk:disable-runtime-information"; From 38f402ceb2619eaa1b56b5c36fb9f8e362675f17 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Thu, 28 Feb 2019 12:43:18 +0200 Subject: [PATCH 18/24] comment changes --- packages/@aws-cdk/cdk/lib/app.ts | 2 +- packages/@aws-cdk/cdk/lib/runtime-info.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index f24b774781b92..e381990ab1a8f 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -105,7 +105,7 @@ export class App extends Root { } private loadContext(defaults: { [key: string]: string } = { }) { - // primve with defaults passed through constructor + // prime with defaults passed through constructor for (const [ k, v ] of Object.entries(defaults)) { this.node.setContext(k, v); } diff --git a/packages/@aws-cdk/cdk/lib/runtime-info.ts b/packages/@aws-cdk/cdk/lib/runtime-info.ts index 863788302abd7..3bd6790634656 100644 --- a/packages/@aws-cdk/cdk/lib/runtime-info.ts +++ b/packages/@aws-cdk/cdk/lib/runtime-info.ts @@ -1,5 +1,8 @@ import cxapi = require('@aws-cdk/cx-api'); +/** + * Returns a list of loaded modules and their versions. + */ export function collectRuntimeInformation(): cxapi.AppRuntime { const libraries: { [name: string]: string } = {}; From b526facfda9a395c4826b754a6f1c71362fac732 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Thu, 28 Feb 2019 12:49:16 +0200 Subject: [PATCH 19/24] update package-lock.json --- packages/@aws-cdk/cdk/package-lock.json | 57 +++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 packages/@aws-cdk/cdk/package-lock.json diff --git a/packages/@aws-cdk/cdk/package-lock.json b/packages/@aws-cdk/cdk/package-lock.json new file mode 100644 index 0000000000000..c7090ffd53e6a --- /dev/null +++ b/packages/@aws-cdk/cdk/package-lock.json @@ -0,0 +1,57 @@ +{ + "name": "@aws-cdk/cdk", + "version": "0.25.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/js-base64": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-2.3.1.tgz", + "integrity": "sha512-4RKbhIDGC87s4EBy2Cp2/5S2O6kmCRcZnD5KRCq1q9z2GhBte1+BdsfVKCpG8yKpDGNyEE2G6IqFIh6W2YwWPA==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.121", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.121.tgz", + "integrity": "sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ==", + "dev": true + }, + "fast-check": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-1.11.0.tgz", + "integrity": "sha512-ZXaJLSga+LqmV4Lqs/ye5+hce1uyahKf772SqUVrcMq84MjWIbGuy9GRQnl6u/vlDak/d2SF6g4WGyi0zXxo1w==", + "dev": true, + "requires": { + "lorem-ipsum": "~1.0.6", + "pure-rand": "^1.6.2" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lorem-ipsum": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-1.0.6.tgz", + "integrity": "sha512-Rx4XH8X4KSDCKAVvWGYlhAfNqdUP5ZdT4rRyf0jjrvWgtViZimDIlopWNfn/y3lGM5K4uuiAoY28TaD+7YKFrQ==", + "dev": true, + "requires": { + "minimist": "~1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "pure-rand": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-1.6.2.tgz", + "integrity": "sha512-HNwHOH63m7kCxe0kWEe5jSLwJiL2N83RUUN8POniFuZS+OsbFcMWlvXgxIU2nwKy2zYG2bQan40WBNK4biYPRg==", + "dev": true + } + } +} From 2b3c595c58c06888923b903b4dbee5b366de2277 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Thu, 28 Feb 2019 13:00:40 +0200 Subject: [PATCH 20/24] fix how "disable version reporting" is evaluated --- packages/@aws-cdk/cdk/lib/app.ts | 4 ++-- packages/@aws-cdk/cdk/test/test.synthesis.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/app.ts b/packages/@aws-cdk/cdk/lib/app.ts index 96b855f1b662d..fb9a73b53bc62 100644 --- a/packages/@aws-cdk/cdk/lib/app.ts +++ b/packages/@aws-cdk/cdk/lib/app.ts @@ -19,8 +19,8 @@ export class App extends Root { this.loadContext(context); // both are reverse logic - this.legacyManifest = this.node.getContext(cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT) === 'true' ? false : true; - this.runtimeInformation = this.node.getContext(cxapi.DISABLE_VERSION_REPORTING) === 'true' ? false : true; + this.legacyManifest = this.node.getContext(cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT) ? false : true; + this.runtimeInformation = this.node.getContext(cxapi.DISABLE_VERSION_REPORTING) ? false : true; } /** diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index cd3875d7c8eae..83fedcc980cf7 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -11,7 +11,7 @@ const storeTestMatrix: any = {}; function createModernApp() { return new cdk.App({ [cxapi.DISABLE_LEGACY_MANIFEST_CONTEXT]: 'true', - [cxapi.DISABLE_RUNTIME_INFO_CONTEXT]: 'true', // for test reproducibility + [cxapi.DISABLE_VERSION_REPORTING]: 'true', // for test reproducibility }); } From 0e12e2a4a14f4092f03278d60bcd2f7f7bf73133 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Thu, 28 Feb 2019 14:01:51 +0200 Subject: [PATCH 21/24] interm --- packages/@aws-cdk/assets/lib/asset.ts | 10 ++++++- packages/@aws-cdk/cx-api/lib/artifacts.ts | 32 ++++++++++++++++------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/assets/lib/asset.ts b/packages/@aws-cdk/assets/lib/asset.ts index d70818cefcae4..12f5df152494f 100644 --- a/packages/@aws-cdk/assets/lib/asset.ts +++ b/packages/@aws-cdk/assets/lib/asset.ts @@ -43,7 +43,7 @@ export interface GenericAssetProps { * An asset represents a local file or directory, which is automatically uploaded to S3 * and then can be referenced within a CDK application. */ -export class Asset extends cdk.Construct { +export class Asset extends cdk.Construct implements cdk.ISynthesizable { /** * Attribute that represents the name of the bucket this asset exists in. */ @@ -178,6 +178,14 @@ export class Asset extends cdk.Construct { // when deploying a new version. this.bucket.grantRead(principal, `${this.s3Prefix}*`); } + + protected synthesize(session: cdk.ISynthesisSession): void { + session.addArtifact(this.node.uniqueId, { + type: cxapi.ArtifactType.S3Object, + } + + }); + } } export interface FileAssetProps { diff --git a/packages/@aws-cdk/cx-api/lib/artifacts.ts b/packages/@aws-cdk/cx-api/lib/artifacts.ts index 4d222d5a3f8a2..d66457eaefa4a 100644 --- a/packages/@aws-cdk/cx-api/lib/artifacts.ts +++ b/packages/@aws-cdk/cx-api/lib/artifacts.ts @@ -1,25 +1,39 @@ export const AWS_ENV_REGEX = /aws\:\/\/([0-9]+|unknown-account)\/([a-z\-0-9]+)/; export enum ArtifactType { - CloudFormationStack = 'aws:cloudformation:stack', - DockerImage = 'aws:docker', - File = 'aws:file' + AwsCloudFormationStack = 'aws:cloudformation:stack', + AwsEcrDockerImage = 'aws:ecr:image', + AwsS3Object = 'aws:s3:object' } -export interface Artifact { +export interface ArtifactMetadata { type: ArtifactType; environment: string; // format: aws://account/region - properties?: { [name: string]: any }; metadata?: { [path: string]: any }; dependencies?: string[]; missing?: { [key: string]: any }; + properties?: { [name: string]: any }; +} + +export interface AwsCloudformationStackArtifact extends ArtifactMetadata { + type: ArtifactType.AwsCloudFormationStack, + properties: { + templateFile: string; + parameters: { + [name: string]: string + } + } +} - /** - * Build instructions for this artifact (for example, lambda-builders, zip directory, docker build, etc) - */ - build?: any; +export interface AwsS3ObjectArtifact extends ArtifactMetadata { + type: ArtifactType.AwsS3Object, + properties: { + file: string; + } } +export type Artifact = AwsCloudformationStackArtifact | AwsS3ObjectArtifact; + 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}`); From 5f27239b52b1807e55af195a74960b1cf8a9a0cd Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Thu, 28 Feb 2019 18:03:17 +0200 Subject: [PATCH 22/24] stack.setParameterValue can be used to assign values to CFN parameters during deployment --- .../@aws-cdk/cdk/lib/cloudformation/stack.ts | 39 ++++++++++++-- packages/@aws-cdk/cdk/lib/synthesis.ts | 4 +- packages/@aws-cdk/cdk/test/test.synthesis.ts | 52 +++++++++++++++---- packages/@aws-cdk/cx-api/lib/artifacts.ts | 21 +------- 4 files changed, 78 insertions(+), 38 deletions(-) diff --git a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts index fb0b779989e33..99f97ae63f069 100644 --- a/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts +++ b/packages/@aws-cdk/cdk/lib/cloudformation/stack.ts @@ -5,6 +5,7 @@ import { Environment } from '../environment'; import { ISynthesisSession } from '../synthesis'; import { CfnReference } from './cfn-tokens'; import { HashedAddressingScheme, IAddressingScheme, LogicalIDs } from './logical-id'; +import { Parameter } from './parameter'; export interface StackProps { /** @@ -88,6 +89,11 @@ export class Stack extends Construct { */ private readonly stackDependencies = new Set(); + /** + * Values set for parameters in cloud assembly. + */ + private readonly parameterValues: { [logicalId: string]: string } = { }; + /** * Creates a new stack. * @@ -109,6 +115,15 @@ export class Stack extends Construct { this.name = this.node.id; } + /** + * Returns the environment specification for this stack (aws://account/region). + */ + public get environment() { + const account = this.env.account || 'unknown-account'; + const region = this.env.region || 'unknown-region'; + return `aws://${account}/${region}`; + } + /** * Looks up a resource by path. * @@ -376,6 +391,15 @@ export class Stack extends Construct { return parseArn(arn, sepIfToken, hasName); } + /** + * Sets the value of a CloudFormation parameter. + * @param parameter The parameter to set the value for + * @param value The value, can use `${}` notation to reference other assembly block attributes. + */ + public setParameterValue(parameter: Parameter, value: string) { + this.parameterValues[parameter.logicalId] = value; + } + /** * Validate stack name * @@ -419,19 +443,24 @@ export class Stack extends Construct { } protected synthesize(session: ISynthesisSession): void { - const account = this.env.account || 'unknown-account'; - const region = this.env.region || 'unknown-region'; const template = `${this.node.id}.template.json`; // write the CloudFormation template as a JSON file session.store.writeJson(template, this.toCloudFormation()); const artifact: cxapi.Artifact = { - type: cxapi.ArtifactType.CloudFormationStack, - environment: `aws://${account}/${region}`, - properties: { template } + type: cxapi.ArtifactType.AwsCloudFormationStack, + environment: this.environment, + properties: { + templateFile: template, + } }; + if (Object.keys(this.parameterValues).length > 0) { + artifact.properties = artifact.properties || { }; + artifact.properties.parameters = this.node.resolve(this.parameterValues); + } + const deps = this.dependencies().map(s => s.node.id); if (deps.length > 0) { artifact.dependencies = deps; diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index 82a3047ffafff..efe423bd4f8e8 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -319,8 +319,8 @@ function renderLegacyStacks(artifacts: { [id: string]: cxapi.Artifact }, store: const stacks = new Array(); for (const [ id, artifact ] of Object.entries(artifacts)) { - if (artifact.type === cxapi.ArtifactType.CloudFormationStack) { - const templateFile = (artifact.properties || {}).template; + if (artifact.type === cxapi.ArtifactType.AwsCloudFormationStack) { + const templateFile = artifact.properties && artifact.properties.templateFile; if (!templateFile) { throw new Error(`Invalid cloudformation artifact. Missing "template" property`); } diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index 83fedcc980cf7..a9832f70d46cd 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -55,8 +55,11 @@ export = { public synthesize(s: cdk.ISynthesisSession) { s.store.writeJson('foo.json', { bar: 123 }); s.addArtifact('my-random-construct', { - type: cxapi.ArtifactType.CloudFormationStack, + type: cxapi.ArtifactType.AwsCloudFormationStack, environment: 'aws://12345/bar', + properties: { + templateFile: 'file://boom' + } }); } } @@ -78,12 +81,13 @@ export = { artifacts: { 'my-random-construct': { type: 'aws:cloudformation:stack', - environment: 'aws://12345/bar' + environment: 'aws://12345/bar', + properties: { templateFile: 'file://boom' } }, 'one-stack': { type: 'aws:cloudformation:stack', environment: 'aws://unknown-account/unknown-region', - properties: { template: 'one-stack.template.json' } + properties: { templateFile: 'one-stack.template.json' } } }, }); @@ -189,16 +193,18 @@ const storeTests = { // WHEN session.addArtifact('my-first-artifact', { - type: cxapi.ArtifactType.CloudFormationStack, + type: cxapi.ArtifactType.AwsCloudFormationStack, environment: 'aws://1222344/us-east-1', dependencies: ['a', 'b'], metadata: { foo: { bar: 123 } }, properties: { - template: templateFile, - prop1: 1234, - prop2: 555 + templateFile, + parameters: { + prop1: '1234', + prop2: '555' + } }, missing: { foo: { @@ -212,10 +218,10 @@ const storeTests = { }); session.addArtifact('minimal-artifact', { - type: cxapi.ArtifactType.CloudFormationStack, + type: cxapi.ArtifactType.AwsCloudFormationStack, environment: 'aws://111/helo-world', properties: { - template: templateFile + templateFile } }); @@ -243,7 +249,13 @@ const storeTests = { environment: 'aws://1222344/us-east-1', dependencies: ['a', 'b'], metadata: { foo: { bar: 123 } }, - properties: { template: 'foo.template.json', prop1: 1234, prop2: 555 }, + properties: { + templateFile: 'foo.template.json', + parameters: { + prop1: '1234', + prop2: '555' + }, + }, missing: { foo: { provider: 'context-provider', props: { a: 'A', b: 2 } } } @@ -251,7 +263,7 @@ const storeTests = { 'minimal-artifact': { type: 'aws:cloudformation:stack', environment: 'aws://111/helo-world', - properties: { template: 'foo.template.json' } + properties: { templateFile: 'foo.template.json' } } } }); @@ -267,6 +279,24 @@ const storeTests = { test.done(); }, + + 'stack.setParameterValue can be used to assign parameters'(test: Test) { + // GIVEN + const app = createModernApp(); + const stack = new cdk.Stack(app, 'my-stack'); + const param = new cdk.Parameter(stack, 'MyParam', { type: 'string' }); + + // WHEN + stack.setParameterValue(param, 'Foo'); + + // THEN + const session = app.run(); + const props = (session.manifest.artifacts && session.manifest.artifacts['my-stack'].properties) || {}; + test.deepEqual(props.parameters, { + MyParam: 'Foo' + }); + test.done(); + }, }; for (const [name, fn] of Object.entries(storeTests)) { diff --git a/packages/@aws-cdk/cx-api/lib/artifacts.ts b/packages/@aws-cdk/cx-api/lib/artifacts.ts index d66457eaefa4a..133027dfe04b1 100644 --- a/packages/@aws-cdk/cx-api/lib/artifacts.ts +++ b/packages/@aws-cdk/cx-api/lib/artifacts.ts @@ -6,7 +6,7 @@ export enum ArtifactType { AwsS3Object = 'aws:s3:object' } -export interface ArtifactMetadata { +export interface Artifact { type: ArtifactType; environment: string; // format: aws://account/region metadata?: { [path: string]: any }; @@ -15,25 +15,6 @@ export interface ArtifactMetadata { properties?: { [name: string]: any }; } -export interface AwsCloudformationStackArtifact extends ArtifactMetadata { - type: ArtifactType.AwsCloudFormationStack, - properties: { - templateFile: string; - parameters: { - [name: string]: string - } - } -} - -export interface AwsS3ObjectArtifact extends ArtifactMetadata { - type: ArtifactType.AwsS3Object, - properties: { - file: string; - } -} - -export type Artifact = AwsCloudformationStackArtifact | AwsS3ObjectArtifact; - 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}`); From b3bdd3b6bd38a3a5c74c516c2e4035a4fa500dc5 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Thu, 28 Feb 2019 18:03:47 +0200 Subject: [PATCH 23/24] build.json and addBuildStep --- packages/@aws-cdk/cdk/lib/synthesis.ts | 18 ++++++++++++ packages/@aws-cdk/cdk/test/test.synthesis.ts | 29 ++++++++++++++++++++ packages/@aws-cdk/cx-api/lib/build.ts | 16 +++++++++++ packages/@aws-cdk/cx-api/lib/cxapi.ts | 7 ++++- packages/@aws-cdk/cx-api/lib/index.ts | 1 + 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 packages/@aws-cdk/cx-api/lib/build.ts diff --git a/packages/@aws-cdk/cdk/lib/synthesis.ts b/packages/@aws-cdk/cdk/lib/synthesis.ts index efe423bd4f8e8..9b5d95d3ae1ae 100644 --- a/packages/@aws-cdk/cdk/lib/synthesis.ts +++ b/packages/@aws-cdk/cdk/lib/synthesis.ts @@ -12,6 +12,7 @@ export interface ISynthesisSession { readonly store: ISessionStore; readonly manifest: cxapi.AssemblyManifest; addArtifact(id: string, droplet: cxapi.Artifact): void; + addBuildStep(id: string, step: cxapi.BuildStep): void; tryGetArtifact(id: string): cxapi.Artifact | undefined; } @@ -45,6 +46,7 @@ export class SynthesisSession implements ISynthesisSession { public readonly store: ISessionStore; private readonly artifacts: { [id: string]: cxapi.Artifact } = { }; + private readonly buildSteps: { [id: string]: cxapi.BuildStep } = { }; private _manifest?: cxapi.AssemblyManifest; private readonly legacyManifest: boolean; private readonly runtimeInfo: boolean; @@ -72,6 +74,13 @@ export class SynthesisSession implements ISynthesisSession { return this.artifacts[id]; } + public addBuildStep(id: string, step: cxapi.BuildStep) { + if (id in this.buildSteps) { + throw new Error(`Build step ${id} already exists`); + } + this.buildSteps[id] = step; + } + public close(): cxapi.AssemblyManifest { const manifest: cxapi.AssemblyManifest = this._manifest = { version: cxapi.PROTO_RESPONSE_VERSION, @@ -84,6 +93,15 @@ export class SynthesisSession implements ISynthesisSession { this.store.writeFile(cxapi.MANIFEST_FILE, 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 + }; + + this.store.writeFile(cxapi.BUILD_FILE, JSON.stringify(buildManifest, undefined, 2)); + } + if (this.legacyManifest) { const legacy: cxapi.SynthesizeResponse = { ...manifest, diff --git a/packages/@aws-cdk/cdk/test/test.synthesis.ts b/packages/@aws-cdk/cdk/test/test.synthesis.ts index a9832f70d46cd..108e668da5668 100644 --- a/packages/@aws-cdk/cdk/test/test.synthesis.ts +++ b/packages/@aws-cdk/cdk/test/test.synthesis.ts @@ -297,6 +297,35 @@ 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(session.store.list(), [ 'build.json', 'manifest.json' ]); + test.deepEqual(session.store.readJson('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/lib/build.ts b/packages/@aws-cdk/cx-api/lib/build.ts new file mode 100644 index 0000000000000..c4363f67d5f50 --- /dev/null +++ b/packages/@aws-cdk/cx-api/lib/build.ts @@ -0,0 +1,16 @@ +export interface BuildStep { + type: string; + depends?: string[]; + parameters: { + [key: string]: any + }; +} + +export interface BuildManifest { + 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 deb5a7f7b61d8..8bbbdcf9340bb 100644 --- a/packages/@aws-cdk/cx-api/lib/cxapi.ts +++ b/packages/@aws-cdk/cx-api/lib/cxapi.ts @@ -26,7 +26,12 @@ export const PROTO_RESPONSE_VERSION = '0.19.0'; /** * The name of the root manifest file of the assembly. */ -export const MANIFEST_FILE = "manifest.json"; +export const MANIFEST_FILE = 'manifest.json'; + +/** + * The name of the root file with build instructions. + */ +export const BUILD_FILE = 'build.json'; export const OUTDIR_ENV = 'CDK_OUTDIR'; export const CONTEXT_ENV = 'CDK_CONTEXT_JSON'; diff --git a/packages/@aws-cdk/cx-api/lib/index.ts b/packages/@aws-cdk/cx-api/lib/index.ts index b2bf7536b9c3a..b3ebfaa8cf77a 100644 --- a/packages/@aws-cdk/cx-api/lib/index.ts +++ b/packages/@aws-cdk/cx-api/lib/index.ts @@ -6,3 +6,4 @@ export * from './context/ssm-parameter'; export * from './context/availability-zones'; export * from './metadata/assets'; export * from './artifacts'; +export * from './build'; From f923ad5a5eb8887533089b8507c11bb32ec3dce4 Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Thu, 28 Feb 2019 18:18:02 +0200 Subject: [PATCH 24/24] revert asset.ts change --- packages/@aws-cdk/assets/lib/asset.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/@aws-cdk/assets/lib/asset.ts b/packages/@aws-cdk/assets/lib/asset.ts index 12f5df152494f..d70818cefcae4 100644 --- a/packages/@aws-cdk/assets/lib/asset.ts +++ b/packages/@aws-cdk/assets/lib/asset.ts @@ -43,7 +43,7 @@ export interface GenericAssetProps { * An asset represents a local file or directory, which is automatically uploaded to S3 * and then can be referenced within a CDK application. */ -export class Asset extends cdk.Construct implements cdk.ISynthesizable { +export class Asset extends cdk.Construct { /** * Attribute that represents the name of the bucket this asset exists in. */ @@ -178,14 +178,6 @@ export class Asset extends cdk.Construct implements cdk.ISynthesizable { // when deploying a new version. this.bucket.grantRead(principal, `${this.s3Prefix}*`); } - - protected synthesize(session: cdk.ISynthesisSession): void { - session.addArtifact(this.node.uniqueId, { - type: cxapi.ArtifactType.S3Object, - } - - }); - } } export interface FileAssetProps {