@reliverse/pathkit 1.0.5 → 1.1.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 +19 -23
- package/bin/mod.d.ts +157 -31
- package/bin/mod.js +721 -43
- package/package.json +23 -4
- package/bin/pathkit-impl/_internal.d.ts +0 -1
- package/bin/pathkit-impl/_internal.js +0 -7
- package/bin/pathkit-impl/_path.d.ts +0 -26
- package/bin/pathkit-impl/_path.js +0 -206
- package/bin/pathkit-impl/args-impl.d.ts +0 -9
- package/bin/pathkit-impl/args-impl.js +0 -16
- package/bin/pathkit-impl/args-utils.d.ts +0 -30
- package/bin/pathkit-impl/args-utils.js +0 -75
package/bin/mod.js
CHANGED
|
@@ -1,50 +1,726 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
const EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
3
|
+
const SLASH = "/";
|
|
4
|
+
const BACK_SLASH = "\\";
|
|
5
|
+
const DOT = ".";
|
|
6
|
+
const DOUBLE_DOT = "..";
|
|
7
|
+
const EMPTY = "";
|
|
8
|
+
const normalizedAliasSymbol = Symbol.for("pathkit:normalizedAlias");
|
|
9
|
+
const DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
|
|
10
|
+
const DRIVE_LETTER_RE = /^[A-Za-z]:$/;
|
|
11
|
+
const UNC_REGEX = /^[/\\]{2}/;
|
|
12
|
+
const IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
13
|
+
const ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
14
|
+
const PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/;
|
|
15
|
+
const IMPORT_REGEX = /(?:import\s+(?:[\s\S]*?)\s+from\s+|import\s*\(\s*)\s*(['"])((?:@)[^'"]+)\1/g;
|
|
16
|
+
const log = (msg) => console.log(`\x1B[2m${msg}\x1B[0m`);
|
|
17
|
+
async function cleanDirs(dirs) {
|
|
18
|
+
await Promise.all(
|
|
19
|
+
dirs.map(async (d) => {
|
|
20
|
+
try {
|
|
21
|
+
await fs.rm(d, { recursive: true, force: true });
|
|
22
|
+
log(`\u2713 cleaned: ${d}`);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
log(
|
|
25
|
+
`\u2717 error cleaning ${d}: ${error instanceof Error ? error.message : String(error)}`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
async function copyDir(src, dest) {
|
|
32
|
+
log(`\u2713 copying: ${src} \u2192 ${dest}`);
|
|
33
|
+
try {
|
|
34
|
+
await fs.mkdir(dest, { recursive: true });
|
|
35
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
36
|
+
await Promise.all(
|
|
37
|
+
entries.map(async (entry) => {
|
|
38
|
+
const srcPath = join(src, entry.name);
|
|
39
|
+
const destPath = join(dest, entry.name);
|
|
40
|
+
if (entry.isDirectory()) {
|
|
41
|
+
return copyDir(srcPath, destPath);
|
|
42
|
+
}
|
|
43
|
+
await fs.copyFile(srcPath, destPath);
|
|
44
|
+
log(` copied: ${srcPath} \u2192 ${destPath}`);
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
49
|
+
log(`\u2717 error copying directory ${src} to ${dest}: ${errorMsg}`);
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function normalizeWindowsPath(input = "") {
|
|
54
|
+
if (!input) return input;
|
|
55
|
+
return input.replace(/\\/g, SLASH).replace(DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
56
|
+
}
|
|
57
|
+
function compareAliases(a, b) {
|
|
58
|
+
return b.split(SLASH).length - a.split(SLASH).length;
|
|
59
|
+
}
|
|
60
|
+
function cwd() {
|
|
61
|
+
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
|
62
|
+
return process.cwd().replace(/\\/g, SLASH);
|
|
63
|
+
}
|
|
64
|
+
return SLASH;
|
|
65
|
+
}
|
|
66
|
+
function normalizeString(path2, allowAboveRoot) {
|
|
67
|
+
let res = EMPTY;
|
|
68
|
+
let lastSegmentLength = 0;
|
|
69
|
+
let lastSlash = -1;
|
|
70
|
+
let dots = 0;
|
|
71
|
+
let char = null;
|
|
72
|
+
for (let index = 0; index <= path2.length; ++index) {
|
|
73
|
+
if (index < path2.length) {
|
|
74
|
+
char = path2[index];
|
|
75
|
+
} else if (char === SLASH) {
|
|
76
|
+
break;
|
|
77
|
+
} else {
|
|
78
|
+
char = SLASH;
|
|
79
|
+
}
|
|
80
|
+
if (char === SLASH) {
|
|
81
|
+
if (lastSlash === index - 1 || dots === 1) {
|
|
82
|
+
} else if (dots === 2) {
|
|
83
|
+
if (res.length < 2 || lastSegmentLength !== 2 || !res.endsWith(DOT) || res[res.length - 2] !== DOT) {
|
|
84
|
+
if (res.length > 2) {
|
|
85
|
+
const lastSlashIndex = res.lastIndexOf(SLASH);
|
|
86
|
+
if (lastSlashIndex === -1) {
|
|
87
|
+
res = EMPTY;
|
|
88
|
+
lastSegmentLength = 0;
|
|
89
|
+
} else {
|
|
90
|
+
res = res.slice(0, lastSlashIndex);
|
|
91
|
+
lastSegmentLength = res.length - 1 - res.lastIndexOf(SLASH);
|
|
92
|
+
}
|
|
93
|
+
lastSlash = index;
|
|
94
|
+
dots = 0;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (res.length > 0) {
|
|
98
|
+
res = EMPTY;
|
|
99
|
+
lastSegmentLength = 0;
|
|
100
|
+
lastSlash = index;
|
|
101
|
+
dots = 0;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (allowAboveRoot) {
|
|
106
|
+
res += res.length > 0 ? `${SLASH}..` : DOUBLE_DOT;
|
|
107
|
+
lastSegmentLength = 2;
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
const segment = path2.slice(lastSlash + 1, index);
|
|
111
|
+
if (res.length > 0) {
|
|
112
|
+
res += `${SLASH}${segment}`;
|
|
113
|
+
} else {
|
|
114
|
+
res = segment;
|
|
115
|
+
}
|
|
116
|
+
lastSegmentLength = segment.length;
|
|
117
|
+
}
|
|
118
|
+
lastSlash = index;
|
|
119
|
+
dots = 0;
|
|
120
|
+
} else if (char === DOT && dots !== -1) {
|
|
121
|
+
++dots;
|
|
122
|
+
} else {
|
|
123
|
+
dots = -1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return res;
|
|
127
|
+
}
|
|
128
|
+
const sep = SLASH;
|
|
129
|
+
const normalize = (path2) => {
|
|
130
|
+
if (path2.length === 0) return DOT;
|
|
131
|
+
const originalPath = path2;
|
|
132
|
+
path2 = normalizeWindowsPath(path2);
|
|
133
|
+
const isPathAbsolute = IS_ABSOLUTE_RE.test(path2);
|
|
134
|
+
const trailingSeparator = path2.endsWith(SLASH);
|
|
135
|
+
path2 = normalizeString(path2, !isPathAbsolute);
|
|
136
|
+
if (path2.length === 0) {
|
|
137
|
+
if (isPathAbsolute) return SLASH;
|
|
138
|
+
return trailingSeparator && originalPath.length > 0 && originalPath !== DOT ? "./" : DOT;
|
|
139
|
+
}
|
|
140
|
+
if (trailingSeparator && !path2.endsWith(SLASH)) {
|
|
141
|
+
path2 += SLASH;
|
|
142
|
+
}
|
|
143
|
+
if (DRIVE_LETTER_RE.test(path2) && path2.length === 2) {
|
|
144
|
+
path2 += SLASH;
|
|
145
|
+
}
|
|
146
|
+
if (UNC_REGEX.test(originalPath.replace(/\\/g, SLASH))) {
|
|
147
|
+
const normOriginal = originalPath.replace(/\\/g, SLASH);
|
|
148
|
+
if (normOriginal.startsWith("//./")) {
|
|
149
|
+
return `//./${path2.startsWith(SLASH) ? path2.substring(1) : path2}`;
|
|
150
|
+
}
|
|
151
|
+
if (normOriginal.startsWith("//") && !normOriginal.startsWith("//./")) {
|
|
152
|
+
return `//${path2.startsWith(SLASH) ? path2.substring(1) : path2}`;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (isPathAbsolute && !IS_ABSOLUTE_RE.test(path2) && path2 !== SLASH) {
|
|
156
|
+
return `${SLASH}${path2}`;
|
|
157
|
+
}
|
|
158
|
+
return path2;
|
|
159
|
+
};
|
|
160
|
+
const join = (...segments) => {
|
|
161
|
+
if (segments.length === 0) return DOT;
|
|
162
|
+
let joined = EMPTY;
|
|
163
|
+
for (const segment of segments) {
|
|
164
|
+
if (typeof segment !== "string") {
|
|
165
|
+
throw new TypeError("Arguments to path.join must be strings");
|
|
166
|
+
}
|
|
167
|
+
if (segment.length > 0) {
|
|
168
|
+
if (joined.length === 0) {
|
|
169
|
+
joined = segment;
|
|
170
|
+
} else {
|
|
171
|
+
joined += `${SLASH}${segment}`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (joined.length === 0) return DOT;
|
|
176
|
+
return normalize(joined);
|
|
177
|
+
};
|
|
178
|
+
const resolve = (...args) => {
|
|
179
|
+
let resolvedPath = EMPTY;
|
|
180
|
+
let resolvedAbsolute = false;
|
|
181
|
+
for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
|
182
|
+
const path2 = i >= 0 ? args[i] : cwd();
|
|
183
|
+
if (typeof path2 !== "string") {
|
|
184
|
+
throw new TypeError("Arguments to path.resolve must be strings");
|
|
185
|
+
}
|
|
186
|
+
if (path2.length === 0) continue;
|
|
187
|
+
const normalizedSegment = normalizeWindowsPath(path2);
|
|
188
|
+
resolvedPath = `${normalizedSegment}${SLASH}${resolvedPath}`;
|
|
189
|
+
resolvedAbsolute = IS_ABSOLUTE_RE.test(normalizedSegment);
|
|
190
|
+
}
|
|
191
|
+
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
|
|
192
|
+
if (resolvedAbsolute) {
|
|
193
|
+
if (IS_ABSOLUTE_RE.test(resolvedPath)) {
|
|
194
|
+
return resolvedPath;
|
|
195
|
+
}
|
|
196
|
+
return `${SLASH}${resolvedPath}`;
|
|
197
|
+
}
|
|
198
|
+
return resolvedPath.length > 0 ? resolvedPath : DOT;
|
|
199
|
+
};
|
|
200
|
+
const isAbsolute = (p) => {
|
|
201
|
+
if (typeof p !== "string") return false;
|
|
202
|
+
return IS_ABSOLUTE_RE.test(normalizeWindowsPath(p));
|
|
203
|
+
};
|
|
204
|
+
const toNamespacedPath = (p) => {
|
|
205
|
+
if (typeof p !== "string" || p.length === 0) return p;
|
|
206
|
+
return normalize(p);
|
|
207
|
+
};
|
|
208
|
+
const extname = (p) => {
|
|
209
|
+
if (typeof p !== "string") return EMPTY;
|
|
210
|
+
const path2 = normalizeWindowsPath(p);
|
|
211
|
+
let lastSlashIdx = path2.lastIndexOf(SLASH);
|
|
212
|
+
if (lastSlashIdx === -1) lastSlashIdx = 0;
|
|
213
|
+
const basePart = lastSlashIdx === 0 ? path2 : path2.substring(lastSlashIdx + 1);
|
|
214
|
+
if (basePart === DOT || basePart === DOUBLE_DOT) return EMPTY;
|
|
215
|
+
const lastDotIdx = basePart.lastIndexOf(DOT);
|
|
216
|
+
if (lastDotIdx <= 0) return EMPTY;
|
|
217
|
+
return basePart.substring(lastDotIdx);
|
|
218
|
+
};
|
|
219
|
+
const relative = (from, to) => {
|
|
220
|
+
const resolvedFrom = resolve(from);
|
|
221
|
+
const resolvedTo = resolve(to);
|
|
222
|
+
if (resolvedFrom === resolvedTo) return EMPTY;
|
|
223
|
+
const fromSegments = resolvedFrom.replace(ROOT_FOLDER_RE, "$1").split(SLASH).filter(Boolean);
|
|
224
|
+
const toSegments = resolvedTo.replace(ROOT_FOLDER_RE, "$1").split(SLASH).filter(Boolean);
|
|
225
|
+
if (fromSegments.length > 0 && toSegments.length > 0 && DRIVE_LETTER_RE.test(fromSegments[0]) && DRIVE_LETTER_RE.test(toSegments[0]) && fromSegments[0].toUpperCase() !== toSegments[0].toUpperCase()) {
|
|
226
|
+
return resolvedTo;
|
|
227
|
+
}
|
|
228
|
+
let commonSegments = 0;
|
|
229
|
+
const maxCommon = Math.min(fromSegments.length, toSegments.length);
|
|
230
|
+
while (commonSegments < maxCommon && fromSegments[commonSegments] === toSegments[commonSegments]) {
|
|
231
|
+
commonSegments++;
|
|
232
|
+
}
|
|
233
|
+
const upSegments = Array(fromSegments.length - commonSegments).fill(
|
|
234
|
+
DOUBLE_DOT
|
|
235
|
+
);
|
|
236
|
+
const downSegments = toSegments.slice(commonSegments);
|
|
237
|
+
const result = [...upSegments, ...downSegments].join(SLASH);
|
|
238
|
+
return result.length > 0 ? result : DOT;
|
|
239
|
+
};
|
|
240
|
+
const dirname = (p) => {
|
|
241
|
+
if (typeof p !== "string" || p.length === 0) return DOT;
|
|
242
|
+
const normalizedPath = normalizeWindowsPath(p);
|
|
243
|
+
const lastSlash = normalizedPath.lastIndexOf(SLASH);
|
|
244
|
+
if (lastSlash === -1) {
|
|
245
|
+
return IS_ABSOLUTE_RE.test(normalizedPath) ? SLASH : DOT;
|
|
246
|
+
}
|
|
247
|
+
if (lastSlash === 0) return SLASH;
|
|
248
|
+
const dir = normalizedPath.slice(0, lastSlash);
|
|
249
|
+
if (DRIVE_LETTER_RE.test(dir) && dir.length === 2) {
|
|
250
|
+
return dir + SLASH;
|
|
251
|
+
}
|
|
252
|
+
return normalize(dir);
|
|
253
|
+
};
|
|
254
|
+
const format = (p) => {
|
|
255
|
+
if (typeof p !== "object" || p === null) {
|
|
256
|
+
throw new TypeError(
|
|
257
|
+
'Parameter "pathObject" must be an object, not null or other type.'
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
const dir = p.dir || p.root || "";
|
|
261
|
+
const base = p.base || `${p.name || ""}${p.ext || ""}`;
|
|
262
|
+
if (!dir) return base;
|
|
263
|
+
if (dir === p.root) return `${dir}${base}`;
|
|
264
|
+
return normalize(`${dir}${SLASH}${base}`);
|
|
265
|
+
};
|
|
266
|
+
const basename = (p, ext) => {
|
|
267
|
+
if (typeof p !== "string") throw new TypeError("Path must be a string.");
|
|
268
|
+
if (ext !== void 0 && typeof ext !== "string")
|
|
269
|
+
throw new TypeError("[basename] `ext` must be a string.");
|
|
270
|
+
const normalizedPath = normalizeWindowsPath(p);
|
|
271
|
+
let end = normalizedPath.length;
|
|
272
|
+
while (end > 0 && normalizedPath[end - 1] === SLASH) {
|
|
273
|
+
end--;
|
|
274
|
+
}
|
|
275
|
+
if (end === 0) return EMPTY;
|
|
276
|
+
let start = normalizedPath.lastIndexOf(SLASH, end - 1);
|
|
277
|
+
start = start === -1 ? 0 : start + 1;
|
|
278
|
+
let filename2 = normalizedPath.slice(start, end);
|
|
279
|
+
if (ext && filename2.endsWith(ext) && filename2 !== ext) {
|
|
280
|
+
filename2 = filename2.slice(0, filename2.length - ext.length);
|
|
281
|
+
}
|
|
282
|
+
return filename2;
|
|
283
|
+
};
|
|
284
|
+
const parse = (p) => {
|
|
285
|
+
if (typeof p !== "string") throw new TypeError("Path must be a string.");
|
|
286
|
+
const normalizedPath = normalizeWindowsPath(p);
|
|
287
|
+
const B = basename(normalizedPath);
|
|
288
|
+
const E = extname(B);
|
|
289
|
+
const N = B.slice(0, B.length - E.length);
|
|
290
|
+
const D = dirname(normalizedPath);
|
|
291
|
+
let R = EMPTY;
|
|
292
|
+
const rootMatch = PATH_ROOT_RE.exec(normalizedPath);
|
|
293
|
+
if (rootMatch) {
|
|
294
|
+
R = rootMatch[0];
|
|
295
|
+
if (DRIVE_LETTER_RE.test(R) && R.length === 2 && normalizedPath.length > 2 && normalizedPath[2] === SLASH) {
|
|
296
|
+
R += SLASH;
|
|
297
|
+
} else if (R === SLASH && D.startsWith("//")) {
|
|
298
|
+
if (UNC_REGEX.exec(D)) {
|
|
299
|
+
const uncParts = D.split(SLASH).slice(0, 3);
|
|
300
|
+
R = uncParts.join(SLASH) || R;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const resolvedDir = D === DOT && R !== EMPTY && R !== DOT ? R : D;
|
|
305
|
+
return {
|
|
306
|
+
root: R,
|
|
307
|
+
dir: resolvedDir,
|
|
308
|
+
base: B,
|
|
309
|
+
ext: E,
|
|
310
|
+
name: N
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
function filename(pathString) {
|
|
314
|
+
const base = basename(pathString);
|
|
315
|
+
if (!base) return void 0;
|
|
316
|
+
const separatorIndex = base.lastIndexOf(DOT);
|
|
317
|
+
return separatorIndex <= 0 ? base : base.slice(0, separatorIndex);
|
|
318
|
+
}
|
|
319
|
+
function normalizeAliases(aliases) {
|
|
320
|
+
if (aliases[normalizedAliasSymbol]) {
|
|
321
|
+
return aliases;
|
|
322
|
+
}
|
|
323
|
+
const sortedAliasesEntries = Object.entries(aliases).map(
|
|
324
|
+
([key, value]) => [normalizeWindowsPath(key), normalizeWindowsPath(value)]
|
|
325
|
+
).sort(([a], [b]) => compareAliases(a, b));
|
|
326
|
+
const sortedAliases = Object.fromEntries(sortedAliasesEntries);
|
|
327
|
+
for (const key in sortedAliases) {
|
|
328
|
+
for (const aliasPrefix in sortedAliases) {
|
|
329
|
+
if (aliasPrefix === key || key.startsWith(aliasPrefix + SLASH) || key === aliasPrefix)
|
|
330
|
+
continue;
|
|
331
|
+
const value = sortedAliases[key];
|
|
332
|
+
if (value?.startsWith(aliasPrefix)) {
|
|
333
|
+
const nextChar = value[aliasPrefix.length];
|
|
334
|
+
if (nextChar === void 0 || nextChar === SLASH) {
|
|
335
|
+
sortedAliases[key] = sortedAliases[aliasPrefix] + value.slice(aliasPrefix.length);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const finalNormalizedAliases = { ...sortedAliases };
|
|
341
|
+
Object.defineProperty(finalNormalizedAliases, normalizedAliasSymbol, {
|
|
342
|
+
value: true,
|
|
343
|
+
enumerable: false
|
|
344
|
+
});
|
|
345
|
+
return finalNormalizedAliases;
|
|
346
|
+
}
|
|
347
|
+
function resolveAlias(path2, aliases) {
|
|
348
|
+
const normalizedPath = normalizeWindowsPath(path2);
|
|
349
|
+
const normalizedAliases = normalizeAliases(aliases);
|
|
350
|
+
for (const [alias, to] of Object.entries(normalizedAliases)) {
|
|
351
|
+
const effectiveAlias = alias.endsWith(SLASH) ? alias : alias + SLASH;
|
|
352
|
+
const effectivePath = normalizedPath.endsWith(SLASH) ? normalizedPath : normalizedPath + SLASH;
|
|
353
|
+
if (effectivePath.startsWith(effectiveAlias)) {
|
|
354
|
+
return join(to, normalizedPath.slice(alias.length));
|
|
355
|
+
}
|
|
356
|
+
if (normalizedPath === alias) {
|
|
357
|
+
return to;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return normalizedPath;
|
|
361
|
+
}
|
|
362
|
+
function reverseResolveAlias(path2, aliases) {
|
|
363
|
+
const normalizedPath = normalizeWindowsPath(path2);
|
|
364
|
+
const normalizedAliases = normalizeAliases(aliases);
|
|
365
|
+
const matches = [];
|
|
366
|
+
for (const [alias, to] of Object.entries(normalizedAliases)) {
|
|
367
|
+
const effectiveTo = to.endsWith(SLASH) ? to : to + SLASH;
|
|
368
|
+
const effectivePath = normalizedPath.endsWith(SLASH) ? normalizedPath : normalizedPath + SLASH;
|
|
369
|
+
if (effectivePath.startsWith(effectiveTo)) {
|
|
370
|
+
matches.push(join(alias, normalizedPath.slice(to.length)));
|
|
371
|
+
}
|
|
372
|
+
if (normalizedPath === to) {
|
|
373
|
+
matches.push(alias);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return matches.sort((a, b) => b.length - a.length);
|
|
377
|
+
}
|
|
378
|
+
const findAliasMatch = (importPath, paths) => {
|
|
379
|
+
if (paths[importPath]?.[0]) {
|
|
380
|
+
return {
|
|
381
|
+
key: importPath,
|
|
382
|
+
root: importPath,
|
|
383
|
+
resolvedPath: paths[importPath][0],
|
|
384
|
+
suffix: ""
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
for (const aliasKey in paths) {
|
|
388
|
+
if (aliasKey.endsWith("/*")) {
|
|
389
|
+
const aliasRoot = aliasKey.slice(0, -2);
|
|
390
|
+
if (importPath === aliasRoot || importPath.startsWith(`${aliasRoot}/`)) {
|
|
391
|
+
const suffix = importPath === aliasRoot ? "" : importPath.slice(aliasRoot.length + 1);
|
|
392
|
+
const targetPaths = paths[aliasKey];
|
|
393
|
+
if (targetPaths?.[0]) {
|
|
394
|
+
const resolvedPathPattern = targetPaths[0].slice(0, -2);
|
|
395
|
+
return {
|
|
396
|
+
key: aliasKey,
|
|
397
|
+
root: aliasRoot,
|
|
398
|
+
resolvedPath: resolvedPathPattern,
|
|
399
|
+
suffix
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return null;
|
|
406
|
+
};
|
|
407
|
+
const toRelativeImport = (absPath, fromDir) => {
|
|
408
|
+
const rel = normalizeWindowsPath(relative(fromDir, absPath));
|
|
409
|
+
return rel.startsWith(DOT) ? rel : `./${rel}`;
|
|
410
|
+
};
|
|
411
|
+
async function resolveFileWithExtensions(basePath, extensions = ["", ...EXTENSIONS, ".json"]) {
|
|
412
|
+
for (const ext of extensions) {
|
|
413
|
+
try {
|
|
414
|
+
const fullPath = basePath + ext;
|
|
415
|
+
const stat = await fs.stat(fullPath);
|
|
416
|
+
if (stat.isFile()) {
|
|
417
|
+
return fullPath;
|
|
418
|
+
}
|
|
419
|
+
} catch {
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
for (const ext of extensions) {
|
|
423
|
+
try {
|
|
424
|
+
const indexPath = join(basePath, `index${ext}`);
|
|
425
|
+
const stat = await fs.stat(indexPath);
|
|
426
|
+
if (stat.isFile()) {
|
|
427
|
+
return indexPath;
|
|
428
|
+
}
|
|
429
|
+
} catch {
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
function getTargetExtension(relPath, originalExt) {
|
|
435
|
+
const foundExt = extname(relPath);
|
|
436
|
+
if (originalExt) {
|
|
437
|
+
return relPath;
|
|
438
|
+
}
|
|
439
|
+
if (foundExt) {
|
|
440
|
+
return relPath.slice(0, -foundExt.length);
|
|
441
|
+
}
|
|
442
|
+
return relPath;
|
|
443
|
+
}
|
|
444
|
+
async function convertStringAliasRelative({
|
|
445
|
+
importPath,
|
|
446
|
+
importerFile,
|
|
447
|
+
pathPattern,
|
|
448
|
+
targetDir
|
|
449
|
+
}) {
|
|
450
|
+
const paths = { [pathPattern]: ["./*"] };
|
|
451
|
+
const importerDir = dirname(importerFile);
|
|
452
|
+
const match = findAliasMatch(importPath, paths);
|
|
453
|
+
if (!match) return importPath;
|
|
454
|
+
const absPath = resolve(targetDir, match.resolvedPath, match.suffix);
|
|
455
|
+
const resolvedFile = await resolveFileWithExtensions(absPath);
|
|
456
|
+
const relPath = toRelativeImport(resolvedFile || absPath, importerDir);
|
|
457
|
+
const originalExt = extname(importPath);
|
|
458
|
+
return getTargetExtension(relPath, originalExt);
|
|
459
|
+
}
|
|
460
|
+
function replaceAllInString(original, searchValue, replaceValue) {
|
|
461
|
+
let currentPosition = 0;
|
|
462
|
+
let result = "";
|
|
463
|
+
while (currentPosition < original.length) {
|
|
464
|
+
const foundIdx = original.indexOf(searchValue, currentPosition);
|
|
465
|
+
if (foundIdx === -1) {
|
|
466
|
+
result += original.substring(currentPosition);
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
result += original.substring(currentPosition, foundIdx);
|
|
470
|
+
result += replaceValue;
|
|
471
|
+
currentPosition = foundIdx + searchValue.length;
|
|
472
|
+
}
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
475
|
+
async function processFile(filePath, aliasToReplace, targetDir, pathExtFilter) {
|
|
476
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
477
|
+
let updated = content;
|
|
478
|
+
const changes = [];
|
|
479
|
+
const matches = Array.from(content.matchAll(IMPORT_REGEX));
|
|
480
|
+
const normalizedAlias = aliasToReplace.endsWith("/*") ? aliasToReplace : `${aliasToReplace}/*`;
|
|
481
|
+
for (const match of matches) {
|
|
482
|
+
const originalQuote = match[1];
|
|
483
|
+
const importPath = match[2];
|
|
484
|
+
const importExt = extname(importPath);
|
|
485
|
+
const shouldProcess = pathExtFilter === "js" && importExt === ".js" || pathExtFilter === "ts" && importExt === ".ts" || pathExtFilter === "none" && importExt === "" || pathExtFilter === "js-ts-none";
|
|
486
|
+
if (!shouldProcess) continue;
|
|
487
|
+
const relPath = await convertStringAliasRelative({
|
|
488
|
+
importPath,
|
|
489
|
+
importerFile: filePath,
|
|
490
|
+
pathPattern: normalizedAlias,
|
|
491
|
+
targetDir
|
|
492
|
+
});
|
|
493
|
+
if (importPath !== relPath) {
|
|
494
|
+
changes.push({ from: importPath, to: relPath });
|
|
495
|
+
const searchString = `${originalQuote}${importPath}${originalQuote}`;
|
|
496
|
+
const replacementString = `${originalQuote}${relPath}${originalQuote}`;
|
|
497
|
+
updated = replaceAllInString(updated, searchString, replacementString);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
if (content !== updated) {
|
|
501
|
+
await fs.writeFile(filePath, updated);
|
|
502
|
+
log(`\u2713 processed: ${filePath}`);
|
|
503
|
+
}
|
|
504
|
+
return changes;
|
|
505
|
+
}
|
|
506
|
+
async function processAllFiles({
|
|
507
|
+
srcDir,
|
|
508
|
+
aliasToReplace,
|
|
509
|
+
extensionsToProcess,
|
|
510
|
+
rootDir,
|
|
511
|
+
pathExtFilter
|
|
512
|
+
}) {
|
|
513
|
+
try {
|
|
514
|
+
const entries = await fs.readdir(srcDir, { withFileTypes: true });
|
|
515
|
+
const results = [];
|
|
516
|
+
await Promise.all(
|
|
517
|
+
entries.map(async (entry) => {
|
|
518
|
+
const fullPath = join(srcDir, entry.name);
|
|
519
|
+
if (entry.isDirectory()) {
|
|
520
|
+
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
521
|
+
return;
|
|
522
|
+
const subdirResults = await processAllFiles({
|
|
523
|
+
srcDir: fullPath,
|
|
524
|
+
aliasToReplace,
|
|
525
|
+
extensionsToProcess,
|
|
526
|
+
rootDir,
|
|
527
|
+
pathExtFilter
|
|
528
|
+
});
|
|
529
|
+
results.push(...subdirResults);
|
|
530
|
+
} else if (extensionsToProcess.includes(extname(entry.name))) {
|
|
531
|
+
const changes = await processFile(
|
|
532
|
+
fullPath,
|
|
533
|
+
aliasToReplace,
|
|
534
|
+
rootDir,
|
|
535
|
+
pathExtFilter
|
|
536
|
+
);
|
|
537
|
+
if (changes.length > 0) {
|
|
538
|
+
results.push({ file: fullPath, changes });
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
})
|
|
542
|
+
);
|
|
543
|
+
return results;
|
|
544
|
+
} catch (error) {
|
|
545
|
+
log(
|
|
546
|
+
`error processing directory ${srcDir}: ${error instanceof Error ? error.message : String(error)}`
|
|
547
|
+
);
|
|
548
|
+
return [];
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
async function convertImportsAliasToRelative({
|
|
552
|
+
targetDir,
|
|
553
|
+
aliasToReplace,
|
|
554
|
+
// e.g. @, ~, @/*, ~/*
|
|
555
|
+
pathExtFilter
|
|
556
|
+
}) {
|
|
557
|
+
const normalizedAlias = aliasToReplace.endsWith("/*") ? aliasToReplace : `${aliasToReplace}/*`;
|
|
558
|
+
log(
|
|
559
|
+
`Converting aliased imports starting with '${aliasToReplace}' to relative paths in "${targetDir}"...`
|
|
560
|
+
);
|
|
561
|
+
log(` (Assuming "${normalizedAlias}" resolves relative to "${targetDir}")`);
|
|
562
|
+
log(` (Using extension mode: ${pathExtFilter})`);
|
|
563
|
+
const results = await processAllFiles({
|
|
564
|
+
srcDir: targetDir,
|
|
565
|
+
aliasToReplace: normalizedAlias,
|
|
566
|
+
extensionsToProcess: EXTENSIONS,
|
|
567
|
+
rootDir: targetDir,
|
|
568
|
+
pathExtFilter
|
|
569
|
+
});
|
|
570
|
+
if (results.length > 0) {
|
|
571
|
+
log("\n[convertImportsAliasToRelative] Summary of changes:");
|
|
572
|
+
for (const { file, changes } of results) {
|
|
573
|
+
const displayPath = relative(targetDir, file) || basename(file);
|
|
574
|
+
log(` in ${displayPath}:`);
|
|
575
|
+
for (const { from, to } of changes) {
|
|
576
|
+
log(` - ${from} \u2192 ${to}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
} else {
|
|
580
|
+
}
|
|
581
|
+
log("Import path conversion process complete.");
|
|
582
|
+
return results;
|
|
583
|
+
}
|
|
584
|
+
async function convertImportsExt({
|
|
585
|
+
targetDir,
|
|
586
|
+
extFrom,
|
|
587
|
+
extTo
|
|
588
|
+
}) {
|
|
589
|
+
const fromExtStr = extFrom === "none" ? "" : `.${extFrom}`;
|
|
590
|
+
const toExtStr = extTo === "none" ? "" : `.${extTo}`;
|
|
591
|
+
const importRegex = new RegExp(
|
|
592
|
+
`(?:import\\s+(?:[\\s\\S]*?)\\s+from\\s+|import\\s*\\(\\s*)\\s*(['"])([^'"]+${fromExtStr.replace(".", "\\.")})(\\1)`,
|
|
593
|
+
"g"
|
|
594
|
+
);
|
|
595
|
+
try {
|
|
596
|
+
const entries = await fs.readdir(targetDir, { withFileTypes: true });
|
|
597
|
+
const results = [];
|
|
598
|
+
await Promise.all(
|
|
599
|
+
entries.map(async (entry) => {
|
|
600
|
+
const fullPath = join(targetDir, entry.name);
|
|
601
|
+
if (entry.isDirectory()) {
|
|
602
|
+
if (entry.name === "node_modules" || entry.name.startsWith(".")) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
const subdirResults = await convertImportsExt({
|
|
606
|
+
targetDir: fullPath,
|
|
607
|
+
extFrom,
|
|
608
|
+
extTo
|
|
609
|
+
});
|
|
610
|
+
results.push(...subdirResults);
|
|
611
|
+
} else if (EXTENSIONS.includes(extname(entry.name))) {
|
|
612
|
+
const content = await fs.readFile(fullPath, "utf-8");
|
|
613
|
+
let updated = content;
|
|
614
|
+
const changes = [];
|
|
615
|
+
const matches = Array.from(content.matchAll(importRegex));
|
|
616
|
+
for (const match of matches) {
|
|
617
|
+
const quote = match[1];
|
|
618
|
+
const importPath = match[2];
|
|
619
|
+
let replacementPath;
|
|
620
|
+
if (extFrom === "none") {
|
|
621
|
+
replacementPath = importPath + toExtStr;
|
|
622
|
+
} else if (extTo === "none") {
|
|
623
|
+
replacementPath = importPath.slice(0, -fromExtStr.length);
|
|
624
|
+
} else {
|
|
625
|
+
replacementPath = importPath.slice(0, -fromExtStr.length) + toExtStr;
|
|
626
|
+
}
|
|
627
|
+
if (importPath === replacementPath) continue;
|
|
628
|
+
changes.push({ from: importPath, to: replacementPath });
|
|
629
|
+
const searchStr = `${quote}${importPath}${quote}`;
|
|
630
|
+
const replaceStr = `${quote}${replacementPath}${quote}`;
|
|
631
|
+
updated = replaceAllInString(updated, searchStr, replaceStr);
|
|
632
|
+
}
|
|
633
|
+
if (content !== updated) {
|
|
634
|
+
await fs.writeFile(fullPath, updated);
|
|
635
|
+
log(`\u2713 processed: ${fullPath}`);
|
|
636
|
+
if (changes.length > 0) {
|
|
637
|
+
results.push({ file: fullPath, changes });
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
})
|
|
642
|
+
);
|
|
643
|
+
if (results.length > 0) {
|
|
644
|
+
log("\n[convertImportsExt] Summary of changes:");
|
|
645
|
+
for (const { file, changes } of results) {
|
|
646
|
+
const displayPath = relative(targetDir, file) || basename(file);
|
|
647
|
+
log(` in ${displayPath}:`);
|
|
648
|
+
for (const { from, to } of changes) {
|
|
649
|
+
log(` - ${from} \u2192 ${to}`);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
} else {
|
|
653
|
+
}
|
|
654
|
+
return results;
|
|
655
|
+
} catch (error) {
|
|
656
|
+
log(
|
|
657
|
+
`error processing directory ${targetDir}: ${error instanceof Error ? error.message : String(error)}`
|
|
658
|
+
);
|
|
659
|
+
return [];
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
const _pathBase = {
|
|
3
663
|
sep,
|
|
4
664
|
normalize,
|
|
5
665
|
join,
|
|
6
666
|
resolve,
|
|
7
|
-
normalizeString,
|
|
8
667
|
isAbsolute,
|
|
9
|
-
toNamespacedPath,
|
|
10
|
-
extname,
|
|
11
|
-
relative,
|
|
12
668
|
dirname,
|
|
13
|
-
format,
|
|
14
|
-
basename,
|
|
15
|
-
parse
|
|
16
|
-
} from "./pathkit-impl/_path.js";
|
|
17
|
-
import { delimiter, posix, win32 } from "./pathkit-impl/args-impl.js";
|
|
18
|
-
import {
|
|
19
|
-
normalizeAliases,
|
|
20
|
-
resolveAlias,
|
|
21
|
-
reverseResolveAlias,
|
|
22
|
-
filename
|
|
23
|
-
} from "./pathkit-impl/args-utils.js";
|
|
24
|
-
export {
|
|
25
669
|
basename,
|
|
26
|
-
delimiter,
|
|
27
|
-
dirname,
|
|
28
670
|
extname,
|
|
29
|
-
filename,
|
|
30
671
|
format,
|
|
31
|
-
isAbsolute,
|
|
32
|
-
join,
|
|
33
|
-
normalize,
|
|
34
|
-
normalizeAliases,
|
|
35
|
-
normalizeString,
|
|
36
|
-
normalizeWindowsPath,
|
|
37
672
|
parse,
|
|
38
|
-
posix,
|
|
39
|
-
relative,
|
|
40
|
-
resolve,
|
|
41
|
-
resolveAlias,
|
|
42
|
-
reverseResolveAlias,
|
|
43
|
-
sep,
|
|
44
673
|
toNamespacedPath,
|
|
45
|
-
|
|
674
|
+
relative,
|
|
675
|
+
filename
|
|
676
|
+
};
|
|
677
|
+
const _platforms = {
|
|
678
|
+
posix: { ..._pathBase },
|
|
679
|
+
win32: {
|
|
680
|
+
..._pathBase,
|
|
681
|
+
sep: BACK_SLASH,
|
|
682
|
+
delimiter: ";",
|
|
683
|
+
isAbsolute: (p) => {
|
|
684
|
+
if (typeof p !== "string") return false;
|
|
685
|
+
return /^[a-zA-Z]:[/\\]/.test(p) || /^[/\\]{2}/.test(p);
|
|
686
|
+
},
|
|
687
|
+
toNamespacedPath: (p) => {
|
|
688
|
+
if (typeof p !== "string" || p.length === 0) return p;
|
|
689
|
+
const resolved = resolve(p);
|
|
690
|
+
if (/^[a-zA-Z]:/.test(resolved)) {
|
|
691
|
+
return `\\\\?\\${resolved.replace(/\//g, BACK_SLASH)}`;
|
|
692
|
+
}
|
|
693
|
+
if (/^[/\\]{2}/.test(resolved)) {
|
|
694
|
+
return `\\\\?\\UNC\\${resolved.substring(2).replace(/\//g, BACK_SLASH)}`;
|
|
695
|
+
}
|
|
696
|
+
return p.replace(/\//g, BACK_SLASH);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
const mix = (platformDefault = "currentSystem") => {
|
|
701
|
+
const actualDefault = platformDefault === "currentSystem" ? globalThis.process?.platform === "win32" ? "win32" : "posix" : platformDefault;
|
|
702
|
+
const defaultPathObject = actualDefault === "win32" ? _platforms.win32 : _platforms.posix;
|
|
703
|
+
return new Proxy(defaultPathObject, {
|
|
704
|
+
get(target, prop) {
|
|
705
|
+
if (prop === "delimiter") return actualDefault === "win32" ? ";" : ":";
|
|
706
|
+
if (prop === "posix") return _platforms.posix;
|
|
707
|
+
if (prop === "win32") return _platforms.win32;
|
|
708
|
+
if (prop in target) {
|
|
709
|
+
return target[prop];
|
|
710
|
+
}
|
|
711
|
+
if (prop in _pathBase) {
|
|
712
|
+
return _pathBase[prop];
|
|
713
|
+
}
|
|
714
|
+
return void 0;
|
|
715
|
+
}
|
|
716
|
+
});
|
|
46
717
|
};
|
|
47
|
-
const
|
|
718
|
+
const path = mix();
|
|
719
|
+
const win32 = _platforms.win32;
|
|
720
|
+
const delimiter = globalThis.process?.platform === "win32" ? ";" : ":";
|
|
721
|
+
export {
|
|
722
|
+
_pathBase as posix,
|
|
723
|
+
win32,
|
|
48
724
|
basename,
|
|
49
725
|
delimiter,
|
|
50
726
|
dirname,
|
|
@@ -54,17 +730,19 @@ const pathObj = {
|
|
|
54
730
|
isAbsolute,
|
|
55
731
|
join,
|
|
56
732
|
normalize,
|
|
57
|
-
normalizeAliases,
|
|
58
|
-
normalizeString,
|
|
59
|
-
normalizeWindowsPath,
|
|
60
733
|
parse,
|
|
61
|
-
posix,
|
|
62
734
|
relative,
|
|
63
735
|
resolve,
|
|
64
|
-
resolveAlias,
|
|
65
|
-
reverseResolveAlias,
|
|
66
736
|
sep,
|
|
67
737
|
toNamespacedPath,
|
|
68
|
-
|
|
738
|
+
normalizeAliases,
|
|
739
|
+
resolveAlias,
|
|
740
|
+
reverseResolveAlias,
|
|
741
|
+
normalizeWindowsPath,
|
|
742
|
+
cleanDirs,
|
|
743
|
+
copyDir,
|
|
744
|
+
convertStringAliasRelative,
|
|
745
|
+
convertImportsAliasToRelative,
|
|
746
|
+
convertImportsExt
|
|
69
747
|
};
|
|
70
|
-
export default
|
|
748
|
+
export default path;
|