@kubb/core 5.0.0-alpha.3 → 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/dist/PluginDriver-D0dY_hpJ.d.ts +1986 -0
- package/dist/{chunk-ByKO4r7w.cjs → chunk-MlS0t1Af.cjs} +15 -0
- package/dist/chunk-O_arW02_.js +17 -0
- package/dist/hooks.cjs +13 -28
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +11 -37
- package/dist/hooks.js +14 -28
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +1469 -831
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +572 -191
- package/dist/index.js +1443 -826
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/Kubb.ts +38 -56
- package/src/KubbFile.ts +143 -0
- package/src/{PluginManager.ts → PluginDriver.ts} +159 -170
- package/src/build.ts +213 -65
- package/src/constants.ts +39 -6
- package/src/createAdapter.ts +25 -0
- package/src/createPlugin.ts +30 -0
- package/src/createStorage.ts +58 -0
- package/src/{config.ts → defineConfig.ts} +11 -16
- package/src/defineGenerator.ts +126 -0
- package/src/defineLogger.ts +13 -3
- package/src/defineParser.ts +57 -0
- package/src/definePresets.ts +16 -0
- package/src/defineResolver.ts +454 -0
- package/src/hooks/index.ts +1 -6
- package/src/hooks/useDriver.ts +11 -0
- package/src/hooks/useMode.ts +4 -4
- package/src/hooks/usePlugin.ts +3 -3
- package/src/index.ts +22 -10
- package/src/renderNode.tsx +25 -0
- package/src/storages/fsStorage.ts +2 -2
- package/src/storages/memoryStorage.ts +2 -2
- package/src/types.ts +639 -52
- package/src/utils/FunctionParams.ts +2 -2
- package/src/utils/TreeNode.ts +40 -2
- package/src/utils/diagnostics.ts +4 -1
- package/src/utils/executeStrategies.ts +29 -10
- package/src/utils/formatters.ts +10 -21
- package/src/utils/getBarrelFiles.ts +80 -10
- package/src/utils/getConfigs.ts +9 -23
- package/src/utils/getPreset.ts +78 -0
- package/src/utils/isInputPath.ts +8 -0
- package/src/utils/linters.ts +23 -3
- package/src/utils/packageJSON.ts +76 -0
- package/dist/chunk--u3MIqq1.js +0 -8
- package/dist/types-CiPWLv-5.d.ts +0 -1001
- 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/useKubb.ts +0 -22
- package/src/hooks/usePluginManager.ts +0 -11
- package/src/utils/getPlugins.ts +0 -23
|
@@ -1,14 +1,13 @@
|
|
|
1
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
|
-
import {
|
|
4
|
+
import { isPromiseRejectedResult, transformReservedWord } from '@internals/utils'
|
|
5
5
|
import type { RootNode } from '@kubb/ast/types'
|
|
6
|
-
import type {
|
|
7
|
-
import
|
|
8
|
-
import { CORE_PLUGIN_NAME, DEFAULT_STUDIO_URL } from './constants.ts'
|
|
6
|
+
import type { Fabric as FabricType } from '@kubb/fabric-core/types'
|
|
7
|
+
import { DEFAULT_STUDIO_URL } from './constants.ts'
|
|
9
8
|
import { openInStudio as openInStudioFn } from './devtools.ts'
|
|
10
|
-
import
|
|
11
|
-
|
|
9
|
+
import type * as KubbFile from './KubbFile.ts'
|
|
10
|
+
|
|
12
11
|
import type {
|
|
13
12
|
Adapter,
|
|
14
13
|
Config,
|
|
@@ -23,11 +22,19 @@ import type {
|
|
|
23
22
|
PluginWithLifeCycle,
|
|
24
23
|
ResolveNameParams,
|
|
25
24
|
ResolvePathParams,
|
|
26
|
-
UserPlugin,
|
|
27
25
|
} from './types.ts'
|
|
26
|
+
import { hookFirst, hookParallel, hookSeq } from './utils/executeStrategies.ts'
|
|
28
27
|
|
|
29
28
|
type RequiredPluginLifecycle = Required<PluginLifecycle>
|
|
30
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Hook dispatch strategy used by the `PluginDriver`.
|
|
32
|
+
*
|
|
33
|
+
* - `hookFirst` — stops at the first non-null result.
|
|
34
|
+
* - `hookForPlugin` — calls only the matching plugin.
|
|
35
|
+
* - `hookParallel` — calls all plugins concurrently.
|
|
36
|
+
* - `hookSeq` — calls all plugins in order, threading the result.
|
|
37
|
+
*/
|
|
31
38
|
export type Strategy = 'hookFirst' | 'hookForPlugin' | 'hookParallel' | 'hookSeq'
|
|
32
39
|
|
|
33
40
|
type ParseResult<H extends PluginLifecycleHooks> = RequiredPluginLifecycle[H]
|
|
@@ -40,7 +47,7 @@ type SafeParseResult<H extends PluginLifecycleHooks, Result = ReturnType<ParseRe
|
|
|
40
47
|
// inspired by: https://github.com/rollup/rollup/blob/master/src/utils/PluginDriver.ts#
|
|
41
48
|
|
|
42
49
|
type Options = {
|
|
43
|
-
fabric:
|
|
50
|
+
fabric: FabricType
|
|
44
51
|
events: AsyncEventEmitter<KubbEvents>
|
|
45
52
|
/**
|
|
46
53
|
* @default Number.POSITIVE_INFINITY
|
|
@@ -48,7 +55,10 @@ type Options = {
|
|
|
48
55
|
concurrency?: number
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Parameters accepted by `PluginDriver.getFile` to resolve a generated file descriptor.
|
|
60
|
+
*/
|
|
61
|
+
export type GetFileOptions<TOptions = object> = {
|
|
52
62
|
name: string
|
|
53
63
|
mode?: KubbFile.Mode
|
|
54
64
|
extname: KubbFile.Extname
|
|
@@ -56,6 +66,15 @@ type GetFileProps<TOptions = object> = {
|
|
|
56
66
|
options?: TOptions
|
|
57
67
|
}
|
|
58
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Returns `'single'` when `fileOrFolder` has a file extension, `'split'` otherwise.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* getMode('src/gen/types.ts') // 'single'
|
|
75
|
+
* getMode('src/gen/types') // 'split'
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
59
78
|
export function getMode(fileOrFolder: string | undefined | null): KubbFile.Mode {
|
|
60
79
|
if (!fileOrFolder) {
|
|
61
80
|
return 'split'
|
|
@@ -63,7 +82,9 @@ export function getMode(fileOrFolder: string | undefined | null): KubbFile.Mode
|
|
|
63
82
|
return extname(fileOrFolder) ? 'single' : 'split'
|
|
64
83
|
}
|
|
65
84
|
|
|
66
|
-
|
|
85
|
+
const hookFirstNullCheck = (state: unknown) => !!(state as SafeParseResult<'resolveName'> | null)?.result
|
|
86
|
+
|
|
87
|
+
export class PluginDriver {
|
|
67
88
|
readonly config: Config
|
|
68
89
|
readonly options: Options
|
|
69
90
|
|
|
@@ -75,21 +96,27 @@ export class PluginManager {
|
|
|
75
96
|
adapter: Adapter | undefined = undefined
|
|
76
97
|
#studioIsOpen = false
|
|
77
98
|
|
|
78
|
-
readonly
|
|
79
|
-
readonly #usedPluginNames: Record<string, number> = {}
|
|
80
|
-
readonly #promiseManager
|
|
99
|
+
readonly plugins = new Map<string, Plugin>()
|
|
81
100
|
|
|
82
101
|
constructor(config: Config, options: Options) {
|
|
83
102
|
this.config = config
|
|
84
103
|
this.options = options
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
104
|
+
config.plugins
|
|
105
|
+
.map((plugin) => Object.assign({ buildStart() {}, buildEnd() {} }, plugin) as unknown as Plugin)
|
|
106
|
+
.filter((plugin) => {
|
|
107
|
+
if (typeof plugin.apply === 'function') {
|
|
108
|
+
return plugin.apply(config)
|
|
109
|
+
}
|
|
110
|
+
return true
|
|
111
|
+
})
|
|
112
|
+
.sort((a, b) => {
|
|
113
|
+
if (b.pre?.includes(a.name)) return 1
|
|
114
|
+
if (b.post?.includes(a.name)) return -1
|
|
115
|
+
return 0
|
|
116
|
+
})
|
|
117
|
+
.forEach((plugin) => {
|
|
118
|
+
this.plugins.set(plugin.name, plugin)
|
|
119
|
+
})
|
|
93
120
|
}
|
|
94
121
|
|
|
95
122
|
get events() {
|
|
@@ -97,16 +124,22 @@ export class PluginManager {
|
|
|
97
124
|
}
|
|
98
125
|
|
|
99
126
|
getContext<TOptions extends PluginFactoryOptions>(plugin: Plugin<TOptions>): PluginContext<TOptions> & Record<string, unknown> {
|
|
100
|
-
const
|
|
101
|
-
const pluginManager = this
|
|
127
|
+
const driver = this
|
|
102
128
|
|
|
103
129
|
const baseContext = {
|
|
104
|
-
fabric:
|
|
105
|
-
config:
|
|
130
|
+
fabric: driver.options.fabric,
|
|
131
|
+
config: driver.config,
|
|
132
|
+
get root(): string {
|
|
133
|
+
return resolve(driver.config.root, driver.config.output.path)
|
|
134
|
+
},
|
|
135
|
+
getMode(output: { path: string }): KubbFile.Mode {
|
|
136
|
+
return getMode(resolve(driver.config.root, driver.config.output.path, output.path))
|
|
137
|
+
},
|
|
138
|
+
events: driver.options.events,
|
|
106
139
|
plugin,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
140
|
+
getPlugin: driver.getPlugin.bind(driver),
|
|
141
|
+
requirePlugin: driver.requirePlugin.bind(driver),
|
|
142
|
+
driver: driver,
|
|
110
143
|
addFile: async (...files: Array<KubbFile.File>) => {
|
|
111
144
|
await this.options.fabric.addFile(...files)
|
|
112
145
|
},
|
|
@@ -114,39 +147,52 @@ export class PluginManager {
|
|
|
114
147
|
await this.options.fabric.upsertFile(...files)
|
|
115
148
|
},
|
|
116
149
|
get rootNode(): RootNode | undefined {
|
|
117
|
-
return
|
|
150
|
+
return driver.rootNode
|
|
118
151
|
},
|
|
119
152
|
get adapter(): Adapter | undefined {
|
|
120
|
-
return
|
|
153
|
+
return driver.adapter
|
|
154
|
+
},
|
|
155
|
+
get resolver() {
|
|
156
|
+
return plugin.resolver
|
|
157
|
+
},
|
|
158
|
+
get transformer() {
|
|
159
|
+
return plugin.transformer
|
|
160
|
+
},
|
|
161
|
+
warn(message: string) {
|
|
162
|
+
driver.events.emit('warn', message)
|
|
163
|
+
},
|
|
164
|
+
error(error: string | Error) {
|
|
165
|
+
driver.events.emit('error', typeof error === 'string' ? new Error(error) : error)
|
|
166
|
+
},
|
|
167
|
+
info(message: string) {
|
|
168
|
+
driver.events.emit('info', message)
|
|
121
169
|
},
|
|
122
170
|
openInStudio(options?: DevtoolsOptions) {
|
|
123
|
-
if (!
|
|
171
|
+
if (!driver.config.devtools || driver.#studioIsOpen) {
|
|
124
172
|
return
|
|
125
173
|
}
|
|
126
174
|
|
|
127
|
-
if (typeof
|
|
175
|
+
if (typeof driver.config.devtools !== 'object') {
|
|
128
176
|
throw new Error('Devtools must be an object')
|
|
129
177
|
}
|
|
130
178
|
|
|
131
|
-
if (!
|
|
179
|
+
if (!driver.rootNode || !driver.adapter) {
|
|
132
180
|
throw new Error('adapter is not defined, make sure you have set the parser in kubb.config.ts')
|
|
133
181
|
}
|
|
134
182
|
|
|
135
|
-
|
|
183
|
+
driver.#studioIsOpen = true
|
|
136
184
|
|
|
137
|
-
const studioUrl =
|
|
185
|
+
const studioUrl = driver.config.devtools?.studioUrl ?? DEFAULT_STUDIO_URL
|
|
138
186
|
|
|
139
|
-
return openInStudioFn(
|
|
187
|
+
return openInStudioFn(driver.rootNode, studioUrl, options)
|
|
140
188
|
},
|
|
141
189
|
} as unknown as PluginContext<TOptions>
|
|
142
190
|
|
|
143
191
|
const mergedExtras: Record<string, unknown> = {}
|
|
144
|
-
|
|
192
|
+
|
|
193
|
+
for (const p of this.plugins.values()) {
|
|
145
194
|
if (typeof p.inject === 'function') {
|
|
146
|
-
const result = (p.inject as (this: PluginContext
|
|
147
|
-
baseContext as unknown as PluginContext,
|
|
148
|
-
baseContext as unknown as PluginContext,
|
|
149
|
-
)
|
|
195
|
+
const result = (p.inject as (this: PluginContext) => unknown).call(baseContext as unknown as PluginContext)
|
|
150
196
|
if (result !== null && typeof result === 'object') {
|
|
151
197
|
Object.assign(mergedExtras, result)
|
|
152
198
|
}
|
|
@@ -158,12 +204,10 @@ export class PluginManager {
|
|
|
158
204
|
...mergedExtras,
|
|
159
205
|
}
|
|
160
206
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileProps<TOptions>): KubbFile.File<{ pluginName: string }> {
|
|
207
|
+
/**
|
|
208
|
+
* @deprecated use resolvers context instead
|
|
209
|
+
*/
|
|
210
|
+
getFile<TOptions = object>({ name, mode, extname, pluginName, options }: GetFileOptions<TOptions>): KubbFile.File<{ pluginName: string }> {
|
|
167
211
|
const resolvedName = mode ? (mode === 'single' ? '' : this.resolveName({ name, pluginName, type: 'file' })) : name
|
|
168
212
|
|
|
169
213
|
const path = this.resolvePath({
|
|
@@ -189,6 +233,9 @@ export class PluginManager {
|
|
|
189
233
|
}
|
|
190
234
|
}
|
|
191
235
|
|
|
236
|
+
/**
|
|
237
|
+
* @deprecated use resolvers context instead
|
|
238
|
+
*/
|
|
192
239
|
resolvePath = <TOptions = object>(params: ResolvePathParams<TOptions>): KubbFile.Path => {
|
|
193
240
|
const root = resolve(this.config.root, this.config.output.path)
|
|
194
241
|
const defaultPath = resolve(root, params.baseName)
|
|
@@ -210,7 +257,9 @@ export class PluginManager {
|
|
|
210
257
|
|
|
211
258
|
return firstResult?.result || defaultPath
|
|
212
259
|
}
|
|
213
|
-
|
|
260
|
+
/**
|
|
261
|
+
* @deprecated use resolvers context instead
|
|
262
|
+
*/
|
|
214
263
|
resolveName = (params: ResolveNameParams): string => {
|
|
215
264
|
if (params.pluginName) {
|
|
216
265
|
const names = this.hookForPluginSync({
|
|
@@ -219,9 +268,7 @@ export class PluginManager {
|
|
|
219
268
|
parameters: [params.name.trim(), params.type],
|
|
220
269
|
})
|
|
221
270
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return transformReservedWord([...uniqueNames].at(0) || params.name)
|
|
271
|
+
return transformReservedWord(names?.at(0) ?? params.name)
|
|
225
272
|
}
|
|
226
273
|
|
|
227
274
|
const name = this.hookFirstSync({
|
|
@@ -244,36 +291,32 @@ export class PluginManager {
|
|
|
244
291
|
hookName: H
|
|
245
292
|
parameters: PluginParameter<H>
|
|
246
293
|
}): Promise<Array<ReturnType<ParseResult<H>> | null>> {
|
|
247
|
-
const
|
|
294
|
+
const plugin = this.plugins.get(pluginName)
|
|
295
|
+
|
|
296
|
+
if (!plugin) {
|
|
297
|
+
return [null]
|
|
298
|
+
}
|
|
248
299
|
|
|
249
300
|
this.events.emit('plugins:hook:progress:start', {
|
|
250
301
|
hookName,
|
|
251
|
-
plugins,
|
|
302
|
+
plugins: [plugin],
|
|
252
303
|
})
|
|
253
304
|
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
parameters,
|
|
261
|
-
plugin,
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
if (result !== undefined && result !== null) {
|
|
265
|
-
items.push(result)
|
|
266
|
-
}
|
|
267
|
-
}
|
|
305
|
+
const result = await this.#execute<H>({
|
|
306
|
+
strategy: 'hookFirst',
|
|
307
|
+
hookName,
|
|
308
|
+
parameters,
|
|
309
|
+
plugin,
|
|
310
|
+
})
|
|
268
311
|
|
|
269
312
|
this.events.emit('plugins:hook:progress:end', { hookName })
|
|
270
313
|
|
|
271
|
-
return
|
|
314
|
+
return [result]
|
|
272
315
|
}
|
|
316
|
+
|
|
273
317
|
/**
|
|
274
318
|
* Run a specific hookName for plugin x.
|
|
275
319
|
*/
|
|
276
|
-
|
|
277
320
|
hookForPluginSync<H extends PluginLifecycleHooks>({
|
|
278
321
|
pluginName,
|
|
279
322
|
hookName,
|
|
@@ -283,20 +326,20 @@ export class PluginManager {
|
|
|
283
326
|
hookName: H
|
|
284
327
|
parameters: PluginParameter<H>
|
|
285
328
|
}): Array<ReturnType<ParseResult<H>>> | null {
|
|
286
|
-
const
|
|
329
|
+
const plugin = this.plugins.get(pluginName)
|
|
287
330
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
strategy: 'hookFirst',
|
|
292
|
-
hookName,
|
|
293
|
-
parameters,
|
|
294
|
-
plugin,
|
|
295
|
-
})
|
|
296
|
-
})
|
|
297
|
-
.filter((x): x is NonNullable<typeof x> => x !== null)
|
|
331
|
+
if (!plugin) {
|
|
332
|
+
return null
|
|
333
|
+
}
|
|
298
334
|
|
|
299
|
-
|
|
335
|
+
const result = this.#executeSync<H>({
|
|
336
|
+
strategy: 'hookFirst',
|
|
337
|
+
hookName,
|
|
338
|
+
parameters,
|
|
339
|
+
plugin,
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
return result !== null ? [result] : []
|
|
300
343
|
}
|
|
301
344
|
|
|
302
345
|
/**
|
|
@@ -311,9 +354,10 @@ export class PluginManager {
|
|
|
311
354
|
parameters: PluginParameter<H>
|
|
312
355
|
skipped?: ReadonlySet<Plugin> | null
|
|
313
356
|
}): Promise<SafeParseResult<H>> {
|
|
314
|
-
const plugins =
|
|
315
|
-
|
|
316
|
-
|
|
357
|
+
const plugins: Array<Plugin> = []
|
|
358
|
+
for (const plugin of this.plugins.values()) {
|
|
359
|
+
if (hookName in plugin && (skipped ? !skipped.has(plugin) : true)) plugins.push(plugin)
|
|
360
|
+
}
|
|
317
361
|
|
|
318
362
|
this.events.emit('plugins:hook:progress:start', { hookName, plugins })
|
|
319
363
|
|
|
@@ -333,7 +377,7 @@ export class PluginManager {
|
|
|
333
377
|
}
|
|
334
378
|
})
|
|
335
379
|
|
|
336
|
-
const result = await
|
|
380
|
+
const result = await hookFirst(promises, hookFirstNullCheck)
|
|
337
381
|
|
|
338
382
|
this.events.emit('plugins:hook:progress:end', { hookName })
|
|
339
383
|
|
|
@@ -353,11 +397,11 @@ export class PluginManager {
|
|
|
353
397
|
skipped?: ReadonlySet<Plugin> | null
|
|
354
398
|
}): SafeParseResult<H> | null {
|
|
355
399
|
let parseResult: SafeParseResult<H> | null = null
|
|
356
|
-
const plugins = this.#getSortedPlugins(hookName).filter((plugin) => {
|
|
357
|
-
return skipped ? !skipped.has(plugin) : true
|
|
358
|
-
})
|
|
359
400
|
|
|
360
|
-
for (const plugin of plugins) {
|
|
401
|
+
for (const plugin of this.plugins.values()) {
|
|
402
|
+
if (!(hookName in plugin)) continue
|
|
403
|
+
if (skipped?.has(plugin)) continue
|
|
404
|
+
|
|
361
405
|
parseResult = {
|
|
362
406
|
result: this.#executeSync<H>({
|
|
363
407
|
strategy: 'hookFirst',
|
|
@@ -368,9 +412,7 @@ export class PluginManager {
|
|
|
368
412
|
plugin,
|
|
369
413
|
} as SafeParseResult<H>
|
|
370
414
|
|
|
371
|
-
if (parseResult
|
|
372
|
-
break
|
|
373
|
-
}
|
|
415
|
+
if (parseResult.result != null) break
|
|
374
416
|
}
|
|
375
417
|
|
|
376
418
|
return parseResult
|
|
@@ -386,7 +428,10 @@ export class PluginManager {
|
|
|
386
428
|
hookName: H
|
|
387
429
|
parameters?: Parameters<RequiredPluginLifecycle[H]> | undefined
|
|
388
430
|
}): Promise<Awaited<TOutput>[]> {
|
|
389
|
-
const plugins =
|
|
431
|
+
const plugins: Array<Plugin> = []
|
|
432
|
+
for (const plugin of this.plugins.values()) {
|
|
433
|
+
if (hookName in plugin) plugins.push(plugin)
|
|
434
|
+
}
|
|
390
435
|
this.events.emit('plugins:hook:progress:start', { hookName, plugins })
|
|
391
436
|
|
|
392
437
|
const pluginStartTimes = new Map<Plugin, number>()
|
|
@@ -403,13 +448,11 @@ export class PluginManager {
|
|
|
403
448
|
}
|
|
404
449
|
})
|
|
405
450
|
|
|
406
|
-
const results = await
|
|
407
|
-
concurrency: this.options.concurrency,
|
|
408
|
-
})
|
|
451
|
+
const results = await hookParallel(promises, this.options.concurrency)
|
|
409
452
|
|
|
410
453
|
results.forEach((result, index) => {
|
|
411
454
|
if (isPromiseRejectedResult<Error>(result)) {
|
|
412
|
-
const plugin =
|
|
455
|
+
const plugin = plugins[index]
|
|
413
456
|
|
|
414
457
|
if (plugin) {
|
|
415
458
|
const startTime = pluginStartTimes.get(plugin) ?? performance.now()
|
|
@@ -438,7 +481,10 @@ export class PluginManager {
|
|
|
438
481
|
* Chains plugins
|
|
439
482
|
*/
|
|
440
483
|
async hookSeq<H extends PluginLifecycleHooks>({ hookName, parameters }: { hookName: H; parameters?: PluginParameter<H> }): Promise<void> {
|
|
441
|
-
const plugins =
|
|
484
|
+
const plugins: Array<Plugin> = []
|
|
485
|
+
for (const plugin of this.plugins.values()) {
|
|
486
|
+
if (hookName in plugin) plugins.push(plugin)
|
|
487
|
+
}
|
|
442
488
|
this.events.emit('plugins:hook:progress:start', { hookName, plugins })
|
|
443
489
|
|
|
444
490
|
const promises = plugins.map((plugin) => {
|
|
@@ -451,67 +497,28 @@ export class PluginManager {
|
|
|
451
497
|
})
|
|
452
498
|
})
|
|
453
499
|
|
|
454
|
-
await
|
|
500
|
+
await hookSeq(promises)
|
|
455
501
|
|
|
456
502
|
this.events.emit('plugins:hook:progress:end', { hookName })
|
|
457
503
|
}
|
|
458
504
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
return plugins.filter((plugin) => hookName in plugin)
|
|
464
|
-
}
|
|
465
|
-
// TODO add test case for sorting with pre/post
|
|
466
|
-
|
|
467
|
-
return plugins
|
|
468
|
-
.map((plugin) => {
|
|
469
|
-
if (plugin.pre) {
|
|
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
|
-
}
|
|
476
|
-
|
|
477
|
-
if (missingPlugins.length > 0) {
|
|
478
|
-
throw new ValidationPluginError(`The plugin '${plugin.name}' has a pre set that references missing plugins for '${missingPlugins.join(', ')}'`)
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
return plugin
|
|
483
|
-
})
|
|
484
|
-
.sort((a, b) => {
|
|
485
|
-
if (b.pre?.includes(a.name)) {
|
|
486
|
-
return 1
|
|
487
|
-
}
|
|
488
|
-
if (b.post?.includes(a.name)) {
|
|
489
|
-
return -1
|
|
490
|
-
}
|
|
491
|
-
return 0
|
|
492
|
-
})
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
getPluginByName(pluginName: string): Plugin | undefined {
|
|
496
|
-
const plugins = [...this.#plugins]
|
|
497
|
-
|
|
498
|
-
return plugins.find((item) => item.name === pluginName)
|
|
505
|
+
getPlugin<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined
|
|
506
|
+
getPlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(pluginName: string): Plugin<TOptions> | undefined
|
|
507
|
+
getPlugin(pluginName: string): Plugin | undefined {
|
|
508
|
+
return this.plugins.get(pluginName) as Plugin | undefined
|
|
499
509
|
}
|
|
500
510
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
return corePlugin ? [corePlugin] : []
|
|
511
|
+
/**
|
|
512
|
+
* Like `getPlugin` but throws a descriptive error when the plugin is not found.
|
|
513
|
+
*/
|
|
514
|
+
requirePlugin<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Plugin<Kubb.PluginRegistry[TName]>
|
|
515
|
+
requirePlugin<TOptions extends PluginFactoryOptions = PluginFactoryOptions>(pluginName: string): Plugin<TOptions>
|
|
516
|
+
requirePlugin(pluginName: string): Plugin {
|
|
517
|
+
const plugin = this.plugins.get(pluginName)
|
|
518
|
+
if (!plugin) {
|
|
519
|
+
throw new Error(`[kubb] Plugin "${pluginName}" is required but not found. Make sure it is included in your Kubb config.`)
|
|
512
520
|
}
|
|
513
|
-
|
|
514
|
-
return pluginByPluginName
|
|
521
|
+
return plugin
|
|
515
522
|
}
|
|
516
523
|
|
|
517
524
|
/**
|
|
@@ -647,22 +654,4 @@ export class PluginManager {
|
|
|
647
654
|
return null
|
|
648
655
|
}
|
|
649
656
|
}
|
|
650
|
-
|
|
651
|
-
#parse(plugin: UserPlugin): Plugin {
|
|
652
|
-
const usedPluginNames = this.#usedPluginNames
|
|
653
|
-
|
|
654
|
-
setUniqueName(plugin.name, usedPluginNames)
|
|
655
|
-
|
|
656
|
-
const usageCount = usedPluginNames[plugin.name]
|
|
657
|
-
if (usageCount && usageCount > 1) {
|
|
658
|
-
throw new ValidationPluginError(
|
|
659
|
-
`Duplicate plugin "${plugin.name}" detected. Each plugin can only be used once. Use a different configuration instead of adding multiple instances of the same plugin.`,
|
|
660
|
-
)
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
return {
|
|
664
|
-
install() {},
|
|
665
|
-
...plugin,
|
|
666
|
-
} as unknown as Plugin
|
|
667
|
-
}
|
|
668
657
|
}
|