From ecbb87b494ac24e0ed9dbc2b41fa43ad37ace8c0 Mon Sep 17 00:00:00 2001 From: Jimmy Gaussen Date: Sun, 4 Feb 2024 10:37:33 +0100 Subject: [PATCH] feat(cli): --project-name init option --- packages/aws-cdk/lib/cli.ts | 3 +- packages/aws-cdk/lib/init.ts | 48 +++++++++++++++++++++++------- packages/aws-cdk/test/init.test.ts | 32 ++++++++++++++++++++ 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/packages/aws-cdk/lib/cli.ts b/packages/aws-cdk/lib/cli.ts index 708f9f5783677..1f7ecd2ae2344 100644 --- a/packages/aws-cdk/lib/cli.ts +++ b/packages/aws-cdk/lib/cli.ts @@ -272,7 +272,8 @@ async function parseCommandLineArguments(args: string[]) { .command('init [TEMPLATE]', 'Create a new, empty CDK project from a template.', (yargs: Argv) => yargs .option('language', { type: 'string', alias: 'l', desc: 'The language to be used for the new project (default can be configured in ~/.cdk.json)', choices: initTemplateLanguages }) .option('list', { type: 'boolean', desc: 'List the available templates' }) - .option('generate-only', { type: 'boolean', default: false, desc: 'If true, only generates project files, without executing additional operations such as setting up a git repo, installing dependencies or compiling the project' }), + .option('generate-only', { type: 'boolean', default: false, desc: 'If true, only generates project files, without executing additional operations such as setting up a git repo, installing dependencies or compiling the project' }) + .option('project-name', { type: 'string', desc: 'Name of the generated project (defaults to current directory name)', requiresArg: true }), ) .command('migrate', false /* hidden from "cdk --help" */, (yargs: Argv) => yargs .option('stack-name', { type: 'string', alias: 'n', desc: 'The name assigned to the stack created in the new project. The name of the app will be based off this name as well.', requiresArg: true }) diff --git a/packages/aws-cdk/lib/init.ts b/packages/aws-cdk/lib/init.ts index faf323100bf56..67997e6ea2834 100644 --- a/packages/aws-cdk/lib/init.ts +++ b/packages/aws-cdk/lib/init.ts @@ -19,6 +19,7 @@ export interface CliInitOptions { readonly language?: string; readonly canUseNetwork?: boolean; readonly generateOnly?: boolean; + readonly projectName?: string; readonly workDir?: string; readonly stackName?: string; readonly migrate?: boolean; @@ -52,7 +53,16 @@ export async function cliInit(options: CliInitOptions) { throw new Error('No language was selected'); } - await initializeProject(template, options.language, canUseNetwork, generateOnly, workDir, options.stackName, options.migrate); + await initializeProject({ + template, + language: options.language, + canUseNetwork, + generateOnly, + projectName: options.projectName, + workDir, + stackName: options.stackName, + migrate: options.migrate, + }); } /** @@ -102,8 +112,10 @@ export class InitTemplate { * * @param language the language to instantiate this template with * @param targetDirectory the directory where the template is to be instantiated into + * @param stackName the output project stack name + * @param projectName the output project name */ - public async install(language: string, targetDirectory: string, stackName?: string) { + public async install(language: string, targetDirectory: string, stackName?: string, projectName?: string) { if (this.languages.indexOf(language) === -1) { error(`The ${chalk.blue(language)} language is not supported for ${chalk.green(this.name)} ` + `(it supports: ${this.languages.map(l => chalk.blue(l)).join(', ')})`); @@ -111,7 +123,7 @@ export class InitTemplate { } const projectInfo: ProjectInfo = { - name: decamelize(path.basename(path.resolve(targetDirectory))), + name: projectName ?? decamelize(path.basename(path.resolve(targetDirectory))), stackName, }; @@ -280,18 +292,32 @@ export async function printAvailableTemplates(language?: string) { } } +interface InitializeProjectOptions { + template: InitTemplate; + language: string; + canUseNetwork: boolean; + generateOnly: boolean; + projectName?: string; + workDir: string; + stackName?: string; + migrate?: boolean; +} + async function initializeProject( - template: InitTemplate, - language: string, - canUseNetwork: boolean, - generateOnly: boolean, - workDir: string, - stackName?: string, - migrate?: boolean, + { + template, + language, + canUseNetwork, + generateOnly, + projectName, + workDir, + stackName, + migrate, + }: InitializeProjectOptions, ) { await assertIsEmptyDirectory(workDir); print(`Applying project template ${chalk.green(template.name)} for ${chalk.blue(language)}`); - await template.install(language, workDir, stackName); + await template.install(language, workDir, stackName, projectName); if (migrate) { await template.addMigrateContext(workDir); } diff --git a/packages/aws-cdk/test/init.test.ts b/packages/aws-cdk/test/init.test.ts index 6d9bd2dc4769b..68cf37e904e8c 100644 --- a/packages/aws-cdk/test/init.test.ts +++ b/packages/aws-cdk/test/init.test.ts @@ -181,6 +181,38 @@ describe('constructs version', () => { expect(await fs.pathExists(path.join(workDir, '.git'))).toBeFalsy(); }); + cliTest('--project-name should change the output directory', async (workDir) => { + const projectName = 'custom_project-name'; + await cliInit({ + type: 'app', + language: 'javascript', + canUseNetwork: false, + generateOnly: true, + workDir, + projectName, + }); + + // Check that lib/, bin/ and test/ files have been set correctly + expect(await fs.pathExists(path.join(workDir, 'bin', `${projectName}.js`))).toBeTruthy(); + expect(await fs.pathExists(path.join(workDir, 'lib', `${projectName}-stack.js`))).toBeTruthy(); + expect(await fs.pathExists(path.join(workDir, 'test', `${projectName}.test.js`))).toBeTruthy(); + + // Check that the package.json "name" and "bin" properties have been set correctly + const packageJsonFile = path.join(workDir, 'package.json'); + expect(await fs.pathExists(packageJsonFile)).toBeTruthy(); + + const packageJson = JSON.parse(await fs.readFile(packageJsonFile, 'utf8')); + expect(packageJson.name).toEqual(projectName); + expect(packageJson.bin).toEqual({ [projectName]: `bin/${projectName}.js` }); + + // Check that the cdk.json "app" property has been set correctly + const cdkJsonFile = path.join(workDir, 'cdk.json'); + expect(await fs.pathExists(cdkJsonFile)).toBeTruthy(); + + const cdkJson = JSON.parse(await fs.readFile(cdkJsonFile, 'utf8')); + expect(cdkJson.app).toEqual(`node bin/${projectName}.js`); + }); + cliTest('git directory does not throw off the initer!', async (workDir) => { fs.mkdirSync(path.join(workDir, '.git'));