@kubb/plugin-fetch 5.0.0-beta.95 → 5.0.0-beta.98

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.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { t as __name } from "./rolldown-runtime-C0LytTxp.js";
2
2
  import { Exclude, Group, Include, Output, OutputOptions, Override, PluginFactoryOptions, Resolver, ResolverPatch, ast } from "kubb/kit";
3
+ import "@kubb/plugin-ts";
4
+ import "kubb/jsx";
5
+ import "@kubb/plugin-zod";
3
6
  //#region ../../internals/client/src/types.d.ts
4
7
  /**
5
8
  * Validator applied to request and response bodies using schemas from `@kubb/plugin-zod`.
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import "./rolldown-runtime-C0LytTxp.js";
2
2
  import path from "node:path";
3
3
  import { Resolver, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
4
- import { File, Function, jsxRenderer } from "kubb/jsx";
5
4
  import { createFunctionParameter, createFunctionParameters, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
5
+ import { File, Function, jsxRenderer } from "kubb/jsx";
6
6
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
7
7
  import { pluginZodName } from "@kubb/plugin-zod";
8
8
  import { fileURLToPath } from "node:url";
@@ -568,64 +568,65 @@ function createGroupConfig(group) {
568
568
  };
569
569
  }
570
570
  //#endregion
571
- //#region ../../internals/client/src/builders/validatorOptions.ts
572
- /**
573
- * Returns `true` when any direction of the validator uses zod (used for dependency checks).
574
- */
575
- function isValidatorEnabled(validator) {
576
- if (!validator) return false;
577
- if (validator === "zod") return true;
578
- return Boolean(validator.request || validator.response);
579
- }
580
- /**
581
- * Returns `'zod'` when request body parsing is enabled, `null` otherwise. The string shorthand
582
- * `'zod'` validates the response only, so it does not enable request parsing.
583
- */
584
- function resolveRequestValidator(validator) {
585
- if (!validator || validator === "zod") return null;
586
- return validator.request ?? null;
587
- }
588
- /**
589
- * Returns `'zod'` when query-parameters parsing is enabled, `null` otherwise. Only the object form
590
- * `{ request: 'zod' }` enables it.
591
- */
592
- function resolveQueryParamsValidator(validator) {
593
- if (!validator || validator === "zod") return null;
594
- return validator.request ?? null;
595
- }
571
+ //#region ../../internals/client/src/builders/paramsRemap.ts
596
572
  /**
597
- * Returns `'zod'` when response parsing is enabled, `null` otherwise. The string shorthand `'zod'`
598
- * maps to response parsing.
573
+ * Builds the call-config entries that rename the camelCased `query` and `headers` keys back to the
574
+ * names the OpenAPI document declares, so the wire format follows the spec while the generated
575
+ * types keep camelCase keys. Returns an empty array when no name changes. Path parameters need no
576
+ * remap because the URL template placeholders are renamed in sync with the `path` keys. Emit the
577
+ * entries after the `...config` spread so they override the camelCased groups the caller passes in.
578
+ *
579
+ * @example
580
+ * ```ts
581
+ * // a query param named include_deleted in the spec
582
+ * buildParamsRemap({ node }) // ['query: config.query ? { "include_deleted": config.query.includeDeleted } : config.query']
583
+ * ```
599
584
  */
600
- function resolveResponseValidator(validator) {
601
- if (!validator) return null;
602
- if (validator === "zod") return "zod";
603
- return validator.response ?? null;
585
+ function buildParamsRemap({ node }) {
586
+ if (!ast.isHttpOperationNode(node)) return [];
587
+ const original = getOperationParameters(node, { paramsCasing: "original" });
588
+ const cased = getOperationParameters(node);
589
+ const queryMapping = buildParamsMapping(original.query, cased.query);
590
+ const headerMapping = buildParamsMapping(original.header, cased.header);
591
+ const entries = [];
592
+ if (queryMapping) entries.push(`query: ${buildParamsRemapExpression({
593
+ source: "config.query",
594
+ mapping: queryMapping
595
+ })}`);
596
+ if (headerMapping) entries.push(`headers: ${buildParamsRemapExpression({
597
+ source: "config.headers",
598
+ mapping: headerMapping
599
+ })}`);
600
+ return entries;
604
601
  }
602
+ //#endregion
603
+ //#region ../../internals/client/src/builders/generics.ts
605
604
  /**
606
- * Resolves the zod expression a generated client validates a success response with. Only success
607
- * (2xx) bodies reach the parse under the throw-on-error contract, so the success-only
608
- * `<operation>ResponseSchema` is used; error bodies are never zod-parsed.
605
+ * Builds the `RequestResult` generic arguments for one operation: the plugin-ts per-status responses
606
+ * record plus the per-call `ThrowOnError` flag. `SuccessOf` / `ErrorOf` split the record inside the
607
+ * runtime, so this only names the record and threads `ThrowOnError`.
608
+ *
609
+ * @example
610
+ * `buildRequestResultGenerics({ node, tsResolver }) // 'AddPetResponses, ThrowOnError'`
609
611
  */
610
- function buildZodResponseParse(node, zodResolver) {
611
- const name = zodResolver.response.response(node);
612
- return name ? {
613
- expression: name,
614
- importNames: [name]
615
- } : null;
612
+ function buildRequestResultGenerics({ node, tsResolver }) {
613
+ return `${tsResolver.response.responses(node)}, ThrowOnError`;
616
614
  }
615
+ //#endregion
616
+ //#region ../../internals/client/src/builders/returnStatement.ts
617
617
  /**
618
- * Resolves the zod expression a generated client validates an error body with on the non-throw path.
619
- * Uses the error-only `<operation>ErrorSchema` (the union of non-2xx statuses); returns `null` when the
620
- * operation documents no error responses with a schema.
618
+ * Builds the return statement of a generated operation function. The runtime call already resolves
619
+ * to `{ data, error, request, response }`; the generated code forwards that result and casts it to
620
+ * the operation's `RequestResult`, which carries the `throwOnError` discrimination.
621
+ *
622
+ * @example
623
+ * `return request({ method: 'POST', url: '/pet', ...config }) as Promise<RequestResult<AddPetResponses, ThrowOnError>>`
621
624
  */
622
- function buildZodErrorParse(node, zodResolver) {
623
- if (!node.responses.some((res) => !isSuccessStatusCode(res.statusCode) && res.content?.some((entry) => entry.schema))) return null;
624
- const name = zodResolver.response.error?.(node);
625
- return name ? {
626
- expression: name,
627
- importNames: [name]
628
- } : null;
625
+ function buildReturnStatement({ node, tsResolver, callConfig }) {
626
+ return `return request(${callConfig}) as Promise<RequestResult<${buildRequestResultGenerics({
627
+ node,
628
+ tsResolver
629
+ })}>>`;
629
630
  }
630
631
  //#endregion
631
632
  //#region ../../internals/client/src/builders/security.ts
@@ -696,67 +697,6 @@ function buildSecurityMetadata({ security }) {
696
697
  return `[${security.map(serializeAuth).join(", ")}]`;
697
698
  }
698
699
  //#endregion
699
- //#region ../../internals/client/src/builders/paramsRemap.ts
700
- /**
701
- * Builds the call-config entries that rename the camelCased `query` and `headers` keys back to the
702
- * names the OpenAPI document declares, so the wire format follows the spec while the generated
703
- * types keep camelCase keys. Returns an empty array when no name changes. Path parameters need no
704
- * remap because the URL template placeholders are renamed in sync with the `path` keys. Emit the
705
- * entries after the `...config` spread so they override the camelCased groups the caller passes in.
706
- *
707
- * @example
708
- * ```ts
709
- * // a query param named include_deleted in the spec
710
- * buildParamsRemap({ node }) // ['query: config.query ? { "include_deleted": config.query.includeDeleted } : config.query']
711
- * ```
712
- */
713
- function buildParamsRemap({ node }) {
714
- if (!ast.isHttpOperationNode(node)) return [];
715
- const original = getOperationParameters(node, { paramsCasing: "original" });
716
- const cased = getOperationParameters(node);
717
- const queryMapping = buildParamsMapping(original.query, cased.query);
718
- const headerMapping = buildParamsMapping(original.header, cased.header);
719
- const entries = [];
720
- if (queryMapping) entries.push(`query: ${buildParamsRemapExpression({
721
- source: "config.query",
722
- mapping: queryMapping
723
- })}`);
724
- if (headerMapping) entries.push(`headers: ${buildParamsRemapExpression({
725
- source: "config.headers",
726
- mapping: headerMapping
727
- })}`);
728
- return entries;
729
- }
730
- //#endregion
731
- //#region ../../internals/client/src/builders/generics.ts
732
- /**
733
- * Builds the `RequestResult` generic arguments for one operation: the plugin-ts per-status responses
734
- * record plus the per-call `ThrowOnError` flag. `SuccessOf` / `ErrorOf` split the record inside the
735
- * runtime, so this only names the record and threads `ThrowOnError`.
736
- *
737
- * @example
738
- * `buildRequestResultGenerics({ node, tsResolver }) // 'AddPetResponses, ThrowOnError'`
739
- */
740
- function buildRequestResultGenerics({ node, tsResolver }) {
741
- return `${tsResolver.response.responses(node)}, ThrowOnError`;
742
- }
743
- //#endregion
744
- //#region ../../internals/client/src/builders/returnStatement.ts
745
- /**
746
- * Builds the return statement of a generated operation function. The runtime call already resolves
747
- * to `{ data, error, request, response }`; the generated code forwards that result and casts it to
748
- * the operation's `RequestResult`, which carries the `throwOnError` discrimination.
749
- *
750
- * @example
751
- * `return request({ method: 'POST', url: '/pet', ...config }) as Promise<RequestResult<AddPetResponses, ThrowOnError>>`
752
- */
753
- function buildReturnStatement({ node, tsResolver, callConfig }) {
754
- return `return request(${callConfig}) as Promise<RequestResult<${buildRequestResultGenerics({
755
- node,
756
- tsResolver
757
- })}>>`;
758
- }
759
- //#endregion
760
700
  //#region ../../internals/client/src/builders/signature.ts
761
701
  const declarationPrinter = functionPrinter({ mode: "declaration" });
762
702
  /**
@@ -788,6 +728,152 @@ function buildGroupedOptionsSignature({ node, tsResolver }) {
788
728
  };
789
729
  }
790
730
  //#endregion
731
+ //#region ../../internals/client/src/builders/validatorOptions.ts
732
+ /**
733
+ * Returns `true` when any direction of the validator uses zod (used for dependency checks).
734
+ */
735
+ function isValidatorEnabled(validator) {
736
+ if (!validator) return false;
737
+ if (validator === "zod") return true;
738
+ return Boolean(validator.request || validator.response);
739
+ }
740
+ /**
741
+ * Returns `'zod'` when request body parsing is enabled, `null` otherwise. The string shorthand
742
+ * `'zod'` validates the response only, so it does not enable request parsing.
743
+ */
744
+ function resolveRequestValidator(validator) {
745
+ if (!validator || validator === "zod") return null;
746
+ return validator.request ?? null;
747
+ }
748
+ /**
749
+ * Returns `'zod'` when query-parameters parsing is enabled, `null` otherwise. Only the object form
750
+ * `{ request: 'zod' }` enables it.
751
+ */
752
+ function resolveQueryParamsValidator(validator) {
753
+ if (!validator || validator === "zod") return null;
754
+ return validator.request ?? null;
755
+ }
756
+ /**
757
+ * Returns `'zod'` when response parsing is enabled, `null` otherwise. The string shorthand `'zod'`
758
+ * maps to response parsing.
759
+ */
760
+ function resolveResponseValidator(validator) {
761
+ if (!validator) return null;
762
+ if (validator === "zod") return "zod";
763
+ return validator.response ?? null;
764
+ }
765
+ /**
766
+ * Resolves the zod expression a generated client validates a success response with. Only success
767
+ * (2xx) bodies reach the parse under the throw-on-error contract, so the success-only
768
+ * `<operation>ResponseSchema` is used; error bodies are never zod-parsed.
769
+ */
770
+ function buildZodResponseParse(node, zodResolver) {
771
+ const name = zodResolver.response.response(node);
772
+ return name ? {
773
+ expression: name,
774
+ importNames: [name]
775
+ } : null;
776
+ }
777
+ /**
778
+ * Resolves the zod expression a generated client validates an error body with on the non-throw path.
779
+ * Uses the error-only `<operation>ErrorSchema` (the union of non-2xx statuses); returns `null` when the
780
+ * operation documents no error responses with a schema.
781
+ */
782
+ function buildZodErrorParse(node, zodResolver) {
783
+ if (!node.responses.some((res) => !isSuccessStatusCode(res.statusCode) && res.content?.some((entry) => entry.schema))) return null;
784
+ const name = zodResolver.response.error?.(node);
785
+ return name ? {
786
+ expression: name,
787
+ importNames: [name]
788
+ } : null;
789
+ }
790
+ //#endregion
791
+ //#region ../../internals/client/src/builders/validator.ts
792
+ /**
793
+ * Builds the validator-hook references for one operation. Request validation runs before the send;
794
+ * response validation runs on the success body only. Returns `null` references when the matching
795
+ * direction is disabled or the schema is absent.
796
+ */
797
+ function buildValidatorHooks({ node, validator, zodResolver }) {
798
+ const importedZodNames = [];
799
+ const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
800
+ const zodRequestName = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) : null;
801
+ const request = zodRequestName ?? null;
802
+ if (zodRequestName) importedZodNames.push(zodRequestName);
803
+ const responseParse = zodResolver && resolveResponseValidator(validator) === "zod" ? buildZodResponseParse(node, zodResolver) : null;
804
+ const response = responseParse ? responseParse.expression : null;
805
+ if (responseParse) importedZodNames.push(...responseParse.importNames);
806
+ const errorParse = zodResolver && resolveResponseValidator(validator) === "zod" ? buildZodErrorParse(node, zodResolver) : null;
807
+ const error = errorParse ? errorParse.expression : null;
808
+ if (errorParse) importedZodNames.push(...errorParse.importNames);
809
+ return {
810
+ request,
811
+ response,
812
+ error,
813
+ importedZodNames
814
+ };
815
+ }
816
+ //#endregion
817
+ //#region ../../internals/client/src/builders/sdkMethod.ts
818
+ /**
819
+ * Builds the call config literal forwarded to the contract client, mirroring the shared `Operation`
820
+ * component: `{ method, url, security?, validator?, ...config }`. The `...config` spread carries every
821
+ * per-call field (including `throwOnError`), so the method stays a thin wrapper over the contract.
822
+ */
823
+ function buildCallConfig({ node, validator, zodResolver, security }) {
824
+ const validators = buildValidatorHooks({
825
+ node,
826
+ validator,
827
+ zodResolver
828
+ });
829
+ const validatorEntries = [validators.request ? `request: ${validators.request}` : null, validators.response ? `response: ${validators.response}` : null].filter(Boolean);
830
+ const validatorLiteral = validatorEntries.length ? `validator: { ${validatorEntries.join(", ")} }` : null;
831
+ const securityLiteral = buildSecurityMetadata({ security });
832
+ return `{ ${[
833
+ `method: '${node.method.toUpperCase()}'`,
834
+ `url: '${Url.toCasedTemplate(node.path, { casing: "camelcase" })}'`,
835
+ securityLiteral ? `security: ${securityLiteral}` : null,
836
+ validatorLiteral,
837
+ "...config",
838
+ ...buildParamsRemap({ node })
839
+ ].filter(Boolean).join(", ")} }`;
840
+ }
841
+ /**
842
+ * Builds a single instance method for a generated SDK class. The body forwards the single grouped
843
+ * `options` object to the instance's own client (`this.client`, built once in the constructor) and
844
+ * returns the `RequestResult`. A per-call `options.client` still overrides the instance client, so
845
+ * one operation can be routed to a different environment without a new instance.
846
+ */
847
+ function buildSdkMethod({ node, name, tsResolver, zodResolver, validator, security }) {
848
+ if (!ast.isHttpOperationNode(node)) return "";
849
+ const signature = buildGroupedOptionsSignature({
850
+ node,
851
+ tsResolver
852
+ });
853
+ const returnStatement = buildReturnStatement({
854
+ node,
855
+ tsResolver,
856
+ callConfig: buildCallConfig({
857
+ node,
858
+ validator,
859
+ zodResolver,
860
+ security
861
+ })
862
+ });
863
+ const generics = signature.generics.length ? `<${signature.generics.join(", ")}>` : "";
864
+ const jsdoc = buildJSDoc(buildOperationComments(node, {
865
+ link: "urlPath",
866
+ linkPosition: "beforeDeprecated",
867
+ splitLines: true
868
+ }));
869
+ const methodBody = [
870
+ "const { client: request = this.client, ...config } = options",
871
+ "",
872
+ returnStatement
873
+ ].map((line) => line ? ` ${line}` : "").join("\n");
874
+ return `${jsdoc} public ${name}${generics}(${signature.paramsSignature}): ${signature.returnType} {\n${methodBody}\n }`;
875
+ }
876
+ //#endregion
791
877
  //#region ../../internals/client/src/builders/styles.ts
792
878
  /**
793
879
  * Renders a parameter name as an object-literal key, quoted when it is not a bare identifier.
@@ -841,32 +927,6 @@ function buildStyles({ node }) {
841
927
  return `{ ${locations.map((location) => `${location}: { ${groups[location].join(", ")} }`).join(", ")} }`;
842
928
  }
843
929
  //#endregion
844
- //#region ../../internals/client/src/builders/validator.ts
845
- /**
846
- * Builds the validator-hook references for one operation. Request validation runs before the send;
847
- * response validation runs on the success body only. Returns `null` references when the matching
848
- * direction is disabled or the schema is absent.
849
- */
850
- function buildValidatorHooks({ node, validator, zodResolver }) {
851
- const importedZodNames = [];
852
- const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
853
- const zodRequestName = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) : null;
854
- const request = zodRequestName ?? null;
855
- if (zodRequestName) importedZodNames.push(zodRequestName);
856
- const responseParse = zodResolver && resolveResponseValidator(validator) === "zod" ? buildZodResponseParse(node, zodResolver) : null;
857
- const response = responseParse ? responseParse.expression : null;
858
- if (responseParse) importedZodNames.push(...responseParse.importNames);
859
- const errorParse = zodResolver && resolveResponseValidator(validator) === "zod" ? buildZodErrorParse(node, zodResolver) : null;
860
- const error = errorParse ? errorParse.expression : null;
861
- if (errorParse) importedZodNames.push(...errorParse.importNames);
862
- return {
863
- request,
864
- response,
865
- error,
866
- importedZodNames
867
- };
868
- }
869
- //#endregion
870
930
  //#region ../../internals/client/src/components/Operation.tsx
871
931
  /**
872
932
  * Renders one client operation: the grouped `<Name>Request` type and the function that forwards a
@@ -941,66 +1001,6 @@ function Operation({ name, node, tsResolver, zodResolver, validator, security, i
941
1001
  });
942
1002
  }
943
1003
  //#endregion
944
- //#region ../../internals/client/src/builders/sdkMethod.ts
945
- /**
946
- * Builds the call config literal forwarded to the contract client, mirroring the shared `Operation`
947
- * component: `{ method, url, security?, validator?, ...config }`. The `...config` spread carries every
948
- * per-call field (including `throwOnError`), so the method stays a thin wrapper over the contract.
949
- */
950
- function buildCallConfig({ node, validator, zodResolver, security }) {
951
- const validators = buildValidatorHooks({
952
- node,
953
- validator,
954
- zodResolver
955
- });
956
- const validatorEntries = [validators.request ? `request: ${validators.request}` : null, validators.response ? `response: ${validators.response}` : null].filter(Boolean);
957
- const validatorLiteral = validatorEntries.length ? `validator: { ${validatorEntries.join(", ")} }` : null;
958
- const securityLiteral = buildSecurityMetadata({ security });
959
- return `{ ${[
960
- `method: '${node.method.toUpperCase()}'`,
961
- `url: '${Url.toCasedTemplate(node.path, { casing: "camelcase" })}'`,
962
- securityLiteral ? `security: ${securityLiteral}` : null,
963
- validatorLiteral,
964
- "...config",
965
- ...buildParamsRemap({ node })
966
- ].filter(Boolean).join(", ")} }`;
967
- }
968
- /**
969
- * Builds a single instance method for a generated SDK class. The body forwards the single grouped
970
- * `options` object to the instance's own client (`this.client`, built once in the constructor) and
971
- * returns the `RequestResult`. A per-call `options.client` still overrides the instance client, so
972
- * one operation can be routed to a different environment without a new instance.
973
- */
974
- function buildSdkMethod({ node, name, tsResolver, zodResolver, validator, security }) {
975
- if (!ast.isHttpOperationNode(node)) return "";
976
- const signature = buildGroupedOptionsSignature({
977
- node,
978
- tsResolver
979
- });
980
- const returnStatement = buildReturnStatement({
981
- node,
982
- tsResolver,
983
- callConfig: buildCallConfig({
984
- node,
985
- validator,
986
- zodResolver,
987
- security
988
- })
989
- });
990
- const generics = signature.generics.length ? `<${signature.generics.join(", ")}>` : "";
991
- const jsdoc = buildJSDoc(buildOperationComments(node, {
992
- link: "urlPath",
993
- linkPosition: "beforeDeprecated",
994
- splitLines: true
995
- }));
996
- const methodBody = [
997
- "const { client: request = this.client, ...config } = options",
998
- "",
999
- returnStatement
1000
- ].map((line) => line ? ` ${line}` : "").join("\n");
1001
- return `${jsdoc} public ${name}${generics}(${signature.paramsSignature}): ${signature.returnType} {\n${methodBody}\n }`;
1002
- }
1003
- //#endregion
1004
1004
  //#region ../../internals/client/src/components/SdkClient.tsx
1005
1005
  /**
1006
1006
  * Renders one instance class per tag with one method per operation. The constructor takes a client