generator-mico-cli 0.1.29 → 0.2.2-8.beta.1

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 (160) hide show
  1. package/README.md +199 -15
  2. package/bin/mico.js +232 -27
  3. package/generators/micro-react/index.js +200 -18
  4. package/generators/micro-react/meta.json +13 -0
  5. package/generators/micro-react/templates/.commitlintrc.js +1 -0
  6. package/generators/micro-react/templates/.cursor/rules/always-read-docs.mdc +14 -4
  7. package/generators/micro-react/templates/.cursor/rules/cicd-deploy.mdc +10 -8
  8. package/generators/micro-react/templates/.cursor/rules/coding-conventions.mdc +1 -1
  9. package/generators/micro-react/templates/.cursor/rules/development-guide.mdc +3 -4
  10. package/generators/micro-react/templates/.cursor/rules/layout-app.mdc +38 -31
  11. package/generators/micro-react/templates/.cursor/rules/project-overview.mdc +7 -4
  12. package/generators/micro-react/templates/.cursor/rules/theme-system.mdc +10 -12
  13. package/generators/micro-react/templates/.eslintrc.js +25 -1
  14. package/generators/micro-react/templates/AGENTS.md +5 -2
  15. package/generators/micro-react/templates/CICD/before_build.sh +76 -0
  16. package/generators/micro-react/templates/CICD/start_dev.sh +27 -3
  17. package/generators/micro-react/templates/CICD/start_prod.sh +26 -3
  18. package/generators/micro-react/templates/CICD/start_test.sh +28 -3
  19. package/generators/micro-react/templates/CICD/wangsu_fresh_dev.sh +4 -4
  20. package/generators/micro-react/templates/CICD/wangsu_fresh_prod.sh +4 -4
  21. package/generators/micro-react/templates/CICD/wangsu_fresh_test.sh +4 -4
  22. package/generators/micro-react/templates/CLAUDE.md +16 -9
  23. package/generators/micro-react/templates/README.md +42 -4
  24. package/generators/micro-react/templates/_gitignore +4 -0
  25. package/generators/micro-react/templates/_npmrc +4 -0
  26. package/generators/micro-react/templates/apps/layout/config/config.dev.ts +33 -17
  27. package/generators/micro-react/templates/apps/layout/config/config.prod.development.ts +24 -29
  28. package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +25 -6
  29. package/generators/micro-react/templates/apps/layout/config/config.prod.ts +16 -7
  30. package/generators/micro-react/templates/apps/layout/config/config.ts +27 -4
  31. package/generators/micro-react/templates/apps/layout/config/routes.ts +10 -5
  32. package/generators/micro-react/templates/apps/layout/docs/arch-/346/227/245/345/277/227/344/270/216/345/270/270/351/207/217.md +2 -2
  33. package/generators/micro-react/templates/apps/layout/docs/arch-/350/257/267/346/261/202/346/250/241/345/235/227.md +1 -1
  34. package/generators/micro-react/templates/apps/layout/docs/common-intl.md +372 -0
  35. package/generators/micro-react/templates/apps/layout/docs/feat-/346/236/204/345/273/272define/344/270/216/345/205/215/350/256/244/350/257/201/345/210/235/345/247/213/346/200/201.md +44 -0
  36. package/generators/micro-react/templates/apps/layout/docs/feature-404/351/241/265/351/235/242.md +103 -0
  37. package/generators/micro-react/templates/apps/layout/docs/feature-/344/270/273/351/242/230/350/211/262/345/210/207/346/215/242.md +22 -26
  38. package/generators/micro-react/templates/apps/layout/docs/feature-/345/276/256/345/211/215/347/253/257/346/250/241/345/274/217.md +185 -28
  39. package/generators/micro-react/templates/apps/layout/docs/feature-/350/217/234/345/215/225/346/235/203/351/231/220/346/216/247/345/210/266.md +420 -0
  40. package/generators/micro-react/templates/apps/layout/docs/feature-/350/267/257/347/224/261/344/270/216/350/217/234/345/215/225/350/247/243/350/200/246.md +179 -0
  41. package/generators/micro-react/templates/apps/layout/docs/fix-SSO/346/227/240/351/231/220/351/207/215/345/256/232/345/220/221.md +88 -0
  42. package/generators/micro-react/templates/apps/layout/docs/utils-timezone.md +324 -0
  43. package/generators/micro-react/templates/apps/layout/mock/api.mock.ts +81 -61
  44. package/generators/micro-react/templates/apps/layout/mock/menus.ts +114 -4
  45. package/generators/micro-react/templates/apps/layout/mock/pages.ts +86 -0
  46. package/generators/micro-react/templates/apps/layout/package.json +7 -4
  47. package/generators/micro-react/templates/apps/layout/src/app.tsx +122 -83
  48. package/generators/micro-react/templates/apps/layout/src/common/auth/index.ts +3 -0
  49. package/generators/micro-react/templates/apps/layout/src/common/helpers.ts +177 -0
  50. package/generators/micro-react/templates/apps/layout/src/common/locale.ts +22 -17
  51. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +283 -28
  52. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +69 -5
  53. package/generators/micro-react/templates/apps/layout/src/common/micro/index.ts +34 -0
  54. package/generators/micro-react/templates/apps/layout/src/common/micro-prefetch.ts +109 -0
  55. package/generators/micro-react/templates/apps/layout/src/common/portal-data.ts +45 -0
  56. package/generators/micro-react/templates/apps/layout/src/common/request/config.ts +72 -10
  57. package/generators/micro-react/templates/apps/layout/src/common/request/index.ts +2 -2
  58. package/generators/micro-react/templates/apps/layout/src/common/request/interceptors.ts +31 -3
  59. package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +29 -11
  60. package/generators/micro-react/templates/apps/layout/src/common/request/url-resolver.ts +23 -8
  61. package/generators/micro-react/templates/apps/layout/src/common/route-guard.ts +345 -0
  62. package/generators/micro-react/templates/apps/layout/src/common/theme.ts +2 -4
  63. package/generators/micro-react/templates/apps/layout/src/common/upload/oss.ts +3 -4
  64. package/generators/micro-react/templates/apps/layout/src/common/upload/types.ts +1 -1
  65. package/generators/micro-react/templates/apps/layout/src/common/uploadFiles.ts +1 -1
  66. package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.less +8 -3
  67. package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.tsx +25 -8
  68. package/generators/micro-react/templates/apps/layout/src/components/HeaderDropdown/index.tsx +20 -0
  69. package/generators/micro-react/templates/apps/layout/src/components/IconFont/index.tsx +5 -6
  70. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.less +21 -6
  71. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +83 -107
  72. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/micro-app-manager.ts +569 -0
  73. package/generators/micro-react/templates/apps/layout/src/components/RightContent/AvatarDropdown.tsx +383 -0
  74. package/generators/micro-react/templates/apps/layout/src/components/RightContent/avatar-dropdown.less +35 -0
  75. package/generators/micro-react/templates/apps/layout/src/components/RightContent/index.ts +2 -0
  76. package/generators/micro-react/templates/apps/layout/src/constants/index.ts +170 -6
  77. package/generators/micro-react/templates/apps/layout/src/global.less +19 -6
  78. package/generators/micro-react/templates/apps/layout/src/hooks/useMenu.ts +3 -2
  79. package/generators/micro-react/templates/apps/layout/src/hooks/useRoutePermissionRefresh.ts +72 -0
  80. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.less +3 -1
  81. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +10 -55
  82. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.less +34 -4
  83. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +33 -9
  84. package/generators/micro-react/templates/apps/layout/src/layouts/index.less +84 -13
  85. package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +178 -47
  86. package/generators/micro-react/templates/apps/layout/src/locales/en-US.ts +12 -0
  87. package/generators/micro-react/templates/apps/layout/src/locales/zh-CN.ts +12 -0
  88. package/generators/micro-react/templates/apps/layout/src/pages/403/index.tsx +34 -0
  89. package/generators/micro-react/templates/apps/layout/src/pages/404/index.tsx +78 -0
  90. package/generators/micro-react/templates/apps/layout/src/pages/Home/index.less +3 -0
  91. package/generators/micro-react/templates/apps/layout/src/pages/Home/index.tsx +7 -1
  92. package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.less +1 -1
  93. package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.tsx +9 -5
  94. package/generators/micro-react/templates/apps/layout/src/requestErrorConfig.ts +1 -1
  95. package/generators/micro-react/templates/apps/layout/src/services/config/index.ts +63 -0
  96. package/generators/micro-react/templates/apps/layout/src/services/config/type.ts +30 -0
  97. package/generators/micro-react/templates/apps/layout/src/services/user.ts +29 -2
  98. package/generators/micro-react/templates/apps/layout/tailwind.config.js +3 -0
  99. package/generators/micro-react/templates/deployDesc.md +3 -3
  100. package/generators/micro-react/templates/dev.preset.json +14 -0
  101. package/generators/micro-react/templates/docs/dev-preset.md +130 -0
  102. package/generators/micro-react/templates/package.json +21 -6
  103. package/generators/micro-react/templates/packages/common-intl/README.md +427 -0
  104. package/generators/micro-react/templates/packages/common-intl/package.json +34 -0
  105. package/generators/micro-react/templates/packages/common-intl/src/index.ts +7 -0
  106. package/generators/micro-react/templates/packages/common-intl/src/indexedDBUtils.ts +51 -0
  107. package/generators/micro-react/templates/packages/common-intl/src/intl.ts +50 -0
  108. package/generators/micro-react/templates/packages/common-intl/src/utils.ts +482 -0
  109. package/generators/micro-react/templates/packages/common-intl/tsconfig.json +22 -0
  110. package/generators/micro-react/templates/packages/common-intl/vite.config.ts +25 -0
  111. package/generators/micro-react/templates/scripts/apply-sentry-plugin.ts +45 -0
  112. package/generators/micro-react/templates/scripts/collect-dist.js +10 -0
  113. package/generators/micro-react/templates/scripts/dev-preset.js +265 -0
  114. package/generators/micro-react/templates/scripts/dev-preset.schema.json +39 -0
  115. package/generators/micro-react/templates/turbo.json +4 -1
  116. package/generators/subapp-react/index.js +326 -40
  117. package/generators/subapp-react/meta.json +10 -0
  118. package/generators/subapp-react/templates/homepage/.env +2 -1
  119. package/generators/subapp-react/templates/homepage/README.md +3 -3
  120. package/generators/subapp-react/templates/homepage/config/config.dev.ts +14 -7
  121. package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +16 -5
  122. package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +16 -5
  123. package/generators/subapp-react/templates/homepage/config/config.prod.ts +14 -5
  124. package/generators/subapp-react/templates/homepage/config/config.ts +27 -0
  125. package/generators/subapp-react/templates/homepage/config/routes.ts +2 -2
  126. package/generators/subapp-react/templates/homepage/mock/api.mock.ts +2 -2
  127. package/generators/subapp-react/templates/homepage/package.json +7 -4
  128. package/generators/subapp-react/templates/homepage/src/app.tsx +18 -27
  129. package/generators/subapp-react/templates/homepage/src/common/request.ts +29 -2
  130. package/generators/subapp-react/templates/homepage/src/global.less +6 -5
  131. package/generators/subapp-react/templates/homepage/src/pages/index.less +3 -3
  132. package/generators/subapp-react/templates/homepage/src/pages/index.tsx +99 -60
  133. package/generators/subapp-react/templates/homepage/src/styles/theme.less +1 -1
  134. package/generators/subapp-umd/ignore-list.json +5 -0
  135. package/generators/subapp-umd/index.js +309 -0
  136. package/generators/subapp-umd/meta.json +11 -0
  137. package/generators/subapp-umd/templates/README.md +94 -0
  138. package/generators/subapp-umd/templates/package.json +35 -0
  139. package/generators/subapp-umd/templates/public/index.html +34 -0
  140. package/generators/subapp-umd/templates/src/App.less +15 -0
  141. package/generators/subapp-umd/templates/src/App.tsx +13 -0
  142. package/generators/subapp-umd/templates/src/index.ts +2 -0
  143. package/generators/subapp-umd/templates/tsconfig.json +27 -0
  144. package/generators/subapp-umd/templates/webpack.config.js +70 -0
  145. package/lib/utils.js +332 -2
  146. package/package.json +15 -2
  147. package/generators/micro-react/templates/apps/layout/mock/menus.json +0 -100
  148. package/generators/micro-react/templates/apps/layout/src/common/constants.ts +0 -38
  149. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/container-manager.ts +0 -202
  150. package/generators/micro-react/templates/packages/shared-styles/README.md +0 -124
  151. package/generators/micro-react/templates/packages/shared-styles/arco-design-mobile-override.less +0 -91
  152. package/generators/micro-react/templates/packages/shared-styles/arco-override.less +0 -119
  153. package/generators/micro-react/templates/packages/shared-styles/index.d.ts +0 -44
  154. package/generators/micro-react/templates/packages/shared-styles/index.less +0 -13
  155. package/generators/micro-react/templates/packages/shared-styles/package.json +0 -30
  156. package/generators/micro-react/templates/packages/shared-styles/theme-inject.less +0 -10
  157. package/generators/micro-react/templates/packages/shared-styles/themes/dark/custom-var.less +0 -290
  158. package/generators/micro-react/templates/packages/shared-styles/themes/normal/custom-var.less +0 -269
  159. package/generators/micro-react/templates/packages/shared-styles/variables-only.less +0 -433
  160. package/generators/micro-react/templates/packages/shared-styles/variables.less +0 -452
package/lib/utils.js CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  const fs = require('node:fs');
4
4
  const path = require('node:path');
5
+ const { exec, execSync, execFileSync, execFile } = require('node:child_process');
6
+ const os = require('node:os');
5
7
 
6
8
  /**
7
9
  * 转换为 kebab-case
@@ -107,7 +109,8 @@ const TEMPLATE_EXTENSIONS = new Set([
107
109
  '.less',
108
110
  '.md',
109
111
  '.mdc',
110
- '.sh'
112
+ '.sh',
113
+ '.html'
111
114
  ]);
112
115
 
113
116
  /**
@@ -119,10 +122,321 @@ function isTemplateFile(filePath) {
119
122
  return TEMPLATE_EXTENSIONS.has(path.extname(filePath));
120
123
  }
121
124
 
125
+ /**
126
+ * 从 monorepo 根目录的 package.json 推断包 scope
127
+ * @param {string} monorepoRoot - monorepo 根目录路径
128
+ * @returns {string|null} 推断出的 scope(如 '@my-project'),未找到返回 null
129
+ */
130
+ function detectPackageScope(monorepoRoot) {
131
+ const rootPkgPath = path.join(monorepoRoot, 'package.json');
132
+ if (fs.existsSync(rootPkgPath)) {
133
+ try {
134
+ const pkg = JSON.parse(fs.readFileSync(rootPkgPath, 'utf-8'));
135
+ if (pkg.name) {
136
+ return pkg.name.startsWith('@')
137
+ ? pkg.name.replace(/^(@[^/]+)\/.*/, '$1')
138
+ : `@${pkg.name}`;
139
+ }
140
+ } catch {
141
+ // ignore
142
+ }
143
+ }
144
+ return null;
145
+ }
146
+
147
+ /** 合法 npm 包名正则:可选 @scope/name,仅允许字母数字、连字符、点、下划线 */
148
+ const VALID_PACKAGE_NAME_RE = /^(@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/i;
149
+
150
+ /** scope 包含 mico 时使用的 registry(如 @mico-platform/*) */
151
+ const MICO_NPM_REGISTRY = 'https://nexus-vywrajy.micoworld.net/repository/mico-base-common/';
152
+
153
+ /**
154
+ * 根据包名 scope 选择 registry:scope 包含 mico 时用 MICO_NPM_REGISTRY,否则用 npm 默认
155
+ * @param {string} packageName - 包名,如 '@mico-platform/ui'
156
+ * @returns {string|undefined} registry URL 或 undefined(使用默认)
157
+ */
158
+ function getRegistryForPackage(packageName) {
159
+ if (!packageName.startsWith('@')) return undefined;
160
+ const scope = packageName.slice(1).split('/')[0] || '';
161
+ return scope.toLowerCase().includes('mico') ? MICO_NPM_REGISTRY : undefined;
162
+ }
163
+
164
+ /**
165
+ * 从 npm registry 获取包的最新版本号(同步版本)
166
+ * registry 根据 packageName 的 scope 自动选择:scope 包含 mico 时用 MICO_NPM_REGISTRY,否则用默认
167
+ * @param {string} packageName - 包名,如 '@mico-platform/ui'
168
+ * @param {string} [fallback='1.0.0'] - 网络或超时时的回退版本
169
+ * @param {number} [timeoutMs=8000] - 超时毫秒
170
+ * @param {string} [cwd] - 执行 npm view 的 cwd,用于加载该目录下的 .npmrc(含 Nexus 认证时必传)
171
+ * @returns {string} 版本号,如 '1.2.3'
172
+ */
173
+ function getLatestNpmVersion(packageName, fallback = '1.0.0', timeoutMs = 8000, cwd) {
174
+ if (!VALID_PACKAGE_NAME_RE.test(packageName)) {
175
+ return fallback;
176
+ }
177
+ const registry = getRegistryForPackage(packageName);
178
+ const args = ['view', packageName, 'version'];
179
+ if (registry) args.push(`--registry=${registry}`);
180
+ try {
181
+ const out = execFileSync('npm', args, {
182
+ encoding: 'utf-8',
183
+ timeout: timeoutMs,
184
+ stdio: ['pipe', 'pipe', 'pipe'],
185
+ ...(cwd && { cwd })
186
+ });
187
+ const v = out.trim();
188
+ return v && /^\d+\.\d+\.\d+/.test(v) ? v : fallback;
189
+ } catch (e) {
190
+ return fallback;
191
+ }
192
+ }
193
+
194
+ /**
195
+ * 从 npm registry 获取包的最新版本号(异步版本)
196
+ * @param {string} packageName - 包名,如 '@mico-platform/ui'
197
+ * @param {string} [fallback='1.0.0'] - 网络或超时时的回退版本
198
+ * @param {number} [timeoutMs=8000] - 超时毫秒
199
+ * @param {string} [cwd] - 执行 npm view 的 cwd
200
+ * @returns {Promise<string>} 版本号,如 '1.2.3'
201
+ */
202
+ function getLatestNpmVersionAsync(packageName, fallback = '1.0.0', timeoutMs = 8000, cwd) {
203
+ if (!VALID_PACKAGE_NAME_RE.test(packageName)) {
204
+ return Promise.resolve(fallback);
205
+ }
206
+ return new Promise((resolve) => {
207
+ let settled = false;
208
+ const done = (value) => {
209
+ if (!settled) {
210
+ settled = true;
211
+ resolve(value);
212
+ }
213
+ };
214
+
215
+ const registry = getRegistryForPackage(packageName);
216
+ const args = ['view', packageName, 'version'];
217
+ if (registry) args.push(`--registry=${registry}`);
218
+
219
+ const child = execFile('npm', args, {
220
+ encoding: 'utf-8',
221
+ timeout: timeoutMs,
222
+ ...(cwd && { cwd })
223
+ }, (error, stdout) => {
224
+ if (error) {
225
+ done(fallback);
226
+ return;
227
+ }
228
+ const v = stdout.trim();
229
+ done(v && /^\d+\.\d+\.\d+/.test(v) ? v : fallback);
230
+ });
231
+
232
+ setTimeout(() => {
233
+ child.kill();
234
+ done(fallback);
235
+ }, timeoutMs + 100);
236
+ });
237
+ }
238
+
239
+ /**
240
+ * 并行获取多个包的版本号
241
+ * @param {Array<{name: string, fallback?: string}>} packages - 包列表
242
+ * @param {number} [timeoutMs=8000] - 超时毫秒
243
+ * @param {string} [cwd] - 执行 npm view 的 cwd
244
+ * @returns {Promise<Record<string, string>>} 包名到版本号的映射
245
+ */
246
+ async function getPackageVersionsParallel(packages, timeoutMs = 8000, cwd) {
247
+ const results = await Promise.all(
248
+ packages.map(async (pkg) => {
249
+ const version = await getLatestNpmVersionAsync(
250
+ pkg.name,
251
+ pkg.fallback || '1.0.0',
252
+ timeoutMs,
253
+ cwd
254
+ );
255
+ return { name: pkg.name, version };
256
+ })
257
+ );
258
+
259
+ return results.reduce((acc, { name, version }) => {
260
+ acc[name] = version;
261
+ return acc;
262
+ }, {});
263
+ }
264
+
265
+ // ============ 配置文件支持 ============
266
+
267
+ /**
268
+ * 查找并加载 .micorc 配置文件
269
+ * 按优先级从高到低查找:当前目录 -> 用户主目录
270
+ * @param {string} [startDir] - 开始查找的目录,默认为 process.cwd()
271
+ * @returns {object} 配置对象,找不到则返回空对象
272
+ */
273
+ function loadMicorc(startDir = process.cwd()) {
274
+ const configNames = ['.micorc', '.micorc.json'];
275
+ const searchPaths = [
276
+ startDir,
277
+ os.homedir()
278
+ ];
279
+
280
+ for (const dir of searchPaths) {
281
+ for (const name of configNames) {
282
+ const configPath = path.join(dir, name);
283
+ if (fs.existsSync(configPath)) {
284
+ try {
285
+ const content = fs.readFileSync(configPath, 'utf-8');
286
+ const config = JSON.parse(content);
287
+ return { config, configPath };
288
+ } catch (e) {
289
+ // 解析失败,继续查找
290
+ console.warn(`Warning: Failed to parse ${configPath}: ${e.message}`);
291
+ }
292
+ }
293
+ }
294
+ }
295
+
296
+ return { config: {}, configPath: null };
297
+ }
298
+
299
+ /**
300
+ * 合并配置与用户输入
301
+ * @param {object} defaults - 默认值
302
+ * @param {object} rcConfig - .micorc 配置
303
+ * @returns {object} 合并后的默认值
304
+ */
305
+ function mergeDefaults(defaults, rcConfig) {
306
+ return { ...defaults, ...rcConfig };
307
+ }
308
+
309
+ // ============ 环境检查 ============
310
+
311
+ /**
312
+ * 检查命令是否可用
313
+ * @param {string} command - 命令名称
314
+ * @returns {{available: boolean, version?: string, error?: string}}
315
+ */
316
+ function checkCommand(command) {
317
+ try {
318
+ const out = execSync(`${command} --version`, {
319
+ encoding: 'utf-8',
320
+ stdio: ['pipe', 'pipe', 'pipe'],
321
+ timeout: 5000
322
+ });
323
+ const version = out.trim().split('\n')[0];
324
+ return { available: true, version };
325
+ } catch (e) {
326
+ return { available: false, error: e.message };
327
+ }
328
+ }
329
+
330
+ /**
331
+ * 检查 Node.js 版本是否满足要求
332
+ * @param {string} required - 要求的最低版本,如 '18'
333
+ * @returns {{satisfied: boolean, current: string, required: string}}
334
+ */
335
+ function checkNodeVersion(required = '18') {
336
+ const current = process.version.replace(/^v/, '');
337
+ const currentMajor = parseInt(current.split('.')[0], 10);
338
+ const requiredMajor = parseInt(required, 10);
339
+ return {
340
+ satisfied: currentMajor >= requiredMajor,
341
+ current,
342
+ required
343
+ };
344
+ }
345
+
346
+ /**
347
+ * 检查网络连接(npm registry)
348
+ * @param {number} [timeoutMs=5000] - 超时毫秒
349
+ * @returns {Promise<{reachable: boolean, registry: string, error?: string}>}
350
+ */
351
+ async function checkNpmRegistry(timeoutMs = 5000) {
352
+ const registry = 'https://registry.npmjs.org';
353
+ return new Promise((resolve) => {
354
+ const child = exec(`npm ping --registry=${registry}`, {
355
+ timeout: timeoutMs
356
+ }, (error) => {
357
+ if (error) {
358
+ resolve({ reachable: false, registry, error: error.message });
359
+ } else {
360
+ resolve({ reachable: true, registry });
361
+ }
362
+ });
363
+
364
+ setTimeout(() => {
365
+ child.kill();
366
+ resolve({ reachable: false, registry, error: 'Timeout' });
367
+ }, timeoutMs + 100);
368
+ });
369
+ }
370
+
371
+ /**
372
+ * 运行完整的环境检查
373
+ * @returns {Promise<object>} 检查结果
374
+ */
375
+ async function runDoctorChecks() {
376
+ const results = {
377
+ node: checkNodeVersion('18'),
378
+ pnpm: checkCommand('pnpm'),
379
+ git: checkCommand('git'),
380
+ npm: null
381
+ };
382
+
383
+ // 异步检查 npm registry
384
+ results.npm = await checkNpmRegistry();
385
+
386
+ return results;
387
+ }
388
+
389
+ /**
390
+ * 检查是否启用了 verbose 模式
391
+ * @returns {boolean}
392
+ */
393
+ function isVerbose() {
394
+ return process.env.MICO_VERBOSE === '1';
395
+ }
396
+
397
+ /**
398
+ * 详细日志输出(仅在 verbose 模式下打印)
399
+ * @param {...any} args - 要打印的内容
400
+ */
401
+ function verboseLog(...args) {
402
+ if (isVerbose()) {
403
+ console.log('\x1b[2m[verbose]', ...args, '\x1b[0m');
404
+ }
405
+ }
406
+
407
+ /**
408
+ * 创建一个带有 verbose 支持的 Logger
409
+ * @param {object} generator - Yeoman generator 实例
410
+ * @returns {object} Logger 对象
411
+ */
412
+ function createLogger(generator) {
413
+ const log = generator.log.bind(generator);
414
+ return {
415
+ info: (...args) => log(...args),
416
+ verbose: (...args) => {
417
+ if (isVerbose()) {
418
+ log('\x1b[2m[verbose]', ...args, '\x1b[0m');
419
+ }
420
+ },
421
+ success: (msg) => log(`\x1b[32m✓\x1b[0m ${msg}`),
422
+ warn: (msg) => log(`\x1b[33m⚠\x1b[0m ${msg}`),
423
+ error: (msg) => log(`\x1b[31m✗\x1b[0m ${msg}`),
424
+ file: (action, filePath) => {
425
+ if (isVerbose()) {
426
+ const actionColor = action === 'create' ? '\x1b[32m' : action === 'copy' ? '\x1b[36m' : '\x1b[33m';
427
+ log(` ${actionColor}${action}\x1b[0m ${filePath}`);
428
+ }
429
+ }
430
+ };
431
+ }
432
+
122
433
  /**
123
434
  * 安装全局未捕获异常处理
435
+ * 在 Vitest 等测试环境中自动跳过,避免干扰测试 runner 的进程管理
124
436
  */
125
437
  function setupErrorHandlers() {
438
+ if (process.env.VITEST) return;
439
+
126
440
  process.on('uncaughtException', (error) => {
127
441
  console.error('');
128
442
  console.error('❌ Unexpected error:');
@@ -156,10 +470,26 @@ module.exports = {
156
470
  toPascal,
157
471
  toCamel,
158
472
  // Generator 工具
473
+ detectPackageScope,
159
474
  shouldIgnorePath,
160
475
  collectFiles,
161
476
  transformDestPath,
162
477
  isTemplateFile,
478
+ getLatestNpmVersion,
479
+ getLatestNpmVersionAsync,
480
+ getPackageVersionsParallel,
163
481
  setupErrorHandlers,
164
- TEMPLATE_EXTENSIONS
482
+ TEMPLATE_EXTENSIONS,
483
+ // 配置文件
484
+ loadMicorc,
485
+ mergeDefaults,
486
+ // 环境检查
487
+ checkCommand,
488
+ checkNodeVersion,
489
+ checkNpmRegistry,
490
+ runDoctorChecks,
491
+ // Verbose 日志
492
+ isVerbose,
493
+ verboseLog,
494
+ createLogger
165
495
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-mico-cli",
3
- "version": "0.1.29",
3
+ "version": "0.2.28.beta.1",
4
4
  "description": "Yeoman generator for Mico CLI projects",
5
5
  "keywords": [
6
6
  "yeoman-generator",
@@ -18,7 +18,19 @@
18
18
  "generators"
19
19
  ],
20
20
  "scripts": {
21
- "sync:subapp-react-template": "node scripts/sync-subapp-react-template.js"
21
+ "prepare": "husky",
22
+ "format": "biome format --write .",
23
+ "format:check": "biome format .",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "sync:subapp-react-template": "node scripts/sync-subapp-react-template.js",
27
+ "verify:micro-react": "node scripts/verify-micro-react.js"
28
+ },
29
+ "devDependencies": {
30
+ "@biomejs/biome": "^1.9.4",
31
+ "husky": "^9.1.7",
32
+ "vitest": "^4.0.18",
33
+ "yeoman-test": "^6.3.0"
22
34
  },
23
35
  "engines": {
24
36
  "node": ">=18"
@@ -26,6 +38,7 @@
26
38
  "dependencies": {
27
39
  "semver": "^7.6.3",
28
40
  "update-notifier": "^7.3.1",
41
+ "yeoman-environment": "^3.19.3",
29
42
  "yeoman-generator": "^5.9.0"
30
43
  }
31
44
  }
@@ -1,100 +0,0 @@
1
- [
2
- {
3
- "id": 1,
4
- "name": "首页",
5
- "type": "page",
6
- "path": null,
7
- "icon": "Home",
8
- "enabled": true,
9
- "sortOrder": 0,
10
- "pageId": 1,
11
- "page": {
12
- "id": 1,
13
- "name": "home",
14
- "route": "/",
15
- "enabled": true,
16
- "htmlUrl": null,
17
- "jsUrls": [],
18
- "cssUrls": []
19
- },
20
- "children": []
21
- },
22
- {
23
- "id": 2,
24
- "name": "示例模块",
25
- "type": "group",
26
- "path": null,
27
- "icon": "List",
28
- "enabled": true,
29
- "sortOrder": 1,
30
- "pageId": null,
31
- "page": null,
32
- "children": [
33
- {
34
- "id": 3,
35
- "name": "示例页面",
36
- "type": "page",
37
- "path": "/example/page",
38
- "icon": "File",
39
- "enabled": true,
40
- "sortOrder": 1,
41
- "pageId": 45,
42
- "page": {
43
- "id": 45,
44
- "name": "example-page",
45
- "route": "/example/page",
46
- "enabled": true,
47
- "htmlUrl": null,
48
- "jsUrls": [],
49
- "cssUrls": []
50
- },
51
- "children": []
52
- }
53
- ]
54
- },
55
- {
56
- "id": 5,
57
- "name": "微应用示例",
58
- "type": "group",
59
- "path": null,
60
- "icon": "Apps",
61
- "enabled": true,
62
- "sortOrder": 2,
63
- "pageId": null,
64
- "page": null,
65
- "children": [
66
- {
67
- "id": 6,
68
- "name": "子应用页面",
69
- "type": "page",
70
- "path": null,
71
- "icon": "Desktop",
72
- "enabled": true,
73
- "sortOrder": 1,
74
- "pageId": 55,
75
- "page": {
76
- "id": 55,
77
- "name": "subapp-example",
78
- "route": "/subapp",
79
- "enabled": true,
80
- "htmlUrl": "//localhost:8010",
81
- "jsUrls": [],
82
- "cssUrls": []
83
- },
84
- "children": []
85
- }
86
- ]
87
- },
88
- {
89
- "id": 7,
90
- "name": "外部链接",
91
- "type": "link",
92
- "path": "https://github.com",
93
- "icon": "Link",
94
- "enabled": true,
95
- "sortOrder": 3,
96
- "pageId": null,
97
- "page": null,
98
- "children": []
99
- }
100
- ]
@@ -1,38 +0,0 @@
1
- /**
2
- * 应用常量定义
3
- */
4
-
5
- /**
6
- * 路由路径常量
7
- */
8
- export const ROUTES = {
9
- /** 登录页 */
10
- LOGIN: '/user/login',
11
- /** 注册页 */
12
- REGISTER: '/user/register',
13
- /** 注册结果页 */
14
- REGISTER_RESULT: '/user/register-result',
15
- /** 无需认证的路由列表 */
16
- NO_AUTH_ROUTES: ['/user/login', '/user/register', '/user/register-result'],
17
- } as const;
18
-
19
- /**
20
- * 主题相关常量
21
- */
22
- export const THEME = {
23
- /** localStorage 存储键 */
24
- STORAGE_KEY: '<%= projectName %>-theme',
25
- /** 默认主题 */
26
- DEFAULT: 'light' as const,
27
- /** 可选主题值 */
28
- VALUES: ['light', 'dark'] as const,
29
- } as const;
30
-
31
- /**
32
- * 存储键常量
33
- */
34
- export const STORAGE_KEYS = {
35
- APP_INFO: 'appInfo',
36
- IS_SUPERUSER: 'is_superuser',
37
- GROUPS: 'groups',
38
- } as const;