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

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