dep-context-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +380 -0
  2. package/dist/analysis/relationships.d.ts +25 -0
  3. package/dist/analysis/relationships.d.ts.map +1 -0
  4. package/dist/analysis/relationships.js +26 -0
  5. package/dist/analysis/relationships.js.map +1 -0
  6. package/dist/build-info.d.ts +15 -0
  7. package/dist/build-info.d.ts.map +1 -0
  8. package/dist/build-info.js +24 -0
  9. package/dist/build-info.js.map +1 -0
  10. package/dist/cache/manager.d.ts +19 -0
  11. package/dist/cache/manager.d.ts.map +1 -0
  12. package/dist/cache/manager.js +131 -0
  13. package/dist/cache/manager.js.map +1 -0
  14. package/dist/cache/registry.d.ts +44 -0
  15. package/dist/cache/registry.d.ts.map +1 -0
  16. package/dist/cache/registry.js +92 -0
  17. package/dist/cache/registry.js.map +1 -0
  18. package/dist/config/loader.d.ts +62 -0
  19. package/dist/config/loader.d.ts.map +1 -0
  20. package/dist/config/loader.js +193 -0
  21. package/dist/config/loader.js.map +1 -0
  22. package/dist/extraction/examples.d.ts +22 -0
  23. package/dist/extraction/examples.d.ts.map +1 -0
  24. package/dist/extraction/examples.js +109 -0
  25. package/dist/extraction/examples.js.map +1 -0
  26. package/dist/extraction/external-resolver.d.ts +26 -0
  27. package/dist/extraction/external-resolver.d.ts.map +1 -0
  28. package/dist/extraction/external-resolver.js +79 -0
  29. package/dist/extraction/external-resolver.js.map +1 -0
  30. package/dist/extraction/import-tracker.d.ts +58 -0
  31. package/dist/extraction/import-tracker.d.ts.map +1 -0
  32. package/dist/extraction/import-tracker.js +113 -0
  33. package/dist/extraction/import-tracker.js.map +1 -0
  34. package/dist/extraction/readme.d.ts +19 -0
  35. package/dist/extraction/readme.d.ts.map +1 -0
  36. package/dist/extraction/readme.js +79 -0
  37. package/dist/extraction/readme.js.map +1 -0
  38. package/dist/extraction/snapshot.d.ts +32 -0
  39. package/dist/extraction/snapshot.d.ts.map +1 -0
  40. package/dist/extraction/snapshot.js +258 -0
  41. package/dist/extraction/snapshot.js.map +1 -0
  42. package/dist/extraction/typescript.d.ts +104 -0
  43. package/dist/extraction/typescript.d.ts.map +1 -0
  44. package/dist/extraction/typescript.js +647 -0
  45. package/dist/extraction/typescript.js.map +1 -0
  46. package/dist/index.d.ts +9 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +329 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/resolver/package.d.ts +62 -0
  51. package/dist/resolver/package.d.ts.map +1 -0
  52. package/dist/resolver/package.js +334 -0
  53. package/dist/resolver/package.js.map +1 -0
  54. package/dist/tools/get-dependency.d.ts +55 -0
  55. package/dist/tools/get-dependency.d.ts.map +1 -0
  56. package/dist/tools/get-dependency.js +105 -0
  57. package/dist/tools/get-dependency.js.map +1 -0
  58. package/dist/tools/index-dependencies.d.ts +51 -0
  59. package/dist/tools/index-dependencies.d.ts.map +1 -0
  60. package/dist/tools/index-dependencies.js +90 -0
  61. package/dist/tools/index-dependencies.js.map +1 -0
  62. package/dist/tools/index-status.d.ts +36 -0
  63. package/dist/tools/index-status.d.ts.map +1 -0
  64. package/dist/tools/index-status.js +45 -0
  65. package/dist/tools/index-status.js.map +1 -0
  66. package/dist/tools/list.d.ts +48 -0
  67. package/dist/tools/list.d.ts.map +1 -0
  68. package/dist/tools/list.js +55 -0
  69. package/dist/tools/list.js.map +1 -0
  70. package/dist/tools/refresh.d.ts +59 -0
  71. package/dist/tools/refresh.d.ts.map +1 -0
  72. package/dist/tools/refresh.js +109 -0
  73. package/dist/tools/refresh.js.map +1 -0
  74. package/dist/tools/relationships.d.ts +41 -0
  75. package/dist/tools/relationships.d.ts.map +1 -0
  76. package/dist/tools/relationships.js +36 -0
  77. package/dist/tools/relationships.js.map +1 -0
  78. package/dist/tools/search-codebase.d.ts +64 -0
  79. package/dist/tools/search-codebase.d.ts.map +1 -0
  80. package/dist/tools/search-codebase.js +117 -0
  81. package/dist/tools/search-codebase.js.map +1 -0
  82. package/dist/tools/search.d.ts +37 -0
  83. package/dist/tools/search.d.ts.map +1 -0
  84. package/dist/tools/search.js +77 -0
  85. package/dist/tools/search.js.map +1 -0
  86. package/dist/utils/logger.d.ts +19 -0
  87. package/dist/utils/logger.d.ts.map +1 -0
  88. package/dist/utils/logger.js +71 -0
  89. package/dist/utils/logger.js.map +1 -0
  90. package/dist/vector/chroma.d.ts +38 -0
  91. package/dist/vector/chroma.d.ts.map +1 -0
  92. package/dist/vector/chroma.js +69 -0
  93. package/dist/vector/chroma.js.map +1 -0
  94. package/dist/vector/chunker.d.ts +29 -0
  95. package/dist/vector/chunker.d.ts.map +1 -0
  96. package/dist/vector/chunker.js +205 -0
  97. package/dist/vector/chunker.js.map +1 -0
  98. package/dist/vector/embeddings.d.ts +36 -0
  99. package/dist/vector/embeddings.d.ts.map +1 -0
  100. package/dist/vector/embeddings.js +106 -0
  101. package/dist/vector/embeddings.js.map +1 -0
  102. package/dist/vector/file-store.d.ts +10 -0
  103. package/dist/vector/file-store.d.ts.map +1 -0
  104. package/dist/vector/file-store.js +80 -0
  105. package/dist/vector/file-store.js.map +1 -0
  106. package/dist/vector/index-manager.d.ts +39 -0
  107. package/dist/vector/index-manager.d.ts.map +1 -0
  108. package/dist/vector/index-manager.js +105 -0
  109. package/dist/vector/index-manager.js.map +1 -0
  110. package/dist/vector/provider-factory.d.ts +23 -0
  111. package/dist/vector/provider-factory.d.ts.map +1 -0
  112. package/dist/vector/provider-factory.js +50 -0
  113. package/dist/vector/provider-factory.js.map +1 -0
  114. package/dist/vector/storage-factory.d.ts +17 -0
  115. package/dist/vector/storage-factory.d.ts.map +1 -0
  116. package/dist/vector/storage-factory.js +55 -0
  117. package/dist/vector/storage-factory.js.map +1 -0
  118. package/package.json +60 -0
@@ -0,0 +1,647 @@
1
+ /**
2
+ * TypeScript type extractor - parses .d.ts files using the TypeScript compiler API
3
+ */
4
+ import * as ts from 'typescript';
5
+ import { readFile } from 'node:fs/promises';
6
+ import { dirname, join, resolve } from 'node:path';
7
+ import { existsSync } from 'node:fs';
8
+ import { createImportTracker } from './import-tracker.js';
9
+ import { createExternalPackageResolver } from './external-resolver.js';
10
+ /**
11
+ * Extracts JSDoc comment from a node
12
+ */
13
+ function getJsDoc(node, sourceFile) {
14
+ const jsDocTags = ts.getJSDocTags(node);
15
+ if (jsDocTags.length > 0) {
16
+ return jsDocTags.map(tag => {
17
+ const tagName = tag.tagName.text;
18
+ const comment = typeof tag.comment === 'string'
19
+ ? tag.comment
20
+ : tag.comment?.map(c => c.text).join('') ?? '';
21
+ return `@${tagName} ${comment}`.trim();
22
+ }).join('\n');
23
+ }
24
+ // Try to get the leading comment
25
+ const fullText = sourceFile.getFullText();
26
+ const nodeStart = node.getFullStart();
27
+ const leadingComments = ts.getLeadingCommentRanges(fullText, nodeStart);
28
+ if (leadingComments && leadingComments.length > 0) {
29
+ const lastComment = leadingComments[leadingComments.length - 1];
30
+ const commentText = fullText.slice(lastComment.pos, lastComment.end);
31
+ // Parse JSDoc style comments
32
+ if (commentText.startsWith('/**')) {
33
+ return commentText
34
+ .replace(/^\/\*\*\s*/, '')
35
+ .replace(/\s*\*\/$/, '')
36
+ .split('\n')
37
+ .map(line => line.replace(/^\s*\*\s?/, ''))
38
+ .join('\n')
39
+ .trim();
40
+ }
41
+ }
42
+ return undefined;
43
+ }
44
+ /**
45
+ * Checks if a node has an export modifier
46
+ */
47
+ function isExported(node) {
48
+ const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
49
+ return modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword) ?? false;
50
+ }
51
+ /**
52
+ * Extracts parameter information from a parameter declaration
53
+ */
54
+ function extractParameter(param, sourceFile) {
55
+ const name = param.name.getText(sourceFile);
56
+ const type = param.type ? param.type.getText(sourceFile) : 'any';
57
+ const optional = param.questionToken !== undefined || param.initializer !== undefined;
58
+ const defaultValue = param.initializer ? param.initializer.getText(sourceFile) : undefined;
59
+ return { name, type, optional, defaultValue };
60
+ }
61
+ /**
62
+ * Extracts a function signature as a string
63
+ */
64
+ function getFunctionSignature(node, sourceFile) {
65
+ const name = node.name?.getText(sourceFile) ?? 'anonymous';
66
+ const typeParams = node.typeParameters
67
+ ? `<${node.typeParameters.map(tp => tp.getText(sourceFile)).join(', ')}>`
68
+ : '';
69
+ const params = node.parameters
70
+ .map(p => {
71
+ const paramName = p.name.getText(sourceFile);
72
+ const paramType = p.type ? p.type.getText(sourceFile) : 'any';
73
+ const optional = p.questionToken ? '?' : '';
74
+ return `${paramName}${optional}: ${paramType}`;
75
+ })
76
+ .join(', ');
77
+ const returnType = node.type ? node.type.getText(sourceFile) : 'void';
78
+ return `${name}${typeParams}(${params}): ${returnType}`;
79
+ }
80
+ /**
81
+ * Extracts a function declaration
82
+ */
83
+ function extractFunction(node, sourceFile) {
84
+ const name = node.name?.getText(sourceFile) ?? 'anonymous';
85
+ const signature = `function ${getFunctionSignature(node, sourceFile)}`;
86
+ const parameters = node.parameters.map(p => extractParameter(p, sourceFile));
87
+ const returnType = node.type ? node.type.getText(sourceFile) : 'void';
88
+ const jsDoc = getJsDoc(node, sourceFile);
89
+ const isAsync = node.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) ?? false;
90
+ return { name, signature, parameters, returnType, jsDoc, isAsync };
91
+ }
92
+ /**
93
+ * Extracts a method from a class or interface
94
+ */
95
+ function extractMethod(node, sourceFile) {
96
+ const name = node.name.getText(sourceFile);
97
+ const signature = getFunctionSignature(node, sourceFile);
98
+ const parameters = node.parameters.map(p => extractParameter(p, sourceFile));
99
+ const returnType = node.type ? node.type.getText(sourceFile) : 'void';
100
+ const jsDoc = getJsDoc(node, sourceFile);
101
+ let isAsync = false;
102
+ let isStatic = false;
103
+ if (ts.isMethodDeclaration(node)) {
104
+ const modifiers = ts.getModifiers(node);
105
+ isAsync = modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) ?? false;
106
+ isStatic = modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) ?? false;
107
+ }
108
+ return { name, signature, parameters, returnType, jsDoc, isAsync, isStatic };
109
+ }
110
+ /**
111
+ * Extracts a property from a class or interface
112
+ */
113
+ function extractProperty(node, sourceFile) {
114
+ const name = node.name.getText(sourceFile);
115
+ const type = node.type ? node.type.getText(sourceFile) : 'any';
116
+ const optional = node.questionToken !== undefined;
117
+ const jsDoc = getJsDoc(node, sourceFile);
118
+ let readonly = false;
119
+ if (ts.isPropertyDeclaration(node)) {
120
+ const modifiers = ts.getModifiers(node);
121
+ readonly = modifiers?.some(m => m.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false;
122
+ }
123
+ else if (ts.isPropertySignature(node)) {
124
+ readonly = node.modifiers?.some(m => m.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false;
125
+ }
126
+ return { name, type, optional, readonly, jsDoc };
127
+ }
128
+ /**
129
+ * Extracts a class declaration
130
+ */
131
+ function extractClass(node, sourceFile) {
132
+ const name = node.name?.getText(sourceFile) ?? 'anonymous';
133
+ const jsDoc = getJsDoc(node, sourceFile);
134
+ let constructorSignature;
135
+ const methods = [];
136
+ const properties = [];
137
+ for (const member of node.members) {
138
+ if (ts.isConstructorDeclaration(member)) {
139
+ const params = member.parameters
140
+ .map(p => {
141
+ const paramName = p.name.getText(sourceFile);
142
+ const paramType = p.type ? p.type.getText(sourceFile) : 'any';
143
+ const optional = p.questionToken ? '?' : '';
144
+ return `${paramName}${optional}: ${paramType}`;
145
+ })
146
+ .join(', ');
147
+ constructorSignature = `constructor(${params})`;
148
+ }
149
+ else if (ts.isMethodDeclaration(member)) {
150
+ // Only include public methods
151
+ const modifiers = ts.getModifiers(member);
152
+ const isPrivate = modifiers?.some(m => m.kind === ts.SyntaxKind.PrivateKeyword);
153
+ if (!isPrivate) {
154
+ methods.push(extractMethod(member, sourceFile));
155
+ }
156
+ }
157
+ else if (ts.isPropertyDeclaration(member)) {
158
+ // Only include public properties
159
+ const modifiers = ts.getModifiers(member);
160
+ const isPrivate = modifiers?.some(m => m.kind === ts.SyntaxKind.PrivateKeyword);
161
+ if (!isPrivate) {
162
+ properties.push(extractProperty(member, sourceFile));
163
+ }
164
+ }
165
+ }
166
+ return { name, constructorSignature, methods, properties, jsDoc };
167
+ }
168
+ /**
169
+ * Extracts an interface declaration
170
+ */
171
+ function extractInterface(node, sourceFile) {
172
+ const name = node.name.getText(sourceFile);
173
+ const jsDoc = getJsDoc(node, sourceFile);
174
+ const methods = [];
175
+ const properties = [];
176
+ for (const member of node.members) {
177
+ if (ts.isMethodSignature(member)) {
178
+ methods.push(extractMethod(member, sourceFile));
179
+ }
180
+ else if (ts.isPropertySignature(member)) {
181
+ properties.push(extractProperty(member, sourceFile));
182
+ }
183
+ }
184
+ return { name, properties, methods, jsDoc };
185
+ }
186
+ /**
187
+ * Extracts a type alias declaration
188
+ */
189
+ function extractTypeAlias(node, sourceFile) {
190
+ const name = node.name.getText(sourceFile);
191
+ const definition = node.type.getText(sourceFile);
192
+ const jsDoc = getJsDoc(node, sourceFile);
193
+ return { name, definition, jsDoc };
194
+ }
195
+ /**
196
+ * Extracts re-export statements from a source file
197
+ * Distinguishes between star exports and named re-exports
198
+ */
199
+ function extractReExports(sourceFile) {
200
+ const result = {
201
+ starExports: [],
202
+ namedReExports: []
203
+ };
204
+ for (const statement of sourceFile.statements) {
205
+ if (ts.isExportDeclaration(statement) && statement.moduleSpecifier) {
206
+ const moduleSpecifier = statement.moduleSpecifier;
207
+ if (!ts.isStringLiteral(moduleSpecifier))
208
+ continue;
209
+ const sourcePath = moduleSpecifier.text;
210
+ if (!statement.exportClause) {
211
+ // export * from './module' - true star export
212
+ result.starExports.push(sourcePath);
213
+ }
214
+ else if (ts.isNamedExports(statement.exportClause)) {
215
+ // export { x, y } from './module' or export { x as y } from './module'
216
+ for (const element of statement.exportClause.elements) {
217
+ const exportedName = element.name.text;
218
+ // propertyName is the original name if aliased (export { original as exported })
219
+ const originalName = element.propertyName?.text ?? exportedName;
220
+ result.namedReExports.push({ exportedName, originalName, sourcePath });
221
+ }
222
+ }
223
+ }
224
+ }
225
+ return result;
226
+ }
227
+ /**
228
+ * Creates an empty extraction result
229
+ */
230
+ function createEmptyResult() {
231
+ return {
232
+ functions: [],
233
+ classes: [],
234
+ interfaces: [],
235
+ types: [],
236
+ reExports: [],
237
+ importedExports: [],
238
+ errors: []
239
+ };
240
+ }
241
+ /**
242
+ * Merges two extraction results
243
+ */
244
+ function mergeResults(a, b) {
245
+ return {
246
+ functions: [...a.functions, ...b.functions],
247
+ classes: [...a.classes, ...b.classes],
248
+ interfaces: [...a.interfaces, ...b.interfaces],
249
+ types: [...a.types, ...b.types],
250
+ reExports: [...a.reExports, ...b.reExports],
251
+ importedExports: [...a.importedExports, ...b.importedExports],
252
+ errors: [...a.errors, ...b.errors]
253
+ };
254
+ }
255
+ /**
256
+ * Extracts all exports from a TypeScript declaration file
257
+ */
258
+ export async function extract(entryPath) {
259
+ const result = createEmptyResult();
260
+ let content;
261
+ try {
262
+ content = await readFile(entryPath, 'utf-8');
263
+ }
264
+ catch (error) {
265
+ result.errors.push(`Failed to read file: ${entryPath}`);
266
+ return result;
267
+ }
268
+ let sourceFile;
269
+ try {
270
+ sourceFile = ts.createSourceFile(entryPath, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
271
+ }
272
+ catch (error) {
273
+ result.errors.push(`Failed to parse file: ${entryPath}`);
274
+ return result;
275
+ }
276
+ // Track imports for import-then-export pattern detection
277
+ const importTracker = createImportTracker(sourceFile);
278
+ // Extract re-exports (export * from './module' and export { x } from './module')
279
+ const reExportInfo = extractReExports(sourceFile);
280
+ result.reExports.push(...reExportInfo.starExports);
281
+ // Named re-exports are treated like importedExports (they need symbol extraction with renaming)
282
+ result.importedExports.push(...reExportInfo.namedReExports);
283
+ // Build a map of all declarations in the file (for export { x } resolution)
284
+ const declarations = new Map();
285
+ // First pass: collect all declarations
286
+ function collectDeclarations(node) {
287
+ if (ts.isFunctionDeclaration(node) && node.name) {
288
+ declarations.set(node.name.text, node);
289
+ }
290
+ if (ts.isClassDeclaration(node) && node.name) {
291
+ declarations.set(node.name.text, node);
292
+ }
293
+ if (ts.isInterfaceDeclaration(node)) {
294
+ declarations.set(node.name.text, node);
295
+ }
296
+ if (ts.isTypeAliasDeclaration(node)) {
297
+ declarations.set(node.name.text, node);
298
+ }
299
+ ts.forEachChild(node, collectDeclarations);
300
+ }
301
+ collectDeclarations(sourceFile);
302
+ // Track which symbols are exported via export { x } declarations
303
+ const exportedViaDeclaration = new Map(); // localName -> exportedName
304
+ // Walk the AST
305
+ function visit(node) {
306
+ try {
307
+ // Exported function declaration (with export keyword)
308
+ if (ts.isFunctionDeclaration(node) && isExported(node) && node.name) {
309
+ result.functions.push(extractFunction(node, sourceFile));
310
+ }
311
+ // Exported class declaration (with export keyword)
312
+ if (ts.isClassDeclaration(node) && isExported(node) && node.name) {
313
+ result.classes.push(extractClass(node, sourceFile));
314
+ }
315
+ // Exported interface declaration (with export keyword)
316
+ if (ts.isInterfaceDeclaration(node) && isExported(node)) {
317
+ result.interfaces.push(extractInterface(node, sourceFile));
318
+ }
319
+ // Exported type alias (with export keyword)
320
+ if (ts.isTypeAliasDeclaration(node) && isExported(node)) {
321
+ result.types.push(extractTypeAlias(node, sourceFile));
322
+ }
323
+ // Handle export declarations without module specifier (export { x, y } or export { x as y })
324
+ if (ts.isExportDeclaration(node) && node.exportClause && !node.moduleSpecifier) {
325
+ if (ts.isNamedExports(node.exportClause)) {
326
+ for (const element of node.exportClause.elements) {
327
+ // The exported name (what consumers see)
328
+ const exportedName = element.name.text;
329
+ // The local name (might be aliased: export { local as exported })
330
+ const localName = element.propertyName?.text ?? exportedName;
331
+ // Check if this is an imported symbol
332
+ const importInfo = importTracker.getImport(localName);
333
+ if (importInfo) {
334
+ result.importedExports.push({
335
+ exportedName,
336
+ originalName: importInfo.originalName,
337
+ sourcePath: importInfo.sourcePath
338
+ });
339
+ }
340
+ else {
341
+ // Not an import - check if it's a local declaration
342
+ // Record it for extraction with the exported name
343
+ exportedViaDeclaration.set(localName, exportedName);
344
+ }
345
+ }
346
+ }
347
+ }
348
+ }
349
+ catch (error) {
350
+ const message = error instanceof Error ? error.message : String(error);
351
+ result.errors.push(`Error processing node: ${message}`);
352
+ }
353
+ ts.forEachChild(node, visit);
354
+ }
355
+ visit(sourceFile);
356
+ // Second pass: extract declarations that are exported via export { x } or export { x as y }
357
+ for (const [localName, exportedName] of exportedViaDeclaration) {
358
+ const decl = declarations.get(localName);
359
+ if (!decl)
360
+ continue;
361
+ if (ts.isFunctionDeclaration(decl) && decl.name) {
362
+ const extracted = extractFunction(decl, sourceFile);
363
+ // Rename if aliased
364
+ if (localName !== exportedName) {
365
+ extracted.name = exportedName;
366
+ extracted.signature = extracted.signature.replace(localName, exportedName);
367
+ }
368
+ result.functions.push(extracted);
369
+ }
370
+ if (ts.isClassDeclaration(decl) && decl.name) {
371
+ const extracted = extractClass(decl, sourceFile);
372
+ if (localName !== exportedName) {
373
+ extracted.name = exportedName;
374
+ }
375
+ result.classes.push(extracted);
376
+ }
377
+ if (ts.isInterfaceDeclaration(decl)) {
378
+ const extracted = extractInterface(decl, sourceFile);
379
+ if (localName !== exportedName) {
380
+ extracted.name = exportedName;
381
+ }
382
+ result.interfaces.push(extracted);
383
+ }
384
+ if (ts.isTypeAliasDeclaration(decl)) {
385
+ const extracted = extractTypeAlias(decl, sourceFile);
386
+ if (localName !== exportedName) {
387
+ extracted.name = exportedName;
388
+ }
389
+ result.types.push(extracted);
390
+ }
391
+ }
392
+ return result;
393
+ }
394
+ /**
395
+ * Checks if a module path is external (not relative)
396
+ */
397
+ function isExternalModule(modulePath) {
398
+ return !modulePath.startsWith('.') && !modulePath.startsWith('/');
399
+ }
400
+ /**
401
+ * Resolves a module path to an actual file path
402
+ * Handles .js → .d.ts mapping and index.d.ts fallbacks
403
+ * For external modules, returns undefined (handled separately)
404
+ */
405
+ function resolveModulePath(modulePath, baseDir) {
406
+ // External modules are handled separately
407
+ if (isExternalModule(modulePath)) {
408
+ return undefined;
409
+ }
410
+ let resolvedPath = resolve(baseDir, modulePath);
411
+ // Handle .js extension (common in ESM - maps to .d.ts)
412
+ if (resolvedPath.endsWith('.js')) {
413
+ const dtsPath = resolvedPath.replace(/\.js$/, '.d.ts');
414
+ if (existsSync(dtsPath)) {
415
+ return dtsPath;
416
+ }
417
+ }
418
+ // Try with .d.ts extension
419
+ if (!resolvedPath.endsWith('.d.ts') && !resolvedPath.endsWith('.ts')) {
420
+ if (existsSync(resolvedPath + '.d.ts')) {
421
+ return resolvedPath + '.d.ts';
422
+ }
423
+ else if (existsSync(resolvedPath + '.ts')) {
424
+ return resolvedPath + '.ts';
425
+ }
426
+ else if (existsSync(join(resolvedPath, 'index.d.ts'))) {
427
+ return join(resolvedPath, 'index.d.ts');
428
+ }
429
+ }
430
+ // Already has extension
431
+ if (existsSync(resolvedPath)) {
432
+ return resolvedPath;
433
+ }
434
+ return undefined;
435
+ }
436
+ /**
437
+ * Extracts specific symbols from a source file
438
+ * Used for import-then-export pattern resolution
439
+ */
440
+ async function extractSymbolsFromSource(sourcePath, symbols, visited) {
441
+ const result = createEmptyResult();
442
+ // Skip if already visited (cycle detection)
443
+ if (visited.has(sourcePath)) {
444
+ return result;
445
+ }
446
+ visited.add(sourcePath);
447
+ // Extract all exports from source file
448
+ const sourceResult = await extract(sourcePath);
449
+ // Follow any re-exports in the source file first
450
+ const followedSource = await followReExports(sourceResult, sourcePath, visited);
451
+ // Filter to only the symbols we're looking for
452
+ const symbolNames = new Set(symbols.map(s => s.originalName));
453
+ result.functions = followedSource.functions.filter(f => symbolNames.has(f.name));
454
+ result.classes = followedSource.classes.filter(c => symbolNames.has(c.name));
455
+ result.interfaces = followedSource.interfaces.filter(i => symbolNames.has(i.name));
456
+ result.types = followedSource.types.filter(t => symbolNames.has(t.name));
457
+ // Handle aliased exports - rename to the exported name
458
+ for (const sym of symbols) {
459
+ if (sym.exportedName !== sym.originalName) {
460
+ // Rename functions
461
+ const fn = result.functions.find(f => f.name === sym.originalName);
462
+ if (fn) {
463
+ fn.name = sym.exportedName;
464
+ fn.signature = fn.signature.replace(sym.originalName, sym.exportedName);
465
+ }
466
+ // Rename classes
467
+ const cls = result.classes.find(c => c.name === sym.originalName);
468
+ if (cls) {
469
+ cls.name = sym.exportedName;
470
+ }
471
+ // Rename interfaces
472
+ const iface = result.interfaces.find(i => i.name === sym.originalName);
473
+ if (iface) {
474
+ iface.name = sym.exportedName;
475
+ }
476
+ // Rename types
477
+ const typ = result.types.find(t => t.name === sym.originalName);
478
+ if (typ) {
479
+ typ.name = sym.exportedName;
480
+ }
481
+ }
482
+ }
483
+ // If we didn't find some symbols, they might be in importedExports of the source
484
+ // (nested import-then-export pattern)
485
+ const foundNames = new Set([
486
+ ...result.functions.map(f => f.name),
487
+ ...result.classes.map(c => c.name),
488
+ ...result.interfaces.map(i => i.name),
489
+ ...result.types.map(t => t.name)
490
+ ]);
491
+ const missingSymbols = symbols.filter(s => !foundNames.has(s.exportedName));
492
+ if (missingSymbols.length > 0 && followedSource.importedExports.length > 0) {
493
+ // Check if missing symbols are in importedExports
494
+ const baseDir = dirname(sourcePath);
495
+ for (const missing of missingSymbols) {
496
+ const importedExport = followedSource.importedExports.find(ie => ie.exportedName === missing.originalName);
497
+ if (importedExport) {
498
+ const nestedPath = resolveModulePath(importedExport.sourcePath, baseDir);
499
+ if (nestedPath) {
500
+ const nestedResult = await extractSymbolsFromSource(nestedPath, [{ exportedName: missing.exportedName, originalName: importedExport.originalName }], visited);
501
+ result.functions.push(...nestedResult.functions);
502
+ result.classes.push(...nestedResult.classes);
503
+ result.interfaces.push(...nestedResult.interfaces);
504
+ result.types.push(...nestedResult.types);
505
+ }
506
+ }
507
+ }
508
+ }
509
+ return result;
510
+ }
511
+ /**
512
+ * Follows re-exports and extracts from referenced modules
513
+ */
514
+ export async function followReExports(result, basePath, visited = new Set(), options = {}) {
515
+ const baseDir = dirname(basePath);
516
+ let mergedResult = { ...result };
517
+ const { externalResolver, maxExternalDepth = 2 } = options;
518
+ // Track external packages we've already processed
519
+ const processedExternalPackages = new Set();
520
+ // Follow traditional re-exports (export * from './module' or 'external-package')
521
+ for (const reExport of result.reExports) {
522
+ // Check if this is an external package
523
+ if (isExternalModule(reExport)) {
524
+ // Only follow external packages if we have a resolver
525
+ if (!externalResolver) {
526
+ continue;
527
+ }
528
+ // Extract package name (handle scoped packages)
529
+ const packageName = reExport.startsWith('@')
530
+ ? reExport.split('/').slice(0, 2).join('/')
531
+ : reExport.split('/')[0];
532
+ // Skip if already processed
533
+ if (processedExternalPackages.has(packageName)) {
534
+ continue;
535
+ }
536
+ processedExternalPackages.add(packageName);
537
+ // Resolve external package
538
+ const resolved = await externalResolver.resolve(packageName);
539
+ if (!resolved.success || !resolved.typesPath) {
540
+ mergedResult.errors.push(`Could not resolve external package: ${packageName}`);
541
+ continue;
542
+ }
543
+ // Skip if already visited
544
+ if (visited.has(resolved.typesPath)) {
545
+ continue;
546
+ }
547
+ visited.add(resolved.typesPath);
548
+ // Extract from external package (with reduced depth for externals)
549
+ const externalResult = await extract(resolved.typesPath);
550
+ // Don't follow external packages' externals too deeply
551
+ const followedExternal = await followReExports(externalResult, resolved.typesPath, visited, { externalResolver: maxExternalDepth > 1 ? externalResolver : undefined, maxExternalDepth: maxExternalDepth - 1 });
552
+ mergedResult = mergeResults(mergedResult, followedExternal);
553
+ continue;
554
+ }
555
+ // Handle relative paths
556
+ const resolvedPath = resolveModulePath(reExport, baseDir);
557
+ if (!resolvedPath) {
558
+ continue;
559
+ }
560
+ // Skip if already visited (circular reference protection)
561
+ if (visited.has(resolvedPath)) {
562
+ continue;
563
+ }
564
+ visited.add(resolvedPath);
565
+ // Extract from the re-exported module
566
+ const reExportResult = await extract(resolvedPath);
567
+ const followedResult = await followReExports(reExportResult, resolvedPath, visited, options);
568
+ mergedResult = mergeResults(mergedResult, followedResult);
569
+ }
570
+ // Follow import-then-export patterns
571
+ // Group by source path for efficiency
572
+ const importsBySource = new Map();
573
+ const externalImports = new Map();
574
+ for (const importedExport of result.importedExports) {
575
+ if (isExternalModule(importedExport.sourcePath)) {
576
+ // External package import
577
+ const packageName = importedExport.sourcePath.startsWith('@')
578
+ ? importedExport.sourcePath.split('/').slice(0, 2).join('/')
579
+ : importedExport.sourcePath.split('/')[0];
580
+ if (!externalImports.has(packageName)) {
581
+ externalImports.set(packageName, []);
582
+ }
583
+ externalImports.get(packageName).push({
584
+ exportedName: importedExport.exportedName,
585
+ originalName: importedExport.originalName
586
+ });
587
+ }
588
+ else {
589
+ // Relative import
590
+ const resolvedPath = resolveModulePath(importedExport.sourcePath, baseDir);
591
+ if (!resolvedPath) {
592
+ continue;
593
+ }
594
+ if (!importsBySource.has(resolvedPath)) {
595
+ importsBySource.set(resolvedPath, []);
596
+ }
597
+ importsBySource.get(resolvedPath).push({
598
+ exportedName: importedExport.exportedName,
599
+ originalName: importedExport.originalName
600
+ });
601
+ }
602
+ }
603
+ // Extract symbols from relative sources
604
+ for (const [sourcePath, symbols] of importsBySource) {
605
+ const extractedSymbols = await extractSymbolsFromSource(sourcePath, symbols, visited);
606
+ mergedResult = mergeResults(mergedResult, extractedSymbols);
607
+ }
608
+ // Extract symbols from external packages
609
+ if (externalResolver) {
610
+ for (const [packageName, symbols] of externalImports) {
611
+ // Skip if already processed
612
+ if (processedExternalPackages.has(packageName)) {
613
+ continue;
614
+ }
615
+ processedExternalPackages.add(packageName);
616
+ const resolved = await externalResolver.resolve(packageName);
617
+ if (!resolved.success || !resolved.typesPath) {
618
+ mergedResult.errors.push(`Could not resolve external package for imports: ${packageName}`);
619
+ continue;
620
+ }
621
+ // Skip if already visited
622
+ if (visited.has(resolved.typesPath)) {
623
+ continue;
624
+ }
625
+ // Extract specific symbols from external package
626
+ const extractedSymbols = await extractSymbolsFromSource(resolved.typesPath, symbols, visited);
627
+ mergedResult = mergeResults(mergedResult, extractedSymbols);
628
+ }
629
+ }
630
+ // Clear re-exports and importedExports from final result (they've been followed)
631
+ mergedResult.reExports = [];
632
+ mergedResult.importedExports = [];
633
+ return mergedResult;
634
+ }
635
+ /**
636
+ * Creates a TypeExtractor instance
637
+ */
638
+ export function createTypeExtractor(projectRoot) {
639
+ const externalResolver = projectRoot ? createExternalPackageResolver(projectRoot) : undefined;
640
+ return {
641
+ extract,
642
+ followReExports: (result, basePath, visited) => followReExports(result, basePath, visited, { externalResolver }),
643
+ clearExternalCache: () => externalResolver?.clearCache(),
644
+ getExternalCacheStats: () => externalResolver?.getCacheStats() ?? { resolved: 0, failed: 0 }
645
+ };
646
+ }
647
+ //# sourceMappingURL=typescript.js.map