create-zephyr-apps
Version:
A CLI tool to create web applications using Zephyr.
159 lines (158 loc) • 6.49 kB
JavaScript
import { cancel, confirm as prompts_confirm, intro, isCancel, note, select as prompts_select, spinner, text as prompts_text } from "@clack/prompts";
import chalk_template from "chalk-template";
import node_path from "node:path";
import { setImmediate } from "node:timers/promises";
import terminal_link from "terminal-link";
import { HELP_TEXT, OperationCancelled, listTemplatesJson, parseCliArgs, resolveCliOptions, shouldUseInteractiveMode } from "./cli.js";
import { createNextSteps, formatScaffoldFailure } from "./presentation.js";
import { ScaffoldFailure, scaffoldProject } from "./scaffold.js";
import { DEFAULT_WEB_TEMPLATE, ProjectTypes, Templates } from "./templates.js";
import * as __rspack_external_node_fs_1b05aee1 from "node:fs";
async function main(args = process.argv.slice(2)) {
const jsonRequested = args.includes('--json');
let loading;
let loadingStarted = false;
try {
const parsed = parseCliArgs(args);
if (parsed.help) {
console.log(HELP_TEXT);
return 0;
}
if (parsed.version) {
console.log(await readCliVersion());
return 0;
}
if (parsed.listTemplates) {
if (parsed.json) console.log(listTemplatesJson());
else console.log(Templates.map((template)=>`${template.name.padEnd(30)} ${template.label} (${template.directory})`).join('\n'));
return 0;
}
const interactive = shouldUseInteractiveMode(parsed, {
inputIsTTY: process.stdin.isTTY,
outputIsTTY: process.stdout.isTTY
});
if (interactive) {
console.clear();
await setImmediate();
intro(chalk_template`Bootstrap your project using {cyan Zephyr}!`);
note(chalk_template`The only sane way to do micro-frontends\n{cyan https://docs.zephyr-cloud.io/}`, 'Zephyr Cloud');
}
const options = await resolveCliOptions(parsed, {
interactive,
prompts: interactive ? createPromptAdapter() : void 0
});
loading = interactive ? spinner() : void 0;
const receipt = await scaffoldProject(options, {
onProgress (_stage, message) {
if (loading) if (loadingStarted) loading.message(message);
else {
loading.start(message);
loadingStarted = true;
}
}
});
if (loadingStarted) {
loading?.stop(chalk_template`Project successfully created at {cyan ${node_path.relative(process.cwd(), receipt.directory) || './'}}!`);
loadingStarted = false;
}
if (options.json) console.log(JSON.stringify(receipt, null, 2));
else printNextSteps(receipt.directory, receipt.packageManager.name, options.projectType, options.template, options.install, options.build);
return 0;
} catch (error) {
if (loadingStarted) loading?.error('Project creation failed.');
if (error instanceof OperationCancelled) {
cancel(error.message);
return 0;
}
if (error instanceof ScaffoldFailure) {
if (jsonRequested) console.log(JSON.stringify(error.receipt, null, 2));
else cancel(formatScaffoldFailure(error));
return error.exitCode;
}
const message = error instanceof Error ? error.message : String(error);
if (jsonRequested) console.log(JSON.stringify({
success: false,
failures: [
{
stage: 'prepare',
message,
exitCode: 1
}
]
}, null, 2));
else cancel(message);
return 1;
}
}
function createPromptAdapter() {
return {
async directory () {
const value = await prompts_text({
message: 'Where should we create your project?',
placeholder: './my-app',
validate (input) {
return input?.trim() ? void 0 : 'Please enter a project name.';
}
});
return isCancel(value) ? void 0 : value;
},
async projectType () {
const value = await prompts_select({
message: 'What type of project are you creating?',
initialValue: ProjectTypes["0"].value,
options: [
...ProjectTypes
],
maxItems: 1
});
return isCancel(value) ? void 0 : value;
},
async template () {
const value = await prompts_select({
message: 'Pick a template:',
initialValue: DEFAULT_WEB_TEMPLATE,
options: Templates.map((template)=>({
value: template.name,
label: template.label,
hint: template.hint
}))
});
return isCancel(value) ? void 0 : value;
},
async initializeGit () {
const value = await prompts_confirm({
message: 'Would you like to initialize a new Git repository?',
initialValue: true
});
return isCancel(value) ? void 0 : value;
}
};
}
function printNextSteps(outputDirectory, packageManager, projectType, template, alreadyInstalled, alreadyBuilt) {
const nextSteps = createNextSteps({
outputDirectory,
invocationDirectory: process.cwd(),
packageManager,
projectType,
template,
alreadyInstalled,
alreadyBuilt
});
note(nextSteps.commands, nextSteps.commandsTitle);
if (nextSteps.guidance) note(nextSteps.guidance.body, nextSteps.guidance.title);
note(chalk_template`
- {cyan ${terminal_link('Discord', 'https://zephyr-cloud.io/discord')}}
- {cyan ${terminal_link('Documentation', nextSteps.documentationUrl)}}
- {cyan ${terminal_link('Open an issue', 'https://github.com/ZephyrCloudIO/zephyr-packages/issues')}}
`.trim(), 'Next steps.');
}
async function readCliVersion() {
const packageJson = JSON.parse(await __rspack_external_node_fs_1b05aee1.promises.readFile(new URL('../package.json', import.meta.url), 'utf8'));
return packageJson.version;
}
main().then((exitCode)=>{
process.exitCode = exitCode;
});
export { main };
//# sourceMappingURL=index.js.map