@kubb/plugin-fetch 5.0.0-beta.80 → 5.0.0-beta.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/plugin.ts +2 -1
- package/templates/fetch.ts +179 -128
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/plugin-fetch",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.81",
|
|
4
4
|
"description": "Generate a slim, type-safe HTTP client with Kubb based on the native Fetch api.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api-client",
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"registry": "https://registry.npmjs.org/"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@kubb/ast": "5.0.0-beta.
|
|
53
|
-
"@kubb/core": "5.0.0-beta.
|
|
54
|
-
"@kubb/renderer-jsx": "5.0.0-beta.
|
|
55
|
-
"@kubb/plugin-ts": "5.0.0-beta.
|
|
56
|
-
"@kubb/plugin-zod": "5.0.0-beta.
|
|
52
|
+
"@kubb/ast": "5.0.0-beta.80",
|
|
53
|
+
"@kubb/core": "5.0.0-beta.80",
|
|
54
|
+
"@kubb/renderer-jsx": "5.0.0-beta.80",
|
|
55
|
+
"@kubb/plugin-ts": "5.0.0-beta.81",
|
|
56
|
+
"@kubb/plugin-zod": "5.0.0-beta.81"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"typescript": "^6.0.3",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"@internals/utils": "0.0.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@kubb/renderer-jsx": "5.0.0-beta.
|
|
65
|
+
"@kubb/renderer-jsx": "5.0.0-beta.80"
|
|
66
66
|
},
|
|
67
67
|
"engines": {
|
|
68
68
|
"node": ">=22"
|
package/src/plugin.ts
CHANGED
|
@@ -80,6 +80,7 @@ export const pluginFetch = definePlugin<PluginFetch>((options) => {
|
|
|
80
80
|
ctx.addGenerator(...selectedGenerators)
|
|
81
81
|
|
|
82
82
|
const root = path.resolve(ctx.config.root, ctx.config.output.path)
|
|
83
|
+
const baseURLExpression = baseURL ? (baseURL.includes('${') ? `\`${baseURL.replaceAll('`', '\\`')}\`` : JSON.stringify(baseURL)) : undefined
|
|
83
84
|
|
|
84
85
|
ctx.injectFile({
|
|
85
86
|
baseName: 'serializers.ts',
|
|
@@ -91,7 +92,7 @@ export const pluginFetch = definePlugin<PluginFetch>((options) => {
|
|
|
91
92
|
baseName: 'client.ts',
|
|
92
93
|
path: path.resolve(root, '.kubb/client.ts'),
|
|
93
94
|
copy: fetchClientTemplatePath,
|
|
94
|
-
footer:
|
|
95
|
+
footer: baseURLExpression ? `client.setConfig({ baseURL: ${baseURLExpression} })` : undefined,
|
|
95
96
|
})
|
|
96
97
|
|
|
97
98
|
ctx.injectFile({
|
package/templates/fetch.ts
CHANGED
|
@@ -387,16 +387,23 @@ export async function resolveAuth(params: {
|
|
|
387
387
|
const { security, auth, headers, query } = params
|
|
388
388
|
if (!security?.length || auth === undefined) return
|
|
389
389
|
|
|
390
|
+
// An explicit caller-set header wins over the resolved token.
|
|
391
|
+
const hasHeader = (name: string) => Object.keys(headers).some((key) => key.toLowerCase() === name.toLowerCase())
|
|
392
|
+
|
|
390
393
|
for (const scheme of security) {
|
|
391
394
|
const token = typeof auth === 'function' ? await auth(scheme) : auth
|
|
392
395
|
if (token === undefined) continue
|
|
393
396
|
|
|
394
397
|
if (scheme.type === 'apiKey') {
|
|
395
398
|
const name = scheme.name ?? 'Authorization'
|
|
396
|
-
if (scheme.in === 'query')
|
|
397
|
-
|
|
398
|
-
else
|
|
399
|
-
|
|
399
|
+
if (scheme.in === 'query') {
|
|
400
|
+
if (query[name] === undefined) query[name] = token
|
|
401
|
+
} else if (scheme.in === 'cookie') {
|
|
402
|
+
headers.Cookie = [headers.Cookie, `${name}=${token}`].filter(Boolean).join('; ')
|
|
403
|
+
} else if (!hasHeader(name)) {
|
|
404
|
+
headers[name] = token
|
|
405
|
+
}
|
|
406
|
+
} else if (!hasHeader('Authorization')) {
|
|
400
407
|
headers.Authorization = scheme.scheme === 'basic' ? `Basic ${btoa(token)}` : `Bearer ${token}`
|
|
401
408
|
}
|
|
402
409
|
return
|
|
@@ -434,73 +441,80 @@ function resolveContentType(contentType: ContentType | undefined): { request?: s
|
|
|
434
441
|
}
|
|
435
442
|
|
|
436
443
|
/**
|
|
437
|
-
*
|
|
444
|
+
* The per-concern serializers for a call, the per-call serializer winning over the client's and
|
|
445
|
+
* falling back to the defaults.
|
|
438
446
|
*/
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
447
|
+
function resolveSerializers({ config, requestConfig }: { config: { serializer?: Serializers }; requestConfig: { serializer?: Serializers } }) {
|
|
448
|
+
return {
|
|
449
|
+
querySerializer: requestConfig.serializer?.query ?? config.serializer?.query ?? defaultQuerySerializer,
|
|
450
|
+
bodySerializer: requestConfig.serializer?.body ?? config.serializer?.body ?? defaultBodySerializer,
|
|
451
|
+
pathSerializer: requestConfig.serializer?.path ?? config.serializer?.path ?? defaultPathSerializer,
|
|
452
|
+
}
|
|
453
|
+
}
|
|
444
454
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
455
|
+
/**
|
|
456
|
+
* Resolves everything a call needs before it touches the transport: merged headers with the
|
|
457
|
+
* negotiated content type, auth on headers or query, serialized cookies, the validated and
|
|
458
|
+
* serialized body, and the full URL.
|
|
459
|
+
*/
|
|
460
|
+
async function resolveRequest<TBody, TRequest, TResponse>({
|
|
461
|
+
config,
|
|
462
|
+
requestConfig,
|
|
463
|
+
}: {
|
|
464
|
+
config: ClientConfig<TRequest, TResponse>
|
|
465
|
+
requestConfig: RequestConfig<TBody, TRequest, TResponse>
|
|
466
|
+
}): Promise<{ request: ResolvedRequest; codecs: Record<string, Codec> }> {
|
|
467
|
+
const { querySerializer, bodySerializer, pathSerializer } = resolveSerializers({ config, requestConfig })
|
|
468
|
+
const codecs = { ...config.codecs, ...requestConfig.codecs }
|
|
469
|
+
|
|
470
|
+
const headers = mergeHeaders(config.headers, applyHeaderStyles(requestConfig.headers, requestConfig.styles?.header))
|
|
471
|
+
const { request: requestContentTypeOption, response: responseContentType } = resolveContentType(requestConfig.contentType)
|
|
472
|
+
const requestContentType = requestContentTypeOption ?? headers['Content-Type'] ?? headers['content-type']
|
|
473
|
+
if (responseContentType && headers['Accept'] === undefined && headers['accept'] === undefined) {
|
|
474
|
+
headers['Accept'] = responseContentType
|
|
449
475
|
}
|
|
450
476
|
|
|
451
|
-
const
|
|
452
|
-
const transport = requestConfig.transport ?? config.transport ?? defaultTransport
|
|
453
|
-
const querySerializer = requestConfig.serializer?.query ?? config.serializer?.query ?? defaultQuerySerializer
|
|
454
|
-
const bodySerializer = requestConfig.serializer?.body ?? config.serializer?.body ?? defaultBodySerializer
|
|
455
|
-
const pathSerializer = requestConfig.serializer?.path ?? config.serializer?.path ?? defaultPathSerializer
|
|
456
|
-
const codecs = { ...config.codecs, ...requestConfig.codecs }
|
|
457
|
-
|
|
458
|
-
const headers = mergeHeaders(config.headers, applyHeaderStyles(requestConfig.headers, requestConfig.styles?.header))
|
|
459
|
-
const { request: requestContentTypeOption, response: responseContentType } = resolveContentType(requestConfig.contentType)
|
|
460
|
-
const requestContentType = requestContentTypeOption ?? headers['Content-Type'] ?? headers['content-type']
|
|
461
|
-
if (responseContentType && headers['Accept'] === undefined && headers['accept'] === undefined) {
|
|
462
|
-
headers['Accept'] = responseContentType
|
|
463
|
-
}
|
|
477
|
+
const query: Record<string, unknown> = { ...((requestConfig.query ?? requestConfig.params) as Record<string, unknown> | undefined) }
|
|
464
478
|
|
|
465
|
-
|
|
479
|
+
await resolveAuth({
|
|
480
|
+
security: requestConfig.security,
|
|
481
|
+
auth: requestConfig.auth ?? config.auth,
|
|
482
|
+
headers,
|
|
483
|
+
query,
|
|
484
|
+
})
|
|
466
485
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
query,
|
|
472
|
-
})
|
|
486
|
+
if (requestConfig.cookies) {
|
|
487
|
+
const cookie = serializeCookies(requestConfig.cookies, requestConfig.styles?.cookie)
|
|
488
|
+
if (cookie) headers.Cookie = [headers.Cookie, cookie].filter(Boolean).join('; ')
|
|
489
|
+
}
|
|
473
490
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
491
|
+
const validatedBody = await runValidator(requestConfig.validator?.request, requestConfig.body)
|
|
492
|
+
const requestContentTypeBase = baseContentType(requestContentType)
|
|
493
|
+
const contentCodec = requestContentTypeBase ? codecs[requestContentTypeBase] : undefined
|
|
494
|
+
const body = contentCodec?.serialize
|
|
495
|
+
? contentCodec.serialize(validatedBody, requestContentType)
|
|
496
|
+
: bodySerializer({ body: validatedBody, contentType: requestContentType, encoding: requestConfig.styles?.body })
|
|
497
|
+
// A FormData body must keep its Content-Type unset so the runtime appends the multipart boundary.
|
|
498
|
+
if (body instanceof FormData) {
|
|
499
|
+
delete headers['Content-Type']
|
|
500
|
+
delete headers['content-type']
|
|
501
|
+
} else if (requestContentTypeOption) {
|
|
502
|
+
headers['Content-Type'] = requestContentTypeOption
|
|
503
|
+
}
|
|
478
504
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
// A FormData body must keep its Content-Type unset so the runtime appends the multipart boundary.
|
|
487
|
-
if (body instanceof FormData) {
|
|
488
|
-
delete headers['Content-Type']
|
|
489
|
-
delete headers['content-type']
|
|
490
|
-
} else if (requestContentTypeOption) {
|
|
491
|
-
headers['Content-Type'] = requestContentTypeOption
|
|
492
|
-
}
|
|
493
|
-
const url = serializeUrl({
|
|
494
|
-
parts: [config.baseURL, requestConfig.baseURL, requestConfig.url],
|
|
495
|
-
pathParams: requestConfig.path ?? {},
|
|
496
|
-
search: querySerializer(query, requestConfig.styles?.query),
|
|
497
|
-
pathSerializer,
|
|
498
|
-
pathStyles: requestConfig.styles?.path,
|
|
499
|
-
})
|
|
505
|
+
const url = serializeUrl({
|
|
506
|
+
parts: [requestConfig.baseURL ?? config.baseURL, requestConfig.url],
|
|
507
|
+
pathParams: requestConfig.path ?? {},
|
|
508
|
+
search: querySerializer(query, requestConfig.styles?.query),
|
|
509
|
+
pathSerializer,
|
|
510
|
+
pathStyles: requestConfig.styles?.path,
|
|
511
|
+
})
|
|
500
512
|
|
|
501
|
-
|
|
513
|
+
const options = config.options || requestConfig.options ? { ...config.options, ...requestConfig.options } : undefined
|
|
502
514
|
|
|
503
|
-
|
|
515
|
+
return {
|
|
516
|
+
codecs,
|
|
517
|
+
request: {
|
|
504
518
|
url,
|
|
505
519
|
method: (requestConfig.method ?? 'GET').toUpperCase(),
|
|
506
520
|
headers,
|
|
@@ -509,48 +523,86 @@ export function createClientCore<TRequest = Request, TResponse = Response>(
|
|
|
509
523
|
credentials: requestConfig.credentials,
|
|
510
524
|
options,
|
|
511
525
|
responseType: requestConfig.responseType,
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
let result = await transport(resolvedRequest)
|
|
516
|
-
result = await interceptors.response.run(result)
|
|
517
|
-
|
|
518
|
-
const isSuccess = result.status >= 200 && result.status < 300
|
|
519
|
-
const throwOnError = requestConfig.throwOnError ?? config.throwOnError ?? true
|
|
520
|
-
|
|
521
|
-
const contentType = result.contentType ?? getResponseContentType(result.headers)
|
|
522
|
-
let decoded = result.data
|
|
523
|
-
if (contentType) {
|
|
524
|
-
const codec = codecs[contentType]
|
|
525
|
-
if (codec?.deserialize) decoded = await codec.deserialize(result.data, contentType)
|
|
526
|
-
}
|
|
526
|
+
},
|
|
527
|
+
}
|
|
528
|
+
}
|
|
527
529
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
530
|
+
/**
|
|
531
|
+
* Turns a transport result into the call result: decodes the body through the matching codec,
|
|
532
|
+
* validates it, and throws a `ResponseError` (after running the error interceptors) for a non-2xx
|
|
533
|
+
* response under `throwOnError`.
|
|
534
|
+
*/
|
|
535
|
+
async function settleResult<TRequest, TResponse>({
|
|
536
|
+
result,
|
|
537
|
+
codecs,
|
|
538
|
+
throwOnError,
|
|
539
|
+
validator,
|
|
540
|
+
errorInterceptors,
|
|
541
|
+
}: {
|
|
542
|
+
result: TransportResult<unknown, TRequest, TResponse>
|
|
543
|
+
codecs: Record<string, Codec>
|
|
544
|
+
throwOnError: boolean
|
|
545
|
+
validator: { response?: Validator; error?: Validator } | undefined
|
|
546
|
+
errorInterceptors: InterceptorStack<ResponseError<unknown, TRequest, TResponse>>
|
|
547
|
+
}): Promise<CallResult<TRequest, TResponse>> {
|
|
548
|
+
const isSuccess = result.status >= 200 && result.status < 300
|
|
549
|
+
const contentType = result.contentType ?? getResponseContentType(result.headers)
|
|
550
|
+
let decoded = result.data
|
|
551
|
+
if (contentType) {
|
|
552
|
+
const codec = codecs[contentType]
|
|
553
|
+
if (codec?.deserialize) decoded = await codec.deserialize(result.data, contentType)
|
|
554
|
+
}
|
|
542
555
|
|
|
543
|
-
|
|
544
|
-
const
|
|
556
|
+
if (isSuccess) {
|
|
557
|
+
const data = await runValidator(validator?.response, decoded)
|
|
558
|
+
return { status: result.status, data, error: undefined, contentType, request: result.request, response: result.response }
|
|
559
|
+
}
|
|
545
560
|
|
|
546
|
-
|
|
561
|
+
const error = await runValidator(validator?.error, decoded)
|
|
562
|
+
if (throwOnError) {
|
|
563
|
+
const responseError = new ResponseError({
|
|
564
|
+
data: error,
|
|
547
565
|
status: result.status,
|
|
548
|
-
|
|
549
|
-
error,
|
|
566
|
+
statusText: result.statusText,
|
|
550
567
|
contentType,
|
|
551
568
|
request: result.request,
|
|
552
569
|
response: result.response,
|
|
553
|
-
}
|
|
570
|
+
})
|
|
571
|
+
await errorInterceptors.run(responseError)
|
|
572
|
+
throw responseError
|
|
573
|
+
}
|
|
574
|
+
return { status: result.status, data: undefined, error, contentType, request: result.request, response: result.response }
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Builds the shared client core bound to a transport, exported by each plugin as `client` plus a `createClient` factory.
|
|
579
|
+
*/
|
|
580
|
+
export function createClientCore<TRequest = Request, TResponse = Response>(
|
|
581
|
+
options: { defaultTransport: Transport<TRequest, TResponse> } & ClientConfig<TRequest, TResponse>,
|
|
582
|
+
): ClientInstance<TRequest, TResponse> {
|
|
583
|
+
const { defaultTransport, ...initialConfig } = options
|
|
584
|
+
let config: ClientConfig<TRequest, TResponse> = { ...initialConfig }
|
|
585
|
+
|
|
586
|
+
const interceptors: Interceptors<TRequest, TResponse> = {
|
|
587
|
+
request: createInterceptorStack<ResolvedRequest>(),
|
|
588
|
+
response: createInterceptorStack<TransportResult<unknown, TRequest, TResponse>>(),
|
|
589
|
+
error: createInterceptorStack<ResponseError<unknown, TRequest, TResponse>>(),
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const client = (async <TBody = unknown>(requestConfig: RequestConfig<TBody, TRequest, TResponse>): Promise<CallResult<TRequest, TResponse>> => {
|
|
593
|
+
const transport = requestConfig.transport ?? config.transport ?? defaultTransport
|
|
594
|
+
const { request, codecs } = await resolveRequest({ config, requestConfig })
|
|
595
|
+
|
|
596
|
+
const resolvedRequest = await interceptors.request.run(request)
|
|
597
|
+
const result = await interceptors.response.run(await transport(resolvedRequest))
|
|
598
|
+
|
|
599
|
+
return settleResult({
|
|
600
|
+
result,
|
|
601
|
+
codecs,
|
|
602
|
+
throwOnError: requestConfig.throwOnError ?? config.throwOnError ?? true,
|
|
603
|
+
validator: requestConfig.validator,
|
|
604
|
+
errorInterceptors: interceptors.error,
|
|
605
|
+
})
|
|
554
606
|
}) as ClientInstance<TRequest, TResponse>
|
|
555
607
|
|
|
556
608
|
client.getConfig = () => config
|
|
@@ -559,11 +611,10 @@ export function createClientCore<TRequest = Request, TResponse = Response>(
|
|
|
559
611
|
return config
|
|
560
612
|
}
|
|
561
613
|
client.getUrl = (requestConfig) => {
|
|
562
|
-
const querySerializer =
|
|
563
|
-
const pathSerializer = requestConfig.serializer?.path ?? config.serializer?.path ?? defaultPathSerializer
|
|
614
|
+
const { querySerializer, pathSerializer } = resolveSerializers({ config, requestConfig })
|
|
564
615
|
const query: Record<string, unknown> = { ...((requestConfig.query ?? requestConfig.params) as Record<string, unknown> | undefined) }
|
|
565
616
|
return serializeUrl({
|
|
566
|
-
parts: [
|
|
617
|
+
parts: [requestConfig.baseURL ?? config.baseURL, requestConfig.url],
|
|
567
618
|
pathParams: requestConfig.path ?? {},
|
|
568
619
|
search: querySerializer(query, requestConfig.styles?.query),
|
|
569
620
|
pathSerializer,
|
|
@@ -607,7 +658,7 @@ async function parseResponse(response: Response, responseType?: ResponseType): P
|
|
|
607
658
|
case 'stream':
|
|
608
659
|
return response.body ?? undefined
|
|
609
660
|
case 'json': {
|
|
610
|
-
// An empty body with a JSON content-type would make response.json() throw
|
|
661
|
+
// An empty body with a JSON content-type would make response.json() throw, so treat it as no data.
|
|
611
662
|
const body = await response.text()
|
|
612
663
|
return body ? JSON.parse(body) : undefined
|
|
613
664
|
}
|
|
@@ -622,6 +673,34 @@ async function parseResponse(response: Response, responseType?: ResponseType): P
|
|
|
622
673
|
}
|
|
623
674
|
}
|
|
624
675
|
|
|
676
|
+
/**
|
|
677
|
+
* The default transport that sends the resolved request through `globalThis.fetch` and returns the parsed body with the native request and response.
|
|
678
|
+
*/
|
|
679
|
+
const defaultTransport: Transport = async (request: ResolvedRequest): Promise<TransportResult> => {
|
|
680
|
+
const init: RequestInit = {
|
|
681
|
+
...request.options, // cache, mode, redirect, keepalive, duplex, next, …
|
|
682
|
+
method: request.method,
|
|
683
|
+
headers: request.headers,
|
|
684
|
+
body: request.body,
|
|
685
|
+
signal: request.signal,
|
|
686
|
+
}
|
|
687
|
+
if (request.credentials) init.credentials = request.credentials
|
|
688
|
+
|
|
689
|
+
const nativeRequest = new Request(request.url, init)
|
|
690
|
+
const response = await globalThis.fetch(nativeRequest)
|
|
691
|
+
const data = await parseResponse(response, request.responseType)
|
|
692
|
+
|
|
693
|
+
return {
|
|
694
|
+
data,
|
|
695
|
+
status: response.status,
|
|
696
|
+
statusText: response.statusText,
|
|
697
|
+
headers: response.headers,
|
|
698
|
+
contentType: getResponseContentType(response.headers),
|
|
699
|
+
request: nativeRequest,
|
|
700
|
+
response,
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
625
704
|
/**
|
|
626
705
|
* One decoded Server-Sent Event, with `data` parsed as JSON when valid and kept as the raw string otherwise.
|
|
627
706
|
*/
|
|
@@ -724,34 +803,6 @@ export async function toEventStream<TData = unknown>(result: Promise<{ data: unk
|
|
|
724
803
|
}
|
|
725
804
|
}
|
|
726
805
|
|
|
727
|
-
/**
|
|
728
|
-
* The default transport that sends the resolved request through `globalThis.fetch` and returns the parsed body with the native request and response.
|
|
729
|
-
*/
|
|
730
|
-
const defaultTransport: Transport = async (request: ResolvedRequest): Promise<TransportResult> => {
|
|
731
|
-
const init: RequestInit = {
|
|
732
|
-
...request.options, // cache, mode, redirect, keepalive, duplex, next, …
|
|
733
|
-
method: request.method,
|
|
734
|
-
headers: request.headers,
|
|
735
|
-
body: request.body,
|
|
736
|
-
signal: request.signal,
|
|
737
|
-
}
|
|
738
|
-
if (request.credentials) init.credentials = request.credentials
|
|
739
|
-
|
|
740
|
-
const nativeRequest = new Request(request.url, init)
|
|
741
|
-
const response = await globalThis.fetch(nativeRequest)
|
|
742
|
-
const data = await parseResponse(response, request.responseType)
|
|
743
|
-
|
|
744
|
-
return {
|
|
745
|
-
data,
|
|
746
|
-
status: response.status,
|
|
747
|
-
statusText: response.statusText,
|
|
748
|
-
headers: response.headers,
|
|
749
|
-
contentType: getResponseContentType(response.headers),
|
|
750
|
-
request: nativeRequest,
|
|
751
|
-
response,
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
|
|
755
806
|
export const client = createClientCore({ defaultTransport })
|
|
756
807
|
|
|
757
808
|
export const createClient = (config?: Parameters<typeof client.createClient>[0]) => client.createClient(config)
|