@semo/cli
Version:
290 lines • 11.3 kB
JavaScript
import { colorize, error, info, parsePackageNames, success, warn, } from '@semo/core';
import path from 'path';
import shell from 'shelljs';
import _ from 'lodash';
import { existsSync } from 'node:fs';
export const plugin = 'semo';
export const command = 'create <name> [repo] [branch]';
export const aliases = 'c';
export const desc = 'Create a new project from specific repo';
export const builder = function (yargs) {
yargs.positional('name', {
type: 'string',
describe: 'Project name',
demandOption: true,
});
yargs.option('yes', {
default: true,
boolean: true,
alias: 'y',
describe: 'Run dep install with --yes',
});
yargs.option('force', {
boolean: true,
default: false,
alias: 'F',
describe: 'Force download, existed folder will be deleted!',
});
yargs.option('merge', {
alias: 'M',
describe: 'Merge config with exist project folder!',
});
yargs.option('empty', {
alias: 'E',
describe: 'Force empty project, ignore repo',
});
yargs.option('template', {
alias: 'T',
describe: 'Select from registered project template repos',
});
yargs.option('template-tag', {
alias: 'tag',
describe: 'Registered project template tag, work with --template',
});
yargs.option('add', {
default: false,
alias: 'A',
describe: 'Add npm package to package.json dependencies',
});
yargs.option('add-dev', {
default: false,
alias: 'D',
describe: 'Add npm package to package.json devDependencies',
});
yargs.option('init-semo', {
alias: 'i',
describe: 'Init new project',
});
yargs.option('init-git', {
default: true,
describe: 'Init a git repo',
});
};
export const handler = async function (argv) {
const scriptName = argv.scriptName || 'semo';
argv.repo = argv.repo || '';
argv.branch = argv.branch || 'main';
argv.tag = argv.tag ? _.castArray(argv.tag) : [];
try {
if (existsSync(path.resolve(process.cwd(), argv.name))) {
if (argv.force) {
shell.rm('-rf', path.resolve(process.cwd(), argv.name));
warn(`Existed ${argv.name} is deleted before creating a new one!`);
}
else if (!argv.merge) {
error(`Destination existed, command abort!`);
}
}
if (argv.merge) {
// Nothing happened.
shell.cd(argv.name);
}
else {
if (argv.template) {
// Fetch repos from hook
let repos = await argv.$core.invokeHook(`${scriptName}:create_project_template`);
// Combine repos with config
Object.assign(repos, argv.$core.getPluginConfig('create.template', {}));
if (Object.keys(repos).length === 0) {
error('No pre-defined repos available.');
}
Object.keys(repos).forEach((key) => {
if (_.isObject(repos[key])) {
repos[key].tags = repos[key].tags
? _.castArray(repos[key].tags)
: [];
if (!repos[key].name) {
repos[key].name = key.replace(/_/g, '-');
}
}
else if (_.isString(repos[key])) {
repos[key] = {
repo: repos[key],
name: key.replace(/_/g, '-'),
description: '',
branch: 'main',
tags: [],
};
}
});
if (argv.tag && argv.tag.length > 0) {
repos = _.pickBy(repos, (repo) => {
if (repo.tags) {
repo.tags = _.castArray(repo.tags);
return _.intersection(repo.tags, argv.tag).length > 0;
}
else {
return false;
}
});
}
const template = repos[argv.template]
? argv.template
: Object.keys(repos).find((key) => repos[key].name && repos[key].name.indexOf(argv.template) > -1);
if (template && repos[template]) {
argv.repo = repos[template].repo || error('Repo not found');
argv.branch = repos[template].branch || 'main';
}
else {
const answer = await argv.$prompt.select({
message: `Please choose a pre-defined repo to continue:`,
choices: Object.keys(repos).map((key) => {
return {
name: `${colorize('green', repos[key].name)} ${repos[key].tags
.map((tag) => colorize('white.bgGreen', ` ${tag} `))
.join(' ')}: ${colorize('white', repos[key].repo)}${repos[key].description ? '\n ' + repos[key].description : ''}`,
value: key,
};
}),
});
argv.repo = repos[answer].repo || error('Repo not found');
argv.branch = repos[answer].branch || 'main';
}
}
else if (argv.empty || !argv.repo) {
shell.mkdir('-p', path.resolve(process.cwd(), argv.name));
shell.cd(argv.name);
if (argv.yarn) {
if (argv.yes) {
shell.exec('yarn init -y');
}
else {
shell.exec('yarn init');
}
}
else {
if (argv.yes) {
shell.exec('npm init -y');
}
else {
shell.exec('npm init');
}
}
shell.exec(`echo "node_modules" > .gitignore`);
if (argv.initGit) {
shell.exec('git init');
success('New .git directory has been created!');
}
}
if (argv.repo && argv.name) {
info(`Downloading from ${argv.repo}`);
try {
shell.exec(`git clone ${argv.repo} ${argv.name} --single-branch --depth=1 --branch ${argv.branch} --progress`);
success('Succeeded!');
shell.cd(argv.name);
const packageFound = existsSync('package.json');
const yarnFound = existsSync('yarn.lock');
const pnpmFound = existsSync('pnpm-lock.yaml');
const npmFound = existsSync('package-lock.json');
shell.rm('-rf', path.resolve(process.cwd(), `.git`));
success('.git directory removed!');
if (packageFound) {
if (yarnFound) {
if (shell.which('yarn')) {
shell.exec('yarn');
}
else {
warn('yarn not found, use npm instead');
shell.exec('npm install');
}
}
else if (pnpmFound) {
if (shell.which('pnpm')) {
shell.exec('pnpm install');
}
else {
warn('pnpm not found, use npm instead');
shell.exec('npm install');
}
}
else if (npmFound) {
shell.exec('npm install');
}
else {
shell.exec('npm install');
}
}
if (argv.initGit) {
shell.exec('git init');
success('New .git directory has been created!');
}
}
catch (e) {
if (argv.verbose) {
error(e);
}
else {
error(e.message);
}
}
}
}
// add packages
const addPackage = parsePackageNames(argv.add);
const addPackageDev = parsePackageNames(argv.addDev);
const yarnFound = existsSync('yarn.lock');
const pnpmFound = existsSync('pnpm-lock.yaml');
const npmFound = existsSync('package-lock.json');
if (addPackage.length > 0) {
if (yarnFound) {
shell.exec(`yarn add ${addPackage.join(' ')}`);
}
else if (pnpmFound) {
shell.exec(`pnpm install ${addPackage.join(' ')}`);
}
else if (npmFound) {
shell.exec(`npm install ${addPackage.join(' ')}`);
}
}
if (addPackageDev.length > 0) {
if (yarnFound) {
shell.exec(`yarn add ${addPackageDev.join(' ')} -D`);
}
else if (pnpmFound) {
shell.exec(`pnpm install ${addPackageDev.join(' ')} --save-dev`);
}
else if (npmFound) {
shell.exec(`npm install ${addPackageDev.join(' ')} --save-dev`);
}
}
// init basic structure
if (argv.initSemo) {
let initExtra = '';
if (yarnFound) {
initExtra = '--pm yarn';
}
else if (pnpmFound) {
initExtra = '--pm pnpm';
}
else if (npmFound) {
initExtra = '--pm npm';
}
if (argv.name.indexOf(`${argv.scriptName}-plugin-`) === 0) {
shell.exec(`${argv.scriptName} init --plugin --force ${initExtra}`);
}
else {
shell.exec(`${argv.scriptName} init --force ${initExtra}`);
}
success('Initial basic structure complete!');
}
if (process.platform === 'win32') {
// TODO: fix this
}
else if (process.platform === 'darwin') {
// change package.json attributes
shell.exec(`sed -i '' 's/"name": ".*"/"name": "${argv.name}"/' package.json`);
}
else {
shell.exec(`sed -i 's/"name": ".*"/"name": "${argv.name}"/' package.json`);
}
}
catch (e) {
if (argv.verbose) {
error(e);
}
else {
error(e.message);
}
}
};
//# sourceMappingURL=create.js.map