@kubb/plugin-fetch 5.0.0-beta.81 → 5.0.0-beta.84
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 +41 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -8
- package/dist/index.js.map +1 -1
- package/package.json +5 -7
- package/src/generators/clientGenerator.tsx +2 -2
- package/src/plugin.ts +2 -2
- package/src/types.ts +1 -1
- package/templates/fetch.ts +20 -10
- package/templates/serializers.ts +4 -0
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.84",
|
|
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,20 +49,18 @@
|
|
|
49
49
|
"registry": "https://registry.npmjs.org/"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@kubb/
|
|
53
|
-
"@kubb/
|
|
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"
|
|
52
|
+
"@kubb/plugin-ts": "5.0.0-beta.84",
|
|
53
|
+
"@kubb/plugin-zod": "5.0.0-beta.84"
|
|
57
54
|
},
|
|
58
55
|
"devDependencies": {
|
|
56
|
+
"kubb": "5.0.0-beta.84",
|
|
59
57
|
"typescript": "^6.0.3",
|
|
60
58
|
"@internals/client": "0.0.0",
|
|
61
59
|
"@internals/shared": "0.0.0",
|
|
62
60
|
"@internals/utils": "0.0.0"
|
|
63
61
|
},
|
|
64
62
|
"peerDependencies": {
|
|
65
|
-
"
|
|
63
|
+
"kubb": "5.0.0-beta.84"
|
|
66
64
|
},
|
|
67
65
|
"engines": {
|
|
68
66
|
"node": ">=22"
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
type SecurityDocument,
|
|
9
9
|
} from '@internals/client'
|
|
10
10
|
import { isEventStream, operationFileEntry } from '@internals/shared'
|
|
11
|
-
import { ast, defineGenerator } from '
|
|
11
|
+
import { ast, defineGenerator } from 'kubb/kit'
|
|
12
12
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
13
13
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
14
|
-
import { File, jsxRenderer } from '
|
|
14
|
+
import { File, jsxRenderer } from 'kubb/jsx'
|
|
15
15
|
import type { PluginFetch } from '../types.ts'
|
|
16
16
|
|
|
17
17
|
/**
|
package/src/plugin.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import { createSdkGenerator, defaultMacros, isValidatorEnabled, resolverClient } from '@internals/client'
|
|
3
3
|
import { createGroupConfig } from '@internals/shared'
|
|
4
|
-
import { definePlugin } from '
|
|
4
|
+
import { definePlugin } from 'kubb/kit'
|
|
5
5
|
import { pluginTsName } from '@kubb/plugin-ts'
|
|
6
6
|
import { pluginZodName } from '@kubb/plugin-zod'
|
|
7
7
|
import { clientGenerator } from './generators/clientGenerator.tsx'
|
|
@@ -22,7 +22,7 @@ export const pluginFetchName = 'plugin-fetch' satisfies PluginFetch['name']
|
|
|
22
22
|
*
|
|
23
23
|
* @example
|
|
24
24
|
* ```ts
|
|
25
|
-
* import { defineConfig } from 'kubb'
|
|
25
|
+
* import { defineConfig } from 'kubb/config'
|
|
26
26
|
* import { pluginTs } from '@kubb/plugin-ts'
|
|
27
27
|
* import { pluginFetch } from '@kubb/plugin-fetch'
|
|
28
28
|
*
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PluginFactoryOptions } from '
|
|
1
|
+
import type { PluginFactoryOptions } from 'kubb/kit'
|
|
2
2
|
import type { Options, ResolvedOptions, ResolverClient } from '@internals/client'
|
|
3
3
|
|
|
4
4
|
export type { Options, ResolvedOptions, ResolverClient } from '@internals/client'
|
package/templates/fetch.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyHeaderStyles, defaultBodySerializer, defaultPathSerializer, defaultQuerySerializer, serializeCookies } from './serializers'
|
|
1
|
+
import { applyHeaderStyles, defaultBodySerializer, defaultPathSerializer, defaultQuerySerializer, isDefaultJsonBody, serializeCookies } from './serializers'
|
|
2
2
|
import type { HeadersInit, PathParamStyle, PathSerializer, Serializers, Styles } from './serializers'
|
|
3
3
|
import { type StandardSchemaValidator, validateStandardSchema } from './standardSchema.ts'
|
|
4
4
|
|
|
@@ -323,6 +323,15 @@ function mergeHeaders(...sources: Array<HeadersInit | undefined>): Record<string
|
|
|
323
323
|
return Object.assign({}, ...sources.map(serializeHeaders))
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
+
function getHeader(headers: Record<string, string>, name: string): string | undefined {
|
|
327
|
+
const key = Object.keys(headers).find((k) => k.toLowerCase() === name.toLowerCase())
|
|
328
|
+
return key ? headers[key] : undefined
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function hasHeader(headers: Record<string, string>, name: string): boolean {
|
|
332
|
+
return Object.keys(headers).some((k) => k.toLowerCase() === name.toLowerCase())
|
|
333
|
+
}
|
|
334
|
+
|
|
326
335
|
/**
|
|
327
336
|
* Joins the URL parts, interpolates URL-encoded `{param}` segments, and appends the serialized query, shared by the send path and `getUrl`.
|
|
328
337
|
*/
|
|
@@ -387,9 +396,6 @@ export async function resolveAuth(params: {
|
|
|
387
396
|
const { security, auth, headers, query } = params
|
|
388
397
|
if (!security?.length || auth === undefined) return
|
|
389
398
|
|
|
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
|
-
|
|
393
399
|
for (const scheme of security) {
|
|
394
400
|
const token = typeof auth === 'function' ? await auth(scheme) : auth
|
|
395
401
|
if (token === undefined) continue
|
|
@@ -400,10 +406,10 @@ export async function resolveAuth(params: {
|
|
|
400
406
|
if (query[name] === undefined) query[name] = token
|
|
401
407
|
} else if (scheme.in === 'cookie') {
|
|
402
408
|
headers.Cookie = [headers.Cookie, `${name}=${token}`].filter(Boolean).join('; ')
|
|
403
|
-
} else if (!hasHeader(name)) {
|
|
409
|
+
} else if (!hasHeader(headers, name)) {
|
|
404
410
|
headers[name] = token
|
|
405
411
|
}
|
|
406
|
-
} else if (!hasHeader('Authorization')) {
|
|
412
|
+
} else if (!hasHeader(headers, 'Authorization')) {
|
|
407
413
|
headers.Authorization = scheme.scheme === 'basic' ? `Basic ${btoa(token)}` : `Bearer ${token}`
|
|
408
414
|
}
|
|
409
415
|
return
|
|
@@ -469,8 +475,8 @@ async function resolveRequest<TBody, TRequest, TResponse>({
|
|
|
469
475
|
|
|
470
476
|
const headers = mergeHeaders(config.headers, applyHeaderStyles(requestConfig.headers, requestConfig.styles?.header))
|
|
471
477
|
const { request: requestContentTypeOption, response: responseContentType } = resolveContentType(requestConfig.contentType)
|
|
472
|
-
const requestContentType = requestContentTypeOption ?? headers
|
|
473
|
-
if (responseContentType && headers
|
|
478
|
+
const requestContentType = requestContentTypeOption ?? getHeader(headers, 'content-type')
|
|
479
|
+
if (responseContentType && !hasHeader(headers, 'accept')) {
|
|
474
480
|
headers['Accept'] = responseContentType
|
|
475
481
|
}
|
|
476
482
|
|
|
@@ -491,15 +497,19 @@ async function resolveRequest<TBody, TRequest, TResponse>({
|
|
|
491
497
|
const validatedBody = await runValidator(requestConfig.validator?.request, requestConfig.body)
|
|
492
498
|
const requestContentTypeBase = baseContentType(requestContentType)
|
|
493
499
|
const contentCodec = requestContentTypeBase ? codecs[requestContentTypeBase] : undefined
|
|
500
|
+
const usesDefaultBodySerializer = !contentCodec?.serialize && bodySerializer === defaultBodySerializer
|
|
494
501
|
const body = contentCodec?.serialize
|
|
495
502
|
? contentCodec.serialize(validatedBody, requestContentType)
|
|
496
503
|
: bodySerializer({ body: validatedBody, contentType: requestContentType, encoding: requestConfig.styles?.body })
|
|
497
504
|
// A FormData body must keep its Content-Type unset so the runtime appends the multipart boundary.
|
|
498
505
|
if (body instanceof FormData) {
|
|
499
|
-
|
|
500
|
-
|
|
506
|
+
for (const key of Object.keys(headers)) {
|
|
507
|
+
if (key.toLowerCase() === 'content-type') delete headers[key]
|
|
508
|
+
}
|
|
501
509
|
} else if (requestContentTypeOption) {
|
|
502
510
|
headers['Content-Type'] = requestContentTypeOption
|
|
511
|
+
} else if (usesDefaultBodySerializer && isDefaultJsonBody(validatedBody) && !hasHeader(headers, 'content-type')) {
|
|
512
|
+
headers['Content-Type'] = 'application/json'
|
|
503
513
|
}
|
|
504
514
|
|
|
505
515
|
const url = serializeUrl({
|
package/templates/serializers.ts
CHANGED
|
@@ -122,6 +122,10 @@ function isFormBody(body: unknown): body is BodyInit {
|
|
|
122
122
|
)
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
export function isDefaultJsonBody(body: unknown): boolean {
|
|
126
|
+
return body !== undefined && body !== null && !isFormBody(body)
|
|
127
|
+
}
|
|
128
|
+
|
|
125
129
|
function appendFormDataValue({ formData, key, value, contentType }: { formData: FormData; key: string; value: unknown; contentType?: string }): void {
|
|
126
130
|
if (value === undefined || value === null) return
|
|
127
131
|
if (value instanceof Blob) formData.append(key, value)
|