定义Context执行上下文类型
src/init/types.d.ts
/**
* cli配置对象
*/
export interface Options {
/**
* 是否强制写入
* @default false
*/
force?: boolean
/**
* 是否从本地缓存读取模板
* @default false
*/
offline?: boolean
}
/**
* 上下文对象
*/
export interface Context {
/**
* 模板名称
*/
readonly template: string
/**
* 项目名称
*/
readonly project: string
/**
* 配置选项,大多数情况下都来自CLI
*/
readonly options: Options
/**
* 模板所在的源目录(绝对)
*/
src: string
/**
* 生成的结果输出目标目录(绝对)。
*/
dest: string
/**
* 此处关于模板配置的内容并未定义,后续在继续定义
* @todu readonly config
* @todu readonly answers
* @todu readonly files
*/
readonly config: object
readonly answers: object
readonly files: []
}
改写init
src/init/index.ts
import { Ware } from '../core/ware'
import { Context, Options } from './types'
/**
* Ware实例
*/
const creator = new Ware<Context>()
// 通过注入中间件在回调函数中打印当前上下文对象
creator.use(async (context) => {
console.log(context)
})
/**
* CLI 主函数部分
* @param template 模板路径
* @param project 项目名称
* @param options 配置选项
*/
export const init = async (template: string, project = '.', options: Options = {}): Promise<void> => {
if (template == null || template === '') {
throw new Error('Missing required argument: `template`.')
}
const context: Context = {
template,
project,
options,
src: '',
dest: '',
config: Object.create(null),
answers: Object.create(null),
files: []
}
try {
creator.run(context)
} catch (error) {
}
}
改写cli
src/cli.ts
import cac from 'cac'
// 从package.json中获取版本及名字
import { name, version } from '../package.json'
import { init } from './index'
// 实例化cac
const cli = cac(name)
/**
* 定义异常处理公共函数
* @param err
*/
const onError = (err: Error): void => {
console.error(err.message)
process.exit(1)
}
// 监听未捕获的异常事件
process.on('uncaughtException', onError)
// 监听Promise未捕获的异常事件
process.on('unhandledRejection', onError)
cli
// 添加命令 ‘<>’ 中为必填项,'[]'中为选填项
.command('<template> [project]', 'Create new project from a template')
// 添加配置 --force 简写为 -f;
// 如果目标存在则覆盖
.option('-f, --force', 'Overwrite if the target exists')
// 添加配置 --offline 简写为 -o ;
// 是否使用本地模板
.option('-o, --offline', 'Try to use an offline template')
// 示例内容配置
.example(' # with an official template')
.example(` $ ${name} <template> [project]`)
.example(' # with a custom github repo')
.example(` $ ${name} <owner>/<repo> [project]`)
// 定义一个动作,传入一个回调函数
.action(init)
// -h, --help出现标志时输出帮助信息。
cli.help()
// -v, --version 出现标志时输出版本号。
cli.version(version)
cli.parse()
测试运行
<projectName> template project -f -o
# 输出结果,成功打印出执行上下文对象
{
template: 'template',
project: 'project',
options: { '--': [], f: true, o: true, force: true, offline: true },
src: '',
dest: '',
config: [Object: null prototype] {},
answers: [Object: null prototype] {},
files: []
}