@ainc/fs 0.1.22 → 0.1.23
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/dist/cache.d.ts +16 -0
- package/dist/cache.js +24 -0
- package/dist/dict.d.ts +21 -0
- package/dist/dict.js +66 -0
- package/dist/downloadFile.js +19 -13
- package/dist/index.d.ts +37 -1
- package/dist/index.exports.json +34 -0
- package/dist/index.js +59 -3
- package/dist/isEsmModule.d.ts +18 -0
- package/dist/isEsmModule.js +63 -0
- package/dist/loadPackageDescription.d.ts +61 -0
- package/dist/loadPackageDescription.js +71 -0
- package/dist/loadTsConfig.d.ts +87 -0
- package/dist/loadTsConfig.js +219 -0
- package/dist/match.d.ts +30 -0
- package/dist/match.js +59 -0
- package/dist/resolveAlias.d.ts +25 -0
- package/dist/resolveAlias.js +82 -0
- package/dist/resolveDirect.d.ts +15 -0
- package/dist/resolveDirect.js +144 -0
- package/dist/resolveExports.d.ts +19 -0
- package/dist/resolveExports.js +54 -0
- package/dist/resolveImports.d.ts +21 -0
- package/dist/resolveImports.js +114 -0
- package/dist/resolveModuleDir.d.ts +12 -0
- package/dist/resolveModuleDir.js +67 -0
- package/dist/resolveModuleId.d.ts +6 -0
- package/dist/resolveModuleId.js +32 -0
- package/dist/resolvePath.d.ts +23 -0
- package/dist/resolvePath.js +86 -0
- package/dist/resolvePaths.d.ts +13 -0
- package/dist/resolvePaths.js +42 -0
- package/dist/split.d.ts +6 -0
- package/dist/split.js +24 -0
- package/dist/sys.d.ts +60 -0
- package/dist/sys.js +260 -0
- package/esm/cache.mjs +22 -0
- package/esm/dict.mjs +63 -0
- package/esm/downloadFile.mjs +19 -13
- package/esm/index.exports.json +34 -0
- package/esm/index.mjs +29 -1
- package/esm/isEsmModule.mjs +59 -0
- package/esm/loadPackageDescription.mjs +67 -0
- package/esm/loadTsConfig.mjs +215 -0
- package/esm/match.mjs +53 -0
- package/esm/resolveAlias.mjs +79 -0
- package/esm/resolveDirect.mjs +142 -0
- package/esm/resolveExports.mjs +51 -0
- package/esm/resolveImports.mjs +112 -0
- package/esm/resolveModuleDir.mjs +64 -0
- package/esm/resolveModuleId.mjs +30 -0
- package/esm/resolvePath.mjs +84 -0
- package/esm/resolvePaths.mjs +40 -0
- package/esm/split.mjs +22 -0
- package/esm/sys.mjs +258 -0
- package/package.json +3 -2
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*****************************************
|
|
3
|
+
* Created by edonet@163.com
|
|
4
|
+
* Created on 2023-12-30 13:48:09
|
|
5
|
+
*****************************************
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
/**
|
|
9
|
+
*****************************************
|
|
10
|
+
* 加载依赖
|
|
11
|
+
*****************************************
|
|
12
|
+
*/
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
import { dirname, resolve, sep, isAbsolute } from 'node:path';
|
|
15
|
+
import { relative, isRelative } from './relative.mjs';
|
|
16
|
+
import { resolveFile } from './resolveFile.mjs';
|
|
17
|
+
import { isFile } from './stat.mjs';
|
|
18
|
+
import { lookup } from './lookup.mjs';
|
|
19
|
+
import { jsonc } from './jsonc.mjs';
|
|
20
|
+
import { match } from './match.mjs';
|
|
21
|
+
import { resolveModuleDirs } from './resolveModuleDir.mjs';
|
|
22
|
+
/**
|
|
23
|
+
*****************************************
|
|
24
|
+
* 加载 TS 配置
|
|
25
|
+
*****************************************
|
|
26
|
+
*/
|
|
27
|
+
export function loadTsConfig(from) {
|
|
28
|
+
const data = resolveTsConfig(from);
|
|
29
|
+
// 返回配置
|
|
30
|
+
if (data) {
|
|
31
|
+
return data.config;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
*****************************************
|
|
36
|
+
* 加载编译配置
|
|
37
|
+
*****************************************
|
|
38
|
+
*/
|
|
39
|
+
export function loadCompilerOptions(from) {
|
|
40
|
+
const data = resolveTsConfig(from);
|
|
41
|
+
// 返回配置
|
|
42
|
+
if (data && data.config) {
|
|
43
|
+
return data.config.compilerOptions;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
*****************************************
|
|
48
|
+
* 缓存内容
|
|
49
|
+
*****************************************
|
|
50
|
+
*/
|
|
51
|
+
const cache = new Map();
|
|
52
|
+
/**
|
|
53
|
+
*****************************************
|
|
54
|
+
* 解析 TS 配置
|
|
55
|
+
*****************************************
|
|
56
|
+
*/
|
|
57
|
+
export function resolveTsConfig(from) {
|
|
58
|
+
return lookup('tsconfig.json', {
|
|
59
|
+
from,
|
|
60
|
+
cache,
|
|
61
|
+
resolve(path) {
|
|
62
|
+
return isFile(path) ? loadTsConfigFile(path) : undefined;
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
*****************************************
|
|
68
|
+
* 解析 TS 配置文件
|
|
69
|
+
*****************************************
|
|
70
|
+
*/
|
|
71
|
+
function loadTsConfigFile(path) {
|
|
72
|
+
const config = parseTsConfig(path, new Set([path]), ['.json', sep + 'tsconfig.json']);
|
|
73
|
+
const dir = dirname(path);
|
|
74
|
+
// 移除继承属性
|
|
75
|
+
config.extends = undefined;
|
|
76
|
+
// 格式化 include 配置
|
|
77
|
+
if (config.include) {
|
|
78
|
+
config.include = config.include.map(path => relative(dir, path));
|
|
79
|
+
}
|
|
80
|
+
// 格式化 exclude 配置
|
|
81
|
+
if (config.exclude) {
|
|
82
|
+
config.exclude = config.exclude.map(path => relative(dir, path));
|
|
83
|
+
}
|
|
84
|
+
// 格式化 files 配置
|
|
85
|
+
if (config.files) {
|
|
86
|
+
config.files = config.files.map(path => relative(dir, path));
|
|
87
|
+
}
|
|
88
|
+
// 返回结果
|
|
89
|
+
return { path, config };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
*****************************************
|
|
93
|
+
* 解析配置
|
|
94
|
+
*****************************************
|
|
95
|
+
*/
|
|
96
|
+
function parseTsConfig(path, tracker, extensions) {
|
|
97
|
+
const data = jsonc(readFileSync(path, 'utf8'));
|
|
98
|
+
const dir = dirname(path);
|
|
99
|
+
const config = normalizeTsConfig(data, dir);
|
|
100
|
+
// 不存在继承,直接返回
|
|
101
|
+
if (!config.extends) {
|
|
102
|
+
return config;
|
|
103
|
+
}
|
|
104
|
+
// 获取继承列表
|
|
105
|
+
const extendsList = Array.isArray(config.extends) ? config.extends : [config.extends];
|
|
106
|
+
const configs = extendsList.map(path => parseExtendsTsConfig(path, dir, tracker, extensions));
|
|
107
|
+
// 追加当前配置
|
|
108
|
+
configs.push(config);
|
|
109
|
+
// 合并配置
|
|
110
|
+
return configs.reduce(mergeTsConfig);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
*****************************************
|
|
114
|
+
* 合并配置
|
|
115
|
+
*****************************************
|
|
116
|
+
*/
|
|
117
|
+
function mergeTsConfig(target, source) {
|
|
118
|
+
const { baseUrl, paths } = source.compilerOptions || {};
|
|
119
|
+
const config = { ...target, ...source };
|
|
120
|
+
// 合并配置项
|
|
121
|
+
config.compilerOptions = { ...target.compilerOptions, ...source.compilerOptions };
|
|
122
|
+
config.watchOptions = { ...target.watchOptions, ...source.watchOptions };
|
|
123
|
+
// 更新 paths 配置
|
|
124
|
+
if (baseUrl || paths) {
|
|
125
|
+
config.compilerOptions.baseUrl = baseUrl;
|
|
126
|
+
config.compilerOptions.paths = paths;
|
|
127
|
+
}
|
|
128
|
+
// 返回配置
|
|
129
|
+
return config;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
*****************************************
|
|
133
|
+
* 解析继承配置
|
|
134
|
+
*****************************************
|
|
135
|
+
*/
|
|
136
|
+
function parseExtendsTsConfig(path, from, tracker, extensions) {
|
|
137
|
+
const extendsFile = resolveExtendsFile(path, from, extensions);
|
|
138
|
+
// 未找到文件
|
|
139
|
+
if (!extendsFile) {
|
|
140
|
+
throw new Error(`file '${path}' not found.`);
|
|
141
|
+
}
|
|
142
|
+
// 循环引用
|
|
143
|
+
if (tracker.has(extendsFile)) {
|
|
144
|
+
throw new Error(`circularity detected while resolving configuration: ${extendsFile}`);
|
|
145
|
+
}
|
|
146
|
+
// 添加引用文件
|
|
147
|
+
tracker.add(extendsFile);
|
|
148
|
+
// 解析文件
|
|
149
|
+
return parseTsConfig(extendsFile, tracker, extensions);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
*****************************************
|
|
153
|
+
* 解析继承文件地址
|
|
154
|
+
*****************************************
|
|
155
|
+
*/
|
|
156
|
+
function resolveExtendsFile(path, from, extensions) {
|
|
157
|
+
// 解析相对路径
|
|
158
|
+
if (isRelative(path)) {
|
|
159
|
+
return resolveFile(resolve(from, path), extensions);
|
|
160
|
+
}
|
|
161
|
+
// 解析绝对路径
|
|
162
|
+
if (isAbsolute(path)) {
|
|
163
|
+
return resolveFile(path, extensions);
|
|
164
|
+
}
|
|
165
|
+
// 解析模块目录
|
|
166
|
+
const moduleDirs = resolveModuleDirs(from);
|
|
167
|
+
// 模块目录
|
|
168
|
+
return match(moduleDirs, dir => resolveFile(resolve(dir, path), extensions));
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
*****************************************
|
|
172
|
+
* 格式化配置
|
|
173
|
+
*****************************************
|
|
174
|
+
*/
|
|
175
|
+
function normalizeTsConfig(config, dir) {
|
|
176
|
+
const compilerOptions = config.compilerOptions;
|
|
177
|
+
const watchOptions = config.watchOptions;
|
|
178
|
+
// 格式化 include 配置
|
|
179
|
+
if (config.include) {
|
|
180
|
+
config.include = config.include.map(path => resolve(dir, path));
|
|
181
|
+
}
|
|
182
|
+
// 格式化 exclude 配置
|
|
183
|
+
if (config.exclude) {
|
|
184
|
+
config.exclude = config.exclude.map(path => resolve(dir, path));
|
|
185
|
+
}
|
|
186
|
+
// 格式化 files 配置
|
|
187
|
+
if (config.files) {
|
|
188
|
+
config.files = config.files.map(path => resolve(dir, path));
|
|
189
|
+
}
|
|
190
|
+
// 格式化 compilerOptions 配置
|
|
191
|
+
if (compilerOptions) {
|
|
192
|
+
// 格式化 baseUrl 配置
|
|
193
|
+
if (compilerOptions.baseUrl) {
|
|
194
|
+
compilerOptions.baseUrl = resolve(dir, compilerOptions.baseUrl);
|
|
195
|
+
}
|
|
196
|
+
// 格式化 outDir 配置
|
|
197
|
+
if (compilerOptions.outDir) {
|
|
198
|
+
compilerOptions.outDir = resolve(dir, compilerOptions.outDir);
|
|
199
|
+
}
|
|
200
|
+
// 格式化 rootDir 配置
|
|
201
|
+
if (compilerOptions.rootDir) {
|
|
202
|
+
compilerOptions.rootDir = resolve(dir, compilerOptions.rootDir);
|
|
203
|
+
}
|
|
204
|
+
// 格式化 rootDirs 配置
|
|
205
|
+
if (compilerOptions.rootDirs) {
|
|
206
|
+
compilerOptions.rootDirs = compilerOptions.rootDirs.map(path => resolve(dir, path));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// 格式化监听路径
|
|
210
|
+
if (watchOptions && watchOptions.excludeDirectories) {
|
|
211
|
+
watchOptions.excludeDirectories = watchOptions.excludeDirectories.map(path => resolve(dir, path));
|
|
212
|
+
}
|
|
213
|
+
// 返回配置
|
|
214
|
+
return config;
|
|
215
|
+
}
|
package/esm/match.mjs
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*****************************************
|
|
3
|
+
* Created by edonet@163.com
|
|
4
|
+
* Created on 2026-03-18 15:12:42
|
|
5
|
+
*****************************************
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
/**
|
|
9
|
+
*****************************************
|
|
10
|
+
* 空函数
|
|
11
|
+
*****************************************
|
|
12
|
+
*/
|
|
13
|
+
export function noop() {
|
|
14
|
+
// do nothing
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
*****************************************
|
|
18
|
+
* nil 函数
|
|
19
|
+
*****************************************
|
|
20
|
+
*/
|
|
21
|
+
export function nil() {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
*****************************************
|
|
26
|
+
* false
|
|
27
|
+
*****************************************
|
|
28
|
+
*/
|
|
29
|
+
export function falsy() {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
*****************************************
|
|
34
|
+
* 一元函数
|
|
35
|
+
*****************************************
|
|
36
|
+
*/
|
|
37
|
+
export function unary(value) {
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
*****************************************
|
|
42
|
+
* 执行匹配
|
|
43
|
+
*****************************************
|
|
44
|
+
*/
|
|
45
|
+
export function match(list, handler) {
|
|
46
|
+
for (let i = 0; i < list.length; i++) {
|
|
47
|
+
const result = handler(list[i]);
|
|
48
|
+
// 查找到结果
|
|
49
|
+
if (result !== undefined) {
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*****************************************
|
|
3
|
+
* Created by edonet@163.com
|
|
4
|
+
* Created on 2025-05-26 22:30:23
|
|
5
|
+
*****************************************
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
/**
|
|
9
|
+
*****************************************
|
|
10
|
+
* 加载依赖
|
|
11
|
+
*****************************************
|
|
12
|
+
*/
|
|
13
|
+
import { Dict } from './dict.mjs';
|
|
14
|
+
import { cache } from './cache.mjs';
|
|
15
|
+
import { resolveDirect } from './resolveDirect.mjs';
|
|
16
|
+
/**
|
|
17
|
+
*****************************************
|
|
18
|
+
* 缓存
|
|
19
|
+
*****************************************
|
|
20
|
+
*/
|
|
21
|
+
const cached = cache(new WeakMap());
|
|
22
|
+
/**
|
|
23
|
+
*****************************************
|
|
24
|
+
* 解析别名
|
|
25
|
+
*****************************************
|
|
26
|
+
*/
|
|
27
|
+
export function resolveAlias(alias) {
|
|
28
|
+
return cached.get(alias, resolveTarget);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
*****************************************
|
|
32
|
+
* 解析别名
|
|
33
|
+
*****************************************
|
|
34
|
+
*/
|
|
35
|
+
function resolveTarget(alias) {
|
|
36
|
+
return resolveDict(alias, resolvePath);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
*****************************************
|
|
40
|
+
* 解析匹配路径
|
|
41
|
+
*****************************************
|
|
42
|
+
*/
|
|
43
|
+
function resolvePath(key, value) {
|
|
44
|
+
const { test, resolve } = resolveDirect(key);
|
|
45
|
+
const rule = resolve(value);
|
|
46
|
+
// 返回匹配函数
|
|
47
|
+
return function match(id, handler) {
|
|
48
|
+
if (test(id)) {
|
|
49
|
+
return handler(rule(id));
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
*****************************************
|
|
55
|
+
* 解析字典
|
|
56
|
+
*****************************************
|
|
57
|
+
*/
|
|
58
|
+
export function resolveDict(data, handler) {
|
|
59
|
+
const result = new Dict();
|
|
60
|
+
// 生成元素
|
|
61
|
+
Object.keys(data)
|
|
62
|
+
.forEach(key => result.set(key, handler(key, data[key])));
|
|
63
|
+
// 排序列表
|
|
64
|
+
result.sort((a, b) => {
|
|
65
|
+
const idxA = a.indexOf('*');
|
|
66
|
+
const idxB = b.indexOf('*');
|
|
67
|
+
const baseA = idxA === -1 ? a.length : idxA;
|
|
68
|
+
const baseB = idxB === -1 ? b.length : idxB;
|
|
69
|
+
// 比较基准长度
|
|
70
|
+
if (baseA !== baseB) {
|
|
71
|
+
return baseB - baseA;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
return idxA === -1 ? -1 : idxB === -1 ? 1 : b.length - a.length;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// 返回结果
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*****************************************
|
|
3
|
+
* Created by edonet@163.com
|
|
4
|
+
* Created on 2026-03-18 13:32:09
|
|
5
|
+
*****************************************
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
/**
|
|
9
|
+
*****************************************
|
|
10
|
+
* 加载依赖
|
|
11
|
+
*****************************************
|
|
12
|
+
*/
|
|
13
|
+
import { sep, isAbsolute } from 'node:path';
|
|
14
|
+
import { unary } from './match.mjs';
|
|
15
|
+
import { split } from './split.mjs';
|
|
16
|
+
/**
|
|
17
|
+
*****************************************
|
|
18
|
+
* 格式化路径
|
|
19
|
+
*****************************************
|
|
20
|
+
*/
|
|
21
|
+
const sepReg = /\//g;
|
|
22
|
+
const normalizePath = (path) => path.replace(sepReg, sep);
|
|
23
|
+
/**
|
|
24
|
+
*****************************************
|
|
25
|
+
* 格式化路径
|
|
26
|
+
*****************************************
|
|
27
|
+
*/
|
|
28
|
+
function normalizeFn(path) {
|
|
29
|
+
return sep === '\\' && isAbsolute(path) ? normalizePath : unary;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
*****************************************
|
|
33
|
+
* 解析指令
|
|
34
|
+
*****************************************
|
|
35
|
+
*/
|
|
36
|
+
export function resolveDirect(direct) {
|
|
37
|
+
const idx = direct.indexOf('*');
|
|
38
|
+
if (idx === -1) {
|
|
39
|
+
return {
|
|
40
|
+
test: id => id === direct,
|
|
41
|
+
resolve: path => () => path,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// 分割路径
|
|
45
|
+
const [prefix, suffix] = [direct.slice(0, idx), direct.slice(idx + 1)];
|
|
46
|
+
// 生成匹配规则
|
|
47
|
+
if (prefix) {
|
|
48
|
+
return suffix ? resolvePrefixSuffix(prefix, suffix) : resolvePrefix(prefix);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return suffix ? resolveSuffix(suffix) : resolveWildcard();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
*****************************************
|
|
56
|
+
* 解析前/后缀
|
|
57
|
+
*****************************************
|
|
58
|
+
*/
|
|
59
|
+
function resolvePrefixSuffix(prefix, suffix) {
|
|
60
|
+
const size = prefix.length + suffix.length;
|
|
61
|
+
return {
|
|
62
|
+
test(id) {
|
|
63
|
+
return id.length >= size && id.startsWith(prefix) && id.endsWith(suffix);
|
|
64
|
+
},
|
|
65
|
+
resolve(path) {
|
|
66
|
+
const [start, end] = split(path, '*');
|
|
67
|
+
const normalize = normalizeFn(start);
|
|
68
|
+
if (end === undefined) {
|
|
69
|
+
return () => start;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
return (id) => start + normalize(id.slice(prefix.length, -suffix.length)) + end;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
*****************************************
|
|
79
|
+
* 解析前缀
|
|
80
|
+
*****************************************
|
|
81
|
+
*/
|
|
82
|
+
function resolvePrefix(prefix) {
|
|
83
|
+
return {
|
|
84
|
+
test(id) {
|
|
85
|
+
return id.startsWith(prefix);
|
|
86
|
+
},
|
|
87
|
+
resolve(path) {
|
|
88
|
+
const [start, end] = split(path, '*');
|
|
89
|
+
const normalize = normalizeFn(start);
|
|
90
|
+
if (end === undefined) {
|
|
91
|
+
return () => start;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return (id) => start + normalize(id.slice(prefix.length)) + end;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
*****************************************
|
|
101
|
+
* 解析后缀
|
|
102
|
+
*****************************************
|
|
103
|
+
*/
|
|
104
|
+
function resolveSuffix(suffix) {
|
|
105
|
+
return {
|
|
106
|
+
test(id) {
|
|
107
|
+
return id.endsWith(suffix);
|
|
108
|
+
},
|
|
109
|
+
resolve(val) {
|
|
110
|
+
const [start, end] = split(val, '*');
|
|
111
|
+
const normalize = normalizeFn(start);
|
|
112
|
+
if (end === undefined) {
|
|
113
|
+
return () => start;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
return (id) => start + normalize(id.slice(0, -suffix.length)) + end;
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
*****************************************
|
|
123
|
+
* 解析通配符
|
|
124
|
+
*****************************************
|
|
125
|
+
*/
|
|
126
|
+
function resolveWildcard() {
|
|
127
|
+
return {
|
|
128
|
+
test() {
|
|
129
|
+
return true;
|
|
130
|
+
},
|
|
131
|
+
resolve(val) {
|
|
132
|
+
const [start, end] = split(val, '*');
|
|
133
|
+
const normalize = normalizeFn(start);
|
|
134
|
+
if (end === undefined) {
|
|
135
|
+
return () => start;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
return (id) => start + normalize(id) + end;
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*****************************************
|
|
3
|
+
* Created by edonet@163.com
|
|
4
|
+
* Created on 2025-05-27 21:02:36
|
|
5
|
+
*****************************************
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
import { resolveImports } from './resolveImports.mjs';
|
|
9
|
+
/**
|
|
10
|
+
*****************************************
|
|
11
|
+
* 缓存
|
|
12
|
+
*****************************************
|
|
13
|
+
*/
|
|
14
|
+
const cache = new WeakMap();
|
|
15
|
+
/**
|
|
16
|
+
*****************************************
|
|
17
|
+
* 解析导出描述
|
|
18
|
+
*****************************************
|
|
19
|
+
*/
|
|
20
|
+
export function resolveTargetDescription(exports) {
|
|
21
|
+
const cached = cache.get(exports);
|
|
22
|
+
if (cached) {
|
|
23
|
+
return cached;
|
|
24
|
+
}
|
|
25
|
+
// 生成目标配置
|
|
26
|
+
const target = Array.isArray(exports) || !Object.keys(exports).some(key => key.charAt(0) === '.')
|
|
27
|
+
? { '.': exports }
|
|
28
|
+
: exports;
|
|
29
|
+
// 添加缓存
|
|
30
|
+
cache.set(exports, target);
|
|
31
|
+
// 返回目标
|
|
32
|
+
return target;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
*****************************************
|
|
36
|
+
* 解析导出配置
|
|
37
|
+
*****************************************
|
|
38
|
+
*/
|
|
39
|
+
export function resolveExports(id, conditions, exports, handler) {
|
|
40
|
+
if (!exports) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// 处理导出路径
|
|
44
|
+
if (typeof exports === 'string') {
|
|
45
|
+
return id === '.' ? exports : undefined;
|
|
46
|
+
}
|
|
47
|
+
// 解析导出描述
|
|
48
|
+
const target = resolveTargetDescription(exports);
|
|
49
|
+
// 获取匹配函数
|
|
50
|
+
return resolveImports(id, conditions, target, handler);
|
|
51
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*****************************************
|
|
3
|
+
* Created by edonet@163.com
|
|
4
|
+
* Created on 2025-06-22 11:21:37
|
|
5
|
+
*****************************************
|
|
6
|
+
*/
|
|
7
|
+
'use strict';
|
|
8
|
+
import { match, nil, unary } from './match.mjs';
|
|
9
|
+
import { cache } from './cache.mjs';
|
|
10
|
+
import { resolveDict } from './resolveAlias.mjs';
|
|
11
|
+
import { resolveDirect } from './resolveDirect.mjs';
|
|
12
|
+
/**
|
|
13
|
+
*****************************************
|
|
14
|
+
* 缓存
|
|
15
|
+
*****************************************
|
|
16
|
+
*/
|
|
17
|
+
const cached = cache(new WeakMap());
|
|
18
|
+
/**
|
|
19
|
+
*****************************************
|
|
20
|
+
* 解析目标
|
|
21
|
+
*****************************************
|
|
22
|
+
*/
|
|
23
|
+
export function resolveImports(id, conditions, target, handler) {
|
|
24
|
+
const rules = cached.get(target, () => resolveDict(target, resolveTargetDescription));
|
|
25
|
+
const resolve = handler || unary;
|
|
26
|
+
// 返回匹配函数
|
|
27
|
+
return rules.match(rule => {
|
|
28
|
+
if (rule.test(id)) {
|
|
29
|
+
return resolvePath(id, conditions, rule.direct, resolve);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
*****************************************
|
|
35
|
+
* 解析规则
|
|
36
|
+
*****************************************
|
|
37
|
+
*/
|
|
38
|
+
function resolveTargetDescription(key, value) {
|
|
39
|
+
const { test, resolve } = resolveDirect(key);
|
|
40
|
+
// 返回配置规则
|
|
41
|
+
return {
|
|
42
|
+
test,
|
|
43
|
+
direct: walk(value, resolve),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
*****************************************
|
|
48
|
+
* 解析重定向
|
|
49
|
+
*****************************************
|
|
50
|
+
*/
|
|
51
|
+
function walk(value, handler) {
|
|
52
|
+
switch (typeof value) {
|
|
53
|
+
case 'string':
|
|
54
|
+
return handler(value);
|
|
55
|
+
case 'object':
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
return nil;
|
|
59
|
+
}
|
|
60
|
+
// 处理空目标
|
|
61
|
+
if (!value) {
|
|
62
|
+
return nil;
|
|
63
|
+
}
|
|
64
|
+
// 处理数组目标
|
|
65
|
+
if (Array.isArray(value)) {
|
|
66
|
+
return value.map(id => walk(id, handler));
|
|
67
|
+
}
|
|
68
|
+
// 定义结果
|
|
69
|
+
const direct = {};
|
|
70
|
+
// 遍历目标描述
|
|
71
|
+
Object.keys(value)
|
|
72
|
+
.forEach(key => {
|
|
73
|
+
direct[key] = walk(value[key], handler);
|
|
74
|
+
});
|
|
75
|
+
// 返回结果
|
|
76
|
+
return direct;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
*****************************************
|
|
80
|
+
* 解析规则
|
|
81
|
+
*****************************************
|
|
82
|
+
*/
|
|
83
|
+
function resolvePath(id, conditions, rule, handler) {
|
|
84
|
+
switch (typeof rule) {
|
|
85
|
+
case 'function':
|
|
86
|
+
return resolvePath(id, conditions, rule(id), handler);
|
|
87
|
+
case 'string':
|
|
88
|
+
return handler(rule);
|
|
89
|
+
case 'object':
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
// 处理空规则
|
|
95
|
+
if (!rule) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
// 处理数组
|
|
99
|
+
if (Array.isArray(rule)) {
|
|
100
|
+
return match(rule, value => resolvePath(id, conditions, value, handler));
|
|
101
|
+
}
|
|
102
|
+
// 处理条件映射
|
|
103
|
+
const condition = conditions.find(key => rule[key]);
|
|
104
|
+
const value = condition ? rule[condition] : rule.default;
|
|
105
|
+
// 存在解析时,继续解析
|
|
106
|
+
if (value) {
|
|
107
|
+
return resolvePath(id, conditions, value, handler);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
}
|