@kubb/plugin-mcp 5.0.0-alpha.29 → 5.0.0-alpha.30

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.
@@ -1,7 +1,6 @@
1
1
  import path from 'node:path'
2
- import { caseParams, transform } from '@kubb/ast'
2
+ import { caseParams } from '@kubb/ast'
3
3
  import { defineGenerator } from '@kubb/core'
4
- import type { PluginZod } from '@kubb/plugin-zod'
5
4
  import { pluginZodName } from '@kubb/plugin-zod'
6
5
  import { File } from '@kubb/react-fabric'
7
6
  import { Server } from '../components/Server.tsx'
@@ -16,12 +15,11 @@ import type { PluginMcp } from '../types.ts'
16
15
  */
17
16
  export const serverGeneratorLegacy = defineGenerator<PluginMcp>({
18
17
  name: 'operations',
19
- type: 'react',
20
- Operations({ nodes, adapter, options, config, driver, resolver, plugin }) {
18
+ operations(nodes, options) {
19
+ const { adapter, config, resolver, plugin, driver, root } = this
21
20
  const { output, paramsCasing, group } = options
22
- const root = path.resolve(config.root, config.output.path)
23
21
 
24
- const pluginZod = driver.getPlugin<PluginZod>(pluginZodName)
22
+ const pluginZod = driver.getPlugin(pluginZodName)
25
23
 
26
24
  if (!pluginZod?.resolver) {
27
25
  return
@@ -43,18 +41,14 @@ export const serverGeneratorLegacy = defineGenerator<PluginMcp>({
43
41
  }
44
42
 
45
43
  const operationsMapped = nodes.map((node) => {
46
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node
47
- const casedParams = caseParams(transformedNode.parameters, paramsCasing)
44
+ const casedParams = caseParams(node.parameters, paramsCasing)
48
45
  const queryParams = casedParams.filter((p) => p.in === 'query')
49
46
  const headerParams = casedParams.filter((p) => p.in === 'header')
50
47
 
51
- const mcpFile = resolver.resolveFile(
52
- { name: transformedNode.operationId, extname: '.ts', tag: transformedNode.tags[0] ?? 'default', path: transformedNode.path },
53
- { root, output, group },
54
- )
48
+ const mcpFile = resolver.resolveFile({ name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path }, { root, output, group })
55
49
 
56
50
  const zodFile = pluginZod?.resolver.resolveFile(
57
- { name: transformedNode.operationId, extname: '.ts', tag: transformedNode.tags[0] ?? 'default', path: transformedNode.path },
51
+ { name: node.operationId, extname: '.ts', tag: node.tags[0] ?? 'default', path: node.path },
58
52
  {
59
53
  root,
60
54
  output: pluginZod?.options?.output ?? output,
@@ -62,21 +56,21 @@ export const serverGeneratorLegacy = defineGenerator<PluginMcp>({
62
56
  },
63
57
  )
64
58
 
65
- const requestName = transformedNode.requestBody?.schema ? pluginZod?.resolver.resolveDataName(transformedNode) : undefined
66
- const responseName = pluginZod?.resolver.resolveResponseName(transformedNode)
59
+ const requestName = node.requestBody?.schema ? pluginZod?.resolver.resolveDataName(node) : undefined
60
+ const responseName = pluginZod?.resolver.resolveResponseName(node)
67
61
 
68
- const zodQueryParams = queryParams.length ? pluginZod?.resolver.resolveQueryParamsName(transformedNode, queryParams[0]!) : undefined
62
+ const zodQueryParams = queryParams.length ? pluginZod?.resolver.resolveQueryParamsName(node, queryParams[0]!) : undefined
69
63
 
70
- const zodHeaderParams = headerParams.length ? pluginZod?.resolver.resolveHeaderParamsName(transformedNode, headerParams[0]!) : undefined
64
+ const zodHeaderParams = headerParams.length ? pluginZod?.resolver.resolveHeaderParamsName(node, headerParams[0]!) : undefined
71
65
 
72
66
  return {
73
67
  tool: {
74
- name: transformedNode.operationId,
75
- title: transformedNode.summary || undefined,
76
- description: transformedNode.description || `Make a ${transformedNode.method.toUpperCase()} request to ${transformedNode.path}`,
68
+ name: node.operationId,
69
+ title: node.summary || undefined,
70
+ description: node.description || `Make a ${node.method.toUpperCase()} request to ${node.path}`,
77
71
  },
78
72
  mcp: {
79
- name: resolver.resolveName(transformedNode.operationId),
73
+ name: resolver.resolveName(node.operationId),
80
74
  file: mcpFile,
81
75
  },
82
76
  zod: {
@@ -87,7 +81,7 @@ export const serverGeneratorLegacy = defineGenerator<PluginMcp>({
87
81
  responseName,
88
82
  file: zodFile,
89
83
  },
90
- node: transformedNode,
84
+ node: node,
91
85
  }
92
86
  })
93
87
 
package/src/plugin.ts CHANGED
@@ -1,14 +1,13 @@
1
1
  import path from 'node:path'
2
2
  import { camelCase } from '@internals/utils'
3
- import { walk } from '@kubb/ast'
4
- import type { OperationNode } from '@kubb/ast/types'
5
- import { createPlugin, type Group, getBarrelFiles, getPreset, runGeneratorOperation, runGeneratorOperations, runGeneratorSchema } from '@kubb/core'
6
- import { type PluginClient, pluginClientName } from '@kubb/plugin-client'
3
+ import { createPlugin, type Group, getPreset, mergeGenerators } from '@kubb/core'
4
+ import { pluginClientName } from '@kubb/plugin-client'
7
5
  import { source as axiosClientSource } from '@kubb/plugin-client/templates/clients/axios.source'
8
6
  import { source as fetchClientSource } from '@kubb/plugin-client/templates/clients/fetch.source'
9
7
  import { source as configSource } from '@kubb/plugin-client/templates/config.source'
10
8
  import { pluginTsName } from '@kubb/plugin-ts'
11
9
  import { pluginZodName } from '@kubb/plugin-zod'
10
+ import { version } from '../package.json'
12
11
  import { presets } from './presets.ts'
13
12
  import type { PluginMcp } from './types.ts'
14
13
 
@@ -40,8 +39,12 @@ export const pluginMcp = createPlugin<PluginMcp>((options) => {
40
39
  generators: userGenerators,
41
40
  })
42
41
 
42
+ const generators = preset.generators ?? []
43
+ const mergedGenerator = mergeGenerators(generators)
44
+
43
45
  return {
44
46
  name: pluginMcpName,
47
+ version,
45
48
  get resolver() {
46
49
  return preset.resolver
47
50
  },
@@ -51,6 +54,9 @@ export const pluginMcp = createPlugin<PluginMcp>((options) => {
51
54
  get options() {
52
55
  return {
53
56
  output,
57
+ exclude,
58
+ include,
59
+ override,
54
60
  group: group
55
61
  ? ({
56
62
  ...group,
@@ -78,21 +84,25 @@ export const pluginMcp = createPlugin<PluginMcp>((options) => {
78
84
  }
79
85
  },
80
86
  pre: [pluginTsName, pluginZodName].filter(Boolean),
81
- async install() {
82
- const { config, fabric, plugin, adapter, rootNode, driver } = this
83
- const root = path.resolve(config.root, config.output.path)
84
- const resolver = preset.resolver
85
-
86
- if (!adapter) {
87
- throw new Error('Plugin cannot work without adapter being set')
88
- }
87
+ async schema(node, options) {
88
+ return mergedGenerator.schema?.call(this, node, options)
89
+ },
90
+ async operation(node, options) {
91
+ return mergedGenerator.operation?.call(this, node, options)
92
+ },
93
+ async operations(nodes, options) {
94
+ return mergedGenerator.operations?.call(this, nodes, options)
95
+ },
96
+ async buildStart() {
97
+ const { adapter, driver } = this
98
+ const root = this.root
89
99
 
90
- const baseURL = adapter.rootNode?.meta?.baseURL
100
+ const baseURL = adapter?.rootNode?.meta?.baseURL
91
101
  if (baseURL) {
92
102
  this.plugin.options.client.baseURL = this.plugin.options.client.baseURL || baseURL
93
103
  }
94
104
 
95
- const hasClientPlugin = !!driver.getPlugin<PluginClient>(pluginClientName)
105
+ const hasClientPlugin = !!driver.getPlugin(pluginClientName)
96
106
 
97
107
  if (this.plugin.options.client.bundle && !hasClientPlugin && !this.plugin.options.client.importPath) {
98
108
  await this.addFile({
@@ -128,37 +138,7 @@ export const pluginMcp = createPlugin<PluginMcp>((options) => {
128
138
  })
129
139
  }
130
140
 
131
- const collectedOperations: Array<OperationNode> = []
132
- const generatorContext = { generators: preset.generators, plugin, resolver, exclude, include, override, fabric, adapter, config, driver }
133
-
134
- await walk(rootNode, {
135
- depth: 'shallow',
136
- async schema(schemaNode) {
137
- await runGeneratorSchema(schemaNode, generatorContext)
138
- },
139
- async operation(operationNode) {
140
- const baseOptions = resolver.resolveOptions(operationNode, { options: plugin.options, exclude, include, override })
141
-
142
- if (baseOptions !== null) {
143
- collectedOperations.push(operationNode)
144
- }
145
-
146
- await runGeneratorOperation(operationNode, generatorContext)
147
- },
148
- })
149
-
150
- await runGeneratorOperations(collectedOperations, generatorContext)
151
-
152
- const barrelFiles = await getBarrelFiles(this.fabric.files, {
153
- type: output.barrelType ?? 'named',
154
- root,
155
- output,
156
- meta: {
157
- pluginName: this.plugin.name,
158
- },
159
- })
160
-
161
- await this.upsertFile(...barrelFiles)
141
+ await this.openInStudio({ ast: true })
162
142
  },
163
143
  }
164
144
  })
package/src/types.ts CHANGED
@@ -83,6 +83,9 @@ export type Options = {
83
83
 
84
84
  type ResolvedOptions = {
85
85
  output: Output
86
+ exclude: Array<Exclude>
87
+ include: Array<Include> | undefined
88
+ override: Array<Override<ResolvedOptions>>
86
89
  group: Group | undefined
87
90
  client: Pick<PluginClient['options'], 'client' | 'clientType' | 'dataReturnType' | 'importPath' | 'baseURL' | 'bundle' | 'paramsCasing'>
88
91
  paramsCasing: Options['paramsCasing']
@@ -90,3 +93,11 @@ type ResolvedOptions = {
90
93
  }
91
94
 
92
95
  export type PluginMcp = PluginFactoryOptions<'plugin-mcp', Options, ResolvedOptions, never, ResolvePathOptions, ResolverMcp>
96
+
97
+ declare global {
98
+ namespace Kubb {
99
+ interface PluginRegistry {
100
+ 'plugin-mcp': PluginMcp
101
+ }
102
+ }
103
+ }