UNPKG

@pixso/create-plugin

Version:

plugin template

279 lines (251 loc) 6.82 kB
#!/usr/bin/env node const fs = require("fs"); const path = require("path"); const prompts = require("prompts"); const fse = require("fs-extra"); const { blue, green, yellow, cyan, magenta, red, reset } = require("kolorist"); const rimraf = require("rimraf"); const argv = require("minimist")(process.argv.slice(2), { string: ["_"] }); const cwd = process.cwd(); const FRAMEWORKS = [ { name: "vue", display: "Vue", color: green, variants: [ { name: "vue-ts", display: "TypeScript", color: blue, }, { name: "vue", display: "JavaScript", color: yellow, }, ], }, { name: "react", display: "React", color: cyan, variants: [ { name: "react-ts", display: "TypeScript", color: blue, }, { name: "react", display: "JavaScript", color: yellow, }, ], }, { name: "preact", display: "Preact", color: magenta, variants: [ { name: "preact-ts", display: "TypeScript", color: blue, }, { name: "preact", display: "JavaScript", color: yellow, }, ], }, { name: "svelte", display: "Svelte", color: red, variants: [ { name: "svelte-ts", display: "TypeScript", color: blue, }, { name: "svelte", display: "JavaScript", color: yellow, }, ], }, ]; const TEMPLATES = FRAMEWORKS.map( (f) => (f.variants && f.variants.map((v) => v.name)) || [f.name] ).reduce((a, b) => a.concat(b), []); function isEmpty(path) { return fs.readdirSync(path).length === 0; } function isValidPackageName(projectName) { return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test( projectName ); } function toValidPackageName(projectName) { return projectName .trim() .toLowerCase() .replace(/\s+/g, "-") .replace(/^[._]/, "") .replace(/[^a-z\d\-~]+/g, "-"); } function pkgFromUserAgent(userAgent) { if (!userAgent) return undefined; const pkgSpec = userAgent.split(" ")[0]; const pkgSpecArr = pkgSpec.split("/"); return { name: pkgSpecArr[0], version: pkgSpecArr[1], }; } async function init() { let targetDir = argv._[0]; let argTemplate = argv.template || argv.t; const defaultProjectName = !targetDir ? "pixso-plugin-project" : targetDir; let result; try { result = await prompts( [ { type: targetDir ? null : "text", name: "projectName", message: "Project name:", initial: defaultProjectName, onState: (state) => (targetDir = state.value.trim() || defaultProjectName), }, { type: () => !fs.existsSync(targetDir) || isEmpty(targetDir) ? null : "confirm", name: "overwrite", message: () => (targetDir === "." ? "Current directory" : `Target directory "${targetDir}"`) + ` is not empty. Remove existing files and continue?`, }, { type: (_, { overwrite } = {}) => { if (overwrite === false) { throw new Error(red("✖") + " Operation cancelled"); } return null; }, name: "overwriteChecker", }, { type: () => (isValidPackageName(targetDir) ? null : "text"), name: "packageName", message: "Package name:", initial: () => toValidPackageName(targetDir), validate: (dir) => isValidPackageName(dir) || "Invalid package.json name", }, { type: argTemplate && TEMPLATES.includes(argTemplate) ? null : "select", name: "framework", message: typeof argTemplate === "string" && !TEMPLATES.includes(argTemplate) ? reset( `"${argTemplate}" isn't a valid template. Please choose from below: ` ) : reset("Select a framework:"), initial: 0, choices: FRAMEWORKS.map((framework) => { const frameworkColor = framework.color; return { title: frameworkColor(framework.display || framework.name), value: framework, }; }), }, { type: (framework) => framework && framework.variants ? "select" : null, name: "variant", message: reset("Select a variant:"), choices: (framework) => framework.variants.map((variant) => { const variantColor = variant.color; return { title: variantColor(variant.display || variant.name), value: variant.name, }; }), }, { type: "confirm", name: "containsHostScript", message: "Contains host script? (which will run in pixso host environment)", active: "yes", inactive: "no", }, ], { onCancel: () => { throw new Error(red("✖") + " Operation cancelled"); }, } ); } catch (cancelled) { console.log(cancelled.message); return; } const { overwrite, packageName, variant, containsHostScript } = result; // todo const root = path.join(cwd, targetDir); if (overwrite) { fse.emptyDirSync(root); } else if (!fs.existsSync(root)) { fs.mkdirSync(root); } argTemplate = variant || template; const templateDir = path.join(__dirname, `template-${argTemplate}`); fse.copySync(templateDir, root); const pkg = require(path.join(root, "package.json")); pkg.name = packageName || targetDir; if (containsHostScript) { const manifest = require(path.join(root, "manifest.json")); manifest.main = { sandbox: manifest.main, host: "dist/host.js", }; fs.writeFileSync( path.join(root, "manifest.json"), JSON.stringify(manifest, null, 2) ); } else { rimraf.sync( path.join(root, `host.${variant.endsWith("-ts") ? "ts" : "js"}`) ); } fs.writeFileSync( path.join(root, "package.json"), JSON.stringify(pkg, null, 2) ); const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent); const pkgManager = pkgInfo ? pkgInfo.name : "npm"; console.log(`\nDone. Now run:\n`); if (root !== cwd) { console.log(` cd ${path.relative(cwd, root)}`); } switch (pkgManager) { case "yarn": console.log(" yarn"); console.log(" yarn dev"); break; default: console.log(` ${pkgManager} install`); console.log(` ${pkgManager} run dev`); break; } } init();