|
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