generator-mico-cli 0.2.1 → 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.
- package/README.md +199 -15
- package/bin/mico.js +232 -27
- package/generators/micro-react/index.js +200 -18
- package/generators/micro-react/meta.json +13 -0
- package/generators/micro-react/templates/.commitlintrc.js +1 -0
- package/generators/micro-react/templates/.cursor/rules/always-read-docs.mdc +14 -4
- package/generators/micro-react/templates/.cursor/rules/cicd-deploy.mdc +10 -8
- package/generators/micro-react/templates/.cursor/rules/coding-conventions.mdc +1 -1
- package/generators/micro-react/templates/.cursor/rules/development-guide.mdc +3 -4
- package/generators/micro-react/templates/.cursor/rules/layout-app.mdc +38 -31
- package/generators/micro-react/templates/.cursor/rules/project-overview.mdc +7 -4
- package/generators/micro-react/templates/.cursor/rules/theme-system.mdc +10 -12
- package/generators/micro-react/templates/.eslintrc.js +25 -1
- package/generators/micro-react/templates/AGENTS.md +5 -2
- package/generators/micro-react/templates/CICD/before_build.sh +76 -0
- package/generators/micro-react/templates/CICD/start_dev.sh +27 -3
- package/generators/micro-react/templates/CICD/start_prod.sh +26 -3
- package/generators/micro-react/templates/CICD/start_test.sh +28 -3
- package/generators/micro-react/templates/CICD/wangsu_fresh_dev.sh +4 -4
- package/generators/micro-react/templates/CICD/wangsu_fresh_prod.sh +4 -4
- package/generators/micro-react/templates/CICD/wangsu_fresh_test.sh +4 -4
- package/generators/micro-react/templates/CLAUDE.md +16 -9
- package/generators/micro-react/templates/README.md +42 -4
- package/generators/micro-react/templates/_gitignore +4 -0
- package/generators/micro-react/templates/_npmrc +4 -0
- package/generators/micro-react/templates/apps/layout/config/config.dev.ts +32 -16
- package/generators/micro-react/templates/apps/layout/config/config.prod.development.ts +24 -29
- package/generators/micro-react/templates/apps/layout/config/config.prod.testing.ts +25 -6
- package/generators/micro-react/templates/apps/layout/config/config.prod.ts +16 -7
- package/generators/micro-react/templates/apps/layout/config/config.ts +27 -4
- package/generators/micro-react/templates/apps/layout/config/routes.ts +5 -5
- 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
- package/generators/micro-react/templates/apps/layout/docs/common-intl.md +372 -0
- 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
- package/generators/micro-react/templates/apps/layout/docs/feature-404/351/241/265/351/235/242.md +103 -0
- 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
- 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
- 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 +308 -63
- 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
- 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
- package/generators/micro-react/templates/apps/layout/docs/utils-timezone.md +324 -0
- package/generators/micro-react/templates/apps/layout/mock/api.mock.ts +81 -61
- package/generators/micro-react/templates/apps/layout/mock/menus.ts +114 -4
- package/generators/micro-react/templates/apps/layout/mock/pages.ts +86 -0
- package/generators/micro-react/templates/apps/layout/package.json +7 -4
- package/generators/micro-react/templates/apps/layout/src/app.tsx +111 -76
- package/generators/micro-react/templates/apps/layout/src/common/auth/index.ts +3 -0
- package/generators/micro-react/templates/apps/layout/src/common/helpers.ts +177 -0
- package/generators/micro-react/templates/apps/layout/src/common/locale.ts +22 -17
- package/generators/micro-react/templates/apps/layout/src/common/menu/parser.ts +192 -42
- package/generators/micro-react/templates/apps/layout/src/common/menu/types.ts +69 -5
- package/generators/micro-react/templates/apps/layout/src/common/micro/index.ts +34 -0
- package/generators/micro-react/templates/apps/layout/src/common/micro-prefetch.ts +109 -0
- package/generators/micro-react/templates/apps/layout/src/common/portal-data.ts +45 -0
- package/generators/micro-react/templates/apps/layout/src/common/request/config.ts +72 -10
- package/generators/micro-react/templates/apps/layout/src/common/request/index.ts +2 -2
- package/generators/micro-react/templates/apps/layout/src/common/request/interceptors.ts +31 -3
- package/generators/micro-react/templates/apps/layout/src/common/request/sso.ts +29 -11
- package/generators/micro-react/templates/apps/layout/src/common/request/url-resolver.ts +1 -1
- package/generators/micro-react/templates/apps/layout/src/common/route-guard.ts +345 -0
- package/generators/micro-react/templates/apps/layout/src/common/theme.ts +2 -4
- package/generators/micro-react/templates/apps/layout/src/common/upload/oss.ts +3 -4
- package/generators/micro-react/templates/apps/layout/src/common/upload/types.ts +1 -1
- package/generators/micro-react/templates/apps/layout/src/common/uploadFiles.ts +1 -1
- package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.less +8 -3
- package/generators/micro-react/templates/apps/layout/src/components/AppTabs/index.tsx +25 -8
- package/generators/micro-react/templates/apps/layout/src/components/HeaderDropdown/index.tsx +20 -0
- package/generators/micro-react/templates/apps/layout/src/components/IconFont/index.tsx +5 -6
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.less +21 -6
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/index.tsx +83 -149
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/micro-app-manager.ts +569 -0
- package/generators/micro-react/templates/apps/layout/src/components/RightContent/AvatarDropdown.tsx +383 -0
- package/generators/micro-react/templates/apps/layout/src/components/RightContent/avatar-dropdown.less +35 -0
- package/generators/micro-react/templates/apps/layout/src/components/RightContent/index.ts +2 -0
- package/generators/micro-react/templates/apps/layout/src/constants/index.ts +170 -6
- package/generators/micro-react/templates/apps/layout/src/global.less +18 -9
- package/generators/micro-react/templates/apps/layout/src/hooks/useMenu.ts +3 -2
- package/generators/micro-react/templates/apps/layout/src/hooks/useRoutePermissionRefresh.ts +72 -0
- package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.less +3 -1
- package/generators/micro-react/templates/apps/layout/src/layouts/components/header/index.tsx +10 -55
- package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.less +34 -4
- package/generators/micro-react/templates/apps/layout/src/layouts/components/menu/index.tsx +24 -8
- package/generators/micro-react/templates/apps/layout/src/layouts/index.less +84 -13
- package/generators/micro-react/templates/apps/layout/src/layouts/index.tsx +156 -69
- package/generators/micro-react/templates/apps/layout/src/locales/en-US.ts +12 -0
- package/generators/micro-react/templates/apps/layout/src/locales/zh-CN.ts +12 -0
- package/generators/micro-react/templates/apps/layout/src/pages/403/index.tsx +8 -2
- package/generators/micro-react/templates/apps/layout/src/pages/404/index.tsx +78 -0
- package/generators/micro-react/templates/apps/layout/src/pages/Home/index.less +3 -0
- package/generators/micro-react/templates/apps/layout/src/pages/Home/index.tsx +7 -1
- package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.less +1 -1
- package/generators/micro-react/templates/apps/layout/src/pages/User/Login/index.tsx +3 -3
- package/generators/micro-react/templates/apps/layout/src/requestErrorConfig.ts +1 -1
- package/generators/micro-react/templates/apps/layout/src/services/config/index.ts +63 -0
- package/generators/micro-react/templates/apps/layout/src/services/config/type.ts +30 -0
- package/generators/micro-react/templates/apps/layout/src/services/user.ts +29 -2
- package/generators/micro-react/templates/apps/layout/tailwind.config.js +3 -0
- package/generators/micro-react/templates/deployDesc.md +3 -3
- package/generators/micro-react/templates/dev.preset.json +14 -0
- package/generators/micro-react/templates/docs/dev-preset.md +130 -0
- package/generators/micro-react/templates/package.json +21 -6
- package/generators/micro-react/templates/packages/common-intl/README.md +427 -0
- package/generators/micro-react/templates/packages/common-intl/package.json +34 -0
- package/generators/micro-react/templates/packages/common-intl/src/index.ts +7 -0
- package/generators/micro-react/templates/packages/common-intl/src/indexedDBUtils.ts +51 -0
- package/generators/micro-react/templates/packages/common-intl/src/intl.ts +50 -0
- package/generators/micro-react/templates/packages/common-intl/src/utils.ts +482 -0
- package/generators/micro-react/templates/packages/common-intl/tsconfig.json +22 -0
- package/generators/micro-react/templates/packages/common-intl/vite.config.ts +25 -0
- package/generators/micro-react/templates/scripts/apply-sentry-plugin.ts +45 -0
- package/generators/micro-react/templates/scripts/collect-dist.js +10 -0
- package/generators/micro-react/templates/scripts/dev-preset.js +265 -0
- package/generators/micro-react/templates/scripts/dev-preset.schema.json +39 -0
- package/generators/micro-react/templates/turbo.json +4 -1
- package/generators/subapp-react/index.js +326 -40
- package/generators/subapp-react/meta.json +10 -0
- package/generators/subapp-react/templates/homepage/.env +2 -1
- package/generators/subapp-react/templates/homepage/README.md +3 -3
- package/generators/subapp-react/templates/homepage/config/config.dev.ts +14 -7
- package/generators/subapp-react/templates/homepage/config/config.prod.development.ts +16 -5
- package/generators/subapp-react/templates/homepage/config/config.prod.testing.ts +16 -5
- package/generators/subapp-react/templates/homepage/config/config.prod.ts +14 -5
- package/generators/subapp-react/templates/homepage/config/config.ts +21 -0
- package/generators/subapp-react/templates/homepage/config/routes.ts +2 -2
- package/generators/subapp-react/templates/homepage/mock/api.mock.ts +2 -2
- package/generators/subapp-react/templates/homepage/package.json +7 -4
- package/generators/subapp-react/templates/homepage/src/app.tsx +18 -27
- package/generators/subapp-react/templates/homepage/src/common/request.ts +29 -2
- package/generators/subapp-react/templates/homepage/src/global.less +6 -5
- package/generators/subapp-react/templates/homepage/src/pages/index.less +3 -3
- package/generators/subapp-react/templates/homepage/src/pages/index.tsx +99 -60
- package/generators/subapp-react/templates/homepage/src/styles/theme.less +1 -1
- package/generators/subapp-umd/ignore-list.json +5 -0
- package/generators/subapp-umd/index.js +309 -0
- package/generators/subapp-umd/meta.json +11 -0
- package/generators/subapp-umd/templates/README.md +94 -0
- package/generators/subapp-umd/templates/package.json +35 -0
- package/generators/subapp-umd/templates/public/index.html +34 -0
- package/generators/subapp-umd/templates/src/App.less +15 -0
- package/generators/subapp-umd/templates/src/App.tsx +13 -0
- package/generators/subapp-umd/templates/src/index.ts +2 -0
- package/generators/subapp-umd/templates/tsconfig.json +27 -0
- package/generators/subapp-umd/templates/webpack.config.js +70 -0
- package/lib/utils.js +332 -2
- package/package.json +15 -2
- package/generators/micro-react/templates/apps/layout/mock/menus.json +0 -100
- package/generators/micro-react/templates/apps/layout/src/common/constants.ts +0 -38
- package/generators/micro-react/templates/apps/layout/src/components/MicroAppLoader/container-manager.ts +0 -202
- package/generators/micro-react/templates/packages/shared-styles/README.md +0 -124
- package/generators/micro-react/templates/packages/shared-styles/arco-design-mobile-override.less +0 -91
- package/generators/micro-react/templates/packages/shared-styles/arco-override.less +0 -119
- package/generators/micro-react/templates/packages/shared-styles/index.d.ts +0 -44
- package/generators/micro-react/templates/packages/shared-styles/index.less +0 -13
- package/generators/micro-react/templates/packages/shared-styles/package.json +0 -30
- package/generators/micro-react/templates/packages/shared-styles/theme-inject.less +0 -10
- package/generators/micro-react/templates/packages/shared-styles/themes/dark/custom-var.less +0 -290
- package/generators/micro-react/templates/packages/shared-styles/themes/normal/custom-var.less +0 -269
- package/generators/micro-react/templates/packages/shared-styles/variables-only.less +0 -433
- package/generators/micro-react/templates/packages/shared-styles/variables.less +0 -452
package/README.md
CHANGED
|
@@ -9,39 +9,89 @@
|
|
|
9
9
|
| [docs/mico-cli.md](docs/mico-cli.md) | Mico CLI 功能概述与技术方案 |
|
|
10
10
|
| [docs/micro-react-generator.md](docs/micro-react-generator.md) | Monorepo 项目生成器说明 |
|
|
11
11
|
| [docs/subapp-react-generator.md](docs/subapp-react-generator.md) | React 子应用生成器说明 |
|
|
12
|
+
| [docs/subapp-umd-generator.md](docs/subapp-umd-generator.md) | UMD 组件包生成器说明 |
|
|
13
|
+
| [docs/feat-integration-tests.md](docs/feat-integration-tests.md) | 集成测试方案(Vitest + yeoman-test) |
|
|
14
|
+
| [docs/fix-command-injection.md](docs/fix-command-injection.md) | 修复 npm version 查询命令注入风险 |
|
|
15
|
+
| [docs/refactor-code-quality-optimizations.md](docs/refactor-code-quality-optimizations.md) | 代码质量优化(DRY / 错误处理 / 确定性 ID / 可配置化 / 冗余清理) |
|
|
12
16
|
|
|
13
17
|
## 要求
|
|
14
18
|
|
|
15
19
|
- Node >= 18
|
|
16
|
-
- Yeoman CLI: `npm install -g yo`
|
|
17
20
|
|
|
18
21
|
## 安装和使用
|
|
19
22
|
|
|
20
23
|
```bash
|
|
21
|
-
npm install -g
|
|
24
|
+
npm install -g generator-mico-cli
|
|
22
25
|
```
|
|
23
26
|
|
|
24
27
|
## 包装器 CLI
|
|
25
28
|
|
|
26
|
-
全局安装后,`mico`
|
|
27
|
-
如果 `generators/<name>` 下存在本地生成器,它将作为 `yo mico-cli:<name>` 运行。
|
|
29
|
+
全局安装后,`mico` 命令可用于运行内置的 Yeoman 生成器。
|
|
28
30
|
|
|
29
31
|
```bash
|
|
30
32
|
mico create subapp-react
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
列出所有可用的生成器:
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
|
-
|
|
38
|
+
mico list
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
使用详细输出模式(显示文件处理过程):
|
|
40
42
|
|
|
41
43
|
```bash
|
|
42
|
-
mico create micro-react --
|
|
44
|
+
mico create micro-react --verbose
|
|
43
45
|
```
|
|
44
46
|
|
|
47
|
+
预览模式(只显示将创建的文件,不实际创建):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
mico create micro-react --dry-run
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
检查环境依赖:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
mico doctor
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 配置文件
|
|
60
|
+
|
|
61
|
+
可以在项目目录或用户主目录创建 `.micorc` 或 `.micorc.json` 文件来预设默认值。
|
|
62
|
+
|
|
63
|
+
配置查找顺序:
|
|
64
|
+
1. 当前目录(或 monorepo 根目录)的 `.micorc` / `.micorc.json`
|
|
65
|
+
2. 用户主目录的 `.micorc` / `.micorc.json`
|
|
66
|
+
|
|
67
|
+
### 完整字段列表
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"projectName": "my-app",
|
|
72
|
+
"packageScope": "@my-company",
|
|
73
|
+
"cdnPrefix": "portal",
|
|
74
|
+
"author": "Team <team@example.com>",
|
|
75
|
+
"defaultSubappName": "subapp",
|
|
76
|
+
"devPort": "8010",
|
|
77
|
+
"defaultUmdName": "my-widget",
|
|
78
|
+
"umdDevPort": "9100"
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| 字段 | 类型 | 适用生成器 | 说明 | 默认值 |
|
|
83
|
+
|------|------|-----------|------|--------|
|
|
84
|
+
| `projectName` | string | micro-react | 项目名称 | 当前目录名 |
|
|
85
|
+
| `packageScope` | string | 所有 | 包作用域(如 `@my-company`) | micro-react: `@<projectName>`;其他: 从根 `package.json` 检测 |
|
|
86
|
+
| `cdnPrefix` | string | micro-react | CDN 路径前缀(如 `portal`、`admin/v2`) | 空字符串 |
|
|
87
|
+
| `author` | string | micro-react | 作者信息 | `Your Name <email@example.com>` |
|
|
88
|
+
| `defaultSubappName` | string | subapp-react | 子应用默认名称 | `subapp` |
|
|
89
|
+
| `devPort` | string | subapp-react | 子应用开发端口 | `8010` |
|
|
90
|
+
| `defaultUmdName` | string | subapp-umd | UMD 包默认名称 | `my-widget` |
|
|
91
|
+
| `umdDevPort` | string | subapp-umd | UMD 包开发端口 | `9100` |
|
|
92
|
+
|
|
93
|
+
所有字段均为可选,未配置时使用默认值或交互式提示。
|
|
94
|
+
|
|
45
95
|
## Monorepo 项目生成器 (micro-react)
|
|
46
96
|
|
|
47
97
|
创建基于 qiankun 微前端架构的完整 Monorepo 项目:
|
|
@@ -53,9 +103,10 @@ mico create micro-react
|
|
|
53
103
|
|
|
54
104
|
生成的项目包含:
|
|
55
105
|
- 主应用 (layout) - qiankun master
|
|
56
|
-
-
|
|
106
|
+
- @mico-platform/ui、@mico-platform/theme
|
|
57
107
|
- Turborepo + pnpm Workspace
|
|
58
108
|
- Husky + Commitlint
|
|
109
|
+
- @common-web/sentry 错误监控与 SourceMap 上传
|
|
59
110
|
|
|
60
111
|
## React 子应用生成器
|
|
61
112
|
|
|
@@ -67,18 +118,151 @@ cd <monorepo-root>
|
|
|
67
118
|
mico create subapp-react
|
|
68
119
|
```
|
|
69
120
|
|
|
70
|
-
##
|
|
121
|
+
## UMD 组件包生成器
|
|
122
|
+
|
|
123
|
+
在 Monorepo 的 `packages/` 目录下创建 UMD 格式的组件包,使用 Webpack 构建。适用于通过 `<script>` 标签加载的场景(如主应用菜单挂载组件、第三方系统嵌入 Widget 等)。
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
cd <monorepo-root>
|
|
127
|
+
mico create subapp-umd
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
生成器会提示输入:
|
|
131
|
+
- **Package name** — 包名(如 `my-widget`)
|
|
132
|
+
- **UMD global variable name** — 全局变量名(如 `MyWidget`)
|
|
133
|
+
- **Package scope** — 包作用域(自动从根 `package.json` 检测)
|
|
134
|
+
- **Dev server port** — 开发端口(默认 `9100`)
|
|
135
|
+
|
|
136
|
+
生成的包支持:
|
|
137
|
+
- `pnpm dev` — 启动 webpack-dev-server,同时提供 HTML 预览页和 UMD JS 文件
|
|
138
|
+
- `pnpm build` — 构建生产环境 UMD 产物到 `dist/`
|
|
139
|
+
|
|
140
|
+
开发模式下:
|
|
141
|
+
|
|
142
|
+
| URL | 用途 |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `http://localhost:<port>/` | HTML 预览页,独立调试 |
|
|
145
|
+
| `http://localhost:<port>/<name>.umd.js` | UMD JS 文件,供主应用通过 `jsUrls` 联调 |
|
|
146
|
+
|
|
147
|
+
DevTools Sources 面板中可在 `webpack://<name>/src/` 下定位原始 TypeScript 源码进行断点调试。
|
|
148
|
+
|
|
149
|
+
## 开发指南
|
|
150
|
+
|
|
151
|
+
### 环境准备
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# 1. 安装依赖
|
|
155
|
+
pnpm install
|
|
156
|
+
|
|
157
|
+
# 2. 将本地包链接到全局
|
|
158
|
+
npm link
|
|
159
|
+
|
|
160
|
+
# 3. 验证链接成功
|
|
161
|
+
mico --version
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
链接成功后,`mico` 命令会使用本地代码,可以直接修改代码并测试:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# 测试 micro-react 生成器
|
|
168
|
+
mkdir test-project && cd test-project
|
|
169
|
+
mico create micro-react
|
|
170
|
+
|
|
171
|
+
# 测试 subapp-react 生成器(需在已有 monorepo 中执行)
|
|
172
|
+
mico create subapp-react
|
|
173
|
+
|
|
174
|
+
# 测试 subapp-umd 生成器(需在已有 monorepo 中执行)
|
|
175
|
+
mico create subapp-umd
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
调试完成后,取消全局链接:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
npm unlink -g generator-mico-cli
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 运行测试
|
|
71
185
|
|
|
72
|
-
|
|
186
|
+
项目使用 Vitest + yeoman-test 进行单元测试和集成测试:
|
|
73
187
|
|
|
74
188
|
```bash
|
|
75
|
-
|
|
189
|
+
# 运行全部测试
|
|
190
|
+
pnpm test
|
|
191
|
+
|
|
192
|
+
# watch 模式
|
|
193
|
+
pnpm test:watch
|
|
76
194
|
```
|
|
77
195
|
|
|
78
|
-
|
|
196
|
+
测试目录结构:
|
|
197
|
+
|
|
198
|
+
| 目录/文件 | 说明 |
|
|
199
|
+
|----------|------|
|
|
200
|
+
| `tests/unit/utils.test.js` | `lib/utils.js` 的单元测试 |
|
|
201
|
+
| `tests/integration/micro-react.test.js` | micro-react 生成器集成测试 |
|
|
202
|
+
| `tests/integration/subapp-react.test.js` | subapp-react 生成器集成测试 |
|
|
203
|
+
| `tests/integration/subapp-umd.test.js` | subapp-umd 生成器集成测试 |
|
|
204
|
+
| `tests/integration/mico-cli.test.js` | `mico` 入口子进程测试(help / version / list / create / doctor) |
|
|
205
|
+
| `tests/helpers/setup.js` | 测试共享工具(路径常量、monorepo fixture 工厂) |
|
|
206
|
+
| `tests/helpers/mico-subprocess.js` | 子进程运行 `bin/mico.js` 工具函数 |
|
|
207
|
+
|
|
208
|
+
### Scripts 说明
|
|
209
|
+
|
|
210
|
+
| 脚本 | 命令 | 说明 |
|
|
211
|
+
|------|------|------|
|
|
212
|
+
| `sync:subapp-react-template` | `pnpm run sync:subapp-react-template -- <source-path>` | 将源项目的 `apps/homepage` 同步到 `subapp-react` 模板目录,忽略清单见 `generators/subapp-react/ignore-list.json` |
|
|
213
|
+
| `verify:micro-react` | `node scripts/verify-micro-react.js [test-dir]` | 端到端验证 micro-react + subapp-react 生成器,自动创建项目并回车通过所有提示 |
|
|
214
|
+
|
|
215
|
+
#### verify-micro-react.js
|
|
216
|
+
|
|
217
|
+
自动化验证脚本,依次执行:
|
|
218
|
+
1. 创建或清空测试目录
|
|
219
|
+
2. 运行 `mico create micro-react`(自动回车通过 5 个提示)
|
|
220
|
+
3. 运行 `mico create subapp-react`(自动回车通过 4 个提示)
|
|
221
|
+
|
|
222
|
+
测试目录支持三种方式指定:
|
|
223
|
+
- 命令行参数:`node scripts/verify-micro-react.js /path/to/dir`
|
|
224
|
+
- 环境变量:`VERIFY_TEST_DIR=/path node scripts/verify-micro-react.js`
|
|
225
|
+
- 默认值:`../test-app2`
|
|
226
|
+
|
|
227
|
+
#### sync-subapp-react-template.js
|
|
228
|
+
|
|
229
|
+
从源 monorepo 项目同步 `apps/homepage` 到生成器模板目录:
|
|
79
230
|
|
|
80
231
|
```bash
|
|
81
|
-
|
|
232
|
+
# 通过环境变量
|
|
233
|
+
SOURCE_PROJECT_ROOT=<source-path> pnpm run sync:subapp-react-template
|
|
234
|
+
|
|
235
|
+
# 通过命令行参数
|
|
236
|
+
pnpm run sync:subapp-react-template -- <source-path>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
会自动记录源仓库的 git commit 信息到 `.template-version.json`。
|
|
240
|
+
|
|
241
|
+
### 项目结构
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
mico-cli/
|
|
245
|
+
├── bin/mico.js # CLI 入口(命令解析、生成器调度)
|
|
246
|
+
├── lib/utils.js # 共享工具函数(字符串转换、文件处理、npm 版本查询、配置加载)
|
|
247
|
+
├── generators/
|
|
248
|
+
│ ├── micro-react/ # Monorepo 项目生成器
|
|
249
|
+
│ ├── subapp-react/ # React 子应用生成器
|
|
250
|
+
│ └── subapp-umd/ # UMD 组件包生成器
|
|
251
|
+
├── scripts/ # 辅助脚本
|
|
252
|
+
├── tests/ # 测试文件
|
|
253
|
+
├── docs/ # 功能文档
|
|
254
|
+
└── vitest.config.js # 测试配置
|
|
82
255
|
```
|
|
83
256
|
|
|
84
|
-
|
|
257
|
+
### 提交规范
|
|
258
|
+
|
|
259
|
+
请使用语义化提交信息:
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
feat: 添加新功能
|
|
263
|
+
fix: 修复 Bug
|
|
264
|
+
refactor: 代码重构
|
|
265
|
+
docs: 文档更新
|
|
266
|
+
test: 测试相关
|
|
267
|
+
chore: 构建/工具链变更
|
|
268
|
+
```
|
package/bin/mico.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const {
|
|
4
|
+
const { spawnSync } = require('node:child_process');
|
|
5
5
|
const fs = require('node:fs');
|
|
6
6
|
const path = require('node:path');
|
|
7
7
|
const readline = require('node:readline');
|
|
8
8
|
|
|
9
|
+
const { setupErrorHandlers } = require('../lib/utils');
|
|
10
|
+
|
|
11
|
+
setupErrorHandlers();
|
|
12
|
+
|
|
9
13
|
const rootDir = path.resolve(__dirname, '..');
|
|
10
14
|
const pkg = JSON.parse(
|
|
11
15
|
fs.readFileSync(path.join(rootDir, 'package.json'), 'utf8')
|
|
@@ -20,24 +24,112 @@ Usage: mico <command> [options]
|
|
|
20
24
|
|
|
21
25
|
Commands:
|
|
22
26
|
create <generator> Run a generator (e.g., mico create subapp-react)
|
|
27
|
+
list List all available generators
|
|
23
28
|
update Update mico-cli to the latest version
|
|
29
|
+
doctor Check environment dependencies
|
|
24
30
|
|
|
25
31
|
Options:
|
|
26
32
|
--help, -h Show this help message
|
|
27
33
|
--version, -v Show version number
|
|
34
|
+
--verbose Show detailed output during generation
|
|
35
|
+
--dry-run Preview files without creating them
|
|
36
|
+
--force Overwrite all existing files without confirmation
|
|
28
37
|
--no-update-check Skip update check
|
|
29
38
|
|
|
30
39
|
Examples:
|
|
31
40
|
mico create subapp-react
|
|
32
|
-
mico create
|
|
41
|
+
mico create micro-react --verbose
|
|
42
|
+
mico create micro-react --dry-run
|
|
43
|
+
mico create micro-react --force
|
|
44
|
+
mico list
|
|
33
45
|
mico update
|
|
46
|
+
mico doctor
|
|
47
|
+
|
|
48
|
+
Configuration:
|
|
49
|
+
Create a .micorc or .micorc.json file in your project or home directory
|
|
50
|
+
to set default values for prompts:
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
"packageScope": "@my-company",
|
|
54
|
+
"cdnPrefix": "portal",
|
|
55
|
+
"author": "Team <team@example.com>"
|
|
56
|
+
}
|
|
34
57
|
|
|
35
58
|
Notes:
|
|
36
|
-
Requires Yeoman CLI (yo) installed globally.
|
|
37
59
|
If a local generator exists at generators/<name>, it will be used.
|
|
38
60
|
`);
|
|
39
61
|
}
|
|
40
62
|
|
|
63
|
+
/**
|
|
64
|
+
* 列出所有可用的生成器
|
|
65
|
+
*/
|
|
66
|
+
function listGenerators() {
|
|
67
|
+
const generatorsDir = path.join(rootDir, 'generators');
|
|
68
|
+
|
|
69
|
+
if (!fs.existsSync(generatorsDir)) {
|
|
70
|
+
console.error('❌ Error: generators directory not found.');
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const entries = fs.readdirSync(generatorsDir, { withFileTypes: true });
|
|
75
|
+
const generators = [];
|
|
76
|
+
|
|
77
|
+
for (const entry of entries) {
|
|
78
|
+
if (!entry.isDirectory()) continue;
|
|
79
|
+
|
|
80
|
+
const generatorPath = path.join(generatorsDir, entry.name);
|
|
81
|
+
const indexPath = path.join(generatorPath, 'index.js');
|
|
82
|
+
const metaPath = path.join(generatorPath, 'meta.json');
|
|
83
|
+
|
|
84
|
+
// 必须有 index.js 才算有效生成器
|
|
85
|
+
if (!fs.existsSync(indexPath)) continue;
|
|
86
|
+
|
|
87
|
+
let meta = { name: entry.name, description: '(No description)' };
|
|
88
|
+
if (fs.existsSync(metaPath)) {
|
|
89
|
+
try {
|
|
90
|
+
meta = { ...meta, ...JSON.parse(fs.readFileSync(metaPath, 'utf8')) };
|
|
91
|
+
} catch (e) {
|
|
92
|
+
console.warn(` ⚠ Failed to parse ${metaPath}: ${e.message}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
generators.push(meta);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (generators.length === 0) {
|
|
100
|
+
console.log('');
|
|
101
|
+
console.log(' No generators found.');
|
|
102
|
+
console.log('');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log(` \x1b[1mAvailable Generators\x1b[0m (mico-cli v${pkg.version})`);
|
|
108
|
+
console.log('');
|
|
109
|
+
|
|
110
|
+
// 计算最长名称用于对齐
|
|
111
|
+
const maxNameLen = Math.max(...generators.map((g) => g.name.length));
|
|
112
|
+
|
|
113
|
+
for (const gen of generators) {
|
|
114
|
+
const name = gen.name.padEnd(maxNameLen + 2);
|
|
115
|
+
console.log(` \x1b[36m${name}\x1b[0m ${gen.description}`);
|
|
116
|
+
|
|
117
|
+
// 如果有 features,显示特性列表
|
|
118
|
+
if (gen.features && gen.features.length > 0) {
|
|
119
|
+
for (const feature of gen.features) {
|
|
120
|
+
console.log(` ${' '.repeat(maxNameLen + 2)} • ${feature}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 如果有 usage,显示用法
|
|
125
|
+
if (gen.usage) {
|
|
126
|
+
console.log(` ${' '.repeat(maxNameLen + 2)} \x1b[2m$ ${gen.usage}\x1b[0m`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log('');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
41
133
|
/**
|
|
42
134
|
* 打印版本信息
|
|
43
135
|
*/
|
|
@@ -45,6 +137,76 @@ function printVersion() {
|
|
|
45
137
|
console.log(`mico-cli v${pkg.version}`);
|
|
46
138
|
}
|
|
47
139
|
|
|
140
|
+
/**
|
|
141
|
+
* 运行 doctor 检查
|
|
142
|
+
*/
|
|
143
|
+
async function runDoctor() {
|
|
144
|
+
const { runDoctorChecks, loadMicorc } = require('../lib/utils');
|
|
145
|
+
|
|
146
|
+
console.log('');
|
|
147
|
+
console.log(` \x1b[1mMico CLI Environment Check\x1b[0m (v${pkg.version})`);
|
|
148
|
+
console.log('');
|
|
149
|
+
|
|
150
|
+
const results = await runDoctorChecks();
|
|
151
|
+
|
|
152
|
+
// Node.js
|
|
153
|
+
const nodeIcon = results.node.satisfied ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
|
|
154
|
+
const nodeStatus = results.node.satisfied ? 'OK' : `Required: >= ${results.node.required}`;
|
|
155
|
+
console.log(` ${nodeIcon} Node.js ${results.node.current} (${nodeStatus})`);
|
|
156
|
+
|
|
157
|
+
// pnpm
|
|
158
|
+
const pnpmIcon = results.pnpm.available ? '\x1b[32m✓\x1b[0m' : '\x1b[31m✗\x1b[0m';
|
|
159
|
+
if (results.pnpm.available) {
|
|
160
|
+
console.log(` ${pnpmIcon} pnpm ${results.pnpm.version}`);
|
|
161
|
+
} else {
|
|
162
|
+
console.log(` ${pnpmIcon} pnpm not found`);
|
|
163
|
+
console.log(' Install: npm install -g pnpm');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Git
|
|
167
|
+
const gitIcon = results.git.available ? '\x1b[32m✓\x1b[0m' : '\x1b[33m⚠\x1b[0m';
|
|
168
|
+
if (results.git.available) {
|
|
169
|
+
console.log(` ${gitIcon} git ${results.git.version}`);
|
|
170
|
+
} else {
|
|
171
|
+
console.log(` ${gitIcon} git not found (optional)`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// npm registry
|
|
175
|
+
const npmIcon = results.npm.reachable ? '\x1b[32m✓\x1b[0m' : '\x1b[33m⚠\x1b[0m';
|
|
176
|
+
if (results.npm.reachable) {
|
|
177
|
+
console.log(` ${npmIcon} npm registry reachable`);
|
|
178
|
+
} else {
|
|
179
|
+
console.log(` ${npmIcon} npm registry unreachable (${results.npm.error})`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// .micorc 配置
|
|
183
|
+
console.log('');
|
|
184
|
+
const { config, configPath } = loadMicorc();
|
|
185
|
+
if (configPath) {
|
|
186
|
+
console.log(` \x1b[32m✓\x1b[0m Config loaded from: ${configPath}`);
|
|
187
|
+
const keys = Object.keys(config);
|
|
188
|
+
if (keys.length > 0) {
|
|
189
|
+
console.log(` Keys: ${keys.join(', ')}`);
|
|
190
|
+
}
|
|
191
|
+
} else {
|
|
192
|
+
console.log(' \x1b[2m○\x1b[0m No .micorc config found (optional)');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
console.log('');
|
|
196
|
+
|
|
197
|
+
// 总结
|
|
198
|
+
const allGood = results.node.satisfied && results.pnpm.available;
|
|
199
|
+
if (allGood) {
|
|
200
|
+
console.log(' \x1b[32m✅ All required dependencies are installed!\x1b[0m');
|
|
201
|
+
} else {
|
|
202
|
+
console.log(' \x1b[31m❌ Some required dependencies are missing.\x1b[0m');
|
|
203
|
+
console.log(' Please install them before using mico-cli.');
|
|
204
|
+
}
|
|
205
|
+
console.log('');
|
|
206
|
+
|
|
207
|
+
return allGood;
|
|
208
|
+
}
|
|
209
|
+
|
|
48
210
|
/**
|
|
49
211
|
* 检查是否有新版本
|
|
50
212
|
* @returns {Promise<{current: string, latest: string, hasUpdate: boolean} | null>}
|
|
@@ -178,8 +340,13 @@ function performUpdate(latestVersion) {
|
|
|
178
340
|
|
|
179
341
|
/**
|
|
180
342
|
* 运行 Yeoman 生成器
|
|
343
|
+
* @param {string} generator - 生成器名称
|
|
344
|
+
* @param {object} options - 选项
|
|
345
|
+
* @param {boolean} options.verbose - 是否启用详细输出
|
|
346
|
+
* @param {boolean} options.dryRun - 是否启用 dry-run 模式
|
|
347
|
+
* @param {boolean} options.force - 是否强制覆盖已有文件
|
|
181
348
|
*/
|
|
182
|
-
function runGenerator(generator,
|
|
349
|
+
async function runGenerator(generator, options = {}) {
|
|
183
350
|
const localGeneratorEntry = path.join(
|
|
184
351
|
rootDir,
|
|
185
352
|
'generators',
|
|
@@ -187,34 +354,50 @@ function runGenerator(generator, rest, passthroughArgs) {
|
|
|
187
354
|
'index.js'
|
|
188
355
|
);
|
|
189
356
|
|
|
357
|
+
if (!fs.existsSync(localGeneratorEntry)) {
|
|
358
|
+
console.error(`❌ Cannot find generator "${generator}".`);
|
|
359
|
+
console.error(` Expected: ${localGeneratorEntry}`);
|
|
360
|
+
console.error('');
|
|
361
|
+
console.error(' Run "mico list" to see available generators.');
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
364
|
+
|
|
190
365
|
const pkgName = typeof pkg.name === 'string' ? pkg.name : '';
|
|
191
366
|
const localNamespace =
|
|
192
367
|
pkgName.replace(/^generator-/, '') || pkgName || 'generator';
|
|
368
|
+
const namespace = `${localNamespace}:${generator}`;
|
|
193
369
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (passthroughArgs.length > 0) {
|
|
201
|
-
yoArgs.push('--', ...passthroughArgs);
|
|
370
|
+
if (options.verbose) {
|
|
371
|
+
process.env.MICO_VERBOSE = '1';
|
|
372
|
+
}
|
|
373
|
+
if (options.dryRun) {
|
|
374
|
+
process.env.MICO_DRY_RUN = '1';
|
|
202
375
|
}
|
|
203
376
|
|
|
204
|
-
const
|
|
377
|
+
const runOptions = {};
|
|
378
|
+
if (options.dryRun) {
|
|
379
|
+
runOptions.dryRun = true;
|
|
380
|
+
}
|
|
381
|
+
if (options.force) {
|
|
382
|
+
runOptions.force = true;
|
|
383
|
+
}
|
|
205
384
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
console.
|
|
385
|
+
if (options.verbose) {
|
|
386
|
+
console.log('');
|
|
387
|
+
console.log(' \x1b[2m[verbose] Running generator:', namespace, '\x1b[0m');
|
|
388
|
+
if (options.dryRun) {
|
|
389
|
+
console.log(' \x1b[2m[verbose] Dry-run mode enabled\x1b[0m');
|
|
211
390
|
}
|
|
212
|
-
|
|
213
|
-
|
|
391
|
+
if (options.force) {
|
|
392
|
+
console.log(' \x1b[2m[verbose] Force mode enabled\x1b[0m');
|
|
393
|
+
}
|
|
394
|
+
console.log('');
|
|
395
|
+
}
|
|
214
396
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
397
|
+
const yeomanEnv = require('yeoman-environment');
|
|
398
|
+
const env = yeomanEnv.createEnv();
|
|
399
|
+
env.register(localGeneratorEntry, namespace);
|
|
400
|
+
await env.run(namespace, runOptions);
|
|
218
401
|
}
|
|
219
402
|
|
|
220
403
|
/**
|
|
@@ -234,6 +417,9 @@ async function main() {
|
|
|
234
417
|
const hasHelp = mainArgs.includes('--help') || mainArgs.includes('-h');
|
|
235
418
|
const hasVersion = mainArgs.includes('--version') || mainArgs.includes('-v');
|
|
236
419
|
const skipUpdateCheck = mainArgs.includes('--no-update-check');
|
|
420
|
+
const isVerbose = mainArgs.includes('--verbose');
|
|
421
|
+
const isDryRun = mainArgs.includes('--dry-run');
|
|
422
|
+
const isForce = mainArgs.includes('--force');
|
|
237
423
|
|
|
238
424
|
// 过滤掉标志参数
|
|
239
425
|
const filteredArgs = mainArgs.filter(
|
|
@@ -242,7 +428,10 @@ async function main() {
|
|
|
242
428
|
arg !== '-h' &&
|
|
243
429
|
arg !== '--version' &&
|
|
244
430
|
arg !== '-v' &&
|
|
245
|
-
arg !== '--no-update-check'
|
|
431
|
+
arg !== '--no-update-check' &&
|
|
432
|
+
arg !== '--verbose' &&
|
|
433
|
+
arg !== '--dry-run' &&
|
|
434
|
+
arg !== '--force'
|
|
246
435
|
);
|
|
247
436
|
|
|
248
437
|
// 处理 --version
|
|
@@ -259,6 +448,18 @@ async function main() {
|
|
|
259
448
|
|
|
260
449
|
const [command, ...rest] = filteredArgs;
|
|
261
450
|
|
|
451
|
+
// 处理 list 命令
|
|
452
|
+
if (command === 'list' || command === 'ls') {
|
|
453
|
+
listGenerators();
|
|
454
|
+
process.exit(0);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// 处理 doctor 命令
|
|
458
|
+
if (command === 'doctor') {
|
|
459
|
+
const success = await runDoctor();
|
|
460
|
+
process.exit(success ? 0 : 1);
|
|
461
|
+
}
|
|
462
|
+
|
|
262
463
|
// 处理 update 命令
|
|
263
464
|
if (command === 'update') {
|
|
264
465
|
const updateInfo = await checkForUpdate();
|
|
@@ -280,8 +481,8 @@ async function main() {
|
|
|
280
481
|
process.exit(1);
|
|
281
482
|
}
|
|
282
483
|
|
|
283
|
-
//
|
|
284
|
-
if (!skipUpdateCheck) {
|
|
484
|
+
// 检查更新(除非跳过或 dry-run)
|
|
485
|
+
if (!skipUpdateCheck && !isDryRun) {
|
|
285
486
|
const updateInfo = await checkForUpdate();
|
|
286
487
|
if (updateInfo && updateInfo.hasUpdate) {
|
|
287
488
|
const shouldUpdate = await askForUpdate(
|
|
@@ -300,7 +501,11 @@ async function main() {
|
|
|
300
501
|
}
|
|
301
502
|
|
|
302
503
|
// 运行生成器
|
|
303
|
-
runGenerator(generator,
|
|
504
|
+
await runGenerator(generator, {
|
|
505
|
+
verbose: isVerbose,
|
|
506
|
+
dryRun: isDryRun,
|
|
507
|
+
force: isForce
|
|
508
|
+
});
|
|
304
509
|
return;
|
|
305
510
|
}
|
|
306
511
|
|