Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

create-vilo

Package Overview
Dependencies
Maintainers
0
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

create-vilo - npm Package Compare versions

Comparing version 1.0.14 to 1.0.15

438

bin/cli.js
#!/usr/bin/env node
import { program } from "commander";

@@ -14,264 +13,199 @@ import inquirer from "inquirer";

import { execSync } from "child_process";
// Get the directory name of the current module
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Update available templates to include both JS and TS versions
const availableTemplates = [
"lit",
"olova",
"preact",
"qwik",
"react",
"solid",
"svelte",
"vanilla",
"vue",
];
// Prompt for template selection
const promptForTemplate = async () => {
const questions = [
{
type: "list",
name: "template",
message: "Select a framework:",
choices: availableTemplates,
default: "olova",
},
{
type: "list",
name: "language",
message: "Select a variant:",
choices: ["JavaScript", "TypeScript"],
default: "JavaScript",
},
];
return await inquirer.prompt(questions);
};
const getTemplateFromGitHub = async (template, language) => {
const octokit = new Octokit();
const owner = "vilojs";
const repo = "vilo";
const basePath = "packages/create-vilo";
try {
// First, get the list of templates
const templatesResponse = await octokit.rest.repos.getContent({
owner,
repo,
path: basePath,
ref: "main",
});
const templateName =
language === "TypeScript"
? `template-${template}-ts`
: `template-${template}`;
const templateDir = templatesResponse.data.find(
(item) => item.name === templateName
);
if (!templateDir) {
throw new Error(`Template '${template}' not found on GitHub`);
const __filename = fileURLToPath(import.meta.url),
__dirname = dirname(__filename),
availableTemplates = [
"lit",
"olova",
"preact",
"qwik",
"react",
"solid",
"svelte",
"vanilla",
"vue",
],
promptForTemplate = async () => {
const e = [
{
type: "list",
name: "template",
message: "Select a framework:",
choices: availableTemplates,
default: "olova",
},
{
type: "list",
name: "language",
message: "Select a variant:",
choices: ["JavaScript", "TypeScript"],
default: "JavaScript",
},
];
return await inquirer.prompt(e);
},
getTemplateFromGitHub = async (e, a) => {
const t = new Octokit(),
r = "vilojs",
o = "vilo";
try {
const n = await t.rest.repos.getContent({
owner: r,
repo: o,
path: "packages/create-vilo",
ref: "main",
}),
c = "TypeScript" === a ? `template-${e}-ts` : `template-${e}`,
i = n.data.find((e) => e.name === c);
if (!i) throw new Error(`Template '${e}' not found on GitHub`);
await t.rest.repos.getContent({
owner: r,
repo: o,
path: i.path,
ref: "main",
});
const s = `https://api.github.com/repos/${r}/${o}/zipball/main`,
p = await fetch(s),
l = await p.arrayBuffer();
return { buffer: Buffer.from(l), path: i.path };
} catch (e) {
throw new Error(
`Oops! TypeScript isn’t supported for this—${e.message} try again!: `
);
}
// Now, get the content of the specific template
const templateContent = await octokit.rest.repos.getContent({
owner,
repo,
path: templateDir.path,
ref: "main",
});
// Download the template as a zip file
const zipUrl = `https://api.github.com/repos/${owner}/${repo}/zipball/main`;
const zipResponse = await fetch(zipUrl);
const arrayBuffer = await zipResponse.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
return { buffer, path: templateDir.path };
} catch (error) {
throw new Error(`Failed to fetch template from GitHub: ${error.message}`);
}
};
const validateProjectName = (projectName) => {
if (fs.existsSync(path.resolve(process.cwd(), projectName))) {
console.error(chalk.red(`Directory ${projectName} already exists`));
process.exit(1);
}
const validNameRegex = /^[a-z0-9-_]+$/i;
if (!validNameRegex.test(projectName)) {
console.error(
chalk.red(
"Project name can only contain letters, numbers, dashes and underscores"
)
);
process.exit(1);
}
};
const detectPackageManager = () => {
try {
execSync("pnpm --version", { stdio: "ignore" });
return "pnpm";
} catch {
},
validateProjectName = (e) => {
fs.existsSync(path.resolve(process.cwd(), e)) &&
(console.error(chalk.red(`Directory ${e} already exists`)),
process.exit(1));
/^[a-z0-9-_]+$/i.test(e) ||
(console.error(
chalk.red(
"Project name can only contain letters, numbers, dashes and underscores"
)
),
process.exit(1));
},
detectPackageManager = () => {
try {
execSync("yarn --version", { stdio: "ignore" });
return "yarn";
return execSync("pnpm --version", { stdio: "ignore" }), "pnpm";
} catch {
return "npm"; // Default to npm if neither pnpm nor yarn is detected
try {
return execSync("yarn --version", { stdio: "ignore" }), "yarn";
} catch {
return "npm";
}
}
}
};
const createProject = async (projectName, template, language) => {
const spinner = ora("Creating project...").start();
try {
const { buffer, path: templatePath } = await getTemplateFromGitHub(
template,
language
);
const targetPath = path.resolve(process.cwd(), projectName);
// Extract the template
const zip = new AdmZip(buffer);
const zipEntries = zip.getEntries();
const repoName = zipEntries[0].entryName.split("/")[0]; // Get the root folder name
zipEntries.forEach((entry) => {
if (entry.entryName.startsWith(`${repoName}/${templatePath}/`)) {
const relativePath = entry.entryName.replace(
`${repoName}/${templatePath}/`,
""
);
if (relativePath) {
const fullPath = path.join(targetPath, relativePath);
if (entry.isDirectory) {
fs.mkdirpSync(fullPath);
} else {
const parentDir = path.dirname(fullPath);
fs.mkdirpSync(parentDir);
fs.writeFileSync(fullPath, entry.getData());
},
createProject = async (e, a, t) => {
const r = ora("Creating project...").start();
try {
const { buffer: o, path: n } = await getTemplateFromGitHub(a, t),
c = path.resolve(process.cwd(), e),
i = new AdmZip(o).getEntries(),
s = i[0].entryName.split("/")[0];
i.forEach((e) => {
if (e.entryName.startsWith(`${s}/${n}/`)) {
const a = e.entryName.replace(`${s}/${n}/`, "");
if (a) {
const t = path.join(c, a);
if (e.isDirectory) fs.mkdirpSync(t);
else {
const a = path.dirname(t);
fs.mkdirpSync(a), fs.writeFileSync(t, e.getData());
}
}
}
});
const p = path.join(c, "package.json");
if (await fs.pathExists(p)) {
const a = await fs.readJson(p);
(a.name = e), await fs.writeJson(p, a, { spaces: 2 });
}
});
// Handle package.json if it exists
const pkgPath = path.join(targetPath, "package.json");
if (await fs.pathExists(pkgPath)) {
const pkg = await fs.readJson(pkgPath);
pkg.name = projectName;
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
const l = detectPackageManager();
if (
(r.succeed("Project created successfully!"),
console.log(chalk.green("\n✨ To get started:")),
console.log(chalk.cyan(` cd ${e}`)),
await fs.pathExists(p))
)
switch (l) {
case "pnpm":
console.log(chalk.cyan(" pnpm install")),
console.log(chalk.cyan(" pnpm run dev"));
break;
case "yarn":
console.log(chalk.cyan(" yarn")),
console.log(chalk.cyan(" yarn dev"));
break;
default:
console.log(chalk.cyan(" npm install")),
console.log(chalk.cyan(" npm run dev"));
}
} catch (e) {
r.fail("Error creating project:"),
console.error(chalk.red(e.message)),
process.exit(1);
}
const packageManager = detectPackageManager();
spinner.succeed("Project created successfully!");
console.log(chalk.green("\n✨ To get started:"));
console.log(chalk.cyan(` cd ${projectName}`));
if (await fs.pathExists(pkgPath)) {
switch (packageManager) {
case "pnpm":
console.log(chalk.cyan(" pnpm install"));
console.log(chalk.cyan(" pnpm run dev"));
break;
case "yarn":
console.log(chalk.cyan(" yarn"));
console.log(chalk.cyan(" yarn dev"));
break;
default:
console.log(chalk.cyan(" npm install"));
console.log(chalk.cyan(" npm run dev"));
},
init = async () => {
program
.name("create-vilo")
.usage("<project-name> [options]")
.argument("[project-name]", "name of the project")
.option("-t, --template <template>", "template to use")
.option(
"-l, --language <language>",
"language variant (JavaScript or TypeScript)"
)
.parse();
const e = program.opts();
let [a] = program.args,
t = e.template,
r = e.language;
if (!a) {
const { name: e } = await inquirer.prompt([
{
type: "input",
name: "name",
message: "Project name:",
validate: (e) => "" !== e.trim() || "Project name cannot be empty",
},
]);
a = e;
}
if (
(validateProjectName(a),
t &&
!availableTemplates.includes(t) &&
(console.log(
chalk.yellow(
`Template '${t}' not found. Please choose from available templates.`
)
),
(t = null)),
t)
) {
if (!r) {
const { selectedLanguage: e } = await inquirer.prompt([
{
type: "list",
name: "selectedLanguage",
message: "Select a variant:",
choices: ["JavaScript", "TypeScript"],
default: "JavaScript",
},
]);
r = e;
}
} else {
const e = await promptForTemplate();
(t = e.template), (r = e.language);
}
} catch (err) {
spinner.fail("Error creating project:");
console.error(chalk.red(err.message));
process.exit(1);
}
};
const init = async () => {
program
.name("create-vilo")
.usage("<project-name> [options]")
.argument("[project-name]", "name of the project")
.option("-t, --template <template>", "template to use")
.option(
"-l, --language <language>",
"language variant (JavaScript or TypeScript)"
)
.parse();
const options = program.opts();
let [projectName] = program.args;
let template = options.template;
let language = options.language;
// If project name is not provided, prompt for it
if (!projectName) {
const { name } = await inquirer.prompt([
{
type: "input",
name: "name",
message: "Project name:",
validate: (input) => {
if (input.trim() === "") {
return "Project name cannot be empty";
}
return true;
},
},
]);
projectName = name;
}
validateProjectName(projectName);
if (template && !availableTemplates.includes(template)) {
console.log(
chalk.yellow(
`Template '${template}' not found. Please choose from available templates.`
)
);
template = null;
}
// If template is provided, use it without prompting
if (!template) {
const answer = await promptForTemplate();
template = answer.template;
language = answer.language;
} else if (!language) {
// If template is provided but language is not, prompt only for language
const { selectedLanguage } = await inquirer.prompt([
{
type: "list",
name: "selectedLanguage",
message: "Select a variant:",
choices: ["JavaScript", "TypeScript"],
default: "JavaScript",
},
]);
language = selectedLanguage;
}
console.log(
chalk.blue(
`Creating a new ${language} project with the ${template} template...`
)
);
await createProject(projectName, template, language);
};
init().catch((err) => {
console.error(chalk.red("An unexpected error occurred:"), err);
process.exit(1);
chalk.blue(`Creating a new ${r} project with the ${t} template...`)
),
await createProject(a, t, r);
};
init().catch((e) => {
console.error(chalk.red("An unexpected error occurred:"), e), process.exit(1);
});
{
"name": "create-vilo",
"version": "1.0.14",
"version": "1.0.15",
"description": "Create projects with one command",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc