@kubb/plugin-client 5.7.0-canary.20261024T190549 → 5.7.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 +105 -51
- 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 +105 -51
- package/dist/index.js.map +1 -1
- package/docs/guides/validate-requests-and-responses.md +23 -0
- package/docs/options.md +9 -7
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -428,7 +428,7 @@ var compatibility = {
|
|
|
428
428
|
};
|
|
429
429
|
//#endregion
|
|
430
430
|
//#region package.json
|
|
431
|
-
var version = "5.7.
|
|
431
|
+
var version = "5.7.1";
|
|
432
432
|
//#endregion
|
|
433
433
|
//#region ../../internals/client/src/builders/validatorOptions.ts
|
|
434
434
|
/**
|
|
@@ -437,7 +437,7 @@ var version = "5.7.0-canary.20261024T190549";
|
|
|
437
437
|
function isValidatorEnabled(validator) {
|
|
438
438
|
if (!validator) return false;
|
|
439
439
|
if (validator === "zod") return true;
|
|
440
|
-
return Boolean(validator.request || validator.response);
|
|
440
|
+
return Boolean(validator.request || validator.params || validator.response);
|
|
441
441
|
}
|
|
442
442
|
/**
|
|
443
443
|
* Returns `'zod'` when request body parsing is enabled, `null` otherwise. The string shorthand
|
|
@@ -448,6 +448,14 @@ function resolveRequestValidator(validator) {
|
|
|
448
448
|
return validator.request ?? null;
|
|
449
449
|
}
|
|
450
450
|
/**
|
|
451
|
+
* Returns `'zod'` when path, query, and header params parsing is enabled, `null` otherwise. Only the
|
|
452
|
+
* object form `{ params: 'zod' }` enables it.
|
|
453
|
+
*/
|
|
454
|
+
function resolveParamsValidator(validator) {
|
|
455
|
+
if (!validator || validator === "zod") return null;
|
|
456
|
+
return validator.params ?? null;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
451
459
|
* Returns `'zod'` when response parsing is enabled, `null` otherwise. The string shorthand `'zod'`
|
|
452
460
|
* maps to response parsing.
|
|
453
461
|
*/
|
|
@@ -466,30 +474,6 @@ function buildZodErrorParse(node, zodResolver) {
|
|
|
466
474
|
return zodResolver.response.error?.(node) || null;
|
|
467
475
|
}
|
|
468
476
|
//#endregion
|
|
469
|
-
//#region ../../internals/client/src/builders/validator.ts
|
|
470
|
-
/**
|
|
471
|
-
* Builds the validator-hook references for one operation. Request validation runs before the send;
|
|
472
|
-
* response validation runs on the success body only. Returns `null` references when the matching
|
|
473
|
-
* direction is disabled or the schema is absent.
|
|
474
|
-
*/
|
|
475
|
-
function buildValidatorHooks({ node, validator, zodResolver }) {
|
|
476
|
-
const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
|
|
477
|
-
const parsesResponse = zodResolver && resolveResponseValidator(validator) === "zod";
|
|
478
|
-
const response = parsesResponse ? zodResolver.response.response(node) || null : null;
|
|
479
|
-
const error = parsesResponse ? buildZodErrorParse(node, zodResolver) : null;
|
|
480
|
-
const request = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) || null : null;
|
|
481
|
-
return {
|
|
482
|
-
request,
|
|
483
|
-
response,
|
|
484
|
-
error,
|
|
485
|
-
importedZodNames: [
|
|
486
|
-
response,
|
|
487
|
-
error,
|
|
488
|
-
request
|
|
489
|
-
].filter((name) => Boolean(name))
|
|
490
|
-
};
|
|
491
|
-
}
|
|
492
|
-
//#endregion
|
|
493
477
|
//#region ../../internals/client/src/builders/security.ts
|
|
494
478
|
function serializeAuth(auth) {
|
|
495
479
|
const parts = [`type: '${auth.type}'`];
|
|
@@ -562,6 +546,49 @@ function buildSecurityMetadata({ security }) {
|
|
|
562
546
|
return `[${security.map(serializeAuth).join(", ")}]`;
|
|
563
547
|
}
|
|
564
548
|
//#endregion
|
|
549
|
+
//#region ../../internals/client/src/builders/validator.ts
|
|
550
|
+
/**
|
|
551
|
+
* Builds the validator-hook references for one operation. Request body and params validation run before the send.
|
|
552
|
+
* Response validation runs on the success body only. Returns `null` references when the matching
|
|
553
|
+
* direction is disabled or the schema is absent.
|
|
554
|
+
*/
|
|
555
|
+
function buildValidatorHooks({ node, validator, zodResolver }) {
|
|
556
|
+
const hasRequestBody = Boolean(node.requestBody?.content?.[0]?.schema);
|
|
557
|
+
const parsesResponse = zodResolver && resolveResponseValidator(validator) === "zod";
|
|
558
|
+
const response = parsesResponse ? zodResolver.response.response(node) || null : null;
|
|
559
|
+
const error = parsesResponse ? buildZodErrorParse(node, zodResolver) : null;
|
|
560
|
+
const request = zodResolver && resolveRequestValidator(validator) === "zod" && hasRequestBody ? zodResolver.response.body(node) || null : null;
|
|
561
|
+
const paramGroups = getOperationParameters(node);
|
|
562
|
+
const resolveParamsName = (kind, params) => zodResolver && resolveParamsValidator(validator) === "zod" && params.length > 0 ? zodResolver.param[kind](node, params[0]) : null;
|
|
563
|
+
const path = resolveParamsName("path", paramGroups.path);
|
|
564
|
+
const query = resolveParamsName("query", paramGroups.query);
|
|
565
|
+
const headers = resolveParamsName("headers", paramGroups.header);
|
|
566
|
+
const importedZodNames = [
|
|
567
|
+
response,
|
|
568
|
+
error,
|
|
569
|
+
request,
|
|
570
|
+
path,
|
|
571
|
+
query,
|
|
572
|
+
headers
|
|
573
|
+
].filter((name) => Boolean(name));
|
|
574
|
+
return {
|
|
575
|
+
request,
|
|
576
|
+
path,
|
|
577
|
+
query,
|
|
578
|
+
headers: headers ? `toHeadersStandardSchema(${headers}, ${headers}.shape)` : null,
|
|
579
|
+
response,
|
|
580
|
+
error,
|
|
581
|
+
importedZodNames
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Prints the `validator: { … }` entry of a call config from the hooks named in `keys`, or `null` when none is set.
|
|
586
|
+
*/
|
|
587
|
+
function buildValidatorLiteral(hooks, keys) {
|
|
588
|
+
const entries = keys.flatMap((key) => hooks?.[key] ? [`${key}: ${hooks[key]}`] : []);
|
|
589
|
+
return entries.length ? `validator: { ${entries.join(", ")} }` : null;
|
|
590
|
+
}
|
|
591
|
+
//#endregion
|
|
565
592
|
//#region ../../internals/client/src/builders/contentType.ts
|
|
566
593
|
/**
|
|
567
594
|
* Builds the `contentType` entry baked into the call config, or `null` for the JSON default.
|
|
@@ -766,12 +793,14 @@ function Operation({ name, node, types, zodResolver, validator, returnType, thro
|
|
|
766
793
|
const eventStream = isEventStream(node);
|
|
767
794
|
const responseType = getResponseType(node);
|
|
768
795
|
const responseTypeLiteral = responseType ? `responseType: '${responseType}'` : null;
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
796
|
+
const validatorLiteral = buildValidatorLiteral(validators, [
|
|
797
|
+
"request",
|
|
798
|
+
"path",
|
|
799
|
+
"query",
|
|
800
|
+
"headers",
|
|
801
|
+
"response",
|
|
802
|
+
"error"
|
|
803
|
+
]);
|
|
775
804
|
const callConfig = `{ ${[
|
|
776
805
|
`method: '${node.method.toUpperCase()}'`,
|
|
777
806
|
`url: '${node.path}'`,
|
|
@@ -818,14 +847,35 @@ function Operation({ name, node, types, zodResolver, validator, returnType, thro
|
|
|
818
847
|
//#endregion
|
|
819
848
|
//#region ../../internals/client/src/resolveOperationTypes.ts
|
|
820
849
|
/**
|
|
821
|
-
*
|
|
850
|
+
* A `plugin-ts` shaped resolver whose operation type names point at the types `pluginZod({ inferred })`
|
|
851
|
+
* exports next to each schema, so code written against `plugin-ts` names picks up the zod types.
|
|
852
|
+
*/
|
|
853
|
+
function toZodTypeResolver(resolver) {
|
|
854
|
+
const type = (name) => resolver.schema.type(name);
|
|
855
|
+
return {
|
|
856
|
+
...resolver,
|
|
857
|
+
file: resolver.file.bind(resolver),
|
|
858
|
+
param: {
|
|
859
|
+
name: (node, p) => type(resolver.param.name(node, p)),
|
|
860
|
+
path: (node, p) => type(resolver.param.path(node, p)),
|
|
861
|
+
query: (node, p) => type(resolver.param.query(node, p)),
|
|
862
|
+
headers: (node, p) => type(resolver.param.headers(node, p))
|
|
863
|
+
},
|
|
864
|
+
response: {
|
|
865
|
+
body: (node) => type(resolver.response.body(node)),
|
|
866
|
+
status: (node, statusCode) => type(resolver.response.status(node, statusCode)),
|
|
867
|
+
response: (node) => type(resolver.response.response(node)),
|
|
868
|
+
responses: (node) => type(resolver.response.responses(node)),
|
|
869
|
+
options: (node) => resolver.response.options(node)
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
/**
|
|
874
|
+
* Picks the plugin generated clients, query hooks, and MCP handlers take their operation types from.
|
|
822
875
|
*
|
|
823
|
-
* `
|
|
824
|
-
*
|
|
825
|
-
*
|
|
826
|
-
* `z.infer` carries what the codecs decode to (a `Temporal` instance, a `Date`) rather than the raw
|
|
827
|
-
* wire type. Throws `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available, since the
|
|
828
|
-
* client has nothing to type against.
|
|
876
|
+
* `pluginZod({ inferred: 'codec' })` wins, so a codec param takes its domain value. Otherwise `plugin-ts`
|
|
877
|
+
* wins when it is in the pipeline, and without it any `pluginZod({ inferred })`. Throws
|
|
878
|
+
* `KUBB_MISSING_DEPENDENCY` for `pluginName` when neither is available.
|
|
829
879
|
*
|
|
830
880
|
* @example
|
|
831
881
|
* ```ts
|
|
@@ -835,16 +885,16 @@ function Operation({ name, node, types, zodResolver, validator, returnType, thro
|
|
|
835
885
|
*/
|
|
836
886
|
function resolveOperationTypes(driver, pluginName) {
|
|
837
887
|
const pluginTs = driver.getPlugin(pluginTsName);
|
|
838
|
-
|
|
888
|
+
const pluginZod = driver.getPlugin(pluginZodName);
|
|
889
|
+
if (pluginTs && pluginZod?.options?.inferred !== "codec") {
|
|
839
890
|
const resolver = driver.getResolver(pluginTsName);
|
|
840
891
|
return {
|
|
841
892
|
response: resolver.response,
|
|
842
893
|
resolver,
|
|
843
894
|
output: pluginTs.options?.output,
|
|
844
|
-
group: pluginTs.options?.group
|
|
895
|
+
group: pluginTs.options?.group ?? void 0
|
|
845
896
|
};
|
|
846
897
|
}
|
|
847
|
-
const pluginZod = driver.getPlugin(pluginZodName);
|
|
848
898
|
if (!pluginZod?.options?.inferred) throw new Diagnostics.Error({
|
|
849
899
|
code: Diagnostics.code.missingDependency,
|
|
850
900
|
severity: "error",
|
|
@@ -853,15 +903,12 @@ function resolveOperationTypes(driver, pluginName) {
|
|
|
853
903
|
location: { kind: "config" },
|
|
854
904
|
plugin: pluginName
|
|
855
905
|
});
|
|
856
|
-
const resolver = driver.getResolver(pluginZodName);
|
|
906
|
+
const resolver = toZodTypeResolver(driver.getResolver(pluginZodName));
|
|
857
907
|
return {
|
|
858
|
-
response:
|
|
859
|
-
options: resolver.response.options,
|
|
860
|
-
responses: (node) => resolver.schema.type(resolver.response.responses(node))
|
|
861
|
-
},
|
|
908
|
+
response: resolver.response,
|
|
862
909
|
resolver,
|
|
863
910
|
output: pluginZod.options.output,
|
|
864
|
-
group: pluginZod.options.group
|
|
911
|
+
group: pluginZod.options.group ?? void 0
|
|
865
912
|
};
|
|
866
913
|
}
|
|
867
914
|
//#endregion
|
|
@@ -883,14 +930,15 @@ function createClientGenerator(name, resolveClientPath) {
|
|
|
883
930
|
const { config, driver, resolver, root } = ctx;
|
|
884
931
|
const { output, validator, returnType, throwOnErrorDefault, group } = ctx.options;
|
|
885
932
|
const types = resolveOperationTypes(driver, ctx.plugin.name);
|
|
886
|
-
const pluginZod =
|
|
933
|
+
const pluginZod = isValidatorEnabled(validator) ? driver.getPlugin(pluginZodName) : null;
|
|
887
934
|
const zodResolver = pluginZod ? driver.getResolver(pluginZodName) : null;
|
|
888
935
|
const importedTypeNames = [types.response.options(node), types.response.responses(node)];
|
|
889
|
-
const
|
|
936
|
+
const validatorHooks = buildValidatorHooks({
|
|
890
937
|
node,
|
|
891
938
|
validator,
|
|
892
939
|
zodResolver
|
|
893
|
-
})
|
|
940
|
+
});
|
|
941
|
+
const importedZodNames = validatorHooks.importedZodNames;
|
|
894
942
|
const meta = {
|
|
895
943
|
name: resolver.name(node.operationId),
|
|
896
944
|
file: resolver.file({
|
|
@@ -922,6 +970,7 @@ function createClientGenerator(name, resolveClientPath) {
|
|
|
922
970
|
const customClientPath = resolveClientPath?.(ctx.options, root);
|
|
923
971
|
const clientPath = customClientPath ?? path.resolve(root, ".kubb/client.ts");
|
|
924
972
|
const clientRoot = customClientPath === void 0 ? meta.file.path : void 0;
|
|
973
|
+
const standardSchemaPath = customClientPath ?? path.resolve(root, ".kubb/standardSchema.ts");
|
|
925
974
|
const eventStream = isEventStream(node);
|
|
926
975
|
const clientValueImports = (() => {
|
|
927
976
|
if (eventStream) return ["client", "toEventStream"];
|
|
@@ -986,6 +1035,11 @@ function createClientGenerator(name, resolveClientPath) {
|
|
|
986
1035
|
root: meta.file.path,
|
|
987
1036
|
path: meta.fileZod.path
|
|
988
1037
|
}),
|
|
1038
|
+
validatorHooks.headers && /* @__PURE__ */ jsx(File.Import, {
|
|
1039
|
+
name: ["toHeadersStandardSchema"],
|
|
1040
|
+
root: clientRoot,
|
|
1041
|
+
path: standardSchemaPath
|
|
1042
|
+
}),
|
|
989
1043
|
/* @__PURE__ */ jsx(Operation, {
|
|
990
1044
|
name: meta.name,
|
|
991
1045
|
node,
|