Skip to content

Commit 05ba6d0

Browse files
committed
chore: wip
1 parent 19b0abf commit 05ba6d0

2 files changed

Lines changed: 61 additions & 63 deletions

File tree

fixtures/output/example-0001.d.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@ import type { BunPlugin } from 'bun';
44
/**
55
* Example of const declaration
66
*/
7-
export const conf: { [key: string]: string };
7+
export declare const conf: {
8+
apiUrl: 'https://api.stacksjs.org';
9+
timeout: '5000';
10+
};
811

9-
export const someObject: {
12+
export declare const someObject: {
1013
someString: string;
1114
someNumber: number;
1215
};
1316

1417
/**
1518
* Example of interface declaration
1619
*/
17-
export interface User {
20+
export declare interface User {
1821
id: number;
1922
name: string;
2023
email: string;
@@ -23,23 +26,23 @@ export interface User {
2326
/**
2427
* Example of type declaration
2528
*/
26-
export interface ResponseData {
29+
export declare interface ResponseData {
2730
success: boolean;
2831
data: User[];
2932
}
3033

3134
/**
3235
* Example of function declaration
3336
*/
34-
export function fetchUsers(): Promise<ResponseData>;
37+
export declare function fetchUsers(): Promise<ResponseData>;
3538

36-
export interface ApiResponse<T> {
39+
export declare interface ApiResponse<T> {
3740
status: number;
3841
message: string;
3942
data: T;
4043
}
4144

42-
export interface Product {
45+
export declare interface Product {
4346
id: number;
4447
name: string;
4548
price: number;
@@ -48,32 +51,32 @@ export interface Product {
4851
/**
4952
* Example of function declaration
5053
*/
51-
export function getProduct(id: number): Promise<ApiResponse<Product>>;
54+
export declare function getProduct(id: number): Promise<ApiResponse<Product>>;
5255

53-
export interface AuthResponse {
56+
export declare interface AuthResponse {
5457
token: string;
5558
expiresIn: number;
5659
}
5760

58-
export type AuthStatus = 'authenticated' | 'unauthenticated';
61+
export declare type AuthStatus = 'authenticated' | 'unauthenticated';
5962

60-
export function authenticate(user: string, password: string): Promise<AuthResponse>;
63+
export declare function authenticate(user: string, password: string): Promise<AuthResponse>;
6164

62-
export const defaultHeaders: {
65+
export declare const defaultHeaders: {
6366
'Content-Type': string;
6467
};
6568

66-
export function dts(options?: DtsGenerationOption): BunPlugin;
69+
export declare function dts(options?: DtsGenerationOption): BunPlugin;
6770

6871
interface Options<T> {
6972
name: string;
7073
cwd?: string;
7174
defaultConfig: T;
7275
}
7376

74-
export function loadConfig<T extends Record<string, unknown>>(options: Options<T>): Promise<T>;
77+
export declare function loadConfig<T extends Record<string, unknown>>(options: Options<T>): Promise<T>;
7578

76-
export const dtsConfig: DtsGenerationConfig;
79+
export declare const dtsConfig: DtsGenerationConfig;
7780

7881
export { generate } from '@stacksjs/dtsx';
7982

src/extract.ts

Lines changed: 43 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export async function extract(filePath: string): Promise<string> {
1313
export function generateDtsTypes(sourceCode: string): string {
1414
const lines = sourceCode.split('\n')
1515
const dtsLines: string[] = []
16+
const imports: string[] = []
17+
const exports: string[] = []
1618

1719
let isMultiLineDeclaration = false
1820
let currentDeclaration = ''
@@ -24,39 +26,49 @@ export function generateDtsTypes(sourceCode: string): string {
2426

2527
// Handle imports
2628
if (trimmed.startsWith('import')) {
27-
return trimmed.endsWith(';') ? trimmed : `${trimmed};`
29+
imports.push(trimmed.endsWith(';') ? trimmed : `${trimmed};`)
30+
return ''
2831
}
2932

3033
// Handle exports from other files
3134
if (trimmed.startsWith('export') && trimmed.includes('from')) {
32-
return trimmed.endsWith(';') ? trimmed : `${trimmed};`
35+
exports.push(trimmed.endsWith(';') ? trimmed : `${trimmed};`)
36+
return ''
3337
}
3438

35-
// Handle interfaces and types
36-
if (trimmed.startsWith('export interface') || trimmed.startsWith('export type') || trimmed.startsWith('interface')) {
39+
// Handle const declarations
40+
if (trimmed.startsWith('export const')) {
41+
const [name, rest] = trimmed.split('=')
42+
const type = name.split(':')[1]?.trim() || 'any'
43+
return `export declare const ${name.split(':')[0].replace('export const', '').trim()}: ${type};`
44+
}
45+
46+
// Handle interface declarations
47+
if (trimmed.startsWith('export interface')) {
3748
return trimmed.replace(/\s*\{\s*([^}]+)\}\s*$/, (_, content) => {
3849
const formattedContent = content
39-
.split(/[,;]/)
50+
.split(';')
4051
.map(prop => prop.trim())
4152
.filter(Boolean)
4253
.map(prop => ` ${prop};`)
4354
.join('\n')
4455
return ` {\n${formattedContent}\n}`
45-
})
56+
}).replace('export ', 'export declare ')
4657
}
4758

48-
// Handle const declarations
49-
if (trimmed.startsWith('export const')) {
50-
const [name, type] = trimmed.split(/:\s*/, 2)
51-
if (type) {
52-
return `${name}: ${type.split('=')[0].trim()};`
53-
}
54-
return `${name}: any;`
59+
// Handle type declarations
60+
if (trimmed.startsWith('export type')) {
61+
return `export declare ${trimmed.replace('export ', '')}`
5562
}
5663

5764
// Handle function declarations
5865
if (trimmed.includes('function')) {
59-
return `${trimmed.split('{')[0].trim()};`
66+
return `export declare ${trimmed.replace('export ', '').split('{')[0].trim()};`
67+
}
68+
69+
// Handle default exports
70+
if (trimmed.startsWith('export default')) {
71+
return `export default ${trimmed.replace('export default ', '')};`
6072
}
6173

6274
return trimmed
@@ -79,10 +91,12 @@ export function generateDtsTypes(sourceCode: string): string {
7991

8092
if (bracketCount === 0 || i === lines.length - 1) {
8193
if (lastCommentBlock) {
82-
dtsLines.push(lastCommentBlock.trim())
94+
dtsLines.push(lastCommentBlock.trimEnd())
8395
lastCommentBlock = ''
8496
}
85-
dtsLines.push(processDeclaration(currentDeclaration))
97+
const processed = processDeclaration(currentDeclaration)
98+
if (processed)
99+
dtsLines.push(processed)
86100
isMultiLineDeclaration = false
87101
currentDeclaration = ''
88102
}
@@ -92,10 +106,12 @@ export function generateDtsTypes(sourceCode: string): string {
92106

93107
if (bracketCount === 0) {
94108
if (lastCommentBlock) {
95-
dtsLines.push(lastCommentBlock.trim())
109+
dtsLines.push(lastCommentBlock.trimEnd())
96110
lastCommentBlock = ''
97111
}
98-
dtsLines.push(processDeclaration(line))
112+
const processed = processDeclaration(line)
113+
if (processed)
114+
dtsLines.push(processed)
99115
}
100116
else {
101117
isMultiLineDeclaration = true
@@ -104,35 +120,14 @@ export function generateDtsTypes(sourceCode: string): string {
104120
}
105121
}
106122

107-
// Remove duplicate exports and format specific declarations
108-
const seenExports = new Set()
109-
const filteredLines = dtsLines.filter((line) => {
110-
if (line.startsWith('export {') || line.startsWith('export type {')) {
111-
const exportName = line.match(/export (?:type )?\{([^}]+)\}/)?.[1].trim()
112-
if (seenExports.has(exportName))
113-
return false
114-
seenExports.add(exportName)
115-
}
116-
return true
117-
}).map((line) => {
118-
if (line.startsWith('export function loadConfig')) {
119-
return 'export function loadConfig<T extends Record<string, unknown>>(options: Options<T>): Promise<T>;'
120-
}
121-
if (line.startsWith('export const dtsConfig')) {
122-
return 'export const dtsConfig: DtsGenerationConfig;'
123-
}
124-
return line
125-
})
126-
127-
// Add missing declarations
128-
filteredLines.push('export { generate } from \'@stacksjs/dtsx\';')
129-
filteredLines.push('export default dts;')
123+
// Combine imports, declarations, and exports
124+
const result = [
125+
...imports,
126+
'',
127+
...dtsLines,
128+
'',
129+
...exports,
130+
].filter(Boolean).join('\n')
130131

131-
// Join lines with a single line break, and add an extra line break before certain declarations
132-
return filteredLines.map((line, index) => {
133-
if (index > 0 && (line.startsWith('export') || line.startsWith('import'))) {
134-
return `\n${line}`
135-
}
136-
return line
137-
}).join('\n')
132+
return result
138133
}

0 commit comments

Comments
 (0)