kubb 5.0.0-beta.4 → 5.0.0-beta.40

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
  <a href="https://kubb.dev" target="_blank" rel="noopener noreferrer">
3
- <img width="180" src="https://raw.githubusercontent.com/kubb-labs/kubb/main/assets/logo.png" alt="Kubb logo">
3
+ <img src="https://kubb.dev/og.png" alt="Kubb banner">
4
4
  </a>
5
5
 
6
6
  [![npm version][npm-version-src]][npm-version-href]
@@ -9,10 +9,6 @@
9
9
  [![License][license-src]][license-href]
10
10
  [![Sponsors][sponsors-src]][sponsors-href]
11
11
 
12
- ### The meta framework for code generation
13
-
14
- **Stop writing glue code. Define your API once and Kubb generates types, clients, hooks, validators, mocks and more.**
15
-
16
12
  <h4>
17
13
  <a href="https://kubb.dev" target="_blank">Documentation</a>
18
14
  <span> · </span>
@@ -24,30 +20,31 @@
24
20
 
25
21
  <br />
26
22
 
23
+ # Kubb
24
+
25
+ ### The meta framework for code generation
26
+
27
+ Point Kubb at an OpenAPI spec and it generates types, clients, hooks, validators, mocks, and more.
28
+
27
29
  ## Installation
28
30
 
29
31
  ```bash
30
- npm install kubb
32
+ bun add kubb
31
33
  # or
32
34
  pnpm add kubb
35
+ # or
36
+ npm install kubb
33
37
  ```
34
38
 
35
- ## Quick Start
39
+ ## Quick start
36
40
 
37
- Get started with Kubb in seconds:
41
+ Run the setup wizard to create a `kubb.config.ts`:
38
42
 
39
43
  ```bash
40
44
  npx kubb init
41
45
  ```
42
46
 
43
- The interactive setup will:
44
-
45
- - Create a `package.json` (if needed)
46
- - Guide you through plugin selection
47
- - Install packages automatically
48
- - Generate `kubb.config.ts`
49
-
50
- Then generate your code:
47
+ The wizard creates a `package.json` if needed, guides you through plugin selection, installs packages, and writes `kubb.config.ts`. Then generate your code:
51
48
 
52
49
  ```bash
53
50
  npx kubb generate
@@ -57,19 +54,22 @@ See the [documentation](https://kubb.dev) for detailed usage and advanced featur
57
54
 
58
55
  ## Features
59
56
 
60
- - Works with Node.js 22+ and TypeScript 6.
61
- - Convert Swagger 2.0, OpenAPI 3.0, and OpenAPI 3.1 to TypeScript types, API clients, and more via the [plugin ecosystem](https://github.com/kubb-labs/kubb-plugins).
62
- - Extensible plugin and middleware system for customizing and composing code generation.
63
- - CLI support with interactive setup, progress bar, and detailed logs.
64
- - Model Context Protocol (MCP) server for AI assistants like [Claude](https://claude.ai), [Cursor](https://cursor.sh), and other MCP-compatible tools.
65
- - JSX-based renderer (`@kubb/renderer-jsx`) for building custom plugin output.
66
- - Barrel file generation via the `@kubb/middleware-barrel` middleware.
57
+ - Generate from a spec: point Kubb at an OpenAPI document and it produces TypeScript types, type-safe API clients, [TanStack Query](https://github.com/TanStack/query) hooks for React and Vue, [SWR](https://github.com/vercel/swr) hooks, [Zod](https://github.com/colinhacks/zod) validators, [Faker](https://github.com/faker-js/faker) mocks, and [MSW](https://github.com/mswjs/msw) handlers.
58
+ - Read Swagger 2.0, OpenAPI 3.0, and 3.1, with TypeScript-first output that runs on Node.js and Bun.
59
+ - Pick what you generate from the [plugin ecosystem](https://github.com/kubb-labs/kubb-plugins): `plugin-ts`, `plugin-client`, `plugin-react-query`, `plugin-vue-query`, `plugin-swr`, `plugin-zod`, `plugin-faker`, `plugin-msw`, `plugin-cypress`, `plugin-redoc`, and `plugin-mcp`. Enable only the ones a project needs.
60
+ - Choose your HTTP client: use the axios or fetch presets, or point at a custom client module so generated requests run through your own wrapper.
61
+ - Control the generated tree: group files by tag, emit barrel exports, and include or exclude operations to keep the output focused.
62
+ - Build your own output with custom plugins, composable middleware, and the JSX-based renderer (`@kubb/renderer-jsx`) for full control over what lands on disk.
63
+ - Hook into your bundler with `unplugin-kubb`, which runs generation inside [Vite](https://github.com/vitejs/vite), [Nuxt](https://github.com/nuxt/nuxt), [Astro](https://github.com/withastro/astro), [webpack](https://github.com/webpack/webpack), and other build tools.
64
+ - Drive generation from AI tools through the built-in Model Context Protocol (MCP) server, which works with [Claude](https://claude.ai), [Cursor](https://cursor.sh), and other MCP-compatible assistants.
65
+ - Generate from inside [Claude Code](https://kubb.dev/docs/5.x/ai/claude) with the Kubb plugin, which adds slash commands, a config skill, and an agent that run the Kubb CLI.
67
66
 
68
67
  ## Supporting Kubb
69
68
 
70
- Kubb is an open source project with its ongoing development made possible entirely by the support of Sponsors. If you would like to become a sponsor, please consider:
69
+ Kubb is an open source project, and its development is funded entirely by sponsors. If you would like to become a sponsor, please consider:
71
70
 
72
71
  - [Become a Sponsor on GitHub](https://github.com/sponsors/stijnvanhulle)
72
+ - [See sponsorship tiers and our sponsors](https://kubb.dev/sponsors)
73
73
 
74
74
  <p align="center">
75
75
  <a href="https://github.com/sponsors/stijnvanhulle">
@@ -77,6 +77,16 @@ Kubb is an open source project with its ongoing development made possible entire
77
77
  </a>
78
78
  </p>
79
79
 
80
+ ## Contributing
81
+
82
+ We welcome contributions that help improve Kubb. A few ways to get involved:
83
+
84
+ - Found a bug? File it in the [issue tracker](https://github.com/kubb-labs/kubb/issues).
85
+ - Have an idea to improve Kubb? [Open an issue](https://github.com/kubb-labs/kubb/issues/new) to share it.
86
+ - Need help? Ask the community on [Discord](https://discord.gg/4dQjA6vrWX).
87
+
88
+ See [CONTRIBUTING.md](https://github.com/kubb-labs/kubb/blob/main/CONTRIBUTING.md) for the project structure, local setup, and commands.
89
+
80
90
  ## Contributors [![Contributors][contributors-src]][contributors-href]
81
91
 
82
92
  <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
@@ -164,15 +174,11 @@ Kubb is an open source project with its ongoing development made possible entire
164
174
 
165
175
  ## License
166
176
 
167
- Most of this repository is licensed under the [MIT License](./licenses/LICENSE-MIT), Copyright © 2025 [Stijn Van Hulle](https://stijnvanhulle.be). Some components are licensed
168
- under AGPL-3.0-or-later.
169
-
170
- - **Most packages** — [MIT](./licenses/LICENSE-MIT)
171
- - **`@kubb/agent`** — [AGPL-3.0-or-later](./licenses/LICENSE-AGPL-3.0)
177
+ Most of this repository is licensed under the [MIT License](./licenses/LICENSE-MIT), Copyright © 2025 [Stijn Van Hulle](https://stijnvanhulle.be). Most packages use [MIT](./licenses/LICENSE-MIT), and `@kubb/agent` uses [AGPL-3.0-or-later](./licenses/LICENSE-AGPL-3.0).
172
178
 
173
179
  See [LICENSE](./LICENSE) for details.
174
180
 
175
- ## Star History
181
+ ## Star history
176
182
 
177
183
  <a href="https://star-history.com/#kubb-labs/kubb&Date">
178
184
  <picture>
package/dist/index.cjs CHANGED
@@ -1,8 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#endregion
3
3
  let _kubb_adapter_oas = require("@kubb/adapter-oas");
4
+ let _kubb_core = require("@kubb/core");
4
5
  let _kubb_middleware_barrel = require("@kubb/middleware-barrel");
5
6
  let _kubb_parser_ts = require("@kubb/parser-ts");
7
+ let _kubb_parser_md = require("@kubb/parser-md");
6
8
  //#region ../../internals/utils/src/promise.ts
7
9
  /** Returns `true` when `result` is a thenable `Promise`.
8
10
  *
@@ -18,15 +20,17 @@ function isPromise(result) {
18
20
  //#endregion
19
21
  //#region src/defineConfig.ts
20
22
  /**
21
- * Applies default adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
23
+ * Applies default `root`, adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
22
24
  *
25
+ * - `root` defaults to `process.cwd()`
23
26
  * - `adapter` defaults to `adapterOas()`
24
- * - `parsers` defaults to `[parserTs, parserTsx]`
27
+ * - `parsers` defaults to `[parserTs, parserTsx, parserMd]`
28
+ * - `reporters` defaults to `[cliReporter, jsonReporter, fileReporter]`
25
29
  * - `middleware` defaults to `[middlewareBarrel()]`
26
30
  * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.
27
31
  * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.
28
- * - `output.format` defaults to `'auto'`
29
- * - `output.lint` defaults to `'auto'`
32
+ * - `output.format` defaults to `false`
33
+ * - `output.lint` defaults to `false`
30
34
  */
31
35
  function applyDefaults(config) {
32
36
  const middleware = config.middleware?.length ? config.middleware : [(0, _kubb_middleware_barrel.middlewareBarrel)()];
@@ -37,8 +41,18 @@ function applyDefaults(config) {
37
41
  if (output.lint === void 0) output.lint = false;
38
42
  return {
39
43
  ...config,
44
+ root: config.root || process.cwd(),
40
45
  adapter: config.adapter ?? (0, _kubb_adapter_oas.adapterOas)(),
41
- parsers: config.parsers?.length ? config.parsers : [_kubb_parser_ts.parserTs, _kubb_parser_ts.parserTsx],
46
+ parsers: config.parsers?.length ? config.parsers : [
47
+ _kubb_parser_ts.parserTs,
48
+ _kubb_parser_ts.parserTsx,
49
+ _kubb_parser_md.parserMd
50
+ ],
51
+ reporters: config.reporters?.length ? config.reporters : [
52
+ _kubb_core.cliReporter,
53
+ _kubb_core.jsonReporter,
54
+ _kubb_core.fileReporter
55
+ ],
42
56
  middleware,
43
57
  output
44
58
  };
@@ -48,21 +62,42 @@ function normalizeConfig(config) {
48
62
  return applyDefaults(config);
49
63
  }
50
64
  /**
51
- * Helper for defining a Kubb configuration with built-in defaults.
65
+ * Defines a Kubb build configuration and applies sensible defaults so the
66
+ * minimal config stays small.
52
67
  *
53
- * When no `adapter` is provided, `adapterOas()` is used automatically.
54
- * When no `parsers` are provided, `[parserTs, parserTsx]` is used automatically.
68
+ * Defaults applied when omitted:
69
+ * - `adapter` `adapterOas()` (OpenAPI 2.0/3.0/3.1).
70
+ * - `parsers` → `[parserTs, parserTsx, parserMd]`.
71
+ * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.
72
+ * - `middleware` → `[middlewareBarrel()]`.
73
+ * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is
74
+ * in the middleware list.
75
+ * - `output.format` and `output.lint` → `false`.
55
76
  *
56
- * Accepts either:
57
- * - A config object or array of configs
58
- * - A function returning the config(s), optionally async,
59
- * receiving the CLI options as argument
77
+ * Accepts a config object, an array of configs, a Promise resolving to one,
78
+ * or a function that receives the parsed CLI options and returns any of the
79
+ * above. The return type is preserved so async/array variants stay typed.
60
80
  *
61
81
  * @example
62
82
  * ```ts
63
- * export default defineConfig(({ logLevel }) => ({
64
- * root: 'src',
65
- * plugins: [myPlugin()],
83
+ * import { defineConfig } from 'kubb'
84
+ * import { pluginTs } from '@kubb/plugin-ts'
85
+ *
86
+ * export default defineConfig({
87
+ * input: { path: './petStore.yaml' },
88
+ * output: { path: './src/gen' },
89
+ * plugins: [pluginTs()],
90
+ * })
91
+ * ```
92
+ *
93
+ * @example Function form with CLI options
94
+ * ```ts
95
+ * import { defineConfig } from 'kubb'
96
+ *
97
+ * export default defineConfig(({ input }) => ({
98
+ * input: { path: input ?? './petStore.yaml' },
99
+ * output: { path: './src/gen' },
100
+ * plugins: [],
66
101
  * }))
67
102
  * ```
68
103
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["middlewareBarrelName","parserTs","parserTsx"],"sources":["../../../internals/utils/src/promise.ts","../src/defineConfig.ts"],"sourcesContent":["/** 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","import { isPromise, type PossiblePromise } from '@internals/utils'\nimport { adapterOas } from '@kubb/adapter-oas'\nimport type { CLIOptions, UserConfig } from '@kubb/core'\nimport { middlewareBarrel, middlewareBarrelName } from '@kubb/middleware-barrel'\nimport { parserTs, parserTsx } from '@kubb/parser-ts'\n\ntype AnyConfigResult = UserConfig<any> | Array<UserConfig<any>>\ntype ConfigInput = AnyConfigResult | Promise<AnyConfigResult> | ((cli: CLIOptions) => PossiblePromise<AnyConfigResult>)\ntype NormalizeConfig<TConfig> =\n TConfig extends Array<UserConfig<infer TInput>> ? Array<UserConfig<TInput>> : TConfig extends UserConfig<infer TInput> ? UserConfig<TInput> : never\ntype DefinedConfig<TConfig extends ConfigInput> = TConfig extends (cli: CLIOptions) => PossiblePromise<infer TResult>\n ? (cli: CLIOptions) => Promise<NormalizeConfig<TResult>>\n : TConfig extends Promise<infer TResult>\n ? Promise<NormalizeConfig<TResult>>\n : NormalizeConfig<TConfig>\n\n/**\n * Applies default adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.\n *\n * - `adapter` defaults to `adapterOas()`\n * - `parsers` defaults to `[parserTs, parserTsx]`\n * - `middleware` defaults to `[middlewareBarrel()]`\n * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.\n * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.\n * - `output.format` defaults to `'auto'`\n * - `output.lint` defaults to `'auto'`\n */\nfunction applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {\n const middleware = config.middleware?.length ? config.middleware : [middlewareBarrel()]\n const hasBarrelMiddleware = middleware.some((m) => m.name === middlewareBarrelName)\n\n const output = { ...config.output }\n if (hasBarrelMiddleware && output.barrel === undefined) {\n output.barrel = { type: 'named' }\n }\n if (output.format === undefined) {\n output.format = false\n }\n if (output.lint === undefined) {\n output.lint = false\n }\n\n return {\n ...config,\n adapter: config.adapter ?? adapterOas(),\n parsers: config.parsers?.length ? config.parsers : [parserTs, parserTsx],\n middleware,\n output,\n }\n}\n\nfunction normalizeConfig<TInput>(config: UserConfig<TInput> | Array<UserConfig<TInput>>): UserConfig<TInput> | Array<UserConfig<TInput>> {\n if (Array.isArray(config)) {\n return config.map(applyDefaults)\n }\n\n return applyDefaults(config)\n}\n\n/**\n * Helper for defining a Kubb configuration with built-in defaults.\n *\n * When no `adapter` is provided, `adapterOas()` is used automatically.\n * When no `parsers` are provided, `[parserTs, parserTsx]` is used automatically.\n *\n * Accepts either:\n * - A config object or array of configs\n * - A function returning the config(s), optionally async,\n * receiving the CLI options as argument\n *\n * @example\n * ```ts\n * export default defineConfig(({ logLevel }) => ({\n * root: 'src',\n * plugins: [myPlugin()],\n * }))\n * ```\n */\nexport function defineConfig<TConfig extends ConfigInput>(config: TConfig): DefinedConfig<TConfig> {\n if (typeof config === 'function') {\n return (async (cli: CLIOptions) => {\n return normalizeConfig(await config(cli))\n }) as DefinedConfig<TConfig>\n }\n\n if (isPromise(config)) {\n return config.then((resolved) => normalizeConfig(resolved)) as DefinedConfig<TConfig>\n }\n\n return normalizeConfig(config) as DefinedConfig<TConfig>\n}\n"],"mappings":";;;;;;;;;;;;;;AAmBA,SAAgB,UAAa,QAAkD;AAC7E,QAAO,WAAW,QAAQ,WAAW,KAAA,KAAa,OAAQ,OAAmC,YAAY;;;;;;;;;;;;;;;ACO3G,SAAS,cAAsB,QAAgD;CAC7E,MAAM,aAAa,OAAO,YAAY,SAAS,OAAO,aAAa,EAAA,GAAA,wBAAA,mBAAmB,CAAC;CACvF,MAAM,sBAAsB,WAAW,MAAM,MAAM,EAAE,SAASA,wBAAAA,qBAAqB;CAEnF,MAAM,SAAS,EAAE,GAAG,OAAO,QAAQ;AACnC,KAAI,uBAAuB,OAAO,WAAW,KAAA,EAC3C,QAAO,SAAS,EAAE,MAAM,SAAS;AAEnC,KAAI,OAAO,WAAW,KAAA,EACpB,QAAO,SAAS;AAElB,KAAI,OAAO,SAAS,KAAA,EAClB,QAAO,OAAO;AAGhB,QAAO;EACL,GAAG;EACH,SAAS,OAAO,YAAA,GAAA,kBAAA,aAAuB;EACvC,SAAS,OAAO,SAAS,SAAS,OAAO,UAAU,CAACC,gBAAAA,UAAUC,gBAAAA,UAAU;EACxE;EACA;EACD;;AAGH,SAAS,gBAAwB,QAAwG;AACvI,KAAI,MAAM,QAAQ,OAAO,CACvB,QAAO,OAAO,IAAI,cAAc;AAGlC,QAAO,cAAc,OAAO;;;;;;;;;;;;;;;;;;;;;AAsB9B,SAAgB,aAA0C,QAAyC;AACjG,KAAI,OAAO,WAAW,WACpB,SAAQ,OAAO,QAAoB;AACjC,SAAO,gBAAgB,MAAM,OAAO,IAAI,CAAC;;AAI7C,KAAI,UAAU,OAAO,CACnB,QAAO,OAAO,MAAM,aAAa,gBAAgB,SAAS,CAAC;AAG7D,QAAO,gBAAgB,OAAO"}
1
+ {"version":3,"file":"index.cjs","names":["middlewareBarrelName","parserTs","parserTsx","parserMd","cliReporter","jsonReporter","fileReporter"],"sources":["../../../internals/utils/src/promise.ts","../src/defineConfig.ts"],"sourcesContent":["function* chunks<T>(arr: readonly T[], size: number): Generator<T[]> {\n for (let i = 0; i < arr.length; i += size) {\n yield arr.slice(i, i + size)\n }\n}\n\nexport type ForBatchesOptions = {\n /**\n * Maximum batch size handed to `process`.\n * Parallel dispatch within a batch is the caller's responsibility\n * (typically via `Promise.all(batch.map(...))`).\n */\n concurrency: number\n /**\n * Called after every batch.\n *\n * Use a cheap, idempotent callback (e.g. one that short-circuits when there\n * is nothing new to do). The helper does not coalesce calls — if you need\n * throttling, do it inside `flush` itself.\n */\n flush?: () => Promise<void>\n}\n\n/**\n * Slices `source` into batches of `concurrency` items and awaits `process` for each batch.\n * Accepts both plain arrays (sync) and `AsyncIterable` (streaming).\n *\n * `process` controls whether items inside a batch run in parallel; this helper only\n * controls batch size and per-batch flushing.\n *\n * @example\n * ```ts\n * // parallel dispatch inside each batch\n * await forBatches(schemas, (batch) => Promise.all(batch.map(process)), { concurrency: 8 })\n *\n * // async iterable with a flush after every batch\n * await forBatches(stream.schemas, (batch) => dispatch(batch), { concurrency: 8, flush })\n * ```\n */\nexport async function forBatches<T>(\n source: readonly T[] | AsyncIterable<T>,\n process: (batch: T[]) => Promise<unknown>,\n options: ForBatchesOptions,\n): Promise<void> {\n const { concurrency, flush } = options\n\n if (Array.isArray(source)) {\n for (const batch of chunks(source, concurrency)) {\n await process(batch)\n if (flush) await flush()\n }\n return\n }\n\n const batch: T[] = []\n for await (const item of source) {\n batch.push(item)\n if (batch.length >= concurrency) {\n await process(batch.splice(0))\n\n if (flush) await flush()\n }\n }\n if (batch.length > 0) {\n await process(batch.splice(0))\n\n if (flush) await flush()\n }\n}\n\n/**\n * Runs `work`, passing `flush` as its periodic-flush callback, then calls\n * `flush` once more to drain any items that did not cross a flush boundary.\n *\n * @example\n * ```ts\n * await withDrain(\n * (flush) => processItems(items, { flush }),\n * () => writeRemainingFiles(),\n * )\n * ```\n */\nexport async function withDrain(work: (flush: () => Promise<void>) => Promise<void>, flush: () => Promise<void>): Promise<void> {\n await work(flush)\n await flush()\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 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\ntype Store<TKey, TValue> = {\n has(key: TKey): boolean\n get(key: TKey): TValue | undefined\n set(key: TKey, value: TValue): unknown\n}\n\n/**\n * Wraps `factory` with a keyed cache backed by the provided store.\n *\n * Pass a `WeakMap` for object keys (results are GC-eligible when the key is\n * collected) or a `Map` for primitive keys. For multi-argument functions,\n * nest two `memoize` calls — the outer keyed by the first argument, the\n * inner (created once per outer miss) keyed by the second.\n *\n * Because the cache is owned by the caller, it can be shared, inspected, or\n * cleared independently of the memoized function.\n *\n * @example Single WeakMap key\n * ```ts\n * const cache = new WeakMap<SchemaNode, Set<string>>()\n * const getRefs = memoize(cache, (node) => collectRefs(node))\n * ```\n *\n * @example Single Map key (primitive)\n * ```ts\n * const cache = new Map<string, Resolver>()\n * const getResolver = memoize(cache, (name) => buildResolver(name))\n * ```\n *\n * @example Two-level (object + primitive)\n * ```ts\n * const outer = new WeakMap<Params[], Map<string, Params[]>>()\n * const fn = memoize(outer, (params) => memoize(new Map(), (key) => transform(params, key)))\n * fn(params)('camelcase')\n * ```\n */\nexport function memoize<TKey, TValue>(store: Store<TKey, TValue>, factory: (key: TKey) => TValue): (key: TKey) => TValue {\n return (key: TKey): TValue => {\n if (store.has(key)) return store.get(key)!\n const value = factory(key)\n store.set(key, value)\n return value\n }\n}\n\n/**\n * Wraps a plain array in a reusable `AsyncIterable`.\n * Each `[Symbol.asyncIterator]()` call returns a fresh generator so the\n * iterable can be consumed multiple times (e.g. once per plugin pre-scan).\n *\n * @example\n * ```ts\n * const stream = arrayToAsyncIterable([1, 2, 3])\n * for await (const n of stream) console.log(n) // 1, 2, 3\n * ```\n */\nexport function arrayToAsyncIterable<T>(arr: readonly T[]): AsyncIterable<T> {\n return {\n [Symbol.asyncIterator]() {\n return (async function* () {\n yield* arr\n })()\n },\n }\n}\n","import { isPromise, type PossiblePromise } from '@internals/utils'\nimport { adapterOas } from '@kubb/adapter-oas'\nimport { cliReporter, type CLIOptions, fileReporter, jsonReporter, type UserConfig } from '@kubb/core'\nimport { middlewareBarrel, middlewareBarrelName } from '@kubb/middleware-barrel'\nimport { parserTs, parserTsx } from '@kubb/parser-ts'\nimport { parserMd } from '@kubb/parser-md'\n\ntype AnyConfigResult = UserConfig<any> | Array<UserConfig<any>>\ntype ConfigInput = AnyConfigResult | Promise<AnyConfigResult> | ((cli: CLIOptions) => PossiblePromise<AnyConfigResult>)\ntype NormalizeConfig<TConfig> =\n TConfig extends Array<UserConfig<infer TInput>> ? Array<UserConfig<TInput>> : TConfig extends UserConfig<infer TInput> ? UserConfig<TInput> : never\ntype DefinedConfig<TConfig extends ConfigInput> = TConfig extends (cli: CLIOptions) => PossiblePromise<infer TResult>\n ? (cli: CLIOptions) => Promise<NormalizeConfig<TResult>>\n : TConfig extends Promise<infer TResult>\n ? Promise<NormalizeConfig<TResult>>\n : NormalizeConfig<TConfig>\n\n/**\n * Applies default `root`, adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.\n *\n * - `root` defaults to `process.cwd()`\n * - `adapter` defaults to `adapterOas()`\n * - `parsers` defaults to `[parserTs, parserTsx, parserMd]`\n * - `reporters` defaults to `[cliReporter, jsonReporter, fileReporter]`\n * - `middleware` defaults to `[middlewareBarrel()]`\n * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.\n * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.\n * - `output.format` defaults to `false`\n * - `output.lint` defaults to `false`\n */\nfunction applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {\n const middleware = config.middleware?.length ? config.middleware : [middlewareBarrel()]\n const hasBarrelMiddleware = middleware.some((m) => m.name === middlewareBarrelName)\n\n const output = { ...config.output }\n if (hasBarrelMiddleware && output.barrel === undefined) {\n output.barrel = { type: 'named' }\n }\n if (output.format === undefined) {\n output.format = false\n }\n if (output.lint === undefined) {\n output.lint = false\n }\n\n return {\n ...config,\n root: config.root || process.cwd(),\n adapter: config.adapter ?? adapterOas(),\n parsers: config.parsers?.length ? config.parsers : [parserTs, parserTsx, parserMd],\n reporters: config.reporters?.length ? config.reporters : [cliReporter, jsonReporter, fileReporter],\n middleware,\n output,\n }\n}\n\nfunction normalizeConfig<TInput>(config: UserConfig<TInput> | Array<UserConfig<TInput>>): UserConfig<TInput> | Array<UserConfig<TInput>> {\n if (Array.isArray(config)) {\n return config.map(applyDefaults)\n }\n\n return applyDefaults(config)\n}\n\n/**\n * Defines a Kubb build configuration and applies sensible defaults so the\n * minimal config stays small.\n *\n * Defaults applied when omitted:\n * - `adapter` → `adapterOas()` (OpenAPI 2.0/3.0/3.1).\n * - `parsers` → `[parserTs, parserTsx, parserMd]`.\n * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.\n * - `middleware` → `[middlewareBarrel()]`.\n * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is\n * in the middleware list.\n * - `output.format` and `output.lint` → `false`.\n *\n * Accepts a config object, an array of configs, a Promise resolving to one,\n * or a function that receives the parsed CLI options and returns any of the\n * above. The return type is preserved so async/array variants stay typed.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { pluginTs } from '@kubb/plugin-ts'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * plugins: [pluginTs()],\n * })\n * ```\n *\n * @example Function form with CLI options\n * ```ts\n * import { defineConfig } from 'kubb'\n *\n * export default defineConfig(({ input }) => ({\n * input: { path: input ?? './petStore.yaml' },\n * output: { path: './src/gen' },\n * plugins: [],\n * }))\n * ```\n */\nexport function defineConfig<TConfig extends ConfigInput>(config: TConfig): DefinedConfig<TConfig> {\n if (typeof config === 'function') {\n return (async (cli: CLIOptions) => {\n return normalizeConfig(await config(cli))\n }) as DefinedConfig<TConfig>\n }\n\n if (isPromise(config)) {\n return config.then((resolved) => normalizeConfig(resolved)) as DefinedConfig<TConfig>\n }\n\n return normalizeConfig(config) as DefinedConfig<TConfig>\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA0GA,SAAgB,UAAa,QAAkD;CAC7E,OAAO,WAAW,QAAQ,WAAW,KAAA,KAAa,OAAQ,OAAmC,YAAY;AAC3G;;;;;;;;;;;;;;;;AC9EA,SAAS,cAAsB,QAAgD;CAC7E,MAAM,aAAa,OAAO,YAAY,SAAS,OAAO,aAAa,EAAA,GAAA,wBAAA,kBAAkB,CAAC;CACtF,MAAM,sBAAsB,WAAW,MAAM,MAAM,EAAE,SAASA,wBAAAA,oBAAoB;CAElF,MAAM,SAAS,EAAE,GAAG,OAAO,OAAO;CAClC,IAAI,uBAAuB,OAAO,WAAW,KAAA,GAC3C,OAAO,SAAS,EAAE,MAAM,QAAQ;CAElC,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,SAAS;CAElB,IAAI,OAAO,SAAS,KAAA,GAClB,OAAO,OAAO;CAGhB,OAAO;EACL,GAAG;EACH,MAAM,OAAO,QAAQ,QAAQ,IAAI;EACjC,SAAS,OAAO,YAAA,GAAA,kBAAA,YAAsB;EACtC,SAAS,OAAO,SAAS,SAAS,OAAO,UAAU;GAACC,gBAAAA;GAAUC,gBAAAA;GAAWC,gBAAAA;EAAQ;EACjF,WAAW,OAAO,WAAW,SAAS,OAAO,YAAY;GAACC,WAAAA;GAAaC,WAAAA;GAAcC,WAAAA;EAAY;EACjG;EACA;CACF;AACF;AAEA,SAAS,gBAAwB,QAAwG;CACvI,IAAI,MAAM,QAAQ,MAAM,GACtB,OAAO,OAAO,IAAI,aAAa;CAGjC,OAAO,cAAc,MAAM;AAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,aAA0C,QAAyC;CACjG,IAAI,OAAO,WAAW,YACpB,QAAQ,OAAO,QAAoB;EACjC,OAAO,gBAAgB,MAAM,OAAO,GAAG,CAAC;CAC1C;CAGF,IAAI,UAAU,MAAM,GAClB,OAAO,OAAO,MAAM,aAAa,gBAAgB,QAAQ,CAAC;CAG5D,OAAO,gBAAgB,MAAM;AAC/B"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { t as __name } from "./chunk--u3MIqq1.js";
2
- import { BarrelType } from "@kubb/middleware-barrel";
1
+ import { t as __name } from "./chunk-C0LytTxp.js";
3
2
  import { CLIOptions, UserConfig } from "@kubb/core";
3
+ import { BarrelType } from "@kubb/middleware-barrel";
4
4
 
5
5
  //#region ../../internals/utils/src/promise.d.ts
6
6
  /** A value that may already be resolved or still pending.
@@ -20,21 +20,42 @@ type ConfigInput = AnyConfigResult | Promise<AnyConfigResult> | ((cli: CLIOption
20
20
  type NormalizeConfig<TConfig> = TConfig extends Array<UserConfig<infer TInput>> ? Array<UserConfig<TInput>> : TConfig extends UserConfig<infer TInput> ? UserConfig<TInput> : never;
21
21
  type DefinedConfig<TConfig extends ConfigInput> = TConfig extends ((cli: CLIOptions) => PossiblePromise<infer TResult>) ? (cli: CLIOptions) => Promise<NormalizeConfig<TResult>> : TConfig extends Promise<infer TResult> ? Promise<NormalizeConfig<TResult>> : NormalizeConfig<TConfig>;
22
22
  /**
23
- * Helper for defining a Kubb configuration with built-in defaults.
23
+ * Defines a Kubb build configuration and applies sensible defaults so the
24
+ * minimal config stays small.
24
25
  *
25
- * When no `adapter` is provided, `adapterOas()` is used automatically.
26
- * When no `parsers` are provided, `[parserTs, parserTsx]` is used automatically.
26
+ * Defaults applied when omitted:
27
+ * - `adapter` `adapterOas()` (OpenAPI 2.0/3.0/3.1).
28
+ * - `parsers` → `[parserTs, parserTsx, parserMd]`.
29
+ * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.
30
+ * - `middleware` → `[middlewareBarrel()]`.
31
+ * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is
32
+ * in the middleware list.
33
+ * - `output.format` and `output.lint` → `false`.
27
34
  *
28
- * Accepts either:
29
- * - A config object or array of configs
30
- * - A function returning the config(s), optionally async,
31
- * receiving the CLI options as argument
35
+ * Accepts a config object, an array of configs, a Promise resolving to one,
36
+ * or a function that receives the parsed CLI options and returns any of the
37
+ * above. The return type is preserved so async/array variants stay typed.
32
38
  *
33
39
  * @example
34
40
  * ```ts
35
- * export default defineConfig(({ logLevel }) => ({
36
- * root: 'src',
37
- * plugins: [myPlugin()],
41
+ * import { defineConfig } from 'kubb'
42
+ * import { pluginTs } from '@kubb/plugin-ts'
43
+ *
44
+ * export default defineConfig({
45
+ * input: { path: './petStore.yaml' },
46
+ * output: { path: './src/gen' },
47
+ * plugins: [pluginTs()],
48
+ * })
49
+ * ```
50
+ *
51
+ * @example Function form with CLI options
52
+ * ```ts
53
+ * import { defineConfig } from 'kubb'
54
+ *
55
+ * export default defineConfig(({ input }) => ({
56
+ * input: { path: input ?? './petStore.yaml' },
57
+ * output: { path: './src/gen' },
58
+ * plugins: [],
38
59
  * }))
39
60
  * ```
40
61
  */
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
- import "./chunk--u3MIqq1.js";
1
+ import "./chunk-C0LytTxp.js";
2
2
  import { adapterOas } from "@kubb/adapter-oas";
3
+ import { cliReporter, fileReporter, jsonReporter } from "@kubb/core";
3
4
  import { middlewareBarrel, middlewareBarrelName } from "@kubb/middleware-barrel";
4
5
  import { parserTs, parserTsx } from "@kubb/parser-ts";
6
+ import { parserMd } from "@kubb/parser-md";
5
7
  //#region ../../internals/utils/src/promise.ts
6
8
  /** Returns `true` when `result` is a thenable `Promise`.
7
9
  *
@@ -17,15 +19,17 @@ function isPromise(result) {
17
19
  //#endregion
18
20
  //#region src/defineConfig.ts
19
21
  /**
20
- * Applies default adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
22
+ * Applies default `root`, adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
21
23
  *
24
+ * - `root` defaults to `process.cwd()`
22
25
  * - `adapter` defaults to `adapterOas()`
23
- * - `parsers` defaults to `[parserTs, parserTsx]`
26
+ * - `parsers` defaults to `[parserTs, parserTsx, parserMd]`
27
+ * - `reporters` defaults to `[cliReporter, jsonReporter, fileReporter]`
24
28
  * - `middleware` defaults to `[middlewareBarrel()]`
25
29
  * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.
26
30
  * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.
27
- * - `output.format` defaults to `'auto'`
28
- * - `output.lint` defaults to `'auto'`
31
+ * - `output.format` defaults to `false`
32
+ * - `output.lint` defaults to `false`
29
33
  */
30
34
  function applyDefaults(config) {
31
35
  const middleware = config.middleware?.length ? config.middleware : [middlewareBarrel()];
@@ -36,8 +40,18 @@ function applyDefaults(config) {
36
40
  if (output.lint === void 0) output.lint = false;
37
41
  return {
38
42
  ...config,
43
+ root: config.root || process.cwd(),
39
44
  adapter: config.adapter ?? adapterOas(),
40
- parsers: config.parsers?.length ? config.parsers : [parserTs, parserTsx],
45
+ parsers: config.parsers?.length ? config.parsers : [
46
+ parserTs,
47
+ parserTsx,
48
+ parserMd
49
+ ],
50
+ reporters: config.reporters?.length ? config.reporters : [
51
+ cliReporter,
52
+ jsonReporter,
53
+ fileReporter
54
+ ],
41
55
  middleware,
42
56
  output
43
57
  };
@@ -47,21 +61,42 @@ function normalizeConfig(config) {
47
61
  return applyDefaults(config);
48
62
  }
49
63
  /**
50
- * Helper for defining a Kubb configuration with built-in defaults.
64
+ * Defines a Kubb build configuration and applies sensible defaults so the
65
+ * minimal config stays small.
51
66
  *
52
- * When no `adapter` is provided, `adapterOas()` is used automatically.
53
- * When no `parsers` are provided, `[parserTs, parserTsx]` is used automatically.
67
+ * Defaults applied when omitted:
68
+ * - `adapter` `adapterOas()` (OpenAPI 2.0/3.0/3.1).
69
+ * - `parsers` → `[parserTs, parserTsx, parserMd]`.
70
+ * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.
71
+ * - `middleware` → `[middlewareBarrel()]`.
72
+ * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is
73
+ * in the middleware list.
74
+ * - `output.format` and `output.lint` → `false`.
54
75
  *
55
- * Accepts either:
56
- * - A config object or array of configs
57
- * - A function returning the config(s), optionally async,
58
- * receiving the CLI options as argument
76
+ * Accepts a config object, an array of configs, a Promise resolving to one,
77
+ * or a function that receives the parsed CLI options and returns any of the
78
+ * above. The return type is preserved so async/array variants stay typed.
59
79
  *
60
80
  * @example
61
81
  * ```ts
62
- * export default defineConfig(({ logLevel }) => ({
63
- * root: 'src',
64
- * plugins: [myPlugin()],
82
+ * import { defineConfig } from 'kubb'
83
+ * import { pluginTs } from '@kubb/plugin-ts'
84
+ *
85
+ * export default defineConfig({
86
+ * input: { path: './petStore.yaml' },
87
+ * output: { path: './src/gen' },
88
+ * plugins: [pluginTs()],
89
+ * })
90
+ * ```
91
+ *
92
+ * @example Function form with CLI options
93
+ * ```ts
94
+ * import { defineConfig } from 'kubb'
95
+ *
96
+ * export default defineConfig(({ input }) => ({
97
+ * input: { path: input ?? './petStore.yaml' },
98
+ * output: { path: './src/gen' },
99
+ * plugins: [],
65
100
  * }))
66
101
  * ```
67
102
  */
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../internals/utils/src/promise.ts","../src/defineConfig.ts"],"sourcesContent":["/** 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","import { isPromise, type PossiblePromise } from '@internals/utils'\nimport { adapterOas } from '@kubb/adapter-oas'\nimport type { CLIOptions, UserConfig } from '@kubb/core'\nimport { middlewareBarrel, middlewareBarrelName } from '@kubb/middleware-barrel'\nimport { parserTs, parserTsx } from '@kubb/parser-ts'\n\ntype AnyConfigResult = UserConfig<any> | Array<UserConfig<any>>\ntype ConfigInput = AnyConfigResult | Promise<AnyConfigResult> | ((cli: CLIOptions) => PossiblePromise<AnyConfigResult>)\ntype NormalizeConfig<TConfig> =\n TConfig extends Array<UserConfig<infer TInput>> ? Array<UserConfig<TInput>> : TConfig extends UserConfig<infer TInput> ? UserConfig<TInput> : never\ntype DefinedConfig<TConfig extends ConfigInput> = TConfig extends (cli: CLIOptions) => PossiblePromise<infer TResult>\n ? (cli: CLIOptions) => Promise<NormalizeConfig<TResult>>\n : TConfig extends Promise<infer TResult>\n ? Promise<NormalizeConfig<TResult>>\n : NormalizeConfig<TConfig>\n\n/**\n * Applies default adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.\n *\n * - `adapter` defaults to `adapterOas()`\n * - `parsers` defaults to `[parserTs, parserTsx]`\n * - `middleware` defaults to `[middlewareBarrel()]`\n * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.\n * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.\n * - `output.format` defaults to `'auto'`\n * - `output.lint` defaults to `'auto'`\n */\nfunction applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {\n const middleware = config.middleware?.length ? config.middleware : [middlewareBarrel()]\n const hasBarrelMiddleware = middleware.some((m) => m.name === middlewareBarrelName)\n\n const output = { ...config.output }\n if (hasBarrelMiddleware && output.barrel === undefined) {\n output.barrel = { type: 'named' }\n }\n if (output.format === undefined) {\n output.format = false\n }\n if (output.lint === undefined) {\n output.lint = false\n }\n\n return {\n ...config,\n adapter: config.adapter ?? adapterOas(),\n parsers: config.parsers?.length ? config.parsers : [parserTs, parserTsx],\n middleware,\n output,\n }\n}\n\nfunction normalizeConfig<TInput>(config: UserConfig<TInput> | Array<UserConfig<TInput>>): UserConfig<TInput> | Array<UserConfig<TInput>> {\n if (Array.isArray(config)) {\n return config.map(applyDefaults)\n }\n\n return applyDefaults(config)\n}\n\n/**\n * Helper for defining a Kubb configuration with built-in defaults.\n *\n * When no `adapter` is provided, `adapterOas()` is used automatically.\n * When no `parsers` are provided, `[parserTs, parserTsx]` is used automatically.\n *\n * Accepts either:\n * - A config object or array of configs\n * - A function returning the config(s), optionally async,\n * receiving the CLI options as argument\n *\n * @example\n * ```ts\n * export default defineConfig(({ logLevel }) => ({\n * root: 'src',\n * plugins: [myPlugin()],\n * }))\n * ```\n */\nexport function defineConfig<TConfig extends ConfigInput>(config: TConfig): DefinedConfig<TConfig> {\n if (typeof config === 'function') {\n return (async (cli: CLIOptions) => {\n return normalizeConfig(await config(cli))\n }) as DefinedConfig<TConfig>\n }\n\n if (isPromise(config)) {\n return config.then((resolved) => normalizeConfig(resolved)) as DefinedConfig<TConfig>\n }\n\n return normalizeConfig(config) as DefinedConfig<TConfig>\n}\n"],"mappings":";;;;;;;;;;;;;AAmBA,SAAgB,UAAa,QAAkD;AAC7E,QAAO,WAAW,QAAQ,WAAW,KAAA,KAAa,OAAQ,OAAmC,YAAY;;;;;;;;;;;;;;;ACO3G,SAAS,cAAsB,QAAgD;CAC7E,MAAM,aAAa,OAAO,YAAY,SAAS,OAAO,aAAa,CAAC,kBAAkB,CAAC;CACvF,MAAM,sBAAsB,WAAW,MAAM,MAAM,EAAE,SAAS,qBAAqB;CAEnF,MAAM,SAAS,EAAE,GAAG,OAAO,QAAQ;AACnC,KAAI,uBAAuB,OAAO,WAAW,KAAA,EAC3C,QAAO,SAAS,EAAE,MAAM,SAAS;AAEnC,KAAI,OAAO,WAAW,KAAA,EACpB,QAAO,SAAS;AAElB,KAAI,OAAO,SAAS,KAAA,EAClB,QAAO,OAAO;AAGhB,QAAO;EACL,GAAG;EACH,SAAS,OAAO,WAAW,YAAY;EACvC,SAAS,OAAO,SAAS,SAAS,OAAO,UAAU,CAAC,UAAU,UAAU;EACxE;EACA;EACD;;AAGH,SAAS,gBAAwB,QAAwG;AACvI,KAAI,MAAM,QAAQ,OAAO,CACvB,QAAO,OAAO,IAAI,cAAc;AAGlC,QAAO,cAAc,OAAO;;;;;;;;;;;;;;;;;;;;;AAsB9B,SAAgB,aAA0C,QAAyC;AACjG,KAAI,OAAO,WAAW,WACpB,SAAQ,OAAO,QAAoB;AACjC,SAAO,gBAAgB,MAAM,OAAO,IAAI,CAAC;;AAI7C,KAAI,UAAU,OAAO,CACnB,QAAO,OAAO,MAAM,aAAa,gBAAgB,SAAS,CAAC;AAG7D,QAAO,gBAAgB,OAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../internals/utils/src/promise.ts","../src/defineConfig.ts"],"sourcesContent":["function* chunks<T>(arr: readonly T[], size: number): Generator<T[]> {\n for (let i = 0; i < arr.length; i += size) {\n yield arr.slice(i, i + size)\n }\n}\n\nexport type ForBatchesOptions = {\n /**\n * Maximum batch size handed to `process`.\n * Parallel dispatch within a batch is the caller's responsibility\n * (typically via `Promise.all(batch.map(...))`).\n */\n concurrency: number\n /**\n * Called after every batch.\n *\n * Use a cheap, idempotent callback (e.g. one that short-circuits when there\n * is nothing new to do). The helper does not coalesce calls — if you need\n * throttling, do it inside `flush` itself.\n */\n flush?: () => Promise<void>\n}\n\n/**\n * Slices `source` into batches of `concurrency` items and awaits `process` for each batch.\n * Accepts both plain arrays (sync) and `AsyncIterable` (streaming).\n *\n * `process` controls whether items inside a batch run in parallel; this helper only\n * controls batch size and per-batch flushing.\n *\n * @example\n * ```ts\n * // parallel dispatch inside each batch\n * await forBatches(schemas, (batch) => Promise.all(batch.map(process)), { concurrency: 8 })\n *\n * // async iterable with a flush after every batch\n * await forBatches(stream.schemas, (batch) => dispatch(batch), { concurrency: 8, flush })\n * ```\n */\nexport async function forBatches<T>(\n source: readonly T[] | AsyncIterable<T>,\n process: (batch: T[]) => Promise<unknown>,\n options: ForBatchesOptions,\n): Promise<void> {\n const { concurrency, flush } = options\n\n if (Array.isArray(source)) {\n for (const batch of chunks(source, concurrency)) {\n await process(batch)\n if (flush) await flush()\n }\n return\n }\n\n const batch: T[] = []\n for await (const item of source) {\n batch.push(item)\n if (batch.length >= concurrency) {\n await process(batch.splice(0))\n\n if (flush) await flush()\n }\n }\n if (batch.length > 0) {\n await process(batch.splice(0))\n\n if (flush) await flush()\n }\n}\n\n/**\n * Runs `work`, passing `flush` as its periodic-flush callback, then calls\n * `flush` once more to drain any items that did not cross a flush boundary.\n *\n * @example\n * ```ts\n * await withDrain(\n * (flush) => processItems(items, { flush }),\n * () => writeRemainingFiles(),\n * )\n * ```\n */\nexport async function withDrain(work: (flush: () => Promise<void>) => Promise<void>, flush: () => Promise<void>): Promise<void> {\n await work(flush)\n await flush()\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 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\ntype Store<TKey, TValue> = {\n has(key: TKey): boolean\n get(key: TKey): TValue | undefined\n set(key: TKey, value: TValue): unknown\n}\n\n/**\n * Wraps `factory` with a keyed cache backed by the provided store.\n *\n * Pass a `WeakMap` for object keys (results are GC-eligible when the key is\n * collected) or a `Map` for primitive keys. For multi-argument functions,\n * nest two `memoize` calls — the outer keyed by the first argument, the\n * inner (created once per outer miss) keyed by the second.\n *\n * Because the cache is owned by the caller, it can be shared, inspected, or\n * cleared independently of the memoized function.\n *\n * @example Single WeakMap key\n * ```ts\n * const cache = new WeakMap<SchemaNode, Set<string>>()\n * const getRefs = memoize(cache, (node) => collectRefs(node))\n * ```\n *\n * @example Single Map key (primitive)\n * ```ts\n * const cache = new Map<string, Resolver>()\n * const getResolver = memoize(cache, (name) => buildResolver(name))\n * ```\n *\n * @example Two-level (object + primitive)\n * ```ts\n * const outer = new WeakMap<Params[], Map<string, Params[]>>()\n * const fn = memoize(outer, (params) => memoize(new Map(), (key) => transform(params, key)))\n * fn(params)('camelcase')\n * ```\n */\nexport function memoize<TKey, TValue>(store: Store<TKey, TValue>, factory: (key: TKey) => TValue): (key: TKey) => TValue {\n return (key: TKey): TValue => {\n if (store.has(key)) return store.get(key)!\n const value = factory(key)\n store.set(key, value)\n return value\n }\n}\n\n/**\n * Wraps a plain array in a reusable `AsyncIterable`.\n * Each `[Symbol.asyncIterator]()` call returns a fresh generator so the\n * iterable can be consumed multiple times (e.g. once per plugin pre-scan).\n *\n * @example\n * ```ts\n * const stream = arrayToAsyncIterable([1, 2, 3])\n * for await (const n of stream) console.log(n) // 1, 2, 3\n * ```\n */\nexport function arrayToAsyncIterable<T>(arr: readonly T[]): AsyncIterable<T> {\n return {\n [Symbol.asyncIterator]() {\n return (async function* () {\n yield* arr\n })()\n },\n }\n}\n","import { isPromise, type PossiblePromise } from '@internals/utils'\nimport { adapterOas } from '@kubb/adapter-oas'\nimport { cliReporter, type CLIOptions, fileReporter, jsonReporter, type UserConfig } from '@kubb/core'\nimport { middlewareBarrel, middlewareBarrelName } from '@kubb/middleware-barrel'\nimport { parserTs, parserTsx } from '@kubb/parser-ts'\nimport { parserMd } from '@kubb/parser-md'\n\ntype AnyConfigResult = UserConfig<any> | Array<UserConfig<any>>\ntype ConfigInput = AnyConfigResult | Promise<AnyConfigResult> | ((cli: CLIOptions) => PossiblePromise<AnyConfigResult>)\ntype NormalizeConfig<TConfig> =\n TConfig extends Array<UserConfig<infer TInput>> ? Array<UserConfig<TInput>> : TConfig extends UserConfig<infer TInput> ? UserConfig<TInput> : never\ntype DefinedConfig<TConfig extends ConfigInput> = TConfig extends (cli: CLIOptions) => PossiblePromise<infer TResult>\n ? (cli: CLIOptions) => Promise<NormalizeConfig<TResult>>\n : TConfig extends Promise<infer TResult>\n ? Promise<NormalizeConfig<TResult>>\n : NormalizeConfig<TConfig>\n\n/**\n * Applies default `root`, adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.\n *\n * - `root` defaults to `process.cwd()`\n * - `adapter` defaults to `adapterOas()`\n * - `parsers` defaults to `[parserTs, parserTsx, parserMd]`\n * - `reporters` defaults to `[cliReporter, jsonReporter, fileReporter]`\n * - `middleware` defaults to `[middlewareBarrel()]`\n * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.\n * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.\n * - `output.format` defaults to `false`\n * - `output.lint` defaults to `false`\n */\nfunction applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {\n const middleware = config.middleware?.length ? config.middleware : [middlewareBarrel()]\n const hasBarrelMiddleware = middleware.some((m) => m.name === middlewareBarrelName)\n\n const output = { ...config.output }\n if (hasBarrelMiddleware && output.barrel === undefined) {\n output.barrel = { type: 'named' }\n }\n if (output.format === undefined) {\n output.format = false\n }\n if (output.lint === undefined) {\n output.lint = false\n }\n\n return {\n ...config,\n root: config.root || process.cwd(),\n adapter: config.adapter ?? adapterOas(),\n parsers: config.parsers?.length ? config.parsers : [parserTs, parserTsx, parserMd],\n reporters: config.reporters?.length ? config.reporters : [cliReporter, jsonReporter, fileReporter],\n middleware,\n output,\n }\n}\n\nfunction normalizeConfig<TInput>(config: UserConfig<TInput> | Array<UserConfig<TInput>>): UserConfig<TInput> | Array<UserConfig<TInput>> {\n if (Array.isArray(config)) {\n return config.map(applyDefaults)\n }\n\n return applyDefaults(config)\n}\n\n/**\n * Defines a Kubb build configuration and applies sensible defaults so the\n * minimal config stays small.\n *\n * Defaults applied when omitted:\n * - `adapter` → `adapterOas()` (OpenAPI 2.0/3.0/3.1).\n * - `parsers` → `[parserTs, parserTsx, parserMd]`.\n * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.\n * - `middleware` → `[middlewareBarrel()]`.\n * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is\n * in the middleware list.\n * - `output.format` and `output.lint` → `false`.\n *\n * Accepts a config object, an array of configs, a Promise resolving to one,\n * or a function that receives the parsed CLI options and returns any of the\n * above. The return type is preserved so async/array variants stay typed.\n *\n * @example\n * ```ts\n * import { defineConfig } from 'kubb'\n * import { pluginTs } from '@kubb/plugin-ts'\n *\n * export default defineConfig({\n * input: { path: './petStore.yaml' },\n * output: { path: './src/gen' },\n * plugins: [pluginTs()],\n * })\n * ```\n *\n * @example Function form with CLI options\n * ```ts\n * import { defineConfig } from 'kubb'\n *\n * export default defineConfig(({ input }) => ({\n * input: { path: input ?? './petStore.yaml' },\n * output: { path: './src/gen' },\n * plugins: [],\n * }))\n * ```\n */\nexport function defineConfig<TConfig extends ConfigInput>(config: TConfig): DefinedConfig<TConfig> {\n if (typeof config === 'function') {\n return (async (cli: CLIOptions) => {\n return normalizeConfig(await config(cli))\n }) as DefinedConfig<TConfig>\n }\n\n if (isPromise(config)) {\n return config.then((resolved) => normalizeConfig(resolved)) as DefinedConfig<TConfig>\n }\n\n return normalizeConfig(config) as DefinedConfig<TConfig>\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0GA,SAAgB,UAAa,QAAkD;CAC7E,OAAO,WAAW,QAAQ,WAAW,KAAA,KAAa,OAAQ,OAAmC,YAAY;AAC3G;;;;;;;;;;;;;;;;AC9EA,SAAS,cAAsB,QAAgD;CAC7E,MAAM,aAAa,OAAO,YAAY,SAAS,OAAO,aAAa,CAAC,iBAAiB,CAAC;CACtF,MAAM,sBAAsB,WAAW,MAAM,MAAM,EAAE,SAAS,oBAAoB;CAElF,MAAM,SAAS,EAAE,GAAG,OAAO,OAAO;CAClC,IAAI,uBAAuB,OAAO,WAAW,KAAA,GAC3C,OAAO,SAAS,EAAE,MAAM,QAAQ;CAElC,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,SAAS;CAElB,IAAI,OAAO,SAAS,KAAA,GAClB,OAAO,OAAO;CAGhB,OAAO;EACL,GAAG;EACH,MAAM,OAAO,QAAQ,QAAQ,IAAI;EACjC,SAAS,OAAO,WAAW,WAAW;EACtC,SAAS,OAAO,SAAS,SAAS,OAAO,UAAU;GAAC;GAAU;GAAW;EAAQ;EACjF,WAAW,OAAO,WAAW,SAAS,OAAO,YAAY;GAAC;GAAa;GAAc;EAAY;EACjG;EACA;CACF;AACF;AAEA,SAAS,gBAAwB,QAAwG;CACvI,IAAI,MAAM,QAAQ,MAAM,GACtB,OAAO,OAAO,IAAI,aAAa;CAGjC,OAAO,cAAc,MAAM;AAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,aAA0C,QAAyC;CACjG,IAAI,OAAO,WAAW,YACpB,QAAQ,OAAO,QAAoB;EACjC,OAAO,gBAAgB,MAAM,OAAO,GAAG,CAAC;CAC1C;CAGF,IAAI,UAAU,MAAM,GAClB,OAAO,OAAO,MAAM,aAAa,gBAAgB,QAAQ,CAAC;CAG5D,OAAO,gBAAgB,MAAM;AAC/B"}
package/package.json CHANGED
@@ -1,24 +1,21 @@
1
1
  {
2
2
  "name": "kubb",
3
- "version": "5.0.0-beta.4",
4
- "description": "Transform OpenAPI specifications into TypeScript, React-Query, Zod, Faker.js, MSW and more with a plugin-based code generation tool.",
3
+ "version": "5.0.0-beta.40",
4
+ "description": "Meta-package and entry point for Kubb — a plugin-based code generation framework for OpenAPI. Includes defineConfig, all public APIs, and serves as the gateway to the entire Kubb ecosystem.",
5
5
  "keywords": [
6
6
  "api-client",
7
- "cli",
8
7
  "code-generator",
9
8
  "codegen",
10
9
  "faker",
11
10
  "kubb",
11
+ "meta-framework",
12
12
  "msw",
13
- "oas",
14
13
  "openapi",
15
14
  "plugin-system",
16
- "plugins",
17
15
  "react-query",
18
16
  "sdk-generator",
19
17
  "swagger",
20
18
  "tanstack-query",
21
- "type-safe",
22
19
  "typescript",
23
20
  "zod"
24
21
  ],
@@ -57,27 +54,25 @@
57
54
  "registry": "https://registry.npmjs.org/"
58
55
  },
59
56
  "dependencies": {
60
- "@kubb/adapter-oas": "5.0.0-beta.4",
61
- "@kubb/cli": "5.0.0-beta.4",
62
- "@kubb/core": "5.0.0-beta.4",
63
- "@kubb/middleware-barrel": "5.0.0-beta.4",
64
- "@kubb/parser-ts": "5.0.0-beta.4",
65
- "@kubb/renderer-jsx": "5.0.0-beta.4"
57
+ "@kubb/adapter-oas": "5.0.0-beta.40",
58
+ "@kubb/cli": "5.0.0-beta.40",
59
+ "@kubb/core": "5.0.0-beta.40",
60
+ "@kubb/mcp": "5.0.0-beta.40",
61
+ "@kubb/middleware-barrel": "5.0.0-beta.40",
62
+ "@kubb/parser-md": "5.0.0-beta.40",
63
+ "@kubb/parser-ts": "5.0.0-beta.40",
64
+ "@kubb/renderer-jsx": "5.0.0-beta.40"
66
65
  },
67
66
  "devDependencies": {
68
67
  "typescript": "^6.0.3",
69
68
  "@internals/utils": "0.0.0"
70
69
  },
71
70
  "peerDependencies": {
72
- "@kubb/agent": "5.0.0-beta.4",
73
- "@kubb/mcp": "5.0.0-beta.4"
71
+ "@kubb/agent": "5.0.0-beta.40"
74
72
  },
75
73
  "peerDependenciesMeta": {
76
74
  "@kubb/agent": {
77
75
  "optional": true
78
- },
79
- "@kubb/mcp": {
80
- "optional": true
81
76
  }
82
77
  },
83
78
  "size-limit": [
@@ -98,6 +93,7 @@
98
93
  "lint:fix": "oxlint --fix .",
99
94
  "release": "pnpm publish --no-git-check",
100
95
  "release:canary": "bash ../../.github/canary.sh && node ../../scripts/build.js canary && pnpm publish --no-git-check",
96
+ "release:stage": "pnpm stage publish --no-git-check",
101
97
  "start": "tsdown --watch",
102
98
  "test": "vitest --passWithNoTests",
103
99
  "typecheck": "tsc -p ./tsconfig.json --noEmit --emitDeclarationOnly false"
@@ -1,8 +1,9 @@
1
1
  import { isPromise, type PossiblePromise } from '@internals/utils'
2
2
  import { adapterOas } from '@kubb/adapter-oas'
3
- import type { CLIOptions, UserConfig } from '@kubb/core'
3
+ import { cliReporter, type CLIOptions, fileReporter, jsonReporter, type UserConfig } from '@kubb/core'
4
4
  import { middlewareBarrel, middlewareBarrelName } from '@kubb/middleware-barrel'
5
5
  import { parserTs, parserTsx } from '@kubb/parser-ts'
6
+ import { parserMd } from '@kubb/parser-md'
6
7
 
7
8
  type AnyConfigResult = UserConfig<any> | Array<UserConfig<any>>
8
9
  type ConfigInput = AnyConfigResult | Promise<AnyConfigResult> | ((cli: CLIOptions) => PossiblePromise<AnyConfigResult>)
@@ -15,15 +16,17 @@ type DefinedConfig<TConfig extends ConfigInput> = TConfig extends (cli: CLIOptio
15
16
  : NormalizeConfig<TConfig>
16
17
 
17
18
  /**
18
- * Applies default adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
19
+ * Applies default `root`, adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
19
20
  *
21
+ * - `root` defaults to `process.cwd()`
20
22
  * - `adapter` defaults to `adapterOas()`
21
- * - `parsers` defaults to `[parserTs, parserTsx]`
23
+ * - `parsers` defaults to `[parserTs, parserTsx, parserMd]`
24
+ * - `reporters` defaults to `[cliReporter, jsonReporter, fileReporter]`
22
25
  * - `middleware` defaults to `[middlewareBarrel()]`
23
26
  * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.
24
27
  * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.
25
- * - `output.format` defaults to `'auto'`
26
- * - `output.lint` defaults to `'auto'`
28
+ * - `output.format` defaults to `false`
29
+ * - `output.lint` defaults to `false`
27
30
  */
28
31
  function applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {
29
32
  const middleware = config.middleware?.length ? config.middleware : [middlewareBarrel()]
@@ -42,8 +45,10 @@ function applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {
42
45
 
43
46
  return {
44
47
  ...config,
48
+ root: config.root || process.cwd(),
45
49
  adapter: config.adapter ?? adapterOas(),
46
- parsers: config.parsers?.length ? config.parsers : [parserTs, parserTsx],
50
+ parsers: config.parsers?.length ? config.parsers : [parserTs, parserTsx, parserMd],
51
+ reporters: config.reporters?.length ? config.reporters : [cliReporter, jsonReporter, fileReporter],
47
52
  middleware,
48
53
  output,
49
54
  }
@@ -58,21 +63,42 @@ function normalizeConfig<TInput>(config: UserConfig<TInput> | Array<UserConfig<T
58
63
  }
59
64
 
60
65
  /**
61
- * Helper for defining a Kubb configuration with built-in defaults.
66
+ * Defines a Kubb build configuration and applies sensible defaults so the
67
+ * minimal config stays small.
62
68
  *
63
- * When no `adapter` is provided, `adapterOas()` is used automatically.
64
- * When no `parsers` are provided, `[parserTs, parserTsx]` is used automatically.
69
+ * Defaults applied when omitted:
70
+ * - `adapter` `adapterOas()` (OpenAPI 2.0/3.0/3.1).
71
+ * - `parsers` → `[parserTs, parserTsx, parserMd]`.
72
+ * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.
73
+ * - `middleware` → `[middlewareBarrel()]`.
74
+ * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is
75
+ * in the middleware list.
76
+ * - `output.format` and `output.lint` → `false`.
65
77
  *
66
- * Accepts either:
67
- * - A config object or array of configs
68
- * - A function returning the config(s), optionally async,
69
- * receiving the CLI options as argument
78
+ * Accepts a config object, an array of configs, a Promise resolving to one,
79
+ * or a function that receives the parsed CLI options and returns any of the
80
+ * above. The return type is preserved so async/array variants stay typed.
70
81
  *
71
82
  * @example
72
83
  * ```ts
73
- * export default defineConfig(({ logLevel }) => ({
74
- * root: 'src',
75
- * plugins: [myPlugin()],
84
+ * import { defineConfig } from 'kubb'
85
+ * import { pluginTs } from '@kubb/plugin-ts'
86
+ *
87
+ * export default defineConfig({
88
+ * input: { path: './petStore.yaml' },
89
+ * output: { path: './src/gen' },
90
+ * plugins: [pluginTs()],
91
+ * })
92
+ * ```
93
+ *
94
+ * @example Function form with CLI options
95
+ * ```ts
96
+ * import { defineConfig } from 'kubb'
97
+ *
98
+ * export default defineConfig(({ input }) => ({
99
+ * input: { path: input ?? './petStore.yaml' },
100
+ * output: { path: './src/gen' },
101
+ * plugins: [],
76
102
  * }))
77
103
  * ```
78
104
  */
File without changes