@pixso/create-plugin
Version:
plugin template
279 lines (251 loc) • 6.82 kB
JavaScript
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();