@kubb/mcp 5.0.0-beta.54 → 5.0.0-beta.56

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 CHANGED
@@ -38,11 +38,12 @@ let node_fs = require("node:fs");
38
38
  node_fs = __toESM(node_fs, 1);
39
39
  let node_path = require("node:path");
40
40
  node_path = __toESM(node_path, 1);
41
+ let node_url = require("node:url");
41
42
  let jiti = require("jiti");
42
43
  let node_process = require("node:process");
43
44
  node_process = __toESM(node_process, 1);
44
45
  //#region package.json
45
- var version = "5.0.0-beta.54";
46
+ var version = "5.0.0-beta.56";
46
47
  //#endregion
47
48
  //#region ../../internals/utils/src/errors.ts
48
49
  /**
@@ -201,38 +202,85 @@ function isPromise(result) {
201
202
  return result !== null && result !== void 0 && typeof result["then"] === "function";
202
203
  }
203
204
  //#endregion
204
- //#region src/schemas/generateSchema.ts
205
- const generateSchema = valibot.object({
206
- config: valibot.optional(valibot.pipe(valibot.string(), valibot.minLength(1), valibot.description("Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory"))),
207
- input: valibot.optional(valibot.pipe(valibot.string(), valibot.minLength(1), valibot.description("Path to OpenAPI/Swagger spec file (overrides config)"))),
208
- output: valibot.optional(valibot.pipe(valibot.string(), valibot.minLength(1), valibot.description("Output directory path (overrides config)"))),
209
- logLevel: valibot.optional(valibot.pipe(valibot.picklist([
210
- "silent",
211
- "info",
212
- "verbose"
213
- ]), valibot.description("Log level for build output")), "info")
214
- });
215
- //#endregion
216
- //#region src/utils/formatDiagnostics.ts
205
+ //#region ../../internals/utils/src/runtime.ts
217
206
  /**
218
- * Renders serialized diagnostics as a plain-text block for an AI assistant. Each entry
219
- * keeps the stable `code`, the source pointer, the suggested fix, and the docs link, so
220
- * the agent can act on the problem rather than parsing a bare message. No ANSI styling,
221
- * unlike the CLI renderer.
207
+ * Detects the JavaScript runtime executing the current process and exposes its name and version.
208
+ *
209
+ * Prefer the shared {@link runtime} instance over constructing your own.
222
210
  */
223
- function formatDiagnostics(diagnostics) {
224
- return diagnostics.map((diagnostic) => formatDiagnostic(diagnostic)).join("\n\n");
225
- }
226
- function formatDiagnostic(diagnostic) {
227
- const { code, severity, message, location, help, plugin, docsUrl } = diagnostic;
228
- const lines = [`${severity} ${plugin ? `${plugin}(${code})` : code}: ${message}`];
229
- if (location && "pointer" in location) lines.push(` at ${location.pointer}`);
230
- if (help) lines.push(` help: ${help}`);
231
- if (docsUrl) lines.push(` docs: ${docsUrl}`);
232
- return lines.join("\n");
233
- }
211
+ var Runtime = class {
212
+ /**
213
+ * `true` when the current process is running under Bun.
214
+ *
215
+ * Detection keys off the global `Bun` object rather than `process.versions`,
216
+ * because Bun polyfills `process.versions.node` for Node compatibility and would
217
+ * otherwise look like Node.
218
+ *
219
+ * @example
220
+ * ```ts
221
+ * if (runtime.isBun) {
222
+ * await Bun.write(path, data)
223
+ * }
224
+ * ```
225
+ */
226
+ get isBun() {
227
+ return typeof Bun !== "undefined";
228
+ }
229
+ /**
230
+ * `true` when the current process is running under Deno.
231
+ */
232
+ get isDeno() {
233
+ return typeof globalThis.Deno !== "undefined";
234
+ }
235
+ /**
236
+ * `true` when the current process is running under Node.
237
+ *
238
+ * Bun and Deno are excluded first so a polyfilled `process` does not register as Node.
239
+ */
240
+ get isNode() {
241
+ return !this.isBun && !this.isDeno && typeof process !== "undefined" && process.versions?.node != null;
242
+ }
243
+ /**
244
+ * Name of the runtime executing the current process.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * runtime.name // 'bun' when run with `bun kubb`, 'node' otherwise
249
+ * ```
250
+ */
251
+ get name() {
252
+ if (this.isBun) return "bun";
253
+ if (this.isDeno) return "deno";
254
+ return "node";
255
+ }
256
+ /**
257
+ * Version of the active runtime, or an empty string when it cannot be read.
258
+ *
259
+ * @example
260
+ * ```ts
261
+ * runtime.version // '1.3.11' under Bun, '22.22.2' under Node
262
+ * ```
263
+ */
264
+ get version() {
265
+ if (this.isBun) return process.versions.bun ?? "";
266
+ if (this.isDeno) return globalThis.Deno?.version?.deno ?? "";
267
+ return process.versions?.node ?? "";
268
+ }
269
+ };
270
+ /**
271
+ * Shared {@link Runtime} instance describing the JavaScript runtime executing the current process.
272
+ */
273
+ const runtime = new Runtime();
234
274
  //#endregion
235
- //#region src/types.ts
275
+ //#region src/constants.ts
276
+ const ALLOWED_CONFIG_EXTENSIONS = new Set([
277
+ ".ts",
278
+ ".mts",
279
+ ".cts",
280
+ ".js",
281
+ ".mjs",
282
+ ".cjs"
283
+ ]);
236
284
  const NotifyTypes = {
237
285
  INFO: "INFO",
238
286
  SUCCESS: "SUCCESS",
@@ -254,34 +302,201 @@ const NotifyTypes = {
254
302
  BUILD_START: "BUILD_START",
255
303
  BUILD_END: "BUILD_END",
256
304
  BUILD_FAILED: "BUILD_FAILED",
257
- BUILD_SUCCESS: "BUILD_SUCCESS",
258
- FATAL_ERROR: "FATAL_ERROR"
305
+ BUILD_SUCCESS: "BUILD_SUCCESS"
259
306
  };
260
307
  //#endregion
261
- //#region src/constants.ts
262
- const ALLOWED_CONFIG_EXTENSIONS = new Set([
263
- ".ts",
264
- ".mts",
265
- ".cts",
266
- ".js",
267
- ".mjs",
268
- ".cjs"
269
- ]);
308
+ //#region src/schemas/generateSchema.ts
309
+ const generateSchema = valibot.object({
310
+ config: valibot.optional(valibot.pipe(valibot.string(), valibot.minLength(1), valibot.description("Path to kubb.config file (supports .ts, .js, .cjs). If not provided, will look for kubb.config.{ts,js,cjs} in current directory"))),
311
+ input: valibot.optional(valibot.pipe(valibot.string(), valibot.minLength(1), valibot.description("Path to OpenAPI/Swagger spec file (overrides config)"))),
312
+ output: valibot.optional(valibot.pipe(valibot.string(), valibot.minLength(1), valibot.description("Output directory path (overrides config)"))),
313
+ logLevel: valibot.optional(valibot.pipe(valibot.picklist([
314
+ "silent",
315
+ "info",
316
+ "verbose"
317
+ ]), valibot.description("Log level for build output")), "info")
318
+ });
319
+ //#endregion
320
+ //#region ../../internals/shared/src/constants.ts
321
+ const KUBB_CONFIG_FILENAME = "kubb.config.ts";
322
+ const availablePlugins = [
323
+ {
324
+ value: "plugin-ts",
325
+ label: "TypeScript",
326
+ hint: "Recommended",
327
+ packageName: "@kubb/plugin-ts",
328
+ importName: "pluginTs",
329
+ category: "types"
330
+ },
331
+ {
332
+ value: "plugin-client",
333
+ label: "Client (Fetch/Axios)",
334
+ packageName: "@kubb/plugin-client",
335
+ importName: "pluginClient",
336
+ category: "client"
337
+ },
338
+ {
339
+ value: "plugin-react-query",
340
+ label: "React Query / TanStack Query",
341
+ packageName: "@kubb/plugin-react-query",
342
+ importName: "pluginReactQuery",
343
+ category: "framework"
344
+ },
345
+ {
346
+ value: "plugin-vue-query",
347
+ label: "Vue Query",
348
+ packageName: "@kubb/plugin-vue-query",
349
+ importName: "pluginVueQuery",
350
+ category: "framework"
351
+ },
352
+ {
353
+ value: "plugin-zod",
354
+ label: "Zod Schemas",
355
+ packageName: "@kubb/plugin-zod",
356
+ importName: "pluginZod",
357
+ category: "validation"
358
+ },
359
+ {
360
+ value: "plugin-faker",
361
+ label: "Faker.js Mocks",
362
+ packageName: "@kubb/plugin-faker",
363
+ importName: "pluginFaker",
364
+ category: "mocks"
365
+ },
366
+ {
367
+ value: "plugin-msw",
368
+ label: "MSW Handlers",
369
+ packageName: "@kubb/plugin-msw",
370
+ importName: "pluginMsw",
371
+ category: "mocks"
372
+ },
373
+ {
374
+ value: "plugin-cypress",
375
+ label: "Cypress Tests",
376
+ packageName: "@kubb/plugin-cypress",
377
+ importName: "pluginCypress",
378
+ category: "testing"
379
+ },
380
+ {
381
+ value: "plugin-mcp",
382
+ label: "MCP Server (AI / Model Context Protocol)",
383
+ packageName: "@kubb/plugin-mcp",
384
+ importName: "pluginMcp",
385
+ category: "ai"
386
+ },
387
+ {
388
+ value: "plugin-redoc",
389
+ label: "ReDoc Documentation",
390
+ packageName: "@kubb/plugin-redoc",
391
+ importName: "pluginRedoc",
392
+ category: "documentation"
393
+ }
394
+ ];
395
+ const pluginDefaultConfigs = {
396
+ "plugin-ts": `pluginTs()`,
397
+ "plugin-client": `pluginClient()`,
398
+ "plugin-react-query": `pluginReactQuery()`,
399
+ "plugin-vue-query": `pluginVueQuery()`,
400
+ "plugin-zod": `pluginZod()`,
401
+ "plugin-faker": `pluginFaker()`,
402
+ "plugin-msw": `pluginMsw()`,
403
+ "plugin-cypress": `pluginCypress()`,
404
+ "plugin-mcp": `pluginMcp()`,
405
+ "plugin-redoc": `pluginRedoc()`
406
+ };
270
407
  //#endregion
271
- //#region src/utils/loadUserConfig.ts
272
- const jiti$1 = (0, jiti.createJiti)(require("url").pathToFileURL(__filename).href, {
408
+ //#region ../../internals/shared/src/init.ts
409
+ function generateConfigFile({ selectedPlugins, inputPath, outputPath }) {
410
+ return `import { defineConfig } from 'kubb'
411
+ ${selectedPlugins.map((plugin) => `import { ${plugin.importName} } from '${plugin.packageName}'`).join("\n")}
412
+
413
+ export default defineConfig({
414
+ root: '.',
415
+ input: {
416
+ path: '${inputPath}',
417
+ },
418
+ output: {
419
+ path: '${outputPath}',
420
+ clean: true,
421
+ },
422
+ plugins: [
423
+ ${selectedPlugins.map((plugin) => {
424
+ return ` ${pluginDefaultConfigs[plugin.value] ?? `${plugin.importName}()`},`;
425
+ }).join("\n")}
426
+ ],
427
+ })
428
+ `;
429
+ }
430
+ //#endregion
431
+ //#region ../../internals/shared/src/loader.ts
432
+ /**
433
+ * jiti options for loading Kubb config modules: the automatic JSX runtime pointed at
434
+ * `@kubb/renderer-jsx`, and `moduleCache` off so a re-load re-evaluates the file.
435
+ */
436
+ const JITI_OPTIONS = {
273
437
  jsx: {
274
438
  runtime: "automatic",
275
439
  importSource: "@kubb/renderer-jsx"
276
440
  },
277
441
  moduleCache: false
278
- });
442
+ };
443
+ /**
444
+ * Creates a runtime-aware loader for Kubb's TypeScript and JavaScript config modules.
445
+ *
446
+ * On Bun and Deno it imports the file natively, skipping jiti's transform step, and falls back to
447
+ * jiti only when the native import throws. On Node it always uses jiti, which transpiles TypeScript
448
+ * and the `@kubb/renderer-jsx` JSX runtime on the fly. The jiti instance is created lazily, so the
449
+ * Bun/Deno happy path never pays for it.
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * const config = await createModuleLoader().load('/abs/kubb.config.ts', { default: true })
454
+ * ```
455
+ */
456
+ function createModuleLoader() {
457
+ let jiti$1;
458
+ const getJiti = () => jiti$1 ??= (0, jiti.createJiti)(require("url").pathToFileURL(__filename).href, JITI_OPTIONS);
459
+ const viaJiti = (filePath, options) => options?.default ? getJiti().import(filePath, { default: true }) : getJiti().import(filePath);
460
+ const viaNative = async (filePath, options) => {
461
+ const href = (0, node_url.pathToFileURL)(filePath).href;
462
+ const mod = await (options?.bust != null ? import(`${href}?t=${options.bust}`) : import(href));
463
+ return options?.default ? mod.default ?? mod : mod;
464
+ };
465
+ return { async load(filePath, options) {
466
+ if (runtime.isBun || runtime.isDeno) try {
467
+ return await viaNative(filePath, options);
468
+ } catch {
469
+ return viaJiti(filePath, options);
470
+ }
471
+ return viaJiti(filePath, options);
472
+ } };
473
+ }
474
+ //#endregion
475
+ //#region src/utils.ts
476
+ /**
477
+ * Renders serialized diagnostics as a plain-text block for an AI assistant. Each entry
478
+ * keeps the stable `code`, the source pointer, the suggested fix, and the docs link, so
479
+ * the agent can act on the problem rather than parsing a bare message. No ANSI styling,
480
+ * unlike the CLI renderer.
481
+ */
482
+ function formatDiagnostics(diagnostics) {
483
+ return diagnostics.map((diagnostic) => formatDiagnostic(diagnostic)).join("\n\n");
484
+ }
485
+ function formatDiagnostic(diagnostic) {
486
+ const { code, severity, message, location, help, plugin, docsUrl } = diagnostic;
487
+ const lines = [`${severity} ${plugin ? `${plugin}(${code})` : code}: ${message}`];
488
+ if (location && "pointer" in location) lines.push(` at ${location.pointer}`);
489
+ if (help) lines.push(` help: ${help}`);
490
+ if (docsUrl) lines.push(` docs: ${docsUrl}`);
491
+ return lines.join("\n");
492
+ }
493
+ const loader = createModuleLoader();
279
494
  const loadedModules = /* @__PURE__ */ new Map();
280
495
  async function loadModule(filePath) {
281
496
  const ext = node_path.default.extname(filePath);
282
497
  if (!ALLOWED_CONFIG_EXTENSIONS.has(ext)) throw new Error(`Invalid config file extension "${ext}". Allowed: ${[...ALLOWED_CONFIG_EXTENSIONS].join(", ")}`);
283
498
  if (loadedModules.has(filePath)) return loadedModules.get(filePath);
284
- const mod = await jiti$1.import(filePath, { default: true });
499
+ const mod = await loader.load(filePath, { default: true });
285
500
  loadedModules.set(filePath, mod);
286
501
  return mod;
287
502
  }
@@ -340,8 +555,6 @@ async function loadUserConfig(configPath, { notify }) {
340
555
  await notify(NotifyTypes.CONFIG_ERROR, "No config file found");
341
556
  throw new Error(`No config file found. Please provide a config path or create one of: ${configFileNames.join(", ")}`);
342
557
  }
343
- //#endregion
344
- //#region src/utils/resolveCwd.ts
345
558
  /**
346
559
  * Determine the root directory based on userConfig.root and resolvedConfigDir
347
560
  * 1. If userConfig.root exists and is absolute, use it as-is
@@ -355,8 +568,6 @@ function resolveCwd(userConfig, cwd) {
355
568
  }
356
569
  return cwd;
357
570
  }
358
- //#endregion
359
- //#region src/utils/resolveUserConfig.ts
360
571
  async function resolveUserConfig(config, options) {
361
572
  const result = typeof config === "function" ? config({
362
573
  logLevel: options.logLevel,
@@ -467,137 +678,6 @@ const generateTool = (0, tmcp_tool.defineTool)({
467
678
  }
468
679
  });
469
680
  //#endregion
470
- //#region ../../internals/shared/src/constants.ts
471
- const KUBB_CONFIG_FILENAME = "kubb.config.ts";
472
- const availablePlugins = [
473
- {
474
- value: "plugin-ts",
475
- label: "TypeScript",
476
- hint: "Recommended",
477
- packageName: "@kubb/plugin-ts",
478
- importName: "pluginTs",
479
- category: "types"
480
- },
481
- {
482
- value: "plugin-client",
483
- label: "Client (Fetch/Axios)",
484
- packageName: "@kubb/plugin-client",
485
- importName: "pluginClient",
486
- category: "client"
487
- },
488
- {
489
- value: "plugin-react-query",
490
- label: "React Query / TanStack Query",
491
- packageName: "@kubb/plugin-react-query",
492
- importName: "pluginReactQuery",
493
- category: "framework"
494
- },
495
- {
496
- value: "plugin-vue-query",
497
- label: "Vue Query",
498
- packageName: "@kubb/plugin-vue-query",
499
- importName: "pluginVueQuery",
500
- category: "framework"
501
- },
502
- {
503
- value: "plugin-zod",
504
- label: "Zod Schemas",
505
- packageName: "@kubb/plugin-zod",
506
- importName: "pluginZod",
507
- category: "validation"
508
- },
509
- {
510
- value: "plugin-faker",
511
- label: "Faker.js Mocks",
512
- packageName: "@kubb/plugin-faker",
513
- importName: "pluginFaker",
514
- category: "mocks"
515
- },
516
- {
517
- value: "plugin-msw",
518
- label: "MSW Handlers",
519
- packageName: "@kubb/plugin-msw",
520
- importName: "pluginMsw",
521
- category: "mocks"
522
- },
523
- {
524
- value: "plugin-cypress",
525
- label: "Cypress Tests",
526
- packageName: "@kubb/plugin-cypress",
527
- importName: "pluginCypress",
528
- category: "testing"
529
- },
530
- {
531
- value: "plugin-mcp",
532
- label: "MCP Server (AI / Model Context Protocol)",
533
- packageName: "@kubb/plugin-mcp",
534
- importName: "pluginMcp",
535
- category: "ai"
536
- },
537
- {
538
- value: "plugin-redoc",
539
- label: "ReDoc Documentation",
540
- packageName: "@kubb/plugin-redoc",
541
- importName: "pluginRedoc",
542
- category: "documentation"
543
- }
544
- ];
545
- const pluginDefaultConfigs = {
546
- "plugin-ts": `pluginTs({
547
- output: { path: 'models' },
548
- })`,
549
- "plugin-client": `pluginClient({
550
- output: { path: 'clients' },
551
- })`,
552
- "plugin-react-query": `pluginReactQuery({
553
- output: { path: 'hooks' },
554
- })`,
555
- "plugin-vue-query": `pluginVueQuery({
556
- output: { path: 'hooks' },
557
- })`,
558
- "plugin-zod": `pluginZod({
559
- output: { path: 'zod' },
560
- })`,
561
- "plugin-faker": `pluginFaker({
562
- output: { path: 'mocks' },
563
- })`,
564
- "plugin-msw": `pluginMsw({
565
- output: { path: 'msw' },
566
- })`,
567
- "plugin-cypress": `pluginCypress({
568
- output: { path: 'cypress' },
569
- })`,
570
- "plugin-mcp": `pluginMcp({
571
- output: { path: 'mcp' },
572
- })`,
573
- "plugin-redoc": `pluginRedoc({
574
- output: { path: 'redoc' },
575
- })`
576
- };
577
- //#endregion
578
- //#region ../../internals/shared/src/init.ts
579
- function generateConfigFile({ selectedPlugins, inputPath, outputPath }) {
580
- return `import { defineConfig } from 'kubb'
581
- ${selectedPlugins.map((plugin) => `import { ${plugin.importName} } from '${plugin.packageName}'`).join("\n")}
582
-
583
- export default defineConfig({
584
- root: '.',
585
- input: {
586
- path: '${inputPath}',
587
- },
588
- output: {
589
- path: '${outputPath}',
590
- clean: true,
591
- },
592
- plugins: [
593
- ${selectedPlugins.map((plugin) => {
594
- return ` ${pluginDefaultConfigs[plugin.value] ?? `${plugin.importName}()`},`;
595
- }).join("\n")}
596
- ],
597
- })
598
- `;
599
- }
600
- //#endregion
601
681
  //#region src/schemas/initSchema.ts
602
682
  const initSchema = valibot.object({
603
683
  input: valibot.optional(valibot.pipe(valibot.string(), valibot.minLength(1), valibot.description("Path to OpenAPI spec (default: ./openapi.yaml)"))),