@kubb/plugin-fetch 6.1.0-canary.20261109T175349 → 6.1.0-canary.20261109T175913

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
@@ -594,22 +594,19 @@ function resolveResponseValidator(validator) {
594
594
  return validator.response ?? null;
595
595
  }
596
596
  /**
597
- * Resolves the zod schema name a generated client validates an error body with on the non-throw path.
598
- * Uses the error-only `<operation>ErrorSchema` (the union of non-2xx statuses); returns `null` when the
599
- * operation documents no error responses with a schema.
597
+ * Builds the `validator.error` map of a call, one plugin-zod `<operation>StatusNNNSchema` per non-2xx response with a
598
+ * schema, such as `{ 404: getPetStatus404Schema, '5XX': getPetStatus5XXSchema }`. Returns `null` without one.
600
599
  */
601
600
  function buildZodErrorParse(node, zodResolver) {
602
- if (!getErrorStatusCodes(node).length) return null;
603
- return zodResolver.response.error?.(node) || null;
604
- }
605
- /** Prints the statuses `<operation>ErrorSchema` covers, such as `[404, '5XX']`, or `null` when a `default` response covers them all. */
606
- function buildErrorStatusLiteral(node) {
607
- const statusCodes = getErrorStatusCodes(node);
608
- if (!statusCodes.length || statusCodes.includes("default")) return null;
609
- return `[${statusCodes.map((statusCode) => /^\d+$/.test(statusCode) ? statusCode : stringify(statusCode)).join(", ")}]`;
610
- }
611
- function getErrorStatusCodes(node) {
612
- return node.responses.filter((res) => !isSuccessStatusCode(res.statusCode) && res.content?.some((entry) => entry.schema)).map((res) => String(res.statusCode));
601
+ const entries = node.responses.filter((res) => !isSuccessStatusCode(res.statusCode) && res.content?.some((entry) => entry.schema)).map((res) => ({
602
+ key: String(res.statusCode),
603
+ name: zodResolver.response.status(node, res.statusCode)
604
+ }));
605
+ if (!entries.length) return null;
606
+ return {
607
+ literal: `{ ${entries.map(({ key, name }) => `${/^\d+$/.test(key) ? key : stringify(key)}: ${name}`).join(", ")} }`,
608
+ names: entries.map(({ name }) => name)
609
+ };
613
610
  }
614
611
  // ../../internals/client/src/builders/generics.ts
615
612
  /**
@@ -814,8 +811,7 @@ function buildValidatorHooks({ node, validator, zodResolver }) {
814
811
  const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
815
812
  const parsesResponse = zodResolver && resolveResponseValidator(validator) === "zod";
816
813
  const response = parsesResponse ? zodResolver.response.response(node) || null : null;
817
- const error = parsesResponse ? buildZodErrorParse(node, zodResolver) : null;
818
- const errorStatus = error ? buildErrorStatusLiteral(node) : null;
814
+ const errorParse = parsesResponse ? buildZodErrorParse(node, zodResolver) : null;
819
815
  const request = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) || null : null;
820
816
  const paramGroups = getOperationParameters(node);
821
817
  const resolveParamsName = (kind, params) => zodResolver && resolveParamsValidator(validator) === "zod" && params.length > 0 ? zodResolver.param[kind](node, params[0]) : null;
@@ -825,7 +821,7 @@ function buildValidatorHooks({ node, validator, zodResolver }) {
825
821
  const cookies = resolveParamsName("cookies", paramGroups.cookie);
826
822
  const importedZodNames = [
827
823
  response,
828
- error,
824
+ ...errorParse?.names ?? [],
829
825
  request,
830
826
  path,
831
827
  query,
@@ -839,17 +835,17 @@ function buildValidatorHooks({ node, validator, zodResolver }) {
839
835
  headers: headers ? `toHeadersStandardSchema(${headers}, ${headers}.shape)` : null,
840
836
  cookies,
841
837
  response,
842
- error,
843
- errorStatus,
838
+ error: errorParse?.literal ?? null,
844
839
  importedZodNames
845
840
  };
846
841
  }
847
842
  /**
848
843
  * Prints the `validator: { … }` entry of a call config from the hooks named in `keys`, or `null` when none is set.
844
+ * The entry spreads `config.validator` last, so a per-call hook overrides the generated one for its key only.
849
845
  */
850
846
  function buildValidatorLiteral(hooks, keys) {
851
847
  const entries = keys.flatMap((key) => hooks?.[key] ? [`${key}: ${hooks[key]}`] : []);
852
- return entries.length ? `validator: { ${entries.join(", ")} }` : null;
848
+ return entries.length ? `validator: { ${entries.join(", ")}, ...config.validator }` : null;
853
849
  }
854
850
  // ../../internals/client/src/builders/contentType.ts
855
851
  /**
@@ -902,13 +898,13 @@ function serializeParameter(parameter) {
902
898
  return parts.length > 0 ? `{ ${parts.join(", ")} }` : null;
903
899
  }
904
900
  /**
905
- * Serializes the `encoding` of the request body's default content type into a `{ property: { ... } }`
906
- * literal, or `null` when it carries none. Only an operation with a single request content type
901
+ * Serializes the `encoding` of the request body's default content type into `property: { ... }`
902
+ * entries, empty when it carries none. Only an operation with a single request content type
907
903
  * emits it, because the runtime applies `styles.body` to whichever type the caller selects.
908
904
  */
909
905
  function serializeBodyEncoding(node) {
910
906
  const content = node.requestBody?.content;
911
- const entries = Object.entries(content?.length === 1 ? content[0]?.encoding ?? {} : {}).map(([property, { contentType, style, explode, allowReserved }]) => {
907
+ return Object.entries(content?.length === 1 ? content[0]?.encoding ?? {} : {}).map(([property, { contentType, style, explode, allowReserved }]) => {
912
908
  const parts = [
913
909
  style && `style: ${JSON.stringify(style)}`,
914
910
  explode !== void 0 && `explode: ${explode}`,
@@ -917,7 +913,6 @@ function serializeBodyEncoding(node) {
917
913
  ].filter(Boolean);
918
914
  return `${isValidVarName(property) ? property : JSON.stringify(property)}: { ${parts.join(", ")} }`;
919
915
  });
920
- return entries.length > 0 ? `body: { ${entries.join(", ")} }` : null;
921
916
  }
922
917
  /**
923
918
  * Builds the per-operation `styles` literal from the operation's parameters, grouped by location.
@@ -927,26 +922,31 @@ function serializeBodyEncoding(node) {
927
922
  * is unchanged. A form request body adds a `body` group keyed by property name from its `encoding`.
928
923
  * Returns `null` when nothing carries metadata.
929
924
  *
925
+ * With `merge`, the literal spreads `config.styles` per parameter, so a per-call entry overrides the generated one for
926
+ * that parameter and leaves the others in place.
927
+ *
930
928
  * @example
931
929
  * ```ts
932
930
  * // a path param with { style: 'matrix', explode: true } and a query param with { explode: false }
933
931
  * buildStyles({ node }) // "{ path: { id: { style: 'matrix', explode: true } }, query: { tags: { explode: false } } }"
934
932
  * ```
935
933
  */
936
- function buildStyles({ node }) {
934
+ function buildStyles({ node, merge }) {
937
935
  if (!_kubb_kit.ast.isHttpOperationNode(node)) return null;
938
936
  const groups = {
939
937
  path: [],
940
938
  query: [],
941
939
  header: [],
942
- cookie: []
940
+ cookie: [],
941
+ body: serializeBodyEncoding(node)
943
942
  };
944
943
  for (const [location, parameters] of Object.entries(getOperationParameters(node))) for (const parameter of parameters) {
945
944
  const literal = serializeParameter(parameter);
946
945
  if (literal) groups[location].push(`${toKey(parameter.name)}: ${literal}`);
947
946
  }
948
- const entries = [...Object.keys(groups).filter((location) => groups[location].length > 0).map((location) => `${location}: { ${groups[location].join(", ")} }`), serializeBodyEncoding(node)].filter(Boolean);
949
- return entries.length > 0 ? `{ ${entries.join(", ")} }` : null;
947
+ const entries = Object.entries(groups).filter(([, items]) => items.length > 0).map(([location, items]) => `${location}: { ${(merge ? [...items, `...config.styles?.${location}`] : items).join(", ")} }`);
948
+ if (entries.length === 0) return null;
949
+ return `{ ${(merge ? ["...config.styles", ...entries] : entries).join(", ")} }`;
950
950
  }
951
951
  // ../../internals/client/src/builders/callConfig.ts
952
952
  /**
@@ -962,7 +962,9 @@ function buildResponseTypeLiteral(node) {
962
962
  }
963
963
  /**
964
964
  * Builds the call config literal a generated operation forwards to the client, shared by the standalone
965
- * functions and the SDK methods. The `throwOnError` fallback is applied after the `...config` spread.
965
+ * functions and the SDK methods. The `validator` and `throwOnError` entries come after the `...config` spread, so a
966
+ * per-call `validator` is merged per key with the generated one instead of replacing it. `styles` is merged the same
967
+ * way, per parameter, unless `returnType` is `'plain'`.
966
968
  *
967
969
  * `mergeContentType` is `true` when the caller must destructure `contentType` from `options`, and
968
970
  * `eventStream` is `true` when the operation streams `text/event-stream` or JSON Lines. Unless `returnType` is `'plain'`, a
@@ -971,16 +973,20 @@ function buildResponseTypeLiteral(node) {
971
973
  function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault, returnType }) {
972
974
  const eventStream = isEventStream(node);
973
975
  const securityLiteral = buildSecurityMetadata({ security });
974
- const stylesLiteral = buildStyles({ node });
976
+ const ownRuntime = returnType !== "plain";
977
+ const stylesLiteral = buildStyles({
978
+ node,
979
+ merge: ownRuntime
980
+ });
981
+ const styles = stylesLiteral ? `styles: ${stylesLiteral}` : null;
975
982
  const validatorLiteral = buildValidatorLiteral(validatorHooks, [
976
983
  "request",
977
984
  "path",
978
985
  "query",
979
986
  "headers",
980
987
  "cookies",
981
- ...eventStream && returnType !== "plain" ? [] : ["response"],
982
- "error",
983
- "errorStatus"
988
+ ...eventStream && ownRuntime ? [] : ["response"],
989
+ "error"
984
990
  ]);
985
991
  const { literal: contentTypeLiteral, merge: mergeContentType } = buildContentType({ node });
986
992
  return {
@@ -988,11 +994,12 @@ function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault,
988
994
  `method: '${node.method.toUpperCase()}'`,
989
995
  `url: '${node.path}'`,
990
996
  securityLiteral ? `security: ${securityLiteral}` : null,
991
- stylesLiteral ? `styles: ${stylesLiteral}` : null,
992
- validatorLiteral,
997
+ ownRuntime ? null : styles,
993
998
  contentTypeLiteral,
994
999
  buildResponseTypeLiteral(node),
995
1000
  "...config",
1001
+ ownRuntime ? styles : null,
1002
+ validatorLiteral,
996
1003
  `throwOnError: config.throwOnError ?? ${throwOnErrorDefault}`
997
1004
  ].filter(Boolean).join(", ")} }`,
998
1005
  mergeContentType,
@@ -1801,7 +1808,7 @@ var compatibility = {
1801
1808
  "node": ">=22.22"
1802
1809
  };
1803
1810
  // package.json
1804
- var version = "6.1.0-canary.20261109T175349";
1811
+ var version = "6.1.0-canary.20261109T175913";
1805
1812
  // src/plugin.ts
1806
1813
  /**
1807
1814
  * Canonical plugin name for `@kubb/plugin-fetch`. Used for driver lookups and cross-plugin