@longzai-intelligence-templates/template-engine 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$prod.log +5 -0
- package/.turbo/turbo-build.log +33 -0
- package/.turbo/turbo-lint.log +11 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +43 -0
- package/README.md +15 -0
- package/dist/index.d.ts +271 -0
- package/dist/index.js +1 -0
- package/docs/overview.md +23 -0
- package/lzi-builder.config.ts +6 -0
- package/lzi-dev.config.ts +10 -0
- package/oxlint.config.ts +6 -0
- package/package.json +32 -0
- package/src/engine.utils.ts +190 -0
- package/src/generator.service.ts +150 -0
- package/src/index.ts +39 -0
- package/src/loader.service.ts +185 -0
- package/src/template.schema.ts +194 -0
- package/tsconfig/.cache/build.tsbuildinfo +1 -0
- package/tsconfig/.cache/node.tsbuildinfo +1 -0
- package/tsconfig/.cache/test.tsbuildinfo +1 -0
- package/tsconfig/app.json +13 -0
- package/tsconfig/build.json +15 -0
- package/tsconfig/node.json +12 -0
- package/tsconfig/test.json +15 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 文件生成器
|
|
3
|
+
*
|
|
4
|
+
* 将模板文件渲染到目标目录
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { TemplateFile, TemplateMeta } from './template.schema';
|
|
8
|
+
|
|
9
|
+
import { replaceVariables, resolveDestinationPath, type VariableValues } from './engine.utils';
|
|
10
|
+
import { readTemplateFile } from './loader.service';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 生成结果项
|
|
14
|
+
*/
|
|
15
|
+
export type GeneratedFile = {
|
|
16
|
+
/**
|
|
17
|
+
* 目标文件路径
|
|
18
|
+
*/
|
|
19
|
+
destination: string;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 是否跳过(条件不满足)
|
|
23
|
+
*/
|
|
24
|
+
skipped: boolean;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 是否为可执行文件
|
|
28
|
+
*/
|
|
29
|
+
executable: boolean;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 预览将要生成的文件列表
|
|
34
|
+
*
|
|
35
|
+
* @param meta - 模板元数据
|
|
36
|
+
* @param variables - 变量值映射
|
|
37
|
+
* @returns 生成结果预览
|
|
38
|
+
*/
|
|
39
|
+
export const previewGeneration = (
|
|
40
|
+
meta: TemplateMeta,
|
|
41
|
+
variables: VariableValues,
|
|
42
|
+
): GeneratedFile[] => {
|
|
43
|
+
return meta.files.map((file) => {
|
|
44
|
+
/**
|
|
45
|
+
* 该文件的生成条件是否满足
|
|
46
|
+
*/
|
|
47
|
+
const conditionMet = checkCondition(file, variables);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 变量替换后的目标文件路径
|
|
51
|
+
*/
|
|
52
|
+
const destination = resolveDestinationPath(file.destination, variables);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
destination,
|
|
56
|
+
skipped: !conditionMet,
|
|
57
|
+
executable: file.executable,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 检查文件的条件是否满足
|
|
64
|
+
*
|
|
65
|
+
* @param file - 模板文件定义
|
|
66
|
+
* @param variables - 变量值映射
|
|
67
|
+
* @returns 条件是否满足
|
|
68
|
+
*/
|
|
69
|
+
const checkCondition = (file: TemplateFile, variables: VariableValues): boolean => {
|
|
70
|
+
if (!file.condition) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 条件变量对应的值,真值时保留该文件
|
|
76
|
+
*/
|
|
77
|
+
const value = variables[file.condition];
|
|
78
|
+
if (typeof value === 'boolean') {
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
if (typeof value === 'string') {
|
|
82
|
+
return value !== '' && value !== 'false';
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 生成模板文件到目标目录
|
|
89
|
+
*
|
|
90
|
+
* @param templateDir - 模板目录路径
|
|
91
|
+
* @param meta - 模板元数据
|
|
92
|
+
* @param variables - 变量值映射
|
|
93
|
+
* @param outputDir - 输出目录路径
|
|
94
|
+
* @param dryRun - 是否仅预览
|
|
95
|
+
* @returns 生成的文件列表
|
|
96
|
+
*/
|
|
97
|
+
export const generateFiles = async (
|
|
98
|
+
templateDir: string,
|
|
99
|
+
meta: TemplateMeta,
|
|
100
|
+
variables: VariableValues,
|
|
101
|
+
outputDir: string,
|
|
102
|
+
dryRun: boolean = false,
|
|
103
|
+
): Promise<GeneratedFile[]> => {
|
|
104
|
+
/**
|
|
105
|
+
* 每个模板文件的处理结果集合
|
|
106
|
+
*/
|
|
107
|
+
const results: GeneratedFile[] = [];
|
|
108
|
+
|
|
109
|
+
for (const file of meta.files) {
|
|
110
|
+
/**
|
|
111
|
+
* 该文件的生成条件是否满足
|
|
112
|
+
*/
|
|
113
|
+
const conditionMet = checkCondition(file, variables);
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 变量替换后的目标文件路径
|
|
117
|
+
*/
|
|
118
|
+
const destination = resolveDestinationPath(file.destination, variables);
|
|
119
|
+
|
|
120
|
+
if (!conditionMet) {
|
|
121
|
+
results.push({ destination, skipped: true, executable: file.executable });
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (dryRun) {
|
|
126
|
+
results.push({ destination, skipped: false, executable: file.executable });
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 读取模板文件内容
|
|
132
|
+
*/
|
|
133
|
+
const content = await readTemplateFile(templateDir, file.source);
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* 替换变量
|
|
137
|
+
*/
|
|
138
|
+
const rendered = replaceVariables(content, variables);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 写入目标文件
|
|
142
|
+
*/
|
|
143
|
+
const fullPath = `${outputDir}/${destination}`;
|
|
144
|
+
await Bun.write(fullPath, rendered);
|
|
145
|
+
|
|
146
|
+
results.push({ destination, skipped: false, executable: file.executable });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return results;
|
|
150
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @longzai-intelligence-templates/template-engine
|
|
3
|
+
*
|
|
4
|
+
* 模板引擎核心包,提供模板变量替换、文件生成和模板加载功能。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
TemplateMetaSchema,
|
|
9
|
+
TemplateVariableSchema,
|
|
10
|
+
TemplateFileSchema,
|
|
11
|
+
BUILTIN_VARIABLES,
|
|
12
|
+
type TemplateMeta,
|
|
13
|
+
type TemplateCategory,
|
|
14
|
+
type VariableType,
|
|
15
|
+
type TemplateVariable,
|
|
16
|
+
type TemplateFile,
|
|
17
|
+
type BuiltinVariable,
|
|
18
|
+
} from './template.schema';
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
replaceVariables,
|
|
22
|
+
parseVariableValue,
|
|
23
|
+
validateVariable,
|
|
24
|
+
buildBuiltinVariables,
|
|
25
|
+
mergeVariableValues,
|
|
26
|
+
resolveDestinationPath,
|
|
27
|
+
type VariableValues,
|
|
28
|
+
} from './engine.utils';
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
loadTemplateMeta,
|
|
32
|
+
loadAllTemplates,
|
|
33
|
+
readTemplateFile,
|
|
34
|
+
filterByCategory,
|
|
35
|
+
searchTemplates,
|
|
36
|
+
findTemplateById,
|
|
37
|
+
} from './loader.service';
|
|
38
|
+
|
|
39
|
+
export { previewGeneration, generateFiles, type GeneratedFile } from './generator.service';
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模板加载器
|
|
3
|
+
*
|
|
4
|
+
* 从文件系统加载模板定义和模板文件
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync } from 'node:fs';
|
|
8
|
+
|
|
9
|
+
import { type TemplateMeta, TemplateMetaSchema } from './template.schema';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 从目录加载模板元数据
|
|
13
|
+
*
|
|
14
|
+
* @param templateDir - 模板目录路径
|
|
15
|
+
* @returns 模板元数据
|
|
16
|
+
* @throws {@link Error} 元数据文件内容未通过 Schema 校验时抛出(含校验错误详情)
|
|
17
|
+
*/
|
|
18
|
+
export const loadTemplateMeta = async (templateDir: string): Promise<TemplateMeta> => {
|
|
19
|
+
/**
|
|
20
|
+
* 模板元数据文件路径,固定为目录下的 template.json
|
|
21
|
+
*/
|
|
22
|
+
const metaPath = `${templateDir}/template.json`;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 元数据文件句柄
|
|
26
|
+
*/
|
|
27
|
+
const file = Bun.file(metaPath);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 解析后的元数据 JSON 内容
|
|
31
|
+
*/
|
|
32
|
+
const content = await file.json();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Schema 校验结果,失败时抛出携带校验详情的错误
|
|
36
|
+
*/
|
|
37
|
+
const parsed = TemplateMetaSchema.safeParse(content);
|
|
38
|
+
if (!parsed.success) {
|
|
39
|
+
throw new Error(`模板元数据校验失败(${metaPath}): ${parsed.error.message}`);
|
|
40
|
+
}
|
|
41
|
+
return parsed.data;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 加载目录下所有模板的元数据
|
|
46
|
+
*
|
|
47
|
+
* @param templatesRoot - 模板根目录路径
|
|
48
|
+
* @returns 模板元数据数组
|
|
49
|
+
*/
|
|
50
|
+
export const loadAllTemplates = async (templatesRoot: string): Promise<TemplateMeta[]> => {
|
|
51
|
+
/**
|
|
52
|
+
* 模板分类目录名列表,与模板仓库的目录划分一一对应
|
|
53
|
+
*/
|
|
54
|
+
const categories = ['projects', 'apps', 'packages', 'domains', 'configs', 'docs', 'adapters'];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 收集到的全部模板元数据
|
|
58
|
+
*/
|
|
59
|
+
const templates: TemplateMeta[] = [];
|
|
60
|
+
|
|
61
|
+
for (const category of categories) {
|
|
62
|
+
/**
|
|
63
|
+
* 当前分类目录的完整路径
|
|
64
|
+
*/
|
|
65
|
+
const categoryDir = `${templatesRoot}/${category}`;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 分类目录存在性,缺失的分类静默跳过
|
|
69
|
+
*/
|
|
70
|
+
const categoryExists = existsSync(categoryDir);
|
|
71
|
+
if (!categoryExists) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 扫描分类目录下子目录用的 glob 匹配器
|
|
77
|
+
*/
|
|
78
|
+
const glob = new Bun.Glob('*');
|
|
79
|
+
|
|
80
|
+
for await (const dir of glob.scan({ cwd: categoryDir, onlyFiles: false })) {
|
|
81
|
+
/**
|
|
82
|
+
* 当前候选模板的元数据文件路径
|
|
83
|
+
*/
|
|
84
|
+
const metaPath = `${categoryDir}/${dir}/template.json`;
|
|
85
|
+
try {
|
|
86
|
+
/**
|
|
87
|
+
* 候选元数据文件句柄
|
|
88
|
+
*/
|
|
89
|
+
const file = Bun.file(metaPath);
|
|
90
|
+
if (await file.exists()) {
|
|
91
|
+
/**
|
|
92
|
+
* 解析后的元数据 JSON 内容
|
|
93
|
+
*/
|
|
94
|
+
const content = await file.json();
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Schema 校验结果,未通过的模板静默跳过
|
|
98
|
+
*/
|
|
99
|
+
const parsed = TemplateMetaSchema.safeParse(content);
|
|
100
|
+
if (parsed.success) {
|
|
101
|
+
templates.push(parsed.data);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
/**
|
|
106
|
+
* 跳过无法加载的模板
|
|
107
|
+
*/
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return templates;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 读取模板文件内容
|
|
117
|
+
*
|
|
118
|
+
* @param templateDir - 模板目录路径
|
|
119
|
+
* @param sourcePath - 源文件路径(相对于模板目录)
|
|
120
|
+
* @returns 文件内容字符串
|
|
121
|
+
*/
|
|
122
|
+
export const readTemplateFile = async (
|
|
123
|
+
templateDir: string,
|
|
124
|
+
sourcePath: string,
|
|
125
|
+
): Promise<string> => {
|
|
126
|
+
/**
|
|
127
|
+
* 模板源文件的完整路径
|
|
128
|
+
*/
|
|
129
|
+
const filePath = `${templateDir}/${sourcePath}`;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* 模板源文件句柄
|
|
133
|
+
*/
|
|
134
|
+
const file = Bun.file(filePath);
|
|
135
|
+
return await file.text();
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 按分类过滤模板
|
|
140
|
+
*
|
|
141
|
+
* @param templates - 模板列表
|
|
142
|
+
* @param category - 分类名称
|
|
143
|
+
* @returns 过滤后的模板列表
|
|
144
|
+
*/
|
|
145
|
+
export const filterByCategory = (templates: TemplateMeta[], category?: string): TemplateMeta[] => {
|
|
146
|
+
if (!category) {
|
|
147
|
+
return templates;
|
|
148
|
+
}
|
|
149
|
+
return templates.filter((t) => t.category === category);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 按关键词搜索模板
|
|
154
|
+
*
|
|
155
|
+
* @param templates - 模板列表
|
|
156
|
+
* @param keyword - 搜索关键词
|
|
157
|
+
* @returns 匹配的模板列表
|
|
158
|
+
*/
|
|
159
|
+
export const searchTemplates = (templates: TemplateMeta[], keyword: string): TemplateMeta[] => {
|
|
160
|
+
/**
|
|
161
|
+
* 小写化后的搜索关键词,用于大小写不敏感匹配
|
|
162
|
+
*/
|
|
163
|
+
const lowerKeyword = keyword.toLowerCase();
|
|
164
|
+
return templates.filter((t) => {
|
|
165
|
+
return (
|
|
166
|
+
t.name.toLowerCase().includes(lowerKeyword) ||
|
|
167
|
+
t.description.toLowerCase().includes(lowerKeyword) ||
|
|
168
|
+
t.tags.some((tag) => tag.toLowerCase().includes(lowerKeyword))
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 根据 ID 查找模板
|
|
175
|
+
*
|
|
176
|
+
* @param templates - 模板列表
|
|
177
|
+
* @param id - 模板 ID
|
|
178
|
+
* @returns 模板元数据或 undefined
|
|
179
|
+
*/
|
|
180
|
+
export const findTemplateById = (
|
|
181
|
+
templates: TemplateMeta[],
|
|
182
|
+
id: string,
|
|
183
|
+
): TemplateMeta | undefined => {
|
|
184
|
+
return templates.find((t) => t.id === id);
|
|
185
|
+
};
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模板元数据 Schema 定义
|
|
3
|
+
*
|
|
4
|
+
* 定义模板的元数据结构,包括分类、变量、文件列表等
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as z from 'zod';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 模板分类枚举 Schema
|
|
11
|
+
*/
|
|
12
|
+
export const TemplateCategorySchema = z.enum([
|
|
13
|
+
'project',
|
|
14
|
+
'app',
|
|
15
|
+
'package',
|
|
16
|
+
'domain',
|
|
17
|
+
'config',
|
|
18
|
+
'docs',
|
|
19
|
+
'adapter',
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 模板分类类型
|
|
24
|
+
*/
|
|
25
|
+
export type TemplateCategory = z.infer<typeof TemplateCategorySchema>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 模板变量类型枚举 Schema
|
|
29
|
+
*/
|
|
30
|
+
export const VariableTypeSchema = z.enum(['string', 'boolean', 'select']);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 模板变量类型
|
|
34
|
+
*/
|
|
35
|
+
export type VariableType = z.infer<typeof VariableTypeSchema>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 模板变量定义 Schema
|
|
39
|
+
*/
|
|
40
|
+
export const TemplateVariableSchema = z.object({
|
|
41
|
+
/**
|
|
42
|
+
* 变量名称
|
|
43
|
+
*/
|
|
44
|
+
name: z.string(),
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 变量类型
|
|
48
|
+
*/
|
|
49
|
+
type: VariableTypeSchema,
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 变量的用途说明,展示给用户辅助填写
|
|
53
|
+
*/
|
|
54
|
+
description: z.string(),
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 默认值
|
|
58
|
+
*/
|
|
59
|
+
defaultValue: z.string().optional(),
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 是否必填
|
|
63
|
+
*/
|
|
64
|
+
required: z.boolean().default(true),
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* select 类型的选项列表
|
|
68
|
+
*/
|
|
69
|
+
options: z
|
|
70
|
+
.array(
|
|
71
|
+
z.object({
|
|
72
|
+
label: z.string(),
|
|
73
|
+
value: z.string(),
|
|
74
|
+
}),
|
|
75
|
+
)
|
|
76
|
+
.optional(),
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 验证正则
|
|
80
|
+
*/
|
|
81
|
+
pattern: z.string().optional(),
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 验证失败提示
|
|
85
|
+
*/
|
|
86
|
+
patternMessage: z.string().optional(),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 模板变量定义类型
|
|
91
|
+
*/
|
|
92
|
+
export type TemplateVariable = z.infer<typeof TemplateVariableSchema>;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 模板文件定义 Schema
|
|
96
|
+
*/
|
|
97
|
+
export const TemplateFileSchema = z.object({
|
|
98
|
+
/**
|
|
99
|
+
* 模板源文件路径(相对于模板目录)
|
|
100
|
+
*/
|
|
101
|
+
source: z.string(),
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 目标文件路径模板(支持变量替换)
|
|
105
|
+
*/
|
|
106
|
+
destination: z.string(),
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 是否为可执行文件
|
|
110
|
+
*/
|
|
111
|
+
executable: z.boolean().default(false),
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 条件变量(仅当该变量为真时生成此文件)
|
|
115
|
+
*/
|
|
116
|
+
condition: z.string().optional(),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 模板文件定义类型
|
|
121
|
+
*/
|
|
122
|
+
export type TemplateFile = z.infer<typeof TemplateFileSchema>;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 模板元数据 Schema
|
|
126
|
+
*/
|
|
127
|
+
export const TemplateMetaSchema = z.object({
|
|
128
|
+
/**
|
|
129
|
+
* 模板唯一标识(kebab-case)
|
|
130
|
+
*/
|
|
131
|
+
id: z.string(),
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 模板显示名称
|
|
135
|
+
*/
|
|
136
|
+
name: z.string(),
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 模板描述
|
|
140
|
+
*/
|
|
141
|
+
description: z.string(),
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 所属分类
|
|
145
|
+
*/
|
|
146
|
+
category: TemplateCategorySchema,
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 标签列表
|
|
150
|
+
*/
|
|
151
|
+
tags: z.array(z.string()).default([]),
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 模板变量定义
|
|
155
|
+
*/
|
|
156
|
+
variables: z.array(TemplateVariableSchema).default([]),
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 模板文件列表
|
|
160
|
+
*/
|
|
161
|
+
files: z.array(TemplateFileSchema).default([]),
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 依赖的其他模板 ID
|
|
165
|
+
*/
|
|
166
|
+
dependencies: z.array(z.string()).default([]),
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* 模板版本
|
|
170
|
+
*/
|
|
171
|
+
version: z.string().default('0.1.0'),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 模板元数据类型
|
|
176
|
+
*/
|
|
177
|
+
export type TemplateMeta = z.infer<typeof TemplateMetaSchema>;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 内置变量名称常量
|
|
181
|
+
*/
|
|
182
|
+
export const BUILTIN_VARIABLES = {
|
|
183
|
+
projectName: 'projectName',
|
|
184
|
+
projectScope: 'projectScope',
|
|
185
|
+
domainName: 'domainName',
|
|
186
|
+
packageName: 'packageName',
|
|
187
|
+
author: 'author',
|
|
188
|
+
year: 'year',
|
|
189
|
+
} as const;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 内置变量类型
|
|
193
|
+
*/
|
|
194
|
+
export type BuiltinVariable = keyof typeof BUILTIN_VARIABLES;
|