@reliverse/pathkit 1.1.4 → 1.1.6
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 +1 -1
- package/bin/impl/getFileImportsExports.d.ts +27 -0
- package/bin/impl/getFileImportsExports.js +189 -0
- package/bin/mod.d.ts +3 -10
- package/bin/mod.js +9 -80
- package/package.json +3 -21
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
- ⚙️ **node.js api compatible** – familiar methods, no learning curve
|
|
13
13
|
- 🚀 **modern & fast** – typescript, pure esm, bun & node‑ready
|
|
14
14
|
- 🧠 **predictable & testable** – deterministic output across windows / macos / linux
|
|
15
|
-
- 🧼 **no dependencies** – just better path api + couple of cool utilities = [
|
|
15
|
+
- 🧼 **no dependencies** – just better path api + couple of cool utilities = [4kB](https://bundlephobia.com/package/@reliverse/pathkit@latest)
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface ImportExportSpecifier {
|
|
2
|
+
type: "named" | "default" | "namespace" | "all";
|
|
3
|
+
name: string;
|
|
4
|
+
alias?: string;
|
|
5
|
+
isType?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface ImportExportInfo {
|
|
8
|
+
statement: string;
|
|
9
|
+
type: "static" | "dynamic";
|
|
10
|
+
kind: "import" | "export";
|
|
11
|
+
source?: string;
|
|
12
|
+
pathType?: "alias" | "relative" | "absolute" | "bare" | "module";
|
|
13
|
+
pathTypeSymbol?: string;
|
|
14
|
+
isTypeOnly?: boolean;
|
|
15
|
+
specifiers?: ImportExportSpecifier[];
|
|
16
|
+
start: number;
|
|
17
|
+
end: number;
|
|
18
|
+
}
|
|
19
|
+
export interface GetFileImportsExportsOptions {
|
|
20
|
+
kind?: "import" | "export" | "all";
|
|
21
|
+
pathTypes?: ("alias" | "relative" | "absolute" | "bare" | "module")[];
|
|
22
|
+
limitPerType?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* analyzes a file's content to extract import and export statements
|
|
26
|
+
*/
|
|
27
|
+
export declare function getFileImportsExports(content: string, options?: GetFileImportsExportsOptions): ImportExportInfo[];
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
export function getFileImportsExports(content, options = {}) {
|
|
2
|
+
const {
|
|
3
|
+
kind = "all",
|
|
4
|
+
pathTypes = ["alias", "relative", "absolute", "bare", "module"],
|
|
5
|
+
limitPerType
|
|
6
|
+
} = options;
|
|
7
|
+
const results = [];
|
|
8
|
+
const patterns = {
|
|
9
|
+
// import statements with from clause
|
|
10
|
+
staticImport: /import\s+(?:type\s+)?(?:(?:\w+)(?:\s*,\s*)?)?(?:\{[^}]*\}|\*\s+as\s+\w+)?\s+from\s+['"]([^'"]+)['"]|import\s+(?:type\s+)?(\w+)\s+from\s+['"]([^'"]+)['"]/g,
|
|
11
|
+
// dynamic imports
|
|
12
|
+
dynamicImport: /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
13
|
+
// export statements with from clause
|
|
14
|
+
staticExport: /export\s+(?:type\s+)?(?:\{[^}]*\}|\*(?:\s+as\s+\w+)?)\s+from\s+['"]([^'"]+)['"]/g,
|
|
15
|
+
// default exports without from
|
|
16
|
+
defaultExport: /export\s+default\s+(?:\w+|\{[^}]*\}|class\s+\w+|function\s+\w+)/g,
|
|
17
|
+
// named exports without from
|
|
18
|
+
namedExport: /export\s+(?:const|let|var|function|class|enum|interface|type)\s+(\w+)/g
|
|
19
|
+
};
|
|
20
|
+
function getPathType(path) {
|
|
21
|
+
if (path.startsWith(".")) return "relative";
|
|
22
|
+
if (path.startsWith("/")) return "absolute";
|
|
23
|
+
if (path.startsWith("@") || path.startsWith("~")) return "alias";
|
|
24
|
+
if (path.startsWith("http://") || path.startsWith("https://"))
|
|
25
|
+
return "module";
|
|
26
|
+
return "bare";
|
|
27
|
+
}
|
|
28
|
+
function extractSpecifiers(statement) {
|
|
29
|
+
const specifiers = [];
|
|
30
|
+
const isTypeOnly = statement.includes("import type") || statement.includes("export type");
|
|
31
|
+
const namespaceMatch = /(?:import|export)\s+(?:type\s+)?\*\s+as\s+(\w+)/.exec(statement);
|
|
32
|
+
if (namespaceMatch) {
|
|
33
|
+
specifiers.push({
|
|
34
|
+
type: "namespace",
|
|
35
|
+
name: namespaceMatch[1],
|
|
36
|
+
isType: isTypeOnly
|
|
37
|
+
});
|
|
38
|
+
return specifiers;
|
|
39
|
+
}
|
|
40
|
+
const defaultMatch = /import\s+(?:type\s+)?(\w+)(?:\s*,|\s+from)/.exec(
|
|
41
|
+
statement
|
|
42
|
+
);
|
|
43
|
+
if (defaultMatch && !statement.includes("{")) {
|
|
44
|
+
specifiers.push({
|
|
45
|
+
type: "default",
|
|
46
|
+
name: defaultMatch[1],
|
|
47
|
+
isType: isTypeOnly
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const namedMatch = /{([^}]*)}/.exec(statement);
|
|
51
|
+
if (namedMatch) {
|
|
52
|
+
const items = namedMatch[1].split(",").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
53
|
+
for (const item of items) {
|
|
54
|
+
const typeMatch = /^type\s+(.+)/.exec(item);
|
|
55
|
+
const actualItem = typeMatch ? typeMatch[1] : item;
|
|
56
|
+
const isItemType = !!typeMatch || isTypeOnly;
|
|
57
|
+
if (actualItem.includes(" as ")) {
|
|
58
|
+
const [name, alias] = actualItem.split(" as ").map((p) => p.trim());
|
|
59
|
+
specifiers.push({
|
|
60
|
+
type: "named",
|
|
61
|
+
name,
|
|
62
|
+
alias,
|
|
63
|
+
isType: isItemType
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
specifiers.push({
|
|
67
|
+
type: "named",
|
|
68
|
+
name: actualItem,
|
|
69
|
+
isType: isItemType
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return specifiers;
|
|
75
|
+
}
|
|
76
|
+
if (kind === "import" || kind === "all") {
|
|
77
|
+
const importMatches = [...content.matchAll(patterns.staticImport)];
|
|
78
|
+
for (const match of importMatches) {
|
|
79
|
+
const source = match[1] || match[3];
|
|
80
|
+
if (!source) continue;
|
|
81
|
+
const pathType = getPathType(source);
|
|
82
|
+
if (!pathTypes.includes(pathType)) continue;
|
|
83
|
+
const info = {
|
|
84
|
+
statement: match[0],
|
|
85
|
+
type: "static",
|
|
86
|
+
kind: "import",
|
|
87
|
+
source,
|
|
88
|
+
pathType,
|
|
89
|
+
pathTypeSymbol: pathType === "alias" ? /^[@~]/.exec(source)?.[0] : void 0,
|
|
90
|
+
isTypeOnly: match[0].includes("import type"),
|
|
91
|
+
specifiers: extractSpecifiers(match[0]),
|
|
92
|
+
start: match.index,
|
|
93
|
+
end: match.index + match[0].length
|
|
94
|
+
};
|
|
95
|
+
results.push(info);
|
|
96
|
+
}
|
|
97
|
+
const dynamicMatches = [...content.matchAll(patterns.dynamicImport)];
|
|
98
|
+
for (const match of dynamicMatches) {
|
|
99
|
+
const source = match[1];
|
|
100
|
+
if (!source) continue;
|
|
101
|
+
const pathType = getPathType(source);
|
|
102
|
+
if (!pathTypes.includes(pathType)) continue;
|
|
103
|
+
const info = {
|
|
104
|
+
statement: match[0],
|
|
105
|
+
type: "dynamic",
|
|
106
|
+
kind: "import",
|
|
107
|
+
source,
|
|
108
|
+
pathType,
|
|
109
|
+
pathTypeSymbol: pathType === "alias" ? /^[@~]/.exec(source)?.[0] : void 0,
|
|
110
|
+
isTypeOnly: false,
|
|
111
|
+
specifiers: [],
|
|
112
|
+
start: match.index,
|
|
113
|
+
end: match.index + match[0].length
|
|
114
|
+
};
|
|
115
|
+
results.push(info);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (kind === "export" || kind === "all") {
|
|
119
|
+
const exportMatches = [...content.matchAll(patterns.staticExport)];
|
|
120
|
+
for (const match of exportMatches) {
|
|
121
|
+
const source = match[1];
|
|
122
|
+
if (!source) continue;
|
|
123
|
+
const pathType = getPathType(source);
|
|
124
|
+
if (!pathTypes.includes(pathType)) continue;
|
|
125
|
+
const info = {
|
|
126
|
+
statement: match[0],
|
|
127
|
+
type: "static",
|
|
128
|
+
kind: "export",
|
|
129
|
+
source,
|
|
130
|
+
pathType,
|
|
131
|
+
pathTypeSymbol: pathType === "alias" ? /^[@~]/.exec(source)?.[0] : void 0,
|
|
132
|
+
isTypeOnly: match[0].includes("export type"),
|
|
133
|
+
specifiers: extractSpecifiers(match[0]),
|
|
134
|
+
start: match.index,
|
|
135
|
+
end: match.index + match[0].length
|
|
136
|
+
};
|
|
137
|
+
results.push(info);
|
|
138
|
+
}
|
|
139
|
+
const defaultMatches = [...content.matchAll(patterns.defaultExport)];
|
|
140
|
+
for (const match of defaultMatches) {
|
|
141
|
+
const info = {
|
|
142
|
+
statement: match[0],
|
|
143
|
+
type: "static",
|
|
144
|
+
kind: "export",
|
|
145
|
+
source: void 0,
|
|
146
|
+
pathType: void 0,
|
|
147
|
+
pathTypeSymbol: void 0,
|
|
148
|
+
isTypeOnly: false,
|
|
149
|
+
specifiers: [{ type: "default", name: "default" }],
|
|
150
|
+
start: match.index,
|
|
151
|
+
end: match.index + match[0].length
|
|
152
|
+
};
|
|
153
|
+
results.push(info);
|
|
154
|
+
}
|
|
155
|
+
const namedMatches = [...content.matchAll(patterns.namedExport)];
|
|
156
|
+
for (const match of namedMatches) {
|
|
157
|
+
const name = match[1];
|
|
158
|
+
if (!name) continue;
|
|
159
|
+
const info = {
|
|
160
|
+
statement: match[0],
|
|
161
|
+
type: "static",
|
|
162
|
+
kind: "export",
|
|
163
|
+
source: void 0,
|
|
164
|
+
pathType: void 0,
|
|
165
|
+
pathTypeSymbol: void 0,
|
|
166
|
+
isTypeOnly: match[0].includes("export type"),
|
|
167
|
+
specifiers: [{ type: "named", name }],
|
|
168
|
+
start: match.index,
|
|
169
|
+
end: match.index + match[0].length
|
|
170
|
+
};
|
|
171
|
+
results.push(info);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (limitPerType) {
|
|
175
|
+
const groupedByType = results.reduce(
|
|
176
|
+
(acc, curr) => {
|
|
177
|
+
const key = `${curr.kind}-${curr.pathType || "none"}`;
|
|
178
|
+
if (!acc[key]) acc[key] = [];
|
|
179
|
+
acc[key].push(curr);
|
|
180
|
+
return acc;
|
|
181
|
+
},
|
|
182
|
+
{}
|
|
183
|
+
);
|
|
184
|
+
return Object.values(groupedByType).flatMap(
|
|
185
|
+
(group) => group.slice(0, limitPerType)
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return results;
|
|
189
|
+
}
|
package/bin/mod.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PlatformPath } from "node:path";
|
|
2
|
+
import { getFileImportsExports, type ImportExportInfo, type ImportExportSpecifier, type GetFileImportsExportsOptions } from "./impl/getFileImportsExports.js";
|
|
2
3
|
declare const normalizedAliasSymbol: unique symbol;
|
|
3
4
|
interface NormalizedRecord extends Record<string, string> {
|
|
4
5
|
[normalizedAliasSymbol]?: true;
|
|
@@ -19,14 +20,6 @@ export interface FormatInputPathObject {
|
|
|
19
20
|
}
|
|
20
21
|
type PathExtFilter = "js" | "ts" | "none" | "js-ts-none";
|
|
21
22
|
type ImportExtType = "js" | "ts" | "none";
|
|
22
|
-
/**
|
|
23
|
-
* removes directories with recursive force option
|
|
24
|
-
*/
|
|
25
|
-
declare function cleanDirs(dirs: string[]): Promise<void>;
|
|
26
|
-
/**
|
|
27
|
-
* recursively copies a directory and its contents
|
|
28
|
-
*/
|
|
29
|
-
declare function copyDir(src: string, dest: string): Promise<void>;
|
|
30
23
|
/**
|
|
31
24
|
* normalizes windows paths to use forward slashes
|
|
32
25
|
*/
|
|
@@ -227,6 +220,6 @@ declare const path: PlatformPath & {
|
|
|
227
220
|
};
|
|
228
221
|
declare const win32: PlatformPath;
|
|
229
222
|
declare const delimiter: string;
|
|
230
|
-
export type { PlatformPath, PathExtFilter, ImportExtType };
|
|
231
|
-
export { _pathBase as posix, win32, basename, delimiter, dirname, extname, filename, format, isAbsolute, join, normalize, parse, relative, resolve, sep, toNamespacedPath, normalizeAliases, resolveAlias, reverseResolveAlias, normalizeWindowsPath,
|
|
223
|
+
export type { PlatformPath, PathExtFilter, ImportExtType, ImportExportInfo, ImportExportSpecifier, GetFileImportsExportsOptions, };
|
|
224
|
+
export { _pathBase as posix, win32, basename, delimiter, dirname, extname, filename, format, isAbsolute, join, normalize, parse, relative, resolve, sep, toNamespacedPath, normalizeAliases, resolveAlias, reverseResolveAlias, normalizeWindowsPath, convertStringAliasRelative, convertImportsAliasToRelative, convertImportsExt, stripPathSegments, stripPathSegmentsInDirectory, attachPathSegments, attachPathSegmentsInDirectory, getFileImportsExports, };
|
|
232
225
|
export default path;
|
package/bin/mod.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
|
+
import {
|
|
3
|
+
getFileImportsExports
|
|
4
|
+
} from "./impl/getFileImportsExports.js";
|
|
2
5
|
const log = (msg) => console.log(`\x1B[2m${msg}\x1B[0m`);
|
|
3
6
|
const logInternal = (msg) => console.log(`\x1B[36;2m${msg}\x1B[0m`);
|
|
4
7
|
const EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
@@ -15,42 +18,6 @@ const IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
|
|
|
15
18
|
const ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
|
|
16
19
|
const PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/;
|
|
17
20
|
const IMPORT_REGEX = /(?:import\s+(?:[\s\S]*?)\s+from\s+|import\s*\(\s*)\s*(['"])([^'"]+)\1/g;
|
|
18
|
-
async function cleanDirs(dirs) {
|
|
19
|
-
await Promise.all(
|
|
20
|
-
dirs.map(async (d) => {
|
|
21
|
-
try {
|
|
22
|
-
await fs.rm(d, { recursive: true, force: true });
|
|
23
|
-
logInternal(`\u2713 cleaned: ${d}`);
|
|
24
|
-
} catch (error) {
|
|
25
|
-
log(
|
|
26
|
-
`\u2717 error cleaning ${d}: ${error instanceof Error ? error.message : String(error)}`
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
})
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
async function copyDir(src, dest) {
|
|
33
|
-
logInternal(`\u2713 copying: ${src} \u2192 ${dest}`);
|
|
34
|
-
try {
|
|
35
|
-
await fs.mkdir(dest, { recursive: true });
|
|
36
|
-
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
37
|
-
await Promise.all(
|
|
38
|
-
entries.map(async (entry) => {
|
|
39
|
-
const srcPath = join(src, entry.name);
|
|
40
|
-
const destPath = join(dest, entry.name);
|
|
41
|
-
if (entry.isDirectory()) {
|
|
42
|
-
return copyDir(srcPath, destPath);
|
|
43
|
-
}
|
|
44
|
-
await fs.copyFile(srcPath, destPath);
|
|
45
|
-
logInternal(` copied: ${srcPath} \u2192 ${destPath}`);
|
|
46
|
-
})
|
|
47
|
-
);
|
|
48
|
-
} catch (error) {
|
|
49
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
50
|
-
log(`\u2717 error copying directory ${src} to ${dest}: ${errorMsg}`);
|
|
51
|
-
throw error;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
21
|
function normalizeWindowsPath(input = "") {
|
|
55
22
|
if (!input) return input;
|
|
56
23
|
return input.replace(/\\/g, SLASH).replace(DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
@@ -510,7 +477,6 @@ async function processFile(filePath, aliasToReplace, targetDir, pathExtFilter) {
|
|
|
510
477
|
}
|
|
511
478
|
if (content !== updated) {
|
|
512
479
|
await fs.writeFile(filePath, updated);
|
|
513
|
-
logInternal(`\u2713 processed: ${filePath}`);
|
|
514
480
|
}
|
|
515
481
|
return changes;
|
|
516
482
|
}
|
|
@@ -548,7 +514,6 @@ async function processAllFiles({
|
|
|
548
514
|
results.push({ file: fullPath, changes });
|
|
549
515
|
}
|
|
550
516
|
} else {
|
|
551
|
-
logInternal(` - skipping non-matching file: ${entry.name}`);
|
|
552
517
|
}
|
|
553
518
|
})
|
|
554
519
|
);
|
|
@@ -571,7 +536,6 @@ async function convertImportsAliasToRelative({
|
|
|
571
536
|
`Converting aliased imports starting with '${aliasToReplace}' to relative paths in "${targetDir}"...`
|
|
572
537
|
);
|
|
573
538
|
log(` (Assuming "${normalizedAlias}" resolves relative to "${targetDir}")`);
|
|
574
|
-
logInternal(` (Using extension mode: ${pathExtFilter})`);
|
|
575
539
|
const results = await processAllFiles({
|
|
576
540
|
srcDir: targetDir,
|
|
577
541
|
aliasToReplace: normalizedAlias,
|
|
@@ -598,9 +562,6 @@ async function convertImportsExt({
|
|
|
598
562
|
extFrom,
|
|
599
563
|
extTo
|
|
600
564
|
}) {
|
|
601
|
-
logInternal(
|
|
602
|
-
`Converting import extensions from '${extFrom}' to '${extTo}' in "${targetDir}"...`
|
|
603
|
-
);
|
|
604
565
|
const fromExtStr = extFrom === "none" ? "" : `.${extFrom}`;
|
|
605
566
|
const toExtStr = extTo === "none" ? "" : `.${extTo}`;
|
|
606
567
|
const importRegex = new RegExp(
|
|
@@ -625,8 +586,9 @@ async function convertImportsExt({
|
|
|
625
586
|
const content = await fs.readFile(fullPath, "utf-8");
|
|
626
587
|
let updated = content;
|
|
627
588
|
const changes = [];
|
|
628
|
-
|
|
629
|
-
|
|
589
|
+
let match;
|
|
590
|
+
match = importRegex.exec(content);
|
|
591
|
+
while (match !== null) {
|
|
630
592
|
const quote = match[1];
|
|
631
593
|
const importPath = match[2];
|
|
632
594
|
let replacementPath;
|
|
@@ -642,16 +604,15 @@ async function convertImportsExt({
|
|
|
642
604
|
const searchStr = `${quote}${importPath}${quote}`;
|
|
643
605
|
const replaceStr = `${quote}${replacementPath}${quote}`;
|
|
644
606
|
updated = replaceAllInString(updated, searchStr, replaceStr);
|
|
607
|
+
match = importRegex.exec(updated);
|
|
645
608
|
}
|
|
646
609
|
if (content !== updated) {
|
|
647
610
|
await fs.writeFile(fullPath, updated);
|
|
648
|
-
logInternal(`\u2713 processed: ${fullPath}`);
|
|
649
611
|
if (changes.length > 0) {
|
|
650
612
|
results.push({ file: fullPath, changes });
|
|
651
613
|
}
|
|
652
614
|
}
|
|
653
615
|
} else {
|
|
654
|
-
logInternal(` - skipping non-matching file: ${entry.name}`);
|
|
655
616
|
}
|
|
656
617
|
})
|
|
657
618
|
);
|
|
@@ -666,7 +627,6 @@ async function convertImportsExt({
|
|
|
666
627
|
}
|
|
667
628
|
} else {
|
|
668
629
|
}
|
|
669
|
-
logInternal("Extension conversion complete.");
|
|
670
630
|
return results;
|
|
671
631
|
} catch (error) {
|
|
672
632
|
log(
|
|
@@ -678,12 +638,8 @@ async function convertImportsExt({
|
|
|
678
638
|
function stripPathSegments(path2, count = 1, alias = "") {
|
|
679
639
|
if (typeof path2 !== "string" || path2.length === 0) return path2;
|
|
680
640
|
if (count <= 0) return path2;
|
|
681
|
-
logInternal(`[stripPathSegments] Processing path: ${path2}`);
|
|
682
|
-
logInternal(` - count: ${count}, alias: ${alias}`);
|
|
683
641
|
const normalizedPath = normalizeWindowsPath(path2);
|
|
684
|
-
logInternal(` - normalized: ${normalizedPath}`);
|
|
685
642
|
const parsed = parse(normalizedPath);
|
|
686
|
-
logInternal(` - parsed: ${JSON.stringify(parsed)}`);
|
|
687
643
|
let pathSegments = [];
|
|
688
644
|
if (parsed.dir && parsed.dir !== parsed.root) {
|
|
689
645
|
let dirRelativeToRoot = parsed.dir;
|
|
@@ -696,32 +652,22 @@ function stripPathSegments(path2, count = 1, alias = "") {
|
|
|
696
652
|
pathSegments.push(parsed.base);
|
|
697
653
|
}
|
|
698
654
|
pathSegments = pathSegments.filter(Boolean);
|
|
699
|
-
logInternal(` - initial segments: ${JSON.stringify(pathSegments)}`);
|
|
700
655
|
const leadingPreservedSegments = [];
|
|
701
656
|
if (alias && pathSegments.length > 0 && pathSegments[0].startsWith(alias)) {
|
|
702
657
|
const preserved = pathSegments.shift();
|
|
703
658
|
leadingPreservedSegments.push(preserved);
|
|
704
|
-
logInternal(` - preserved alias segment: ${preserved}`);
|
|
705
659
|
}
|
|
706
660
|
while (pathSegments.length > 0 && (pathSegments[0] === DOT || pathSegments[0] === DOUBLE_DOT)) {
|
|
707
661
|
const preserved = pathSegments.shift();
|
|
708
662
|
leadingPreservedSegments.push(preserved);
|
|
709
|
-
logInternal(` - preserved relative segment: ${preserved}`);
|
|
710
663
|
}
|
|
711
664
|
const numToStrip = Math.min(count, pathSegments.length);
|
|
712
665
|
const remainingBodySegments = pathSegments.slice(numToStrip);
|
|
713
|
-
logInternal(
|
|
714
|
-
` - stripping ${numToStrip} segments from: ${JSON.stringify(pathSegments)}`
|
|
715
|
-
);
|
|
716
|
-
logInternal(
|
|
717
|
-
` - remaining body segments: ${JSON.stringify(remainingBodySegments)}`
|
|
718
|
-
);
|
|
719
666
|
const pathRoot = parsed.root;
|
|
720
667
|
const effectiveSegments = [
|
|
721
668
|
...leadingPreservedSegments,
|
|
722
669
|
...remainingBodySegments
|
|
723
670
|
];
|
|
724
|
-
logInternal(` - effective segments: ${JSON.stringify(effectiveSegments)}`);
|
|
725
671
|
let result;
|
|
726
672
|
if (effectiveSegments.length === 0) {
|
|
727
673
|
result = normalize(pathRoot || DOT);
|
|
@@ -730,7 +676,6 @@ function stripPathSegments(path2, count = 1, alias = "") {
|
|
|
730
676
|
} else {
|
|
731
677
|
result = join(...effectiveSegments);
|
|
732
678
|
}
|
|
733
|
-
logInternal(` - final result: ${result}`);
|
|
734
679
|
return result;
|
|
735
680
|
}
|
|
736
681
|
async function stripPathSegmentsInDirectory({
|
|
@@ -741,7 +686,6 @@ async function stripPathSegmentsInDirectory({
|
|
|
741
686
|
}) {
|
|
742
687
|
log(`[stripPathSegmentsInDirectory] Processing directory: ${targetDir}`);
|
|
743
688
|
log(` - segmentsToStrip: ${segmentsToStrip}, alias: ${alias}`);
|
|
744
|
-
logInternal(` - extensions: ${JSON.stringify(extensionsToProcess)}`);
|
|
745
689
|
try {
|
|
746
690
|
const entries = await fs.readdir(targetDir, { withFileTypes: true });
|
|
747
691
|
const results = [];
|
|
@@ -750,7 +694,6 @@ async function stripPathSegmentsInDirectory({
|
|
|
750
694
|
const fullPath = join(targetDir, entry.name);
|
|
751
695
|
if (entry.isDirectory()) {
|
|
752
696
|
if (entry.name === "node_modules") return;
|
|
753
|
-
logInternal(` - recursing into directory: ${entry.name}`);
|
|
754
697
|
const subdirResults = await stripPathSegmentsInDirectory({
|
|
755
698
|
targetDir: fullPath,
|
|
756
699
|
segmentsToStrip,
|
|
@@ -759,50 +702,40 @@ async function stripPathSegmentsInDirectory({
|
|
|
759
702
|
});
|
|
760
703
|
results.push(...subdirResults);
|
|
761
704
|
} else if (extensionsToProcess.includes(extname(entry.name))) {
|
|
762
|
-
logInternal(` Processing file: ${entry.name}`);
|
|
763
705
|
const content = await fs.readFile(fullPath, "utf-8");
|
|
764
706
|
let updated = content;
|
|
765
707
|
const changes = [];
|
|
766
708
|
const matches = Array.from(content.matchAll(IMPORT_REGEX));
|
|
767
|
-
logInternal(` - found ${matches.length} import statements`);
|
|
768
709
|
for (const match of matches) {
|
|
769
710
|
const originalQuote = match[1];
|
|
770
711
|
const importPath = match[2];
|
|
771
712
|
if (!importPath.includes(SLASH)) {
|
|
772
|
-
logInternal(` - skipping non-path import: ${importPath}`);
|
|
773
713
|
continue;
|
|
774
714
|
}
|
|
775
715
|
if (alias && !importPath.startsWith(alias.replace("/*", ""))) {
|
|
776
|
-
logInternal(` - skipping non-alias import: ${importPath}`);
|
|
777
716
|
continue;
|
|
778
717
|
}
|
|
779
|
-
logInternal(` Processing import: ${importPath}`);
|
|
780
718
|
const strippedPath = stripPathSegments(
|
|
781
719
|
importPath,
|
|
782
720
|
segmentsToStrip,
|
|
783
721
|
alias
|
|
784
722
|
);
|
|
785
723
|
if (importPath === strippedPath) {
|
|
786
|
-
logInternal(" - no changes needed");
|
|
787
724
|
continue;
|
|
788
725
|
}
|
|
789
726
|
changes.push({ from: importPath, to: strippedPath });
|
|
790
|
-
logInternal(` - transformed: ${importPath} \u2192 ${strippedPath}`);
|
|
791
727
|
const searchStr = `${originalQuote}${importPath}${originalQuote}`;
|
|
792
728
|
const replaceStr = `${originalQuote}${strippedPath}${originalQuote}`;
|
|
793
729
|
updated = replaceAllInString(updated, searchStr, replaceStr);
|
|
794
730
|
}
|
|
795
731
|
if (content !== updated) {
|
|
796
732
|
await fs.writeFile(fullPath, updated);
|
|
797
|
-
logInternal(" \u2713 wrote changes to file");
|
|
798
733
|
if (changes.length > 0) {
|
|
799
734
|
results.push({ file: fullPath, changes });
|
|
800
735
|
}
|
|
801
736
|
} else {
|
|
802
|
-
logInternal(" - no changes made to file");
|
|
803
737
|
}
|
|
804
738
|
} else {
|
|
805
|
-
logInternal(` - skipping non-matching file: ${entry.name}`);
|
|
806
739
|
}
|
|
807
740
|
})
|
|
808
741
|
);
|
|
@@ -816,7 +749,6 @@ async function stripPathSegmentsInDirectory({
|
|
|
816
749
|
}
|
|
817
750
|
}
|
|
818
751
|
} else {
|
|
819
|
-
logInternal(" No changes were made in any files");
|
|
820
752
|
}
|
|
821
753
|
return results;
|
|
822
754
|
} catch (error) {
|
|
@@ -905,13 +837,11 @@ async function attachPathSegmentsInDirectory({
|
|
|
905
837
|
}
|
|
906
838
|
if (content !== updated) {
|
|
907
839
|
await fs.writeFile(fullPath, updated);
|
|
908
|
-
logInternal(`\u2713 processed: ${fullPath}`);
|
|
909
840
|
if (changes.length > 0) {
|
|
910
841
|
results.push({ file: fullPath, changes });
|
|
911
842
|
}
|
|
912
843
|
}
|
|
913
844
|
} else {
|
|
914
|
-
logInternal(` - skipping non-matching file: ${entry.name}`);
|
|
915
845
|
}
|
|
916
846
|
})
|
|
917
847
|
);
|
|
@@ -1013,14 +943,13 @@ export {
|
|
|
1013
943
|
resolveAlias,
|
|
1014
944
|
reverseResolveAlias,
|
|
1015
945
|
normalizeWindowsPath,
|
|
1016
|
-
cleanDirs,
|
|
1017
|
-
copyDir,
|
|
1018
946
|
convertStringAliasRelative,
|
|
1019
947
|
convertImportsAliasToRelative,
|
|
1020
948
|
convertImportsExt,
|
|
1021
949
|
stripPathSegments,
|
|
1022
950
|
stripPathSegmentsInDirectory,
|
|
1023
951
|
attachPathSegments,
|
|
1024
|
-
attachPathSegmentsInDirectory
|
|
952
|
+
attachPathSegmentsInDirectory,
|
|
953
|
+
getFileImportsExports
|
|
1025
954
|
};
|
|
1026
955
|
export default path;
|
package/package.json
CHANGED
|
@@ -5,26 +5,8 @@
|
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"name": "@reliverse/pathkit",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"version": "1.1.
|
|
9
|
-
"devDependencies": {
|
|
10
|
-
"@biomejs/biome": "1.9.4",
|
|
11
|
-
"@eslint/js": "^9.27.0",
|
|
12
|
-
"@reliverse/dler": "^1.3.6",
|
|
13
|
-
"@reliverse/relifso": "^1.2.10",
|
|
14
|
-
"@reliverse/relinka": "^1.4.5",
|
|
15
|
-
"@reliverse/rematch": "^1.1.0",
|
|
16
|
-
"@stylistic/eslint-plugin": "^4.2.0",
|
|
17
|
-
"@types/bun": "^1.2.14",
|
|
18
|
-
"@types/node": "^22.15.21",
|
|
19
|
-
"eslint": "^9.27.0",
|
|
20
|
-
"eslint-plugin-no-relative-import-paths": "^1.6.1",
|
|
21
|
-
"eslint-plugin-perfectionist": "^4.13.0",
|
|
22
|
-
"knip": "^5.57.2",
|
|
23
|
-
"magic-string": "^0.30.17",
|
|
24
|
-
"p-map": "^7.0.3",
|
|
25
|
-
"typescript": "^5.8.3",
|
|
26
|
-
"typescript-eslint": "^8.32.1"
|
|
27
|
-
},
|
|
8
|
+
"version": "1.1.6",
|
|
9
|
+
"devDependencies": {},
|
|
28
10
|
"exports": {
|
|
29
11
|
".": "./bin/mod.js"
|
|
30
12
|
},
|
|
@@ -39,4 +21,4 @@
|
|
|
39
21
|
"publishConfig": {
|
|
40
22
|
"access": "public"
|
|
41
23
|
}
|
|
42
|
-
}
|
|
24
|
+
}
|