@kubb/plugin-fetch 5.12.0-canary.20261105T092614 → 5.12.0

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 CHANGED
@@ -1511,7 +1511,7 @@ var compatibility = {
1511
1511
  "node": ">=22.22"
1512
1512
  };
1513
1513
  // package.json
1514
- var version = "5.12.0-canary.20261105T092614";
1514
+ var version = "5.12.0";
1515
1515
  // src/templates.ts
1516
1516
  /** Absolute path to the fetch client template, copied into `.kubb/client.ts`. */
1517
1517
  const fetchClientTemplatePath = (0, node_url.fileURLToPath)(new URL("../templates/fetch.ts", require("url").pathToFileURL(__filename).href));
package/dist/index.js CHANGED
@@ -1485,7 +1485,7 @@ var compatibility = {
1485
1485
  "node": ">=22.22"
1486
1486
  };
1487
1487
  // package.json
1488
- var version = "5.12.0-canary.20261105T092614";
1488
+ var version = "5.12.0";
1489
1489
  // src/templates.ts
1490
1490
  /** Absolute path to the fetch client template, copied into `.kubb/client.ts`. */
1491
1491
  const fetchClientTemplatePath = fileURLToPath(new URL("../templates/fetch.ts", import.meta.url));
@@ -169,6 +169,17 @@ export type ValidationErrorHandler = (error: ParseError, context: ValidationErro
169
169
  } | void | Promise<{
170
170
  value: unknown;
171
171
  } | void>;
172
+ /**
173
+ * Turns generated validation on or off. `false` skips every validator, an object skips only the directions set to `false`:
174
+ * `request` is the body, `params` are path, query, and header params, `response` and `error` are the response bodies.
175
+ * @default true
176
+ */
177
+ export type ValidateOption = boolean | {
178
+ request?: boolean;
179
+ params?: boolean;
180
+ response?: boolean;
181
+ error?: boolean;
182
+ };
172
183
  /**
173
184
  * A resolved security scheme carried on each generated call's `security` array and passed to the `auth` resolver.
174
185
  */
@@ -223,6 +234,7 @@ export type RequestConfig<TBody = unknown, TRequest = Request, TResponse = Respo
223
234
  error?: Validator;
224
235
  };
225
236
  onValidationError?: ValidationErrorHandler;
237
+ validate?: ValidateOption;
226
238
  security?: Array<Auth>;
227
239
  auth?: AuthResolver;
228
240
  };
@@ -246,6 +258,7 @@ export type ClientConfig<TRequest = Request, TResponse = Response> = {
246
258
  serializer?: Serializers;
247
259
  codecs?: Record<string, Codec>;
248
260
  onValidationError?: ValidationErrorHandler;
261
+ validate?: ValidateOption;
249
262
  auth?: AuthResolver;
250
263
  };
251
264
  /**
@@ -116,3 +116,21 @@ A `ParseError` reports schema validation issues. A `ResponseError` reports a non
116
116
 
117
117
  Calling `.unwrap()` on a `throwOnError: false` call turns that same `error` into a rejection, so a
118
118
  `try`/`catch` works there too.
119
+
120
+ ## Turn validation off at runtime
121
+
122
+ The `validator` option decides at generation time which schemas each call carries. Set `validate` on the client to skip them at runtime, for example in production or in tests with partial fixtures:
123
+
124
+ ```typescript
125
+ import { client } from './gen/.kubb/client'
126
+
127
+ client.setConfig({ validate: import.meta.env.DEV })
128
+ ```
129
+
130
+ `validate: false` skips every schema. An object skips only the directions set to `false`: `request` (the body), `params` (path, query, and header params), `response`, and `error`:
131
+
132
+ ```typescript
133
+ client.setConfig({ validate: { response: false } })
134
+ ```
135
+
136
+ A per-call `validate` overrides the client setting, such as `getPetById({ path: { petId: 1 }, validate: true })`. The default is `true`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/plugin-fetch",
3
- "version": "5.12.0-canary.20261105T092614",
3
+ "version": "5.12.0",
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",
@@ -81,13 +81,13 @@
81
81
  },
82
82
  "dependencies": {
83
83
  "@kubb/kit": "^5.15.4",
84
- "@kubb/plugin-ts": "^5.5.0-canary.20261105T092614",
85
- "@kubb/plugin-zod": "^5.9.0-canary.20261105T092614",
84
+ "@kubb/plugin-ts": "^5.4.0",
85
+ "@kubb/plugin-zod": "^5.8.1",
86
86
  "@kubb/renderer-jsx": "^5.15.4"
87
87
  },
88
88
  "devDependencies": {
89
- "@internals/client": "0.1.0-canary.20261105T092614",
90
- "@internals/shared": "0.1.0-canary.20261105T092614",
89
+ "@internals/client": "0.0.0",
90
+ "@internals/shared": "0.0.0",
91
91
  "typescript": "^7.0.2"
92
92
  },
93
93
  "peerDependencies": {},
@@ -168,6 +168,13 @@ export type ValidationErrorContext = {
168
168
  */
169
169
  export type ValidationErrorHandler = (error: ParseError, context: ValidationErrorContext) => { value: unknown } | void | Promise<{ value: unknown } | void>
170
170
 
171
+ /**
172
+ * Turns generated validation on or off. `false` skips every validator, an object skips only the directions set to `false`:
173
+ * `request` is the body, `params` are path, query, and header params, `response` and `error` are the response bodies.
174
+ * @default true
175
+ */
176
+ export type ValidateOption = boolean | { request?: boolean; params?: boolean; response?: boolean; error?: boolean }
177
+
171
178
  /**
172
179
  * A resolved security scheme carried on each generated call's `security` array and passed to the `auth` resolver.
173
180
  */
@@ -217,6 +224,7 @@ export type RequestConfig<TBody = unknown, TRequest = Request, TResponse = Respo
217
224
  codecs?: Record<string, Codec>
218
225
  validator?: { request?: Validator; path?: Validator; query?: Validator; headers?: Validator; response?: Validator; error?: Validator }
219
226
  onValidationError?: ValidationErrorHandler
227
+ validate?: ValidateOption
220
228
  security?: Array<Auth>
221
229
  auth?: AuthResolver
222
230
  }
@@ -246,6 +254,7 @@ export type ClientConfig<TRequest = Request, TResponse = Response> = {
246
254
  serializer?: Serializers
247
255
  codecs?: Record<string, Codec>
248
256
  onValidationError?: ValidationErrorHandler
257
+ validate?: ValidateOption
249
258
  auth?: AuthResolver
250
259
  }
251
260
 
@@ -493,6 +502,10 @@ export async function resolveAuth(params: {
493
502
  }
494
503
  }
495
504
 
505
+ function isValidationEnabled(validate: ValidateOption | undefined, direction: 'request' | 'params' | 'response' | 'error'): boolean {
506
+ return typeof validate === 'object' ? validate[direction] !== false : validate !== false
507
+ }
508
+
496
509
  async function runValidator<T>({
497
510
  validator,
498
511
  value,
@@ -540,10 +553,11 @@ async function resolveRequest<TBody, TRequest, TResponse>({
540
553
  }: {
541
554
  config: ClientConfig<TRequest, TResponse>
542
555
  requestConfig: RequestConfig<TBody, TRequest, TResponse>
543
- }): Promise<{ request: ResolvedRequest; codecs: Record<string, Codec> }> {
556
+ }): Promise<{ request: ResolvedRequest; codecs: Record<string, Codec>; validate: ValidateOption | undefined }> {
544
557
  const { querySerializer, bodySerializer, pathSerializer } = resolveSerializers({ config, requestConfig })
545
558
  const codecs = { ...config.codecs, ...requestConfig.codecs }
546
559
  const onValidationError = requestConfig.onValidationError ?? config.onValidationError
560
+ const validate = requestConfig.validate ?? config.validate
547
561
  const validationContext = { direction: 'request', method: requestConfig.method, url: requestConfig.url } as const
548
562
 
549
563
  // Params are encoded before anything reads them: headers before styling, query before auth adds its values.
@@ -554,7 +568,12 @@ async function resolveRequest<TBody, TRequest, TResponse>({
554
568
  }
555
569
  const [validatedPath, validatedQuery, validatedHeaders] = await Promise.all(
556
570
  (['path', 'query', 'headers'] as const).map((source) =>
557
- runValidator({ validator: requestConfig.validator?.[source], value: paramValues[source], context: { ...validationContext, source }, onValidationError }),
571
+ runValidator({
572
+ validator: isValidationEnabled(validate, 'params') ? requestConfig.validator?.[source] : undefined,
573
+ value: paramValues[source],
574
+ context: { ...validationContext, source },
575
+ onValidationError,
576
+ }),
558
577
  ),
559
578
  )
560
579
 
@@ -581,7 +600,7 @@ async function resolveRequest<TBody, TRequest, TResponse>({
581
600
  }
582
601
 
583
602
  const validatedBody = await runValidator({
584
- validator: requestConfig.validator?.request,
603
+ validator: isValidationEnabled(validate, 'request') ? requestConfig.validator?.request : undefined,
585
604
  value: requestConfig.body,
586
605
  context: { ...validationContext, source: 'body' },
587
606
  onValidationError,
@@ -615,6 +634,7 @@ async function resolveRequest<TBody, TRequest, TResponse>({
615
634
 
616
635
  return {
617
636
  codecs,
637
+ validate,
618
638
  request: {
619
639
  url,
620
640
  method: (requestConfig.method ?? 'GET').toUpperCase(),
@@ -645,7 +665,7 @@ export function createClientCore<TRequest = Request, TResponse = Response>(
645
665
 
646
666
  const client = (async <TBody = unknown>(requestConfig: RequestConfig<TBody, TRequest, TResponse>): Promise<CallResult<TRequest, TResponse>> => {
647
667
  const transport = requestConfig.transport ?? config.transport ?? defaultTransport
648
- const { request, codecs } = await resolveRequest({ config, requestConfig })
668
+ const { request, codecs, validate } = await resolveRequest({ config, requestConfig })
649
669
 
650
670
  const resolvedRequest = await interceptors.request.run(request, requestConfig)
651
671
  const result = await interceptors.response.run(await transport(resolvedRequest), requestConfig)
@@ -654,13 +674,14 @@ export function createClientCore<TRequest = Request, TResponse = Response>(
654
674
  const validator = requestConfig.validator
655
675
  const onValidationError = requestConfig.onValidationError ?? config.onValidationError
656
676
  const isSuccess = result.status >= 200 && result.status < 300
677
+ const direction = isSuccess ? 'response' : 'error'
657
678
  const contentType = result.contentType ?? getResponseContentType(result.headers)
658
679
  const codec = contentType ? codecs[contentType] : undefined
659
680
  const decoded = contentType && codec?.deserialize ? await codec.deserialize(result.data, contentType) : result.data
660
681
  const data = await runValidator({
661
- validator: isSuccess ? validator?.response : validator?.error,
682
+ validator: isValidationEnabled(validate, direction) ? validator?.[direction] : undefined,
662
683
  value: decoded,
663
- context: { direction: isSuccess ? 'response' : 'error', source: 'body', method: resolvedRequest.method, url: resolvedRequest.url, status: result.status },
684
+ context: { direction, source: 'body', method: resolvedRequest.method, url: resolvedRequest.url, status: result.status },
664
685
  onValidationError,
665
686
  })
666
687
  if (!isSuccess && throwOnError) {