@moluoxixi/create-app 2.0.413 → 2.0.414

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 (187) hide show
  1. package/README.md +57 -1
  2. package/dist/commands/create.js +1 -1
  3. package/dist/core/feature.d.ts +80 -0
  4. package/dist/core/feature.js +252 -0
  5. package/dist/core/index.d.ts +6 -0
  6. package/dist/core/index.js +6 -0
  7. package/dist/core/prompts.d.ts +17 -0
  8. package/dist/core/prompts.js +235 -0
  9. package/dist/core/template.d.ts +22 -0
  10. package/dist/core/template.js +177 -0
  11. package/dist/generators/index.d.ts +0 -2
  12. package/dist/generators/index.js +0 -2
  13. package/dist/generators/project.d.ts +1 -0
  14. package/dist/generators/project.js +66 -13
  15. package/dist/generators/react.d.ts +5 -5
  16. package/dist/generators/react.js +6 -9
  17. package/dist/generators/vue.d.ts +5 -5
  18. package/dist/generators/vue.js +6 -9
  19. package/dist/test.d.ts +0 -4
  20. package/dist/test.js +32 -17
  21. package/dist/types/index.d.ts +25 -26
  22. package/dist/types/index.js +2 -3
  23. package/dist/utils/featureMapping.js +6 -3
  24. package/dist/utils/generateFrameworkProject.d.ts +10 -20
  25. package/dist/utils/generateFrameworkProject.js +32 -127
  26. package/dist/utils/index.d.ts +1 -6
  27. package/dist/utils/index.js +1 -6
  28. package/dist/utils/prompts.js +7 -3
  29. package/package.json +2 -2
  30. package/templates/common/base/package.json +3 -1
  31. package/templates/common/base/vite/index.ts +53 -0
  32. package/templates/common/base/vite.config.ts +56 -0
  33. package/templates/common/features/husky/node_modules/.bin/tsc +17 -0
  34. package/templates/common/features/husky/node_modules/.bin/tsc.CMD +12 -0
  35. package/templates/common/features/husky/node_modules/.bin/tsc.ps1 +41 -0
  36. package/templates/common/features/husky/node_modules/.bin/tsserver +17 -0
  37. package/templates/common/features/husky/node_modules/.bin/tsserver.CMD +12 -0
  38. package/templates/common/features/husky/node_modules/.bin/tsserver.ps1 +41 -0
  39. package/templates/react/base/src/main/index.ts +34 -0
  40. package/templates/react/base/src/main.tsx +34 -0
  41. package/templates/react/base/tsconfig.app.json +1 -0
  42. package/templates/react/base/tsconfig.node.json +1 -0
  43. package/templates/react/features/ant-design/package.json +2 -1
  44. package/templates/react/features/ant-design/src/main/features/ant-design.ts +21 -0
  45. package/templates/react/features/i18n/package.json +2 -1
  46. package/templates/react/features/i18n/src/main/features/i18n.ts +19 -0
  47. package/templates/react/features/manualRoutes/package.json +1 -0
  48. package/templates/react/features/sentry/package.json +2 -1
  49. package/templates/react/features/sentry/src/main/features/sentry.ts +20 -0
  50. package/templates/react/features/sentry/vite/features/sentry.ts +39 -0
  51. package/templates/react/features/zustand/src/apis/types/user.ts +39 -0
  52. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/jiti +17 -0
  53. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/jiti.CMD +12 -0
  54. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/jiti.ps1 +41 -0
  55. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/parser +17 -0
  56. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/parser.CMD +12 -0
  57. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/parser.ps1 +41 -0
  58. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/rollup +17 -0
  59. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/rollup.CMD +12 -0
  60. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/rollup.ps1 +41 -0
  61. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/sass +17 -0
  62. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/sass.CMD +12 -0
  63. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/sass.ps1 +41 -0
  64. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/terser +17 -0
  65. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/terser.CMD +12 -0
  66. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/terser.ps1 +41 -0
  67. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsc +17 -0
  68. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsc.CMD +12 -0
  69. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsc.ps1 +41 -0
  70. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsserver +17 -0
  71. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsserver.CMD +12 -0
  72. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsserver.ps1 +41 -0
  73. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsx +17 -0
  74. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsx.CMD +12 -0
  75. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsx.ps1 +41 -0
  76. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/vite +17 -0
  77. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/vite.CMD +12 -0
  78. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/vite.ps1 +41 -0
  79. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/yaml +17 -0
  80. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/yaml.CMD +12 -0
  81. package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/yaml.ps1 +41 -0
  82. package/templates/react/micro-frontends/qiankun/base/package.json +7 -2
  83. package/templates/react/micro-frontends/qiankun/base/src/main/index.ts +34 -0
  84. package/templates/react/micro-frontends/qiankun/base/src/{main.tsx.ejs → main.tsx} +13 -27
  85. package/templates/react/micro-frontends/qiankun/base/vite/index.ts +53 -0
  86. package/templates/react/micro-frontends/qiankun/base/vite.config.ts +58 -0
  87. package/templates/vue/base/src/main/index.ts +36 -0
  88. package/templates/vue/base/src/main.ts +34 -0
  89. package/templates/vue/base/tsconfig.app.json +2 -1
  90. package/templates/vue/base/tsconfig.node.json +2 -1
  91. package/templates/vue/features/ant-design-vue/package.json +3 -1
  92. package/templates/vue/features/ant-design-vue/src/main/features/ant-design-vue.ts +18 -0
  93. package/templates/vue/features/element-plus/package.json +5 -1
  94. package/templates/vue/features/element-plus/src/main/features/element-plus.ts +23 -0
  95. package/templates/vue/features/element-plus/src/stores/index.ts +6 -0
  96. package/templates/vue/features/element-plus/src/stores/modules/system.ts +51 -0
  97. package/templates/vue/features/element-plus/vite/features/element-plus.ts +35 -0
  98. package/templates/vue/features/i18n/package.json +3 -1
  99. package/templates/vue/features/i18n/src/main/features/i18n.ts +19 -0
  100. package/templates/vue/features/manualRoutes/package.json +7 -1
  101. package/templates/vue/features/manualRoutes/src/layouts/index.ts +26 -0
  102. package/templates/vue/features/manualRoutes/src/stores/index.ts +6 -0
  103. package/templates/vue/features/manualRoutes/src/stores/modules/system.ts +51 -0
  104. package/templates/vue/features/pageRoutes/package.json +7 -1
  105. package/templates/vue/features/pageRoutes/src/layouts/index.ts +26 -0
  106. package/templates/vue/features/pageRoutes/src/stores/index.ts +6 -0
  107. package/templates/vue/features/pageRoutes/src/stores/modules/system.ts +51 -0
  108. package/templates/vue/features/pinia/package.json +3 -1
  109. package/templates/vue/features/pinia/src/main/features/pinia.ts +19 -0
  110. package/templates/vue/features/sentry/package.json +4 -2
  111. package/templates/vue/features/sentry/src/main/features/sentry.ts +22 -0
  112. package/templates/vue/features/sentry/vite/features/sentry.ts +39 -0
  113. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/jiti +17 -0
  114. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/jiti.CMD +12 -0
  115. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/jiti.ps1 +41 -0
  116. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/parser +17 -0
  117. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/parser.CMD +12 -0
  118. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/parser.ps1 +41 -0
  119. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/rollup +17 -0
  120. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/rollup.CMD +12 -0
  121. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/rollup.ps1 +41 -0
  122. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/sass +17 -0
  123. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/sass.CMD +12 -0
  124. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/sass.ps1 +41 -0
  125. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/terser +17 -0
  126. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/terser.CMD +12 -0
  127. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/terser.ps1 +41 -0
  128. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsc +17 -0
  129. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsc.CMD +12 -0
  130. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsc.ps1 +41 -0
  131. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsserver +17 -0
  132. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsserver.CMD +12 -0
  133. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsserver.ps1 +41 -0
  134. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsx +17 -0
  135. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsx.CMD +12 -0
  136. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsx.ps1 +41 -0
  137. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/vite +17 -0
  138. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/vite.CMD +12 -0
  139. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/vite.ps1 +41 -0
  140. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/yaml +17 -0
  141. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/yaml.CMD +12 -0
  142. package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/yaml.ps1 +41 -0
  143. package/templates/vue/micro-frontends/qiankun/base/package.json +7 -2
  144. package/templates/vue/micro-frontends/qiankun/base/src/main/index.ts +36 -0
  145. package/templates/vue/micro-frontends/qiankun/base/src/{main.ts.ejs → main.ts} +11 -28
  146. package/templates/vue/micro-frontends/qiankun/base/vite/index.ts +53 -0
  147. package/templates/vue/micro-frontends/qiankun/base/vite.config.ts +59 -0
  148. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/jiti +17 -0
  149. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/jiti.CMD +12 -0
  150. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/jiti.ps1 +41 -0
  151. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/sass +17 -0
  152. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/sass.CMD +12 -0
  153. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/sass.ps1 +41 -0
  154. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/terser +17 -0
  155. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/terser.CMD +12 -0
  156. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/terser.ps1 +41 -0
  157. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsc +17 -0
  158. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsc.CMD +12 -0
  159. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsc.ps1 +41 -0
  160. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsserver +17 -0
  161. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsserver.CMD +12 -0
  162. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsserver.ps1 +41 -0
  163. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsx +17 -0
  164. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsx.CMD +12 -0
  165. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsx.ps1 +41 -0
  166. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/vite +17 -0
  167. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/vite.CMD +12 -0
  168. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/vite.ps1 +41 -0
  169. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/yaml +17 -0
  170. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/yaml.CMD +12 -0
  171. package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/yaml.ps1 +41 -0
  172. package/templates/vue/micro-frontends/qiankun/features/element-plus/package.json +10 -0
  173. package/templates/vue/micro-frontends/qiankun/features/element-plus/src/components/SubMenu/index.ts +8 -0
  174. package/templates/vue/micro-frontends/qiankun/features/element-plus/src/components/SubMenu/src/_types/index.ts +1 -0
  175. package/templates/vue/micro-frontends/qiankun/features/element-plus/src/components/SubMenu/src/_types/props.ts +16 -0
  176. package/templates/vue/micro-frontends/qiankun/features/element-plus/src/components/SubMenu/src/index.vue +60 -0
  177. package/templates/vue/micro-frontends/qiankun/features/element-plus/src/main/features/element-plus.ts +24 -0
  178. package/templates/vue/micro-frontends/qiankun/features/element-plus/src/stores/index.ts +6 -0
  179. package/templates/vue/micro-frontends/qiankun/features/element-plus/src/stores/modules/system.ts +51 -0
  180. package/templates/vue/micro-frontends/qiankun/features/element-plus/vite/features/element-plus.ts +35 -0
  181. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/package.json +6 -1
  182. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/package.json +6 -1
  183. package/templates/common/base/vite.config.ts.ejs +0 -85
  184. package/templates/react/base/src/main.tsx.ejs +0 -56
  185. package/templates/react/micro-frontends/qiankun/base/vite.config.ts.ejs +0 -89
  186. package/templates/vue/base/src/main.ts.ejs +0 -61
  187. package/templates/vue/micro-frontends/qiankun/base/vite.config.ts.ejs +0 -89
package/README.md CHANGED
@@ -50,7 +50,63 @@ npm create @moluoxixi/app
50
50
  | `@moluoxixi/class-names` | CSS 类名工具 |
51
51
  | `@moluoxixi/css-module-global-root-plugin` | CSS Module 插件 |
52
52
 
53
- ## 项目结构
53
+ ## 源码目录结构
54
+
55
+ 本项目采用清晰的模块化架构,将业务逻辑和工具函数分离:
56
+
57
+ ```
58
+ src/
59
+ ├── commands/ # CLI 命令
60
+ │ ├── index.ts # 命令导出
61
+ │ └── create.ts # create 命令实现
62
+
63
+ ├── constants/ # 常量定义
64
+ │ └── index.ts # 文件常量、路径常量等
65
+
66
+ ├── core/ # 核心业务逻辑模块
67
+ │ ├── index.ts # 核心模块导出
68
+ │ ├── feature.ts # Feature 管理(扫描、映射、渲染)
69
+ │ ├── prompts.ts # 交互式问答(收集用户配置)
70
+ │ └── template.ts # 模板渲染(文件复制、合并)
71
+
72
+ ├── generators/ # 项目生成器
73
+ │ ├── index.ts # 生成器导出
74
+ │ └── project.ts # 项目生成核心逻辑
75
+
76
+ ├── types/ # TypeScript 类型定义
77
+ │ ├── index.ts # 公共类型导出
78
+ │ ├── features.ts # Feature 相关类型
79
+ │ └── packageJson.ts # package.json 类型
80
+
81
+ ├── utils/ # 纯工具函数(无业务逻辑)
82
+ │ ├── index.ts # 工具函数导出
83
+ │ ├── deepMerge.ts # 深度合并对象
84
+ │ ├── file.ts # 文件操作(读写、复制、路径处理)
85
+ │ ├── install.ts # 依赖安装、Git 初始化
86
+ │ ├── npmConfig.ts # npm 配置读取
87
+ │ └── sortDependencies.ts # 依赖排序
88
+
89
+ ├── index.ts # CLI 入口
90
+ └── test.ts # 测试脚本
91
+ ```
92
+
93
+ ### 目录职责说明
94
+
95
+ - **`commands/`** - CLI 命令实现,处理用户交互和流程控制
96
+ - **`core/`** - 核心业务逻辑,包含 feature 管理、模板渲染、用户配置收集
97
+ - **`generators/`** - 项目生成器,根据配置生成完整的项目结构
98
+ - **`utils/`** - 纯工具函数,不包含业务逻辑,可独立使用
99
+ - **`types/`** - TypeScript 类型定义,确保类型安全
100
+ - **`constants/`** - 常量定义,集中管理配置值
101
+
102
+ ### 设计原则
103
+
104
+ 1. **职责分离** - 业务逻辑在 `core/`,工具函数在 `utils/`
105
+ 2. **模块化** - 每个模块职责单一,便于维护和测试
106
+ 3. **类型安全** - 完整的 TypeScript 类型定义
107
+ 4. **可扩展性** - 通过文件系统扫描自动发现 features,无需手动配置
108
+
109
+ ## 生成的项目结构
54
110
 
55
111
  生成的项目结构示例:
56
112
 
@@ -5,10 +5,10 @@
5
5
  import process from 'node:process';
6
6
  import chalk from 'chalk';
7
7
  import ora from 'ora';
8
+ import { collectProjectConfig, confirmOverwrite } from "../core/prompts.js";
8
9
  import { generateProject } from "../generators/project.js";
9
10
  import { pathExists } from "../utils/file.js";
10
11
  import { initGit, installDependencies } from "../utils/install.js";
11
- import { collectProjectConfig, confirmOverwrite } from "../utils/prompts.js";
12
12
  /**
13
13
  * 创建项目
14
14
  * @param projectName 项目名称(可选)
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Feature 核心模块
3
+ * 统一管理 features 的扫描、映射、渲染逻辑
4
+ */
5
+ import type { FrameworkType, ProjectConfigType, RouteModeType } from '../types/index.ts';
6
+ /**
7
+ * 扫描所有 features(框架的 + 公共的)
8
+ * @param framework 框架类型
9
+ * @returns 所有 feature 名称数组(UI 库按优先级排序)
10
+ */
11
+ export declare function scanAllFeatures(framework: FrameworkType): string[];
12
+ /**
13
+ * Feature 名称转换为配置键和值(用于测试用例生成)
14
+ * 注意:大部分情况下 feature 名称 === 配置名称
15
+ * @param feature feature 名称
16
+ * @param _framework 框架类型(保留参数以保持接口兼容性)
17
+ * @returns 配置键值对,如果无法映射则返回 null
18
+ */
19
+ export declare function featureToConfig(feature: string, _framework: FrameworkType): {
20
+ key: string;
21
+ value: string | boolean;
22
+ } | null;
23
+ /**
24
+ * 根据路由模式获取对应的布尔特征配置
25
+ * @param routeMode 路由模式('pageRoutes' | 'manualRoutes')
26
+ * @returns 包含 manualRoutes 和 pageRoutes 布尔值的对象
27
+ */
28
+ export declare function getRouteModeFeatures(routeMode: RouteModeType): {
29
+ manualRoutes: boolean;
30
+ pageRoutes: boolean;
31
+ };
32
+ /**
33
+ * 渲染框架特定的 features
34
+ * 通过文件系统扫描自动发现并渲染 features
35
+ * @param config 项目配置
36
+ * @param targetDir 目标目录
37
+ * @throws {Error} 如果路径不安全或模板渲染失败
38
+ */
39
+ export declare function renderFrameworkFeatures(config: ProjectConfigType, targetDir: string): void;
40
+ /**
41
+ * 渲染公共 features
42
+ * 通过文件系统扫描自动发现并渲染公共 features
43
+ * @param config 项目配置
44
+ * @param targetDir 目标目录
45
+ * @throws {Error} 如果路径不安全或模板渲染失败
46
+ */
47
+ export declare function renderCommonFeatures(config: ProjectConfigType, targetDir: string): void;
48
+ /**
49
+ * 渲染微前端专属的 features(覆盖标准 features)
50
+ * 只渲染文件系统中存在的微前端 features,实现按需覆盖
51
+ * @param config 项目配置
52
+ * @param targetDir 目标目录
53
+ * @param microFrontendEngine 微前端引擎类型
54
+ * @throws {Error} 如果路径不安全或模板渲染失败
55
+ */
56
+ export declare function renderMicroFrontendFeatures(config: ProjectConfigType, targetDir: string, microFrontendEngine: string): void;
57
+ /**
58
+ * 验证微前端引擎是否存在
59
+ * @param framework 框架类型
60
+ * @param engine 微前端引擎名称
61
+ * @returns 引擎是否存在
62
+ */
63
+ export declare function validateMicroFrontendEngine(framework: FrameworkType, engine: string): boolean;
64
+ /**
65
+ * 获取可用的公共 features(用于测试和文档生成)
66
+ * @returns 公共 feature 名称数组
67
+ */
68
+ export declare function getAvailableCommonFeatures(): string[];
69
+ /**
70
+ * 获取可用的框架 features(用于测试和文档生成)
71
+ * @param framework 框架类型
72
+ * @returns 框架 feature 名称数组
73
+ */
74
+ export declare function getAvailableFrameworkFeatures(framework: FrameworkType): string[];
75
+ /**
76
+ * 获取可用的微前端引擎(用于测试和文档生成)
77
+ * @param framework 框架类型
78
+ * @returns 微前端引擎名称数组
79
+ */
80
+ export declare function getAvailableMicroFrontendEngines(framework: FrameworkType): string[];
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Feature 核心模块
3
+ * 统一管理 features 的扫描、映射、渲染逻辑
4
+ */
5
+ import fs from 'fs-extra';
6
+ import path from 'node:path';
7
+ import { getTemplatesDir } from "../utils/file.js";
8
+ import { renderTemplate } from "./template.js";
9
+ // ============================================================================
10
+ // Feature 扫描
11
+ // ============================================================================
12
+ /**
13
+ * 扫描指定目录下的所有 feature 目录
14
+ * @param baseDir 基础目录
15
+ * @returns feature 名称数组
16
+ */
17
+ function scanFeatures(baseDir) {
18
+ if (!fs.existsSync(baseDir)) {
19
+ return [];
20
+ }
21
+ return fs.readdirSync(baseDir).filter((item) => {
22
+ const itemPath = path.join(baseDir, item);
23
+ return fs.statSync(itemPath).isDirectory();
24
+ });
25
+ }
26
+ /**
27
+ * 获取公共 features 列表(从文件系统扫描)
28
+ * @returns 公共 feature 名称数组
29
+ */
30
+ function getCommonFeatures() {
31
+ const templatesDir = getTemplatesDir();
32
+ const commonFeaturesDir = path.join(templatesDir, 'common', 'features');
33
+ return scanFeatures(commonFeaturesDir);
34
+ }
35
+ /**
36
+ * 获取框架 features 列表(从文件系统扫描)
37
+ * @param framework 框架类型
38
+ * @returns 框架 feature 名称数组
39
+ */
40
+ function getFrameworkFeatures(framework) {
41
+ const templatesDir = getTemplatesDir();
42
+ const frameworkFeaturesDir = path.join(templatesDir, framework, 'features');
43
+ return scanFeatures(frameworkFeaturesDir);
44
+ }
45
+ /**
46
+ * 获取微前端引擎列表(从文件系统扫描)
47
+ * @param framework 框架类型
48
+ * @returns 微前端引擎名称数组
49
+ */
50
+ function getMicroFrontendEngines(framework) {
51
+ const templatesDir = getTemplatesDir();
52
+ const microFrontendsDir = path.join(templatesDir, framework, 'micro-frontends');
53
+ return scanFeatures(microFrontendsDir);
54
+ }
55
+ // ============================================================================
56
+ // Feature 映射(用于测试用例生成)
57
+ // ============================================================================
58
+ /**
59
+ * UI 库优先级顺序(用于排序,确保默认选择)
60
+ * TODO: ant-design-vue 和 ant-design (React) 功能暂时关闭
61
+ */
62
+ const UI_LIBRARY_PRIORITY = {
63
+ 'element-plus': 1,
64
+ // 'ant-design-vue': 2, // TODO: 暂时关闭
65
+ // 'ant-design': 1, // TODO: 暂时关闭 (React)
66
+ };
67
+ /**
68
+ * 扫描所有 features(框架的 + 公共的)
69
+ * @param framework 框架类型
70
+ * @returns 所有 feature 名称数组(UI 库按优先级排序)
71
+ */
72
+ export function scanAllFeatures(framework) {
73
+ const frameworkDir = path.join(getTemplatesDir(), framework, 'features');
74
+ const commonDir = path.join(getTemplatesDir(), 'common', 'features');
75
+ const features = [];
76
+ if (fs.existsSync(frameworkDir)) {
77
+ features.push(...fs.readdirSync(frameworkDir).filter(f => fs.statSync(path.join(frameworkDir, f)).isDirectory()));
78
+ }
79
+ if (fs.existsSync(commonDir)) {
80
+ features.push(...fs.readdirSync(commonDir).filter(f => fs.statSync(path.join(commonDir, f)).isDirectory()));
81
+ }
82
+ // 对 UI 库进行排序,确保 element-plus 优先(优先级数字越小越靠前)
83
+ return features.sort((a, b) => {
84
+ const priorityA = UI_LIBRARY_PRIORITY[a] ?? 999;
85
+ const priorityB = UI_LIBRARY_PRIORITY[b] ?? 999;
86
+ if (priorityA !== priorityB) {
87
+ return priorityA - priorityB;
88
+ }
89
+ // 相同优先级时保持字母顺序
90
+ return a.localeCompare(b);
91
+ });
92
+ }
93
+ /**
94
+ * Feature 名称转换为配置键和值(用于测试用例生成)
95
+ * 注意:大部分情况下 feature 名称 === 配置名称
96
+ * @param feature feature 名称
97
+ * @param _framework 框架类型(保留参数以保持接口兼容性)
98
+ * @returns 配置键值对,如果无法映射则返回 null
99
+ */
100
+ export function featureToConfig(feature, _framework) {
101
+ // UI 库:配置键是 uiLibrary,值是 feature 名称
102
+ // TODO: ant-design-vue 和 ant-design (React) 功能暂时关闭
103
+ // const uiLibraries = ['element-plus', 'ant-design-vue', 'ant-design']
104
+ const uiLibraries = ['element-plus'];
105
+ if (uiLibraries.includes(feature)) {
106
+ return { key: 'uiLibrary', value: feature };
107
+ }
108
+ // 路由模式 features:用于测试分类
109
+ if (feature === 'manualRoutes' || feature === 'pageRoutes') {
110
+ return { key: 'routeMode', value: feature };
111
+ }
112
+ // 布尔类型的 features:配置名 === feature 名
113
+ const booleanFeatures = [
114
+ 'eslint',
115
+ 'i18n',
116
+ 'sentry',
117
+ 'pinia',
118
+ 'zustand',
119
+ 'husky',
120
+ ];
121
+ if (booleanFeatures.includes(feature)) {
122
+ return { key: feature, value: true };
123
+ }
124
+ return null;
125
+ }
126
+ // ============================================================================
127
+ // 路由模式转换
128
+ // ============================================================================
129
+ /**
130
+ * 根据路由模式获取对应的布尔特征配置
131
+ * @param routeMode 路由模式('pageRoutes' | 'manualRoutes')
132
+ * @returns 包含 manualRoutes 和 pageRoutes 布尔值的对象
133
+ */
134
+ export function getRouteModeFeatures(routeMode) {
135
+ return {
136
+ manualRoutes: routeMode === 'manualRoutes',
137
+ pageRoutes: routeMode === 'pageRoutes',
138
+ };
139
+ }
140
+ // ============================================================================
141
+ // Feature 渲染
142
+ // ============================================================================
143
+ /**
144
+ * 渲染框架特定的 features
145
+ * 通过文件系统扫描自动发现并渲染 features
146
+ * @param config 项目配置
147
+ * @param targetDir 目标目录
148
+ * @throws {Error} 如果路径不安全或模板渲染失败
149
+ */
150
+ export function renderFrameworkFeatures(config, targetDir) {
151
+ const templatesDir = getTemplatesDir();
152
+ const { framework, uiLibrary } = config;
153
+ // 从文件系统扫描获取所有框架 features
154
+ const availableFeatures = getFrameworkFeatures(framework);
155
+ // 遍历配置对象,渲染所有值为 true 且存在于文件系统的 features
156
+ for (const [key, value] of Object.entries(config)) {
157
+ // 如果配置值为 true 且 feature 目录存在,则渲染
158
+ if (value === true && availableFeatures.includes(key)) {
159
+ const featurePath = path.join(templatesDir, framework, 'features', key);
160
+ renderTemplate(featurePath, targetDir);
161
+ }
162
+ }
163
+ // UI 库单独处理(配置值 === feature 目录名)
164
+ if (uiLibrary && availableFeatures.includes(uiLibrary)) {
165
+ renderTemplate(path.join(templatesDir, framework, 'features', uiLibrary), targetDir);
166
+ }
167
+ }
168
+ /**
169
+ * 渲染公共 features
170
+ * 通过文件系统扫描自动发现并渲染公共 features
171
+ * @param config 项目配置
172
+ * @param targetDir 目标目录
173
+ * @throws {Error} 如果路径不安全或模板渲染失败
174
+ */
175
+ export function renderCommonFeatures(config, targetDir) {
176
+ const templatesDir = getTemplatesDir();
177
+ // 从文件系统扫描获取所有公共 features
178
+ const availableFeatures = getCommonFeatures();
179
+ // 遍历配置对象,渲染所有值为 true 且存在于文件系统的公共 features
180
+ for (const [key, value] of Object.entries(config)) {
181
+ if (value === true && availableFeatures.includes(key)) {
182
+ const featurePath = path.join(templatesDir, 'common', 'features', key);
183
+ renderTemplate(featurePath, targetDir);
184
+ }
185
+ }
186
+ }
187
+ /**
188
+ * 渲染微前端专属的 features(覆盖标准 features)
189
+ * 只渲染文件系统中存在的微前端 features,实现按需覆盖
190
+ * @param config 项目配置
191
+ * @param targetDir 目标目录
192
+ * @param microFrontendEngine 微前端引擎类型
193
+ * @throws {Error} 如果路径不安全或模板渲染失败
194
+ */
195
+ export function renderMicroFrontendFeatures(config, targetDir, microFrontendEngine) {
196
+ const templatesDir = getTemplatesDir();
197
+ const { framework, uiLibrary } = config;
198
+ const microFrontendFeaturesPath = path.join(templatesDir, framework, 'micro-frontends', microFrontendEngine, 'features');
199
+ // 如果微前端 features 目录不存在,直接返回
200
+ if (!fs.existsSync(microFrontendFeaturesPath)) {
201
+ return;
202
+ }
203
+ // 扫描微前端 features 目录
204
+ const availableMicroFrontendFeatures = scanFeatures(microFrontendFeaturesPath);
205
+ // 遍历配置对象,渲染所有值为 true 且存在于微前端 features 的 features
206
+ for (const [key, value] of Object.entries(config)) {
207
+ if (value === true && availableMicroFrontendFeatures.includes(key)) {
208
+ const featurePath = path.join(microFrontendFeaturesPath, key);
209
+ renderTemplate(featurePath, targetDir);
210
+ }
211
+ }
212
+ // UI 库单独处理(如果微前端有 UI 库专属的覆盖)
213
+ if (uiLibrary && availableMicroFrontendFeatures.includes(uiLibrary)) {
214
+ renderTemplate(path.join(microFrontendFeaturesPath, uiLibrary), targetDir);
215
+ }
216
+ }
217
+ // ============================================================================
218
+ // 公共 API(用于测试和文档生成)
219
+ // ============================================================================
220
+ /**
221
+ * 验证微前端引擎是否存在
222
+ * @param framework 框架类型
223
+ * @param engine 微前端引擎名称
224
+ * @returns 引擎是否存在
225
+ */
226
+ export function validateMicroFrontendEngine(framework, engine) {
227
+ const availableEngines = getMicroFrontendEngines(framework);
228
+ return availableEngines.includes(engine);
229
+ }
230
+ /**
231
+ * 获取可用的公共 features(用于测试和文档生成)
232
+ * @returns 公共 feature 名称数组
233
+ */
234
+ export function getAvailableCommonFeatures() {
235
+ return getCommonFeatures();
236
+ }
237
+ /**
238
+ * 获取可用的框架 features(用于测试和文档生成)
239
+ * @param framework 框架类型
240
+ * @returns 框架 feature 名称数组
241
+ */
242
+ export function getAvailableFrameworkFeatures(framework) {
243
+ return getFrameworkFeatures(framework);
244
+ }
245
+ /**
246
+ * 获取可用的微前端引擎(用于测试和文档生成)
247
+ * @param framework 框架类型
248
+ * @returns 微前端引擎名称数组
249
+ */
250
+ export function getAvailableMicroFrontendEngines(framework) {
251
+ return getMicroFrontendEngines(framework);
252
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 核心模块导出
3
+ */
4
+ export * from './feature.ts';
5
+ export * from './prompts.ts';
6
+ export * from './template.ts';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 核心模块导出
3
+ */
4
+ export * from "./feature.js";
5
+ export * from "./prompts.js";
6
+ export * from "./template.js";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * 交互式问答模块
3
+ * 收集用户的项目配置信息(对标 create-vue)
4
+ */
5
+ import type { ProjectConfigType } from '../types/index.ts';
6
+ /**
7
+ * 收集项目配置信息
8
+ * @param projectName 项目名称(可选)
9
+ * @returns 项目配置对象
10
+ */
11
+ export declare function collectProjectConfig(projectName?: string): Promise<ProjectConfigType>;
12
+ /**
13
+ * 确认覆盖目录
14
+ * @param dirPath 目录路径
15
+ * @returns 是否确认覆盖
16
+ */
17
+ export declare function confirmOverwrite(dirPath: string): Promise<boolean>;
@@ -0,0 +1,235 @@
1
+ /**
2
+ * 交互式问答模块
3
+ * 收集用户的项目配置信息(对标 create-vue)
4
+ */
5
+ import fs from 'node:fs';
6
+ import process from 'node:process';
7
+ import inquirer from 'inquirer';
8
+ import { getDefaultAuthor } from "../utils/npmConfig.js";
9
+ import { getRouteModeFeatures } from "./feature.js";
10
+ /**
11
+ * 收集项目配置信息
12
+ * @param projectName 项目名称(可选)
13
+ * @returns 项目配置对象
14
+ */
15
+ export async function collectProjectConfig(projectName) {
16
+ // 获取默认作者信息
17
+ const defaultAuthor = getDefaultAuthor();
18
+ const answers = await inquirer.prompt([
19
+ // 项目名称
20
+ {
21
+ type: 'input',
22
+ name: 'projectName',
23
+ message: '项目名称:',
24
+ default: projectName || 'my-project',
25
+ validate: (input) => {
26
+ const trimmed = input.trim();
27
+ if (!trimmed) {
28
+ return '项目名称不能为空';
29
+ }
30
+ const minLength = 1;
31
+ const maxLength = 214;
32
+ if (trimmed.length < minLength || trimmed.length > maxLength) {
33
+ return `项目名称长度必须在 ${minLength}-${maxLength} 个字符之间`;
34
+ }
35
+ if (!/^[\w-]+$/.test(trimmed)) {
36
+ return '项目名称只能包含字母、数字、连字符和下划线';
37
+ }
38
+ const reservedNames = [
39
+ 'node',
40
+ 'npm',
41
+ 'test',
42
+ 'lib',
43
+ 'api',
44
+ 'www',
45
+ 'admin',
46
+ 'root',
47
+ 'config',
48
+ 'build',
49
+ 'dist',
50
+ 'src',
51
+ 'public',
52
+ 'private',
53
+ ];
54
+ if (reservedNames.includes(trimmed.toLowerCase())) {
55
+ return `项目名称不能使用保留名称: ${trimmed}`;
56
+ }
57
+ // 检查目标目录是否已存在且不为空
58
+ const targetDir = `${process.cwd()}/${trimmed}`;
59
+ if (fs.existsSync(targetDir)) {
60
+ try {
61
+ const stats = fs.statSync(targetDir);
62
+ if (stats.isDirectory()) {
63
+ const files = fs.readdirSync(targetDir);
64
+ if (files.length > 0) {
65
+ return `目录 ${targetDir} 已存在且不为空,请选择其他名称或先清空该目录`;
66
+ }
67
+ }
68
+ }
69
+ catch {
70
+ // 忽略检查错误,让后续流程处理
71
+ }
72
+ }
73
+ return true;
74
+ },
75
+ },
76
+ // 项目描述
77
+ {
78
+ type: 'input',
79
+ name: 'description',
80
+ message: '项目描述:',
81
+ default: 'A Vite project',
82
+ },
83
+ // 作者
84
+ {
85
+ type: 'input',
86
+ name: 'author',
87
+ message: '作者:',
88
+ default: defaultAuthor,
89
+ },
90
+ // 框架选择
91
+ {
92
+ type: 'list',
93
+ name: 'framework',
94
+ message: '选择框架:',
95
+ choices: [
96
+ { name: 'Vue 3', value: 'vue' },
97
+ // TODO: React 功能暂时关闭
98
+ // { name: 'React', value: 'react' },
99
+ ],
100
+ },
101
+ // UI 库选择
102
+ {
103
+ type: 'list',
104
+ name: 'uiLibrary',
105
+ message: '选择 UI 组件库:',
106
+ choices: (answers) => {
107
+ if (answers.framework === 'vue') {
108
+ return [
109
+ { name: 'Element Plus', value: 'element-plus' },
110
+ // TODO: Ant Design Vue 功能暂时关闭
111
+ // { name: 'Ant Design Vue', value: 'ant-design-vue' },
112
+ ];
113
+ }
114
+ else {
115
+ // TODO: React 功能暂时关闭
116
+ // return [{ name: 'Ant Design', value: 'ant-design' }]
117
+ return [];
118
+ }
119
+ },
120
+ },
121
+ // 路由模式(路由已内置,只需选择模式)
122
+ {
123
+ type: 'list',
124
+ name: 'routeMode',
125
+ message: '选择路由模式:',
126
+ choices: [
127
+ { name: '文件系统路由 (vite-plugin-pages)', value: 'pageRoutes' },
128
+ { name: '手动配置路由', value: 'manualRoutes' },
129
+ ],
130
+ },
131
+ // 是否启用国际化
132
+ {
133
+ type: 'confirm',
134
+ name: 'i18n',
135
+ message: '是否启用国际化 (i18n)?',
136
+ default: true,
137
+ },
138
+ // 是否启用微前端
139
+ {
140
+ type: 'confirm',
141
+ name: 'microFrontend',
142
+ message: '是否启用微前端支持?',
143
+ default: false,
144
+ },
145
+ // 微前端引擎选择
146
+ {
147
+ type: 'list',
148
+ name: 'microFrontendEngine',
149
+ message: '选择微前端引擎:',
150
+ choices: [
151
+ { name: 'qiankun (阿里开源)', value: 'qiankun' },
152
+ // TODO: 还没有,后续可考虑接入
153
+ // { name: 'micro-app (京东开源)', value: 'micro-app' },
154
+ ],
155
+ when: (answers) => answers.microFrontend === true,
156
+ },
157
+ // 是否启用错误监控
158
+ {
159
+ type: 'confirm',
160
+ name: 'sentry',
161
+ message: '是否启用错误监控 (Sentry)?',
162
+ default: false,
163
+ },
164
+ // 是否启用 ESLint
165
+ {
166
+ type: 'confirm',
167
+ name: 'eslint',
168
+ message: '是否启用 ESLint 代码规范检查?',
169
+ default: true,
170
+ },
171
+ // 是否启用 Git Hooks
172
+ {
173
+ type: 'confirm',
174
+ name: 'gitHooks',
175
+ message: '是否启用 Git Hooks (husky + commitlint)?',
176
+ default: true,
177
+ },
178
+ // 包管理器选择
179
+ {
180
+ type: 'list',
181
+ name: 'packageManager',
182
+ message: '选择包管理器:',
183
+ choices: [
184
+ { name: 'pnpm (推荐)', value: 'pnpm' },
185
+ { name: 'npm', value: 'npm' },
186
+ { name: 'yarn', value: 'yarn' },
187
+ ],
188
+ default: 'pnpm',
189
+ },
190
+ ]);
191
+ const targetDir = `${process.cwd()}/${answers.projectName}`;
192
+ // 根据框架确定状态管理 feature
193
+ const isPinia = answers.framework === 'vue';
194
+ const isZustand = answers.framework === 'react';
195
+ // 根据路由模式获取对应的布尔特征配置
196
+ const routeMode = answers.routeMode;
197
+ const routeModeFeatures = getRouteModeFeatures(routeMode);
198
+ return {
199
+ projectName: answers.projectName,
200
+ description: answers.description,
201
+ author: answers.author,
202
+ framework: answers.framework,
203
+ uiLibrary: answers.uiLibrary,
204
+ routeMode,
205
+ // feature 名称与目录名称一致
206
+ pinia: isPinia,
207
+ zustand: isZustand,
208
+ manualRoutes: routeModeFeatures.manualRoutes,
209
+ pageRoutes: routeModeFeatures.pageRoutes,
210
+ i18n: answers.i18n,
211
+ microFrontend: answers.microFrontend || false,
212
+ microFrontendEngine: answers.microFrontendEngine,
213
+ sentry: answers.sentry,
214
+ eslint: answers.eslint,
215
+ husky: answers.gitHooks,
216
+ packageManager: answers.packageManager,
217
+ targetDir,
218
+ };
219
+ }
220
+ /**
221
+ * 确认覆盖目录
222
+ * @param dirPath 目录路径
223
+ * @returns 是否确认覆盖
224
+ */
225
+ export async function confirmOverwrite(dirPath) {
226
+ const { confirm } = await inquirer.prompt([
227
+ {
228
+ type: 'confirm',
229
+ name: 'confirm',
230
+ message: `目录 ${dirPath} 已存在,是否覆盖?`,
231
+ default: false,
232
+ },
233
+ ]);
234
+ return confirm;
235
+ }