@deplens/mcp 0.1.7 → 0.1.8
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/deplens-mcp.js +0 -0
- package/package.json +6 -3
- package/src/core/changelog-parser.mjs +313 -0
- package/src/core/diff-analyzer.mjs +590 -0
- package/src/core/diff.mjs +145 -0
- package/src/core/inspect.mjs +950 -482
- package/src/core/parse-dts.mjs +198 -172
- package/src/core/parse-source.mjs +524 -0
- package/src/core/version-resolver.mjs +317 -0
- package/src/server.mjs +581 -37
package/src/core/inspect.mjs
CHANGED
|
@@ -1,58 +1,62 @@
|
|
|
1
1
|
// inspect.mjs
|
|
2
|
-
import { createRequire } from "module"
|
|
3
|
-
import fs from "fs"
|
|
4
|
-
import path from "path"
|
|
5
|
-
import { fileURLToPath, pathToFileURL } from "url"
|
|
6
|
-
import fg from "fast-glob"
|
|
7
|
-
import { resolve as importMetaResolve } from "import-meta-resolve"
|
|
8
|
-
import { parseDtsFile } from "./parse-dts.mjs"
|
|
2
|
+
import { createRequire } from "module";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
6
|
+
import fg from "fast-glob";
|
|
7
|
+
import { resolve as importMetaResolve } from "import-meta-resolve";
|
|
8
|
+
import { parseDtsFile } from "./parse-dts.mjs";
|
|
9
|
+
import { analyzePackageSource } from "./parse-source.mjs";
|
|
10
|
+
import { downloadVersion } from "./version-resolver.mjs";
|
|
9
11
|
|
|
10
12
|
function getPackageName(target) {
|
|
11
|
-
if (!target) return target
|
|
13
|
+
if (!target) return target;
|
|
12
14
|
if (target.startsWith("@")) {
|
|
13
|
-
const parts = target.split("/")
|
|
14
|
-
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : target
|
|
15
|
+
const parts = target.split("/");
|
|
16
|
+
return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : target;
|
|
15
17
|
}
|
|
16
|
-
return target.split("/")[0]
|
|
18
|
+
return target.split("/")[0];
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
function getPackageSubpath(target) {
|
|
20
|
-
if (!target) return null
|
|
21
|
-
const base = getPackageName(target)
|
|
22
|
-
if (!base) return null
|
|
23
|
-
if (target === base) return null
|
|
24
|
-
const prefix = `${base}
|
|
25
|
-
return target.startsWith(prefix) ? target.slice(prefix.length) : null
|
|
22
|
+
if (!target) return null;
|
|
23
|
+
const base = getPackageName(target);
|
|
24
|
+
if (!base) return null;
|
|
25
|
+
if (target === base) return null;
|
|
26
|
+
const prefix = `${base}/`;
|
|
27
|
+
return target.startsWith(prefix) ? target.slice(prefix.length) : null;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
async function findWorkspaceRoot(startDir) {
|
|
29
|
-
if (!startDir) return null
|
|
30
|
-
let dir = path.resolve(startDir)
|
|
31
|
+
if (!startDir) return null;
|
|
32
|
+
let dir = path.resolve(startDir);
|
|
31
33
|
while (true) {
|
|
32
|
-
const pkgPath = path.join(dir, "package.json")
|
|
34
|
+
const pkgPath = path.join(dir, "package.json");
|
|
33
35
|
if (fs.existsSync(pkgPath)) {
|
|
34
36
|
try {
|
|
35
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"))
|
|
36
|
-
if (pkg?.workspaces) return { dir, pkg }
|
|
37
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
38
|
+
if (pkg?.workspaces) return { dir, pkg };
|
|
37
39
|
} catch (e) {}
|
|
38
40
|
}
|
|
39
|
-
const parent = path.dirname(dir)
|
|
40
|
-
if (parent === dir) break
|
|
41
|
-
dir = parent
|
|
41
|
+
const parent = path.dirname(dir);
|
|
42
|
+
if (parent === dir) break;
|
|
43
|
+
dir = parent;
|
|
42
44
|
}
|
|
43
|
-
return null
|
|
45
|
+
return null;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
async function listWorkspacePackageDirs(rootDir, workspaces, targetPackage) {
|
|
47
|
-
const patterns = Array.isArray(workspaces)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const patterns = Array.isArray(workspaces)
|
|
50
|
+
? workspaces
|
|
51
|
+
: workspaces?.packages;
|
|
52
|
+
if (!Array.isArray(patterns) || patterns.length === 0) return [];
|
|
53
|
+
const dirs = [];
|
|
54
|
+
const target = getPackageName(targetPackage);
|
|
51
55
|
|
|
52
56
|
for (const pattern of patterns) {
|
|
53
|
-
if (!pattern) continue
|
|
54
|
-
const normalized = String(pattern).replace(/\\/g, "/").replace(/\/?$/, "/")
|
|
55
|
-
const globPattern = `${normalized}package.json
|
|
57
|
+
if (!pattern) continue;
|
|
58
|
+
const normalized = String(pattern).replace(/\\/g, "/").replace(/\/?$/, "/");
|
|
59
|
+
const globPattern = `${normalized}package.json`;
|
|
56
60
|
const matches =
|
|
57
61
|
typeof Bun !== "undefined" && Bun.Glob
|
|
58
62
|
? await Array.fromAsync(
|
|
@@ -69,257 +73,373 @@ async function listWorkspacePackageDirs(rootDir, workspaces, targetPackage) {
|
|
|
69
73
|
onlyFiles: true,
|
|
70
74
|
dot: false,
|
|
71
75
|
followSymbolicLinks: false,
|
|
72
|
-
})
|
|
76
|
+
});
|
|
73
77
|
for (const match of matches) {
|
|
74
|
-
const pkgPath = path.join(rootDir, match)
|
|
78
|
+
const pkgPath = path.join(rootDir, match);
|
|
75
79
|
try {
|
|
76
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"))
|
|
80
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
77
81
|
const depTables = [
|
|
78
82
|
pkg?.dependencies,
|
|
79
83
|
pkg?.devDependencies,
|
|
80
84
|
pkg?.peerDependencies,
|
|
81
85
|
pkg?.optionalDependencies,
|
|
82
|
-
]
|
|
86
|
+
];
|
|
83
87
|
const hasTarget =
|
|
84
88
|
Boolean(target) &&
|
|
85
|
-
depTables.some(
|
|
89
|
+
depTables.some(
|
|
90
|
+
(deps) =>
|
|
91
|
+
deps && Object.prototype.hasOwnProperty.call(deps, target),
|
|
92
|
+
);
|
|
86
93
|
if (hasTarget) {
|
|
87
|
-
dirs.push(path.dirname(pkgPath))
|
|
94
|
+
dirs.push(path.dirname(pkgPath));
|
|
88
95
|
}
|
|
89
96
|
} catch (e) {}
|
|
90
97
|
}
|
|
91
98
|
}
|
|
92
99
|
|
|
93
|
-
return dirs
|
|
100
|
+
return dirs;
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
async function resolveTargetModule(target, cwd, resolveFrom) {
|
|
97
|
-
const baseDir = resolveFrom || cwd
|
|
98
|
-
if (!baseDir) return { resolved: null, resolveCwd: baseDir, resolver: null }
|
|
104
|
+
const baseDir = resolveFrom || cwd;
|
|
105
|
+
if (!baseDir) return { resolved: null, resolveCwd: baseDir, resolver: null };
|
|
99
106
|
|
|
100
107
|
const tryResolve = async (dir) => {
|
|
101
|
-
if (!dir) return null
|
|
108
|
+
if (!dir) return null;
|
|
102
109
|
if (typeof Bun !== "undefined" && Bun.resolve) {
|
|
103
110
|
try {
|
|
104
|
-
const resolved = await Bun.resolve(target, dir)
|
|
105
|
-
return { resolved, resolver: "bun", resolveCwd: dir }
|
|
111
|
+
const resolved = await Bun.resolve(target, dir);
|
|
112
|
+
return { resolved, resolver: "bun", resolveCwd: dir };
|
|
106
113
|
} catch (e) {}
|
|
107
114
|
}
|
|
108
115
|
try {
|
|
109
|
-
const parentUrl = pathToFileURL(path.join(dir, "noop.js")).href
|
|
110
|
-
const resolvedUrl = await importMetaResolve(target, parentUrl)
|
|
111
|
-
const resolvedPath = resolvedUrl.startsWith("file://")
|
|
112
|
-
|
|
116
|
+
const parentUrl = pathToFileURL(path.join(dir, "noop.js")).href;
|
|
117
|
+
const resolvedUrl = await importMetaResolve(target, parentUrl);
|
|
118
|
+
const resolvedPath = resolvedUrl.startsWith("file://")
|
|
119
|
+
? fileURLToPath(resolvedUrl)
|
|
120
|
+
: resolvedUrl;
|
|
121
|
+
return {
|
|
122
|
+
resolved: resolvedPath,
|
|
123
|
+
resolver: "import-meta-resolve",
|
|
124
|
+
resolveCwd: dir,
|
|
125
|
+
};
|
|
113
126
|
} catch (e) {}
|
|
114
127
|
try {
|
|
115
|
-
const req = createRequire(path.join(dir, "noop.js"))
|
|
116
|
-
const resolved = req.resolve(target)
|
|
117
|
-
return { resolved, resolver: "require", resolveCwd: dir }
|
|
128
|
+
const req = createRequire(path.join(dir, "noop.js"));
|
|
129
|
+
const resolved = req.resolve(target);
|
|
130
|
+
return { resolved, resolver: "require", resolveCwd: dir };
|
|
118
131
|
} catch (e) {
|
|
119
|
-
return null
|
|
132
|
+
return null;
|
|
120
133
|
}
|
|
121
|
-
}
|
|
134
|
+
};
|
|
122
135
|
|
|
123
|
-
const direct = await tryResolve(baseDir)
|
|
124
|
-
if (direct) return direct
|
|
136
|
+
const direct = await tryResolve(baseDir);
|
|
137
|
+
if (direct) return direct;
|
|
125
138
|
|
|
126
|
-
const workspace = await findWorkspaceRoot(baseDir)
|
|
139
|
+
const workspace = await findWorkspaceRoot(baseDir);
|
|
127
140
|
if (workspace?.pkg?.workspaces) {
|
|
128
|
-
const dirs = await listWorkspacePackageDirs(
|
|
141
|
+
const dirs = await listWorkspacePackageDirs(
|
|
142
|
+
workspace.dir,
|
|
143
|
+
workspace.pkg.workspaces,
|
|
144
|
+
target,
|
|
145
|
+
);
|
|
129
146
|
for (const dir of dirs) {
|
|
130
|
-
const resolved = await tryResolve(dir)
|
|
131
|
-
if (resolved) return resolved
|
|
147
|
+
const resolved = await tryResolve(dir);
|
|
148
|
+
if (resolved) return resolved;
|
|
132
149
|
}
|
|
133
150
|
}
|
|
134
151
|
|
|
135
|
-
return { resolved: null, resolveCwd: baseDir, resolver: null }
|
|
152
|
+
return { resolved: null, resolveCwd: baseDir, resolver: null };
|
|
136
153
|
}
|
|
137
154
|
|
|
138
155
|
function findPackageJsonFromPath(startPath) {
|
|
139
|
-
if (!startPath) return null
|
|
140
|
-
let dir = path.dirname(startPath)
|
|
156
|
+
if (!startPath) return null;
|
|
157
|
+
let dir = path.dirname(startPath);
|
|
141
158
|
for (let i = 0; i < 10; i++) {
|
|
142
|
-
const candidate = path.join(dir, "package.json")
|
|
143
|
-
if (fs.existsSync(candidate)) return candidate
|
|
144
|
-
const parent = path.dirname(dir)
|
|
145
|
-
if (parent === dir) break
|
|
146
|
-
dir = parent
|
|
159
|
+
const candidate = path.join(dir, "package.json");
|
|
160
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
161
|
+
const parent = path.dirname(dir);
|
|
162
|
+
if (parent === dir) break;
|
|
163
|
+
dir = parent;
|
|
147
164
|
}
|
|
148
|
-
return null
|
|
165
|
+
return null;
|
|
149
166
|
}
|
|
150
167
|
|
|
151
168
|
function findPackageJsonInNodeModules(startDir, basePkg) {
|
|
152
|
-
if (!startDir || !basePkg) return null
|
|
153
|
-
const segments = basePkg.split("/")
|
|
154
|
-
let dir = path.resolve(startDir)
|
|
169
|
+
if (!startDir || !basePkg) return null;
|
|
170
|
+
const segments = basePkg.split("/");
|
|
171
|
+
let dir = path.resolve(startDir);
|
|
155
172
|
while (true) {
|
|
156
|
-
const candidate = path.join(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
173
|
+
const candidate = path.join(
|
|
174
|
+
dir,
|
|
175
|
+
"node_modules",
|
|
176
|
+
...segments,
|
|
177
|
+
"package.json",
|
|
178
|
+
);
|
|
179
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
180
|
+
const parent = path.dirname(dir);
|
|
181
|
+
if (parent === dir) break;
|
|
182
|
+
dir = parent;
|
|
161
183
|
}
|
|
162
|
-
return null
|
|
184
|
+
return null;
|
|
163
185
|
}
|
|
164
186
|
|
|
165
187
|
function resolvePackageInfo(basePkg, require, resolveFrom, resolvedPath) {
|
|
166
|
-
let pkgPath
|
|
167
|
-
let pkgDir
|
|
188
|
+
let pkgPath;
|
|
189
|
+
let pkgDir;
|
|
168
190
|
try {
|
|
169
|
-
pkgPath = require.resolve(`${basePkg}/package.json`)
|
|
170
|
-
pkgDir = path.dirname(pkgPath)
|
|
191
|
+
pkgPath = require.resolve(`${basePkg}/package.json`);
|
|
192
|
+
pkgDir = path.dirname(pkgPath);
|
|
171
193
|
} catch (e) {
|
|
172
194
|
try {
|
|
173
|
-
const mainPath = require.resolve(basePkg)
|
|
174
|
-
let dir = path.dirname(mainPath)
|
|
195
|
+
const mainPath = require.resolve(basePkg);
|
|
196
|
+
let dir = path.dirname(mainPath);
|
|
175
197
|
for (let i = 0; i < 5; i++) {
|
|
176
|
-
const candidate = path.join(dir, "package.json")
|
|
198
|
+
const candidate = path.join(dir, "package.json");
|
|
177
199
|
if (fs.existsSync(candidate)) {
|
|
178
|
-
pkgPath = candidate
|
|
179
|
-
pkgDir = dir
|
|
180
|
-
break
|
|
200
|
+
pkgPath = candidate;
|
|
201
|
+
pkgDir = dir;
|
|
202
|
+
break;
|
|
181
203
|
}
|
|
182
|
-
dir = path.dirname(dir)
|
|
204
|
+
dir = path.dirname(dir);
|
|
183
205
|
}
|
|
184
206
|
} catch (err) {}
|
|
185
207
|
}
|
|
186
208
|
|
|
187
209
|
if (!pkgPath && resolveFrom && basePkg) {
|
|
188
|
-
const fallback = findPackageJsonInNodeModules(resolveFrom, basePkg)
|
|
210
|
+
const fallback = findPackageJsonInNodeModules(resolveFrom, basePkg);
|
|
189
211
|
if (fallback) {
|
|
190
|
-
pkgPath = fallback
|
|
191
|
-
pkgDir = path.dirname(fallback)
|
|
212
|
+
pkgPath = fallback;
|
|
213
|
+
pkgDir = path.dirname(fallback);
|
|
192
214
|
}
|
|
193
215
|
}
|
|
194
216
|
|
|
195
217
|
if (!pkgPath && resolvedPath) {
|
|
196
|
-
const fallback = findPackageJsonFromPath(resolvedPath)
|
|
218
|
+
const fallback = findPackageJsonFromPath(resolvedPath);
|
|
197
219
|
if (fallback) {
|
|
198
|
-
pkgPath = fallback
|
|
199
|
-
pkgDir = path.dirname(fallback)
|
|
220
|
+
pkgPath = fallback;
|
|
221
|
+
pkgDir = path.dirname(fallback);
|
|
200
222
|
}
|
|
201
223
|
}
|
|
202
224
|
|
|
203
225
|
if (resolveFrom && basePkg) {
|
|
204
|
-
const rootCandidate = findPackageJsonInNodeModules(resolveFrom, basePkg)
|
|
226
|
+
const rootCandidate = findPackageJsonInNodeModules(resolveFrom, basePkg);
|
|
205
227
|
if (rootCandidate && rootCandidate !== pkgPath) {
|
|
206
|
-
pkgPath = rootCandidate
|
|
207
|
-
pkgDir = path.dirname(rootCandidate)
|
|
228
|
+
pkgPath = rootCandidate;
|
|
229
|
+
pkgDir = path.dirname(rootCandidate);
|
|
208
230
|
}
|
|
209
231
|
}
|
|
210
232
|
|
|
211
|
-
if (!pkgPath || !fs.existsSync(pkgPath)) return null
|
|
212
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"))
|
|
213
|
-
return { pkg, pkgPath, pkgDir }
|
|
233
|
+
if (!pkgPath || !fs.existsSync(pkgPath)) return null;
|
|
234
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
235
|
+
return { pkg, pkgPath, pkgDir };
|
|
214
236
|
}
|
|
215
237
|
|
|
216
238
|
function resolveTypesFromExportEntry(entry) {
|
|
217
|
-
if (!entry) return null
|
|
218
|
-
if (typeof entry === "string") return entry
|
|
239
|
+
if (!entry) return null;
|
|
240
|
+
if (typeof entry === "string") return entry;
|
|
219
241
|
if (typeof entry === "object") {
|
|
220
|
-
|
|
242
|
+
// First try explicit types field
|
|
243
|
+
if (typeof entry.types === "string") return entry.types;
|
|
244
|
+
|
|
245
|
+
// Then try import/require/default but look for their types too
|
|
221
246
|
for (const key of ["import", "require", "default"]) {
|
|
222
|
-
|
|
247
|
+
const value = entry[key];
|
|
248
|
+
if (typeof value === "string") {
|
|
249
|
+
// Try to find corresponding .d.ts
|
|
250
|
+
return value;
|
|
251
|
+
} else if (
|
|
252
|
+
value &&
|
|
253
|
+
typeof value === "object" &&
|
|
254
|
+
typeof value.types === "string"
|
|
255
|
+
) {
|
|
256
|
+
return value.types;
|
|
257
|
+
}
|
|
223
258
|
}
|
|
224
259
|
}
|
|
225
|
-
return null
|
|
260
|
+
return null;
|
|
226
261
|
}
|
|
227
262
|
|
|
228
263
|
function coerceTypesPath(typesPath) {
|
|
229
|
-
if (!typesPath) return typesPath
|
|
230
|
-
if (
|
|
231
|
-
|
|
264
|
+
if (!typesPath) return typesPath;
|
|
265
|
+
if (
|
|
266
|
+
typesPath.endsWith(".d.ts") ||
|
|
267
|
+
typesPath.endsWith(".d.cts") ||
|
|
268
|
+
typesPath.endsWith(".d.mts")
|
|
269
|
+
) {
|
|
270
|
+
return typesPath;
|
|
232
271
|
}
|
|
233
|
-
if (typesPath.endsWith(".mjs")) return typesPath.replace(/\.mjs$/, ".d.mts")
|
|
234
|
-
if (typesPath.endsWith(".cjs")) return typesPath.replace(/\.cjs$/, ".d.cts")
|
|
235
|
-
if (typesPath.endsWith(".js")) return typesPath.replace(/\.js$/, ".d.ts")
|
|
236
|
-
return typesPath
|
|
272
|
+
if (typesPath.endsWith(".mjs")) return typesPath.replace(/\.mjs$/, ".d.mts");
|
|
273
|
+
if (typesPath.endsWith(".cjs")) return typesPath.replace(/\.cjs$/, ".d.cts");
|
|
274
|
+
if (typesPath.endsWith(".js")) return typesPath.replace(/\.js$/, ".d.ts");
|
|
275
|
+
return typesPath;
|
|
237
276
|
}
|
|
238
277
|
|
|
239
|
-
function
|
|
240
|
-
if (!
|
|
241
|
-
|
|
242
|
-
|
|
278
|
+
function tryResolveTypesPackage(basePkgName, require) {
|
|
279
|
+
if (!basePkgName || basePkgName.startsWith("@types/")) return null;
|
|
280
|
+
|
|
281
|
+
// Convert package name to @types format
|
|
282
|
+
// react -> @types/react
|
|
283
|
+
// @foo/bar -> @types/foo__bar
|
|
284
|
+
let typesPackageName;
|
|
285
|
+
if (basePkgName.startsWith("@")) {
|
|
286
|
+
const [scope, name] = basePkgName.slice(1).split("/");
|
|
287
|
+
typesPackageName = `@types/${scope}__${name}`;
|
|
288
|
+
} else {
|
|
289
|
+
typesPackageName = `@types/${basePkgName}`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
// Try to resolve the @types package
|
|
294
|
+
const typesPkgJsonPath = require.resolve(
|
|
295
|
+
`${typesPackageName}/package.json`,
|
|
296
|
+
);
|
|
297
|
+
if (typesPkgJsonPath && fs.existsSync(typesPkgJsonPath)) {
|
|
298
|
+
const typesPkg = JSON.parse(fs.readFileSync(typesPkgJsonPath, "utf-8"));
|
|
299
|
+
const typesPkgDir = path.dirname(typesPkgJsonPath);
|
|
300
|
+
|
|
301
|
+
// Find the types file in @types package
|
|
302
|
+
const typesEntry = typesPkg.types || typesPkg.typings || "index.d.ts";
|
|
303
|
+
const typesFullPath = path.resolve(typesPkgDir, typesEntry);
|
|
304
|
+
|
|
305
|
+
if (fs.existsSync(typesFullPath)) {
|
|
306
|
+
return {
|
|
307
|
+
typesFile: typesEntry,
|
|
308
|
+
dtsPath: typesFullPath,
|
|
309
|
+
source: "@types",
|
|
310
|
+
pkgDir: typesPkgDir,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
} catch (e) {
|
|
315
|
+
// @types package not found or not resolvable
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function resolveTypesFile(pkg, pkgDir, subpath, basePkgName, require) {
|
|
322
|
+
if (!pkg || !pkgDir) return { typesFile: null, dtsPath: null, source: null };
|
|
323
|
+
let typesFile = null;
|
|
324
|
+
let source = null;
|
|
243
325
|
|
|
244
326
|
if (pkg.exports) {
|
|
245
|
-
let entry = null
|
|
327
|
+
let entry = null;
|
|
246
328
|
if (subpath) {
|
|
247
|
-
const key = subpath.startsWith(".") ? subpath : `./${subpath}
|
|
329
|
+
const key = subpath.startsWith(".") ? subpath : `./${subpath}`;
|
|
248
330
|
if (typeof pkg.exports === "object") {
|
|
249
|
-
entry = pkg.exports[key]
|
|
331
|
+
entry = pkg.exports[key];
|
|
250
332
|
}
|
|
251
333
|
} else if (typeof pkg.exports === "string") {
|
|
252
|
-
entry = pkg.exports
|
|
334
|
+
entry = pkg.exports;
|
|
253
335
|
} else if (typeof pkg.exports === "object") {
|
|
254
|
-
entry = pkg.exports["."] ?? pkg.exports["./"]
|
|
336
|
+
entry = pkg.exports["."] ?? pkg.exports["./"];
|
|
255
337
|
}
|
|
256
338
|
|
|
257
|
-
const typesFromExport = resolveTypesFromExportEntry(entry)
|
|
339
|
+
const typesFromExport = resolveTypesFromExportEntry(entry);
|
|
258
340
|
if (typesFromExport) {
|
|
259
|
-
typesFile = coerceTypesPath(typesFromExport)
|
|
260
|
-
source = "exports"
|
|
341
|
+
typesFile = coerceTypesPath(typesFromExport);
|
|
342
|
+
source = "exports";
|
|
261
343
|
}
|
|
262
344
|
}
|
|
263
345
|
|
|
264
346
|
if (!typesFile) {
|
|
265
|
-
typesFile = pkg.types || pkg.typings || null
|
|
266
|
-
if (typesFile) source = "package"
|
|
347
|
+
typesFile = pkg.types || pkg.typings || null;
|
|
348
|
+
if (typesFile) source = "package";
|
|
267
349
|
}
|
|
268
350
|
|
|
269
351
|
if (!typesFile) {
|
|
270
352
|
const candidates = [
|
|
353
|
+
"index.d.ts",
|
|
354
|
+
"index.d.cts",
|
|
355
|
+
"index.d.mts",
|
|
271
356
|
"dist/index.d.ts",
|
|
272
357
|
"dist/index.d.cts",
|
|
273
358
|
"dist/index.d.mts",
|
|
274
359
|
"lib/index.d.ts",
|
|
275
360
|
"lib/index.d.cts",
|
|
276
361
|
"lib/index.d.mts",
|
|
277
|
-
"index.d.ts",
|
|
278
|
-
"index.d.cts",
|
|
279
|
-
"index.d.mts",
|
|
280
362
|
"types/index.d.ts",
|
|
281
|
-
|
|
363
|
+
"types/index.d.cts",
|
|
364
|
+
"types/index.d.mts",
|
|
365
|
+
"src/index.d.ts",
|
|
366
|
+
"dist/types/index.d.ts",
|
|
367
|
+
"build/index.d.ts",
|
|
368
|
+
];
|
|
282
369
|
for (const candidate of candidates) {
|
|
283
|
-
const candidatePath = path.resolve(pkgDir, candidate)
|
|
370
|
+
const candidatePath = path.resolve(pkgDir, candidate);
|
|
284
371
|
if (fs.existsSync(candidatePath)) {
|
|
285
|
-
typesFile = candidate
|
|
286
|
-
source = "fallback"
|
|
287
|
-
break
|
|
372
|
+
typesFile = candidate;
|
|
373
|
+
source = "fallback";
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Last resort: search for any .d.ts file in package root or common directories
|
|
380
|
+
if (!typesFile) {
|
|
381
|
+
const searchDirs = [".", "dist", "lib", "types", "build"];
|
|
382
|
+
for (const dir of searchDirs) {
|
|
383
|
+
const searchPath = path.resolve(pkgDir, dir);
|
|
384
|
+
if (!fs.existsSync(searchPath)) continue;
|
|
385
|
+
|
|
386
|
+
try {
|
|
387
|
+
const files = fs.readdirSync(searchPath);
|
|
388
|
+
const dtsFile = files.find(
|
|
389
|
+
(f) =>
|
|
390
|
+
f.endsWith(".d.ts") || f.endsWith(".d.mts") || f.endsWith(".d.cts"),
|
|
391
|
+
);
|
|
392
|
+
if (dtsFile) {
|
|
393
|
+
typesFile = path.join(dir === "." ? "" : dir, dtsFile);
|
|
394
|
+
source = "search";
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
} catch (e) {
|
|
398
|
+
// Skip directories we can't read
|
|
288
399
|
}
|
|
289
400
|
}
|
|
290
401
|
}
|
|
291
402
|
|
|
292
403
|
if (!typesFile) {
|
|
293
|
-
|
|
404
|
+
// Try @types/* package before giving up
|
|
405
|
+
if (basePkgName && require) {
|
|
406
|
+
const typesPackageResult = tryResolveTypesPackage(basePkgName, require);
|
|
407
|
+
if (typesPackageResult) {
|
|
408
|
+
return typesPackageResult;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return { typesFile: null, dtsPath: null, source: null };
|
|
294
412
|
}
|
|
295
413
|
|
|
296
|
-
const resolved = path.isAbsolute(typesFile)
|
|
297
|
-
|
|
414
|
+
const resolved = path.isAbsolute(typesFile)
|
|
415
|
+
? typesFile
|
|
416
|
+
: path.resolve(pkgDir, typesFile);
|
|
417
|
+
let dtsPath = resolved;
|
|
298
418
|
if (!fs.existsSync(dtsPath)) {
|
|
299
|
-
const mapped = coerceTypesPath(dtsPath)
|
|
419
|
+
const mapped = coerceTypesPath(dtsPath);
|
|
300
420
|
if (mapped !== dtsPath && fs.existsSync(mapped)) {
|
|
301
|
-
dtsPath = mapped
|
|
421
|
+
dtsPath = mapped;
|
|
302
422
|
} else {
|
|
303
|
-
const replacements = [".d.ts", ".d.cts", ".d.mts"]
|
|
423
|
+
const replacements = [".d.ts", ".d.cts", ".d.mts"];
|
|
304
424
|
for (const ext of replacements) {
|
|
305
|
-
if (dtsPath.endsWith(ext)) continue
|
|
306
|
-
const candidate = `${dtsPath}${ext}
|
|
425
|
+
if (dtsPath.endsWith(ext)) continue;
|
|
426
|
+
const candidate = `${dtsPath}${ext}`;
|
|
307
427
|
if (fs.existsSync(candidate)) {
|
|
308
|
-
dtsPath = candidate
|
|
309
|
-
break
|
|
428
|
+
dtsPath = candidate;
|
|
429
|
+
break;
|
|
310
430
|
}
|
|
311
431
|
}
|
|
312
432
|
if (!fs.existsSync(dtsPath) && dtsPath.endsWith(".d.ts")) {
|
|
313
|
-
const ctsPath = dtsPath.replace(".d.ts", ".d.cts")
|
|
314
|
-
const mtsPath = dtsPath.replace(".d.ts", ".d.mts")
|
|
315
|
-
if (fs.existsSync(ctsPath)) dtsPath = ctsPath
|
|
316
|
-
else if (fs.existsSync(mtsPath)) dtsPath = mtsPath
|
|
433
|
+
const ctsPath = dtsPath.replace(".d.ts", ".d.cts");
|
|
434
|
+
const mtsPath = dtsPath.replace(".d.ts", ".d.mts");
|
|
435
|
+
if (fs.existsSync(ctsPath)) dtsPath = ctsPath;
|
|
436
|
+
else if (fs.existsSync(mtsPath)) dtsPath = mtsPath;
|
|
317
437
|
}
|
|
318
438
|
}
|
|
319
439
|
}
|
|
320
440
|
|
|
321
441
|
if (!fs.existsSync(dtsPath)) {
|
|
322
|
-
const altDir = path.dirname(dtsPath)
|
|
442
|
+
const altDir = path.dirname(dtsPath);
|
|
323
443
|
const altCandidates = [
|
|
324
444
|
"types.d.ts",
|
|
325
445
|
"types.d.mts",
|
|
@@ -327,185 +447,216 @@ function resolveTypesFile(pkg, pkgDir, subpath) {
|
|
|
327
447
|
"index.d.ts",
|
|
328
448
|
"index.d.mts",
|
|
329
449
|
"index.d.cts",
|
|
330
|
-
]
|
|
450
|
+
];
|
|
331
451
|
for (const candidate of altCandidates) {
|
|
332
|
-
const altPath = path.join(altDir, candidate)
|
|
452
|
+
const altPath = path.join(altDir, candidate);
|
|
333
453
|
if (fs.existsSync(altPath)) {
|
|
334
|
-
dtsPath = altPath
|
|
335
|
-
typesFile = path.relative(pkgDir, altPath)
|
|
454
|
+
dtsPath = altPath;
|
|
455
|
+
typesFile = path.relative(pkgDir, altPath);
|
|
336
456
|
if (!source || source === "exports" || source === "package") {
|
|
337
|
-
source = "fallback"
|
|
457
|
+
source = "fallback";
|
|
338
458
|
}
|
|
339
|
-
break
|
|
459
|
+
break;
|
|
340
460
|
}
|
|
341
461
|
}
|
|
342
462
|
}
|
|
343
463
|
|
|
344
|
-
|
|
464
|
+
// Final fallback: If declared types file doesn't exist, try @types/* package
|
|
465
|
+
if (!fs.existsSync(dtsPath) && basePkgName && require) {
|
|
466
|
+
const typesPackageResult = tryResolveTypesPackage(basePkgName, require);
|
|
467
|
+
if (typesPackageResult) {
|
|
468
|
+
return typesPackageResult;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return { typesFile, dtsPath, source };
|
|
345
473
|
}
|
|
346
474
|
|
|
347
475
|
function normalizeCjsExports(exportsValue) {
|
|
348
476
|
if (exportsValue === null || exportsValue === undefined) {
|
|
349
|
-
return { default: exportsValue }
|
|
477
|
+
return { default: exportsValue };
|
|
350
478
|
}
|
|
351
479
|
if (typeof exportsValue === "object" || typeof exportsValue === "function") {
|
|
352
|
-
return { ...exportsValue, default: exportsValue }
|
|
480
|
+
return { ...exportsValue, default: exportsValue };
|
|
353
481
|
}
|
|
354
|
-
return { default: exportsValue }
|
|
482
|
+
return { default: exportsValue };
|
|
355
483
|
}
|
|
356
484
|
|
|
357
485
|
function detectModuleFormat(resolvedPath, pkg) {
|
|
358
|
-
const ext = path.extname(resolvedPath)
|
|
359
|
-
if (ext === ".cjs" || ext === ".cts") return "cjs"
|
|
360
|
-
if (ext === ".mjs" || ext === ".mts") return "esm"
|
|
361
|
-
if (pkg?.type === "module") return "esm"
|
|
362
|
-
return "cjs"
|
|
486
|
+
const ext = path.extname(resolvedPath);
|
|
487
|
+
if (ext === ".cjs" || ext === ".cts") return "cjs";
|
|
488
|
+
if (ext === ".mjs" || ext === ".mts") return "esm";
|
|
489
|
+
if (pkg?.type === "module") return "esm";
|
|
490
|
+
return "cjs";
|
|
363
491
|
}
|
|
364
492
|
|
|
365
493
|
function isProbablyClass(fn) {
|
|
366
|
-
if (typeof fn !== "function") return false
|
|
367
|
-
const source = Function.prototype.toString.call(fn)
|
|
368
|
-
if (source.startsWith("class ")) return true
|
|
494
|
+
if (typeof fn !== "function") return false;
|
|
495
|
+
const source = Function.prototype.toString.call(fn);
|
|
496
|
+
if (source.startsWith("class ")) return true;
|
|
369
497
|
if (fn.prototype) {
|
|
370
|
-
const protoProps = Object.getOwnPropertyNames(fn.prototype).filter(
|
|
371
|
-
|
|
498
|
+
const protoProps = Object.getOwnPropertyNames(fn.prototype).filter(
|
|
499
|
+
(p) => p !== "constructor",
|
|
500
|
+
);
|
|
501
|
+
if (protoProps.length > 0) return true;
|
|
372
502
|
}
|
|
373
|
-
return false
|
|
503
|
+
return false;
|
|
374
504
|
}
|
|
375
505
|
|
|
376
506
|
async function loadModuleExports(resolvedPath, require, pkg) {
|
|
377
|
-
const format = detectModuleFormat(resolvedPath, pkg)
|
|
507
|
+
const format = detectModuleFormat(resolvedPath, pkg);
|
|
378
508
|
if (format === "cjs") {
|
|
379
|
-
const mod = require(resolvedPath)
|
|
380
|
-
return { module: normalizeCjsExports(mod), format }
|
|
509
|
+
const mod = require(resolvedPath);
|
|
510
|
+
return { module: normalizeCjsExports(mod), format };
|
|
381
511
|
}
|
|
382
|
-
const mod = await import(pathToFileURL(resolvedPath).href)
|
|
383
|
-
return { module: mod, format }
|
|
512
|
+
const mod = await import(pathToFileURL(resolvedPath).href);
|
|
513
|
+
return { module: mod, format };
|
|
384
514
|
}
|
|
385
515
|
|
|
386
516
|
function buildSymbolMatcher(symbols, fallbackFilter) {
|
|
387
|
-
const patterns = []
|
|
517
|
+
const patterns = [];
|
|
388
518
|
const addPattern = (value) => {
|
|
389
|
-
if (!value) return
|
|
519
|
+
if (!value) return;
|
|
390
520
|
if (value.startsWith("/") && value.endsWith("/") && value.length > 2) {
|
|
391
521
|
try {
|
|
392
|
-
patterns.push({
|
|
393
|
-
|
|
522
|
+
patterns.push({
|
|
523
|
+
type: "regex",
|
|
524
|
+
value: new RegExp(value.slice(1, -1), "i"),
|
|
525
|
+
});
|
|
526
|
+
return;
|
|
394
527
|
} catch (e) {
|
|
395
|
-
patterns.push({ type: "substring", value: value.toLowerCase() })
|
|
396
|
-
return
|
|
528
|
+
patterns.push({ type: "substring", value: value.toLowerCase() });
|
|
529
|
+
return;
|
|
397
530
|
}
|
|
398
531
|
}
|
|
399
532
|
if (value.includes("*")) {
|
|
400
|
-
const escaped = value
|
|
401
|
-
|
|
402
|
-
|
|
533
|
+
const escaped = value
|
|
534
|
+
.replace(/[.+?^${}()|[\]\\]/g, "\\$&")
|
|
535
|
+
.replace(/\*/g, ".*");
|
|
536
|
+
patterns.push({ type: "regex", value: new RegExp(`^${escaped}$`, "i") });
|
|
537
|
+
return;
|
|
403
538
|
}
|
|
404
|
-
patterns.push({ type: "substring", value: value.toLowerCase() })
|
|
405
|
-
}
|
|
539
|
+
patterns.push({ type: "substring", value: value.toLowerCase() });
|
|
540
|
+
};
|
|
406
541
|
|
|
407
542
|
if (Array.isArray(symbols)) {
|
|
408
|
-
symbols.forEach(addPattern)
|
|
543
|
+
symbols.forEach(addPattern);
|
|
409
544
|
} else if (typeof symbols === "string") {
|
|
410
|
-
addPattern(symbols)
|
|
545
|
+
addPattern(symbols);
|
|
411
546
|
} else if (fallbackFilter) {
|
|
412
|
-
addPattern(fallbackFilter)
|
|
547
|
+
addPattern(fallbackFilter);
|
|
413
548
|
}
|
|
414
549
|
|
|
415
|
-
if (patterns.length === 0) return null
|
|
550
|
+
if (patterns.length === 0) return null;
|
|
416
551
|
return (name) => {
|
|
417
|
-
const lower = name.toLowerCase()
|
|
552
|
+
const lower = name.toLowerCase();
|
|
418
553
|
return patterns.some((pattern) => {
|
|
419
|
-
if (pattern.type === "regex") return pattern.value.test(name)
|
|
420
|
-
return lower.includes(pattern.value)
|
|
421
|
-
})
|
|
422
|
-
}
|
|
554
|
+
if (pattern.type === "regex") return pattern.value.test(name);
|
|
555
|
+
return lower.includes(pattern.value);
|
|
556
|
+
});
|
|
557
|
+
};
|
|
423
558
|
}
|
|
424
559
|
|
|
425
560
|
function truncateSummary(text, mode, maxLen, truncateMode) {
|
|
426
|
-
if (!text) return ""
|
|
427
|
-
const normalized = text.replace(/\s+/g, " ").trim()
|
|
428
|
-
if (truncateMode === "none") return normalized
|
|
429
|
-
const limit =
|
|
430
|
-
|
|
561
|
+
if (!text) return "";
|
|
562
|
+
const normalized = text.replace(/\s+/g, " ").trim();
|
|
563
|
+
if (truncateMode === "none") return normalized;
|
|
564
|
+
const limit =
|
|
565
|
+
typeof maxLen === "number" ? maxLen : mode === "compact" ? 240 : 1200;
|
|
566
|
+
if (normalized.length <= limit) return normalized;
|
|
431
567
|
if (truncateMode === "sentence") {
|
|
432
|
-
const slice = normalized.slice(0, limit)
|
|
433
|
-
const lastPeriod = Math.max(
|
|
568
|
+
const slice = normalized.slice(0, limit);
|
|
569
|
+
const lastPeriod = Math.max(
|
|
570
|
+
slice.lastIndexOf("."),
|
|
571
|
+
slice.lastIndexOf("!"),
|
|
572
|
+
slice.lastIndexOf("?"),
|
|
573
|
+
);
|
|
434
574
|
if (lastPeriod > 40) {
|
|
435
|
-
return `${slice.slice(0, lastPeriod + 1)}
|
|
575
|
+
return `${slice.slice(0, lastPeriod + 1)}`;
|
|
436
576
|
}
|
|
437
577
|
}
|
|
438
578
|
if (truncateMode === "word") {
|
|
439
|
-
const slice = normalized.slice(0, limit)
|
|
440
|
-
const lastSpace = slice.lastIndexOf(" ")
|
|
579
|
+
const slice = normalized.slice(0, limit);
|
|
580
|
+
const lastSpace = slice.lastIndexOf(" ");
|
|
441
581
|
if (lastSpace > 40) {
|
|
442
|
-
return `${slice.slice(0, lastSpace)}
|
|
582
|
+
return `${slice.slice(0, lastSpace)}...`;
|
|
443
583
|
}
|
|
444
584
|
}
|
|
445
|
-
return `${normalized.slice(0, Math.max(0, limit - 3))}
|
|
585
|
+
return `${normalized.slice(0, Math.max(0, limit - 3))}...`;
|
|
446
586
|
}
|
|
447
587
|
|
|
448
588
|
function formatJsdocEntry(name, doc, options) {
|
|
449
|
-
const mode = options.mode || "compact"
|
|
450
|
-
const truncateMode = options.truncate || "word"
|
|
451
|
-
const maxLen = options.maxLen
|
|
452
|
-
const sections =
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const
|
|
457
|
-
const
|
|
458
|
-
|
|
589
|
+
const mode = options.mode || "compact";
|
|
590
|
+
const truncateMode = options.truncate || "word";
|
|
591
|
+
const maxLen = options.maxLen;
|
|
592
|
+
const sections =
|
|
593
|
+
options.sections && options.sections.length > 0
|
|
594
|
+
? options.sections
|
|
595
|
+
: ["summary", "tags"];
|
|
596
|
+
const includeTags = options.tags?.include || null;
|
|
597
|
+
const excludeTags = options.tags?.exclude || null;
|
|
598
|
+
|
|
599
|
+
const summary = truncateSummary(
|
|
600
|
+
doc.summary || "",
|
|
601
|
+
mode,
|
|
602
|
+
maxLen,
|
|
603
|
+
truncateMode,
|
|
604
|
+
);
|
|
605
|
+
const tags = doc.tags || {};
|
|
606
|
+
const tagLines = [];
|
|
459
607
|
|
|
460
608
|
const addTag = (tagName, values) => {
|
|
461
609
|
if (!values || values.length === 0) {
|
|
462
|
-
tagLines.push(`@${tagName}`)
|
|
463
|
-
return
|
|
610
|
+
tagLines.push(`@${tagName}`);
|
|
611
|
+
return;
|
|
464
612
|
}
|
|
465
613
|
for (const value of values) {
|
|
466
|
-
tagLines.push(value ? `@${tagName} ${value}` : `@${tagName}`)
|
|
614
|
+
tagLines.push(value ? `@${tagName} ${value}` : `@${tagName}`);
|
|
467
615
|
}
|
|
468
|
-
}
|
|
616
|
+
};
|
|
469
617
|
|
|
470
|
-
const wantParams = sections.includes("params")
|
|
471
|
-
const wantReturns = sections.includes("returns")
|
|
472
|
-
const wantTags = sections.includes("tags")
|
|
618
|
+
const wantParams = sections.includes("params");
|
|
619
|
+
const wantReturns = sections.includes("returns");
|
|
620
|
+
const wantTags = sections.includes("tags");
|
|
473
621
|
|
|
474
622
|
if (wantParams) {
|
|
475
|
-
if (tags.param) addTag("param", tags.param)
|
|
623
|
+
if (tags.param) addTag("param", tags.param);
|
|
476
624
|
}
|
|
477
625
|
if (wantReturns) {
|
|
478
|
-
if (tags.returns) addTag("returns", tags.returns)
|
|
479
|
-
if (tags.return) addTag("return", tags.return)
|
|
626
|
+
if (tags.returns) addTag("returns", tags.returns);
|
|
627
|
+
if (tags.return) addTag("return", tags.return);
|
|
480
628
|
}
|
|
481
629
|
if (wantTags) {
|
|
482
630
|
for (const [tagName, values] of Object.entries(tags)) {
|
|
483
|
-
if (tagName === "param" || tagName === "returns" || tagName === "return")
|
|
484
|
-
|
|
485
|
-
if (
|
|
631
|
+
if (tagName === "param" || tagName === "returns" || tagName === "return")
|
|
632
|
+
continue;
|
|
633
|
+
if (includeTags && !includeTags.includes(tagName)) continue;
|
|
634
|
+
if (excludeTags && excludeTags.includes(tagName)) continue;
|
|
486
635
|
if (mode === "compact" && !includeTags && !excludeTags) {
|
|
487
|
-
if (!["deprecated", "since", "experimental"].includes(tagName))
|
|
636
|
+
if (!["deprecated", "since", "experimental"].includes(tagName))
|
|
637
|
+
continue;
|
|
488
638
|
}
|
|
489
|
-
addTag(tagName, values)
|
|
639
|
+
addTag(tagName, values);
|
|
490
640
|
}
|
|
491
641
|
}
|
|
492
642
|
|
|
493
|
-
const parts = []
|
|
643
|
+
const parts = [];
|
|
494
644
|
if (sections.includes("summary") && summary) {
|
|
495
|
-
parts.push(summary)
|
|
645
|
+
parts.push(summary);
|
|
496
646
|
}
|
|
497
647
|
if (tagLines.length > 0) {
|
|
498
|
-
parts.push(tagLines.join("; "))
|
|
648
|
+
parts.push(tagLines.join("; "));
|
|
499
649
|
}
|
|
500
650
|
|
|
501
|
-
return `${name}: ${parts.join(" | ")}`.trim()
|
|
651
|
+
return `${name}: ${parts.join(" | ")}`.trim();
|
|
502
652
|
}
|
|
503
653
|
|
|
504
654
|
function filterTypeInfo(typeInfo, filter, kindFilter) {
|
|
505
|
-
if (!typeInfo) return null
|
|
506
|
-
const includeName = (name) => !filter || name.toLowerCase().includes(filter)
|
|
507
|
-
const allow = (kind) =>
|
|
508
|
-
|
|
655
|
+
if (!typeInfo) return null;
|
|
656
|
+
const includeName = (name) => !filter || name.toLowerCase().includes(filter);
|
|
657
|
+
const allow = (kind) =>
|
|
658
|
+
!kindFilter || kindFilter.length === 0 || kindFilter.includes(kind);
|
|
659
|
+
const includeExtras = !kindFilter || kindFilter.length === 0;
|
|
509
660
|
|
|
510
661
|
const filtered = {
|
|
511
662
|
functions: {},
|
|
@@ -516,270 +667,431 @@ function filterTypeInfo(typeInfo, filter, kindFilter) {
|
|
|
516
667
|
namespaces: {},
|
|
517
668
|
defaults: [],
|
|
518
669
|
jsdoc: {},
|
|
519
|
-
}
|
|
670
|
+
};
|
|
520
671
|
|
|
521
672
|
if (allow("function")) {
|
|
522
673
|
for (const [name, info] of Object.entries(typeInfo.functions)) {
|
|
523
|
-
if (includeName(name)) filtered.functions[name] = info
|
|
674
|
+
if (includeName(name)) filtered.functions[name] = info;
|
|
524
675
|
}
|
|
525
676
|
}
|
|
526
677
|
|
|
527
678
|
if (allow("interface")) {
|
|
528
679
|
for (const [name, props] of Object.entries(typeInfo.interfaces)) {
|
|
529
|
-
if (includeName(name)) filtered.interfaces[name] = props
|
|
680
|
+
if (includeName(name)) filtered.interfaces[name] = props;
|
|
530
681
|
}
|
|
531
682
|
}
|
|
532
683
|
|
|
533
684
|
if (allow("type")) {
|
|
534
685
|
for (const [name, def] of Object.entries(typeInfo.types)) {
|
|
535
|
-
if (includeName(name)) filtered.types[name] = def
|
|
686
|
+
if (includeName(name)) filtered.types[name] = def;
|
|
536
687
|
}
|
|
537
688
|
}
|
|
538
689
|
|
|
539
690
|
if (allow("class")) {
|
|
540
691
|
for (const [name, info] of Object.entries(typeInfo.classes)) {
|
|
541
|
-
if (includeName(name)) filtered.classes[name] = info
|
|
692
|
+
if (includeName(name)) filtered.classes[name] = info;
|
|
542
693
|
}
|
|
543
694
|
}
|
|
544
695
|
|
|
545
696
|
if (includeExtras) {
|
|
546
697
|
for (const [name, members] of Object.entries(typeInfo.enums || {})) {
|
|
547
|
-
if (includeName(name)) filtered.enums[name] = members
|
|
698
|
+
if (includeName(name)) filtered.enums[name] = members;
|
|
548
699
|
}
|
|
549
700
|
for (const [name, value] of Object.entries(typeInfo.namespaces || {})) {
|
|
550
|
-
if (includeName(name)) filtered.namespaces[name] = value
|
|
701
|
+
if (includeName(name)) filtered.namespaces[name] = value;
|
|
551
702
|
}
|
|
552
|
-
filtered.defaults = (typeInfo.defaults || []).filter(
|
|
703
|
+
filtered.defaults = (typeInfo.defaults || []).filter(
|
|
704
|
+
(value) => includeName("default") || includeName(value),
|
|
705
|
+
);
|
|
553
706
|
}
|
|
554
707
|
|
|
555
708
|
if (typeInfo.jsdoc) {
|
|
556
709
|
for (const [name, doc] of Object.entries(typeInfo.jsdoc)) {
|
|
557
|
-
if (includeName(name)) filtered.jsdoc[name] = doc
|
|
710
|
+
if (includeName(name)) filtered.jsdoc[name] = doc;
|
|
558
711
|
}
|
|
559
712
|
}
|
|
560
713
|
|
|
561
|
-
return filtered
|
|
714
|
+
return filtered;
|
|
562
715
|
}
|
|
563
716
|
|
|
564
717
|
// Helper function to inspect object properties recursively
|
|
565
718
|
function inspectObject(obj, currentDepth = 0, maxDepth = 1, indent = " ") {
|
|
566
719
|
if (currentDepth >= maxDepth || obj === null || obj === undefined) {
|
|
567
|
-
return []
|
|
720
|
+
return [];
|
|
568
721
|
}
|
|
569
722
|
|
|
570
|
-
const lines = []
|
|
723
|
+
const lines = [];
|
|
571
724
|
try {
|
|
572
|
-
const descriptors = Object.getOwnPropertyDescriptors(obj)
|
|
573
|
-
const keys = Object.keys(descriptors).slice(0, 10) // Limit to first 10 properties
|
|
725
|
+
const descriptors = Object.getOwnPropertyDescriptors(obj);
|
|
726
|
+
const keys = Object.keys(descriptors).slice(0, 10); // Limit to first 10 properties
|
|
574
727
|
for (const key of keys) {
|
|
575
728
|
try {
|
|
576
|
-
const descriptor = descriptors[key]
|
|
729
|
+
const descriptor = descriptors[key];
|
|
577
730
|
if (descriptor.get || descriptor.set) {
|
|
578
|
-
lines.push(`${indent.repeat(currentDepth + 1)}${key}: <getter>`)
|
|
579
|
-
continue
|
|
731
|
+
lines.push(`${indent.repeat(currentDepth + 1)}${key}: <getter>`);
|
|
732
|
+
continue;
|
|
580
733
|
}
|
|
581
|
-
const value = descriptor.value
|
|
582
|
-
const type = typeof value
|
|
583
|
-
const prefix = indent.repeat(currentDepth + 1)
|
|
734
|
+
const value = descriptor.value;
|
|
735
|
+
const type = typeof value;
|
|
736
|
+
const prefix = indent.repeat(currentDepth + 1);
|
|
584
737
|
|
|
585
738
|
if (type === "function") {
|
|
586
|
-
const paramCount = value.length
|
|
587
|
-
lines.push(
|
|
739
|
+
const paramCount = value.length;
|
|
740
|
+
lines.push(
|
|
741
|
+
`${prefix}${key}(${paramCount} param${paramCount !== 1 ? "s" : ""})`,
|
|
742
|
+
);
|
|
588
743
|
} else if (type === "object" && value !== null) {
|
|
589
|
-
lines.push(`${prefix}${key}: {object}`)
|
|
744
|
+
lines.push(`${prefix}${key}: {object}`);
|
|
590
745
|
if (currentDepth + 1 < maxDepth) {
|
|
591
|
-
lines.push(
|
|
746
|
+
lines.push(
|
|
747
|
+
...inspectObject(value, currentDepth + 1, maxDepth, indent),
|
|
748
|
+
);
|
|
592
749
|
}
|
|
593
750
|
} else {
|
|
594
|
-
const valStr =
|
|
595
|
-
|
|
751
|
+
const valStr =
|
|
752
|
+
type === "string"
|
|
753
|
+
? `"${String(value).substring(0, 30)}"`
|
|
754
|
+
: String(value).substring(0, 30);
|
|
755
|
+
lines.push(`${prefix}${key}: ${valStr}`);
|
|
596
756
|
}
|
|
597
757
|
} catch (e) {
|
|
598
758
|
// Skip properties that throw on access
|
|
599
759
|
}
|
|
600
760
|
}
|
|
601
|
-
const totalKeys = Object.keys(descriptors).length
|
|
761
|
+
const totalKeys = Object.keys(descriptors).length;
|
|
602
762
|
if (totalKeys > 10) {
|
|
603
|
-
lines.push(
|
|
763
|
+
lines.push(
|
|
764
|
+
`${indent.repeat(currentDepth + 1)}... and ${totalKeys - 10} more`,
|
|
765
|
+
);
|
|
604
766
|
}
|
|
605
767
|
} catch (e) {
|
|
606
768
|
// Skip if object is not enumerable
|
|
607
769
|
}
|
|
608
|
-
return lines
|
|
770
|
+
return lines;
|
|
609
771
|
}
|
|
610
772
|
|
|
611
773
|
export async function runInspect(options) {
|
|
612
|
-
const collect = !options?.write && !options?.writeError
|
|
613
|
-
const output = collect ? [] : null
|
|
614
|
-
const write = options?.write
|
|
615
|
-
const writeError = options?.writeError ?? options?.write
|
|
774
|
+
const collect = !options?.write && !options?.writeError;
|
|
775
|
+
const output = collect ? [] : null;
|
|
776
|
+
const write = options?.write;
|
|
777
|
+
const writeError = options?.writeError ?? options?.write;
|
|
778
|
+
const format =
|
|
779
|
+
options?.format === "object"
|
|
780
|
+
? "object"
|
|
781
|
+
: options?.format === "json"
|
|
782
|
+
? "json"
|
|
783
|
+
: "text";
|
|
616
784
|
|
|
617
785
|
const log = (line = "") => {
|
|
618
|
-
if (
|
|
619
|
-
|
|
620
|
-
|
|
786
|
+
if (format === "json" || format === "object") return;
|
|
787
|
+
if (collect) output.push(String(line));
|
|
788
|
+
else if (write) write(String(line));
|
|
789
|
+
};
|
|
621
790
|
const logErr = (line = "") => {
|
|
622
|
-
if (
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
const
|
|
628
|
-
const
|
|
629
|
-
const
|
|
630
|
-
const
|
|
631
|
-
const
|
|
632
|
-
const
|
|
633
|
-
|
|
791
|
+
if (format === "json" || format === "object") return;
|
|
792
|
+
if (collect) output.push(String(line));
|
|
793
|
+
else if (writeError) writeError(String(line));
|
|
794
|
+
};
|
|
795
|
+
|
|
796
|
+
const target = options?.target;
|
|
797
|
+
const filterRaw = options?.filter || null;
|
|
798
|
+
const filter = filterRaw ? filterRaw.toLowerCase() : null;
|
|
799
|
+
const showTypes = Boolean(options?.showTypes);
|
|
800
|
+
const remote = Boolean(options?.remote);
|
|
801
|
+
const remoteVersion = options?.remoteVersion
|
|
802
|
+
? String(options.remoteVersion)
|
|
803
|
+
: null;
|
|
804
|
+
const jsdocModeRaw = options?.jsdoc
|
|
805
|
+
? String(options.jsdoc).toLowerCase()
|
|
806
|
+
: null;
|
|
807
|
+
const jsdocQuery = options?.jsdocQuery || null;
|
|
808
|
+
const jsdocOutputRaw = options?.jsdocOutput
|
|
809
|
+
? String(options.jsdocOutput).toLowerCase()
|
|
810
|
+
: null;
|
|
811
|
+
const jsdocOutput = jsdocOutputRaw || (jsdocQuery ? "section" : "off");
|
|
812
|
+
const wantJsdoc = jsdocOutput !== "off";
|
|
634
813
|
const jsdocMode =
|
|
635
|
-
showTypes || wantJsdoc
|
|
814
|
+
showTypes || wantJsdoc
|
|
815
|
+
? jsdocQuery?.mode || jsdocModeRaw || "compact"
|
|
816
|
+
: "off";
|
|
636
817
|
const kindFilter = Array.isArray(options?.kind)
|
|
637
818
|
? options.kind.map((k) => String(k).trim().toLowerCase())
|
|
638
|
-
: null
|
|
639
|
-
let depth = typeof options?.depth === "number" ? options.depth : 1
|
|
640
|
-
if (isNaN(depth) || depth < 0 || depth > 5) depth = 1
|
|
819
|
+
: null;
|
|
820
|
+
let depth = typeof options?.depth === "number" ? options.depth : 1;
|
|
821
|
+
if (isNaN(depth) || depth < 0 || depth > 5) depth = 1;
|
|
822
|
+
const analyzeSource = Boolean(options?.analyzeSource);
|
|
823
|
+
const sourceMaxFiles =
|
|
824
|
+
typeof options?.sourceMaxFiles === "number" ? options.sourceMaxFiles : 5;
|
|
825
|
+
const sourceIncludeBody = Boolean(options?.sourceIncludeBody);
|
|
826
|
+
|
|
827
|
+
const jsonOutput =
|
|
828
|
+
format === "json" || format === "object"
|
|
829
|
+
? {
|
|
830
|
+
schemaVersion: 1,
|
|
831
|
+
package: null,
|
|
832
|
+
version: null,
|
|
833
|
+
description: null,
|
|
834
|
+
exports: null,
|
|
835
|
+
types: null,
|
|
836
|
+
docs: null,
|
|
837
|
+
sections: null,
|
|
838
|
+
examples: null,
|
|
839
|
+
resolution: null,
|
|
840
|
+
meta: {
|
|
841
|
+
target: target || null,
|
|
842
|
+
showTypes,
|
|
843
|
+
format,
|
|
844
|
+
remote,
|
|
845
|
+
remoteVersion,
|
|
846
|
+
},
|
|
847
|
+
warnings: [],
|
|
848
|
+
}
|
|
849
|
+
: null;
|
|
850
|
+
|
|
851
|
+
const warn = (message) => {
|
|
852
|
+
if (jsonOutput) {
|
|
853
|
+
jsonOutput.warnings.push(message);
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
logErr(`⚠️ ${message}`);
|
|
857
|
+
};
|
|
641
858
|
|
|
642
859
|
if (!target) {
|
|
643
860
|
logErr(
|
|
644
861
|
"Uso: node inspect.mjs <pacote> [filtro] [--filter VALUE] [--types] [--jsdoc off|compact|full] [--jsdoc-output off|section|inline|only] [--jsdoc-symbol NAME|glob|/re/] [--jsdoc-sections summary,params,returns,tags] [--jsdoc-tags t1,t2] [--jsdoc-tags-exclude t1,t2] [--jsdoc-truncate none|sentence|word] [--jsdoc-max-len N] [--kind function,class,...] [--depth N] [--resolve-from DIR]",
|
|
645
|
-
)
|
|
646
|
-
|
|
862
|
+
);
|
|
863
|
+
if (format === "object") return jsonOutput;
|
|
864
|
+
if (format === "json") return JSON.stringify(jsonOutput, null, 2);
|
|
865
|
+
return collect ? output.join("\n") : "";
|
|
647
866
|
}
|
|
648
867
|
|
|
649
|
-
const baseCwd = options?.cwd
|
|
650
|
-
|
|
868
|
+
const baseCwd = options?.cwd;
|
|
869
|
+
let resolveFrom = options?.resolveFrom
|
|
651
870
|
? path.resolve(baseCwd || process.cwd(), options.resolveFrom)
|
|
652
|
-
: baseCwd
|
|
871
|
+
: baseCwd;
|
|
872
|
+
|
|
873
|
+
if (remote) {
|
|
874
|
+
const basePkgName = getPackageName(target);
|
|
875
|
+
if (basePkgName) {
|
|
876
|
+
const spec = remoteVersion || "latest";
|
|
877
|
+
log(`\n🌐 Remote: downloading ${basePkgName}@${spec}...`);
|
|
878
|
+
try {
|
|
879
|
+
const downloaded = downloadVersion(basePkgName, spec, {
|
|
880
|
+
timeout: 120000,
|
|
881
|
+
});
|
|
882
|
+
resolveFrom = downloaded.path;
|
|
883
|
+
log(` CachePath: ${downloaded.path}`);
|
|
884
|
+
log(` Cached: ${downloaded.cached ? "yes" : "no"}`);
|
|
885
|
+
} catch (e) {
|
|
886
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
887
|
+
logErr(`\n❌ Remote download failed: ${message}`);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
653
892
|
if (baseCwd) {
|
|
654
893
|
try {
|
|
655
|
-
process.chdir(baseCwd)
|
|
894
|
+
process.chdir(baseCwd);
|
|
656
895
|
} catch (e) {}
|
|
657
896
|
}
|
|
658
897
|
|
|
659
|
-
const resolution = await resolveTargetModule(target, baseCwd, resolveFrom)
|
|
660
|
-
const resolveCwd = resolution.resolveCwd || baseCwd
|
|
661
|
-
const require = createRequire(
|
|
662
|
-
|
|
898
|
+
const resolution = await resolveTargetModule(target, baseCwd, resolveFrom);
|
|
899
|
+
const resolveCwd = resolution.resolveCwd || baseCwd;
|
|
900
|
+
const require = createRequire(
|
|
901
|
+
resolveCwd ? path.join(resolveCwd, "noop.js") : import.meta.url,
|
|
902
|
+
);
|
|
903
|
+
const resolvedPath = resolution.resolved;
|
|
663
904
|
const entrypointPath =
|
|
664
905
|
typeof resolvedPath === "string" && resolvedPath.startsWith("file://")
|
|
665
906
|
? fileURLToPath(resolvedPath)
|
|
666
|
-
: resolvedPath
|
|
667
|
-
const entrypointExists = entrypointPath
|
|
907
|
+
: resolvedPath;
|
|
908
|
+
const entrypointExists = entrypointPath
|
|
909
|
+
? fs.existsSync(entrypointPath)
|
|
910
|
+
: false;
|
|
911
|
+
|
|
912
|
+
if (jsonOutput) {
|
|
913
|
+
jsonOutput.resolution = {
|
|
914
|
+
target,
|
|
915
|
+
resolveFrom: resolveFrom || null,
|
|
916
|
+
resolveCwd: resolveCwd || null,
|
|
917
|
+
resolved: resolution.resolved || null,
|
|
918
|
+
entrypointPath: entrypointPath || null,
|
|
919
|
+
entrypointExists,
|
|
920
|
+
};
|
|
921
|
+
}
|
|
668
922
|
|
|
669
|
-
const flags = []
|
|
670
|
-
if (
|
|
671
|
-
if (kindFilter) flags.push(`Kind: ${kindFilter.join(",")}`)
|
|
672
|
-
if (showTypes || wantJsdoc) flags.push("Type Analysis")
|
|
673
|
-
if (
|
|
674
|
-
if (
|
|
923
|
+
const flags = [];
|
|
924
|
+
if (filterRaw) flags.push(`Filtro: "${filterRaw}"`);
|
|
925
|
+
if (kindFilter) flags.push(`Kind: ${kindFilter.join(",")}`);
|
|
926
|
+
if (showTypes || wantJsdoc) flags.push("Type Analysis");
|
|
927
|
+
if (remote) flags.push(`Remote${remoteVersion ? `@${remoteVersion}` : ""}`);
|
|
928
|
+
if (jsdocOutput !== "off") flags.push(`JSDoc: ${jsdocMode}`);
|
|
929
|
+
if (depth > 1) flags.push(`Depth: ${depth}`);
|
|
675
930
|
|
|
676
|
-
const flagsStr = flags.length > 0 ? ` (${flags.join(" | ")})` : ""
|
|
677
|
-
log(`🔍 Target: ${target}${flagsStr}`)
|
|
931
|
+
const flagsStr = flags.length > 0 ? ` (${flags.join(" | ")})` : "";
|
|
932
|
+
log(`🔍 Target: ${target}${flagsStr}`);
|
|
678
933
|
|
|
679
934
|
try {
|
|
680
935
|
if (!resolution.resolved) {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
logErr(
|
|
684
|
-
|
|
936
|
+
const errorMsg = `Não foi possível resolver '${target}'`;
|
|
937
|
+
warn(errorMsg);
|
|
938
|
+
logErr(`\n❌ Erro: ${errorMsg}`);
|
|
939
|
+
logErr(`ResolveFrom: ${resolveFrom || baseCwd || "unknown"}`);
|
|
940
|
+
logErr(
|
|
941
|
+
`Certifique-se que '${target}' está instalado e é um caminho válido.`,
|
|
942
|
+
);
|
|
943
|
+
if (format === "object") return jsonOutput;
|
|
944
|
+
if (format === "json") return JSON.stringify(jsonOutput, null, 2);
|
|
945
|
+
return collect ? output.join("\n") : "";
|
|
685
946
|
}
|
|
686
947
|
|
|
687
|
-
const basePkg = getPackageName(target)
|
|
688
|
-
const subpath = getPackageSubpath(target)
|
|
948
|
+
const basePkg = getPackageName(target);
|
|
949
|
+
const subpath = getPackageSubpath(target);
|
|
689
950
|
const pkgInfo = basePkg
|
|
690
|
-
? resolvePackageInfo(
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
951
|
+
? resolvePackageInfo(
|
|
952
|
+
basePkg,
|
|
953
|
+
require,
|
|
954
|
+
resolveFrom || baseCwd || process.cwd(),
|
|
955
|
+
entrypointPath,
|
|
956
|
+
)
|
|
957
|
+
: null;
|
|
958
|
+
const pkg = pkgInfo?.pkg;
|
|
959
|
+
const pkgDir = pkgInfo?.pkgDir;
|
|
960
|
+
|
|
961
|
+
log(`\n🧭 Resolution:`);
|
|
962
|
+
log(` ResolveFrom: ${resolveFrom || baseCwd || "unknown"}`);
|
|
963
|
+
log(` Entrypoint: ${resolution.resolved}`);
|
|
698
964
|
if (resolution.resolver) {
|
|
699
|
-
log(` Resolver: ${resolution.resolver}`)
|
|
965
|
+
log(` Resolver: ${resolution.resolver}`);
|
|
700
966
|
}
|
|
701
967
|
if (pkgDir) {
|
|
702
|
-
log(` PackageRoot: ${pkgDir}`)
|
|
968
|
+
log(` PackageRoot: ${pkgDir}`);
|
|
703
969
|
}
|
|
704
970
|
|
|
705
|
-
let dtsPath
|
|
706
|
-
let typesFile
|
|
707
|
-
let typesSource
|
|
971
|
+
let dtsPath;
|
|
972
|
+
let typesFile;
|
|
973
|
+
let typesSource;
|
|
708
974
|
|
|
709
975
|
if (pkg) {
|
|
710
|
-
log(`\n📄 Package Info:`)
|
|
711
|
-
log(` Name: ${pkg.name || basePkg}`)
|
|
712
|
-
log(` Version: ${pkg.version || "Unknown"}`)
|
|
976
|
+
log(`\n📄 Package Info:`);
|
|
977
|
+
log(` Name: ${pkg.name || basePkg}`);
|
|
978
|
+
log(` Version: ${pkg.version || "Unknown"}`);
|
|
713
979
|
if (pkg.description) {
|
|
714
|
-
log(` Description: ${pkg.description}`)
|
|
980
|
+
log(` Description: ${pkg.description}`);
|
|
715
981
|
}
|
|
716
982
|
if (pkg.license) {
|
|
717
|
-
log(` License: ${pkg.license}`)
|
|
983
|
+
log(` License: ${pkg.license}`);
|
|
718
984
|
}
|
|
719
985
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
986
|
+
if (jsonOutput) {
|
|
987
|
+
jsonOutput.package = pkg.name || basePkg;
|
|
988
|
+
jsonOutput.version = pkg.version || null;
|
|
989
|
+
jsonOutput.description = pkg.description || null;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
const typesResolution = resolveTypesFile(
|
|
993
|
+
pkg,
|
|
994
|
+
pkgDir,
|
|
995
|
+
subpath,
|
|
996
|
+
basePkg,
|
|
997
|
+
require,
|
|
998
|
+
);
|
|
999
|
+
typesFile = typesResolution.typesFile;
|
|
1000
|
+
dtsPath = typesResolution.dtsPath;
|
|
1001
|
+
typesSource = typesResolution.source;
|
|
1002
|
+
|
|
1003
|
+
// Update pkgDir if we're using @types package
|
|
1004
|
+
if (typesResolution.pkgDir && typesSource === "@types") {
|
|
1005
|
+
// Keep original pkgDir for runtime, but use types pkgDir for dtsPath
|
|
1006
|
+
// dtsPath is already set correctly from typesResolution
|
|
1007
|
+
}
|
|
724
1008
|
|
|
725
1009
|
if (typesFile) {
|
|
726
|
-
const sourceLabel = typesSource ? ` (${typesSource})` : ""
|
|
727
|
-
const existsLabel =
|
|
728
|
-
|
|
1010
|
+
const sourceLabel = typesSource ? ` (${typesSource})` : "";
|
|
1011
|
+
const existsLabel =
|
|
1012
|
+
dtsPath && fs.existsSync(dtsPath) ? "" : " (missing)";
|
|
1013
|
+
log(` Types: ${typesFile}${sourceLabel}${existsLabel}`);
|
|
729
1014
|
} else {
|
|
730
|
-
log(` Types: Not found`)
|
|
1015
|
+
log(` Types: Not found`);
|
|
731
1016
|
}
|
|
732
1017
|
|
|
733
1018
|
// === Mostrar subpath exports ===
|
|
734
1019
|
if (pkg.exports && typeof pkg.exports === "object") {
|
|
735
|
-
const exportEntries = Object.entries(pkg.exports)
|
|
1020
|
+
const exportEntries = Object.entries(pkg.exports);
|
|
736
1021
|
if (exportEntries.length > 0) {
|
|
737
|
-
log(`\n🚪 Subpath Exports (${exportEntries.length} available):`)
|
|
1022
|
+
log(`\n🚪 Subpath Exports (${exportEntries.length} available):`);
|
|
738
1023
|
for (const [pathKey, value] of exportEntries.slice(0, 10)) {
|
|
739
1024
|
if (typeof value === "string") {
|
|
740
|
-
log(` ${pathKey} → ${value}`)
|
|
1025
|
+
log(` ${pathKey} → ${value}`);
|
|
741
1026
|
} else if (value && typeof value === "object") {
|
|
742
|
-
const targets = Object.keys(value).join(", ")
|
|
743
|
-
log(` ${pathKey} → { ${targets} }`)
|
|
1027
|
+
const targets = Object.keys(value).join(", ");
|
|
1028
|
+
log(` ${pathKey} → { ${targets} }`);
|
|
744
1029
|
}
|
|
745
1030
|
}
|
|
746
1031
|
if (exportEntries.length > 10) {
|
|
747
|
-
log(` ... and ${exportEntries.length - 10} more`)
|
|
1032
|
+
log(` ... and ${exportEntries.length - 10} more`);
|
|
748
1033
|
}
|
|
749
1034
|
}
|
|
750
1035
|
}
|
|
751
1036
|
}
|
|
752
1037
|
|
|
753
|
-
let typeInfoRaw = null
|
|
1038
|
+
let typeInfoRaw = null;
|
|
754
1039
|
if ((showTypes || wantJsdoc) && dtsPath && fs.existsSync(dtsPath)) {
|
|
755
|
-
typeInfoRaw = parseDtsFile(dtsPath, null)
|
|
1040
|
+
typeInfoRaw = parseDtsFile(dtsPath, null);
|
|
756
1041
|
}
|
|
757
1042
|
|
|
758
|
-
let moduleNamespace = {}
|
|
759
|
-
let moduleDescriptors = {}
|
|
760
|
-
let allExports = []
|
|
761
|
-
const runtimeAvailable = Boolean(entrypointExists)
|
|
1043
|
+
let moduleNamespace = {};
|
|
1044
|
+
let moduleDescriptors = {};
|
|
1045
|
+
let allExports = [];
|
|
1046
|
+
const runtimeAvailable = Boolean(entrypointExists);
|
|
762
1047
|
if (!runtimeAvailable) {
|
|
763
|
-
log(`\n⚠️ Entrypoint not found on disk; runtime exports skipped.`)
|
|
1048
|
+
log(`\n⚠️ Entrypoint not found on disk; runtime exports skipped.`);
|
|
764
1049
|
} else {
|
|
765
|
-
const { module: loadedNamespace } = await loadModuleExports(
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
1050
|
+
const { module: loadedNamespace } = await loadModuleExports(
|
|
1051
|
+
entrypointPath,
|
|
1052
|
+
require,
|
|
1053
|
+
pkg,
|
|
1054
|
+
);
|
|
1055
|
+
moduleNamespace = loadedNamespace;
|
|
1056
|
+
moduleDescriptors = Object.getOwnPropertyDescriptors(moduleNamespace);
|
|
1057
|
+
allExports = Object.keys(moduleDescriptors);
|
|
769
1058
|
}
|
|
770
1059
|
|
|
771
|
-
// Lógica de Filtro
|
|
772
|
-
let finalList = allExports
|
|
773
|
-
if (
|
|
774
|
-
|
|
1060
|
+
// Lógica de Filtro (case-insensitive, supports regex)
|
|
1061
|
+
let finalList = allExports;
|
|
1062
|
+
if (filterRaw) {
|
|
1063
|
+
// Check if it's a regex pattern
|
|
1064
|
+
const isRegex =
|
|
1065
|
+
filterRaw.startsWith("/") &&
|
|
1066
|
+
filterRaw.endsWith("/") &&
|
|
1067
|
+
filterRaw.length > 2;
|
|
1068
|
+
if (isRegex) {
|
|
1069
|
+
try {
|
|
1070
|
+
const regexPattern = filterRaw.slice(1, -1);
|
|
1071
|
+
const regex = new RegExp(regexPattern, "i"); // case-insensitive
|
|
1072
|
+
finalList = allExports.filter((key) => regex.test(key));
|
|
1073
|
+
} catch (e) {
|
|
1074
|
+
// Fallback to substring match if regex is invalid
|
|
1075
|
+
finalList = allExports.filter((key) =>
|
|
1076
|
+
key.toLowerCase().includes(filter),
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
} else {
|
|
1080
|
+
// Simple substring match (case-insensitive)
|
|
1081
|
+
finalList = allExports.filter((key) =>
|
|
1082
|
+
key.toLowerCase().includes(filter),
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
775
1085
|
}
|
|
776
1086
|
|
|
777
1087
|
// Se a lista for muito grande e não tiver filtro, avisa e corta
|
|
778
|
-
const LIMIT = 100
|
|
779
|
-
if (!
|
|
780
|
-
log(
|
|
781
|
-
|
|
782
|
-
|
|
1088
|
+
const LIMIT = 100;
|
|
1089
|
+
if (!filterRaw && finalList.length > LIMIT) {
|
|
1090
|
+
log(
|
|
1091
|
+
`\n⚠️ Módulo exporta ${finalList.length} itens. Mostrando os primeiros ${LIMIT}...`,
|
|
1092
|
+
);
|
|
1093
|
+
log(`DICA: Use o parâmetro 'filter' para encontrar o que procura.`);
|
|
1094
|
+
finalList = finalList.slice(0, LIMIT);
|
|
783
1095
|
}
|
|
784
1096
|
|
|
785
1097
|
// === MELHORIA 2: Categorizar exports por tipo ===
|
|
@@ -789,45 +1101,49 @@ export async function runInspect(options) {
|
|
|
789
1101
|
objects: [],
|
|
790
1102
|
primitives: [],
|
|
791
1103
|
constants: [],
|
|
792
|
-
}
|
|
1104
|
+
};
|
|
793
1105
|
|
|
794
1106
|
if (runtimeAvailable) {
|
|
795
1107
|
for (const key of finalList) {
|
|
796
|
-
const descriptor = moduleDescriptors[key]
|
|
797
|
-
if (!descriptor) continue
|
|
1108
|
+
const descriptor = moduleDescriptors[key];
|
|
1109
|
+
if (!descriptor) continue;
|
|
798
1110
|
if (descriptor.get || descriptor.set) {
|
|
799
|
-
categorized.objects.push(key)
|
|
800
|
-
continue
|
|
1111
|
+
categorized.objects.push(key);
|
|
1112
|
+
continue;
|
|
801
1113
|
}
|
|
802
|
-
const value = descriptor.value
|
|
803
|
-
const type = typeof value
|
|
1114
|
+
const value = descriptor.value;
|
|
1115
|
+
const type = typeof value;
|
|
804
1116
|
|
|
805
1117
|
if (type === "function") {
|
|
806
1118
|
// Distinguir class vs function
|
|
807
1119
|
if (isProbablyClass(value)) {
|
|
808
|
-
categorized.classes.push(key)
|
|
1120
|
+
categorized.classes.push(key);
|
|
809
1121
|
} else {
|
|
810
|
-
categorized.functions.push(key)
|
|
1122
|
+
categorized.functions.push(key);
|
|
811
1123
|
}
|
|
812
1124
|
} else if (type === "object" && value !== null) {
|
|
813
|
-
categorized.objects.push(key)
|
|
814
|
-
} else if (
|
|
815
|
-
|
|
1125
|
+
categorized.objects.push(key);
|
|
1126
|
+
} else if (
|
|
1127
|
+
type === "string" ||
|
|
1128
|
+
type === "number" ||
|
|
1129
|
+
type === "boolean"
|
|
1130
|
+
) {
|
|
1131
|
+
categorized.constants.push(key);
|
|
816
1132
|
} else {
|
|
817
|
-
categorized.primitives.push(key)
|
|
1133
|
+
categorized.primitives.push(key);
|
|
818
1134
|
}
|
|
819
1135
|
}
|
|
820
1136
|
|
|
821
1137
|
// Prefer class from type info when available
|
|
822
1138
|
if (typeInfoRaw && Object.keys(typeInfoRaw.classes).length > 0) {
|
|
823
|
-
const classNames = new Set(Object.keys(typeInfoRaw.classes))
|
|
1139
|
+
const classNames = new Set(Object.keys(typeInfoRaw.classes));
|
|
824
1140
|
categorized.functions = categorized.functions.filter((name) => {
|
|
825
1141
|
if (classNames.has(name)) {
|
|
826
|
-
categorized.classes.push(name)
|
|
827
|
-
return false
|
|
1142
|
+
categorized.classes.push(name);
|
|
1143
|
+
return false;
|
|
828
1144
|
}
|
|
829
|
-
return true
|
|
830
|
-
})
|
|
1145
|
+
return true;
|
|
1146
|
+
});
|
|
831
1147
|
}
|
|
832
1148
|
|
|
833
1149
|
// Apply kind filter if specified
|
|
@@ -837,70 +1153,89 @@ export async function runInspect(options) {
|
|
|
837
1153
|
class: "classes",
|
|
838
1154
|
object: "objects",
|
|
839
1155
|
constant: "constants",
|
|
840
|
-
}
|
|
1156
|
+
};
|
|
841
1157
|
|
|
842
1158
|
// Keep only the requested kinds
|
|
843
1159
|
for (const [key, value] of Object.entries(categorized)) {
|
|
844
1160
|
const shouldKeep = Object.entries(kindMap).some(
|
|
845
1161
|
([kind, catKey]) => kindFilter.includes(kind) && catKey === key,
|
|
846
|
-
)
|
|
1162
|
+
);
|
|
847
1163
|
if (!shouldKeep) {
|
|
848
|
-
categorized[key] = []
|
|
1164
|
+
categorized[key] = [];
|
|
849
1165
|
}
|
|
850
1166
|
}
|
|
851
1167
|
|
|
852
1168
|
// Update finalList to only include filtered kinds
|
|
853
|
-
finalList = [
|
|
1169
|
+
finalList = [
|
|
1170
|
+
...categorized.functions,
|
|
1171
|
+
...categorized.classes,
|
|
1172
|
+
...categorized.objects,
|
|
1173
|
+
...categorized.constants,
|
|
1174
|
+
];
|
|
854
1175
|
}
|
|
855
1176
|
}
|
|
856
1177
|
|
|
1178
|
+
if (jsonOutput) {
|
|
1179
|
+
jsonOutput.exports = {
|
|
1180
|
+
total: finalList.length,
|
|
1181
|
+
functions: categorized.functions,
|
|
1182
|
+
classes: categorized.classes,
|
|
1183
|
+
objects: categorized.objects,
|
|
1184
|
+
constants: categorized.constants,
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
|
|
857
1188
|
// Mostrar exports categorizados
|
|
858
1189
|
if (jsdocOutput !== "only") {
|
|
859
1190
|
if (!runtimeAvailable) {
|
|
860
|
-
log(
|
|
1191
|
+
log(
|
|
1192
|
+
`\nℹ️ Runtime exports unavailable. Use --types to inspect type exports.`,
|
|
1193
|
+
);
|
|
861
1194
|
}
|
|
862
|
-
log(`\n🔑 Exports Encontrados (${finalList.length} total):`)
|
|
1195
|
+
log(`\n🔑 Exports Encontrados (${finalList.length} total):`);
|
|
863
1196
|
|
|
864
1197
|
if (categorized.functions.length > 0) {
|
|
865
|
-
log(`\n 📘 Functions (${categorized.functions.length}):`)
|
|
866
|
-
log(` ${categorized.functions.join(", ")}`)
|
|
1198
|
+
log(`\n 📘 Functions (${categorized.functions.length}):`);
|
|
1199
|
+
log(` ${categorized.functions.join(", ")}`);
|
|
867
1200
|
}
|
|
868
1201
|
|
|
869
1202
|
if (categorized.classes.length > 0) {
|
|
870
|
-
log(`\n 🏛️ Classes (${categorized.classes.length}):`)
|
|
871
|
-
log(` ${categorized.classes.join(", ")}`)
|
|
1203
|
+
log(`\n 🏛️ Classes (${categorized.classes.length}):`);
|
|
1204
|
+
log(` ${categorized.classes.join(", ")}`);
|
|
872
1205
|
}
|
|
873
1206
|
|
|
874
1207
|
if (categorized.objects.length > 0) {
|
|
875
|
-
log(`\n 📦 Objects/Namespaces (${categorized.objects.length}):`)
|
|
876
|
-
log(` ${categorized.objects.join(", ")}`)
|
|
1208
|
+
log(`\n 📦 Objects/Namespaces (${categorized.objects.length}):`);
|
|
1209
|
+
log(` ${categorized.objects.join(", ")}`);
|
|
877
1210
|
|
|
878
1211
|
// If depth > 0, show object contents
|
|
879
1212
|
if (depth > 0 && categorized.objects.length <= 10) {
|
|
880
|
-
log(`\n 📦 Object Contents (depth: ${depth}):`)
|
|
1213
|
+
log(`\n 📦 Object Contents (depth: ${depth}):`);
|
|
881
1214
|
for (const objName of categorized.objects) {
|
|
882
|
-
log(`\n ${objName}:`)
|
|
883
|
-
const descriptor = moduleDescriptors[objName]
|
|
1215
|
+
log(`\n ${objName}:`);
|
|
1216
|
+
const descriptor = moduleDescriptors[objName];
|
|
884
1217
|
if (!descriptor || descriptor.get || descriptor.set) {
|
|
885
|
-
log(` ${objName}: <getter>`)
|
|
886
|
-
continue
|
|
1218
|
+
log(` ${objName}: <getter>`);
|
|
1219
|
+
continue;
|
|
887
1220
|
}
|
|
888
|
-
const objValue = descriptor.value
|
|
889
|
-
const lines = inspectObject(objValue, 0, depth, " ")
|
|
890
|
-
lines.forEach((line) => log(` ${line}`))
|
|
1221
|
+
const objValue = descriptor.value;
|
|
1222
|
+
const lines = inspectObject(objValue, 0, depth, " ");
|
|
1223
|
+
lines.forEach((line) => log(` ${line}`));
|
|
891
1224
|
}
|
|
892
1225
|
} else if (depth > 0 && categorized.objects.length > 10) {
|
|
893
|
-
log(
|
|
1226
|
+
log(
|
|
1227
|
+
`\n ℹ️ Too many objects to show contents. Use 'filter' to narrow down.`,
|
|
1228
|
+
);
|
|
894
1229
|
}
|
|
895
1230
|
}
|
|
896
1231
|
|
|
897
1232
|
if (categorized.constants.length > 0) {
|
|
898
|
-
log(`\n 🔢 Constants (${categorized.constants.length}):`)
|
|
899
|
-
log(` ${categorized.constants.join(", ")}`)
|
|
1233
|
+
log(`\n 🔢 Constants (${categorized.constants.length}):`);
|
|
1234
|
+
log(` ${categorized.constants.join(", ")}`);
|
|
900
1235
|
}
|
|
901
1236
|
|
|
902
1237
|
if (finalList.length === 0) {
|
|
903
|
-
log("Nenhum export corresponde ao filtro.")
|
|
1238
|
+
log("Nenhum export corresponde ao filtro.");
|
|
904
1239
|
}
|
|
905
1240
|
}
|
|
906
1241
|
|
|
@@ -908,28 +1243,47 @@ export async function runInspect(options) {
|
|
|
908
1243
|
if (jsdocOutput !== "only") {
|
|
909
1244
|
if (!runtimeAvailable) {
|
|
910
1245
|
// Skip runtime-only signature/default export hints when entrypoint is missing
|
|
911
|
-
} else if (
|
|
912
|
-
|
|
1246
|
+
} else if (
|
|
1247
|
+
!showTypes &&
|
|
1248
|
+
categorized.functions.length > 0 &&
|
|
1249
|
+
categorized.functions.length <= 15
|
|
1250
|
+
) {
|
|
1251
|
+
log(`\n✍️ Function Signatures:`);
|
|
913
1252
|
for (const fname of categorized.functions) {
|
|
914
|
-
const descriptor = moduleDescriptors[fname]
|
|
915
|
-
const fn = descriptor?.value
|
|
1253
|
+
const descriptor = moduleDescriptors[fname];
|
|
1254
|
+
const fn = descriptor?.value;
|
|
916
1255
|
if (typeof fn === "function") {
|
|
917
|
-
const paramCount = fn.length
|
|
918
|
-
const params =
|
|
919
|
-
|
|
1256
|
+
const paramCount = fn.length;
|
|
1257
|
+
const params =
|
|
1258
|
+
paramCount === 0
|
|
1259
|
+
? ""
|
|
1260
|
+
: paramCount === 1
|
|
1261
|
+
? "1 param"
|
|
1262
|
+
: `${paramCount} params`;
|
|
1263
|
+
log(` ${fname}(${params})`);
|
|
920
1264
|
}
|
|
921
1265
|
}
|
|
922
1266
|
}
|
|
923
1267
|
|
|
924
1268
|
// Default export handling
|
|
925
1269
|
if (runtimeAvailable) {
|
|
926
|
-
const defaultDescriptor = moduleDescriptors.default
|
|
927
|
-
if (
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1270
|
+
const defaultDescriptor = moduleDescriptors.default;
|
|
1271
|
+
if (
|
|
1272
|
+
defaultDescriptor &&
|
|
1273
|
+
(!filterRaw || "default".toLowerCase().includes(filter))
|
|
1274
|
+
) {
|
|
1275
|
+
const defaultValue =
|
|
1276
|
+
defaultDescriptor.get || defaultDescriptor.set
|
|
1277
|
+
? undefined
|
|
1278
|
+
: defaultDescriptor.value;
|
|
1279
|
+
const defaultType = typeof defaultValue;
|
|
1280
|
+
log(`\n📦 Default Export: ${defaultType}`);
|
|
1281
|
+
if (
|
|
1282
|
+
defaultType === "function" &&
|
|
1283
|
+
defaultValue &&
|
|
1284
|
+
defaultValue.length !== undefined
|
|
1285
|
+
) {
|
|
1286
|
+
log(` Parameters: ${defaultValue.length}`);
|
|
933
1287
|
}
|
|
934
1288
|
}
|
|
935
1289
|
}
|
|
@@ -939,19 +1293,23 @@ export async function runInspect(options) {
|
|
|
939
1293
|
if (showTypes || wantJsdoc) {
|
|
940
1294
|
if (dtsPath && fs.existsSync(dtsPath)) {
|
|
941
1295
|
if (jsdocOutput !== "only") {
|
|
942
|
-
log(`\n🔬 Type Definitions Analysis:`)
|
|
943
|
-
log(` Source: ${path.basename(dtsPath)}`)
|
|
1296
|
+
log(`\n🔬 Type Definitions Analysis:`);
|
|
1297
|
+
log(` Source: ${path.basename(dtsPath)}`);
|
|
944
1298
|
}
|
|
945
1299
|
|
|
946
|
-
const typeInfo = filterTypeInfo(typeInfoRaw, filter, kindFilter)
|
|
1300
|
+
const typeInfo = filterTypeInfo(typeInfoRaw, filter, kindFilter);
|
|
1301
|
+
|
|
1302
|
+
if (jsonOutput) {
|
|
1303
|
+
jsonOutput.types = typeInfo;
|
|
1304
|
+
}
|
|
947
1305
|
|
|
948
1306
|
if (typeInfo) {
|
|
949
1307
|
if (jsdocOutput !== "only") {
|
|
950
1308
|
// Show function signatures with full type info
|
|
951
1309
|
if (Object.keys(typeInfo.functions).length > 0) {
|
|
952
|
-
log(`\n 📘 Function Type Signatures:`)
|
|
1310
|
+
log(`\n 📘 Function Type Signatures:`);
|
|
953
1311
|
for (const [name, info] of Object.entries(typeInfo.functions)) {
|
|
954
|
-
log(` ${name}(${info.params}): ${info.returnType}`)
|
|
1312
|
+
log(` ${name}(${info.params}): ${info.returnType}`);
|
|
955
1313
|
if (jsdocOutput === "inline" && typeInfo.jsdoc?.[name]) {
|
|
956
1314
|
const entry = formatJsdocEntry(name, typeInfo.jsdoc[name], {
|
|
957
1315
|
mode: jsdocMode,
|
|
@@ -959,22 +1317,22 @@ export async function runInspect(options) {
|
|
|
959
1317
|
maxLen: jsdocQuery?.maxLen,
|
|
960
1318
|
sections: jsdocQuery?.sections,
|
|
961
1319
|
tags: jsdocQuery?.tags,
|
|
962
|
-
})
|
|
963
|
-
log(` ↳ ${entry}`)
|
|
1320
|
+
});
|
|
1321
|
+
log(` ↳ ${entry}`);
|
|
964
1322
|
}
|
|
965
1323
|
}
|
|
966
1324
|
}
|
|
967
1325
|
|
|
968
1326
|
// Show interfaces
|
|
969
1327
|
if (Object.keys(typeInfo.interfaces).length > 0) {
|
|
970
|
-
log(`\n 📋 Interfaces:`)
|
|
1328
|
+
log(`\n 📋 Interfaces:`);
|
|
971
1329
|
for (const [name, props] of Object.entries(typeInfo.interfaces)) {
|
|
972
|
-
log(` interface ${name} {`)
|
|
973
|
-
props.forEach((prop) => log(` ${prop}`))
|
|
1330
|
+
log(` interface ${name} {`);
|
|
1331
|
+
props.forEach((prop) => log(` ${prop}`));
|
|
974
1332
|
if (props.length === 5) {
|
|
975
|
-
log(` ... (truncated)`)
|
|
1333
|
+
log(` ... (truncated)`);
|
|
976
1334
|
}
|
|
977
|
-
log(` }`)
|
|
1335
|
+
log(` }`);
|
|
978
1336
|
if (jsdocOutput === "inline" && typeInfo.jsdoc?.[name]) {
|
|
979
1337
|
const entry = formatJsdocEntry(name, typeInfo.jsdoc[name], {
|
|
980
1338
|
mode: jsdocMode,
|
|
@@ -982,18 +1340,21 @@ export async function runInspect(options) {
|
|
|
982
1340
|
maxLen: jsdocQuery?.maxLen,
|
|
983
1341
|
sections: jsdocQuery?.sections,
|
|
984
1342
|
tags: jsdocQuery?.tags,
|
|
985
|
-
})
|
|
986
|
-
log(` ↳ ${entry}`)
|
|
1343
|
+
});
|
|
1344
|
+
log(` ↳ ${entry}`);
|
|
987
1345
|
}
|
|
988
1346
|
}
|
|
989
1347
|
}
|
|
990
1348
|
|
|
991
1349
|
// Show type aliases
|
|
992
1350
|
if (Object.keys(typeInfo.types).length > 0) {
|
|
993
|
-
log(`\n 📝 Type Aliases:`)
|
|
1351
|
+
log(`\n 📝 Type Aliases:`);
|
|
994
1352
|
for (const [name, definition] of Object.entries(typeInfo.types)) {
|
|
995
|
-
const shortDef =
|
|
996
|
-
|
|
1353
|
+
const shortDef =
|
|
1354
|
+
definition.length > 80
|
|
1355
|
+
? definition.substring(0, 80) + "..."
|
|
1356
|
+
: definition;
|
|
1357
|
+
log(` type ${name} = ${shortDef}`);
|
|
997
1358
|
if (jsdocOutput === "inline" && typeInfo.jsdoc?.[name]) {
|
|
998
1359
|
const entry = formatJsdocEntry(name, typeInfo.jsdoc[name], {
|
|
999
1360
|
mode: jsdocMode,
|
|
@@ -1001,18 +1362,22 @@ export async function runInspect(options) {
|
|
|
1001
1362
|
maxLen: jsdocQuery?.maxLen,
|
|
1002
1363
|
sections: jsdocQuery?.sections,
|
|
1003
1364
|
tags: jsdocQuery?.tags,
|
|
1004
|
-
})
|
|
1005
|
-
log(` ↳ ${entry}`)
|
|
1365
|
+
});
|
|
1366
|
+
log(` ↳ ${entry}`);
|
|
1006
1367
|
}
|
|
1007
1368
|
}
|
|
1008
1369
|
}
|
|
1009
1370
|
|
|
1010
1371
|
// Show class inheritance
|
|
1011
1372
|
if (Object.keys(typeInfo.classes).length > 0) {
|
|
1012
|
-
log(`\n 🏛️ Class Definitions:`)
|
|
1013
|
-
for (const [name, extendsClass] of Object.entries(
|
|
1014
|
-
|
|
1015
|
-
|
|
1373
|
+
log(`\n 🏛️ Class Definitions:`);
|
|
1374
|
+
for (const [name, extendsClass] of Object.entries(
|
|
1375
|
+
typeInfo.classes,
|
|
1376
|
+
)) {
|
|
1377
|
+
const inheritance = extendsClass
|
|
1378
|
+
? ` extends ${extendsClass}`
|
|
1379
|
+
: "";
|
|
1380
|
+
log(` class ${name}${inheritance}`);
|
|
1016
1381
|
if (jsdocOutput === "inline" && typeInfo.jsdoc?.[name]) {
|
|
1017
1382
|
const entry = formatJsdocEntry(name, typeInfo.jsdoc[name], {
|
|
1018
1383
|
mode: jsdocMode,
|
|
@@ -1020,17 +1385,18 @@ export async function runInspect(options) {
|
|
|
1020
1385
|
maxLen: jsdocQuery?.maxLen,
|
|
1021
1386
|
sections: jsdocQuery?.sections,
|
|
1022
1387
|
tags: jsdocQuery?.tags,
|
|
1023
|
-
})
|
|
1024
|
-
log(` ↳ ${entry}`)
|
|
1388
|
+
});
|
|
1389
|
+
log(` ↳ ${entry}`);
|
|
1025
1390
|
}
|
|
1026
1391
|
}
|
|
1027
1392
|
}
|
|
1028
1393
|
|
|
1029
1394
|
if (Object.keys(typeInfo.enums).length > 0) {
|
|
1030
|
-
log(`\n 🧾 Enums:`)
|
|
1395
|
+
log(`\n 🧾 Enums:`);
|
|
1031
1396
|
for (const [name, members] of Object.entries(typeInfo.enums)) {
|
|
1032
|
-
const preview =
|
|
1033
|
-
|
|
1397
|
+
const preview =
|
|
1398
|
+
members.length > 0 ? ` = [${members.join(", ")}]` : "";
|
|
1399
|
+
log(` enum ${name}${preview}`);
|
|
1034
1400
|
if (jsdocOutput === "inline" && typeInfo.jsdoc?.[name]) {
|
|
1035
1401
|
const entry = formatJsdocEntry(name, typeInfo.jsdoc[name], {
|
|
1036
1402
|
mode: jsdocMode,
|
|
@@ -1038,16 +1404,16 @@ export async function runInspect(options) {
|
|
|
1038
1404
|
maxLen: jsdocQuery?.maxLen,
|
|
1039
1405
|
sections: jsdocQuery?.sections,
|
|
1040
1406
|
tags: jsdocQuery?.tags,
|
|
1041
|
-
})
|
|
1042
|
-
log(` ↳ ${entry}`)
|
|
1407
|
+
});
|
|
1408
|
+
log(` ↳ ${entry}`);
|
|
1043
1409
|
}
|
|
1044
1410
|
}
|
|
1045
1411
|
}
|
|
1046
1412
|
|
|
1047
1413
|
if (Object.keys(typeInfo.namespaces).length > 0) {
|
|
1048
|
-
log(`\n 📦 Namespaces:`)
|
|
1414
|
+
log(`\n 📦 Namespaces:`);
|
|
1049
1415
|
for (const name of Object.keys(typeInfo.namespaces)) {
|
|
1050
|
-
log(` namespace ${name}`)
|
|
1416
|
+
log(` namespace ${name}`);
|
|
1051
1417
|
if (jsdocOutput === "inline" && typeInfo.jsdoc?.[name]) {
|
|
1052
1418
|
const entry = formatJsdocEntry(name, typeInfo.jsdoc[name], {
|
|
1053
1419
|
mode: jsdocMode,
|
|
@@ -1055,26 +1421,36 @@ export async function runInspect(options) {
|
|
|
1055
1421
|
maxLen: jsdocQuery?.maxLen,
|
|
1056
1422
|
sections: jsdocQuery?.sections,
|
|
1057
1423
|
tags: jsdocQuery?.tags,
|
|
1058
|
-
})
|
|
1059
|
-
log(` ↳ ${entry}`)
|
|
1424
|
+
});
|
|
1425
|
+
log(` ↳ ${entry}`);
|
|
1060
1426
|
}
|
|
1061
1427
|
}
|
|
1062
1428
|
}
|
|
1063
1429
|
|
|
1064
1430
|
if (typeInfo.defaults.length > 0) {
|
|
1065
|
-
log(`\n 📦 Default Exports:`)
|
|
1066
|
-
typeInfo.defaults
|
|
1431
|
+
log(`\n 📦 Default Exports:`);
|
|
1432
|
+
typeInfo.defaults
|
|
1433
|
+
.slice(0, 5)
|
|
1434
|
+
.forEach((value) => log(` default = ${value}`));
|
|
1067
1435
|
}
|
|
1068
1436
|
}
|
|
1069
1437
|
|
|
1070
|
-
if (
|
|
1071
|
-
|
|
1438
|
+
if (
|
|
1439
|
+
wantJsdoc &&
|
|
1440
|
+
jsdocMode !== "off" &&
|
|
1441
|
+
typeInfo.jsdoc &&
|
|
1442
|
+
Object.keys(typeInfo.jsdoc).length > 0
|
|
1443
|
+
) {
|
|
1444
|
+
const symbolMatcher = buildSymbolMatcher(
|
|
1445
|
+
jsdocQuery?.symbols,
|
|
1446
|
+
filter,
|
|
1447
|
+
);
|
|
1072
1448
|
const entries = Object.entries(typeInfo.jsdoc)
|
|
1073
1449
|
.filter(([name]) => (symbolMatcher ? symbolMatcher(name) : true))
|
|
1074
|
-
.slice(0, 50)
|
|
1450
|
+
.slice(0, 50);
|
|
1075
1451
|
|
|
1076
1452
|
if (entries.length > 0) {
|
|
1077
|
-
log(`\n 📚 JSDoc:`)
|
|
1453
|
+
log(`\n 📚 JSDoc:`);
|
|
1078
1454
|
for (const [name, doc] of entries) {
|
|
1079
1455
|
const entry = formatJsdocEntry(name, doc, {
|
|
1080
1456
|
mode: jsdocMode,
|
|
@@ -1082,8 +1458,8 @@ export async function runInspect(options) {
|
|
|
1082
1458
|
maxLen: jsdocQuery?.maxLen,
|
|
1083
1459
|
sections: jsdocQuery?.sections,
|
|
1084
1460
|
tags: jsdocQuery?.tags,
|
|
1085
|
-
})
|
|
1086
|
-
log(` ${entry}`)
|
|
1461
|
+
});
|
|
1462
|
+
log(` ${entry}`);
|
|
1087
1463
|
}
|
|
1088
1464
|
}
|
|
1089
1465
|
}
|
|
@@ -1096,19 +1472,25 @@ export async function runInspect(options) {
|
|
|
1096
1472
|
...Object.keys(typeInfo.classes),
|
|
1097
1473
|
...Object.keys(typeInfo.enums),
|
|
1098
1474
|
...Object.keys(typeInfo.namespaces),
|
|
1099
|
-
])
|
|
1475
|
+
]);
|
|
1100
1476
|
if (runtimeAvailable) {
|
|
1101
|
-
const runtimeNames = new Set(allExports)
|
|
1102
|
-
const runtimeOnly = [...runtimeNames].filter(
|
|
1103
|
-
|
|
1477
|
+
const runtimeNames = new Set(allExports);
|
|
1478
|
+
const runtimeOnly = [...runtimeNames].filter(
|
|
1479
|
+
(name) => !typeExportNames.has(name),
|
|
1480
|
+
);
|
|
1481
|
+
const typesOnly = [...typeExportNames].filter(
|
|
1482
|
+
(name) => !runtimeNames.has(name),
|
|
1483
|
+
);
|
|
1104
1484
|
|
|
1105
1485
|
if (runtimeOnly.length > 0 || typesOnly.length > 0) {
|
|
1106
|
-
log(`\n ⚖️ Runtime/Types Mismatch:`)
|
|
1486
|
+
log(`\n ⚖️ Runtime/Types Mismatch:`);
|
|
1107
1487
|
if (runtimeOnly.length > 0) {
|
|
1108
|
-
log(
|
|
1488
|
+
log(
|
|
1489
|
+
` Runtime only: ${runtimeOnly.slice(0, 10).join(", ")}`,
|
|
1490
|
+
);
|
|
1109
1491
|
}
|
|
1110
1492
|
if (typesOnly.length > 0) {
|
|
1111
|
-
log(` Types only: ${typesOnly.slice(0, 10).join(", ")}`)
|
|
1493
|
+
log(` Types only: ${typesOnly.slice(0, 10).join(", ")}`);
|
|
1112
1494
|
}
|
|
1113
1495
|
}
|
|
1114
1496
|
}
|
|
@@ -1122,24 +1504,110 @@ export async function runInspect(options) {
|
|
|
1122
1504
|
Object.keys(typeInfo.namespaces).length === 0 &&
|
|
1123
1505
|
typeInfo.defaults.length === 0
|
|
1124
1506
|
) {
|
|
1125
|
-
log(` ⚠️ No type definitions found for filtered exports`)
|
|
1507
|
+
log(` ⚠️ No type definitions found for filtered exports`);
|
|
1126
1508
|
}
|
|
1127
1509
|
}
|
|
1128
1510
|
} else {
|
|
1129
1511
|
if (jsdocOutput !== "only") {
|
|
1130
|
-
log(` ⚠️ Could not parse type definitions`)
|
|
1512
|
+
log(` ⚠️ Could not parse type definitions`);
|
|
1131
1513
|
}
|
|
1132
1514
|
}
|
|
1133
1515
|
} else {
|
|
1134
1516
|
if (jsdocOutput !== "only") {
|
|
1135
|
-
log(`\n⚠️ Type definitions not available for this package`)
|
|
1517
|
+
log(`\n⚠️ Type definitions not available for this package`);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
// Source code analysis
|
|
1523
|
+
if (analyzeSource && pkgDir) {
|
|
1524
|
+
log(`\n📝 Source Code Analysis:`);
|
|
1525
|
+
try {
|
|
1526
|
+
const sourceAnalysis = analyzePackageSource(pkgDir, {
|
|
1527
|
+
filter: filterRaw,
|
|
1528
|
+
maxFiles: sourceMaxFiles,
|
|
1529
|
+
includeBody: sourceIncludeBody,
|
|
1530
|
+
maxBodyLines: 10,
|
|
1531
|
+
});
|
|
1532
|
+
|
|
1533
|
+
if (sourceAnalysis.error) {
|
|
1534
|
+
log(` ⚠️ ${sourceAnalysis.error}`);
|
|
1535
|
+
} else {
|
|
1536
|
+
log(` Files analyzed: ${sourceAnalysis.summary.totalFiles}`);
|
|
1537
|
+
log(` Functions found: ${sourceAnalysis.summary.totalFunctions}`);
|
|
1538
|
+
log(` Avg complexity: ${sourceAnalysis.summary.avgComplexity}`);
|
|
1539
|
+
|
|
1540
|
+
if (sourceAnalysis.summary.highComplexityFunctions.length > 0) {
|
|
1541
|
+
log(`\n ⚠️ High Complexity Functions (≥10):`);
|
|
1542
|
+
for (const fn of sourceAnalysis.summary.highComplexityFunctions.slice(
|
|
1543
|
+
0,
|
|
1544
|
+
5,
|
|
1545
|
+
)) {
|
|
1546
|
+
log(` ${fn.name} (${fn.complexity}) - ${fn.file}`);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
for (const file of sourceAnalysis.files) {
|
|
1551
|
+
const fnCount = Object.keys(file.functions).length;
|
|
1552
|
+
if (fnCount === 0) continue;
|
|
1553
|
+
|
|
1554
|
+
log(`\n 📄 ${file.path} (${fnCount} functions):`);
|
|
1555
|
+
|
|
1556
|
+
for (const [name, info] of Object.entries(file.functions)) {
|
|
1557
|
+
const asyncTag = info.async ? "async " : "";
|
|
1558
|
+
const exportTag = info.exported ? "export " : "";
|
|
1559
|
+
const params = info.params
|
|
1560
|
+
.map(
|
|
1561
|
+
(p) =>
|
|
1562
|
+
`${p.name}${p.optional ? "?" : ""}: ${p.type}${p.default ? ` = ${p.default}` : ""}`,
|
|
1563
|
+
)
|
|
1564
|
+
.join(", ");
|
|
1565
|
+
|
|
1566
|
+
log(
|
|
1567
|
+
` ${exportTag}${asyncTag}${name}(${params}): ${info.returnType}`,
|
|
1568
|
+
);
|
|
1569
|
+
log(
|
|
1570
|
+
` ├─ Complexity: ${info.complexity} | Lines: ${info.lines}`,
|
|
1571
|
+
);
|
|
1572
|
+
|
|
1573
|
+
if (info.dependencies.length > 0) {
|
|
1574
|
+
log(
|
|
1575
|
+
` ├─ Uses: ${info.dependencies.slice(0, 5).join(", ")}${info.dependencies.length > 5 ? "..." : ""}`,
|
|
1576
|
+
);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
if (info.patterns.length > 0) {
|
|
1580
|
+
log(` └─ Patterns: ${info.patterns.join(", ")}`);
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
if (info.body && sourceIncludeBody) {
|
|
1584
|
+
log(` 📋 Body:`);
|
|
1585
|
+
info.body
|
|
1586
|
+
.split("\n")
|
|
1587
|
+
.slice(0, 8)
|
|
1588
|
+
.forEach((line) => {
|
|
1589
|
+
log(` ${line}`);
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1136
1594
|
}
|
|
1595
|
+
} catch (sourceErr) {
|
|
1596
|
+
log(` ❌ Source analysis error: ${sourceErr.message}`);
|
|
1137
1597
|
}
|
|
1138
1598
|
}
|
|
1139
1599
|
} catch (e) {
|
|
1140
|
-
|
|
1141
|
-
|
|
1600
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
1601
|
+
if (jsonOutput) {
|
|
1602
|
+
warn(message);
|
|
1603
|
+
}
|
|
1604
|
+
logErr(`\n❌ Erro: ${message}`);
|
|
1605
|
+
logErr(
|
|
1606
|
+
`Certifique-se que '${target}' está instalado e é um caminho válido.`,
|
|
1607
|
+
);
|
|
1142
1608
|
}
|
|
1143
1609
|
|
|
1144
|
-
|
|
1610
|
+
if (format === "object") return jsonOutput;
|
|
1611
|
+
if (format === "json") return JSON.stringify(jsonOutput, null, 2);
|
|
1612
|
+
return collect ? output.join("\n") : "";
|
|
1145
1613
|
}
|