@kubb/plugin-fetch 5.9.0-canary.20261024T190549 → 5.9.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.d.cts CHANGED
@@ -2,16 +2,17 @@ import { Exclude, Group, Include, Output, OutputOptions, Override, PluginType, R
2
2
  import "@kubb/plugin-zod";
3
3
  //#region ../../internals/client/src/types.d.ts
4
4
  /**
5
- * Validator applied to request and response bodies using schemas from `@kubb/plugin-zod`.
5
+ * Validator applied to the request and response using schemas from `@kubb/plugin-zod`.
6
6
  * - `false`: no validation.
7
7
  * - `'zod'`: validates the success (2xx) response body, and the error body when a non-2xx call does
8
8
  * not throw (`throwOnError: false`).
9
- * - `{ request?: 'zod'; response?: 'zod' }`: opt in per direction. `request` validates the request
10
- * body before the call; `response` validates the success response body and,
11
- * on the non-throw path, the error body.
9
+ * - `{ request?: 'zod'; params?: 'zod'; response?: 'zod' }`: opt in per slot. `request` encodes the
10
+ * request body before the call; `params` validate the path, query, and header params;
11
+ * `response` validates the success response body and, on the non-throw path, the error body.
12
12
  */
13
13
  type ValidatorOptions = false | 'zod' | {
14
14
  request?: 'zod';
15
+ params?: 'zod';
15
16
  response?: 'zod';
16
17
  };
17
18
  /**
@@ -86,7 +87,7 @@ type Options = OutputOptions & {
86
87
  */
87
88
  throwOnErrorDefault?: boolean;
88
89
  /**
89
- * Validate request and response bodies with schemas from `@kubb/plugin-zod`.
90
+ * Validate the request body, the request params, and the response with schemas from `@kubb/plugin-zod`.
90
91
  *
91
92
  * @default false
92
93
  */
package/dist/index.d.ts CHANGED
@@ -2,16 +2,17 @@ import { Exclude, Group, Include, Output, OutputOptions, Override, PluginType, R
2
2
  import "@kubb/plugin-zod";
3
3
  //#region ../../internals/client/src/types.d.ts
4
4
  /**
5
- * Validator applied to request and response bodies using schemas from `@kubb/plugin-zod`.
5
+ * Validator applied to the request and response using schemas from `@kubb/plugin-zod`.
6
6
  * - `false`: no validation.
7
7
  * - `'zod'`: validates the success (2xx) response body, and the error body when a non-2xx call does
8
8
  * not throw (`throwOnError: false`).
9
- * - `{ request?: 'zod'; response?: 'zod' }`: opt in per direction. `request` validates the request
10
- * body before the call; `response` validates the success response body and,
11
- * on the non-throw path, the error body.
9
+ * - `{ request?: 'zod'; params?: 'zod'; response?: 'zod' }`: opt in per slot. `request` encodes the
10
+ * request body before the call; `params` validate the path, query, and header params;
11
+ * `response` validates the success response body and, on the non-throw path, the error body.
12
12
  */
13
13
  type ValidatorOptions = false | 'zod' | {
14
14
  request?: 'zod';
15
+ params?: 'zod';
15
16
  response?: 'zod';
16
17
  };
17
18
  /**
@@ -86,7 +87,7 @@ type Options = OutputOptions & {
86
87
  */
87
88
  throwOnErrorDefault?: boolean;
88
89
  /**
89
- * Validate request and response bodies with schemas from `@kubb/plugin-zod`.
90
+ * Validate the request body, the request params, and the response with schemas from `@kubb/plugin-zod`.
90
91
  *
91
92
  * @default false
92
93
  */
package/dist/index.js CHANGED
@@ -446,7 +446,7 @@ function createGroupConfig(group) {
446
446
  function isValidatorEnabled(validator) {
447
447
  if (!validator) return false;
448
448
  if (validator === "zod") return true;
449
- return Boolean(validator.request || validator.response);
449
+ return Boolean(validator.request || validator.params || validator.response);
450
450
  }
451
451
  /**
452
452
  * Returns `'zod'` when request body parsing is enabled, `null` otherwise. The string shorthand
@@ -457,6 +457,14 @@ function resolveRequestValidator(validator) {
457
457
  return validator.request ?? null;
458
458
  }
459
459
  /**
460
+ * Returns `'zod'` when path, query, and header params parsing is enabled, `null` otherwise. Only the
461
+ * object form `{ params: 'zod' }` enables it.
462
+ */
463
+ function resolveParamsValidator(validator) {
464
+ if (!validator || validator === "zod") return null;
465
+ return validator.params ?? null;
466
+ }
467
+ /**
460
468
  * Returns `'zod'` when response parsing is enabled, `null` otherwise. The string shorthand `'zod'`
461
469
  * maps to response parsing.
462
470
  */
@@ -475,30 +483,6 @@ function buildZodErrorParse(node, zodResolver) {
475
483
  return zodResolver.response.error?.(node) || null;
476
484
  }
477
485
  //#endregion
478
- //#region ../../internals/client/src/builders/validator.ts
479
- /**
480
- * Builds the validator-hook references for one operation. Request validation runs before the send;
481
- * response validation runs on the success body only. Returns `null` references when the matching
482
- * direction is disabled or the schema is absent.
483
- */
484
- function buildValidatorHooks({ node, validator, zodResolver }) {
485
- const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
486
- const parsesResponse = zodResolver && resolveResponseValidator(validator) === "zod";
487
- const response = parsesResponse ? zodResolver.response.response(node) || null : null;
488
- const error = parsesResponse ? buildZodErrorParse(node, zodResolver) : null;
489
- const request = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) || null : null;
490
- return {
491
- request,
492
- response,
493
- error,
494
- importedZodNames: [
495
- response,
496
- error,
497
- request
498
- ].filter((name) => Boolean(name))
499
- };
500
- }
501
- //#endregion
502
486
  //#region ../../internals/client/src/builders/security.ts
503
487
  function serializeAuth(auth) {
504
488
  const parts = [`type: '${auth.type}'`];
@@ -571,6 +555,49 @@ function buildSecurityMetadata({ security }) {
571
555
  return `[${security.map(serializeAuth).join(", ")}]`;
572
556
  }
573
557
  //#endregion
558
+ //#region ../../internals/client/src/builders/validator.ts
559
+ /**
560
+ * Builds the validator-hook references for one operation. Request body and params validation run before the send.
561
+ * Response validation runs on the success body only. Returns `null` references when the matching
562
+ * direction is disabled or the schema is absent.
563
+ */
564
+ function buildValidatorHooks({ node, validator, zodResolver }) {
565
+ const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
566
+ const parsesResponse = zodResolver && resolveResponseValidator(validator) === "zod";
567
+ const response = parsesResponse ? zodResolver.response.response(node) || null : null;
568
+ const error = parsesResponse ? buildZodErrorParse(node, zodResolver) : null;
569
+ const request = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) || null : null;
570
+ const paramGroups = getOperationParameters(node);
571
+ const resolveParamsName = (kind, params) => zodResolver && resolveParamsValidator(validator) === "zod" && params.length > 0 ? zodResolver.param[kind](node, params[0]) : null;
572
+ const path = resolveParamsName("path", paramGroups.path);
573
+ const query = resolveParamsName("query", paramGroups.query);
574
+ const headers = resolveParamsName("headers", paramGroups.header);
575
+ const importedZodNames = [
576
+ response,
577
+ error,
578
+ request,
579
+ path,
580
+ query,
581
+ headers
582
+ ].filter((name) => Boolean(name));
583
+ return {
584
+ request,
585
+ path,
586
+ query,
587
+ headers: headers ? `toHeadersStandardSchema(${headers}, ${headers}.shape)` : null,
588
+ response,
589
+ error,
590
+ importedZodNames
591
+ };
592
+ }
593
+ /**
594
+ * Prints the `validator: { … }` entry of a call config from the hooks named in `keys`, or `null` when none is set.
595
+ */
596
+ function buildValidatorLiteral(hooks, keys) {
597
+ const entries = keys.flatMap((key) => hooks?.[key] ? [`${key}: ${hooks[key]}`] : []);
598
+ return entries.length ? `validator: { ${entries.join(", ")} }` : null;
599
+ }
600
+ //#endregion
574
601
  //#region ../../internals/client/src/builders/contentType.ts
575
602
  /**
576
603
  * Builds the `contentType` entry baked into the call config, or `null` for the JSON default.
@@ -775,12 +802,14 @@ function Operation({ name, node, types, zodResolver, validator, returnType, thro
775
802
  const eventStream = isEventStream(node);
776
803
  const responseType = getResponseType(node);
777
804
  const responseTypeLiteral = responseType ? `responseType: '${responseType}'` : null;
778
- const validatorEntries = [
779
- validators.request ? `request: ${validators.request}` : null,
780
- validators.response ? `response: ${validators.response}` : null,
781
- validators.error ? `error: ${validators.error}` : null
782
- ].filter(Boolean);
783
- const validatorLiteral = validatorEntries.length ? `validator: { ${validatorEntries.join(", ")} }` : null;
805
+ const validatorLiteral = buildValidatorLiteral(validators, [
806
+ "request",
807
+ "path",
808
+ "query",
809
+ "headers",
810
+ "response",
811
+ "error"
812
+ ]);
784
813
  const callConfig = `{ ${[
785
814
  `method: '${node.method.toUpperCase()}'`,
786
815
  `url: '${node.path}'`,
@@ -892,14 +921,15 @@ function createClientGenerator(name, resolveClientPath) {
892
921
  const { config, driver, resolver, root } = ctx;
893
922
  const { output, validator, returnType, throwOnErrorDefault, group } = ctx.options;
894
923
  const types = resolveOperationTypes(driver, ctx.plugin.name);
895
- const pluginZod = resolveResponseValidator(validator) === "zod" || resolveRequestValidator(validator) === "zod" ? driver.getPlugin(pluginZodName) : null;
924
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : null;
896
925
  const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
897
926
  const importedTypeNames = [types.response.options(node), types.response.responses(node)];
898
- const importedZodNames = buildValidatorHooks({
927
+ const validatorHooks = buildValidatorHooks({
899
928
  node,
900
929
  validator,
901
930
  zodResolver
902
- }).importedZodNames;
931
+ });
932
+ const importedZodNames = validatorHooks.importedZodNames;
903
933
  const meta = {
904
934
  name: resolver.name(node.operationId),
905
935
  file: resolver.file({
@@ -931,6 +961,7 @@ function createClientGenerator(name, resolveClientPath) {
931
961
  const customClientPath = resolveClientPath?.(ctx.options, root);
932
962
  const clientPath = customClientPath ?? path.resolve(root, ".kubb/client.ts");
933
963
  const clientRoot = customClientPath === void 0 ? meta.file.path : void 0;
964
+ const standardSchemaPath = customClientPath ?? path.resolve(root, ".kubb/standardSchema.ts");
934
965
  const eventStream = isEventStream(node);
935
966
  const clientValueImports = (() => {
936
967
  if (eventStream) return ["client", "toEventStream"];
@@ -995,6 +1026,11 @@ function createClientGenerator(name, resolveClientPath) {
995
1026
  root: meta.file.path,
996
1027
  path: meta.fileZod.path
997
1028
  }),
1029
+ validatorHooks.headers && /* @__PURE__ */ jsx(File.Import, {
1030
+ name: ["toHeadersStandardSchema"],
1031
+ root: clientRoot,
1032
+ path: standardSchemaPath
1033
+ }),
998
1034
  /* @__PURE__ */ jsx(Operation, {
999
1035
  name: meta.name,
1000
1036
  node,
@@ -1015,14 +1051,14 @@ function createClientGenerator(name, resolveClientPath) {
1015
1051
  /**
1016
1052
  * Builds the call config literal forwarded to the contract client; the `throwOnError` fallback is applied after the `...config` spread.
1017
1053
  */
1018
- function buildCallConfig({ node, validator, zodResolver, security, throwOnErrorDefault }) {
1019
- const validators = buildValidatorHooks({
1020
- node,
1021
- validator,
1022
- zodResolver
1023
- });
1024
- const validatorEntries = [validators.request ? `request: ${validators.request}` : null, validators.response ? `response: ${validators.response}` : null].filter(Boolean);
1025
- const validatorLiteral = validatorEntries.length ? `validator: { ${validatorEntries.join(", ")} }` : null;
1054
+ function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault }) {
1055
+ const validatorLiteral = buildValidatorLiteral(validatorHooks, [
1056
+ "request",
1057
+ "path",
1058
+ "query",
1059
+ "headers",
1060
+ "response"
1061
+ ]);
1026
1062
  const securityLiteral = buildSecurityMetadata({ security });
1027
1063
  const { literal: contentTypeLiteral } = buildContentType({ node });
1028
1064
  return `{ ${[
@@ -1038,7 +1074,7 @@ function buildCallConfig({ node, validator, zodResolver, security, throwOnErrorD
1038
1074
  /**
1039
1075
  * Builds one instance method of a generated SDK class; a per-call `options.client` overrides `this.client`.
1040
1076
  */
1041
- function buildSdkMethod({ node, name, types, zodResolver, validator, security, returnType, throwOnErrorDefault }) {
1077
+ function buildSdkMethod({ node, name, types, validatorHooks, security, returnType, throwOnErrorDefault }) {
1042
1078
  if (!ast.isHttpOperationNode(node)) return "";
1043
1079
  const signature = buildGroupedOptionsSignature({
1044
1080
  node,
@@ -1051,8 +1087,7 @@ function buildSdkMethod({ node, name, types, zodResolver, validator, security, r
1051
1087
  types,
1052
1088
  callConfig: buildCallConfig({
1053
1089
  node,
1054
- validator,
1055
- zodResolver,
1090
+ validatorHooks,
1056
1091
  security,
1057
1092
  throwOnErrorDefault
1058
1093
  }),
@@ -1078,13 +1113,12 @@ function buildSdkMethod({ node, name, types, zodResolver, validator, security, r
1078
1113
  * instance: `const api = new PetClient({ baseURL }); api.getPetById(...)`. A per-call `client` option
1079
1114
  * still overrides the instance client for a one-off call.
1080
1115
  */
1081
- function SdkClient({ name, operations, validator, returnType, throwOnErrorDefault }) {
1082
- const methods = operations.map(({ node, name: methodName, types, zodResolver, security }) => buildSdkMethod({
1116
+ function SdkClient({ name, operations, returnType, throwOnErrorDefault }) {
1117
+ const methods = operations.map(({ node, name: methodName, types, validatorHooks, security }) => buildSdkMethod({
1083
1118
  node,
1084
1119
  name: methodName,
1085
1120
  types,
1086
- zodResolver,
1087
- validator,
1121
+ validatorHooks,
1088
1122
  security,
1089
1123
  returnType,
1090
1124
  throwOnErrorDefault
@@ -1132,9 +1166,6 @@ function SdkFacade({ name, members }) {
1132
1166
  function resolveTypeImportNames(node, types) {
1133
1167
  return [types.response.options(node), types.response.responses(node)];
1134
1168
  }
1135
- function resolveZodImportNames(node, zodResolver, validator) {
1136
- return [resolveResponseValidator(validator) === "zod" ? zodResolver.response.response(node) : null, resolveRequestValidator(validator) === "zod" && node.requestBody?.content?.[0]?.schema ? zodResolver.response.body(node) : null].filter((n) => Boolean(n));
1137
- }
1138
1169
  /**
1139
1170
  * Groups operations into one controller per tag. Operations without a tag fall back to a single
1140
1171
  * `Client`/`ApiClient` controller, matching the resolver's default naming.
@@ -1163,13 +1194,18 @@ function buildControllers(nodes, ctx, types) {
1163
1194
  method: node.method,
1164
1195
  path: node.path
1165
1196
  }) : void 0;
1197
+ const validatorHooks = zodResolver ? buildValidatorHooks({
1198
+ node,
1199
+ validator,
1200
+ zodResolver
1201
+ }) : null;
1166
1202
  return {
1167
1203
  node,
1168
1204
  name: resolver.name(node.operationId),
1169
1205
  types,
1170
- zodResolver,
1171
1206
  typeFile,
1172
1207
  zodFile,
1208
+ validatorHooks,
1173
1209
  security
1174
1210
  };
1175
1211
  }
@@ -1242,6 +1278,7 @@ function createSdkGenerator() {
1242
1278
  });
1243
1279
  const controllers = buildControllers(nodes, ctx, resolveOperationTypes(ctx.driver, ctx.plugin.name));
1244
1280
  const clientPath = path.resolve(root, ".kubb/client.ts");
1281
+ const standardSchemaPath = path.resolve(root, ".kubb/standardSchema.ts");
1245
1282
  const banner = (file) => resolver.default.banner(ctx.meta, {
1246
1283
  output,
1247
1284
  config,
@@ -1265,7 +1302,7 @@ function createSdkGenerator() {
1265
1302
  }));
1266
1303
  const { namesByPath: zodNamesByPath, filesByPath: zodFilesByPath } = isValidatorEnabled(validator) ? collectImportsByFile(ops, (op) => ({
1267
1304
  file: op.zodFile,
1268
- names: op.zodResolver ? resolveZodImportNames(op.node, op.zodResolver, validator) : []
1305
+ names: op.validatorHooks?.importedZodNames.filter((name) => name !== op.validatorHooks?.error) ?? []
1269
1306
  })) : {
1270
1307
  namesByPath: /* @__PURE__ */ new Map(),
1271
1308
  filesByPath: /* @__PURE__ */ new Map()
@@ -1315,10 +1352,14 @@ function createSdkGenerator() {
1315
1352
  root: file.path,
1316
1353
  path: zodFilesByPath.get(filePath).path
1317
1354
  }, filePath)),
1355
+ ops.some((op) => op.validatorHooks?.headers) && /* @__PURE__ */ jsx(File.Import, {
1356
+ name: ["toHeadersStandardSchema"],
1357
+ root: file.path,
1358
+ path: standardSchemaPath
1359
+ }),
1318
1360
  /* @__PURE__ */ jsx(SdkClient, {
1319
1361
  name: className,
1320
1362
  operations: ops,
1321
- validator,
1322
1363
  returnType,
1323
1364
  throwOnErrorDefault
1324
1365
  })
@@ -1421,7 +1462,7 @@ var compatibility = {
1421
1462
  };
1422
1463
  //#endregion
1423
1464
  //#region package.json
1424
- var version = "5.9.0-canary.20261024T190549";
1465
+ var version = "5.9.0";
1425
1466
  //#endregion
1426
1467
  //#region src/templates.ts
1427
1468
  /** Absolute path to the fetch client template, copied into `.kubb/client.ts`. */