一个微生成器项目为一个模块项目或者一个 Npm 包,包中包含几个基本部分:
npm 包描述信息,包含 name、version、main 等字段。
上述 main 字段对应的 js 文件。文件为默认导出一个生成器函数,函数格式如下:
export default async (
context: GeneratorContext,
generator: GeneratorCore,
) => {};
该函数参数为 context 和 generator:
context 提供 codesmith 运行时维护的上下文信息。其类型定义为:
interface GeneratorContext {
materials: Record<string, FsMaterial>; // 资源
config: Record<string, any>; // 用户 config 配置
data?: Record<string, any>; // 用户 data 配置
current: { material: FsMaterial } | null; // 当前生成器运行可获取的文件资源
[key: string]: any; // 其他补充字段
}
materials 是 codesmith 的抽象文件系统,维护这生成器名称和可操作文件的映射关系。
materials 中还维护这一个 default 的映射关系,用于维护当前生成器执行目录的资源信息,通过该字段可以对目标项目资源进行操作。
例如当需要修改当前项目的 package.json
中的字段:
const resource = context.materials.default.get(
path.join(appDir, 'package.json'),
);
将获取到的 resource 传递给 codesmith 提供的 JSON API 即可实现 json 操作。
GeneratorContext 的 current 字段上维护这当前运行的生成器文件资源,可以通过 current.material
获取到当前的 FsMaterial
.
FsMaterial 中提供了 get 方法用于获取资源文件并将资源文件传给生成器支持的 API 即可对模板文件进行处理。
例如:
const resourceMap = await material.find('templates/**/*');
通过上述方式可以获取到生成器中符合 templates/**/*
规则的所有模板文件,遍历该对象即可对资源文件进行操作。
generator 提供 codesmith 运行时的函数方法。其类型定义为:
interface GeneratorCore {
logger: Logger; // log 函数,支持 info、warning、debug、error、verbose、stream
outputPath: string; // 输出文件路径
output: {
fs: (file: string | number, data: any, options?: string | fs.WriteFileOptions | undefined) => Promise<void>
}; // 写文件方法
runSubGenerator: (subGenerator: string, relativePwdPath?: string | undefined, config?: Record<string, any> | undefined): Promise<void> // 运行子生成器
}
其中 outputPath 和 context 中的 materials.default
指向相同的目录,outputPath 用于直接计算目标路径并操作,materials.default
用于获取资源文件。
runSubGenerator 提供了在一个微生成器中去运行其他微生成器的方法,该方法将自动更新和维护新的 context 上下文信息。
生成器模板文件。
推荐在项目根目录创建一个 templates 目录,用于维护该微生成器的模板文件,微生成器执行过程中只能使用自身的模板文件,对于需要共用的模板文件,建议通过共用子生成器实现。