UNPKG

wxt

Version:

⚡ Next-gen Web Extension Framework

126 lines (125 loc) 4.48 kB
import { pathExists } from "./utils/fs.mjs"; import { readdir, rename } from "node:fs/promises"; import path from "node:path"; import { consola as consola$1 } from "consola"; import { styleText } from "node:util"; import prompts from "prompts"; import { downloadTemplate } from "giget"; //#region src/core/initialize.ts async function initialize(options) { consola$1.info("Initializing new project"); const templates = await listTemplates(); const defaultTemplate = templates.find((template) => template.name === options.template?.toLowerCase().trim()); const input = await prompts([ { name: "directory", type: () => options.directory == null ? "text" : void 0, message: "Project Directory", initial: options.directory }, { name: "template", type: () => defaultTemplate == null ? "select" : void 0, message: "Choose a template", choices: templates.map((template) => ({ title: TEMPLATE_COLORS[template.name] ? styleText(TEMPLATE_COLORS[template.name], template.name) : template.name, value: template })) }, { name: "packageManager", type: () => options.packageManager == null ? "select" : void 0, message: "Package Manager", choices: [ { title: styleText("magenta", "bun"), value: "bun" }, { title: styleText("red", "npm"), value: "npm" }, { title: styleText("yellow", "pnpm"), value: "pnpm" }, { title: styleText("cyan", "yarn"), value: "yarn" } ] } ], { onCancel: () => process.exit(1) }); input.directory ||= options.directory || "."; input.template ??= defaultTemplate; input.packageManager ??= options.packageManager; if (await pathExists(input.directory)) { if (!((await readdir(input.directory)).filter((dir) => dir !== ".git").length === 0)) { consola$1.error(`The directory ${path.resolve(input.directory)} is not empty. Aborted.`); process.exit(1); } } await cloneProject(input); const cdPath = path.relative(process.cwd(), path.resolve(input.directory)); console.log(); consola$1.log(`✨ WXT project created with the ${TEMPLATE_COLORS[input.template.name] ? styleText(TEMPLATE_COLORS[input.template.name], input.template.name) : input.template.name} template.`); console.log(); consola$1.log("Next steps:"); let step = 0; if (cdPath !== "") consola$1.log(` ${++step}.`, styleText("cyan", `cd ${cdPath}`)); consola$1.log(` ${++step}.`, styleText("cyan", `${input.packageManager} install`)); console.log(); } async function listTemplates() { return (await listTemplatesUngh().catch((err) => { consola$1.debug("Failed to load templates via ungh:", err); return listTemplatesGithub(); })).sort((l, r) => { const diff = (TEMPLATE_SORT_WEIGHT[l.name] ?? Number.MAX_SAFE_INTEGER) - (TEMPLATE_SORT_WEIGHT[r.name] ?? Number.MAX_SAFE_INTEGER); if (diff !== 0) return diff; return l.name.localeCompare(r.name); }); } async function listTemplatesUngh() { const res = await fetch("https://ungh.cc/repos/wxt-dev/wxt/files/main"); if (res.status !== 200) throw Error(`Request failed with status ${res.status} ${res.statusText}: ${await res.text()}`); return (await res.json()).files.map((item) => item.path.match(/templates\/(.+)\/package\.json/)?.[1]).filter((name) => name != null).map((name) => ({ name, path: `templates/${name}` })); } async function listTemplatesGithub() { const res = await fetch(`https://api.github.com/repos/${REPO}/contents/templates`, { headers: { Accept: "application/vnd.github+json" } }); if (res.status !== 200) throw Error(`Request failed with status ${res.status} ${res.statusText}: ${await res.text()}`); return await res.json(); } async function cloneProject({ directory, template }) { const { createSpinner } = await import("nanospinner"); const spinner = createSpinner("Downloading template").start(); try { await downloadTemplate(`gh:${REPO}/${template.path}`, { dir: directory, force: true }); await rename(path.join(directory, "_gitignore"), path.join(directory, ".gitignore")).catch((err) => consola$1.warn("Failed to move _gitignore to .gitignore:", err)); spinner.success(); } catch (err) { spinner.error(); throw Error(`Failed to setup new project: ${JSON.stringify(err, null, 2)}`); } } const TEMPLATE_COLORS = { vanilla: "blue", vue: "green", react: "cyan", svelte: "red", solid: "blue" }; const TEMPLATE_SORT_WEIGHT = { vanilla: 0, vue: 1, react: 2 }; const REPO = "wxt-dev/wxt"; //#endregion export { initialize };