@kubb/plugin-fetch 5.9.0-canary.20261024T190549 → 5.9.1
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 +131 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -5
- package/dist/index.d.ts +7 -5
- package/dist/index.js +131 -72
- package/dist/index.js.map +1 -1
- package/dist/templates/fetch.d.ts +11 -4
- package/dist/templates/standardSchema.d.ts +14 -0
- package/docs/options.md +16 -10
- package/package.json +5 -5
- package/templates/fetch.ts +53 -15
- package/templates/standardSchema.ts +55 -0
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,30 +509,6 @@ 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}'`];
|
|
@@ -597,6 +581,49 @@ function buildSecurityMetadata({ security }) {
|
|
|
597
581
|
return `[${security.map(serializeAuth).join(", ")}]`;
|
|
598
582
|
}
|
|
599
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
|
|
600
627
|
//#region ../../internals/client/src/builders/contentType.ts
|
|
601
628
|
/**
|
|
602
629
|
* Builds the `contentType` entry baked into the call config, or `null` for the JSON default.
|
|
@@ -801,12 +828,14 @@ function Operation({ name, node, types, zodResolver, validator, returnType, thro
|
|
|
801
828
|
const eventStream = isEventStream(node);
|
|
802
829
|
const responseType = getResponseType(node);
|
|
803
830
|
const responseTypeLiteral = responseType ? `responseType: '${responseType}'` : null;
|
|
804
|
-
const
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
831
|
+
const validatorLiteral = buildValidatorLiteral(validators, [
|
|
832
|
+
"request",
|
|
833
|
+
"path",
|
|
834
|
+
"query",
|
|
835
|
+
"headers",
|
|
836
|
+
"response",
|
|
837
|
+
"error"
|
|
838
|
+
]);
|
|
810
839
|
const callConfig = `{ ${[
|
|
811
840
|
`method: '${node.method.toUpperCase()}'`,
|
|
812
841
|
`url: '${node.path}'`,
|
|
@@ -853,14 +882,35 @@ function Operation({ name, node, types, zodResolver, validator, returnType, thro
|
|
|
853
882
|
//#endregion
|
|
854
883
|
//#region ../../internals/client/src/resolveOperationTypes.ts
|
|
855
884
|
/**
|
|
856
|
-
*
|
|
885
|
+
* A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
|
|
886
|
+
* exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
|
|
887
|
+
*/
|
|
888
|
+
function toZodTypeResolver(resolver) {
|
|
889
|
+
const type = (name) => resolver.schema.type(name);
|
|
890
|
+
return {
|
|
891
|
+
...resolver,
|
|
892
|
+
file: resolver.file.bind(resolver),
|
|
893
|
+
param: {
|
|
894
|
+
name: (node, p) => type(resolver.param.name(node, p)),
|
|
895
|
+
path: (node, p) => type(resolver.param.path(node, p)),
|
|
896
|
+
query: (node, p) => type(resolver.param.query(node, p)),
|
|
897
|
+
headers: (node, p) => type(resolver.param.headers(node, p))
|
|
898
|
+
},
|
|
899
|
+
response: {
|
|
900
|
+
body: (node) => type(resolver.response.body(node)),
|
|
901
|
+
status: (node, statusCode) => type(resolver.response.status(node, statusCode)),
|
|
902
|
+
response: (node) => type(resolver.response.response(node)),
|
|
903
|
+
responses: (node) => type(resolver.response.responses(node)),
|
|
904
|
+
options: (node) => resolver.response.options(node)
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Picks the plugin generated clients, query hooks, and MCP handlers take their operation types from.
|
|
857
910
|
*
|
|
858
|
-
* `
|
|
859
|
-
*
|
|
860
|
-
*
|
|
861
|
-
* `z.infer` carries what the codecs decode to (a `Temporal` instance, a `Date`) rather than the raw
|
|
862
|
-
* wire type. Throws `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available, since the
|
|
863
|
-
* client has nothing to type against.
|
|
911
|
+
* `pluginZod({ inferred: 'codec' })` wins, so a codec param takes its domain value. Otherwise `plugin-ts`
|
|
912
|
+
* wins when it is in the pipeline, and without it any `pluginZod({ inferred })`. Throws
|
|
913
|
+
* `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available.
|
|
864
914
|
*
|
|
865
915
|
* @example
|
|
866
916
|
* ```ts
|
|
@@ -870,16 +920,16 @@ function Operation({ name, node, types, zodResolver, validator, returnType, thro
|
|
|
870
920
|
*/
|
|
871
921
|
function resolveOperationTypes(driver, pluginName) {
|
|
872
922
|
const pluginTs = driver.getPlugin(_kubb_plugin_ts.pluginTsName);
|
|
873
|
-
|
|
923
|
+
const pluginZod = driver.getPlugin(_kubb_plugin_zod.pluginZodName);
|
|
924
|
+
if (pluginTs && pluginZod?.options?.inferred !== "codec") {
|
|
874
925
|
const resolver = driver.getResolver(_kubb_plugin_ts.pluginTsName);
|
|
875
926
|
return {
|
|
876
927
|
response: resolver.response,
|
|
877
928
|
resolver,
|
|
878
929
|
output: pluginTs.options?.output,
|
|
879
|
-
group: pluginTs.options?.group
|
|
930
|
+
group: pluginTs.options?.group ?? void 0
|
|
880
931
|
};
|
|
881
932
|
}
|
|
882
|
-
const pluginZod = driver.getPlugin(_kubb_plugin_zod.pluginZodName);
|
|
883
933
|
if (!pluginZod?.options?.inferred) throw new kubb_kit.Diagnostics.Error({
|
|
884
934
|
code: kubb_kit.Diagnostics.code.missingDependency,
|
|
885
935
|
severity: "error",
|
|
@@ -888,15 +938,12 @@ function resolveOperationTypes(driver, pluginName) {
|
|
|
888
938
|
location: { kind: "config" },
|
|
889
939
|
plugin: pluginName
|
|
890
940
|
});
|
|
891
|
-
const resolver = driver.getResolver(_kubb_plugin_zod.pluginZodName);
|
|
941
|
+
const resolver = toZodTypeResolver(driver.getResolver(_kubb_plugin_zod.pluginZodName));
|
|
892
942
|
return {
|
|
893
|
-
response:
|
|
894
|
-
options: resolver.response.options,
|
|
895
|
-
responses: (node) => resolver.schema.type(resolver.response.responses(node))
|
|
896
|
-
},
|
|
943
|
+
response: resolver.response,
|
|
897
944
|
resolver,
|
|
898
945
|
output: pluginZod.options.output,
|
|
899
|
-
group: pluginZod.options.group
|
|
946
|
+
group: pluginZod.options.group ?? void 0
|
|
900
947
|
};
|
|
901
948
|
}
|
|
902
949
|
//#endregion
|
|
@@ -918,14 +965,15 @@ function createClientGenerator(name, resolveClientPath) {
|
|
|
918
965
|
const { config, driver, resolver, root } = ctx;
|
|
919
966
|
const { output, validator, returnType, throwOnErrorDefault, group } = ctx.options;
|
|
920
967
|
const types = resolveOperationTypes(driver, ctx.plugin.name);
|
|
921
|
-
const pluginZod =
|
|
968
|
+
const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(_kubb_plugin_zod.pluginZodName) : null;
|
|
922
969
|
const zodResolver = pluginZod ? driver.getResolver(_kubb_plugin_zod.pluginZodName) : null;
|
|
923
970
|
const importedTypeNames = [types.response.options(node), types.response.responses(node)];
|
|
924
|
-
const
|
|
971
|
+
const validatorHooks = buildValidatorHooks({
|
|
925
972
|
node,
|
|
926
973
|
validator,
|
|
927
974
|
zodResolver
|
|
928
|
-
})
|
|
975
|
+
});
|
|
976
|
+
const importedZodNames = validatorHooks.importedZodNames;
|
|
929
977
|
const meta = {
|
|
930
978
|
name: resolver.name(node.operationId),
|
|
931
979
|
file: resolver.file({
|
|
@@ -957,6 +1005,7 @@ function createClientGenerator(name, resolveClientPath) {
|
|
|
957
1005
|
const customClientPath = resolveClientPath?.(ctx.options, root);
|
|
958
1006
|
const clientPath = customClientPath ?? node_path.default.resolve(root, ".kubb/client.ts");
|
|
959
1007
|
const clientRoot = customClientPath === void 0 ? meta.file.path : void 0;
|
|
1008
|
+
const standardSchemaPath = customClientPath ?? node_path.default.resolve(root, ".kubb/standardSchema.ts");
|
|
960
1009
|
const eventStream = isEventStream(node);
|
|
961
1010
|
const clientValueImports = (() => {
|
|
962
1011
|
if (eventStream) return ["client", "toEventStream"];
|
|
@@ -1021,6 +1070,11 @@ function createClientGenerator(name, resolveClientPath) {
|
|
|
1021
1070
|
root: meta.file.path,
|
|
1022
1071
|
path: meta.fileZod.path
|
|
1023
1072
|
}),
|
|
1073
|
+
validatorHooks.headers && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
|
|
1074
|
+
name: ["toHeadersStandardSchema"],
|
|
1075
|
+
root: clientRoot,
|
|
1076
|
+
path: standardSchemaPath
|
|
1077
|
+
}),
|
|
1024
1078
|
/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(Operation, {
|
|
1025
1079
|
name: meta.name,
|
|
1026
1080
|
node,
|
|
@@ -1041,14 +1095,14 @@ function createClientGenerator(name, resolveClientPath) {
|
|
|
1041
1095
|
/**
|
|
1042
1096
|
* Builds the call config literal forwarded to the contract client; the `throwOnError` fallback is applied after the `...config` spread.
|
|
1043
1097
|
*/
|
|
1044
|
-
function buildCallConfig({ node,
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1098
|
+
function buildCallConfig({ node, validatorHooks, security, throwOnErrorDefault }) {
|
|
1099
|
+
const validatorLiteral = buildValidatorLiteral(validatorHooks, [
|
|
1100
|
+
"request",
|
|
1101
|
+
"path",
|
|
1102
|
+
"query",
|
|
1103
|
+
"headers",
|
|
1104
|
+
"response"
|
|
1105
|
+
]);
|
|
1052
1106
|
const securityLiteral = buildSecurityMetadata({ security });
|
|
1053
1107
|
const { literal: contentTypeLiteral } = buildContentType({ node });
|
|
1054
1108
|
return `{ ${[
|
|
@@ -1064,7 +1118,7 @@ function buildCallConfig({ node, validator, zodResolver, security, throwOnErrorD
|
|
|
1064
1118
|
/**
|
|
1065
1119
|
* Builds one instance method of a generated SDK class; a per-call `options.client` overrides `this.client`.
|
|
1066
1120
|
*/
|
|
1067
|
-
function buildSdkMethod({ node, name, types,
|
|
1121
|
+
function buildSdkMethod({ node, name, types, validatorHooks, security, returnType, throwOnErrorDefault }) {
|
|
1068
1122
|
if (!kubb_kit.ast.isHttpOperationNode(node)) return "";
|
|
1069
1123
|
const signature = buildGroupedOptionsSignature({
|
|
1070
1124
|
node,
|
|
@@ -1077,8 +1131,7 @@ function buildSdkMethod({ node, name, types, zodResolver, validator, security, r
|
|
|
1077
1131
|
types,
|
|
1078
1132
|
callConfig: buildCallConfig({
|
|
1079
1133
|
node,
|
|
1080
|
-
|
|
1081
|
-
zodResolver,
|
|
1134
|
+
validatorHooks,
|
|
1082
1135
|
security,
|
|
1083
1136
|
throwOnErrorDefault
|
|
1084
1137
|
}),
|
|
@@ -1104,13 +1157,12 @@ function buildSdkMethod({ node, name, types, zodResolver, validator, security, r
|
|
|
1104
1157
|
* instance: `const api = new PetClient({ baseURL }); api.getPetById(...)`. A per-call `client` option
|
|
1105
1158
|
* still overrides the instance client for a one-off call.
|
|
1106
1159
|
*/
|
|
1107
|
-
function SdkClient({ name, operations,
|
|
1108
|
-
const methods = operations.map(({ node, name: methodName, types,
|
|
1160
|
+
function SdkClient({ name, operations, returnType, throwOnErrorDefault }) {
|
|
1161
|
+
const methods = operations.map(({ node, name: methodName, types, validatorHooks, security }) => buildSdkMethod({
|
|
1109
1162
|
node,
|
|
1110
1163
|
name: methodName,
|
|
1111
1164
|
types,
|
|
1112
|
-
|
|
1113
|
-
validator,
|
|
1165
|
+
validatorHooks,
|
|
1114
1166
|
security,
|
|
1115
1167
|
returnType,
|
|
1116
1168
|
throwOnErrorDefault
|
|
@@ -1158,9 +1210,6 @@ function SdkFacade({ name, members }) {
|
|
|
1158
1210
|
function resolveTypeImportNames(node, types) {
|
|
1159
1211
|
return [types.response.options(node), types.response.responses(node)];
|
|
1160
1212
|
}
|
|
1161
|
-
function resolveZodImportNames(node, zodResolver, validator) {
|
|
1162
|
-
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));
|
|
1163
|
-
}
|
|
1164
1213
|
/**
|
|
1165
1214
|
* Groups operations into one controller per tag. Operations without a tag fall back to a single
|
|
1166
1215
|
* `Client`/`ApiClient` controller, matching the resolver's default naming.
|
|
@@ -1189,13 +1238,18 @@ function buildControllers(nodes, ctx, types) {
|
|
|
1189
1238
|
method: node.method,
|
|
1190
1239
|
path: node.path
|
|
1191
1240
|
}) : void 0;
|
|
1241
|
+
const validatorHooks = zodResolver ? buildValidatorHooks({
|
|
1242
|
+
node,
|
|
1243
|
+
validator,
|
|
1244
|
+
zodResolver
|
|
1245
|
+
}) : null;
|
|
1192
1246
|
return {
|
|
1193
1247
|
node,
|
|
1194
1248
|
name: resolver.name(node.operationId),
|
|
1195
1249
|
types,
|
|
1196
|
-
zodResolver,
|
|
1197
1250
|
typeFile,
|
|
1198
1251
|
zodFile,
|
|
1252
|
+
validatorHooks,
|
|
1199
1253
|
security
|
|
1200
1254
|
};
|
|
1201
1255
|
}
|
|
@@ -1268,6 +1322,7 @@ function createSdkGenerator() {
|
|
|
1268
1322
|
});
|
|
1269
1323
|
const controllers = buildControllers(nodes, ctx, resolveOperationTypes(ctx.driver, ctx.plugin.name));
|
|
1270
1324
|
const clientPath = node_path.default.resolve(root, ".kubb/client.ts");
|
|
1325
|
+
const standardSchemaPath = node_path.default.resolve(root, ".kubb/standardSchema.ts");
|
|
1271
1326
|
const banner = (file) => resolver.default.banner(ctx.meta, {
|
|
1272
1327
|
output,
|
|
1273
1328
|
config,
|
|
@@ -1291,7 +1346,7 @@ function createSdkGenerator() {
|
|
|
1291
1346
|
}));
|
|
1292
1347
|
const { namesByPath: zodNamesByPath, filesByPath: zodFilesByPath } = isValidatorEnabled(validator) ? collectImportsByFile(ops, (op) => ({
|
|
1293
1348
|
file: op.zodFile,
|
|
1294
|
-
names: op.
|
|
1349
|
+
names: op.validatorHooks?.importedZodNames.filter((name) => name !== op.validatorHooks?.error) ?? []
|
|
1295
1350
|
})) : {
|
|
1296
1351
|
namesByPath: /* @__PURE__ */ new Map(),
|
|
1297
1352
|
filesByPath: /* @__PURE__ */ new Map()
|
|
@@ -1341,10 +1396,14 @@ function createSdkGenerator() {
|
|
|
1341
1396
|
root: file.path,
|
|
1342
1397
|
path: zodFilesByPath.get(filePath).path
|
|
1343
1398
|
}, filePath)),
|
|
1399
|
+
ops.some((op) => op.validatorHooks?.headers) && /* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(kubb_jsx.File.Import, {
|
|
1400
|
+
name: ["toHeadersStandardSchema"],
|
|
1401
|
+
root: file.path,
|
|
1402
|
+
path: standardSchemaPath
|
|
1403
|
+
}),
|
|
1344
1404
|
/* @__PURE__ */ (0, kubb_jsx_jsx_runtime.jsx)(SdkClient, {
|
|
1345
1405
|
name: className,
|
|
1346
1406
|
operations: ops,
|
|
1347
|
-
validator,
|
|
1348
1407
|
returnType,
|
|
1349
1408
|
throwOnErrorDefault
|
|
1350
1409
|
})
|
|
@@ -1447,7 +1506,7 @@ var compatibility = {
|
|
|
1447
1506
|
};
|
|
1448
1507
|
//#endregion
|
|
1449
1508
|
//#region package.json
|
|
1450
|
-
var version = "5.9.
|
|
1509
|
+
var version = "5.9.1";
|
|
1451
1510
|
//#endregion
|
|
1452
1511
|
//#region src/templates.ts
|
|
1453
1512
|
/** Absolute path to the fetch client template, copied into `.kubb/client.ts`. */
|