常用工具
具体使用
cli.js
import arg from 'arg';
import inquirer from 'inquirer'
import { createProject } from './main'
function parseArgumentsIntoOptions(rawArgs) {
const args = arg(
{
'--git': Boolean,
'--yes': Boolean,
'--install': Boolean,
'-g': '--git',
'-y': '--yes',
'-i': '--install',
},
{
argv: rawArgs.slice(2),
}
)
return {
skipPrompts: args['--yes'] || false,
git: args['--git'] || false,
template: args._[0],
runInstall: args['--install'] || false,
}
}
async function promptForMissingOptions(options) {
const defaultTemplate = 'JavaScript';
if (options.skipPrompts) {
return {
...options,
template: options.template || defaultTemplate,
};
}
const questions = [];
if (!options.template) {
questions.push({
type: 'list',
name: 'template',
message: 'Please choose which project template to use',
choices: ['JavaScript', 'TypeScript'],
default: defaultTemplate,
});
}
if (!options.git) {
questions.push({
type: 'confirm',
name: 'git',
message: 'Initialize a git repository?',
default: false,
});
}
const answers = await inquirer.prompt(questions);
return {
...options,
template: options.template || answers.template,
git: options.git || answers.git,
};
}
export async function cli(args) {
let options = parseArgumentsIntoOptions(args)
options = await promptForMissingOptions(options)
console.log(options)
await createProject(options)
}
main.js
import chalk from 'chalk'
import fs from 'fs'
import ncp from 'ncp'
import path from 'path'
import { promisify } from 'util'
import execa from 'execa'
import Listr from 'listr'
import { projectInstall } from 'pkg-install'
const access = promisify(fs.access)
const copy = promisify(ncp)
async function copyTemplateFiles(options) {
return copy(options.templateDirectory, options.targetDirectory, {
clobber: false,
})
}
async function initGit(options) {
const result = await execa('git', ['init'], {
cwd: options.targetDirectory,
})
if (result.failed) {
return Promise.reject(new Error('Failed to initialize git'))
}
return
}
export async function createProject(options) {
options = {
...options,
targetDirectory: options.targetDirectory || process.cwd()
}
const templateDir = path.resolve(new URL(import.meta.url).pathname,'../../templates',options.template)
options.templateDirectory = templateDir
try {
await access(templateDir, fs.constants.R_OK)
} catch (err) {
console.error('%s Invalid template name', chalk.red.bold('ERROR'))
process.exit(1)
}
const tasks = new Listr([
{
title: 'Copy project files',
task: () => copyTemplateFiles(options),
},
{
title: 'Initialize git',
task: () => initGit(options),
enabled: () => options.git,
},
{
title: 'Install dependencies',
task: () =>
projectInstall({
cwd: options.targetDirectory,
}),
skip: () =>
!options.runInstall
? 'Pass --install to automatically install dependencies'
: undefined,
},
])
await tasks.run()
console.log('%s Project ready', chalk.green.bold('DONE'))
return true
}