@kubb/core 5.0.0-alpha.8 → 5.0.0-beta.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +23 -20
  2. package/dist/PluginDriver-BXibeQk-.cjs +1036 -0
  3. package/dist/PluginDriver-BXibeQk-.cjs.map +1 -0
  4. package/dist/PluginDriver-DV3p2Hky.js +945 -0
  5. package/dist/PluginDriver-DV3p2Hky.js.map +1 -0
  6. package/dist/index.cjs +756 -1693
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.ts +297 -239
  9. package/dist/index.js +743 -1661
  10. package/dist/index.js.map +1 -1
  11. package/dist/mocks.cjs +145 -0
  12. package/dist/mocks.cjs.map +1 -0
  13. package/dist/mocks.d.ts +80 -0
  14. package/dist/mocks.js +140 -0
  15. package/dist/mocks.js.map +1 -0
  16. package/dist/types-CuNocrbJ.d.ts +2148 -0
  17. package/package.json +51 -57
  18. package/src/FileManager.ts +115 -0
  19. package/src/FileProcessor.ts +86 -0
  20. package/src/Kubb.ts +208 -160
  21. package/src/PluginDriver.ts +326 -565
  22. package/src/constants.ts +20 -47
  23. package/src/createAdapter.ts +16 -6
  24. package/src/createKubb.ts +548 -0
  25. package/src/createRenderer.ts +57 -0
  26. package/src/createStorage.ts +40 -26
  27. package/src/defineGenerator.ts +87 -0
  28. package/src/defineLogger.ts +19 -0
  29. package/src/defineMiddleware.ts +62 -0
  30. package/src/defineParser.ts +44 -0
  31. package/src/definePlugin.ts +83 -0
  32. package/src/defineResolver.ts +521 -0
  33. package/src/devtools.ts +14 -14
  34. package/src/index.ts +14 -17
  35. package/src/mocks.ts +178 -0
  36. package/src/renderNode.ts +35 -0
  37. package/src/storages/fsStorage.ts +41 -11
  38. package/src/storages/memoryStorage.ts +4 -2
  39. package/src/types.ts +1054 -270
  40. package/src/utils/diagnostics.ts +4 -1
  41. package/src/utils/isInputPath.ts +10 -0
  42. package/src/utils/packageJSON.ts +99 -0
  43. package/dist/PluginDriver-DRfJIbG1.d.ts +0 -1056
  44. package/dist/chunk-ByKO4r7w.cjs +0 -38
  45. package/dist/hooks.cjs +0 -102
  46. package/dist/hooks.cjs.map +0 -1
  47. package/dist/hooks.d.ts +0 -75
  48. package/dist/hooks.js +0 -97
  49. package/dist/hooks.js.map +0 -1
  50. package/src/PackageManager.ts +0 -180
  51. package/src/build.ts +0 -419
  52. package/src/config.ts +0 -56
  53. package/src/createGenerator.ts +0 -106
  54. package/src/createLogger.ts +0 -7
  55. package/src/createPlugin.ts +0 -12
  56. package/src/errors.ts +0 -1
  57. package/src/hooks/index.ts +0 -4
  58. package/src/hooks/useKubb.ts +0 -138
  59. package/src/hooks/useMode.ts +0 -11
  60. package/src/hooks/usePlugin.ts +0 -11
  61. package/src/hooks/usePluginDriver.ts +0 -11
  62. package/src/utils/FunctionParams.ts +0 -155
  63. package/src/utils/TreeNode.ts +0 -215
  64. package/src/utils/executeStrategies.ts +0 -81
  65. package/src/utils/formatters.ts +0 -56
  66. package/src/utils/getBarrelFiles.ts +0 -141
  67. package/src/utils/getConfigs.ts +0 -30
  68. package/src/utils/getPlugins.ts +0 -23
  69. package/src/utils/linters.ts +0 -25
  70. package/src/utils/resolveOptions.ts +0 -93
package/src/types.ts CHANGED
@@ -1,241 +1,420 @@
1
1
  import type { AsyncEventEmitter, PossiblePromise } from '@internals/utils'
2
- import type { RootNode, SchemaNode } from '@kubb/ast/types'
3
- import type { Fabric as FabricType, KubbFile } from '@kubb/fabric-core/types'
2
+ import type { FileNode, HttpMethod, ImportNode, InputNode, Node, SchemaNode, UserFileNode, Visitor } from '@kubb/ast'
4
3
  import type { DEFAULT_STUDIO_URL, logLevel } from './constants.ts'
5
- import type { DefineStorage } from './createStorage.ts'
6
- import type { KubbEvents } from './Kubb.ts'
4
+ import type { RendererFactory } from './createRenderer.ts'
5
+ import type { Storage } from './createStorage.ts'
6
+ import type { Generator } from './defineGenerator.ts'
7
+ import type { Middleware } from './defineMiddleware.ts'
8
+ import type { Parser } from './defineParser.ts'
9
+ import type { Plugin } from './definePlugin.ts'
10
+ import type { KubbHooks } from './Kubb.ts'
7
11
  import type { PluginDriver } from './PluginDriver.ts'
8
12
 
9
- export type { Printer, PrinterFactoryOptions } from '@kubb/ast/types'
10
-
11
- declare global {
12
- namespace Kubb {
13
- interface PluginContext {}
14
- }
15
- }
13
+ export type { Renderer, RendererFactory } from './createRenderer.ts'
16
14
 
17
15
  /**
18
- * Config used in `kubb.config.ts`
16
+ * Safely extracts a type from a registry, returning `{}` if the key doesn't exist.
17
+ * Enables optional interface augmentation for `Kubb.ConfigOptionsRegistry` and `Kubb.PluginOptionsRegistry`
18
+ * without requiring changes to core.
19
19
  *
20
- * @example
21
- * import { defineConfig } from '@kubb/core'
22
- * export default defineConfig({
23
- * ...
24
- * })
20
+ * @internal
25
21
  */
26
- export type UserConfig<TInput = Input> = Omit<Config<TInput>, 'root' | 'plugins'> & {
27
- /**
28
- * The project root directory, which can be either an absolute path or a path relative to the location of your `kubb.config.ts` file.
29
- * @default process.cwd()
30
- */
31
- root?: string
32
- /**
33
- * An array of Kubb plugins used for generation. Each plugin may have additional configurable options (defined within the plugin itself). If a plugin relies on another plugin, an error will occur if the required dependency is missing. Refer to “pre” for more details.
34
- */
35
- // inject needs to be omitted because else we have a clash with the PluginDriver instance
36
- plugins?: Array<Omit<UnknownUserPlugin, 'inject'>>
37
- }
22
+ type ExtractRegistryKey<T, K extends PropertyKey> = K extends keyof T ? T[K] : {}
38
23
 
24
+ /**
25
+ * Reference to an input file to generate code from.
26
+ *
27
+ * Specify an absolute path or a path relative to the config file location.
28
+ * The adapter will parse this file (e.g., OpenAPI YAML or JSON) into the universal AST.
29
+ */
39
30
  export type InputPath = {
40
31
  /**
41
- * Specify your Swagger/OpenAPI file, either as an absolute path or a path relative to the root.
32
+ * Path to your Swagger/OpenAPI file, absolute or relative to the config file location.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * { path: './petstore.yaml' }
37
+ * { path: '/absolute/path/to/openapi.json' }
38
+ * ```
42
39
  */
43
40
  path: string
44
41
  }
45
42
 
43
+ /**
44
+ * Inline input data to generate code from.
45
+ *
46
+ * Useful when you want to pass the specification directly instead of from a file.
47
+ * Can be a string (YAML/JSON) or a parsed object.
48
+ */
46
49
  export type InputData = {
47
50
  /**
48
- * A `string` or `object` that contains your Swagger/OpenAPI data.
51
+ * Swagger/OpenAPI data as a string (YAML/JSON) or a parsed object.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * { data: fs.readFileSync('./openapi.yaml', 'utf8') }
56
+ * { data: { openapi: '3.1.0', info: { ... } } }
57
+ * ```
49
58
  */
50
59
  data: string | unknown
51
60
  }
52
61
 
53
- type Input = InputPath | InputData | Array<InputPath>
62
+ type Input = InputPath | InputData
54
63
 
55
64
  /**
56
- * The raw source passed to an adapter's `parse` function.
57
- * Mirrors the shape of `Config['input']` with paths already resolved to absolute.
65
+ * Source data passed to an adapter's `parse` function.
66
+ * Mirrors the config input shape with paths resolved to absolute.
58
67
  */
59
68
  export type AdapterSource = { type: 'path'; path: string } | { type: 'data'; data: string | unknown } | { type: 'paths'; paths: Array<string> }
60
69
 
61
70
  /**
62
- * Type parameters for an adapter definition.
71
+ * Generic type parameters for an adapter definition.
63
72
  *
64
- * Mirrors `PluginFactoryOptions` but scoped to the adapter lifecycle:
65
- * - `TName` — unique string identifier (e.g. `'oas'`, `'asyncapi'`)
66
- * - `TOptions` — raw user-facing options passed to the adapter factory
67
- * - `TResolvedOptions` — defaults applied; what the adapter stores as `options`
73
+ * - `TName` unique identifier (e.g. `'oas'`, `'asyncapi'`)
74
+ * - `TOptions` — user-facing options passed to the adapter factory
75
+ * - `TResolvedOptions` — options after defaults applied
76
+ * - `TDocument` — type of the parsed source document
68
77
  */
69
- export type AdapterFactoryOptions<TName extends string = string, TOptions extends object = object, TResolvedOptions extends object = TOptions> = {
78
+ export type AdapterFactoryOptions<
79
+ TName extends string = string,
80
+ TOptions extends object = object,
81
+ TResolvedOptions extends object = TOptions,
82
+ TDocument = unknown,
83
+ > = {
70
84
  name: TName
71
85
  options: TOptions
72
86
  resolvedOptions: TResolvedOptions
87
+ document: TDocument
73
88
  }
74
89
 
75
90
  /**
76
- * An adapter converts a source file or data into a `@kubb/ast` `RootNode`.
91
+ * Adapter that converts input files or data into an `InputNode`.
77
92
  *
78
- * Adapters are the single entry-point for different schema formats
79
- * (OpenAPI, AsyncAPI, Drizzle, …) and produce the universal `RootNode`
80
- * that all Kubb plugins consume.
93
+ * Adapters parse different schema formats (OpenAPI, AsyncAPI, Drizzle, etc.) into Kubb's
94
+ * universal intermediate representation that all plugins consume.
81
95
  *
82
96
  * @example
83
97
  * ```ts
84
- * import { oasAdapter } from '@kubb/adapter-oas'
98
+ * import { adapterOas } from '@kubb/adapter-oas'
85
99
  *
86
100
  * export default defineConfig({
87
- * adapter: adapterOas(), // default — OpenAPI / Swagger
88
- * input: { path: './openapi.yaml' },
101
+ * adapter: adapterOas(),
102
+ * input: { path: './openapi.yaml' },
89
103
  * plugins: [pluginTs(), pluginZod()],
90
104
  * })
91
105
  * ```
92
106
  */
93
107
  export type Adapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptions> = {
94
- /** Human-readable identifier, e.g. `'oas'`, `'drizzle'`, `'asyncapi'`. */
108
+ /**
109
+ * Human-readable adapter identifier (e.g. `'oas'`, `'asyncapi'`).
110
+ */
95
111
  name: TOptions['name']
96
- /** Resolved options (after defaults have been applied). */
112
+ /**
113
+ * Resolved adapter options after defaults have been applied.
114
+ */
97
115
  options: TOptions['resolvedOptions']
98
- /** Convert the raw source into a universal `RootNode`. */
99
- parse: (source: AdapterSource) => PossiblePromise<RootNode>
100
116
  /**
101
- * Extracts `KubbFile.Import` entries needed by a `SchemaNode` tree.
102
- * Populated after the first `parse()` call. Returns an empty array before that.
117
+ * Parsed source document after the first `parse()` call. `null` before parsing.
118
+ */
119
+ document: TOptions['document'] | null
120
+ inputNode: InputNode | null
121
+ /**
122
+ * Parse the source into a universal `InputNode`.
123
+ */
124
+ parse: (source: AdapterSource) => PossiblePromise<InputNode>
125
+ /**
126
+ * Extract `ImportNode` entries for a schema tree.
127
+ * Returns an empty array before the first `parse()` call.
103
128
  *
104
129
  * The `resolve` callback receives the collision-corrected schema name and must
105
- * return the `{ name, path }` pair for the import, or `undefined` to skip it.
130
+ * return `{ name, path }` for the import, or `undefined` to skip it.
106
131
  */
107
- getImports: (node: SchemaNode, resolve: (schemaName: string) => { name: string; path: string }) => Array<KubbFile.Import>
132
+ getImports: (node: SchemaNode, resolve: (schemaName: string) => { name: string; path: string }) => Array<ImportNode>
108
133
  }
109
134
 
110
- export type BarrelType = 'all' | 'named' | 'propagate'
111
-
112
135
  export type DevtoolsOptions = {
113
136
  /**
114
- * Open the AST inspector view (`/ast`) in Kubb Studio.
115
- * When `false`, opens the main Studio page instead.
137
+ * Open the AST inspector in Kubb Studio (`/ast`). Defaults to the main Studio page.
116
138
  * @default false
117
139
  */
118
140
  ast?: boolean
119
141
  }
120
142
 
121
143
  /**
144
+ * Build configuration for Kubb code generation.
145
+ *
146
+ * The Config is the main entry point for customizing how Kubb generates code. It specifies:
147
+ * - What to generate from (adapter + input)
148
+ * - Where to output generated code (output)
149
+ * - How to generate (plugins + middleware)
150
+ * - Runtime details (parsers, storage, renderer)
151
+ *
152
+ * See `UserConfig` for a relaxed version with sensible defaults.
153
+ *
122
154
  * @private
123
155
  */
124
156
  export type Config<TInput = Input> = {
125
157
  /**
126
- * The name to display in the CLI output.
158
+ * Display name for this configuration in CLI output and logs.
159
+ * Useful when running multiple builds with `defineConfig` arrays.
160
+ *
161
+ * @example
162
+ * ```ts
163
+ * name: 'api-client'
164
+ * ```
127
165
  */
128
166
  name?: string
129
167
  /**
130
- * The project root directory, which can be either an absolute path or a path relative to the location of your `kubb.config.ts` file.
168
+ * Project root directory, absolute or relative to the config file.
131
169
  * @default process.cwd()
132
170
  */
133
171
  root: string
134
172
  /**
135
- * Adapter that converts the input file into a `@kubb/ast` `RootNode` — the universal
136
- * intermediate representation consumed by all Kubb plugins.
173
+ * Parsers that convert generated files to strings.
174
+ * Each parser handles specific extensions (e.g. `.ts`, `.tsx`).
175
+ * A fallback parser is appended for unhandled extensions.
176
+ * When omitted, defaults to `parserTs` from `@kubb/parser-ts`.
137
177
  *
138
- * - Omit (or pass `undefined`) to use the built-in OpenAPI/Swagger adapter.
139
- * - Use `@kubb/adapter-oas` for explicit OpenAPI configuration (validate, contentType, …).
140
- * - Use `@kubb/adapter-drizzle` or `@kubb/adapter-asyncapi` for other formats.
178
+ * @default [parserTs] from `@kubb/parser-ts`
179
+ * @example
180
+ * ```ts
181
+ * import { parserTs, tsxParser } from '@kubb/parser-ts'
182
+ * export default defineConfig({
183
+ * parsers: [parserTs, tsxParser],
184
+ * })
185
+ * ```
186
+ */
187
+ parsers: Array<Parser>
188
+ /**
189
+ * Adapter that parses input files into the universal `InputNode` representation.
190
+ * Use `@kubb/adapter-oas` for OpenAPI/Swagger or `@kubb/adapter-asyncapi` for other formats.
141
191
  *
142
192
  * @example
143
193
  * ```ts
144
- * import { drizzleAdapter } from '@kubb/adapter-drizzle'
194
+ * import { adapterOas } from '@kubb/adapter-oas'
145
195
  * export default defineConfig({
146
- * adapter: drizzleAdapter(),
147
- * input: { path: './src/schema.ts' },
196
+ * adapter: adapterOas(),
197
+ * input: { path: './petstore.yaml' },
148
198
  * })
149
199
  * ```
150
200
  */
151
- adapter?: Adapter
201
+ adapter: Adapter
152
202
  /**
153
- * You can use either `input.path` or `input.data`, depending on your specific needs.
203
+ * Source file or data to generate code from.
204
+ * Use `input.path` for a file path or `input.data` for inline data.
154
205
  */
155
206
  input: TInput
156
207
  output: {
157
208
  /**
158
- * The path where all generated files receives exported.
159
- * This can be an absolute path or a path relative to the specified root option.
209
+ * Output directory for generated files, absolute or relative to `root`.
210
+ *
211
+ * All generated files will be written under this directory. Subdirectories can be created
212
+ * by plugins based on grouping strategy (by tag, path, etc.).
213
+ *
214
+ * @example
215
+ * ```ts
216
+ * output: {
217
+ * path: './src/gen', // generates ./src/gen/api.ts, ./src/gen/types.ts, etc.
218
+ * }
219
+ * ```
160
220
  */
161
221
  path: string
162
222
  /**
163
- * Clean the output directory before each build.
223
+ * Remove all files from the output directory before starting the build.
224
+ *
225
+ * Useful to ensure old generated files aren't mixed with new ones.
226
+ * Set to `true` for fresh builds, `false` to preserve manual edits in output dir.
227
+ *
228
+ * @default false
229
+ * @example
230
+ * ```ts
231
+ * clean: true // wipes ./src/gen/* before generating
232
+ * ```
164
233
  */
165
234
  clean?: boolean
166
235
  /**
167
- * Save files to the file system.
236
+ * Persists generated files to the file system.
237
+ *
168
238
  * @default true
169
- * @deprecated Use `storage` to control where files are written.
239
+ * @deprecated Use `storage` option to control where files are written instead.
170
240
  */
171
241
  write?: boolean
172
242
  /**
173
- * Storage backend for generated files.
174
- * Defaults to `fsStorage()` — the built-in filesystem driver.
175
- * Accepts any object implementing the {@link DefineStorage} interface.
176
- * Keys are root-relative paths (e.g. `src/gen/api/getPets.ts`).
177
- * @default fsStorage()
243
+ * Auto-format generated files after code generation completes.
244
+ *
245
+ * Applies a code formatter to all generated files. Use `'auto'` to detect which formatter
246
+ * is available on your system. Pass `false` to skip formatting (useful for CI or specific workflows).
247
+ *
248
+ * @default false
178
249
  * @example
179
250
  * ```ts
180
- * import { createStorage, fsStorage } from '@kubb/core'
181
- * storage: createStorage(fsStorage())
251
+ * format: 'auto' // auto-detect prettier, biome, or oxfmt
252
+ * format: 'prettier' // force prettier
253
+ * format: false // skip formatting
182
254
  * ```
183
255
  */
184
- storage?: DefineStorage
185
- /**
186
- * Specifies the formatting tool to be used.
187
- * - 'auto' automatically detects and uses biome or prettier (in that order of preference).
188
- * - 'prettier' uses Prettier for code formatting.
189
- * - 'biome' uses Biome for code formatting.
190
- * - 'oxfmt' uses Oxfmt for code formatting.
191
- * - false disables code formatting.
192
- * @default 'prettier'
193
- */
194
256
  format?: 'auto' | 'prettier' | 'biome' | 'oxfmt' | false
195
257
  /**
196
- * Specifies the linter that should be used to analyze the code.
197
- * - 'auto' automatically detects and uses biome, oxlint, or eslint (in that order of preference).
198
- * - 'eslint' uses ESLint for linting.
199
- * - 'biome' uses Biome for linting.
200
- * - 'oxlint' uses Oxlint for linting.
201
- * - false disables linting.
202
- * @default 'auto'
258
+ * Auto-lint generated files after code generation completes.
259
+ *
260
+ * Analyzes all generated files for style/correctness issues. Use `'auto'` to detect which linter
261
+ * is available on your system. Pass `false` to skip linting.
262
+ *
263
+ * @default false
264
+ * @example
265
+ * ```ts
266
+ * lint: 'auto' // auto-detect oxlint, biome, or eslint
267
+ * lint: 'eslint' // force eslint
268
+ * lint: false // skip linting
269
+ * ```
203
270
  */
204
271
  lint?: 'auto' | 'eslint' | 'biome' | 'oxlint' | false
205
272
  /**
206
- * Overrides the extension for generated imports and exports. By default, each plugin adds an extension.
207
- * @default { '.ts': '.ts'}
208
- */
209
- extension?: Record<KubbFile.Extname, KubbFile.Extname | ''>
210
- /**
211
- * Configures how `index.ts` files are created, including disabling barrel file generation. Each plugin has its own `barrelType` option; this setting controls the root barrel file (e.g., `src/gen/index.ts`).
212
- * @default 'named'
273
+ * Map file extensions to different output extensions.
274
+ *
275
+ * Useful when you want generated `.ts` imports to reference `.js` files or vice versa (e.g., for ESM dual packages).
276
+ * Keys are the original extension, values are the output extension. Use empty string `''` to omit extension.
277
+ *
278
+ * @default { '.ts': '.ts' }
279
+ * @example
280
+ * ```ts
281
+ * extension: { '.ts': '.js' } // generates import './api.js' instead of './api.ts'
282
+ * extension: { '.ts': '', '.tsx': '.jsx' }
283
+ * ```
213
284
  */
214
- barrelType?: Exclude<BarrelType, 'propagate'> | false
285
+ extension?: Record<FileNode['extname'], FileNode['extname'] | ''>
215
286
  /**
216
- * Adds a default banner to the start of every generated file indicating it was generated by Kubb.
217
- * - 'simple' adds banner with link to Kubb.
218
- * - 'full' adds source, title, description, and OpenAPI version.
219
- * - false disables banner generation.
287
+ * Banner text prepended to every generated file.
288
+ *
289
+ * Useful for auto-generation notices or license headers. Choose a preset or write custom text.
290
+ * Use `'simple'` for a basic Kubb banner, `'full'` for detailed metadata, or `false` to omit.
291
+ *
220
292
  * @default 'simple'
293
+ * @example
294
+ * ```ts
295
+ * defaultBanner: 'simple' // "This file was autogenerated by Kubb"
296
+ * defaultBanner: 'full' // adds source, title, description, API version
297
+ * defaultBanner: false // no banner
298
+ * ```
221
299
  */
222
300
  defaultBanner?: 'simple' | 'full' | false
223
301
  /**
224
- * Whether to override existing external files if they already exist.
225
- * When setting the option in the global configuration, all plugins inherit the same behavior by default.
226
- * However, all plugins also have an `output.override` option, which can be used to override the behavior for a specific plugin.
302
+ * When `true`, overwrites existing files. When `false`, skips generated files that already exist.
303
+ *
304
+ * Individual plugins can override this setting. This is useful for preventing accidental data loss
305
+ * when re-generating while you have local edits in the output folder.
306
+ *
227
307
  * @default false
308
+ * @example
309
+ * ```ts
310
+ * override: true // regenerate everything, even existing files
311
+ * override: false // skip files that already exist
312
+ * ```
228
313
  */
229
314
  override?: boolean
230
- }
315
+ } & ExtractRegistryKey<Kubb.ConfigOptionsRegistry, 'output'>
231
316
  /**
232
- * An array of Kubb plugins that used in the generation.
233
- * Each plugin may include additional configurable options(defined in the plugin itself).
234
- * If a plugin depends on another plugin, an error is returned if the required dependency is missing. See pre for more details.
317
+ * Storage backend that controls where and how generated files are persisted.
318
+ *
319
+ * Defaults to `fsStorage()` which writes to the file system. Pass `memoryStorage()` to keep files in RAM,
320
+ * or implement a custom `Storage` interface to write to cloud storage, databases, or other backends.
321
+ *
322
+ * @default fsStorage()
323
+ * @example
324
+ * ```ts
325
+ * import { memoryStorage } from '@kubb/core'
326
+ *
327
+ * // Keep generated files in memory (useful for testing, CI pipelines)
328
+ * storage: memoryStorage()
329
+ *
330
+ * // Use custom S3 storage
331
+ * storage: myS3Storage()
332
+ * ```
333
+ *
334
+ * @see {@link Storage} interface for implementing custom backends.
235
335
  */
236
- plugins?: Array<Plugin>
336
+ storage?: Storage
237
337
  /**
238
- * Devtools configuration for Kubb Studio integration.
338
+ * Plugins that execute during the build to generate code and transform the AST.
339
+ *
340
+ * Each plugin processes the AST produced by the adapter and can emit files for different
341
+ * programming languages or formats (TypeScript, Zod schemas, Faker data, etc.).
342
+ * Dependencies are enforced — an error is thrown if a plugin requires another plugin that isn't registered.
343
+ *
344
+ * Plugins can declare their own options via `PluginFactoryOptions`. See plugin documentation for details.
345
+ *
346
+ * @example
347
+ * ```ts
348
+ * import { pluginTs } from '@kubb/plugin-ts'
349
+ * import { pluginZod } from '@kubb/plugin-zod'
350
+ *
351
+ * plugins: [
352
+ * pluginTs({ output: { path: './src/gen' } }),
353
+ * pluginZod({ output: { path: './src/gen' } }),
354
+ * ]
355
+ * ```
356
+ */
357
+ plugins: Array<Plugin>
358
+ /**
359
+ * Middleware instances that observe build events and post-process generated code.
360
+ *
361
+ * Middleware fires AFTER all plugins for each event. Perfect for tasks like:
362
+ * - Auditing what was generated
363
+ * - Adding barrel/index files
364
+ * - Validating output
365
+ * - Running custom transformations
366
+ *
367
+ * @example
368
+ * ```ts
369
+ * import { middlewareBarrel } from '@kubb/middleware-barrel'
370
+ *
371
+ * middleware: [middlewareBarrel()]
372
+ * ```
373
+ *
374
+ * @see {@link defineMiddleware} to create custom middleware.
375
+ */
376
+ middleware?: Array<Middleware>
377
+ /**
378
+ * Default renderer factory used by all plugins and generators.
379
+ * Resolution chain: `generator.renderer` → `plugin.renderer` → `config.renderer` → `undefined` (raw FileNode[] mode).
380
+ *
381
+ * @example
382
+ * ```ts
383
+ * import { jsxRenderer } from '@kubb/renderer-jsx'
384
+ * export default defineConfig({
385
+ * renderer: jsxRenderer,
386
+ * plugins: [pluginTs(), pluginZod()],
387
+ * })
388
+ * ```
389
+ */
390
+ /**
391
+ * Renderer that converts generated AST nodes to code strings.
392
+ *
393
+ * By default, Kubb uses the JSX renderer (`rendererJsx`). Pass a custom renderer to support
394
+ * different output formats (template engines, code generation DSLs, etc.).
395
+ *
396
+ * @default rendererJsx() // from @kubb/renderer-jsx
397
+ * @example
398
+ * ```ts
399
+ * import { rendererJsx } from '@kubb/renderer-jsx'
400
+ * renderer: rendererJsx()
401
+ * ```
402
+ *
403
+ * @see {@link Renderer} to implement a custom renderer.
404
+ */
405
+ renderer?: RendererFactory
406
+ /**
407
+ * Kubb Studio cloud integration settings.
408
+ *
409
+ * Kubb Studio (https://studio.kubb.dev) is a web-based IDE for managing API specs and generated code.
410
+ * Set to `true` to enable with default settings, or pass an object to customize the Studio URL.
411
+ *
412
+ * @default false // disabled by default
413
+ * @example
414
+ * ```ts
415
+ * devtools: true // use default Kubb Studio
416
+ * devtools: { studioUrl: 'https://my-studio.dev' } // custom Studio instance
417
+ * ```
239
418
  */
240
419
  devtools?:
241
420
  | true
@@ -247,12 +426,33 @@ export type Config<TInput = Input> = {
247
426
  studioUrl?: typeof DEFAULT_STUDIO_URL | (string & {})
248
427
  }
249
428
  /**
250
- * Hooks triggered when a specific action occurs in Kubb.
429
+ * Lifecycle hooks that execute during or after the build process.
430
+ *
431
+ * Hooks allow you to run external tools (prettier, eslint, custom scripts) based on build events.
432
+ * Currently supports the `done` hook which fires after all plugins and middleware complete.
433
+ *
434
+ * @example
435
+ * ```ts
436
+ * hooks: {
437
+ * done: 'prettier --write "./src/gen"', // auto-format generated files
438
+ * // or multiple commands:
439
+ * done: ['prettier --write "./src/gen"', 'eslint --fix "./src/gen"']
440
+ * }
441
+ * ```
251
442
  */
252
443
  hooks?: {
253
444
  /**
254
- * Hook that triggers at the end of all executions.
255
- * Useful for running Prettier or ESLint to format/lint your code.
445
+ * Command(s) to run after all plugins and middleware complete generation.
446
+ *
447
+ * Useful for post-processing: formatting, linting, copying files, or custom validation.
448
+ * Pass a single command string or array of command strings to run sequentially.
449
+ * Commands are executed relative to the `root` directory.
450
+ *
451
+ * @example
452
+ * ```ts
453
+ * done: 'prettier --write "./src/gen"'
454
+ * done: ['prettier --write "./src/gen"', 'eslint --fix "./src/gen"']
455
+ * ```
256
456
  */
257
457
  done?: string | Array<string>
258
458
  }
@@ -260,253 +460,837 @@ export type Config<TInput = Input> = {
260
460
 
261
461
  // plugin
262
462
 
463
+ /**
464
+ * Type/string pattern filter for include/exclude/override matching.
465
+ */
466
+ type PatternFilter = {
467
+ type: string
468
+ pattern: string | RegExp
469
+ }
470
+
471
+ /**
472
+ * Pattern filter with partial option overrides applied when the pattern matches.
473
+ */
474
+ type PatternOverride<TOptions> = PatternFilter & {
475
+ options: Omit<Partial<TOptions>, 'override'>
476
+ }
477
+
478
+ /**
479
+ * Context for resolving filtered options for a given operation or schema node.
480
+ *
481
+ * @internal
482
+ */
483
+ export type ResolveOptionsContext<TOptions> = {
484
+ options: TOptions
485
+ exclude?: Array<PatternFilter>
486
+ include?: Array<PatternFilter>
487
+ override?: Array<PatternOverride<TOptions>>
488
+ }
489
+
490
+ /**
491
+ * Base constraint for all plugin resolver objects.
492
+ *
493
+ * `default`, `resolveOptions`, `resolvePath`, `resolveFile`, `resolveBanner`, and `resolveFooter`
494
+ * are injected automatically by `defineResolver` — extend this type to add custom resolution methods.
495
+ *
496
+ * @example
497
+ * ```ts
498
+ * type MyResolver = Resolver & {
499
+ * resolveName(node: SchemaNode): string
500
+ * resolveTypedName(node: SchemaNode): string
501
+ * }
502
+ * ```
503
+ */
504
+ export type Resolver = {
505
+ name: string
506
+ pluginName: Plugin['name']
507
+ default(name: string, type?: 'file' | 'function' | 'type' | 'const'): string
508
+ resolveOptions<TOptions>(node: Node, context: ResolveOptionsContext<TOptions>): TOptions | null
509
+ resolvePath(params: ResolverPathParams, context: ResolverContext): string
510
+ resolveFile(params: ResolverFileParams, context: ResolverContext): FileNode
511
+ resolveBanner(node: InputNode | null, context: ResolveBannerContext): string | undefined
512
+ resolveFooter(node: InputNode | null, context: ResolveBannerContext): string | undefined
513
+ }
514
+
263
515
  export type PluginFactoryOptions<
264
516
  /**
265
- * Name to be used for the plugin.
517
+ * Unique plugin name.
266
518
  */
267
519
  TName extends string = string,
268
520
  /**
269
- * Options of the plugin.
521
+ * User-facing plugin options.
270
522
  */
271
523
  TOptions extends object = object,
272
524
  /**
273
- * Options of the plugin that can be used later on, see `options` inside your plugin config.
525
+ * Plugin options after defaults are applied.
274
526
  */
275
527
  TResolvedOptions extends object = TOptions,
276
528
  /**
277
- * Context that you want to expose to other plugins.
529
+ * Resolver that encapsulates naming and path-resolution helpers.
530
+ * Define with `defineResolver` and export alongside the plugin.
278
531
  */
279
- TContext = unknown,
280
- /**
281
- * When calling `resolvePath` you can specify better types.
282
- */
283
- TResolvePathOptions extends object = object,
532
+ TResolver extends Resolver = Resolver,
284
533
  > = {
285
534
  name: TName
286
535
  options: TOptions
287
536
  resolvedOptions: TResolvedOptions
288
- context: TContext
289
- resolvePathOptions: TResolvePathOptions
537
+ resolver: TResolver
290
538
  }
291
539
 
292
- export type GetPluginFactoryOptions<TPlugin extends UserPlugin> = TPlugin extends UserPlugin<infer X> ? X : never
540
+ /**
541
+ * Normalized plugin after setup, with runtime fields populated.
542
+ * For internal use only — plugins use the public `Plugin` type externally.
543
+ *
544
+ * @internal
545
+ */
546
+ export type NormalizedPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = Plugin<TOptions> & {
547
+ options: TOptions['resolvedOptions'] & {
548
+ output: Output
549
+ include?: Array<Include>
550
+ exclude: Array<Exclude>
551
+ override: Array<Override<TOptions['resolvedOptions']>>
552
+ }
553
+ resolver: TOptions['resolver']
554
+ transformer?: Visitor
555
+ renderer?: RendererFactory
556
+ generators?: Array<Generator>
557
+ apply?: (config: Config) => boolean
558
+ version?: string
559
+ }
293
560
 
294
- export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
561
+ /**
562
+ * Partial `Config` for user-facing entry points with sensible defaults.
563
+ *
564
+ * `UserConfig` is what you pass to `defineConfig()`. It has optional `root`, `plugins`, `parsers`, and `adapter`
565
+ * fields (which fall back to sensible defaults). All other Config options are available, including `output`, `input`,
566
+ * `storage`, `middleware`, `renderer`, `devtools`, and `hooks`.
567
+ *
568
+ * @example
569
+ * ```ts
570
+ * export default defineConfig({
571
+ * input: { path: './petstore.yaml' },
572
+ * output: { path: './src/gen' },
573
+ * plugins: [pluginTs(), pluginZod()],
574
+ * })
575
+ * ```
576
+ */
577
+ export type UserConfig<TInput = Input> = Omit<Config<TInput>, 'root' | 'plugins' | 'parsers' | 'adapter'> & {
295
578
  /**
296
- * Unique name used for the plugin
297
- * The name of the plugin follows the format scope:foo-bar or foo-bar, adding scope: can avoid naming conflicts with other plugins.
298
- * @example @kubb/typescript
579
+ * Project root directory, absolute or relative to the config file location.
580
+ *
581
+ * Used as the base path for `root`-relative paths (e.g., `output.path`, file paths in hooks).
582
+ *
583
+ * @default process.cwd()
584
+ * @example
585
+ * ```ts
586
+ * root: '/home/user/my-project'
587
+ * root: './my-project' // relative to config file
588
+ * ```
299
589
  */
300
- name: TOptions['name']
590
+ root?: string
591
+ /**
592
+ * Custom parsers that convert generated AST nodes to strings (TypeScript, JSON, markdown, etc.).
593
+ *
594
+ * Each parser handles a specific file type. By default, Kubb uses `parserTs` from `@kubb/parser-ts` for TypeScript files.
595
+ * Pass custom parsers to support additional languages or custom formats.
596
+ *
597
+ * @default [parserTs] // from @kubb/parser-ts
598
+ * @example
599
+ * ```ts
600
+ * import { parserTs } from '@kubb/parser-ts'
601
+ * import { parserJsonSchema } from '@kubb/parser-json-schema'
602
+ *
603
+ * parsers: [parserTs(), parserJsonSchema()]
604
+ * ```
605
+ *
606
+ * @see {@link Parser} to implement a custom parser.
607
+ */
608
+ parsers?: Array<Parser>
609
+ /**
610
+ * Adapter that parses your API specification (OpenAPI, GraphQL, AsyncAPI, etc.) into Kubb's universal AST.
611
+ *
612
+ * The adapter bridge between your input format and Kubb's internal representation. By default, uses the OAS adapter.
613
+ * Pass an alternative adapter (or multiple configs with different adapters) to support different spec formats.
614
+ *
615
+ * @default new OasAdapter() // from @kubb/adapter-oas
616
+ * @example
617
+ * ```ts
618
+ * import { Oas } from '@kubb/adapter-oas'
619
+ *
620
+ * adapter: new Oas({ apiVersion: '3.0.0' })
621
+ * ```
622
+ *
623
+ * @see {@link Adapter} to implement a custom adapter for GraphQL or other formats.
624
+ */
625
+ adapter?: Adapter
626
+ /**
627
+ * Plugins that execute during the build to generate code and transform the AST.
628
+ *
629
+ * Each plugin processes the AST produced by the adapter and can emit files for different
630
+ * programming languages or formats (TypeScript, Zod schemas, Faker data, etc.).
631
+ *
632
+ * @default [] // no plugins (useful for setup/testing)
633
+ * @example
634
+ * ```ts
635
+ * plugins: [
636
+ * pluginTs({ output: { path: './src/gen' } }),
637
+ * pluginZod({ output: { path: './src/gen' } }),
638
+ * ]
639
+ * ```
640
+ *
641
+ * @see {@link definePlugin} to create a custom plugin.
642
+ */
643
+ plugins?: Array<Plugin>
644
+ }
645
+
646
+ export type ResolveNameParams = {
647
+ name: string
648
+ pluginName?: string
649
+ /**
650
+ * Entity type being named.
651
+ * - `'file'` — file name (camelCase)
652
+ * - `'function'` — exported function name (camelCase)
653
+ * - `'type'` — TypeScript type name (PascalCase)
654
+ * - `'const'` — variable name (camelCase)
655
+ */
656
+ type?: 'file' | 'function' | 'type' | 'const'
657
+ }
658
+ /**
659
+ * Context object passed to generator `schema`, `operation`, and `operations` methods.
660
+ *
661
+ * The adapter is always defined (guaranteed by `runPluginAstHooks`) so no runtime checks
662
+ * are needed. `ctx.options` carries resolved per-node options after exclude/include/override
663
+ * filtering for individual schema/operation calls, or plugin-level options for operations.
664
+ */
665
+ export type GeneratorContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
666
+ config: Config
667
+ /**
668
+ * Absolute path to the current plugin's output directory.
669
+ */
670
+ root: string
671
+ /**
672
+ * Determine output mode based on the output config.
673
+ * Returns `'single'` when `output.path` is a file, `'split'` for a directory.
674
+ */
675
+ getMode: (output: { path: string }) => 'single' | 'split'
676
+ driver: PluginDriver
677
+ /**
678
+ * Get a plugin by name, typed via `Kubb.PluginRegistry` when registered.
679
+ */
680
+ getPlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined
681
+ getPlugin(name: string): Plugin | undefined
682
+ /**
683
+ * Get a plugin by name, throws an error if not found.
684
+ */
685
+ requirePlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]>
686
+ requirePlugin(name: string): Plugin
687
+ /**
688
+ * Get a resolver by plugin name, typed via `Kubb.PluginRegistry` when registered.
689
+ */
690
+ getResolver<TName extends keyof Kubb.PluginRegistry>(name: TName): Kubb.PluginRegistry[TName]['resolver']
691
+ getResolver(name: string): Resolver
301
692
  /**
302
- * Options set for a specific plugin(see kubb.config.js), passthrough of options.
693
+ * Add files only if they don't exist.
694
+ */
695
+ addFile: (...file: Array<FileNode>) => Promise<void>
696
+ /**
697
+ * Merge sources into the same output file.
698
+ */
699
+ upsertFile: (...file: Array<FileNode>) => Promise<void>
700
+ hooks: AsyncEventEmitter<KubbHooks>
701
+ /**
702
+ * The current plugin instance.
703
+ */
704
+ plugin: Plugin<TOptions>
705
+ /**
706
+ * The current plugin's resolver.
707
+ */
708
+ resolver: TOptions['resolver']
709
+ /**
710
+ * The current plugin's transformer.
711
+ */
712
+ transformer: Visitor | undefined
713
+ /**
714
+ * Emit a warning.
715
+ */
716
+ warn: (message: string) => void
717
+ /**
718
+ * Emit an error.
719
+ */
720
+ error: (error: string | Error) => void
721
+ /**
722
+ * Emit an info message.
723
+ */
724
+ info: (message: string) => void
725
+ /**
726
+ * Open the current input node in Kubb Studio.
727
+ */
728
+ openInStudio: (options?: DevtoolsOptions) => Promise<void>
729
+ /**
730
+ * The configured adapter instance.
731
+ */
732
+ adapter: Adapter
733
+ /**
734
+ * The universal `InputNode` produced by the adapter.
735
+ */
736
+ inputNode: InputNode
737
+ /**
738
+ * Resolved options after exclude/include/override filtering.
303
739
  */
304
740
  options: TOptions['resolvedOptions']
741
+ }
742
+ /**
743
+ * Output configuration for generated files.
744
+ */
745
+ export type Output<_TOptions = unknown> = {
746
+ /**
747
+ * Output folder or file path for generated code.
748
+ */
749
+ path: string
305
750
  /**
306
- * Specifies the preceding plugins for the current plugin. You can pass an array of preceding plugin names, and the current plugin is executed after these plugins.
307
- * Can be used to validate dependent plugins.
751
+ * Text or function prepended to every generated file.
752
+ * When a function, receives the current `InputNode` and returns a string.
308
753
  */
309
- pre?: Array<string>
754
+ banner?: string | ((node?: InputNode) => string)
310
755
  /**
311
- * Specifies the succeeding plugins for the current plugin. You can pass an array of succeeding plugin names, and the current plugin is executed before these plugins.
756
+ * Text or function appended to every generated file.
757
+ * When a function, receives the current `InputNode` and returns a string.
312
758
  */
313
- post?: Array<string>
314
- inject?: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => TOptions['context']
759
+ footer?: string | ((node?: InputNode) => string)
760
+ /**
761
+ * Whether to override existing external files if they already exist.
762
+ * @default false
763
+ */
764
+ override?: boolean
765
+ } & ExtractRegistryKey<Kubb.PluginOptionsRegistry, 'output'>
766
+
767
+ export type Group = {
768
+ /**
769
+ * How to group files into subdirectories.
770
+ * - `'tag'` — group by OpenAPI tags
771
+ * - `'path'` — group by OpenAPI paths
772
+ */
773
+ type: 'tag' | 'path'
774
+ /**
775
+ * Function that returns the subdirectory name for a group value.
776
+ * Defaults to `${camelCase(group)}Controller` for tags, first path segment for paths.
777
+ */
778
+ name?: (context: { group: string }) => string
779
+ }
780
+
781
+ export type LoggerOptions = {
782
+ /**
783
+ * Log level for output verbosity.
784
+ * @default 3
785
+ */
786
+ logLevel: (typeof logLevel)[keyof typeof logLevel]
315
787
  }
316
788
 
317
- export type UserPluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = UserPlugin<TOptions> & PluginLifecycle<TOptions>
789
+ /**
790
+ * Shared context passed to plugins, parsers, and other internals.
791
+ */
792
+ export type LoggerContext = AsyncEventEmitter<KubbHooks>
318
793
 
319
- export type UnknownUserPlugin = UserPlugin<PluginFactoryOptions<any, any, any, any, any>>
794
+ export type Logger<TOptions extends LoggerOptions = LoggerOptions> = {
795
+ name: string
796
+ install: (context: LoggerContext, options?: TOptions) => void | Promise<void>
797
+ }
798
+
799
+ export type UserLogger<TOptions extends LoggerOptions = LoggerOptions> = Logger<TOptions>
320
800
 
321
- export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
801
+ export type { Storage } from './createStorage.ts'
802
+ export type { Generator } from './defineGenerator.ts'
803
+ export type { Middleware } from './defineMiddleware.ts'
804
+ export type { Plugin } from './definePlugin.ts'
805
+ export type { Kubb, KubbHooks } from './Kubb.ts'
806
+
807
+ /**
808
+ * Context for hook-style plugin `kubb:plugin:setup` handler.
809
+ * Provides methods to register generators, configure resolvers, transformers, and renderers.
810
+ */
811
+ export type KubbPluginSetupContext<TFactory extends PluginFactoryOptions = PluginFactoryOptions> = {
322
812
  /**
323
- * Unique name used for the plugin
324
- * @example @kubb/typescript
813
+ * Register a generator dynamically. Generators fire during the AST walk (schema/operation/operations)
814
+ * just like generators declared statically on `createPlugin`.
325
815
  */
326
- name: TOptions['name']
816
+ addGenerator<TElement = unknown>(generator: Generator<TFactory, TElement>): void
327
817
  /**
328
- * Specifies the preceding plugins for the current plugin. You can pass an array of preceding plugin names, and the current plugin is executed after these plugins.
329
- * Can be used to validate dependent plugins.
818
+ * Set or override the resolver for this plugin.
819
+ * The resolver controls file naming and path resolution.
330
820
  */
331
- pre?: Array<string>
821
+ setResolver(resolver: Partial<TFactory['resolver']>): void
332
822
  /**
333
- * Specifies the succeeding plugins for the current plugin. You can pass an array of succeeding plugin names, and the current plugin is executed before these plugins.
823
+ * Set the AST transformer to pre-process nodes before they reach generators.
334
824
  */
335
- post?: Array<string>
825
+ setTransformer(visitor: Visitor): void
336
826
  /**
337
- * Options set for a specific plugin(see kubb.config.js), passthrough of options.
827
+ * Set the renderer factory to process JSX elements from generators.
338
828
  */
339
- options: TOptions['resolvedOptions']
829
+ setRenderer(renderer: RendererFactory): void
830
+ /**
831
+ * Set resolved options merged into the normalized plugin's `options`.
832
+ * Call this in `kubb:plugin:setup` to provide options generators need.
833
+ */
834
+ setOptions(options: TFactory['resolvedOptions']): void
835
+ /**
836
+ * Inject a raw file into the build output, bypassing the generation pipeline.
837
+ */
838
+ injectFile(userFileNode: UserFileNode): void
839
+ /**
840
+ * Merge a partial config update into the current build configuration.
841
+ */
842
+ updateConfig(config: Partial<Config>): void
843
+ /**
844
+ * The resolved build configuration at setup time.
845
+ */
846
+ config: Config
847
+ /**
848
+ * The plugin's user-provided options.
849
+ */
850
+ options: TFactory['options']
851
+ }
852
+
853
+ /**
854
+ * Context for hook-style plugin `kubb:build:start` handler.
855
+ * Fires immediately before the plugin execution loop begins.
856
+ */
857
+ export type KubbBuildStartContext = {
858
+ config: Config
859
+ adapter: Adapter
860
+ inputNode: InputNode
861
+ /**
862
+ * Get a plugin by name, typed via `Kubb.PluginRegistry` when registered.
863
+ */
864
+ getPlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined
865
+ getPlugin(name: string): Plugin | undefined
866
+ /**
867
+ * Get all files currently in the file manager.
868
+ * Call this lazily (e.g. in `kubb:plugin:end`) to see files added by prior plugins.
869
+ */
870
+ readonly files: ReadonlyArray<FileNode>
871
+ /**
872
+ * Upsert one or more files into the file manager.
873
+ * Files with the same path are merged; new files are appended.
874
+ * Safe to call at any point during the plugin lifecycle, including inside `kubb:plugin:end`.
875
+ */
876
+ upsertFile: (...files: Array<FileNode>) => void
877
+ }
340
878
 
341
- install: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => PossiblePromise<void>
879
+ /**
880
+ * Context for `kubb:plugins:end` handlers.
881
+ * Fires after plugins run and per-plugin barrels are written, before final write to disk.
882
+ * Middleware that needs final files (e.g. root barrel) use this event.
883
+ */
884
+ export type KubbPluginsEndContext = {
885
+ config: Config
342
886
  /**
343
- * Define a context that can be used by other plugins, see `PluginDriver' where we convert from `UserPlugin` to `Plugin`(used when calling `createPlugin`).
887
+ * All files currently in the file manager (lazy snapshot).
344
888
  */
345
- inject: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => TOptions['context']
889
+ readonly files: ReadonlyArray<FileNode>
890
+ /**
891
+ * Upsert files into the file manager.
892
+ * Files added here are included in the write pass.
893
+ */
894
+ upsertFile: (...files: Array<FileNode>) => void
346
895
  }
347
896
 
348
- export type PluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = Plugin<TOptions> & PluginLifecycle<TOptions>
897
+ /**
898
+ * Context for hook-style plugin `kubb:build:end` handler.
899
+ * Fires after all files have been written to disk.
900
+ */
901
+ export type KubbBuildEndContext = {
902
+ files: Array<FileNode>
903
+ config: Config
904
+ outputDir: string
905
+ }
906
+
907
+ export type KubbLifecycleStartContext = {
908
+ version: string
909
+ }
910
+
911
+ export type KubbConfigEndContext = {
912
+ configs: Array<Config>
913
+ }
914
+
915
+ export type KubbGenerationStartContext = {
916
+ config: Config
917
+ }
918
+
919
+ export type KubbGenerationEndContext = {
920
+ config: Config
921
+ files: Array<FileNode>
922
+ sources: Map<string, string>
923
+ }
924
+
925
+ export type KubbGenerationSummaryContext = {
926
+ config: Config
927
+ failedPlugins: Set<{ plugin: Plugin; error: Error }>
928
+ status: 'success' | 'failed'
929
+ hrStart: [number, number]
930
+ filesCreated: number
931
+ pluginTimings?: Map<Plugin['name'], number>
932
+ }
933
+
934
+ export type KubbVersionNewContext = {
935
+ currentVersion: string
936
+ latestVersion: string
937
+ }
938
+
939
+ export type KubbInfoContext = {
940
+ message: string
941
+ info?: string
942
+ }
943
+
944
+ export type KubbErrorContext = {
945
+ error: Error
946
+ meta?: Record<string, unknown>
947
+ }
948
+
949
+ export type KubbSuccessContext = {
950
+ message: string
951
+ info?: string
952
+ }
953
+
954
+ export type KubbWarnContext = {
955
+ message: string
956
+ info?: string
957
+ }
958
+
959
+ export type KubbDebugContext = {
960
+ date: Date
961
+ logs: Array<string>
962
+ fileName?: string
963
+ }
964
+
965
+ export type KubbFilesProcessingStartContext = {
966
+ files: Array<FileNode>
967
+ }
349
968
 
350
- export type PluginLifecycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
969
+ export type KubbFileProcessingUpdateContext = {
351
970
  /**
352
- * Start of the lifecycle of a plugin.
353
- * @type hookParallel
971
+ * Number of files processed.
354
972
  */
355
- install?: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => PossiblePromise<void>
973
+ processed: number
356
974
  /**
357
- * Resolve to a Path based on a baseName(example: `./Pet.ts`) and directory(example: `./models`).
358
- * Options can als be included.
359
- * @type hookFirst
360
- * @example ('./Pet.ts', './src/gen/') => '/src/gen/Pet.ts'
975
+ * Total files to process.
361
976
  */
362
- resolvePath?: (this: PluginContext<TOptions>, baseName: KubbFile.BaseName, mode?: KubbFile.Mode, options?: TOptions['resolvePathOptions']) => KubbFile.Path
977
+ total: number
363
978
  /**
364
- * Resolve to a name based on a string.
365
- * Useful when converting to PascalCase or camelCase.
366
- * @type hookFirst
367
- * @example ('pet') => 'Pet'
979
+ * Processing percentage (0–100).
368
980
  */
369
- resolveName?: (this: PluginContext<TOptions>, name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
981
+ percentage: number
982
+ /**
983
+ * Optional source identifier.
984
+ */
985
+ source?: string
986
+ /**
987
+ * The file being processed.
988
+ */
989
+ file: FileNode
990
+ /**
991
+ * The current build configuration.
992
+ */
993
+ config: Config
370
994
  }
371
995
 
372
- export type PluginLifecycleHooks = keyof PluginLifecycle
996
+ export type KubbFilesProcessingEndContext = {
997
+ files: Array<FileNode>
998
+ }
373
999
 
374
- export type PluginParameter<H extends PluginLifecycleHooks> = Parameters<Required<PluginLifecycle>[H]>
1000
+ export type KubbPluginStartContext = {
1001
+ plugin: NormalizedPlugin
1002
+ }
375
1003
 
376
- export type ResolvePathParams<TOptions = object> = {
377
- pluginName?: string
378
- baseName: KubbFile.BaseName
379
- mode?: KubbFile.Mode
1004
+ export type KubbPluginEndContext = {
1005
+ plugin: NormalizedPlugin
1006
+ duration: number
1007
+ success: boolean
1008
+ error?: Error
1009
+ config: Config
380
1010
  /**
381
- * Options to be passed to 'resolvePath' 3th parameter
1011
+ * Returns all files currently in the file manager (lazy snapshot).
1012
+ * Includes files added by plugins that have already run.
382
1013
  */
383
- options?: TOptions
1014
+ readonly files: ReadonlyArray<FileNode>
1015
+ /**
1016
+ * Upsert one or more files into the file manager.
1017
+ */
1018
+ upsertFile: (...files: Array<FileNode>) => void
384
1019
  }
385
1020
 
386
- export type ResolveNameParams = {
387
- name: string
388
- pluginName?: string
1021
+ export type KubbHookStartContext = {
1022
+ id?: string
1023
+ command: string
1024
+ args?: readonly string[]
1025
+ }
1026
+
1027
+ export type KubbHookEndContext = {
1028
+ id?: string
1029
+ command: string
1030
+ args?: readonly string[]
1031
+ success: boolean
1032
+ error: Error | null
1033
+ }
1034
+
1035
+ type ByTag = {
389
1036
  /**
390
- * Specifies the type of entity being named.
391
- * - 'file' customizes the name of the created file (uses camelCase).
392
- * - 'function' customizes the exported function names (uses camelCase).
393
- * - 'type' customizes TypeScript types (uses PascalCase).
394
- * - 'const' customizes variable names (uses camelCase).
395
- * @default undefined
1037
+ * Filter by OpenAPI `tags` field. Matches one or more tags assigned to operations.
396
1038
  */
397
- type?: 'file' | 'function' | 'type' | 'const'
1039
+ type: 'tag'
1040
+ /**
1041
+ * Tag name to match (case-sensitive). Can be a literal string or regex pattern.
1042
+ */
1043
+ pattern: string | RegExp
398
1044
  }
399
1045
 
400
- export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
401
- fabric: FabricType
402
- config: Config
403
- driver: PluginDriver
1046
+ type ByOperationId = {
404
1047
  /**
405
- * Only add when the file does not exist yet
1048
+ * Filter by OpenAPI `operationId` field. Each operation (GET, POST, etc.) has a unique identifier.
406
1049
  */
407
- addFile: (...file: Array<KubbFile.File>) => Promise<void>
1050
+ type: 'operationId'
408
1051
  /**
409
- * merging multiple sources into the same output file
1052
+ * Operation ID to match (case-sensitive). Can be a literal string or regex pattern.
410
1053
  */
411
- upsertFile: (...file: Array<KubbFile.File>) => Promise<void>
412
- events: AsyncEventEmitter<KubbEvents>
413
- mode: KubbFile.Mode
1054
+ pattern: string | RegExp
1055
+ }
1056
+
1057
+ type ByPath = {
414
1058
  /**
415
- * Current plugin
1059
+ * Filter by OpenAPI `path` (URL endpoint). Useful to group or filter by service segments like `/pets`, `/users`, etc.
416
1060
  */
417
- plugin: Plugin<TOptions>
1061
+ type: 'path'
1062
+ /**
1063
+ * URL path to match (case-sensitive). Can be a literal string or regex pattern. Matches against the full path.
1064
+ */
1065
+ pattern: string | RegExp
1066
+ }
418
1067
 
1068
+ type ByMethod = {
419
1069
  /**
420
- * Opens the Kubb Studio URL for the current `rootNode` in the default browser.
421
- * Falls back to printing the URL if the browser cannot be launched.
422
- * No-ops silently when no adapter has set a `rootNode`.
1070
+ * Filter by HTTP method: `'get'`, `'post'`, `'put'`, `'delete'`, `'patch'`, `'head'`, `'options'`.
423
1071
  */
424
- openInStudio: (options?: DevtoolsOptions) => Promise<void>
425
- } & (
426
- | {
427
- /**
428
- * Returns the universal `@kubb/ast` `RootNode` produced by the configured adapter.
429
- * Returns `undefined` when no adapter was set (legacy OAS-only usage).
430
- */
431
- rootNode: RootNode
432
- /**
433
- * Return the adapter from `@kubb/ast`
434
- */
435
- adapter: Adapter
436
- }
437
- | {
438
- rootNode?: never
439
- adapter?: never
440
- }
441
- ) &
442
- Kubb.PluginContext
443
- /**
444
- * Specify the export location for the files and define the behavior of the output
445
- */
446
- export type Output<TOptions> = {
1072
+ type: 'method'
447
1073
  /**
448
- * Path to the output folder or file that will contain the generated code
1074
+ * HTTP method to match (case-insensitive when using string, or regex for dynamic matching).
449
1075
  */
450
- path: string
1076
+ pattern: HttpMethod | RegExp
1077
+ }
1078
+ // TODO implement as alternative for ByMethod
1079
+ // type ByMethods = {
1080
+ // type: 'methods'
1081
+ // pattern: Array<HttpMethod>
1082
+ // }
1083
+
1084
+ type BySchemaName = {
451
1085
  /**
452
- * Define what needs to be exported, here you can also disable the export of barrel files
453
- * @default 'named'
1086
+ * Filter by schema component name (TypeScript or JSON schema). Matches schemas in `#/components/schemas`.
454
1087
  */
455
- barrelType?: BarrelType | false
1088
+ type: 'schemaName'
456
1089
  /**
457
- * Add a banner text in the beginning of every file
1090
+ * Schema name to match (case-sensitive). Can be a literal string or regex pattern.
458
1091
  */
459
- banner?: string | ((options: TOptions) => string)
1092
+ pattern: string | RegExp
1093
+ }
1094
+
1095
+ type ByContentType = {
460
1096
  /**
461
- * Add a footer text in the beginning of every file
1097
+ * Filter by response or request content type: `'application/json'`, `'application/xml'`, etc.
462
1098
  */
463
- footer?: string | ((options: TOptions) => string)
1099
+ type: 'contentType'
464
1100
  /**
465
- * Whether to override existing external files if they already exist.
466
- * @default false
1101
+ * Content type to match (case-sensitive). Can be a literal string or regex pattern.
467
1102
  */
468
- override?: boolean
1103
+ pattern: string | RegExp
469
1104
  }
470
1105
 
471
- type GroupContext = {
472
- group: string
1106
+ /**
1107
+ * A pattern filter that prevents matching nodes from being generated.
1108
+ *
1109
+ * Use to skip code generation for specific operations or schemas. For example, exclude deprecated endpoints
1110
+ * or internal-only schemas. Can filter by tag, operationId, path, HTTP method, content type, or schema name.
1111
+ *
1112
+ * @example
1113
+ * ```ts
1114
+ * exclude: [
1115
+ * { type: 'tag', pattern: 'internal' }, // skip "internal" tag
1116
+ * { type: 'path', pattern: /^\/admin/ }, // skip all /admin endpoints
1117
+ * { type: 'operationId', pattern: 'deprecated_*' } // skip operationIds matching pattern
1118
+ * ]
1119
+ * ```
1120
+ */
1121
+ export type Exclude = ByTag | ByOperationId | ByPath | ByMethod | ByContentType | BySchemaName
1122
+
1123
+ /**
1124
+ * A pattern filter that restricts generation to only matching nodes.
1125
+ *
1126
+ * Use to generate code for a subset of operations or schemas. For example, only generate for a specific service
1127
+ * tag or only for "production" endpoints. Can filter by tag, operationId, path, HTTP method, content type, or schema name.
1128
+ *
1129
+ * @example
1130
+ * ```ts
1131
+ * include: [
1132
+ * { type: 'tag', pattern: 'public' }, // generate only "public" tag
1133
+ * { type: 'path', pattern: /^\/api\/v1/ }, // generate only v1 endpoints
1134
+ * ]
1135
+ * ```
1136
+ */
1137
+ export type Include = ByTag | ByOperationId | ByPath | ByMethod | ByContentType | BySchemaName
1138
+
1139
+ /**
1140
+ * A pattern filter paired with partial option overrides applied when the pattern matches.
1141
+ *
1142
+ * Use to customize generation for specific operations or schemas. For example, apply different output paths
1143
+ * for different tags, or use custom resolver functions per operation. Can filter by tag, operationId, path,
1144
+ * HTTP method, schema name, or content type.
1145
+ *
1146
+ * @example
1147
+ * ```ts
1148
+ * override: [
1149
+ * {
1150
+ * type: 'tag',
1151
+ * pattern: 'admin',
1152
+ * options: { output: { path: './src/gen/admin' } } // admin APIs go to separate folder
1153
+ * },
1154
+ * {
1155
+ * type: 'operationId',
1156
+ * pattern: 'listPets',
1157
+ * options: { exclude: true } // skip this specific operation
1158
+ * }
1159
+ * ]
1160
+ * ```
1161
+ */
1162
+ export type Override<TOptions> = (ByTag | ByOperationId | ByPath | ByMethod | BySchemaName | ByContentType) & {
1163
+ //TODO should be options: Omit<Partial<TOptions>, 'override'>
1164
+ options: Partial<TOptions>
473
1165
  }
474
1166
 
475
- export type Group = {
1167
+ /**
1168
+ * File-specific parameters for `Resolver.resolvePath`.
1169
+ *
1170
+ * Pass alongside a `ResolverContext` to identify which file to resolve.
1171
+ * Provide `tag` for tag-based grouping or `path` for path-based grouping.
1172
+ *
1173
+ * @example
1174
+ * ```ts
1175
+ * resolver.resolvePath(
1176
+ * { baseName: 'petTypes.ts', tag: 'pets' },
1177
+ * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
1178
+ * )
1179
+ * // → '/src/types/petsController/petTypes.ts'
1180
+ * ```
1181
+ */
1182
+ export type ResolverPathParams = {
1183
+ baseName: FileNode['baseName']
1184
+ pathMode?: 'single' | 'split'
476
1185
  /**
477
- * Defines the type where to group the files.
478
- * - 'tag' groups files by OpenAPI tags.
479
- * - 'path' groups files by OpenAPI paths.
480
- * @default undefined
1186
+ * Tag value used when `group.type === 'tag'`.
481
1187
  */
482
- type: 'tag' | 'path'
1188
+ tag?: string
483
1189
  /**
484
- * Return the name of a group based on the group name, this used for the file and name generation
1190
+ * Path value used when `group.type === 'path'`.
485
1191
  */
486
- name?: (context: GroupContext) => string
1192
+ path?: string
487
1193
  }
488
1194
 
489
- export type LoggerOptions = {
1195
+ /**
1196
+ * Shared context passed as the second argument to `Resolver.resolvePath` and `Resolver.resolveFile`.
1197
+ *
1198
+ * Describes where on disk output is rooted, which output config is active, and the optional
1199
+ * grouping strategy that controls subdirectory layout.
1200
+ *
1201
+ * @example
1202
+ * ```ts
1203
+ * const context: ResolverContext = {
1204
+ * root: config.root,
1205
+ * output,
1206
+ * group,
1207
+ * }
1208
+ * ```
1209
+ */
1210
+ export type ResolverContext = {
1211
+ root: string
1212
+ output: Output
1213
+ group?: Group
490
1214
  /**
491
- * @default 3
1215
+ * Plugin name used to populate `meta.pluginName` on the resolved file.
492
1216
  */
493
- logLevel: (typeof logLevel)[keyof typeof logLevel]
1217
+ pluginName?: string
494
1218
  }
495
1219
 
496
1220
  /**
497
- * Shared context passed to all plugins, parsers, and Fabric internals.
1221
+ * File-specific parameters for `Resolver.resolveFile`.
1222
+ *
1223
+ * Pass alongside a `ResolverContext` to fully describe the file to resolve.
1224
+ * `tag` and `path` are used only when a matching `group` is present in the context.
1225
+ *
1226
+ * @example
1227
+ * ```ts
1228
+ * resolver.resolveFile(
1229
+ * { name: 'listPets', extname: '.ts', tag: 'pets' },
1230
+ * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
1231
+ * )
1232
+ * // → { baseName: 'listPets.ts', path: '/src/types/petsController/listPets.ts', ... }
1233
+ * ```
498
1234
  */
499
- export interface LoggerContext extends AsyncEventEmitter<KubbEvents> {}
1235
+ export type ResolverFileParams = {
1236
+ name: string
1237
+ extname: FileNode['extname']
1238
+ /**
1239
+ * Tag value used when `group.type === 'tag'`.
1240
+ */
1241
+ tag?: string
1242
+ /**
1243
+ * Path value used when `group.type === 'path'`.
1244
+ */
1245
+ path?: string
1246
+ }
500
1247
 
501
- type Install<TOptions = unknown> = (context: LoggerContext, options?: TOptions) => void | Promise<void>
1248
+ /**
1249
+ * Context passed to `Resolver.resolveBanner` and `Resolver.resolveFooter`.
1250
+ *
1251
+ * `output` is optional — not every plugin configures a banner/footer.
1252
+ * `config` carries the global Kubb config, used to derive the default Kubb banner.
1253
+ *
1254
+ * @example
1255
+ * ```ts
1256
+ * resolver.resolveBanner(inputNode, { output: { banner: '// generated' }, config })
1257
+ * // → '// generated'
1258
+ * ```
1259
+ */
1260
+ export type ResolveBannerContext = {
1261
+ output?: Pick<Output, 'banner' | 'footer'>
1262
+ config: Config
1263
+ }
502
1264
 
503
- export type Logger<TOptions extends LoggerOptions = LoggerOptions> = {
504
- name: string
505
- install: Install<TOptions>
1265
+ /**
1266
+ * CLI options derived from command-line flags.
1267
+ */
1268
+ export type CLIOptions = {
1269
+ /**
1270
+ * Path to `kubb.config.js`.
1271
+ */
1272
+ config?: string
1273
+ /**
1274
+ * Enable watch mode for input files.
1275
+ */
1276
+ watch?: boolean
1277
+ /**
1278
+ * Logging verbosity for CLI usage.
1279
+ * @default 'silent'
1280
+ */
1281
+ logLevel?: 'silent' | 'info' | 'debug'
506
1282
  }
507
1283
 
508
- export type UserLogger<TOptions extends LoggerOptions = LoggerOptions> = Omit<Logger<TOptions>, 'logLevel'>
1284
+ /**
1285
+ * All accepted forms of a Kubb configuration.
1286
+ *
1287
+ * Config is always `@kubb/core` {@link Config}.
1288
+ * - `PossibleConfig` accepts `Config`/`Config[]`/promise or a no-arg config factory.
1289
+ * - `PossibleConfig<TCliOptions>` accepts the same config forms or a config factory receiving `TCliOptions`.
1290
+ */
1291
+ export type PossibleConfig<TCliOptions = undefined> =
1292
+ | PossiblePromise<Config | Config[]>
1293
+ | ((...args: [TCliOptions] extends [undefined] ? [] : [TCliOptions]) => PossiblePromise<Config | Config[]>)
509
1294
 
510
- export type { CoreGeneratorV2, Generator, ReactGeneratorV2 } from './createGenerator.ts'
511
- export type { DefineStorage } from './createStorage.ts'
512
- export type { KubbEvents } from './Kubb.ts'
1295
+ export type { BuildOutput } from './createKubb.ts'
1296
+ export type { Parser } from './defineParser.ts'