@ainc/fs 0.1.22 → 0.1.24

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.
Files changed (64) hide show
  1. package/dist/cache.d.ts +16 -0
  2. package/dist/cache.js +24 -0
  3. package/dist/dict.d.ts +21 -0
  4. package/dist/dict.js +66 -0
  5. package/dist/download.js +4 -16
  6. package/dist/downloadFile.js +19 -13
  7. package/dist/gzip.d.ts +13 -0
  8. package/dist/gzip.js +50 -0
  9. package/dist/index.d.ts +37 -1
  10. package/dist/index.exports.json +34 -0
  11. package/dist/index.js +60 -3
  12. package/dist/isEsmModule.d.ts +18 -0
  13. package/dist/isEsmModule.js +63 -0
  14. package/dist/loadPackageDescription.d.ts +61 -0
  15. package/dist/loadPackageDescription.js +71 -0
  16. package/dist/loadTsConfig.d.ts +87 -0
  17. package/dist/loadTsConfig.js +219 -0
  18. package/dist/match.d.ts +30 -0
  19. package/dist/match.js +59 -0
  20. package/dist/promises.d.ts +69 -0
  21. package/dist/promises.js +103 -0
  22. package/dist/resolveAlias.d.ts +25 -0
  23. package/dist/resolveAlias.js +82 -0
  24. package/dist/resolveDirect.d.ts +15 -0
  25. package/dist/resolveDirect.js +144 -0
  26. package/dist/resolveExports.d.ts +19 -0
  27. package/dist/resolveExports.js +54 -0
  28. package/dist/resolveImports.d.ts +21 -0
  29. package/dist/resolveImports.js +114 -0
  30. package/dist/resolveModuleDir.d.ts +12 -0
  31. package/dist/resolveModuleDir.js +67 -0
  32. package/dist/resolveModuleId.d.ts +6 -0
  33. package/dist/resolveModuleId.js +32 -0
  34. package/dist/resolvePath.d.ts +23 -0
  35. package/dist/resolvePath.js +86 -0
  36. package/dist/resolvePaths.d.ts +13 -0
  37. package/dist/resolvePaths.js +42 -0
  38. package/dist/split.d.ts +6 -0
  39. package/dist/split.js +24 -0
  40. package/dist/sys.d.ts +60 -0
  41. package/dist/sys.js +260 -0
  42. package/esm/cache.mjs +22 -0
  43. package/esm/dict.mjs +63 -0
  44. package/esm/download.mjs +4 -16
  45. package/esm/downloadFile.mjs +19 -13
  46. package/esm/gzip.mjs +47 -0
  47. package/esm/index.exports.json +34 -0
  48. package/esm/index.mjs +29 -1
  49. package/esm/isEsmModule.mjs +59 -0
  50. package/esm/loadPackageDescription.mjs +67 -0
  51. package/esm/loadTsConfig.mjs +215 -0
  52. package/esm/match.mjs +53 -0
  53. package/esm/promises.mjs +96 -0
  54. package/esm/resolveAlias.mjs +79 -0
  55. package/esm/resolveDirect.mjs +142 -0
  56. package/esm/resolveExports.mjs +51 -0
  57. package/esm/resolveImports.mjs +112 -0
  58. package/esm/resolveModuleDir.mjs +64 -0
  59. package/esm/resolveModuleId.mjs +30 -0
  60. package/esm/resolvePath.mjs +84 -0
  61. package/esm/resolvePaths.mjs +40 -0
  62. package/esm/split.mjs +22 -0
  63. package/esm/sys.mjs +258 -0
  64. package/package.json +5 -6
@@ -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
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ *****************************************
3
+ * Created by edonet@163.com
4
+ * Created on 2025-05-29 20:26:27
5
+ *****************************************
6
+ */
7
+ 'use strict';
8
+ /**
9
+ *****************************************
10
+ * 加载依赖
11
+ *****************************************
12
+ */
13
+ import { resolve, join } from 'node:path';
14
+ import { dirname } from './dirname.mjs';
15
+ import { isDir } from './stat.mjs';
16
+ import { match } from './match.mjs';
17
+ /**
18
+ *****************************************
19
+ * 模块路径缓存
20
+ *****************************************
21
+ */
22
+ const cacheModuleDirs = new Map();
23
+ const cacheModuleDir = new Map();
24
+ /**
25
+ *****************************************
26
+ * 解析模块目录
27
+ *****************************************
28
+ */
29
+ export function resolveModuleDir(id, from) {
30
+ const cacheId = `${from}:${id}`;
31
+ if (cacheModuleDir.has(cacheId)) {
32
+ return cacheModuleDir.get(cacheId);
33
+ }
34
+ // 解析目录
35
+ const dirs = resolveModuleDirs(from);
36
+ const result = match(dirs, dir => isDir(resolve(dir, id)));
37
+ // 缓存结果
38
+ cacheModuleDir.set(cacheId, result);
39
+ // 返回结果
40
+ return result;
41
+ }
42
+ /**
43
+ *****************************************
44
+ * 解析模块目录列表
45
+ *****************************************
46
+ */
47
+ export function resolveModuleDirs(from) {
48
+ if (!from) {
49
+ return [];
50
+ }
51
+ // 存在缓存时,直接返回
52
+ const cached = cacheModuleDirs.get(from);
53
+ if (cached) {
54
+ return cached;
55
+ }
56
+ // 解析目录
57
+ const dirs = resolveModuleDirs(dirname(from));
58
+ const dir = join(from, 'node_modules');
59
+ const result = isDir(dir) ? [dir, ...dirs] : dirs;
60
+ // 缓存结果
61
+ cacheModuleDirs.set(from, result);
62
+ // 返回结果
63
+ return result;
64
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ *****************************************
3
+ * Created by edonet@163.com
4
+ * Created on 2025-05-29 20:26:27
5
+ *****************************************
6
+ */
7
+ 'use strict';
8
+ /**
9
+ *****************************************
10
+ * 解析模块路径
11
+ *****************************************
12
+ */
13
+ export function resolveModuleId(id) {
14
+ const idx1 = id.indexOf('/');
15
+ // 处理不带域的模块路径
16
+ if (idx1 === -1) {
17
+ return [id, '.'];
18
+ }
19
+ else if (id.charAt(0) !== '@') {
20
+ return [id.slice(0, idx1), '.' + id.slice(idx1)];
21
+ }
22
+ // 分割模块路径
23
+ const idx2 = id.indexOf('/', idx1 + 1);
24
+ if (idx2 === -1) {
25
+ return [id, '.'];
26
+ }
27
+ else {
28
+ return [id.slice(0, idx2), '.' + id.slice(idx2)];
29
+ }
30
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ *****************************************
3
+ * Created by edonet@163.com
4
+ * Created on 2026-03-18 20:06:20
5
+ *****************************************
6
+ */
7
+ 'use strict';
8
+ /**
9
+ *****************************************
10
+ * 加载依赖
11
+ *****************************************
12
+ */
13
+ import { dirname, resolve } from 'node:path';
14
+ import { loadCompilerOptions } from './loadTsConfig.mjs';
15
+ import { sys } from './sys.mjs';
16
+ import { isEsmFile, isEsmPackage } from './isEsmModule.mjs';
17
+ /**
18
+ *****************************************
19
+ * 创建文件系统
20
+ *****************************************
21
+ */
22
+ function createFileSystem(options) {
23
+ return {
24
+ ...sys,
25
+ ...options,
26
+ cache: options.cache || sys.cache,
27
+ cwd: options.cwd || sys.cwd,
28
+ mainFields: options.mainFields || sys.mainFields,
29
+ conditions: options.conditions || sys.conditions,
30
+ extensions: options.extensions || sys.extensions,
31
+ };
32
+ }
33
+ /**
34
+ *****************************************
35
+ * 判断是否为 ESM 模块
36
+ *****************************************
37
+ */
38
+ function isEsmModule(dir, filename) {
39
+ if (filename) {
40
+ const result = isEsmFile(filename);
41
+ if (result !== undefined) {
42
+ return result;
43
+ }
44
+ }
45
+ // 判断为 ESM 模块
46
+ if (isEsmPackage(dir)) {
47
+ return true;
48
+ }
49
+ // 判断 TS 配置
50
+ const { module } = loadCompilerOptions(dir) || {};
51
+ if (module && module.toLowerCase().startsWith('es')) {
52
+ return true;
53
+ }
54
+ else {
55
+ return false;
56
+ }
57
+ }
58
+ /**
59
+ *****************************************
60
+ * 解析路径
61
+ *****************************************
62
+ */
63
+ export function resolvePath(id, issuer, options) {
64
+ const from = issuer ? dirname(resolve(issuer)) : process.cwd();
65
+ const opts = options || {};
66
+ const sys = createFileSystem(opts);
67
+ // 设置模块路径映射
68
+ if (!opts.paths && !opts.baseUrl) {
69
+ const { baseUrl, paths } = loadCompilerOptions(from) || {};
70
+ sys.baseUrl = baseUrl;
71
+ sys.paths = paths;
72
+ }
73
+ else {
74
+ sys.baseUrl = opts.baseUrl && resolve(opts.baseUrl);
75
+ }
76
+ // 设置加载条件
77
+ if (!opts.conditions) {
78
+ sys.conditions = isEsmModule(from, issuer) ? ['import', 'node'] : ['require', 'node'];
79
+ }
80
+ // 生成缓存 ID
81
+ sys.cacheSalt = sys.conditions.join(',');
82
+ // 执行解析
83
+ return sys.resolve(id, from);
84
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ *****************************************
3
+ * Created by edonet@163.com
4
+ * Created on 2025-05-26 22:30:23
5
+ *****************************************
6
+ */
7
+ 'use strict';
8
+ import { match } 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 resolvePaths(paths) {
24
+ return cached.get(paths, () => resolveDict(paths, resolvePath));
25
+ }
26
+ /**
27
+ *****************************************
28
+ * 解析匹配规则
29
+ *****************************************
30
+ */
31
+ function resolvePath(key, paths) {
32
+ const { test, resolve } = resolveDirect(key);
33
+ const rules = paths.map(resolve);
34
+ // 返回解析函数
35
+ return function resolve(id, handler) {
36
+ if (test(id)) {
37
+ return match(rules, direct => handler(direct(id)));
38
+ }
39
+ };
40
+ }
package/esm/split.mjs ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ *****************************************
3
+ * Created by edonet@163.com
4
+ * Created on 2025-05-24 23:56:16
5
+ *****************************************
6
+ */
7
+ 'use strict';
8
+ /**
9
+ *****************************************
10
+ * 分割字符串
11
+ *****************************************
12
+ */
13
+ export function split(str, sep) {
14
+ const idx = str.indexOf(sep);
15
+ // 执行切割
16
+ if (idx === -1) {
17
+ return [str, undefined];
18
+ }
19
+ else {
20
+ return [str.slice(0, idx), str.slice(idx + sep.length)];
21
+ }
22
+ }