-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(toolkit): add 'cdk context' command #1169
Changes from 3 commits
a22a17a
00b7101
041982f
06e782a
c4bbf50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import colors = require('colors/safe'); | ||
import table = require('table'); | ||
import yargs = require('yargs'); | ||
import { print } from '../../lib/logging'; | ||
import { DEFAULTS, loadProjectConfig, saveProjectConfig } from '../settings'; | ||
|
||
export const command = 'context'; | ||
export const describe = 'Manage cached context values'; | ||
export const builder = { | ||
reset: { | ||
alias: 'e', | ||
desc: 'The context key (or its index) to reset', | ||
type: 'string', | ||
requiresArg: 'KEY' | ||
}, | ||
clear: { | ||
desc: 'Clear all context', | ||
type: 'boolean', | ||
}, | ||
}; | ||
|
||
export async function handler(args: yargs.Arguments): Promise<number> { | ||
const settings = await loadProjectConfig(); | ||
const context = settings.get(['context']) || {}; | ||
|
||
if (args.clear) { | ||
settings.set(['context'], {}); | ||
await saveProjectConfig(settings); | ||
print('All context values cleared.'); | ||
} else if (args.reset) { | ||
invalidateContext(context, args.reset); | ||
settings.set(['context'], context); | ||
await saveProjectConfig(settings); | ||
} else { | ||
// List -- support '--json' flag | ||
if (args.json) { | ||
process.stdout.write(JSON.stringify(context, undefined, 2)); | ||
} else { | ||
listContext(context); | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
function listContext(context: any) { | ||
const keys = contextKeys(context); | ||
|
||
// Print config by default | ||
const data: any[] = [[colors.green('#'), colors.green('Key'), colors.green('Value')]]; | ||
for (const [i, key] of keys) { | ||
const jsonWithoutNewlines = JSON.stringify(context[key], undefined, 2).replace(/\s+/g, ' '); | ||
data.push([i, key, jsonWithoutNewlines]); | ||
} | ||
|
||
print(`Context found in ${colors.blue(DEFAULTS)}:\n`); | ||
|
||
print(table.table(data, { | ||
border: table.getBorderCharacters('norc'), | ||
columns: { | ||
1: { width: 50, wrapWord: true } as any, | ||
2: { width: 50, wrapWord: true } as any | ||
} | ||
})); | ||
|
||
// tslint:disable-next-line:max-line-length | ||
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) { | ||
const i = parseInt(key, 10); | ||
if (`${i}` === key) { | ||
// Twas a number and we fully parsed it. | ||
key = keyByNumber(context, i); | ||
} | ||
|
||
// Unset! | ||
if (key in context) { | ||
delete context[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)}`); | ||
} | ||
} | ||
|
||
function keyByNumber(context: any, n: number) { | ||
for (const [i, key] of contextKeys(context)) { | ||
if (n === i) { | ||
return key; | ||
} | ||
} | ||
throw new Error(`No context key with number: ${n}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add --force and this will be no-op (similar to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is for a semi-interactive usage, where copying the key is a bother and you simply supply the number. Blindly deleting by key # is dangerous, given that the numbering is not unique. But yeah, just deleting a nonexistant key will be a no-op. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right of course! |
||
} | ||
|
||
/** | ||
* Return enumerated keys in a definitive order | ||
*/ | ||
function contextKeys(context: any) { | ||
const keys = Object.keys(context); | ||
keys.sort(); | ||
return enumerate1(keys); | ||
} | ||
|
||
function enumerate1<T>(xs: T[]): Array<[number, T]> { | ||
const ret = new Array<[number, T]>(); | ||
let i = 1; | ||
for (const x of xs) { | ||
ret.push([i, x]); | ||
i += 1; | ||
} | ||
return ret; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a
--json
flag that will output the context as JSON for machines?