@moluoxixi/create-app 2.0.413 → 2.0.415
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 +57 -1
- package/dist/commands/create.js +1 -1
- package/dist/core/feature.d.ts +80 -0
- package/dist/core/feature.js +252 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +6 -0
- package/dist/core/prompts.d.ts +17 -0
- package/dist/core/prompts.js +235 -0
- package/dist/core/template.d.ts +22 -0
- package/dist/core/template.js +177 -0
- package/dist/generators/index.d.ts +0 -2
- package/dist/generators/index.js +0 -2
- package/dist/generators/project.d.ts +1 -0
- package/dist/generators/project.js +66 -13
- package/dist/generators/react.d.ts +5 -5
- package/dist/generators/react.js +6 -9
- package/dist/generators/vue.d.ts +5 -5
- package/dist/generators/vue.js +6 -9
- package/dist/test.d.ts +0 -4
- package/dist/test.js +32 -17
- package/dist/types/index.d.ts +25 -26
- package/dist/types/index.js +2 -3
- package/dist/utils/featureMapping.js +6 -3
- package/dist/utils/generateFrameworkProject.d.ts +10 -20
- package/dist/utils/generateFrameworkProject.js +32 -127
- package/dist/utils/index.d.ts +1 -6
- package/dist/utils/index.js +1 -6
- package/dist/utils/prompts.js +7 -3
- package/package.json +3 -9
- package/templates/common/base/package.json +3 -1
- package/templates/common/base/vite/index.ts +53 -0
- package/templates/common/base/vite.config.ts +56 -0
- package/templates/common/features/husky/node_modules/.bin/tsc +17 -0
- package/templates/common/features/husky/node_modules/.bin/tsc.CMD +12 -0
- package/templates/common/features/husky/node_modules/.bin/tsc.ps1 +41 -0
- package/templates/common/features/husky/node_modules/.bin/tsserver +17 -0
- package/templates/common/features/husky/node_modules/.bin/tsserver.CMD +12 -0
- package/templates/common/features/husky/node_modules/.bin/tsserver.ps1 +41 -0
- package/templates/react/base/src/main/index.ts +34 -0
- package/templates/react/base/src/main.tsx +34 -0
- package/templates/react/base/tsconfig.app.json +1 -0
- package/templates/react/base/tsconfig.node.json +1 -0
- package/templates/react/features/ant-design/package.json +2 -1
- package/templates/react/features/ant-design/src/main/features/ant-design.ts +21 -0
- package/templates/react/features/i18n/package.json +2 -1
- package/templates/react/features/i18n/src/main/features/i18n.ts +19 -0
- package/templates/react/features/manualRoutes/package.json +1 -0
- package/templates/react/features/sentry/package.json +2 -1
- package/templates/react/features/sentry/src/main/features/sentry.ts +20 -0
- package/templates/react/features/sentry/vite/features/sentry.ts +39 -0
- package/templates/react/features/zustand/src/apis/types/user.ts +39 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/browserslist +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/browserslist.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/browserslist.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/jiti +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/jiti.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/jiti.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/parser +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/parser.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/parser.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/rollup +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/rollup.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/rollup.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/sass +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/sass.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/sass.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/terser +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/terser.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/terser.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsc +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsc.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsc.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsserver +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsserver.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsserver.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsx +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsx.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/tsx.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/vite +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/vite.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/vite.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/yaml +17 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/yaml.CMD +12 -0
- package/templates/react/micro-frontends/qiankun/base/node_modules/.bin/yaml.ps1 +41 -0
- package/templates/react/micro-frontends/qiankun/base/package.json +7 -2
- package/templates/react/micro-frontends/qiankun/base/src/main/index.ts +34 -0
- package/templates/react/micro-frontends/qiankun/base/src/{main.tsx.ejs → main.tsx} +13 -27
- package/templates/react/micro-frontends/qiankun/base/vite/index.ts +53 -0
- package/templates/react/micro-frontends/qiankun/base/vite.config.ts +58 -0
- package/templates/vue/base/src/main/index.ts +36 -0
- package/templates/vue/base/src/main.ts +34 -0
- package/templates/vue/base/tsconfig.app.json +2 -1
- package/templates/vue/base/tsconfig.node.json +2 -1
- package/templates/vue/features/ant-design-vue/package.json +3 -1
- package/templates/vue/features/ant-design-vue/src/main/features/ant-design-vue.ts +18 -0
- package/templates/vue/features/element-plus/package.json +5 -1
- package/templates/vue/features/element-plus/src/main/features/element-plus.ts +23 -0
- package/templates/vue/features/element-plus/src/stores/index.ts +6 -0
- package/templates/vue/features/element-plus/src/stores/modules/system.ts +51 -0
- package/templates/vue/features/element-plus/vite/features/element-plus.ts +35 -0
- package/templates/vue/features/i18n/package.json +3 -1
- package/templates/vue/features/i18n/src/main/features/i18n.ts +19 -0
- package/templates/vue/features/manualRoutes/package.json +7 -1
- package/templates/vue/features/manualRoutes/src/layouts/index.ts +26 -0
- package/templates/vue/features/manualRoutes/src/stores/index.ts +6 -0
- package/templates/vue/features/manualRoutes/src/stores/modules/system.ts +51 -0
- package/templates/vue/features/pageRoutes/package.json +7 -1
- package/templates/vue/features/pageRoutes/src/layouts/index.ts +26 -0
- package/templates/vue/features/pageRoutes/src/stores/index.ts +6 -0
- package/templates/vue/features/pageRoutes/src/stores/modules/system.ts +51 -0
- package/templates/vue/features/pinia/package.json +3 -1
- package/templates/vue/features/pinia/src/main/features/pinia.ts +19 -0
- package/templates/vue/features/sentry/package.json +4 -2
- package/templates/vue/features/sentry/src/main/features/sentry.ts +22 -0
- package/templates/vue/features/sentry/vite/features/sentry.ts +39 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/browserslist +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/browserslist.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/browserslist.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/jiti +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/jiti.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/jiti.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/parser +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/parser.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/parser.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/rollup +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/rollup.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/rollup.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/sass +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/sass.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/sass.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/terser +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/terser.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/terser.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsc +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsc.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsc.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsserver +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsserver.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsserver.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsx +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsx.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/tsx.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/vite +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/vite.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/vite.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/yaml +17 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/yaml.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/base/node_modules/.bin/yaml.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/base/package.json +7 -2
- package/templates/vue/micro-frontends/qiankun/base/src/main/index.ts +36 -0
- package/templates/vue/micro-frontends/qiankun/base/src/{main.ts.ejs → main.ts} +11 -28
- package/templates/vue/micro-frontends/qiankun/base/vite/index.ts +53 -0
- package/templates/vue/micro-frontends/qiankun/base/vite.config.ts +59 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/jiti +17 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/jiti.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/jiti.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/sass +17 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/sass.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/sass.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/terser +17 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/terser.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/terser.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsc +17 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsc.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsc.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsserver +17 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsserver.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsserver.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsx +17 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsx.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/tsx.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/vite +17 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/vite.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/vite.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/yaml +17 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/yaml.CMD +12 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/node_modules/.bin/yaml.ps1 +41 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/package.json +10 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/components/SubMenu/index.ts +8 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/components/SubMenu/src/_types/index.ts +1 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/components/SubMenu/src/_types/props.ts +16 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/components/SubMenu/src/index.vue +60 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/main/features/element-plus.ts +24 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/stores/index.ts +6 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/src/stores/modules/system.ts +51 -0
- package/templates/vue/micro-frontends/qiankun/features/element-plus/vite/features/element-plus.ts +35 -0
- package/templates/vue/micro-frontends/qiankun/features/manualRoutes/package.json +6 -1
- package/templates/vue/micro-frontends/qiankun/features/pageRoutes/package.json +6 -1
- package/templates/common/base/vite.config.ts.ejs +0 -85
- package/templates/react/base/src/main.tsx.ejs +0 -56
- package/templates/react/micro-frontends/qiankun/base/vite.config.ts.ejs +0 -89
- package/templates/vue/base/src/main.ts.ejs +0 -61
- package/templates/vue/micro-frontends/qiankun/base/vite.config.ts.ejs +0 -89
package/README.md
CHANGED
|
@@ -50,7 +50,63 @@ npm create @moluoxixi/app
|
|
|
50
50
|
| `@moluoxixi/class-names` | CSS 类名工具 |
|
|
51
51
|
| `@moluoxixi/css-module-global-root-plugin` | CSS Module 插件 |
|
|
52
52
|
|
|
53
|
-
##
|
|
53
|
+
## 源码目录结构
|
|
54
|
+
|
|
55
|
+
本项目采用清晰的模块化架构,将业务逻辑和工具函数分离:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
src/
|
|
59
|
+
├── commands/ # CLI 命令
|
|
60
|
+
│ ├── index.ts # 命令导出
|
|
61
|
+
│ └── create.ts # create 命令实现
|
|
62
|
+
│
|
|
63
|
+
├── constants/ # 常量定义
|
|
64
|
+
│ └── index.ts # 文件常量、路径常量等
|
|
65
|
+
│
|
|
66
|
+
├── core/ # 核心业务逻辑模块
|
|
67
|
+
│ ├── index.ts # 核心模块导出
|
|
68
|
+
│ ├── feature.ts # Feature 管理(扫描、映射、渲染)
|
|
69
|
+
│ ├── prompts.ts # 交互式问答(收集用户配置)
|
|
70
|
+
│ └── template.ts # 模板渲染(文件复制、合并)
|
|
71
|
+
│
|
|
72
|
+
├── generators/ # 项目生成器
|
|
73
|
+
│ ├── index.ts # 生成器导出
|
|
74
|
+
│ └── project.ts # 项目生成核心逻辑
|
|
75
|
+
│
|
|
76
|
+
├── types/ # TypeScript 类型定义
|
|
77
|
+
│ ├── index.ts # 公共类型导出
|
|
78
|
+
│ ├── features.ts # Feature 相关类型
|
|
79
|
+
│ └── packageJson.ts # package.json 类型
|
|
80
|
+
│
|
|
81
|
+
├── utils/ # 纯工具函数(无业务逻辑)
|
|
82
|
+
│ ├── index.ts # 工具函数导出
|
|
83
|
+
│ ├── deepMerge.ts # 深度合并对象
|
|
84
|
+
│ ├── file.ts # 文件操作(读写、复制、路径处理)
|
|
85
|
+
│ ├── install.ts # 依赖安装、Git 初始化
|
|
86
|
+
│ ├── npmConfig.ts # npm 配置读取
|
|
87
|
+
│ └── sortDependencies.ts # 依赖排序
|
|
88
|
+
│
|
|
89
|
+
├── index.ts # CLI 入口
|
|
90
|
+
└── test.ts # 测试脚本
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 目录职责说明
|
|
94
|
+
|
|
95
|
+
- **`commands/`** - CLI 命令实现,处理用户交互和流程控制
|
|
96
|
+
- **`core/`** - 核心业务逻辑,包含 feature 管理、模板渲染、用户配置收集
|
|
97
|
+
- **`generators/`** - 项目生成器,根据配置生成完整的项目结构
|
|
98
|
+
- **`utils/`** - 纯工具函数,不包含业务逻辑,可独立使用
|
|
99
|
+
- **`types/`** - TypeScript 类型定义,确保类型安全
|
|
100
|
+
- **`constants/`** - 常量定义,集中管理配置值
|
|
101
|
+
|
|
102
|
+
### 设计原则
|
|
103
|
+
|
|
104
|
+
1. **职责分离** - 业务逻辑在 `core/`,工具函数在 `utils/`
|
|
105
|
+
2. **模块化** - 每个模块职责单一,便于维护和测试
|
|
106
|
+
3. **类型安全** - 完整的 TypeScript 类型定义
|
|
107
|
+
4. **可扩展性** - 通过文件系统扫描自动发现 features,无需手动配置
|
|
108
|
+
|
|
109
|
+
## 生成的项目结构
|
|
54
110
|
|
|
55
111
|
生成的项目结构示例:
|
|
56
112
|
|
package/dist/commands/create.js
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
import process from 'node:process';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
import ora from 'ora';
|
|
8
|
+
import { collectProjectConfig, confirmOverwrite } from "../core/prompts.js";
|
|
8
9
|
import { generateProject } from "../generators/project.js";
|
|
9
10
|
import { pathExists } from "../utils/file.js";
|
|
10
11
|
import { initGit, installDependencies } from "../utils/install.js";
|
|
11
|
-
import { collectProjectConfig, confirmOverwrite } from "../utils/prompts.js";
|
|
12
12
|
/**
|
|
13
13
|
* 创建项目
|
|
14
14
|
* @param projectName 项目名称(可选)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 核心模块
|
|
3
|
+
* 统一管理 features 的扫描、映射、渲染逻辑
|
|
4
|
+
*/
|
|
5
|
+
import type { FrameworkType, ProjectConfigType, RouteModeType } from '../types/index.ts';
|
|
6
|
+
/**
|
|
7
|
+
* 扫描所有 features(框架的 + 公共的)
|
|
8
|
+
* @param framework 框架类型
|
|
9
|
+
* @returns 所有 feature 名称数组(UI 库按优先级排序)
|
|
10
|
+
*/
|
|
11
|
+
export declare function scanAllFeatures(framework: FrameworkType): string[];
|
|
12
|
+
/**
|
|
13
|
+
* Feature 名称转换为配置键和值(用于测试用例生成)
|
|
14
|
+
* 注意:大部分情况下 feature 名称 === 配置名称
|
|
15
|
+
* @param feature feature 名称
|
|
16
|
+
* @param _framework 框架类型(保留参数以保持接口兼容性)
|
|
17
|
+
* @returns 配置键值对,如果无法映射则返回 null
|
|
18
|
+
*/
|
|
19
|
+
export declare function featureToConfig(feature: string, _framework: FrameworkType): {
|
|
20
|
+
key: string;
|
|
21
|
+
value: string | boolean;
|
|
22
|
+
} | null;
|
|
23
|
+
/**
|
|
24
|
+
* 根据路由模式获取对应的布尔特征配置
|
|
25
|
+
* @param routeMode 路由模式('pageRoutes' | 'manualRoutes')
|
|
26
|
+
* @returns 包含 manualRoutes 和 pageRoutes 布尔值的对象
|
|
27
|
+
*/
|
|
28
|
+
export declare function getRouteModeFeatures(routeMode: RouteModeType): {
|
|
29
|
+
manualRoutes: boolean;
|
|
30
|
+
pageRoutes: boolean;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* 渲染框架特定的 features
|
|
34
|
+
* 通过文件系统扫描自动发现并渲染 features
|
|
35
|
+
* @param config 项目配置
|
|
36
|
+
* @param targetDir 目标目录
|
|
37
|
+
* @throws {Error} 如果路径不安全或模板渲染失败
|
|
38
|
+
*/
|
|
39
|
+
export declare function renderFrameworkFeatures(config: ProjectConfigType, targetDir: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* 渲染公共 features
|
|
42
|
+
* 通过文件系统扫描自动发现并渲染公共 features
|
|
43
|
+
* @param config 项目配置
|
|
44
|
+
* @param targetDir 目标目录
|
|
45
|
+
* @throws {Error} 如果路径不安全或模板渲染失败
|
|
46
|
+
*/
|
|
47
|
+
export declare function renderCommonFeatures(config: ProjectConfigType, targetDir: string): void;
|
|
48
|
+
/**
|
|
49
|
+
* 渲染微前端专属的 features(覆盖标准 features)
|
|
50
|
+
* 只渲染文件系统中存在的微前端 features,实现按需覆盖
|
|
51
|
+
* @param config 项目配置
|
|
52
|
+
* @param targetDir 目标目录
|
|
53
|
+
* @param microFrontendEngine 微前端引擎类型
|
|
54
|
+
* @throws {Error} 如果路径不安全或模板渲染失败
|
|
55
|
+
*/
|
|
56
|
+
export declare function renderMicroFrontendFeatures(config: ProjectConfigType, targetDir: string, microFrontendEngine: string): void;
|
|
57
|
+
/**
|
|
58
|
+
* 验证微前端引擎是否存在
|
|
59
|
+
* @param framework 框架类型
|
|
60
|
+
* @param engine 微前端引擎名称
|
|
61
|
+
* @returns 引擎是否存在
|
|
62
|
+
*/
|
|
63
|
+
export declare function validateMicroFrontendEngine(framework: FrameworkType, engine: string): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 获取可用的公共 features(用于测试和文档生成)
|
|
66
|
+
* @returns 公共 feature 名称数组
|
|
67
|
+
*/
|
|
68
|
+
export declare function getAvailableCommonFeatures(): string[];
|
|
69
|
+
/**
|
|
70
|
+
* 获取可用的框架 features(用于测试和文档生成)
|
|
71
|
+
* @param framework 框架类型
|
|
72
|
+
* @returns 框架 feature 名称数组
|
|
73
|
+
*/
|
|
74
|
+
export declare function getAvailableFrameworkFeatures(framework: FrameworkType): string[];
|
|
75
|
+
/**
|
|
76
|
+
* 获取可用的微前端引擎(用于测试和文档生成)
|
|
77
|
+
* @param framework 框架类型
|
|
78
|
+
* @returns 微前端引擎名称数组
|
|
79
|
+
*/
|
|
80
|
+
export declare function getAvailableMicroFrontendEngines(framework: FrameworkType): string[];
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature 核心模块
|
|
3
|
+
* 统一管理 features 的扫描、映射、渲染逻辑
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { getTemplatesDir } from "../utils/file.js";
|
|
8
|
+
import { renderTemplate } from "./template.js";
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Feature 扫描
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* 扫描指定目录下的所有 feature 目录
|
|
14
|
+
* @param baseDir 基础目录
|
|
15
|
+
* @returns feature 名称数组
|
|
16
|
+
*/
|
|
17
|
+
function scanFeatures(baseDir) {
|
|
18
|
+
if (!fs.existsSync(baseDir)) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
return fs.readdirSync(baseDir).filter((item) => {
|
|
22
|
+
const itemPath = path.join(baseDir, item);
|
|
23
|
+
return fs.statSync(itemPath).isDirectory();
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 获取公共 features 列表(从文件系统扫描)
|
|
28
|
+
* @returns 公共 feature 名称数组
|
|
29
|
+
*/
|
|
30
|
+
function getCommonFeatures() {
|
|
31
|
+
const templatesDir = getTemplatesDir();
|
|
32
|
+
const commonFeaturesDir = path.join(templatesDir, 'common', 'features');
|
|
33
|
+
return scanFeatures(commonFeaturesDir);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 获取框架 features 列表(从文件系统扫描)
|
|
37
|
+
* @param framework 框架类型
|
|
38
|
+
* @returns 框架 feature 名称数组
|
|
39
|
+
*/
|
|
40
|
+
function getFrameworkFeatures(framework) {
|
|
41
|
+
const templatesDir = getTemplatesDir();
|
|
42
|
+
const frameworkFeaturesDir = path.join(templatesDir, framework, 'features');
|
|
43
|
+
return scanFeatures(frameworkFeaturesDir);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 获取微前端引擎列表(从文件系统扫描)
|
|
47
|
+
* @param framework 框架类型
|
|
48
|
+
* @returns 微前端引擎名称数组
|
|
49
|
+
*/
|
|
50
|
+
function getMicroFrontendEngines(framework) {
|
|
51
|
+
const templatesDir = getTemplatesDir();
|
|
52
|
+
const microFrontendsDir = path.join(templatesDir, framework, 'micro-frontends');
|
|
53
|
+
return scanFeatures(microFrontendsDir);
|
|
54
|
+
}
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Feature 映射(用于测试用例生成)
|
|
57
|
+
// ============================================================================
|
|
58
|
+
/**
|
|
59
|
+
* UI 库优先级顺序(用于排序,确保默认选择)
|
|
60
|
+
* TODO: ant-design-vue 和 ant-design (React) 功能暂时关闭
|
|
61
|
+
*/
|
|
62
|
+
const UI_LIBRARY_PRIORITY = {
|
|
63
|
+
'element-plus': 1,
|
|
64
|
+
// 'ant-design-vue': 2, // TODO: 暂时关闭
|
|
65
|
+
// 'ant-design': 1, // TODO: 暂时关闭 (React)
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* 扫描所有 features(框架的 + 公共的)
|
|
69
|
+
* @param framework 框架类型
|
|
70
|
+
* @returns 所有 feature 名称数组(UI 库按优先级排序)
|
|
71
|
+
*/
|
|
72
|
+
export function scanAllFeatures(framework) {
|
|
73
|
+
const frameworkDir = path.join(getTemplatesDir(), framework, 'features');
|
|
74
|
+
const commonDir = path.join(getTemplatesDir(), 'common', 'features');
|
|
75
|
+
const features = [];
|
|
76
|
+
if (fs.existsSync(frameworkDir)) {
|
|
77
|
+
features.push(...fs.readdirSync(frameworkDir).filter(f => fs.statSync(path.join(frameworkDir, f)).isDirectory()));
|
|
78
|
+
}
|
|
79
|
+
if (fs.existsSync(commonDir)) {
|
|
80
|
+
features.push(...fs.readdirSync(commonDir).filter(f => fs.statSync(path.join(commonDir, f)).isDirectory()));
|
|
81
|
+
}
|
|
82
|
+
// 对 UI 库进行排序,确保 element-plus 优先(优先级数字越小越靠前)
|
|
83
|
+
return features.sort((a, b) => {
|
|
84
|
+
const priorityA = UI_LIBRARY_PRIORITY[a] ?? 999;
|
|
85
|
+
const priorityB = UI_LIBRARY_PRIORITY[b] ?? 999;
|
|
86
|
+
if (priorityA !== priorityB) {
|
|
87
|
+
return priorityA - priorityB;
|
|
88
|
+
}
|
|
89
|
+
// 相同优先级时保持字母顺序
|
|
90
|
+
return a.localeCompare(b);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Feature 名称转换为配置键和值(用于测试用例生成)
|
|
95
|
+
* 注意:大部分情况下 feature 名称 === 配置名称
|
|
96
|
+
* @param feature feature 名称
|
|
97
|
+
* @param _framework 框架类型(保留参数以保持接口兼容性)
|
|
98
|
+
* @returns 配置键值对,如果无法映射则返回 null
|
|
99
|
+
*/
|
|
100
|
+
export function featureToConfig(feature, _framework) {
|
|
101
|
+
// UI 库:配置键是 uiLibrary,值是 feature 名称
|
|
102
|
+
// TODO: ant-design-vue 和 ant-design (React) 功能暂时关闭
|
|
103
|
+
// const uiLibraries = ['element-plus', 'ant-design-vue', 'ant-design']
|
|
104
|
+
const uiLibraries = ['element-plus'];
|
|
105
|
+
if (uiLibraries.includes(feature)) {
|
|
106
|
+
return { key: 'uiLibrary', value: feature };
|
|
107
|
+
}
|
|
108
|
+
// 路由模式 features:用于测试分类
|
|
109
|
+
if (feature === 'manualRoutes' || feature === 'pageRoutes') {
|
|
110
|
+
return { key: 'routeMode', value: feature };
|
|
111
|
+
}
|
|
112
|
+
// 布尔类型的 features:配置名 === feature 名
|
|
113
|
+
const booleanFeatures = [
|
|
114
|
+
'eslint',
|
|
115
|
+
'i18n',
|
|
116
|
+
'sentry',
|
|
117
|
+
'pinia',
|
|
118
|
+
'zustand',
|
|
119
|
+
'husky',
|
|
120
|
+
];
|
|
121
|
+
if (booleanFeatures.includes(feature)) {
|
|
122
|
+
return { key: feature, value: true };
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
// ============================================================================
|
|
127
|
+
// 路由模式转换
|
|
128
|
+
// ============================================================================
|
|
129
|
+
/**
|
|
130
|
+
* 根据路由模式获取对应的布尔特征配置
|
|
131
|
+
* @param routeMode 路由模式('pageRoutes' | 'manualRoutes')
|
|
132
|
+
* @returns 包含 manualRoutes 和 pageRoutes 布尔值的对象
|
|
133
|
+
*/
|
|
134
|
+
export function getRouteModeFeatures(routeMode) {
|
|
135
|
+
return {
|
|
136
|
+
manualRoutes: routeMode === 'manualRoutes',
|
|
137
|
+
pageRoutes: routeMode === 'pageRoutes',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// Feature 渲染
|
|
142
|
+
// ============================================================================
|
|
143
|
+
/**
|
|
144
|
+
* 渲染框架特定的 features
|
|
145
|
+
* 通过文件系统扫描自动发现并渲染 features
|
|
146
|
+
* @param config 项目配置
|
|
147
|
+
* @param targetDir 目标目录
|
|
148
|
+
* @throws {Error} 如果路径不安全或模板渲染失败
|
|
149
|
+
*/
|
|
150
|
+
export function renderFrameworkFeatures(config, targetDir) {
|
|
151
|
+
const templatesDir = getTemplatesDir();
|
|
152
|
+
const { framework, uiLibrary } = config;
|
|
153
|
+
// 从文件系统扫描获取所有框架 features
|
|
154
|
+
const availableFeatures = getFrameworkFeatures(framework);
|
|
155
|
+
// 遍历配置对象,渲染所有值为 true 且存在于文件系统的 features
|
|
156
|
+
for (const [key, value] of Object.entries(config)) {
|
|
157
|
+
// 如果配置值为 true 且 feature 目录存在,则渲染
|
|
158
|
+
if (value === true && availableFeatures.includes(key)) {
|
|
159
|
+
const featurePath = path.join(templatesDir, framework, 'features', key);
|
|
160
|
+
renderTemplate(featurePath, targetDir);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// UI 库单独处理(配置值 === feature 目录名)
|
|
164
|
+
if (uiLibrary && availableFeatures.includes(uiLibrary)) {
|
|
165
|
+
renderTemplate(path.join(templatesDir, framework, 'features', uiLibrary), targetDir);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* 渲染公共 features
|
|
170
|
+
* 通过文件系统扫描自动发现并渲染公共 features
|
|
171
|
+
* @param config 项目配置
|
|
172
|
+
* @param targetDir 目标目录
|
|
173
|
+
* @throws {Error} 如果路径不安全或模板渲染失败
|
|
174
|
+
*/
|
|
175
|
+
export function renderCommonFeatures(config, targetDir) {
|
|
176
|
+
const templatesDir = getTemplatesDir();
|
|
177
|
+
// 从文件系统扫描获取所有公共 features
|
|
178
|
+
const availableFeatures = getCommonFeatures();
|
|
179
|
+
// 遍历配置对象,渲染所有值为 true 且存在于文件系统的公共 features
|
|
180
|
+
for (const [key, value] of Object.entries(config)) {
|
|
181
|
+
if (value === true && availableFeatures.includes(key)) {
|
|
182
|
+
const featurePath = path.join(templatesDir, 'common', 'features', key);
|
|
183
|
+
renderTemplate(featurePath, targetDir);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 渲染微前端专属的 features(覆盖标准 features)
|
|
189
|
+
* 只渲染文件系统中存在的微前端 features,实现按需覆盖
|
|
190
|
+
* @param config 项目配置
|
|
191
|
+
* @param targetDir 目标目录
|
|
192
|
+
* @param microFrontendEngine 微前端引擎类型
|
|
193
|
+
* @throws {Error} 如果路径不安全或模板渲染失败
|
|
194
|
+
*/
|
|
195
|
+
export function renderMicroFrontendFeatures(config, targetDir, microFrontendEngine) {
|
|
196
|
+
const templatesDir = getTemplatesDir();
|
|
197
|
+
const { framework, uiLibrary } = config;
|
|
198
|
+
const microFrontendFeaturesPath = path.join(templatesDir, framework, 'micro-frontends', microFrontendEngine, 'features');
|
|
199
|
+
// 如果微前端 features 目录不存在,直接返回
|
|
200
|
+
if (!fs.existsSync(microFrontendFeaturesPath)) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
// 扫描微前端 features 目录
|
|
204
|
+
const availableMicroFrontendFeatures = scanFeatures(microFrontendFeaturesPath);
|
|
205
|
+
// 遍历配置对象,渲染所有值为 true 且存在于微前端 features 的 features
|
|
206
|
+
for (const [key, value] of Object.entries(config)) {
|
|
207
|
+
if (value === true && availableMicroFrontendFeatures.includes(key)) {
|
|
208
|
+
const featurePath = path.join(microFrontendFeaturesPath, key);
|
|
209
|
+
renderTemplate(featurePath, targetDir);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// UI 库单独处理(如果微前端有 UI 库专属的覆盖)
|
|
213
|
+
if (uiLibrary && availableMicroFrontendFeatures.includes(uiLibrary)) {
|
|
214
|
+
renderTemplate(path.join(microFrontendFeaturesPath, uiLibrary), targetDir);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// ============================================================================
|
|
218
|
+
// 公共 API(用于测试和文档生成)
|
|
219
|
+
// ============================================================================
|
|
220
|
+
/**
|
|
221
|
+
* 验证微前端引擎是否存在
|
|
222
|
+
* @param framework 框架类型
|
|
223
|
+
* @param engine 微前端引擎名称
|
|
224
|
+
* @returns 引擎是否存在
|
|
225
|
+
*/
|
|
226
|
+
export function validateMicroFrontendEngine(framework, engine) {
|
|
227
|
+
const availableEngines = getMicroFrontendEngines(framework);
|
|
228
|
+
return availableEngines.includes(engine);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 获取可用的公共 features(用于测试和文档生成)
|
|
232
|
+
* @returns 公共 feature 名称数组
|
|
233
|
+
*/
|
|
234
|
+
export function getAvailableCommonFeatures() {
|
|
235
|
+
return getCommonFeatures();
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* 获取可用的框架 features(用于测试和文档生成)
|
|
239
|
+
* @param framework 框架类型
|
|
240
|
+
* @returns 框架 feature 名称数组
|
|
241
|
+
*/
|
|
242
|
+
export function getAvailableFrameworkFeatures(framework) {
|
|
243
|
+
return getFrameworkFeatures(framework);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* 获取可用的微前端引擎(用于测试和文档生成)
|
|
247
|
+
* @param framework 框架类型
|
|
248
|
+
* @returns 微前端引擎名称数组
|
|
249
|
+
*/
|
|
250
|
+
export function getAvailableMicroFrontendEngines(framework) {
|
|
251
|
+
return getMicroFrontendEngines(framework);
|
|
252
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互式问答模块
|
|
3
|
+
* 收集用户的项目配置信息(对标 create-vue)
|
|
4
|
+
*/
|
|
5
|
+
import type { ProjectConfigType } from '../types/index.ts';
|
|
6
|
+
/**
|
|
7
|
+
* 收集项目配置信息
|
|
8
|
+
* @param projectName 项目名称(可选)
|
|
9
|
+
* @returns 项目配置对象
|
|
10
|
+
*/
|
|
11
|
+
export declare function collectProjectConfig(projectName?: string): Promise<ProjectConfigType>;
|
|
12
|
+
/**
|
|
13
|
+
* 确认覆盖目录
|
|
14
|
+
* @param dirPath 目录路径
|
|
15
|
+
* @returns 是否确认覆盖
|
|
16
|
+
*/
|
|
17
|
+
export declare function confirmOverwrite(dirPath: string): Promise<boolean>;
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互式问答模块
|
|
3
|
+
* 收集用户的项目配置信息(对标 create-vue)
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import process from 'node:process';
|
|
7
|
+
import inquirer from 'inquirer';
|
|
8
|
+
import { getDefaultAuthor } from "../utils/npmConfig.js";
|
|
9
|
+
import { getRouteModeFeatures } from "./feature.js";
|
|
10
|
+
/**
|
|
11
|
+
* 收集项目配置信息
|
|
12
|
+
* @param projectName 项目名称(可选)
|
|
13
|
+
* @returns 项目配置对象
|
|
14
|
+
*/
|
|
15
|
+
export async function collectProjectConfig(projectName) {
|
|
16
|
+
// 获取默认作者信息
|
|
17
|
+
const defaultAuthor = getDefaultAuthor();
|
|
18
|
+
const answers = await inquirer.prompt([
|
|
19
|
+
// 项目名称
|
|
20
|
+
{
|
|
21
|
+
type: 'input',
|
|
22
|
+
name: 'projectName',
|
|
23
|
+
message: '项目名称:',
|
|
24
|
+
default: projectName || 'my-project',
|
|
25
|
+
validate: (input) => {
|
|
26
|
+
const trimmed = input.trim();
|
|
27
|
+
if (!trimmed) {
|
|
28
|
+
return '项目名称不能为空';
|
|
29
|
+
}
|
|
30
|
+
const minLength = 1;
|
|
31
|
+
const maxLength = 214;
|
|
32
|
+
if (trimmed.length < minLength || trimmed.length > maxLength) {
|
|
33
|
+
return `项目名称长度必须在 ${minLength}-${maxLength} 个字符之间`;
|
|
34
|
+
}
|
|
35
|
+
if (!/^[\w-]+$/.test(trimmed)) {
|
|
36
|
+
return '项目名称只能包含字母、数字、连字符和下划线';
|
|
37
|
+
}
|
|
38
|
+
const reservedNames = [
|
|
39
|
+
'node',
|
|
40
|
+
'npm',
|
|
41
|
+
'test',
|
|
42
|
+
'lib',
|
|
43
|
+
'api',
|
|
44
|
+
'www',
|
|
45
|
+
'admin',
|
|
46
|
+
'root',
|
|
47
|
+
'config',
|
|
48
|
+
'build',
|
|
49
|
+
'dist',
|
|
50
|
+
'src',
|
|
51
|
+
'public',
|
|
52
|
+
'private',
|
|
53
|
+
];
|
|
54
|
+
if (reservedNames.includes(trimmed.toLowerCase())) {
|
|
55
|
+
return `项目名称不能使用保留名称: ${trimmed}`;
|
|
56
|
+
}
|
|
57
|
+
// 检查目标目录是否已存在且不为空
|
|
58
|
+
const targetDir = `${process.cwd()}/${trimmed}`;
|
|
59
|
+
if (fs.existsSync(targetDir)) {
|
|
60
|
+
try {
|
|
61
|
+
const stats = fs.statSync(targetDir);
|
|
62
|
+
if (stats.isDirectory()) {
|
|
63
|
+
const files = fs.readdirSync(targetDir);
|
|
64
|
+
if (files.length > 0) {
|
|
65
|
+
return `目录 ${targetDir} 已存在且不为空,请选择其他名称或先清空该目录`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// 忽略检查错误,让后续流程处理
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return true;
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
// 项目描述
|
|
77
|
+
{
|
|
78
|
+
type: 'input',
|
|
79
|
+
name: 'description',
|
|
80
|
+
message: '项目描述:',
|
|
81
|
+
default: 'A Vite project',
|
|
82
|
+
},
|
|
83
|
+
// 作者
|
|
84
|
+
{
|
|
85
|
+
type: 'input',
|
|
86
|
+
name: 'author',
|
|
87
|
+
message: '作者:',
|
|
88
|
+
default: defaultAuthor,
|
|
89
|
+
},
|
|
90
|
+
// 框架选择
|
|
91
|
+
{
|
|
92
|
+
type: 'list',
|
|
93
|
+
name: 'framework',
|
|
94
|
+
message: '选择框架:',
|
|
95
|
+
choices: [
|
|
96
|
+
{ name: 'Vue 3', value: 'vue' },
|
|
97
|
+
// TODO: React 功能暂时关闭
|
|
98
|
+
// { name: 'React', value: 'react' },
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
// UI 库选择
|
|
102
|
+
{
|
|
103
|
+
type: 'list',
|
|
104
|
+
name: 'uiLibrary',
|
|
105
|
+
message: '选择 UI 组件库:',
|
|
106
|
+
choices: (answers) => {
|
|
107
|
+
if (answers.framework === 'vue') {
|
|
108
|
+
return [
|
|
109
|
+
{ name: 'Element Plus', value: 'element-plus' },
|
|
110
|
+
// TODO: Ant Design Vue 功能暂时关闭
|
|
111
|
+
// { name: 'Ant Design Vue', value: 'ant-design-vue' },
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// TODO: React 功能暂时关闭
|
|
116
|
+
// return [{ name: 'Ant Design', value: 'ant-design' }]
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
// 路由模式(路由已内置,只需选择模式)
|
|
122
|
+
{
|
|
123
|
+
type: 'list',
|
|
124
|
+
name: 'routeMode',
|
|
125
|
+
message: '选择路由模式:',
|
|
126
|
+
choices: [
|
|
127
|
+
{ name: '文件系统路由 (vite-plugin-pages)', value: 'pageRoutes' },
|
|
128
|
+
{ name: '手动配置路由', value: 'manualRoutes' },
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
// 是否启用国际化
|
|
132
|
+
{
|
|
133
|
+
type: 'confirm',
|
|
134
|
+
name: 'i18n',
|
|
135
|
+
message: '是否启用国际化 (i18n)?',
|
|
136
|
+
default: true,
|
|
137
|
+
},
|
|
138
|
+
// 是否启用微前端
|
|
139
|
+
{
|
|
140
|
+
type: 'confirm',
|
|
141
|
+
name: 'microFrontend',
|
|
142
|
+
message: '是否启用微前端支持?',
|
|
143
|
+
default: false,
|
|
144
|
+
},
|
|
145
|
+
// 微前端引擎选择
|
|
146
|
+
{
|
|
147
|
+
type: 'list',
|
|
148
|
+
name: 'microFrontendEngine',
|
|
149
|
+
message: '选择微前端引擎:',
|
|
150
|
+
choices: [
|
|
151
|
+
{ name: 'qiankun (阿里开源)', value: 'qiankun' },
|
|
152
|
+
// TODO: 还没有,后续可考虑接入
|
|
153
|
+
// { name: 'micro-app (京东开源)', value: 'micro-app' },
|
|
154
|
+
],
|
|
155
|
+
when: (answers) => answers.microFrontend === true,
|
|
156
|
+
},
|
|
157
|
+
// 是否启用错误监控
|
|
158
|
+
{
|
|
159
|
+
type: 'confirm',
|
|
160
|
+
name: 'sentry',
|
|
161
|
+
message: '是否启用错误监控 (Sentry)?',
|
|
162
|
+
default: false,
|
|
163
|
+
},
|
|
164
|
+
// 是否启用 ESLint
|
|
165
|
+
{
|
|
166
|
+
type: 'confirm',
|
|
167
|
+
name: 'eslint',
|
|
168
|
+
message: '是否启用 ESLint 代码规范检查?',
|
|
169
|
+
default: true,
|
|
170
|
+
},
|
|
171
|
+
// 是否启用 Git Hooks
|
|
172
|
+
{
|
|
173
|
+
type: 'confirm',
|
|
174
|
+
name: 'gitHooks',
|
|
175
|
+
message: '是否启用 Git Hooks (husky + commitlint)?',
|
|
176
|
+
default: true,
|
|
177
|
+
},
|
|
178
|
+
// 包管理器选择
|
|
179
|
+
{
|
|
180
|
+
type: 'list',
|
|
181
|
+
name: 'packageManager',
|
|
182
|
+
message: '选择包管理器:',
|
|
183
|
+
choices: [
|
|
184
|
+
{ name: 'pnpm (推荐)', value: 'pnpm' },
|
|
185
|
+
{ name: 'npm', value: 'npm' },
|
|
186
|
+
{ name: 'yarn', value: 'yarn' },
|
|
187
|
+
],
|
|
188
|
+
default: 'pnpm',
|
|
189
|
+
},
|
|
190
|
+
]);
|
|
191
|
+
const targetDir = `${process.cwd()}/${answers.projectName}`;
|
|
192
|
+
// 根据框架确定状态管理 feature
|
|
193
|
+
const isPinia = answers.framework === 'vue';
|
|
194
|
+
const isZustand = answers.framework === 'react';
|
|
195
|
+
// 根据路由模式获取对应的布尔特征配置
|
|
196
|
+
const routeMode = answers.routeMode;
|
|
197
|
+
const routeModeFeatures = getRouteModeFeatures(routeMode);
|
|
198
|
+
return {
|
|
199
|
+
projectName: answers.projectName,
|
|
200
|
+
description: answers.description,
|
|
201
|
+
author: answers.author,
|
|
202
|
+
framework: answers.framework,
|
|
203
|
+
uiLibrary: answers.uiLibrary,
|
|
204
|
+
routeMode,
|
|
205
|
+
// feature 名称与目录名称一致
|
|
206
|
+
pinia: isPinia,
|
|
207
|
+
zustand: isZustand,
|
|
208
|
+
manualRoutes: routeModeFeatures.manualRoutes,
|
|
209
|
+
pageRoutes: routeModeFeatures.pageRoutes,
|
|
210
|
+
i18n: answers.i18n,
|
|
211
|
+
microFrontend: answers.microFrontend || false,
|
|
212
|
+
microFrontendEngine: answers.microFrontendEngine,
|
|
213
|
+
sentry: answers.sentry,
|
|
214
|
+
eslint: answers.eslint,
|
|
215
|
+
husky: answers.gitHooks,
|
|
216
|
+
packageManager: answers.packageManager,
|
|
217
|
+
targetDir,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* 确认覆盖目录
|
|
222
|
+
* @param dirPath 目录路径
|
|
223
|
+
* @returns 是否确认覆盖
|
|
224
|
+
*/
|
|
225
|
+
export async function confirmOverwrite(dirPath) {
|
|
226
|
+
const { confirm } = await inquirer.prompt([
|
|
227
|
+
{
|
|
228
|
+
type: 'confirm',
|
|
229
|
+
name: 'confirm',
|
|
230
|
+
message: `目录 ${dirPath} 已存在,是否覆盖?`,
|
|
231
|
+
default: false,
|
|
232
|
+
},
|
|
233
|
+
]);
|
|
234
|
+
return confirm;
|
|
235
|
+
}
|