kubb 5.0.0-beta.50 → 5.0.0-beta.52

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
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#endregion
3
3
  let _kubb_adapter_oas = require("@kubb/adapter-oas");
4
4
  let _kubb_core = require("@kubb/core");
5
- let _kubb_middleware_barrel = require("@kubb/middleware-barrel");
5
+ let _kubb_plugin_barrel = require("@kubb/plugin-barrel");
6
6
  let _kubb_parser_ts = require("@kubb/parser-ts");
7
7
  let _kubb_parser_md = require("@kubb/parser-md");
8
8
  //#region ../../internals/utils/src/promise.ts
@@ -20,24 +20,24 @@ function isPromise(result) {
20
20
  //#endregion
21
21
  //#region src/defineConfig.ts
22
22
  /**
23
- * Applies default `root`, adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
23
+ * Applies default `root`, adapter, parsers, plugins, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
24
24
  *
25
25
  * - `root` defaults to `process.cwd()`
26
26
  * - `adapter` defaults to `adapterOas()`
27
27
  * - `parsers` defaults to `[parserTs, parserTsx, parserMd]`
28
28
  * - `reporters` defaults to `[cliReporter, jsonReporter, fileReporter]`
29
- * - `middleware` defaults to `[middlewareBarrel()]`
30
- * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.
31
- * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.
29
+ * - `plugins` gets `pluginBarrel()` appended when none is already present
30
+ * - `output.barrel` defaults to `{ type: 'named' }` **only when `pluginBarrel` is part of `plugins`**.
31
+ * When the user provides a plugins list without `pluginBarrel`, `barrel` is left untouched.
32
32
  * - `output.format` defaults to `false`
33
33
  * - `output.lint` defaults to `false`
34
34
  * - `cache` defaults to `fsCache()`; pass `false` to turn caching off
35
35
  */
36
36
  function applyDefaults(config) {
37
- const middleware = config.middleware?.length ? config.middleware : [(0, _kubb_middleware_barrel.middlewareBarrel)()];
38
- const hasBarrelMiddleware = middleware.some((m) => m.name === _kubb_middleware_barrel.middlewareBarrelName);
37
+ const plugins = config.plugins?.some((p) => p.name === _kubb_plugin_barrel.pluginBarrelName) ? config.plugins ?? [] : [...config.plugins ?? [], (0, _kubb_plugin_barrel.pluginBarrel)()];
38
+ const hasBarrelPlugin = plugins.some((p) => p.name === _kubb_plugin_barrel.pluginBarrelName);
39
39
  const output = { ...config.output };
40
- if (hasBarrelMiddleware && output.barrel === void 0) output.barrel = { type: "named" };
40
+ if (hasBarrelPlugin && output.barrel === void 0) output.barrel = { type: "named" };
41
41
  if (output.format === void 0) output.format = false;
42
42
  if (output.lint === void 0) output.lint = false;
43
43
  return {
@@ -54,7 +54,7 @@ function applyDefaults(config) {
54
54
  _kubb_core.jsonReporter,
55
55
  _kubb_core.fileReporter
56
56
  ],
57
- middleware,
57
+ plugins,
58
58
  output,
59
59
  cache: config.cache === void 0 ? (0, _kubb_core.fsCache)() : config.cache
60
60
  };
@@ -71,9 +71,9 @@ function normalizeConfig(config) {
71
71
  * - `adapter` → `adapterOas()` (OpenAPI 2.0/3.0/3.1).
72
72
  * - `parsers` → `[parserTs, parserTsx, parserMd]`.
73
73
  * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.
74
- * - `middleware` → `[middlewareBarrel()]`.
75
- * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is
76
- * in the middleware list.
74
+ * - `plugins` → `pluginBarrel()` is appended when not already present.
75
+ * - `output.barrel` → `{ type: 'named' }` only when `pluginBarrel` is
76
+ * in the plugins list.
77
77
  * - `output.format` and `output.lint` → `false`.
78
78
  * - `cache` → `fsCache()` (local disk); pass `false` to turn caching off.
79
79
  *
@@ -1 +1 @@
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, fsCache, 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 * - `cache` defaults to `fsCache()`; pass `false` to turn caching off\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 cache: config.cache === undefined ? fsCache() : config.cache,\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 * - `cache` → `fsCache()` (local disk); pass `false` to turn caching off.\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;;;;;;;;;;;;;;;;;AC7EA,SAAS,cAAsB,QAAgD;CAC7E,MAAM,aAAa,OAAO,YAAY,SAAS,OAAO,aAAa,EAAA,GAAA,wBAAA,iBAAA,CAAkB,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,WAAA,CAAsB;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;EACA,OAAO,OAAO,UAAU,KAAA,KAAA,GAAA,WAAA,QAAA,CAAoB,IAAI,OAAO;CACzD;AACF;AAEA,SAAS,gBAAwB,QAAwG;CACvI,IAAI,MAAM,QAAQ,MAAM,GACtB,OAAO,OAAO,IAAI,aAAa;CAGjC,OAAO,cAAc,MAAM;AAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,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"}
1
+ {"version":3,"file":"index.cjs","names":["pluginBarrelName","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, fsCache, jsonReporter, type UserConfig } from '@kubb/core'\nimport { pluginBarrel, pluginBarrelName } from '@kubb/plugin-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, plugins, `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 * - `plugins` gets `pluginBarrel()` appended when none is already present\n * - `output.barrel` defaults to `{ type: 'named' }` **only when `pluginBarrel` is part of `plugins`**.\n * When the user provides a plugins list without `pluginBarrel`, `barrel` is left untouched.\n * - `output.format` defaults to `false`\n * - `output.lint` defaults to `false`\n * - `cache` defaults to `fsCache()`; pass `false` to turn caching off\n */\nfunction applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {\n const alreadyHasBarrel = config.plugins?.some((p) => p.name === pluginBarrelName)\n const plugins = alreadyHasBarrel ? (config.plugins ?? []) : [...(config.plugins ?? []), pluginBarrel()]\n const hasBarrelPlugin = plugins.some((p) => p.name === pluginBarrelName)\n\n const output = { ...config.output }\n if (hasBarrelPlugin && 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 plugins,\n output,\n cache: config.cache === undefined ? fsCache() : config.cache,\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 * - `plugins` → `pluginBarrel()` is appended when not already present.\n * - `output.barrel` → `{ type: 'named' }` only when `pluginBarrel` is\n * in the plugins list.\n * - `output.format` and `output.lint` → `false`.\n * - `cache` → `fsCache()` (local disk); pass `false` to turn caching off.\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;;;;;;;;;;;;;;;;;AC7EA,SAAS,cAAsB,QAAgD;CAE7E,MAAM,UADmB,OAAO,SAAS,MAAM,MAAM,EAAE,SAASA,oBAAAA,gBAAgB,IAC5C,OAAO,WAAW,CAAC,IAAK,CAAC,GAAI,OAAO,WAAW,CAAC,IAAA,GAAA,oBAAA,aAAA,CAAiB,CAAC;CACtG,MAAM,kBAAkB,QAAQ,MAAM,MAAM,EAAE,SAASA,oBAAAA,gBAAgB;CAEvE,MAAM,SAAS,EAAE,GAAG,OAAO,OAAO;CAClC,IAAI,mBAAmB,OAAO,WAAW,KAAA,GACvC,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,WAAA,CAAsB;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;EACA,OAAO,OAAO,UAAU,KAAA,KAAA,GAAA,WAAA,QAAA,CAAoB,IAAI,OAAO;CACzD;AACF;AAEA,SAAS,gBAAwB,QAAwG;CACvI,IAAI,MAAM,QAAQ,MAAM,GACtB,OAAO,OAAO,IAAI,aAAa;CAGjC,OAAO,cAAc,MAAM;AAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,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
1
  import { t as __name } from "./chunk-C0LytTxp.js";
2
2
  import { CLIOptions, UserConfig } from "@kubb/core";
3
- import { BarrelType } from "@kubb/middleware-barrel";
3
+ import { BarrelType } from "@kubb/plugin-barrel";
4
4
 
5
5
  //#region ../../internals/utils/src/promise.d.ts
6
6
  /** A value that may already be resolved or still pending.
@@ -27,9 +27,9 @@ type DefinedConfig<TConfig extends ConfigInput> = TConfig extends ((cli: CLIOpti
27
27
  * - `adapter` → `adapterOas()` (OpenAPI 2.0/3.0/3.1).
28
28
  * - `parsers` → `[parserTs, parserTsx, parserMd]`.
29
29
  * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.
30
- * - `middleware` → `[middlewareBarrel()]`.
31
- * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is
32
- * in the middleware list.
30
+ * - `plugins` → `pluginBarrel()` is appended when not already present.
31
+ * - `output.barrel` → `{ type: 'named' }` only when `pluginBarrel` is
32
+ * in the plugins list.
33
33
  * - `output.format` and `output.lint` → `false`.
34
34
  * - `cache` → `fsCache()` (local disk); pass `false` to turn caching off.
35
35
  *
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import "./chunk-C0LytTxp.js";
2
2
  import { adapterOas } from "@kubb/adapter-oas";
3
3
  import { cliReporter, fileReporter, fsCache, jsonReporter } from "@kubb/core";
4
- import { middlewareBarrel, middlewareBarrelName } from "@kubb/middleware-barrel";
4
+ import { pluginBarrel, pluginBarrelName } from "@kubb/plugin-barrel";
5
5
  import { parserTs, parserTsx } from "@kubb/parser-ts";
6
6
  import { parserMd } from "@kubb/parser-md";
7
7
  //#region ../../internals/utils/src/promise.ts
@@ -19,24 +19,24 @@ function isPromise(result) {
19
19
  //#endregion
20
20
  //#region src/defineConfig.ts
21
21
  /**
22
- * Applies default `root`, adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
22
+ * Applies default `root`, adapter, parsers, plugins, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
23
23
  *
24
24
  * - `root` defaults to `process.cwd()`
25
25
  * - `adapter` defaults to `adapterOas()`
26
26
  * - `parsers` defaults to `[parserTs, parserTsx, parserMd]`
27
27
  * - `reporters` defaults to `[cliReporter, jsonReporter, fileReporter]`
28
- * - `middleware` defaults to `[middlewareBarrel()]`
29
- * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.
30
- * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.
28
+ * - `plugins` gets `pluginBarrel()` appended when none is already present
29
+ * - `output.barrel` defaults to `{ type: 'named' }` **only when `pluginBarrel` is part of `plugins`**.
30
+ * When the user provides a plugins list without `pluginBarrel`, `barrel` is left untouched.
31
31
  * - `output.format` defaults to `false`
32
32
  * - `output.lint` defaults to `false`
33
33
  * - `cache` defaults to `fsCache()`; pass `false` to turn caching off
34
34
  */
35
35
  function applyDefaults(config) {
36
- const middleware = config.middleware?.length ? config.middleware : [middlewareBarrel()];
37
- const hasBarrelMiddleware = middleware.some((m) => m.name === middlewareBarrelName);
36
+ const plugins = config.plugins?.some((p) => p.name === pluginBarrelName) ? config.plugins ?? [] : [...config.plugins ?? [], pluginBarrel()];
37
+ const hasBarrelPlugin = plugins.some((p) => p.name === pluginBarrelName);
38
38
  const output = { ...config.output };
39
- if (hasBarrelMiddleware && output.barrel === void 0) output.barrel = { type: "named" };
39
+ if (hasBarrelPlugin && output.barrel === void 0) output.barrel = { type: "named" };
40
40
  if (output.format === void 0) output.format = false;
41
41
  if (output.lint === void 0) output.lint = false;
42
42
  return {
@@ -53,7 +53,7 @@ function applyDefaults(config) {
53
53
  jsonReporter,
54
54
  fileReporter
55
55
  ],
56
- middleware,
56
+ plugins,
57
57
  output,
58
58
  cache: config.cache === void 0 ? fsCache() : config.cache
59
59
  };
@@ -70,9 +70,9 @@ function normalizeConfig(config) {
70
70
  * - `adapter` → `adapterOas()` (OpenAPI 2.0/3.0/3.1).
71
71
  * - `parsers` → `[parserTs, parserTsx, parserMd]`.
72
72
  * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.
73
- * - `middleware` → `[middlewareBarrel()]`.
74
- * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is
75
- * in the middleware list.
73
+ * - `plugins` → `pluginBarrel()` is appended when not already present.
74
+ * - `output.barrel` → `{ type: 'named' }` only when `pluginBarrel` is
75
+ * in the plugins list.
76
76
  * - `output.format` and `output.lint` → `false`.
77
77
  * - `cache` → `fsCache()` (local disk); pass `false` to turn caching off.
78
78
  *
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":["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, fsCache, 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 * - `cache` defaults to `fsCache()`; pass `false` to turn caching off\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 cache: config.cache === undefined ? fsCache() : config.cache,\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 * - `cache` → `fsCache()` (local disk); pass `false` to turn caching off.\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;;;;;;;;;;;;;;;;;AC7EA,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;EACA,OAAO,OAAO,UAAU,KAAA,IAAY,QAAQ,IAAI,OAAO;CACzD;AACF;AAEA,SAAS,gBAAwB,QAAwG;CACvI,IAAI,MAAM,QAAQ,MAAM,GACtB,OAAO,OAAO,IAAI,aAAa;CAGjC,OAAO,cAAc,MAAM;AAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,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"}
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, fsCache, jsonReporter, type UserConfig } from '@kubb/core'\nimport { pluginBarrel, pluginBarrelName } from '@kubb/plugin-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, plugins, `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 * - `plugins` gets `pluginBarrel()` appended when none is already present\n * - `output.barrel` defaults to `{ type: 'named' }` **only when `pluginBarrel` is part of `plugins`**.\n * When the user provides a plugins list without `pluginBarrel`, `barrel` is left untouched.\n * - `output.format` defaults to `false`\n * - `output.lint` defaults to `false`\n * - `cache` defaults to `fsCache()`; pass `false` to turn caching off\n */\nfunction applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {\n const alreadyHasBarrel = config.plugins?.some((p) => p.name === pluginBarrelName)\n const plugins = alreadyHasBarrel ? (config.plugins ?? []) : [...(config.plugins ?? []), pluginBarrel()]\n const hasBarrelPlugin = plugins.some((p) => p.name === pluginBarrelName)\n\n const output = { ...config.output }\n if (hasBarrelPlugin && 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 plugins,\n output,\n cache: config.cache === undefined ? fsCache() : config.cache,\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 * - `plugins` → `pluginBarrel()` is appended when not already present.\n * - `output.barrel` → `{ type: 'named' }` only when `pluginBarrel` is\n * in the plugins list.\n * - `output.format` and `output.lint` → `false`.\n * - `cache` → `fsCache()` (local disk); pass `false` to turn caching off.\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;;;;;;;;;;;;;;;;;AC7EA,SAAS,cAAsB,QAAgD;CAE7E,MAAM,UADmB,OAAO,SAAS,MAAM,MAAM,EAAE,SAAS,gBAAgB,IAC5C,OAAO,WAAW,CAAC,IAAK,CAAC,GAAI,OAAO,WAAW,CAAC,GAAI,aAAa,CAAC;CACtG,MAAM,kBAAkB,QAAQ,MAAM,MAAM,EAAE,SAAS,gBAAgB;CAEvE,MAAM,SAAS,EAAE,GAAG,OAAO,OAAO;CAClC,IAAI,mBAAmB,OAAO,WAAW,KAAA,GACvC,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;EACA,OAAO,OAAO,UAAU,KAAA,IAAY,QAAQ,IAAI,OAAO;CACzD;AACF;AAEA,SAAS,gBAAwB,QAAwG;CACvI,IAAI,MAAM,QAAQ,MAAM,GACtB,OAAO,OAAO,IAAI,aAAa;CAGjC,OAAO,cAAc,MAAM;AAC7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,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,6 +1,6 @@
1
1
  {
2
2
  "name": "kubb",
3
- "version": "5.0.0-beta.50",
3
+ "version": "5.0.0-beta.52",
4
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",
@@ -54,14 +54,14 @@
54
54
  "registry": "https://registry.npmjs.org/"
55
55
  },
56
56
  "dependencies": {
57
- "@kubb/adapter-oas": "5.0.0-beta.50",
58
- "@kubb/cli": "5.0.0-beta.50",
59
- "@kubb/core": "5.0.0-beta.50",
60
- "@kubb/mcp": "5.0.0-beta.50",
61
- "@kubb/middleware-barrel": "5.0.0-beta.50",
62
- "@kubb/parser-md": "5.0.0-beta.50",
63
- "@kubb/parser-ts": "5.0.0-beta.50",
64
- "@kubb/renderer-jsx": "5.0.0-beta.50"
57
+ "@kubb/adapter-oas": "5.0.0-beta.52",
58
+ "@kubb/cli": "5.0.0-beta.52",
59
+ "@kubb/core": "5.0.0-beta.52",
60
+ "@kubb/mcp": "5.0.0-beta.52",
61
+ "@kubb/parser-md": "5.0.0-beta.52",
62
+ "@kubb/parser-ts": "5.0.0-beta.52",
63
+ "@kubb/plugin-barrel": "5.0.0-beta.52",
64
+ "@kubb/renderer-jsx": "5.0.0-beta.52"
65
65
  },
66
66
  "devDependencies": {
67
67
  "typescript": "^6.0.3",
@@ -1,7 +1,7 @@
1
1
  import { isPromise, type PossiblePromise } from '@internals/utils'
2
2
  import { adapterOas } from '@kubb/adapter-oas'
3
3
  import { cliReporter, type CLIOptions, fileReporter, fsCache, jsonReporter, type UserConfig } from '@kubb/core'
4
- import { middlewareBarrel, middlewareBarrelName } from '@kubb/middleware-barrel'
4
+ import { pluginBarrel, pluginBarrelName } from '@kubb/plugin-barrel'
5
5
  import { parserTs, parserTsx } from '@kubb/parser-ts'
6
6
  import { parserMd } from '@kubb/parser-md'
7
7
 
@@ -16,25 +16,26 @@ type DefinedConfig<TConfig extends ConfigInput> = TConfig extends (cli: CLIOptio
16
16
  : NormalizeConfig<TConfig>
17
17
 
18
18
  /**
19
- * Applies default `root`, adapter, parsers, middleware, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
19
+ * Applies default `root`, adapter, parsers, plugins, `output.barrel`, `output.format`, and `output.lint` to a single user config when not set.
20
20
  *
21
21
  * - `root` defaults to `process.cwd()`
22
22
  * - `adapter` defaults to `adapterOas()`
23
23
  * - `parsers` defaults to `[parserTs, parserTsx, parserMd]`
24
24
  * - `reporters` defaults to `[cliReporter, jsonReporter, fileReporter]`
25
- * - `middleware` defaults to `[middlewareBarrel()]`
26
- * - `output.barrel` defaults to `{ type: 'named' }` **only when `middlewareBarrel` is part of `middleware`**.
27
- * When the user provides a custom middleware list without `middlewareBarrel`, `barrel` is left untouched.
25
+ * - `plugins` gets `pluginBarrel()` appended when none is already present
26
+ * - `output.barrel` defaults to `{ type: 'named' }` **only when `pluginBarrel` is part of `plugins`**.
27
+ * When the user provides a plugins list without `pluginBarrel`, `barrel` is left untouched.
28
28
  * - `output.format` defaults to `false`
29
29
  * - `output.lint` defaults to `false`
30
30
  * - `cache` defaults to `fsCache()`; pass `false` to turn caching off
31
31
  */
32
32
  function applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {
33
- const middleware = config.middleware?.length ? config.middleware : [middlewareBarrel()]
34
- const hasBarrelMiddleware = middleware.some((m) => m.name === middlewareBarrelName)
33
+ const alreadyHasBarrel = config.plugins?.some((p) => p.name === pluginBarrelName)
34
+ const plugins = alreadyHasBarrel ? (config.plugins ?? []) : [...(config.plugins ?? []), pluginBarrel()]
35
+ const hasBarrelPlugin = plugins.some((p) => p.name === pluginBarrelName)
35
36
 
36
37
  const output = { ...config.output }
37
- if (hasBarrelMiddleware && output.barrel === undefined) {
38
+ if (hasBarrelPlugin && output.barrel === undefined) {
38
39
  output.barrel = { type: 'named' }
39
40
  }
40
41
  if (output.format === undefined) {
@@ -50,7 +51,7 @@ function applyDefaults<TInput>(config: UserConfig<TInput>): UserConfig<TInput> {
50
51
  adapter: config.adapter ?? adapterOas(),
51
52
  parsers: config.parsers?.length ? config.parsers : [parserTs, parserTsx, parserMd],
52
53
  reporters: config.reporters?.length ? config.reporters : [cliReporter, jsonReporter, fileReporter],
53
- middleware,
54
+ plugins,
54
55
  output,
55
56
  cache: config.cache === undefined ? fsCache() : config.cache,
56
57
  }
@@ -72,9 +73,9 @@ function normalizeConfig<TInput>(config: UserConfig<TInput> | Array<UserConfig<T
72
73
  * - `adapter` → `adapterOas()` (OpenAPI 2.0/3.0/3.1).
73
74
  * - `parsers` → `[parserTs, parserTsx, parserMd]`.
74
75
  * - `reporters` → `[cliReporter, jsonReporter, fileReporter]`.
75
- * - `middleware` → `[middlewareBarrel()]`.
76
- * - `output.barrel` → `{ type: 'named' }` only when `middlewareBarrel` is
77
- * in the middleware list.
76
+ * - `plugins` → `pluginBarrel()` is appended when not already present.
77
+ * - `output.barrel` → `{ type: 'named' }` only when `pluginBarrel` is
78
+ * in the plugins list.
78
79
  * - `output.format` and `output.lint` → `false`.
79
80
  * - `cache` → `fsCache()` (local disk); pass `false` to turn caching off.
80
81
  *
package/src/index.ts CHANGED
@@ -1,2 +1,2 @@
1
- export type { BarrelType } from '@kubb/middleware-barrel'
1
+ export type { BarrelType } from '@kubb/plugin-barrel'
2
2
  export { defineConfig } from './defineConfig.ts'