@kubb/plugin-mcp 5.0.0-beta.84 → 5.0.0-beta.86

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.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import "./rolldown-runtime-C0LytTxp.js";
2
- import path from "node:path";
3
- import { ast, defineGenerator, definePlugin, defineResolver } from "kubb/kit";
2
+ import { Resolver, ast, createResolver, defineGenerator, definePlugin } from "kubb/kit";
4
3
  import { Const, File, Function, jsxRenderer } from "kubb/jsx";
5
4
  import { Fragment, jsx, jsxs } from "kubb/jsx/jsx-runtime";
6
5
  import { createFunctionParameter, createFunctionParameters, createObjectBindingPattern, functionPrinter, pluginTsName } from "@kubb/plugin-ts";
6
+ import path from "node:path";
7
7
  import { pluginZodName } from "@kubb/plugin-zod";
8
8
  //#region ../../internals/utils/src/casing.ts
9
9
  /**
@@ -32,31 +32,6 @@ function camelCase(text, { prefix = "", suffix = "" } = {}) {
32
32
  return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
33
33
  }
34
34
  //#endregion
35
- //#region ../../internals/utils/src/fs.ts
36
- /**
37
- * Builds a nested file path from a dotted name. Splits on dots that precede a letter
38
- * (so version numbers embedded in operationIds like `v2025.0` stay intact), camelCases
39
- * every earlier segment, applies `caseLast` to the final segment, and joins with `/`.
40
- *
41
- * Empty segments are dropped before joining. They arise when the name starts with a dot
42
- * followed by a letter (e.g. `..Schema` splits into `['..', 'Schema']` and `'..'` cases to
43
- * an empty string). Without this a leading `/` would form, which `path.resolve` reads as an
44
- * absolute path, letting generated files escape the configured output directory.
45
- *
46
- * @example Nested path from a dotted name
47
- * `toFilePath('pet.petId') // 'pet/petId'`
48
- *
49
- * @example PascalCase the final segment
50
- * `toFilePath('pet.Pet', pascalCase) // 'pet/Pet'`
51
- *
52
- * @example Suffix applied to the final segment only
53
- * `toFilePath('tag.tag', (part) => camelCase(part, { suffix: 'schema' })) // 'tag/tagSchema'`
54
- */
55
- function toFilePath(name, caseLast = camelCase) {
56
- const parts = name.split(/\.(?=[a-zA-Z])/);
57
- return parts.map((part, i) => i === parts.length - 1 ? caseLast(part) : camelCase(part)).filter(Boolean).join("/");
58
- }
59
- //#endregion
60
35
  //#region ../../internals/utils/src/reserved.ts
61
36
  /**
62
37
  * JavaScript and Java reserved words.
@@ -312,13 +287,13 @@ function dedupeByCasedName(params) {
312
287
  //#region ../../internals/shared/src/operation.ts
313
288
  /**
314
289
  * Builds the `ResolverFileParams` every operation generator passes to
315
- * `resolver.resolveFile`: a file named `name`, tagged by the operation's first
290
+ * `resolver.file`: a file named `name`, tagged by the operation's first
316
291
  * tag (or `'default'`), at the operation's path. Centralizes the entry object
317
292
  * that was repeated at dozens of call sites across the client and query plugins.
318
293
  *
319
294
  * @example
320
295
  * ```ts
321
- * resolver.resolveFile(operationFileEntry(node, node.operationId), { root, output, group })
296
+ * resolver.file(operationFileEntry(node, node.operationId), { root, output, group })
322
297
  * ```
323
298
  */
324
299
  function operationFileEntry(node, name, extname = ".ts") {
@@ -401,7 +376,7 @@ function getRequestGroupOptionality(node) {
401
376
  }
402
377
  /**
403
378
  * Builds the grouped `{ path, query, body, headers }` parameter for a generated client
404
- * function, typed from the operation's `RequestConfig` (minus `url`). Only the groups the
379
+ * function, typed from the operation's `Options` (minus `url`). Only the groups the
405
380
  * operation actually has are destructured. The trailing `config` parameter carries the
406
381
  * runtime `RequestConfig` overrides plus `client`.
407
382
  */
@@ -415,7 +390,7 @@ function buildRequestParamsSignature(node, resolver, options = {}) {
415
390
  "headers"
416
391
  ].filter((key) => groups[key]);
417
392
  return {
418
- signature: [names.length > 0 ? `{ ${names.join(", ")} }: ${resolver.resolveRequestConfigName(node)}${isOptional ? " = {}" : ""}` : null, isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null].filter(Boolean).join(", "),
393
+ signature: [names.length > 0 ? `{ ${names.join(", ")} }: ${resolver.response.options(node)}${isOptional ? " = {}" : ""}` : null, isConfigurable ? `config: ${buildRequestConfigType(node)} = {}` : null].filter(Boolean).join(", "),
419
394
  groups
420
395
  };
421
396
  }
@@ -744,15 +719,15 @@ function resolveClientOperation(options) {
744
719
  const { clientPlugin, driver, node, root, output } = options;
745
720
  if (!clientPlugin) return null;
746
721
  const resolver = driver.getResolver(clientPlugin.pluginName);
747
- if (!resolver) return null;
748
722
  const plugin = driver.getPlugin(clientPlugin.pluginName);
749
- const file = resolver.resolveFile(operationFileEntry(node, node.operationId), {
723
+ const file = resolver.file({
724
+ ...operationFileEntry(node, node.operationId),
750
725
  root,
751
726
  output: plugin?.options?.output ?? output,
752
727
  group: plugin?.options?.group ?? void 0
753
728
  });
754
729
  return {
755
- name: resolver.resolveName(node.operationId),
730
+ name: resolver.name(node.operationId),
756
731
  path: file.path,
757
732
  clientPath: path.resolve(root, ".kubb/client.ts")
758
733
  };
@@ -783,25 +758,23 @@ const mcpGenerator = defineGenerator({
783
758
  output
784
759
  });
785
760
  if (!contractOp) return null;
786
- const requestConfigName = tsResolver.resolveRequestConfigName(node);
761
+ const optionsName = tsResolver.response.options(node);
787
762
  const meta = {
788
- name: resolver.resolveHandlerName(node),
789
- file: resolver.resolveFile({
763
+ name: resolver.handler.name(node),
764
+ file: resolver.file({
790
765
  name: node.operationId,
791
766
  extname: ".ts",
792
767
  tag: node.tags[0] ?? "default",
793
- path: node.path
794
- }, {
768
+ path: node.path,
795
769
  root,
796
770
  output,
797
771
  group: group ?? void 0
798
772
  }),
799
- fileTs: tsResolver.resolveFile({
773
+ fileTs: tsResolver.file({
800
774
  name: node.operationId,
801
775
  extname: ".ts",
802
776
  tag: node.tags[0] ?? "default",
803
- path: node.path
804
- }, {
777
+ path: node.path,
805
778
  root,
806
779
  output: pluginTs.options?.output ?? output,
807
780
  group: pluginTs.options?.group ?? void 0
@@ -812,8 +785,8 @@ const mcpGenerator = defineGenerator({
812
785
  path: meta.file.path,
813
786
  meta: meta.file.meta,
814
787
  children: [
815
- meta.fileTs && requestConfigName && /* @__PURE__ */ jsx(File.Import, {
816
- name: [requestConfigName],
788
+ meta.fileTs && optionsName && /* @__PURE__ */ jsx(File.Import, {
789
+ name: [optionsName],
817
790
  root: meta.file.path,
818
791
  path: meta.fileTs.path,
819
792
  isTypeOnly: true
@@ -878,32 +851,30 @@ const serverGenerator = defineGenerator({
878
851
  };
879
852
  const operationsMapped = nodes.filter(ast.isHttpOperationNode).map((node) => {
880
853
  const { path: pathParams, query: queryParams, header: headerParams } = getOperationParameters(node);
881
- const mcpFile = resolver.resolveFile({
854
+ const mcpFile = resolver.file({
882
855
  name: node.operationId,
883
856
  extname: ".ts",
884
857
  tag: node.tags[0] ?? "default",
885
- path: node.path
886
- }, {
858
+ path: node.path,
887
859
  root,
888
860
  output,
889
861
  group: group ?? void 0
890
862
  });
891
- const zodFile = zodResolver.resolveFile({
863
+ const zodFile = zodResolver.file({
892
864
  name: node.operationId,
893
865
  extname: ".ts",
894
866
  tag: node.tags[0] ?? "default",
895
- path: node.path
896
- }, {
867
+ path: node.path,
897
868
  root,
898
869
  output: pluginZod.options?.output ?? output,
899
870
  group: pluginZod.options?.group ?? void 0
900
871
  });
901
- const requestName = node.requestBody?.content?.[0]?.schema ? zodResolver.resolveDataName(node) : null;
872
+ const requestName = node.requestBody?.content?.[0]?.schema ? zodResolver.response.body(node) : null;
902
873
  const successStatus = findSuccessStatusCode(node.responses);
903
- const responseName = successStatus ? zodResolver.resolveResponseStatusName(node, successStatus) : null;
874
+ const responseName = successStatus ? zodResolver.response.status(node, successStatus) : null;
904
875
  const resolveParams = (params) => params.map((p) => ({
905
876
  name: p.name,
906
- schemaName: zodResolver.resolveParamName(node, p)
877
+ schemaName: zodResolver.param.name(node, p)
907
878
  }));
908
879
  return {
909
880
  tool: {
@@ -912,7 +883,7 @@ const serverGenerator = defineGenerator({
912
883
  description: node.description || `Make a ${node.method.toUpperCase()} request to ${node.path}`
913
884
  },
914
885
  mcp: {
915
- name: resolver.resolveHandlerName(node),
886
+ name: resolver.handler.name(node),
916
887
  file: mcpFile
917
888
  },
918
889
  zod: {
@@ -949,7 +920,7 @@ const serverGenerator = defineGenerator({
949
920
  baseName: serverFile.baseName,
950
921
  path: serverFile.path,
951
922
  meta: serverFile.meta,
952
- banner: resolver.resolveBanner(ctx.meta, {
923
+ banner: resolver.default.banner(ctx.meta, {
953
924
  output,
954
925
  config,
955
926
  file: {
@@ -957,7 +928,7 @@ const serverGenerator = defineGenerator({
957
928
  baseName: serverFile.baseName
958
929
  }
959
930
  }),
960
- footer: resolver.resolveFooter(ctx.meta, {
931
+ footer: resolver.default.footer(ctx.meta, {
961
932
  output,
962
933
  config,
963
934
  file: {
@@ -1018,26 +989,18 @@ const serverGenerator = defineGenerator({
1018
989
  * ```ts
1019
990
  * import { resolverMcp } from '@kubb/plugin-mcp'
1020
991
  *
1021
- * resolverMcp.default('addPet', 'function') // 'addPetHandler'
992
+ * resolverMcp.name('addPet') // 'addPetHandler'
1022
993
  * ```
1023
994
  */
1024
- const resolverMcp = defineResolver(() => ({
1025
- name: "default",
995
+ const resolverMcp = createResolver({
1026
996
  pluginName: "plugin-mcp",
1027
- default(name, type) {
1028
- if (type === "file") return toFilePath(name);
997
+ name(name) {
1029
998
  return camelCase(name, { suffix: "handler" });
1030
999
  },
1031
- resolveName(name) {
1032
- return this.default(name, "function");
1033
- },
1034
- resolvePathName(name, type) {
1035
- return this.default(name, type);
1036
- },
1037
- resolveHandlerName(node) {
1038
- return this.resolveName(node.operationId);
1039
- }
1040
- }));
1000
+ handler: { name(node) {
1001
+ return this.name(node.operationId);
1002
+ } }
1003
+ });
1041
1004
  //#endregion
1042
1005
  //#region src/plugin.ts
1043
1006
  /**
@@ -1083,10 +1046,7 @@ const pluginMcp = definePlugin((options) => {
1083
1046
  options,
1084
1047
  dependencies: [pluginTsName, pluginZodName],
1085
1048
  hooks: { "kubb:plugin:setup"(ctx) {
1086
- const resolver = userResolver ? {
1087
- ...resolverMcp,
1088
- ...userResolver
1089
- } : resolverMcp;
1049
+ const resolver = userResolver ? Resolver.merge(resolverMcp, userResolver) : resolverMcp;
1090
1050
  const resolvedClient = resolveClient({
1091
1051
  client,
1092
1052
  pluginNames: (ctx.config.plugins ?? []).map((p) => p.name).filter((name) => Boolean(name))