diff --git a/packages/aws-cdk/lib/commands/context.ts b/packages/aws-cdk/lib/commands/context.ts index 40d3b9489fe64..429e1360f5357 100644 --- a/packages/aws-cdk/lib/commands/context.ts +++ b/packages/aws-cdk/lib/commands/context.ts @@ -2,7 +2,7 @@ import colors = require('colors/safe'); import yargs = require('yargs'); import { CommandOptions } from '../command-api'; import { print } from '../logging'; -import { PROJECT_CONFIG } from '../settings'; +import { Context, PROJECT_CONFIG } from '../settings'; import { renderTable } from '../util'; export const command = 'context'; @@ -34,8 +34,7 @@ export async function realHandler(options: CommandOptions): Promise { await configuration.saveContext(); print('All context values cleared.'); } else if (args.reset) { - invalidateContext(contextValues, args.reset); - configuration.context.setAll(contextValues); + invalidateContext(configuration.context, args.reset); await configuration.saveContext(); } else { // List -- support '--json' flag @@ -77,7 +76,7 @@ function listContext(context: any) { print(`Run ${colors.blue('cdk context --reset KEY_OR_NUMBER')} to remove a context key. It will be refreshed on the next CDK synthesis run.`); } -function invalidateContext(context: any, key: string) { +function invalidateContext(context: Context, key: string) { const i = parseInt(key, 10); if (`${i}` === key) { // Twas a number and we fully parsed it. @@ -85,8 +84,8 @@ function invalidateContext(context: any, key: string) { } // Unset! - if (key in context) { - delete context[key]; + if (context.has(key)) { + context.unset(key); print(`Context value ${colors.blue(key)} reset. It will be refreshed on the next SDK synthesis run.`); } else { print(`No context value with key ${colors.blue(key)}`); diff --git a/packages/aws-cdk/lib/settings.ts b/packages/aws-cdk/lib/settings.ts index 844ac296bf686..0b7e1e6f9295e 100644 --- a/packages/aws-cdk/lib/settings.ts +++ b/packages/aws-cdk/lib/settings.ts @@ -24,6 +24,7 @@ export class Configuration { private readonly commandLineArguments: Settings; private projectConfig: Settings; private projectContext: Settings; + private loaded = false; constructor(commandLineArguments?: yargs.Arguments) { this.commandLineArguments = commandLineArguments @@ -48,6 +49,8 @@ export class Configuration { .merge(this.commandLineArguments) .makeReadOnly(); + this.loaded = true; + return this; } @@ -55,6 +58,8 @@ export class Configuration { * Save the project config */ public async saveContext(): Promise { + if (!this.loaded) { return this; } + if (this.context.modifiedBottom) { await this.projectConfig.save(PROJECT_CONFIG); } @@ -85,6 +90,14 @@ export class Context { constructor(private readonly bottom: Settings, private readonly bottomPrefixPath: string[], private readonly top: Settings) { } + public get keys(): string[] { + return Object.keys(this.everything()); + } + + public has(key: string) { + return this.keys.indexOf(key) > -1; + } + public everything(): {[key: string]: any} { const b = this.bottom.get(this.bottomPrefixPath) || {}; const t = this.top.get([]) || {}; @@ -105,18 +118,12 @@ export class Context { } } - public setAll(values: object) { - for (const [key, value] of Object.entries(values)) { - this.set(key, value); - } - } - public unset(key: string) { this.set(key, undefined); } public clear() { - for (const key of Object.keys(this.everything())) { + for (const key of this.keys) { this.unset(key); } } diff --git a/packages/aws-cdk/test/commands/test.context-command.ts b/packages/aws-cdk/test/commands/test.context-command.ts new file mode 100644 index 0000000000000..1e0ef1a4e12ba --- /dev/null +++ b/packages/aws-cdk/test/commands/test.context-command.ts @@ -0,0 +1,25 @@ +import { Test } from 'nodeunit'; +import { realHandler } from '../../lib/commands/context'; +import { Configuration } from '../../lib/settings'; + +export = { + async 'context reset can remove a context key'(test: Test) { + // GIVEN + const configuration = new Configuration(); + configuration.context.set('foo', 'bar'); + configuration.context.set('baz', 'quux'); + + // WHEN + await realHandler({ + configuration, + args: { reset: 'foo' } + } as any); + + // THEN + test.deepEqual(configuration.context.everything(), { + baz: 'quux' + }); + + test.done(); + }, +}; \ No newline at end of file