|
| 1 | +import type { Interceptor } from '@orpc/shared' |
1 | 2 | import type { StandardLazyResponse, StandardRequest } from '@orpc/standard-server' |
2 | 3 | import type { ToFetchRequestOptions } from '@orpc/standard-server-fetch' |
3 | 4 | import type { ClientContext, ClientOptions } from '../../types' |
4 | 5 | import type { StandardLinkClient } from '../standard' |
| 6 | +import type { LinkFetchPlugin } from './plugin' |
| 7 | +import { intercept, toArray } from '@orpc/shared' |
5 | 8 | import { toFetchRequest, toStandardLazyResponse } from '@orpc/standard-server-fetch' |
| 9 | +import { CompositeLinkFetchPlugin } from './plugin' |
| 10 | + |
| 11 | +export interface LinkFetchInterceptorOptions<T extends ClientContext> extends ClientOptions<T> { |
| 12 | + request: Request |
| 13 | + init: { redirect?: Request['redirect'] } |
| 14 | + path: readonly string[] |
| 15 | + input: unknown |
| 16 | +} |
6 | 17 |
|
7 | 18 | export interface LinkFetchClientOptions<T extends ClientContext> extends ToFetchRequestOptions { |
8 | 19 | fetch?: ( |
9 | 20 | request: Request, |
10 | | - init: { redirect?: Request['redirect'] }, |
| 21 | + init: LinkFetchInterceptorOptions<T>['init'], |
11 | 22 | options: ClientOptions<T>, |
12 | 23 | path: readonly string[], |
13 | 24 | input: unknown, |
14 | 25 | ) => Promise<Response> |
| 26 | + |
| 27 | + adapterInterceptors?: Interceptor<LinkFetchInterceptorOptions<T>, Promise<Response>>[] |
| 28 | + |
| 29 | + plugins?: LinkFetchPlugin<T>[] |
15 | 30 | } |
16 | 31 |
|
17 | 32 | export class LinkFetchClient<T extends ClientContext> implements StandardLinkClient<T> { |
18 | 33 | private readonly fetch: Exclude<LinkFetchClientOptions<T>['fetch'], undefined> |
19 | 34 | private readonly toFetchRequestOptions: ToFetchRequestOptions |
| 35 | + private readonly adapterInterceptors: Exclude<LinkFetchClientOptions<T>['adapterInterceptors'], undefined> |
20 | 36 |
|
21 | 37 | constructor(options: LinkFetchClientOptions<T>) { |
22 | | - this.fetch = options?.fetch ?? globalThis.fetch.bind(globalThis) |
| 38 | + const plugin = new CompositeLinkFetchPlugin(options.plugins) |
| 39 | + |
| 40 | + plugin.initRuntimeAdapter(options) |
| 41 | + |
| 42 | + this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis) |
23 | 43 | this.toFetchRequestOptions = options |
| 44 | + this.adapterInterceptors = toArray(options.adapterInterceptors) |
24 | 45 | } |
25 | 46 |
|
26 | | - async call(request: StandardRequest, options: ClientOptions<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse> { |
27 | | - const fetchRequest = toFetchRequest(request, this.toFetchRequestOptions) |
| 47 | + async call(standardRequest: StandardRequest, options: ClientOptions<T>, path: readonly string[], input: unknown): Promise<StandardLazyResponse> { |
| 48 | + const request = toFetchRequest(standardRequest, this.toFetchRequestOptions) |
28 | 49 |
|
29 | | - const fetchResponse = await this.fetch(fetchRequest, { redirect: 'manual' }, options, path, input) |
| 50 | + const fetchResponse = await intercept( |
| 51 | + this.adapterInterceptors, |
| 52 | + { ...options, request, path, input, init: { redirect: 'manual' } }, |
| 53 | + ({ request, path, input, init, ...options }) => this.fetch(request, init, options, path, input), |
| 54 | + ) |
30 | 55 |
|
31 | | - const lazyResponse = toStandardLazyResponse(fetchResponse, { signal: fetchRequest.signal }) |
| 56 | + const lazyResponse = toStandardLazyResponse(fetchResponse, { signal: request.signal }) |
32 | 57 |
|
33 | 58 | return lazyResponse |
34 | 59 | } |
|
0 commit comments