deps-conflict-resolver 1.0.0
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 +248 -0
- package/dist/config.types-CN7glPbA.d.cts +237 -0
- package/dist/config.types-CN7glPbA.d.ts +237 -0
- package/dist/index.cjs +2219 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +162 -0
- package/dist/index.d.ts +162 -0
- package/dist/index.js +2210 -0
- package/dist/index.js.map +1 -0
- package/dist/resolver-BjbDmC24.d.ts +67 -0
- package/dist/resolver-Dew5GU0y.d.cts +67 -0
- package/dist/vite.cjs +2376 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.cts +35 -0
- package/dist/vite.d.ts +35 -0
- package/dist/vite.js +2366 -0
- package/dist/vite.js.map +1 -0
- package/dist/webpack.cjs +2380 -0
- package/dist/webpack.cjs.map +1 -0
- package/dist/webpack.d.cts +58 -0
- package/dist/webpack.d.ts +58 -0
- package/dist/webpack.js +2370 -0
- package/dist/webpack.js.map +1 -0
- package/package.json +116 -0
package/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# deps-conflict-resolver
|
|
2
|
+
|
|
3
|
+
一个支持 Webpack 和 Vite 的插件,自动解析 peer 依赖冲突,通过创建别名来支持不同版本的依赖共存。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 🔍 **递归依赖分析**:深度分析依赖树中的所有子依赖、孙依赖
|
|
8
|
+
- 🎯 **智能冲突检测**:自动识别 peer 依赖与主工程的版本冲突
|
|
9
|
+
- 📦 **自动别名安装**:为冲突的依赖创建别名并自动安装合适的版本
|
|
10
|
+
- 🔄 **模块解析重定向**:在运行时自动将模块引用重定向到正确的别名版本
|
|
11
|
+
- 🌐 **远程版本查询**:从 npm 注册表获取版本列表,智能选择最佳版本
|
|
12
|
+
- ⚡ **支持 Webpack 和 Vite**:提供两种构建工具的插件实现
|
|
13
|
+
|
|
14
|
+
## 使用场景
|
|
15
|
+
|
|
16
|
+
典型场景:你的 Vue 3 项目需要使用一个仅支持 Vue 2 的第三方库。该库的依赖链中可能包含 Vue 2、vue-router 3 等低版本依赖。本插件可以:
|
|
17
|
+
|
|
18
|
+
1. 自动检测这些版本冲突
|
|
19
|
+
2. 为冲突的依赖(如 vue@2.x)创建别名(如 `aliased-vue2`)
|
|
20
|
+
3. 自动安装别名依赖
|
|
21
|
+
4. 在模块解析时自动重定向:第三方库中的 `import Vue from 'vue'` 会被解析到 `vue@2.x`,而你的主工程代码中的 `import Vue from 'vue'` 仍然解析到 `vue@3.x`
|
|
22
|
+
|
|
23
|
+
## 安装
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install deps-conflict-resolver --save-dev
|
|
27
|
+
# 或
|
|
28
|
+
yarn add deps-conflict-resolver -D
|
|
29
|
+
# 或
|
|
30
|
+
pnpm add deps-conflict-resolver -D
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 使用方法
|
|
34
|
+
|
|
35
|
+
### Vite
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// vite.config.ts
|
|
39
|
+
import { defineConfig } from 'vite';
|
|
40
|
+
import { depsConflictResolverVitePlugin } from 'deps-conflict-resolver/vite';
|
|
41
|
+
|
|
42
|
+
export default defineConfig({
|
|
43
|
+
plugins: [
|
|
44
|
+
depsConflictResolverVitePlugin({
|
|
45
|
+
// 需要分析的依赖包
|
|
46
|
+
dependencies: ['legacy-vue2-library'],
|
|
47
|
+
|
|
48
|
+
// 可选配置
|
|
49
|
+
autoInstall: true, // 自动安装缺失的别名依赖
|
|
50
|
+
packageManager: 'npm', // npm | yarn | pnpm
|
|
51
|
+
debug: false, // 开启调试日志
|
|
52
|
+
}),
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Webpack
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// webpack.config.js
|
|
61
|
+
const { DepsConflictResolverWebpackPlugin } = require('deps-conflict-resolver/webpack');
|
|
62
|
+
|
|
63
|
+
module.exports = {
|
|
64
|
+
plugins: [
|
|
65
|
+
new DepsConflictResolverWebpackPlugin({
|
|
66
|
+
dependencies: ['legacy-vue2-library'],
|
|
67
|
+
autoInstall: true,
|
|
68
|
+
packageManager: 'npm',
|
|
69
|
+
}),
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 编程式使用
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { createResolver } from 'deps-conflict-resolver';
|
|
78
|
+
|
|
79
|
+
const resolver = await createResolver({
|
|
80
|
+
dependencies: ['legacy-vue2-library'],
|
|
81
|
+
projectRoot: process.cwd(),
|
|
82
|
+
autoInstall: true,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// 获取分析结果
|
|
86
|
+
const result = resolver.getAnalysisResult();
|
|
87
|
+
console.log('Peer conflicts:', result.peerConflicts);
|
|
88
|
+
console.log('Alias mappings:', result.aliasMappings);
|
|
89
|
+
|
|
90
|
+
// 手动解析模块
|
|
91
|
+
const resolved = resolver.resolveModule('vue', '/path/to/importer.js');
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 配置选项
|
|
95
|
+
|
|
96
|
+
| 选项 | 类型 | 默认值 | 说明 |
|
|
97
|
+
| ---------------- | ------------------------------------- | --------------- | ------------------------------------------ |
|
|
98
|
+
| `dependencies` | `string[]` | - | **必填**,需要分析的依赖包名列表 |
|
|
99
|
+
| `projectRoot` | `string` | `process.cwd()` | 项目根目录路径 |
|
|
100
|
+
| `autoInstall` | `boolean` | `true` | 是否自动安装缺失的别名依赖 |
|
|
101
|
+
| `packageManager` | `'auto' \| 'npm' \| 'yarn' \| 'pnpm'` | `'auto'` | 包管理器类型,`'auto'` 自动检测 |
|
|
102
|
+
| `registry` | `string` | 自动检测 | NPM 注册表地址,不指定则自动从 .npmrc 读取 |
|
|
103
|
+
| `debug` | `boolean` | `false` | 是否启用调试日志 |
|
|
104
|
+
| `aliasPrefix` | `string` | `'aliased-'` | 别名前缀 |
|
|
105
|
+
|
|
106
|
+
### 自动检测
|
|
107
|
+
|
|
108
|
+
插件支持自动检测包管理器和 registry:
|
|
109
|
+
|
|
110
|
+
**包管理器检测优先级:**
|
|
111
|
+
|
|
112
|
+
1. `package.json` 中的 `packageManager` 字段(如 `"pnpm@8.0.0"`)
|
|
113
|
+
2. lock 文件存在性(`pnpm-lock.yaml` → pnpm, `yarn.lock` → yarn, `package-lock.json` → npm)
|
|
114
|
+
3. 默认使用 npm
|
|
115
|
+
|
|
116
|
+
**Registry 检测优先级:**
|
|
117
|
+
|
|
118
|
+
1. 项目级 `.npmrc` 文件
|
|
119
|
+
2. 用户级 `~/.npmrc` 文件
|
|
120
|
+
3. yarn 项目的 `.yarnrc.yml` 文件
|
|
121
|
+
4. 默认使用 `https://registry.npmjs.org`
|
|
122
|
+
|
|
123
|
+
## 工作原理
|
|
124
|
+
|
|
125
|
+
### 1. 依赖分析
|
|
126
|
+
|
|
127
|
+
插件会递归分析指定依赖的整个依赖树:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
package-a
|
|
131
|
+
├── package-b
|
|
132
|
+
│ └── package-c (peerDeps: vue@^2.0.0)
|
|
133
|
+
└── package-d (peerDeps: vue-router@^3.0.0)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 2. 冲突检测
|
|
137
|
+
|
|
138
|
+
对比主工程中已安装的版本与 peer 依赖要求:
|
|
139
|
+
|
|
140
|
+
- 主工程:`vue@3.2.0`, `vue-router@4.1.0`
|
|
141
|
+
- Peer 依赖要求:`vue@^2.0.0`, `vue-router@^3.0.0`
|
|
142
|
+
- 检测到冲突 ✗
|
|
143
|
+
|
|
144
|
+
### 3. 版本解析
|
|
145
|
+
|
|
146
|
+
从 npm 注册表获取可用版本列表,找到满足所有 peer 依赖范围的最佳版本:
|
|
147
|
+
|
|
148
|
+
- `vue@^2.0.0` → 选择 `vue@2.7.14`
|
|
149
|
+
- `vue-router@^3.0.0` → 选择 `vue-router@3.6.5`
|
|
150
|
+
|
|
151
|
+
### 4. 别名安装
|
|
152
|
+
|
|
153
|
+
创建并安装别名依赖:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
npm install aliased-vue2@npm:vue@2.7.14
|
|
157
|
+
npm install aliased-vue-router3@npm:vue-router@3.6.5
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 5. 模块解析重定向
|
|
161
|
+
|
|
162
|
+
在构建时,自动重定向模块引用:
|
|
163
|
+
|
|
164
|
+
```javascript
|
|
165
|
+
// 在 package-c 中
|
|
166
|
+
import Vue from 'vue'; // → 解析到 aliased-vue2
|
|
167
|
+
|
|
168
|
+
// 在主工程中
|
|
169
|
+
import Vue from 'vue'; // → 解析到 vue (3.x)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 高级用法
|
|
173
|
+
|
|
174
|
+
### 钩子函数
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
depsConflictResolverVitePlugin({
|
|
178
|
+
dependencies: ['legacy-lib'],
|
|
179
|
+
hooks: {
|
|
180
|
+
// 分析完成后
|
|
181
|
+
onAnalysisComplete: result => {
|
|
182
|
+
console.log('Found conflicts:', result.peerConflicts);
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
// 安装完成后
|
|
186
|
+
onInstallComplete: installed => {
|
|
187
|
+
console.log('Installed aliases:', installed);
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
// 自定义模块解析
|
|
191
|
+
beforeResolve: (source, importer) => {
|
|
192
|
+
// 返回新的模块名或 null 跳过
|
|
193
|
+
if (source === 'special-module') {
|
|
194
|
+
return 'custom-alias';
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### 复用已有别名
|
|
203
|
+
|
|
204
|
+
如果项目中已经安装了合适版本的别名(如 `vue2@npm:vue@2.6.14`),插件会自动检测并复用,不会重复安装。
|
|
205
|
+
|
|
206
|
+
## API 参考
|
|
207
|
+
|
|
208
|
+
### `createResolver(options): Promise<DepsConflictResolver>`
|
|
209
|
+
|
|
210
|
+
创建并初始化依赖解析器。
|
|
211
|
+
|
|
212
|
+
### `DepsConflictResolver`
|
|
213
|
+
|
|
214
|
+
主解析器类:
|
|
215
|
+
|
|
216
|
+
- `initialize(): Promise<void>` - 初始化解析器
|
|
217
|
+
- `resolveModule(request, importer): string | null` - 解析模块
|
|
218
|
+
- `getAnalysisResult(): AnalysisResult` - 获取分析结果
|
|
219
|
+
- `getAliasPathMappings(): AliasPathMapping[]` - 获取通用的别名路径映射
|
|
220
|
+
|
|
221
|
+
> 核心模块返回通用的 `AliasPathMapping[]` 格式,由各构建工具插件(Webpack/Vite)自行转换为各自需要的别名配置格式。
|
|
222
|
+
|
|
223
|
+
### 工具函数
|
|
224
|
+
|
|
225
|
+
为减少对外 API 面并提升 treeshake 效果,本包不再从主入口导出内部工具函数(如 semver/fs/npm registry 等)。如需版本判断等能力,请直接使用 `semver`。
|
|
226
|
+
|
|
227
|
+
## 开发
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
# 安装依赖
|
|
231
|
+
npm install
|
|
232
|
+
|
|
233
|
+
# 开发模式
|
|
234
|
+
npm run dev
|
|
235
|
+
|
|
236
|
+
# 构建
|
|
237
|
+
npm run build
|
|
238
|
+
|
|
239
|
+
# 运行测试
|
|
240
|
+
npm test
|
|
241
|
+
|
|
242
|
+
# 类型检查
|
|
243
|
+
npm run typecheck
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## 许可证
|
|
247
|
+
|
|
248
|
+
MIT
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 依赖信息
|
|
3
|
+
*/
|
|
4
|
+
interface DependencyInfo {
|
|
5
|
+
/**
|
|
6
|
+
* 包名
|
|
7
|
+
*/
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* 版本号或版本范围
|
|
11
|
+
*/
|
|
12
|
+
version: string;
|
|
13
|
+
/**
|
|
14
|
+
* 依赖路径(从根依赖到当前依赖的路径)
|
|
15
|
+
*/
|
|
16
|
+
dependencyPath: string[];
|
|
17
|
+
/**
|
|
18
|
+
* 子依赖
|
|
19
|
+
*/
|
|
20
|
+
dependencies: Record<string, string>;
|
|
21
|
+
/**
|
|
22
|
+
* Peer 依赖
|
|
23
|
+
*/
|
|
24
|
+
peerDependencies: Record<string, string>;
|
|
25
|
+
/**
|
|
26
|
+
* Peer 依赖元信息
|
|
27
|
+
*/
|
|
28
|
+
peerDependenciesMeta?: Record<string, {
|
|
29
|
+
optional?: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* 是否为可选 peer 依赖
|
|
33
|
+
*/
|
|
34
|
+
isOptionalPeer?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Peer 依赖冲突信息
|
|
38
|
+
*/
|
|
39
|
+
interface PeerConflict {
|
|
40
|
+
/**
|
|
41
|
+
* 包名
|
|
42
|
+
*/
|
|
43
|
+
packageName: string;
|
|
44
|
+
/**
|
|
45
|
+
* 主工程中的版本
|
|
46
|
+
*/
|
|
47
|
+
mainProjectVersion: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* peer 依赖要求的版本范围
|
|
50
|
+
*/
|
|
51
|
+
requiredRange: string;
|
|
52
|
+
/**
|
|
53
|
+
* 请求此 peer 依赖的包路径列表
|
|
54
|
+
*/
|
|
55
|
+
requestedBy: DependencyPath[];
|
|
56
|
+
/**
|
|
57
|
+
* 冲突的版本范围(与主工程版本不兼容的)
|
|
58
|
+
*/
|
|
59
|
+
conflictingRanges: DependencyPath[];
|
|
60
|
+
/**
|
|
61
|
+
* 是否存在冲突
|
|
62
|
+
*/
|
|
63
|
+
hasConflict: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 是否需要安装别名
|
|
66
|
+
*/
|
|
67
|
+
needsAlias: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 依赖路径
|
|
71
|
+
*/
|
|
72
|
+
interface DependencyPath {
|
|
73
|
+
/**
|
|
74
|
+
* 依赖路径数组
|
|
75
|
+
*/
|
|
76
|
+
path: string[];
|
|
77
|
+
/**
|
|
78
|
+
* 要求的版本范围
|
|
79
|
+
*/
|
|
80
|
+
requiredRange: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 别名映射
|
|
85
|
+
*/
|
|
86
|
+
interface AliasMapping {
|
|
87
|
+
/**
|
|
88
|
+
* 原始包名
|
|
89
|
+
*/
|
|
90
|
+
originalName: string;
|
|
91
|
+
/**
|
|
92
|
+
* 别名(用于安装)
|
|
93
|
+
*/
|
|
94
|
+
aliasName: string;
|
|
95
|
+
/**
|
|
96
|
+
* 实际安装的包名和版本
|
|
97
|
+
*/
|
|
98
|
+
installSpec: string;
|
|
99
|
+
/**
|
|
100
|
+
* 解析后的版本
|
|
101
|
+
*/
|
|
102
|
+
resolvedVersion: string;
|
|
103
|
+
/**
|
|
104
|
+
* 使用此别名的模块路径(声明 peerDependency 的包)
|
|
105
|
+
*/
|
|
106
|
+
usedBy: string[];
|
|
107
|
+
/**
|
|
108
|
+
* 所有需要重定向的依赖包名列表
|
|
109
|
+
* 包含 usedBy 中包的所有运行时子依赖(dependencies)
|
|
110
|
+
* 用于判断某个 importer 是否需要重定向到别名版本
|
|
111
|
+
*/
|
|
112
|
+
allDependents: string[];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 依赖分析结果
|
|
116
|
+
*/
|
|
117
|
+
interface AnalysisResult {
|
|
118
|
+
/**
|
|
119
|
+
* 所有分析过的依赖
|
|
120
|
+
*/
|
|
121
|
+
analyzedDependencies: Map<string, DependencyInfo>;
|
|
122
|
+
/**
|
|
123
|
+
* Peer 依赖冲突列表
|
|
124
|
+
*/
|
|
125
|
+
peerConflicts: PeerConflict[];
|
|
126
|
+
/**
|
|
127
|
+
* 需要创建的别名映射
|
|
128
|
+
*/
|
|
129
|
+
aliasMappings: AliasMapping[];
|
|
130
|
+
/**
|
|
131
|
+
* 第一层依赖中缺失的 peer 依赖(无冲突,需要安装)
|
|
132
|
+
*/
|
|
133
|
+
missingFirstLevelPeers: Array<{
|
|
134
|
+
packageName: string;
|
|
135
|
+
requiredRange: string;
|
|
136
|
+
requestedBy: string;
|
|
137
|
+
}>;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 通用的别名路径映射
|
|
141
|
+
* 核心模块提供此格式,由各构建工具插件转换为各自需要的格式
|
|
142
|
+
*/
|
|
143
|
+
interface AliasPathMapping {
|
|
144
|
+
/** 别名包名 (如 react-npm-18.2.0) */
|
|
145
|
+
aliasName: string;
|
|
146
|
+
/** 原始包名 (如 react) */
|
|
147
|
+
originalName: string;
|
|
148
|
+
/** 解析后的绝对路径 */
|
|
149
|
+
path: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 依赖解析器的配置选项
|
|
154
|
+
*/
|
|
155
|
+
interface DepsConflictResolverOptions {
|
|
156
|
+
/**
|
|
157
|
+
* 需要分析的依赖包名列表
|
|
158
|
+
*/
|
|
159
|
+
dependencies: string[];
|
|
160
|
+
/**
|
|
161
|
+
* 项目根目录路径
|
|
162
|
+
*/
|
|
163
|
+
projectRoot?: string;
|
|
164
|
+
/**
|
|
165
|
+
* 是否自动安装缺失的别名依赖
|
|
166
|
+
* @default true
|
|
167
|
+
*/
|
|
168
|
+
autoInstall?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* 包管理器类型
|
|
171
|
+
* - 'auto': 自动检测(基于 lock 文件或 package.json 的 packageManager 字段)
|
|
172
|
+
* - 'npm' | 'yarn' | 'pnpm': 指定包管理器
|
|
173
|
+
* @default 'auto'
|
|
174
|
+
*/
|
|
175
|
+
packageManager?: 'auto' | 'npm' | 'yarn' | 'pnpm';
|
|
176
|
+
/**
|
|
177
|
+
* NPM 注册表地址
|
|
178
|
+
* - 不指定或 undefined: 自动检测(从 .npmrc 等配置文件读取)
|
|
179
|
+
* - 字符串: 指定 registry 地址
|
|
180
|
+
* @default 自动检测
|
|
181
|
+
*/
|
|
182
|
+
registry?: string;
|
|
183
|
+
/**
|
|
184
|
+
* 是否启用调试日志
|
|
185
|
+
* @default false
|
|
186
|
+
*/
|
|
187
|
+
debug?: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* 自定义别名前缀
|
|
190
|
+
* @default 'aliased-'
|
|
191
|
+
*/
|
|
192
|
+
aliasPrefix?: string;
|
|
193
|
+
/**
|
|
194
|
+
* 排除特定依赖包对某些模块的解析重定向
|
|
195
|
+
* 键为原始包名,值为需要排除重定向的依赖包名列表
|
|
196
|
+
* @example { vue: ['vue-demi'] } - vue-demi 中的 import vue 不会被重定向
|
|
197
|
+
*/
|
|
198
|
+
excludeRedirects?: Record<string, string[]>;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* 解析后的配置(带默认值)
|
|
202
|
+
* 注意:packageManager 和 registry 在解析后会是具体的值,不会是 'auto'
|
|
203
|
+
*/
|
|
204
|
+
interface ResolvedOptions extends Required<DepsConflictResolverOptions> {
|
|
205
|
+
/**
|
|
206
|
+
* 解析后的包管理器类型(已自动检测或用户指定)
|
|
207
|
+
*/
|
|
208
|
+
packageManager: 'npm' | 'yarn' | 'pnpm';
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* 插件钩子
|
|
212
|
+
*/
|
|
213
|
+
interface PluginHooks {
|
|
214
|
+
/**
|
|
215
|
+
* 分析完成后的钩子
|
|
216
|
+
*/
|
|
217
|
+
onAnalysisComplete?: (result: AnalysisResult) => void | Promise<void>;
|
|
218
|
+
/**
|
|
219
|
+
* 安装完成后的钩子
|
|
220
|
+
*/
|
|
221
|
+
onInstallComplete?: (installed: AliasMapping[]) => void | Promise<void>;
|
|
222
|
+
/**
|
|
223
|
+
* 解析模块前的钩子
|
|
224
|
+
*/
|
|
225
|
+
beforeResolve?: (source: string, importer: string | undefined) => string | null | undefined;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* 完整的插件配置
|
|
229
|
+
*/
|
|
230
|
+
interface PluginConfig extends DepsConflictResolverOptions {
|
|
231
|
+
/**
|
|
232
|
+
* 钩子函数
|
|
233
|
+
*/
|
|
234
|
+
hooks?: PluginHooks;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export type { AliasMapping as A, DepsConflictResolverOptions as D, PeerConflict as P, ResolvedOptions as R, AliasPathMapping as a, AnalysisResult as b, PluginConfig as c, PluginHooks as d };
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 依赖信息
|
|
3
|
+
*/
|
|
4
|
+
interface DependencyInfo {
|
|
5
|
+
/**
|
|
6
|
+
* 包名
|
|
7
|
+
*/
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* 版本号或版本范围
|
|
11
|
+
*/
|
|
12
|
+
version: string;
|
|
13
|
+
/**
|
|
14
|
+
* 依赖路径(从根依赖到当前依赖的路径)
|
|
15
|
+
*/
|
|
16
|
+
dependencyPath: string[];
|
|
17
|
+
/**
|
|
18
|
+
* 子依赖
|
|
19
|
+
*/
|
|
20
|
+
dependencies: Record<string, string>;
|
|
21
|
+
/**
|
|
22
|
+
* Peer 依赖
|
|
23
|
+
*/
|
|
24
|
+
peerDependencies: Record<string, string>;
|
|
25
|
+
/**
|
|
26
|
+
* Peer 依赖元信息
|
|
27
|
+
*/
|
|
28
|
+
peerDependenciesMeta?: Record<string, {
|
|
29
|
+
optional?: boolean;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* 是否为可选 peer 依赖
|
|
33
|
+
*/
|
|
34
|
+
isOptionalPeer?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Peer 依赖冲突信息
|
|
38
|
+
*/
|
|
39
|
+
interface PeerConflict {
|
|
40
|
+
/**
|
|
41
|
+
* 包名
|
|
42
|
+
*/
|
|
43
|
+
packageName: string;
|
|
44
|
+
/**
|
|
45
|
+
* 主工程中的版本
|
|
46
|
+
*/
|
|
47
|
+
mainProjectVersion: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* peer 依赖要求的版本范围
|
|
50
|
+
*/
|
|
51
|
+
requiredRange: string;
|
|
52
|
+
/**
|
|
53
|
+
* 请求此 peer 依赖的包路径列表
|
|
54
|
+
*/
|
|
55
|
+
requestedBy: DependencyPath[];
|
|
56
|
+
/**
|
|
57
|
+
* 冲突的版本范围(与主工程版本不兼容的)
|
|
58
|
+
*/
|
|
59
|
+
conflictingRanges: DependencyPath[];
|
|
60
|
+
/**
|
|
61
|
+
* 是否存在冲突
|
|
62
|
+
*/
|
|
63
|
+
hasConflict: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 是否需要安装别名
|
|
66
|
+
*/
|
|
67
|
+
needsAlias: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 依赖路径
|
|
71
|
+
*/
|
|
72
|
+
interface DependencyPath {
|
|
73
|
+
/**
|
|
74
|
+
* 依赖路径数组
|
|
75
|
+
*/
|
|
76
|
+
path: string[];
|
|
77
|
+
/**
|
|
78
|
+
* 要求的版本范围
|
|
79
|
+
*/
|
|
80
|
+
requiredRange: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 别名映射
|
|
85
|
+
*/
|
|
86
|
+
interface AliasMapping {
|
|
87
|
+
/**
|
|
88
|
+
* 原始包名
|
|
89
|
+
*/
|
|
90
|
+
originalName: string;
|
|
91
|
+
/**
|
|
92
|
+
* 别名(用于安装)
|
|
93
|
+
*/
|
|
94
|
+
aliasName: string;
|
|
95
|
+
/**
|
|
96
|
+
* 实际安装的包名和版本
|
|
97
|
+
*/
|
|
98
|
+
installSpec: string;
|
|
99
|
+
/**
|
|
100
|
+
* 解析后的版本
|
|
101
|
+
*/
|
|
102
|
+
resolvedVersion: string;
|
|
103
|
+
/**
|
|
104
|
+
* 使用此别名的模块路径(声明 peerDependency 的包)
|
|
105
|
+
*/
|
|
106
|
+
usedBy: string[];
|
|
107
|
+
/**
|
|
108
|
+
* 所有需要重定向的依赖包名列表
|
|
109
|
+
* 包含 usedBy 中包的所有运行时子依赖(dependencies)
|
|
110
|
+
* 用于判断某个 importer 是否需要重定向到别名版本
|
|
111
|
+
*/
|
|
112
|
+
allDependents: string[];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 依赖分析结果
|
|
116
|
+
*/
|
|
117
|
+
interface AnalysisResult {
|
|
118
|
+
/**
|
|
119
|
+
* 所有分析过的依赖
|
|
120
|
+
*/
|
|
121
|
+
analyzedDependencies: Map<string, DependencyInfo>;
|
|
122
|
+
/**
|
|
123
|
+
* Peer 依赖冲突列表
|
|
124
|
+
*/
|
|
125
|
+
peerConflicts: PeerConflict[];
|
|
126
|
+
/**
|
|
127
|
+
* 需要创建的别名映射
|
|
128
|
+
*/
|
|
129
|
+
aliasMappings: AliasMapping[];
|
|
130
|
+
/**
|
|
131
|
+
* 第一层依赖中缺失的 peer 依赖(无冲突,需要安装)
|
|
132
|
+
*/
|
|
133
|
+
missingFirstLevelPeers: Array<{
|
|
134
|
+
packageName: string;
|
|
135
|
+
requiredRange: string;
|
|
136
|
+
requestedBy: string;
|
|
137
|
+
}>;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* 通用的别名路径映射
|
|
141
|
+
* 核心模块提供此格式,由各构建工具插件转换为各自需要的格式
|
|
142
|
+
*/
|
|
143
|
+
interface AliasPathMapping {
|
|
144
|
+
/** 别名包名 (如 react-npm-18.2.0) */
|
|
145
|
+
aliasName: string;
|
|
146
|
+
/** 原始包名 (如 react) */
|
|
147
|
+
originalName: string;
|
|
148
|
+
/** 解析后的绝对路径 */
|
|
149
|
+
path: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 依赖解析器的配置选项
|
|
154
|
+
*/
|
|
155
|
+
interface DepsConflictResolverOptions {
|
|
156
|
+
/**
|
|
157
|
+
* 需要分析的依赖包名列表
|
|
158
|
+
*/
|
|
159
|
+
dependencies: string[];
|
|
160
|
+
/**
|
|
161
|
+
* 项目根目录路径
|
|
162
|
+
*/
|
|
163
|
+
projectRoot?: string;
|
|
164
|
+
/**
|
|
165
|
+
* 是否自动安装缺失的别名依赖
|
|
166
|
+
* @default true
|
|
167
|
+
*/
|
|
168
|
+
autoInstall?: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* 包管理器类型
|
|
171
|
+
* - 'auto': 自动检测(基于 lock 文件或 package.json 的 packageManager 字段)
|
|
172
|
+
* - 'npm' | 'yarn' | 'pnpm': 指定包管理器
|
|
173
|
+
* @default 'auto'
|
|
174
|
+
*/
|
|
175
|
+
packageManager?: 'auto' | 'npm' | 'yarn' | 'pnpm';
|
|
176
|
+
/**
|
|
177
|
+
* NPM 注册表地址
|
|
178
|
+
* - 不指定或 undefined: 自动检测(从 .npmrc 等配置文件读取)
|
|
179
|
+
* - 字符串: 指定 registry 地址
|
|
180
|
+
* @default 自动检测
|
|
181
|
+
*/
|
|
182
|
+
registry?: string;
|
|
183
|
+
/**
|
|
184
|
+
* 是否启用调试日志
|
|
185
|
+
* @default false
|
|
186
|
+
*/
|
|
187
|
+
debug?: boolean;
|
|
188
|
+
/**
|
|
189
|
+
* 自定义别名前缀
|
|
190
|
+
* @default 'aliased-'
|
|
191
|
+
*/
|
|
192
|
+
aliasPrefix?: string;
|
|
193
|
+
/**
|
|
194
|
+
* 排除特定依赖包对某些模块的解析重定向
|
|
195
|
+
* 键为原始包名,值为需要排除重定向的依赖包名列表
|
|
196
|
+
* @example { vue: ['vue-demi'] } - vue-demi 中的 import vue 不会被重定向
|
|
197
|
+
*/
|
|
198
|
+
excludeRedirects?: Record<string, string[]>;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* 解析后的配置(带默认值)
|
|
202
|
+
* 注意:packageManager 和 registry 在解析后会是具体的值,不会是 'auto'
|
|
203
|
+
*/
|
|
204
|
+
interface ResolvedOptions extends Required<DepsConflictResolverOptions> {
|
|
205
|
+
/**
|
|
206
|
+
* 解析后的包管理器类型(已自动检测或用户指定)
|
|
207
|
+
*/
|
|
208
|
+
packageManager: 'npm' | 'yarn' | 'pnpm';
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* 插件钩子
|
|
212
|
+
*/
|
|
213
|
+
interface PluginHooks {
|
|
214
|
+
/**
|
|
215
|
+
* 分析完成后的钩子
|
|
216
|
+
*/
|
|
217
|
+
onAnalysisComplete?: (result: AnalysisResult) => void | Promise<void>;
|
|
218
|
+
/**
|
|
219
|
+
* 安装完成后的钩子
|
|
220
|
+
*/
|
|
221
|
+
onInstallComplete?: (installed: AliasMapping[]) => void | Promise<void>;
|
|
222
|
+
/**
|
|
223
|
+
* 解析模块前的钩子
|
|
224
|
+
*/
|
|
225
|
+
beforeResolve?: (source: string, importer: string | undefined) => string | null | undefined;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* 完整的插件配置
|
|
229
|
+
*/
|
|
230
|
+
interface PluginConfig extends DepsConflictResolverOptions {
|
|
231
|
+
/**
|
|
232
|
+
* 钩子函数
|
|
233
|
+
*/
|
|
234
|
+
hooks?: PluginHooks;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export type { AliasMapping as A, DepsConflictResolverOptions as D, PeerConflict as P, ResolvedOptions as R, AliasPathMapping as a, AnalysisResult as b, PluginConfig as c, PluginHooks as d };
|