@reliverse/pathkit 1.1.5 → 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/bin/impl/getFileImportsExports.d.ts +27 -0
- package/bin/impl/getFileImportsExports.js +189 -0
- package/bin/mod.d.ts +3 -2
- package/bin/mod.js +9 -3
- package/package.json +2 -20
|
@@ -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;
|
|
@@ -219,6 +220,6 @@ declare const path: PlatformPath & {
|
|
|
219
220
|
};
|
|
220
221
|
declare const win32: PlatformPath;
|
|
221
222
|
declare const delimiter: string;
|
|
222
|
-
export type { PlatformPath, PathExtFilter, ImportExtType };
|
|
223
|
-
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, };
|
|
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, };
|
|
224
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"];
|
|
@@ -583,8 +586,9 @@ async function convertImportsExt({
|
|
|
583
586
|
const content = await fs.readFile(fullPath, "utf-8");
|
|
584
587
|
let updated = content;
|
|
585
588
|
const changes = [];
|
|
586
|
-
|
|
587
|
-
|
|
589
|
+
let match;
|
|
590
|
+
match = importRegex.exec(content);
|
|
591
|
+
while (match !== null) {
|
|
588
592
|
const quote = match[1];
|
|
589
593
|
const importPath = match[2];
|
|
590
594
|
let replacementPath;
|
|
@@ -600,6 +604,7 @@ async function convertImportsExt({
|
|
|
600
604
|
const searchStr = `${quote}${importPath}${quote}`;
|
|
601
605
|
const replaceStr = `${quote}${replacementPath}${quote}`;
|
|
602
606
|
updated = replaceAllInString(updated, searchStr, replaceStr);
|
|
607
|
+
match = importRegex.exec(updated);
|
|
603
608
|
}
|
|
604
609
|
if (content !== updated) {
|
|
605
610
|
await fs.writeFile(fullPath, updated);
|
|
@@ -944,6 +949,7 @@ export {
|
|
|
944
949
|
stripPathSegments,
|
|
945
950
|
stripPathSegmentsInDirectory,
|
|
946
951
|
attachPathSegments,
|
|
947
|
-
attachPathSegmentsInDirectory
|
|
952
|
+
attachPathSegmentsInDirectory,
|
|
953
|
+
getFileImportsExports
|
|
948
954
|
};
|
|
949
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.4.6",
|
|
13
|
-
"@reliverse/relifso": "^1.2.10",
|
|
14
|
-
"@reliverse/relinka": "^1.4.6",
|
|
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
|
},
|