@kubb/mcp 5.0.0-alpha.8 → 5.0.0-beta.75
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/README.md +8 -7
- package/dist/index.cjs +156 -69
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +155 -67
- package/dist/index.js.map +1 -1
- package/package.json +40 -42
- package/src/constants.ts +1 -0
- package/src/schemas/generateSchema.ts +0 -1
- package/src/tools/generate.ts +24 -27
- package/src/utils/loadUserConfig.ts +38 -16
- package/src/utils/resolveUserConfig.ts +8 -5
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ This starts an MCP server that communicates via stdio (standard input/output), m
|
|
|
49
49
|
Add to your MCP client configuration (e.g., [Claude Desktop](https://claude.ai/download)'s `claude_desktop_config.json`):
|
|
50
50
|
|
|
51
51
|
**Option 1: Using Kubb CLI (recommended):**
|
|
52
|
+
|
|
52
53
|
```json
|
|
53
54
|
{
|
|
54
55
|
"mcpServers": {
|
|
@@ -61,6 +62,7 @@ Add to your MCP client configuration (e.g., [Claude Desktop](https://claude.ai/d
|
|
|
61
62
|
```
|
|
62
63
|
|
|
63
64
|
**Option 2: Using standalone bin:**
|
|
65
|
+
|
|
64
66
|
```json
|
|
65
67
|
{
|
|
66
68
|
"mcpServers": {
|
|
@@ -93,6 +95,7 @@ For project-specific configurations, you can specify the working directory:
|
|
|
93
95
|
Generate code from OpenAPI/Swagger specifications using Kubb configuration.
|
|
94
96
|
|
|
95
97
|
**Parameters:**
|
|
98
|
+
|
|
96
99
|
- `config` (string, optional): Path to kubb.config.ts file. If not provided, looks for kubb.config.ts in current directory
|
|
97
100
|
- `input` (string, optional): Path to OpenAPI/Swagger spec file (overrides config file setting)
|
|
98
101
|
- `output` (string, optional): Output directory path (overrides config file setting)
|
|
@@ -101,6 +104,7 @@ Generate code from OpenAPI/Swagger specifications using Kubb configuration.
|
|
|
101
104
|
**Examples:**
|
|
102
105
|
|
|
103
106
|
Using default config file:
|
|
107
|
+
|
|
104
108
|
```json
|
|
105
109
|
{
|
|
106
110
|
"config": "./kubb.config.ts"
|
|
@@ -108,6 +112,7 @@ Using default config file:
|
|
|
108
112
|
```
|
|
109
113
|
|
|
110
114
|
Overriding input and output:
|
|
115
|
+
|
|
111
116
|
```json
|
|
112
117
|
{
|
|
113
118
|
"config": "./kubb.config.ts",
|
|
@@ -117,6 +122,7 @@ Overriding input and output:
|
|
|
117
122
|
```
|
|
118
123
|
|
|
119
124
|
With verbose logging:
|
|
125
|
+
|
|
120
126
|
```json
|
|
121
127
|
{
|
|
122
128
|
"config": "./kubb.config.ts",
|
|
@@ -131,7 +137,7 @@ The build tool looks for `kubb.config.ts` in the current directory by default. Y
|
|
|
131
137
|
Example `kubb.config.ts`:
|
|
132
138
|
|
|
133
139
|
```typescript
|
|
134
|
-
import { defineConfig } from '
|
|
140
|
+
import { defineConfig } from 'kubb'
|
|
135
141
|
import { pluginOas } from '@kubb/plugin-oas'
|
|
136
142
|
import { pluginTs } from '@kubb/plugin-ts'
|
|
137
143
|
import { pluginClient } from '@kubb/plugin-client'
|
|
@@ -143,11 +149,6 @@ export default defineConfig({
|
|
|
143
149
|
output: {
|
|
144
150
|
path: './src/generated',
|
|
145
151
|
},
|
|
146
|
-
plugins: [
|
|
147
|
-
pluginOas(),
|
|
148
|
-
pluginTs(),
|
|
149
|
-
pluginClient(),
|
|
150
|
-
],
|
|
152
|
+
plugins: [pluginOas(), pluginTs(), pluginClient()],
|
|
151
153
|
})
|
|
152
154
|
```
|
|
153
|
-
|
package/dist/index.cjs
CHANGED
|
@@ -22,18 +22,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
}) : target, mod));
|
|
23
23
|
//#endregion
|
|
24
24
|
let node_process = require("node:process");
|
|
25
|
-
node_process = __toESM(node_process);
|
|
25
|
+
node_process = __toESM(node_process, 1);
|
|
26
26
|
let _modelcontextprotocol_sdk_server_mcp_js = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
27
27
|
let _modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
28
28
|
let zod = require("zod");
|
|
29
29
|
let node_events = require("node:events");
|
|
30
|
+
let node_fs = require("node:fs");
|
|
30
31
|
let node_path = require("node:path");
|
|
31
|
-
node_path = __toESM(node_path);
|
|
32
|
+
node_path = __toESM(node_path, 1);
|
|
32
33
|
let _kubb_core = require("@kubb/core");
|
|
33
|
-
let
|
|
34
|
-
jiti = __toESM(jiti);
|
|
34
|
+
let unrun = require("unrun");
|
|
35
35
|
//#region package.json
|
|
36
|
-
var version = "5.0.0-
|
|
36
|
+
var version = "5.0.0-beta.75";
|
|
37
37
|
//#endregion
|
|
38
38
|
//#region src/schemas/generateSchema.ts
|
|
39
39
|
const generateSchema = zod.z.object({
|
|
@@ -53,8 +53,14 @@ const generateSchema = zod.z.object({
|
|
|
53
53
|
//#region ../../internals/utils/src/errors.ts
|
|
54
54
|
/**
|
|
55
55
|
* Coerces an unknown thrown value to an `Error` instance.
|
|
56
|
-
*
|
|
57
|
-
*
|
|
56
|
+
* Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* try { ... } catch(err) {
|
|
61
|
+
* throw new BuildError('Build failed', { cause: toError(err), errors: [] })
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
58
64
|
*/
|
|
59
65
|
function toError(value) {
|
|
60
66
|
return value instanceof Error ? value : new Error(String(value));
|
|
@@ -62,12 +68,19 @@ function toError(value) {
|
|
|
62
68
|
//#endregion
|
|
63
69
|
//#region ../../internals/utils/src/asyncEventEmitter.ts
|
|
64
70
|
/**
|
|
65
|
-
*
|
|
71
|
+
* Typed `EventEmitter` that awaits all async listeners before resolving.
|
|
66
72
|
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
|
|
77
|
+
* emitter.on('build', async (name) => { console.log(name) })
|
|
78
|
+
* await emitter.emit('build', 'petstore') // all listeners awaited
|
|
79
|
+
* ```
|
|
67
80
|
*/
|
|
68
81
|
var AsyncEventEmitter = class {
|
|
69
82
|
/**
|
|
70
|
-
*
|
|
83
|
+
* Maximum number of listeners per event before Node emits a memory-leak warning.
|
|
71
84
|
* @default 10
|
|
72
85
|
*/
|
|
73
86
|
constructor(maxListener = 10) {
|
|
@@ -75,31 +88,48 @@ var AsyncEventEmitter = class {
|
|
|
75
88
|
}
|
|
76
89
|
#emitter = new node_events.EventEmitter();
|
|
77
90
|
/**
|
|
78
|
-
* Emits
|
|
91
|
+
* Emits `eventName` and awaits all registered listeners sequentially.
|
|
79
92
|
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* await emitter.emit('build', 'petstore')
|
|
97
|
+
* ```
|
|
80
98
|
*/
|
|
81
99
|
async emit(eventName, ...eventArgs) {
|
|
82
100
|
const listeners = this.#emitter.listeners(eventName);
|
|
83
101
|
if (listeners.length === 0) return;
|
|
84
|
-
|
|
102
|
+
for (const listener of listeners) try {
|
|
103
|
+
await listener(...eventArgs);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
let serializedArgs;
|
|
85
106
|
try {
|
|
86
|
-
|
|
87
|
-
} catch
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
serializedArgs = JSON.stringify(eventArgs);
|
|
91
|
-
} catch {
|
|
92
|
-
serializedArgs = String(eventArgs);
|
|
93
|
-
}
|
|
94
|
-
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
|
|
107
|
+
serializedArgs = JSON.stringify(eventArgs);
|
|
108
|
+
} catch {
|
|
109
|
+
serializedArgs = String(eventArgs);
|
|
95
110
|
}
|
|
96
|
-
|
|
111
|
+
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
|
|
112
|
+
}
|
|
97
113
|
}
|
|
98
|
-
/**
|
|
114
|
+
/**
|
|
115
|
+
* Registers a persistent listener for `eventName`.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* emitter.on('build', async (name) => { console.log(name) })
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
99
122
|
on(eventName, handler) {
|
|
100
123
|
this.#emitter.on(eventName, handler);
|
|
101
124
|
}
|
|
102
|
-
/**
|
|
125
|
+
/**
|
|
126
|
+
* Registers a one-shot listener that removes itself after the first invocation.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* emitter.onOnce('build', async (name) => { console.log(name) })
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
103
133
|
onOnce(eventName, handler) {
|
|
104
134
|
const wrapper = (...args) => {
|
|
105
135
|
this.off(eventName, wrapper);
|
|
@@ -107,18 +137,51 @@ var AsyncEventEmitter = class {
|
|
|
107
137
|
};
|
|
108
138
|
this.on(eventName, wrapper);
|
|
109
139
|
}
|
|
110
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* Removes a previously registered listener.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* emitter.off('build', handler)
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
111
148
|
off(eventName, handler) {
|
|
112
149
|
this.#emitter.off(eventName, handler);
|
|
113
150
|
}
|
|
114
|
-
/**
|
|
151
|
+
/**
|
|
152
|
+
* Returns the number of listeners registered for `eventName`.
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* emitter.on('build', handler)
|
|
157
|
+
* emitter.listenerCount('build') // 1
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
listenerCount(eventName) {
|
|
161
|
+
return this.#emitter.listenerCount(eventName);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Removes all listeners from every event channel.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* emitter.removeAll()
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
115
171
|
removeAll() {
|
|
116
172
|
this.#emitter.removeAllListeners();
|
|
117
173
|
}
|
|
118
174
|
};
|
|
119
175
|
//#endregion
|
|
120
176
|
//#region ../../internals/utils/src/promise.ts
|
|
121
|
-
/** Returns `true` when `result` is a thenable `Promise`.
|
|
177
|
+
/** Returns `true` when `result` is a thenable `Promise`.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* isPromise(Promise.resolve(1)) // true
|
|
182
|
+
* isPromise(42) // false
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
122
185
|
function isPromise(result) {
|
|
123
186
|
return result !== null && result !== void 0 && typeof result["then"] === "function";
|
|
124
187
|
}
|
|
@@ -148,19 +211,48 @@ const NotifyTypes = {
|
|
|
148
211
|
FATAL_ERROR: "FATAL_ERROR"
|
|
149
212
|
};
|
|
150
213
|
//#endregion
|
|
214
|
+
//#region src/constants.ts
|
|
215
|
+
const ALLOWED_CONFIG_EXTENSIONS = new Set([
|
|
216
|
+
".ts",
|
|
217
|
+
".mts",
|
|
218
|
+
".cts",
|
|
219
|
+
".js",
|
|
220
|
+
".mjs",
|
|
221
|
+
".cjs"
|
|
222
|
+
]);
|
|
223
|
+
//#endregion
|
|
151
224
|
//#region src/utils/loadUserConfig.ts
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
225
|
+
const loadedModules = /* @__PURE__ */ new Map();
|
|
226
|
+
async function loadModule(filePath) {
|
|
227
|
+
const ext = node_path.default.extname(filePath);
|
|
228
|
+
if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) throw new Error(`Invalid config file extension "${ext}". Allowed: ${[...ALLOWED_CONFIG_EXTENSIONS].join(", ")}`);
|
|
229
|
+
if (loadedModules.has(filePath)) return loadedModules.get(filePath);
|
|
230
|
+
const { module } = await (0, unrun.unrun)({ path: filePath });
|
|
231
|
+
loadedModules.set(filePath, module);
|
|
232
|
+
return module;
|
|
233
|
+
}
|
|
156
234
|
async function loadUserConfig(configPath, { notify }) {
|
|
157
235
|
let userConfig;
|
|
158
236
|
let cwd;
|
|
159
237
|
if (configPath) {
|
|
160
|
-
|
|
238
|
+
const ext = node_path.default.extname(configPath);
|
|
239
|
+
if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) {
|
|
240
|
+
const msg = `Invalid config file extension "${ext}". Allowed: ${[...ALLOWED_CONFIG_EXTENSIONS].join(", ")}`;
|
|
241
|
+
await notify(NotifyTypes.CONFIG_ERROR, msg);
|
|
242
|
+
throw new Error(msg);
|
|
243
|
+
}
|
|
244
|
+
const base = node_path.default.resolve(process.cwd());
|
|
245
|
+
const resolvedConfigPath = node_path.default.resolve(base, configPath);
|
|
246
|
+
const relative = node_path.default.relative(base, resolvedConfigPath);
|
|
247
|
+
if (relative.startsWith("..") || node_path.default.isAbsolute(relative)) {
|
|
248
|
+
const msg = "Invalid config file path: must be within the current working directory";
|
|
249
|
+
await notify(NotifyTypes.CONFIG_ERROR, msg);
|
|
250
|
+
throw new Error(msg);
|
|
251
|
+
}
|
|
252
|
+
cwd = node_path.default.dirname(resolvedConfigPath);
|
|
161
253
|
try {
|
|
162
|
-
userConfig = await
|
|
163
|
-
await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${
|
|
254
|
+
userConfig = await loadModule(resolvedConfigPath);
|
|
255
|
+
await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${resolvedConfigPath}`);
|
|
164
256
|
} catch (error) {
|
|
165
257
|
await notify(NotifyTypes.CONFIG_ERROR, `Failed to load config: ${error instanceof Error ? error.message : String(error)}`);
|
|
166
258
|
throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -169,15 +261,20 @@ async function loadUserConfig(configPath, { notify }) {
|
|
|
169
261
|
cwd = process.cwd();
|
|
170
262
|
const configFileNames = [
|
|
171
263
|
"kubb.config.ts",
|
|
264
|
+
"kubb.config.mts",
|
|
265
|
+
"kubb.config.cts",
|
|
172
266
|
"kubb.config.js",
|
|
173
267
|
"kubb.config.cjs"
|
|
174
268
|
];
|
|
175
|
-
for (const configFileName of configFileNames)
|
|
269
|
+
for (const configFileName of configFileNames) {
|
|
176
270
|
const configFilePath = node_path.default.resolve(process.cwd(), configFileName);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
271
|
+
if (!(0, node_fs.existsSync)(configFilePath)) continue;
|
|
272
|
+
try {
|
|
273
|
+
userConfig = await loadModule(configFilePath);
|
|
274
|
+
await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`);
|
|
275
|
+
break;
|
|
276
|
+
} catch {}
|
|
277
|
+
}
|
|
181
278
|
if (!userConfig) {
|
|
182
279
|
await notify(NotifyTypes.CONFIG_ERROR, "No config file found");
|
|
183
280
|
throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(", ")}`);
|
|
@@ -208,10 +305,10 @@ function resolveCwd(userConfig, cwd) {
|
|
|
208
305
|
/**
|
|
209
306
|
* Resolve the config by handling function configs and returning the final configuration
|
|
210
307
|
*/
|
|
211
|
-
async function resolveUserConfig(
|
|
212
|
-
let kubbUserConfig = Promise.resolve(
|
|
213
|
-
if (typeof
|
|
214
|
-
const possiblePromise =
|
|
308
|
+
async function resolveUserConfig(config, options) {
|
|
309
|
+
let kubbUserConfig = Promise.resolve(config);
|
|
310
|
+
if (typeof config === "function") {
|
|
311
|
+
const possiblePromise = config({
|
|
215
312
|
logLevel: options.logLevel,
|
|
216
313
|
config: options.configPath
|
|
217
314
|
});
|
|
@@ -229,7 +326,7 @@ async function resolveUserConfig(userConfig, options) {
|
|
|
229
326
|
async function generate(schema, handler) {
|
|
230
327
|
const { config: configPath, input, output, logLevel } = schema;
|
|
231
328
|
try {
|
|
232
|
-
const
|
|
329
|
+
const hooks = new AsyncEventEmitter();
|
|
233
330
|
const messages = [];
|
|
234
331
|
const notify = async (type, message, data) => {
|
|
235
332
|
messages.push(`${type}: ${message}`);
|
|
@@ -240,37 +337,37 @@ async function generate(schema, handler) {
|
|
|
240
337
|
...data
|
|
241
338
|
});
|
|
242
339
|
};
|
|
243
|
-
|
|
340
|
+
hooks.on("kubb:info", async ({ message }) => {
|
|
244
341
|
await notify(NotifyTypes.INFO, message);
|
|
245
342
|
});
|
|
246
|
-
|
|
343
|
+
hooks.on("kubb:success", async ({ message }) => {
|
|
247
344
|
await notify(NotifyTypes.SUCCESS, message);
|
|
248
345
|
});
|
|
249
|
-
|
|
346
|
+
hooks.on("kubb:error", async ({ error }) => {
|
|
250
347
|
await notify(NotifyTypes.ERROR, error.message, { stack: error.stack });
|
|
251
348
|
});
|
|
252
|
-
|
|
349
|
+
hooks.on("kubb:warn", async ({ message }) => {
|
|
253
350
|
await notify(NotifyTypes.WARN, message);
|
|
254
351
|
});
|
|
255
|
-
|
|
256
|
-
await notify(NotifyTypes.PLUGIN_START, `Plugin starting: ${name}`);
|
|
352
|
+
hooks.on("kubb:plugin:start", async ({ plugin }) => {
|
|
353
|
+
await notify(NotifyTypes.PLUGIN_START, `Plugin starting: ${plugin.name}`);
|
|
257
354
|
});
|
|
258
|
-
|
|
259
|
-
await notify(NotifyTypes.PLUGIN_END, `Plugin finished: ${name}`, { duration });
|
|
355
|
+
hooks.on("kubb:plugin:end", async ({ plugin, duration }) => {
|
|
356
|
+
await notify(NotifyTypes.PLUGIN_END, `Plugin finished: ${plugin.name}`, { duration });
|
|
260
357
|
});
|
|
261
|
-
|
|
358
|
+
hooks.on("kubb:files:processing:start", async () => {
|
|
262
359
|
await notify(NotifyTypes.FILES_START, "Starting file processing");
|
|
263
360
|
});
|
|
264
|
-
|
|
361
|
+
hooks.on("kubb:file:processing:update", async ({ file }) => {
|
|
265
362
|
await notify(NotifyTypes.FILE_UPDATE, `Processing file: ${file.name}`);
|
|
266
363
|
});
|
|
267
|
-
|
|
364
|
+
hooks.on("kubb:files:processing:end", async () => {
|
|
268
365
|
await notify(NotifyTypes.FILES_END, "File processing complete");
|
|
269
366
|
});
|
|
270
|
-
|
|
367
|
+
hooks.on("kubb:generation:start", async () => {
|
|
271
368
|
await notify(NotifyTypes.GENERATION_START, "Generation started");
|
|
272
369
|
});
|
|
273
|
-
|
|
370
|
+
hooks.on("kubb:generation:end", async () => {
|
|
274
371
|
await notify(NotifyTypes.GENERATION_END, "Generation ended");
|
|
275
372
|
});
|
|
276
373
|
let userConfig;
|
|
@@ -310,21 +407,11 @@ async function generate(schema, handler) {
|
|
|
310
407
|
};
|
|
311
408
|
await notify(NotifyTypes.CONFIG_READY, "Configuration ready", { root: config.root });
|
|
312
409
|
await notify(NotifyTypes.SETUP_START, "Setting up Kubb");
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
events
|
|
316
|
-
});
|
|
410
|
+
const kubb = (0, _kubb_core.createKubb)(config, { hooks });
|
|
411
|
+
await kubb.setup();
|
|
317
412
|
await notify(NotifyTypes.SETUP_END, "Kubb setup complete");
|
|
318
413
|
await notify(NotifyTypes.BUILD_START, "Starting build");
|
|
319
|
-
const { files, failedPlugins, error } = await
|
|
320
|
-
config,
|
|
321
|
-
events
|
|
322
|
-
}, {
|
|
323
|
-
driver,
|
|
324
|
-
fabric,
|
|
325
|
-
events,
|
|
326
|
-
sources
|
|
327
|
-
});
|
|
414
|
+
const { files, failedPlugins, error } = await kubb.safeBuild();
|
|
328
415
|
await notify(NotifyTypes.BUILD_END, `Build complete - Generated ${files.length} files`);
|
|
329
416
|
if (error || failedPlugins.size > 0) {
|
|
330
417
|
const allErrors = [error, ...Array.from(failedPlugins).filter((it) => it.error).map((it) => it.error)].filter(Boolean);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["z","#emitter","NodeEventEmitter","jiti","path","path","StdioServerTransport","McpServer"],"sources":["../package.json","../src/schemas/generateSchema.ts","../../../internals/utils/src/errors.ts","../../../internals/utils/src/asyncEventEmitter.ts","../../../internals/utils/src/promise.ts","../src/types.ts","../src/utils/loadUserConfig.ts","../src/utils/resolveCwd.ts","../src/utils/resolveUserConfig.ts","../src/tools/generate.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["","import { z } from 'zod'\n\nexport const generateSchema = z.object({\n config: z\n .string()\n .optional()\n\n .describe('Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory'),\n input: z.string().optional().describe('Path to OpenAPI/Swagger spec file (overrides config)'),\n output: z.string().optional().describe('Output directory path (overrides config)'),\n logLevel: z.enum(['silent', 'error', 'warn', 'info', 'verbose', 'debug']).optional().default('info').describe('Log level for build output'),\n})\n\n","/** Thrown when a plugin's configuration or input fails validation. */\nexport class ValidationPluginError extends Error {}\n\n/**\n * Thrown when one or more errors occur during a Kubb build.\n * Carries the full list of underlying errors on `errors`.\n */\nexport class BuildError extends Error {\n errors: Array<Error>\n\n constructor(message: string, options: { cause?: Error; errors: Array<Error> }) {\n super(message, { cause: options.cause })\n this.name = 'BuildError'\n this.errors = options.errors\n }\n}\n\n/**\n * Coerces an unknown thrown value to an `Error` instance.\n * When the value is already an `Error` it is returned as-is;\n * otherwise a new `Error` is created whose message is `String(value)`.\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Safely extracts a human-readable message from any thrown value.\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n\n/**\n * Extracts the `.cause` of an `Error` as an `Error | undefined`.\n * Returns `undefined` when the cause is absent or is not an `Error`.\n */\nexport function toCause(error: Error): Error | undefined {\n return error.cause instanceof Error ? error.cause : undefined\n}\n","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport { toError } from './errors.ts'\n\n/** A function that can be registered as an event listener, synchronous or async. */\ntype AsyncListener<TArgs extends unknown[]> = (...args: TArgs) => void | Promise<void>\n\n/**\n * A typed EventEmitter that awaits all async listeners before resolving.\n * Wraps Node's `EventEmitter` with full TypeScript event-map inference.\n */\nexport class AsyncEventEmitter<TEvents extends { [K in keyof TEvents]: unknown[] }> {\n /**\n * `maxListener` controls the maximum number of listeners per event before Node emits a memory-leak warning.\n * @default 10\n */\n constructor(maxListener = 10) {\n this.#emitter.setMaxListeners(maxListener)\n }\n\n #emitter = new NodeEventEmitter()\n\n /**\n * Emits an event and awaits all registered listeners in parallel.\n * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.\n */\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<AsyncListener<TEvents[TEventName]>>\n\n if (listeners.length === 0) {\n return undefined\n }\n\n await Promise.all(\n listeners.map(async (listener) => {\n try {\n return await listener(...eventArgs)\n } catch (err) {\n let serializedArgs: string\n try {\n serializedArgs = JSON.stringify(eventArgs)\n } catch {\n serializedArgs = String(eventArgs)\n }\n throw new Error(`Error in async listener for \"${eventName}\" with eventArgs ${serializedArgs}`, { cause: toError(err) })\n }\n }),\n )\n }\n\n /** Registers a persistent listener for the given event. */\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.on(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /** Registers a one-shot listener that removes itself after the first invocation. */\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n const wrapper: AsyncListener<TEvents[TEventName]> = (...args) => {\n this.off(eventName, wrapper)\n return handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n /** Removes a previously registered listener. */\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.off(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /** Removes all listeners from every event channel. */\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","/** A value that may already be resolved or still pending. */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`. */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\n/** Type guard for a fulfilled `Promise.allSettled` result. */\nexport function isPromiseFulfilledResult<T = unknown>(result: PromiseSettledResult<unknown>): result is PromiseFulfilledResult<T> {\n return result.status === 'fulfilled'\n}\n\n/** Type guard for a rejected `Promise.allSettled` result with a typed `reason`. */\nexport function isPromiseRejectedResult<T>(result: PromiseSettledResult<unknown>): result is Omit<PromiseRejectedResult, 'reason'> & { reason: T } {\n return result.status === 'rejected'\n}\n","export const NotifyTypes = {\n INFO: 'INFO',\n SUCCESS: 'SUCCESS',\n ERROR: 'ERROR',\n WARN: 'WARN',\n PLUGIN_START: 'PLUGIN_START',\n PLUGIN_END: 'PLUGIN_END',\n FILES_START: 'FILES_START',\n FILE_UPDATE: 'FILE_UPDATE',\n FILES_END: 'FILES_END',\n GENERATION_START: 'GENERATION_START',\n GENERATION_END: 'GENERATION_END',\n CONFIG_LOADED: 'CONFIG_LOADED',\n CONFIG_ERROR: 'CONFIG_ERROR',\n CONFIG_READY: 'CONFIG_READY',\n SETUP_START: 'SETUP_START',\n SETUP_END: 'SETUP_END',\n BUILD_START: 'BUILD_START',\n BUILD_END: 'BUILD_END',\n BUILD_FAILED: 'BUILD_FAILED',\n BUILD_SUCCESS: 'BUILD_SUCCESS',\n FATAL_ERROR: 'FATAL_ERROR',\n} as const\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\nimport createJiti from 'jiti'\nimport { NotifyTypes } from '../types.ts'\n\ntype NotifyFunction = (type: string, message: string, data?: Record<string, unknown>) => Promise<void>\n\nconst jiti = createJiti(import.meta.url, {\n sourceMaps: true,\n})\n\n/**\n * Load the user configuration from the specified path or current directory\n */\nexport async function loadUserConfig(configPath: string | undefined, { notify }: { notify: NotifyFunction }): Promise<{ userConfig: Config; cwd: string }> {\n let userConfig: Config | undefined\n let cwd: string\n\n if (configPath) {\n // Resolve the config path to absolute path and get its directory\n cwd = path.dirname(path.resolve(configPath))\n\n // Try to load from path\n try {\n userConfig = await jiti.import(configPath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${configPath}`)\n } catch (error) {\n await notify(NotifyTypes.CONFIG_ERROR, `Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n }\n } else {\n // Look for kubb.config in current directory with various extensions\n cwd = process.cwd()\n const configFileNames = ['kubb.config.ts', 'kubb.config.js', 'kubb.config.cjs']\n\n for (const configFileName of configFileNames) {\n try {\n const configFilePath = path.resolve(process.cwd(), configFileName)\n userConfig = await jiti.import(configFilePath, { default: true })\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`)\n break\n } catch {\n // Continue trying next config file\n }\n }\n\n if (!userConfig) {\n await notify(NotifyTypes.CONFIG_ERROR, 'No config file found')\n\n throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(', ')}`)\n }\n }\n\n return { userConfig: userConfig!, cwd }\n}\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\n\n/**\n * Determine the root directory based on userConfig.root and resolvedConfigDir\n * 1. If userConfig.root exists and is absolute, use it as-is\n * 2. If userConfig.root exists and is relative, resolve it relative to config directory\n * 3. Otherwise, use the config directory as root\n */\nexport function resolveCwd(userConfig: Config, cwd: string): string {\n if (userConfig.root) {\n if (path.isAbsolute(userConfig.root)) {\n return userConfig.root\n }\n\n return path.resolve(cwd, userConfig.root)\n }\n\n return cwd\n}\n","import { isPromise } from '@internals/utils'\nimport type { CLIOptions, Config, UserConfig } from '@kubb/core'\n\nexport type ResolveUserConfigOptions = {\n configPath?: string\n logLevel?: string\n}\n\n/**\n * Resolve the config by handling function configs and returning the final configuration\n */\nexport async function resolveUserConfig(userConfig: UserConfig, options: ResolveUserConfigOptions): Promise<Config> {\n let kubbUserConfig = Promise.resolve(userConfig) as Promise<UserConfig>\n\n if (typeof userConfig === 'function') {\n const possiblePromise = (userConfig as any)({ logLevel: options.logLevel, config: options.configPath } as CLIOptions)\n if (isPromise(possiblePromise)) {\n kubbUserConfig = possiblePromise\n } else {\n kubbUserConfig = Promise.resolve(possiblePromise)\n }\n }\n\n return (await kubbUserConfig) as Config\n}\n","import { AsyncEventEmitter } from '@internals/utils'\nimport { type Config, type KubbEvents, safeBuild, setup } from '@kubb/core'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.d.ts'\nimport type { z } from 'zod'\nimport type { generateSchema } from '../schemas/generateSchema.ts'\nimport { NotifyTypes } from '../types.ts'\nimport { loadUserConfig } from '../utils/loadUserConfig.ts'\nimport { resolveCwd } from '../utils/resolveCwd.ts'\nimport { resolveUserConfig } from '../utils/resolveUserConfig.ts'\n\ninterface NotificationHandler {\n sendNotification(method: string, params: unknown): Promise<void>\n}\n\n/**\n * Build tool that generates code from OpenAPI specs using Kubb.\n * Sends real-time notifications of build progress and events.\n */\nexport async function generate(schema: z.infer<typeof generateSchema>, handler: NotificationHandler): Promise<CallToolResult> {\n const { config: configPath, input, output, logLevel } = schema\n\n try {\n const events = new AsyncEventEmitter<KubbEvents>()\n const messages: string[] = []\n\n // Helper to send notifications\n const notify = async (type: string, message: string, data?: Record<string, unknown>) => {\n messages.push(`${type}: ${message}`)\n\n await handler.sendNotification('kubb/progress', {\n type,\n message,\n timestamp: new Date().toISOString(),\n ...data,\n })\n }\n\n // Capture events for output and send notifications\n events.on('info', async (message: string) => {\n await notify(NotifyTypes.INFO, message)\n })\n\n events.on('success', async (message: string) => {\n await notify(NotifyTypes.SUCCESS, message)\n })\n\n events.on('error', async (error: Error) => {\n await notify(NotifyTypes.ERROR, error.message, { stack: error.stack })\n })\n\n events.on('warn', async (message: string) => {\n await notify(NotifyTypes.WARN, message)\n })\n\n // Plugin lifecycle events\n events.on('plugin:start', async ({ name }: { name: string }) => {\n await notify(NotifyTypes.PLUGIN_START, `Plugin starting: ${name}`)\n })\n\n events.on('plugin:end', async ({ name, duration }: { name: string; duration?: number }) => {\n await notify(NotifyTypes.PLUGIN_END, `Plugin finished: ${name}`, { duration })\n })\n\n // File processing events\n events.on('files:processing:start', async () => {\n await notify(NotifyTypes.FILES_START, 'Starting file processing')\n })\n\n events.on('file:processing:update', async ({ file }: { file: { name: string } }) => {\n await notify(NotifyTypes.FILE_UPDATE, `Processing file: ${file.name}`)\n })\n\n events.on('files:processing:end', async () => {\n await notify(NotifyTypes.FILES_END, 'File processing complete')\n })\n\n // Generation events\n events.on('generation:start', async () => {\n await notify(NotifyTypes.GENERATION_START, 'Generation started')\n })\n\n events.on('generation:end', async () => {\n await notify(NotifyTypes.GENERATION_END, 'Generation ended')\n })\n\n // Load and process configuration\n let userConfig: Config\n let cwd: string\n\n try {\n const configResult = await loadUserConfig(configPath, { notify })\n userConfig = configResult.userConfig\n cwd = configResult.cwd\n\n if (Array.isArray(userConfig) && userConfig.length) {\n throw new Error('Array type in kubb.config.ts is not supported in this tool. Please provide a single configuration object.')\n }\n\n userConfig = await resolveUserConfig(userConfig, { configPath, logLevel })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n await notify(NotifyTypes.CONFIG_ERROR, errorMessage)\n return {\n content: [\n {\n type: 'text',\n text: errorMessage,\n },\n ],\n isError: true,\n }\n }\n\n const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)\n\n // Override config with CLI options\n const config: Config = {\n ...userConfig,\n root: resolveCwd(userConfig, cwd),\n input: inputPath\n ? {\n ...userConfig.input,\n path: inputPath,\n }\n : userConfig.input,\n output: output\n ? {\n ...userConfig.output,\n path: output,\n }\n : userConfig.output,\n }\n\n await notify(NotifyTypes.CONFIG_READY, 'Configuration ready', {\n root: config.root,\n })\n\n // Setup and build\n await notify(NotifyTypes.SETUP_START, 'Setting up Kubb')\n\n const { fabric, driver, sources } = await setup({\n config,\n events,\n })\n await notify(NotifyTypes.SETUP_END, 'Kubb setup complete')\n\n await notify(NotifyTypes.BUILD_START, 'Starting build')\n const { files, failedPlugins, error } = await safeBuild(\n {\n config,\n events,\n },\n { driver, fabric, events, sources },\n )\n await notify(NotifyTypes.BUILD_END, `Build complete - Generated ${files.length} files`)\n\n if (error || failedPlugins.size > 0) {\n const allErrors: Error[] = [\n error,\n ...Array.from(failedPlugins)\n .filter((it) => it.error)\n .map((it) => it.error),\n ].filter(Boolean)\n\n await notify(NotifyTypes.BUILD_FAILED, `Build failed with ${allErrors.length} error(s)`, {\n errorCount: allErrors.length,\n errors: allErrors.map((err) => err.message),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build failed:\\n${allErrors.map((err) => err.message).join('\\n')}\\n\\n${messages.join('\\n')}`,\n },\n ],\n isError: true,\n }\n }\n\n await notify(NotifyTypes.BUILD_SUCCESS, `Build completed successfully - Generated ${files.length} files`, {\n filesCount: files.length,\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build completed successfully!\\n\\nGenerated ${files.length} files\\n\\n${messages.join('\\n')}`,\n },\n ],\n }\n } catch (caughtError) {\n const error = caughtError as Error\n\n await handler.sendNotification('kubb/progress', {\n type: NotifyTypes.FATAL_ERROR,\n message: error.message,\n stack: error.stack,\n timestamp: new Date().toISOString(),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build error: ${error.message}\\n${error.stack || ''}`,\n },\n ],\n isError: true,\n }\n }\n}\n","import process from 'node:process'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { version } from '../package.json'\nimport { generateSchema } from './schemas/generateSchema.ts'\nimport { generate } from './tools/generate.ts'\n\n/**\n * Kubb MCP Server\n *\n * Provides tools for building OpenAPI specifications using Kubb.\n */\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n const server = new McpServer({\n name: 'Kubb',\n version,\n })\n\n // Build tool - runs Kubb build using @kubb/core\n // Wrapped to pass notification handler for real-time progress updates\n server.tool('generate', 'Generate OpenAPI spec helpers using Kubb configuration', generateSchema.shape, async (args) => {\n // Create notification handler that sends events back to the client\n const notificationHandler = {\n sendNotification: async (method: string, params: any) => {\n try {\n await transport.send({\n jsonrpc: '2.0',\n method,\n params,\n })\n } catch (error) {\n console.error('Failed to send notification:', error)\n }\n },\n }\n\n // Call build tool with notification handler\n return generate(args, notificationHandler)\n })\n\n await server.connect(transport)\n } catch (error) {\n console.error('Failed to start MCP server:', error)\n process.exit(1)\n }\n}\n","import { startServer } from './server.ts'\n\nexport async function run(_argv?: string[]): Promise<void> {\n await startServer()\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["z","#emitter","NodeEventEmitter","path","path","StdioServerTransport","McpServer"],"sources":["../package.json","../src/schemas/generateSchema.ts","../../../internals/utils/src/errors.ts","../../../internals/utils/src/asyncEventEmitter.ts","../../../internals/utils/src/promise.ts","../src/types.ts","../src/constants.ts","../src/utils/loadUserConfig.ts","../src/utils/resolveCwd.ts","../src/utils/resolveUserConfig.ts","../src/tools/generate.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["","import { z } from 'zod'\n\nexport const generateSchema = z.object({\n config: z\n .string()\n .optional()\n\n .describe('Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory'),\n input: z.string().optional().describe('Path to OpenAPI/Swagger spec file (overrides config)'),\n output: z.string().optional().describe('Output directory path (overrides config)'),\n logLevel: z.enum(['silent', 'error', 'warn', 'info', 'verbose', 'debug']).optional().default('info').describe('Log level for build output'),\n})\n","/**\n * Thrown when one or more errors occur during a Kubb build.\n * Carries the full list of underlying errors on `errors`.\n *\n * @example\n * ```ts\n * throw new BuildError('Build failed', { errors: [err1, err2] })\n * ```\n */\nexport class BuildError extends Error {\n errors: Array<Error>\n\n constructor(message: string, options: { cause?: Error; errors: Array<Error> }) {\n super(message, { cause: options.cause })\n this.name = 'BuildError'\n this.errors = options.errors\n }\n}\n\n/**\n * Coerces an unknown thrown value to an `Error` instance.\n * Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.\n *\n * @example\n * ```ts\n * try { ... } catch(err) {\n * throw new BuildError('Build failed', { cause: toError(err), errors: [] })\n * }\n * ```\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value))\n}\n\n/**\n * Extracts a human-readable message from any thrown value.\n *\n * @example\n * ```ts\n * getErrorMessage(new Error('oops')) // 'oops'\n * getErrorMessage('plain string') // 'plain string'\n * ```\n */\nexport function getErrorMessage(value: unknown): string {\n return value instanceof Error ? value.message : String(value)\n}\n\n/**\n * Extracts the `.cause` of an `Error` as an `Error`, or `undefined` when absent or not an `Error`.\n *\n * @example\n * ```ts\n * const cause = toCause(buildError) // Error | undefined\n * ```\n */\nexport function toCause(error: Error): Error | undefined {\n return error.cause instanceof Error ? error.cause : undefined\n}\n","import { EventEmitter as NodeEventEmitter } from 'node:events'\nimport { toError } from './errors.ts'\n\n/**\n * A function that can be registered as an event listener, synchronous or async.\n */\ntype AsyncListener<TArgs extends unknown[]> = (...args: TArgs) => void | Promise<void>\n\n/**\n * Typed `EventEmitter` that awaits all async listeners before resolving.\n * Wraps Node's `EventEmitter` with full TypeScript event-map inference.\n *\n * @example\n * ```ts\n * const emitter = new AsyncEventEmitter<{ build: [name: string] }>()\n * emitter.on('build', async (name) => { console.log(name) })\n * await emitter.emit('build', 'petstore') // all listeners awaited\n * ```\n */\nexport class AsyncEventEmitter<TEvents extends { [K in keyof TEvents]: unknown[] }> {\n /**\n * Maximum number of listeners per event before Node emits a memory-leak warning.\n * @default 10\n */\n constructor(maxListener = 10) {\n this.#emitter.setMaxListeners(maxListener)\n }\n\n #emitter = new NodeEventEmitter()\n\n /**\n * Emits `eventName` and awaits all registered listeners sequentially.\n * Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.\n *\n * @example\n * ```ts\n * await emitter.emit('build', 'petstore')\n * ```\n */\n async emit<TEventName extends keyof TEvents & string>(eventName: TEventName, ...eventArgs: TEvents[TEventName]): Promise<void> {\n const listeners = this.#emitter.listeners(eventName) as Array<AsyncListener<TEvents[TEventName]>>\n\n if (listeners.length === 0) {\n return\n }\n\n for (const listener of listeners) {\n try {\n await listener(...eventArgs)\n } catch (err) {\n let serializedArgs: string\n try {\n serializedArgs = JSON.stringify(eventArgs)\n } catch {\n serializedArgs = String(eventArgs)\n }\n throw new Error(`Error in async listener for \"${eventName}\" with eventArgs ${serializedArgs}`, { cause: toError(err) })\n }\n }\n }\n\n /**\n * Registers a persistent listener for `eventName`.\n *\n * @example\n * ```ts\n * emitter.on('build', async (name) => { console.log(name) })\n * ```\n */\n on<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.on(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /**\n * Registers a one-shot listener that removes itself after the first invocation.\n *\n * @example\n * ```ts\n * emitter.onOnce('build', async (name) => { console.log(name) })\n * ```\n */\n onOnce<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n const wrapper: AsyncListener<TEvents[TEventName]> = (...args) => {\n this.off(eventName, wrapper)\n return handler(...args)\n }\n this.on(eventName, wrapper)\n }\n\n /**\n * Removes a previously registered listener.\n *\n * @example\n * ```ts\n * emitter.off('build', handler)\n * ```\n */\n off<TEventName extends keyof TEvents & string>(eventName: TEventName, handler: AsyncListener<TEvents[TEventName]>): void {\n this.#emitter.off(eventName, handler as AsyncListener<unknown[]>)\n }\n\n /**\n * Returns the number of listeners registered for `eventName`.\n *\n * @example\n * ```ts\n * emitter.on('build', handler)\n * emitter.listenerCount('build') // 1\n * ```\n */\n listenerCount<TEventName extends keyof TEvents & string>(eventName: TEventName): number {\n return this.#emitter.listenerCount(eventName)\n }\n\n /**\n * Removes all listeners from every event channel.\n *\n * @example\n * ```ts\n * emitter.removeAll()\n * ```\n */\n removeAll(): void {\n this.#emitter.removeAllListeners()\n }\n}\n","/** A value that may already be resolved or still pending.\n *\n * @example\n * ```ts\n * function load(id: string): PossiblePromise<string> {\n * return cache.get(id) ?? fetchRemote(id)\n * }\n * ```\n */\nexport type PossiblePromise<T> = Promise<T> | T\n\n/** Returns `true` when `result` is a thenable `Promise`.\n *\n * @example\n * ```ts\n * isPromise(Promise.resolve(1)) // true\n * isPromise(42) // false\n * ```\n */\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return result !== null && result !== undefined && typeof (result as Record<string, unknown>)['then'] === 'function'\n}\n\n/** Returns `true` when `result` is a fulfilled `Promise.allSettled` result.\n *\n * @example\n * ```ts\n * const results = await Promise.allSettled([p1, p2])\n * results.filter(isPromiseFulfilledResult).map((r) => r.value)\n * ```\n */\nexport function isPromiseFulfilledResult<T = unknown>(result: PromiseSettledResult<unknown>): result is PromiseFulfilledResult<T> {\n return result.status === 'fulfilled'\n}\n\n/** Returns `true` when `result` is a rejected `Promise.allSettled` result with a typed `reason`.\n *\n * @example\n * ```ts\n * const results = await Promise.allSettled([p1, p2])\n * results.filter(isPromiseRejectedResult<Error>).map((r) => r.reason.message)\n * ```\n */\nexport function isPromiseRejectedResult<T>(result: PromiseSettledResult<unknown>): result is Omit<PromiseRejectedResult, 'reason'> & { reason: T } {\n return result.status === 'rejected'\n}\n","export const NotifyTypes = {\n INFO: 'INFO',\n SUCCESS: 'SUCCESS',\n ERROR: 'ERROR',\n WARN: 'WARN',\n PLUGIN_START: 'PLUGIN_START',\n PLUGIN_END: 'PLUGIN_END',\n FILES_START: 'FILES_START',\n FILE_UPDATE: 'FILE_UPDATE',\n FILES_END: 'FILES_END',\n GENERATION_START: 'GENERATION_START',\n GENERATION_END: 'GENERATION_END',\n CONFIG_LOADED: 'CONFIG_LOADED',\n CONFIG_ERROR: 'CONFIG_ERROR',\n CONFIG_READY: 'CONFIG_READY',\n SETUP_START: 'SETUP_START',\n SETUP_END: 'SETUP_END',\n BUILD_START: 'BUILD_START',\n BUILD_END: 'BUILD_END',\n BUILD_FAILED: 'BUILD_FAILED',\n BUILD_SUCCESS: 'BUILD_SUCCESS',\n FATAL_ERROR: 'FATAL_ERROR',\n} as const\n","export const ALLOWED_CONFIG_EXTENSIONS = new Set(['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs'])\n","import { existsSync } from 'node:fs'\nimport path from 'node:path'\nimport type { Config } from '@kubb/core'\nimport { unrun } from 'unrun'\nimport { ALLOWED_CONFIG_EXTENSIONS } from '../constants.ts'\nimport { NotifyTypes } from '../types.ts'\n\ntype NotifyFunction = (type: string, message: string, data?: Record<string, unknown>) => Promise<void>\n\nconst loadedModules = new Map<string, unknown>()\n\nasync function loadModule(filePath: string): Promise<unknown> {\n const ext = path.extname(filePath)\n if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) {\n throw new Error(`Invalid config file extension \"${ext}\". Allowed: ${[...ALLOWED_CONFIG_EXTENSIONS].join(', ')}`)\n }\n if (loadedModules.has(filePath)) {\n return loadedModules.get(filePath)\n }\n const { module } = await unrun({ path: filePath })\n loadedModules.set(filePath, module)\n return module\n}\n\nexport async function loadUserConfig(configPath: string | undefined, { notify }: { notify: NotifyFunction }): Promise<{ userConfig: Config; cwd: string }> {\n let userConfig: Config | undefined\n let cwd: string\n\n if (configPath) {\n const ext = path.extname(configPath)\n if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) {\n const msg = `Invalid config file extension \"${ext}\". Allowed: ${[...ALLOWED_CONFIG_EXTENSIONS].join(', ')}`\n await notify(NotifyTypes.CONFIG_ERROR, msg)\n throw new Error(msg)\n }\n const base = path.resolve(process.cwd())\n const resolvedConfigPath = path.resolve(base, configPath)\n const relative = path.relative(base, resolvedConfigPath)\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n const msg = 'Invalid config file path: must be within the current working directory'\n await notify(NotifyTypes.CONFIG_ERROR, msg)\n throw new Error(msg)\n }\n cwd = path.dirname(resolvedConfigPath)\n\n try {\n userConfig = (await loadModule(resolvedConfigPath)) as Config\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded config from ${resolvedConfigPath}`)\n } catch (error) {\n await notify(NotifyTypes.CONFIG_ERROR, `Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`)\n }\n } else {\n cwd = process.cwd()\n const configFileNames = ['kubb.config.ts', 'kubb.config.mts', 'kubb.config.cts', 'kubb.config.js', 'kubb.config.cjs']\n\n for (const configFileName of configFileNames) {\n const configFilePath = path.resolve(process.cwd(), configFileName)\n if (!existsSync(configFilePath)) continue\n try {\n userConfig = (await loadModule(configFilePath)) as Config\n await notify(NotifyTypes.CONFIG_LOADED, `Loaded ${configFileName} from current directory`)\n break\n } catch {\n // Continue trying next config file\n }\n }\n\n if (!userConfig) {\n await notify(NotifyTypes.CONFIG_ERROR, 'No config file found')\n\n throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(', ')}`)\n }\n }\n\n return { userConfig: userConfig!, cwd }\n}\n","import path from 'node:path'\nimport type { Config } from '@kubb/core'\n\n/**\n * Determine the root directory based on userConfig.root and resolvedConfigDir\n * 1. If userConfig.root exists and is absolute, use it as-is\n * 2. If userConfig.root exists and is relative, resolve it relative to config directory\n * 3. Otherwise, use the config directory as root\n */\nexport function resolveCwd(userConfig: Config, cwd: string): string {\n if (userConfig.root) {\n if (path.isAbsolute(userConfig.root)) {\n return userConfig.root\n }\n\n return path.resolve(cwd, userConfig.root)\n }\n\n return cwd\n}\n","import { isPromise } from '@internals/utils'\nimport type { CLIOptions, Config } from '@kubb/core'\n\nexport type ResolveUserConfigOptions = {\n configPath?: string\n logLevel?: string\n}\n\n/**\n * Resolve the config by handling function configs and returning the final configuration\n */\nexport async function resolveUserConfig(config: Config, options: ResolveUserConfigOptions): Promise<Config> {\n let kubbUserConfig = Promise.resolve(config) as Promise<Config>\n\n if (typeof config === 'function') {\n const possiblePromise = (config as any)({\n logLevel: options.logLevel,\n config: options.configPath,\n } as CLIOptions)\n if (isPromise(possiblePromise)) {\n kubbUserConfig = possiblePromise\n } else {\n kubbUserConfig = Promise.resolve(possiblePromise)\n }\n }\n\n return (await kubbUserConfig) as Config\n}\n","import { AsyncEventEmitter } from '@internals/utils'\nimport { type Config, createKubb, type KubbHooks } from '@kubb/core'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.d.ts'\nimport type { z } from 'zod'\nimport type { generateSchema } from '../schemas/generateSchema.ts'\nimport { NotifyTypes } from '../types.ts'\nimport { loadUserConfig } from '../utils/loadUserConfig.ts'\nimport { resolveCwd } from '../utils/resolveCwd.ts'\nimport { resolveUserConfig } from '../utils/resolveUserConfig.ts'\n\ninterface NotificationHandler {\n sendNotification(method: string, params: unknown): Promise<void>\n}\n\n/**\n * Build tool that generates code from OpenAPI specs using Kubb.\n * Sends real-time notifications of build progress and events.\n */\nexport async function generate(schema: z.infer<typeof generateSchema>, handler: NotificationHandler): Promise<CallToolResult> {\n const { config: configPath, input, output, logLevel } = schema\n\n try {\n const hooks = new AsyncEventEmitter<KubbHooks>()\n const messages: string[] = []\n\n // Helper to send notifications\n const notify = async (type: string, message: string, data?: Record<string, unknown>) => {\n messages.push(`${type}: ${message}`)\n\n await handler.sendNotification('kubb/progress', {\n type,\n message,\n timestamp: new Date().toISOString(),\n ...data,\n })\n }\n\n // Capture events for output and send notifications\n hooks.on('kubb:info', async ({ message }: { message: string }) => {\n await notify(NotifyTypes.INFO, message)\n })\n\n hooks.on('kubb:success', async ({ message }: { message: string }) => {\n await notify(NotifyTypes.SUCCESS, message)\n })\n\n hooks.on('kubb:error', async ({ error }: { error: Error }) => {\n await notify(NotifyTypes.ERROR, error.message, { stack: error.stack })\n })\n\n hooks.on('kubb:warn', async ({ message }: { message: string }) => {\n await notify(NotifyTypes.WARN, message)\n })\n\n // Plugin lifecycle events\n hooks.on('kubb:plugin:start', async ({ plugin }) => {\n await notify(NotifyTypes.PLUGIN_START, `Plugin starting: ${plugin.name}`)\n })\n\n hooks.on('kubb:plugin:end', async ({ plugin, duration }) => {\n await notify(NotifyTypes.PLUGIN_END, `Plugin finished: ${plugin.name}`, {\n duration,\n })\n })\n\n // File processing events\n hooks.on('kubb:files:processing:start', async () => {\n await notify(NotifyTypes.FILES_START, 'Starting file processing')\n })\n\n hooks.on('kubb:file:processing:update', async ({ file }: { file: { name: string } }) => {\n await notify(NotifyTypes.FILE_UPDATE, `Processing file: ${file.name}`)\n })\n\n hooks.on('kubb:files:processing:end', async () => {\n await notify(NotifyTypes.FILES_END, 'File processing complete')\n })\n\n // Generation events\n hooks.on('kubb:generation:start', async () => {\n await notify(NotifyTypes.GENERATION_START, 'Generation started')\n })\n\n hooks.on('kubb:generation:end', async () => {\n await notify(NotifyTypes.GENERATION_END, 'Generation ended')\n })\n\n // Load and process configuration\n let userConfig: Config\n let cwd: string\n\n try {\n const configResult = await loadUserConfig(configPath, { notify })\n userConfig = configResult.userConfig\n cwd = configResult.cwd\n\n if (Array.isArray(userConfig) && userConfig.length) {\n throw new Error('Array type in kubb.config.ts is not supported in this tool. Please provide a single configuration object.')\n }\n\n userConfig = await resolveUserConfig(userConfig, {\n configPath,\n logLevel,\n })\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n await notify(NotifyTypes.CONFIG_ERROR, errorMessage)\n return {\n content: [\n {\n type: 'text',\n text: errorMessage,\n },\n ],\n isError: true,\n }\n }\n\n const inputPath = input ?? ('path' in userConfig.input ? userConfig.input.path : undefined)\n\n // Override config with CLI options\n const config: Config = {\n ...userConfig,\n root: resolveCwd(userConfig, cwd),\n input: inputPath\n ? {\n ...userConfig.input,\n path: inputPath,\n }\n : userConfig.input,\n output: output\n ? {\n ...userConfig.output,\n path: output,\n }\n : userConfig.output,\n }\n\n await notify(NotifyTypes.CONFIG_READY, 'Configuration ready', {\n root: config.root,\n })\n\n // Setup and build\n await notify(NotifyTypes.SETUP_START, 'Setting up Kubb')\n\n const kubb = createKubb(config, { hooks })\n await kubb.setup()\n await notify(NotifyTypes.SETUP_END, 'Kubb setup complete')\n\n await notify(NotifyTypes.BUILD_START, 'Starting build')\n const { files, failedPlugins, error } = await kubb.safeBuild()\n await notify(NotifyTypes.BUILD_END, `Build complete - Generated ${files.length} files`)\n\n if (error || failedPlugins.size > 0) {\n const allErrors: Error[] = [\n error,\n ...Array.from(failedPlugins)\n .filter((it) => it.error)\n .map((it) => it.error),\n ].filter(Boolean)\n\n await notify(NotifyTypes.BUILD_FAILED, `Build failed with ${allErrors.length} error(s)`, {\n errorCount: allErrors.length,\n errors: allErrors.map((err) => err.message),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build failed:\\n${allErrors.map((err) => err.message).join('\\n')}\\n\\n${messages.join('\\n')}`,\n },\n ],\n isError: true,\n }\n }\n\n await notify(NotifyTypes.BUILD_SUCCESS, `Build completed successfully - Generated ${files.length} files`, {\n filesCount: files.length,\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build completed successfully!\\n\\nGenerated ${files.length} files\\n\\n${messages.join('\\n')}`,\n },\n ],\n }\n } catch (caughtError) {\n const error = caughtError as Error\n\n await handler.sendNotification('kubb/progress', {\n type: NotifyTypes.FATAL_ERROR,\n message: error.message,\n stack: error.stack,\n timestamp: new Date().toISOString(),\n })\n\n return {\n content: [\n {\n type: 'text',\n text: `Build error: ${error.message}\\n${error.stack || ''}`,\n },\n ],\n isError: true,\n }\n }\n}\n","import process from 'node:process'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { version } from '../package.json'\nimport { generateSchema } from './schemas/generateSchema.ts'\nimport { generate } from './tools/generate.ts'\n\n/**\n * Kubb MCP Server\n *\n * Provides tools for building OpenAPI specifications using Kubb.\n */\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n const server = new McpServer({\n name: 'Kubb',\n version,\n })\n\n // Build tool - runs Kubb build using @kubb/core\n // Wrapped to pass notification handler for real-time progress updates\n server.tool('generate', 'Generate OpenAPI spec helpers using Kubb configuration', generateSchema.shape, async (args) => {\n // Create notification handler that sends events back to the client\n const notificationHandler = {\n sendNotification: async (method: string, params: any) => {\n try {\n await transport.send({\n jsonrpc: '2.0',\n method,\n params,\n })\n } catch (error) {\n console.error('Failed to send notification:', error)\n }\n },\n }\n\n // Call build tool with notification handler\n return generate(args, notificationHandler)\n })\n\n await server.connect(transport)\n } catch (error) {\n console.error('Failed to start MCP server:', error)\n process.exit(1)\n }\n}\n","import { startServer } from './server.ts'\n\nexport async function run(_argv?: string[]): Promise<void> {\n await startServer()\n}\n"],"mappings":"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"}
|