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.
- package/README.md +6 -0
- package/generators/micro-react/README.md +1 -1
- package/generators/micro-react/index.js +9 -18
- package/generators/micro-react/templates/apps/layout/config/config.dev.ts +2 -0
- 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
- package/generators/micro-react/templates/apps/layout/src/app.tsx +20 -2
- package/generators/micro-react/templates/apps/layout/src/common/logger.ts +1 -1
- package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +36 -0
- package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +6 -0
- package/generators/micro-react/templates/apps/layout/src/common/request/index.ts +8 -2
- package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +128 -11
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +6 -2
- package/generators/micro-react/templates/apps/layout/src/constants/index.ts +22 -0
- package/generators/micro-react/templates/apps/layout/src/hooks/useFilteredMenuItems.ts +29 -0
- package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.less +73 -0
- package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +51 -4
- package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +25 -18
- package/generators/micro-react/templates/apps/layout/src/locales/en-US.ts +4 -0
- package/generators/micro-react/templates/apps/layout/src/locales/zh-CN.ts +4 -0
- package/generators/micro-react/templates/apps/layout/src/services/config/index.ts +1 -0
- package/generators/micro-react/templates/packages/common-intl/src/intl.ts +20 -0
- package/generators/subapp-react/index.js +10 -19
- package/generators/subapp-react/templates/homepage/src/common/logger.ts +1 -1
- package/generators/subapp-umd/index.js +6 -0
- package/generators/subapp-umd/templates/package.json +1 -1
- package/lib/utils.js +222 -0
- 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.
|
|
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",
|