From c0f9a834602e39748d724646bfbc1cbba0f932cb Mon Sep 17 00:00:00 2001 From: Ansgar Mertens Date: Wed, 19 Jan 2022 11:26:20 +0100 Subject: [PATCH] fix(cli): speed up shell autocompletions Speed up shell autocompletions by pulling actual handler code into a separate entrypoint which is only required when it is going to be invoked. When testing this speed up shell completions by 6x (from 1.2s to 0.2s [locally on OS X]). The main reason seemed to be e.g. the React package required by e.g. ink which is deffered into a separate bundle / entrypoint now. Also `inquirer` seems to have been quite a burden (used in `init`). --- packages/cdktf-cli/bin/cmds/convert.ts | 83 +----- packages/cdktf-cli/bin/cmds/deploy.ts | 26 +- packages/cdktf-cli/bin/cmds/destroy.ts | 26 +- packages/cdktf-cli/bin/cmds/diff.ts | 24 +- packages/cdktf-cli/bin/cmds/get.ts | 45 +-- packages/cdktf-cli/bin/cmds/handlers.ts | 278 ++++++++++++++++++ .../bin/cmds/helper/init-templates.ts | 12 + packages/cdktf-cli/bin/cmds/helper/init.ts | 12 +- .../cdktf-cli/bin/cmds/helper/utilities.ts | 52 ++++ packages/cdktf-cli/bin/cmds/init.ts | 18 +- packages/cdktf-cli/bin/cmds/list.ts | 19 +- packages/cdktf-cli/bin/cmds/login.ts | 46 +-- packages/cdktf-cli/bin/cmds/synth.ts | 37 +-- packages/cdktf-cli/bin/cmds/watch.ts | 39 +-- packages/cdktf-cli/build.ts | 8 +- packages/cdktf-cli/lib/server/index.ts | 2 +- packages/cdktf-cli/lib/util.ts | 2 +- packages/cdktf-cli/package.json | 2 +- 18 files changed, 397 insertions(+), 334 deletions(-) create mode 100644 packages/cdktf-cli/bin/cmds/handlers.ts create mode 100644 packages/cdktf-cli/bin/cmds/helper/init-templates.ts diff --git a/packages/cdktf-cli/bin/cmds/convert.ts b/packages/cdktf-cli/bin/cmds/convert.ts index a7dbac9795..d082b4f897 100644 --- a/packages/cdktf-cli/bin/cmds/convert.ts +++ b/packages/cdktf-cli/bin/cmds/convert.ts @@ -1,49 +1,5 @@ import yargs from "yargs"; -import { convert } from "@cdktf/hcl2cdk"; -import { displayVersionMessage } from "./helper/version-check"; -import { sendTelemetry } from "../../lib/checkpoint"; -import { Errors } from "../../lib/errors"; -import * as fs from "fs-extra"; -import * as path from "path"; -import { - readSchema, - ConstructsMakerProviderTarget, - LANGUAGES, - config, -} from "@cdktf/provider-generator"; - -function readStreamAsString(stream: typeof process.stdin): Promise { - return new Promise((ok, ko) => { - if (stream.isTTY) { - ko( - "No stdin was passed, please use it like this: cat main.tf | cdktf convert > imported.ts" - ); - } else { - let string = ""; - stream.on("data", (data) => (string += data.toString())); - - stream.on("close", () => ok(string)); - stream.on("error", (err) => ko(err)); - } - }); -} - -function findFileAboveCwd( - file: string, - rootPath = process.cwd() -): string | null { - const fullPath = path.resolve(rootPath, file); - if (fs.existsSync(fullPath)) { - return fullPath; - } - - const parentDir = path.resolve(rootPath, ".."); - if (fs.existsSync(parentDir) && parentDir !== rootPath) { - return findFileAboveCwd(file, parentDir); - } - - return null; -} +import { requireHandlers } from "./helper/utilities"; class Command implements yargs.CommandModule { public readonly command = "convert [OPTIONS]"; @@ -76,39 +32,10 @@ class Command implements yargs.CommandModule { }) .showHelpOnFail(true); - public async handler({ language }: any) { - await displayVersionMessage(); - - const providerRequirements: string[] = yargs.argv.provider as string[]; - const cdktfJsonPath = findFileAboveCwd("cdktf.json"); - if (cdktfJsonPath) { - const cdktfJson = await fs.readJson(cdktfJsonPath); - providerRequirements.push(...cdktfJson.terraformProviders); - } - // Get all the provider schemas - const { providerSchema } = await readSchema( - providerRequirements.map((spec) => - ConstructsMakerProviderTarget.from( - new config.TerraformProviderConstraint(spec), - LANGUAGES[0] - ) - ) - ); - - const input = await readStreamAsString(process.stdin); - let output; - try { - const { all, stats } = await convert(input, { - language, - providerSchema, - }); - output = all; - await sendTelemetry("convert", { ...stats, error: false }); - } catch (err) { - throw Errors.Internal("convert", err.message, { language }); - } - - console.log(output); + public async handler(argv: any) { + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.convert(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/deploy.ts b/packages/cdktf-cli/bin/cmds/deploy.ts index 31f84fce5f..5f009d80ef 100644 --- a/packages/cdktf-cli/bin/cmds/deploy.ts +++ b/packages/cdktf-cli/bin/cmds/deploy.ts @@ -1,11 +1,6 @@ import * as yargs from "yargs"; -import React from "react"; -import { Deploy } from "./ui/deploy"; import { config as cfg } from "@cdktf/provider-generator"; -import { renderInk } from "./helper/render-ink"; -import { displayVersionMessage } from "./helper/version-check"; -import { throwIfNotProjectDirectory } from "./helper/check-directory"; -import { checkEnvironment } from "./helper/check-environment"; +import { requireHandlers } from "./helper/utilities"; const config = cfg.readConfigSync(); @@ -41,22 +36,9 @@ class Command implements yargs.CommandModule { .showHelpOnFail(true); public async handler(argv: any) { - throwIfNotProjectDirectory("deploy"); - await displayVersionMessage(); - await checkEnvironment("deploy"); - const command = argv.app; - const outdir = argv.output; - const autoApprove = argv.autoApprove; - const stack = argv.stack; - - await renderInk( - React.createElement(Deploy, { - targetDir: outdir, - targetStack: stack, - synthCommand: command, - autoApprove, - }) - ); + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.deploy(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/destroy.ts b/packages/cdktf-cli/bin/cmds/destroy.ts index 7e348e7df4..22c80747ff 100644 --- a/packages/cdktf-cli/bin/cmds/destroy.ts +++ b/packages/cdktf-cli/bin/cmds/destroy.ts @@ -1,11 +1,6 @@ import * as yargs from "yargs"; -import React from "react"; -import { Destroy } from "./ui/destroy"; import { config as cfg } from "@cdktf/provider-generator"; -import { renderInk } from "./helper/render-ink"; -import { displayVersionMessage } from "./helper/version-check"; -import { throwIfNotProjectDirectory } from "./helper/check-directory"; -import { checkEnvironment } from "./helper/check-environment"; +import { requireHandlers } from "./helper/utilities"; const config = cfg.readConfigSync(); @@ -40,22 +35,9 @@ class Command implements yargs.CommandModule { .showHelpOnFail(true); public async handler(argv: any) { - throwIfNotProjectDirectory("destroy"); - await displayVersionMessage(); - await checkEnvironment("destroy"); - const command = argv.app; - const outdir = argv.output; - const autoApprove = argv.autoApprove; - const stack = argv.stack; - - await renderInk( - React.createElement(Destroy, { - targetDir: outdir, - targetStack: stack, - synthCommand: command, - autoApprove, - }) - ); + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.destroy(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/diff.ts b/packages/cdktf-cli/bin/cmds/diff.ts index bc871374f6..a82a4d53c9 100644 --- a/packages/cdktf-cli/bin/cmds/diff.ts +++ b/packages/cdktf-cli/bin/cmds/diff.ts @@ -1,11 +1,6 @@ import yargs from "yargs"; -import React from "react"; -import { Diff } from "./ui/diff"; import { config as cfg } from "@cdktf/provider-generator"; -import { renderInk } from "./helper/render-ink"; -import { displayVersionMessage } from "./helper/version-check"; -import { throwIfNotProjectDirectory } from "./helper/check-directory"; -import { checkEnvironment } from "./helper/check-environment"; +import { requireHandlers } from "./helper/utilities"; const config = cfg.readConfigSync(); @@ -36,20 +31,9 @@ class Command implements yargs.CommandModule { .showHelpOnFail(true); public async handler(argv: any) { - throwIfNotProjectDirectory("diff"); - await displayVersionMessage(); - await checkEnvironment("diff"); - const command = argv.app; - const outdir = argv.output; - const stack = argv.stack; - - await renderInk( - React.createElement(Diff, { - targetDir: outdir, - targetStack: stack, - synthCommand: command, - }) - ); + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.diff(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/get.ts b/packages/cdktf-cli/bin/cmds/get.ts index f3a31e0f1a..6f262d81e1 100644 --- a/packages/cdktf-cli/bin/cmds/get.ts +++ b/packages/cdktf-cli/bin/cmds/get.ts @@ -1,19 +1,8 @@ import yargs from "yargs"; -import React from "react"; -import { Language, LANGUAGES, config as cfg } from "@cdktf/provider-generator"; -import { Get } from "./ui/get"; -import { renderInk } from "./helper/render-ink"; -import { displayVersionMessage } from "./helper/version-check"; -import { throwIfNotProjectDirectory } from "./helper/check-directory"; -import { checkEnvironment } from "./helper/check-environment"; - +import { LANGUAGES, config as cfg } from "@cdktf/provider-generator"; +import { requireHandlers } from "./helper/utilities"; const config = cfg.readConfigSync(); -interface Arguments { - output: string; - language: Language; -} - class Command implements yargs.CommandModule { public readonly command = "get [OPTIONS]"; public readonly describe = @@ -38,33 +27,9 @@ class Command implements yargs.CommandModule { }); public async handler(argv: any) { - throwIfNotProjectDirectory("get"); - await displayVersionMessage(); - await checkEnvironment("get"); - const args = argv as Arguments; - const providers = config.terraformProviders ?? []; - const modules = config.terraformModules ?? []; - const { output, language } = args; - - const constraints: cfg.TerraformDependencyConstraint[] = [ - ...providers, - ...modules, - ]; - - if (constraints.length === 0) { - console.error( - `ERROR: Please specify providers or modules in "cdktf.json" config file` - ); - process.exit(1); - } - - await renderInk( - React.createElement(Get, { - codeMakerOutput: output, - language: language, - constraints, - }) - ); + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.get(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/handlers.ts b/packages/cdktf-cli/bin/cmds/handlers.ts new file mode 100644 index 0000000000..83fe47acc6 --- /dev/null +++ b/packages/cdktf-cli/bin/cmds/handlers.ts @@ -0,0 +1,278 @@ +import chalk from "chalk"; +import * as fs from "fs-extra"; +import React from "react"; +import yargs from "yargs"; +import { convert as hcl2cdkConvert } from "@cdktf/hcl2cdk"; +import { + readSchema, + ConstructsMakerProviderTarget, + LANGUAGES, + config as cfg, + Language, +} from "@cdktf/provider-generator"; + +import { throwIfNotProjectDirectory } from "./helper/check-directory"; +import { checkEnvironment } from "./helper/check-environment"; +import { checkForEmptyDirectory, runInit } from "./helper/init"; +import { renderInk } from "./helper/render-ink"; +import { terraformCheck } from "./helper/terraform-check"; +import * as terraformCloudClient from "./helper/terraform-cloud-client"; +import { TerraformLogin } from "./helper/terraform-login"; +import { findFileAboveCwd, readStreamAsString } from "./helper/utilities"; +import { displayVersionMessage } from "./helper/version-check"; + +import { Diff } from "./ui/diff"; +import { Deploy } from "./ui/deploy"; +import { Destroy } from "./ui/destroy"; +import { Get } from "./ui/get"; +import { List } from "./ui/list"; +import { Synth } from "./ui/synth"; +import { Watch } from "./ui/watch"; + +import { sendTelemetry } from "../../lib/checkpoint"; +import { GraphQLServerProvider } from "../../lib/client/react"; +import { Errors } from "../../lib/errors"; + +const chalkColour = new chalk.Instance(); +const config = cfg.readConfigSync(); + +export async function convert({ language }: any) { + await displayVersionMessage(); + + const providerRequirements: string[] = yargs.argv.provider as string[]; + const cdktfJsonPath = findFileAboveCwd("cdktf.json"); + if (cdktfJsonPath) { + const cdktfJson = await fs.readJson(cdktfJsonPath); + providerRequirements.push(...cdktfJson.terraformProviders); + } + // Get all the provider schemas + const { providerSchema } = await readSchema( + providerRequirements.map((spec) => + ConstructsMakerProviderTarget.from( + new cfg.TerraformProviderConstraint(spec), + LANGUAGES[0] + ) + ) + ); + + const input = await readStreamAsString(process.stdin); + let output; + try { + const { all, stats } = await hcl2cdkConvert(input, { + language, + providerSchema, + }); + output = all; + await sendTelemetry("convert", { ...stats, error: false }); + } catch (err) { + throw Errors.Internal("convert", (err as Error).message, { language }); + } + + console.log(output); +} + +export async function deploy(argv: any) { + throwIfNotProjectDirectory("deploy"); + await displayVersionMessage(); + await checkEnvironment("deploy"); + const command = argv.app; + const outdir = argv.output; + const autoApprove = argv.autoApprove; + const stack = argv.stack; + + await renderInk( + React.createElement(Deploy, { + targetDir: outdir, + targetStack: stack, + synthCommand: command, + autoApprove, + }) + ); +} + +export async function destroy(argv: any) { + throwIfNotProjectDirectory("destroy"); + await displayVersionMessage(); + await checkEnvironment("destroy"); + const command = argv.app; + const outdir = argv.output; + const autoApprove = argv.autoApprove; + const stack = argv.stack; + + await renderInk( + React.createElement(Destroy, { + targetDir: outdir, + targetStack: stack, + synthCommand: command, + autoApprove, + }) + ); +} + +export async function diff(argv: any) { + throwIfNotProjectDirectory("diff"); + await displayVersionMessage(); + await checkEnvironment("diff"); + const command = argv.app; + const outdir = argv.output; + const stack = argv.stack; + + await renderInk( + React.createElement(Diff, { + targetDir: outdir, + targetStack: stack, + synthCommand: command, + }) + ); +} + +export async function get(argv: any) { + throwIfNotProjectDirectory("get"); + await displayVersionMessage(); + await checkEnvironment("get"); + const args = argv as { + output: string; + language: Language; + }; + const providers = config.terraformProviders ?? []; + const modules = config.terraformModules ?? []; + const { output, language } = args; + + const constraints: cfg.TerraformDependencyConstraint[] = [ + ...providers, + ...modules, + ]; + + if (constraints.length === 0) { + console.error( + `ERROR: Please specify providers or modules in "cdktf.json" config file` + ); + process.exit(1); + } + + await renderInk( + React.createElement(Get, { + codeMakerOutput: output, + language: language, + constraints, + }) + ); +} + +export async function init(argv: any) { + await terraformCheck(); + await displayVersionMessage(); + await checkEnvironment("init"); + + checkForEmptyDirectory("."); + + await runInit(argv); +} + +export async function list(argv: any) { + throwIfNotProjectDirectory("list"); + await displayVersionMessage(); + await checkEnvironment("list"); + const command = argv.app; + const outdir = argv.output; + + await renderInk( + React.createElement(List, { targetDir: outdir, synthCommand: command }) + ); +} + +export async function login(argv: any) { + await terraformCheck(); + await displayVersionMessage(); + + const args = argv as yargs.Arguments; + if (args["_"].length > 1) { + console.error( + chalkColour`{redBright ERROR: 'cdktf login' command cannot have more than one argument.}\n` + ); + yargs.showHelp(); + process.exit(1); + } + + const terraformLogin = new TerraformLogin(); + const token = await terraformLogin.askToLogin(); + if (token == "") { + console.error( + chalkColour`{redBright ERROR: couldn't configure Terraform Cloud credentials.}\n` + ); + process.exit(1); + } + + // Get user details if token is set + const userAccount = await terraformCloudClient.getAccountDetails(token); + if (userAccount) { + const username = userAccount.data.attributes.username; + console.log( + chalkColour`\n{greenBright cdktf has successfully configured Terraform Cloud credentials!}` + ); + console.log(chalkColour`\nWelcome {bold ${username}}!`); + } else { + console.error( + chalkColour`{redBright ERROR: couldn't configure Terraform Cloud credentials.}\n` + ); + process.exit(1); + } +} + +export async function synth(argv: any) { + throwIfNotProjectDirectory("synth"); + await displayVersionMessage(); + await checkEnvironment("synth"); + const command = argv.app; + const outdir = argv.output; + const jsonOutput = argv.json; + const stack = argv.stack; + + if ( + config.checkCodeMakerOutput && + !(await fs.pathExists(config.codeMakerOutput)) + ) { + console.error( + `ERROR: synthesis failed, run "cdktf get" to generate providers in ${config.codeMakerOutput}` + ); + process.exit(1); + } + + await renderInk( + React.createElement(Synth, { + targetDir: outdir, + targetStack: stack, + synthCommand: command, + jsonOutput: jsonOutput, + }) + ); +} + +export async function watch(argv: any) { + throwIfNotProjectDirectory("watch"); + await displayVersionMessage(); + const command = argv.app; + const outdir = argv.output; + const autoApprove = argv.autoApprove; + const stack = argv.stack; + + if (!autoApprove) { + console.error( + chalkColour`{redBright ERROR: The watch command always automatically deploys and approves changes. To make this behaviour explicit the --auto-approve flag must be set}` + ); + process.exit(1); + } + + await renderInk( + React.createElement( + GraphQLServerProvider, + undefined, + React.createElement(Watch, { + targetDir: outdir, + targetStack: stack, + synthCommand: command, + autoApprove, + }) + ) + ); +} diff --git a/packages/cdktf-cli/bin/cmds/helper/init-templates.ts b/packages/cdktf-cli/bin/cmds/helper/init-templates.ts new file mode 100644 index 0000000000..46446e419b --- /dev/null +++ b/packages/cdktf-cli/bin/cmds/helper/init-templates.ts @@ -0,0 +1,12 @@ +import * as fs from "fs-extra"; +import * as path from "path"; +import { projectRootPath } from "./utilities"; + +export const templatesDir = path.join(projectRootPath(), "templates"); +const availableTemplates = fs + .readdirSync(templatesDir) + .filter((x) => !x.startsWith(".")); +export const templates: string[] = []; +for (const template of availableTemplates) { + templates.push(template); +} diff --git a/packages/cdktf-cli/bin/cmds/helper/init.ts b/packages/cdktf-cli/bin/cmds/helper/init.ts index 46e5633b0b..18b0c31d30 100644 --- a/packages/cdktf-cli/bin/cmds/helper/init.ts +++ b/packages/cdktf-cli/bin/cmds/helper/init.ts @@ -27,19 +27,11 @@ import { LANGUAGES, config, } from "@cdktf/provider-generator"; -import { readPackageJson, projectRootPath } from "./utilities"; +import { readPackageJson } from "./utilities"; +import { templates, templatesDir } from "./init-templates"; const chalkColour = new chalk.Instance(); -const templatesDir = path.join(projectRootPath(), "templates"); -const availableTemplates = fs - .readdirSync(templatesDir) - .filter((x) => !x.startsWith(".")); -export const templates: string[] = []; -for (const template of availableTemplates) { - templates.push(template); -} - const pkg = readPackageJson(); const constructsVersion = pkg.dependencies.constructs; diff --git a/packages/cdktf-cli/bin/cmds/helper/utilities.ts b/packages/cdktf-cli/bin/cmds/helper/utilities.ts index 4cd207c37e..e67b97d428 100644 --- a/packages/cdktf-cli/bin/cmds/helper/utilities.ts +++ b/packages/cdktf-cli/bin/cmds/helper/utilities.ts @@ -19,3 +19,55 @@ export const projectRootPath = () => { return path.dirname(pkgPath); }; + +// deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) +export const requireHandlers = () => { + // if file exists relative to this file return its file path + // otherwise return the file path relative to the project root + const filePath = path.join(__dirname, "..", "handlers.js"); + if (fs.existsSync(filePath)) { + return require(filePath); + } + return require(path.join( + projectRootPath(), + "bundle", + "bin", + "cmds", + "handlers.js" + )); +}; + +export function readStreamAsString( + stream: typeof process.stdin +): Promise { + return new Promise((ok, ko) => { + if (stream.isTTY) { + ko( + "No stdin was passed, please use it like this: cat main.tf | cdktf convert > imported.ts" + ); + } else { + let string = ""; + stream.on("data", (data) => (string += data.toString())); + + stream.on("close", () => ok(string)); + stream.on("error", (err) => ko(err)); + } + }); +} + +export function findFileAboveCwd( + file: string, + rootPath = process.cwd() +): string | null { + const fullPath = path.resolve(rootPath, file); + if (fs.existsSync(fullPath)) { + return fullPath; + } + + const parentDir = path.resolve(rootPath, ".."); + if (fs.existsSync(parentDir) && parentDir !== rootPath) { + return findFileAboveCwd(file, parentDir); + } + + return null; +} diff --git a/packages/cdktf-cli/bin/cmds/init.ts b/packages/cdktf-cli/bin/cmds/init.ts index 77c637a17e..7470b8bd46 100644 --- a/packages/cdktf-cli/bin/cmds/init.ts +++ b/packages/cdktf-cli/bin/cmds/init.ts @@ -1,9 +1,7 @@ import yargs from "yargs"; -import { terraformCheck } from "./helper/terraform-check"; -import { displayVersionMessage } from "./helper/version-check"; -import { checkForEmptyDirectory, runInit, templates } from "./helper/init"; -import { checkEnvironment } from "./helper/check-environment"; -import { readPackageJson } from "./helper/utilities"; + +import { templates } from "./helper/init-templates"; +import { readPackageJson, requireHandlers } from "./helper/utilities"; const pkg = readPackageJson(); @@ -48,13 +46,9 @@ class Command implements yargs.CommandModule { .strict(); public async handler(argv: any) { - await terraformCheck(); - await displayVersionMessage(); - await checkEnvironment("init"); - - checkForEmptyDirectory("."); - - await runInit(argv); + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.init(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/list.ts b/packages/cdktf-cli/bin/cmds/list.ts index 36504977d9..7666eb7bef 100644 --- a/packages/cdktf-cli/bin/cmds/list.ts +++ b/packages/cdktf-cli/bin/cmds/list.ts @@ -1,11 +1,6 @@ import yargs from "yargs"; -import React from "react"; -import { List } from "./ui/list"; import { config as cfg } from "@cdktf/provider-generator"; -import { renderInk } from "./helper/render-ink"; -import { displayVersionMessage } from "./helper/version-check"; -import { throwIfNotProjectDirectory } from "./helper/check-directory"; -import { checkEnvironment } from "./helper/check-environment"; +import { requireHandlers } from "./helper/utilities"; const config = cfg.readConfigSync(); @@ -28,15 +23,9 @@ class Command implements yargs.CommandModule { .showHelpOnFail(true); public async handler(argv: any) { - throwIfNotProjectDirectory("list"); - await displayVersionMessage(); - await checkEnvironment("list"); - const command = argv.app; - const outdir = argv.output; - - await renderInk( - React.createElement(List, { targetDir: outdir, synthCommand: command }) - ); + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.list(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/login.ts b/packages/cdktf-cli/bin/cmds/login.ts index 22c07fad2a..524ad1a4bd 100644 --- a/packages/cdktf-cli/bin/cmds/login.ts +++ b/packages/cdktf-cli/bin/cmds/login.ts @@ -1,11 +1,5 @@ import yargs from "yargs"; -import { TerraformLogin } from "./helper/terraform-login"; -import * as terraformCloudClient from "./helper/terraform-cloud-client"; -import * as chalk from "chalk"; -import { terraformCheck } from "./helper/terraform-check"; -import { displayVersionMessage } from "./helper/version-check"; - -const chalkColour = new chalk.Instance(); +import { requireHandlers } from "./helper/utilities"; class Command implements yargs.CommandModule { public readonly command = "login"; @@ -14,41 +8,9 @@ class Command implements yargs.CommandModule { public readonly builder = (args: yargs.Argv) => args.showHelpOnFail(true); public async handler(argv: any) { - await terraformCheck(); - await displayVersionMessage(); - - const args = argv as yargs.Arguments; - if (args["_"].length > 1) { - console.error( - chalkColour`{redBright ERROR: 'cdktf login' command cannot have more than one argument.}\n` - ); - yargs.showHelp(); - process.exit(1); - } - - const terraformLogin = new TerraformLogin(); - const token = await terraformLogin.askToLogin(); - if (token == "") { - console.error( - chalkColour`{redBright ERROR: couldn't configure Terraform Cloud credentials.}\n` - ); - process.exit(1); - } - - // Get user details if token is set - const userAccount = await terraformCloudClient.getAccountDetails(token); - if (userAccount) { - const username = userAccount.data.attributes.username; - console.log( - chalkColour`\n{greenBright cdktf has successfully configured Terraform Cloud credentials!}` - ); - console.log(chalkColour`\nWelcome {bold ${username}}!`); - } else { - console.error( - chalkColour`{redBright ERROR: couldn't configure Terraform Cloud credentials.}\n` - ); - process.exit(1); - } + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.login(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/synth.ts b/packages/cdktf-cli/bin/cmds/synth.ts index a0bb64e5e4..8544acedd9 100644 --- a/packages/cdktf-cli/bin/cmds/synth.ts +++ b/packages/cdktf-cli/bin/cmds/synth.ts @@ -1,12 +1,6 @@ import yargs from "yargs"; -import React from "react"; -import { Synth } from "./ui/synth"; import { config as cfg } from "@cdktf/provider-generator"; -import { renderInk } from "./helper/render-ink"; -import * as fs from "fs-extra"; -import { displayVersionMessage } from "./helper/version-check"; -import { throwIfNotProjectDirectory } from "./helper/check-directory"; -import { checkEnvironment } from "./helper/check-environment"; +import { requireHandlers } from "./helper/utilities"; const config = cfg.readConfigSync(); @@ -40,32 +34,9 @@ class Command implements yargs.CommandModule { .showHelpOnFail(true); public async handler(argv: any) { - throwIfNotProjectDirectory("synth"); - await displayVersionMessage(); - await checkEnvironment("synth"); - const command = argv.app; - const outdir = argv.output; - const jsonOutput = argv.json; - const stack = argv.stack; - - if ( - config.checkCodeMakerOutput && - !(await fs.pathExists(config.codeMakerOutput)) - ) { - console.error( - `ERROR: synthesis failed, run "cdktf get" to generate providers in ${config.codeMakerOutput}` - ); - process.exit(1); - } - - await renderInk( - React.createElement(Synth, { - targetDir: outdir, - targetStack: stack, - synthCommand: command, - jsonOutput: jsonOutput, - }) - ); + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.synth(argv); } } diff --git a/packages/cdktf-cli/bin/cmds/watch.ts b/packages/cdktf-cli/bin/cmds/watch.ts index f3f478583d..d85e8a928a 100644 --- a/packages/cdktf-cli/bin/cmds/watch.ts +++ b/packages/cdktf-cli/bin/cmds/watch.ts @@ -1,14 +1,6 @@ import * as yargs from "yargs"; -import React from "react"; -import { Watch } from "./ui/watch"; import { config as cfg } from "@cdktf/provider-generator"; -import { renderInk } from "./helper/render-ink"; -import * as chalk from "chalk"; -import { displayVersionMessage } from "./helper/version-check"; -import { GraphQLServerProvider } from "../../lib/client/react"; -import { throwIfNotProjectDirectory } from "./helper/check-directory"; - -const chalkColour = new chalk.Instance(); +import { requireHandlers } from "./helper/utilities"; const config = cfg.readConfigSync(); @@ -44,32 +36,9 @@ class Command implements yargs.CommandModule { .showHelpOnFail(true); public async handler(argv: any) { - throwIfNotProjectDirectory("watch"); - await displayVersionMessage(); - const command = argv.app; - const outdir = argv.output; - const autoApprove = argv.autoApprove; - const stack = argv.stack; - - if (!autoApprove) { - console.error( - chalkColour`{redBright ERROR: The watch command always automatically deploys and approves changes. To make this behaviour explicit the --auto-approve flag must be set}` - ); - process.exit(1); - } - - await renderInk( - React.createElement( - GraphQLServerProvider, - undefined, - React.createElement(Watch, { - targetDir: outdir, - targetStack: stack, - synthCommand: command, - autoApprove, - }) - ) - ); + // deferred require to keep cdktf-cli main entrypoint small (e.g. for fast shell completions) + const api = requireHandlers(); + api.watch(argv); } } diff --git a/packages/cdktf-cli/build.ts b/packages/cdktf-cli/build.ts index ea70c4587f..728fa6d69b 100644 --- a/packages/cdktf-cli/build.ts +++ b/packages/cdktf-cli/build.ts @@ -50,11 +50,15 @@ const nativeNodeModulesPlugin = { (async () => { await esbuild.build({ - entryPoints: ["./bin/cdktf.ts", "./lib/server/server.ts"], + entryPoints: [ + "./bin/cdktf.ts", + "./lib/server/server.ts", + "./bin/cmds/handlers.ts", + ], bundle: true, outdir: "./bundle", format: "cjs", - target: "node12", + target: "node14", minify: true, sourcemap: true, platform: "node", diff --git a/packages/cdktf-cli/lib/server/index.ts b/packages/cdktf-cli/lib/server/index.ts index a4afc30134..1dba5b6459 100644 --- a/packages/cdktf-cli/lib/server/index.ts +++ b/packages/cdktf-cli/lib/server/index.ts @@ -11,7 +11,7 @@ import { projectRootPath } from "../../bin/cmds/helper/utilities"; const serverLogger = getLogger("cli-server"); const loadFile = (file: string) => { - // if file exists relative ot this file return its file path + // if file exists relative to this file return its file path // otherwise return the file path relative to the project root const filePath = path.join(__dirname, file); if (fs.existsSync(filePath)) { diff --git a/packages/cdktf-cli/lib/util.ts b/packages/cdktf-cli/lib/util.ts index 143335eaa1..12195cf239 100644 --- a/packages/cdktf-cli/lib/util.ts +++ b/packages/cdktf-cli/lib/util.ts @@ -4,7 +4,7 @@ import { https, http } from "follow-redirects"; import * as os from "os"; import * as path from "path"; import { processLoggerError, processLoggerDebug } from "./logging"; -import { IManifest, Manifest } from "cdktf/lib/manifest"; +import { IManifest, Manifest } from "cdktf"; import { config } from "@cdktf/provider-generator"; export async function shell( diff --git a/packages/cdktf-cli/package.json b/packages/cdktf-cli/package.json index b7aad6428b..459b4c4cba 100644 --- a/packages/cdktf-cli/package.json +++ b/packages/cdktf-cli/package.json @@ -77,7 +77,6 @@ ] }, "devDependencies": { - "jsii-srcmak": "^0.1.448", "@apollo/client": "^3.5.7", "@cdktf/provider-generator": "0.0.0", "@graphql-tools/graphql-file-loader": "^6.2.7", @@ -134,6 +133,7 @@ "ink-use-stdout-dimensions": "^1.0.5", "inquirer": "^8.2.0", "jest": "^26.6.3", + "jsii-srcmak": "^0.1.448", "lodash.isequal": "^4.5.0", "log4js": "^6.3.0", "nock": "^13.2.2",