create-component-template-cli 1.0.0 → 1.0.2

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.
Files changed (78) hide show
  1. package/.changeset/config.json +1 -1
  2. package/AGENTS.md +114 -0
  3. package/CHANGELOG.md +13 -1
  4. package/CLAUDE.md +20 -8
  5. package/README.md +49 -21
  6. package/bin/cli.mjs +38 -29
  7. package/docs/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204-/346/200/235/350/267/257/346/226/207/346/241/243.md +167 -0
  8. package/docs/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204-/346/200/273/347/273/223/346/226/207/346/241/243.md +80 -0
  9. package/docs/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204/2026-05-11T10-04-44-/344/270/211/345/245/227/346/250/241/346/235/277/351/207/215/346/236/204-/350/256/276/350/256/241/346/226/271/346/241/210.md +477 -0
  10. package/docs/2026-05-11T12-35-00-npx/346/211/247/350/241/214/345/205/245/345/217/243/344/277/256/345/244/215/2026-05-11T12-35-00-npx/346/211/247/350/241/214/345/205/245/345/217/243/344/277/256/345/244/215-/345/256/236/346/226/275/346/226/271/346/241/210.md +66 -0
  11. package/docs/2026-05-11T12-35-00-npx/346/211/247/350/241/214/345/205/245/345/217/243/344/277/256/345/244/215/2026-05-11T12-35-00-npx/346/211/247/350/241/214/345/205/245/345/217/243/344/277/256/345/244/215-/346/200/235/350/267/257/346/226/207/346/241/243.md +69 -0
  12. package/docs/2026-05-11T12-35-00-npx/346/211/247/350/241/214/345/205/245/345/217/243/344/277/256/345/244/215/2026-05-11T12-35-00-npx/346/211/247/350/241/214/345/205/245/345/217/243/344/277/256/345/244/215-/346/200/273/347/273/223/346/226/207/346/241/243.md +27 -0
  13. package/package.json +4 -3
  14. package/plop-templates/general/data.ts.hbs +16 -0
  15. package/plop-templates/general/hook.ts.hbs +11 -0
  16. package/plop-templates/general/index.normal.vue.hbs +28 -0
  17. package/plop-templates/general/index.scss.hbs +5 -0
  18. package/plop-templates/general/index.setup.vue.hbs +20 -0
  19. package/plop-templates/{index.ts.hbs → general/index.ts.hbs} +2 -1
  20. package/plop-templates/general/typing.ts.hbs +13 -0
  21. package/plop-templates/multiple-pick/data.ts.hbs +20 -0
  22. package/plop-templates/multiple-pick/hook.ts.hbs +11 -0
  23. package/plop-templates/multiple-pick/index.normal.vue.hbs +37 -0
  24. package/plop-templates/multiple-pick/index.scss.hbs +5 -0
  25. package/plop-templates/multiple-pick/index.setup.vue.hbs +22 -0
  26. package/plop-templates/multiple-pick/index.ts.hbs +4 -0
  27. package/plop-templates/multiple-pick/typing.ts.hbs +13 -0
  28. package/plop-templates/single-pick/data.ts.hbs +16 -0
  29. package/plop-templates/single-pick/hook.ts.hbs +11 -0
  30. package/plop-templates/single-pick/index.normal.vue.hbs +36 -0
  31. package/plop-templates/single-pick/index.scss.hbs +5 -0
  32. package/plop-templates/single-pick/index.setup.vue.hbs +23 -0
  33. package/plop-templates/single-pick/index.ts.hbs +4 -0
  34. package/plop-templates/single-pick/typing.ts.hbs +13 -0
  35. package/plopfile.mjs +68 -59
  36. package/src/generate.mjs +101 -31
  37. package/tmp-output/GeneralNormalDemo/index.ts +4 -0
  38. package/tmp-output/GeneralNormalDemo/src/data.ts +16 -0
  39. package/tmp-output/GeneralNormalDemo/src/hook.ts +11 -0
  40. package/tmp-output/GeneralNormalDemo/src/index.scss +5 -0
  41. package/tmp-output/GeneralNormalDemo/src/index.vue +28 -0
  42. package/tmp-output/GeneralNormalDemo/src/typing.ts +13 -0
  43. package/tmp-output/GeneralSetupDemo/index.ts +4 -0
  44. package/tmp-output/GeneralSetupDemo/src/data.ts +16 -0
  45. package/tmp-output/GeneralSetupDemo/src/hook.ts +11 -0
  46. package/tmp-output/GeneralSetupDemo/src/index.scss +5 -0
  47. package/tmp-output/GeneralSetupDemo/src/index.vue +20 -0
  48. package/tmp-output/GeneralSetupDemo/src/typing.ts +13 -0
  49. package/tmp-output/MultiplePickNormalDemo/index.ts +4 -0
  50. package/tmp-output/MultiplePickNormalDemo/src/data.ts +20 -0
  51. package/tmp-output/MultiplePickNormalDemo/src/hook.ts +11 -0
  52. package/tmp-output/MultiplePickNormalDemo/src/index.scss +5 -0
  53. package/tmp-output/MultiplePickNormalDemo/src/index.vue +37 -0
  54. package/tmp-output/MultiplePickNormalDemo/src/typing.ts +13 -0
  55. package/tmp-output/MultiplePickSetupDemo/index.ts +4 -0
  56. package/tmp-output/MultiplePickSetupDemo/src/data.ts +20 -0
  57. package/tmp-output/MultiplePickSetupDemo/src/hook.ts +11 -0
  58. package/tmp-output/MultiplePickSetupDemo/src/index.scss +5 -0
  59. package/tmp-output/MultiplePickSetupDemo/src/index.vue +22 -0
  60. package/tmp-output/MultiplePickSetupDemo/src/typing.ts +13 -0
  61. package/tmp-output/SinglePickNormalDemo/index.ts +4 -0
  62. package/tmp-output/SinglePickNormalDemo/src/data.ts +16 -0
  63. package/tmp-output/SinglePickNormalDemo/src/hook.ts +11 -0
  64. package/tmp-output/SinglePickNormalDemo/src/index.scss +5 -0
  65. package/tmp-output/SinglePickNormalDemo/src/index.vue +36 -0
  66. package/tmp-output/SinglePickNormalDemo/src/typing.ts +13 -0
  67. package/tmp-output/SinglePickSetupDemo/index.ts +4 -0
  68. package/tmp-output/SinglePickSetupDemo/src/data.ts +16 -0
  69. package/tmp-output/SinglePickSetupDemo/src/hook.ts +11 -0
  70. package/tmp-output/SinglePickSetupDemo/src/index.scss +5 -0
  71. package/tmp-output/SinglePickSetupDemo/src/index.vue +23 -0
  72. package/tmp-output/SinglePickSetupDemo/src/typing.ts +13 -0
  73. package/plop-templates/data.ts.hbs +0 -7
  74. package/plop-templates/hook.ts.hbs +0 -29
  75. package/plop-templates/index.scss.hbs +0 -1
  76. package/plop-templates/index.setup.vue.hbs +0 -25
  77. package/plop-templates/index.vue.hbs +0 -38
  78. package/plop-templates/typing.ts.hbs +0 -14
@@ -0,0 +1,477 @@
1
+ # 三套业务模板与两套 Vue 语法风格并存设计方案
2
+
3
+ ## 1. 背景
4
+
5
+ 当前项目里存在两个容易混淆的概念:
6
+
7
+ 1. 业务模板类型
8
+ 表示要生成哪一类业务组件骨架。
9
+
10
+ 2. Vue 语法风格
11
+ 只表示 `index.vue` 使用哪种 Vue 写法。
12
+
13
+ 这次需求已经明确:
14
+
15
+ - 业务层面的 `templateType` 一共有三种:
16
+ - `general`
17
+ - `single-pick`
18
+ - `multiple-pick`
19
+ - 当前逻辑中的 `setup` 和 `normal` 仍然保留
20
+ - `setup/normal` 只用于决定 `index.vue` 的 Vue 模板写法
21
+
22
+ 因此,这次设计的核心是把“业务模板类型”和“Vue 语法风格”拆成两个独立维度,而不是让 `templateType` 同时承担两种含义。
23
+
24
+ ## 2. 目标
25
+
26
+ ### 2.1 功能目标
27
+
28
+ 1. 支持三种业务模板类型
29
+ 2. 保留两种 Vue 语法风格
30
+ 3. 支持任意业务模板类型与任意 Vue 语法风格组合使用
31
+ 4. 保持现有输出目录结构不变
32
+ 5. 最终生成的组件文件名保持稳定
33
+
34
+ ### 2.2 设计目标
35
+
36
+ 1. 参数语义清晰
37
+ 2. 模板目录结构清晰
38
+ 3. 生成逻辑采用配置驱动
39
+ 4. 交互模式与非交互模式规则一致
40
+
41
+ ## 3. 需求拆解
42
+
43
+ 这次需求不是“三套模板替换两套模板”,而是“两层模板选择并存”。
44
+
45
+ ### 3.1 第一层:业务模板类型
46
+
47
+ 这一层决定整套生成内容的业务语义:
48
+
49
+ - `general`:通用业务模板
50
+ - `single-pick`:产品组单选业务模板
51
+ - `multiple-pick`:产品组多选业务模板
52
+
53
+ 这一层会影响的文件不只有 `index.vue`,还可能包括:
54
+
55
+ - `typing.ts`
56
+ - `hook.ts`
57
+ - `data.ts`
58
+ - `index.scss`
59
+ - `index.ts`
60
+
61
+ ### 3.2 第二层:Vue 语法风格
62
+
63
+ 这一层只决定 `index.vue` 使用哪种 Vue 写法:
64
+
65
+ - `setup`:`<script setup>`
66
+ - `normal`:`defineComponent`
67
+
68
+ 最终允许的组合关系应为:
69
+
70
+ - `general + setup`
71
+ - `general + normal`
72
+ - `single-pick + setup`
73
+ - `single-pick + normal`
74
+ - `multiple-pick + setup`
75
+ - `multiple-pick + normal`
76
+
77
+ ## 4. 现状分析
78
+
79
+ ### 4.1 当前实现特点
80
+
81
+ 当前实现里:
82
+
83
+ 1. `templateType` 只有 `setup` 和 `normal`
84
+ 2. 实际上只有 `index.vue` 会根据 `templateType` 切换模板文件
85
+ 3. 其他文件模板都是固定的
86
+
87
+ 这说明当前架构本质上只支持:
88
+
89
+ - 单一业务模板
90
+ - 两种 Vue 语法风格
91
+
92
+ ### 4.2 当前问题
93
+
94
+ 1. `templateType` 语义混乱
95
+ 它现在承载的是 Vue 写法选择,而不是业务模板选择。
96
+
97
+ 2. 缺少业务模板层
98
+ 目前没有一个明确维度控制 `general`、`single-pick`、`multiple-pick`。
99
+
100
+ 3. 模板组织方式扩展性不足
101
+ 如果继续在平铺目录上叠加判断,后续文件差异会越来越难维护。
102
+
103
+ ## 5. 重构原则
104
+
105
+ ### 5.1 两个维度必须拆开
106
+
107
+ 业务模板类型和 Vue 语法风格属于不同维度,不能再复用同一个参数语义。
108
+
109
+ ### 5.2 业务模板决定整套模板目录
110
+
111
+ 每种业务模板对应一套独立模板资源。
112
+
113
+ ### 5.3 Vue 风格只决定 `index.vue`
114
+
115
+ `setup/normal` 只影响 `index.vue` 模板文件选择,不影响其他文件来源。
116
+
117
+ ### 5.4 模板源文件名与最终输出文件名分离
118
+
119
+ 内部可以通过不同模板源文件区分 Vue 写法,但最终输出给组件目录的文件名必须统一。
120
+
121
+ ## 6. 参数设计
122
+
123
+ 建议把参数拆成两个:
124
+
125
+ ### 6.1 `templateType`
126
+
127
+ 表示业务模板类型:
128
+
129
+ - `general`
130
+ - `single-pick`
131
+ - `multiple-pick`
132
+
133
+ ### 6.2 `vueTemplateType`
134
+
135
+ 表示 Vue 语法风格:
136
+
137
+ - `setup`
138
+ - `normal`
139
+
140
+ 如果暂时不想新增参数名,也可以过渡为:
141
+
142
+ - `templateType`:业务模板类型
143
+ - `vueStyle`:Vue 语法风格
144
+
145
+ 本方案更推荐使用语义更明确的命名,例如 `vueTemplateType`。
146
+
147
+ ## 7. 目录设计
148
+
149
+ 建议模板目录按业务模板类型分组,在每个业务模板目录中,仅对 `index.vue` 的模板源文件再区分两种 Vue 写法。
150
+
151
+ ```txt
152
+ plop-templates/
153
+ general/
154
+ index.setup.vue.hbs
155
+ index.normal.vue.hbs
156
+ typing.ts.hbs
157
+ hook.ts.hbs
158
+ data.ts.hbs
159
+ index.scss.hbs
160
+ index.ts.hbs
161
+ single-pick/
162
+ index.setup.vue.hbs
163
+ index.normal.vue.hbs
164
+ typing.ts.hbs
165
+ hook.ts.hbs
166
+ data.ts.hbs
167
+ index.scss.hbs
168
+ index.ts.hbs
169
+ multiple-pick/
170
+ index.setup.vue.hbs
171
+ index.normal.vue.hbs
172
+ typing.ts.hbs
173
+ hook.ts.hbs
174
+ data.ts.hbs
175
+ index.scss.hbs
176
+ index.ts.hbs
177
+ ```
178
+
179
+ ### 7.1 输出文件命名规则
180
+
181
+ 这里必须严格区分“模板源文件名”和“最终生成文件名”:
182
+
183
+ 1. 模板源文件名
184
+ 内部允许使用:
185
+ - `index.setup.vue.hbs`
186
+ - `index.normal.vue.hbs`
187
+
188
+ 2. 最终生成文件名
189
+ 无论选择哪种 Vue 风格,最终都只生成:
190
+ - `src/index.vue`
191
+
192
+ 也就是说,`setup/normal` 只参与模板选择,不进入最终产物文件名。
193
+
194
+ ### 7.2 这样设计的原因
195
+
196
+ 1. 在算什么
197
+ 这里算的是“如何让模板选择逻辑可区分,同时保持最终产物结构稳定”。
198
+
199
+ 2. 为什么这么算
200
+ 因为 `setup/normal` 只是模板来源差异,不是最终组件目录结构差异。对使用方来说,组件入口文件始终应该是统一的 `index.vue`。
201
+
202
+ 3. 好处
203
+ 后续如果新增业务模板,只需要新增一个目录;如果新增新的 Vue 风格,只需要在各业务目录下补充对应的 `index.xxx.vue.hbs`。
204
+
205
+ ## 8. 配置结构设计
206
+
207
+ 建议抽离两套配置。
208
+
209
+ ### 8.1 业务模板注册表
210
+
211
+ ```js
212
+ BUSINESS_TEMPLATE_MAP = {
213
+ general: {
214
+ label: '通用模板',
215
+ templateDir: 'general'
216
+ },
217
+ 'single-pick': {
218
+ label: '产品组单选模板',
219
+ templateDir: 'single-pick'
220
+ },
221
+ 'multiple-pick': {
222
+ label: '产品组多选模板',
223
+ templateDir: 'multiple-pick'
224
+ }
225
+ }
226
+ ```
227
+
228
+ ### 8.2 Vue 风格注册表
229
+
230
+ ```js
231
+ VUE_TEMPLATE_STYLE_MAP = {
232
+ setup: {
233
+ label: 'script setup 风格',
234
+ vueTemplateFile: 'index.setup.vue.hbs'
235
+ },
236
+ normal: {
237
+ label: 'defineComponent 风格',
238
+ vueTemplateFile: 'index.normal.vue.hbs'
239
+ }
240
+ }
241
+ ```
242
+
243
+ ### 8.3 固定输出文件清单
244
+
245
+ ```js
246
+ TEMPLATE_FILES = [
247
+ { output: 'src/index.vue', type: 'vue-entry' },
248
+ { output: 'src/index.scss', template: 'index.scss.hbs' },
249
+ { output: 'src/typing.ts', template: 'typing.ts.hbs' },
250
+ { output: 'src/hook.ts', template: 'hook.ts.hbs' },
251
+ { output: 'src/data.ts', template: 'data.ts.hbs' },
252
+ { output: 'index.ts', template: 'index.ts.hbs' }
253
+ ]
254
+ ```
255
+
256
+ ## 9. 模板选择逻辑
257
+
258
+ ### 9.1 选择流程
259
+
260
+ 1. 先根据 `templateType` 选择业务模板目录
261
+ 2. 再根据 `vueTemplateType` 选择 `index.vue` 对应模板源文件
262
+ 3. 将选中的 Vue 模板源文件渲染后统一写入 `src/index.vue`
263
+ 4. 其他文件全部从业务模板目录读取固定模板
264
+
265
+ ### 9.2 伪代码
266
+
267
+ ```js
268
+ 读取 templateType
269
+ 读取 vueTemplateType
270
+
271
+ 校验 templateType 是否合法
272
+ 校验 vueTemplateType 是否合法
273
+
274
+ businessDir = BUSINESS_TEMPLATE_MAP[templateType].templateDir
275
+ vueFile = VUE_TEMPLATE_STYLE_MAP[vueTemplateType].vueTemplateFile
276
+
277
+ for 每个输出文件:
278
+ if 当前文件是 index.vue:
279
+ templatePath = businessDir + vueFile
280
+ outputPath = src/index.vue
281
+ else:
282
+ templatePath = businessDir + 固定模板文件名
283
+ outputPath = 固定输出路径
284
+
285
+ 读取模板
286
+ 渲染变量
287
+ 写入 outputPath
288
+ ```
289
+
290
+ ## 10. 代码改造方案
291
+
292
+ ### 10.1 `src/generate.mjs`
293
+
294
+ #### 改造目标
295
+
296
+ 让生成器同时接收“业务模板类型”和“Vue 风格”两个参数。
297
+
298
+ #### 改造内容
299
+
300
+ 1. 新增业务模板合法值校验
301
+ 2. 新增 Vue 风格合法值校验
302
+ 3. 把 `index.vue` 模板选择逻辑改成二段式选择
303
+ 4. 选中的 Vue 模板源文件最终统一输出为 `src/index.vue`
304
+ 5. 其他模板文件按业务模板目录读取
305
+
306
+ ### 10.2 `plopfile.mjs`
307
+
308
+ #### 改造目标
309
+
310
+ 交互模式中要让用户先后选择两个维度。
311
+
312
+ #### 改造内容
313
+
314
+ 1. 增加业务模板选择项
315
+ 2. 保留 Vue 风格选择项
316
+ 3. 生成动作时同时带上两个参数
317
+ 4. 模板路径拼接逻辑改为“业务目录 + Vue 风格文件名”
318
+ 5. 最终输出路径始终保持 `src/index.vue`
319
+
320
+ ### 10.3 `bin/cli.mjs`
321
+
322
+ #### 改造目标
323
+
324
+ CLI 参数说明与帮助文案反映双维度结构。
325
+
326
+ #### 改造内容
327
+
328
+ 1. `--templateType` 改为说明业务模板类型
329
+ 2. 新增 Vue 风格参数说明
330
+ 3. 明确说明 `setup/normal` 不会改变最终输出文件名
331
+ 4. 示例命令补充若干典型组合
332
+
333
+ ### 10.4 文档同步
334
+
335
+ 需要同步更新:
336
+
337
+ - `README.md`
338
+ - `AGENTS.md`
339
+ - `CLAUDE.md`
340
+
341
+ 避免后续使用者继续把 `templateType` 理解成 Vue 写法开关。
342
+
343
+ ## 11. 模板内容设计
344
+
345
+ ### 11.1 `general`
346
+
347
+ 用途:通用业务组件骨架。
348
+
349
+ 设计原则:
350
+
351
+ - 参考现有模板内容
352
+ - 去掉单选、多选场景的强业务耦合
353
+ - 保留基础 props、hook、data 占位
354
+
355
+ ### 11.2 `single-pick`
356
+
357
+ 用途:产品组单选业务模板。
358
+
359
+ 设计原则:
360
+
361
+ - 参考现有 `SinglePickButtonGroup` 相关痕迹
362
+ - `typing.ts` 预置单选值结构
363
+ - `data.ts` 预置单选项数组结构
364
+
365
+ ### 11.3 `multiple-pick`
366
+
367
+ 用途:产品组多选业务模板。
368
+
369
+ 设计原则:
370
+
371
+ - 在单选模板思路基础上扩展为多选语义
372
+ - `typing.ts` 预置多选值结构
373
+ - `data.ts` 预置多选项数组结构
374
+
375
+ ### 11.4 关于 `index.vue`
376
+
377
+ 每个业务模板都提供两份 `index.vue` 模板源文件:
378
+
379
+ - `index.setup.vue.hbs`
380
+ - `index.normal.vue.hbs`
381
+
382
+ 它们表达的是同一业务模板下的两种 Vue 书写方式,不是两类业务模板。
383
+ 最终落地生成时,文件名始终统一为 `index.vue`。
384
+
385
+ ## 12. 兼容性策略
386
+
387
+ ### 12.1 旧参数兼容问题
388
+
389
+ 当前实现中 `templateType` 还承担 Vue 风格含义,因此重构后存在迁移问题。
390
+
391
+ ### 12.2 建议过渡方案
392
+
393
+ 建议采用过渡兼容:
394
+
395
+ 1. 新版本引入双参数模型
396
+ 2. 若用户仍传旧的 `templateType=setup|normal`
397
+ 则提示参数语义已调整
398
+ 3. 过渡期内可将旧值映射为:
399
+ - 业务模板默认 `general`
400
+ - Vue 风格使用旧值
401
+
402
+ ### 12.3 过渡映射示意
403
+
404
+ ```txt
405
+ 旧输入:
406
+ --templateType=setup
407
+
408
+ 过渡解释:
409
+ templateType = general
410
+ vueTemplateType = setup
411
+ ```
412
+
413
+ 这样做的原因是:
414
+
415
+ 1. 在算什么
416
+ 这里算的是“如何减少旧脚本失效风险”。
417
+
418
+ 2. 为什么这么算
419
+ 因为旧值本来就只表达 Vue 风格,并不表达业务模板,所以映射到默认业务模板 `general` 最符合原始语义。
420
+
421
+ ## 13. 测试与验证方案
422
+
423
+ ### 13.1 组合验证
424
+
425
+ 至少验证以下 6 组:
426
+
427
+ 1. `general + setup`
428
+ 2. `general + normal`
429
+ 3. `single-pick + setup`
430
+ 4. `single-pick + normal`
431
+ 5. `multiple-pick + setup`
432
+ 6. `multiple-pick + normal`
433
+
434
+ ### 13.2 异常验证
435
+
436
+ 1. 非法 `templateType` 报错
437
+ 2. 非法 `vueTemplateType` 报错
438
+ 3. 未传业务模板时默认值正确
439
+ 4. 未传 Vue 风格时默认值正确
440
+ 5. `overwrite` / `skip` 行为保持不变
441
+
442
+ ### 13.3 输出验证
443
+
444
+ 重点检查:
445
+
446
+ 1. 目录结构是否正确
447
+ 2. 六个目标文件是否完整生成
448
+ 3. `index.vue` 是否真的对应到所选 Vue 风格
449
+ 4. 其他文件是否真的来自所选业务模板
450
+ 5. 最终输出文件名是否始终为 `index.vue`
451
+
452
+ ## 14. 实施步骤
453
+
454
+ 1. 修正模板参数设计
455
+ 2. 新建三套业务模板目录
456
+ 3. 每套业务模板补齐两份 `index.vue` 模板源文件
457
+ 4. 复制并改造 `typing.ts`、`hook.ts`、`data.ts` 等文件模板
458
+ 5. 重构 `src/generate.mjs`
459
+ 6. 重构 `plopfile.mjs`
460
+ 7. 更新 `bin/cli.mjs` 帮助文案
461
+ 8. 更新仓库说明文档
462
+ 9. 执行 6 组组合命令做闭环验证
463
+ 10. 验证最终是否始终输出统一文件名 `index.vue`
464
+ 11. 产出实施总结文档
465
+
466
+ ## 15. 结论
467
+
468
+ 推荐采用“业务模板类型 + Vue 语法风格”双维度方案。
469
+
470
+ 其中:
471
+
472
+ - `templateType` 只负责业务模板语义
473
+ - `setup/normal` 只负责 `index.vue` 的 Vue 书写风格
474
+ - `index.setup.vue.hbs` / `index.normal.vue.hbs` 只是模板源文件名
475
+ - 最终生成文件名始终统一为 `index.vue`
476
+
477
+ 这样既符合你的补充定义,也能最大程度复用现有逻辑,并为后续继续扩展业务模板留下稳定结构。
@@ -0,0 +1,66 @@
1
+ # npx 执行入口修复-实施方案
2
+
3
+ ## 1. 问题描述
4
+
5
+ 用户在发包成功后执行 `npx create-component-template-cli`,终端报错:
6
+
7
+ ```text
8
+ 'cvct' 不是内部或外部命令,也不是可运行的程序或批处理文件。
9
+ ```
10
+
11
+ 但执行 `npx cvct` 可以正常输出版本号。
12
+
13
+ ## 2. 原因分析
14
+
15
+ 当前包的 `package.json` 只声明了一个可执行入口:
16
+
17
+ ```text
18
+ bin:
19
+ cvct -> bin/cli.mjs
20
+ ```
21
+
22
+ 这会导致:
23
+
24
+ 1. 用户如果明确执行 `npx cvct`,npm 能找到对应的可执行文件。
25
+ 2. 用户如果执行 `npx create-component-template-cli`,npm 在 Windows 环境下不会自动把包名映射成 `cvct`,从而出现命令不存在。
26
+
27
+ ## 3. 实施方案
28
+
29
+ ### 3.1 修复入口映射
30
+
31
+ 在 `package.json` 中同时声明两个可执行名称,并都指向同一个入口文件:
32
+
33
+ ```text
34
+ bin:
35
+ cvct -> bin/cli.mjs
36
+ create-component-template-cli -> bin/cli.mjs
37
+ ```
38
+
39
+ ### 3.2 更新使用文档
40
+
41
+ 在 README 中明确说明两种推荐调用方式:
42
+
43
+ ```text
44
+ npx create-component-template-cli
45
+ npx cvct
46
+ ```
47
+
48
+ 这样做的原因是:
49
+
50
+ 1. 包名调用方式更符合用户直觉。
51
+ 2. 短命令调用方式更适合高频使用。
52
+
53
+ ## 4. 验证方案
54
+
55
+ 使用以下命令做闭环验证:
56
+
57
+ ```text
58
+ 步骤 1:验证本地入口文件仍可正常输出版本
59
+ 步骤 2:验证 npx cvct --version 可以执行
60
+ 步骤 3:验证 npx create-component-template-cli --version 可以执行
61
+ 步骤 4:验证 npm pack 后产物包含 bin/cli.mjs 与双 bin 映射
62
+ ```
63
+
64
+ ## 5. 风险说明
65
+
66
+ 本次修改只涉及包元数据与说明文档,不改变模板生成逻辑,业务风险较低。
@@ -0,0 +1,69 @@
1
+ # npx 执行入口修复-思路文档
2
+
3
+ ## 1. 排查思路
4
+
5
+ 这次问题表面上看是“命令找不到”,但需要先区分是以下哪一层出了问题:
6
+
7
+ 1. 包没有成功发布。
8
+ 2. 发布包里缺少 `bin/cli.mjs`。
9
+ 3. `package.json` 的 `bin` 字段配置错误。
10
+ 4. `npx` 调用的命令名和实际暴露的 bin 名不一致。
11
+
12
+ ## 2. 实际排查过程
13
+
14
+ ### 2.1 先看本地源码
15
+
16
+ 确认 `package.json` 中存在:
17
+
18
+ ```text
19
+ name = create-component-template-cli
20
+ bin.cvct = bin/cli.mjs
21
+ ```
22
+
23
+ 说明源码只暴露了 `cvct` 这个命令。
24
+
25
+ ### 2.2 再看打包产物
26
+
27
+ 通过 `npm pack` 检查 tarball 内容,确认 `bin/cli.mjs` 已被打进包里。
28
+
29
+ 这一步的意义是:
30
+
31
+ 1. 排除“发包漏文件”。
32
+ 2. 证明运行时报错不是因为入口脚本缺失。
33
+
34
+ ### 2.3 再看线上元数据
35
+
36
+ 通过 `npm view create-component-template-cli ...` 查看线上元数据,确认线上 `bin` 仍然只有 `cvct`。
37
+
38
+ ### 2.4 最后做最小复现
39
+
40
+ 复现结果:
41
+
42
+ ```text
43
+ npx cvct --version -> 成功
44
+ npx create-component-template-cli --version -> 失败
45
+ ```
46
+
47
+ 这说明真正的问题不是 CLI 代码本身,而是可执行命令别名不完整。
48
+
49
+ ## 3. 为什么这样修
50
+
51
+ 最小改动方案是直接补一个与包名同名的 bin 映射,而不是改动 `bin/cli.mjs` 的执行逻辑。
52
+
53
+ 原因:
54
+
55
+ 1. 问题发生在 npm 命令解析阶段,不在业务代码阶段。
56
+ 2. 增加包名别名不会影响已有用户继续使用 `cvct`。
57
+ 3. 兼容“记包名”和“记短命令”两类用户习惯。
58
+
59
+ ## 4. 伪代码示意
60
+
61
+ ```text
62
+ if user_run_by_package_name:
63
+ resolve bin["create-component-template-cli"]
64
+
65
+ if user_run_by_short_name:
66
+ resolve bin["cvct"]
67
+
68
+ both -> execute "bin/cli.mjs"
69
+ ```
@@ -0,0 +1,27 @@
1
+ # npx 执行入口修复-总结文档
2
+
3
+ ## 本次完成内容
4
+
5
+ 1. 定位了 `npx create-component-template-cli` 报错的根因。
6
+ 2. 在 `package.json` 中新增了 `create-component-template-cli -> bin/cli.mjs` 的 bin 映射。
7
+ 3. 保留了原有 `cvct -> bin/cli.mjs` 的短命令入口,避免兼容性回退。
8
+ 4. 重写 README 的使用说明,补充了包名调用方式与短命令调用方式。
9
+ 5. 完成了本地命令验证与打包产物验证。
10
+
11
+ ## 当前版本收益
12
+
13
+ 1. 用户可以直接执行 `npx create-component-template-cli`,调用方式和包名保持一致。
14
+ 2. 老用户仍可继续执行 `npx cvct`,不会受到影响。
15
+ 3. 文档说明更完整,后续排障成本更低。
16
+
17
+ ## 目前不足
18
+
19
+ 1. README 之外的其他文档(如 AGENTS/CLAUDE 中的示例)仍以本地 `node bin/cli.mjs` 为主,没有单独强调包名执行方式。
20
+ 2. 仓库当前没有自动化测试覆盖“npx/发布后入口解析”这个场景,未来仍可能出现回归。
21
+ 3. 打包产物目前包含较多与发布无关的文件,后续可以考虑通过 `files` 字段进一步收敛 npm 包体积。
22
+
23
+ ## 后续建议
24
+
25
+ 1. 发一个补丁版本,把新的 bin 映射发布到 npm。
26
+ 2. 增加一个发布前校验脚本,自动验证 tarball 中的 `bin` 配置和入口文件是否完整。
27
+ 3. 视情况补充 `files` 字段,减少无关文件进入 npm 包。
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "create-component-template-cli",
3
- "description": "create-vue-component-template,A CLI tool for creating standardized Vue 3 + TypeScript + Sass public component templates.",
4
- "version": "1.0.0",
3
+ "description": "create-vue-component-template-cli,A CLI tool for creating standardized Vue 3 + TypeScript + Sass public component templates.",
4
+ "version": "1.0.2",
5
5
  "type": "module",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
9
9
  "bin": {
10
- "cvct": "bin/cli.mjs"
10
+ "cctc": "bin/cli.mjs",
11
+ "create-component-template-cli": "bin/cli.mjs"
11
12
  },
12
13
  "access": "public",
13
14
  "dependencies": {
@@ -0,0 +1,16 @@
1
+ import type { DataType } from './typing'
2
+
3
+ const data: Array<DataType> = [
4
+ {
5
+ label: '示例项1',
6
+ value: 'option-1',
7
+ },
8
+ {
9
+ label: '示例项2',
10
+ value: 'option-2',
11
+ },
12
+ ]
13
+
14
+ export {
15
+ data,
16
+ }
@@ -0,0 +1,11 @@
1
+ import { ref } from 'vue'
2
+ import type { {{ componentName }}Props } from './typing'
3
+
4
+ export const use{{ componentName }} = (props: {{ componentName }}Props) => {
5
+ const visible = ref(true)
6
+
7
+ return {
8
+ props,
9
+ visible,
10
+ }
11
+ }