Last active
August 12, 2022 13:27
-
-
Save IlCallo/288ccdc2cac782854bb4d78783389fd5 to your computer and use it in GitHub Desktop.
Run a "create" command on the CLI and programmatically answer it's prompts. Check out https://github.com/dreamonkey/cli-ghostwriter which has been derived from this example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { spawn } from "node:child_process"; | |
export type SupportedPackageManager = "npm" | "yarn" | "pnpm"; | |
export const ACCEPT_DEFAULT = "ACCEPT_DEFAULT"; | |
export const ENTER_KEY = "\n"; | |
export const WHITESPACE_KEY = " "; | |
// Octals literals are banned into ESM | |
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Deprecated_octal#octal_escape_sequences | |
export const DOWN_KEY = "\u001b[B"; | |
interface CreateParams { | |
packageManager: SupportedPackageManager; | |
packageName: string; | |
answersMap: Record<string, string | undefined>; | |
endingMarker: string; | |
enableLogs?: boolean; | |
} | |
export function cliCreate({ | |
packageManager, | |
packageName, | |
answersMap, | |
endingMarker, | |
enableLogs, | |
}: CreateParams) { | |
enableLogs = enableLogs ?? false; | |
return new Promise<void>((resolve, reject) => { | |
const childProcess = spawn(packageManager, ["create", packageName], { | |
cwd: process.cwd(), | |
stdio: "pipe", | |
shell: true, | |
}); | |
childProcess.stdout.setEncoding("utf8"); | |
childProcess.stdout.on("data", (data: string) => { | |
if (data.includes(endingMarker)) { | |
childProcess.stdin.end(); | |
} | |
enableLogs && console.log("prompt:", data); | |
for (const question in answersMap) { | |
if (data.includes(question)) { | |
const answer = answersMap[question]; | |
enableLogs && console.log("answer:", answer); | |
// To accept the default value we just need to press enter, | |
// so we aren't going to write the answer | |
if (!!answer && answer !== ACCEPT_DEFAULT) { | |
childProcess.stdin.write(answer); | |
} | |
childProcess.stdin.write(ENTER_KEY); | |
// If we don't remove the question once used, we'd match the line showing | |
// the question after it has been answered too, generating erratic behavior | |
delete answersMap[question]; | |
break; | |
} | |
} | |
}); | |
childProcess.on("exit", (code) => { | |
console.log(); | |
if (code) { | |
console.log(` Creation FAILED...`); | |
console.log(); | |
reject(); | |
} else { | |
resolve(); | |
} | |
}); | |
}); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ACCEPT_DEFAULT, cliCreate, DOWN_KEY, WHITESPACE_KEY } from "./cli-create"; | |
// Test this with `create-quasar` | |
const answersMap: Record<string, string | undefined> = { | |
"What would you like to build?": ACCEPT_DEFAULT, // App | |
"Project folder": "my-project-folder", | |
"Remove existing files and continue?": "y", | |
"Pick Quasar version": ACCEPT_DEFAULT, // Qv2 | |
"Pick script type": DOWN_KEY, // TypeScript | |
"Pick Quasar App CLI variant": ACCEPT_DEFAULT, // Webpack | |
"Package name": "my-project", | |
"Project product name": "My Project", | |
"Project description": "", | |
Author: ACCEPT_DEFAULT, | |
"Pick a Vue component style": DOWN_KEY, // composition-setup | |
"Pick your CSS preprocessor": ACCEPT_DEFAULT, // SCSS | |
"Check the features needed for your project": `${DOWN_KEY}${WHITESPACE_KEY}${DOWN_KEY}${DOWN_KEY}${WHITESPACE_KEY}`, // checks: ESLint (default), Pinia, Axios | |
"Pick an ESLint preset": ACCEPT_DEFAULT, // prettier | |
"Install project dependencies?": DOWN_KEY, // No | |
}; | |
await cliCreate({ | |
packageManager: "pnpm", | |
packageName: "quasar", | |
answersMap, | |
endingMarker: "Enjoy! - Quasar Team", | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment