@kubb/core 5.0.0-alpha.3 → 5.0.0-alpha.31

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 (60) hide show
  1. package/dist/PluginDriver-D0dY_hpJ.d.ts +1986 -0
  2. package/dist/{chunk-ByKO4r7w.cjs → chunk-MlS0t1Af.cjs} +15 -0
  3. package/dist/chunk-O_arW02_.js +17 -0
  4. package/dist/hooks.cjs +13 -28
  5. package/dist/hooks.cjs.map +1 -1
  6. package/dist/hooks.d.ts +11 -37
  7. package/dist/hooks.js +14 -28
  8. package/dist/hooks.js.map +1 -1
  9. package/dist/index.cjs +1469 -831
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.ts +572 -191
  12. package/dist/index.js +1443 -826
  13. package/dist/index.js.map +1 -1
  14. package/package.json +7 -7
  15. package/src/Kubb.ts +38 -56
  16. package/src/KubbFile.ts +143 -0
  17. package/src/{PluginManager.ts → PluginDriver.ts} +159 -170
  18. package/src/build.ts +213 -65
  19. package/src/constants.ts +39 -6
  20. package/src/createAdapter.ts +25 -0
  21. package/src/createPlugin.ts +30 -0
  22. package/src/createStorage.ts +58 -0
  23. package/src/{config.ts → defineConfig.ts} +11 -16
  24. package/src/defineGenerator.ts +126 -0
  25. package/src/defineLogger.ts +13 -3
  26. package/src/defineParser.ts +57 -0
  27. package/src/definePresets.ts +16 -0
  28. package/src/defineResolver.ts +454 -0
  29. package/src/hooks/index.ts +1 -6
  30. package/src/hooks/useDriver.ts +11 -0
  31. package/src/hooks/useMode.ts +4 -4
  32. package/src/hooks/usePlugin.ts +3 -3
  33. package/src/index.ts +22 -10
  34. package/src/renderNode.tsx +25 -0
  35. package/src/storages/fsStorage.ts +2 -2
  36. package/src/storages/memoryStorage.ts +2 -2
  37. package/src/types.ts +639 -52
  38. package/src/utils/FunctionParams.ts +2 -2
  39. package/src/utils/TreeNode.ts +40 -2
  40. package/src/utils/diagnostics.ts +4 -1
  41. package/src/utils/executeStrategies.ts +29 -10
  42. package/src/utils/formatters.ts +10 -21
  43. package/src/utils/getBarrelFiles.ts +80 -10
  44. package/src/utils/getConfigs.ts +9 -23
  45. package/src/utils/getPreset.ts +78 -0
  46. package/src/utils/isInputPath.ts +8 -0
  47. package/src/utils/linters.ts +23 -3
  48. package/src/utils/packageJSON.ts +76 -0
  49. package/dist/chunk--u3MIqq1.js +0 -8
  50. package/dist/types-CiPWLv-5.d.ts +0 -1001
  51. package/src/BarrelManager.ts +0 -74
  52. package/src/PackageManager.ts +0 -180
  53. package/src/PromiseManager.ts +0 -40
  54. package/src/defineAdapter.ts +0 -22
  55. package/src/definePlugin.ts +0 -12
  56. package/src/defineStorage.ts +0 -56
  57. package/src/errors.ts +0 -1
  58. package/src/hooks/useKubb.ts +0 -22
  59. package/src/hooks/usePluginManager.ts +0 -11
  60. package/src/utils/getPlugins.ts +0 -23
package/src/types.ts CHANGED
@@ -1,17 +1,39 @@
1
1
  import type { AsyncEventEmitter, PossiblePromise } from '@internals/utils'
2
- import type { RootNode, SchemaNode } from '@kubb/ast/types'
3
- import type { KubbFile } from '@kubb/fabric-core/types'
4
- import type { Fabric } from '@kubb/react-fabric'
2
+ import type { Node, OperationNode, Printer, RootNode, SchemaNode, Visitor } from '@kubb/ast/types'
3
+ import type { Fabric as FabricType } from '@kubb/fabric-core/types'
4
+ import type { HttpMethod } from '@kubb/oas'
5
+ import type { FabricReactNode } from '@kubb/react-fabric/types'
5
6
  import type { DEFAULT_STUDIO_URL, logLevel } from './constants.ts'
6
- import type { DefineStorage } from './defineStorage.ts'
7
+ import type { Storage } from './createStorage.ts'
8
+ import type { Generator } from './defineGenerator.ts'
9
+ import type { Parser } from './defineParser.ts'
7
10
  import type { KubbEvents } from './Kubb.ts'
8
- import type { PluginManager } from './PluginManager.ts'
11
+ import type * as KubbFile from './KubbFile.ts'
12
+ import type { PluginDriver } from './PluginDriver.ts'
9
13
 
10
- export type { Printer, PrinterFactoryOptions } from '@kubb/ast/types'
14
+ export type { Printer, PrinterFactoryOptions, PrinterPartial } from '@kubb/ast/types'
11
15
 
12
16
  declare global {
13
17
  namespace Kubb {
14
18
  interface PluginContext {}
19
+ /**
20
+ * Registry that maps plugin names to their `PluginFactoryOptions`.
21
+ * Augment this interface in each plugin's `types.ts` to enable automatic
22
+ * typing for `getPlugin` and `requirePlugin`.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * // packages/plugin-ts/src/types.ts
27
+ * declare global {
28
+ * namespace Kubb {
29
+ * interface PluginRegistry {
30
+ * 'plugin-ts': PluginTs
31
+ * }
32
+ * }
33
+ * }
34
+ * ```
35
+ */
36
+ interface PluginRegistry {}
15
37
  }
16
38
  }
17
39
 
@@ -24,16 +46,47 @@ declare global {
24
46
  * ...
25
47
  * })
26
48
  */
27
- export type UserConfig<TInput = Input> = Omit<Config<TInput>, 'root' | 'plugins'> & {
49
+ export type UserConfig<TInput = Input> = Omit<Config<TInput>, 'root' | 'plugins' | 'parsers' | 'adapter'> & {
28
50
  /**
29
51
  * The project root directory, which can be either an absolute path or a path relative to the location of your `kubb.config.ts` file.
30
52
  * @default process.cwd()
31
53
  */
32
54
  root?: string
55
+ /**
56
+ * An array of parsers used to convert generated files to strings.
57
+ * Each parser handles specific file extensions (e.g. `.ts`, `.tsx`).
58
+ *
59
+ * A catch-all fallback parser is always appended last for any unhandled extension.
60
+ *
61
+ * When omitted, `parserTs` from `@kubb/parser-ts` is used automatically as the
62
+ * default (requires `@kubb/parser-ts` to be installed as an optional dependency).
63
+ * @default [parserTs] — from `@kubb/parser-ts`
64
+ * @example
65
+ * ```ts
66
+ * import { parserTs, tsxParser } from '@kubb/parser-ts'
67
+ * export default defineConfig({
68
+ * parsers: [parserTs, tsxParser],
69
+ * })
70
+ * ```
71
+ */
72
+ parsers?: Array<Parser>
73
+ /**
74
+ * Adapter that converts the input file into a `@kubb/ast` `RootNode` — the universal
75
+ * intermediate representation consumed by all Kubb plugins.
76
+ *
77
+ * When omitted, `adapterOas()` from `@kubb/adapter-oas` is used automatically as the
78
+ * default (requires `@kubb/adapter-oas` to be installed as an optional dependency).
79
+ *
80
+ * - Use `@kubb/adapter-oas` for OpenAPI / Swagger (default).
81
+ * - Use `@kubb/adapter-drizzle` or `@kubb/adapter-asyncapi` for other formats.
82
+ *
83
+ * @default adapterOas() — from `@kubb/adapter-oas`
84
+ */
85
+ adapter?: Adapter
33
86
  /**
34
87
  * 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.
35
88
  */
36
- // inject needs to be omitted because else we have a clash with the PluginManager instance
89
+ // inject needs to be omitted because else we have a clash with the PluginDriver instance
37
90
  plugins?: Array<Omit<UnknownUserPlugin, 'inject'>>
38
91
  }
39
92
 
@@ -51,7 +104,7 @@ export type InputData = {
51
104
  data: string | unknown
52
105
  }
53
106
 
54
- type Input = InputPath | InputData | Array<InputPath>
107
+ type Input = InputPath | InputData
55
108
 
56
109
  /**
57
110
  * The raw source passed to an adapter's `parse` function.
@@ -66,11 +119,18 @@ export type AdapterSource = { type: 'path'; path: string } | { type: 'data'; dat
66
119
  * - `TName` — unique string identifier (e.g. `'oas'`, `'asyncapi'`)
67
120
  * - `TOptions` — raw user-facing options passed to the adapter factory
68
121
  * - `TResolvedOptions` — defaults applied; what the adapter stores as `options`
122
+ * - `TDocument` — type of the raw source document exposed by the adapter after `parse()`
69
123
  */
70
- export type AdapterFactoryOptions<TName extends string = string, TOptions extends object = object, TResolvedOptions extends object = TOptions> = {
124
+ export type AdapterFactoryOptions<
125
+ TName extends string = string,
126
+ TOptions extends object = object,
127
+ TResolvedOptions extends object = TOptions,
128
+ TDocument = unknown,
129
+ > = {
71
130
  name: TName
72
131
  options: TOptions
73
132
  resolvedOptions: TResolvedOptions
133
+ document: TDocument
74
134
  }
75
135
 
76
136
  /**
@@ -92,11 +152,23 @@ export type AdapterFactoryOptions<TName extends string = string, TOptions extend
92
152
  * ```
93
153
  */
94
154
  export type Adapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptions> = {
95
- /** Human-readable identifier, e.g. `'oas'`, `'drizzle'`, `'asyncapi'`. */
155
+ /**
156
+ * Human-readable identifier, e.g. `'oas'`, `'drizzle'`, `'asyncapi'`.
157
+ */
96
158
  name: TOptions['name']
97
- /** Resolved options (after defaults have been applied). */
159
+ /**
160
+ * Resolved options (after defaults have been applied).
161
+ */
98
162
  options: TOptions['resolvedOptions']
99
- /** Convert the raw source into a universal `RootNode`. */
163
+ /**
164
+ * The raw source document produced after the first `parse()` call.
165
+ * `undefined` before parsing; typed by the adapter's `TDocument` generic.
166
+ */
167
+ document: TOptions['document'] | null
168
+ rootNode: RootNode | null
169
+ /**
170
+ * Convert the raw source into a universal `RootNode`.
171
+ */
100
172
  parse: (source: AdapterSource) => PossiblePromise<RootNode>
101
173
  /**
102
174
  * Extracts `KubbFile.Import` entries needed by a `SchemaNode` tree.
@@ -132,24 +204,41 @@ export type Config<TInput = Input> = {
132
204
  * @default process.cwd()
133
205
  */
134
206
  root: string
207
+ /**
208
+ * An array of parsers used to convert generated files to strings.
209
+ * Each parser handles specific file extensions (e.g. `.ts`, `.tsx`).
210
+ *
211
+ * A catch-all fallback parser is always appended last for any unhandled extension.
212
+ *
213
+ * When omitted, `parserTs` from `@kubb/parser-ts` is used automatically as the
214
+ * default (requires `@kubb/parser-ts` to be installed as an optional dependency).
215
+ * @default [parserTs] — from `@kubb/parser-ts`
216
+ * @example
217
+ * ```ts
218
+ * import { parserTs, tsxParser } from '@kubb/parser-ts'
219
+ * export default defineConfig({
220
+ * parsers: [parserTs, tsxParser],
221
+ * })
222
+ * ```
223
+ */
224
+ parsers: Array<Parser>
135
225
  /**
136
226
  * Adapter that converts the input file into a `@kubb/ast` `RootNode` — the universal
137
227
  * intermediate representation consumed by all Kubb plugins.
138
228
  *
139
- * - Omit (or pass `undefined`) to use the built-in OpenAPI/Swagger adapter.
140
- * - Use `@kubb/adapter-oas` for explicit OpenAPI configuration (validate, contentType, …).
229
+ * - Use `@kubb/adapter-oas` for OpenAPI / Swagger.
141
230
  * - Use `@kubb/adapter-drizzle` or `@kubb/adapter-asyncapi` for other formats.
142
231
  *
143
232
  * @example
144
233
  * ```ts
145
- * import { drizzleAdapter } from '@kubb/adapter-drizzle'
234
+ * import { adapterOas } from '@kubb/adapter-oas'
146
235
  * export default defineConfig({
147
- * adapter: drizzleAdapter(),
148
- * input: { path: './src/schema.ts' },
236
+ * adapter: adapterOas(),
237
+ * input: { path: './petStore.yaml' },
149
238
  * })
150
239
  * ```
151
240
  */
152
- adapter?: Adapter
241
+ adapter: Adapter
153
242
  /**
154
243
  * You can use either `input.path` or `input.data`, depending on your specific needs.
155
244
  */
@@ -173,16 +262,16 @@ export type Config<TInput = Input> = {
173
262
  /**
174
263
  * Storage backend for generated files.
175
264
  * Defaults to `fsStorage()` — the built-in filesystem driver.
176
- * Accepts any object implementing the {@link DefineStorage} interface.
265
+ * Accepts any object implementing the {@link Storage} interface.
177
266
  * Keys are root-relative paths (e.g. `src/gen/api/getPets.ts`).
178
267
  * @default fsStorage()
179
268
  * @example
180
269
  * ```ts
181
- * import { defineStorage, fsStorage } from '@kubb/core'
182
- * storage: defineStorage(fsStorage())
270
+ * import { memoryStorage } from '@kubb/core'
271
+ * storage: memoryStorage()
183
272
  * ```
184
273
  */
185
- storage?: DefineStorage
274
+ storage?: Storage
186
275
  /**
187
276
  * Specifies the formatting tool to be used.
188
277
  * - 'auto' automatically detects and uses biome or prettier (in that order of preference).
@@ -212,7 +301,7 @@ export type Config<TInput = Input> = {
212
301
  * 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`).
213
302
  * @default 'named'
214
303
  */
215
- barrelType?: Exclude<BarrelType, 'propagate'> | false
304
+ barrelType?: 'all' | 'named' | false
216
305
  /**
217
306
  * Adds a default banner to the start of every generated file indicating it was generated by Kubb.
218
307
  * - 'simple' adds banner with link to Kubb.
@@ -234,7 +323,7 @@ export type Config<TInput = Input> = {
234
323
  * Each plugin may include additional configurable options(defined in the plugin itself).
235
324
  * If a plugin depends on another plugin, an error is returned if the required dependency is missing. See pre for more details.
236
325
  */
237
- plugins?: Array<Plugin>
326
+ plugins: Array<Plugin>
238
327
  /**
239
328
  * Devtools configuration for Kubb Studio integration.
240
329
  */
@@ -261,6 +350,74 @@ export type Config<TInput = Input> = {
261
350
 
262
351
  // plugin
263
352
 
353
+ /**
354
+ * A type/string-pattern filter used for `include`, `exclude`, and `override` matching.
355
+ */
356
+ type PatternFilter = {
357
+ type: string
358
+ pattern: string | RegExp
359
+ }
360
+
361
+ /**
362
+ * A pattern filter paired with partial option overrides to apply when the pattern matches.
363
+ */
364
+ type PatternOverride<TOptions> = PatternFilter & {
365
+ options: Omit<Partial<TOptions>, 'override'>
366
+ }
367
+
368
+ /**
369
+ * Context passed to `resolver.resolveOptions` to apply include/exclude/override filtering
370
+ * for a given operation or schema node.
371
+ */
372
+ export type ResolveOptionsContext<TOptions> = {
373
+ options: TOptions
374
+ exclude?: Array<PatternFilter>
375
+ include?: Array<PatternFilter>
376
+ override?: Array<PatternOverride<TOptions>>
377
+ }
378
+
379
+ /**
380
+ * Base constraint for all plugin resolver objects.
381
+ *
382
+ * `default`, `resolveOptions`, `resolvePath`, and `resolveFile` are injected automatically
383
+ * by `defineResolver` — plugin authors may override them but never need to implement them
384
+ * from scratch.
385
+ *
386
+ * @example
387
+ * ```ts
388
+ * type MyResolver = Resolver & {
389
+ * resolveName(node: SchemaNode): string
390
+ * resolveTypedName(node: SchemaNode): string
391
+ * }
392
+ * ```
393
+ */
394
+ export type Resolver = {
395
+ name: string
396
+ pluginName: Plugin['name']
397
+ default(name: ResolveNameParams['name'], type?: ResolveNameParams['type']): string
398
+ resolveOptions<TOptions>(node: Node, context: ResolveOptionsContext<TOptions>): TOptions | null
399
+ resolvePath(params: ResolverPathParams, context: ResolverContext): KubbFile.Path
400
+ resolveFile(params: ResolverFileParams, context: ResolverContext): KubbFile.File
401
+ resolveBanner(node: RootNode | null, context: ResolveBannerContext): string | undefined
402
+ resolveFooter(node: RootNode | null, context: ResolveBannerContext): string | undefined
403
+ }
404
+
405
+ /**
406
+ * The user-facing subset of a `Resolver` — everything except the four methods injected by
407
+ * `defineResolver` (`default`, `resolveOptions`, `resolvePath`, and `resolveFile`).
408
+ *
409
+ * All four injected methods can still be overridden by providing them explicitly in the builder.
410
+ *
411
+ * @example
412
+ * ```ts
413
+ * export const resolver = defineResolver<PluginTs>(() => ({
414
+ * name: 'default',
415
+ * resolveName(node) { return this.default(node.name, 'function') },
416
+ * }))
417
+ * ```
418
+ */
419
+ export type UserResolver = Omit<Resolver, 'default' | 'resolveOptions' | 'resolvePath' | 'resolveFile' | 'resolveBanner' | 'resolveFooter'>
420
+
264
421
  export type PluginFactoryOptions<
265
422
  /**
266
423
  * Name to be used for the plugin.
@@ -282,16 +439,20 @@ export type PluginFactoryOptions<
282
439
  * When calling `resolvePath` you can specify better types.
283
440
  */
284
441
  TResolvePathOptions extends object = object,
442
+ /**
443
+ * Resolver object that encapsulates the naming and path-resolution helpers used by this plugin.
444
+ * Use `defineResolver` to define the resolver object and export it alongside the plugin.
445
+ */
446
+ TResolver extends Resolver = Resolver,
285
447
  > = {
286
448
  name: TName
287
449
  options: TOptions
288
450
  resolvedOptions: TResolvedOptions
289
451
  context: TContext
290
452
  resolvePathOptions: TResolvePathOptions
453
+ resolver: TResolver
291
454
  }
292
455
 
293
- export type GetPluginFactoryOptions<TPlugin extends UserPlugin> = TPlugin extends UserPlugin<infer X> ? X : never
294
-
295
456
  export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
296
457
  /**
297
458
  * Unique name used for the plugin
@@ -302,7 +463,23 @@ export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOpti
302
463
  /**
303
464
  * Options set for a specific plugin(see kubb.config.js), passthrough of options.
304
465
  */
305
- options: TOptions['resolvedOptions']
466
+ options: TOptions['resolvedOptions'] & {
467
+ output: Output
468
+ include?: Array<Include>
469
+ exclude: Array<Exclude>
470
+ override: Array<Override<TOptions['resolvedOptions']>>
471
+ }
472
+ /**
473
+ * The resolver for this plugin.
474
+ * Composed by `getPreset` from the preset resolver and the user's `resolver` partial override.
475
+ */
476
+ resolver?: TOptions['resolver']
477
+ /**
478
+ * The composed transformer for this plugin.
479
+ * Composed by `getPreset` from the preset's transformers and the user's `transformer` visitor.
480
+ * When a visitor method returns `null`/`undefined`, the preset transformer's result is used instead.
481
+ */
482
+ transformer?: Visitor
306
483
  /**
307
484
  * 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.
308
485
  * Can be used to validate dependent plugins.
@@ -312,12 +489,63 @@ export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOpti
312
489
  * 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.
313
490
  */
314
491
  post?: Array<string>
315
- inject?: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => TOptions['context']
492
+ /**
493
+ * When `apply` is defined, the plugin is only activated when `apply(config)` returns `true`.
494
+ * Inspired by Vite's `apply` option.
495
+ *
496
+ * @example
497
+ * ```ts
498
+ * apply: (config) => config.output.path !== 'disabled'
499
+ * ```
500
+ */
501
+ apply?: (config: Config) => boolean
502
+ /**
503
+ * Expose shared helpers or data to all other plugins via `PluginContext`.
504
+ * The object returned is merged into the context that every plugin receives.
505
+ * Use the `declare global { namespace Kubb { interface PluginContext { … } } }` pattern
506
+ * to make the injected properties type-safe.
507
+ *
508
+ * @example
509
+ * ```ts
510
+ * inject() {
511
+ * return { getOas: () => parseSpec(this.config) }
512
+ * }
513
+ * // Other plugins can then call `this.getOas()` inside buildStart()
514
+ * ```
515
+ */
516
+ inject?: (this: PluginContext<TOptions>) => TOptions['context']
316
517
  }
317
518
 
318
519
  export type UserPluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = UserPlugin<TOptions> & PluginLifecycle<TOptions>
319
520
 
320
- export type UnknownUserPlugin = UserPlugin<PluginFactoryOptions<any, any, any, any, any>>
521
+ type UnknownUserPlugin = UserPlugin<PluginFactoryOptions<string, object, object, unknown, object>>
522
+
523
+ /**
524
+ * Handler for a single schema node. Used by the `schema` hook on a plugin.
525
+ */
526
+ export type SchemaHook<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = (
527
+ this: GeneratorContext<TOptions>,
528
+ node: SchemaNode,
529
+ options: TOptions['resolvedOptions'],
530
+ ) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
531
+
532
+ /**
533
+ * Handler for a single operation node. Used by the `operation` hook on a plugin.
534
+ */
535
+ export type OperationHook<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = (
536
+ this: GeneratorContext<TOptions>,
537
+ node: OperationNode,
538
+ options: TOptions['resolvedOptions'],
539
+ ) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
540
+
541
+ /**
542
+ * Handler for all collected operation nodes. Used by the `operations` hook on a plugin.
543
+ */
544
+ export type OperationsHook<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = (
545
+ this: GeneratorContext<TOptions>,
546
+ nodes: Array<OperationNode>,
547
+ options: TOptions['resolvedOptions'],
548
+ ) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
321
549
 
322
550
  export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
323
551
  /**
@@ -337,28 +565,114 @@ export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
337
565
  /**
338
566
  * Options set for a specific plugin(see kubb.config.js), passthrough of options.
339
567
  */
340
- options: TOptions['resolvedOptions']
568
+ options: TOptions['resolvedOptions'] & {
569
+ output: Output
570
+ include?: Array<Include>
571
+ exclude: Array<Exclude>
572
+ override: Array<Override<TOptions['resolvedOptions']>>
573
+ }
574
+ /**
575
+ * The resolver for this plugin.
576
+ * Composed by `getPreset` from the preset resolver and the user's `resolver` partial override.
577
+ */
578
+ resolver: TOptions['resolver']
579
+ /**
580
+ * The composed transformer for this plugin. Accessible via `context.transformer`.
581
+ * Composed by `getPreset` from the preset's transformers and the user's `transformer` visitor.
582
+ * When a visitor method returns `null`/`undefined`, the preset transformer's result is used instead.
583
+ */
584
+ transformer?: Visitor
585
+
586
+ /**
587
+ * When `apply` is defined, the plugin is only activated when `apply(config)` returns `true`.
588
+ * Inspired by Vite's `apply` option.
589
+ */
590
+ apply?: (config: Config) => boolean
591
+ /**
592
+ * Optional semver version string for this plugin, e.g. `"1.2.3"`.
593
+ * Used in diagnostic messages and version-conflict detection.
594
+ */
595
+ version?: string
341
596
 
342
- install: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => PossiblePromise<void>
597
+ buildStart: (this: PluginContext<TOptions>) => PossiblePromise<void>
343
598
  /**
344
- * Define a context that can be used by other plugins, see `PluginManager' where we convert from `UserPlugin` to `Plugin`(used when calling `definePlugin`).
599
+ * Called once per plugin after all files have been written to disk.
600
+ * Use this for post-processing, copying assets, or generating summary reports.
345
601
  */
346
- inject: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => TOptions['context']
602
+ buildEnd: (this: PluginContext<TOptions>) => PossiblePromise<void>
603
+ /**
604
+ * Called for each schema node during the AST walk.
605
+ * Return a React element, an array of `KubbFile.File`, or `void` for manual handling.
606
+ * Nodes matching `exclude`/`include` filters are skipped automatically.
607
+ *
608
+ * For multiple generators, use `composeGenerators` inside the plugin factory.
609
+ */
610
+ schema?: SchemaHook<TOptions>
611
+ /**
612
+ * Called for each operation node during the AST walk.
613
+ * Return a React element, an array of `KubbFile.File`, or `void` for manual handling.
614
+ *
615
+ * For multiple generators, use `composeGenerators` inside the plugin factory.
616
+ */
617
+ operation?: OperationHook<TOptions>
618
+ /**
619
+ * Called once after all operations have been walked, with the full collected set.
620
+ *
621
+ * For multiple generators, use `composeGenerators` inside the plugin factory.
622
+ */
623
+ operations?: OperationsHook<TOptions>
624
+ /**
625
+ * Expose shared helpers or data to all other plugins via `PluginContext`.
626
+ * The returned object is merged into the context received by every plugin.
627
+ */
628
+ inject: (this: PluginContext<TOptions>) => TOptions['context']
347
629
  }
348
630
 
349
631
  export type PluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = Plugin<TOptions> & PluginLifecycle<TOptions>
350
632
 
351
633
  export type PluginLifecycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
352
634
  /**
353
- * Start of the lifecycle of a plugin.
635
+ * Called once per plugin at the start of its processing phase, before schema/operation/operations hooks run.
636
+ * Use this to set up shared state, fetch remote data, or perform any async initialization.
637
+ * @type hookParallel
638
+ */
639
+ buildStart?: (this: PluginContext<TOptions>) => PossiblePromise<void>
640
+ /**
641
+ * Called once per plugin after all files have been written to disk.
642
+ * Use this for post-processing, copying assets, or generating summary reports.
354
643
  * @type hookParallel
355
644
  */
356
- install?: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => PossiblePromise<void>
645
+ buildEnd?: (this: PluginContext<TOptions>) => PossiblePromise<void>
646
+ /**
647
+ * Called for each schema node during the AST walk.
648
+ * Return a React element (`<File>...</File>`), an array of `KubbFile.File` objects,
649
+ * or `void` to handle file writing manually via `this.upsertFile`.
650
+ * Nodes matching `exclude` / `include` filters are skipped automatically.
651
+ *
652
+ * For multiple generators, use `composeGenerators` inside the plugin factory.
653
+ */
654
+ schema?: SchemaHook<TOptions>
655
+ /**
656
+ * Called for each operation node during the AST walk.
657
+ * Return a React element (`<File>...</File>`), an array of `KubbFile.File` objects,
658
+ * or `void` to handle file writing manually via `this.upsertFile`.
659
+ *
660
+ * For multiple generators, use `composeGenerators` inside the plugin factory.
661
+ */
662
+ operation?: OperationHook<TOptions>
663
+ /**
664
+ * Called once after all operation nodes have been walked, with the full collection.
665
+ * Useful for generating index/barrel files per group or aggregate operation handlers.
666
+ *
667
+ * For multiple generators, use `composeGenerators` inside the plugin factory.
668
+ */
669
+ operations?: OperationsHook<TOptions>
357
670
  /**
358
671
  * Resolve to a Path based on a baseName(example: `./Pet.ts`) and directory(example: `./models`).
359
672
  * Options can als be included.
360
673
  * @type hookFirst
361
674
  * @example ('./Pet.ts', './src/gen/') => '/src/gen/Pet.ts'
675
+ * @deprecated this will be replaced by resolvers
362
676
  */
363
677
  resolvePath?: (this: PluginContext<TOptions>, baseName: KubbFile.BaseName, mode?: KubbFile.Mode, options?: TOptions['resolvePathOptions']) => KubbFile.Path
364
678
  /**
@@ -366,6 +680,7 @@ export type PluginLifecycle<TOptions extends PluginFactoryOptions = PluginFactor
366
680
  * Useful when converting to PascalCase or camelCase.
367
681
  * @type hookFirst
368
682
  * @example ('pet') => 'Pet'
683
+ * @deprecated this will be replaced by resolvers
369
684
  */
370
685
  resolveName?: (this: PluginContext<TOptions>, name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
371
686
  }
@@ -399,9 +714,32 @@ export type ResolveNameParams = {
399
714
  }
400
715
 
401
716
  export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
402
- fabric: Fabric
717
+ fabric: FabricType
403
718
  config: Config
404
- pluginManager: PluginManager
719
+ /**
720
+ * Absolute path to the output directory for the current plugin.
721
+ * Shorthand for `path.resolve(config.root, config.output.path)`.
722
+ */
723
+ root: string
724
+ /**
725
+ * Returns the output mode for the given output config.
726
+ * Returns `'single'` when `output.path` has a file extension, `'split'` otherwise.
727
+ * Shorthand for `getMode(path.resolve(this.root, output.path))`.
728
+ */
729
+ getMode: (output: { path: string }) => KubbFile.Mode
730
+ driver: PluginDriver
731
+ /**
732
+ * Get a plugin by name. Returns the plugin typed via `Kubb.PluginRegistry` when
733
+ * the name is a registered key, otherwise returns the generic `Plugin`.
734
+ */
735
+ getPlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined
736
+ getPlugin(name: string): Plugin | undefined
737
+ /**
738
+ * Like `getPlugin` but throws a descriptive error when the plugin is not found.
739
+ * Useful for enforcing dependencies inside `buildStart()`.
740
+ */
741
+ requirePlugin<TName extends keyof Kubb.PluginRegistry>(name: TName): Plugin<Kubb.PluginRegistry[TName]>
742
+ requirePlugin(name: string): Plugin
405
743
  /**
406
744
  * Only add when the file does not exist yet
407
745
  */
@@ -410,13 +748,39 @@ export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryO
410
748
  * merging multiple sources into the same output file
411
749
  */
412
750
  upsertFile: (...file: Array<KubbFile.File>) => Promise<void>
751
+ /**
752
+ * @deprecated use this.warn, this.error, this.info instead
753
+ */
413
754
  events: AsyncEventEmitter<KubbEvents>
414
- mode: KubbFile.Mode
415
755
  /**
416
756
  * Current plugin
417
757
  */
418
758
  plugin: Plugin<TOptions>
759
+ /**
760
+ * Resolver for the current plugin. Shorthand for `plugin.resolver`.
761
+ */
762
+ resolver: TOptions['resolver']
763
+ /**
764
+ * Composed transformer for the current plugin. Shorthand for `plugin.transformer`.
765
+ * Apply with `transform(node, context.transformer)` to pre-process AST nodes before printing.
766
+ */
767
+ transformer: Visitor | undefined
419
768
 
769
+ /**
770
+ * Emit a warning via the build event system.
771
+ * Shorthand for `this.events.emit('warn', message)`.
772
+ */
773
+ warn: (message: string) => void
774
+ /**
775
+ * Emit an error via the build event system.
776
+ * Shorthand for `this.events.emit('error', error)`.
777
+ */
778
+ error: (error: string | Error) => void
779
+ /**
780
+ * Emit an info message via the build event system.
781
+ * Shorthand for `this.events.emit('info', message)`.
782
+ */
783
+ info: (message: string) => void
420
784
  /**
421
785
  * Opens the Kubb Studio URL for the current `rootNode` in the default browser.
422
786
  * Falls back to printing the URL if the browser cannot be launched.
@@ -441,10 +805,23 @@ export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryO
441
805
  }
442
806
  ) &
443
807
  Kubb.PluginContext
808
+
809
+ /**
810
+ * Narrowed `PluginContext` used as the `this` type inside generator and plugin AST hook methods.
811
+ *
812
+ * Generators and the `schema`/`operation`/`operations` plugin hooks are only invoked from
813
+ * `runPluginAstHooks`, which already guards against a missing adapter. This type reflects
814
+ * that guarantee — `this.adapter` and `this.rootNode` are always defined, so no runtime
815
+ * checks or casts are needed inside the method bodies.
816
+ */
817
+ export type GeneratorContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = Omit<PluginContext<TOptions>, 'adapter' | 'rootNode'> & {
818
+ adapter: Adapter
819
+ rootNode: RootNode
820
+ }
444
821
  /**
445
822
  * Specify the export location for the files and define the behavior of the output
446
823
  */
447
- export type Output<TOptions> = {
824
+ export type Output<_TOptions = unknown> = {
448
825
  /**
449
826
  * Path to the output folder or file that will contain the generated code
450
827
  */
@@ -457,11 +834,11 @@ export type Output<TOptions> = {
457
834
  /**
458
835
  * Add a banner text in the beginning of every file
459
836
  */
460
- banner?: string | ((options: TOptions) => string)
837
+ banner?: string | ((node?: RootNode) => string)
461
838
  /**
462
839
  * Add a footer text in the beginning of every file
463
840
  */
464
- footer?: string | ((options: TOptions) => string)
841
+ footer?: string | ((node?: RootNode) => string)
465
842
  /**
466
843
  * Whether to override existing external files if they already exist.
467
844
  * @default false
@@ -469,8 +846,18 @@ export type Output<TOptions> = {
469
846
  override?: boolean
470
847
  }
471
848
 
472
- type GroupContext = {
473
- group: string
849
+ export type UserGroup = {
850
+ /**
851
+ * Defines the type where to group the files.
852
+ * - 'tag' groups files by OpenAPI tags.
853
+ * - 'path' groups files by OpenAPI paths.
854
+ * @default undefined
855
+ */
856
+ type: 'tag' | 'path'
857
+ /**
858
+ * Return the name of a group based on the group name, this is used for the file and name generation.
859
+ */
860
+ name?: (context: { group: string }) => string
474
861
  }
475
862
 
476
863
  export type Group = {
@@ -482,9 +869,9 @@ export type Group = {
482
869
  */
483
870
  type: 'tag' | 'path'
484
871
  /**
485
- * Return the name of a group based on the group name, this used for the file and name generation
872
+ * Return the name of a group based on the group name, this is used for the file and name generation.
486
873
  */
487
- name?: (context: GroupContext) => string
874
+ name: (context: { group: string }) => string
488
875
  }
489
876
 
490
877
  export type LoggerOptions = {
@@ -497,16 +884,216 @@ export type LoggerOptions = {
497
884
  /**
498
885
  * Shared context passed to all plugins, parsers, and Fabric internals.
499
886
  */
500
- export interface LoggerContext extends AsyncEventEmitter<KubbEvents> {}
501
-
502
- type Install<TOptions = unknown> = (context: LoggerContext, options?: TOptions) => void | Promise<void>
887
+ export type LoggerContext = AsyncEventEmitter<KubbEvents>
503
888
 
504
889
  export type Logger<TOptions extends LoggerOptions = LoggerOptions> = {
505
890
  name: string
506
- install: Install<TOptions>
891
+ install: (context: LoggerContext, options?: TOptions) => void | Promise<void>
507
892
  }
508
893
 
509
- export type UserLogger<TOptions extends LoggerOptions = LoggerOptions> = Omit<Logger<TOptions>, 'logLevel'>
894
+ export type UserLogger<TOptions extends LoggerOptions = LoggerOptions> = Logger<TOptions>
510
895
 
511
- export type { DefineStorage } from './defineStorage.ts'
896
+ /**
897
+ * Compatibility preset for code generation tools.
898
+ * - `'default'` – no compatibility adjustments (default behavior).
899
+ * - `'kubbV4'` – align generated names and structures with Kubb v4 output.
900
+ */
901
+ export type CompatibilityPreset = 'default' | 'kubbV4'
902
+
903
+ export type { Storage } from './createStorage.ts'
904
+ export type { Generator } from './defineGenerator.ts'
512
905
  export type { KubbEvents } from './Kubb.ts'
906
+
907
+ /**
908
+ * A preset bundles a name, a resolver, optional AST transformers,
909
+ * and optional generators into a single reusable configuration object.
910
+ *
911
+ * @template TResolver - The concrete resolver type for this preset.
912
+ */
913
+ export type Preset<TResolver extends Resolver = Resolver> = {
914
+ /**
915
+ * Unique identifier for this preset.
916
+ */
917
+ name: string
918
+ /**
919
+ * The resolver used by this preset.
920
+ */
921
+ resolver: TResolver
922
+ /**
923
+ * Optional AST visitors / transformers applied after resolving.
924
+ */
925
+ transformers?: Array<Visitor>
926
+ /**
927
+ * Optional generators used by this preset. Plugin implementations cast this
928
+ * to their concrete generator type.
929
+ */
930
+ generators?: Array<Generator<any>>
931
+ /**
932
+ * Optional printer factory used by this preset.
933
+ * The generator calls this function at render-time to produce a configured printer instance.
934
+ */
935
+ printer?: (options: any) => Printer
936
+ }
937
+
938
+ /**
939
+ * A named registry of presets, keyed by preset name.
940
+ *
941
+ * @template TResolver - The concrete resolver type shared by all presets in this registry.
942
+ * @template TName - The union of valid preset name keys.
943
+ */
944
+ export type Presets<TResolver extends Resolver = Resolver> = Record<CompatibilityPreset, Preset<TResolver>>
945
+
946
+ type ByTag = {
947
+ type: 'tag'
948
+ pattern: string | RegExp
949
+ }
950
+
951
+ type ByOperationId = {
952
+ type: 'operationId'
953
+ pattern: string | RegExp
954
+ }
955
+
956
+ type ByPath = {
957
+ type: 'path'
958
+ pattern: string | RegExp
959
+ }
960
+
961
+ type ByMethod = {
962
+ type: 'method'
963
+ pattern: HttpMethod | RegExp
964
+ }
965
+ // TODO implement as alternative for ByMethod
966
+ // type ByMethods = {
967
+ // type: 'methods'
968
+ // pattern: Array<HttpMethod>
969
+ // }
970
+
971
+ type BySchemaName = {
972
+ type: 'schemaName'
973
+ pattern: string | RegExp
974
+ }
975
+
976
+ type ByContentType = {
977
+ type: 'contentType'
978
+ pattern: string | RegExp
979
+ }
980
+
981
+ export type Exclude = ByTag | ByOperationId | ByPath | ByMethod | ByContentType | BySchemaName
982
+ export type Include = ByTag | ByOperationId | ByPath | ByMethod | ByContentType | BySchemaName
983
+
984
+ export type Override<TOptions> = (ByTag | ByOperationId | ByPath | ByMethod | BySchemaName | ByContentType) & {
985
+ //TODO should be options: Omit<Partial<TOptions>, 'override'>
986
+ options: Partial<TOptions>
987
+ }
988
+
989
+ export type ResolvePathOptions = {
990
+ pluginName?: string
991
+ group?: {
992
+ tag?: string
993
+ path?: string
994
+ }
995
+ type?: ResolveNameParams['type']
996
+ }
997
+
998
+ /**
999
+ * File-specific parameters for `Resolver.resolvePath`.
1000
+ *
1001
+ * Pass alongside a `ResolverContext` to identify which file to resolve.
1002
+ * Provide `tag` for tag-based grouping or `path` for path-based grouping.
1003
+ *
1004
+ * @example
1005
+ * ```ts
1006
+ * resolver.resolvePath(
1007
+ * { baseName: 'petTypes.ts', tag: 'pets' },
1008
+ * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
1009
+ * )
1010
+ * // → '/src/types/petsController/petTypes.ts'
1011
+ * ```
1012
+ */
1013
+ export type ResolverPathParams = {
1014
+ baseName: KubbFile.BaseName
1015
+ pathMode?: KubbFile.Mode
1016
+ /**
1017
+ * Tag value used when `group.type === 'tag'`.
1018
+ */
1019
+ tag?: string
1020
+ /**
1021
+ * Path value used when `group.type === 'path'`.
1022
+ */
1023
+ path?: string
1024
+ }
1025
+
1026
+ /**
1027
+ * Shared context passed as the second argument to `Resolver.resolvePath` and `Resolver.resolveFile`.
1028
+ *
1029
+ * Describes where on disk output is rooted, which output config is active, and the optional
1030
+ * grouping strategy that controls subdirectory layout.
1031
+ *
1032
+ * @example
1033
+ * ```ts
1034
+ * const context: ResolverContext = {
1035
+ * root: config.root,
1036
+ * output,
1037
+ * group,
1038
+ * }
1039
+ * ```
1040
+ */
1041
+ export type ResolverContext = {
1042
+ root: string
1043
+ output: Output
1044
+ group?: Group
1045
+ /**
1046
+ * Plugin name used to populate `meta.pluginName` on the resolved file.
1047
+ */
1048
+ pluginName?: string
1049
+ }
1050
+
1051
+ /**
1052
+ * File-specific parameters for `Resolver.resolveFile`.
1053
+ *
1054
+ * Pass alongside a `ResolverContext` to fully describe the file to resolve.
1055
+ * `tag` and `path` are used only when a matching `group` is present in the context.
1056
+ *
1057
+ * @example
1058
+ * ```ts
1059
+ * resolver.resolveFile(
1060
+ * { name: 'listPets', extname: '.ts', tag: 'pets' },
1061
+ * { root: '/src', output: { path: 'types' }, group: { type: 'tag' } },
1062
+ * )
1063
+ * // → { baseName: 'listPets.ts', path: '/src/types/petsController/listPets.ts', ... }
1064
+ * ```
1065
+ */
1066
+ export type ResolverFileParams = {
1067
+ name: string
1068
+ extname: KubbFile.Extname
1069
+ /**
1070
+ * Tag value used when `group.type === 'tag'`.
1071
+ */
1072
+ tag?: string
1073
+ /**
1074
+ * Path value used when `group.type === 'path'`.
1075
+ */
1076
+ path?: string
1077
+ }
1078
+
1079
+ /**
1080
+ * Context passed to `Resolver.resolveBanner` and `Resolver.resolveFooter`.
1081
+ *
1082
+ * `output` is optional — not every plugin configures a banner/footer.
1083
+ * `config` carries the global Kubb config, used to derive the default Kubb banner.
1084
+ *
1085
+ * @example
1086
+ * ```ts
1087
+ * resolver.resolveBanner(rootNode, { output: { banner: '// generated' }, config })
1088
+ * // → '// generated'
1089
+ * ```
1090
+ */
1091
+ export type ResolveBannerContext = {
1092
+ output?: Pick<Output, 'banner' | 'footer'>
1093
+ config: Config
1094
+ }
1095
+
1096
+ export type { CLIOptions, ConfigInput } from './defineConfig.ts'
1097
+ export type { Parser, UserParser } from './defineParser.ts'
1098
+ export type { FunctionParamsAST } from './utils/FunctionParams.ts'
1099
+ export type { FileMetaBase } from './utils/getBarrelFiles.ts'