From e4713fb8043d71d211d93fb9866c305b169562aa Mon Sep 17 00:00:00 2001 From: Sam Goodwin Date: Tue, 16 Apr 2019 14:59:35 -0700 Subject: [PATCH 01/12] Setup @aws-cdk/cdk-common with utilities common between cdk-* CLI commands --- packages/@aws-cdk/cdk-common/.gitignore | 15 + packages/@aws-cdk/cdk-common/.npmignore | 12 + packages/@aws-cdk/cdk-common/LICENSE | 201 ++ packages/@aws-cdk/cdk-common/NOTICE | 2 + packages/@aws-cdk/cdk-common/README.md | 1 + .../@aws-cdk/cdk-common/lib/account-cache.ts | 92 + .../@aws-cdk/cdk-common/lib/credentials.ts | 29 + packages/@aws-cdk/cdk-common/lib/index.ts | 5 + packages/@aws-cdk/cdk-common/lib/logging.ts | 54 + packages/@aws-cdk/cdk-common/lib/plugin.ts | 86 + packages/@aws-cdk/cdk-common/lib/sdk.ts | 437 ++++ .../@aws-cdk/cdk-common/lib/sdk_ini_file.ts | 59 + packages/@aws-cdk/cdk-common/lib/serialize.ts | 38 + .../@aws-cdk/cdk-common/lib/util/arrays.ts | 31 + .../@aws-cdk/cdk-common/lib/util/index.ts | 4 + .../@aws-cdk/cdk-common/lib/util/objects.ts | 136 ++ .../cdk-common/lib/util/please-hold.ts | 26 + .../lib/util/string-manipulation.ts | 7 + .../@aws-cdk/cdk-common/lib/util/tables.ts | 7 + .../@aws-cdk/cdk-common/lib/util/toposort.ts | 44 + .../@aws-cdk/cdk-common/lib/util/types.ts | 32 + .../@aws-cdk/cdk-common/package-lock.json | 2140 +++++++++++++++++ packages/@aws-cdk/cdk-common/package.json | 79 + packages/@aws-cdk/cdk-common/tsconfig.json | 26 + 24 files changed, 3563 insertions(+) create mode 100644 packages/@aws-cdk/cdk-common/.gitignore create mode 100644 packages/@aws-cdk/cdk-common/.npmignore create mode 100644 packages/@aws-cdk/cdk-common/LICENSE create mode 100644 packages/@aws-cdk/cdk-common/NOTICE create mode 100644 packages/@aws-cdk/cdk-common/README.md create mode 100644 packages/@aws-cdk/cdk-common/lib/account-cache.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/credentials.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/index.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/logging.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/plugin.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/sdk.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/sdk_ini_file.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/serialize.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/util/arrays.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/util/index.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/util/objects.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/util/please-hold.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/util/string-manipulation.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/util/tables.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/util/toposort.ts create mode 100644 packages/@aws-cdk/cdk-common/lib/util/types.ts create mode 100644 packages/@aws-cdk/cdk-common/package-lock.json create mode 100644 packages/@aws-cdk/cdk-common/package.json create mode 100644 packages/@aws-cdk/cdk-common/tsconfig.json diff --git a/packages/@aws-cdk/cdk-common/.gitignore b/packages/@aws-cdk/cdk-common/.gitignore new file mode 100644 index 0000000000000..cd4b6d8758860 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/.gitignore @@ -0,0 +1,15 @@ +*.js +*.js.map +*.d.ts +node_modules +dist + +# Generated by generate.sh +lib/version.ts + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-common/.npmignore b/packages/@aws-cdk/cdk-common/.npmignore new file mode 100644 index 0000000000000..947b2350f7580 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/.npmignore @@ -0,0 +1,12 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.template.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +*.snk \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-common/LICENSE b/packages/@aws-cdk/cdk-common/LICENSE new file mode 100644 index 0000000000000..46c185646b439 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/cdk-common/NOTICE b/packages/@aws-cdk/cdk-common/NOTICE new file mode 100644 index 0000000000000..8585168af8b7d --- /dev/null +++ b/packages/@aws-cdk/cdk-common/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/cdk-common/README.md b/packages/@aws-cdk/cdk-common/README.md new file mode 100644 index 0000000000000..f87f5c14cbbd7 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/README.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-common/lib/account-cache.ts b/packages/@aws-cdk/cdk-common/lib/account-cache.ts new file mode 100644 index 0000000000000..6c013fed8d415 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/account-cache.ts @@ -0,0 +1,92 @@ +import fs = require('fs-extra'); +import os = require('os'); +import path = require('path'); +import { debug } from './logging'; + +/** + * Disk cache which maps access key IDs to account IDs. + * Usage: + * cache.get(accessKey) => accountId | undefined + * cache.put(accessKey, accountId) + */ +export class AccountAccessKeyCache { + /** + * Max number of entries in the cache, after which the cache will be reset. + */ + public static readonly MAX_ENTRIES = 1000; + + private readonly cacheFile: string; + + /** + * @param filePath Path to the cache file + */ + constructor(filePath?: string) { + this.cacheFile = filePath || path.join(os.homedir(), '.cdk', 'cache', 'accounts.json'); + } + + /** + * Tries to fetch the account ID from cache. If it's not in the cache, invokes + * the resolver function which should retrieve the account ID and return it. + * Then, it will be stored into disk cache returned. + * + * Example: + * + * const accountId = cache.fetch(accessKey, async () => { + * return await fetchAccountIdFromSomewhere(accessKey); + * }); + * + * @param accessKeyId + * @param resolver + */ + public async fetch(accessKeyId: string, resolver: () => Promise) { + // try to get account ID based on this access key ID from disk. + const cached = await this.get(accessKeyId); + if (cached) { + debug(`Retrieved account ID ${cached} from disk cache`); + return cached; + } + + // if it's not in the cache, resolve and put in cache. + const accountId = await resolver(); + if (accountId) { + await this.put(accessKeyId, accountId); + } + + return accountId; + } + + /** Get the account ID from an access key or undefined if not in cache */ + public async get(accessKeyId: string): Promise { + const map = await this.loadMap(); + return map[accessKeyId]; + } + + /** Put a mapping betweenn access key and account ID */ + public async put(accessKeyId: string, accountId: string) { + let map = await this.loadMap(); + + // nuke cache if it's too big. + if (Object.keys(map).length >= AccountAccessKeyCache.MAX_ENTRIES) { + map = { }; + } + + map[accessKeyId] = accountId; + await this.saveMap(map); + } + + private async loadMap(): Promise<{ [accessKeyId: string]: string }> { + if (!(await fs.pathExists(this.cacheFile))) { + return { }; + } + + return await fs.readJson(this.cacheFile); + } + + private async saveMap(map: { [accessKeyId: string]: string }) { + if (!(await fs.pathExists(this.cacheFile))) { + await fs.mkdirs(path.dirname(this.cacheFile)); + } + + await fs.writeJson(this.cacheFile, map, { spaces: 2 }); + } +} diff --git a/packages/@aws-cdk/cdk-common/lib/credentials.ts b/packages/@aws-cdk/cdk-common/lib/credentials.ts new file mode 100644 index 0000000000000..e151f231a4a18 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/credentials.ts @@ -0,0 +1,29 @@ +import aws = require('aws-sdk'); + +export enum Mode { + ForReading, + ForWriting +} + +export interface CredentialProviderSource { + name: string; + + /** + * Whether the credential provider is even online + * + * Guaranteed to be called before any of the other functions are called. + */ + isAvailable(): Promise; + + /** + * Whether the credential provider can provide credentials for the given account. + */ + canProvideCredentials(accountId: string): Promise; + + /** + * Construct a credential provider for the given account and the given access mode + * + * Guaranteed to be called only if canProvideCredentails() returned true at some point. + */ + getProvider(accountId: string, mode: Mode): Promise; +} diff --git a/packages/@aws-cdk/cdk-common/lib/index.ts b/packages/@aws-cdk/cdk-common/lib/index.ts new file mode 100644 index 0000000000000..493de9d2f20ee --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/index.ts @@ -0,0 +1,5 @@ +export * from './credentials'; +export * from './logging'; +export * from './sdk'; +export * from './serialize'; +export * from './util'; diff --git a/packages/@aws-cdk/cdk-common/lib/logging.ts b/packages/@aws-cdk/cdk-common/lib/logging.ts new file mode 100644 index 0000000000000..d9b6ef87a2900 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/logging.ts @@ -0,0 +1,54 @@ +import colors = require('colors/safe'); +import util = require('util'); + +// tslint:disable:no-console the whole point of those methods is precisely to output to the console... + +export let isVerbose = false; + +export function setVerbose(enabled = true) { + isVerbose = enabled; +} + +export function error(fmt: string, ...args: any[]) { + console.error(colors.red(util.format(fmt, ...args))); +} + +export function debug(fmt: string, ...args: any[]) { + if (isVerbose) { + console.error(colors.gray(util.format(fmt, ...args))); + } +} + +export function highlight(fmt: string, ...args: any[]) { + console.error(colors.bold(colors.white(util.format(fmt, ...args)))); +} + +export function success(fmt: string, ...args: any[]) { + console.error(colors.green(util.format(fmt, ...args))); +} + +export function warning(fmt: string, ...args: any[]) { + console.error(colors.yellow(util.format(fmt, ...args))); +} + +export function print(fmt: string, ...args: any[]) { + console.error(colors.white(util.format(fmt, ...args))); +} + +export function data(fmt: string, ...args: any[]) { + console.log(util.format(fmt, ...args)); +} + +export type LoggerFunction = (fmt: string, ...args: any[]) => void; + +/** + * Create a logger output that features a constant prefix string. + * + * @param prefixString the prefix string to be appended before any log entry. + * @param fn the logger function to be used (typically one of the other functions in this module) + * + * @returns a new LoggerFunction. + */ +export function prefix(prefixString: string, fn: LoggerFunction): LoggerFunction { + return (fmt: string, ...args: any[]) => fn(`%s ${fmt}`, prefixString, ...args); +} diff --git a/packages/@aws-cdk/cdk-common/lib/plugin.ts b/packages/@aws-cdk/cdk-common/lib/plugin.ts new file mode 100644 index 0000000000000..8ee33fe75c6e2 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/plugin.ts @@ -0,0 +1,86 @@ +import { green } from 'colors/safe'; + +import { CredentialProviderSource } from './credentials'; +import { error } from './logging'; + +/** + * The basic contract for plug-ins to adhere to:: + * + * import { Plugin, PluginHost } from 'aws-cdk'; + * import { CustomCredentialProviderSource } from './custom-credential-provider-source'; + * + * export default class FooCDKPlugIn implements PluginHost { + * public readonly version = '1'; + * + * public init(host: PluginHost) { + * host.registerCredentialProviderSource(new CustomCredentialProviderSource()); + * } + * } + */ +export interface Plugin { + /** + * The version of the plug-in interface used by the plug-in. This will be used by + * the plug-in host to handle version changes. + */ + version: '1'; + + /** + * When defined, this function is invoked right after the plug-in has been loaded, + * so that the plug-in is able to initialize itself. It may call methods of the + * ``PluginHost`` instance it receives to register new ``CredentialProviderSource`` + * instances. + */ + init?: (host: PluginHost) => void; +} + +/** + * A utility to manage plug-ins. + */ +export class PluginHost { + public static instance = new PluginHost(); + + /** + * Access the currently registered CredentialProviderSources. New sources can + * be registered using the +registerCredentialProviderSource+ method. + */ + public readonly credentialProviderSources = new Array(); + + constructor() { + if (PluginHost.instance && PluginHost.instance !== this) { + throw new Error('New instances of PluginHost must not be built. Use PluginHost.instance instead!'); + } + } + + /** + * Loads a plug-in into this PluginHost. + * + * @param moduleSpec the specification (path or name) of the plug-in module to be loaded. + */ + public load(moduleSpec: string) { + try { + // tslint:disable-next-line:no-var-requires + const plugin = require(moduleSpec); + if (!isPlugin(plugin)) { + error(`Module ${green(moduleSpec)} is not a valid plug-in, or has an unsupported version.`); + throw new Error(`Module ${moduleSpec} does not define a valid plug-in.`); + } + if (plugin.init) { plugin.init(PluginHost.instance); } + } catch (e) { + error(`Unable to load ${green(moduleSpec)}: ${e.stack}`); + throw new Error(`Unable to load plug-in: ${moduleSpec}`); + } + + function isPlugin(x: any): x is Plugin { + return x != null && x.version === '1'; + } + } + + /** + * Allows plug-ins to register new CredentialProviderSources. + * + * @param source a new CredentialProviderSource to register. + */ + public registerCredentialProviderSource(source: CredentialProviderSource) { + this.credentialProviderSources.push(source); + } +} diff --git a/packages/@aws-cdk/cdk-common/lib/sdk.ts b/packages/@aws-cdk/cdk-common/lib/sdk.ts new file mode 100644 index 0000000000000..d424cad3ea62f --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/sdk.ts @@ -0,0 +1,437 @@ +import { Environment} from '@aws-cdk/cx-api'; +import AWS = require('aws-sdk'); +import child_process = require('child_process'); +import fs = require('fs-extra'); +import os = require('os'); +import path = require('path'); +import util = require('util'); +import { AccountAccessKeyCache } from './account-cache'; +import { CredentialProviderSource, Mode } from './credentials'; +import { debug } from './logging'; +import { PluginHost } from './plugin'; +import { SharedIniFile } from './sdk_ini_file'; + +export interface SDKOptions { + /** + * Profile name to use + * + * @default No profile + */ + profile?: string; + + /** + * Proxy address to use + * + * @default No proxy + */ + proxyAddress?: string; + + /** + * Whether we should try instance credentials + * + * True/false to force/disable. Default is to guess. + * + * @default Automatically determine. + */ + ec2creds?: boolean; +} + +/** + * Source for SDK client objects + * + * Credentials are first obtained from the SDK defaults (using environment variables and the + * ~/.aws/{config,credentials} files). + * + * If those don't suffice, a list of CredentialProviderSources is interrogated for access + * to the requested account. + */ +export class SDK { + private readonly defaultAwsAccount: DefaultAWSAccount; + private readonly credentialsCache: CredentialsCache; + private readonly profile?: string; + + /** + * Default retry options for SDK clients + * + * Biggest bottleneck is CloudFormation, with a 1tps call rate. We want to be + * a little more tenacious than the defaults, and with a little more breathing + * room between calls (defaults are {retries=3, base=100}). + * + * I've left this running in a tight loop for an hour and the throttle errors + * haven't escaped the retry mechanism. + */ + private readonly retryOptions = { maxRetries: 6, retryDelayOptions: { base: 300 }}; + + constructor(options: SDKOptions = {}) { + this.profile = options.profile; + + const defaultCredentialProvider = makeCLICompatibleCredentialProvider(options.profile, options.ec2creds); + + // Find the package.json from the main toolkit + const pkg = (require.main as any).require('../package.json'); + AWS.config.update({ + customUserAgent: `${pkg.name}/${pkg.version}` + }); + + // https://aws.amazon.com/blogs/developer/using-the-aws-sdk-for-javascript-from-behind-a-proxy/ + if (options.proxyAddress === undefined) { + options.proxyAddress = httpsProxyFromEnvironment(); + } + if (options.proxyAddress) { // Ignore empty string on purpose + debug('Using proxy server: %s', options.proxyAddress); + AWS.config.update({ + httpOptions: { agent: require('proxy-agent')(options.proxyAddress) } + }); + } + + this.defaultAwsAccount = new DefaultAWSAccount(defaultCredentialProvider, getCLICompatibleDefaultRegion(this.profile)); + this.credentialsCache = new CredentialsCache(this.defaultAwsAccount, defaultCredentialProvider); + } + + public async cloudFormation(environment: Environment, mode: Mode): Promise { + return new AWS.CloudFormation({ + ...this.retryOptions, + region: environment.region, + credentials: await this.credentialsCache.get(environment.account, mode) + }); + } + + public async ec2(awsAccountId: string | undefined, region: string | undefined, mode: Mode): Promise { + return new AWS.EC2({ + ...this.retryOptions, + region, + credentials: await this.credentialsCache.get(awsAccountId, mode) + }); + } + + public async ssm(awsAccountId: string | undefined, region: string | undefined, mode: Mode): Promise { + return new AWS.SSM({ + ...this.retryOptions, + region, + credentials: await this.credentialsCache.get(awsAccountId, mode) + }); + } + + public async s3(environment: Environment, mode: Mode): Promise { + return new AWS.S3({ + ...this.retryOptions, + region: environment.region, + credentials: await this.credentialsCache.get(environment.account, mode) + }); + } + + public async route53(awsAccountId: string | undefined, region: string | undefined, mode: Mode): Promise { + return new AWS.Route53({ + ...this.retryOptions, + region, + credentials: await this.credentialsCache.get(awsAccountId, mode), + }); + } + + public async ecr(environment: Environment, mode: Mode): Promise { + return new AWS.ECR({ + ...this.retryOptions, + region: environment.region, + credentials: await this.credentialsCache.get(environment.account, mode) + }); + } + + public async defaultRegion(): Promise { + return await getCLICompatibleDefaultRegion(this.profile); + } + + public defaultAccount(): Promise { + return this.defaultAwsAccount.get(); + } +} + +/** + * Cache for credential providers. + * + * Given an account and an operating mode (read or write) will return an + * appropriate credential provider for credentials for the given account. The + * credential provider will be cached so that multiple AWS clients for the same + * environment will not make multiple network calls to obtain credentials. + * + * Will use default credentials if they are for the right account; otherwise, + * all loaded credential provider plugins will be tried to obtain credentials + * for the given account. + */ +class CredentialsCache { + private readonly cache: {[key: string]: AWS.Credentials} = {}; + + public constructor( + private readonly defaultAwsAccount: DefaultAWSAccount, + private readonly defaultCredentialProvider: Promise) { + } + + public async get(awsAccountId: string | undefined, mode: Mode): Promise { + const key = `${awsAccountId}-${mode}`; + if (!(key in this.cache)) { + this.cache[key] = await this.getCredentials(awsAccountId, mode); + } + return this.cache[key]; + } + + private async getCredentials(awsAccountId: string | undefined, mode: Mode): Promise { + // If requested account is undefined or equal to default account, use default credentials provider. + // (Note that we ignore the mode in this case, if you preloaded credentials they better be correct!) + const defaultAccount = await this.defaultAwsAccount.get(); + if (!awsAccountId || awsAccountId === defaultAccount) { + debug(`Using default AWS SDK credentials for account ${awsAccountId}`); + + // CredentialProviderChain extends Credentials, but that is a lie. + // https://github.com/aws/aws-sdk-js/issues/2235 + // Call resolve() instead. + return (await this.defaultCredentialProvider).resolvePromise(); + } + + const triedSources: CredentialProviderSource[] = []; + // Otherwise, inspect the various credential sources we have + for (const source of PluginHost.instance.credentialProviderSources) { + if (!(await source.isAvailable())) { + debug('Credentials source %s is not available, ignoring it.', source.name); + continue; + } + triedSources.push(source); + if (!(await source.canProvideCredentials(awsAccountId))) { continue; } + debug(`Using ${source.name} credentials for account ${awsAccountId}`); + const providerOrCreds = await source.getProvider(awsAccountId, mode); + + // Backwards compatibility: if the plugin returns a ProviderChain, resolve that chain. + // Otherwise it must have returned credentials. + if ((providerOrCreds as any).resolvePromise) { + return await (providerOrCreds as any).resolvePromise(); + } + return providerOrCreds; + } + const sourceNames = ['default credentials'].concat(triedSources.map(s => s.name)).join(', '); + throw new Error(`Need to perform AWS calls for account ${awsAccountId}, but no credentials found. Tried: ${sourceNames}.`); + } +} + +/** + * Class to retrieve the account for default credentials and cache it. + * + * Uses the default credentials provider to obtain credentials (if available), + * and uses those credentials to call STS to request the current account ID. + * + * The credentials => accountId lookup is cached on disk, since it's + * guaranteed that igven access key will always remain for the same account. + */ +class DefaultAWSAccount { + private defaultAccountFetched = false; + private defaultAccountId?: string = undefined; + private readonly accountCache = new AccountAccessKeyCache(); + + constructor( + private readonly defaultCredentialsProvider: Promise, + private readonly region: Promise) { + } + + /** + * Return the default account + */ + public async get(): Promise { + if (!this.defaultAccountFetched) { + this.defaultAccountId = await this.lookupDefaultAccount(); + this.defaultAccountFetched = true; + } + return this.defaultAccountId; + } + + private async lookupDefaultAccount(): Promise { + try { + // There just is *NO* way to do AssumeRole credentials as long as AWS_SDK_LOAD_CONFIG is not set. The SDK + // crash if the file does not exist though. So set the environment variable if we can find that file. + await setConfigVariable(); + + debug('Resolving default credentials'); + const credentialProvider = await this.defaultCredentialsProvider; + const creds = await credentialProvider.resolvePromise(); + + const accessKeyId = creds.accessKeyId; + if (!accessKeyId) { + throw new Error('Unable to resolve AWS credentials (setup with "aws configure")'); + } + + const accountId = await this.accountCache.fetch(creds.accessKeyId, async () => { + // if we don't have one, resolve from STS and store in cache. + debug('Looking up default account ID from STS'); + const result = await new AWS.STS({ credentials: creds, region: await this.region }).getCallerIdentity().promise(); + const aid = result.Account; + if (!aid) { + debug('STS didn\'t return an account ID'); + return undefined; + } + debug('Default account ID:', aid); + return aid; + }); + + return accountId; + } catch (e) { + debug('Unable to determine the default AWS account (did you configure "aws configure"?):', e); + return undefined; + } + } +} + +/** + * Build an AWS CLI-compatible credential chain provider + * + * This is similar to the default credential provider chain created by the SDK + * except it also accepts the profile argument in the constructor (not just from + * the environment). + * + * To mimic the AWS CLI behavior: + * + * - we default to ~/.aws/credentials if environment variable for credentials + * file location is not given (SDK expects explicit environment variable with name). + * - AWS_DEFAULT_PROFILE is also inspected for profile name (not just AWS_PROFILE). + */ +async function makeCLICompatibleCredentialProvider(profile: string | undefined, ec2creds: boolean | undefined) { + profile = profile || process.env.AWS_PROFILE || process.env.AWS_DEFAULT_PROFILE || 'default'; + + // Need to construct filename ourselves, without appropriate environment variables + // no defaults used by JS SDK. + const filename = process.env.AWS_SHARED_CREDENTIALS_FILE || path.join(os.homedir(), '.aws', 'credentials'); + + const sources = [ + () => new AWS.EnvironmentCredentials('AWS'), + () => new AWS.EnvironmentCredentials('AMAZON'), + ]; + if (fs.pathExists(filename)) { + sources.push(() => new AWS.SharedIniFileCredentials({ profile, filename })); + } + + if (hasEcsCredentials()) { + sources.push(() => new AWS.ECSCredentials()); + } else { + // else if: don't get EC2 creds if we should have gotten ECS creds--ECS instances also + // run on EC2 boxes but the creds represent something different. Same behavior as + // upstream code. + + if (ec2creds === undefined) { ec2creds = await hasEc2Credentials(); } + + if (ec2creds) { + sources.push(() => new AWS.EC2MetadataCredentials()); + } + } + + return new AWS.CredentialProviderChain(sources); +} + +/** + * Return the default region in a CLI-compatible way + * + * Mostly copied from node_loader.js, but with the following differences: + * + * - Takes a runtime profile name to load the region from, not just based on environment + * variables at process start. + * - We have needed to create a local copy of the SharedIniFile class because the + * implementation in 'aws-sdk' is private (and the default use of it in the + * SDK does not allow us to specify a profile at runtime). + * - AWS_DEFAULT_PROFILE and AWS_DEFAULT_REGION are also used as environment + * variables to be used to determine the region. + */ +async function getCLICompatibleDefaultRegion(profile: string | undefined): Promise { + profile = profile || process.env.AWS_PROFILE || process.env.AWS_DEFAULT_PROFILE || 'default'; + + // Defaults inside constructor + const toCheck = [ + {filename: process.env.AWS_SHARED_CREDENTIALS_FILE }, + {isConfig: true, filename: process.env.AWS_CONFIG_FILE}, + ]; + + let region = process.env.AWS_REGION || process.env.AMAZON_REGION || + process.env.AWS_DEFAULT_REGION || process.env.AMAZON_DEFAULT_REGION; + + while (!region && toCheck.length > 0) { + const configFile = new SharedIniFile(toCheck.shift()); + const section = await configFile.getProfile(profile); + region = section && section.region; + } + + return region; +} + +/** + * Find and return the configured HTTPS proxy address + */ +function httpsProxyFromEnvironment(): string | undefined { + if (process.env.https_proxy) { + return process.env.https_proxy; + } + if (process.env.HTTPS_PROXY) { + return process.env.HTTPS_PROXY; + } + return undefined; +} + +/** + * Return whether it looks like we'll have ECS credentials available + */ +function hasEcsCredentials() { + return (AWS.ECSCredentials.prototype as any).isConfiguredForEcsCredentials(); +} + +/** + * Return whether we're on an EC2 instance + */ +async function hasEc2Credentials() { + debug("Determining whether we're on an EC2 instance."); + + let instance = false; + if (process.platform === 'win32') { + // https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/identify_ec2_instances.html + const result = await util.promisify(child_process.exec)('wmic path win32_computersystemproduct get uuid', { encoding: 'utf-8' }); + // output looks like + // UUID + // EC2AE145-D1DC-13B2-94ED-01234ABCDEF + const lines = result.stdout.toString().split('\n'); + instance = lines.some(x => matchesRegex(/^ec2/i, x)); + } else { + // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html + const files: Array<[string, RegExp]> = [ + // This recognizes the Xen hypervisor based instances (pre-5th gen) + ['/sys/hypervisor/uuid', /^ec2/i], + + // This recognizes the new Hypervisor (5th-gen instances and higher) + // Can't use the advertised file '/sys/devices/virtual/dmi/id/product_uuid' because it requires root to read. + // Instead, sys_vendor contains something like 'Amazon EC2'. + ['/sys/devices/virtual/dmi/id/sys_vendor', /ec2/i], + ]; + for (const [file, re] of files) { + if (matchesRegex(re, await readIfPossible(file))) { + instance = true; + break; + } + } + } + + debug(instance ? 'Looks like EC2 instance.' : 'Does not look like EC2 instance.'); + return instance; +} + +async function setConfigVariable() { + const homeDir = process.env.HOME || process.env.USERPROFILE + || (process.env.HOMEPATH ? ((process.env.HOMEDRIVE || 'C:/') + process.env.HOMEPATH) : null) || os.homedir(); + + if (await fs.pathExists(path.resolve(homeDir, '.aws', 'config'))) { + process.env.AWS_SDK_LOAD_CONFIG = '1'; + } +} + +async function readIfPossible(filename: string): Promise { + try { + if (!await fs.pathExists(filename)) { return undefined; } + return fs.readFile(filename, { encoding: 'utf-8' }); + } catch (e) { + debug(e); + return undefined; + } +} + +function matchesRegex(re: RegExp, s: string | undefined) { + return s !== undefined && re.exec(s) !== null; +} diff --git a/packages/@aws-cdk/cdk-common/lib/sdk_ini_file.ts b/packages/@aws-cdk/cdk-common/lib/sdk_ini_file.ts new file mode 100644 index 0000000000000..1e9f625061f0f --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/sdk_ini_file.ts @@ -0,0 +1,59 @@ +/** + * A reimplementation of JS AWS SDK's SharedIniFile class + * + * We need that class to parse the ~/.aws/config file to determine the correct + * region at runtime, but unfortunately it is private upstream. + */ + +import AWS = require('aws-sdk'); +import fs = require('fs-extra'); +import os = require('os'); +import path = require('path'); + +export interface SharedIniFileOptions { + isConfig?: boolean; + filename?: string; +} + +export class SharedIniFile { + private readonly isConfig: boolean; + private readonly filename: string; + private parsedContents?: {[key: string]: {[key: string]: string}}; + + constructor(options?: SharedIniFileOptions) { + options = options || {}; + this.isConfig = options.isConfig === true; + this.filename = options.filename || this.getDefaultFilepath(); + } + + public async getProfile(profile: string) { + await this.ensureFileLoaded(); + + const profileIndex = profile !== (AWS as any).util.defaultProfile && this.isConfig ? + 'profile ' + profile : profile; + + return this.parsedContents![profileIndex]; + } + + private getDefaultFilepath(): string { + return path.join( + os.homedir(), + '.aws', + this.isConfig ? 'config' : 'credentials' + ); + } + + private async ensureFileLoaded() { + if (this.parsedContents) { + return; + } + + if (!await fs.pathExists(this.filename)) { + this.parsedContents = {}; + return; + } + + const contents: string = (await fs.readFile(this.filename)).toString(); + this.parsedContents = (AWS as any).util.ini.parse(contents); + } +} diff --git a/packages/@aws-cdk/cdk-common/lib/serialize.ts b/packages/@aws-cdk/cdk-common/lib/serialize.ts new file mode 100644 index 0000000000000..3219cb5a48836 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/serialize.ts @@ -0,0 +1,38 @@ +import YAML = require('yaml'); + +/** + * Stringify to YAML + */ +export function toYAML(obj: any): string { + return YAML.stringify(obj, { schema: 'yaml-1.1' }); +} + +/** + * Parse YAML + */ +export function fromYAML(str: string): any { + return YAML.parse(str, { schema: 'yaml-1.1' }); +} + +/** + * Parse either YAML or JSON + */ +export function deserializeStructure(str: string) { + try { + return fromYAML(str); + } catch (e) { + // This shouldn't really ever happen I think, but it's the code we had so I'm leaving it. + return JSON.parse(str); + } +} + +/** + * Serialize to either YAML or JSON + */ +export function serializeStructure(object: any, json: boolean) { + if (json) { + return JSON.stringify(object, undefined, 2); + } else { + return toYAML(object); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-common/lib/util/arrays.ts b/packages/@aws-cdk/cdk-common/lib/util/arrays.ts new file mode 100644 index 0000000000000..516466cd11254 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/util/arrays.ts @@ -0,0 +1,31 @@ +/** + * Map a function over an array and concatenate the results + */ +export function flatMap(xs: T[], fn: ((x: T, i: number) => U[])): U[] { + return flatten(xs.map(fn)); +} + +/** + * Flatten a list of lists into a list of elements + */ +export function flatten(xs: T[][]): T[] { + return Array.prototype.concat.apply([], xs); +} + +/** + * Partition a collection by removing and returning all elements that match a predicate + * + * Note: the input collection is modified in-place! + */ +export function partition(collection: T[], pred: (x: T) => boolean): T[] { + const ret: T[] = []; + let i = 0; + while (i < collection.length) { + if (pred(collection[i])) { + ret.push(collection.splice(i, 1)[0]); + } else { + i++; + } + } + return ret; +} diff --git a/packages/@aws-cdk/cdk-common/lib/util/index.ts b/packages/@aws-cdk/cdk-common/lib/util/index.ts new file mode 100644 index 0000000000000..a9a8af258b0f2 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/util/index.ts @@ -0,0 +1,4 @@ +export * from './arrays'; +export * from './objects'; +export * from './types'; +export * from './tables'; diff --git a/packages/@aws-cdk/cdk-common/lib/util/objects.ts b/packages/@aws-cdk/cdk-common/lib/util/objects.ts new file mode 100644 index 0000000000000..7fb660525687c --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/util/objects.ts @@ -0,0 +1,136 @@ +import { isArray, isObject, Obj } from './types'; + +/** + * Return a new object by adding missing keys into another object + */ +export function applyDefaults(hash: any, defaults: any) { + const result: any = { }; + + Object.keys(hash).forEach(k => result[k] = hash[k]); + + Object.keys(defaults) + .filter(k => !(k in result)) + .forEach(k => result[k] = defaults[k]); + + return result; +} + +/** + * Return whether the given parameter is an empty object or empty list. + */ +export function isEmpty(x: any) { + if (x == null) { return false; } + if (isArray(x)) { return x.length === 0; } + return Object.keys(x).length === 0; +} + +/** + * Deep clone a tree of objects, lists or scalars + * + * Does not support cycles. + */ +export function deepClone(x: any): any { + if (typeof x === 'undefined') { return undefined; } + if (x === null) { return null; } + if (isArray(x)) { return x.map(deepClone); } + if (isObject(x)) { return makeObject(mapObject(x, (k, v) => [k, deepClone(v)] as [string, any])); } + return x; +} + +/** + * Map over an object, treating it as a dictionary + */ +export function mapObject(x: Obj, fn: (key: string, value: T) => U): U[] { + const ret: U[] = []; + Object.keys(x).forEach(key => { + ret.push(fn(key, x[key])); + }); + return ret; +} + +/** + * Construct an object from a list of (k, v) pairs + */ +export function makeObject(pairs: Array<[string, T]>): Obj { + const ret: Obj = {}; + for (const pair of pairs) { + ret[pair[0]] = pair[1]; + } + return ret; +} + +/** + * Deep get a value from a tree of nested objects + * + * Returns undefined if any part of the path was unset or + * not an object. + */ +export function deepGet(x: any, path: string[]): any { + path = path.slice(); + + while (path.length > 0 && isObject(x)) { + const key = path.shift()!; + x = x[key]; + } + return path.length === 0 ? x : undefined; +} + +/** + * Deep set a value in a tree of nested objects + * + * Throws an error if any part of the path is not an object. + */ +export function deepSet(x: any, path: string[], value: any) { + path = path.slice(); + + if (path.length === 0) { + throw new Error('Path may not be empty'); + } + + while (path.length > 1 && isObject(x)) { + const key = path.shift()!; + if (!(key in x)) { x[key] = {}; } + x = x[key]; + } + + if (!isObject(x)) { + throw new Error(`Expected an object, got '${x}'`); + } + + if (value !== undefined) { + x[path[0]] = value; + } else { + delete x[path[0]]; + } +} + +/** + * Recursively merge objects together + * + * The leftmost object is mutated and returned. Arrays are not merged + * but overwritten just like scalars. + * + * If an object is merged into a non-object, the non-object is lost. + */ +export function deepMerge(...objects: Array | undefined>) { + function mergeOne(target: Obj, source: Obj) { + for (const key of Object.keys(source)) { + const value = source[key]; + + if (isObject(value)) { + if (!isObject(target[key])) { target[key] = {}; } // Overwrite on purpose + mergeOne(target[key], value); + } else if (typeof value !== 'undefined') { + target[key] = value; + } + } + } + + const others = objects.filter(x => x != null) as Array>; + + if (others.length === 0) { return {}; } + const into = others.splice(0, 1)[0]; + + others.forEach(other => mergeOne(into, other)); + return into; +} diff --git a/packages/@aws-cdk/cdk-common/lib/util/please-hold.ts b/packages/@aws-cdk/cdk-common/lib/util/please-hold.ts new file mode 100644 index 0000000000000..cb6eff963296b --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/util/please-hold.ts @@ -0,0 +1,26 @@ +import colors = require('colors/safe'); +import { print } from "../logging"; + +/** + * Print a message to the logger in case the operation takes a long time + */ +export class PleaseHold { + private handle?: NodeJS.Timer; + + constructor(private readonly message: string, private readonly timeoutSec = 10) { + } + + public start() { + this.handle = setTimeout(this.printMessage.bind(this), this.timeoutSec * 1000); + } + + public stop() { + if (this.handle) { + clearTimeout(this.handle); + } + } + + private printMessage() { + print(colors.yellow(this.message)); + } +} diff --git a/packages/@aws-cdk/cdk-common/lib/util/string-manipulation.ts b/packages/@aws-cdk/cdk-common/lib/util/string-manipulation.ts new file mode 100644 index 0000000000000..aa51679967ba3 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/util/string-manipulation.ts @@ -0,0 +1,7 @@ +/** + * Pad 's' on the left with 'char' until it is n characters wide + */ +export function leftPad(s: string, n: number, char: string) { + const padding = Math.max(0, n - s.length); + return char.repeat(padding) + s; +} \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-common/lib/util/tables.ts b/packages/@aws-cdk/cdk-common/lib/util/tables.ts new file mode 100644 index 0000000000000..bfc059bef40fc --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/util/tables.ts @@ -0,0 +1,7 @@ +import cfnDiff = require('@aws-cdk/cloudformation-diff'); + +export function renderTable(cells: string[][], columns?: number) { + // The cfnDiff module has logic for terminal-width aware table + // formatting (and nice colors), let's just reuse that. + return cfnDiff.formatTable(cells, columns); +} \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-common/lib/util/toposort.ts b/packages/@aws-cdk/cdk-common/lib/util/toposort.ts new file mode 100644 index 0000000000000..97dd35ea8bb46 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/util/toposort.ts @@ -0,0 +1,44 @@ +export type KeyFunc = (x: T) => string; +export type DepFunc = (x: T) => string[]; + +/** + * Return a topological sort of all elements of xs, according to the given dependency functions + * + * Dependencies outside the referenced set are ignored. + * + * Not a stable sort, but in order to keep the order as stable as possible, we'll sort by key + * among elements of equal precedence. + */ +export function topologicalSort(xs: Iterable, keyFn: KeyFunc, depFn: DepFunc): T[] { + const remaining = new Map>(); + for (const element of xs) { + const key = keyFn(element); + remaining.set(key, { key, element, dependencies: depFn(element) }); + } + + const ret = new Array(); + while (remaining.size > 0) { + // All elements with no more deps in the set can be ordered + const selectable = Array.from(remaining.values()).filter(e => e.dependencies.every(d => !remaining.has(d))); + + selectable.sort((a, b) => a.key < b.key ? -1 : b.key < a.key ? 1 : 0); + + for (const selected of selectable) { + ret.push(selected.element); + remaining.delete(selected.key); + } + + // If we didn't make any progress, we got stuck + if (selectable.length === 0) { + throw new Error(`Could not determine ordering between: ${Array.from(remaining.keys()).join(', ')}`); + } + } + + return ret; +} + +interface TopoElement { + key: string; + dependencies: string[]; + element: T; +} \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-common/lib/util/types.ts b/packages/@aws-cdk/cdk-common/lib/util/types.ts new file mode 100644 index 0000000000000..8d18b6e53e360 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/lib/util/types.ts @@ -0,0 +1,32 @@ +/** + * Type of a map mapping strings to some arbitrary type + * + * Name is not ideal, but: + * + * - Cannot call it Object, that already means something. + * - Cannot call it Dict or Dictionary, since in other languages + * those also allow specifying the key type. + */ +export type Obj = {[key: string]: T}; + +/** + * Return whether the given value is an object + * + * Even though arrays technically are objects, we usually want to treat them differently, + * so we return false in those cases. + */ +export function isObject(x: any): x is Obj { + return x !== null && typeof x === 'object' && !isArray(x); +} + +/** + * Return whether the given value is an array + */ +export const isArray = Array.isArray; + +/** + * Return the value of the first argument if it's not undefined, otherwise the default + */ +export function ifDefined(x: T | undefined, def: T): T { + return typeof x !== 'undefined' ? x : def; +} diff --git a/packages/@aws-cdk/cdk-common/package-lock.json b/packages/@aws-cdk/cdk-common/package-lock.json new file mode 100644 index 0000000000000..675e02d2840d4 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/package-lock.json @@ -0,0 +1,2140 @@ +{ + "name": "@aws-cdk/cdk-common", + "version": "0.28.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/runtime": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz", + "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@sinonjs/commons": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", + "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.1.tgz", + "integrity": "sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash": "^4.17.11" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "@types/archiver": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-2.1.3.tgz", + "integrity": "sha512-x37dj6VvV8jArjvqvZP+qz5+24qOwgFesLMvn98uNz8qebjCg+uteqquRf9mqaxxhcM7S1vPl4YFhBs2/abcFQ==", + "dev": true, + "requires": { + "@types/glob": "*" + } + }, + "@types/caseless": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/form-data": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", + "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/fs-extra": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.5.tgz", + "integrity": "sha512-w7iqhDH9mN8eLClQOYTkhdYUOSpp25eXxfc6VbFOGtzxW34JcvctH2bKjj4jD4++z4R5iO5D+pg48W2e03I65A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/mockery": { + "version": "1.4.29", + "resolved": "https://registry.npmjs.org/@types/mockery/-/mockery-1.4.29.tgz", + "integrity": "sha1-m6It838H43gP/4Ux0aOOYz+UV6U=", + "dev": true + }, + "@types/node": { + "version": "8.10.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.45.tgz", + "integrity": "sha512-tGVTbA+i3qfXsLbq9rEq/hezaHY55QxQLeXQL2ejNgFAxxrgu8eMmYIOsRcl7hN1uTLVsKOOYacV/rcJM3sfgQ==" + }, + "@types/request": { + "version": "2.48.1", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.1.tgz", + "integrity": "sha512-ZgEZ1TiD+KGA9LiAAPPJL68Id2UWfeSO62ijSXZjFJArVV+2pKcsVHmrcu+1oiE3q6eDGiFiSolRc4JHoerBBg==", + "dev": true, + "requires": { + "@types/caseless": "*", + "@types/form-data": "*", + "@types/node": "*", + "@types/tough-cookie": "*" + } + }, + "@types/semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==", + "dev": true + }, + "@types/sinon": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.0.11.tgz", + "integrity": "sha512-6ee09Ugx6GyEr0opUIakmxIWFNmqYPjkqa3/BuxCBokA0klsOLPgMD5K4q40lH7/yZVuJVzOfQpd7pipwjngkQ==", + "dev": true + }, + "@types/table": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/table/-/table-4.0.5.tgz", + "integrity": "sha512-M/e/pWOWjm8X/fu8I9eOhc/ww1RsUG1yOr/G3vgdBwVFmfnMiqCRIiEKpDZdscNNCzr/kAAzuTNqGUH1uAk/qQ==", + "dev": true + }, + "@types/tough-cookie": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz", + "integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==", + "dev": true + }, + "@types/uuid": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz", + "integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/yaml": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.0.2.tgz", + "integrity": "sha512-rS1VJFjyGKNHk8H97COnPIK+oeLnc0J9G0ES63o/Ky+WlJCeaFGiGCTGhV/GEVKua7ZWIV1JIDopYUwrfvTo7A==", + "dev": true + }, + "@types/yargs": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "integrity": "sha512-YdxO7zGQf2qJeMgR0fNO8QTlj88L2zCP5GOddovoTyetgLiNDOUXcWzhWKb4EdZZlOjLQUA0JM8lW7VcKQL+9w==", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "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": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "archiver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", + "requires": { + "archiver-utils": "^1.3.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^1.2.0" + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash": "^4.8.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "ast-types": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.12.3.tgz", + "integrity": "sha512-wJUcAfrdW+IgDoMGNz5MmcvahKgB7BwIbLupdKVVHxHNYt+HVR2k35swdYNv9aZpF8nvlkjbnkp2rrNwxGckZA==" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "requires": { + "lodash": "^4.17.11" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sdk": { + "version": "2.438.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.438.0.tgz", + "integrity": "sha512-j+7zZYHekFFqoERSLDF1fDmC9awmZG2YJDoGuxBxwozi6Rg2GjyglwVehrNs3oC51UyrWhzWdn7jOVG6It5nmw==", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.8", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "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" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "^5.1.0" + } + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-uri-to-buffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.1.tgz", + "integrity": "sha512-OkVVLrerfAKZlW2ZZ3Ve2y65jgiWqBKsTfUIAFbn8nVbPcCZg6l6gikKlEYv0kXcmzqGm6mFq/Jf2vriuEkv8A==", + "requires": { + "@types/node": "^8.0.7" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "requires": { + "xregexp": "4.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "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" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.8.2.tgz", + "integrity": "sha1-q6jZ4ZQ6iVrJaDemKjmz9V7NlKs=" + }, + "es6-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "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" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + } + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-uri": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.3.tgz", + "integrity": "sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw==", + "requires": { + "data-uri-to-buffer": "2", + "debug": "4", + "extend": "~3.0.2", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "readable-stream": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", + "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "heap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", + "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "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" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "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", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lolex": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-3.1.0.tgz", + "integrity": "sha512-zFo5MgCJ0rZ7gQg69S4pqBsLURbFw11X68C18OcJjJQbqaXm2NoTrGl1IMM3TIz0/BnN1tIs2tzmmqvCsOMMjw==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "requires": { + "mime-db": "~1.38.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mockery": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mockery/-/mockery-2.1.0.tgz", + "integrity": "sha512-9VkOmxKlWXoDO/h1jDZaS4lH33aWfRiJiNT/tKj+8OGzrcFDLo8d0syGdbsc3Bc4GvRXPb+NMMvojotmuGJTvA==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" + }, + "nise": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.10.tgz", + "integrity": "sha512-sa0RRbj53dovjc7wombHmVli9ZihXbXCQ2uH3TNm03DyvOSIQbxg+pbqDKrk2oxMK1rtLGVlKxcB9rrc6X5YjA==", + "dev": true, + "requires": { + "@sinonjs/formatio": "^3.1.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^2.3.2", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "pac-proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", + "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "promptly": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-0.2.1.tgz", + "integrity": "sha1-ZETnyk29mJnn7rXsOSKCfr3CKzs=", + "requires": { + "read": "~1.0.4" + } + }, + "proxy-agent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.0.tgz", + "integrity": "sha512-IkbZL4ClW3wwBL/ABFD2zJ8iP84CY0uKMvBPk/OceQe/cEjrxzN1pMHsLwhbzUoRhG9QbSxYC+Z7LBkTiBNvrA==", + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "pac-proxy-agent": "^3.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "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", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sinon": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.3.1.tgz", + "integrity": "sha512-eQKMaeWovtOtYe2xThEvaHmmxf870Di+bim10c3ZPrL5bZhLGtu8cz+rOBTFz0CwBV4Q/7dYwZiqZbGVLZ+vjQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.1", + "diff": "^3.5.0", + "lolex": "^3.1.0", + "nise": "^1.4.10", + "supports-color": "^5.5.0" + } + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "smart-buffer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", + "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==" + }, + "socks": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz", + "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==", + "requires": { + "ip": "^1.1.5", + "smart-buffer": "4.0.2" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", + "requires": { + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xregexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yaml": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.5.0.tgz", + "integrity": "sha512-nKxSWOa7vxAP2pikrGxbkZsG/garQseRiLn9mIDjzwoQsyVy7ZWIpLoARejnINGGLA4fttuzRFFNxxbsztdJgw==", + "requires": { + "@babel/runtime": "^7.4.3" + } + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "requires": { + "archiver-utils": "^1.3.0", + "compress-commons": "^1.2.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0" + } + } + } +} diff --git a/packages/@aws-cdk/cdk-common/package.json b/packages/@aws-cdk/cdk-common/package.json new file mode 100644 index 0000000000000..171c05adcb316 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/package.json @@ -0,0 +1,79 @@ +{ + "name": "@aws-cdk/cdk-common", + "description": "Common classes and utilities for CDK CLI applications", + "version": "0.28.0", + "private": true, + "main": "lib/index.js", + "types": "lib/index.d.ts", + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "pkglint": "pkglint -f", + "test": "cdk-test", + "package": "cdk-package" + }, + "nyc": { + "statements": 8, + "lines": 8, + "branches": 3 + }, + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@types/archiver": "^2.1.2", + "@types/fs-extra": "^5.0.4", + "@types/minimatch": "^3.0.3", + "@types/mockery": "^1.4.29", + "@types/request": "^2.47.1", + "@types/semver": "^5.5.0", + "@types/sinon": "^7.0.10", + "@types/table": "^4.0.5", + "@types/uuid": "^3.4.3", + "@types/yaml": "^1.0.0", + "@types/yargs": "^8.0.3", + "cdk-build-tools": "^0.28.0", + "mockery": "^2.1.0", + "pkglint": "^0.28.0", + "sinon": "^7.2.7" + }, + "dependencies": { + "@aws-cdk/applet-js": "^0.28.0", + "@aws-cdk/cloudformation-diff": "^0.28.0", + "@aws-cdk/cx-api": "^0.28.0", + "@aws-cdk/region-info": "^0.28.0", + "archiver": "^2.1.1", + "aws-sdk": "^2.259.1", + "camelcase": "^5.0.0", + "colors": "^1.2.1", + "decamelize": "^2.0.0", + "fs-extra": "^7.0.0", + "json-diff": "^0.3.1", + "minimatch": ">=3.0", + "promptly": "^0.2.0", + "proxy-agent": "^3.0.1", + "request": "^2.83.0", + "semver": "^5.5.0", + "source-map-support": "^0.5.6", + "table": "^5.2.1", + "yaml": "^1.1.0", + "yargs": "^9.0.1" + }, + "repository": { + "url": "https://github.com/awslabs/aws-cdk.git", + "type": "git", + "directory": "packages/@aws-cdk/cdk-common" + }, + "keywords": [ + "aws", + "cdk" + ], + "homepage": "https://github.com/awslabs/aws-cdk", + "engines": { + "node": ">= 8.10.0" + } +} diff --git a/packages/@aws-cdk/cdk-common/tsconfig.json b/packages/@aws-cdk/cdk-common/tsconfig.json new file mode 100644 index 0000000000000..b2d05e7902fc2 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "target":"ES2018", + "module": "commonjs", + "lib": ["es2016", "es2017.object", "es2017.string"], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization":false + }, + "include": [ + "**/*.ts", + "**/*.d.ts" + ] +} + From 7820ce8c06d1eb0d0062e89bee8b405e4bde8cb7 Mon Sep 17 00:00:00 2001 From: Sam Goodwin Date: Tue, 16 Apr 2019 18:23:21 -0700 Subject: [PATCH 02/12] Move classes into cdk-deploy --- packages/@aws-cdk/cdk-common/lib/index.ts | 1 + .../cdk-common}/lib/os.ts | 0 .../@aws-cdk/cdk-common/lib/util/index.ts | 5 +- packages/@aws-cdk/cdk-deploy/.gitignore | 15 + packages/@aws-cdk/cdk-deploy/.npmignore | 12 + packages/@aws-cdk/cdk-deploy/LICENSE | 201 ++ packages/@aws-cdk/cdk-deploy/NOTICE | 2 + packages/@aws-cdk/cdk-deploy/README.md | 174 ++ packages/@aws-cdk/cdk-deploy/bin/cdk-deploy | 2 + .../@aws-cdk/cdk-deploy/bin/cdk-deploy.ts | 0 .../lib/api/bootstrap-environment.ts | 2 +- .../cdk-deploy}/lib/api/deploy-stack.ts | 5 +- .../cdk-deploy}/lib/api/deployment-target.ts | 5 +- .../cdk-deploy}/lib/api/index.ts | 2 - .../cdk-deploy}/lib/api/toolkit-info.ts | 4 +- .../lib/api/util/cloudformation.ts | 2 +- .../cloudformation/stack-activity-monitor.ts | 2 +- .../api/util/cloudformation/stack-status.ts | 0 .../cdk-deploy}/lib/archive.ts | 0 .../cdk-deploy}/lib/assets.ts | 4 +- .../cdk-deploy}/lib/cdk-toolkit.ts | 6 +- .../cdk-deploy}/lib/diff.ts | 2 +- .../cdk-deploy}/lib/docker.ts | 4 +- .../@aws-cdk/cdk-deploy/package-lock.json | 2140 +++++++++++++++++ packages/@aws-cdk/cdk-deploy/package.json | 82 + packages/@aws-cdk/cdk-deploy/tsconfig.json | 25 + .../aws-cdk/lib/api/aws-auth/credentials.ts | 29 - packages/aws-cdk/lib/api/cxapp/exec.ts | 3 +- packages/aws-cdk/lib/api/cxapp/stacks.ts | 7 +- .../aws-cdk/lib/api/util/account-cache.ts | 92 - packages/aws-cdk/lib/api/util/sdk.ts | 437 ---- packages/aws-cdk/lib/api/util/sdk_ini_file.ts | 59 - .../lib/api/util/string-manipulation.ts | 7 - packages/aws-cdk/lib/api/util/toposort.ts | 44 - packages/aws-cdk/lib/command-api.ts | 2 +- packages/aws-cdk/lib/commands/context.ts | 2 +- .../context-providers/availability-zones.ts | 3 +- .../lib/context-providers/hosted-zones.ts | 3 +- .../aws-cdk/lib/context-providers/index.ts | 3 +- .../lib/context-providers/ssm-parameters.ts | 3 +- .../aws-cdk/lib/context-providers/vpcs.ts | 3 +- packages/aws-cdk/lib/index.ts | 1 - packages/aws-cdk/lib/logging.ts | 54 - packages/aws-cdk/lib/plugin.ts | 86 - packages/aws-cdk/lib/renames.ts | 2 +- packages/aws-cdk/lib/serialize.ts | 38 - packages/aws-cdk/lib/settings.ts | 9 +- packages/aws-cdk/lib/util/arrays.ts | 31 - packages/aws-cdk/lib/util/index.ts | 4 - packages/aws-cdk/lib/util/objects.ts | 136 -- packages/aws-cdk/lib/util/please-hold.ts | 26 - packages/aws-cdk/lib/util/tables.ts | 7 - packages/aws-cdk/lib/util/types.ts | 32 - packages/aws-cdk/package.json | 1 + packages/aws-cdk/tsconfig.json | 2 +- 55 files changed, 2689 insertions(+), 1134 deletions(-) rename packages/{aws-cdk => @aws-cdk/cdk-common}/lib/os.ts (100%) create mode 100644 packages/@aws-cdk/cdk-deploy/.gitignore create mode 100644 packages/@aws-cdk/cdk-deploy/.npmignore create mode 100644 packages/@aws-cdk/cdk-deploy/LICENSE create mode 100644 packages/@aws-cdk/cdk-deploy/NOTICE create mode 100644 packages/@aws-cdk/cdk-deploy/README.md create mode 100644 packages/@aws-cdk/cdk-deploy/bin/cdk-deploy create mode 100644 packages/@aws-cdk/cdk-deploy/bin/cdk-deploy.ts rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/api/bootstrap-environment.ts (97%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/api/deploy-stack.ts (97%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/api/deployment-target.ts (92%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/api/index.ts (67%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/api/toolkit-info.ts (98%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/api/util/cloudformation.ts (99%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/api/util/cloudformation/stack-activity-monitor.ts (99%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/api/util/cloudformation/stack-status.ts (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/archive.ts (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/assets.ts (97%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/cdk-toolkit.ts (96%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/diff.ts (98%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/lib/docker.ts (98%) create mode 100644 packages/@aws-cdk/cdk-deploy/package-lock.json create mode 100644 packages/@aws-cdk/cdk-deploy/package.json create mode 100644 packages/@aws-cdk/cdk-deploy/tsconfig.json delete mode 100644 packages/aws-cdk/lib/api/aws-auth/credentials.ts delete mode 100644 packages/aws-cdk/lib/api/util/account-cache.ts delete mode 100644 packages/aws-cdk/lib/api/util/sdk.ts delete mode 100644 packages/aws-cdk/lib/api/util/sdk_ini_file.ts delete mode 100644 packages/aws-cdk/lib/api/util/string-manipulation.ts delete mode 100644 packages/aws-cdk/lib/api/util/toposort.ts delete mode 100644 packages/aws-cdk/lib/logging.ts delete mode 100644 packages/aws-cdk/lib/plugin.ts delete mode 100644 packages/aws-cdk/lib/serialize.ts delete mode 100644 packages/aws-cdk/lib/util/arrays.ts delete mode 100644 packages/aws-cdk/lib/util/index.ts delete mode 100644 packages/aws-cdk/lib/util/objects.ts delete mode 100644 packages/aws-cdk/lib/util/please-hold.ts delete mode 100644 packages/aws-cdk/lib/util/tables.ts delete mode 100644 packages/aws-cdk/lib/util/types.ts diff --git a/packages/@aws-cdk/cdk-common/lib/index.ts b/packages/@aws-cdk/cdk-common/lib/index.ts index 493de9d2f20ee..56baa97de0374 100644 --- a/packages/@aws-cdk/cdk-common/lib/index.ts +++ b/packages/@aws-cdk/cdk-common/lib/index.ts @@ -1,5 +1,6 @@ export * from './credentials'; export * from './logging'; +export * from './os'; export * from './sdk'; export * from './serialize'; export * from './util'; diff --git a/packages/aws-cdk/lib/os.ts b/packages/@aws-cdk/cdk-common/lib/os.ts similarity index 100% rename from packages/aws-cdk/lib/os.ts rename to packages/@aws-cdk/cdk-common/lib/os.ts diff --git a/packages/@aws-cdk/cdk-common/lib/util/index.ts b/packages/@aws-cdk/cdk-common/lib/util/index.ts index a9a8af258b0f2..e081d30f61d37 100644 --- a/packages/@aws-cdk/cdk-common/lib/util/index.ts +++ b/packages/@aws-cdk/cdk-common/lib/util/index.ts @@ -1,4 +1,7 @@ export * from './arrays'; export * from './objects'; -export * from './types'; +export * from './please-hold'; +export * from './string-manipulation'; export * from './tables'; +export * from './toposort'; +export * from './types'; diff --git a/packages/@aws-cdk/cdk-deploy/.gitignore b/packages/@aws-cdk/cdk-deploy/.gitignore new file mode 100644 index 0000000000000..cd4b6d8758860 --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/.gitignore @@ -0,0 +1,15 @@ +*.js +*.js.map +*.d.ts +node_modules +dist + +# Generated by generate.sh +lib/version.ts + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-deploy/.npmignore b/packages/@aws-cdk/cdk-deploy/.npmignore new file mode 100644 index 0000000000000..947b2350f7580 --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/.npmignore @@ -0,0 +1,12 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.template.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +*.snk \ No newline at end of file diff --git a/packages/@aws-cdk/cdk-deploy/LICENSE b/packages/@aws-cdk/cdk-deploy/LICENSE new file mode 100644 index 0000000000000..46c185646b439 --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/cdk-deploy/NOTICE b/packages/@aws-cdk/cdk-deploy/NOTICE new file mode 100644 index 0000000000000..8585168af8b7d --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/cdk-deploy/README.md b/packages/@aws-cdk/cdk-deploy/README.md new file mode 100644 index 0000000000000..7fd8bff8b8057 --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/README.md @@ -0,0 +1,174 @@ +## AWS CDK Toolkit +The AWS CDK Toolkit provides the `cdk` command-line interface that can be used to work with AWS CDK applications. + +Command | Description +----------------------------------|------------------------------------------------------------------------------------- +[`cdk docs`](#cdk-docs) | Access the online documentation +[`cdk init`](#cdk-init) | Start a new CDK project (app or library) +[`cdk list`](#cdk-list) | List stacks in an application +[`cdk synth`](#cdk-synthesize) | Synthesize a CDK app to CloudFormation template(s) +[`cdk diff`](#cdk-diff) | Diff stacks against current state +[`cdk deploy`](#cdk-deploy) | Deploy a stack into an AWS account +[`cdk destroy`](#cdk-destroy) | Deletes a stack from an AWS account +[`cdk bootstrap`](#cdk-bootstrap) | Deploy a toolkit stack to support deploying large stacks & artifacts +[`cdk doctor`](#cdk-doctor) | Inspect the environment and produce information useful for troubleshooting + +This module is part of the [AWS Cloud Development Kit](https://github.com/awslabs/aws-cdk) project. + +### Commands +#### `cdk docs` +Outputs the URL to the documentation for the current toolkit version, and attempts to open a browser to that URL. + +```console +$ # Open the documentation in the default browser (using 'open') +$ cdk docs +https://awslabs.github.io/aws-cdk/versions/0.7.4-beta/ + +$ # Open the documentation in Chrome. +$ cdk docs --browser='chrome %u' +https://awslabs.github.io/aws-cdk/versions/0.7.4-beta/ +``` + +#### `cdk init` +Creates a new CDK project. + +```console +$ # List the available template types & languages +$ cdk init --list +Available templates: +* app: Template for a CDK Application + └─ cdk init app --language=[java|typescript] +* lib: Template for a CDK Construct Library + └─ cdk init lib --language=typescript + +$ # Create a new library application in typescript +$ cdk init lib --language=typescript +``` + +#### `cdk list` +Lists the stacks modeled in the CDK app. + +```console +$ # List all stacks in the CDK app 'node bin/main.js' +$ cdk list --app='node bin/main.js' +Foo +Bar +Baz + +$ # List all stack including all details (add --json to output JSON instead of YAML) +$ cdk list --app='node bin/main.js' --long +- + name: Foo + environment: + name: 000000000000/bermuda-triangle-1 + account: '000000000000' + region: bermuda-triangle-1 +- + name: Bar + environment: + name: 111111111111/bermuda-triangle-2 + account: '111111111111' + region: bermuda-triangle-2 +- + name: Baz + environment: + name: 333333333333/bermuda-triangle-3 + account: '333333333333' + region: bermuda-triangle-3 +``` + +#### `cdk synthesize` +Synthesize the CDK app and outputs CloudFormation templates. If the application contains multiple stacks and no +stack name is provided in the command-line arguments, the `--output` option is mandatory and a CloudFormation template +will be generated in the output folder for each stack. + +By default, templates are generated in YAML format. The `--json` option can be used to switch to JSON. + +```console +$ # Generate the template for StackName and output it to STDOUT +$ cdk synthesize --app='node bin/main.js' MyStackName + +$ # Generate the template for MyStackName and save it to template.yml +$ cdk synth --app='node bin/main.js' MyStackName --output=template.yml + +$ # Generate templates for all the stacks and save them into templates/ +$ cdk synth --app='node bin/main.js' --output=templates +``` + +#### `cdk diff` +Computes differences between the infrastructure specified in the current state of the CDK app and the currently +deployed application (or a user-specified CloudFormation template). This command returns non-zero if any differences are +found. + +```console +$ # Diff against the currently deployed stack +$ cdk diff --app='node bin/main.js' MyStackName + +$ # Diff against a specific template document +$ cdk diff --app='node bin/main.js' MyStackName --template=path/to/template.yml +``` + +#### `cdk deploy` +Deploys a stack of your CDK app to it's environment. During the deployment, the toolkit will output progress +indications, similar to what can be observed in the AWS CloudFormation Console. If the environment was never +bootstrapped (using `cdk bootstrap`), only stacks that are not using assets and synthesize to a template that is under +51,200 bytes will successfully deploy. + +```console +$ cdk deploy --app='node bin/main.js' MyStackName +``` + +#### `cdk destroy` +Deletes a stack from it's environment. This will cause the resources in the stack to be destroyed (unless they were +configured with a `DeletionPolicy` of `Retain`). During the stack destruction, the command will output progress +information similar to what `cdk deploy` provides. + +```console +$ cdk destroy --app='node bin/main.js' MyStackName +``` + +#### `cdk bootstrap` +Deploys a `CDKToolkit` CloudFormation stack into the specified environment(s), that provides an S3 bucket that +`cdk deploy` will use to store synthesized templates and the related assets, before triggering a CloudFormation stack +update. The name of the deployed stack can be configured using the `--toolkit-stack-name` argument. + +```console +$ # Deploys to all environments +$ cdk bootstrap --app='node bin/main.js' + +$ # Deploys only to environments foo and bar +$ cdk bootstrap --app='node bin/main.js' foo bar +``` + +#### `cdk doctor` +Inspect the current command-line environment and configurations, and collect information that can be useful for +troubleshooting problems. It is usually a good idea to include the information provided by this command when submitting +a bug report. + +```console +$ cdk doctor +ℹ️ CDK Version: 0.7.4-beta (build 0191444) +ℹ️ AWS environment variables: + - AWS_EC2_METADATA_DISABLED = 1 + - AWS_SDK_LOAD_CONFIG = 1 +``` + +### Configuration +On top of passing configuration through command-line arguments, it is possible to use JSON configuration files. The +configuration's order of precedence is: +1. Command-line arguments +2. Project configuration (`./cdk.json`) +3. User configuration (`~/.cdk.json`) + +#### JSON Configuration files +Some of the interesting keys that can be used in the JSON configuration files: +```js +{ + "app": "node bin/main.js", // Command to start the CDK app (--app='node bin/main.js') + "context": { // Context entries (--context=key=value) + "key": "value", + }, + "toolkitStackName": "foo", // Customize 'bootstrap' stack name (--toolkit-stack-name=foo) + "versionReporting": false, // Opt-out of version reporting (--no-version-reporting) +} +``` diff --git a/packages/@aws-cdk/cdk-deploy/bin/cdk-deploy b/packages/@aws-cdk/cdk-deploy/bin/cdk-deploy new file mode 100644 index 0000000000000..493ca3d9d4d61 --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/bin/cdk-deploy @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./cdk-deploy.js'); diff --git a/packages/@aws-cdk/cdk-deploy/bin/cdk-deploy.ts b/packages/@aws-cdk/cdk-deploy/bin/cdk-deploy.ts new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/aws-cdk/lib/api/bootstrap-environment.ts b/packages/@aws-cdk/cdk-deploy/lib/api/bootstrap-environment.ts similarity index 97% rename from packages/aws-cdk/lib/api/bootstrap-environment.ts rename to packages/@aws-cdk/cdk-deploy/lib/api/bootstrap-environment.ts index 122899919e97a..b3e54793f22b5 100644 --- a/packages/aws-cdk/lib/api/bootstrap-environment.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/bootstrap-environment.ts @@ -1,6 +1,6 @@ +import { SDK } from '@aws-cdk/cdk-common'; import { Environment, SynthesizedStack } from '@aws-cdk/cx-api'; import { deployStack, DeployStackResult } from './deploy-stack'; -import { SDK } from './util/sdk'; // tslint:disable:max-line-length diff --git a/packages/aws-cdk/lib/api/deploy-stack.ts b/packages/@aws-cdk/cdk-deploy/lib/api/deploy-stack.ts similarity index 97% rename from packages/aws-cdk/lib/api/deploy-stack.ts rename to packages/@aws-cdk/cdk-deploy/lib/api/deploy-stack.ts index d7c8f96da323a..878af3f769a8b 100644 --- a/packages/aws-cdk/lib/api/deploy-stack.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/deploy-stack.ts @@ -1,16 +1,13 @@ +import { debug, error, Mode, print, SDK, toYAML } from '@aws-cdk/cdk-common'; import cxapi = require('@aws-cdk/cx-api'); import aws = require('aws-sdk'); import colors = require('colors/safe'); import uuid = require('uuid'); import { prepareAssets } from '../assets'; -import { debug, error, print } from '../logging'; -import { toYAML } from '../serialize'; -import { Mode } from './aws-auth/credentials'; import { ToolkitInfo } from './toolkit-info'; import { changeSetHasNoChanges, describeStack, stackExists, stackFailedCreating, waitForChangeSet, waitForStack } from './util/cloudformation'; import { StackActivityMonitor } from './util/cloudformation/stack-activity-monitor'; import { StackStatus } from './util/cloudformation/stack-status'; -import { SDK } from './util/sdk'; type TemplateBodyParameter = { TemplateBody?: string diff --git a/packages/aws-cdk/lib/api/deployment-target.ts b/packages/@aws-cdk/cdk-deploy/lib/api/deployment-target.ts similarity index 92% rename from packages/aws-cdk/lib/api/deployment-target.ts rename to packages/@aws-cdk/cdk-deploy/lib/api/deployment-target.ts index 61dc56458fc42..79a523a113412 100644 --- a/packages/aws-cdk/lib/api/deployment-target.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/deployment-target.ts @@ -1,10 +1,7 @@ +import { debug, deserializeStructure, Mode, SDK } from '@aws-cdk/cdk-common'; import cxapi = require('@aws-cdk/cx-api'); -import { debug } from '../logging'; -import { deserializeStructure } from '../serialize'; -import { Mode } from './aws-auth/credentials'; import { deployStack, DeployStackResult } from './deploy-stack'; import { loadToolkitInfo } from './toolkit-info'; -import { SDK } from './util/sdk'; export const DEFAULT_TOOLKIT_STACK_NAME = 'CDKToolkit'; diff --git a/packages/aws-cdk/lib/api/index.ts b/packages/@aws-cdk/cdk-deploy/lib/api/index.ts similarity index 67% rename from packages/aws-cdk/lib/api/index.ts rename to packages/@aws-cdk/cdk-deploy/lib/api/index.ts index 0d859da25319c..28c834362ed1c 100644 --- a/packages/aws-cdk/lib/api/index.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/index.ts @@ -1,7 +1,5 @@ import 'source-map-support/register'; -export * from './aws-auth/credentials'; export * from './bootstrap-environment'; export * from './deploy-stack'; export * from './toolkit-info'; -export * from './util/sdk'; diff --git a/packages/aws-cdk/lib/api/toolkit-info.ts b/packages/@aws-cdk/cdk-deploy/lib/api/toolkit-info.ts similarity index 98% rename from packages/aws-cdk/lib/api/toolkit-info.ts rename to packages/@aws-cdk/cdk-deploy/lib/api/toolkit-info.ts index 9ddb0994d8345..e980072bbe162 100644 --- a/packages/aws-cdk/lib/api/toolkit-info.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/toolkit-info.ts @@ -1,12 +1,10 @@ +import { debug, Mode, SDK } from '@aws-cdk/cdk-common'; import cxapi = require('@aws-cdk/cx-api'); import aws = require('aws-sdk'); import colors = require('colors/safe'); import { md5hash } from '../archive'; -import { debug } from '../logging'; -import { Mode } from './aws-auth/credentials'; import { BUCKET_DOMAIN_NAME_OUTPUT, BUCKET_NAME_OUTPUT } from './bootstrap-environment'; import { waitForStack } from './util/cloudformation'; -import { SDK } from './util/sdk'; export interface UploadProps { s3KeyPrefix?: string, diff --git a/packages/aws-cdk/lib/api/util/cloudformation.ts b/packages/@aws-cdk/cdk-deploy/lib/api/util/cloudformation.ts similarity index 99% rename from packages/aws-cdk/lib/api/util/cloudformation.ts rename to packages/@aws-cdk/cdk-deploy/lib/api/util/cloudformation.ts index b5b621eadef06..92ea15e7fd361 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/util/cloudformation.ts @@ -1,5 +1,5 @@ +import { debug } from '@aws-cdk/cdk-common'; import { CloudFormation } from 'aws-sdk'; -import { debug } from '../../logging'; import { StackStatus } from './cloudformation/stack-status'; /** diff --git a/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts b/packages/@aws-cdk/cdk-deploy/lib/api/util/cloudformation/stack-activity-monitor.ts similarity index 99% rename from packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts rename to packages/@aws-cdk/cdk-deploy/lib/api/util/cloudformation/stack-activity-monitor.ts index 8615b01583395..ee02911778cd1 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/util/cloudformation/stack-activity-monitor.ts @@ -1,8 +1,8 @@ +import { error } from '@aws-cdk/cdk-common/lib/logging'; import cxapi = require('@aws-cdk/cx-api'); import aws = require('aws-sdk'); import colors = require('colors/safe'); import util = require('util'); -import { error } from '../../../logging'; interface StackActivity { readonly event: aws.CloudFormation.StackEvent; diff --git a/packages/aws-cdk/lib/api/util/cloudformation/stack-status.ts b/packages/@aws-cdk/cdk-deploy/lib/api/util/cloudformation/stack-status.ts similarity index 100% rename from packages/aws-cdk/lib/api/util/cloudformation/stack-status.ts rename to packages/@aws-cdk/cdk-deploy/lib/api/util/cloudformation/stack-status.ts diff --git a/packages/aws-cdk/lib/archive.ts b/packages/@aws-cdk/cdk-deploy/lib/archive.ts similarity index 100% rename from packages/aws-cdk/lib/archive.ts rename to packages/@aws-cdk/cdk-deploy/lib/archive.ts diff --git a/packages/aws-cdk/lib/assets.ts b/packages/@aws-cdk/cdk-deploy/lib/assets.ts similarity index 97% rename from packages/aws-cdk/lib/assets.ts rename to packages/@aws-cdk/cdk-deploy/lib/assets.ts index 5ea3de78d726e..bfbe27ddf88d3 100644 --- a/packages/aws-cdk/lib/assets.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/assets.ts @@ -1,14 +1,14 @@ // tslint:disable-next-line:max-line-length +import { debug, success } from '@aws-cdk/cdk-common'; import { ASSET_METADATA, ASSET_PREFIX_SEPARATOR, AssetMetadataEntry, FileAssetMetadataEntry, StackMetadata, SynthesizedStack } from '@aws-cdk/cx-api'; import { CloudFormation } from 'aws-sdk'; import colors = require('colors'); import fs = require('fs-extra'); import os = require('os'); import path = require('path'); +import { zipDirectory } from '../../../aws-cdk/lib/archive'; import { ToolkitInfo } from './api/toolkit-info'; -import { zipDirectory } from './archive'; import { prepareContainerAsset } from './docker'; -import { debug, success } from './logging'; // tslint:disable-next-line:max-line-length export async function prepareAssets(stack: SynthesizedStack, toolkitInfo?: ToolkitInfo, ci?: boolean, reuse?: string[]): Promise { diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts similarity index 96% rename from packages/aws-cdk/lib/cdk-toolkit.ts rename to packages/@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts index 1aad96c3b8b81..c52b1469f64af 100644 --- a/packages/aws-cdk/lib/cdk-toolkit.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts @@ -1,11 +1,11 @@ import colors = require('colors/safe'); import fs = require('fs-extra'); import { format, promisify } from 'util'; -import { AppStacks, ExtendedStackSelection } from "./api/cxapp/stacks"; +// import { AppStacks, ExtendedStackSelection } from "../../../aws-cdk/lib/api/cxapp/stacks"; +import { data, error, highlight, print, success } from '../../../aws-cdk/lib/logging'; +import { deserializeStructure } from '../../../aws-cdk/lib/serialize'; import { IDeploymentTarget } from './api/deployment-target'; import { printSecurityDiff, printStackDiff, RequireApproval } from './diff'; -import { data, error, highlight, print, success } from './logging'; -import { deserializeStructure } from './serialize'; // tslint:disable-next-line:no-var-requires const promptly = require('promptly'); diff --git a/packages/aws-cdk/lib/diff.ts b/packages/@aws-cdk/cdk-deploy/lib/diff.ts similarity index 98% rename from packages/aws-cdk/lib/diff.ts rename to packages/@aws-cdk/cdk-deploy/lib/diff.ts index 5b5532070ced5..c614fb2ac5b51 100644 --- a/packages/aws-cdk/lib/diff.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/diff.ts @@ -1,8 +1,8 @@ +import { print, warning } from '@aws-cdk/cdk-common'; import cfnDiff = require('@aws-cdk/cloudformation-diff'); import { FormatStream } from '@aws-cdk/cloudformation-diff'; import cxapi = require('@aws-cdk/cx-api'); import colors = require('colors/safe'); -import { print, warning } from './logging'; /** * Pretty-prints the differences between two template states to the console. diff --git a/packages/aws-cdk/lib/docker.ts b/packages/@aws-cdk/cdk-deploy/lib/docker.ts similarity index 98% rename from packages/aws-cdk/lib/docker.ts rename to packages/@aws-cdk/cdk-deploy/lib/docker.ts index 524eee7df69d3..641999786fe8d 100644 --- a/packages/aws-cdk/lib/docker.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/docker.ts @@ -1,10 +1,8 @@ +import { debug, PleaseHold, print, shell } from '@aws-cdk/cdk-common'; import { ContainerImageAssetMetadataEntry } from '@aws-cdk/cx-api'; import { CloudFormation } from 'aws-sdk'; import crypto = require('crypto'); import { ToolkitInfo } from './api/toolkit-info'; -import { debug, print } from './logging'; -import { shell } from './os'; -import { PleaseHold } from './util/please-hold'; /** * Build and upload a Docker image diff --git a/packages/@aws-cdk/cdk-deploy/package-lock.json b/packages/@aws-cdk/cdk-deploy/package-lock.json new file mode 100644 index 0000000000000..ebc2cf1c7c6eb --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/package-lock.json @@ -0,0 +1,2140 @@ +{ + "name": "@aws-cdk/cdk-deploy", + "version": "0.28.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/runtime": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.3.tgz", + "integrity": "sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "@sinonjs/commons": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", + "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", + "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "@sinonjs/samsam": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.1.tgz", + "integrity": "sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash": "^4.17.11" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "@types/archiver": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-2.1.3.tgz", + "integrity": "sha512-x37dj6VvV8jArjvqvZP+qz5+24qOwgFesLMvn98uNz8qebjCg+uteqquRf9mqaxxhcM7S1vPl4YFhBs2/abcFQ==", + "dev": true, + "requires": { + "@types/glob": "*" + } + }, + "@types/caseless": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "dev": true + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/form-data": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", + "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/fs-extra": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.5.tgz", + "integrity": "sha512-w7iqhDH9mN8eLClQOYTkhdYUOSpp25eXxfc6VbFOGtzxW34JcvctH2bKjj4jD4++z4R5iO5D+pg48W2e03I65A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/mockery": { + "version": "1.4.29", + "resolved": "https://registry.npmjs.org/@types/mockery/-/mockery-1.4.29.tgz", + "integrity": "sha1-m6It838H43gP/4Ux0aOOYz+UV6U=", + "dev": true + }, + "@types/node": { + "version": "8.10.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.45.tgz", + "integrity": "sha512-tGVTbA+i3qfXsLbq9rEq/hezaHY55QxQLeXQL2ejNgFAxxrgu8eMmYIOsRcl7hN1uTLVsKOOYacV/rcJM3sfgQ==" + }, + "@types/request": { + "version": "2.48.1", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.1.tgz", + "integrity": "sha512-ZgEZ1TiD+KGA9LiAAPPJL68Id2UWfeSO62ijSXZjFJArVV+2pKcsVHmrcu+1oiE3q6eDGiFiSolRc4JHoerBBg==", + "dev": true, + "requires": { + "@types/caseless": "*", + "@types/form-data": "*", + "@types/node": "*", + "@types/tough-cookie": "*" + } + }, + "@types/semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==", + "dev": true + }, + "@types/sinon": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.0.11.tgz", + "integrity": "sha512-6ee09Ugx6GyEr0opUIakmxIWFNmqYPjkqa3/BuxCBokA0klsOLPgMD5K4q40lH7/yZVuJVzOfQpd7pipwjngkQ==", + "dev": true + }, + "@types/table": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/table/-/table-4.0.5.tgz", + "integrity": "sha512-M/e/pWOWjm8X/fu8I9eOhc/ww1RsUG1yOr/G3vgdBwVFmfnMiqCRIiEKpDZdscNNCzr/kAAzuTNqGUH1uAk/qQ==", + "dev": true + }, + "@types/tough-cookie": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz", + "integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg==", + "dev": true + }, + "@types/uuid": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz", + "integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/yaml": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.0.2.tgz", + "integrity": "sha512-rS1VJFjyGKNHk8H97COnPIK+oeLnc0J9G0ES63o/Ky+WlJCeaFGiGCTGhV/GEVKua7ZWIV1JIDopYUwrfvTo7A==", + "dev": true + }, + "@types/yargs": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-8.0.3.tgz", + "integrity": "sha512-YdxO7zGQf2qJeMgR0fNO8QTlj88L2zCP5GOddovoTyetgLiNDOUXcWzhWKb4EdZZlOjLQUA0JM8lW7VcKQL+9w==", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "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": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "archiver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", + "requires": { + "archiver-utils": "^1.3.0", + "async": "^2.0.0", + "buffer-crc32": "^0.2.1", + "glob": "^7.0.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0", + "tar-stream": "^1.5.0", + "zip-stream": "^1.2.0" + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "requires": { + "glob": "^7.0.0", + "graceful-fs": "^4.1.0", + "lazystream": "^1.0.0", + "lodash": "^4.8.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "ast-types": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.12.3.tgz", + "integrity": "sha512-wJUcAfrdW+IgDoMGNz5MmcvahKgB7BwIbLupdKVVHxHNYt+HVR2k35swdYNv9aZpF8nvlkjbnkp2rrNwxGckZA==" + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "requires": { + "lodash": "^4.17.11" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sdk": { + "version": "2.438.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.438.0.tgz", + "integrity": "sha512-j+7zZYHekFFqoERSLDF1fDmC9awmZG2YJDoGuxBxwozi6Rg2GjyglwVehrNs3oC51UyrWhzWdn7jOVG6It5nmw==", + "requires": { + "buffer": "4.9.1", + "events": "1.1.1", + "ieee754": "1.1.8", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "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" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "requires": { + "buffer-crc32": "^0.2.1", + "crc32-stream": "^2.0.0", + "normalize-path": "^2.0.0", + "readable-stream": "^2.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "^5.1.0" + } + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "requires": { + "crc": "^3.4.4", + "readable-stream": "^2.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-uri-to-buffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.1.tgz", + "integrity": "sha512-OkVVLrerfAKZlW2ZZ3Ve2y65jgiWqBKsTfUIAFbn8nVbPcCZg6l6gikKlEYv0kXcmzqGm6mFq/Jf2vriuEkv8A==", + "requires": { + "@types/node": "^8.0.7" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", + "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", + "requires": { + "xregexp": "4.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "degenerator": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-1.0.4.tgz", + "integrity": "sha1-/PSQo37OJmRk2cxDGrmMWBnO0JU=", + "requires": { + "ast-types": "0.x.x", + "escodegen": "1.x.x", + "esprima": "3.x.x" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "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" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.8.2.tgz", + "integrity": "sha1-q6jZ4ZQ6iVrJaDemKjmz9V7NlKs=" + }, + "es6-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==" + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "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" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + } + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-uri": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-2.0.3.tgz", + "integrity": "sha512-x5j6Ks7FOgLD/GlvjKwgu7wdmMR55iuRHhn8hj/+gA+eSbxQvZ+AEomq+3MgVEZj1vpi738QahGbCCSIDtXtkw==", + "requires": { + "data-uri-to-buffer": "2", + "debug": "4", + "extend": "~3.0.2", + "file-uri-to-path": "1", + "ftp": "~0.3.10", + "readable-stream": "3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "readable-stream": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", + "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "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", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "heap": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.6.tgz", + "integrity": "sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw=" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "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" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "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", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lolex": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-3.1.0.tgz", + "integrity": "sha512-zFo5MgCJ0rZ7gQg69S4pqBsLURbFw11X68C18OcJjJQbqaXm2NoTrGl1IMM3TIz0/BnN1tIs2tzmmqvCsOMMjw==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "requires": { + "mime-db": "~1.38.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mockery": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mockery/-/mockery-2.1.0.tgz", + "integrity": "sha512-9VkOmxKlWXoDO/h1jDZaS4lH33aWfRiJiNT/tKj+8OGzrcFDLo8d0syGdbsc3Bc4GvRXPb+NMMvojotmuGJTvA==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "netmask": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-1.0.6.tgz", + "integrity": "sha1-ICl+idhvb2QA8lDZ9Pa0wZRfzTU=" + }, + "nise": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.10.tgz", + "integrity": "sha512-sa0RRbj53dovjc7wombHmVli9ZihXbXCQ2uH3TNm03DyvOSIQbxg+pbqDKrk2oxMK1rtLGVlKxcB9rrc6X5YjA==", + "dev": true, + "requires": { + "@sinonjs/formatio": "^3.1.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^2.3.2", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "pac-proxy-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-3.0.0.tgz", + "integrity": "sha512-AOUX9jES/EkQX2zRz0AW7lSx9jD//hQS8wFXBvcnd/J2Py9KaMJMqV/LPqJssj1tgGufotb2mmopGPR15ODv1Q==", + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "get-uri": "^2.0.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "pac-resolver": "^3.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "^4.0.1" + } + }, + "pac-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-3.0.0.tgz", + "integrity": "sha512-tcc38bsjuE3XZ5+4vP96OfhOugrX+JcnpUbhfuc4LuXBLQhoTthOstZeoQJBDnQUDYzYmdImKsbz0xSl1/9qeA==", + "requires": { + "co": "^4.6.0", + "degenerator": "^1.0.4", + "ip": "^1.1.5", + "netmask": "^1.0.6", + "thunkify": "^2.1.2" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "promptly": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-0.2.1.tgz", + "integrity": "sha1-ZETnyk29mJnn7rXsOSKCfr3CKzs=", + "requires": { + "read": "~1.0.4" + } + }, + "proxy-agent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-3.1.0.tgz", + "integrity": "sha512-IkbZL4ClW3wwBL/ABFD2zJ8iP84CY0uKMvBPk/OceQe/cEjrxzN1pMHsLwhbzUoRhG9QbSxYC+Z7LBkTiBNvrA==", + "requires": { + "agent-base": "^4.2.0", + "debug": "^3.1.0", + "http-proxy-agent": "^2.1.0", + "https-proxy-agent": "^2.2.1", + "lru-cache": "^4.1.2", + "pac-proxy-agent": "^3.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^4.0.1" + } + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "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", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "sinon": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.3.1.tgz", + "integrity": "sha512-eQKMaeWovtOtYe2xThEvaHmmxf870Di+bim10c3ZPrL5bZhLGtu8cz+rOBTFz0CwBV4Q/7dYwZiqZbGVLZ+vjQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.4.0", + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/samsam": "^3.3.1", + "diff": "^3.5.0", + "lolex": "^3.1.0", + "nise": "^1.4.10", + "supports-color": "^5.5.0" + } + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "smart-buffer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", + "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==" + }, + "socks": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz", + "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==", + "requires": { + "ip": "^1.1.5", + "smart-buffer": "4.0.2" + } + }, + "socks-proxy-agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", + "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "requires": { + "agent-base": "~4.2.1", + "socks": "~2.3.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz", + "integrity": "sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", + "requires": { + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, + "thunkify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/thunkify/-/thunkify-2.1.2.tgz", + "integrity": "sha1-+qDp0jDFGsyVyhOjYawFyn4EVT0=" + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xregexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yaml": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.5.0.tgz", + "integrity": "sha512-nKxSWOa7vxAP2pikrGxbkZsG/garQseRiLn9mIDjzwoQsyVy7ZWIpLoARejnINGGLA4fttuzRFFNxxbsztdJgw==", + "requires": { + "@babel/runtime": "^7.4.3" + } + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "requires": { + "archiver-utils": "^1.3.0", + "compress-commons": "^1.2.0", + "lodash": "^4.8.0", + "readable-stream": "^2.0.0" + } + } + } +} diff --git a/packages/@aws-cdk/cdk-deploy/package.json b/packages/@aws-cdk/cdk-deploy/package.json new file mode 100644 index 0000000000000..3daf6de81dfee --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/package.json @@ -0,0 +1,82 @@ +{ + "name": "@aws-cdk/cdk-deploy", + "description": "Command-line utility for deploying CDK applications", + "version": "0.28.0", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "bin": { + "cdk-deploy": "bin/cdk-deploy" + }, + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "pkglint": "pkglint -f", + "test": "cdk-test", + "package": "cdk-package" + }, + "nyc": { + "statements": 8, + "lines": 8, + "branches": 3 + }, + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@types/archiver": "^2.1.2", + "@types/fs-extra": "^5.0.4", + "@types/minimatch": "^3.0.3", + "@types/mockery": "^1.4.29", + "@types/request": "^2.47.1", + "@types/semver": "^5.5.0", + "@types/sinon": "^7.0.10", + "@types/table": "^4.0.5", + "@types/uuid": "^3.4.3", + "@types/yaml": "^1.0.0", + "@types/yargs": "^8.0.3", + "cdk-build-tools": "^0.28.0", + "mockery": "^2.1.0", + "pkglint": "^0.28.0", + "sinon": "^7.2.7" + }, + "dependencies": { + "@aws-cdk/applet-js": "^0.28.0", + "@aws-cdk/cdk-common": "^0.28.0", + "@aws-cdk/cloudformation-diff": "^0.28.0", + "@aws-cdk/cx-api": "^0.28.0", + "@aws-cdk/region-info": "^0.28.0", + "archiver": "^2.1.1", + "aws-sdk": "^2.259.1", + "camelcase": "^5.0.0", + "colors": "^1.2.1", + "decamelize": "^2.0.0", + "fs-extra": "^7.0.0", + "json-diff": "^0.3.1", + "minimatch": ">=3.0", + "promptly": "^0.2.0", + "proxy-agent": "^3.0.1", + "request": "^2.83.0", + "semver": "^5.5.0", + "source-map-support": "^0.5.6", + "table": "^5.2.1", + "yaml": "^1.1.0", + "yargs": "^9.0.1" + }, + "repository": { + "url": "https://github.com/awslabs/aws-cdk.git", + "type": "git", + "directory": "packages/@aws-cdk/cdk-deploy" + }, + "keywords": [ + "aws", + "cdk" + ], + "homepage": "https://github.com/awslabs/aws-cdk", + "engines": { + "node": ">= 8.10.0" + } +} diff --git a/packages/@aws-cdk/cdk-deploy/tsconfig.json b/packages/@aws-cdk/cdk-deploy/tsconfig.json new file mode 100644 index 0000000000000..2255294ca5d31 --- /dev/null +++ b/packages/@aws-cdk/cdk-deploy/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target":"ES2018", + "module": "commonjs", + "lib": ["es2016", "es2017.object", "es2017.string"], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization":false + }, + "include": [ + "**/*.ts" + ] +} + diff --git a/packages/aws-cdk/lib/api/aws-auth/credentials.ts b/packages/aws-cdk/lib/api/aws-auth/credentials.ts deleted file mode 100644 index e151f231a4a18..0000000000000 --- a/packages/aws-cdk/lib/api/aws-auth/credentials.ts +++ /dev/null @@ -1,29 +0,0 @@ -import aws = require('aws-sdk'); - -export enum Mode { - ForReading, - ForWriting -} - -export interface CredentialProviderSource { - name: string; - - /** - * Whether the credential provider is even online - * - * Guaranteed to be called before any of the other functions are called. - */ - isAvailable(): Promise; - - /** - * Whether the credential provider can provide credentials for the given account. - */ - canProvideCredentials(accountId: string): Promise; - - /** - * Construct a credential provider for the given account and the given access mode - * - * Guaranteed to be called only if canProvideCredentails() returned true at some point. - */ - getProvider(accountId: string, mode: Mode): Promise; -} diff --git a/packages/aws-cdk/lib/api/cxapp/exec.ts b/packages/aws-cdk/lib/api/cxapp/exec.ts index 72d1412c367c6..dcc50965b53aa 100644 --- a/packages/aws-cdk/lib/api/cxapp/exec.ts +++ b/packages/aws-cdk/lib/api/cxapp/exec.ts @@ -1,12 +1,11 @@ +import { debug, SDK } from '@aws-cdk/cdk-common'; import cxapi = require('@aws-cdk/cx-api'); import childProcess = require('child_process'); import fs = require('fs-extra'); import os = require('os'); import path = require('path'); import semver = require('semver'); -import { debug } from '../../logging'; import { Configuration, PROJECT_CONFIG, USER_DEFAULTS } from '../../settings'; -import { SDK } from '../util/sdk'; /** Invokes the cloud executable and returns JSON output */ export async function execProgram(aws: SDK, config: Configuration): Promise { diff --git a/packages/aws-cdk/lib/api/cxapp/stacks.ts b/packages/aws-cdk/lib/api/cxapp/stacks.ts index 7d913155e2a70..f3a87afe7127c 100644 --- a/packages/aws-cdk/lib/api/cxapp/stacks.ts +++ b/packages/aws-cdk/lib/api/cxapp/stacks.ts @@ -1,14 +1,13 @@ +import { debug, error, print, SDK, warning } from '@aws-cdk/cdk-common'; +import cdkUtil = require('@aws-cdk/cdk-common/lib/util'); +import { topologicalSort } from '@aws-cdk/cdk-common/lib/util/toposort'; import cxapi = require('@aws-cdk/cx-api'); import regionInfo = require('@aws-cdk/region-info'); import colors = require('colors/safe'); import minimatch = require('minimatch'); import contextproviders = require('../../context-providers'); -import { debug, error, print, warning } from '../../logging'; import { Renames } from '../../renames'; import { Configuration } from '../../settings'; -import cdkUtil = require('../../util'); -import { SDK } from '../util/sdk'; -import { topologicalSort } from '../util/toposort'; type Synthesizer = (aws: SDK, config: Configuration) => Promise; diff --git a/packages/aws-cdk/lib/api/util/account-cache.ts b/packages/aws-cdk/lib/api/util/account-cache.ts deleted file mode 100644 index 42a7ce85ccecc..0000000000000 --- a/packages/aws-cdk/lib/api/util/account-cache.ts +++ /dev/null @@ -1,92 +0,0 @@ -import fs = require('fs-extra'); -import os = require('os'); -import path = require('path'); -import { debug } from '../../logging'; - -/** - * Disk cache which maps access key IDs to account IDs. - * Usage: - * cache.get(accessKey) => accountId | undefined - * cache.put(accessKey, accountId) - */ -export class AccountAccessKeyCache { - /** - * Max number of entries in the cache, after which the cache will be reset. - */ - public static readonly MAX_ENTRIES = 1000; - - private readonly cacheFile: string; - - /** - * @param filePath Path to the cache file - */ - constructor(filePath?: string) { - this.cacheFile = filePath || path.join(os.homedir(), '.cdk', 'cache', 'accounts.json'); - } - - /** - * Tries to fetch the account ID from cache. If it's not in the cache, invokes - * the resolver function which should retrieve the account ID and return it. - * Then, it will be stored into disk cache returned. - * - * Example: - * - * const accountId = cache.fetch(accessKey, async () => { - * return await fetchAccountIdFromSomewhere(accessKey); - * }); - * - * @param accessKeyId - * @param resolver - */ - public async fetch(accessKeyId: string, resolver: () => Promise) { - // try to get account ID based on this access key ID from disk. - const cached = await this.get(accessKeyId); - if (cached) { - debug(`Retrieved account ID ${cached} from disk cache`); - return cached; - } - - // if it's not in the cache, resolve and put in cache. - const accountId = await resolver(); - if (accountId) { - await this.put(accessKeyId, accountId); - } - - return accountId; - } - - /** Get the account ID from an access key or undefined if not in cache */ - public async get(accessKeyId: string): Promise { - const map = await this.loadMap(); - return map[accessKeyId]; - } - - /** Put a mapping betweenn access key and account ID */ - public async put(accessKeyId: string, accountId: string) { - let map = await this.loadMap(); - - // nuke cache if it's too big. - if (Object.keys(map).length >= AccountAccessKeyCache.MAX_ENTRIES) { - map = { }; - } - - map[accessKeyId] = accountId; - await this.saveMap(map); - } - - private async loadMap(): Promise<{ [accessKeyId: string]: string }> { - if (!(await fs.pathExists(this.cacheFile))) { - return { }; - } - - return await fs.readJson(this.cacheFile); - } - - private async saveMap(map: { [accessKeyId: string]: string }) { - if (!(await fs.pathExists(this.cacheFile))) { - await fs.mkdirs(path.dirname(this.cacheFile)); - } - - await fs.writeJson(this.cacheFile, map, { spaces: 2 }); - } -} diff --git a/packages/aws-cdk/lib/api/util/sdk.ts b/packages/aws-cdk/lib/api/util/sdk.ts deleted file mode 100644 index 59ce0adf02b7f..0000000000000 --- a/packages/aws-cdk/lib/api/util/sdk.ts +++ /dev/null @@ -1,437 +0,0 @@ -import { Environment} from '@aws-cdk/cx-api'; -import AWS = require('aws-sdk'); -import child_process = require('child_process'); -import fs = require('fs-extra'); -import os = require('os'); -import path = require('path'); -import util = require('util'); -import { debug } from '../../logging'; -import { PluginHost } from '../../plugin'; -import { CredentialProviderSource, Mode } from '../aws-auth/credentials'; -import { AccountAccessKeyCache } from './account-cache'; -import { SharedIniFile } from './sdk_ini_file'; - -export interface SDKOptions { - /** - * Profile name to use - * - * @default No profile - */ - profile?: string; - - /** - * Proxy address to use - * - * @default No proxy - */ - proxyAddress?: string; - - /** - * Whether we should try instance credentials - * - * True/false to force/disable. Default is to guess. - * - * @default Automatically determine. - */ - ec2creds?: boolean; -} - -/** - * Source for SDK client objects - * - * Credentials are first obtained from the SDK defaults (using environment variables and the - * ~/.aws/{config,credentials} files). - * - * If those don't suffice, a list of CredentialProviderSources is interrogated for access - * to the requested account. - */ -export class SDK { - private readonly defaultAwsAccount: DefaultAWSAccount; - private readonly credentialsCache: CredentialsCache; - private readonly profile?: string; - - /** - * Default retry options for SDK clients - * - * Biggest bottleneck is CloudFormation, with a 1tps call rate. We want to be - * a little more tenacious than the defaults, and with a little more breathing - * room between calls (defaults are {retries=3, base=100}). - * - * I've left this running in a tight loop for an hour and the throttle errors - * haven't escaped the retry mechanism. - */ - private readonly retryOptions = { maxRetries: 6, retryDelayOptions: { base: 300 }}; - - constructor(options: SDKOptions = {}) { - this.profile = options.profile; - - const defaultCredentialProvider = makeCLICompatibleCredentialProvider(options.profile, options.ec2creds); - - // Find the package.json from the main toolkit - const pkg = (require.main as any).require('../package.json'); - AWS.config.update({ - customUserAgent: `${pkg.name}/${pkg.version}` - }); - - // https://aws.amazon.com/blogs/developer/using-the-aws-sdk-for-javascript-from-behind-a-proxy/ - if (options.proxyAddress === undefined) { - options.proxyAddress = httpsProxyFromEnvironment(); - } - if (options.proxyAddress) { // Ignore empty string on purpose - debug('Using proxy server: %s', options.proxyAddress); - AWS.config.update({ - httpOptions: { agent: require('proxy-agent')(options.proxyAddress) } - }); - } - - this.defaultAwsAccount = new DefaultAWSAccount(defaultCredentialProvider, getCLICompatibleDefaultRegion(this.profile)); - this.credentialsCache = new CredentialsCache(this.defaultAwsAccount, defaultCredentialProvider); - } - - public async cloudFormation(environment: Environment, mode: Mode): Promise { - return new AWS.CloudFormation({ - ...this.retryOptions, - region: environment.region, - credentials: await this.credentialsCache.get(environment.account, mode) - }); - } - - public async ec2(awsAccountId: string | undefined, region: string | undefined, mode: Mode): Promise { - return new AWS.EC2({ - ...this.retryOptions, - region, - credentials: await this.credentialsCache.get(awsAccountId, mode) - }); - } - - public async ssm(awsAccountId: string | undefined, region: string | undefined, mode: Mode): Promise { - return new AWS.SSM({ - ...this.retryOptions, - region, - credentials: await this.credentialsCache.get(awsAccountId, mode) - }); - } - - public async s3(environment: Environment, mode: Mode): Promise { - return new AWS.S3({ - ...this.retryOptions, - region: environment.region, - credentials: await this.credentialsCache.get(environment.account, mode) - }); - } - - public async route53(awsAccountId: string | undefined, region: string | undefined, mode: Mode): Promise { - return new AWS.Route53({ - ...this.retryOptions, - region, - credentials: await this.credentialsCache.get(awsAccountId, mode), - }); - } - - public async ecr(environment: Environment, mode: Mode): Promise { - return new AWS.ECR({ - ...this.retryOptions, - region: environment.region, - credentials: await this.credentialsCache.get(environment.account, mode) - }); - } - - public async defaultRegion(): Promise { - return await getCLICompatibleDefaultRegion(this.profile); - } - - public defaultAccount(): Promise { - return this.defaultAwsAccount.get(); - } -} - -/** - * Cache for credential providers. - * - * Given an account and an operating mode (read or write) will return an - * appropriate credential provider for credentials for the given account. The - * credential provider will be cached so that multiple AWS clients for the same - * environment will not make multiple network calls to obtain credentials. - * - * Will use default credentials if they are for the right account; otherwise, - * all loaded credential provider plugins will be tried to obtain credentials - * for the given account. - */ -class CredentialsCache { - private readonly cache: {[key: string]: AWS.Credentials} = {}; - - public constructor( - private readonly defaultAwsAccount: DefaultAWSAccount, - private readonly defaultCredentialProvider: Promise) { - } - - public async get(awsAccountId: string | undefined, mode: Mode): Promise { - const key = `${awsAccountId}-${mode}`; - if (!(key in this.cache)) { - this.cache[key] = await this.getCredentials(awsAccountId, mode); - } - return this.cache[key]; - } - - private async getCredentials(awsAccountId: string | undefined, mode: Mode): Promise { - // If requested account is undefined or equal to default account, use default credentials provider. - // (Note that we ignore the mode in this case, if you preloaded credentials they better be correct!) - const defaultAccount = await this.defaultAwsAccount.get(); - if (!awsAccountId || awsAccountId === defaultAccount) { - debug(`Using default AWS SDK credentials for account ${awsAccountId}`); - - // CredentialProviderChain extends Credentials, but that is a lie. - // https://github.com/aws/aws-sdk-js/issues/2235 - // Call resolve() instead. - return (await this.defaultCredentialProvider).resolvePromise(); - } - - const triedSources: CredentialProviderSource[] = []; - // Otherwise, inspect the various credential sources we have - for (const source of PluginHost.instance.credentialProviderSources) { - if (!(await source.isAvailable())) { - debug('Credentials source %s is not available, ignoring it.', source.name); - continue; - } - triedSources.push(source); - if (!(await source.canProvideCredentials(awsAccountId))) { continue; } - debug(`Using ${source.name} credentials for account ${awsAccountId}`); - const providerOrCreds = await source.getProvider(awsAccountId, mode); - - // Backwards compatibility: if the plugin returns a ProviderChain, resolve that chain. - // Otherwise it must have returned credentials. - if ((providerOrCreds as any).resolvePromise) { - return await (providerOrCreds as any).resolvePromise(); - } - return providerOrCreds; - } - const sourceNames = ['default credentials'].concat(triedSources.map(s => s.name)).join(', '); - throw new Error(`Need to perform AWS calls for account ${awsAccountId}, but no credentials found. Tried: ${sourceNames}.`); - } -} - -/** - * Class to retrieve the account for default credentials and cache it. - * - * Uses the default credentials provider to obtain credentials (if available), - * and uses those credentials to call STS to request the current account ID. - * - * The credentials => accountId lookup is cached on disk, since it's - * guaranteed that igven access key will always remain for the same account. - */ -class DefaultAWSAccount { - private defaultAccountFetched = false; - private defaultAccountId?: string = undefined; - private readonly accountCache = new AccountAccessKeyCache(); - - constructor( - private readonly defaultCredentialsProvider: Promise, - private readonly region: Promise) { - } - - /** - * Return the default account - */ - public async get(): Promise { - if (!this.defaultAccountFetched) { - this.defaultAccountId = await this.lookupDefaultAccount(); - this.defaultAccountFetched = true; - } - return this.defaultAccountId; - } - - private async lookupDefaultAccount(): Promise { - try { - // There just is *NO* way to do AssumeRole credentials as long as AWS_SDK_LOAD_CONFIG is not set. The SDK - // crash if the file does not exist though. So set the environment variable if we can find that file. - await setConfigVariable(); - - debug('Resolving default credentials'); - const credentialProvider = await this.defaultCredentialsProvider; - const creds = await credentialProvider.resolvePromise(); - - const accessKeyId = creds.accessKeyId; - if (!accessKeyId) { - throw new Error('Unable to resolve AWS credentials (setup with "aws configure")'); - } - - const accountId = await this.accountCache.fetch(creds.accessKeyId, async () => { - // if we don't have one, resolve from STS and store in cache. - debug('Looking up default account ID from STS'); - const result = await new AWS.STS({ credentials: creds, region: await this.region }).getCallerIdentity().promise(); - const aid = result.Account; - if (!aid) { - debug('STS didn\'t return an account ID'); - return undefined; - } - debug('Default account ID:', aid); - return aid; - }); - - return accountId; - } catch (e) { - debug('Unable to determine the default AWS account (did you configure "aws configure"?):', e); - return undefined; - } - } -} - -/** - * Build an AWS CLI-compatible credential chain provider - * - * This is similar to the default credential provider chain created by the SDK - * except it also accepts the profile argument in the constructor (not just from - * the environment). - * - * To mimic the AWS CLI behavior: - * - * - we default to ~/.aws/credentials if environment variable for credentials - * file location is not given (SDK expects explicit environment variable with name). - * - AWS_DEFAULT_PROFILE is also inspected for profile name (not just AWS_PROFILE). - */ -async function makeCLICompatibleCredentialProvider(profile: string | undefined, ec2creds: boolean | undefined) { - profile = profile || process.env.AWS_PROFILE || process.env.AWS_DEFAULT_PROFILE || 'default'; - - // Need to construct filename ourselves, without appropriate environment variables - // no defaults used by JS SDK. - const filename = process.env.AWS_SHARED_CREDENTIALS_FILE || path.join(os.homedir(), '.aws', 'credentials'); - - const sources = [ - () => new AWS.EnvironmentCredentials('AWS'), - () => new AWS.EnvironmentCredentials('AMAZON'), - ]; - if (fs.pathExists(filename)) { - sources.push(() => new AWS.SharedIniFileCredentials({ profile, filename })); - } - - if (hasEcsCredentials()) { - sources.push(() => new AWS.ECSCredentials()); - } else { - // else if: don't get EC2 creds if we should have gotten ECS creds--ECS instances also - // run on EC2 boxes but the creds represent something different. Same behavior as - // upstream code. - - if (ec2creds === undefined) { ec2creds = await hasEc2Credentials(); } - - if (ec2creds) { - sources.push(() => new AWS.EC2MetadataCredentials()); - } - } - - return new AWS.CredentialProviderChain(sources); -} - -/** - * Return the default region in a CLI-compatible way - * - * Mostly copied from node_loader.js, but with the following differences: - * - * - Takes a runtime profile name to load the region from, not just based on environment - * variables at process start. - * - We have needed to create a local copy of the SharedIniFile class because the - * implementation in 'aws-sdk' is private (and the default use of it in the - * SDK does not allow us to specify a profile at runtime). - * - AWS_DEFAULT_PROFILE and AWS_DEFAULT_REGION are also used as environment - * variables to be used to determine the region. - */ -async function getCLICompatibleDefaultRegion(profile: string | undefined): Promise { - profile = profile || process.env.AWS_PROFILE || process.env.AWS_DEFAULT_PROFILE || 'default'; - - // Defaults inside constructor - const toCheck = [ - {filename: process.env.AWS_SHARED_CREDENTIALS_FILE }, - {isConfig: true, filename: process.env.AWS_CONFIG_FILE}, - ]; - - let region = process.env.AWS_REGION || process.env.AMAZON_REGION || - process.env.AWS_DEFAULT_REGION || process.env.AMAZON_DEFAULT_REGION; - - while (!region && toCheck.length > 0) { - const configFile = new SharedIniFile(toCheck.shift()); - const section = await configFile.getProfile(profile); - region = section && section.region; - } - - return region; -} - -/** - * Find and return the configured HTTPS proxy address - */ -function httpsProxyFromEnvironment(): string | undefined { - if (process.env.https_proxy) { - return process.env.https_proxy; - } - if (process.env.HTTPS_PROXY) { - return process.env.HTTPS_PROXY; - } - return undefined; -} - -/** - * Return whether it looks like we'll have ECS credentials available - */ -function hasEcsCredentials() { - return (AWS.ECSCredentials.prototype as any).isConfiguredForEcsCredentials(); -} - -/** - * Return whether we're on an EC2 instance - */ -async function hasEc2Credentials() { - debug("Determining whether we're on an EC2 instance."); - - let instance = false; - if (process.platform === 'win32') { - // https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/identify_ec2_instances.html - const result = await util.promisify(child_process.exec)('wmic path win32_computersystemproduct get uuid', { encoding: 'utf-8' }); - // output looks like - // UUID - // EC2AE145-D1DC-13B2-94ED-01234ABCDEF - const lines = result.stdout.toString().split('\n'); - instance = lines.some(x => matchesRegex(/^ec2/i, x)); - } else { - // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html - const files: Array<[string, RegExp]> = [ - // This recognizes the Xen hypervisor based instances (pre-5th gen) - ['/sys/hypervisor/uuid', /^ec2/i], - - // This recognizes the new Hypervisor (5th-gen instances and higher) - // Can't use the advertised file '/sys/devices/virtual/dmi/id/product_uuid' because it requires root to read. - // Instead, sys_vendor contains something like 'Amazon EC2'. - ['/sys/devices/virtual/dmi/id/sys_vendor', /ec2/i], - ]; - for (const [file, re] of files) { - if (matchesRegex(re, await readIfPossible(file))) { - instance = true; - break; - } - } - } - - debug(instance ? 'Looks like EC2 instance.' : 'Does not look like EC2 instance.'); - return instance; -} - -async function setConfigVariable() { - const homeDir = process.env.HOME || process.env.USERPROFILE - || (process.env.HOMEPATH ? ((process.env.HOMEDRIVE || 'C:/') + process.env.HOMEPATH) : null) || os.homedir(); - - if (await fs.pathExists(path.resolve(homeDir, '.aws', 'config'))) { - process.env.AWS_SDK_LOAD_CONFIG = '1'; - } -} - -async function readIfPossible(filename: string): Promise { - try { - if (!await fs.pathExists(filename)) { return undefined; } - return fs.readFile(filename, { encoding: 'utf-8' }); - } catch (e) { - debug(e); - return undefined; - } -} - -function matchesRegex(re: RegExp, s: string | undefined) { - return s !== undefined && re.exec(s) !== null; -} diff --git a/packages/aws-cdk/lib/api/util/sdk_ini_file.ts b/packages/aws-cdk/lib/api/util/sdk_ini_file.ts deleted file mode 100644 index 1e9f625061f0f..0000000000000 --- a/packages/aws-cdk/lib/api/util/sdk_ini_file.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * A reimplementation of JS AWS SDK's SharedIniFile class - * - * We need that class to parse the ~/.aws/config file to determine the correct - * region at runtime, but unfortunately it is private upstream. - */ - -import AWS = require('aws-sdk'); -import fs = require('fs-extra'); -import os = require('os'); -import path = require('path'); - -export interface SharedIniFileOptions { - isConfig?: boolean; - filename?: string; -} - -export class SharedIniFile { - private readonly isConfig: boolean; - private readonly filename: string; - private parsedContents?: {[key: string]: {[key: string]: string}}; - - constructor(options?: SharedIniFileOptions) { - options = options || {}; - this.isConfig = options.isConfig === true; - this.filename = options.filename || this.getDefaultFilepath(); - } - - public async getProfile(profile: string) { - await this.ensureFileLoaded(); - - const profileIndex = profile !== (AWS as any).util.defaultProfile && this.isConfig ? - 'profile ' + profile : profile; - - return this.parsedContents![profileIndex]; - } - - private getDefaultFilepath(): string { - return path.join( - os.homedir(), - '.aws', - this.isConfig ? 'config' : 'credentials' - ); - } - - private async ensureFileLoaded() { - if (this.parsedContents) { - return; - } - - if (!await fs.pathExists(this.filename)) { - this.parsedContents = {}; - return; - } - - const contents: string = (await fs.readFile(this.filename)).toString(); - this.parsedContents = (AWS as any).util.ini.parse(contents); - } -} diff --git a/packages/aws-cdk/lib/api/util/string-manipulation.ts b/packages/aws-cdk/lib/api/util/string-manipulation.ts deleted file mode 100644 index aa51679967ba3..0000000000000 --- a/packages/aws-cdk/lib/api/util/string-manipulation.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Pad 's' on the left with 'char' until it is n characters wide - */ -export function leftPad(s: string, n: number, char: string) { - const padding = Math.max(0, n - s.length); - return char.repeat(padding) + s; -} \ No newline at end of file diff --git a/packages/aws-cdk/lib/api/util/toposort.ts b/packages/aws-cdk/lib/api/util/toposort.ts deleted file mode 100644 index 97dd35ea8bb46..0000000000000 --- a/packages/aws-cdk/lib/api/util/toposort.ts +++ /dev/null @@ -1,44 +0,0 @@ -export type KeyFunc = (x: T) => string; -export type DepFunc = (x: T) => string[]; - -/** - * Return a topological sort of all elements of xs, according to the given dependency functions - * - * Dependencies outside the referenced set are ignored. - * - * Not a stable sort, but in order to keep the order as stable as possible, we'll sort by key - * among elements of equal precedence. - */ -export function topologicalSort(xs: Iterable, keyFn: KeyFunc, depFn: DepFunc): T[] { - const remaining = new Map>(); - for (const element of xs) { - const key = keyFn(element); - remaining.set(key, { key, element, dependencies: depFn(element) }); - } - - const ret = new Array(); - while (remaining.size > 0) { - // All elements with no more deps in the set can be ordered - const selectable = Array.from(remaining.values()).filter(e => e.dependencies.every(d => !remaining.has(d))); - - selectable.sort((a, b) => a.key < b.key ? -1 : b.key < a.key ? 1 : 0); - - for (const selected of selectable) { - ret.push(selected.element); - remaining.delete(selected.key); - } - - // If we didn't make any progress, we got stuck - if (selectable.length === 0) { - throw new Error(`Could not determine ordering between: ${Array.from(remaining.keys()).join(', ')}`); - } - } - - return ret; -} - -interface TopoElement { - key: string; - dependencies: string[]; - element: T; -} \ No newline at end of file diff --git a/packages/aws-cdk/lib/command-api.ts b/packages/aws-cdk/lib/command-api.ts index dff4faeb5200a..c5b963427a949 100644 --- a/packages/aws-cdk/lib/command-api.ts +++ b/packages/aws-cdk/lib/command-api.ts @@ -1,6 +1,6 @@ +import { SDK } from '@aws-cdk/cdk-common'; import yargs = require('yargs'); import { AppStacks } from './api/cxapp/stacks'; -import { SDK } from './api/util/sdk'; import { Configuration } from './settings'; /** diff --git a/packages/aws-cdk/lib/commands/context.ts b/packages/aws-cdk/lib/commands/context.ts index 4cdd2f3440dee..8159d4a7ff55d 100644 --- a/packages/aws-cdk/lib/commands/context.ts +++ b/packages/aws-cdk/lib/commands/context.ts @@ -1,9 +1,9 @@ +import { renderTable } from '@aws-cdk/cdk-common'; import colors = require('colors/safe'); import yargs = require('yargs'); import { CommandOptions } from '../command-api'; import { print } from '../logging'; import { Context, PROJECT_CONFIG } from '../settings'; -import { renderTable } from '../util'; export const command = 'context'; export const describe = 'Manage cached context values'; diff --git a/packages/aws-cdk/lib/context-providers/availability-zones.ts b/packages/aws-cdk/lib/context-providers/availability-zones.ts index f6f80c60150c3..9bec686acd872 100644 --- a/packages/aws-cdk/lib/context-providers/availability-zones.ts +++ b/packages/aws-cdk/lib/context-providers/availability-zones.ts @@ -1,5 +1,4 @@ -import { Mode, SDK } from '../api'; -import { debug } from '../logging'; +import { debug, Mode, SDK } from '@aws-cdk/cdk-common'; import { ContextProviderPlugin } from './provider'; /** diff --git a/packages/aws-cdk/lib/context-providers/hosted-zones.ts b/packages/aws-cdk/lib/context-providers/hosted-zones.ts index 28773aefbd3a6..a98d5b3e1e46c 100644 --- a/packages/aws-cdk/lib/context-providers/hosted-zones.ts +++ b/packages/aws-cdk/lib/context-providers/hosted-zones.ts @@ -1,6 +1,5 @@ +import { debug, Mode, SDK } from '@aws-cdk/cdk-common'; import cxapi = require('@aws-cdk/cx-api'); -import { Mode, SDK } from '../api'; -import { debug } from '../logging'; import { ContextProviderPlugin } from './provider'; export class HostedZoneContextProviderPlugin implements ContextProviderPlugin { diff --git a/packages/aws-cdk/lib/context-providers/index.ts b/packages/aws-cdk/lib/context-providers/index.ts index 898874be1778f..54b22fdd7a71c 100644 --- a/packages/aws-cdk/lib/context-providers/index.ts +++ b/packages/aws-cdk/lib/context-providers/index.ts @@ -1,6 +1,5 @@ +import { debug, SDK } from '@aws-cdk/cdk-common'; import cxapi = require('@aws-cdk/cx-api'); -import { SDK } from '../api/util/sdk'; -import { debug } from '../logging'; import { Context } from '../settings'; import { AZContextProviderPlugin } from './availability-zones'; import { HostedZoneContextProviderPlugin } from './hosted-zones'; diff --git a/packages/aws-cdk/lib/context-providers/ssm-parameters.ts b/packages/aws-cdk/lib/context-providers/ssm-parameters.ts index 96915c8cea2cd..fd4886ab06387 100644 --- a/packages/aws-cdk/lib/context-providers/ssm-parameters.ts +++ b/packages/aws-cdk/lib/context-providers/ssm-parameters.ts @@ -1,6 +1,5 @@ +import { debug, Mode, SDK } from '@aws-cdk/cdk-common'; import AWS = require('aws-sdk'); -import { Mode, SDK } from '../api'; -import { debug } from '../logging'; import { ContextProviderPlugin } from './provider'; /** diff --git a/packages/aws-cdk/lib/context-providers/vpcs.ts b/packages/aws-cdk/lib/context-providers/vpcs.ts index 7ed8c6955d4cf..87e4c47855b95 100644 --- a/packages/aws-cdk/lib/context-providers/vpcs.ts +++ b/packages/aws-cdk/lib/context-providers/vpcs.ts @@ -1,7 +1,6 @@ +import { debug, Mode, SDK } from '@aws-cdk/cdk-common'; import cxapi = require('@aws-cdk/cx-api'); import AWS = require('aws-sdk'); -import { Mode, SDK } from '../api'; -import { debug } from '../logging'; import { ContextProviderPlugin } from './provider'; export class VpcNetworkContextProviderPlugin implements ContextProviderPlugin { diff --git a/packages/aws-cdk/lib/index.ts b/packages/aws-cdk/lib/index.ts index 8985834248f6f..1110b6451f6a1 100644 --- a/packages/aws-cdk/lib/index.ts +++ b/packages/aws-cdk/lib/index.ts @@ -1,2 +1 @@ -export * from './api'; export * from './plugin'; diff --git a/packages/aws-cdk/lib/logging.ts b/packages/aws-cdk/lib/logging.ts deleted file mode 100644 index d9b6ef87a2900..0000000000000 --- a/packages/aws-cdk/lib/logging.ts +++ /dev/null @@ -1,54 +0,0 @@ -import colors = require('colors/safe'); -import util = require('util'); - -// tslint:disable:no-console the whole point of those methods is precisely to output to the console... - -export let isVerbose = false; - -export function setVerbose(enabled = true) { - isVerbose = enabled; -} - -export function error(fmt: string, ...args: any[]) { - console.error(colors.red(util.format(fmt, ...args))); -} - -export function debug(fmt: string, ...args: any[]) { - if (isVerbose) { - console.error(colors.gray(util.format(fmt, ...args))); - } -} - -export function highlight(fmt: string, ...args: any[]) { - console.error(colors.bold(colors.white(util.format(fmt, ...args)))); -} - -export function success(fmt: string, ...args: any[]) { - console.error(colors.green(util.format(fmt, ...args))); -} - -export function warning(fmt: string, ...args: any[]) { - console.error(colors.yellow(util.format(fmt, ...args))); -} - -export function print(fmt: string, ...args: any[]) { - console.error(colors.white(util.format(fmt, ...args))); -} - -export function data(fmt: string, ...args: any[]) { - console.log(util.format(fmt, ...args)); -} - -export type LoggerFunction = (fmt: string, ...args: any[]) => void; - -/** - * Create a logger output that features a constant prefix string. - * - * @param prefixString the prefix string to be appended before any log entry. - * @param fn the logger function to be used (typically one of the other functions in this module) - * - * @returns a new LoggerFunction. - */ -export function prefix(prefixString: string, fn: LoggerFunction): LoggerFunction { - return (fmt: string, ...args: any[]) => fn(`%s ${fmt}`, prefixString, ...args); -} diff --git a/packages/aws-cdk/lib/plugin.ts b/packages/aws-cdk/lib/plugin.ts deleted file mode 100644 index 87de94aa697ff..0000000000000 --- a/packages/aws-cdk/lib/plugin.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { green } from 'colors/safe'; - -import { CredentialProviderSource } from './api/aws-auth/credentials'; -import { error } from './logging'; - -/** - * The basic contract for plug-ins to adhere to:: - * - * import { Plugin, PluginHost } from 'aws-cdk'; - * import { CustomCredentialProviderSource } from './custom-credential-provider-source'; - * - * export default class FooCDKPlugIn implements PluginHost { - * public readonly version = '1'; - * - * public init(host: PluginHost) { - * host.registerCredentialProviderSource(new CustomCredentialProviderSource()); - * } - * } - */ -export interface Plugin { - /** - * The version of the plug-in interface used by the plug-in. This will be used by - * the plug-in host to handle version changes. - */ - version: '1'; - - /** - * When defined, this function is invoked right after the plug-in has been loaded, - * so that the plug-in is able to initialize itself. It may call methods of the - * ``PluginHost`` instance it receives to register new ``CredentialProviderSource`` - * instances. - */ - init?: (host: PluginHost) => void; -} - -/** - * A utility to manage plug-ins. - */ -export class PluginHost { - public static instance = new PluginHost(); - - /** - * Access the currently registered CredentialProviderSources. New sources can - * be registered using the +registerCredentialProviderSource+ method. - */ - public readonly credentialProviderSources = new Array(); - - constructor() { - if (PluginHost.instance && PluginHost.instance !== this) { - throw new Error('New instances of PluginHost must not be built. Use PluginHost.instance instead!'); - } - } - - /** - * Loads a plug-in into this PluginHost. - * - * @param moduleSpec the specification (path or name) of the plug-in module to be loaded. - */ - public load(moduleSpec: string) { - try { - // tslint:disable-next-line:no-var-requires - const plugin = require(moduleSpec); - if (!isPlugin(plugin)) { - error(`Module ${green(moduleSpec)} is not a valid plug-in, or has an unsupported version.`); - throw new Error(`Module ${moduleSpec} does not define a valid plug-in.`); - } - if (plugin.init) { plugin.init(PluginHost.instance); } - } catch (e) { - error(`Unable to load ${green(moduleSpec)}: ${e.stack}`); - throw new Error(`Unable to load plug-in: ${moduleSpec}`); - } - - function isPlugin(x: any): x is Plugin { - return x != null && x.version === '1'; - } - } - - /** - * Allows plug-ins to register new CredentialProviderSources. - * - * @param source a new CredentialProviderSource to register. - */ - public registerCredentialProviderSource(source: CredentialProviderSource) { - this.credentialProviderSources.push(source); - } -} diff --git a/packages/aws-cdk/lib/renames.ts b/packages/aws-cdk/lib/renames.ts index 7ef533e7b83cb..a55c13843b5a2 100644 --- a/packages/aws-cdk/lib/renames.ts +++ b/packages/aws-cdk/lib/renames.ts @@ -1,5 +1,5 @@ +import util = require('@aws-cdk/cdk-common/lib/util'); import cxapi = require('@aws-cdk/cx-api'); -import util = require('./util'); export type RenameTable = {[key: string]: string}; diff --git a/packages/aws-cdk/lib/serialize.ts b/packages/aws-cdk/lib/serialize.ts deleted file mode 100644 index 3219cb5a48836..0000000000000 --- a/packages/aws-cdk/lib/serialize.ts +++ /dev/null @@ -1,38 +0,0 @@ -import YAML = require('yaml'); - -/** - * Stringify to YAML - */ -export function toYAML(obj: any): string { - return YAML.stringify(obj, { schema: 'yaml-1.1' }); -} - -/** - * Parse YAML - */ -export function fromYAML(str: string): any { - return YAML.parse(str, { schema: 'yaml-1.1' }); -} - -/** - * Parse either YAML or JSON - */ -export function deserializeStructure(str: string) { - try { - return fromYAML(str); - } catch (e) { - // This shouldn't really ever happen I think, but it's the code we had so I'm leaving it. - return JSON.parse(str); - } -} - -/** - * Serialize to either YAML or JSON - */ -export function serializeStructure(object: any, json: boolean) { - if (json) { - return JSON.stringify(object, undefined, 2); - } else { - return toYAML(object); - } -} \ No newline at end of file diff --git a/packages/aws-cdk/lib/settings.ts b/packages/aws-cdk/lib/settings.ts index 5f984f6e43fa7..ce3e6138de216 100644 --- a/packages/aws-cdk/lib/settings.ts +++ b/packages/aws-cdk/lib/settings.ts @@ -1,9 +1,8 @@ +import { debug, deepClone, deepGet, deepMerge, deepSet, warning } from '@aws-cdk/cdk-common'; import fs = require('fs-extra'); import os = require('os'); import fs_path = require('path'); import yargs = require('yargs'); -import { debug, warning } from './logging'; -import util = require('./util'); export type SettingsMap = {[key: string]: any}; @@ -255,7 +254,7 @@ export class Settings { } public merge(other: Settings): Settings { - return new Settings(util.deepMerge(this.settings, other.settings)); + return new Settings(deepMerge(this.settings, other.settings)); } public subSettings(keyPrefix: string[]) { @@ -278,7 +277,7 @@ export class Settings { } public get(path: string[]): any { - return util.deepClone(util.deepGet(this.settings, path)); + return deepClone(deepGet(this.settings, path)); } public set(path: string[], value: any): Settings { @@ -289,7 +288,7 @@ export class Settings { // deepSet can't handle this case this.settings = value; } else { - util.deepSet(this.settings, path, value); + deepSet(this.settings, path, value); } return this; } diff --git a/packages/aws-cdk/lib/util/arrays.ts b/packages/aws-cdk/lib/util/arrays.ts deleted file mode 100644 index 516466cd11254..0000000000000 --- a/packages/aws-cdk/lib/util/arrays.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Map a function over an array and concatenate the results - */ -export function flatMap(xs: T[], fn: ((x: T, i: number) => U[])): U[] { - return flatten(xs.map(fn)); -} - -/** - * Flatten a list of lists into a list of elements - */ -export function flatten(xs: T[][]): T[] { - return Array.prototype.concat.apply([], xs); -} - -/** - * Partition a collection by removing and returning all elements that match a predicate - * - * Note: the input collection is modified in-place! - */ -export function partition(collection: T[], pred: (x: T) => boolean): T[] { - const ret: T[] = []; - let i = 0; - while (i < collection.length) { - if (pred(collection[i])) { - ret.push(collection.splice(i, 1)[0]); - } else { - i++; - } - } - return ret; -} diff --git a/packages/aws-cdk/lib/util/index.ts b/packages/aws-cdk/lib/util/index.ts deleted file mode 100644 index a9a8af258b0f2..0000000000000 --- a/packages/aws-cdk/lib/util/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './arrays'; -export * from './objects'; -export * from './types'; -export * from './tables'; diff --git a/packages/aws-cdk/lib/util/objects.ts b/packages/aws-cdk/lib/util/objects.ts deleted file mode 100644 index 7fb660525687c..0000000000000 --- a/packages/aws-cdk/lib/util/objects.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { isArray, isObject, Obj } from './types'; - -/** - * Return a new object by adding missing keys into another object - */ -export function applyDefaults(hash: any, defaults: any) { - const result: any = { }; - - Object.keys(hash).forEach(k => result[k] = hash[k]); - - Object.keys(defaults) - .filter(k => !(k in result)) - .forEach(k => result[k] = defaults[k]); - - return result; -} - -/** - * Return whether the given parameter is an empty object or empty list. - */ -export function isEmpty(x: any) { - if (x == null) { return false; } - if (isArray(x)) { return x.length === 0; } - return Object.keys(x).length === 0; -} - -/** - * Deep clone a tree of objects, lists or scalars - * - * Does not support cycles. - */ -export function deepClone(x: any): any { - if (typeof x === 'undefined') { return undefined; } - if (x === null) { return null; } - if (isArray(x)) { return x.map(deepClone); } - if (isObject(x)) { return makeObject(mapObject(x, (k, v) => [k, deepClone(v)] as [string, any])); } - return x; -} - -/** - * Map over an object, treating it as a dictionary - */ -export function mapObject(x: Obj, fn: (key: string, value: T) => U): U[] { - const ret: U[] = []; - Object.keys(x).forEach(key => { - ret.push(fn(key, x[key])); - }); - return ret; -} - -/** - * Construct an object from a list of (k, v) pairs - */ -export function makeObject(pairs: Array<[string, T]>): Obj { - const ret: Obj = {}; - for (const pair of pairs) { - ret[pair[0]] = pair[1]; - } - return ret; -} - -/** - * Deep get a value from a tree of nested objects - * - * Returns undefined if any part of the path was unset or - * not an object. - */ -export function deepGet(x: any, path: string[]): any { - path = path.slice(); - - while (path.length > 0 && isObject(x)) { - const key = path.shift()!; - x = x[key]; - } - return path.length === 0 ? x : undefined; -} - -/** - * Deep set a value in a tree of nested objects - * - * Throws an error if any part of the path is not an object. - */ -export function deepSet(x: any, path: string[], value: any) { - path = path.slice(); - - if (path.length === 0) { - throw new Error('Path may not be empty'); - } - - while (path.length > 1 && isObject(x)) { - const key = path.shift()!; - if (!(key in x)) { x[key] = {}; } - x = x[key]; - } - - if (!isObject(x)) { - throw new Error(`Expected an object, got '${x}'`); - } - - if (value !== undefined) { - x[path[0]] = value; - } else { - delete x[path[0]]; - } -} - -/** - * Recursively merge objects together - * - * The leftmost object is mutated and returned. Arrays are not merged - * but overwritten just like scalars. - * - * If an object is merged into a non-object, the non-object is lost. - */ -export function deepMerge(...objects: Array | undefined>) { - function mergeOne(target: Obj, source: Obj) { - for (const key of Object.keys(source)) { - const value = source[key]; - - if (isObject(value)) { - if (!isObject(target[key])) { target[key] = {}; } // Overwrite on purpose - mergeOne(target[key], value); - } else if (typeof value !== 'undefined') { - target[key] = value; - } - } - } - - const others = objects.filter(x => x != null) as Array>; - - if (others.length === 0) { return {}; } - const into = others.splice(0, 1)[0]; - - others.forEach(other => mergeOne(into, other)); - return into; -} diff --git a/packages/aws-cdk/lib/util/please-hold.ts b/packages/aws-cdk/lib/util/please-hold.ts deleted file mode 100644 index cb6eff963296b..0000000000000 --- a/packages/aws-cdk/lib/util/please-hold.ts +++ /dev/null @@ -1,26 +0,0 @@ -import colors = require('colors/safe'); -import { print } from "../logging"; - -/** - * Print a message to the logger in case the operation takes a long time - */ -export class PleaseHold { - private handle?: NodeJS.Timer; - - constructor(private readonly message: string, private readonly timeoutSec = 10) { - } - - public start() { - this.handle = setTimeout(this.printMessage.bind(this), this.timeoutSec * 1000); - } - - public stop() { - if (this.handle) { - clearTimeout(this.handle); - } - } - - private printMessage() { - print(colors.yellow(this.message)); - } -} diff --git a/packages/aws-cdk/lib/util/tables.ts b/packages/aws-cdk/lib/util/tables.ts deleted file mode 100644 index bfc059bef40fc..0000000000000 --- a/packages/aws-cdk/lib/util/tables.ts +++ /dev/null @@ -1,7 +0,0 @@ -import cfnDiff = require('@aws-cdk/cloudformation-diff'); - -export function renderTable(cells: string[][], columns?: number) { - // The cfnDiff module has logic for terminal-width aware table - // formatting (and nice colors), let's just reuse that. - return cfnDiff.formatTable(cells, columns); -} \ No newline at end of file diff --git a/packages/aws-cdk/lib/util/types.ts b/packages/aws-cdk/lib/util/types.ts deleted file mode 100644 index 8d18b6e53e360..0000000000000 --- a/packages/aws-cdk/lib/util/types.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Type of a map mapping strings to some arbitrary type - * - * Name is not ideal, but: - * - * - Cannot call it Object, that already means something. - * - Cannot call it Dict or Dictionary, since in other languages - * those also allow specifying the key type. - */ -export type Obj = {[key: string]: T}; - -/** - * Return whether the given value is an object - * - * Even though arrays technically are objects, we usually want to treat them differently, - * so we return false in those cases. - */ -export function isObject(x: any): x is Obj { - return x !== null && typeof x === 'object' && !isArray(x); -} - -/** - * Return whether the given value is an array - */ -export const isArray = Array.isArray; - -/** - * Return the value of the first argument if it's not undefined, otherwise the default - */ -export function ifDefined(x: T | undefined, def: T): T { - return typeof x !== 'undefined' ? x : def; -} diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index b070ab282e2b2..600ce6cc24775 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -50,6 +50,7 @@ }, "dependencies": { "@aws-cdk/applet-js": "^0.28.0", + "@aws-cdk/cdk-common": "^0.28.0", "@aws-cdk/cloudformation-diff": "^0.28.0", "@aws-cdk/cx-api": "^0.28.0", "@aws-cdk/region-info": "^0.28.0", diff --git a/packages/aws-cdk/tsconfig.json b/packages/aws-cdk/tsconfig.json index 0c02dab2c6a45..a945c2d9b858d 100644 --- a/packages/aws-cdk/tsconfig.json +++ b/packages/aws-cdk/tsconfig.json @@ -20,7 +20,7 @@ }, "include": [ "**/*.ts", - "**/*.d.ts" + "**/*.d.ts", "../@aws-cdk/cdk-deploy/lib/assets.ts", "../@aws-cdk/cdk-deploy/lib/archive.ts", "../@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts", "../@aws-cdk/cd, "../@aws-cdk/cdk-deploy/lib/diff.ts"k-deploy/lib/docker.ts", "../@aws-cdk/cdk-common/lib/logging.ts", "../@aws-cdk/cdk-common/lib/serialize.ts", "../@aws-cdk/cdk-common/lib/os.ts" ], "exclude": [ "lib/init-templates/**/*" From b04a821e80e0577224e1423ad0a5a9710a52cf8b Mon Sep 17 00:00:00 2001 From: Sam Goodwin Date: Tue, 16 Apr 2019 20:28:09 -0700 Subject: [PATCH 03/12] move tests to cdk-common --- .../cdk-common/test/test.account-cache.ts | 85 ++++++++++++++ .../cdk-common/test/test.applydefaults.ts | 14 +++ .../@aws-cdk/cdk-common/test/test.arrays.ts | 30 +++++ .../@aws-cdk/cdk-common/test/test.objects.ts | 50 ++++++++ .../@aws-cdk/cdk-common/test/util/mock-sdk.ts | 107 ++++++++++++++++++ 5 files changed, 286 insertions(+) create mode 100644 packages/@aws-cdk/cdk-common/test/test.account-cache.ts create mode 100644 packages/@aws-cdk/cdk-common/test/test.applydefaults.ts create mode 100644 packages/@aws-cdk/cdk-common/test/test.arrays.ts create mode 100644 packages/@aws-cdk/cdk-common/test/test.objects.ts create mode 100644 packages/@aws-cdk/cdk-common/test/util/mock-sdk.ts diff --git a/packages/@aws-cdk/cdk-common/test/test.account-cache.ts b/packages/@aws-cdk/cdk-common/test/test.account-cache.ts new file mode 100644 index 0000000000000..5c00872da3c60 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/test/test.account-cache.ts @@ -0,0 +1,85 @@ +import fs = require('fs-extra'); +import { ICallbackFunction, Test } from 'nodeunit'; +import path = require('path'); +import { AccountAccessKeyCache } from '../lib/account-cache'; + +export = { + async 'setUp'(cb: ICallbackFunction) { + const self = this as any; + const dir = await fs.mkdtemp('/tmp/account-cache-test'); + self.file = path.join(dir, 'cache.json'); + self.cache = new AccountAccessKeyCache(self.file); + return cb(); + }, + + async 'tearDown'(cb: ICallbackFunction) { + const self = this as any; + await fs.remove(path.dirname(self.file)); + cb(); + }, + + async 'get(k) when cache is empty'(test: Test) { + const self = this as any; + const cache: AccountAccessKeyCache = self.cache; + test.equal(await cache.get('foo'), undefined, 'get returns undefined'); + test.equal(await fs.pathExists(self.file), false, 'cache file is not created'); + test.done(); + }, + + async 'put(k,v) and then get(k)'(test: Test) { + const self = this as any; + const cache: AccountAccessKeyCache = self.cache; + + await cache.put('key', 'value'); + await cache.put('boo', 'bar'); + test.deepEqual(await cache.get('key'), 'value', '"key" is mapped to "value"'); + + // create another cache instance on the same file, should still work + const cache2 = new AccountAccessKeyCache(self.file); + test.deepEqual(await cache2.get('boo'), 'bar', '"boo" is mapped to "bar"'); + + // whitebox: read the file + test.deepEqual(await fs.readJson(self.file), { + key: 'value', + boo: 'bar' + }); + + test.done(); + }, + + async 'fetch(k, resolver) can be used to "atomically" get + resolve + put'(test: Test) { + const self = this as any; + const cache: AccountAccessKeyCache = self.cache; + + test.deepEqual(await cache.get('foo'), undefined, 'no value for "foo" yet'); + test.deepEqual(await cache.fetch('foo', async () => 'bar'), 'bar', 'resolved by fetch and returned'); + test.deepEqual(await cache.get('foo'), 'bar', 'stored in cache by fetch()'); + test.done(); + }, + + async 'cache is nuked if it exceeds 1000 entries'(test: Test) { + const self = this as any; + const cache: AccountAccessKeyCache = self.cache; + + for (let i = 0; i < AccountAccessKeyCache.MAX_ENTRIES; ++i) { + await cache.put(`key${i}`, `value${i}`); + } + + // verify all 1000 values are on disk + const otherCache = new AccountAccessKeyCache(self.file); + for (let i = 0; i < AccountAccessKeyCache.MAX_ENTRIES; ++i) { + test.equal(await otherCache.get(`key${i}`), `value${i}`); + } + + // add another value + await cache.put('nuke-me', 'genesis'); + + // now, we expect only `nuke-me` to exist on disk + test.equal(await otherCache.get('nuke-me'), 'genesis'); + for (let i = 0; i < AccountAccessKeyCache.MAX_ENTRIES; ++i) { + test.equal(await otherCache.get(`key${i}`), undefined); + } + + test.done(); + } +}; diff --git a/packages/@aws-cdk/cdk-common/test/test.applydefaults.ts b/packages/@aws-cdk/cdk-common/test/test.applydefaults.ts new file mode 100644 index 0000000000000..db4350346b133 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/test/test.applydefaults.ts @@ -0,0 +1,14 @@ +import { Test } from 'nodeunit'; +import { applyDefaults } from '../lib'; + +export = { + 'applyDefaults() works'(test: Test) { + const given = { a: 1 }; + const defaults = { a: 2, b: 2 }; + + const output = applyDefaults(given, defaults); + + test.deepEqual({ a: 1, b: 2}, output); + test.done(); + } +}; diff --git a/packages/@aws-cdk/cdk-common/test/test.arrays.ts b/packages/@aws-cdk/cdk-common/test/test.arrays.ts new file mode 100644 index 0000000000000..d9978a6cde9b8 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/test/test.arrays.ts @@ -0,0 +1,30 @@ +import { Test } from 'nodeunit'; +import { flatMap, flatten, partition } from '../lib'; + +export = { + 'flatten combines arrays'(test: Test) { + const output = flatten([ + ['a', 'b'], + [], + ['c'] + ]); + + test.deepEqual(output, ['a', 'b', 'c']); + test.done(); + }, + 'flatMap maps and combines'(test: Test) { + const input = ['A', 'B', 'C']; + const output = flatMap(input, x => [x.toLowerCase()]); + + test.deepEqual(output, ['a', 'b', 'c']); + test.done(); + }, + 'partition splits the collection in twain'(test: Test) { + const xs = [1, 2, 3, 4, 5]; + const evens = partition(xs, x => x % 2 === 0); + + test.deepEqual(evens, [2, 4]); + test.deepEqual(xs, [1, 3, 5]); + test.done(); + }, +}; diff --git a/packages/@aws-cdk/cdk-common/test/test.objects.ts b/packages/@aws-cdk/cdk-common/test/test.objects.ts new file mode 100644 index 0000000000000..6ca7479a03289 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/test/test.objects.ts @@ -0,0 +1,50 @@ +import { Test } from 'nodeunit'; +import { deepClone, deepGet, deepMerge, deepSet } from '../lib'; + +export = { + 'deepSet can set deeply'(test: Test) { + const obj = {}; + deepSet(obj, ['a', 'b'], 3); + test.deepEqual(obj, {a: {b: 3}}); + test.done(); + }, + 'deepGet can get deeply'(test: Test) { + const obj = {a: {b: 3}}; + test.equal(deepGet(obj, ['a', 'b']), 3); + test.done(); + }, + 'deepGet can return an array'(test: Test) { + const obj = {a: [1, 2, 3]}; + test.deepEqual(deepGet(obj, ['a']), [1, 2, 3]); + test.done(); + }, + 'changing deepClones copy leaves the original intact'(test: Test) { + const original = {a: [{b: 3}]}; + const copy = deepClone(original); + copy.a[0].c = 5; + + test.deepEqual(original, {a: [{b: 3}]}); + test.done(); + }, + 'deepMerge merges objects'(test: Test) { + const original = {a: {b: 3}}; + deepMerge(original, {a: {c: 4}}); + + test.deepEqual(original, {a: {b: 3, c: 4}}); + test.done(); + }, + 'deepMerge overwrites non-objects'(test: Test) { + const original = {a: []}; + deepMerge(original, {a: {b: 3}}); + + test.deepEqual(original, {a: {b: 3}}); + test.done(); + }, + 'deepMerge does not overwrite if rightmost is "undefined"'(test: Test) { + const original = {a: 1}; + deepMerge(original, {a: undefined}); + + test.deepEqual(original, {a: 1}); + test.done(); + } +}; diff --git a/packages/@aws-cdk/cdk-common/test/util/mock-sdk.ts b/packages/@aws-cdk/cdk-common/test/util/mock-sdk.ts new file mode 100644 index 0000000000000..127c3061487d5 --- /dev/null +++ b/packages/@aws-cdk/cdk-common/test/util/mock-sdk.ts @@ -0,0 +1,107 @@ +import AWS = require('aws-sdk'); +import sinon = require('sinon'); +import { SDK } from '../../lib'; + +/** + * An SDK that allows replacing (some of) the clients + * + * Its the responsibility of the consumer to replace all calls that + * actually will be called. + */ +export class MockSDK extends SDK { + private readonly sandbox: sinon.SinonSandbox; + constructor() { + super(); + this.sandbox = sinon.createSandbox(); + } + + /** + * Replace the CloudFormation client with the given object + */ + public stubCloudFormation(stubs: SyncHandlerSubsetOf) { + this.sandbox.stub(this, 'cloudFormation').returns(Promise.resolve(partialAwsService(stubs))); + } + + /** + * Replace the ECR client with the given object + */ + public stubEcr(stubs: SyncHandlerSubsetOf) { + this.sandbox.stub(this, 'ecr').returns(Promise.resolve(partialAwsService(stubs))); + } +} + +/** + * Wrap synchronous fake handlers so that they sort-of function like a real AWS client + * + * For example, turns an object like this: + * + * ```ts + * { + * someCall(opts: AWS.Service.SomeCallInput): AWS.Service.SomeCallOutput { + * return {...whatever...}; + * } + * } + * ``` + * + * Into an object that in the type system pretends to be an 'AWS.Service' + * class (even though it really isn't) and can be called like this: + * + * ```ts + * const service = await sdk.someService(...); + * const response = await service.someCall(...).promise(); + * ``` + * + * We only implement the narrow subset of the AWS SDK API that the CDK actually + * uses, and we cheat on the types to make TypeScript happy on the rest of the API. + * + * Most important feature of this class is that it will derive the input and output + * types of the handlers on the input object from the ACTUAL AWS Service class, + * so that you don't have to declare them. + */ +function partialAwsService(fns: SyncHandlerSubsetOf): S { + // Super unsafe in here because I don't know how to make TypeScript happy, + // but at least the outer types make sure everything that happens in here works out. + const ret: any = {}; + + for (const [key, handler] of Object.entries(fns)) { + ret[key] = (args: any) => new FakeAWSResponse((handler as any)(args)); + } + + return ret; +} + +// Because of the overloads an AWS handler type looks like this: +// +// { +// (params: INPUTSTRUCT, callback?: ((err: AWSError, data: {}) => void) | undefined): Request; +// (callback?: ((err: AWS.AWSError, data: {}) => void) | undefined): AWS.Request<...>; +// } +// +// Get the first overload and extract the input and output struct types +type AwsCallInputOutput = + T extends { + (args: infer INPUT, callback?: ((err: AWS.AWSError, data: any) => void) | undefined): AWS.Request; + (callback?: ((err: AWS.AWSError, data: {}) => void) | undefined): AWS.Request; + } ? [INPUT, OUTPUT] : never; + +// Determine the type of the mock handler from the type of the Input/Output type pair. +// Don't need to worry about the 'never', TypeScript will propagate it upwards making it +// impossible to specify the field that has 'never' anywhere in its type. +type MockHandlerType = (input: AI[0]) => AI[1]; + +// Any subset of the full type that synchronously returns the output structure is okay +type SyncHandlerSubsetOf = {[K in keyof S]?: MockHandlerType>}; + +/** + * Fake AWS response. + * + * We only ever 'await response.promise()' so that's the only thing we implement here. + */ +class FakeAWSResponse { + constructor(private readonly x: T) { + } + + public promise(): Promise { + return Promise.resolve(this.x); + } +} From 311b7cb37d70b011378c84a8107738864d59041e Mon Sep 17 00:00:00 2001 From: Sam Goodwin Date: Tue, 16 Apr 2019 20:48:56 -0700 Subject: [PATCH 04/12] Move tests into cdk-deploy --- packages/@aws-cdk/cdk-deploy/bin/cdk-deploy | 0 packages/@aws-cdk/cdk-deploy/lib/assets.ts | 2 +- .../@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts | 42 +++---- .../cdk-deploy}/test/api/test.deploy-stack.ts | 4 +- .../test/test-archive-follow/data/linked | 0 .../test/test-archive-follow/data/one.txt | 0 .../test/test-archive-follow/linked/two.txt | 0 .../cdk-deploy}/test/test-archive/file1.txt | 0 .../cdk-deploy}/test/test-archive/file2.txt | 0 .../test/test-archive/subdir/file3.txt | 0 .../cdk-deploy}/test/test.archive.ts | 0 .../cdk-deploy}/test/test.assets.ts | 2 +- .../cdk-deploy}/test/test.diff.ts | 15 +-- .../cdk-deploy}/test/test.docker.ts | 4 +- packages/aws-cdk/test/api/test.stacks.ts | 2 +- packages/aws-cdk/test/test.account-cache.ts | 85 -------------- packages/aws-cdk/test/util/mock-sdk.ts | 107 ------------------ .../aws-cdk/test/util/test.applydefaults.ts | 14 --- packages/aws-cdk/test/util/test.arrays.ts | 30 ----- packages/aws-cdk/test/util/test.objects.ts | 50 -------- packages/aws-cdk/tsconfig.json | 2 +- 21 files changed, 26 insertions(+), 333 deletions(-) mode change 100644 => 100755 packages/@aws-cdk/cdk-deploy/bin/cdk-deploy rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/api/test.deploy-stack.ts (88%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test-archive-follow/data/linked (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test-archive-follow/data/one.txt (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test-archive-follow/linked/two.txt (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test-archive/file1.txt (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test-archive/file2.txt (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test-archive/subdir/file3.txt (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test.archive.ts (100%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test.assets.ts (98%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test.diff.ts (82%) rename packages/{aws-cdk => @aws-cdk/cdk-deploy}/test/test.docker.ts (90%) delete mode 100644 packages/aws-cdk/test/test.account-cache.ts delete mode 100644 packages/aws-cdk/test/util/mock-sdk.ts delete mode 100644 packages/aws-cdk/test/util/test.applydefaults.ts delete mode 100644 packages/aws-cdk/test/util/test.arrays.ts delete mode 100644 packages/aws-cdk/test/util/test.objects.ts diff --git a/packages/@aws-cdk/cdk-deploy/bin/cdk-deploy b/packages/@aws-cdk/cdk-deploy/bin/cdk-deploy old mode 100644 new mode 100755 diff --git a/packages/@aws-cdk/cdk-deploy/lib/assets.ts b/packages/@aws-cdk/cdk-deploy/lib/assets.ts index bfbe27ddf88d3..3a009d8f3946f 100644 --- a/packages/@aws-cdk/cdk-deploy/lib/assets.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/assets.ts @@ -6,7 +6,7 @@ import colors = require('colors'); import fs = require('fs-extra'); import os = require('os'); import path = require('path'); -import { zipDirectory } from '../../../aws-cdk/lib/archive'; +import { zipDirectory } from '../lib/archive'; import { ToolkitInfo } from './api/toolkit-info'; import { prepareContainerAsset } from './docker'; diff --git a/packages/@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts b/packages/@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts index c52b1469f64af..286e59078d3ab 100644 --- a/packages/@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts @@ -1,9 +1,8 @@ +import { data, deserializeStructure, error, highlight, print, success } from '@aws-cdk/cdk-common'; +import cxapi = require('@aws-cdk/cx-api'); import colors = require('colors/safe'); import fs = require('fs-extra'); import { format, promisify } from 'util'; -// import { AppStacks, ExtendedStackSelection } from "../../../aws-cdk/lib/api/cxapp/stacks"; -import { data, error, highlight, print, success } from '../../../aws-cdk/lib/logging'; -import { deserializeStructure } from '../../../aws-cdk/lib/serialize'; import { IDeploymentTarget } from './api/deployment-target'; import { printSecurityDiff, printStackDiff, RequireApproval } from './diff'; @@ -15,7 +14,7 @@ export interface CdkToolkitProps { /** * The (stacks of the) CDK application */ - appStacks: AppStacks; + stacks: cxapi.SynthesizedStack[]; /** * The provisioning engine used to apply changes to the cloud @@ -24,25 +23,20 @@ export interface CdkToolkitProps { } /** - * Toolkit logic + * Diffs and deploys an application's stacks. * - * The toolkit takes CDK app models from the `appStacks` - * object and applies them to the `provisioner`. + * // TODO: rename? */ -export class CdkToolkit { - private readonly appStacks: AppStacks; +export class CDKToolkit { + private readonly stacks: cxapi.SynthesizedStack[]; private readonly provisioner: IDeploymentTarget; constructor(props: CdkToolkitProps) { - this.appStacks = props.appStacks; + this.stacks = props.stacks; this.provisioner = props.provisioner; } public async diff(options: DiffOptions): Promise { - const stacks = await this.appStacks.selectStacks( - options.stackNames, - options.exclusively ? ExtendedStackSelection.None : ExtendedStackSelection.Upstream); - const strict = !!options.strict; const contextLines = options.contextLines || 3; const stream = options.stream || process.stderr; @@ -50,7 +44,7 @@ export class CdkToolkit { let ret = 0; if (options.templatePath !== undefined) { // Compare single stack against fixed template - if (stacks.length !== 1) { + if (this.stacks.length !== 1) { throw new Error('Can only select one stack when comparing to fixed template. Use --excusively to avoid selecting multiple stacks.'); } @@ -58,10 +52,10 @@ export class CdkToolkit { throw new Error(`There is no file at ${options.templatePath}`); } const template = deserializeStructure(await fs.readFile(options.templatePath, { encoding: 'UTF-8' })); - ret = printStackDiff(template, stacks[0], strict, contextLines, options.stream); + ret = printStackDiff(template, this.stacks[0], strict, contextLines, options.stream); } else { // Compare N stacks against deployed templates - for (const stack of stacks) { + for (const stack of this.stacks) { stream.write(format('Stack %s\n', colors.bold(stack.name))); const currentTemplate = await this.provisioner.readCurrentTemplate(stack); if (printStackDiff(currentTemplate, stack, !!options.strict, options.contextLines || 3, stream) !== 0) { @@ -76,12 +70,8 @@ export class CdkToolkit { public async deploy(options: DeployOptions) { const requireApproval = options.requireApproval !== undefined ? options.requireApproval : RequireApproval.Broadening; - const stacks = await this.appStacks.selectStacks( - options.stackNames, - options.exclusively ? ExtendedStackSelection.None : ExtendedStackSelection.Upstream); - - for (const stack of stacks) { - if (stacks.length !== 1) { highlight(stack.name); } + for (const stack of this.stacks) { + if (this.stacks.length !== 1) { highlight(stack.name); } if (!stack.environment) { // tslint:disable-next-line:max-line-length throw new Error(`Stack ${stack.name} does not define an environment, and AWS credentials could not be obtained from standard locations or no region was configured.`); @@ -103,11 +93,7 @@ export class CdkToolkit { } } - if (stack.name !== stack.originalName) { - print('%s: deploying... (was %s)', colors.bold(stack.name), colors.bold(stack.originalName)); - } else { - print('%s: deploying...', colors.bold(stack.name)); - } + print('%s: deploying...', colors.bold(stack.name)); try { const result = await this.provisioner.deployStack({ diff --git a/packages/aws-cdk/test/api/test.deploy-stack.ts b/packages/@aws-cdk/cdk-deploy/test/api/test.deploy-stack.ts similarity index 88% rename from packages/aws-cdk/test/api/test.deploy-stack.ts rename to packages/@aws-cdk/cdk-deploy/test/api/test.deploy-stack.ts index ef5e4ed614e7a..5af58e9baf3e6 100644 --- a/packages/aws-cdk/test/api/test.deploy-stack.ts +++ b/packages/@aws-cdk/cdk-deploy/test/api/test.deploy-stack.ts @@ -1,6 +1,6 @@ +import { MockSDK } from '@aws-cdk/cdk-common/test/util/mock-sdk'; import { Test } from 'nodeunit'; -import { deployStack } from '../../lib'; -import { MockSDK } from '../util/mock-sdk'; +import { deployStack } from '../../lib/api/deploy-stack'; const FAKE_STACK = { name: 'withouterrors', diff --git a/packages/aws-cdk/test/test-archive-follow/data/linked b/packages/@aws-cdk/cdk-deploy/test/test-archive-follow/data/linked similarity index 100% rename from packages/aws-cdk/test/test-archive-follow/data/linked rename to packages/@aws-cdk/cdk-deploy/test/test-archive-follow/data/linked diff --git a/packages/aws-cdk/test/test-archive-follow/data/one.txt b/packages/@aws-cdk/cdk-deploy/test/test-archive-follow/data/one.txt similarity index 100% rename from packages/aws-cdk/test/test-archive-follow/data/one.txt rename to packages/@aws-cdk/cdk-deploy/test/test-archive-follow/data/one.txt diff --git a/packages/aws-cdk/test/test-archive-follow/linked/two.txt b/packages/@aws-cdk/cdk-deploy/test/test-archive-follow/linked/two.txt similarity index 100% rename from packages/aws-cdk/test/test-archive-follow/linked/two.txt rename to packages/@aws-cdk/cdk-deploy/test/test-archive-follow/linked/two.txt diff --git a/packages/aws-cdk/test/test-archive/file1.txt b/packages/@aws-cdk/cdk-deploy/test/test-archive/file1.txt similarity index 100% rename from packages/aws-cdk/test/test-archive/file1.txt rename to packages/@aws-cdk/cdk-deploy/test/test-archive/file1.txt diff --git a/packages/aws-cdk/test/test-archive/file2.txt b/packages/@aws-cdk/cdk-deploy/test/test-archive/file2.txt similarity index 100% rename from packages/aws-cdk/test/test-archive/file2.txt rename to packages/@aws-cdk/cdk-deploy/test/test-archive/file2.txt diff --git a/packages/aws-cdk/test/test-archive/subdir/file3.txt b/packages/@aws-cdk/cdk-deploy/test/test-archive/subdir/file3.txt similarity index 100% rename from packages/aws-cdk/test/test-archive/subdir/file3.txt rename to packages/@aws-cdk/cdk-deploy/test/test-archive/subdir/file3.txt diff --git a/packages/aws-cdk/test/test.archive.ts b/packages/@aws-cdk/cdk-deploy/test/test.archive.ts similarity index 100% rename from packages/aws-cdk/test/test.archive.ts rename to packages/@aws-cdk/cdk-deploy/test/test.archive.ts diff --git a/packages/aws-cdk/test/test.assets.ts b/packages/@aws-cdk/cdk-deploy/test/test.assets.ts similarity index 98% rename from packages/aws-cdk/test/test.assets.ts rename to packages/@aws-cdk/cdk-deploy/test/test.assets.ts index ff1ec67a82bb5..5ef74c567deda 100644 --- a/packages/aws-cdk/test/test.assets.ts +++ b/packages/@aws-cdk/cdk-deploy/test/test.assets.ts @@ -1,6 +1,6 @@ import { AssetMetadataEntry, ContainerImageAssetMetadataEntry, SynthesizedStack } from '@aws-cdk/cx-api'; import { Test } from 'nodeunit'; -import { Uploaded, UploadProps } from '../lib'; +import { Uploaded, UploadProps } from '../lib/api/toolkit-info'; import { prepareAssets } from '../lib/assets'; export = { diff --git a/packages/aws-cdk/test/test.diff.ts b/packages/@aws-cdk/cdk-deploy/test/test.diff.ts similarity index 82% rename from packages/aws-cdk/test/test.diff.ts rename to packages/@aws-cdk/cdk-deploy/test/test.diff.ts index 04a6818cd745c..f78edad2e7de7 100644 --- a/packages/aws-cdk/test/test.diff.ts +++ b/packages/@aws-cdk/cdk-deploy/test/test.diff.ts @@ -2,12 +2,9 @@ import cxapi = require('@aws-cdk/cx-api'); import { Test } from 'nodeunit'; import { Writable } from 'stream'; import { NodeStringDecoder, StringDecoder } from 'string_decoder'; -import { DeployStackOptions, DeployStackResult } from '../lib'; -import { AppStacks } from '../lib/api/cxapp/stacks'; +import { DeployStackOptions, DeployStackResult } from '../lib/api'; import { IDeploymentTarget, Template } from '../lib/api/deployment-target'; -import { SDK } from '../lib/api/util/sdk'; -import { CdkToolkit } from '../lib/cdk-toolkit'; -import { Configuration } from '../lib/settings'; +import { CDKToolkit } from '../lib/cdk-toolkit'; const FIXED_RESULT: cxapi.SynthesizeResponse = { version: '1', @@ -28,11 +25,7 @@ const FIXED_RESULT: cxapi.SynthesizeResponse = { ] }; -const appStacks = new AppStacks({ - configuration: new Configuration(), - aws: new SDK(), - synthesizer: async () => FIXED_RESULT, -}); +const stacks = FIXED_RESULT.stacks; export = { async 'diff can diff multiple stacks'(test: Test) { @@ -45,7 +38,7 @@ export = { return { noOp: true, outputs: {}, stackArn: ''}; } }; - const toolkit = new CdkToolkit({ appStacks, provisioner }); + const toolkit = new CDKToolkit({ stacks, provisioner }); const buffer = new StringWritable(); // WHEN diff --git a/packages/aws-cdk/test/test.docker.ts b/packages/@aws-cdk/cdk-deploy/test/test.docker.ts similarity index 90% rename from packages/aws-cdk/test/test.docker.ts rename to packages/@aws-cdk/cdk-deploy/test/test.docker.ts index efda5f52d728e..08249dbc66337 100644 --- a/packages/aws-cdk/test/test.docker.ts +++ b/packages/@aws-cdk/cdk-deploy/test/test.docker.ts @@ -1,8 +1,8 @@ +import { MockSDK } from '@aws-cdk/cdk-common/test/util/mock-sdk'; import cxapi = require('@aws-cdk/cx-api'); import { Test } from 'nodeunit'; -import { ToolkitInfo } from '../lib'; +import { ToolkitInfo } from '../lib/api/toolkit-info'; import { prepareContainerAsset } from '../lib/docker'; -import { MockSDK } from './util/mock-sdk'; export = { async 'creates repository with given name'(test: Test) { diff --git a/packages/aws-cdk/test/api/test.stacks.ts b/packages/aws-cdk/test/api/test.stacks.ts index 2322668d3ad67..b1bcf1bf70222 100644 --- a/packages/aws-cdk/test/api/test.stacks.ts +++ b/packages/aws-cdk/test/api/test.stacks.ts @@ -1,6 +1,6 @@ +import { SDK } from '@aws-cdk/cdk-common'; import cxapi = require('@aws-cdk/cx-api'); import { Test } from 'nodeunit'; -import { SDK } from '../../lib'; import { AppStacks, ExtendedStackSelection } from '../../lib/api/cxapp/stacks'; import { Renames } from '../../lib/renames'; import { Configuration } from '../../lib/settings'; diff --git a/packages/aws-cdk/test/test.account-cache.ts b/packages/aws-cdk/test/test.account-cache.ts deleted file mode 100644 index 2c56c01d28108..0000000000000 --- a/packages/aws-cdk/test/test.account-cache.ts +++ /dev/null @@ -1,85 +0,0 @@ -import fs = require('fs-extra'); -import { ICallbackFunction, Test } from 'nodeunit'; -import path = require('path'); -import { AccountAccessKeyCache } from '../lib/api/util/account-cache'; - -export = { - async 'setUp'(cb: ICallbackFunction) { - const self = this as any; - const dir = await fs.mkdtemp('/tmp/account-cache-test'); - self.file = path.join(dir, 'cache.json'); - self.cache = new AccountAccessKeyCache(self.file); - return cb(); - }, - - async 'tearDown'(cb: ICallbackFunction) { - const self = this as any; - await fs.remove(path.dirname(self.file)); - cb(); - }, - - async 'get(k) when cache is empty'(test: Test) { - const self = this as any; - const cache: AccountAccessKeyCache = self.cache; - test.equal(await cache.get('foo'), undefined, 'get returns undefined'); - test.equal(await fs.pathExists(self.file), false, 'cache file is not created'); - test.done(); - }, - - async 'put(k,v) and then get(k)'(test: Test) { - const self = this as any; - const cache: AccountAccessKeyCache = self.cache; - - await cache.put('key', 'value'); - await cache.put('boo', 'bar'); - test.deepEqual(await cache.get('key'), 'value', '"key" is mapped to "value"'); - - // create another cache instance on the same file, should still work - const cache2 = new AccountAccessKeyCache(self.file); - test.deepEqual(await cache2.get('boo'), 'bar', '"boo" is mapped to "bar"'); - - // whitebox: read the file - test.deepEqual(await fs.readJson(self.file), { - key: 'value', - boo: 'bar' - }); - - test.done(); - }, - - async 'fetch(k, resolver) can be used to "atomically" get + resolve + put'(test: Test) { - const self = this as any; - const cache: AccountAccessKeyCache = self.cache; - - test.deepEqual(await cache.get('foo'), undefined, 'no value for "foo" yet'); - test.deepEqual(await cache.fetch('foo', async () => 'bar'), 'bar', 'resolved by fetch and returned'); - test.deepEqual(await cache.get('foo'), 'bar', 'stored in cache by fetch()'); - test.done(); - }, - - async 'cache is nuked if it exceeds 1000 entries'(test: Test) { - const self = this as any; - const cache: AccountAccessKeyCache = self.cache; - - for (let i = 0; i < AccountAccessKeyCache.MAX_ENTRIES; ++i) { - await cache.put(`key${i}`, `value${i}`); - } - - // verify all 1000 values are on disk - const otherCache = new AccountAccessKeyCache(self.file); - for (let i = 0; i < AccountAccessKeyCache.MAX_ENTRIES; ++i) { - test.equal(await otherCache.get(`key${i}`), `value${i}`); - } - - // add another value - await cache.put('nuke-me', 'genesis'); - - // now, we expect only `nuke-me` to exist on disk - test.equal(await otherCache.get('nuke-me'), 'genesis'); - for (let i = 0; i < AccountAccessKeyCache.MAX_ENTRIES; ++i) { - test.equal(await otherCache.get(`key${i}`), undefined); - } - - test.done(); - } -}; diff --git a/packages/aws-cdk/test/util/mock-sdk.ts b/packages/aws-cdk/test/util/mock-sdk.ts deleted file mode 100644 index 43c88c83508d9..0000000000000 --- a/packages/aws-cdk/test/util/mock-sdk.ts +++ /dev/null @@ -1,107 +0,0 @@ -import AWS = require('aws-sdk'); -import sinon = require('sinon'); -import { SDK } from "../../lib/api/util/sdk"; - -/** - * An SDK that allows replacing (some of) the clients - * - * Its the responsibility of the consumer to replace all calls that - * actually will be called. - */ -export class MockSDK extends SDK { - private readonly sandbox: sinon.SinonSandbox; - constructor() { - super(); - this.sandbox = sinon.createSandbox(); - } - - /** - * Replace the CloudFormation client with the given object - */ - public stubCloudFormation(stubs: SyncHandlerSubsetOf) { - this.sandbox.stub(this, 'cloudFormation').returns(Promise.resolve(partialAwsService(stubs))); - } - - /** - * Replace the ECR client with the given object - */ - public stubEcr(stubs: SyncHandlerSubsetOf) { - this.sandbox.stub(this, 'ecr').returns(Promise.resolve(partialAwsService(stubs))); - } -} - -/** - * Wrap synchronous fake handlers so that they sort-of function like a real AWS client - * - * For example, turns an object like this: - * - * ```ts - * { - * someCall(opts: AWS.Service.SomeCallInput): AWS.Service.SomeCallOutput { - * return {...whatever...}; - * } - * } - * ``` - * - * Into an object that in the type system pretends to be an 'AWS.Service' - * class (even though it really isn't) and can be called like this: - * - * ```ts - * const service = await sdk.someService(...); - * const response = await service.someCall(...).promise(); - * ``` - * - * We only implement the narrow subset of the AWS SDK API that the CDK actually - * uses, and we cheat on the types to make TypeScript happy on the rest of the API. - * - * Most important feature of this class is that it will derive the input and output - * types of the handlers on the input object from the ACTUAL AWS Service class, - * so that you don't have to declare them. - */ -function partialAwsService(fns: SyncHandlerSubsetOf): S { - // Super unsafe in here because I don't know how to make TypeScript happy, - // but at least the outer types make sure everything that happens in here works out. - const ret: any = {}; - - for (const [key, handler] of Object.entries(fns)) { - ret[key] = (args: any) => new FakeAWSResponse((handler as any)(args)); - } - - return ret; -} - -// Because of the overloads an AWS handler type looks like this: -// -// { -// (params: INPUTSTRUCT, callback?: ((err: AWSError, data: {}) => void) | undefined): Request; -// (callback?: ((err: AWS.AWSError, data: {}) => void) | undefined): AWS.Request<...>; -// } -// -// Get the first overload and extract the input and output struct types -type AwsCallInputOutput = - T extends { - (args: infer INPUT, callback?: ((err: AWS.AWSError, data: any) => void) | undefined): AWS.Request; - (callback?: ((err: AWS.AWSError, data: {}) => void) | undefined): AWS.Request; - } ? [INPUT, OUTPUT] : never; - -// Determine the type of the mock handler from the type of the Input/Output type pair. -// Don't need to worry about the 'never', TypeScript will propagate it upwards making it -// impossible to specify the field that has 'never' anywhere in its type. -type MockHandlerType = (input: AI[0]) => AI[1]; - -// Any subset of the full type that synchronously returns the output structure is okay -type SyncHandlerSubsetOf = {[K in keyof S]?: MockHandlerType>}; - -/** - * Fake AWS response. - * - * We only ever 'await response.promise()' so that's the only thing we implement here. - */ -class FakeAWSResponse { - constructor(private readonly x: T) { - } - - public promise(): Promise { - return Promise.resolve(this.x); - } -} diff --git a/packages/aws-cdk/test/util/test.applydefaults.ts b/packages/aws-cdk/test/util/test.applydefaults.ts deleted file mode 100644 index e87ad9f04dab5..0000000000000 --- a/packages/aws-cdk/test/util/test.applydefaults.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Test } from 'nodeunit'; -import { applyDefaults } from '../../lib/util'; - -export = { - 'applyDefaults() works'(test: Test) { - const given = { a: 1 }; - const defaults = { a: 2, b: 2 }; - - const output = applyDefaults(given, defaults); - - test.deepEqual({ a: 1, b: 2}, output); - test.done(); - } -}; diff --git a/packages/aws-cdk/test/util/test.arrays.ts b/packages/aws-cdk/test/util/test.arrays.ts deleted file mode 100644 index 9a66251a155b2..0000000000000 --- a/packages/aws-cdk/test/util/test.arrays.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Test } from 'nodeunit'; -import { flatMap, flatten, partition } from '../../lib/util'; - -export = { - 'flatten combines arrays'(test: Test) { - const output = flatten([ - ['a', 'b'], - [], - ['c'] - ]); - - test.deepEqual(output, ['a', 'b', 'c']); - test.done(); - }, - 'flatMap maps and combines'(test: Test) { - const input = ['A', 'B', 'C']; - const output = flatMap(input, x => [x.toLowerCase()]); - - test.deepEqual(output, ['a', 'b', 'c']); - test.done(); - }, - 'partition splits the collection in twain'(test: Test) { - const xs = [1, 2, 3, 4, 5]; - const evens = partition(xs, x => x % 2 === 0); - - test.deepEqual(evens, [2, 4]); - test.deepEqual(xs, [1, 3, 5]); - test.done(); - }, -}; diff --git a/packages/aws-cdk/test/util/test.objects.ts b/packages/aws-cdk/test/util/test.objects.ts deleted file mode 100644 index 1566bcf4f240d..0000000000000 --- a/packages/aws-cdk/test/util/test.objects.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Test } from 'nodeunit'; -import { deepClone, deepGet, deepMerge, deepSet } from '../../lib/util'; - -export = { - 'deepSet can set deeply'(test: Test) { - const obj = {}; - deepSet(obj, ['a', 'b'], 3); - test.deepEqual(obj, {a: {b: 3}}); - test.done(); - }, - 'deepGet can get deeply'(test: Test) { - const obj = {a: {b: 3}}; - test.equal(deepGet(obj, ['a', 'b']), 3); - test.done(); - }, - 'deepGet can return an array'(test: Test) { - const obj = {a: [1, 2, 3]}; - test.deepEqual(deepGet(obj, ['a']), [1, 2, 3]); - test.done(); - }, - 'changing deepClones copy leaves the original intact'(test: Test) { - const original = {a: [{b: 3}]}; - const copy = deepClone(original); - copy.a[0].c = 5; - - test.deepEqual(original, {a: [{b: 3}]}); - test.done(); - }, - 'deepMerge merges objects'(test: Test) { - const original = {a: {b: 3}}; - deepMerge(original, {a: {c: 4}}); - - test.deepEqual(original, {a: {b: 3, c: 4}}); - test.done(); - }, - 'deepMerge overwrites non-objects'(test: Test) { - const original = {a: []}; - deepMerge(original, {a: {b: 3}}); - - test.deepEqual(original, {a: {b: 3}}); - test.done(); - }, - 'deepMerge does not overwrite if rightmost is "undefined"'(test: Test) { - const original = {a: 1}; - deepMerge(original, {a: undefined}); - - test.deepEqual(original, {a: 1}); - test.done(); - } -}; diff --git a/packages/aws-cdk/tsconfig.json b/packages/aws-cdk/tsconfig.json index a945c2d9b858d..c4a89df076559 100644 --- a/packages/aws-cdk/tsconfig.json +++ b/packages/aws-cdk/tsconfig.json @@ -20,7 +20,7 @@ }, "include": [ "**/*.ts", - "**/*.d.ts", "../@aws-cdk/cdk-deploy/lib/assets.ts", "../@aws-cdk/cdk-deploy/lib/archive.ts", "../@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts", "../@aws-cdk/cd, "../@aws-cdk/cdk-deploy/lib/diff.ts"k-deploy/lib/docker.ts", "../@aws-cdk/cdk-common/lib/logging.ts", "../@aws-cdk/cdk-common/lib/serialize.ts", "../@aws-cdk/cdk-common/lib/os.ts" + "**/*.d.ts", "../@aws-cdk/cdk-deploy/lib/assets.ts", "../@aws-cdk/cdk-deploy/lib/archive.ts", "../@aws-cdk/cdk-deploy/lib/Deployer.ts", "../@aws-cdk/cd, "../@aws-cdk/cdk-deploy/lib/diff.ts"k-deploy/lib/docker.ts", "../@aws-cdk/cdk-common/lib/logging.ts", "../@aws-cdk/cdk-common/lib/serialize.ts", "../@aws-cdk/cdk-common/lib/os.ts", "../@aws-cdk/cdk-common/test/test.account-cache.ts", "../@aws-cdk/cdk-common/test/test.objects.ts", "../@aws-cdk/cdk-common/test/test.arrays.ts", "../@aws-cdk/cdk-common/test/test.applydefaults.ts" ], "exclude": [ "lib/init-templates/**/*" From 0a7075e2b00c49514609c276f093d23b5389299c Mon Sep 17 00:00:00 2001 From: Sam Goodwin Date: Tue, 16 Apr 2019 22:15:53 -0700 Subject: [PATCH 05/12] Refactor aws-cdk to use @aws-cdk/cdk-common and @aws-cdk/cdk-deploy --- packages/@aws-cdk/cdk-common/lib/index.ts | 1 + .../lib/api/bootstrap-environment.ts | 2 +- .../cdk-deploy/lib/api/deploy-stack.ts | 5 ++- .../cdk-deploy/lib/api/deployment-target.ts | 28 ++++++++-------- packages/@aws-cdk/cdk-deploy/lib/api/index.ts | 2 -- .../@aws-cdk/cdk-deploy/lib/cdk-toolkit.ts | 1 - packages/@aws-cdk/cdk-deploy/lib/index.ts | 6 ++++ .../cdk-deploy/test/api/test.deploy-stack.ts | 5 ++- packages/aws-cdk/bin/cdk.ts | 33 ++++++++++--------- packages/aws-cdk/lib/commands/context.ts | 2 +- packages/aws-cdk/lib/commands/docs.ts | 2 +- packages/aws-cdk/lib/commands/doctor.ts | 2 +- packages/aws-cdk/lib/index.ts | 1 - packages/aws-cdk/lib/init.ts | 2 +- packages/aws-cdk/lib/interactive.ts | 2 +- packages/aws-cdk/package-lock.json | 2 +- packages/aws-cdk/package.json | 1 + packages/aws-cdk/test/test.yaml.ts | 2 +- packages/aws-cdk/tsconfig.json | 3 +- 19 files changed, 54 insertions(+), 48 deletions(-) create mode 100644 packages/@aws-cdk/cdk-deploy/lib/index.ts delete mode 100644 packages/aws-cdk/lib/index.ts diff --git a/packages/@aws-cdk/cdk-common/lib/index.ts b/packages/@aws-cdk/cdk-common/lib/index.ts index 56baa97de0374..a8c55b709d4cc 100644 --- a/packages/@aws-cdk/cdk-common/lib/index.ts +++ b/packages/@aws-cdk/cdk-common/lib/index.ts @@ -1,6 +1,7 @@ export * from './credentials'; export * from './logging'; export * from './os'; +export * from './plugin'; export * from './sdk'; export * from './serialize'; export * from './util'; diff --git a/packages/@aws-cdk/cdk-deploy/lib/api/bootstrap-environment.ts b/packages/@aws-cdk/cdk-deploy/lib/api/bootstrap-environment.ts index b3e54793f22b5..414006e51a2c7 100644 --- a/packages/@aws-cdk/cdk-deploy/lib/api/bootstrap-environment.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/bootstrap-environment.ts @@ -35,5 +35,5 @@ export async function bootstrapEnvironment(environment: Environment, aws: SDK, t }, name: toolkitStackName, }; - return await deployStack({ stack: synthesizedStack, sdk: aws, roleArn }); + return await deployStack(aws, { stack: synthesizedStack, roleArn }); } diff --git a/packages/@aws-cdk/cdk-deploy/lib/api/deploy-stack.ts b/packages/@aws-cdk/cdk-deploy/lib/api/deploy-stack.ts index 878af3f769a8b..39ca1a4e4c10e 100644 --- a/packages/@aws-cdk/cdk-deploy/lib/api/deploy-stack.ts +++ b/packages/@aws-cdk/cdk-deploy/lib/api/deploy-stack.ts @@ -22,7 +22,6 @@ export interface DeployStackResult { export interface DeployStackOptions { stack: cxapi.SynthesizedStack; - sdk: SDK; toolkitInfo?: ToolkitInfo; roleArn?: string; deployName?: string; @@ -33,7 +32,7 @@ export interface DeployStackOptions { const LARGE_TEMPLATE_SIZE_KB = 50; -export async function deployStack(options: DeployStackOptions): Promise { +export async function deployStack(sdk: SDK, options: DeployStackOptions): Promise { if (!options.stack.environment) { throw new Error(`The stack ${options.stack.name} does not have an environment`); } @@ -44,7 +43,7 @@ export async function deployStack(options: DeployStackOptions): Promise; } -export interface DeployStackOptions { - stack: cxapi.SynthesizedStack; - roleArn?: string; - deployName?: string; - quiet?: boolean; - ci?: boolean; - toolkitStackName?: string; - reuseAssets?: string[]; -} +// export interface DeployStackOptions { +// stack: cxapi.SynthesizedStack; +// roleArn?: string; +// deployName?: string; +// quiet?: boolean; +// ci?: boolean; +// toolkitStackName?: string; +// reuseAssets?: string[]; +// } export interface ProvisionerProps { aws: SDK; + toolkitStackName: string; } /** @@ -36,9 +37,11 @@ export interface ProvisionerProps { */ export class CloudFormationDeploymentTarget implements IDeploymentTarget { private readonly aws: SDK; + private readonly toolkitStackName: string; constructor(props: ProvisionerProps) { this.aws = props.aws; + this.toolkitStackName = props.toolkitStackName; } public async readCurrentTemplate(stack: cxapi.SynthesizedStack): Promise