@kubb/core 5.0.0-alpha.20 → 5.0.0-alpha.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "5.0.0-alpha.20",
3
+ "version": "5.0.0-alpha.22",
4
4
  "description": "Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -71,7 +71,7 @@
71
71
  "remeda": "^2.33.6",
72
72
  "semver": "^7.7.4",
73
73
  "tinyexec": "^1.0.4",
74
- "@kubb/ast": "5.0.0-alpha.20"
74
+ "@kubb/ast": "5.0.0-alpha.22"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@types/semver": "^7.7.1",
package/src/Kubb.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { KubbFile } from '@kubb/fabric-core/types'
1
+ import type { FabricFile } from '@kubb/fabric-core/types'
2
2
  import type { Strategy } from './PluginDriver.ts'
3
3
  import type { Config, Plugin, PluginLifecycleHooks } from './types'
4
4
 
@@ -76,7 +76,7 @@ export interface KubbEvents {
76
76
  /**
77
77
  * Emitted when code generation phase completes.
78
78
  */
79
- 'generation:end': [config: Config, files: Array<KubbFile.ResolvedFile>, sources: Map<KubbFile.Path, string>]
79
+ 'generation:end': [config: Config, files: Array<FabricFile.ResolvedFile>, sources: Map<FabricFile.Path, string>]
80
80
  /**
81
81
  * Emitted with a summary of the generation results.
82
82
  * Contains summary lines, title, and success status.
@@ -160,7 +160,7 @@ export interface KubbEvents {
160
160
  * Emitted when file processing starts.
161
161
  * Contains the list of files to be processed.
162
162
  */
163
- 'files:processing:start': [files: Array<KubbFile.ResolvedFile>]
163
+ 'files:processing:start': [files: Array<FabricFile.ResolvedFile>]
164
164
  /**
165
165
  * Emitted for each file being processed, providing progress updates.
166
166
  * Contains processed count, total count, percentage, and file details.
@@ -186,7 +186,7 @@ export interface KubbEvents {
186
186
  /**
187
187
  * The file being processed.
188
188
  */
189
- file: KubbFile.ResolvedFile
189
+ file: FabricFile.ResolvedFile
190
190
  /**
191
191
  * Kubb configuration (not present in Fabric).
192
192
  * Provides access to the current config during file processing.
@@ -198,7 +198,7 @@ export interface KubbEvents {
198
198
  * Emitted when file processing completes.
199
199
  * Contains the list of processed files.
200
200
  */
201
- 'files:processing:end': [files: Array<KubbFile.ResolvedFile>]
201
+ 'files:processing:end': [files: Array<FabricFile.ResolvedFile>]
202
202
 
203
203
  /**
204
204
  * Emitted when a plugin starts executing.
@@ -3,7 +3,7 @@ import { performance } from 'node:perf_hooks'
3
3
  import type { AsyncEventEmitter } from '@internals/utils'
4
4
  import { isPromiseRejectedResult, setUniqueName, transformReservedWord, ValidationPluginError } from '@internals/utils'
5
5
  import type { RootNode } from '@kubb/ast/types'
6
- import type { Fabric as FabricType, KubbFile } from '@kubb/fabric-core/types'
6
+ import type { FabricFile, Fabric as FabricType } from '@kubb/fabric-core/types'
7
7
  import { CORE_PLUGIN_NAME, DEFAULT_STUDIO_URL } from './constants.ts'
8
8
  import { openInStudio as openInStudioFn } from './devtools.ts'
9
9
 
@@ -27,6 +27,14 @@ import { hookFirst, hookParallel, hookSeq } from './utils/executeStrategies.ts'
27
27
 
28
28
  type RequiredPluginLifecycle = Required<PluginLifecycle>
29
29
 
30
+ /**
31
+ * Hook dispatch strategy used by the `PluginDriver`.
32
+ *
33
+ * - `hookFirst` — stops at the first non-null result.
34
+ * - `hookForPlugin` — calls only the matching plugin.
35
+ * - `hookParallel` — calls all plugins concurrently.
36
+ * - `hookSeq` — calls all plugins in order, threading the result.
37
+ */
30
38
  export type Strategy = 'hookFirst' | 'hookForPlugin' | 'hookParallel' | 'hookSeq'
31
39
 
32
40
  type ParseResult<H extends PluginLifecycleHooks> = RequiredPluginLifecycle[H]
@@ -47,15 +55,27 @@ type Options = {
47
55
  concurrency?: number
48
56
  }
49
57
 
58
+ /**
59
+ * Parameters accepted by `PluginDriver.getFile` to resolve a generated file descriptor.
60
+ */
50
61
  export type GetFileOptions<TOptions = object> = {
51
62
  name: string
52
- mode?: KubbFile.Mode
53
- extname: KubbFile.Extname
63
+ mode?: FabricFile.Mode
64
+ extname: FabricFile.Extname
54
65
  pluginName: string
55
66
  options?: TOptions
56
67
  }
57
68
 
58
- export function getMode(fileOrFolder: string | undefined | null): KubbFile.Mode {
69
+ /**
70
+ * Returns `'single'` when `fileOrFolder` has a file extension, `'split'` otherwise.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * getMode('src/gen/types.ts') // 'single'
75
+ * getMode('src/gen/types') // 'split'
76
+ * ```
77
+ */
78
+ export function getMode(fileOrFolder: string | undefined | null): FabricFile.Mode {
59
79
  if (!fileOrFolder) {
60
80
  return 'split'
61
81
  }
@@ -104,10 +124,10 @@ export class PluginDriver {
104
124
  events: this.options.events,
105
125
  driver: this,
106
126
  mode: getMode(resolve(this.config.root, this.config.output.path)),
107
- addFile: async (...files: Array<KubbFile.File>) => {
127
+ addFile: async (...files: Array<FabricFile.File>) => {
108
128
  await this.options.fabric.addFile(...files)
109
129
  },
110
- upsertFile: async (...files: Array<KubbFile.File>) => {
130
+ upsertFile: async (...files: Array<FabricFile.File>) => {
111
131
  await this.options.fabric.upsertFile(...files)
112
132
  },
113
133
  get rootNode(): RootNode | undefined {
@@ -160,7 +180,7 @@ export class PluginDriver {
160
180
  return this.#getSortedPlugins()
161
181
  }
162
182
 
163
- getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileOptions<TOptions>): KubbFile.File<{ pluginName: string }> {
183
+ getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileOptions<TOptions>): FabricFile.File<{ pluginName: string }> {
164
184
  const resolvedName = mode ? (mode === 'single' ? '' : this.resolveName({ name, pluginName, type: 'file' })) : name
165
185
 
166
186
  const path = this.resolvePath({
@@ -176,7 +196,7 @@ export class PluginDriver {
176
196
 
177
197
  return {
178
198
  path,
179
- baseName: basename(path) as KubbFile.File['baseName'],
199
+ baseName: basename(path) as FabricFile.File['baseName'],
180
200
  meta: {
181
201
  pluginName,
182
202
  },
@@ -186,7 +206,7 @@ export class PluginDriver {
186
206
  }
187
207
  }
188
208
 
189
- resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): KubbFile.Path => {
209
+ resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): FabricFile.Path => {
190
210
  const root = resolve(this.config.root, this.config.output.path)
191
211
  const defaultPath = resolve(root, params.baseName)
192
212
 
package/src/build.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { dirname, relative, resolve } from 'node:path'
2
2
  import { AsyncEventEmitter, BuildError, exists, formatMs, getElapsedMs, getRelativePath, URLPath } from '@internals/utils'
3
- import type { Fabric as FabricType, KubbFile } from '@kubb/fabric-core/types'
3
+ import type { FabricFile, Fabric as FabricType } from '@kubb/fabric-core/types'
4
4
  import { createFabric } from '@kubb/react-fabric'
5
5
  import { typescriptParser } from '@kubb/react-fabric/parsers'
6
6
  import { fsPlugin } from '@kubb/react-fabric/plugins'
@@ -26,7 +26,7 @@ type BuildOutput = {
26
26
  */
27
27
  failedPlugins: Set<{ plugin: Plugin; error: Error }>
28
28
  fabric: FabricType
29
- files: Array<KubbFile.ResolvedFile>
29
+ files: Array<FabricFile.ResolvedFile>
30
30
  driver: PluginDriver
31
31
  /**
32
32
  * Elapsed time in milliseconds for each plugin, keyed by plugin name.
@@ -36,7 +36,7 @@ type BuildOutput = {
36
36
  /**
37
37
  * Raw generated source, keyed by absolute file path.
38
38
  */
39
- sources: Map<KubbFile.Path, string>
39
+ sources: Map<FabricFile.Path, string>
40
40
  }
41
41
 
42
42
  /**
@@ -46,7 +46,7 @@ type SetupResult = {
46
46
  events: AsyncEventEmitter<KubbEvents>
47
47
  fabric: FabricType
48
48
  driver: PluginDriver
49
- sources: Map<KubbFile.Path, string>
49
+ sources: Map<FabricFile.Path, string>
50
50
  }
51
51
 
52
52
  /**
@@ -63,7 +63,7 @@ type SetupResult = {
63
63
  export async function setup(options: BuildOptions): Promise<SetupResult> {
64
64
  const { config: userConfig, events = new AsyncEventEmitter<KubbEvents>() } = options
65
65
 
66
- const sources: Map<KubbFile.Path, string> = new Map<KubbFile.Path, string>()
66
+ const sources: Map<FabricFile.Path, string> = new Map<FabricFile.Path, string>()
67
67
  const diagnosticInfo = getDiagnosticInfo()
68
68
 
69
69
  if (Array.isArray(userConfig.input)) {
@@ -351,7 +351,7 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
351
351
  existingBarrel?.exports?.flatMap((e) => (Array.isArray(e.name) ? e.name : [e.name])).filter((n): n is string => Boolean(n)) ?? [],
352
352
  )
353
353
 
354
- const rootFile: KubbFile.File = {
354
+ const rootFile: FabricFile.File = {
355
355
  path: rootPath,
356
356
  baseName: BARREL_FILENAME,
357
357
  exports: buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }),
@@ -394,14 +394,14 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
394
394
  }
395
395
 
396
396
  type BuildBarrelExportsParams = {
397
- barrelFiles: KubbFile.ResolvedFile[]
397
+ barrelFiles: FabricFile.ResolvedFile[]
398
398
  rootDir: string
399
399
  existingExports: Set<string>
400
400
  config: Config
401
401
  driver: PluginDriver
402
402
  }
403
403
 
404
- function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }: BuildBarrelExportsParams): KubbFile.Export[] {
404
+ function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }: BuildBarrelExportsParams): FabricFile.Export[] {
405
405
  const pluginNameMap = new Map<string, Plugin>()
406
406
  for (const plugin of driver.plugins) {
407
407
  pluginNameMap.set(plugin.name, plugin)
@@ -433,7 +433,7 @@ function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, dri
433
433
  name: exportName,
434
434
  path: getRelativePath(rootDir, file.path),
435
435
  isTypeOnly: config.output.barrelType === 'all' ? containsOnlyTypes : source.isTypeOnly,
436
- } satisfies KubbFile.Export,
436
+ } satisfies FabricFile.Export,
437
437
  ]
438
438
  })
439
439
  })
package/src/constants.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { KubbFile } from '@kubb/fabric-core/types'
1
+ import type { FabricFile } from '@kubb/fabric-core/types'
2
2
 
3
3
  /**
4
4
  * Base URL for the Kubb Studio web app.
@@ -33,7 +33,7 @@ export const DEFAULT_BANNER = 'simple' as const
33
33
  /**
34
34
  * Default file-extension mapping used when no explicit mapping is configured.
35
35
  */
36
- export const DEFAULT_EXTENSION: Record<KubbFile.Extname, KubbFile.Extname | ''> = { '.ts': '.ts' }
36
+ export const DEFAULT_EXTENSION: Record<FabricFile.Extname, FabricFile.Extname | ''> = { '.ts': '.ts' }
37
37
 
38
38
  /**
39
39
  * Characters recognized as path separators on both POSIX and Windows.
@@ -0,0 +1,26 @@
1
+ import type { PluginFactoryOptions } from './types.ts'
2
+
3
+ /**
4
+ * Builder type for the plugin-specific builder fields.
5
+ * `name` is required; all other methods are defined by the concrete plugin builder type.
6
+ */
7
+ type BuilderBuilder<T extends PluginFactoryOptions> = () => T['builder'] & ThisType<T['builder']>
8
+
9
+ /**
10
+ * Defines a builder for a plugin — a named collection of schema-building helpers that
11
+ * can be exported alongside the plugin and imported by other plugins or generators.
12
+ *
13
+ * @example
14
+ * export const builder = defineBuilder<PluginTs>(() => ({
15
+ * name: 'default',
16
+ * buildParamsSchema({ params, node, resolver }) {
17
+ * return createSchema({ type: 'object', properties: [] })
18
+ * },
19
+ * buildDataSchemaNode({ node, resolver }) {
20
+ * return createSchema({ type: 'object', properties: [] })
21
+ * },
22
+ * }))
23
+ */
24
+ export function defineBuilder<T extends PluginFactoryOptions>(build: BuilderBuilder<T>): T['builder'] {
25
+ return build() as T['builder']
26
+ }
@@ -1,5 +1,5 @@
1
1
  import type { OperationNode, SchemaNode } from '@kubb/ast/types'
2
- import type { KubbFile } from '@kubb/fabric-core/types'
2
+ import type { FabricFile } from '@kubb/fabric-core/types'
3
3
  import type { FabricReactNode } from '@kubb/react-fabric/types'
4
4
  import type { Adapter, Config, Plugin, PluginFactoryOptions } from './types.ts'
5
5
 
@@ -10,6 +10,7 @@ export type Version = '1' | '2'
10
10
  */
11
11
  export type OperationsV2Props<TPlugin extends PluginFactoryOptions = PluginFactoryOptions> = {
12
12
  config: Config
13
+ plugin: Plugin<TPlugin>
13
14
  adapter: Adapter
14
15
  options: Plugin<TPlugin>['options']
15
16
  nodes: Array<OperationNode>
@@ -21,6 +22,7 @@ export type OperationsV2Props<TPlugin extends PluginFactoryOptions = PluginFacto
21
22
  export type OperationV2Props<TPlugin extends PluginFactoryOptions = PluginFactoryOptions> = {
22
23
  config: Config
23
24
  adapter: Adapter
25
+ plugin: Plugin<TPlugin>
24
26
  options: Plugin<TPlugin>['options']
25
27
  node: OperationNode
26
28
  }
@@ -31,19 +33,26 @@ export type OperationV2Props<TPlugin extends PluginFactoryOptions = PluginFactor
31
33
  export type SchemaV2Props<TPlugin extends PluginFactoryOptions = PluginFactoryOptions> = {
32
34
  config: Config
33
35
  adapter: Adapter
36
+ plugin: Plugin<TPlugin>
34
37
  options: Plugin<TPlugin>['options']
35
38
  node: SchemaNode
36
39
  }
37
40
 
41
+ /**
42
+ * Input shape for a core v2 async generator — lifecycle methods are optional.
43
+ */
38
44
  type UserCoreGeneratorV2<TPlugin extends PluginFactoryOptions> = {
39
45
  name: string
40
46
  type: 'core'
41
47
  version?: '2'
42
- operations?(props: OperationsV2Props<TPlugin>): Promise<Array<KubbFile.File>>
43
- operation?(props: OperationV2Props<TPlugin>): Promise<Array<KubbFile.File>>
44
- schema?(props: SchemaV2Props<TPlugin>): Promise<Array<KubbFile.File>>
48
+ operations?(props: OperationsV2Props<TPlugin>): Promise<Array<FabricFile.File>>
49
+ operation?(props: OperationV2Props<TPlugin>): Promise<Array<FabricFile.File>>
50
+ schema?(props: SchemaV2Props<TPlugin>): Promise<Array<FabricFile.File>>
45
51
  }
46
52
 
53
+ /**
54
+ * Input shape for a React v2 generator — component methods are optional.
55
+ */
47
56
  type UserReactGeneratorV2<TPlugin extends PluginFactoryOptions> = {
48
57
  name: string
49
58
  type: 'react'
@@ -53,15 +62,21 @@ type UserReactGeneratorV2<TPlugin extends PluginFactoryOptions> = {
53
62
  Schema?(props: SchemaV2Props<TPlugin>): FabricReactNode
54
63
  }
55
64
 
65
+ /**
66
+ * A fully resolved core v2 generator with `version: '2'` and guaranteed async lifecycle methods.
67
+ */
56
68
  export type CoreGeneratorV2<TPlugin extends PluginFactoryOptions = PluginFactoryOptions> = {
57
69
  name: string
58
70
  type: 'core'
59
71
  version: '2'
60
- operations(props: OperationsV2Props<TPlugin>): Promise<Array<KubbFile.File>>
61
- operation(props: OperationV2Props<TPlugin>): Promise<Array<KubbFile.File>>
62
- schema(props: SchemaV2Props<TPlugin>): Promise<Array<KubbFile.File>>
72
+ operations(props: OperationsV2Props<TPlugin>): Promise<Array<FabricFile.File>>
73
+ operation(props: OperationV2Props<TPlugin>): Promise<Array<FabricFile.File>>
74
+ schema(props: SchemaV2Props<TPlugin>): Promise<Array<FabricFile.File>>
63
75
  }
64
76
 
77
+ /**
78
+ * A fully resolved React v2 generator with `version: '2'` and guaranteed component methods.
79
+ */
65
80
  export type ReactGeneratorV2<TPlugin extends PluginFactoryOptions = PluginFactoryOptions> = {
66
81
  name: string
67
82
  type: 'react'
@@ -71,6 +86,9 @@ export type ReactGeneratorV2<TPlugin extends PluginFactoryOptions = PluginFactor
71
86
  Schema(props: SchemaV2Props<TPlugin>): FabricReactNode
72
87
  }
73
88
 
89
+ /**
90
+ * Union of all v2 generator shapes accepted by the plugin system.
91
+ */
74
92
  export type Generator<TPlugin extends PluginFactoryOptions = PluginFactoryOptions> = UserCoreGeneratorV2<TPlugin> | UserReactGeneratorV2<TPlugin>
75
93
 
76
94
  /**
@@ -1,9 +1,9 @@
1
1
  import type { Visitor } from '@kubb/ast/types'
2
- import type { Preset, Resolver } from './types.ts'
2
+ import type { Generator, Preset, Resolver } from './types.ts'
3
3
 
4
4
  /**
5
- * Creates a typed preset object that bundles a name, resolvers, and optional
6
- * transformers — the building block for composable plugin presets.
5
+ * Creates a typed preset object that bundles a name, resolvers, optional
6
+ * transformers, and optional generators — the building block for composable plugin presets.
7
7
  *
8
8
  * @example
9
9
  * import { definePreset } from '@kubb/core'
@@ -14,10 +14,14 @@ import type { Preset, Resolver } from './types.ts'
14
14
  * @example
15
15
  * // With custom transformers
16
16
  * export const myPreset = definePreset('myPreset', { resolvers: [resolverTsLegacy], transformers: [myTransformer] })
17
+ *
18
+ * @example
19
+ * // With generators
20
+ * export const myPreset = definePreset('myPreset', { resolvers: [resolverTsLegacy], generators: [typeGeneratorLegacy] })
17
21
  */
18
22
  export function definePreset<TResolver extends Resolver = Resolver, TName extends string = string>(
19
23
  name: TName,
20
- { resolvers, transformers }: { resolvers: Array<TResolver>; transformers?: Array<Visitor> },
24
+ { resolvers, transformers, generators }: { resolvers: Array<TResolver>; transformers?: Array<Visitor>; generators?: Array<Generator<any>> },
21
25
  ): Preset<TResolver> & { name: TName } {
22
- return { name, resolvers, transformers }
26
+ return { name, resolvers, transformers, generators }
23
27
  }