generator-mico-cli 0.2.32 → 0.2.34

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 (27) hide show
  1. package/README.md +6 -0
  2. package/generators/micro-react/README.md +1 -1
  3. package/generators/micro-react/index.js +9 -18
  4. package/generators/micro-react/templates/apps/layout/config/config.dev.ts +2 -0
  5. package/generators/micro-react/templates/apps/layout/docs/feature-/345/244/264/351/203/250/344/270/200/347/272/247/345/257/274/350/210/252/345/270/203/345/261/200.md +166 -0
  6. package/generators/micro-react/templates/apps/layout/src/app.tsx +20 -2
  7. package/generators/micro-react/templates/apps/layout/src/common/logger.ts +1 -1
  8. package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +36 -0
  9. package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +6 -0
  10. package/generators/micro-react/templates/apps/layout/src/common/request/index.ts +8 -2
  11. package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +128 -11
  12. package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +6 -2
  13. package/generators/micro-react/templates/apps/layout/src/constants/index.ts +22 -0
  14. package/generators/micro-react/templates/apps/layout/src/hooks/useFilteredMenuItems.ts +29 -0
  15. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.less +73 -0
  16. package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +51 -4
  17. package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +25 -18
  18. package/generators/micro-react/templates/apps/layout/src/locales/en-US.ts +4 -0
  19. package/generators/micro-react/templates/apps/layout/src/locales/zh-CN.ts +4 -0
  20. package/generators/micro-react/templates/apps/layout/src/services/config/index.ts +1 -0
  21. package/generators/micro-react/templates/packages/common-intl/src/intl.ts +20 -0
  22. package/generators/subapp-react/index.js +10 -19
  23. package/generators/subapp-react/templates/homepage/src/common/logger.ts +1 -1
  24. package/generators/subapp-umd/index.js +6 -0
  25. package/generators/subapp-umd/templates/package.json +1 -1
  26. package/lib/utils.js +222 -0
  27. package/package.json +5 -1
package/lib/utils.js CHANGED
@@ -4,6 +4,7 @@ const fs = require('node:fs');
4
4
  const path = require('node:path');
5
5
  const { exec, execSync, execFileSync, execFile } = require('node:child_process');
6
6
  const os = require('node:os');
7
+ const semver = require('semver');
7
8
 
8
9
  /**
9
10
  * 转换为 kebab-case
@@ -150,6 +151,9 @@ const VALID_PACKAGE_NAME_RE = /^(@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/
150
151
  /** scope 包含 mico 时使用的 registry(如 @mico-platform/*) */
151
152
  const MICO_NPM_REGISTRY = 'https://nexus-vywrajy.micoworld.net/repository/mico-base-common/';
152
153
 
154
+ /** 生成器模板中由 micoPackages 管理的包名 */
155
+ const MICO_TEMPLATE_PACKAGES = ['@mico-platform/ui', '@mico-platform/theme'];
156
+
153
157
  /**
154
158
  * 根据包名 scope 选择 registry:scope 包含 mico 时用 MICO_NPM_REGISTRY,否则用 npm 默认
155
159
  * @param {string} packageName - 包名,如 '@mico-platform/ui'
@@ -161,6 +165,27 @@ function getRegistryForPackage(packageName) {
161
165
  return scope.toLowerCase().includes('mico') ? MICO_NPM_REGISTRY : undefined;
162
166
  }
163
167
 
168
+ /**
169
+ * 读取版本覆盖(用于测试/验证场景锁定版本,跳过 npm view)
170
+ * 通过环境变量 MICO_PKG_VERSIONS(JSON 映射,如 {"@mico-platform/ui":"0.0.25"})指定
171
+ * @param {string} packageName - 包名,如 '@mico-platform/ui'
172
+ * @returns {string|undefined} 命中且为合法版本号时返回,否则 undefined
173
+ */
174
+ function getVersionOverride(packageName) {
175
+ const raw = process.env.MICO_PKG_VERSIONS;
176
+ if (!raw) return undefined;
177
+ try {
178
+ const map = JSON.parse(raw);
179
+ const v = map && map[packageName];
180
+ if (typeof v === 'string' && /^\d+\.\d+\.\d+/.test(v.trim())) {
181
+ return v.trim();
182
+ }
183
+ } catch {
184
+ // 解析失败时忽略覆盖,回退到正常获取流程
185
+ }
186
+ return undefined;
187
+ }
188
+
164
189
  /**
165
190
  * 从 npm registry 获取包的最新版本号(同步版本)
166
191
  * registry 根据 packageName 的 scope 自动选择:scope 包含 mico 时用 MICO_NPM_REGISTRY,否则用默认
@@ -174,6 +199,8 @@ function getLatestNpmVersion(packageName, fallback = '1.0.0', timeoutMs = 8000,
174
199
  if (!VALID_PACKAGE_NAME_RE.test(packageName)) {
175
200
  return fallback;
176
201
  }
202
+ const override = getVersionOverride(packageName);
203
+ if (override) return override;
177
204
  const registry = getRegistryForPackage(packageName);
178
205
  const args = ['view', packageName, 'version'];
179
206
  if (registry) args.push(`--registry=${registry}`);
@@ -203,6 +230,8 @@ function getLatestNpmVersionAsync(packageName, fallback = '1.0.0', timeoutMs = 8
203
230
  if (!VALID_PACKAGE_NAME_RE.test(packageName)) {
204
231
  return Promise.resolve(fallback);
205
232
  }
233
+ const override = getVersionOverride(packageName);
234
+ if (override) return Promise.resolve(override);
206
235
  return new Promise((resolve) => {
207
236
  let settled = false;
208
237
  const done = (value) => {
@@ -262,6 +291,195 @@ async function getPackageVersionsParallel(packages, timeoutMs = 8000, cwd) {
262
291
  }, {});
263
292
  }
264
293
 
294
+ /**
295
+ * 读取 CLI package.json 中的 micoPackages(组件库版本 range 唯一维护点)
296
+ * @param {string} [cliRoot] - CLI 仓库根目录,默认 lib/ 的上级
297
+ * @returns {Record<string, string>} 包名 → semver range
298
+ */
299
+ function loadMicoPackages(cliRoot) {
300
+ const root = cliRoot || path.resolve(__dirname, '..');
301
+ const pkgPath = path.join(root, 'package.json');
302
+ if (!fs.existsSync(pkgPath)) {
303
+ throw new Error(`CLI package.json not found: ${pkgPath}`);
304
+ }
305
+
306
+ let pkg;
307
+ try {
308
+ pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
309
+ } catch (e) {
310
+ throw new Error(`Failed to parse CLI package.json: ${e.message}`);
311
+ }
312
+
313
+ const { micoPackages } = pkg;
314
+ if (!micoPackages || typeof micoPackages !== 'object') {
315
+ throw new Error(
316
+ 'CLI package.json must define "micoPackages" with @mico-platform/ui and @mico-platform/theme ranges',
317
+ );
318
+ }
319
+
320
+ const result = {};
321
+ for (const name of MICO_TEMPLATE_PACKAGES) {
322
+ const range = micoPackages[name];
323
+ if (typeof range !== 'string' || !range.trim()) {
324
+ throw new Error(`micoPackages.${name} must be a non-empty semver range string`);
325
+ }
326
+ const trimmed = range.trim();
327
+ if (!semver.validRange(trimmed)) {
328
+ throw new Error(`micoPackages.${name} is not a valid semver range: ${range}`);
329
+ }
330
+ result[name] = trimmed;
331
+ }
332
+
333
+ return result;
334
+ }
335
+
336
+ /**
337
+ * 执行 npm view <pkg>@<spec> version
338
+ * @returns {Promise<string|undefined>}
339
+ */
340
+ function npmViewVersionAsync(packageName, spec, timeoutMs = 8000, cwd) {
341
+ if (!VALID_PACKAGE_NAME_RE.test(packageName)) {
342
+ return Promise.resolve(undefined);
343
+ }
344
+
345
+ return new Promise((resolve) => {
346
+ let settled = false;
347
+ const done = (value) => {
348
+ if (!settled) {
349
+ settled = true;
350
+ resolve(value);
351
+ }
352
+ };
353
+
354
+ const registry = getRegistryForPackage(packageName);
355
+ const args = ['view', `${packageName}@${spec}`, 'version'];
356
+ if (registry) args.push(`--registry=${registry}`);
357
+
358
+ const child = execFile(
359
+ 'npm',
360
+ args,
361
+ {
362
+ encoding: 'utf-8',
363
+ timeout: timeoutMs,
364
+ ...(cwd && { cwd }),
365
+ },
366
+ (error, stdout) => {
367
+ if (error) {
368
+ done(undefined);
369
+ return;
370
+ }
371
+ const v = stdout.trim();
372
+ done(v && semver.valid(v) ? v : undefined);
373
+ },
374
+ );
375
+
376
+ setTimeout(() => {
377
+ child.kill();
378
+ done(undefined);
379
+ }, timeoutMs + 100);
380
+ });
381
+ }
382
+
383
+ /**
384
+ * 执行 npm view <pkg> versions --json
385
+ * @returns {Promise<string[]>}
386
+ */
387
+ function npmViewAllVersionsAsync(packageName, timeoutMs = 8000, cwd) {
388
+ if (!VALID_PACKAGE_NAME_RE.test(packageName)) {
389
+ return Promise.resolve([]);
390
+ }
391
+
392
+ return new Promise((resolve) => {
393
+ let settled = false;
394
+ const done = (value) => {
395
+ if (!settled) {
396
+ settled = true;
397
+ resolve(value);
398
+ }
399
+ };
400
+
401
+ const registry = getRegistryForPackage(packageName);
402
+ const args = ['view', packageName, 'versions', '--json'];
403
+ if (registry) args.push(`--registry=${registry}`);
404
+
405
+ const child = execFile(
406
+ 'npm',
407
+ args,
408
+ {
409
+ encoding: 'utf-8',
410
+ timeout: timeoutMs,
411
+ ...(cwd && { cwd }),
412
+ },
413
+ (error, stdout) => {
414
+ if (error) {
415
+ done([]);
416
+ return;
417
+ }
418
+ try {
419
+ const list = JSON.parse(stdout.trim());
420
+ done(Array.isArray(list) ? list.filter((v) => semver.valid(v)) : []);
421
+ } catch {
422
+ done([]);
423
+ }
424
+ },
425
+ );
426
+
427
+ setTimeout(() => {
428
+ child.kill();
429
+ done([]);
430
+ }, timeoutMs + 100);
431
+ });
432
+ }
433
+
434
+ /**
435
+ * 在 semver range 内解析包的最新精确版本(用于 CDN / micoUiVersionExact)
436
+ * MICO_PKG_VERSIONS 可覆盖 resolved,但仍须满足 range
437
+ * @param {string} packageName
438
+ * @param {string} range - semver range,如 0.x
439
+ * @param {number} [timeoutMs=8000]
440
+ * @param {string} [cwd]
441
+ * @returns {Promise<string>}
442
+ */
443
+ async function resolveNpmVersionInRangeAsync(packageName, range, timeoutMs = 8000, cwd) {
444
+ const override = getVersionOverride(packageName);
445
+ if (override) {
446
+ if (!semver.satisfies(override, range, { includePrerelease: true })) {
447
+ throw new Error(
448
+ `MICO_PKG_VERSIONS override ${override} does not satisfy range ${range} for ${packageName}`,
449
+ );
450
+ }
451
+ return override;
452
+ }
453
+
454
+ const direct = await npmViewVersionAsync(packageName, range, timeoutMs, cwd);
455
+ if (direct) return direct;
456
+
457
+ const versions = await npmViewAllVersionsAsync(packageName, timeoutMs, cwd);
458
+ const resolved = semver.maxSatisfying(versions, range, { includePrerelease: false });
459
+ if (resolved) return resolved;
460
+
461
+ throw new Error(`No version found for ${packageName} satisfying range ${range}`);
462
+ }
463
+
464
+ /**
465
+ * 读取 micoPackages range,并解析各包在 range 内的最新精确版本
466
+ * @param {string} cliRoot - CLI 仓库根目录
467
+ * @param {number} [timeoutMs=8000]
468
+ * @returns {Promise<Record<string, { range: string, resolved: string }>>}
469
+ */
470
+ async function getMicoTemplateVersions(cliRoot, timeoutMs = 8000) {
471
+ const micoPackages = loadMicoPackages(cliRoot);
472
+ const entries = await Promise.all(
473
+ MICO_TEMPLATE_PACKAGES.map(async (name) => {
474
+ const range = micoPackages[name];
475
+ const resolved = await resolveNpmVersionInRangeAsync(name, range, timeoutMs, cliRoot);
476
+ return [name, { range, resolved }];
477
+ }),
478
+ );
479
+
480
+ return Object.fromEntries(entries);
481
+ }
482
+
265
483
  // ============ 配置文件支持 ============
266
484
 
267
485
  /**
@@ -478,6 +696,10 @@ module.exports = {
478
696
  getLatestNpmVersion,
479
697
  getLatestNpmVersionAsync,
480
698
  getPackageVersionsParallel,
699
+ MICO_TEMPLATE_PACKAGES,
700
+ loadMicoPackages,
701
+ resolveNpmVersionInRangeAsync,
702
+ getMicoTemplateVersions,
481
703
  setupErrorHandlers,
482
704
  TEMPLATE_EXTENSIONS,
483
705
  // 配置文件
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generator-mico-cli",
3
- "version": "0.2.32",
3
+ "version": "0.2.34",
4
4
  "description": "Yeoman generator for Mico CLI projects",
5
5
  "keywords": [
6
6
  "yeoman-generator",
@@ -35,6 +35,10 @@
35
35
  "engines": {
36
36
  "node": ">=18"
37
37
  },
38
+ "micoPackages": {
39
+ "@mico-platform/ui": "0.x",
40
+ "@mico-platform/theme": "0.x"
41
+ },
38
42
  "dependencies": {
39
43
  "semver": "^7.6.3",
40
44
  "update-notifier": "^7.3.1",