@kubb/core 4.36.1 → 5.0.0-alpha.10
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/dist/{types-D30QAz2y.d.ts → PluginDriver-BkFepPdm.d.ts} +354 -291
- package/dist/hooks.cjs +85 -8
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +66 -4
- package/dist/hooks.js +83 -8
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +346 -315
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +91 -77
- package/dist/index.js +338 -305
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/Kubb.ts +27 -55
- package/src/{PluginManager.ts → PluginDriver.ts} +69 -82
- package/src/build.ts +32 -33
- package/src/constants.ts +1 -1
- package/src/createAdapter.ts +25 -0
- package/src/createPlugin.ts +28 -0
- package/src/createStorage.ts +58 -0
- package/src/defineGenerator.ts +134 -0
- package/src/defineLogger.ts +13 -3
- package/src/defineResolver.ts +131 -0
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useKubb.ts +143 -0
- package/src/hooks/useMode.ts +5 -2
- package/src/hooks/usePlugin.ts +5 -2
- package/src/hooks/usePluginDriver.ts +11 -0
- package/src/index.ts +7 -7
- package/src/storages/fsStorage.ts +2 -2
- package/src/storages/memoryStorage.ts +2 -2
- package/src/types.ts +94 -48
- package/src/utils/FunctionParams.ts +2 -2
- package/src/utils/TreeNode.ts +1 -1
- package/src/utils/formatters.ts +1 -1
- package/src/utils/getBarrelFiles.ts +73 -11
- package/src/utils/getConfigs.ts +3 -21
- package/src/utils/linters.ts +1 -1
- package/src/utils/packageJSON.ts +61 -0
- package/src/BarrelManager.ts +0 -74
- package/src/PackageManager.ts +0 -180
- package/src/PromiseManager.ts +0 -40
- package/src/defineAdapter.ts +0 -22
- package/src/definePlugin.ts +0 -12
- package/src/defineStorage.ts +0 -56
- package/src/errors.ts +0 -1
- package/src/hooks/usePluginManager.ts +0 -8
- package/src/utils/getPlugins.ts +0 -23
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import type { RootNode } from '@kubb/ast/types'
|
|
3
|
+
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
4
|
+
import { useFabric } from '@kubb/react-fabric'
|
|
5
|
+
import type { GetFileOptions, PluginDriver } from '../PluginDriver.ts'
|
|
6
|
+
import type { Config, Plugin, PluginFactoryOptions, ResolveNameParams, ResolvePathParams } from '../types.ts'
|
|
7
|
+
|
|
8
|
+
type ResolvePathOptions = {
|
|
9
|
+
pluginName?: string
|
|
10
|
+
group?: {
|
|
11
|
+
tag?: string
|
|
12
|
+
path?: string
|
|
13
|
+
}
|
|
14
|
+
type?: ResolveNameParams['type']
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type UseKubbReturn<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
|
|
18
|
+
plugin: Plugin<TOptions>
|
|
19
|
+
mode: KubbFile.Mode
|
|
20
|
+
config: Config
|
|
21
|
+
/**
|
|
22
|
+
* Returns the plugin whose `name` matches `pluginName`, defaulting to the current plugin.
|
|
23
|
+
*/
|
|
24
|
+
getPluginByName: (pluginName?: string) => Plugin | undefined
|
|
25
|
+
/**
|
|
26
|
+
* Resolves a file reference, defaulting `pluginName` to the current plugin.
|
|
27
|
+
*/
|
|
28
|
+
getFile: (params: Omit<GetFileOptions<ResolvePathOptions>, 'pluginName'> & { pluginName?: string }) => KubbFile.File<{ pluginName: string }>
|
|
29
|
+
/**
|
|
30
|
+
* Resolves a name, defaulting `pluginName` to the current plugin.
|
|
31
|
+
*/
|
|
32
|
+
resolveName: (params: Omit<ResolveNameParams, 'pluginName'> & { pluginName?: string }) => string
|
|
33
|
+
/**
|
|
34
|
+
* Resolves a path, defaulting `pluginName` to the current plugin.
|
|
35
|
+
*/
|
|
36
|
+
resolvePath: <TPathOptions = object>(params: Omit<ResolvePathParams<TPathOptions>, 'pluginName'> & { pluginName?: string }) => KubbFile.Path
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the banner using the plugin's `output.banner` option.
|
|
39
|
+
* Falls back to the default "Generated by Kubb" banner when `output.banner` is unset.
|
|
40
|
+
* When `output.banner` is a function and no node is provided, returns the default banner.
|
|
41
|
+
*/
|
|
42
|
+
resolveBanner: (node?: RootNode) => string | undefined
|
|
43
|
+
/**
|
|
44
|
+
* Resolves the footer using the plugin's `output.footer` option.
|
|
45
|
+
* Returns `undefined` when no footer is configured.
|
|
46
|
+
* When `output.footer` is a function and no node is provided, returns `undefined`.
|
|
47
|
+
*/
|
|
48
|
+
resolveFooter: (node?: RootNode) => string | undefined
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Generates the default "Generated by Kubb" banner from node metadata.
|
|
53
|
+
*/
|
|
54
|
+
function buildDefaultBanner({ title, description, version, config }: { title?: string; description?: string; version?: string; config: Config }): string {
|
|
55
|
+
try {
|
|
56
|
+
let source = ''
|
|
57
|
+
if (Array.isArray(config.input)) {
|
|
58
|
+
const first = config.input[0]
|
|
59
|
+
if (first && 'path' in first) {
|
|
60
|
+
source = path.basename(first.path)
|
|
61
|
+
}
|
|
62
|
+
} else if ('path' in config.input) {
|
|
63
|
+
source = path.basename(config.input.path)
|
|
64
|
+
} else if ('data' in config.input) {
|
|
65
|
+
source = 'text content'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let banner = '/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n'
|
|
69
|
+
|
|
70
|
+
if (config.output.defaultBanner === 'simple') {
|
|
71
|
+
banner += '*/\n'
|
|
72
|
+
return banner
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (source) {
|
|
76
|
+
banner += `* Source: ${source}\n`
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (title) {
|
|
80
|
+
banner += `* Title: ${title}\n`
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (description) {
|
|
84
|
+
const formattedDescription = description.replace(/\n/gm, '\n* ')
|
|
85
|
+
banner += `* Description: ${formattedDescription}\n`
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (version) {
|
|
89
|
+
banner += `* OpenAPI spec version: ${version}\n`
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
banner += '*/\n'
|
|
93
|
+
return banner
|
|
94
|
+
} catch (_error) {
|
|
95
|
+
return '/**\n* Generated by Kubb (https://kubb.dev/).\n* Do not edit manually.\n*/'
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function useKubb<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(): UseKubbReturn<TOptions> {
|
|
100
|
+
const { meta } = useFabric<{
|
|
101
|
+
plugin: Plugin<TOptions>
|
|
102
|
+
mode: KubbFile.Mode
|
|
103
|
+
driver: PluginDriver
|
|
104
|
+
}>()
|
|
105
|
+
|
|
106
|
+
const config = meta.driver.config
|
|
107
|
+
const defaultPluginName = meta.plugin.name
|
|
108
|
+
|
|
109
|
+
const output = (
|
|
110
|
+
meta.plugin.options as { output?: { banner?: string | ((node: RootNode) => string); footer?: string | ((node: RootNode) => string) } } | undefined
|
|
111
|
+
)?.output
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
plugin: meta.plugin as Plugin<TOptions>,
|
|
115
|
+
mode: meta.mode,
|
|
116
|
+
config,
|
|
117
|
+
getPluginByName: (pluginName = defaultPluginName) => meta.driver.getPluginByName.call(meta.driver, pluginName),
|
|
118
|
+
getFile: ({ pluginName = defaultPluginName, ...rest }) => meta.driver.getFile.call(meta.driver, { pluginName, ...rest }),
|
|
119
|
+
resolveName: ({ pluginName = defaultPluginName, ...rest }) => meta.driver.resolveName.call(meta.driver, { pluginName, ...rest }),
|
|
120
|
+
resolvePath: ({ pluginName = defaultPluginName, ...rest }) => meta.driver.resolvePath.call(meta.driver, { pluginName, ...rest }),
|
|
121
|
+
resolveBanner: (node?: RootNode) => {
|
|
122
|
+
if (typeof output?.banner === 'function') {
|
|
123
|
+
return node ? output.banner(node) : buildDefaultBanner({ config })
|
|
124
|
+
}
|
|
125
|
+
if (typeof output?.banner === 'string') {
|
|
126
|
+
return output.banner
|
|
127
|
+
}
|
|
128
|
+
if (config.output.defaultBanner === false) {
|
|
129
|
+
return undefined
|
|
130
|
+
}
|
|
131
|
+
return buildDefaultBanner({ config })
|
|
132
|
+
},
|
|
133
|
+
resolveFooter: (node?: RootNode) => {
|
|
134
|
+
if (typeof output?.footer === 'function') {
|
|
135
|
+
return node ? output.footer(node) : undefined
|
|
136
|
+
}
|
|
137
|
+
if (typeof output?.footer === 'string') {
|
|
138
|
+
return output.footer
|
|
139
|
+
}
|
|
140
|
+
return undefined
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
}
|
package/src/hooks/useMode.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
2
|
-
import {
|
|
2
|
+
import { useFabric } from '@kubb/react-fabric'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated use `useKubb` instead
|
|
6
|
+
*/
|
|
4
7
|
export function useMode(): KubbFile.Mode {
|
|
5
|
-
const { meta } =
|
|
8
|
+
const { meta } = useFabric<{ mode: KubbFile.Mode }>()
|
|
6
9
|
|
|
7
10
|
return meta.mode
|
|
8
11
|
}
|
package/src/hooks/usePlugin.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useFabric } from '@kubb/react-fabric'
|
|
2
2
|
import type { Plugin, PluginFactoryOptions } from '../types.ts'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated use useKubb instead
|
|
6
|
+
*/
|
|
4
7
|
export function usePlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(): Plugin<TOptions> {
|
|
5
|
-
const { meta } =
|
|
8
|
+
const { meta } = useFabric<{ plugin: Plugin<TOptions> }>()
|
|
6
9
|
|
|
7
10
|
return meta.plugin
|
|
8
11
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useFabric } from '@kubb/react-fabric'
|
|
2
|
+
import type { PluginDriver } from '../PluginDriver.ts'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated use `useKubb` instead
|
|
6
|
+
*/
|
|
7
|
+
export function usePluginDriver(): PluginDriver {
|
|
8
|
+
const { meta } = useFabric<{ driver: PluginDriver }>()
|
|
9
|
+
|
|
10
|
+
return meta.driver
|
|
11
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
export { AsyncEventEmitter, URLPath } from '@internals/utils'
|
|
2
1
|
export { definePrinter } from '@kubb/ast'
|
|
3
2
|
export { build, build as default, safeBuild, setup } from './build.ts'
|
|
4
3
|
export { type CLIOptions, type ConfigInput, defineConfig, isInputPath } from './config.ts'
|
|
5
4
|
export { formatters, linters, logLevel } from './constants.ts'
|
|
6
|
-
export {
|
|
5
|
+
export { createAdapter } from './createAdapter.ts'
|
|
6
|
+
export { createPlugin } from './createPlugin.ts'
|
|
7
|
+
export { createStorage } from './createStorage.ts'
|
|
8
|
+
export { defineGenerator } from './defineGenerator.ts'
|
|
7
9
|
export { defineLogger } from './defineLogger.ts'
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export { PackageManager } from './PackageManager.ts'
|
|
11
|
-
export { getMode, PluginManager } from './PluginManager.ts'
|
|
12
|
-
export { PromiseManager } from './PromiseManager.ts'
|
|
10
|
+
export { defaultResolveOptions, defineResolver } from './defineResolver.ts'
|
|
11
|
+
export { getMode, PluginDriver } from './PluginDriver.ts'
|
|
13
12
|
export { fsStorage } from './storages/fsStorage.ts'
|
|
14
13
|
export { memoryStorage } from './storages/memoryStorage.ts'
|
|
15
14
|
export * from './types.ts'
|
|
@@ -20,3 +19,4 @@ export type { FileMetaBase } from './utils/getBarrelFiles.ts'
|
|
|
20
19
|
export { getBarrelFiles } from './utils/getBarrelFiles.ts'
|
|
21
20
|
export { getConfigs } from './utils/getConfigs.ts'
|
|
22
21
|
export { detectLinter } from './utils/linters.ts'
|
|
22
|
+
export { satisfiesDependency } from './utils/packageJSON.ts'
|
|
@@ -2,7 +2,7 @@ import type { Dirent } from 'node:fs'
|
|
|
2
2
|
import { access, readdir, readFile, rm } from 'node:fs/promises'
|
|
3
3
|
import { join, resolve } from 'node:path'
|
|
4
4
|
import { clean, write } from '@internals/utils'
|
|
5
|
-
import {
|
|
5
|
+
import { createStorage } from '../createStorage.ts'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Built-in filesystem storage driver.
|
|
@@ -27,7 +27,7 @@ import { defineStorage } from '../defineStorage.ts'
|
|
|
27
27
|
* })
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
export const fsStorage =
|
|
30
|
+
export const fsStorage = createStorage(() => ({
|
|
31
31
|
name: 'fs',
|
|
32
32
|
async hasItem(key: string) {
|
|
33
33
|
try {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createStorage } from '../createStorage.ts'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* In-memory storage driver. Useful for testing and dry-run scenarios where
|
|
@@ -17,7 +17,7 @@ import { defineStorage } from '../defineStorage.ts'
|
|
|
17
17
|
* })
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
|
-
export const memoryStorage =
|
|
20
|
+
export const memoryStorage = createStorage(() => {
|
|
21
21
|
const store = new Map<string, string>()
|
|
22
22
|
|
|
23
23
|
return {
|
package/src/types.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { AsyncEventEmitter, PossiblePromise } from '@internals/utils'
|
|
2
|
-
import type { RootNode } 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, RootNode, SchemaNode } from '@kubb/ast/types'
|
|
3
|
+
import type { Fabric as FabricType, KubbFile } from '@kubb/fabric-core/types'
|
|
5
4
|
import type { DEFAULT_STUDIO_URL, logLevel } from './constants.ts'
|
|
6
|
-
import type {
|
|
5
|
+
import type { Storage } from './createStorage.ts'
|
|
7
6
|
import type { KubbEvents } from './Kubb.ts'
|
|
8
|
-
import type {
|
|
7
|
+
import type { PluginDriver } from './PluginDriver.ts'
|
|
9
8
|
|
|
10
9
|
export type { Printer, PrinterFactoryOptions } from '@kubb/ast/types'
|
|
11
10
|
|
|
@@ -33,7 +32,7 @@ export type UserConfig<TInput = Input> = Omit<Config<TInput>, 'root' | 'plugins'
|
|
|
33
32
|
/**
|
|
34
33
|
* 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
34
|
*/
|
|
36
|
-
// inject needs to be omitted because else we have a clash with the
|
|
35
|
+
// inject needs to be omitted because else we have a clash with the PluginDriver instance
|
|
37
36
|
plugins?: Array<Omit<UnknownUserPlugin, 'inject'>>
|
|
38
37
|
}
|
|
39
38
|
|
|
@@ -98,6 +97,14 @@ export type Adapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptio
|
|
|
98
97
|
options: TOptions['resolvedOptions']
|
|
99
98
|
/** Convert the raw source into a universal `RootNode`. */
|
|
100
99
|
parse: (source: AdapterSource) => PossiblePromise<RootNode>
|
|
100
|
+
/**
|
|
101
|
+
* Extracts `KubbFile.Import` entries needed by a `SchemaNode` tree.
|
|
102
|
+
* Populated after the first `parse()` call. Returns an empty array before that.
|
|
103
|
+
*
|
|
104
|
+
* The `resolve` callback receives the collision-corrected schema name and must
|
|
105
|
+
* return the `{ name, path }` pair for the import, or `undefined` to skip it.
|
|
106
|
+
*/
|
|
107
|
+
getImports: (node: SchemaNode, resolve: (schemaName: string) => { name: string; path: string }) => Array<KubbFile.Import>
|
|
101
108
|
}
|
|
102
109
|
|
|
103
110
|
export type BarrelType = 'all' | 'named' | 'propagate'
|
|
@@ -165,16 +172,16 @@ export type Config<TInput = Input> = {
|
|
|
165
172
|
/**
|
|
166
173
|
* Storage backend for generated files.
|
|
167
174
|
* Defaults to `fsStorage()` — the built-in filesystem driver.
|
|
168
|
-
* Accepts any object implementing the {@link
|
|
175
|
+
* Accepts any object implementing the {@link Storage} interface.
|
|
169
176
|
* Keys are root-relative paths (e.g. `src/gen/api/getPets.ts`).
|
|
170
177
|
* @default fsStorage()
|
|
171
178
|
* @example
|
|
172
179
|
* ```ts
|
|
173
|
-
* import {
|
|
174
|
-
* storage:
|
|
180
|
+
* import { memoryStorage } from '@kubb/core'
|
|
181
|
+
* storage: memoryStorage()
|
|
175
182
|
* ```
|
|
176
183
|
*/
|
|
177
|
-
storage?:
|
|
184
|
+
storage?: Storage
|
|
178
185
|
/**
|
|
179
186
|
* Specifies the formatting tool to be used.
|
|
180
187
|
* - 'auto' automatically detects and uses biome or prettier (in that order of preference).
|
|
@@ -253,9 +260,47 @@ export type Config<TInput = Input> = {
|
|
|
253
260
|
|
|
254
261
|
// plugin
|
|
255
262
|
|
|
263
|
+
type PatternFilter = {
|
|
264
|
+
type: string
|
|
265
|
+
pattern: string | RegExp
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
type PatternOverride<TOptions> = PatternFilter & {
|
|
269
|
+
options: Omit<Partial<TOptions>, 'override'>
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export type ResolveOptionsContext<TOptions> = {
|
|
273
|
+
options: TOptions
|
|
274
|
+
exclude?: Array<PatternFilter>
|
|
275
|
+
include?: Array<PatternFilter>
|
|
276
|
+
override?: Array<PatternOverride<TOptions>>
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Base constraint for all plugin resolver objects.
|
|
281
|
+
*
|
|
282
|
+
* `default` and `resolveOptions` are injected automatically by `defineResolver` — plugin
|
|
283
|
+
* authors may override them but never need to implement them from scratch.
|
|
284
|
+
* Concrete plugin resolver types extend this with their own helper methods.
|
|
285
|
+
*/
|
|
286
|
+
export type Resolver = {
|
|
287
|
+
default(name: ResolveNameParams['name'], type?: ResolveNameParams['type']): string
|
|
288
|
+
resolveOptions<TOptions>(node: Node, context: ResolveOptionsContext<TOptions>): TOptions | null
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* The user-facing subset of a `Resolver` — everything except the methods injected by
|
|
293
|
+
* `defineResolver` (`default` and `resolveOptions`).
|
|
294
|
+
*
|
|
295
|
+
* When you pass a `UserResolver` to `defineResolver`, the standard `default` and
|
|
296
|
+
* `resolveOptions` implementations are injected automatically so plugin authors never
|
|
297
|
+
* need to define them by hand. Both can still be overridden by providing them explicitly.
|
|
298
|
+
*/
|
|
299
|
+
export type UserResolver = Omit<Resolver, 'default' | 'resolveOptions'>
|
|
300
|
+
|
|
256
301
|
export type PluginFactoryOptions<
|
|
257
302
|
/**
|
|
258
|
-
* Name to be used for the plugin
|
|
303
|
+
* Name to be used for the plugin.
|
|
259
304
|
*/
|
|
260
305
|
TName extends string = string,
|
|
261
306
|
/**
|
|
@@ -274,22 +319,20 @@ export type PluginFactoryOptions<
|
|
|
274
319
|
* When calling `resolvePath` you can specify better types.
|
|
275
320
|
*/
|
|
276
321
|
TResolvePathOptions extends object = object,
|
|
277
|
-
> = {
|
|
278
|
-
name: TName
|
|
279
322
|
/**
|
|
280
|
-
*
|
|
323
|
+
* Resolver object that encapsulates the naming and path-resolution helpers used by this plugin.
|
|
324
|
+
* Use `defineResolver` to define the resolver object and export it alongside the plugin.
|
|
281
325
|
*/
|
|
282
|
-
|
|
326
|
+
TResolver extends Resolver = Resolver,
|
|
327
|
+
> = {
|
|
328
|
+
name: TName
|
|
283
329
|
options: TOptions
|
|
284
330
|
resolvedOptions: TResolvedOptions
|
|
285
331
|
context: TContext
|
|
286
332
|
resolvePathOptions: TResolvePathOptions
|
|
333
|
+
resolver: TResolver
|
|
287
334
|
}
|
|
288
335
|
|
|
289
|
-
export type PluginKey<TName> = [name: TName, identifier?: string | number]
|
|
290
|
-
|
|
291
|
-
export type GetPluginFactoryOptions<TPlugin extends UserPlugin> = TPlugin extends UserPlugin<infer X> ? X : never
|
|
292
|
-
|
|
293
336
|
export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
|
|
294
337
|
/**
|
|
295
338
|
* Unique name used for the plugin
|
|
@@ -315,7 +358,7 @@ export type UserPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOpti
|
|
|
315
358
|
|
|
316
359
|
export type UserPluginWithLifeCycle<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = UserPlugin<TOptions> & PluginLifecycle<TOptions>
|
|
317
360
|
|
|
318
|
-
|
|
361
|
+
type UnknownUserPlugin = UserPlugin<PluginFactoryOptions<string, object, object, unknown, object>>
|
|
319
362
|
|
|
320
363
|
export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
|
|
321
364
|
/**
|
|
@@ -323,11 +366,6 @@ export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
|
|
|
323
366
|
* @example @kubb/typescript
|
|
324
367
|
*/
|
|
325
368
|
name: TOptions['name']
|
|
326
|
-
/**
|
|
327
|
-
* Internal key used when a developer uses more than one of the same plugin
|
|
328
|
-
* @private
|
|
329
|
-
*/
|
|
330
|
-
key: TOptions['key']
|
|
331
369
|
/**
|
|
332
370
|
* 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.
|
|
333
371
|
* Can be used to validate dependent plugins.
|
|
@@ -344,7 +382,7 @@ export type Plugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>
|
|
|
344
382
|
|
|
345
383
|
install: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => PossiblePromise<void>
|
|
346
384
|
/**
|
|
347
|
-
*
|
|
385
|
+
* Defines a context that can be used by other plugins, see `PluginDriver` where we convert from `UserPlugin` to `Plugin` (used when calling `createPlugin`).
|
|
348
386
|
*/
|
|
349
387
|
inject: (this: PluginContext<TOptions>, context: PluginContext<TOptions>) => TOptions['context']
|
|
350
388
|
}
|
|
@@ -378,7 +416,7 @@ export type PluginLifecycleHooks = keyof PluginLifecycle
|
|
|
378
416
|
export type PluginParameter<H extends PluginLifecycleHooks> = Parameters<Required<PluginLifecycle>[H]>
|
|
379
417
|
|
|
380
418
|
export type ResolvePathParams<TOptions = object> = {
|
|
381
|
-
|
|
419
|
+
pluginName?: string
|
|
382
420
|
baseName: KubbFile.BaseName
|
|
383
421
|
mode?: KubbFile.Mode
|
|
384
422
|
/**
|
|
@@ -389,7 +427,7 @@ export type ResolvePathParams<TOptions = object> = {
|
|
|
389
427
|
|
|
390
428
|
export type ResolveNameParams = {
|
|
391
429
|
name: string
|
|
392
|
-
|
|
430
|
+
pluginName?: string
|
|
393
431
|
/**
|
|
394
432
|
* Specifies the type of entity being named.
|
|
395
433
|
* - 'file' customizes the name of the created file (uses camelCase).
|
|
@@ -402,9 +440,9 @@ export type ResolveNameParams = {
|
|
|
402
440
|
}
|
|
403
441
|
|
|
404
442
|
export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
|
|
405
|
-
fabric:
|
|
443
|
+
fabric: FabricType
|
|
406
444
|
config: Config
|
|
407
|
-
|
|
445
|
+
driver: PluginDriver
|
|
408
446
|
/**
|
|
409
447
|
* Only add when the file does not exist yet
|
|
410
448
|
*/
|
|
@@ -419,18 +457,31 @@ export type PluginContext<TOptions extends PluginFactoryOptions = PluginFactoryO
|
|
|
419
457
|
* Current plugin
|
|
420
458
|
*/
|
|
421
459
|
plugin: Plugin<TOptions>
|
|
422
|
-
|
|
423
|
-
* Returns the universal `@kubb/ast` `RootNode` produced by the configured adapter.
|
|
424
|
-
* Returns `undefined` when no adapter was set (legacy OAS-only usage).
|
|
425
|
-
*/
|
|
426
|
-
rootNode: RootNode | undefined
|
|
460
|
+
|
|
427
461
|
/**
|
|
428
462
|
* Opens the Kubb Studio URL for the current `rootNode` in the default browser.
|
|
429
463
|
* Falls back to printing the URL if the browser cannot be launched.
|
|
430
464
|
* No-ops silently when no adapter has set a `rootNode`.
|
|
431
465
|
*/
|
|
432
466
|
openInStudio: (options?: DevtoolsOptions) => Promise<void>
|
|
433
|
-
} &
|
|
467
|
+
} & (
|
|
468
|
+
| {
|
|
469
|
+
/**
|
|
470
|
+
* Returns the universal `@kubb/ast` `RootNode` produced by the configured adapter.
|
|
471
|
+
* Returns `undefined` when no adapter was set (legacy OAS-only usage).
|
|
472
|
+
*/
|
|
473
|
+
rootNode: RootNode
|
|
474
|
+
/**
|
|
475
|
+
* Return the adapter from `@kubb/ast`
|
|
476
|
+
*/
|
|
477
|
+
adapter: Adapter
|
|
478
|
+
}
|
|
479
|
+
| {
|
|
480
|
+
rootNode?: never
|
|
481
|
+
adapter?: never
|
|
482
|
+
}
|
|
483
|
+
) &
|
|
484
|
+
Kubb.PluginContext
|
|
434
485
|
/**
|
|
435
486
|
* Specify the export location for the files and define the behavior of the output
|
|
436
487
|
*/
|
|
@@ -459,10 +510,6 @@ export type Output<TOptions> = {
|
|
|
459
510
|
override?: boolean
|
|
460
511
|
}
|
|
461
512
|
|
|
462
|
-
type GroupContext = {
|
|
463
|
-
group: string
|
|
464
|
-
}
|
|
465
|
-
|
|
466
513
|
export type Group = {
|
|
467
514
|
/**
|
|
468
515
|
* Defines the type where to group the files.
|
|
@@ -472,9 +519,9 @@ export type Group = {
|
|
|
472
519
|
*/
|
|
473
520
|
type: 'tag' | 'path'
|
|
474
521
|
/**
|
|
475
|
-
* Return the name of a group based on the group name, this used for the file and name generation
|
|
522
|
+
* Return the name of a group based on the group name, this is used for the file and name generation.
|
|
476
523
|
*/
|
|
477
|
-
name?: (context:
|
|
524
|
+
name?: (context: { group: string }) => string
|
|
478
525
|
}
|
|
479
526
|
|
|
480
527
|
export type LoggerOptions = {
|
|
@@ -487,16 +534,15 @@ export type LoggerOptions = {
|
|
|
487
534
|
/**
|
|
488
535
|
* Shared context passed to all plugins, parsers, and Fabric internals.
|
|
489
536
|
*/
|
|
490
|
-
export
|
|
491
|
-
|
|
492
|
-
type Install<TOptions = unknown> = (context: LoggerContext, options?: TOptions) => void | Promise<void>
|
|
537
|
+
export type LoggerContext = AsyncEventEmitter<KubbEvents>
|
|
493
538
|
|
|
494
539
|
export type Logger<TOptions extends LoggerOptions = LoggerOptions> = {
|
|
495
540
|
name: string
|
|
496
|
-
install:
|
|
541
|
+
install: (context: LoggerContext, options?: TOptions) => void | Promise<void>
|
|
497
542
|
}
|
|
498
543
|
|
|
499
|
-
export type UserLogger<TOptions extends LoggerOptions = LoggerOptions> =
|
|
544
|
+
export type UserLogger<TOptions extends LoggerOptions = LoggerOptions> = Logger<TOptions>
|
|
500
545
|
|
|
501
|
-
export type {
|
|
546
|
+
export type { Storage } from './createStorage.ts'
|
|
547
|
+
export type { CoreGeneratorV2, Generator, ReactGeneratorV2 } from './defineGenerator.ts'
|
|
502
548
|
export type { KubbEvents } from './Kubb.ts'
|
|
@@ -30,12 +30,12 @@ type FunctionParamsASTWithType = {
|
|
|
30
30
|
default?: string
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* @deprecated
|
|
33
|
+
* @deprecated use ast package instead
|
|
34
34
|
*/
|
|
35
35
|
export type FunctionParamsAST = FunctionParamsASTWithoutType | FunctionParamsASTWithType
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* @deprecated
|
|
38
|
+
* @deprecated use ast package instead
|
|
39
39
|
*/
|
|
40
40
|
export class FunctionParams {
|
|
41
41
|
#items: Array<FunctionParamsAST | FunctionParamsAST[]> = []
|
package/src/utils/TreeNode.ts
CHANGED
package/src/utils/formatters.ts
CHANGED
|
@@ -44,7 +44,7 @@ async function isFormatterAvailable(formatter: Formatter): Promise<boolean> {
|
|
|
44
44
|
* ```
|
|
45
45
|
*/
|
|
46
46
|
export async function detectFormatter(): Promise<Formatter | undefined> {
|
|
47
|
-
const formatterNames
|
|
47
|
+
const formatterNames = new Set(['biome', 'oxfmt', 'prettier'] as const)
|
|
48
48
|
|
|
49
49
|
for (const formatter of formatterNames) {
|
|
50
50
|
if (await isFormatterAvailable(formatter)) {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
/** biome-ignore-all lint/suspicious/useIterableCallbackReturn: not needed */
|
|
1
2
|
import { join } from 'node:path'
|
|
3
|
+
import { getRelativePath } from '@internals/utils'
|
|
2
4
|
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
+
import type { BarrelType } from '../types.ts'
|
|
6
|
+
import { TreeNode } from './TreeNode.ts'
|
|
5
7
|
|
|
6
8
|
export type FileMetaBase = {
|
|
7
|
-
|
|
9
|
+
pluginName?: string
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
type AddIndexesProps = {
|
|
@@ -27,6 +29,72 @@ type AddIndexesProps = {
|
|
|
27
29
|
meta?: FileMetaBase
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
function getBarrelFilesByRoot(root: string | undefined, files: Array<KubbFile.ResolvedFile>): Array<KubbFile.File> {
|
|
33
|
+
const cachedFiles = new Map<KubbFile.Path, KubbFile.File>()
|
|
34
|
+
|
|
35
|
+
TreeNode.build(files, root)?.forEach((treeNode) => {
|
|
36
|
+
if (!treeNode || !treeNode.children || !treeNode.parent?.data.path) {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const barrelFilePath = join(treeNode.parent?.data.path, 'index.ts') as KubbFile.Path
|
|
41
|
+
const barrelFile: KubbFile.File = {
|
|
42
|
+
path: barrelFilePath,
|
|
43
|
+
baseName: 'index.ts',
|
|
44
|
+
exports: [],
|
|
45
|
+
imports: [],
|
|
46
|
+
sources: [],
|
|
47
|
+
}
|
|
48
|
+
const previousBarrelFile = cachedFiles.get(barrelFile.path)
|
|
49
|
+
const leaves = treeNode.leaves
|
|
50
|
+
|
|
51
|
+
leaves.forEach((item) => {
|
|
52
|
+
if (!item.data.name) {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const sources = item.data.file?.sources || []
|
|
57
|
+
|
|
58
|
+
sources.forEach((source) => {
|
|
59
|
+
if (!item.data.file?.path || !source.isIndexable || !source.name) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
const alreadyContainInPreviousBarrelFile = previousBarrelFile?.sources.some(
|
|
63
|
+
(item) => item.name === source.name && item.isTypeOnly === source.isTypeOnly,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if (alreadyContainInPreviousBarrelFile) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
barrelFile.exports!.push({
|
|
71
|
+
name: [source.name],
|
|
72
|
+
path: getRelativePath(treeNode.parent?.data.path, item.data.path),
|
|
73
|
+
isTypeOnly: source.isTypeOnly,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
barrelFile.sources.push({
|
|
77
|
+
name: source.name,
|
|
78
|
+
isTypeOnly: source.isTypeOnly,
|
|
79
|
+
//TODO use parser to generate import
|
|
80
|
+
value: '',
|
|
81
|
+
isExportable: false,
|
|
82
|
+
isIndexable: false,
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
if (previousBarrelFile) {
|
|
88
|
+
previousBarrelFile.sources.push(...barrelFile.sources)
|
|
89
|
+
previousBarrelFile.exports?.push(...(barrelFile.exports || []))
|
|
90
|
+
} else {
|
|
91
|
+
cachedFiles.set(barrelFile.path, barrelFile)
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
return [...cachedFiles.values()]
|
|
96
|
+
}
|
|
97
|
+
|
|
30
98
|
function trimExtName(text: string): string {
|
|
31
99
|
const dotIndex = text.lastIndexOf('.')
|
|
32
100
|
// Only strip when the dot is found and no path separator follows it
|
|
@@ -37,24 +105,18 @@ function trimExtName(text: string): string {
|
|
|
37
105
|
return text
|
|
38
106
|
}
|
|
39
107
|
|
|
40
|
-
export async function getBarrelFiles(files: Array<KubbFile.ResolvedFile>, { type, meta = {}, root, output }: AddIndexesProps): Promise<KubbFile.File
|
|
108
|
+
export async function getBarrelFiles(files: Array<KubbFile.ResolvedFile>, { type, meta = {}, root, output }: AddIndexesProps): Promise<Array<KubbFile.File>> {
|
|
41
109
|
if (!type || type === 'propagate') {
|
|
42
110
|
return []
|
|
43
111
|
}
|
|
44
112
|
|
|
45
|
-
const barrelManager = new BarrelManager()
|
|
46
|
-
|
|
47
113
|
const pathToBuildFrom = join(root, output.path)
|
|
48
114
|
|
|
49
115
|
if (trimExtName(pathToBuildFrom).endsWith('index')) {
|
|
50
116
|
return []
|
|
51
117
|
}
|
|
52
118
|
|
|
53
|
-
const barrelFiles =
|
|
54
|
-
files,
|
|
55
|
-
root: pathToBuildFrom,
|
|
56
|
-
meta,
|
|
57
|
-
})
|
|
119
|
+
const barrelFiles = getBarrelFilesByRoot(pathToBuildFrom, files)
|
|
58
120
|
|
|
59
121
|
if (type === 'all') {
|
|
60
122
|
return barrelFiles.map((file) => {
|