From 7833930bfc3478231a84889ad050bce5e756e077 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 24 Oct 2024 13:38:26 +0200 Subject: [PATCH] chore: wip --- fixtures/output/example-0001.d.ts | 40 ++++++++++++++++++++---- src/extract.ts | 51 +++++++++++++++++++++---------- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/fixtures/output/example-0001.d.ts b/fixtures/output/example-0001.d.ts index a8ae5d9..9e7b40d 100644 --- a/fixtures/output/example-0001.d.ts +++ b/fixtures/output/example-0001.d.ts @@ -1,14 +1,15 @@ import type { BunPlugin } from 'bun' -import process from 'node:process' -import { generate, deepMerge } from '@stacksjs/dtsx' import type { DtsGenerationConfig, DtsGenerationOption } from '@stacksjs/dtsx' import { existsSync } from 'node:fs' +import { generate, deepMerge } from '@stacksjs/dtsx' import { resolve } from 'node:path' +import process from 'node:process' /** * Example of const declaration */ export declare const conf: { [key: string]: string }; + export declare const someObject: { someString: 'Stacks'; someNumber: 1000; @@ -38,6 +39,7 @@ export declare const someObject: { someInlineCall2: (...args: any[]) => void; someInlineCall3: (...args: any[]) => void; }; + /** * Example of interface declaration * with another comment in an extra line @@ -47,6 +49,7 @@ export declare interface User { name: string email: string } + /** * Example of type declaration * @@ -56,6 +59,7 @@ export declare interface ResponseData { success: boolean data: User[] } + /** * Example of function declaration * @@ -63,50 +67,64 @@ export declare interface ResponseData { * with multiple empty lines, including an empty lines */ export declare function fetchUsers(): Promise; + export declare interface ApiResponse { status: number message: string data: T } + /** * Example of another const declaration * * with multiple empty lines, including being poorly formatted */ declare const settings: { [key: string]: any }; + export declare interface Product { id: number name: string price: number } + /** * Example of function declaration */ export declare function getProduct(id: number): Promise>; + export declare interface AuthResponse { token: string expiresIn: number } + export declare type AuthStatus = 'authenticated' | 'unauthenticated'; + export declare function authenticate(user: string, password: string): Promise; + export declare const defaultHeaders: { 'Content-Type': 'application/json'; }; + export declare function dts(options?: DtsGenerationOption): BunPlugin; + declare interface Options { name: string cwd?: string defaultConfig: T } + export declare async function loadConfig>(options: Options): Promise; + + declare const dtsConfig: DtsGenerationConfig; + export { generate, dtsConfig } + export type { DtsGenerationOption } + export { config } from './config' -export * from './extract' -export * from './generate' -export * from './types' -export * from './utils' + + export declare interface ComplexGeneric, K extends keyof T> { data: T key: K @@ -114,11 +132,21 @@ export declare interface ComplexGeneric, K ext transform: (input: T[K]) => string nested: Array> } + + export declare type ComplexUnionIntersection = + | (User & { role: 'admin' }) + | (Product & { category: string }) + & { metadata: Record } +export * from './extract' +export * from './generate' +export * from './types' +export * from './utils' + export default dts diff --git a/src/extract.ts b/src/extract.ts index cbb1f61..14eb86a 100644 --- a/src/extract.ts +++ b/src/extract.ts @@ -587,8 +587,6 @@ function processConstDeclaration(declaration: string, isExported = true): string console.log('Processing const declaration:', { declaration }) const lines = declaration.split('\n') const firstLine = lines[0] - const indentMatch = firstLine.match(/^(\s*)/) - const indent = indentMatch ? indentMatch[1] : '' // Check for type annotation const typeMatch = firstLine.match(/const\s+([^:]+):\s*([^=]+)\s*=/) @@ -1234,11 +1232,12 @@ function processSourceFile(content: string, state: ProcessingState): void { const lines = content.split('\n') const importLines: string[] = [] const exportDefaultLines: string[] = [] + const exportStarLines: string[] = [] let currentBlock: string[] = [] let currentComments: string[] = [] let isInMultilineDeclaration = false - // First pass: collect imports and export defaults + // First pass: collect imports and exports for (const line of lines) { const trimmedLine = line.trim() if (trimmedLine.startsWith('import')) { @@ -1249,20 +1248,26 @@ function processSourceFile(content: string, state: ProcessingState): void { exportDefaultLines.push(line) continue } + if (trimmedLine.startsWith('export *')) { + exportStarLines.push(line) + continue + } } // Process imports if (importLines.length > 0) { - state.dtsLines.push(...importLines) + state.dtsLines.push(...cleanImports(importLines)) state.dtsLines.push('') // Add single line break after imports } - // Process rest of the content + // Process main content for (const line of lines) { const trimmedLine = line.trim() - // Skip imports and export defaults as they're handled separately - if (trimmedLine.startsWith('import') || trimmedLine.startsWith('export default')) { + // Skip already processed lines + if (trimmedLine.startsWith('import') + || trimmedLine.startsWith('export default') + || trimmedLine.startsWith('export *')) { continue } @@ -1272,6 +1277,7 @@ function processSourceFile(content: string, state: ProcessingState): void { processDeclarationBlock(currentBlock, currentComments, state) currentBlock = [] currentComments = [] + state.dtsLines.push('') // Add line break after each declaration } continue } @@ -1307,24 +1313,35 @@ function processSourceFile(content: string, state: ProcessingState): void { processDeclarationBlock(currentBlock, currentComments, state) currentBlock = [] currentComments = [] + state.dtsLines.push('') // Add line break after each declaration } } else if (!trimmedLine.endsWith(',')) { processDeclarationBlock(currentBlock, currentComments, state) currentBlock = [] currentComments = [] + state.dtsLines.push('') // Add line break after each declaration } } // Process any remaining block if (currentBlock.length > 0) { processDeclarationBlock(currentBlock, currentComments, state) + state.dtsLines.push('') + } + + // Add export * statements with proper spacing + if (exportStarLines.length > 0) { + if (state.dtsLines[state.dtsLines.length - 1] !== '') { + state.dtsLines.push('') + } + state.dtsLines.push(...exportStarLines) } // Add export default at the end with proper spacing if (exportDefaultLines.length > 0) { if (state.dtsLines[state.dtsLines.length - 1] !== '') { - state.dtsLines.push('') // Add line break before export default + state.dtsLines.push('') } state.dtsLines.push(...exportDefaultLines) } @@ -1684,16 +1701,18 @@ function getDeclarationType(line: string): 'interface' | 'type' | 'const' | 'fun * Format the final output with proper spacing and organization */ function formatOutput(state: ProcessingState): string { - let output = state.dtsLines.join('\n') + const output = state.dtsLines + // Remove more than two consecutive empty lines + .reduce((acc, line, index, arr) => { + if (line === '' && arr[index - 1] === '' && arr[index - 2] === '') { + return acc + } + return [...acc, line] + }, [] as string[]) + .join('\n') - // Ensure proper formatting - output = `${output - // Remove multiple consecutive empty lines - .replace(/\n{3,}/g, '\n\n') // Ensure file ends with single newline - .trim()}\n` - - return output + return `${output.trim()}\n` } function getIndentation(line: string): string {