tools/@aws-cdk/spec2cdk/lib/cli/cli.ts (128 lines of code) (raw):

import * as path from 'node:path'; import { parseArgs } from 'node:util'; import { PositionalArg, showHelp } from './help'; import { GenerateModuleMap, PatternKeys, generate, generateAll } from '../generate'; import { log, parsePattern } from '../util'; const command = 'spec2cdk'; const args: PositionalArg[] = [{ name: 'output-path', required: true, description: 'The directory the generated code will be written to', }]; const config = { 'help': { short: 'h', type: 'boolean', description: 'Show this help', }, 'debug': { type: 'boolean', description: 'Show additional debug output', }, 'pattern': { type: 'string', default: '%moduleName%/%serviceShortName%.generated.ts', description: 'File and path pattern for generated files', }, 'augmentations': { type: 'string', default: '%moduleName%/%serviceShortName%-augmentations.generated.ts', description: 'File and path pattern for generated augmentations files', }, 'metrics': { type: 'string', default: '%moduleName%/%serviceShortName%-canned-metrics.generated.ts', description: 'File and path pattern for generated canned metrics files ', }, 'service': { short: 's', type: 'string', description: 'Generate files only for a specific service, e.g. AWS::S3', multiple: true, }, 'clear-output': { type: 'boolean', default: false, description: 'Completely delete the output path before generating new files', }, 'augmentations-support': { type: 'boolean', default: false, description: 'Generates additional files required for augmentation files to compile. Use for testing only', }, } as const; const helpText = `Path patterns can use the following variables: %moduleName% The name of the module, e.g. aws-lambda %serviceName% The full name of the service, e.g. aws-lambda %serviceShortName% The short name of the service, e.g. lambda Note that %moduleName% and %serviceName% can be different if multiple services are generated into a single module.`; const help = () => showHelp(command, args, config, helpText); export const shortHelp = () => showHelp(command, args); export async function main(argv: string[]) { const { positionals, values: options, } = parseArgs({ args: argv, allowPositionals: true, options: config, }); if (options.help) { help(); return; } if (options.debug) { process.env.DEBUG = '1'; } log.debug('CLI args', positionals, options); const outputDir = positionals[0]; if (!outputDir) { throw new EvalError('Please specify the output-path'); } const pss: Record<PatternKeys, true> = { moduleName: true, serviceName: true, serviceShortName: true }; const outputPath = outputDir ?? path.join(__dirname, '..', 'services'); const resourceFilePattern = parsePattern( stringOr(options.pattern, path.join('%moduleName%', '%serviceShortName%.generated.ts')), pss, ); const augmentationsFilePattern = parsePattern( stringOr(options.augmentations, path.join('%moduleName%', '%serviceShortName%-augmentations.generated.ts')), pss, ); const cannedMetricsFilePattern = parsePattern( stringOr(options.metrics, path.join('%moduleName%', '%serviceShortName%-canned-metrics.generated.ts')), pss, ); const generatorOptions = { outputPath, filePatterns: { resources: resourceFilePattern, augmentations: augmentationsFilePattern, cannedMetrics: cannedMetricsFilePattern, }, clearOutput: options['clear-output'], augmentationsSupport: options['augmentations-support'], debug: options.debug as boolean, }; if (options.service?.length) { const moduleMap: GenerateModuleMap = {}; for (const service of options.service) { if (!service.includes('::')) { throw new EvalError(`Each service must be in the form <Partition>::<Service>, e.g. AWS::S3. Got: ${service}`); } moduleMap[service.toLocaleLowerCase().split('::').join('-')] = { services: [service] }; } await generate(moduleMap, generatorOptions); return; } await generateAll(generatorOptions); } function stringOr(pat: unknown, def: string) { if (!pat) { return def; } if (typeof pat !== 'string') { throw new Error(`Expected string, got: ${JSON.stringify(pat)}`); } return pat; }