@moluoxixi/create-app 2.0.408 → 2.0.411

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 (107) hide show
  1. package/dist/test.js +168 -87
  2. package/dist/types/features.d.ts +7 -9
  3. package/dist/types/features.js +6 -25
  4. package/dist/types/index.d.ts +20 -13
  5. package/dist/utils/featureMapping.d.ts +5 -26
  6. package/dist/utils/featureMapping.js +24 -68
  7. package/dist/utils/generateFrameworkProject.d.ts +2 -0
  8. package/dist/utils/generateFrameworkProject.js +136 -21
  9. package/dist/utils/prompts.js +37 -7
  10. package/dist/utils/renderFeatures.d.ts +38 -1
  11. package/dist/utils/renderFeatures.js +121 -37
  12. package/dist/utils/routeModeMapping.d.ts +14 -0
  13. package/dist/utils/routeModeMapping.js +15 -0
  14. package/package.json +2 -3
  15. package/templates/common/base/package.json +1 -1
  16. package/templates/common/base/vite.config.ts.ejs +1 -1
  17. package/templates/react/base/package.json +1 -3
  18. package/templates/react/base/src/main.tsx.ejs +16 -43
  19. package/templates/react/features/pageRoutes/package.json +1 -0
  20. package/templates/react/micro-frontends/qiankun/base/package.json +6 -0
  21. package/templates/react/micro-frontends/qiankun/base/src/main.tsx.ejs +83 -0
  22. package/templates/react/micro-frontends/qiankun/base/vite.config.ts.ejs +89 -0
  23. package/templates/vue/base/package.json +1 -5
  24. package/templates/vue/base/src/main.ts.ejs +18 -41
  25. package/templates/vue/features/element-plus/src/layouts/element.vue +1 -4
  26. package/templates/vue/features/manualRoutes/package.json +0 -1
  27. package/templates/vue/features/manualRoutes/src/router/index.ts +11 -12
  28. package/templates/vue/features/manualRoutes/src/router/routes.ts +14 -23
  29. package/templates/vue/features/pageRoutes/package.json +0 -1
  30. package/templates/vue/features/pageRoutes/src/router/index.ts +11 -12
  31. package/templates/vue/features/pinia/node_modules/.bin/tsc +17 -0
  32. package/templates/vue/features/pinia/node_modules/.bin/tsc.CMD +12 -0
  33. package/templates/vue/features/pinia/node_modules/.bin/tsc.ps1 +41 -0
  34. package/templates/vue/features/pinia/node_modules/.bin/tsserver +17 -0
  35. package/templates/vue/features/pinia/node_modules/.bin/tsserver.CMD +12 -0
  36. package/templates/vue/features/pinia/node_modules/.bin/tsserver.ps1 +41 -0
  37. package/templates/vue/features/pinia/package.json +6 -0
  38. package/templates/vue/micro-frontends/qiankun/base/package.json +6 -0
  39. package/templates/vue/micro-frontends/qiankun/base/src/main.ts.ejs +87 -0
  40. package/templates/vue/micro-frontends/qiankun/base/vite.config.ts.ejs +89 -0
  41. package/templates/vue/micro-frontends/qiankun/features/element-plus/src/layouts/element.vue +120 -0
  42. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/jiti +17 -0
  43. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/jiti.CMD +12 -0
  44. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/jiti.ps1 +41 -0
  45. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/sass +17 -0
  46. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/sass.CMD +12 -0
  47. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/sass.ps1 +41 -0
  48. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/terser +17 -0
  49. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/terser.CMD +12 -0
  50. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/terser.ps1 +41 -0
  51. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsc +17 -0
  52. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsc.CMD +12 -0
  53. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsc.ps1 +41 -0
  54. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsserver +17 -0
  55. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsserver.CMD +12 -0
  56. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsserver.ps1 +41 -0
  57. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsx +17 -0
  58. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsx.CMD +12 -0
  59. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/tsx.ps1 +41 -0
  60. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/vite +17 -0
  61. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/vite.CMD +12 -0
  62. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/vite.ps1 +41 -0
  63. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/yaml +17 -0
  64. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/yaml.CMD +12 -0
  65. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/node_modules/.bin/yaml.ps1 +41 -0
  66. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/package.json +5 -0
  67. package/templates/vue/micro-frontends/qiankun/features/manualRoutes/src/router/index.ts +56 -0
  68. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/jiti +17 -0
  69. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/jiti.CMD +12 -0
  70. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/jiti.ps1 +41 -0
  71. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/sass +17 -0
  72. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/sass.CMD +12 -0
  73. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/sass.ps1 +41 -0
  74. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/terser +17 -0
  75. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/terser.CMD +12 -0
  76. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/terser.ps1 +41 -0
  77. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsc +17 -0
  78. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsc.CMD +12 -0
  79. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsc.ps1 +41 -0
  80. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsserver +17 -0
  81. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsserver.CMD +12 -0
  82. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsserver.ps1 +41 -0
  83. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsx +17 -0
  84. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsx.CMD +12 -0
  85. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/tsx.ps1 +41 -0
  86. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/vite +17 -0
  87. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/vite.CMD +12 -0
  88. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/vite.ps1 +41 -0
  89. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/yaml +17 -0
  90. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/yaml.CMD +12 -0
  91. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/node_modules/.bin/yaml.ps1 +41 -0
  92. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/package.json +5 -0
  93. package/templates/vue/micro-frontends/qiankun/features/pageRoutes/src/router/index.ts +57 -0
  94. package/templates/react/base/src/qiankun/index.ts +0 -83
  95. package/templates/react/base/src/stores/user.ts +0 -55
  96. package/templates/vue/base/src/router/layout.vue +0 -15
  97. package/templates/vue/features/manualRoutes/src/stores/index.ts +0 -6
  98. package/templates/vue/features/manualRoutes/src/stores/modules/system.ts +0 -51
  99. package/templates/vue/features/manualRoutes/src/stores/modules/user.ts +0 -41
  100. package/templates/vue/features/pageRoutes/src/stores/index.ts +0 -6
  101. package/templates/vue/features/pageRoutes/src/stores/modules/system.ts +0 -51
  102. package/templates/vue/features/pageRoutes/src/stores/modules/user.ts +0 -41
  103. /package/templates/react/features/{router → manualRoutes}/package.json +0 -0
  104. /package/templates/react/{base → features/zustand}/src/stores/index.ts +0 -0
  105. /package/templates/vue/{base → features/pinia}/src/stores/index.ts +0 -0
  106. /package/templates/vue/{base → features/pinia}/src/stores/modules/system.ts +0 -0
  107. /package/templates/vue/{base → features/pinia}/src/stores/modules/user.ts +0 -0
package/dist/test.js CHANGED
@@ -14,18 +14,58 @@ import fs from 'fs-extra';
14
14
  import { FILE_CONSTANTS } from "./constants/index.js";
15
15
  import { generateProject } from "./generators/index.js";
16
16
  import { featureToConfig, scanAllFeatures } from "./utils/featureMapping.js";
17
+ import { getRouteModeFeatures } from "./utils/routeModeMapping.js";
17
18
  const __filename = fileURLToPath(import.meta.url);
18
19
  const __dirname = path.dirname(__filename);
19
20
  /** 测试输出目录 */
20
21
  const TEST_OUTPUT_DIR = path.resolve(__dirname, '../test');
21
22
  /**
22
- * 解析命令行参数
23
+ * 测试配置
24
+ * 集中管理测试选项,方便随时调整
23
25
  */
24
- function parseArgs() {
25
- const args = process.argv.slice(2);
26
- const minimalOnly = args.includes('--minimal') || args.includes('--min') || args.includes('-m');
27
- return { minimalOnly };
28
- }
26
+ const TEST_CONFIG = {
27
+ /** 固定默认值(不参与组合测试) */
28
+ defaults: {
29
+ /** 项目名称(会自动生成,此处为描述) */
30
+ projectName: 'auto-generated',
31
+ /** 项目描述 */
32
+ description: 'A Vite project',
33
+ /** 作者 */
34
+ author: 'test',
35
+ /** 是否启用国际化 */
36
+ i18n: true,
37
+ /** 是否启用错误监控 */
38
+ sentry: false,
39
+ /** 是否启用 ESLint */
40
+ eslint: true,
41
+ /** 是否启用 Git Hooks */
42
+ husky: true,
43
+ },
44
+ /** 参与组合测试的选项 */
45
+ combinations: {
46
+ /** 框架列表(空数组表示不启用) */
47
+ frameworks: ['vue', 'react'],
48
+ /** UI 库配置(按框架分组,空数组表示不启用,需要明确配置才启用) */
49
+ uiLibraries: {
50
+ vue: ['element-plus', 'ant-design-vue'], // Vue 可用的 UI 库
51
+ react: ['ant-design'], // React 可用的 UI 库
52
+ },
53
+ /** 路由模式列表(空数组表示不启用) */
54
+ routeModes: ['manualRoutes', 'pageRoutes'],
55
+ /** 微前端引擎列表(空数组表示不启用) */
56
+ microFrontendEngines: ['qiankun'],
57
+ /** 包管理器列表(空数组表示不启用) */
58
+ packageManagers: ['pnpm'],
59
+ /** 是否测试 i18n 的组合 */
60
+ i18n: false,
61
+ /** 是否测试 sentry 的组合 */
62
+ sentry: false,
63
+ /** 是否测试 eslint 的组合 */
64
+ eslint: false,
65
+ /** 是否测试 husky 的组合 */
66
+ husky: false,
67
+ },
68
+ };
29
69
  /**
30
70
  * 生成所有可能的组合(包括全开、全关)
31
71
  */
@@ -44,11 +84,16 @@ function generateAllCombinations(items) {
44
84
  }
45
85
  /**
46
86
  * 自动生成测试用例配置(基于组合算法)
47
- * @param minimalOnly 是否只生成全量和最小配置
48
87
  */
49
- function generateTestConfigs(minimalOnly = false) {
88
+ function generateTestConfigs() {
50
89
  const configs = [];
51
- const frameworks = ['vue', 'react'];
90
+ // 框架列表(空数组表示不启用)
91
+ const frameworks = TEST_CONFIG.combinations.frameworks.length > 0
92
+ ? TEST_CONFIG.combinations.frameworks
93
+ : [];
94
+ if (frameworks.length === 0) {
95
+ return configs;
96
+ }
52
97
  for (const framework of frameworks) {
53
98
  const allFeatures = scanAllFeatures(framework);
54
99
  // 分离不同类型的 features
@@ -71,74 +116,104 @@ function generateTestConfigs(minimalOnly = false) {
71
116
  }
72
117
  if (uiLibraries.length === 0)
73
118
  continue;
74
- if (minimalOnly) {
75
- // 只生成全量和最小配置:每个框架只选择一个 UI 库和一个路由模式
76
- const uiLibrary = uiLibraries[0]; // 只选择第一个 UI 库
77
- const routeModeFeature = routeModes.length > 0 ? routeModes[0] : 'manualRoutes'; // 只选择第一个路由模式
78
- // 只生成全量和最小两种配置
79
- const allFalse = Array.from({ length: booleanFeatures.length }, () => false);
80
- const allTrue = Array.from({ length: booleanFeatures.length }, () => true);
81
- const combinations = [allFalse, allTrue];
82
- // 为每种包管理器生成测试用例
83
- const packageManagers = ['pnpm', 'npm', 'yarn'];
84
- for (const packageManager of packageManagers) {
85
- for (const combination of combinations) {
86
- const config = {
87
- framework,
88
- uiLibrary: uiLibrary,
89
- routeMode: featureToConfig(routeModeFeature, framework).value,
90
- packageManager,
91
- };
92
- // 应用布尔 features 的组合
93
- for (let i = 0; i < booleanFeatures.length; i++) {
94
- const feature = booleanFeatures[i];
95
- const enabled = combination[i];
96
- const featureConfig = featureToConfig(feature, framework);
97
- if (featureConfig && featureConfig.key !== 'uiLibrary' && featureConfig.key !== 'routeMode') {
98
- config[featureConfig.key] = enabled;
99
- }
100
- }
101
- // 生成测试用例名称(包含包管理器)
102
- const suffix = combination.every(v => !v) ? 'minimal' : 'full';
103
- configs.push(createTestConfig(framework, uiLibrary, `${packageManager}-${suffix}`, config));
119
+ // 过滤掉不需要测试的布尔特性(根据 combinations 配置决定)
120
+ // 过滤掉根据框架自动选择的特性(pinia/zustand)
121
+ const autoSelectedFeatures = framework === 'vue' ? ['pinia'] : ['zustand'];
122
+ const filteredBooleanFeatures = booleanFeatures.filter((feature) => {
123
+ // 排除自动选择的特性
124
+ if (autoSelectedFeatures.includes(feature)) {
125
+ return false;
126
+ }
127
+ // 根据 combinations 配置决定是否参与组合测试
128
+ const featureConfig = featureToConfig(feature, framework);
129
+ if (featureConfig && featureConfig.key in TEST_CONFIG.combinations) {
130
+ const combinationValue = TEST_CONFIG.combinations[featureConfig.key];
131
+ // 如果是数组(frameworks, uiLibraries, routeModes, packageManagers),跳过
132
+ if (Array.isArray(combinationValue)) {
133
+ return true;
104
134
  }
135
+ // 其他布尔特性根据配置决定(i18n, sentry, eslint, husky)
136
+ // 使用 Boolean() 转换,避免类型检查问题
137
+ return Boolean(combinationValue);
105
138
  }
139
+ // 默认参与组合测试
140
+ return true;
141
+ });
142
+ // 生成所有组合
143
+ // UI 库列表(按框架分组配置,空数组表示不启用)
144
+ const frameworkUiLibraries = TEST_CONFIG.combinations.uiLibraries[framework] || [];
145
+ // 如果配置为空数组,表示不启用该框架的 UI 库测试
146
+ if (frameworkUiLibraries.length === 0) {
147
+ continue;
106
148
  }
107
- else {
108
- // 生成所有组合
109
- for (const uiLibrary of uiLibraries) {
110
- // 为每个路由模式生成测试用例
111
- const routeModesToTest = routeModes.length > 0 ? routeModes : ['manualRoutes']; // 默认
112
- for (const routeModeFeature of routeModesToTest) {
149
+ // 只测试配置中指定的 UI 库
150
+ const uiLibrariesToTest = uiLibraries.filter(uiLib => frameworkUiLibraries.includes(uiLib));
151
+ if (uiLibrariesToTest.length === 0) {
152
+ continue;
153
+ }
154
+ for (const uiLibrary of uiLibrariesToTest) {
155
+ // 路由模式列表(空数组表示不启用,使用默认值)
156
+ const routeModesToTest = TEST_CONFIG.combinations.routeModes.length > 0
157
+ ? routeModes.filter(routeMode => TEST_CONFIG.combinations.routeModes.includes(routeMode))
158
+ : (routeModes.length > 0 ? routeModes : ['manualRoutes']); // 默认
159
+ if (routeModesToTest.length === 0) {
160
+ continue;
161
+ }
162
+ for (const routeModeFeature of routeModesToTest) {
163
+ // 微前端引擎列表(空数组表示不启用)
164
+ const microFrontendEnginesToTest = TEST_CONFIG.combinations.microFrontendEngines;
165
+ // 如果配置了微前端引擎,生成两种组合:不带微前端(null)和带微前端(配置的引擎)
166
+ // 如果没配置,只生成不带微前端的组合
167
+ const microFrontendOptions = microFrontendEnginesToTest.length > 0
168
+ ? [null, ...microFrontendEnginesToTest] // 总是包含 null(不带),再加上配置的引擎
169
+ : [null]; // 如果没配置,只生成不带微前端的
170
+ for (const microFrontendEngine of microFrontendOptions) {
113
171
  // 生成所有布尔 features 的组合(2^n 种)
114
- const combinations = generateAllCombinations(booleanFeatures);
115
- // 为每种包管理器生成测试用例
116
- const packageManagers = ['pnpm', 'npm', 'yarn'];
117
- for (const packageManager of packageManagers) {
172
+ const combinations = generateAllCombinations(filteredBooleanFeatures);
173
+ // 包管理器列表(空数组表示不启用)
174
+ const packageManagersToTest = TEST_CONFIG.combinations.packageManagers;
175
+ if (packageManagersToTest.length === 0) {
176
+ continue;
177
+ }
178
+ for (const packageManager of packageManagersToTest) {
118
179
  for (const combination of combinations) {
119
180
  const config = {
120
181
  framework,
121
182
  uiLibrary: uiLibrary,
122
183
  routeMode: featureToConfig(routeModeFeature, framework).value,
123
184
  packageManager,
185
+ microFrontend: microFrontendEngine !== null,
186
+ microFrontendEngine: microFrontendEngine || undefined,
124
187
  };
188
+ // 根据 routeMode 设置对应的布尔 feature
189
+ const routeModeFeatures = getRouteModeFeatures(routeModeFeature);
190
+ config.manualRoutes = routeModeFeatures.manualRoutes;
191
+ config.pageRoutes = routeModeFeatures.pageRoutes;
125
192
  // 应用布尔 features 的组合
126
- for (let i = 0; i < booleanFeatures.length; i++) {
127
- const feature = booleanFeatures[i];
193
+ for (let i = 0; i < filteredBooleanFeatures.length; i++) {
194
+ const feature = filteredBooleanFeatures[i];
128
195
  const enabled = combination[i];
129
196
  const featureConfig = featureToConfig(feature, framework);
130
197
  if (featureConfig && featureConfig.key !== 'uiLibrary' && featureConfig.key !== 'routeMode') {
131
198
  config[featureConfig.key] = enabled;
132
199
  }
133
200
  }
134
- // 生成测试用例名称(包含包管理器)
135
- const enabledFeatures = booleanFeatures.filter((_, i) => combination[i]);
136
- const suffix = enabledFeatures.length === 0
137
- ? 'minimal'
138
- : enabledFeatures.length === booleanFeatures.length
139
- ? 'full'
140
- : enabledFeatures.join('-');
141
- configs.push(createTestConfig(framework, uiLibrary, `${packageManager}-${routeModeFeature}-${suffix}`, config));
201
+ // 生成测试用例名称
202
+ // 如果没有布尔特性组合,使用固定后缀
203
+ const suffix = filteredBooleanFeatures.length === 0
204
+ ? 'default'
205
+ : (() => {
206
+ const enabledFeatures = filteredBooleanFeatures.filter((_, i) => combination[i]);
207
+ return enabledFeatures.length === 0
208
+ ? 'minimal'
209
+ : enabledFeatures.length === filteredBooleanFeatures.length
210
+ ? 'full'
211
+ : enabledFeatures.join('-');
212
+ })();
213
+ // 生成测试用例名称
214
+ const packageManagerSuffix = TEST_CONFIG.combinations.packageManagers.length > 1 ? `${packageManager}-` : '';
215
+ const microFrontendSuffix = microFrontendEngine ? `${microFrontendEngine}-` : '';
216
+ configs.push(createTestConfig(framework, uiLibrary, `${packageManagerSuffix}${microFrontendSuffix}${routeModeFeature}-${suffix}`, config));
142
217
  }
143
218
  }
144
219
  }
@@ -160,23 +235,28 @@ function createTestConfig(framework, uiLibrary, suffix, overrides) {
160
235
  return {
161
236
  name,
162
237
  config: {
238
+ // 固定默认值,不参与组合测试
163
239
  projectName: name,
164
- description: `${framework === 'vue' ? 'Vue' : 'React'} + ${uiLibrary} ${suffix}`,
165
- author: 'test',
240
+ description: TEST_CONFIG.defaults.description,
241
+ author: TEST_CONFIG.defaults.author,
242
+ // 固定默认值,不参与组合测试(避免几何级增长)
243
+ i18n: TEST_CONFIG.defaults.i18n,
244
+ sentry: TEST_CONFIG.defaults.sentry,
245
+ eslint: TEST_CONFIG.defaults.eslint,
246
+ husky: TEST_CONFIG.defaults.husky,
247
+ packageManager: TEST_CONFIG.combinations.packageManagers[0],
166
248
  ...overrides,
167
249
  },
168
250
  };
169
251
  }
170
252
  /**
171
253
  * 生成测试项目
172
- * @param minimalOnly 是否只生成全量和最小配置
173
254
  * @returns Promise<void>
174
255
  */
175
- async function generateTestProjects(minimalOnly = false) {
176
- const mode = minimalOnly ? '(仅全量和最小配置)' : '(全部组合)';
177
- console.log(chalk.blue.bold(`\n🧪 开始生成测试项目${mode}...\n`));
256
+ async function generateTestProjects() {
257
+ console.log(chalk.blue.bold('\n🧪 开始生成测试项目...\n'));
178
258
  // 扫描并生成测试配置
179
- const TEST_CONFIGS = generateTestConfigs(minimalOnly);
259
+ const TEST_CONFIGS = generateTestConfigs();
180
260
  console.log(chalk.cyan(`📋 扫描到 ${TEST_CONFIGS.length} 个测试用例\n`));
181
261
  // 清理并创建测试目录
182
262
  if (fs.existsSync(TEST_OUTPUT_DIR)) {
@@ -193,20 +273,26 @@ async function generateTestProjects(minimalOnly = false) {
193
273
  // 根据框架决定输出目录
194
274
  const frameworkOutputDir = config.framework === 'vue' ? vueOutputDir : reactOutputDir;
195
275
  const fullConfig = {
196
- projectName: config.projectName,
197
- description: config.description,
198
- author: config.author,
276
+ // 固定默认值(不参与组合测试)
277
+ projectName: config.projectName || name,
278
+ description: config.description || TEST_CONFIG.defaults.description,
279
+ author: config.author || TEST_CONFIG.defaults.author,
199
280
  framework: config.framework,
200
281
  uiLibrary: config.uiLibrary,
201
282
  routeMode: config.routeMode,
202
- router: config.router ?? true,
203
- stateManagement: config.stateManagement ?? true,
204
- i18n: config.i18n,
205
- qiankun: config.qiankun,
206
- sentry: config.sentry,
207
- eslint: config.eslint,
208
- gitHooks: config.gitHooks,
209
- packageManager: config.packageManager,
283
+ // feature 名称与目录名称一致
284
+ pinia: config.framework === 'vue',
285
+ zustand: config.framework === 'react',
286
+ ...getRouteModeFeatures(config.routeMode),
287
+ // 固定默认值(不参与组合测试,避免几何级增长)
288
+ i18n: config.i18n ?? TEST_CONFIG.defaults.i18n,
289
+ sentry: config.sentry ?? TEST_CONFIG.defaults.sentry,
290
+ eslint: config.eslint ?? TEST_CONFIG.defaults.eslint,
291
+ husky: config.husky ?? TEST_CONFIG.defaults.husky,
292
+ // 参与组合测试的特性
293
+ microFrontend: config.microFrontend ?? false,
294
+ microFrontendEngine: config.microFrontendEngine,
295
+ packageManager: config.packageManager ?? TEST_CONFIG.combinations.packageManagers[0],
210
296
  targetDir: path.join(frameworkOutputDir, name),
211
297
  };
212
298
  try {
@@ -257,11 +343,10 @@ function checkPackageJsonVersions(projectDir) {
257
343
  }
258
344
  /**
259
345
  * 审计 @moluoxixi 依赖
260
- * @param minimalOnly 是否只生成全量和最小配置
261
346
  */
262
- async function auditMoluoxixiDeps(minimalOnly = false) {
347
+ async function auditMoluoxixiDeps() {
263
348
  console.log(chalk.blue.bold('\n🔍 开始审计 @moluoxixi 依赖...\n'));
264
- const TEST_CONFIGS = generateTestConfigs(minimalOnly);
349
+ const TEST_CONFIGS = generateTestConfigs();
265
350
  const requiredDeps = [
266
351
  '@moluoxixi/vite-config',
267
352
  '@moluoxixi/ajax-package',
@@ -312,7 +397,7 @@ async function auditMoluoxixiDeps(minimalOnly = false) {
312
397
  console.log(chalk.green(` ✅ eslint.config.ts 已正确移除`));
313
398
  }
314
399
  }
315
- if (!config.gitHooks) {
400
+ if (!config.husky) {
316
401
  const huskyDir = path.join(projectDir, '.husky');
317
402
  if (fs.existsSync(huskyDir)) {
318
403
  console.log(chalk.red(` ❌ 不应存在 .husky/ 目录(Git Hooks 已禁用)`));
@@ -400,17 +485,13 @@ async function printFileTree(dir, indent) {
400
485
  * @returns Promise<void>
401
486
  */
402
487
  async function main() {
403
- const { minimalOnly } = parseArgs();
404
488
  console.log(chalk.blue.bold(`\n${'='.repeat(60)}`));
405
489
  console.log(chalk.blue.bold(' Vite CLI Next - 产物审计测试'));
406
- if (minimalOnly) {
407
- console.log(chalk.yellow.bold(' 模式: 仅全量和最小配置'));
408
- }
409
490
  console.log(chalk.blue.bold('='.repeat(60)));
410
491
  // 1. 生成测试项目
411
- await generateTestProjects(minimalOnly);
492
+ await generateTestProjects();
412
493
  // 2. 审计 @moluoxixi 依赖
413
- await auditMoluoxixiDeps(minimalOnly);
494
+ await auditMoluoxixiDeps();
414
495
  // 3. 显示文件树
415
496
  await showFileTrees();
416
497
  console.log(chalk.green.bold('\n✅ 全量产物审计完成!\n'));
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * 特性配置定义
3
- * 定义所有可用特性的 ID
3
+ * 核心依赖和微前端引擎类型定义
4
+ *
5
+ * 注意:Features 现在通过文件系统扫描自动发现,无需在此维护常量列表
6
+ * 参考:src/utils/renderFeatures.ts
4
7
  */
5
8
  /**
6
9
  * @moluoxixi 核心依赖配置
@@ -14,12 +17,7 @@ export declare const MOLUOXIXI_DEPS: {
14
17
  readonly '@moluoxixi/css-module-global-root-plugin': "latest";
15
18
  };
16
19
  /**
17
- * Vue 特性 ID
20
+ * 微前端引擎类型
18
21
  */
19
- export declare const VUE_FEATURES: readonly ["router", "pinia", "eslint", "i18n", "sentry", "qiankun", "pageRoutes", "element-plus", "ant-design-vue"];
20
- /**
21
- * React 特性 ID
22
- */
23
- export declare const REACT_FEATURES: readonly ["router", "zustand", "eslint", "i18n", "sentry", "qiankun", "ant-design"];
24
- export type VueFeatureId = typeof VUE_FEATURES[number];
25
- export type ReactFeatureId = typeof REACT_FEATURES[number];
22
+ export declare const MICRO_FRONTEND_ENGINES: readonly ["qiankun", "micro-app"];
23
+ export type MicroFrontendEngine = typeof MICRO_FRONTEND_ENGINES[number];
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * 特性配置定义
3
- * 定义所有可用特性的 ID
3
+ * 核心依赖和微前端引擎类型定义
4
+ *
5
+ * 注意:Features 现在通过文件系统扫描自动发现,无需在此维护常量列表
6
+ * 参考:src/utils/renderFeatures.ts
4
7
  */
5
8
  /**
6
9
  * @moluoxixi 核心依赖配置
@@ -14,28 +17,6 @@ export const MOLUOXIXI_DEPS = {
14
17
  '@moluoxixi/css-module-global-root-plugin': 'latest',
15
18
  };
16
19
  /**
17
- * Vue 特性 ID
20
+ * 微前端引擎类型
18
21
  */
19
- export const VUE_FEATURES = [
20
- 'router',
21
- 'pinia',
22
- 'eslint',
23
- 'i18n',
24
- 'sentry',
25
- 'qiankun',
26
- 'pageRoutes',
27
- 'element-plus',
28
- 'ant-design-vue',
29
- ];
30
- /**
31
- * React 特性 ID
32
- */
33
- export const REACT_FEATURES = [
34
- 'router',
35
- 'zustand',
36
- 'eslint',
37
- 'i18n',
38
- 'sentry',
39
- 'qiankun',
40
- 'ant-design',
41
- ];
22
+ export const MICRO_FRONTEND_ENGINES = ['qiankun', 'micro-app'];
@@ -2,6 +2,7 @@
2
2
  * CLI 类型定义
3
3
  * 定义项目配置、模板层级等核心类型
4
4
  */
5
+ import type { MicroFrontendEngine } from './features.ts';
5
6
  export * from './ejs.ts';
6
7
  export * from './features.ts';
7
8
  /**
@@ -15,7 +16,7 @@ export type UILibraryType = 'element-plus' | 'ant-design-vue' | 'ant-design';
15
16
  /**
16
17
  * 路由模式类型
17
18
  */
18
- export type RouteModeType = 'file-system' | 'manual';
19
+ export type RouteModeType = 'manualRoutes' | 'pageRoutes';
19
20
  /**
20
21
  * 包管理器类型
21
22
  */
@@ -32,24 +33,30 @@ export interface ProjectConfigType {
32
33
  author: string;
33
34
  /** 框架类型 */
34
35
  framework: FrameworkType;
35
- /** UI */
36
+ /** UI 库(feature 名称:element-plus | ant-design-vue | ant-design) */
36
37
  uiLibrary: UILibraryType;
37
- /** 路由模式 */
38
+ /** 路由模式(决定使用 manualRoutes 还是 pageRoutes feature) */
38
39
  routeMode: RouteModeType;
39
- /** 是否启用路由 */
40
- router: boolean;
41
- /** 是否启用状态管理 (Vue: pinia, React: zustand) */
42
- stateManagement: boolean;
43
- /** 是否启用国际化 */
40
+ /** 是否启用 pinia/zustand feature */
41
+ pinia?: boolean;
42
+ /** 是否启用 zustand feature (React) */
43
+ zustand?: boolean;
44
+ /** 是否启用 manualRoutes feature */
45
+ manualRoutes?: boolean;
46
+ /** 是否启用 pageRoutes feature */
47
+ pageRoutes?: boolean;
48
+ /** 是否启用 i18n feature */
44
49
  i18n: boolean;
45
50
  /** 是否启用微前端支持 */
46
- qiankun: boolean;
47
- /** 是否启用错误监控 */
51
+ microFrontend: boolean;
52
+ /** 微前端引擎(qiankun、micro-app 等)- 当 microFrontend 为 true 时有效 */
53
+ microFrontendEngine?: MicroFrontendEngine;
54
+ /** 是否启用 sentry feature */
48
55
  sentry: boolean;
49
- /** 是否启用 ESLint */
56
+ /** 是否启用 eslint feature */
50
57
  eslint: boolean;
51
- /** 是否启用 Git Hooks (husky + commitlint + lint-staged) */
52
- gitHooks: boolean;
58
+ /** 是否启用 husky feature (Git Hooks) */
59
+ husky: boolean;
53
60
  /** 包管理器 */
54
61
  packageManager: PackageManagerType;
55
62
  /** 目标目录 */
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Features 映射工具
3
- * 统一管理配置项到 feature 目录的映射关系
3
+ * 用于测试用例生成和 feature 扫描
4
+ * 注意:配置名称与 feature 目录名称完全一致,无需额外映射
4
5
  */
5
6
  import type { FrameworkType } from '../types/index.ts';
6
7
  /**
@@ -9,36 +10,14 @@ import type { FrameworkType } from '../types/index.ts';
9
10
  * @returns 所有 feature 名称数组(UI 库按优先级排序)
10
11
  */
11
12
  export declare function scanAllFeatures(framework: FrameworkType): string[];
12
- /**
13
- * 配置项到 feature 目录的映射(从 renderFeatures 提取)
14
- * @param _framework 框架类型(已不再使用,保留以保持接口兼容性)
15
- * @returns 配置键到 feature 名称的映射对象
16
- */
17
- export declare function getConfigToFeatureMap(_framework: FrameworkType): Record<string, string>;
18
- /**
19
- * 公共 features 映射
20
- * @returns 公共配置键到 feature 名称的映射对象
21
- */
22
- export declare function getCommonFeatureMap(): Record<string, string>;
23
- /**
24
- * 路由模式映射
25
- * @param routeMode 路由模式('manual' 或 'file-system')
26
- * @returns feature 名称
27
- */
28
- export declare function getRouteModeFeature(routeMode: string): string;
29
- /**
30
- * UI 库映射
31
- * @param uiLibrary UI 库名称
32
- * @returns feature 名称(通常与 UI 库名称相同)
33
- */
34
- export declare function getUILibraryFeature(uiLibrary: string): string;
35
13
  /**
36
14
  * Feature 名称转换为配置键和值(用于测试用例生成)
15
+ * 注意:大部分情况下 feature 名称 === 配置名称
37
16
  * @param feature feature 名称
38
- * @param framework 框架类型
17
+ * @param _framework 框架类型(保留参数以保持接口兼容性)
39
18
  * @returns 配置键值对,如果无法映射则返回 null
40
19
  */
41
- export declare function featureToConfig(feature: string, framework: FrameworkType): {
20
+ export declare function featureToConfig(feature: string, _framework: FrameworkType): {
42
21
  key: string;
43
22
  value: string | boolean;
44
23
  } | null;
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Features 映射工具
3
- * 统一管理配置项到 feature 目录的映射关系
3
+ * 用于测试用例生成和 feature 扫描
4
+ * 注意:配置名称与 feature 目录名称完全一致,无需额外映射
4
5
  */
5
6
  import fs from 'fs-extra';
6
7
  import path from 'node:path';
@@ -39,79 +40,34 @@ export function scanAllFeatures(framework) {
39
40
  return a.localeCompare(b);
40
41
  });
41
42
  }
42
- /**
43
- * 配置项到 feature 目录的映射(从 renderFeatures 提取)
44
- * @param _framework 框架类型(已不再使用,保留以保持接口兼容性)
45
- * @returns 配置键到 feature 名称的映射对象
46
- */
47
- export function getConfigToFeatureMap(_framework) {
48
- return {
49
- // router、stateManagement、qiankun 已内置到 base,不再作为 feature
50
- eslint: 'eslint',
51
- i18n: 'i18n',
52
- sentry: 'sentry',
53
- };
54
- }
55
- /**
56
- * 公共 features 映射
57
- * @returns 公共配置键到 feature 名称的映射对象
58
- */
59
- export function getCommonFeatureMap() {
60
- return {
61
- gitHooks: 'husky',
62
- };
63
- }
64
- /**
65
- * 路由模式映射
66
- * @param routeMode 路由模式('manual' 或 'file-system')
67
- * @returns feature 名称
68
- */
69
- export function getRouteModeFeature(routeMode) {
70
- return routeMode === 'manual' ? 'manualRoutes' : 'pageRoutes';
71
- }
72
- /**
73
- * UI 库映射
74
- * @param uiLibrary UI 库名称
75
- * @returns feature 名称(通常与 UI 库名称相同)
76
- */
77
- export function getUILibraryFeature(uiLibrary) {
78
- return uiLibrary;
79
- }
80
43
  /**
81
44
  * Feature 名称转换为配置键和值(用于测试用例生成)
45
+ * 注意:大部分情况下 feature 名称 === 配置名称
82
46
  * @param feature feature 名称
83
- * @param framework 框架类型
47
+ * @param _framework 框架类型(保留参数以保持接口兼容性)
84
48
  * @returns 配置键值对,如果无法映射则返回 null
85
49
  */
86
- export function featureToConfig(feature, framework) {
87
- // 路由模式
88
- if (feature === 'manualRoutes')
89
- return { key: 'routeMode', value: 'manual' };
90
- if (feature === 'pageRoutes')
91
- return { key: 'routeMode', value: 'file-system' };
92
- // UI 库
50
+ export function featureToConfig(feature, _framework) {
51
+ // UI 库:配置键是 uiLibrary,值是 feature 名称
93
52
  const uiLibraries = ['element-plus', 'ant-design-vue', 'ant-design'];
94
- if (uiLibraries.includes(feature))
53
+ if (uiLibraries.includes(feature)) {
95
54
  return { key: 'uiLibrary', value: feature };
96
- // 状态管理(反向映射)
97
- const stateManagementMap = {
98
- pinia: 'stateManagement',
99
- zustand: 'stateManagement',
100
- };
101
- if (stateManagementMap[feature])
102
- return { key: stateManagementMap[feature], value: true };
103
- // Git Hooks(公共 feature)
104
- if (feature === 'husky')
105
- return { key: 'gitHooks', value: true };
106
- // 其他布尔 features(通过映射查找)
107
- const configMap = getConfigToFeatureMap(framework);
108
- const configKey = Object.keys(configMap).find(key => configMap[key] === feature);
109
- if (configKey)
110
- return { key: configKey, value: true };
111
- // 公共 features
112
- const commonMap = getCommonFeatureMap();
113
- const commonKey = Object.keys(commonMap).find(key => commonMap[key] === feature);
114
- if (commonKey)
115
- return { key: commonKey, value: true };
55
+ }
56
+ // 路由模式 features:用于测试分类
57
+ if (feature === 'manualRoutes' || feature === 'pageRoutes') {
58
+ return { key: 'routeMode', value: feature };
59
+ }
60
+ // 布尔类型的 features:配置名 === feature
61
+ const booleanFeatures = [
62
+ 'eslint',
63
+ 'i18n',
64
+ 'sentry',
65
+ 'pinia',
66
+ 'zustand',
67
+ 'husky',
68
+ ];
69
+ if (booleanFeatures.includes(feature)) {
70
+ return { key: feature, value: true };
71
+ }
116
72
  return null;
117
73
  }