Skip to content

Commit 053bde5

Browse files
committed
chore: wip
1 parent 084920a commit 053bde5

File tree

9 files changed

+153
-155
lines changed

9 files changed

+153
-155
lines changed

src/processor.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,8 +1240,12 @@ function inferFunctionType(value: string, inUnion: boolean = false): string {
12401240
const innerFuncType = inferFunctionType(body, false)
12411241
returnType = innerFuncType
12421242
} else {
1243-
// Expression body - try to infer
1244-
returnType = inferNarrowType(body, false)
1243+
// Expression body - try to infer, but be conservative in union contexts
1244+
if (inUnion) {
1245+
returnType = 'unknown'
1246+
} else {
1247+
returnType = inferNarrowType(body, false)
1248+
}
12451249
}
12461250

12471251
const funcType = `${generics}${params} => ${returnType}`

test/dts.test.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import { generate } from '../src/generator'
66

77
describe('dts-generation', () => {
88
const testDir = join(__dirname, 'fixtures')
9-
const inputDir = join(testDir, 'input', 'example')
10-
const outputDir = join(testDir, 'output', 'example')
9+
const inputDir = join(testDir, 'input')
10+
const outputDir = join(testDir, 'output')
1111
const generatedDir = join(testDir, 'generated')
1212

1313
// List of all example files to test
@@ -25,11 +25,27 @@ describe('dts-generation', () => {
2525
'0011'
2626
]
2727

28+
// List of all fixture files to test (excluding checker.ts which is too large)
29+
const fixtures = [
30+
'class',
31+
'edge-cases',
32+
'enum',
33+
'exports',
34+
'function',
35+
'function-types',
36+
'imports',
37+
'interface',
38+
'module',
39+
'namespace',
40+
'type',
41+
'variable'
42+
]
43+
2844
// Generate a test for each example file
2945
examples.forEach((example) => {
3046
it(`should properly generate types for example ${example}`, async () => {
3147
const config: DtsGenerationOption = {
32-
entrypoints: [join(inputDir, `${example}.ts`)],
48+
entrypoints: [join(inputDir, 'example', `${example}.ts`)],
3349
outdir: generatedDir,
3450
clean: false,
3551
tsconfigPath: join(__dirname, '..', 'tsconfig.json'),
@@ -38,7 +54,7 @@ describe('dts-generation', () => {
3854

3955
await generate(config)
4056

41-
const outputPath = join(outputDir, `${example}.d.ts`)
57+
const outputPath = join(outputDir, 'example', `${example}.d.ts`)
4258
const generatedPath = join(generatedDir, `${example}.d.ts`)
4359

4460
const expectedContent = await Bun.file(outputPath).text()
@@ -48,6 +64,29 @@ describe('dts-generation', () => {
4864
})
4965
})
5066

67+
// Generate a test for each fixture file
68+
fixtures.forEach((fixture) => {
69+
it(`should properly generate types for fixture ${fixture}`, async () => {
70+
const config: DtsGenerationOption = {
71+
entrypoints: [join(inputDir, `${fixture}.ts`)],
72+
outdir: generatedDir,
73+
clean: false,
74+
tsconfigPath: join(__dirname, '..', 'tsconfig.json'),
75+
outputStructure: 'flat',
76+
}
77+
78+
await generate(config)
79+
80+
const outputPath = join(outputDir, `${fixture}.d.ts`)
81+
const generatedPath = join(generatedDir, `${fixture}.d.ts`)
82+
83+
const expectedContent = await Bun.file(outputPath).text()
84+
const generatedContent = await Bun.file(generatedPath).text()
85+
86+
expect(generatedContent).toBe(expectedContent)
87+
})
88+
})
89+
5190
afterEach(async () => {
5291
// Clean up generated files
5392
try {

test/fixtures/output/exports.d.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
import type { BunPlugin } from 'bun';
2-
import type { SomeOtherType } from '@stacksjs/types';
32
import { dtsConfig } from './config';
4-
import { generate, something as dts } from './generate';
5-
6-
export type { SomeOtherType }
7-
export type { BunRegisterPlugin } from 'bun'
8-
9-
export { generate, dtsConfig, type BunPlugin }
10-
export { config } from './config'
11-
12-
export * from './extract'
13-
export * from './generate'
14-
export * from './types'
15-
export * from './utils'
16-
3+
import { generate } from './generate';
4+
import type { SomeOtherType } from '@stacksjs/types';
5+
export type { SomeOtherType };
6+
export type { BunRegisterPlugin } from 'bun';
7+
export { generate, dtsConfig, type BunPlugin };
8+
export { config } from './config';
9+
export * from './extract';
10+
export * from './generate';
11+
export * from './types';
12+
export * from './utils';
1713
export default dts;

test/fixtures/output/function.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { BunPlugin } from 'bun';
22
import type { DtsGenerationOption } from '@stacksjs/dtsx';
3-
43
export declare function fetchUsers(): Promise<ResponseData>;
54
export declare function getProduct(id: number): Promise<ApiResponse<Product>>;
65
export declare function authenticate(user: string, password: string): Promise<AuthResponse>;

test/fixtures/output/imports.d.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
1-
import forge, { pki, tls } from 'node-forge';
21
import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep, toNamespacedPath } from 'node:path';
32
import { generate } from '@stacksjs/dtsx';
4-
import { something as dts } from './generate';
5-
3+
import forge, { pki, tls } from 'node-forge';
64
export declare function actionsPath(path?: string): string;
75
export declare function corePath(path?: string): string;
86
export declare function frameworkPath(path?: string, options?: { relative?: boolean, cwd?: string }): string;
97
export declare function storagePath(path?: string): string;
10-
export declare function projectPath(filePath = '', options?: { relative: boolean }): string;
8+
export declare function projectPath(filePath?: any, options?: { relative: boolean }): string;
119
export declare function userActionsPath(path?: string, options?: { relative: true }): string;
1210
export declare function builtUserActionsPath(path?: string, options?: { relative: boolean }): string;
1311
export declare function homeDir(path?: string): string;
14-
export declare type LibraryType = 'vue-components' | 'web-components' | 'functions'
1512
export declare function libraryEntryPath(type: LibraryType): string;
1613
export declare function examplesPath(type?: 'vue-components' | 'web-components'): string;
17-
18-
export { basename, forge, generate, pki, tls, delimiter, dirname, dts, extname, isAbsolute, join, normalize, relative, resolve, sep, toNamespacedPath }
14+
export declare const path: Path;
15+
export declare interface Path {
16+
actionsPath: (path?: string) => string
17+
userActionsPath: (path?: string) => string
18+
builtUserActionsPath: (path?: string, option?: { relative: boolean }) => string
19+
examplesPath: (type?: 'vue-components' | 'web-components') => string
20+
libraryEntryPath: (type: LibraryType) => string
21+
homeDir: (path?: string) => string
22+
parse: (path: string) => ParsedPath
23+
sep: () => '/' | '\\'
24+
}
25+
export type LibraryType = 'vue-components' | 'web-components' | 'functions'
26+
export { basename, forge, generate, pki, tls, delimiter, dirname, dts, extname, isAbsolute, join, normalize, relative, resolve, sep, toNamespacedPath };
27+
export default forge;

test/fixtures/output/interface.d.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,14 @@ export declare interface AuthResponse {
2121
token: string
2222
expiresIn: number
2323
}
24-
declare interface Options<T> {
25-
name: string
26-
cwd?: string
27-
defaultConfig: T
28-
}
2924
export declare interface ComplexGeneric<T extends Record<string, unknown>, K extends keyof T> {
3025
data: T
3126
key: K
3227
value: T[K]
3328
transform: (input: T[K]) => string
3429
nested: Array<Partial<T>>
3530
}
36-
export declare interface DefaultGeneric<
37-
T = string,
38-
K extends keyof any = string,
39-
V extends Record<K, T> = Record<K, T>
40-
> {
31+
export declare interface DefaultGeneric<T = string, K extends keyof any = string, V extends Record<K, T> = Record<K, T>> {
4132
key: K
4233
value: T
4334
record: V

test/fixtures/output/module.d.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
declare module '@stacksjs/some-module' {
22
interface DtsGenerationConfig {
3-
customPlugins?: Array<{
3+
customPlugins?: Array<{
44
name: string
55
transform: (code: string) => string
66
}>
7-
}
8-
7+
}
98
interface DtsGenerationResult {
10-
customPluginResults?: Record<string, string>
11-
}
9+
customPluginResults?: Record<string, string>
10+
}
1211
}

test/fixtures/output/type.d.ts

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,50 @@
11
import type { DtsGenerationOption } from '@stacksjs/dtsx';
2-
3-
export type { DtsGenerationOption }
4-
export declare type AuthStatus = 'authenticated' | 'unauthenticated'
5-
6-
export type ComplexUnionIntersection =
7-
| (User & { role: 'admin' })
2+
export type { DtsGenerationOption };
3+
export type AuthStatus = 'authenticated' | 'unauthenticated'
4+
export type ComplexUnionIntersection = | (User & { role: 'admin' })
85
| (Product & { category: string })
96
& {
107
metadata: Record<string, unknown>
118
}
12-
13-
149
export type ReadonlyDeep<T> = {
1510
readonly [P in keyof T]: T[P] extends object ? ReadonlyDeep<T[P]> : T[P]
1611
}
17-
1812
export type ConditionalResponse<T> = T extends Array<infer U>
1913
? ApiResponse<U[]>
2014
: T extends object
2115
? ApiResponse<T>
2216
: ApiResponse<string>
23-
2417
export type EventType = 'click' | 'focus' | 'blur'
2518
export type ElementType = 'button' | 'input' | 'form'
2619
export type EventHandler = `on${Capitalize<EventType>}${Capitalize<ElementType>}`
27-
2820
export type RecursiveObject = {
2921
id: string
3022
children?: RecursiveObject[]
3123
parent?: RecursiveObject
3224
metadata: Record<string, unknown>
3325
}
34-
3526
export type UserId = string & { readonly __brand: unique symbol }
3627
export type ProductId = number & {
3728
readonly __brand: unique symbol
3829
}
39-
4030
export type DeepPartial<T> = T extends object ? {
4131
[P in keyof T]?: DeepPartial<T[P]>
4232
} : T
43-
4433
export type DeepRequired<T> = T extends object ? {
4534
[P in keyof T]-?: DeepRequired<T[P]>
4635
} : T
47-
4836
export type PolymorphicComponent<P = {}> = {
4937
<C extends React.ElementType>(
5038
props: { as?: C } & Omit<React.ComponentPropsWithRef<C>, keyof P> & P
5139
): React.ReactElement | null
5240
}
53-
5441
export type DynamicRecord<K extends PropertyKey> = {
5542
[P in K]: P extends number
5643
? Array<unknown>
5744
: P extends string
5845
? Record<string, unknown>
5946
: never
6047
}
61-
6248
export type RecordMerge<T, U> = IsEmptyType<U> extends true
6349
? T
6450
: [T, U] extends [any[], any[]]

0 commit comments

Comments
 (0)