@kubb/core 4.5.0 → 4.5.2

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 (66) hide show
  1. package/dist/EventEmitter-3-rxpjGN.cjs +32 -0
  2. package/dist/EventEmitter-3-rxpjGN.cjs.map +1 -0
  3. package/dist/EventEmitter-IlDflnd2.js +25 -0
  4. package/dist/EventEmitter-IlDflnd2.js.map +1 -0
  5. package/dist/getBarrelFiles-B9LswRVo.d.cts +37 -0
  6. package/dist/getBarrelFiles-CB-XIF32.d.ts +37 -0
  7. package/dist/getBarrelFiles-D7p4n7Ug.js +962 -0
  8. package/dist/getBarrelFiles-D7p4n7Ug.js.map +1 -0
  9. package/dist/getBarrelFiles-o9ETjpTV.cjs +1017 -0
  10. package/dist/getBarrelFiles-o9ETjpTV.cjs.map +1 -0
  11. package/dist/hooks.d.cts +1 -2
  12. package/dist/hooks.d.ts +2 -3
  13. package/dist/index.cjs +83 -953
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +45 -62
  16. package/dist/index.d.ts +46 -63
  17. package/dist/index.js +51 -921
  18. package/dist/index.js.map +1 -1
  19. package/dist/{logger-Bxe022ug.js → logger-BGuor9Uu.js} +5 -26
  20. package/dist/logger-BGuor9Uu.js.map +1 -0
  21. package/dist/{logger-BIzTtBYJ.cjs → logger-CLbtdL9m.cjs} +4 -32
  22. package/dist/logger-CLbtdL9m.cjs.map +1 -0
  23. package/dist/{logger-BwhJWK-H.d.ts → logger-weazBKCW.d.ts} +1 -1
  24. package/dist/logger.cjs +2 -1
  25. package/dist/logger.d.ts +1 -1
  26. package/dist/logger.js +2 -1
  27. package/dist/{prompt-D5DZPtWc.cjs → prompt-39QFDCh6.cjs} +1 -1
  28. package/dist/{prompt-D5DZPtWc.cjs.map → prompt-39QFDCh6.cjs.map} +1 -1
  29. package/dist/{prompt-xM0onfy8.js → prompt-CIYhgpSM.js} +1 -1
  30. package/dist/{prompt-xM0onfy8.js.map → prompt-CIYhgpSM.js.map} +1 -1
  31. package/dist/{transformers-CeNW0G32.js → transformers-BaV4FwQd.js} +1 -1
  32. package/dist/{transformers-CeNW0G32.js.map → transformers-BaV4FwQd.js.map} +1 -1
  33. package/dist/{transformers-DWLXDYKb.cjs → transformers-BpnIvSiH.cjs} +1 -1
  34. package/dist/{transformers-DWLXDYKb.cjs.map → transformers-BpnIvSiH.cjs.map} +1 -1
  35. package/dist/transformers.cjs +1 -1
  36. package/dist/transformers.js +1 -1
  37. package/dist/{types-CyDeSlGF.d.ts → types-CqYAL0CK.d.ts} +29 -38
  38. package/dist/{types-CVONMhN_.d.cts → types-DqHtLxpp.d.cts} +28 -37
  39. package/dist/utils.cjs +7 -5
  40. package/dist/utils.cjs.map +1 -1
  41. package/dist/utils.d.cts +4 -2
  42. package/dist/utils.d.ts +4 -2
  43. package/dist/utils.js +4 -3
  44. package/dist/utils.js.map +1 -1
  45. package/package.json +4 -4
  46. package/src/BarrelManager.ts +1 -1
  47. package/src/PluginManager.ts +74 -76
  48. package/src/build.ts +24 -13
  49. package/src/config.ts +35 -29
  50. package/src/definePlugin.ts +12 -0
  51. package/src/index.ts +5 -5
  52. package/src/types.ts +19 -40
  53. package/src/utils/AsyncEventEmitter.ts +45 -0
  54. package/src/utils/TreeNode.ts +1 -1
  55. package/src/utils/__snapshots__/barrel.json +147 -0
  56. package/src/{FileManager.ts → utils/getBarrelFiles.ts} +4 -11
  57. package/src/utils/index.ts +1 -0
  58. package/dist/URLPath-DbWtfVa1.js +0 -116
  59. package/dist/URLPath-DbWtfVa1.js.map +0 -1
  60. package/dist/URLPath-Dir2mxRT.cjs +0 -133
  61. package/dist/URLPath-Dir2mxRT.cjs.map +0 -1
  62. package/dist/logger-BIzTtBYJ.cjs.map +0 -1
  63. package/dist/logger-Bxe022ug.js.map +0 -1
  64. package/dist/types-DCR_QgGt.d.ts +0 -5
  65. package/dist/types-DueAg3XP.d.cts +0 -5
  66. package/src/plugin.ts +0 -80
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "4.5.0",
3
+ "version": "4.5.2",
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",
@@ -83,7 +83,7 @@
83
83
  }
84
84
  ],
85
85
  "dependencies": {
86
- "@kubb/react-fabric": "0.2.14",
86
+ "@kubb/react-fabric": "0.2.19",
87
87
  "camelcase": "^8.0.0",
88
88
  "find-up": "^7.0.0",
89
89
  "fs-extra": "^11.3.2",
@@ -106,10 +106,10 @@
106
106
  "zod": "^4.1.12"
107
107
  },
108
108
  "optionalDependencies": {
109
- "@kubb/fabric-core": "0.2.14"
109
+ "@kubb/fabric-core": "0.2.19"
110
110
  },
111
111
  "peerDependencies": {
112
- "@kubb/react-fabric": "0.2.14"
112
+ "@kubb/react-fabric": "0.2.19"
113
113
  },
114
114
  "engines": {
115
115
  "node": ">=20"
@@ -1,9 +1,9 @@
1
1
  /** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */
2
2
  import { join } from 'node:path'
3
3
  import type { KubbFile } from '@kubb/fabric-core/types'
4
- import type { FileMetaBase } from './FileManager.ts'
5
4
  import { getRelativePath } from './fs/index.ts'
6
5
  import type { Logger } from './logger.ts'
6
+ import type { FileMetaBase } from './utils/getBarrelFiles.ts'
7
7
  import { TreeNode } from './utils/TreeNode.ts'
8
8
 
9
9
  type BarrelManagerOptions = {
@@ -1,16 +1,16 @@
1
+ import path from 'node:path'
1
2
  import type { KubbFile } from '@kubb/fabric-core/types'
2
3
  import type { Fabric } from '@kubb/react-fabric'
3
4
  import { ValidationPluginError } from './errors.ts'
4
5
  import type { Logger } from './logger.ts'
5
6
  import { isPromiseRejectedResult, PromiseManager } from './PromiseManager.ts'
6
- import type { PluginCore } from './plugin.ts'
7
- import { pluginCore } from './plugin.ts'
8
7
  import { transformReservedWord } from './transformers/transformReservedWord.ts'
9
8
  import { trim } from './transformers/trim.ts'
10
9
  import type {
11
10
  Config,
12
11
  GetPluginFactoryOptions,
13
12
  Plugin,
13
+ PluginContext,
14
14
  PluginFactoryOptions,
15
15
  PluginLifecycle,
16
16
  PluginLifecycleHooks,
@@ -19,7 +19,6 @@ import type {
19
19
  ResolveNameParams,
20
20
  ResolvePathParams,
21
21
  UserPlugin,
22
- UserPluginWithLifeCycle,
23
22
  } from './types.ts'
24
23
  import { EventEmitter } from './utils/EventEmitter.ts'
25
24
  import { setUniqueName } from './utils/uniqueName.ts'
@@ -69,8 +68,14 @@ type GetFileProps<TOptions = object> = {
69
68
  options?: TOptions
70
69
  }
71
70
 
71
+ export function getMode(fileOrFolder: string | undefined | null): KubbFile.Mode {
72
+ if (!fileOrFolder) {
73
+ return 'split'
74
+ }
75
+ return path.extname(fileOrFolder) ? 'single' : 'split'
76
+ }
77
+
72
78
  export class PluginManager {
73
- readonly plugins = new Set<Plugin<GetPluginFactoryOptions<any>>>()
74
79
  readonly events: EventEmitter<Events> = new EventEmitter()
75
80
 
76
81
  readonly config: Config
@@ -78,8 +83,8 @@ export class PluginManager {
78
83
  readonly executed: Array<Executer> = []
79
84
  readonly logger: Logger
80
85
  readonly options: Options
81
- readonly #core: Plugin<PluginCore>
82
86
 
87
+ readonly #plugins = new Set<Plugin<GetPluginFactoryOptions<any>>>()
83
88
  readonly #usedPluginNames: Record<string, number> = {}
84
89
  readonly #promiseManager: PromiseManager
85
90
 
@@ -91,27 +96,51 @@ export class PluginManager {
91
96
  nullCheck: (state: SafeParseResult<'resolveName'> | null) => !!state?.result,
92
97
  })
93
98
 
94
- const core = pluginCore({
95
- fabric: options.fabric,
96
- config,
97
- logger: this.logger,
98
- pluginManager: this,
99
- resolvePath: this.resolvePath.bind(this),
100
- resolveName: this.resolveName.bind(this),
101
- getPlugins: this.#getSortedPlugins.bind(this),
102
- })
99
+ ;[...(config.plugins || [])].forEach((plugin) => {
100
+ const parsedPlugin = this.#parse(plugin as UserPlugin)
103
101
 
104
- // call core.context.call with empty context so we can transform `context()` to `context: {}`
105
- this.#core = this.#parse(core as unknown as UserPlugin, this as any, core.context.call(null as any)) as Plugin<PluginCore>
106
- ;[this.#core, ...(config.plugins || [])].forEach((plugin) => {
107
- const parsedPlugin = this.#parse(plugin as UserPlugin, this, this.#core.context)
108
-
109
- this.plugins.add(parsedPlugin)
102
+ this.#plugins.add(parsedPlugin)
110
103
  })
111
104
 
112
105
  return this
113
106
  }
114
107
 
108
+ getContext<TOptions extends PluginFactoryOptions>(plugin: Plugin<TOptions>): PluginContext<TOptions> & Record<string, any> {
109
+ const plugins = [...this.#plugins]
110
+ const baseContext = {
111
+ fabric: this.options.fabric,
112
+ config: this.config,
113
+ plugin,
114
+ logger: this.options.logger,
115
+ pluginManager: this,
116
+ mode: getMode(path.resolve(this.config.root, this.config.output.path)),
117
+ addFile: async (...files: Array<KubbFile.File>) => {
118
+ await this.options.fabric.addFile(...files)
119
+ },
120
+ } as unknown as PluginContext<TOptions>
121
+
122
+ let mergedExtras: Record<string, any> = {}
123
+ for (const p of plugins) {
124
+ if (typeof p.inject === 'function') {
125
+ const injector = p.inject.bind(baseContext as any) as any
126
+
127
+ const result = injector(baseContext)
128
+ if (result && typeof result === 'object') {
129
+ mergedExtras = { ...mergedExtras, ...result }
130
+ }
131
+ }
132
+ }
133
+
134
+ return {
135
+ ...baseContext,
136
+ ...mergedExtras,
137
+ }
138
+ }
139
+
140
+ get plugins(): Array<Plugin> {
141
+ return this.#getSortedPlugins()
142
+ }
143
+
115
144
  getFile<TOptions = object>({ name, mode, extname, pluginKey, options }: GetFileProps<TOptions>): KubbFile.File<{ pluginKey: Plugin['key'] }> {
116
145
  const baseName = `${name}${extname}` as const
117
146
  const path = this.resolvePath({ baseName, mode, pluginKey, options })
@@ -130,7 +159,10 @@ export class PluginManager {
130
159
  }
131
160
  }
132
161
 
133
- resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): KubbFile.OptionalPath => {
162
+ resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): KubbFile.Path => {
163
+ const root = path.resolve(this.config.root, this.config.output.path)
164
+ const defaultPath = path.resolve(root, params.baseName)
165
+
134
166
  if (params.pluginKey) {
135
167
  const paths = this.hookForPluginSync({
136
168
  pluginKey: params.pluginKey,
@@ -150,13 +182,16 @@ export class PluginManager {
150
182
  })
151
183
  }
152
184
 
153
- return paths?.at(0)
185
+ return paths?.at(0) || defaultPath
154
186
  }
155
- return this.hookFirstSync({
187
+
188
+ const firstResult = this.hookFirstSync({
156
189
  hookName: 'resolvePath',
157
190
  parameters: [params.baseName, params.mode, params.options as object],
158
191
  message: `Resolving path '${params.baseName}'`,
159
- }).result
192
+ })
193
+
194
+ return firstResult?.result || defaultPath
160
195
  }
161
196
  //TODO refactor by using the order of plugins and the cache of the fileManager instead of guessing and recreating the name/path
162
197
  resolveName = (params: ResolveNameParams): string => {
@@ -423,8 +458,8 @@ export class PluginManager {
423
458
  this.logger.emit('progress_stop', { id: hookName })
424
459
  }
425
460
 
426
- #getSortedPlugins(hookName?: keyof PluginLifecycle): Plugin[] {
427
- const plugins = [...this.plugins].filter((plugin) => plugin.name !== 'core')
461
+ #getSortedPlugins(hookName?: keyof PluginLifecycle): Array<Plugin> {
462
+ const plugins = [...this.#plugins]
428
463
 
429
464
  if (hookName) {
430
465
  return plugins.filter((plugin) => hookName in plugin)
@@ -434,10 +469,10 @@ export class PluginManager {
434
469
  return plugins
435
470
  .map((plugin) => {
436
471
  if (plugin.pre) {
437
- const isValid = plugin.pre.every((pluginName) => plugins.find((pluginToFind) => pluginToFind.name === pluginName))
472
+ const missingPlugins = plugin.pre.filter((pluginName) => !plugins.find((pluginToFind) => pluginToFind.name === pluginName))
438
473
 
439
- if (!isValid) {
440
- throw new ValidationPluginError(`This plugin has a pre set that is not valid(${JSON.stringify(plugin.pre, undefined, 2)})`)
474
+ if (missingPlugins.length > 0) {
475
+ throw new ValidationPluginError(`The plugin '${plugin.name}' has a pre set that references missing plugins for '${missingPlugins.join(', ')}'`)
441
476
  }
442
477
  }
443
478
 
@@ -455,7 +490,7 @@ export class PluginManager {
455
490
  }
456
491
 
457
492
  getPluginByKey(pluginKey: Plugin['key']): Plugin | undefined {
458
- const plugins = [...this.plugins]
493
+ const plugins = [...this.#plugins]
459
494
  const [searchPluginName] = pluginKey
460
495
 
461
496
  return plugins.find((item) => {
@@ -547,7 +582,8 @@ export class PluginManager {
547
582
  const task = (async () => {
548
583
  try {
549
584
  if (typeof hook === 'function') {
550
- const result = await Promise.resolve((hook as Function).apply({ ...this.#core.context, plugin }, parameters))
585
+ const context = this.getContext(plugin)
586
+ const result = await Promise.resolve((hook as Function).apply(context, parameters))
551
587
 
552
588
  output = result
553
589
 
@@ -615,7 +651,8 @@ export class PluginManager {
615
651
 
616
652
  try {
617
653
  if (typeof hook === 'function') {
618
- const fn = (hook as Function).apply({ ...this.#core.context, plugin }, parameters) as ReturnType<ParseResult<H>>
654
+ const context = this.getContext(plugin)
655
+ const fn = (hook as Function).apply(context, parameters) as ReturnType<ParseResult<H>>
619
656
 
620
657
  output = fn
621
658
 
@@ -657,54 +694,15 @@ export class PluginManager {
657
694
  this.events.emit('error', cause)
658
695
  }
659
696
 
660
- #parse<TPlugin extends UserPluginWithLifeCycle>(
661
- plugin: TPlugin,
662
- pluginManager: PluginManager,
663
- context: PluginCore['context'] | undefined,
664
- ): Plugin<GetPluginFactoryOptions<TPlugin>> {
665
- const usedPluginNames = pluginManager.#usedPluginNames
697
+ #parse(plugin: UserPlugin): Plugin {
698
+ const usedPluginNames = this.#usedPluginNames
666
699
 
667
700
  setUniqueName(plugin.name, usedPluginNames)
668
701
 
669
- const key = [plugin.name, usedPluginNames[plugin.name]].filter(Boolean) as [typeof plugin.name, string]
670
-
671
- if (plugin.context && typeof plugin.context === 'function') {
672
- return {
673
- ...plugin,
674
- key,
675
- context: (plugin.context as Function).call(context) as typeof plugin.context,
676
- } as unknown as Plugin<GetPluginFactoryOptions<TPlugin>>
677
- }
678
-
679
702
  return {
703
+ install() {},
680
704
  ...plugin,
681
- key,
682
- } as unknown as Plugin<GetPluginFactoryOptions<TPlugin>>
683
- }
684
-
685
- static getDependedPlugins<
686
- T1 extends PluginFactoryOptions,
687
- T2 extends PluginFactoryOptions = never,
688
- T3 extends PluginFactoryOptions = never,
689
- TOutput = T3 extends never ? (T2 extends never ? [T1: Plugin<T1>] : [T1: Plugin<T1>, T2: Plugin<T2>]) : [T1: Plugin<T1>, T2: Plugin<T2>, T3: Plugin<T3>],
690
- >(plugins: Array<Plugin>, dependedPluginNames: string | string[]): TOutput {
691
- let pluginNames: string[] = []
692
- if (typeof dependedPluginNames === 'string') {
693
- pluginNames = [dependedPluginNames]
694
- } else {
695
- pluginNames = dependedPluginNames
696
- }
697
-
698
- return pluginNames.map((pluginName) => {
699
- const plugin = plugins.find((plugin) => plugin.name === pluginName)
700
- if (!plugin) {
701
- throw new ValidationPluginError(`This plugin depends on the ${pluginName} plugin.`)
702
- }
703
- return plugin
704
- }) as TOutput
705
- }
706
-
707
- static get hooks() {
708
- return ['buildStart', 'resolvePath', 'resolveName', 'buildEnd'] as const
705
+ key: [plugin.name, usedPluginNames[plugin.name]].filter(Boolean) as [typeof plugin.name, string],
706
+ } as unknown as Plugin
709
707
  }
710
708
  }
package/src/build.ts CHANGED
@@ -11,7 +11,7 @@ import { clean, exists, getRelativePath, write } from './fs/index.ts'
11
11
  import type { Logger } from './logger.ts'
12
12
  import { createLogger } from './logger.ts'
13
13
  import { PluginManager } from './PluginManager.ts'
14
- import type { Config, Output, UserConfig } from './types.ts'
14
+ import type { Config, Output, Plugin, UserConfig } from './types.ts'
15
15
  import { URLPath } from './utils/URLPath.ts'
16
16
 
17
17
  type BuildOptions = {
@@ -23,11 +23,14 @@ type BuildOptions = {
23
23
  }
24
24
 
25
25
  type BuildOutput = {
26
+ failedPlugins: Set<{ plugin: Plugin; error: Error }>
26
27
  fabric: Fabric
27
28
  files: Array<KubbFile.ResolvedFile>
28
29
  pluginManager: PluginManager
30
+ // TODO check if we can remove error
29
31
  /**
30
- * Only for safeBuild
32
+ * Only for safeBuild,
33
+ * @deprecated
31
34
  */
32
35
  error?: Error
33
36
  }
@@ -92,13 +95,14 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
92
95
  }
93
96
 
94
97
  export async function build(options: BuildOptions, overrides?: SetupResult): Promise<BuildOutput> {
95
- const { fabric, files, pluginManager, error } = await safeBuild(options, overrides)
98
+ const { fabric, files, pluginManager, failedPlugins, error } = await safeBuild(options, overrides)
96
99
 
97
100
  if (error) {
98
101
  throw error
99
102
  }
100
103
 
101
104
  return {
105
+ failedPlugins,
102
106
  fabric,
103
107
  files,
104
108
  pluginManager,
@@ -109,14 +113,21 @@ export async function build(options: BuildOptions, overrides?: SetupResult): Pro
109
113
  export async function safeBuild(options: BuildOptions, overrides?: SetupResult): Promise<BuildOutput> {
110
114
  const { fabric, pluginManager } = overrides ? overrides : await setup(options)
111
115
 
116
+ const failedPlugins = new Set<{ plugin: Plugin; error: Error }>()
112
117
  const config = pluginManager.config
113
118
 
114
119
  try {
115
- await pluginManager.hookParallel({
116
- hookName: 'buildStart',
117
- parameters: [config],
118
- message: 'buildStart',
119
- })
120
+ for (const plugin of pluginManager.plugins) {
121
+ const context = pluginManager.getContext(plugin)
122
+
123
+ const installer = plugin.install.bind(context)
124
+
125
+ try {
126
+ await installer(context)
127
+ } catch (e) {
128
+ failedPlugins.add({ plugin, error: e as Error })
129
+ }
130
+ }
120
131
 
121
132
  if (config.output.barrelType) {
122
133
  const root = resolve(config.root)
@@ -166,11 +177,11 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
166
177
  await fabric.addFile(rootFile)
167
178
  }
168
179
 
169
- fabric.context.events.on('process:start', ({ files }) => {
180
+ fabric.context.on('process:start', ({ files }) => {
170
181
  pluginManager.logger.emit('progress_start', { id: 'files', size: files.length, message: 'Writing files ...' })
171
182
  })
172
183
 
173
- fabric.context.events.on('process:progress', async ({ file, source }) => {
184
+ fabric.context.on('process:progress', async ({ file, source }) => {
174
185
  const message = file ? `Writing ${relative(config.root, file.path)}` : ''
175
186
  pluginManager.logger.emit('progressed', { id: 'files', message })
176
187
 
@@ -179,22 +190,22 @@ export async function safeBuild(options: BuildOptions, overrides?: SetupResult):
179
190
  }
180
191
  })
181
192
 
182
- fabric.context.events.on('process:end', () => {
193
+ fabric.context.on('process:end', () => {
183
194
  pluginManager.logger.emit('progress_stop', { id: 'files' })
184
195
  })
185
196
  const files = [...fabric.files]
186
197
 
187
198
  await fabric.write({ extension: config.output.extension })
188
199
 
189
- await pluginManager.hookParallel({ hookName: 'buildEnd', message: `Build stopped for ${config.name}` })
190
-
191
200
  return {
201
+ failedPlugins,
192
202
  fabric,
193
203
  files,
194
204
  pluginManager,
195
205
  }
196
206
  } catch (e) {
197
207
  return {
208
+ failedPlugins,
198
209
  fabric,
199
210
  files: [],
200
211
  pluginManager,
package/src/config.ts CHANGED
@@ -1,47 +1,53 @@
1
1
  import type { InputPath, UserConfig } from './types.ts'
2
2
  import type { PossiblePromise } from './utils/types.ts'
3
3
 
4
- type Args = {
5
- /**
6
- * Path to `kubb.config.js`
7
- */
4
+ /**
5
+ * CLI options derived from command-line flags.
6
+ */
7
+ export type CLIOptions = {
8
+ /** Path to `kubb.config.js` */
8
9
  config?: string
9
- /**
10
- * Watch changes on input
11
- */
10
+
11
+ /** Enable watch mode for input files */
12
12
  watch?: boolean
13
13
 
14
14
  /**
15
- * Log level to report when using the CLI
15
+ * Logging verbosity for CLI usage.
16
16
  *
17
- * `silent` will hide all information that is not relevant
18
- *
19
- * `info` will show all information possible(not related to the PluginManager)
20
- *
21
- * `debug` will show all information possible(related to the PluginManager), handy for seeing logs
22
- * @default `silent`
23
- */
24
- logLevel?: string
25
- /**
26
- * Run Kubb with Bun
17
+ * - `silent`: hide non-essential logs
18
+ * - `info`: show general logs (non-plugin-related)
19
+ * - `debug`: include detailed plugin lifecycle logs
20
+ * @default 'silent'
27
21
  */
22
+ logLevel?: 'silent' | 'info' | 'debug'
23
+
24
+ /** Run Kubb with Bun */
28
25
  bun?: boolean
29
26
  }
30
27
 
31
28
  /**
32
- * Type helper to make it easier to use vite.config.ts accepts a direct UserConfig object, or a function that returns it. The function receives a ConfigEnv object.
29
+ * Helper for defining a Kubb configuration.
30
+ *
31
+ * Accepts either:
32
+ * - A config object or array of configs
33
+ * - A function returning the config(s), optionally async,
34
+ * receiving the CLI options as argument
35
+ *
36
+ * @example
37
+ * export default defineConfig(({ logLevel }) => ({
38
+ * root: 'src',
39
+ * plugins: [myPlugin()],
40
+ * }))
33
41
  */
34
42
  export function defineConfig(
35
- options:
36
- | PossiblePromise<UserConfig | Array<UserConfig>>
37
- | ((
38
- /** The options derived from the CLI flags */
39
- args: Args,
40
- ) => PossiblePromise<UserConfig | Array<UserConfig>>),
41
- ): typeof options {
42
- return options
43
+ config: PossiblePromise<UserConfig | UserConfig[]> | ((cli: CLIOptions) => PossiblePromise<UserConfig | UserConfig[]>),
44
+ ): typeof config {
45
+ return config
43
46
  }
44
47
 
45
- export function isInputPath(result: UserConfig | undefined): result is UserConfig<InputPath> {
46
- return !!result && 'path' in (result?.input as any)
48
+ /**
49
+ * Type guard to check if a given config has an `input.path`.
50
+ */
51
+ export function isInputPath(config: UserConfig | undefined): config is UserConfig<InputPath> {
52
+ return typeof config?.input === 'object' && config.input !== null && 'path' in config.input
47
53
  }
@@ -0,0 +1,12 @@
1
+ import type { PluginFactoryOptions, UserPluginWithLifeCycle } from './types.ts'
2
+
3
+ type PluginBuilder<T extends PluginFactoryOptions = PluginFactoryOptions> = (options: T['options']) => UserPluginWithLifeCycle<T>
4
+
5
+ /**
6
+ * Wraps a plugin builder to make the options parameter optional.
7
+ */
8
+ export function definePlugin<T extends PluginFactoryOptions = PluginFactoryOptions>(
9
+ build: PluginBuilder<T>,
10
+ ): (options?: T['options']) => UserPluginWithLifeCycle<T> {
11
+ return (options) => build(options ?? ({} as T['options']))
12
+ }
package/src/index.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  export { BaseGenerator } from './BaseGenerator.ts'
2
2
  export { build, build as default, safeBuild, setup } from './build.ts'
3
- export { defineConfig, isInputPath } from './config.ts'
4
- export type { FileMetaBase } from './FileManager.ts'
5
- export { getBarrelFiles, getMode } from './FileManager.ts'
3
+ export { type CLIOptions, defineConfig, isInputPath } from './config.ts'
4
+ export { definePlugin } from './definePlugin.ts'
6
5
  export { PackageManager } from './PackageManager.ts'
7
- export { PluginManager } from './PluginManager.ts'
6
+ export { getMode, PluginManager } from './PluginManager.ts'
8
7
  export { PromiseManager } from './PromiseManager.ts'
9
- export { createPlugin } from './plugin.ts'
10
8
  export type * from './types.ts'
9
+ export type { FileMetaBase } from './utils/getBarrelFiles.ts'
10
+ export { getBarrelFiles } from './utils/getBarrelFiles.ts'
package/src/types.ts CHANGED
@@ -1,9 +1,15 @@
1
1
  import type { KubbFile } from '@kubb/fabric-core/types'
2
- import type { Fabric, FileManager } from '@kubb/react-fabric'
2
+ import type { Fabric } from '@kubb/react-fabric'
3
3
  import type { Logger } from './logger.ts'
4
4
  import type { PluginManager } from './PluginManager.ts'
5
5
  import type { PossiblePromise } from './utils/types.ts'
6
6
 
7
+ declare global {
8
+ namespace Kubb {
9
+ interface PluginContext {}
10
+ }
11
+ }
12
+
7
13
  /**
8
14
  * Config used in `kubb.config.ts`
9
15
  *
@@ -191,13 +197,8 @@ export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOpti
191
197
  * Specifies the succeeding plugins for the current plugin. You can pass an array of succeeding plugin names, and the current plugin will be executed before these plugins.
192
198
  */
193
199
  post?: Array<string>
194
- } & (TOptions['context'] extends never
195
- ? {
196
- context?: never
197
- }
198
- : {
199
- context: (this: TOptions['name'] extends 'core' ? null : Omit<PluginContext<TOptions>, 'addFile'>) => TOptions['context']
200
- })
200
+ inject?: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => TOptions['context']
201
+ }
201
202
 
202
203
  export type UserPluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = UserPlugin<TOptions> & PluginLifecycle<TOptions>
203
204
 
@@ -227,16 +228,13 @@ export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
227
228
  * Options set for a specific plugin(see kubb.config.js), passthrough of options.
228
229
  */
229
230
  options: TOptions['resolvedOptions']
231
+
232
+ install: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => PossiblePromise<void>
230
233
  /**
231
- * Define a context that can be used by other plugins, see `PluginManager' where we convert from `UserPlugin` to `Plugin`(used when calling `createPlugin`).
234
+ * Define a context that can be used by other plugins, see `PluginManager' where we convert from `UserPlugin` to `Plugin`(used when calling `definePlugin`).
232
235
  */
233
- } & (TOptions['context'] extends never
234
- ? {
235
- context?: never
236
- }
237
- : {
238
- context: TOptions['context']
239
- })
236
+ inject: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => TOptions['context']
237
+ }
240
238
 
241
239
  export type PluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = Plugin<TOptions> & PluginLifecycle<TOptions>
242
240
 
@@ -245,19 +243,14 @@ export type PluginLifecycle<TOptions extends PluginFactoryOptions = PluginFactor
245
243
  * Start of the lifecycle of a plugin.
246
244
  * @type hookParallel
247
245
  */
248
- buildStart?: (this: PluginContext<TOptions>, Config: Config) => PossiblePromise<void>
246
+ install?: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => PossiblePromise<void>
249
247
  /**
250
248
  * Resolve to a Path based on a baseName(example: `./Pet.ts`) and directory(example: `./models`).
251
249
  * Options can als be included.
252
250
  * @type hookFirst
253
251
  * @example ('./Pet.ts', './src/gen/') => '/src/gen/Pet.ts'
254
252
  */
255
- resolvePath?: (
256
- this: PluginContext<TOptions>,
257
- baseName: KubbFile.BaseName,
258
- mode?: KubbFile.Mode,
259
- options?: TOptions['resolvePathOptions'],
260
- ) => KubbFile.OptionalPath
253
+ resolvePath?: (this: PluginContext<TOptions>, baseName: KubbFile.BaseName, mode?: KubbFile.Mode, options?: TOptions['resolvePathOptions']) => KubbFile.Path
261
254
  /**
262
255
  * Resolve to a name based on a string.
263
256
  * Useful when converting to PascalCase or camelCase.
@@ -265,11 +258,6 @@ export type PluginLifecycle<TOptions extends PluginFactoryOptions = PluginFactor
265
258
  * @example ('pet') => 'Pet'
266
259
  */
267
260
  resolveName?: (this: PluginContext<TOptions>, name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
268
- /**
269
- * End of the plugin lifecycle.
270
- * @type hookParallel
271
- */
272
- buildEnd?: (this: PluginContext<TOptions>) => PossiblePromise<void>
273
261
  }
274
262
 
275
263
  export type PluginLifecycleHooks = keyof PluginLifecycle
@@ -301,24 +289,15 @@ export type ResolveNameParams = {
301
289
  export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
302
290
  fabric: Fabric
303
291
  config: Config
304
- /**
305
- * @deprecated
306
- */
307
- fileManager: FileManager
308
292
  pluginManager: PluginManager
309
- addFile: (...file: Array<KubbFile.File>) => Promise<Array<KubbFile.ResolvedFile>>
310
- resolvePath: (params: ResolvePathParams<TOptions['resolvePathOptions']>) => KubbFile.OptionalPath
311
- resolveName: (params: ResolveNameParams) => string
293
+ addFile: (...file: Array<KubbFile.File>) => Promise<void>
312
294
  logger: Logger
313
- /**
314
- * All plugins
315
- */
316
- plugins: Plugin[]
295
+ mode: KubbFile.Mode
317
296
  /**
318
297
  * Current plugin
319
298
  */
320
299
  plugin: Plugin<TOptions>
321
- }
300
+ } & Kubb.PluginContext
322
301
  /**
323
302
  * Specify the export location for the files and define the behavior of the output
324
303
  */