|
1 | 1 | import * as fs from 'fs'; |
2 | 2 | import * as path from 'path'; |
3 | | -import { initializeProject, availableInitTemplates } from '../../lib/init'; |
| 3 | +import * as cdk_from_cfn from 'cdk-from-cfn'; |
| 4 | +import { cliInit } from '../../lib/init'; |
4 | 5 | import { warning } from '../logging'; |
5 | | -import * as nocti from '../vendor/noctilucent'; |
| 6 | + |
| 7 | +/* eslint-disable @typescript-eslint/no-var-requires */ // Packages don't have @types module |
| 8 | +// eslint-disable-next-line @typescript-eslint/no-require-imports |
| 9 | +const camelCase = require('camelcase'); |
| 10 | +// eslint-disable-next-line @typescript-eslint/no-require-imports |
| 11 | +const decamelize = require('decamelize'); |
6 | 12 |
|
7 | 13 | /** The list of languages supported by the built-in noctilucent binary. */ |
8 | | -export const MIGRATE_SUPPORTED_LANGUAGES: readonly string[] = nocti.supported_languages(); |
| 14 | +export const MIGRATE_SUPPORTED_LANGUAGES: readonly string[] = cdk_from_cfn.supported_languages(); |
9 | 15 |
|
10 | | -export async function cliMigrate( |
11 | | - inputpath: string = process.cwd() + '/../template.txt', |
12 | | - language = MIGRATE_SUPPORTED_LANGUAGES[0], |
13 | | - generateOnly = false, |
14 | | - outputpath = process.cwd(), |
15 | | -) { |
16 | | - warning('This is an experimental feature. We make no guarantees about the outcome or stability of the functionality.'); |
17 | | - const type = 'default'; // "default" is the default type (and maps to 'app') |
18 | | - const template = (await availableInitTemplates()).find(t => t.hasName(type!)); |
19 | | - if (!template) { |
20 | | - throw new Error(`couldn't find template for ${type} app type, this should never happen`); |
21 | | - } |
| 16 | +export interface CliMigrateOptions { |
| 17 | + readonly stackName: string; |
| 18 | + readonly language?: string; |
| 19 | + readonly fromPath?: string; |
| 20 | + readonly outputPath?: string; |
| 21 | +} |
22 | 22 |
|
23 | | - if (!MIGRATE_SUPPORTED_LANGUAGES.includes(language)) { |
24 | | - throw new Error(`Unsupported language for cdk migrate: ${language}. Supported languages are: ${MIGRATE_SUPPORTED_LANGUAGES.join(', ')}`); |
25 | | - } |
| 23 | +export async function cliMigrate(options: CliMigrateOptions) { |
| 24 | + warning('This is an experimental feature. We make no guarantees about the outcome or stability of the functionality.'); |
26 | 25 |
|
27 | | - await initializeProject(template, language, true, generateOnly, outputpath); |
28 | | - const template_file = fs.readFileSync(inputpath, 'utf8'); |
29 | | - const generated_app = nocti.transmute(template_file, language); |
| 26 | + // TODO: Validate stack name |
30 | 27 |
|
31 | | - // clear out the init'd bin/lib files to replace with our own |
32 | | - delete_files(outputpath + '/lib/'); |
| 28 | + const language = options.language ?? 'typescript'; |
| 29 | + const outputPath = path.join(options.outputPath ?? process.cwd(), options.stackName); |
33 | 30 |
|
34 | | - // we hardcode everything to be called noctstack still so this works for now. |
35 | | - // Will change this to be much smarter once we can change stack name in noct |
36 | | - const bin_app = `#!/usr/bin/env node |
37 | | - import 'source-map-support/register'; |
38 | | - import * as cdk from 'aws-cdk-lib'; |
39 | | - import { NoctStack } from '../lib/generated_stack'; |
| 31 | + const generatedStack = generateStack(options, language); |
| 32 | + const stackName = decamelize(options.stackName); |
40 | 33 |
|
41 | | - const app = new cdk.App(); |
42 | | - new NoctStack(app, 'NoctStack', { |
43 | | - /* If you don't specify 'env', this stack will be environment-agnostic. |
44 | | - * Account/Region-dependent features and context lookups will not work, |
45 | | - * but a single synthesized template can be deployed anywhere. */ |
| 34 | + try { |
| 35 | + fs.rmSync(outputPath, { recursive: true, force: true }); |
| 36 | + fs.mkdirSync(outputPath, { recursive: true }); |
| 37 | + await cliInit('app', language, true, false, outputPath, options.stackName); |
46 | 38 |
|
47 | | - /* Uncomment the next line to specialize this stack for the AWS Account |
48 | | - * and Region that are implied by the current CLI configuration. */ |
49 | | - // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION }, |
| 39 | + let stackFileName: string; |
| 40 | + switch (language) { |
| 41 | + case 'typescript': |
| 42 | + stackFileName = `${outputPath}/lib/${stackName}-stack.ts`; |
| 43 | + break; |
| 44 | + case 'java': |
| 45 | + stackFileName = `${outputPath}/src/main/java/com/myorg/${camelCase(stackName, { pascalCase: true })}Stack.java`; |
| 46 | + break; |
| 47 | + case 'python': |
| 48 | + stackFileName = `${outputPath}/${stackName.replace(/-/g, '_')}/${stackName.replace(/-/g, '_')}_stack.py`; |
| 49 | + break; |
| 50 | + case 'csharp': |
| 51 | + stackFileName = `${outputPath}/src/${camelCase(stackName, { pascalCase: true })}/${camelCase(stackName, { pascalCase: true })}Stack.cs`; |
| 52 | + break; |
| 53 | + // TODO: Add Go support |
| 54 | + default: |
| 55 | + throw new Error(`${language} is not supported by CDK Migrate. Please choose from: ${MIGRATE_SUPPORTED_LANGUAGES.join(', ')}`); |
| 56 | + } |
| 57 | + fs.writeFileSync(stackFileName!, generatedStack); |
| 58 | + } catch (error) { |
| 59 | + fs.rmSync(outputPath, { recursive: true, force: true }); |
| 60 | + throw error; |
| 61 | + } |
50 | 62 |
|
51 | | - /* Uncomment the next line if you know exactly what Account and Region you |
52 | | - * want to deploy the stack to. */ |
53 | | - // env: { account: '123456789012', region: 'us-east-1' }, |
| 63 | +} |
54 | 64 |
|
55 | | - /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */ |
56 | | - });`; |
57 | | - const myname = path.basename(outputpath); |
58 | | - fs.writeFileSync(outputpath + '/lib/' + 'generated_stack.ts', generated_app); |
59 | | - fs.writeFileSync(outputpath + '/bin/' + `${myname}.ts`, bin_app); |
| 65 | +function generateStack(options: CliMigrateOptions, language: string) { |
| 66 | + const stackName = `${camelCase(decamelize(options.stackName), { pascalCase: true })}Stack`; |
| 67 | + // We will add other options here in a future change. |
| 68 | + if (options.fromPath) { |
| 69 | + return fromPath(stackName, options.fromPath, language); |
| 70 | + } |
| 71 | + // TODO: replace with actual output for other options. |
| 72 | + return ''; |
60 | 73 | } |
61 | 74 |
|
62 | | -function delete_files(filepath: string) { |
63 | | - fs.readdir(filepath, (err, files) => { |
64 | | - if (err) throw err; |
65 | | - for (const file of files) { |
66 | | - fs.unlink(filepath + file, (cause) => { |
67 | | - if (cause) throw cause; |
68 | | - }); |
69 | | - } |
70 | | - }); |
| 75 | +function fromPath(stackName: string, inputPath: string, language: string): string { |
| 76 | + const templateFile = fs.readFileSync(inputPath, 'utf8'); |
| 77 | + return cdk_from_cfn.transmute(templateFile, language, stackName); |
71 | 78 | } |
0 commit comments