@kubb/plugin-fetch 5.5.0-canary.20260924T111237 → 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 -67
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.js +58 -67
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/plugin.ts +7 -34
- package/templates/fetch.ts +4 -9
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
|
@@ -476,7 +476,7 @@ function buildResultType({ node, types, returnType }) {
|
|
|
476
476
|
* `withUnwrap`, so the caller can `await` it directly or call `.unwrap()` for the bare success
|
|
477
477
|
* body. With `returnType: 'data'` it instead routes the call through the runtime's `unwrapResult`,
|
|
478
478
|
* which narrows the resolved value down to the bare success body the same way `RequestResult`
|
|
479
|
-
* already does,
|
|
479
|
+
* already does, using the plugin default when the call leaves `throwOnError` unset.
|
|
480
480
|
*
|
|
481
481
|
* Cast first, wrap second, for the `'full'` path. That order keeps `withUnwrap`'s generic inferred
|
|
482
482
|
* as `RequestResult` instead of the runtime's own internal result type. Casting an `Unwrappable<A>`
|
|
@@ -486,10 +486,10 @@ function buildResultType({ node, types, returnType }) {
|
|
|
486
486
|
* @example
|
|
487
487
|
* `return withUnwrap(request({ method: 'POST', url: '/pet', ...config }) as Promise<RequestResult<AddPetResponses, ThrowOnError>>)`
|
|
488
488
|
* @example
|
|
489
|
-
* `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>>`
|
|
490
490
|
*/
|
|
491
|
-
function buildReturnStatement({ node, types, callConfig, returnType }) {
|
|
492
|
-
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({
|
|
493
493
|
node,
|
|
494
494
|
types,
|
|
495
495
|
returnType
|
|
@@ -579,7 +579,7 @@ const declarationPrinter = functionPrinter({ mode: "declaration" });
|
|
|
579
579
|
* per-operation input type has to be emitted. Both names come from `types`, which is `plugin-ts` or
|
|
580
580
|
* `plugin-zod`'s inferred types (see `resolveOperationTypes`).
|
|
581
581
|
*/
|
|
582
|
-
function buildGroupedOptionsSignature({ node, types, returnType }) {
|
|
582
|
+
function buildGroupedOptionsSignature({ node, types, returnType, throwOnErrorDefault }) {
|
|
583
583
|
const optionsName = types.response.options(node);
|
|
584
584
|
const { isOptional } = getRequestGroupOptionality(node);
|
|
585
585
|
return {
|
|
@@ -593,7 +593,7 @@ function buildGroupedOptionsSignature({ node, types, returnType }) {
|
|
|
593
593
|
types,
|
|
594
594
|
returnType
|
|
595
595
|
}),
|
|
596
|
-
generics: [
|
|
596
|
+
generics: [`ThrowOnError extends boolean = ${throwOnErrorDefault}`]
|
|
597
597
|
};
|
|
598
598
|
}
|
|
599
599
|
//#endregion
|
|
@@ -687,9 +687,10 @@ function buildValidatorHooks({ node, validator, zodResolver }) {
|
|
|
687
687
|
/**
|
|
688
688
|
* Builds the call config literal forwarded to the contract client, mirroring the shared `Operation`
|
|
689
689
|
* component: `{ method, url, security?, validator?, ...config }`. The `...config` spread carries every
|
|
690
|
-
* 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.
|
|
691
692
|
*/
|
|
692
|
-
function buildCallConfig({ node, validator, zodResolver, security }) {
|
|
693
|
+
function buildCallConfig({ node, validator, zodResolver, security, throwOnErrorDefault }) {
|
|
693
694
|
const validators = buildValidatorHooks({
|
|
694
695
|
node,
|
|
695
696
|
validator,
|
|
@@ -703,7 +704,8 @@ function buildCallConfig({ node, validator, zodResolver, security }) {
|
|
|
703
704
|
`url: '${node.path}'`,
|
|
704
705
|
securityLiteral ? `security: ${securityLiteral}` : null,
|
|
705
706
|
validatorLiteral,
|
|
706
|
-
"...config"
|
|
707
|
+
"...config",
|
|
708
|
+
`throwOnError: config.throwOnError ?? ${throwOnErrorDefault}`
|
|
707
709
|
].filter(Boolean).join(", ")} }`;
|
|
708
710
|
}
|
|
709
711
|
/**
|
|
@@ -713,12 +715,13 @@ function buildCallConfig({ node, validator, zodResolver, security }) {
|
|
|
713
715
|
* instance client, so one operation can be routed to a different environment without a new
|
|
714
716
|
* instance.
|
|
715
717
|
*/
|
|
716
|
-
function buildSdkMethod({ node, name, types, zodResolver, validator, security, returnType }) {
|
|
718
|
+
function buildSdkMethod({ node, name, types, zodResolver, validator, security, returnType, throwOnErrorDefault }) {
|
|
717
719
|
if (!ast.isHttpOperationNode(node)) return "";
|
|
718
720
|
const signature = buildGroupedOptionsSignature({
|
|
719
721
|
node,
|
|
720
722
|
types,
|
|
721
|
-
returnType
|
|
723
|
+
returnType,
|
|
724
|
+
throwOnErrorDefault
|
|
722
725
|
});
|
|
723
726
|
const returnStatement = buildReturnStatement({
|
|
724
727
|
node,
|
|
@@ -727,9 +730,11 @@ function buildSdkMethod({ node, name, types, zodResolver, validator, security, r
|
|
|
727
730
|
node,
|
|
728
731
|
validator,
|
|
729
732
|
zodResolver,
|
|
730
|
-
security
|
|
733
|
+
security,
|
|
734
|
+
throwOnErrorDefault
|
|
731
735
|
}),
|
|
732
|
-
returnType
|
|
736
|
+
returnType,
|
|
737
|
+
throwOnErrorDefault
|
|
733
738
|
});
|
|
734
739
|
const generics = signature.generics.length ? `<${signature.generics.join(", ")}>` : "";
|
|
735
740
|
const jsdoc = buildJSDoc(buildOperationComments(node, {
|
|
@@ -805,12 +810,13 @@ function buildStyles({ node }) {
|
|
|
805
810
|
* type, signature, and call config are built with the AST factory, and only the jsx-renderer emits
|
|
806
811
|
* the source.
|
|
807
812
|
*/
|
|
808
|
-
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 }) {
|
|
809
814
|
if (!ast.isHttpOperationNode(node)) return null;
|
|
810
815
|
const signature = buildGroupedOptionsSignature({
|
|
811
816
|
node,
|
|
812
817
|
types,
|
|
813
|
-
returnType
|
|
818
|
+
returnType,
|
|
819
|
+
throwOnErrorDefault
|
|
814
820
|
});
|
|
815
821
|
const validators = buildValidatorHooks({
|
|
816
822
|
node,
|
|
@@ -840,7 +846,8 @@ function Operation({ name, node, types, zodResolver, validator, returnType, secu
|
|
|
840
846
|
validatorLiteral,
|
|
841
847
|
contentTypeLiteral,
|
|
842
848
|
responseTypeLiteral,
|
|
843
|
-
"...config"
|
|
849
|
+
"...config",
|
|
850
|
+
`throwOnError: config.throwOnError ?? ${throwOnErrorDefault}`
|
|
844
851
|
].filter(Boolean).join(", ")} }`;
|
|
845
852
|
const eventType = `SuccessOf<${types.response.responses(node)}>`;
|
|
846
853
|
const functionReturnType = eventStream ? `Promise<EventStreamResult<${eventType}>>` : signature.returnType;
|
|
@@ -848,7 +855,8 @@ function Operation({ name, node, types, zodResolver, validator, returnType, secu
|
|
|
848
855
|
node,
|
|
849
856
|
types,
|
|
850
857
|
callConfig,
|
|
851
|
-
returnType
|
|
858
|
+
returnType,
|
|
859
|
+
throwOnErrorDefault
|
|
852
860
|
});
|
|
853
861
|
return /* @__PURE__ */ jsx(File.Source, {
|
|
854
862
|
name,
|
|
@@ -881,7 +889,7 @@ function Operation({ name, node, types, zodResolver, validator, returnType, secu
|
|
|
881
889
|
* instance: `const api = new PetClient({ baseURL }); api.getPetById(...)`. A per-call `client` option
|
|
882
890
|
* still overrides the instance client for a one-off call.
|
|
883
891
|
*/
|
|
884
|
-
function SdkClient({ name, isExportable = true, isIndexable = true, operations, validator, returnType, children }) {
|
|
892
|
+
function SdkClient({ name, isExportable = true, isIndexable = true, operations, validator, returnType, throwOnErrorDefault, children }) {
|
|
885
893
|
const methods = operations.map(({ node, name: methodName, types, zodResolver, security }) => buildSdkMethod({
|
|
886
894
|
node,
|
|
887
895
|
name: methodName,
|
|
@@ -889,7 +897,8 @@ function SdkClient({ name, isExportable = true, isIndexable = true, operations,
|
|
|
889
897
|
zodResolver,
|
|
890
898
|
validator,
|
|
891
899
|
security,
|
|
892
|
-
returnType
|
|
900
|
+
returnType,
|
|
901
|
+
throwOnErrorDefault
|
|
893
902
|
}));
|
|
894
903
|
const classCode = `export class ${name} {\n${[
|
|
895
904
|
" private readonly client: ClientInstance",
|
|
@@ -969,7 +978,7 @@ function createClientGenerator(name) {
|
|
|
969
978
|
operation(node, ctx) {
|
|
970
979
|
if (!ast.isHttpOperationNode(node)) return null;
|
|
971
980
|
const { config, driver, resolver, root } = ctx;
|
|
972
|
-
const { output, validator, returnType, group } = ctx.options;
|
|
981
|
+
const { output, validator, returnType, throwOnErrorDefault, group } = ctx.options;
|
|
973
982
|
const types = resolveOperationTypes(driver);
|
|
974
983
|
if (!types) {
|
|
975
984
|
ctx.warn(MISSING_OPERATION_TYPES_WARNING);
|
|
@@ -1072,6 +1081,7 @@ function createClientGenerator(name) {
|
|
|
1072
1081
|
zodResolver,
|
|
1073
1082
|
validator,
|
|
1074
1083
|
returnType,
|
|
1084
|
+
throwOnErrorDefault,
|
|
1075
1085
|
security
|
|
1076
1086
|
})
|
|
1077
1087
|
]
|
|
@@ -1212,7 +1222,7 @@ function createSdkGenerator() {
|
|
|
1212
1222
|
renderer: jsxRenderer,
|
|
1213
1223
|
operations(nodes, ctx) {
|
|
1214
1224
|
const { config, resolver, root } = ctx;
|
|
1215
|
-
const { output, group, validator, returnType, sdk } = ctx.options;
|
|
1225
|
+
const { output, group, validator, returnType, throwOnErrorDefault, sdk } = ctx.options;
|
|
1216
1226
|
if (!sdk) return null;
|
|
1217
1227
|
const types = resolveOperationTypes(ctx.driver);
|
|
1218
1228
|
if (!types) {
|
|
@@ -1298,7 +1308,8 @@ function createSdkGenerator() {
|
|
|
1298
1308
|
name: className,
|
|
1299
1309
|
operations: ops,
|
|
1300
1310
|
validator,
|
|
1301
|
-
returnType
|
|
1311
|
+
returnType,
|
|
1312
|
+
throwOnErrorDefault
|
|
1302
1313
|
})
|
|
1303
1314
|
]
|
|
1304
1315
|
}, file.path);
|
|
@@ -1384,6 +1395,27 @@ const resolverClient = createResolver({
|
|
|
1384
1395
|
}
|
|
1385
1396
|
});
|
|
1386
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
|
|
1387
1419
|
//#region src/generators/clientGenerator.tsx
|
|
1388
1420
|
/**
|
|
1389
1421
|
* Built-in operation generator for `@kubb/plugin-fetch`. Emits one async function per OpenAPI
|
|
@@ -1435,7 +1467,7 @@ const pluginFetch = definePlugin((options) => {
|
|
|
1435
1467
|
const { output = {
|
|
1436
1468
|
path: "clients",
|
|
1437
1469
|
barrel: { type: "named" }
|
|
1438
|
-
}, 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;
|
|
1439
1471
|
const resolved = {
|
|
1440
1472
|
output,
|
|
1441
1473
|
exclude,
|
|
@@ -1443,6 +1475,7 @@ const pluginFetch = definePlugin((options) => {
|
|
|
1443
1475
|
override,
|
|
1444
1476
|
group: createGroupConfig(group),
|
|
1445
1477
|
baseURL,
|
|
1478
|
+
throwOnErrorDefault,
|
|
1446
1479
|
validator,
|
|
1447
1480
|
returnType,
|
|
1448
1481
|
sdk: sdk ? {
|
|
@@ -1468,52 +1501,10 @@ const pluginFetch = definePlugin((options) => {
|
|
|
1468
1501
|
path: path.resolve(root, ".kubb/serializers.ts"),
|
|
1469
1502
|
copy: fetchSerializersTemplatePath
|
|
1470
1503
|
});
|
|
1471
|
-
const clientPath = path.resolve(root, ".kubb/client.ts");
|
|
1472
|
-
const clientSource = readFileSync(fetchClientTemplatePath, "utf8");
|
|
1473
|
-
const clientBody = clientSource.slice(clientSource.indexOf("\n\n") + 2);
|
|
1474
|
-
const runtimeRoot = path.dirname(clientPath);
|
|
1475
1504
|
ctx.injectFile({
|
|
1476
1505
|
baseName: "client.ts",
|
|
1477
|
-
path:
|
|
1478
|
-
|
|
1479
|
-
ast.factory.createImport({
|
|
1480
|
-
name: [
|
|
1481
|
-
"applyHeaderStyles",
|
|
1482
|
-
"defaultBodySerializer",
|
|
1483
|
-
"defaultPathSerializer",
|
|
1484
|
-
"defaultQuerySerializer",
|
|
1485
|
-
"isDefaultJsonBody",
|
|
1486
|
-
"serializeCookies"
|
|
1487
|
-
],
|
|
1488
|
-
path: path.resolve(root, ".kubb/serializers.ts"),
|
|
1489
|
-
root: runtimeRoot
|
|
1490
|
-
}),
|
|
1491
|
-
ast.factory.createImport({
|
|
1492
|
-
name: [
|
|
1493
|
-
"HeadersInit",
|
|
1494
|
-
"PathParamStyle",
|
|
1495
|
-
"PathSerializer",
|
|
1496
|
-
"RequestBody",
|
|
1497
|
-
"Serializers",
|
|
1498
|
-
"Styles"
|
|
1499
|
-
],
|
|
1500
|
-
path: path.resolve(root, ".kubb/serializers.ts"),
|
|
1501
|
-
root: runtimeRoot,
|
|
1502
|
-
isTypeOnly: true
|
|
1503
|
-
}),
|
|
1504
|
-
ast.factory.createImport({
|
|
1505
|
-
name: ["ParseError", "validateStandardSchema"],
|
|
1506
|
-
path: path.resolve(root, ".kubb/standardSchema.ts"),
|
|
1507
|
-
root: runtimeRoot
|
|
1508
|
-
}),
|
|
1509
|
-
ast.factory.createImport({
|
|
1510
|
-
name: ["StandardSchemaValidator"],
|
|
1511
|
-
path: path.resolve(root, ".kubb/standardSchema.ts"),
|
|
1512
|
-
root: runtimeRoot,
|
|
1513
|
-
isTypeOnly: true
|
|
1514
|
-
})
|
|
1515
|
-
],
|
|
1516
|
-
sources: [ast.factory.createSource({ nodes: [ast.factory.createText(clientBody)] })],
|
|
1506
|
+
path: path.resolve(root, ".kubb/client.ts"),
|
|
1507
|
+
banner: runtimeTemplate(fetchClientTemplatePath, ctx.config),
|
|
1517
1508
|
footer: baseURLExpression ? `client.setConfig({ baseURL: ${baseURLExpression} })` : void 0
|
|
1518
1509
|
});
|
|
1519
1510
|
ctx.injectFile({
|