generator-mico-cli 0.2.20 → 0.2.21

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 (29) hide show
  1. package/README.md +29 -0
  2. package/bin/mico.js +124 -5
  3. package/generators/micro-react/index.js +76 -17
  4. package/generators/micro-react/templates/CLAUDE.md +11 -5
  5. package/generators/micro-react/templates/_gitignore +2 -0
  6. package/generators/micro-react/templates/apps/layout/config/config.ts +21 -0
  7. package/generators/micro-react/templates/apps/layout/docs/common-intl.md +8 -6
  8. 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 +60 -35
  9. 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 +7 -2
  10. package/generators/micro-react/templates/apps/layout/docs/utils-timezone.md +4 -2
  11. package/generators/micro-react/templates/apps/layout/mock/menus.ts +7 -2
  12. package/generators/micro-react/templates/apps/layout/package.json +3 -2
  13. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +3 -15
  14. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +4 -0
  15. package/generators/micro-react/templates/apps/layout/src/global.less +1 -2
  16. package/generators/micro-react/templates/package.json +2 -1
  17. package/generators/subapp-react/index.js +81 -13
  18. package/generators/subapp-react/templates/homepage/config/config.dev.ts +8 -1
  19. package/generators/subapp-react/templates/homepage/config/config.ts +21 -0
  20. package/generators/subapp-react/templates/homepage/config/routes.ts +1 -1
  21. package/generators/subapp-react/templates/homepage/mock/api.mock.ts +2 -2
  22. package/generators/subapp-react/templates/homepage/package.json +3 -2
  23. package/generators/subapp-react/templates/homepage/src/app.tsx +1 -1
  24. package/generators/subapp-react/templates/homepage/src/common/request.ts +2 -2
  25. package/generators/subapp-react/templates/homepage/src/global.less +2 -1
  26. package/generators/subapp-react/templates/homepage/src/pages/index.less +1 -1
  27. package/generators/subapp-react/templates/homepage/src/pages/index.tsx +27 -27
  28. package/lib/utils.js +200 -2
  29. package/package.json +1 -1
package/lib/utils.js CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  const fs = require('node:fs');
4
4
  const path = require('node:path');
5
- const { execSync } = require('node:child_process');
5
+ const { execSync, exec } = require('node:child_process');
6
+ const os = require('node:os');
6
7
 
7
8
  /**
8
9
  * 转换为 kebab-case
@@ -135,7 +136,7 @@ function getRegistryForPackage(packageName) {
135
136
  }
136
137
 
137
138
  /**
138
- * 从 npm registry 获取包的最新版本号(不使用 latest 标签,避免不可复现)
139
+ * 从 npm registry 获取包的最新版本号(同步版本)
139
140
  * registry 根据 packageName 的 scope 自动选择:scope 包含 mico 时用 MICO_NPM_REGISTRY,否则用默认
140
141
  * @param {string} packageName - 包名,如 '@mico-platform/ui'
141
142
  * @param {string} [fallback='1.0.0'] - 网络或超时时的回退版本
@@ -161,6 +162,193 @@ function getLatestNpmVersion(packageName, fallback = '1.0.0', timeoutMs = 8000,
161
162
  }
162
163
  }
163
164
 
165
+ /**
166
+ * 从 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
171
+ * @returns {Promise<string>} 版本号,如 '1.2.3'
172
+ */
173
+ function getLatestNpmVersionAsync(packageName, fallback = '1.0.0', timeoutMs = 8000, cwd) {
174
+ return new Promise((resolve) => {
175
+ const registry = getRegistryForPackage(packageName);
176
+ const registryArg = registry ? `--registry=${registry}` : '';
177
+ const cmd = `npm view ${packageName} version ${registryArg}`.trim();
178
+
179
+ const child = exec(cmd, {
180
+ encoding: 'utf-8',
181
+ timeout: timeoutMs,
182
+ ...(cwd && { cwd })
183
+ }, (error, stdout) => {
184
+ if (error) {
185
+ resolve(fallback);
186
+ return;
187
+ }
188
+ const v = stdout.trim();
189
+ resolve(v && /^\d+\.\d+\.\d+/.test(v) ? v : fallback);
190
+ });
191
+
192
+ // 确保超时后也能 resolve
193
+ setTimeout(() => {
194
+ child.kill();
195
+ resolve(fallback);
196
+ }, timeoutMs + 100);
197
+ });
198
+ }
199
+
200
+ /**
201
+ * 并行获取多个包的版本号
202
+ * @param {Array<{name: string, fallback?: string}>} packages - 包列表
203
+ * @param {number} [timeoutMs=8000] - 超时毫秒
204
+ * @param {string} [cwd] - 执行 npm view 的 cwd
205
+ * @returns {Promise<Record<string, string>>} 包名到版本号的映射
206
+ */
207
+ async function getPackageVersionsParallel(packages, timeoutMs = 8000, cwd) {
208
+ const results = await Promise.all(
209
+ packages.map(async (pkg) => {
210
+ const version = await getLatestNpmVersionAsync(
211
+ pkg.name,
212
+ pkg.fallback || '1.0.0',
213
+ timeoutMs,
214
+ cwd
215
+ );
216
+ return { name: pkg.name, version };
217
+ })
218
+ );
219
+
220
+ return results.reduce((acc, { name, version }) => {
221
+ acc[name] = version;
222
+ return acc;
223
+ }, {});
224
+ }
225
+
226
+ // ============ 配置文件支持 ============
227
+
228
+ /**
229
+ * 查找并加载 .micorc 配置文件
230
+ * 按优先级从高到低查找:当前目录 -> 用户主目录
231
+ * @param {string} [startDir] - 开始查找的目录,默认为 process.cwd()
232
+ * @returns {object} 配置对象,找不到则返回空对象
233
+ */
234
+ function loadMicorc(startDir = process.cwd()) {
235
+ const configNames = ['.micorc', '.micorc.json'];
236
+ const searchPaths = [
237
+ startDir,
238
+ os.homedir()
239
+ ];
240
+
241
+ for (const dir of searchPaths) {
242
+ for (const name of configNames) {
243
+ const configPath = path.join(dir, name);
244
+ if (fs.existsSync(configPath)) {
245
+ try {
246
+ const content = fs.readFileSync(configPath, 'utf-8');
247
+ const config = JSON.parse(content);
248
+ return { config, configPath };
249
+ } catch (e) {
250
+ // 解析失败,继续查找
251
+ console.warn(`Warning: Failed to parse ${configPath}: ${e.message}`);
252
+ }
253
+ }
254
+ }
255
+ }
256
+
257
+ return { config: {}, configPath: null };
258
+ }
259
+
260
+ /**
261
+ * 合并配置与用户输入
262
+ * @param {object} defaults - 默认值
263
+ * @param {object} rcConfig - .micorc 配置
264
+ * @returns {object} 合并后的默认值
265
+ */
266
+ function mergeDefaults(defaults, rcConfig) {
267
+ return { ...defaults, ...rcConfig };
268
+ }
269
+
270
+ // ============ 环境检查 ============
271
+
272
+ /**
273
+ * 检查命令是否可用
274
+ * @param {string} command - 命令名称
275
+ * @returns {{available: boolean, version?: string, error?: string}}
276
+ */
277
+ function checkCommand(command) {
278
+ try {
279
+ const versionFlag = command === 'pnpm' ? '--version' : '--version';
280
+ const out = execSync(`${command} ${versionFlag}`, {
281
+ encoding: 'utf-8',
282
+ stdio: ['pipe', 'pipe', 'pipe'],
283
+ timeout: 5000
284
+ });
285
+ const version = out.trim().split('\n')[0];
286
+ return { available: true, version };
287
+ } catch (e) {
288
+ return { available: false, error: e.message };
289
+ }
290
+ }
291
+
292
+ /**
293
+ * 检查 Node.js 版本是否满足要求
294
+ * @param {string} required - 要求的最低版本,如 '18'
295
+ * @returns {{satisfied: boolean, current: string, required: string}}
296
+ */
297
+ function checkNodeVersion(required = '18') {
298
+ const current = process.version.replace(/^v/, '');
299
+ const currentMajor = parseInt(current.split('.')[0], 10);
300
+ const requiredMajor = parseInt(required, 10);
301
+ return {
302
+ satisfied: currentMajor >= requiredMajor,
303
+ current,
304
+ required
305
+ };
306
+ }
307
+
308
+ /**
309
+ * 检查网络连接(npm registry)
310
+ * @param {number} [timeoutMs=5000] - 超时毫秒
311
+ * @returns {Promise<{reachable: boolean, registry: string, error?: string}>}
312
+ */
313
+ async function checkNpmRegistry(timeoutMs = 5000) {
314
+ const registry = 'https://registry.npmjs.org';
315
+ return new Promise((resolve) => {
316
+ const child = exec(`npm ping --registry=${registry}`, {
317
+ timeout: timeoutMs
318
+ }, (error) => {
319
+ if (error) {
320
+ resolve({ reachable: false, registry, error: error.message });
321
+ } else {
322
+ resolve({ reachable: true, registry });
323
+ }
324
+ });
325
+
326
+ setTimeout(() => {
327
+ child.kill();
328
+ resolve({ reachable: false, registry, error: 'Timeout' });
329
+ }, timeoutMs + 100);
330
+ });
331
+ }
332
+
333
+ /**
334
+ * 运行完整的环境检查
335
+ * @returns {Promise<object>} 检查结果
336
+ */
337
+ async function runDoctorChecks() {
338
+ const results = {
339
+ node: checkNodeVersion('18'),
340
+ pnpm: checkCommand('pnpm'),
341
+ yo: checkCommand('yo'),
342
+ git: checkCommand('git'),
343
+ npm: null
344
+ };
345
+
346
+ // 异步检查 npm registry
347
+ results.npm = await checkNpmRegistry();
348
+
349
+ return results;
350
+ }
351
+
164
352
  /**
165
353
  * 检查是否启用了 verbose 模式
166
354
  * @returns {boolean}
@@ -247,8 +435,18 @@ module.exports = {
247
435
  transformDestPath,
248
436
  isTemplateFile,
249
437
  getLatestNpmVersion,
438
+ getLatestNpmVersionAsync,
439
+ getPackageVersionsParallel,
250
440
  setupErrorHandlers,
251
441
  TEMPLATE_EXTENSIONS,
442
+ // 配置文件
443
+ loadMicorc,
444
+ mergeDefaults,
445
+ // 环境检查
446
+ checkCommand,
447
+ checkNodeVersion,
448
+ checkNpmRegistry,
449
+ runDoctorChecks,
252
450
  // Verbose 日志
253
451
  isVerbose,
254
452
  verboseLog,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-mico-cli",
3
- "version": "0.2.20",
3
+ "version": "0.2.21",
4
4
  "description": "Yeoman generator for Mico CLI projects",
5
5
  "keywords": ["yeoman-generator", "generator", "cli"],
6
6
  "license": "MIT",