@kubb/core 5.0.0-alpha.34 → 5.0.0-alpha.36
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-B_65W4fv.js +1677 -0
- package/dist/PluginDriver-B_65W4fv.js.map +1 -0
- package/dist/{PluginDriver-BBi_41VF.d.ts → PluginDriver-C9iBgYbk.d.ts} +743 -376
- package/dist/PluginDriver-CCdkwR14.cjs +1806 -0
- package/dist/PluginDriver-CCdkwR14.cjs.map +1 -0
- package/dist/hooks.d.ts +1 -1
- package/dist/index.cjs +272 -1666
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +62 -141
- package/dist/index.js +231 -1623
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +165 -0
- package/dist/mocks.cjs.map +1 -0
- package/dist/mocks.d.ts +74 -0
- package/dist/mocks.js +159 -0
- package/dist/mocks.js.map +1 -0
- package/package.json +11 -5
- package/src/FileManager.ts +1 -1
- package/src/FileProcessor.ts +1 -1
- package/src/Kubb.ts +145 -38
- package/src/PluginDriver.ts +318 -40
- package/src/constants.ts +1 -1
- package/src/{build.ts → createKubb.ts} +180 -122
- package/src/createPlugin.ts +1 -0
- package/src/createRenderer.ts +57 -0
- package/src/defineGenerator.ts +57 -84
- package/src/defineLogger.ts +2 -2
- package/src/defineParser.ts +3 -2
- package/src/definePlugin.ts +95 -0
- package/src/defineResolver.ts +1 -1
- package/src/devtools.ts +1 -1
- package/src/index.ts +7 -6
- package/src/mocks.ts +234 -0
- package/src/renderNode.ts +35 -0
- package/src/types.ts +275 -210
- package/src/utils/TreeNode.ts +1 -1
- package/src/utils/getBarrelFiles.ts +3 -3
- package/src/utils/getFunctionParams.ts +14 -7
- package/src/utils/isInputPath.ts +2 -2
- package/src/utils/packageJSON.ts +2 -3
- package/src/defineConfig.ts +0 -51
- package/src/definePresets.ts +0 -16
- package/src/renderNode.tsx +0 -28
- package/src/utils/getConfigs.ts +0 -16
- package/src/utils/getPreset.ts +0 -78
package/src/PluginDriver.ts
CHANGED
|
@@ -2,17 +2,24 @@ 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 { isPromiseRejectedResult, transformReservedWord } from '@internals/utils'
|
|
5
|
+
import type { FileNode, InputNode } from '@kubb/ast'
|
|
5
6
|
import { createFile } from '@kubb/ast'
|
|
6
|
-
import type { FileNode, InputNode } from '@kubb/ast/types'
|
|
7
7
|
import { DEFAULT_STUDIO_URL } from './constants.ts'
|
|
8
|
+
import type { Generator } from './defineGenerator.ts'
|
|
9
|
+
import { type HookStylePlugin, isHookStylePlugin } from './definePlugin.ts'
|
|
10
|
+
import { defineResolver } from './defineResolver.ts'
|
|
8
11
|
import { openInStudio as openInStudioFn } from './devtools.ts'
|
|
9
12
|
import { FileManager } from './FileManager.ts'
|
|
13
|
+
import { applyHookResult } from './renderNode.ts'
|
|
10
14
|
|
|
11
15
|
import type {
|
|
12
16
|
Adapter,
|
|
13
17
|
Config,
|
|
14
18
|
DevtoolsOptions,
|
|
15
|
-
|
|
19
|
+
Group,
|
|
20
|
+
KubbHooks,
|
|
21
|
+
KubbPluginSetupContext,
|
|
22
|
+
Output,
|
|
16
23
|
Plugin,
|
|
17
24
|
PluginContext,
|
|
18
25
|
PluginFactoryOptions,
|
|
@@ -22,6 +29,7 @@ import type {
|
|
|
22
29
|
PluginWithLifeCycle,
|
|
23
30
|
ResolveNameParams,
|
|
24
31
|
ResolvePathParams,
|
|
32
|
+
Resolver,
|
|
25
33
|
} from './types.ts'
|
|
26
34
|
import { hookFirst, hookParallel, hookSeq } from './utils/executeStrategies.ts'
|
|
27
35
|
|
|
@@ -47,7 +55,7 @@ type SafeParseResult<H extends PluginLifecycleHooks, Result = ReturnType<ParseRe
|
|
|
47
55
|
// inspired by: https://github.com/rollup/rollup/blob/master/src/utils/PluginDriver.ts#
|
|
48
56
|
|
|
49
57
|
type Options = {
|
|
50
|
-
|
|
58
|
+
hooks?: AsyncEventEmitter<KubbHooks>
|
|
51
59
|
/**
|
|
52
60
|
* @default Number.POSITIVE_INFINITY
|
|
53
61
|
*/
|
|
@@ -104,11 +112,28 @@ export class PluginDriver {
|
|
|
104
112
|
|
|
105
113
|
readonly plugins = new Map<string, Plugin>()
|
|
106
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Tracks which plugins have generators registered via `addGenerator()` (event-based path).
|
|
117
|
+
* Used by the build loop to decide whether to emit generator events for a given plugin.
|
|
118
|
+
*/
|
|
119
|
+
readonly #pluginsWithEventGenerators = new Set<string>()
|
|
120
|
+
readonly #resolvers = new Map<string, Resolver>()
|
|
121
|
+
readonly #defaultResolvers = new Map<string, Resolver>()
|
|
122
|
+
readonly #hookListeners = new Map<keyof KubbHooks, Set<(...args: never[]) => void | Promise<void>>>()
|
|
123
|
+
|
|
107
124
|
constructor(config: Config, options: Options) {
|
|
108
125
|
this.config = config
|
|
109
|
-
this.options =
|
|
126
|
+
this.options = {
|
|
127
|
+
...options,
|
|
128
|
+
hooks: options.hooks,
|
|
129
|
+
}
|
|
110
130
|
config.plugins
|
|
111
|
-
.map((
|
|
131
|
+
.map((rawPlugin) => {
|
|
132
|
+
if (isHookStylePlugin(rawPlugin)) {
|
|
133
|
+
return this.#normalizeHookStylePlugin(rawPlugin as HookStylePlugin)
|
|
134
|
+
}
|
|
135
|
+
return { ...rawPlugin, buildStart: rawPlugin.buildStart ?? (() => {}), buildEnd: rawPlugin.buildEnd ?? (() => {}) } as unknown as Plugin
|
|
136
|
+
})
|
|
112
137
|
.filter((plugin) => {
|
|
113
138
|
if (typeof plugin.apply === 'function') {
|
|
114
139
|
return plugin.apply(config)
|
|
@@ -116,8 +141,8 @@ export class PluginDriver {
|
|
|
116
141
|
return true
|
|
117
142
|
})
|
|
118
143
|
.sort((a, b) => {
|
|
119
|
-
if (b.
|
|
120
|
-
if (
|
|
144
|
+
if (b.dependencies?.includes(a.name)) return -1
|
|
145
|
+
if (a.dependencies?.includes(b.name)) return 1
|
|
121
146
|
return 0
|
|
122
147
|
})
|
|
123
148
|
.forEach((plugin) => {
|
|
@@ -125,8 +150,267 @@ export class PluginDriver {
|
|
|
125
150
|
})
|
|
126
151
|
}
|
|
127
152
|
|
|
128
|
-
get
|
|
129
|
-
|
|
153
|
+
get hooks() {
|
|
154
|
+
if (!this.options.hooks) {
|
|
155
|
+
throw new Error('hooks are not defined')
|
|
156
|
+
}
|
|
157
|
+
return this.options.hooks
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Creates a `Plugin`-compatible object from a hook-style plugin and registers
|
|
162
|
+
* its lifecycle handlers on the `AsyncEventEmitter`.
|
|
163
|
+
*
|
|
164
|
+
* The normalized plugin has an empty `buildStart` — generators registered via
|
|
165
|
+
* `addGenerator()` in `kubb:plugin:setup` are stored on `normalizedPlugin.generators`
|
|
166
|
+
* and used by `runPluginAstHooks` during the build.
|
|
167
|
+
*/
|
|
168
|
+
#normalizeHookStylePlugin(hookPlugin: HookStylePlugin): Plugin {
|
|
169
|
+
const generators: Plugin['generators'] = []
|
|
170
|
+
const driver = this
|
|
171
|
+
// The options shape is the minimal struct required by Plugin. Hook-style plugins
|
|
172
|
+
// use generators registered via addGenerator() and resolvers set via setResolver().
|
|
173
|
+
// `inject` and `resolver` are required by the Plugin type but are irrelevant for hook-style
|
|
174
|
+
// plugins: inject is a no-op and resolver is set dynamically via setResolver() in kubb:plugin:setup.
|
|
175
|
+
//
|
|
176
|
+
// `resolveName` and `resolvePath` bridge the legacy PluginDriver.resolveName/resolvePath
|
|
177
|
+
// lifecycle so that other plugins calling `driver.resolveName({ pluginName })` or
|
|
178
|
+
// `driver.getFile({ pluginName })` still get correct results from hook-style plugins.
|
|
179
|
+
const normalizedPlugin = {
|
|
180
|
+
name: hookPlugin.name,
|
|
181
|
+
dependencies: hookPlugin.dependencies,
|
|
182
|
+
options: { output: { path: '.' }, exclude: [], override: [] },
|
|
183
|
+
generators,
|
|
184
|
+
inject: () => undefined,
|
|
185
|
+
resolveName(name: string, type?: ResolveNameParams['type']) {
|
|
186
|
+
const resolver = driver.getResolver(hookPlugin.name)
|
|
187
|
+
return resolver.default(name, type)
|
|
188
|
+
},
|
|
189
|
+
resolvePath(baseName: FileNode['baseName'], pathMode?: 'single' | 'split', resolveOptions?: Record<string, unknown>) {
|
|
190
|
+
const resolver = driver.getResolver(hookPlugin.name)
|
|
191
|
+
const opts = normalizedPlugin.options as Record<string, unknown>
|
|
192
|
+
const group = resolveOptions?.group as Record<string, string> | undefined
|
|
193
|
+
return resolver.resolvePath(
|
|
194
|
+
{ baseName, pathMode, tag: group?.tag, path: group?.path },
|
|
195
|
+
{ root: resolve(driver.config.root, driver.config.output.path), output: opts.output as Output, group: opts.group as Group | undefined },
|
|
196
|
+
)
|
|
197
|
+
},
|
|
198
|
+
buildStart() {},
|
|
199
|
+
buildEnd() {},
|
|
200
|
+
} as unknown as Plugin
|
|
201
|
+
this.registerPluginHooks(hookPlugin, normalizedPlugin)
|
|
202
|
+
return normalizedPlugin
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Registers a hook-style plugin's lifecycle handlers on the shared `AsyncEventEmitter`.
|
|
207
|
+
*
|
|
208
|
+
* For `kubb:plugin:setup`, the registered listener wraps the globally emitted context with a
|
|
209
|
+
* plugin-specific one so that `addGenerator`, `setResolver`, `setTransformer`, and
|
|
210
|
+
* `setRenderer` all target the correct `normalizedPlugin` entry in the plugins map.
|
|
211
|
+
*
|
|
212
|
+
* All other hooks are iterated and registered directly as pass-through listeners.
|
|
213
|
+
* Any event key present in the global `KubbHooks` interface can be subscribed to.
|
|
214
|
+
*
|
|
215
|
+
* External tooling can subscribe to any of these events via `hooks.on(...)` to observe
|
|
216
|
+
* the plugin lifecycle without modifying plugin behavior.
|
|
217
|
+
*/
|
|
218
|
+
registerPluginHooks(hookPlugin: HookStylePlugin, normalizedPlugin: Plugin): void {
|
|
219
|
+
const { hooks } = hookPlugin
|
|
220
|
+
|
|
221
|
+
// kubb:plugin:setup gets special treatment: the globally emitted context is wrapped with
|
|
222
|
+
// plugin-specific implementations so that addGenerator / setResolver / etc. target
|
|
223
|
+
// this plugin's normalizedPlugin entry rather than being no-ops.
|
|
224
|
+
if (hooks['kubb:plugin:setup']) {
|
|
225
|
+
const setupHandler = (globalCtx: KubbPluginSetupContext) => {
|
|
226
|
+
const pluginCtx: KubbPluginSetupContext = {
|
|
227
|
+
...globalCtx,
|
|
228
|
+
options: hookPlugin.options ?? {},
|
|
229
|
+
addGenerator: (gen) => {
|
|
230
|
+
this.registerGenerator(normalizedPlugin.name, gen)
|
|
231
|
+
},
|
|
232
|
+
setResolver: (resolver) => {
|
|
233
|
+
this.setPluginResolver(normalizedPlugin.name, resolver)
|
|
234
|
+
},
|
|
235
|
+
setTransformer: (visitor) => {
|
|
236
|
+
normalizedPlugin.transformer = visitor
|
|
237
|
+
},
|
|
238
|
+
setRenderer: (renderer) => {
|
|
239
|
+
normalizedPlugin.renderer = renderer
|
|
240
|
+
},
|
|
241
|
+
setOptions: (opts) => {
|
|
242
|
+
normalizedPlugin.options = { ...normalizedPlugin.options, ...opts }
|
|
243
|
+
},
|
|
244
|
+
injectFile: (file) => {
|
|
245
|
+
const fileNode = createFile({
|
|
246
|
+
baseName: file.baseName,
|
|
247
|
+
path: file.path,
|
|
248
|
+
sources: file.sources ?? [],
|
|
249
|
+
imports: [],
|
|
250
|
+
exports: [],
|
|
251
|
+
})
|
|
252
|
+
this.fileManager.add(fileNode)
|
|
253
|
+
},
|
|
254
|
+
}
|
|
255
|
+
return hooks['kubb:plugin:setup']!(pluginCtx)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this.hooks.on('kubb:plugin:setup', setupHandler)
|
|
259
|
+
this.#trackHookListener('kubb:plugin:setup', setupHandler as (...args: never[]) => void | Promise<void>)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// All other hooks are registered as direct pass-through listeners on the shared emitter.
|
|
263
|
+
for (const [event, handler] of Object.entries(hooks) as Array<[keyof KubbHooks, ((...args: never[]) => void | Promise<void>) | undefined]>) {
|
|
264
|
+
if (event === 'kubb:plugin:setup' || !handler) continue
|
|
265
|
+
this.hooks.on(event, handler as never)
|
|
266
|
+
this.#trackHookListener(event, handler as (...args: never[]) => void | Promise<void>)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Emits the `kubb:plugin:setup` event so that all registered hook-style plugin listeners
|
|
272
|
+
* can configure generators, resolvers, transformers and renderers before `buildStart` runs.
|
|
273
|
+
*
|
|
274
|
+
* Call this once from `safeBuild` before the plugin execution loop begins.
|
|
275
|
+
*/
|
|
276
|
+
async emitSetupHooks(): Promise<void> {
|
|
277
|
+
await this.hooks.emit('kubb:plugin:setup', {
|
|
278
|
+
config: this.config,
|
|
279
|
+
addGenerator: () => {},
|
|
280
|
+
setResolver: () => {},
|
|
281
|
+
setTransformer: () => {},
|
|
282
|
+
setRenderer: () => {},
|
|
283
|
+
setOptions: () => {},
|
|
284
|
+
injectFile: () => {},
|
|
285
|
+
updateConfig: () => {},
|
|
286
|
+
options: {},
|
|
287
|
+
})
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Registers a generator for the given plugin on the shared event emitter.
|
|
292
|
+
*
|
|
293
|
+
* The generator's `schema`, `operation`, and `operations` methods are registered as
|
|
294
|
+
* listeners on `kubb:generate:schema`, `kubb:generate:operation`, and `kubb:generate:operations`
|
|
295
|
+
* respectively. Each listener is scoped to the owning plugin via a `ctx.plugin.name` check
|
|
296
|
+
* so that generators from different plugins do not cross-fire.
|
|
297
|
+
*
|
|
298
|
+
* The renderer resolution chain is: `generator.renderer → plugin.renderer → config.renderer`.
|
|
299
|
+
* Set `generator.renderer = null` to explicitly opt out of rendering even when the plugin
|
|
300
|
+
* declares a renderer.
|
|
301
|
+
*
|
|
302
|
+
* Call this method inside `addGenerator()` (in `kubb:plugin:setup`) to wire up a generator.
|
|
303
|
+
*/
|
|
304
|
+
registerGenerator(pluginName: string, gen: Generator<any>): void {
|
|
305
|
+
const resolveRenderer = () => {
|
|
306
|
+
const plugin = this.plugins.get(pluginName)
|
|
307
|
+
return gen.renderer === null ? undefined : (gen.renderer ?? plugin?.renderer ?? this.config.renderer)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (gen.schema) {
|
|
311
|
+
const schemaHandler = async (node: Parameters<NonNullable<typeof gen.schema>>[0], ctx: Parameters<NonNullable<typeof gen.schema>>[1]) => {
|
|
312
|
+
if (ctx.plugin.name !== pluginName) return
|
|
313
|
+
const result = await gen.schema!(node, ctx)
|
|
314
|
+
await applyHookResult(result, this, resolveRenderer())
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
this.hooks.on('kubb:generate:schema', schemaHandler)
|
|
318
|
+
this.#trackHookListener('kubb:generate:schema', schemaHandler as (...args: never[]) => void | Promise<void>)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (gen.operation) {
|
|
322
|
+
const operationHandler = async (node: Parameters<NonNullable<typeof gen.operation>>[0], ctx: Parameters<NonNullable<typeof gen.operation>>[1]) => {
|
|
323
|
+
if (ctx.plugin.name !== pluginName) return
|
|
324
|
+
const result = await gen.operation!(node, ctx)
|
|
325
|
+
await applyHookResult(result, this, resolveRenderer())
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
this.hooks.on('kubb:generate:operation', operationHandler)
|
|
329
|
+
this.#trackHookListener('kubb:generate:operation', operationHandler as (...args: never[]) => void | Promise<void>)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (gen.operations) {
|
|
333
|
+
const operationsHandler = async (nodes: Parameters<NonNullable<typeof gen.operations>>[0], ctx: Parameters<NonNullable<typeof gen.operations>>[1]) => {
|
|
334
|
+
if (ctx.plugin.name !== pluginName) return
|
|
335
|
+
const result = await gen.operations!(nodes, ctx)
|
|
336
|
+
await applyHookResult(result, this, resolveRenderer())
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
this.hooks.on('kubb:generate:operations', operationsHandler)
|
|
340
|
+
this.#trackHookListener('kubb:generate:operations', operationsHandler as (...args: never[]) => void | Promise<void>)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
this.#pluginsWithEventGenerators.add(pluginName)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Returns `true` when at least one generator was registered for the given plugin
|
|
348
|
+
* via `addGenerator()` in `kubb:plugin:setup` (event-based path).
|
|
349
|
+
*
|
|
350
|
+
* Used by the build loop to decide whether to walk the AST and emit generator events
|
|
351
|
+
* for a plugin that has no static `plugin.generators`.
|
|
352
|
+
*/
|
|
353
|
+
hasRegisteredGenerators(pluginName: string): boolean {
|
|
354
|
+
return this.#pluginsWithEventGenerators.has(pluginName)
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
dispose(): void {
|
|
358
|
+
for (const [event, handlers] of this.#hookListeners) {
|
|
359
|
+
for (const handler of handlers) {
|
|
360
|
+
this.hooks.off(event, handler as never)
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
this.#hookListeners.clear()
|
|
364
|
+
this.#pluginsWithEventGenerators.clear()
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
#trackHookListener(event: keyof KubbHooks, handler: (...args: never[]) => void | Promise<void>): void {
|
|
368
|
+
let handlers = this.#hookListeners.get(event)
|
|
369
|
+
if (!handlers) {
|
|
370
|
+
handlers = new Set()
|
|
371
|
+
this.#hookListeners.set(event, handlers)
|
|
372
|
+
}
|
|
373
|
+
handlers.add(handler)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
#createDefaultResolver(pluginName: string): Resolver {
|
|
377
|
+
const existingResolver = this.#defaultResolvers.get(pluginName)
|
|
378
|
+
if (existingResolver) {
|
|
379
|
+
return existingResolver
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const resolver = defineResolver<PluginFactoryOptions>(() => ({
|
|
383
|
+
name: 'default',
|
|
384
|
+
pluginName,
|
|
385
|
+
}))
|
|
386
|
+
this.#defaultResolvers.set(pluginName, resolver)
|
|
387
|
+
return resolver
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
setPluginResolver(pluginName: string, partial: Partial<Resolver>): void {
|
|
391
|
+
const defaultResolver = this.#createDefaultResolver(pluginName)
|
|
392
|
+
const merged = { ...defaultResolver, ...partial }
|
|
393
|
+
this.#resolvers.set(pluginName, merged)
|
|
394
|
+
// Mirror the resolved resolver onto the plugin so that consumers using
|
|
395
|
+
// `getPlugin(name).resolver` get the correct resolver without going through getResolver().
|
|
396
|
+
const plugin = this.plugins.get(pluginName)
|
|
397
|
+
if (plugin) {
|
|
398
|
+
plugin.resolver = merged
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
getResolver(pluginName: string): Resolver {
|
|
403
|
+
const dynamicResolver = this.#resolvers.get(pluginName)
|
|
404
|
+
if (dynamicResolver) {
|
|
405
|
+
return dynamicResolver
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const pluginResolver = this.plugins.get(pluginName)?.resolver
|
|
409
|
+
if (pluginResolver) {
|
|
410
|
+
return pluginResolver
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return this.#createDefaultResolver(pluginName)
|
|
130
414
|
}
|
|
131
415
|
|
|
132
416
|
getContext<TOptions extends PluginFactoryOptions>(plugin: Plugin<TOptions>): PluginContext<TOptions> & Record<string, unknown> {
|
|
@@ -140,7 +424,7 @@ export class PluginDriver {
|
|
|
140
424
|
getMode(output: { path: string }): 'single' | 'split' {
|
|
141
425
|
return getMode(resolve(driver.config.root, driver.config.output.path, output.path))
|
|
142
426
|
},
|
|
143
|
-
|
|
427
|
+
hooks: driver.hooks,
|
|
144
428
|
plugin,
|
|
145
429
|
getPlugin: driver.getPlugin.bind(driver),
|
|
146
430
|
requirePlugin: driver.requirePlugin.bind(driver),
|
|
@@ -158,19 +442,19 @@ export class PluginDriver {
|
|
|
158
442
|
return driver.adapter
|
|
159
443
|
},
|
|
160
444
|
get resolver() {
|
|
161
|
-
return plugin.
|
|
445
|
+
return driver.getResolver(plugin.name)
|
|
162
446
|
},
|
|
163
447
|
get transformer() {
|
|
164
448
|
return plugin.transformer
|
|
165
449
|
},
|
|
166
450
|
warn(message: string) {
|
|
167
|
-
driver.
|
|
451
|
+
driver.hooks.emit('kubb:warn', message)
|
|
168
452
|
},
|
|
169
453
|
error(error: string | Error) {
|
|
170
|
-
driver.
|
|
454
|
+
driver.hooks.emit('kubb:error', typeof error === 'string' ? new Error(error) : error)
|
|
171
455
|
},
|
|
172
456
|
info(message: string) {
|
|
173
|
-
driver.
|
|
457
|
+
driver.hooks.emit('kubb:info', message)
|
|
174
458
|
},
|
|
175
459
|
openInStudio(options?: DevtoolsOptions) {
|
|
176
460
|
if (!driver.config.devtools || driver.#studioIsOpen) {
|
|
@@ -193,13 +477,13 @@ export class PluginDriver {
|
|
|
193
477
|
},
|
|
194
478
|
} as unknown as PluginContext<TOptions>
|
|
195
479
|
|
|
196
|
-
|
|
480
|
+
let mergedExtras: Record<string, unknown> = {}
|
|
197
481
|
|
|
198
482
|
for (const p of this.plugins.values()) {
|
|
199
483
|
if (typeof p.inject === 'function') {
|
|
200
484
|
const result = (p.inject as (this: PluginContext) => unknown).call(baseContext as unknown as PluginContext)
|
|
201
485
|
if (result !== null && typeof result === 'object') {
|
|
202
|
-
|
|
486
|
+
mergedExtras = { ...mergedExtras, ...(result as Record<string, unknown>) }
|
|
203
487
|
}
|
|
204
488
|
}
|
|
205
489
|
}
|
|
@@ -302,7 +586,7 @@ export class PluginDriver {
|
|
|
302
586
|
return [null]
|
|
303
587
|
}
|
|
304
588
|
|
|
305
|
-
this.
|
|
589
|
+
this.hooks.emit('kubb:plugins:hook:progress:start', {
|
|
306
590
|
hookName,
|
|
307
591
|
plugins: [plugin],
|
|
308
592
|
})
|
|
@@ -314,7 +598,7 @@ export class PluginDriver {
|
|
|
314
598
|
plugin,
|
|
315
599
|
})
|
|
316
600
|
|
|
317
|
-
this.
|
|
601
|
+
this.hooks.emit('kubb:plugins:hook:progress:end', { hookName })
|
|
318
602
|
|
|
319
603
|
return [result]
|
|
320
604
|
}
|
|
@@ -364,7 +648,7 @@ export class PluginDriver {
|
|
|
364
648
|
if (hookName in plugin && (skipped ? !skipped.has(plugin) : true)) plugins.push(plugin)
|
|
365
649
|
}
|
|
366
650
|
|
|
367
|
-
this.
|
|
651
|
+
this.hooks.emit('kubb:plugins:hook:progress:start', { hookName, plugins })
|
|
368
652
|
|
|
369
653
|
const promises = plugins.map((plugin) => {
|
|
370
654
|
return async () => {
|
|
@@ -384,7 +668,7 @@ export class PluginDriver {
|
|
|
384
668
|
|
|
385
669
|
const result = await hookFirst(promises, hookFirstNullCheck)
|
|
386
670
|
|
|
387
|
-
this.
|
|
671
|
+
this.hooks.emit('kubb:plugins:hook:progress:end', { hookName })
|
|
388
672
|
|
|
389
673
|
return result
|
|
390
674
|
}
|
|
@@ -424,7 +708,7 @@ export class PluginDriver {
|
|
|
424
708
|
}
|
|
425
709
|
|
|
426
710
|
/**
|
|
427
|
-
* Runs all plugins in parallel based on `this.plugin` order and `
|
|
711
|
+
* Runs all plugins in parallel based on `this.plugin` order and `dependencies` settings.
|
|
428
712
|
*/
|
|
429
713
|
async hookParallel<H extends PluginLifecycleHooks, TOutput = void>({
|
|
430
714
|
hookName,
|
|
@@ -437,7 +721,7 @@ export class PluginDriver {
|
|
|
437
721
|
for (const plugin of this.plugins.values()) {
|
|
438
722
|
if (hookName in plugin) plugins.push(plugin)
|
|
439
723
|
}
|
|
440
|
-
this.
|
|
724
|
+
this.hooks.emit('kubb:plugins:hook:progress:start', { hookName, plugins })
|
|
441
725
|
|
|
442
726
|
const pluginStartTimes = new Map<Plugin, number>()
|
|
443
727
|
|
|
@@ -461,7 +745,7 @@ export class PluginDriver {
|
|
|
461
745
|
|
|
462
746
|
if (plugin) {
|
|
463
747
|
const startTime = pluginStartTimes.get(plugin) ?? performance.now()
|
|
464
|
-
this.
|
|
748
|
+
this.hooks.emit('kubb:error', result.reason, {
|
|
465
749
|
plugin,
|
|
466
750
|
hookName,
|
|
467
751
|
strategy: 'hookParallel',
|
|
@@ -472,7 +756,7 @@ export class PluginDriver {
|
|
|
472
756
|
}
|
|
473
757
|
})
|
|
474
758
|
|
|
475
|
-
this.
|
|
759
|
+
this.hooks.emit('kubb:plugins:hook:progress:end', { hookName })
|
|
476
760
|
|
|
477
761
|
return results.reduce((acc, result) => {
|
|
478
762
|
if (result.status === 'fulfilled') {
|
|
@@ -483,14 +767,14 @@ export class PluginDriver {
|
|
|
483
767
|
}
|
|
484
768
|
|
|
485
769
|
/**
|
|
486
|
-
*
|
|
770
|
+
* Execute a lifecycle hook sequentially for all plugins that implement it.
|
|
487
771
|
*/
|
|
488
772
|
async hookSeq<H extends PluginLifecycleHooks>({ hookName, parameters }: { hookName: H; parameters?: PluginParameter<H> }): Promise<void> {
|
|
489
773
|
const plugins: Array<Plugin> = []
|
|
490
774
|
for (const plugin of this.plugins.values()) {
|
|
491
775
|
if (hookName in plugin) plugins.push(plugin)
|
|
492
776
|
}
|
|
493
|
-
this.
|
|
777
|
+
this.hooks.emit('kubb:plugins:hook:progress:start', { hookName, plugins })
|
|
494
778
|
|
|
495
779
|
const promises = plugins.map((plugin) => {
|
|
496
780
|
return () =>
|
|
@@ -504,7 +788,7 @@ export class PluginDriver {
|
|
|
504
788
|
|
|
505
789
|
await hookSeq(promises)
|
|
506
790
|
|
|
507
|
-
this.
|
|
791
|
+
this.hooks.emit('kubb:plugins:hook:progress:end', { hookName })
|
|
508
792
|
}
|
|
509
793
|
|
|
510
794
|
getPlugin<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined
|
|
@@ -527,10 +811,7 @@ export class PluginDriver {
|
|
|
527
811
|
}
|
|
528
812
|
|
|
529
813
|
/**
|
|
530
|
-
*
|
|
531
|
-
* @param hookName Name of the plugin hook. Must be either in `PluginHooks` or `OutputPluginValueHooks`.
|
|
532
|
-
* @param args Arguments passed to the plugin hook.
|
|
533
|
-
* @param plugin The actual pluginObject to run.
|
|
814
|
+
* Emit hook-processing completion metadata after a plugin hook resolves.
|
|
534
815
|
*/
|
|
535
816
|
#emitProcessingEnd<H extends PluginLifecycleHooks>({
|
|
536
817
|
startTime,
|
|
@@ -547,7 +828,7 @@ export class PluginDriver {
|
|
|
547
828
|
plugin: PluginWithLifeCycle
|
|
548
829
|
parameters: unknown[] | undefined
|
|
549
830
|
}): void {
|
|
550
|
-
this.
|
|
831
|
+
this.hooks.emit('kubb:plugins:hook:processing:end', {
|
|
551
832
|
duration: Math.round(performance.now() - startTime),
|
|
552
833
|
parameters,
|
|
553
834
|
output,
|
|
@@ -575,7 +856,7 @@ export class PluginDriver {
|
|
|
575
856
|
return null
|
|
576
857
|
}
|
|
577
858
|
|
|
578
|
-
this.
|
|
859
|
+
this.hooks.emit('kubb:plugins:hook:processing:start', {
|
|
579
860
|
strategy,
|
|
580
861
|
hookName,
|
|
581
862
|
parameters,
|
|
@@ -593,7 +874,7 @@ export class PluginDriver {
|
|
|
593
874
|
|
|
594
875
|
return output as ReturnType<ParseResult<H>>
|
|
595
876
|
} catch (error) {
|
|
596
|
-
this.
|
|
877
|
+
this.hooks.emit('kubb:error', error as Error, {
|
|
597
878
|
plugin,
|
|
598
879
|
hookName,
|
|
599
880
|
strategy,
|
|
@@ -608,10 +889,7 @@ export class PluginDriver {
|
|
|
608
889
|
}
|
|
609
890
|
|
|
610
891
|
/**
|
|
611
|
-
*
|
|
612
|
-
* @param hookName Name of the plugin hook. Must be in `PluginHooks`.
|
|
613
|
-
* @param args Arguments passed to the plugin hook.
|
|
614
|
-
* @param plugin The actual plugin
|
|
892
|
+
* Execute a plugin lifecycle hook synchronously and return its output.
|
|
615
893
|
*/
|
|
616
894
|
#executeSync<H extends PluginLifecycleHooks>({
|
|
617
895
|
strategy,
|
|
@@ -630,7 +908,7 @@ export class PluginDriver {
|
|
|
630
908
|
return null
|
|
631
909
|
}
|
|
632
910
|
|
|
633
|
-
this.
|
|
911
|
+
this.hooks.emit('kubb:plugins:hook:processing:start', {
|
|
634
912
|
strategy,
|
|
635
913
|
hookName,
|
|
636
914
|
parameters,
|
|
@@ -649,7 +927,7 @@ export class PluginDriver {
|
|
|
649
927
|
|
|
650
928
|
return output
|
|
651
929
|
} catch (error) {
|
|
652
|
-
this.
|
|
930
|
+
this.hooks.emit('kubb:error', error as Error, {
|
|
653
931
|
plugin,
|
|
654
932
|
hookName,
|
|
655
933
|
strategy,
|
package/src/constants.ts
CHANGED