diff --git a/packages/cli/src/commands/new.ts b/packages/cli/src/commands/new.ts index 0d798822e4..fa22966fac 100644 --- a/packages/cli/src/commands/new.ts +++ b/packages/cli/src/commands/new.ts @@ -13,7 +13,6 @@ import {PromptAbortedError} from "../errors/prompt-aborted" import {runPrisma} from "./prisma" export interface Flags { - js: boolean "skip-install": boolean "skip-upgrade": boolean "dry-run": boolean @@ -23,6 +22,7 @@ export interface Flags { yarn: boolean form?: string template?: string + language?: string } type PkgManager = "npm" | "yarn" | "pnpm" @@ -34,6 +34,9 @@ const PREFERABLE_PKG_MANAGER: PkgManager = IS_PNPM_INSTALLED ? "yarn" : "npm" +const LANGUAGES = ["TypeScript", "JavaScript"] +const DEFAULT_LANG = "TypeScript" + type Template = "full" | "minimal" const templates: {[key in Template]: AppGeneratorOptions["template"]} = { full: { @@ -59,10 +62,9 @@ export class New extends Command { static flags = { help: flags.help({char: "h"}), - js: flags.boolean({ - description: "Generates a JS project. TypeScript is the default unless you add this flag.", - default: false, - hidden: true, + language: flags.string({ + description: "Pick your new app language. Options: typescript, javascript.", + options: ["typescript", "javascript"], }), npm: flags.boolean({ description: "Use npm as the package manager", @@ -110,6 +112,7 @@ export class New extends Command { private pkgManager: PkgManager = PREFERABLE_PKG_MANAGER private shouldInstallDeps = true + private useTs = true private template: AppGeneratorOptions["template"] = templates.full async run() { @@ -126,6 +129,7 @@ export class New extends Command { } } + await this.determineLanguage(flags) await this.determineTemplate(flags) await this.determinePkgManagerToInstallDeps(flags) const {pkgManager, shouldInstallDeps, template} = this @@ -149,7 +153,7 @@ export class New extends Command { destinationRoot, appName, dryRun, - useTs: !flags.js, + useTs: this.useTs, yarn: pkgManager === "yarn", pnpm: pkgManager === "pnpm", form, @@ -228,7 +232,7 @@ export class New extends Command { } else { const hasPkgManagerChoice = IS_YARN_INSTALLED || IS_PNPM_INSTALLED if (hasPkgManagerChoice) { - const {pkgManager}: any = await this.enquirer.prompt({ + const {pkgManager} = (await this.enquirer.prompt({ type: "select", name: "pkgManager", message: "Install dependencies?", @@ -248,23 +252,39 @@ export class New extends Command { }, "skip", ].filter(Boolean), - }) + })) as {pkgManager: PkgManager | "skip"} if (pkgManager === "skip") { this.shouldInstallDeps = false } else { this.pkgManager = pkgManager } } else { - const {installDeps}: any = await this.enquirer.prompt({ + const {installDeps} = (await this.enquirer.prompt({ type: "confirm", name: "installDeps", message: "Install dependencies?", initial: true, - }) + })) as {installDeps: boolean} this.shouldInstallDeps = installDeps } } } + + private async determineLanguage(flags: Flags): Promise { + if (flags.language) { + this.useTs = flags.language === "typescript" + } else { + const {language} = (await this.enquirer.prompt({ + type: "select", + name: "language", + message: "Pick a new project's language", + initial: LANGUAGES.indexOf(DEFAULT_LANG), + choices: LANGUAGES, + })) as {language: typeof LANGUAGES[number]} + this.useTs = language === "TypeScript" + } + } + private async determineFormLib(flags: Flags): Promise> { if (flags.form) { switch (flags.form) { @@ -285,12 +305,12 @@ export class New extends Command { {name: "Formik"}, ] - const promptResult: any = await this.enquirer.prompt({ + const promptResult = (await this.enquirer.prompt({ type: "select", name: "form", message: "Pick a form library (you can switch to something else later if you want)", choices: formChoices, - }) + })) as {form: typeof formChoices[number]["name"]} return promptResult.form } private async determineTemplate(flags: Flags): Promise { @@ -383,12 +403,12 @@ export class New extends Command { }, ] - const promptResult: any = await this.enquirer.prompt({ + const promptResult = (await this.enquirer.prompt({ type: "select", name: "upgrade", message: "Your global blitz version is outdated. Upgrade?", choices: upgradeChoices, - }) + })) as {upgrade: typeof upgradeChoices[number]["name"]} return promptResult.upgrade === "yes" } diff --git a/packages/cli/test/commands/new.test.ts b/packages/cli/test/commands/new.test.ts index 8ef7024613..a2f29b6f04 100644 --- a/packages/cli/test/commands/new.test.ts +++ b/packages/cli/test/commands/new.test.ts @@ -202,6 +202,30 @@ describe("`new` command", () => { }) }) + testIfNotWindows("generates javascript app with --language=javascript flag", async () => { + await withNewApp(["--language=javascript", "--template=minimal"], (dirName, packageJson) => { + const { + devDependencies: {typescript}, + } = packageJson + + expect(typescript).toBeUndefined() + + expect(fs.existsSync(path.join(dirName, "jsconfig.json"))).toBe(true) + }) + }) + + testIfNotWindows("generates typescript app with --language=typescript flag", async () => { + await withNewApp(["--language=typescript", "--template=minimal"], (dirName, packageJson) => { + const { + devDependencies: {typescript}, + } = packageJson + + expect(typescript).not.toBeUndefined() + + expect(fs.existsSync(path.join(dirName, "tsconfig.json"))).toBe(true) + }) + }) + testIfNotWindows("accepts --dry-run flag and doesn't create files", async () => { const newAppDir = fs.mkdtempSync(path.join(tempDir, "full-install-")) await whileStayingInCWD(() => New.run([newAppDir, "--skip-upgrade", "--dry-run"]))