UNPKG

create-esmx

Version:

A scaffold tool for creating Esmx projects

167 lines (161 loc) 4.97 kB
import { cancel, intro, isCancel, note, outro, select, text } from "@clack/prompts"; import minimist from "minimist"; import color from "picocolors"; import { createProjectFromTemplate } from "./project.mjs"; import { getAvailableTemplates, getEsmxVersion } from "./template.mjs"; import { formatProjectName, getCommand } from "./utils/index.mjs"; function showHelp(userAgent) { const createCmd = getCommand("create", userAgent); console.log(` ${color.reset(color.bold(color.blue("\u{1F680} Create Esmx Project")))} ${color.bold("Usage:")} ${createCmd} [project-name] ${createCmd} [project-name] [options] ${color.bold("Options:")} -t, --template <template> Template to use (default: vue2-csr) -n, --name <name> Project name or path -f, --force Force overwrite existing directory -h, --help Show help information -v, --version Show version number ${color.bold("Examples:")} ${createCmd} my-project ${createCmd} my-project -t vue2-csr ${createCmd} my-project --force ${createCmd} . -f -t vue2-csr ${color.bold("Available Templates:")} ${getAvailableTemplates().map((t) => ` ${t.folder.padEnd(25)} ${t.description}`).join("\n")} For more information, visit: ${color.cyan("https://esmx.dev")} `); } async function getProjectName(argName, positionalName) { const providedName = argName || positionalName; if (providedName) { return providedName; } const projectName = await text({ message: "Project name or path:", placeholder: "my-esmx-project", validate: (value) => { if (!value.trim()) { return "Project name or path is required"; } if (!/^[a-zA-Z0-9_./@-]+$/.test(value.trim())) { return "Project name or path should only contain letters, numbers, hyphens, underscores, dots, and slashes"; } } }); return String(projectName).trim(); } async function getTemplateType(argTemplate) { const availableTemplates = getAvailableTemplates(); if (argTemplate && availableTemplates.some((t) => t.folder === argTemplate)) { return argTemplate; } const options = availableTemplates.map((t) => ({ label: color.reset(color.gray(`${t.folder} - `) + color.bold(t.name)), value: t.folder, hint: t.description })); const template = await select({ message: "Select a template:", options }); return String(template); } export async function cli(options = {}) { const { argv, cwd, userAgent, version } = options; const commandLineArgs = argv || process.argv.slice(2); const workingDir = cwd || process.cwd(); const parsedArgs = minimist(commandLineArgs, { string: ["template", "name"], boolean: ["help", "version", "force"], alias: { t: "template", n: "name", f: "force", h: "help", v: "version" } }); if (parsedArgs.help) { showHelp(userAgent); return; } if (parsedArgs.version) { console.log(getEsmxVersion()); return; } console.log(); intro( color.reset( color.bold(color.blue("\u{1F680} Welcome to Esmx Project Creator!")) ) ); const projectNameInput = await getProjectName( parsedArgs.name, parsedArgs._[0] ); if (isCancel(projectNameInput)) { cancel("Operation cancelled"); return; } let name; let root; if (parsedArgs.name && parsedArgs._[0]) { name = parsedArgs.name; root = formatProjectName(parsedArgs._[0], workingDir).root; } else { const result = formatProjectName(projectNameInput, workingDir); name = result.name; root = result.root; } const templateType = await getTemplateType(parsedArgs.template); if (isCancel(templateType)) { cancel("Operation cancelled"); return; } const installCommand = getCommand("install", userAgent); const devCommand = getCommand("dev", userAgent); const buildCommand = getCommand("build", userAgent); const startCommand = getCommand("start", userAgent); const buildTypeCommand = getCommand("build:type", userAgent); const lintTypeCommand = getCommand("lint:type", userAgent); await createProjectFromTemplate( root, templateType, workingDir, parsedArgs.force, { projectName: name, esmxVersion: version || getEsmxVersion(), installCommand, devCommand, buildCommand, startCommand, buildTypeCommand, lintTypeCommand } ); const installCmd = installCommand; const devCmd = devCommand; const targetDirForDisplay = projectNameInput === "." ? "." : projectNameInput; const steps = [ projectNameInput !== "." ? `cd ${targetDirForDisplay}` : null, installCmd, `git init ${color.gray("(optional)")}`, devCmd ].filter(Boolean); const nextSteps = steps.map((step, index) => { return color.reset(`${index + 1}. ${color.cyan(step)}`); }); note(nextSteps.join("\n"), "Next steps"); outro(color.reset(color.green("Happy coding! \u{1F389}"))); }