@kubb/core 5.0.0-alpha.30 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "5.0.0-alpha.30",
3
+ "version": "5.0.0-alpha.31",
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.7",
72
72
  "semver": "^7.7.4",
73
73
  "tinyexec": "^1.0.4",
74
- "@kubb/ast": "5.0.0-alpha.30"
74
+ "@kubb/ast": "5.0.0-alpha.31"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@types/semver": "^7.7.1",
package/src/Kubb.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { FabricFile } from '@kubb/fabric-core/types'
1
+ import type * as KubbFile from './KubbFile.ts'
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<FabricFile.ResolvedFile>, sources: Map<FabricFile.Path, string>]
79
+ 'generation:end': [config: Config, files: Array<KubbFile.ResolvedFile>, sources: Map<KubbFile.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<FabricFile.ResolvedFile>]
163
+ 'files:processing:start': [files: Array<KubbFile.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: FabricFile.ResolvedFile
189
+ file: KubbFile.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<FabricFile.ResolvedFile>]
201
+ 'files:processing:end': [files: Array<KubbFile.ResolvedFile>]
202
202
 
203
203
  /**
204
204
  * Emitted when a plugin starts executing.
@@ -0,0 +1,143 @@
1
+ type ImportName =
2
+ | string
3
+ | Array<
4
+ | string
5
+ | {
6
+ propertyName: string
7
+ name?: string
8
+ }
9
+ >
10
+
11
+ export type Import = {
12
+ /**
13
+ * Import name to be used.
14
+ * @example ["useState"]
15
+ * @example "React"
16
+ */
17
+ name: ImportName
18
+ /**
19
+ * Path for the import.
20
+ * @example '@kubb/core'
21
+ */
22
+ path: string
23
+ /**
24
+ * Add type-only import prefix.
25
+ * - `true` generates `import type { Type } from './path'`
26
+ * - `false` generates `import { Type } from './path'`
27
+ * @default false
28
+ */
29
+ isTypeOnly?: boolean
30
+ /**
31
+ * Import entire module as namespace.
32
+ * - `true` generates `import * as Name from './path'`
33
+ * - `false` generates standard import
34
+ * @default false
35
+ */
36
+ isNameSpace?: boolean
37
+ /**
38
+ * When root is set it will compute a relative path with `getRelativePath(root, path)`.
39
+ */
40
+ root?: string
41
+ }
42
+
43
+ export type Source = {
44
+ name?: string
45
+ value?: string
46
+ /**
47
+ * Make this source a type-only export.
48
+ * @default false
49
+ */
50
+ isTypeOnly?: boolean
51
+ /**
52
+ * Include export keyword in source.
53
+ * @default false
54
+ */
55
+ isExportable?: boolean
56
+ /**
57
+ * Include in barrel file generation.
58
+ * @default false
59
+ */
60
+ isIndexable?: boolean
61
+ }
62
+
63
+ export type Export = {
64
+ /**
65
+ * Export name to be used.
66
+ * @example ["useState"]
67
+ * @example "React"
68
+ */
69
+ name?: string | Array<string>
70
+ /**
71
+ * Path for the export.
72
+ * @example '@kubb/core'
73
+ */
74
+ path: string
75
+ /**
76
+ * Add type-only export prefix.
77
+ * - `true` generates `export type { Type } from './path'`
78
+ * - `false` generates `export { Type } from './path'`
79
+ * @default false
80
+ */
81
+ isTypeOnly?: boolean
82
+ /**
83
+ * Export as aliased namespace.
84
+ * - `true` generates `export * as aliasName from './path'`
85
+ * - `false` generates standard export
86
+ * @default false
87
+ */
88
+ asAlias?: boolean
89
+ }
90
+
91
+ export type Extname = '.ts' | '.js' | '.tsx' | '.json' | `.${string}`
92
+
93
+ export type Mode = 'single' | 'split'
94
+
95
+ /**
96
+ * Name to be used to dynamically create the baseName (based on input.path).
97
+ * Based on UNIX basename.
98
+ * @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
99
+ */
100
+ export type BaseName = `${string}.${string}`
101
+
102
+ /**
103
+ * Fully qualified path to a specified file.
104
+ */
105
+ export type Path = string
106
+
107
+ export type File<TMeta extends object = object> = {
108
+ /**
109
+ * Name used to create the path.
110
+ * Based on UNIX basename, `${name}${extname}`.
111
+ * @link https://nodejs.org/api/path.html#pathbasenamepath-suffix
112
+ */
113
+ baseName: BaseName
114
+ /**
115
+ * Fully qualified path to the file.
116
+ */
117
+ path: Path
118
+ sources: Array<Source>
119
+ imports: Array<Import>
120
+ exports: Array<Export>
121
+ /**
122
+ * Extra metadata used for barrel/index file generation.
123
+ */
124
+ meta?: TMeta
125
+ banner?: string
126
+ footer?: string
127
+ }
128
+
129
+ export type ResolvedFile<TMeta extends object = object> = File<TMeta> & {
130
+ /**
131
+ * Unique identifier, generated from a hash.
132
+ * @default hash
133
+ */
134
+ id: string
135
+ /**
136
+ * First part of the `baseName`, derived from the file name.
137
+ * @link https://nodejs.org/api/path.html#pathformatpathobject
138
+ */
139
+ name: string
140
+ extname: Extname
141
+ imports: Array<Import>
142
+ exports: Array<Export>
143
+ }
@@ -3,9 +3,10 @@ import { performance } from 'node:perf_hooks'
3
3
  import type { AsyncEventEmitter } from '@internals/utils'
4
4
  import { isPromiseRejectedResult, transformReservedWord } from '@internals/utils'
5
5
  import type { RootNode } from '@kubb/ast/types'
6
- import type { FabricFile, Fabric as FabricType } from '@kubb/fabric-core/types'
6
+ import type { Fabric as FabricType } from '@kubb/fabric-core/types'
7
7
  import { DEFAULT_STUDIO_URL } from './constants.ts'
8
8
  import { openInStudio as openInStudioFn } from './devtools.ts'
9
+ import type * as KubbFile from './KubbFile.ts'
9
10
 
10
11
  import type {
11
12
  Adapter,
@@ -59,8 +60,8 @@ type Options = {
59
60
  */
60
61
  export type GetFileOptions<TOptions = object> = {
61
62
  name: string
62
- mode?: FabricFile.Mode
63
- extname: FabricFile.Extname
63
+ mode?: KubbFile.Mode
64
+ extname: KubbFile.Extname
64
65
  pluginName: string
65
66
  options?: TOptions
66
67
  }
@@ -74,7 +75,7 @@ export type GetFileOptions<TOptions = object> = {
74
75
  * getMode('src/gen/types') // 'split'
75
76
  * ```
76
77
  */
77
- export function getMode(fileOrFolder: string | undefined | null): FabricFile.Mode {
78
+ export function getMode(fileOrFolder: string | undefined | null): KubbFile.Mode {
78
79
  if (!fileOrFolder) {
79
80
  return 'split'
80
81
  }
@@ -131,7 +132,7 @@ export class PluginDriver {
131
132
  get root(): string {
132
133
  return resolve(driver.config.root, driver.config.output.path)
133
134
  },
134
- getMode(output: { path: string }): FabricFile.Mode {
135
+ getMode(output: { path: string }): KubbFile.Mode {
135
136
  return getMode(resolve(driver.config.root, driver.config.output.path, output.path))
136
137
  },
137
138
  events: driver.options.events,
@@ -139,10 +140,10 @@ export class PluginDriver {
139
140
  getPlugin: driver.getPlugin.bind(driver),
140
141
  requirePlugin: driver.requirePlugin.bind(driver),
141
142
  driver: driver,
142
- addFile: async (...files: Array<FabricFile.File>) => {
143
+ addFile: async (...files: Array<KubbFile.File>) => {
143
144
  await this.options.fabric.addFile(...files)
144
145
  },
145
- upsertFile: async (...files: Array<FabricFile.File>) => {
146
+ upsertFile: async (...files: Array<KubbFile.File>) => {
146
147
  await this.options.fabric.upsertFile(...files)
147
148
  },
148
149
  get rootNode(): RootNode | undefined {
@@ -206,7 +207,7 @@ export class PluginDriver {
206
207
  /**
207
208
  * @deprecated use resolvers context instead
208
209
  */
209
- getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileOptions<TOptions>): FabricFile.File<{ pluginName: string }> {
210
+ getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileOptions<TOptions>): KubbFile.File<{ pluginName: string }> {
210
211
  const resolvedName = mode ? (mode === 'single' ? '' : this.resolveName({ name, pluginName, type: 'file' })) : name
211
212
 
212
213
  const path = this.resolvePath({
@@ -222,7 +223,7 @@ export class PluginDriver {
222
223
 
223
224
  return {
224
225
  path,
225
- baseName: basename(path) as FabricFile.File['baseName'],
226
+ baseName: basename(path) as KubbFile.File['baseName'],
226
227
  meta: {
227
228
  pluginName,
228
229
  },
@@ -235,7 +236,7 @@ export class PluginDriver {
235
236
  /**
236
237
  * @deprecated use resolvers context instead
237
238
  */
238
- resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): FabricFile.Path => {
239
+ resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): KubbFile.Path => {
239
240
  const root = resolve(this.config.root, this.config.output.path)
240
241
  const defaultPath = resolve(root, params.baseName)
241
242
 
package/src/build.ts CHANGED
@@ -2,12 +2,12 @@ import { dirname, relative, resolve } from 'node:path'
2
2
  import { AsyncEventEmitter, BuildError, exists, formatMs, getElapsedMs, getRelativePath, URLPath } from '@internals/utils'
3
3
  import { transform, walk } from '@kubb/ast'
4
4
  import type { OperationNode } from '@kubb/ast/types'
5
- import type { FabricFile, Fabric as FabricType } from '@kubb/fabric-core/types'
5
+ import type { Fabric as FabricType } from '@kubb/fabric-core/types'
6
6
  import { createFabric } from '@kubb/react-fabric'
7
- import { typescriptParser } from '@kubb/react-fabric/parsers'
8
7
  import { fsPlugin } from '@kubb/react-fabric/plugins'
9
- import { isInputPath } from './config.ts'
10
8
  import { BARREL_FILENAME, DEFAULT_BANNER, DEFAULT_CONCURRENCY, DEFAULT_EXTENSION, DEFAULT_STUDIO_URL } from './constants.ts'
9
+ import { defineParser } from './defineParser.ts'
10
+ import type * as KubbFile from './KubbFile.ts'
11
11
  import { PluginDriver } from './PluginDriver.ts'
12
12
  import { applyHookResult } from './renderNode.tsx'
13
13
  import { fsStorage } from './storages/fsStorage.ts'
@@ -15,6 +15,7 @@ import type { AdapterSource, Config, KubbEvents, Plugin, PluginContext, Storage,
15
15
  import { getDiagnosticInfo } from './utils/diagnostics.ts'
16
16
  import type { FileMetaBase } from './utils/getBarrelFiles.ts'
17
17
  import { getBarrelFiles } from './utils/getBarrelFiles.ts'
18
+ import { isInputPath } from './utils/isInputPath.ts'
18
19
 
19
20
  type BuildOptions = {
20
21
  config: UserConfig
@@ -30,7 +31,7 @@ type BuildOutput = {
30
31
  */
31
32
  failedPlugins: Set<{ plugin: Plugin; error: Error }>
32
33
  fabric: FabricType
33
- files: Array<FabricFile.ResolvedFile>
34
+ files: Array<KubbFile.ResolvedFile>
34
35
  driver: PluginDriver
35
36
  /**
36
37
  * Elapsed time in milliseconds for each plugin, keyed by plugin name.
@@ -40,7 +41,7 @@ type BuildOutput = {
40
41
  /**
41
42
  * Raw generated source, keyed by absolute file path.
42
43
  */
43
- sources: Map<FabricFile.Path, string>
44
+ sources: Map<KubbFile.Path, string>
44
45
  }
45
46
 
46
47
  /**
@@ -50,7 +51,8 @@ type SetupResult = {
50
51
  events: AsyncEventEmitter<KubbEvents>
51
52
  fabric: FabricType
52
53
  driver: PluginDriver
53
- sources: Map<FabricFile.Path, string>
54
+ sources: Map<KubbFile.Path, string>
55
+ config: Config
54
56
  }
55
57
 
56
58
  /**
@@ -60,6 +62,7 @@ type SetupResult = {
60
62
  * - Applies config defaults (`root`, `output.*`, `devtools`).
61
63
  * - Creates the Fabric instance and wires storage, format, and lint hooks.
62
64
  * - Runs the adapter (if configured) to produce the universal `RootNode`.
65
+ * When no adapter is supplied and `@kubb/adapter-oas` is installed as an
63
66
  *
64
67
  * Pass the returned {@link SetupResult} directly to {@link safeBuild} or {@link build}
65
68
  * via the `overrides` argument to reuse the same infrastructure across multiple runs.
@@ -67,7 +70,7 @@ type SetupResult = {
67
70
  export async function setup(options: BuildOptions): Promise<SetupResult> {
68
71
  const { config: userConfig, events = new AsyncEventEmitter<KubbEvents>() } = options
69
72
 
70
- const sources: Map<FabricFile.Path, string> = new Map<FabricFile.Path, string>()
73
+ const sources: Map<KubbFile.Path, string> = new Map<KubbFile.Path, string>()
71
74
  const diagnosticInfo = getDiagnosticInfo()
72
75
 
73
76
  if (Array.isArray(userConfig.input)) {
@@ -115,9 +118,15 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
115
118
  }
116
119
  }
117
120
 
118
- const definedConfig: Config = {
121
+ if (!userConfig.adapter) {
122
+ throw new Error('Adapter should be defined')
123
+ }
124
+
125
+ const config: Config = {
119
126
  root: userConfig.root || process.cwd(),
120
127
  ...userConfig,
128
+ parsers: userConfig.parsers ?? [],
129
+ adapter: userConfig.adapter,
121
130
  output: {
122
131
  write: true,
123
132
  barrelType: 'named',
@@ -138,19 +147,35 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
138
147
  // storage or fall back to fsStorage (backwards-compatible default).
139
148
  // Keys are root-relative (e.g. `src/gen/api/getPets.ts`) so fsStorage()
140
149
  // needs no configuration — it resolves them against process.cwd().
141
- const storage: Storage | null = definedConfig.output.write === false ? null : (definedConfig.output.storage ?? fsStorage())
150
+ const storage: Storage | null = config.output.write === false ? null : (config.output.storage ?? fsStorage())
142
151
 
143
- if (definedConfig.output.clean) {
152
+ if (config.output.clean) {
144
153
  await events.emit('debug', {
145
154
  date: new Date(),
146
- logs: ['Cleaning output directories', ` • Output: ${definedConfig.output.path}`],
155
+ logs: ['Cleaning output directories', ` • Output: ${config.output.path}`],
147
156
  })
148
- await storage?.clear(resolve(definedConfig.root, definedConfig.output.path))
157
+ await storage?.clear(resolve(config.root, config.output.path))
149
158
  }
150
159
 
151
160
  const fabric = createFabric()
152
161
  fabric.use(fsPlugin)
153
- fabric.use(typescriptParser)
162
+
163
+ for (const parser of config.parsers) {
164
+ fabric.use(parser)
165
+ }
166
+ // Catch-all fallback: joins all source values for any unhandled extension
167
+ fabric.use(
168
+ defineParser({
169
+ name: 'fallback',
170
+ extNames: undefined,
171
+ parse(file) {
172
+ return file.sources
173
+ .map((item) => item.value)
174
+ .filter((value): value is string => value != null)
175
+ .join('\n\n')
176
+ },
177
+ }),
178
+ )
154
179
 
155
180
  fabric.context.on('files:processing:start', (files) => {
156
181
  events.emit('files:processing:start', files)
@@ -164,13 +189,13 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
164
189
  const { file, source } = params
165
190
  await events.emit('file:processing:update', {
166
191
  ...params,
167
- config: definedConfig,
192
+ config: config,
168
193
  source,
169
194
  })
170
195
 
171
196
  if (source) {
172
197
  // Key is root-relative so it's meaningful for any backend (fs, S3, Redis…)
173
- const key = relative(resolve(definedConfig.root), file.path)
198
+ const key = relative(resolve(config.root), file.path)
174
199
  await storage?.setItem(key, source)
175
200
  sources.set(file.path, source)
176
201
  }
@@ -186,45 +211,45 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
186
211
 
187
212
  await events.emit('debug', {
188
213
  date: new Date(),
189
- logs: [
190
- '✓ Fabric initialized',
191
- ` • Storage: ${storage ? storage.name : 'disabled (dry-run)'}`,
192
- ` • Barrel type: ${definedConfig.output.barrelType || 'none'}`,
193
- ],
214
+ logs: ['✓ Fabric initialized', ` • Storage: ${storage ? storage.name : 'disabled (dry-run)'}`, ` • Barrel type: ${config.output.barrelType || 'none'}`],
194
215
  })
195
216
 
196
- const pluginDriver = new PluginDriver(definedConfig, {
217
+ const driver = new PluginDriver(config, {
197
218
  fabric,
198
219
  events,
199
220
  concurrency: DEFAULT_CONCURRENCY,
200
221
  })
201
222
 
202
- // Run the adapter (if provided) to produce the universal RootNode
203
- if (definedConfig.adapter) {
204
- const source = inputToAdapterSource(definedConfig)
223
+ // Run the adapter to produce the universal RootNode.
205
224
 
206
- await events.emit('debug', {
207
- date: new Date(),
208
- logs: [`Running adapter: ${definedConfig.adapter.name}`],
209
- })
225
+ const adapter = config.adapter
226
+ if (!adapter) {
227
+ throw new Error('No adapter configured. Please provide an adapter in your kubb.config.ts.')
228
+ }
229
+ const source = inputToAdapterSource(config)
210
230
 
211
- pluginDriver.adapter = definedConfig.adapter
212
- pluginDriver.rootNode = await definedConfig.adapter.parse(source)
231
+ await events.emit('debug', {
232
+ date: new Date(),
233
+ logs: [`Running adapter: ${adapter.name}`],
234
+ })
213
235
 
214
- await events.emit('debug', {
215
- date: new Date(),
216
- logs: [
217
- `✓ Adapter '${definedConfig.adapter.name}' resolved RootNode`,
218
- ` • Schemas: ${pluginDriver.rootNode.schemas.length}`,
219
- ` • Operations: ${pluginDriver.rootNode.operations.length}`,
220
- ],
221
- })
222
- }
236
+ driver.adapter = adapter
237
+ driver.rootNode = await adapter.parse(source)
238
+
239
+ await events.emit('debug', {
240
+ date: new Date(),
241
+ logs: [
242
+ `✓ Adapter '${adapter.name}' resolved RootNode`,
243
+ ` • Schemas: ${driver.rootNode.schemas.length}`,
244
+ ` • Operations: ${driver.rootNode.operations.length}`,
245
+ ],
246
+ })
223
247
 
224
248
  return {
249
+ config,
225
250
  events,
226
251
  fabric,
227
- driver: pluginDriver,
252
+ driver,
228
253
  sources,
229
254
  }
230
255
  }
@@ -266,7 +291,7 @@ export async function build(options: BuildOptions, overrides?: SetupResult): Pro
266
291
  * - Each hook accepts a single handler **or an array** — all entries are called in sequence.
267
292
  * - Nodes that are excluded by `exclude`/`include` plugin options are skipped automatically.
268
293
  * - Return values are handled via `applyHookResult`: React elements are rendered,
269
- * `FabricFile.File[]` are written via upsert, and `void` is a no-op (manual handling).
294
+ * `KubbFile.File[]` are written via upsert, and `void` is a no-op (manual handling).
270
295
  * - Barrel files are generated automatically when `output.barrelType` is set.
271
296
  */
272
297
  async function runPluginAstHooks(plugin: Plugin, context: PluginContext): Promise<void> {
@@ -422,7 +447,7 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
422
447
  existingBarrel?.exports?.flatMap((e) => (Array.isArray(e.name) ? e.name : [e.name])).filter((n): n is string => Boolean(n)) ?? [],
423
448
  )
424
449
 
425
- const rootFile: FabricFile.File = {
450
+ const rootFile: KubbFile.File = {
426
451
  path: rootPath,
427
452
  baseName: BARREL_FILENAME,
428
453
  exports: buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }),
@@ -473,14 +498,14 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
473
498
  }
474
499
 
475
500
  type BuildBarrelExportsParams = {
476
- barrelFiles: FabricFile.ResolvedFile[]
501
+ barrelFiles: KubbFile.ResolvedFile[]
477
502
  rootDir: string
478
503
  existingExports: Set<string>
479
504
  config: Config
480
505
  driver: PluginDriver
481
506
  }
482
507
 
483
- function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }: BuildBarrelExportsParams): FabricFile.Export[] {
508
+ function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, driver }: BuildBarrelExportsParams): KubbFile.Export[] {
484
509
  const pluginNameMap = new Map<string, Plugin>()
485
510
  for (const plugin of driver.plugins.values()) {
486
511
  pluginNameMap.set(plugin.name, plugin)
@@ -512,7 +537,7 @@ function buildBarrelExports({ barrelFiles, rootDir, existingExports, config, dri
512
537
  name: exportName,
513
538
  path: getRelativePath(rootDir, file.path),
514
539
  isTypeOnly: config.output.barrelType === 'all' ? containsOnlyTypes : source.isTypeOnly,
515
- } satisfies FabricFile.Export,
540
+ } satisfies KubbFile.Export,
516
541
  ]
517
542
  })
518
543
  })
package/src/constants.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { FabricFile } from '@kubb/fabric-core/types'
1
+ import type * as KubbFile from './KubbFile.ts'
2
2
 
3
3
  /**
4
4
  * Base URL for the Kubb Studio web app.
@@ -23,7 +23,7 @@ export const DEFAULT_BANNER = 'simple' as const
23
23
  /**
24
24
  * Default file-extension mapping used when no explicit mapping is configured.
25
25
  */
26
- export const DEFAULT_EXTENSION: Record<FabricFile.Extname, FabricFile.Extname | ''> = { '.ts': '.ts' }
26
+ export const DEFAULT_EXTENSION: Record<KubbFile.Extname, KubbFile.Extname | ''> = { '.ts': '.ts' }
27
27
 
28
28
  /**
29
29
  * Characters recognized as path separators on both POSIX and Windows.
@@ -1,5 +1,5 @@
1
1
  import type { PossiblePromise } from '@internals/utils'
2
- import type { InputPath, UserConfig } from './types.ts'
2
+ import type { UserConfig } from './types.ts'
3
3
 
4
4
  /**
5
5
  * CLI options derived from command-line flags.
@@ -42,16 +42,10 @@ export type ConfigInput = PossiblePromise<UserConfig | UserConfig[]> | ((cli: CL
42
42
  * root: 'src',
43
43
  * plugins: [myPlugin()],
44
44
  * }))
45
+ * @deprecated as of Kubb v5, @kubb/core will not expose `defineConfig` anymore. use the `kubb` package instead
45
46
  */
46
47
  export function defineConfig(config: (cli: CLIOptions) => PossiblePromise<UserConfig | UserConfig[]>): typeof config
47
48
  export function defineConfig(config: PossiblePromise<UserConfig | UserConfig[]>): typeof config
48
49
  export function defineConfig(config: ConfigInput): ConfigInput {
49
50
  return config
50
51
  }
51
-
52
- /**
53
- * Type guard to check if a given config has an `input.path`.
54
- */
55
- export function isInputPath(config: UserConfig | undefined): config is UserConfig<InputPath> {
56
- return typeof config?.input === 'object' && config.input !== null && 'path' in config.input
57
- }
@@ -1,7 +1,7 @@
1
1
  import type { PossiblePromise } from '@internals/utils'
2
2
  import type { OperationNode, SchemaNode } from '@kubb/ast/types'
3
- import type { FabricFile } from '@kubb/fabric-core/types'
4
3
  import type { FabricReactNode } from '@kubb/react-fabric/types'
4
+ import type * as KubbFile from './KubbFile.ts'
5
5
  import { applyHookResult } from './renderNode.tsx'
6
6
  import type { GeneratorContext, PluginFactoryOptions } from './types.ts'
7
7
 
@@ -13,7 +13,7 @@ export type { GeneratorContext } from './types.ts'
13
13
  * giving full access to `this.config`, `this.resolver`, `this.adapter`, `this.fabric`,
14
14
  * `this.driver`, etc.
15
15
  *
16
- * Return a React element, an array of `FabricFile.File`, or `void` to handle file
16
+ * Return a React element, an array of `KubbFile.File`, or `void` to handle file
17
17
  * writing manually via `this.upsertFile`. Both React and core (non-React) generators
18
18
  * use the same method signatures — the return type determines how output is handled.
19
19
  *
@@ -43,7 +43,7 @@ export type Generator<TOptions extends PluginFactoryOptions = PluginFactoryOptio
43
43
  this: GeneratorContext<TOptions>,
44
44
  node: SchemaNode,
45
45
  options: TOptions['resolvedOptions'],
46
- ) => PossiblePromise<FabricReactNode | Array<FabricFile.File> | void>
46
+ ) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
47
47
  /**
48
48
  * Called for each operation node in the AST walk.
49
49
  * `this` is the parent plugin's context with `adapter` and `rootNode` guaranteed present.
@@ -52,7 +52,7 @@ export type Generator<TOptions extends PluginFactoryOptions = PluginFactoryOptio
52
52
  this: GeneratorContext<TOptions>,
53
53
  node: OperationNode,
54
54
  options: TOptions['resolvedOptions'],
55
- ) => PossiblePromise<FabricReactNode | Array<FabricFile.File> | void>
55
+ ) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
56
56
  /**
57
57
  * Called once after all operations have been walked.
58
58
  * `this` is the parent plugin's context with `adapter` and `rootNode` guaranteed present.
@@ -61,7 +61,7 @@ export type Generator<TOptions extends PluginFactoryOptions = PluginFactoryOptio
61
61
  this: GeneratorContext<TOptions>,
62
62
  nodes: Array<OperationNode>,
63
63
  options: TOptions['resolvedOptions'],
64
- ) => PossiblePromise<FabricReactNode | Array<FabricFile.File> | void>
64
+ ) => PossiblePromise<FabricReactNode | Array<KubbFile.File> | void>
65
65
  }
66
66
 
67
67
  /**
@@ -0,0 +1,57 @@
1
+ import type * as KubbFile from './KubbFile.ts'
2
+
3
+ type PrintOptions = {
4
+ extname?: KubbFile.Extname
5
+ }
6
+
7
+ export type Parser<TMeta extends object = any> = {
8
+ name: string
9
+ type: 'parser'
10
+ /**
11
+ * File extensions this parser handles.
12
+ * Use `undefined` to create a catch-all fallback parser.
13
+ *
14
+ * @example ['.ts', '.js']
15
+ */
16
+ extNames: Array<KubbFile.Extname> | undefined
17
+ /**
18
+ * @deprecated Will be removed once Fabric no longer requires it.
19
+ * @default () => {}
20
+ */
21
+ install(...args: unknown[]): void | Promise<void>
22
+ /**
23
+ * Convert a resolved file to a string.
24
+ */
25
+ parse(file: KubbFile.ResolvedFile<TMeta>, options?: PrintOptions): Promise<string> | string
26
+ }
27
+
28
+ export type UserParser<TMeta extends object = any> = Omit<Parser<TMeta>, 'type' | 'install'> & {
29
+ install?(...args: unknown[]): void | Promise<void>
30
+ }
31
+
32
+ /**
33
+ * Defines a parser with type safety.
34
+ *
35
+ * Use this function to create parsers that transform generated files to strings
36
+ * based on their extension.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * import { defineParser } from '@kubb/core'
41
+ *
42
+ * export const jsonParser = defineParser({
43
+ * name: 'json',
44
+ * extNames: ['.json'],
45
+ * parse(file) {
46
+ * return file.sources.map((s) => s.value).join('\n')
47
+ * },
48
+ * })
49
+ * ```
50
+ */
51
+ export function defineParser<TMeta extends object = any>(parser: UserParser<TMeta>): Parser<TMeta> {
52
+ return {
53
+ install() {},
54
+ type: 'parser',
55
+ ...parser,
56
+ }
57
+ }