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

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.
@@ -1,8 +1,8 @@
1
1
  import { t as __name } from "./chunk--u3MIqq1.js";
2
2
  import { EventEmitter } from "node:events";
3
3
  import { Fabric } from "@kubb/react-fabric";
4
+ import { Printer, PrinterFactoryOptions, RootNode, SchemaNode } from "@kubb/ast/types";
4
5
  import { KubbFile } from "@kubb/fabric-core/types";
5
- import { Printer, PrinterFactoryOptions, RootNode } from "@kubb/ast/types";
6
6
 
7
7
  //#region ../../internals/utils/dist/index.d.ts
8
8
  /**
@@ -226,6 +226,7 @@ declare class PluginManager {
226
226
  * the build pipeline after the adapter's `parse()` resolves.
227
227
  */
228
228
  rootNode: RootNode | undefined;
229
+ adapter: Adapter | undefined;
229
230
  constructor(config: Config, options: Options);
230
231
  get events(): AsyncEventEmitter<KubbEvents>;
231
232
  getContext<TOptions extends PluginFactoryOptions>(plugin: Plugin<TOptions>): PluginContext<TOptions> & Record<string, unknown>;
@@ -617,6 +618,17 @@ type Adapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptions> = {
617
618
  /** Human-readable identifier, e.g. `'oas'`, `'drizzle'`, `'asyncapi'`. */name: TOptions['name']; /** Resolved options (after defaults have been applied). */
618
619
  options: TOptions['resolvedOptions']; /** Convert the raw source into a universal `RootNode`. */
619
620
  parse: (source: AdapterSource) => PossiblePromise<RootNode>;
621
+ /**
622
+ * Extracts `KubbFile.Import` entries needed by a `SchemaNode` tree.
623
+ * Populated after the first `parse()` call. Returns an empty array before that.
624
+ *
625
+ * The `resolve` callback receives the collision-corrected schema name and must
626
+ * return the `{ name, path }` pair for the import, or `undefined` to skip it.
627
+ */
628
+ getImports: (node: SchemaNode, resolve: (schemaName: string) => {
629
+ name: string;
630
+ path: string;
631
+ }) => Array<KubbFile.Import>;
620
632
  };
621
633
  type BarrelType = 'all' | 'named' | 'propagate';
622
634
  type DevtoolsOptions = {
@@ -905,18 +917,26 @@ type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
905
917
  * Current plugin
906
918
  */
907
919
  plugin: Plugin<TOptions>;
908
- /**
909
- * Returns the universal `@kubb/ast` `RootNode` produced by the configured adapter.
910
- * Returns `undefined` when no adapter was set (legacy OAS-only usage).
911
- */
912
- rootNode: RootNode | undefined;
913
920
  /**
914
921
  * Opens the Kubb Studio URL for the current `rootNode` in the default browser.
915
922
  * Falls back to printing the URL if the browser cannot be launched.
916
923
  * No-ops silently when no adapter has set a `rootNode`.
917
924
  */
918
925
  openInStudio: (options?: DevtoolsOptions) => Promise<void>;
919
- } & Kubb.PluginContext;
926
+ } & ({
927
+ /**
928
+ * Returns the universal `@kubb/ast` `RootNode` produced by the configured adapter.
929
+ * Returns `undefined` when no adapter was set (legacy OAS-only usage).
930
+ */
931
+ rootNode: RootNode;
932
+ /**
933
+ * Return the adapter from `@kubb/ast`
934
+ */
935
+ adapter: Adapter;
936
+ } | {
937
+ rootNode?: never;
938
+ adapter?: never;
939
+ }) & Kubb.PluginContext;
920
940
  /**
921
941
  * Specify the export location for the files and define the behavior of the output
922
942
  */
@@ -978,4 +998,4 @@ type Logger<TOptions extends LoggerOptions = LoggerOptions> = {
978
998
  type UserLogger<TOptions extends LoggerOptions = LoggerOptions> = Omit<Logger<TOptions>, 'logLevel'>;
979
999
  //#endregion
980
1000
  export { UserPluginWithLifeCycle as A, URLPath as B, PrinterFactoryOptions as C, UserConfig as D, UnknownUserPlugin as E, defineStorage as F, formatters as I, linters as L, PluginManager as M, getMode as N, UserLogger as O, DefineStorage as P, logLevel as R, Printer as S, ResolvePathParams as T, PluginFactoryOptions as _, Config as a, PluginParameter as b, Group as c, Logger as d, LoggerContext as f, PluginContext as g, Plugin as h, BarrelType as i, KubbEvents as j, UserPlugin as k, InputData as l, Output as m, AdapterFactoryOptions as n, DevtoolsOptions as o, LoggerOptions as p, AdapterSource as r, GetPluginFactoryOptions as s, Adapter as t, InputPath as u, PluginLifecycle as v, ResolveNameParams as w, PluginWithLifeCycle as x, PluginLifecycleHooks as y, AsyncEventEmitter as z };
981
- //# sourceMappingURL=types-B7eZvqwD.d.ts.map
1001
+ //# sourceMappingURL=types-CiPWLv-5.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "5.0.0-alpha.2",
3
+ "version": "5.0.0-alpha.3",
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.2"
74
+ "@kubb/ast": "5.0.0-alpha.3"
75
75
  },
76
76
  "devDependencies": {
77
77
  "@types/semver": "^7.7.1",
@@ -1,4 +1,4 @@
1
- import path from 'node:path'
1
+ import { basename, extname, resolve } from 'node:path'
2
2
  import { performance } from 'node:perf_hooks'
3
3
  import type { AsyncEventEmitter } from '@internals/utils'
4
4
  import { setUniqueName, transformReservedWord } from '@internals/utils'
@@ -10,6 +10,7 @@ import { openInStudio as openInStudioFn } from './devtools.ts'
10
10
  import { ValidationPluginError } from './errors.ts'
11
11
  import { isPromiseRejectedResult, PromiseManager } from './PromiseManager.ts'
12
12
  import type {
13
+ Adapter,
13
14
  Config,
14
15
  DevtoolsOptions,
15
16
  KubbEvents,
@@ -59,7 +60,7 @@ export function getMode(fileOrFolder: string | undefined | null): KubbFile.Mode
59
60
  if (!fileOrFolder) {
60
61
  return 'split'
61
62
  }
62
- return path.extname(fileOrFolder) ? 'single' : 'split'
63
+ return extname(fileOrFolder) ? 'single' : 'split'
63
64
  }
64
65
 
65
66
  export class PluginManager {
@@ -71,6 +72,7 @@ export class PluginManager {
71
72
  * the build pipeline after the adapter's `parse()` resolves.
72
73
  */
73
74
  rootNode: RootNode | undefined = undefined
75
+ adapter: Adapter | undefined = undefined
74
76
  #studioIsOpen = false
75
77
 
76
78
  readonly #plugins = new Set<Plugin>()
@@ -104,7 +106,7 @@ export class PluginManager {
104
106
  plugin,
105
107
  events: this.options.events,
106
108
  pluginManager: this,
107
- mode: getMode(path.resolve(this.config.root, this.config.output.path)),
109
+ mode: getMode(resolve(this.config.root, this.config.output.path)),
108
110
  addFile: async (...files: Array<KubbFile.File>) => {
109
111
  await this.options.fabric.addFile(...files)
110
112
  },
@@ -114,17 +116,20 @@ export class PluginManager {
114
116
  get rootNode(): RootNode | undefined {
115
117
  return pluginManager.rootNode
116
118
  },
119
+ get adapter(): Adapter | undefined {
120
+ return pluginManager.adapter
121
+ },
117
122
  openInStudio(options?: DevtoolsOptions) {
123
+ if (!pluginManager.config.devtools || pluginManager.#studioIsOpen) {
124
+ return
125
+ }
126
+
118
127
  if (typeof pluginManager.config.devtools !== 'object') {
119
128
  throw new Error('Devtools must be an object')
120
129
  }
121
130
 
122
- if (!pluginManager.rootNode) {
123
- throw new Error('RootNode is not defined, make sure you have set the parser in kubb.config.ts')
124
- }
125
-
126
- if (pluginManager.#studioIsOpen) {
127
- return
131
+ if (!pluginManager.rootNode || !pluginManager.adapter) {
132
+ throw new Error('adapter is not defined, make sure you have set the parser in kubb.config.ts')
128
133
  }
129
134
 
130
135
  pluginManager.#studioIsOpen = true
@@ -159,16 +164,22 @@ export class PluginManager {
159
164
  }
160
165
 
161
166
  getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileProps<TOptions>): KubbFile.File<{ pluginName: string }> {
162
- const baseName = `${name}${extname}` as const
163
- const path = this.resolvePath({ baseName, mode, pluginName, options })
167
+ const resolvedName = mode ? (mode === 'single' ? '' : this.resolveName({ name, pluginName, type: 'file' })) : name
168
+
169
+ const path = this.resolvePath({
170
+ baseName: `${resolvedName}${extname}` as const,
171
+ mode,
172
+ pluginName,
173
+ options,
174
+ })
164
175
 
165
176
  if (!path) {
166
- throw new Error(`Filepath should be defined for resolvedName "${name}" and pluginName "${pluginName}"`)
177
+ throw new Error(`Filepath should be defined for resolvedName "${resolvedName}" and pluginName "${pluginName}"`)
167
178
  }
168
179
 
169
180
  return {
170
181
  path,
171
- baseName,
182
+ baseName: basename(path) as KubbFile.File['baseName'],
172
183
  meta: {
173
184
  pluginName,
174
185
  },
@@ -179,8 +190,8 @@ export class PluginManager {
179
190
  }
180
191
 
181
192
  resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): KubbFile.Path => {
182
- const root = path.resolve(this.config.root, this.config.output.path)
183
- const defaultPath = path.resolve(root, params.baseName)
193
+ const root = resolve(this.config.root, this.config.output.path)
194
+ const defaultPath = resolve(root, params.baseName)
184
195
 
185
196
  if (params.pluginName) {
186
197
  const paths = this.hookForPluginSync({
@@ -456,7 +467,12 @@ export class PluginManager {
456
467
  return plugins
457
468
  .map((plugin) => {
458
469
  if (plugin.pre) {
459
- const missingPlugins = plugin.pre.filter((pluginName) => !plugins.find((pluginToFind) => pluginToFind.name === pluginName))
470
+ let missingPlugins = plugin.pre.filter((pluginName) => !plugins.find((pluginToFind) => pluginToFind.name === pluginName))
471
+
472
+ // when adapter is set, we can ignore the depends on plugin-oas, in v5 this will not be needed anymore
473
+ if (missingPlugins.includes('plugin-oas') && this.adapter) {
474
+ missingPlugins = missingPlugins.filter((pluginName) => pluginName !== 'plugin-oas')
475
+ }
460
476
 
461
477
  if (missingPlugins.length > 0) {
462
478
  throw new ValidationPluginError(`The plugin '${plugin.name}' has a pre set that references missing plugins for '${missingPlugins.join(', ')}'`)
package/src/build.ts CHANGED
@@ -180,6 +180,7 @@ export async function setup(options: BuildOptions): Promise<SetupResult> {
180
180
  logs: [`Running adapter: ${definedConfig.adapter.name}`],
181
181
  })
182
182
 
183
+ pluginManager.adapter = definedConfig.adapter
183
184
  pluginManager.rootNode = await definedConfig.adapter.parse(source)
184
185
 
185
186
  await events.emit('debug', {
@@ -1,3 +1,8 @@
1
+ export { useKubb } from './useKubb.ts'
2
+
3
+ /** @deprecated Use `useKubb` from `@kubb/core/hooks` instead */
1
4
  export { useMode } from './useMode.ts'
5
+ /** @deprecated Use `useKubb` from `@kubb/core/hooks` instead */
2
6
  export { usePlugin } from './usePlugin.ts'
7
+ /** @deprecated Use `useKubb` from `@kubb/core/hooks` instead */
3
8
  export { usePluginManager } from './usePluginManager.ts'
@@ -0,0 +1,22 @@
1
+ import type { KubbFile } from '@kubb/fabric-core/types'
2
+ import { useApp as useAppBase } from '@kubb/react-fabric'
3
+ import type { PluginManager } from '../PluginManager.ts'
4
+ import type { Plugin, PluginFactoryOptions } from '../types.ts'
5
+
6
+ export function useKubb<TOptions extends PluginFactoryOptions = PluginFactoryOptions>() {
7
+ const { meta } = useAppBase<{
8
+ plugin: Plugin<TOptions>
9
+ mode: KubbFile.Mode
10
+ pluginManager: PluginManager
11
+ }>()
12
+
13
+ return {
14
+ plugin: meta.plugin as Plugin<TOptions>,
15
+ mode: meta.mode,
16
+ config: meta.pluginManager.config,
17
+ getPluginByName: meta.pluginManager.getPluginByName.bind(meta.pluginManager),
18
+ getFile: meta.pluginManager.getFile.bind(meta.pluginManager),
19
+ resolveName: meta.pluginManager.resolveName.bind(meta.pluginManager),
20
+ resolvePath: meta.pluginManager.resolvePath.bind(meta.pluginManager),
21
+ }
22
+ }
@@ -1,6 +1,9 @@
1
1
  import type { KubbFile } from '@kubb/fabric-core/types'
2
2
  import { useApp } from '@kubb/react-fabric'
3
3
 
4
+ /**
5
+ * @deprecated use `useKubb` instead
6
+ */
4
7
  export function useMode(): KubbFile.Mode {
5
8
  const { meta } = useApp<{ mode: KubbFile.Mode }>()
6
9
 
@@ -1,6 +1,9 @@
1
1
  import { useApp } from '@kubb/react-fabric'
2
2
  import type { Plugin, PluginFactoryOptions } from '../types.ts'
3
3
 
4
+ /**
5
+ * @deprecated use useApp instead
6
+ */
4
7
  export function usePlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(): Plugin<TOptions> {
5
8
  const { meta } = useApp<{ plugin: Plugin<TOptions> }>()
6
9
 
@@ -1,6 +1,9 @@
1
1
  import { useApp } from '@kubb/react-fabric'
2
2
  import type { PluginManager } from '../PluginManager.ts'
3
3
 
4
+ /**
5
+ * @deprecated use `useKubb` instead
6
+ */
4
7
  export function usePluginManager(): PluginManager {
5
8
  const { meta } = useApp<{ pluginManager: PluginManager }>()
6
9
 
package/src/types.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { AsyncEventEmitter, PossiblePromise } from '@internals/utils'
2
- import type { RootNode } from '@kubb/ast/types'
2
+ import type { RootNode, SchemaNode } from '@kubb/ast/types'
3
3
  import type { KubbFile } from '@kubb/fabric-core/types'
4
4
  import type { Fabric } from '@kubb/react-fabric'
5
5
  import type { DEFAULT_STUDIO_URL, logLevel } from './constants.ts'
@@ -98,6 +98,14 @@ export type Adapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptio
98
98
  options: TOptions['resolvedOptions']
99
99
  /** Convert the raw source into a universal `RootNode`. */
100
100
  parse: (source: AdapterSource) => PossiblePromise<RootNode>
101
+ /**
102
+ * Extracts `KubbFile.Import` entries needed by a `SchemaNode` tree.
103
+ * Populated after the first `parse()` call. Returns an empty array before that.
104
+ *
105
+ * The `resolve` callback receives the collision-corrected schema name and must
106
+ * return the `{ name, path }` pair for the import, or `undefined` to skip it.
107
+ */
108
+ getImports: (node: SchemaNode, resolve: (schemaName: string) => { name: string; path: string }) => Array<KubbFile.Import>
101
109
  }
102
110
 
103
111
  export type BarrelType = 'all' | 'named' | 'propagate'
@@ -408,18 +416,31 @@ export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryO
408
416
  * Current plugin
409
417
  */
410
418
  plugin: Plugin<TOptions>
411
- /**
412
- * Returns the universal `@kubb/ast` `RootNode` produced by the configured adapter.
413
- * Returns `undefined` when no adapter was set (legacy OAS-only usage).
414
- */
415
- rootNode: RootNode | undefined
419
+
416
420
  /**
417
421
  * Opens the Kubb Studio URL for the current `rootNode` in the default browser.
418
422
  * Falls back to printing the URL if the browser cannot be launched.
419
423
  * No-ops silently when no adapter has set a `rootNode`.
420
424
  */
421
425
  openInStudio: (options?: DevtoolsOptions) => Promise<void>
422
- } & Kubb.PluginContext
426
+ } & (
427
+ | {
428
+ /**
429
+ * Returns the universal `@kubb/ast` `RootNode` produced by the configured adapter.
430
+ * Returns `undefined` when no adapter was set (legacy OAS-only usage).
431
+ */
432
+ rootNode: RootNode
433
+ /**
434
+ * Return the adapter from `@kubb/ast`
435
+ */
436
+ adapter: Adapter
437
+ }
438
+ | {
439
+ rootNode?: never
440
+ adapter?: never
441
+ }
442
+ ) &
443
+ Kubb.PluginContext
423
444
  /**
424
445
  * Specify the export location for the files and define the behavior of the output
425
446
  */