@kubb/plugin-fetch 5.9.0-canary.20261024T172532 → 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.cjs CHANGED
@@ -472,7 +472,7 @@ function createGroupConfig(group) {
472
472
  function isValidatorEnabled(validator) {
473
473
  if (!validator) return false;
474
474
  if (validator === "zod") return true;
475
- return Boolean(validator.request || validator.response);
475
+ return Boolean(validator.request || validator.params || validator.response);
476
476
  }
477
477
  /**
478
478
  * Returns `'zod'` when request body parsing is enabled, `null` otherwise. The string shorthand
@@ -483,6 +483,14 @@ function resolveRequestValidator(validator) {
483
483
  return validator.request ?? null;
484
484
  }
485
485
  /**
486
+ * Returns `'zod'` when path, query, and header params parsing is enabled, `null` otherwise. Only the
487
+ * object form `{ params: 'zod' }` enables it.
488
+ */
489
+ function resolveParamsValidator(validator) {
490
+ if (!validator || validator === "zod") return null;
491
+ return validator.params ?? null;
492
+ }
493
+ /**
486
494
  * Returns `'zod'` when response parsing is enabled, `null` otherwise. The string shorthand `'zod'`
487
495
  * maps to response parsing.
488
496
  */
@@ -501,36 +509,13 @@ function buildZodErrorParse(node, zodResolver) {
501
509
  return zodResolver.response.error?.(node) || null;
502
510
  }
503
511
  //#endregion
504
- //#region ../../internals/client/src/builders/validator.ts
505
- /**
506
- * Builds the validator-hook references for one operation. Request validation runs before the send;
507
- * response validation runs on the success body only. Returns `null` references when the matching
508
- * direction is disabled or the schema is absent.
509
- */
510
- function buildValidatorHooks({ node, validator, zodResolver }) {
511
- const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
512
- const parsesResponse = zodResolver && resolveResponseValidator(validator) === "zod";
513
- const response = parsesResponse ? zodResolver.response.response(node) || null : null;
514
- const error = parsesResponse ? buildZodErrorParse(node, zodResolver) : null;
515
- const request = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) || null : null;
516
- return {
517
- request,
518
- response,
519
- error,
520
- importedZodNames: [
521
- response,
522
- error,
523
- request
524
- ].filter((name) => Boolean(name))
525
- };
526
- }
527
- //#endregion
528
512
  //#region ../../internals/client/src/builders/security.ts
529
513
  function serializeAuth(auth) {
530
514
  const parts = [`type: '${auth.type}'`];
531
515
  if (auth.scheme) parts.push(`scheme: '${auth.scheme}'`);
532
516
  if (auth.name) parts.push(`name: '${auth.name}'`);
533
517
  if (auth.in) parts.push(`in: '${auth.in}'`);
518
+ if (auth.scopes?.length) parts.push(`scopes: [${auth.scopes.map((scope) => `'${scope}'`).join(", ")}]`);
534
519
  return `{ ${parts.join(", ")} }`;
535
520
  }
536
521
  /**
@@ -573,11 +558,14 @@ function getOperationSecurity({ document, method, path }) {
573
558
  const definitions = document.components?.securitySchemes ?? {};
574
559
  const security = [];
575
560
  const seen = /* @__PURE__ */ new Set();
576
- for (const requirement of requirements) for (const schemeName of Object.keys(requirement)) {
561
+ for (const requirement of requirements) for (const [schemeName, scopes] of Object.entries(requirement)) {
577
562
  if (seen.has(schemeName)) continue;
578
563
  seen.add(schemeName);
579
564
  const auth = resolveSecurityScheme(definitions[schemeName]);
580
- if (auth) security.push(auth);
565
+ if (auth) security.push(scopes.length ? {
566
+ ...auth,
567
+ scopes
568
+ } : auth);
581
569
  }
582
570
  return security.length ? security : void 0;
583
571
  }
@@ -593,6 +581,49 @@ function buildSecurityMetadata({ security }) {
593
581
  return `[${security.map(serializeAuth).join(", ")}]`;
594
582
  }
595
583
  //#endregion
584
+ //#region ../../internals/client/src/builders/validator.ts
585
+ /**
586
+ * Builds the validator-hook references for one operation. Request body and params validation run before the send.
587
+ * Response validation runs on the success body only. Returns `null` references when the matching
588
+ * direction is disabled or the schema is absent.
589
+ */
590
+ function buildValidatorHooks({ node, validator, zodResolver }) {
591
+ const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
592
+ const parsesResponse = zodResolver && resolveResponseValidator(validator) === "zod";
593
+ const response = parsesResponse ? zodResolver.response.response(node) || null : null;
594
+ const error = parsesResponse ? buildZodErrorParse(node, zodResolver) : null;
595
+ const request = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) || null : null;
596
+ const paramGroups = getOperationParameters(node);
597
+ const resolveParamsName = (kind, params) => zodResolver && resolveParamsValidator(validator) === "zod" && params.length > 0 ? zodResolver.param[kind](node, params[0]) : null;
598
+ const path = resolveParamsName("path", paramGroups.path);
599
+ const query = resolveParamsName("query", paramGroups.query);
600
+ const headers = resolveParamsName("headers", paramGroups.header);
601
+ const importedZodNames = [
602
+ response,
603
+ error,
604
+ request,
605
+ path,
606
+ query,
607
+ headers
608
+ ].filter((name) => Boolean(name));
609
+ return {
610
+ request,
611
+ path,
612
+ query,
613
+ headers: headers ? `toHeadersStandardSchema(${headers}, ${headers}.shape)` : null,
614
+ response,
615
+ error,
616
+ importedZodNames
617
+ };
618
+ }
619
+ /**
620
+ * Prints the `validator: { … }` entry of a call config from the hooks named in `keys`, or `null` when none is set.
621
+ */
622
+ function buildValidatorLiteral(hooks, keys) {
623
+ const entries = keys.flatMap((key) => hooks?.[key] ? [`${key}: ${hooks[key]}`] : []);
624
+ return entries.length ? `validator: { ${entries.join(", ")} }` : null;
625
+ }
626
+ //#endregion
596
627
  //#region ../../internals/client/src/builders/contentType.ts
597
628
  /**
598
629
  * Builds the `contentType` entry baked into the call config, or `null` for the JSON default.
@@ -797,12 +828,14 @@ function Operation({ name, node, types, zodResolver, validator, returnType, thro
797
828
  const eventStream = isEventStream(node);
798
829
  const responseType = getResponseType(node);
799
830
  const responseTypeLiteral = responseType ? `responseType: '${responseType}'` : null;
800
- const validatorEntries = [
801
- validators.request ? `request: ${validators.request}` : null,
802
- validators.response ? `response: ${validators.response}` : null,
803
- validators.error ? `error: ${validators.error}` : null
804
- ].filter(Boolean);
805
- const validatorLiteral = validatorEntries.length ? `validator: { ${validatorEntries.join(", ")} }` : null;
831
+ const validatorLiteral = buildValidatorLiteral(validators, [
832
+ "request",
833
+ "path",
834
+ "query",
835
+ "headers",
836
+ "response",
837
+ "error"
838
+ ]);
806
839
  const callConfig = `{ ${[
807
840
  `method: '${node.method.toUpperCase()}'`,
808
841
  `url: '${node.path}'`,
@@ -914,14 +947,15 @@ function createClientGenerator(name, resolveClientPath) {
914
947
  const { config, driver, resolver, root } = ctx;
915
948
  const { output, validator, returnType, throwOnErrorDefault, group } = ctx.options;
916
949
  const types = resolveOperationTypes(driver, ctx.plugin.name);
917
- const pluginZod = resolveResponseValidator(validator) === "zod" || resolveRequestValidator(validator) === "zod" ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
950
+ const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
918
951
  const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
919
952
  const importedTypeNames = [types.response.options(node), types.response.responses(node)];
920
- const importedZodNames = buildValidatorHooks({
953
+ const validatorHooks = buildValidatorHooks({
921
954
  node,
922
955
  validator,
923
956
  zodResolver
924
- }).importedZodNames;
957
+ });
958
+ const importedZodNames = validatorHooks.importedZodNames;
925
959
  const meta = {
926
960
  name: resolver.name(node.operationId),
927
961
  file: resolver.file({
@@ -953,6 +987,7 @@ function createClientGenerator(name, resolveClientPath) {
953
987
  const customClientPath = resolveClientPath?.(ctx.options, root);
954
988
  const clientPath = customClientPath ?? node_path.default.resolve(root, ".kubb/client.ts");
955
989
  const clientRoot = customClientPath === void 0 ? meta.file.path : void 0;
990
+ const standardSchemaPath = customClientPath ?? node_path.default.resolve(root, ".kubb/standardSchema.ts");
956
991
  const eventStream = isEventStream(node);
957
992
  const clientValueImports = (() => {
958
993
  if (eventStream) return ["client", "toEventStream"];
@@ -1017,6 +1052,11 @@ function createClientGenerator(name, resolveClientPath) {
1017
1052
  root: meta.file.path,
1018
1053
  path: meta.fileZod.path
1019
1054
  }),
1055
+ validatorHooks.headers && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1056
+ name: ["toHeadersStandardSchema"],
1057
+ root: clientRoot,
1058
+ path: standardSchemaPath
1059
+ }),
1020
1060
  /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Operation, {
1021
1061
  name: meta.name,
1022
1062
  node,
@@ -1037,14 +1077,14 @@ function createClientGenerator(name, resolveClientPath) {
1037
1077
  /**
1038
1078
  * Builds the call config literal forwarded to the contract client; the `throwOnError` fallback is applied after the `...config` spread.
1039
1079
  */
1040
- function buildCallConfig({ node, validator, zodResolver, security, throwOnErrorDefault }) {
1041
- const validators = buildValidatorHooks({
1042
- node,
1043
- validator,
1044
- zodResolver
1045
- });
1046
- const validatorEntries = [validators.request ? `request: ${validators.request}` : null, validators.response ? `response: ${validators.response}` : null].filter(Boolean);
1047
- const validatorLiteral = validatorEntries.length ? `validator: { ${validatorEntries.join(", ")} }` : null;
1080
+ function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault }) {
1081
+ const validatorLiteral = buildValidatorLiteral(validatorHooks, [
1082
+ "request",
1083
+ "path",
1084
+ "query",
1085
+ "headers",
1086
+ "response"
1087
+ ]);
1048
1088
  const securityLiteral = buildSecurityMetadata({ security });
1049
1089
  const { literal: contentTypeLiteral } = buildContentType({ node });
1050
1090
  return `{ ${[
@@ -1060,7 +1100,7 @@ function buildCallConfig({ node, validator, zodResolver, security, throwOnErrorD
1060
1100
  /**
1061
1101
  * Builds one instance method of a generated SDK class; a per-call `options.client` overrides `this.client`.
1062
1102
  */
1063
- function buildSdkMethod({ node, name, types, zodResolver, validator, security, returnType, throwOnErrorDefault }) {
1103
+ function buildSdkMethod({ node, name, types, validatorHooks, security, returnType, throwOnErrorDefault }) {
1064
1104
  if (!kubb_kit.ast.isHttpOperationNode(node)) return "";
1065
1105
  const signature = buildGroupedOptionsSignature({
1066
1106
  node,
@@ -1073,8 +1113,7 @@ function buildSdkMethod({ node, name, types, zodResolver, validator, security, r
1073
1113
  types,
1074
1114
  callConfig: buildCallConfig({
1075
1115
  node,
1076
- validator,
1077
- zodResolver,
1116
+ validatorHooks,
1078
1117
  security,
1079
1118
  throwOnErrorDefault
1080
1119
  }),
@@ -1100,13 +1139,12 @@ function buildSdkMethod({ node, name, types, zodResolver, validator, security, r
1100
1139
  * instance: `const api = new PetClient({ baseURL }); api.getPetById(...)`. A per-call `client` option
1101
1140
  * still overrides the instance client for a one-off call.
1102
1141
  */
1103
- function SdkClient({ name, operations, validator, returnType, throwOnErrorDefault }) {
1104
- const methods = operations.map(({ node, name: methodName, types, zodResolver, security }) => buildSdkMethod({
1142
+ function SdkClient({ name, operations, returnType, throwOnErrorDefault }) {
1143
+ const methods = operations.map(({ node, name: methodName, types, validatorHooks, security }) => buildSdkMethod({
1105
1144
  node,
1106
1145
  name: methodName,
1107
1146
  types,
1108
- zodResolver,
1109
- validator,
1147
+ validatorHooks,
1110
1148
  security,
1111
1149
  returnType,
1112
1150
  throwOnErrorDefault
@@ -1154,9 +1192,6 @@ function SdkFacade({ name, members }) {
1154
1192
  function resolveTypeImportNames(node, types) {
1155
1193
  return [types.response.options(node), types.response.responses(node)];
1156
1194
  }
1157
- function resolveZodImportNames(node, zodResolver, validator) {
1158
- 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));
1159
- }
1160
1195
  /**
1161
1196
  * Groups operations into one controller per tag. Operations without a tag fall back to a single
1162
1197
  * `Client`/`ApiClient` controller, matching the resolver's default naming.
@@ -1185,13 +1220,18 @@ function buildControllers(nodes, ctx, types) {
1185
1220
  method: node.method,
1186
1221
  path: node.path
1187
1222
  }) : void 0;
1223
+ const validatorHooks = zodResolver ? buildValidatorHooks({
1224
+ node,
1225
+ validator,
1226
+ zodResolver
1227
+ }) : null;
1188
1228
  return {
1189
1229
  node,
1190
1230
  name: resolver.name(node.operationId),
1191
1231
  types,
1192
- zodResolver,
1193
1232
  typeFile,
1194
1233
  zodFile,
1234
+ validatorHooks,
1195
1235
  security
1196
1236
  };
1197
1237
  }
@@ -1264,6 +1304,7 @@ function createSdkGenerator() {
1264
1304
  });
1265
1305
  const controllers = buildControllers(nodes, ctx, resolveOperationTypes(ctx.driver, ctx.plugin.name));
1266
1306
  const clientPath = node_path.default.resolve(root, ".kubb/client.ts");
1307
+ const standardSchemaPath = node_path.default.resolve(root, ".kubb/standardSchema.ts");
1267
1308
  const banner = (file) => resolver.default.banner(ctx.meta, {
1268
1309
  output,
1269
1310
  config,
@@ -1287,7 +1328,7 @@ function createSdkGenerator() {
1287
1328
  }));
1288
1329
  const { namesByPath: zodNamesByPath, filesByPath: zodFilesByPath } = isValidatorEnabled(validator) ? collectImportsByFile(ops, (op) => ({
1289
1330
  file: op.zodFile,
1290
- names: op.zodResolver ? resolveZodImportNames(op.node, op.zodResolver, validator) : []
1331
+ names: op.validatorHooks?.importedZodNames.filter((name) => name !== op.validatorHooks?.error) ?? []
1291
1332
  })) : {
1292
1333
  namesByPath: /* @__PURE__ */ new Map(),
1293
1334
  filesByPath: /* @__PURE__ */ new Map()
@@ -1337,10 +1378,14 @@ function createSdkGenerator() {
1337
1378
  root: file.path,
1338
1379
  path: zodFilesByPath.get(filePath).path
1339
1380
  }, filePath)),
1381
+ ops.some((op) => op.validatorHooks?.headers) && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
1382
+ name: ["toHeadersStandardSchema"],
1383
+ root: file.path,
1384
+ path: standardSchemaPath
1385
+ }),
1340
1386
  /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(SdkClient, {
1341
1387
  name: className,
1342
1388
  operations: ops,
1343
- validator,
1344
1389
  returnType,
1345
1390
  throwOnErrorDefault
1346
1391
  })
@@ -1443,7 +1488,7 @@ var compatibility = {
1443
1488
  };
1444
1489
  //#endregion
1445
1490
  //#region package.json
1446
- var version = "5.9.0-canary.20261024T172532";
1491
+ var version = "5.9.0";
1447
1492
  //#endregion
1448
1493
  //#region src/templates.ts
1449
1494
  /** Absolute path to the fetch client template, copied into `.kubb/client.ts`. */