(
options: Omit<UseGenerationOptions<TInput, TResult>, 'onResult'> & {
onResult?: (result: TResult) => TTransformed
},
)
| 104 | // default, leaving the parameter `any` — a hard error under `strict`. See |
| 105 | // issue #848. |
| 106 | export function useGeneration< |
| 107 | TInput extends Record<string, any>, |
| 108 | TResult, |
| 109 | TTransformed = void, |
| 110 | >( |
| 111 | options: Omit<UseGenerationOptions<TInput, TResult>, 'onResult'> & { |
| 112 | onResult?: (result: TResult) => TTransformed |
| 113 | }, |
| 114 | ): UseGenerationReturn<InferGenerationOutputFromReturn<TResult, TTransformed>> { |
| 115 | type TOutput = InferGenerationOutputFromReturn<TResult, TTransformed> |
| 116 | const hookId = createUniqueId() |
| 117 | const clientId = options.id || hookId |
| 118 | |
| 119 | const [result, setResult] = createSignal<TOutput | null>(null) |
| 120 | const [isLoading, setIsLoading] = createSignal(false) |
| 121 | const [error, setError] = createSignal<Error | undefined>(undefined) |
| 122 | const [status, setStatus] = createSignal<GenerationClientState>('idle') |
| 123 | |
| 124 | const client = createMemo(() => { |
| 125 | // Conditional spread on `body`: `GenerationClientOptions.body` is a |
| 126 | // strict optional (`body?: Record<string, any>`) and EOPT forbids |
| 127 | // assigning the source `T | undefined` directly. |
| 128 | const clientOptions: GenerationClientOptions<TInput, TResult, TOutput> = { |
| 129 | id: clientId, |
| 130 | body: options.body, |
| 131 | devtoolsBridgeFactory: createGenerationDevtoolsBridge, |
| 132 | devtools: { |
| 133 | ...options.devtools, |
| 134 | framework: 'solid', |
| 135 | hookName: 'useGeneration', |
| 136 | }, |
| 137 | // The transform's raw return type (`TTransformed`) and the stored output |
| 138 | // (`TOutput`, with null/void/undefined stripped) are identical at runtime; |
| 139 | // the cast bridges the relationship that the conditional type hides. |
| 140 | onResult: ((r: TResult) => options.onResult?.(r)) as ( |
| 141 | result: TResult, |
| 142 | ) => TOutput | null | void, |
| 143 | onError: (e: Error) => options.onError?.(e), |
| 144 | onProgress: (p: number, m?: string) => options.onProgress?.(p, m), |
| 145 | onChunk: (c: StreamChunk) => options.onChunk?.(c), |
| 146 | onResultChange: setResult, |
| 147 | onLoadingChange: setIsLoading, |
| 148 | onErrorChange: setError, |
| 149 | onStatusChange: setStatus, |
| 150 | } |
| 151 | |
| 152 | if (options.connection) { |
| 153 | return new GenerationClient<TInput, TResult, TOutput>({ |
| 154 | ...clientOptions, |
| 155 | connection: options.connection, |
| 156 | }) |
| 157 | } |
| 158 | |
| 159 | if (options.fetcher) { |
| 160 | return new GenerationClient<TInput, TResult, TOutput>({ |
| 161 | ...clientOptions, |
| 162 | fetcher: options.fetcher, |
| 163 | }) |
no test coverage detected