@kubb/plugin-fetch 5.5.0-canary.20260924T110844 → 5.5.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 +58 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.js +58 -24
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/plugin.ts +5 -2
- package/templates/fetch.ts +29 -31
package/dist/index.d.ts
CHANGED
|
@@ -25,9 +25,8 @@ type Mode = 'tag' | 'flat';
|
|
|
25
25
|
/**
|
|
26
26
|
* Shape of the value a generated operation function resolves to.
|
|
27
27
|
* - `'full'`: the complete `{ status, data, error, contentType, request, response }` result.
|
|
28
|
-
* - `'data'`: the bare success body
|
|
29
|
-
*
|
|
30
|
-
* needs `error` to discriminate a failed response.
|
|
28
|
+
* - `'data'`: the bare success body when `throwOnError` is true, or the full result when it is false
|
|
29
|
+
* so callers can inspect `error`.
|
|
31
30
|
*/
|
|
32
31
|
type ReturnTypeOption = 'full' | 'data';
|
|
33
32
|
/**
|
|
@@ -71,13 +70,20 @@ type Options = OutputOptions & {
|
|
|
71
70
|
/**
|
|
72
71
|
* Apply a different options object to operations matching a pattern.
|
|
73
72
|
*/
|
|
74
|
-
override?: Array<Override<ResolvedOptions
|
|
73
|
+
override?: Array<Override<Omit<ResolvedOptions, 'throwOnErrorDefault'>>>;
|
|
75
74
|
/**
|
|
76
75
|
* Base URL prepended to every request. When omitted, falls back to the adapter's server URL.
|
|
77
76
|
* Values containing a `${...}` interpolation are emitted as template literals in the generated
|
|
78
77
|
* client config, which keeps runtime environment reads dynamic.
|
|
79
78
|
*/
|
|
80
79
|
baseURL?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Default error behavior for generated operations and their client. Per-call `throwOnError`
|
|
82
|
+
* takes precedence.
|
|
83
|
+
*
|
|
84
|
+
* @default true
|
|
85
|
+
*/
|
|
86
|
+
throwOnErrorDefault?: boolean;
|
|
81
87
|
/**
|
|
82
88
|
* Validate request and response bodies with schemas from `@kubb/plugin-zod`.
|
|
83
89
|
*
|
|
@@ -160,9 +166,10 @@ type ResolvedOptions = {
|
|
|
160
166
|
output: Output;
|
|
161
167
|
exclude: Array<Exclude>;
|
|
162
168
|
include: Array<Include> | undefined;
|
|
163
|
-
override: Array<Override<ResolvedOptions
|
|
169
|
+
override: Array<Override<Omit<ResolvedOptions, 'throwOnErrorDefault'>>>;
|
|
164
170
|
group: Group | null;
|
|
165
171
|
baseURL: Options['baseURL'];
|
|
172
|
+
throwOnErrorDefault: boolean;
|
|
166
173
|
validator: NonNullable<Options['validator']>;
|
|
167
174
|
returnType: ReturnTypeOption;
|
|
168
175
|
sdk: {
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createFunctionParameter, createFunctionParameters, functionPrinter, plu
|
|
|
5
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
|
+
import { readFileSync } from "node:fs";
|
|
8
9
|
import { fileURLToPath } from "node:url";
|
|
9
10
|
//#region ../../internals/shared/src/params.ts
|
|
10
11
|
/**
|
|
@@ -475,7 +476,7 @@ function buildResultType({ node, types, returnType }) {
|
|
|
475
476
|
* `withUnwrap`, so the caller can `await` it directly or call `.unwrap()` for the bare success
|
|
476
477
|
* body. With `returnType: 'data'` it instead routes the call through the runtime's `unwrapResult`,
|
|
477
478
|
* which narrows the resolved value down to the bare success body the same way `RequestResult`
|
|
478
|
-
* already does,
|
|
479
|
+
* already does, using the plugin default when the call leaves `throwOnError` unset.
|
|
479
480
|
*
|
|
480
481
|
* Cast first, wrap second, for the `'full'` path. That order keeps `withUnwrap`'s generic inferred
|
|
481
482
|
* as `RequestResult` instead of the runtime's own internal result type. Casting an `Unwrappable<A>`
|
|
@@ -485,10 +486,10 @@ function buildResultType({ node, types, returnType }) {
|
|
|
485
486
|
* @example
|
|
486
487
|
* `return withUnwrap(request({ method: 'POST', url: '/pet', ...config }) as Promise<RequestResult<AddPetResponses, ThrowOnError>>)`
|
|
487
488
|
* @example
|
|
488
|
-
* `return unwrapResult(request({ method: 'POST', url: '/pet', ...config }), config.throwOnError) as Promise<UnwrappedResult<AddPetResponses, ThrowOnError>>`
|
|
489
|
+
* `return unwrapResult(request({ method: 'POST', url: '/pet', ...config }), config.throwOnError ?? false) as Promise<UnwrappedResult<AddPetResponses, ThrowOnError>>`
|
|
489
490
|
*/
|
|
490
|
-
function buildReturnStatement({ node, types, callConfig, returnType }) {
|
|
491
|
-
if (returnType === "data") return `return unwrapResult(request(${callConfig}), config.throwOnError) as ${buildResultType({
|
|
491
|
+
function buildReturnStatement({ node, types, callConfig, returnType, throwOnErrorDefault }) {
|
|
492
|
+
if (returnType === "data") return `return unwrapResult(request(${callConfig}), config.throwOnError ?? ${throwOnErrorDefault}) as ${buildResultType({
|
|
492
493
|
node,
|
|
493
494
|
types,
|
|
494
495
|
returnType
|
|
@@ -578,7 +579,7 @@ const declarationPrinter = functionPrinter({ mode: "declaration" });
|
|
|
578
579
|
* per-operation input type has to be emitted. Both names come from `types`, which is `plugin-ts` or
|
|
579
580
|
* `plugin-zod`'s inferred types (see `resolveOperationTypes`).
|
|
580
581
|
*/
|
|
581
|
-
function buildGroupedOptionsSignature({ node, types, returnType }) {
|
|
582
|
+
function buildGroupedOptionsSignature({ node, types, returnType, throwOnErrorDefault }) {
|
|
582
583
|
const optionsName = types.response.options(node);
|
|
583
584
|
const { isOptional } = getRequestGroupOptionality(node);
|
|
584
585
|
return {
|
|
@@ -592,7 +593,7 @@ function buildGroupedOptionsSignature({ node, types, returnType }) {
|
|
|
592
593
|
types,
|
|
593
594
|
returnType
|
|
594
595
|
}),
|
|
595
|
-
generics: [
|
|
596
|
+
generics: [`ThrowOnError extends boolean = ${throwOnErrorDefault}`]
|
|
596
597
|
};
|
|
597
598
|
}
|
|
598
599
|
//#endregion
|
|
@@ -686,9 +687,10 @@ function buildValidatorHooks({ node, validator, zodResolver }) {
|
|
|
686
687
|
/**
|
|
687
688
|
* Builds the call config literal forwarded to the contract client, mirroring the shared `Operation`
|
|
688
689
|
* component: `{ method, url, security?, validator?, ...config }`. The `...config` spread carries every
|
|
689
|
-
* per-call field
|
|
690
|
+
* per-call field. The plugin's `throwOnError` fallback is applied after the spread so it also wins
|
|
691
|
+
* over a client instance's runtime config when the call omits an override.
|
|
690
692
|
*/
|
|
691
|
-
function buildCallConfig({ node, validator, zodResolver, security }) {
|
|
693
|
+
function buildCallConfig({ node, validator, zodResolver, security, throwOnErrorDefault }) {
|
|
692
694
|
const validators = buildValidatorHooks({
|
|
693
695
|
node,
|
|
694
696
|
validator,
|
|
@@ -702,7 +704,8 @@ function buildCallConfig({ node, validator, zodResolver, security }) {
|
|
|
702
704
|
`url: '${node.path}'`,
|
|
703
705
|
securityLiteral ? `security: ${securityLiteral}` : null,
|
|
704
706
|
validatorLiteral,
|
|
705
|
-
"...config"
|
|
707
|
+
"...config",
|
|
708
|
+
`throwOnError: config.throwOnError ?? ${throwOnErrorDefault}`
|
|
706
709
|
].filter(Boolean).join(", ")} }`;
|
|
707
710
|
}
|
|
708
711
|
/**
|
|
@@ -712,12 +715,13 @@ function buildCallConfig({ node, validator, zodResolver, security }) {
|
|
|
712
715
|
* instance client, so one operation can be routed to a different environment without a new
|
|
713
716
|
* instance.
|
|
714
717
|
*/
|
|
715
|
-
function buildSdkMethod({ node, name, types, zodResolver, validator, security, returnType }) {
|
|
718
|
+
function buildSdkMethod({ node, name, types, zodResolver, validator, security, returnType, throwOnErrorDefault }) {
|
|
716
719
|
if (!ast.isHttpOperationNode(node)) return "";
|
|
717
720
|
const signature = buildGroupedOptionsSignature({
|
|
718
721
|
node,
|
|
719
722
|
types,
|
|
720
|
-
returnType
|
|
723
|
+
returnType,
|
|
724
|
+
throwOnErrorDefault
|
|
721
725
|
});
|
|
722
726
|
const returnStatement = buildReturnStatement({
|
|
723
727
|
node,
|
|
@@ -726,9 +730,11 @@ function buildSdkMethod({ node, name, types, zodResolver, validator, security, r
|
|
|
726
730
|
node,
|
|
727
731
|
validator,
|
|
728
732
|
zodResolver,
|
|
729
|
-
security
|
|
733
|
+
security,
|
|
734
|
+
throwOnErrorDefault
|
|
730
735
|
}),
|
|
731
|
-
returnType
|
|
736
|
+
returnType,
|
|
737
|
+
throwOnErrorDefault
|
|
732
738
|
});
|
|
733
739
|
const generics = signature.generics.length ? `<${signature.generics.join(", ")}>` : "";
|
|
734
740
|
const jsdoc = buildJSDoc(buildOperationComments(node, {
|
|
@@ -804,12 +810,13 @@ function buildStyles({ node }) {
|
|
|
804
810
|
* type, signature, and call config are built with the AST factory, and only the jsx-renderer emits
|
|
805
811
|
* the source.
|
|
806
812
|
*/
|
|
807
|
-
function Operation({ name, node, types, zodResolver, validator, returnType, security, isExportable = true, isIndexable = true }) {
|
|
813
|
+
function Operation({ name, node, types, zodResolver, validator, returnType, throwOnErrorDefault, security, isExportable = true, isIndexable = true }) {
|
|
808
814
|
if (!ast.isHttpOperationNode(node)) return null;
|
|
809
815
|
const signature = buildGroupedOptionsSignature({
|
|
810
816
|
node,
|
|
811
817
|
types,
|
|
812
|
-
returnType
|
|
818
|
+
returnType,
|
|
819
|
+
throwOnErrorDefault
|
|
813
820
|
});
|
|
814
821
|
const validators = buildValidatorHooks({
|
|
815
822
|
node,
|
|
@@ -839,7 +846,8 @@ function Operation({ name, node, types, zodResolver, validator, returnType, secu
|
|
|
839
846
|
validatorLiteral,
|
|
840
847
|
contentTypeLiteral,
|
|
841
848
|
responseTypeLiteral,
|
|
842
|
-
"...config"
|
|
849
|
+
"...config",
|
|
850
|
+
`throwOnError: config.throwOnError ?? ${throwOnErrorDefault}`
|
|
843
851
|
].filter(Boolean).join(", ")} }`;
|
|
844
852
|
const eventType = `SuccessOf<${types.response.responses(node)}>`;
|
|
845
853
|
const functionReturnType = eventStream ? `Promise<EventStreamResult<${eventType}>>` : signature.returnType;
|
|
@@ -847,7 +855,8 @@ function Operation({ name, node, types, zodResolver, validator, returnType, secu
|
|
|
847
855
|
node,
|
|
848
856
|
types,
|
|
849
857
|
callConfig,
|
|
850
|
-
returnType
|
|
858
|
+
returnType,
|
|
859
|
+
throwOnErrorDefault
|
|
851
860
|
});
|
|
852
861
|
return /* @__PURE__ */ jsx(File.Source, {
|
|
853
862
|
name,
|
|
@@ -880,7 +889,7 @@ function Operation({ name, node, types, zodResolver, validator, returnType, secu
|
|
|
880
889
|
* instance: `const api = new PetClient({ baseURL }); api.getPetById(...)`. A per-call `client` option
|
|
881
890
|
* still overrides the instance client for a one-off call.
|
|
882
891
|
*/
|
|
883
|
-
function SdkClient({ name, isExportable = true, isIndexable = true, operations, validator, returnType, children }) {
|
|
892
|
+
function SdkClient({ name, isExportable = true, isIndexable = true, operations, validator, returnType, throwOnErrorDefault, children }) {
|
|
884
893
|
const methods = operations.map(({ node, name: methodName, types, zodResolver, security }) => buildSdkMethod({
|
|
885
894
|
node,
|
|
886
895
|
name: methodName,
|
|
@@ -888,7 +897,8 @@ function SdkClient({ name, isExportable = true, isIndexable = true, operations,
|
|
|
888
897
|
zodResolver,
|
|
889
898
|
validator,
|
|
890
899
|
security,
|
|
891
|
-
returnType
|
|
900
|
+
returnType,
|
|
901
|
+
throwOnErrorDefault
|
|
892
902
|
}));
|
|
893
903
|
const classCode = `export class ${name} {\n${[
|
|
894
904
|
" private readonly client: ClientInstance",
|
|
@@ -968,7 +978,7 @@ function createClientGenerator(name) {
|
|
|
968
978
|
operation(node, ctx) {
|
|
969
979
|
if (!ast.isHttpOperationNode(node)) return null;
|
|
970
980
|
const { config, driver, resolver, root } = ctx;
|
|
971
|
-
const { output, validator, returnType, group } = ctx.options;
|
|
981
|
+
const { output, validator, returnType, throwOnErrorDefault, group } = ctx.options;
|
|
972
982
|
const types = resolveOperationTypes(driver);
|
|
973
983
|
if (!types) {
|
|
974
984
|
ctx.warn(MISSING_OPERATION_TYPES_WARNING);
|
|
@@ -1071,6 +1081,7 @@ function createClientGenerator(name) {
|
|
|
1071
1081
|
zodResolver,
|
|
1072
1082
|
validator,
|
|
1073
1083
|
returnType,
|
|
1084
|
+
throwOnErrorDefault,
|
|
1074
1085
|
security
|
|
1075
1086
|
})
|
|
1076
1087
|
]
|
|
@@ -1211,7 +1222,7 @@ function createSdkGenerator() {
|
|
|
1211
1222
|
renderer: jsxRenderer,
|
|
1212
1223
|
operations(nodes, ctx) {
|
|
1213
1224
|
const { config, resolver, root } = ctx;
|
|
1214
|
-
const { output, group, validator, returnType, sdk } = ctx.options;
|
|
1225
|
+
const { output, group, validator, returnType, throwOnErrorDefault, sdk } = ctx.options;
|
|
1215
1226
|
if (!sdk) return null;
|
|
1216
1227
|
const types = resolveOperationTypes(ctx.driver);
|
|
1217
1228
|
if (!types) {
|
|
@@ -1297,7 +1308,8 @@ function createSdkGenerator() {
|
|
|
1297
1308
|
name: className,
|
|
1298
1309
|
operations: ops,
|
|
1299
1310
|
validator,
|
|
1300
|
-
returnType
|
|
1311
|
+
returnType,
|
|
1312
|
+
throwOnErrorDefault
|
|
1301
1313
|
})
|
|
1302
1314
|
]
|
|
1303
1315
|
}, file.path);
|
|
@@ -1383,6 +1395,27 @@ const resolverClient = createResolver({
|
|
|
1383
1395
|
}
|
|
1384
1396
|
});
|
|
1385
1397
|
//#endregion
|
|
1398
|
+
//#region ../../internals/client/src/runtimeTemplate.ts
|
|
1399
|
+
/** Apply the active TypeScript parser's import extension to a copied client runtime. */
|
|
1400
|
+
function runtimeTemplate(path, config) {
|
|
1401
|
+
const parser = config.parsers.find((item) => item.extNames?.includes(".ts"));
|
|
1402
|
+
const probe = ast.factory.createFile({
|
|
1403
|
+
baseName: "probe.ts",
|
|
1404
|
+
path: "probe.ts",
|
|
1405
|
+
imports: [ast.factory.createImport({
|
|
1406
|
+
name: ["KubbRuntimeImport"],
|
|
1407
|
+
path: "/probeDependency.ts",
|
|
1408
|
+
root: "/"
|
|
1409
|
+
})],
|
|
1410
|
+
sources: [ast.factory.createSource({
|
|
1411
|
+
name: "probe",
|
|
1412
|
+
nodes: [ast.factory.createText("KubbRuntimeImport")]
|
|
1413
|
+
})]
|
|
1414
|
+
});
|
|
1415
|
+
const extension = parser?.parse(probe).match(/from ['"]\.\/probeDependency(\.[^'"]+)?['"]/)?.[1] ?? "";
|
|
1416
|
+
return readFileSync(path, "utf8").replace(/(from ['"]\.\/(?:serializers|standardSchema))(?:\.ts|\.js)?(['"])/g, `$1${extension}$2`);
|
|
1417
|
+
}
|
|
1418
|
+
//#endregion
|
|
1386
1419
|
//#region src/generators/clientGenerator.tsx
|
|
1387
1420
|
/**
|
|
1388
1421
|
* Built-in operation generator for `@kubb/plugin-fetch`. Emits one async function per OpenAPI
|
|
@@ -1434,7 +1467,7 @@ const pluginFetch = definePlugin((options) => {
|
|
|
1434
1467
|
const { output = {
|
|
1435
1468
|
path: "clients",
|
|
1436
1469
|
barrel: { type: "named" }
|
|
1437
|
-
}, exclude = [], include, override = [], baseURL, validator = false, returnType = "full", group, sdk, resolver: userResolver } = options;
|
|
1470
|
+
}, exclude = [], include, override = [], baseURL, throwOnErrorDefault = true, validator = false, returnType = "full", group, sdk, resolver: userResolver } = options;
|
|
1438
1471
|
const resolved = {
|
|
1439
1472
|
output,
|
|
1440
1473
|
exclude,
|
|
@@ -1442,6 +1475,7 @@ const pluginFetch = definePlugin((options) => {
|
|
|
1442
1475
|
override,
|
|
1443
1476
|
group: createGroupConfig(group),
|
|
1444
1477
|
baseURL,
|
|
1478
|
+
throwOnErrorDefault,
|
|
1445
1479
|
validator,
|
|
1446
1480
|
returnType,
|
|
1447
1481
|
sdk: sdk ? {
|
|
@@ -1470,7 +1504,7 @@ const pluginFetch = definePlugin((options) => {
|
|
|
1470
1504
|
ctx.injectFile({
|
|
1471
1505
|
baseName: "client.ts",
|
|
1472
1506
|
path: path.resolve(root, ".kubb/client.ts"),
|
|
1473
|
-
|
|
1507
|
+
banner: runtimeTemplate(fetchClientTemplatePath, ctx.config),
|
|
1474
1508
|
footer: baseURLExpression ? `client.setConfig({ baseURL: ${baseURLExpression} })` : void 0
|
|
1475
1509
|
});
|
|
1476
1510
|
ctx.injectFile({
|