Skip to content

Commit da82012

Browse files
committed
chore: several improvements
1 parent 22a10ef commit da82012

21 files changed

Lines changed: 582 additions & 658 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ fixtures/generated
1717
/test/temp-output
1818
test/debug
1919
/test/fixtures/generated
20+
/pantry

packages/dtsx/.test-cli/docs-test/api-docs/API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# API Documentation
22

3-
> Generated on 2025-11-30T12:48:29.571Z
3+
> Generated on 2026-02-08T21:09:35.476Z
44
55
## Table of Contents
66

packages/dtsx/src/cache.ts

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,30 @@ export class BuildCache {
130130
* Check if a file needs to be regenerated
131131
*/
132132
needsRegeneration(filePath: string, cwd: string): boolean {
133+
return this.getCachedIfValid(filePath, cwd) === null
134+
}
135+
136+
/**
137+
* Get cached content for a file
138+
*/
139+
getCached(filePath: string, cwd: string): string | null {
140+
return this.getCachedIfValid(filePath, cwd)
141+
}
142+
143+
/**
144+
* Get cached DTS content if the cache entry is still valid, or null if regeneration is needed.
145+
* Combines cache validation and retrieval in a single operation.
146+
*/
147+
getCachedIfValid(filePath: string, cwd: string): string | null {
133148
if (!this.manifest) {
134-
return true
149+
return null
135150
}
136151

137152
const relativePath = relative(cwd, filePath)
138153
const entry = this.manifest.entries[relativePath]
139154

140155
if (!entry) {
141-
return true
156+
return null
142157
}
143158

144159
try {
@@ -152,37 +167,19 @@ export class BuildCache {
152167
const hash = this.hashContent(content)
153168

154169
if (hash !== entry.sourceHash) {
155-
return true
170+
return null
156171
}
157172

158173
// Hash matches despite mtime change (e.g., touched file)
159174
// Update mtime in cache
160175
entry.sourceMtime = mtime
161176
}
162177

163-
return false
178+
return entry.dtsContent
164179
}
165180
catch {
166-
return true
167-
}
168-
}
169-
170-
/**
171-
* Get cached content for a file
172-
*/
173-
getCached(filePath: string, cwd: string): string | null {
174-
if (!this.manifest) {
175181
return null
176182
}
177-
178-
const relativePath = relative(cwd, filePath)
179-
const entry = this.manifest.entries[relativePath]
180-
181-
if (!entry) {
182-
return null
183-
}
184-
185-
return entry.dtsContent
186183
}
187184

188185
/**

packages/dtsx/src/compat.ts

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -263,31 +263,3 @@ export function getRuntimeInfo(): RuntimeInfo {
263263
}
264264
}
265265

266-
/**
267-
* Namespace export for drop-in Bun API replacement
268-
*/
269-
export const compat: {
270-
file: typeof file
271-
write: typeof write
272-
spawn: typeof spawnProcess
273-
readTextFile: typeof readTextFile
274-
writeTextFile: typeof writeTextFile
275-
fileExists: typeof fileExists
276-
getRuntimeInfo: typeof getRuntimeInfo
277-
runtime: typeof runtime
278-
isBun: typeof isBun
279-
isNode: typeof isNode
280-
} = {
281-
file,
282-
write,
283-
spawn: spawnProcess,
284-
readTextFile,
285-
writeTextFile,
286-
fileExists,
287-
getRuntimeInfo,
288-
runtime,
289-
isBun,
290-
isNode,
291-
}
292-
293-
export default compat

packages/dtsx/src/extractor/builders.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -311,17 +311,6 @@ function isPrivateMemberName(member: { name?: import('typescript').PropertyName
311311
return member.name ? isPrivateIdentifier(member.name) : false
312312
}
313313

314-
/**
315-
* Check if a property name is a symbol expression (Symbol.iterator, etc.)
316-
*/
317-
function _isSymbolPropertyName(member: { name?: import('typescript').PropertyName }): boolean {
318-
if (!member.name)
319-
return false
320-
const text = member.name.getText()
321-
// Check for [Symbol.xxx] pattern
322-
return text.startsWith('[Symbol.') || text.startsWith('[customSymbol')
323-
}
324-
325314
/**
326315
* Get the property name text, handling computed properties and symbols
327316
*/

packages/dtsx/src/extractor/cache.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,25 @@ export function hashContent(content: string): number {
5959
}
6060

6161
/**
62-
* Evict oldest entries if cache exceeds max size
62+
* Evict oldest entry if cache exceeds max size
63+
* Uses O(n) scan instead of O(n log n) sort since we add one entry at a time
6364
*/
6465
export function evictOldestEntries(): void {
6566
if (sourceFileCache.size <= MAX_CACHE_SIZE) {
6667
return
6768
}
6869

69-
// Sort by last access time and remove oldest entries
70-
const entries = Array.from(sourceFileCache.entries())
71-
.sort((a, b) => a[1].lastAccess - b[1].lastAccess)
72-
73-
const toRemove = entries.slice(0, entries.length - MAX_CACHE_SIZE)
74-
for (const [key] of toRemove) {
75-
sourceFileCache.delete(key)
70+
// Find the oldest entry by last access time
71+
let oldestKey: string | null = null
72+
let oldestTime = Infinity
73+
for (const [key, entry] of sourceFileCache) {
74+
if (entry.lastAccess < oldestTime) {
75+
oldestTime = entry.lastAccess
76+
oldestKey = key
77+
}
78+
}
79+
if (oldestKey) {
80+
sourceFileCache.delete(oldestKey)
7681
}
7782
}
7883

packages/dtsx/src/extractor/declarations.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,20 @@ export function extractImportDeclaration(node: ImportDeclaration, sourceCode: st
3434
/**
3535
* Extract export declaration
3636
*/
37-
export function extractExportDeclaration(node: ExportDeclaration, sourceCode: string): Declaration {
37+
export function extractExportDeclaration(node: ExportDeclaration, sourceCode: string, sourceFile?: SourceFile, keepComments: boolean = false): Declaration {
3838
const text = getNodeText(node, sourceCode)
3939
const isTypeOnly = !!node.isTypeOnly
4040

41+
// Extract comments if enabled and sourceFile is available
42+
const leadingComments = keepComments && sourceFile ? extractJSDocComments(node, sourceFile) : undefined
43+
4144
return {
4245
kind: 'export',
4346
name: '', // Export declarations don't have a single name
4447
text,
4548
isExported: true,
4649
isTypeOnly,
50+
leadingComments,
4751
source: node.moduleSpecifier?.getText().slice(1, -1), // Remove quotes if present
4852
start: node.getStart(),
4953
end: node.getEnd(),
@@ -53,15 +57,19 @@ export function extractExportDeclaration(node: ExportDeclaration, sourceCode: st
5357
/**
5458
* Extract export assignment (export default)
5559
*/
56-
export function extractExportAssignment(node: ExportAssignment, sourceCode: string): Declaration {
60+
export function extractExportAssignment(node: ExportAssignment, sourceCode: string, sourceFile?: SourceFile, keepComments: boolean = false): Declaration {
5761
const text = getNodeText(node, sourceCode)
5862

63+
// Extract comments if enabled and sourceFile is available
64+
const leadingComments = keepComments && sourceFile ? extractJSDocComments(node, sourceFile) : undefined
65+
5966
return {
6067
kind: 'export',
6168
name: 'default',
6269
text,
6370
isExported: true,
6471
isTypeOnly: false,
72+
leadingComments,
6573
start: node.getStart(),
6674
end: node.getEnd(),
6775
}
@@ -170,16 +178,6 @@ function isAsConstAssertion(node: import('typescript').Expression): boolean {
170178
return false
171179
}
172180

173-
/**
174-
* Get the underlying expression from an 'as const' assertion
175-
*/
176-
function _getAsConstValue(node: import('typescript').Expression): import('typescript').Expression | null {
177-
if (isAsExpression(node) && isAsConstAssertion(node)) {
178-
return node.expression
179-
}
180-
return null
181-
}
182-
183181
/**
184182
* Infer a literal type from a value for 'as const' declarations
185183
* This creates readonly types for objects and arrays
@@ -491,7 +489,7 @@ export function findReferencedTypes(declarations: Declaration[], _sourceCode: st
491489
/**
492490
* Extract declarations for referenced types by searching the entire source file
493491
*/
494-
export function extractReferencedTypeDeclarations(sourceFile: SourceFile, referencedTypes: Set<string>, sourceCode: string): Declaration[] {
492+
export function extractReferencedTypeDeclarations(sourceFile: SourceFile, referencedTypes: Set<string>, sourceCode: string, keepComments: boolean = true): Declaration[] {
495493
const additionalDeclarations: Declaration[] = []
496494

497495
if (referencedTypes.size === 0) {
@@ -505,7 +503,7 @@ export function extractReferencedTypeDeclarations(sourceFile: SourceFile, refere
505503
const interfaceNode = node as InterfaceDeclaration
506504
const interfaceName = interfaceNode.name.getText()
507505
if (referencedTypes.has(interfaceName)) {
508-
const decl = extractInterfaceDeclaration(interfaceNode, sourceCode, sourceFile, false) // Don't extract comments for referenced types
506+
const decl = extractInterfaceDeclaration(interfaceNode, sourceCode, sourceFile, keepComments)
509507
additionalDeclarations.push(decl)
510508
referencedTypes.delete(interfaceName) // Remove to avoid duplicates
511509
}
@@ -516,7 +514,7 @@ export function extractReferencedTypeDeclarations(sourceFile: SourceFile, refere
516514
const typeNode = node as TypeAliasDeclaration
517515
const typeName = typeNode.name.getText()
518516
if (referencedTypes.has(typeName)) {
519-
const decl = extractTypeAliasDeclaration(typeNode, sourceCode, sourceFile, false) // Don't extract comments for referenced types
517+
const decl = extractTypeAliasDeclaration(typeNode, sourceCode, sourceFile, keepComments)
520518
additionalDeclarations.push(decl)
521519
referencedTypes.delete(typeName)
522520
}
@@ -528,7 +526,7 @@ export function extractReferencedTypeDeclarations(sourceFile: SourceFile, refere
528526
if (classNode.name) {
529527
const className = classNode.name.getText()
530528
if (referencedTypes.has(className)) {
531-
const decl = extractClassDeclaration(classNode, sourceCode, sourceFile, false) // Don't extract comments for referenced types
529+
const decl = extractClassDeclaration(classNode, sourceCode, sourceFile, keepComments)
532530
additionalDeclarations.push(decl)
533531
referencedTypes.delete(className)
534532
}
@@ -540,7 +538,7 @@ export function extractReferencedTypeDeclarations(sourceFile: SourceFile, refere
540538
const enumNode = node as EnumDeclaration
541539
const enumName = enumNode.name.getText()
542540
if (referencedTypes.has(enumName)) {
543-
const decl = extractEnumDeclaration(enumNode, sourceCode, sourceFile, false) // Don't extract comments for referenced types
541+
const decl = extractEnumDeclaration(enumNode, sourceCode, sourceFile, keepComments)
544542
additionalDeclarations.push(decl)
545543
referencedTypes.delete(enumName)
546544
}

0 commit comments

Comments
 (0)