@kubb/core 5.0.0-beta.19 → 5.0.0-beta.20
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-DXp767s2.cjs → KubbDriver-BXSnJ3qM.cjs} +546 -102
- package/dist/KubbDriver-BXSnJ3qM.cjs.map +1 -0
- package/dist/{PluginDriver-uNex0SAr.js → KubbDriver-Cxii_rBp.js} +522 -96
- package/dist/KubbDriver-Cxii_rBp.js.map +1 -0
- package/dist/{createKubb-BJGymYhe.d.ts → createKubb-Dcmtjqds.d.ts} +32 -62
- package/dist/index.cjs +257 -684
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +248 -675
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +9 -10
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.ts +5 -5
- package/dist/mocks.js +5 -6
- package/dist/mocks.js.map +1 -1
- package/package.json +4 -4
- package/src/{PluginDriver.ts → KubbDriver.ts} +175 -88
- package/src/constants.ts +4 -4
- package/src/createAdapter.ts +0 -8
- package/src/createKubb.ts +293 -469
- package/src/defineGenerator.ts +9 -8
- package/src/definePlugin.ts +5 -5
- package/src/defineResolver.ts +26 -40
- package/src/index.ts +1 -1
- package/src/mocks.ts +8 -8
- package/dist/PluginDriver-DXp767s2.cjs.map +0 -1
- package/dist/PluginDriver-uNex0SAr.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolve } from 'node:path'
|
|
2
|
-
import type
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
2
|
+
import { arrayToAsyncIterable, type AsyncEventEmitter, memoize, URLPath } from '@internals/utils'
|
|
3
|
+
import { createFile, createStreamInput } from '@kubb/ast'
|
|
4
|
+
import type { FileNode, InputMeta, InputNode, InputStreamNode, OperationNode, SchemaNode } from '@kubb/ast'
|
|
5
5
|
import { DEFAULT_STUDIO_URL } from './constants.ts'
|
|
6
6
|
import type { Generator } from './defineGenerator.ts'
|
|
7
7
|
import type { Plugin } from './definePlugin.ts'
|
|
@@ -13,18 +13,18 @@ import type { RendererFactory } from './createRenderer.ts'
|
|
|
13
13
|
|
|
14
14
|
import type {
|
|
15
15
|
Adapter,
|
|
16
|
+
AdapterSource,
|
|
16
17
|
Config,
|
|
17
18
|
DevtoolsOptions,
|
|
18
19
|
GeneratorContext,
|
|
19
20
|
KubbHooks,
|
|
20
21
|
KubbPluginSetupContext,
|
|
22
|
+
Middleware,
|
|
21
23
|
NormalizedPlugin,
|
|
22
24
|
PluginFactoryOptions,
|
|
23
25
|
Resolver,
|
|
24
26
|
} from './types.ts'
|
|
25
27
|
|
|
26
|
-
// inspired by: https://github.com/rollup/rollup/blob/master/src/utils/PluginDriver.ts#
|
|
27
|
-
|
|
28
28
|
type Options = {
|
|
29
29
|
hooks: AsyncEventEmitter<KubbHooks>
|
|
30
30
|
}
|
|
@@ -33,7 +33,7 @@ function enforceOrder(enforce: 'pre' | 'post' | undefined): number {
|
|
|
33
33
|
return enforce === 'pre' ? -1 : enforce === 'post' ? 1 : 0
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
export class
|
|
36
|
+
export class KubbDriver {
|
|
37
37
|
readonly config: Config
|
|
38
38
|
readonly options: Options
|
|
39
39
|
|
|
@@ -42,8 +42,8 @@ export class PluginDriver {
|
|
|
42
42
|
*
|
|
43
43
|
* @example
|
|
44
44
|
* ```ts
|
|
45
|
-
*
|
|
46
|
-
*
|
|
45
|
+
* KubbDriver.getMode('src/gen/types.ts') // 'single'
|
|
46
|
+
* KubbDriver.getMode('src/gen/types') // 'split'
|
|
47
47
|
* ```
|
|
48
48
|
*/
|
|
49
49
|
static getMode(fileOrFolder: string | undefined | null): 'single' | 'split' {
|
|
@@ -51,17 +51,32 @@ export class PluginDriver {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
* The
|
|
55
|
-
*
|
|
54
|
+
* The streaming `InputStreamNode` produced by the adapter.
|
|
55
|
+
* Always set after adapter setup — parse-only adapters are wrapped automatically.
|
|
56
56
|
*/
|
|
57
|
-
inputNode:
|
|
57
|
+
inputNode: InputStreamNode | undefined = undefined
|
|
58
|
+
adapter: Adapter | undefined = undefined
|
|
58
59
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
60
|
+
* Studio session state, kept together so `dispose()` can reset it atomically.
|
|
61
|
+
*
|
|
62
|
+
* - `source` holds the raw adapter source so `adapter.parse()` can be called lazily.
|
|
63
|
+
* Intentionally outlives the build; cleared by `dispose()`.
|
|
64
|
+
* - `isOpen` prevents opening the studio more than once per build.
|
|
65
|
+
* - `inputNode` caches the parse promise so `adapter.parse()` is called at most once
|
|
66
|
+
* per studio session, even when `openInStudio()` is called multiple times.
|
|
61
67
|
*/
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
#studio: { source: AdapterSource | undefined; isOpen: boolean; inputNode: Promise<InputNode> | undefined } = {
|
|
69
|
+
source: undefined,
|
|
70
|
+
isOpen: false,
|
|
71
|
+
inputNode: undefined,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Register middleware hooks after all plugin hooks are registered.
|
|
75
|
+
// Because AsyncEventEmitter calls listeners in registration order,
|
|
76
|
+
// middleware hooks for any event fire after all plugin hooks for that event.
|
|
77
|
+
// Handlers are tracked so they can be removed after each build (disposeMiddleware),
|
|
78
|
+
// preventing accumulation when multiple configs share the same hooks instance.
|
|
79
|
+
#middlewareListeners: Array<[keyof KubbHooks & string, (...args: never[]) => void | Promise<void>]> = []
|
|
65
80
|
|
|
66
81
|
/**
|
|
67
82
|
* Central file store for all generated files.
|
|
@@ -76,7 +91,7 @@ export class PluginDriver {
|
|
|
76
91
|
* Tracks which plugins have generators registered via `addGenerator()` (event-based path).
|
|
77
92
|
* Used by the build loop to decide whether to emit generator events for a given plugin.
|
|
78
93
|
*/
|
|
79
|
-
readonly #
|
|
94
|
+
readonly #eventGeneratorPlugins = new Set<string>()
|
|
80
95
|
readonly #resolvers = new Map<string, Resolver>()
|
|
81
96
|
readonly #defaultResolvers = new Map<string, Resolver>()
|
|
82
97
|
readonly #hookListeners = new Map<keyof KubbHooks, Set<(...args: never[]) => void | Promise<void>>>()
|
|
@@ -84,23 +99,38 @@ export class PluginDriver {
|
|
|
84
99
|
constructor(config: Config, options: Options) {
|
|
85
100
|
this.config = config
|
|
86
101
|
this.options = options
|
|
87
|
-
config.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
102
|
+
this.adapter = config.adapter
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async setup() {
|
|
106
|
+
const normalized: NormalizedPlugin[] = this.config.plugins.map((rawPlugin) => this.#normalizePlugin(rawPlugin as Plugin))
|
|
107
|
+
|
|
108
|
+
normalized.sort((a, b) => {
|
|
109
|
+
if (b.dependencies?.includes(a.name)) return -1
|
|
110
|
+
if (a.dependencies?.includes(b.name)) return 1
|
|
111
|
+
|
|
112
|
+
return enforceOrder(a.enforce) - enforceOrder(b.enforce)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
for (const plugin of normalized) {
|
|
116
|
+
if (plugin.apply) {
|
|
117
|
+
plugin.apply(this.config)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.#registerPlugin(plugin)
|
|
121
|
+
this.plugins.set(plugin.name, plugin)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (this.config.middleware) {
|
|
125
|
+
for (const middleware of this.config.middleware) {
|
|
126
|
+
for (const event of Object.keys(middleware.hooks) as Array<keyof KubbHooks & string>) {
|
|
127
|
+
this.#registerMiddleware(event, middleware.hooks)
|
|
92
128
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// enforce: 'pre' plugins run first, 'post' plugins run last
|
|
99
|
-
return enforceOrder(a.enforce) - enforceOrder(b.enforce)
|
|
100
|
-
})
|
|
101
|
-
.forEach((plugin) => {
|
|
102
|
-
this.plugins.set(plugin.name, plugin)
|
|
103
|
-
})
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (this.config.adapter) {
|
|
132
|
+
await this.#registerAdapter(this.config.adapter)
|
|
133
|
+
}
|
|
104
134
|
}
|
|
105
135
|
|
|
106
136
|
get hooks() {
|
|
@@ -111,16 +141,59 @@ export class PluginDriver {
|
|
|
111
141
|
* Creates an `NormalizedPlugin` from a hook-style plugin and registers
|
|
112
142
|
* its lifecycle handlers on the `AsyncEventEmitter`.
|
|
113
143
|
*/
|
|
114
|
-
#normalizePlugin(
|
|
115
|
-
const
|
|
116
|
-
name:
|
|
117
|
-
dependencies:
|
|
118
|
-
enforce:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
144
|
+
#normalizePlugin(plugin: Plugin): NormalizedPlugin {
|
|
145
|
+
const normalized: NormalizedPlugin = {
|
|
146
|
+
name: plugin.name,
|
|
147
|
+
dependencies: plugin.dependencies,
|
|
148
|
+
enforce: plugin.enforce,
|
|
149
|
+
hooks: plugin.hooks,
|
|
150
|
+
options: plugin.options ?? { output: { path: '.' }, exclude: [], override: [] },
|
|
151
|
+
} as NormalizedPlugin
|
|
152
|
+
|
|
153
|
+
if ('apply' in plugin && typeof plugin.apply === 'function') {
|
|
154
|
+
normalized.apply = plugin.apply as (config: Config) => boolean
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return normalized
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async #registerAdapter(adapter: Adapter) {
|
|
161
|
+
const source = inputToAdapterSource(this.config)
|
|
162
|
+
this.#studio.source = source
|
|
163
|
+
|
|
164
|
+
if (adapter.stream) {
|
|
165
|
+
this.inputNode = await adapter.stream(source)
|
|
166
|
+
|
|
167
|
+
await this.hooks.emit('kubb:debug', {
|
|
168
|
+
date: new Date(),
|
|
169
|
+
logs: [`✓ Adapter '${adapter.name}' producing input stream`],
|
|
170
|
+
})
|
|
171
|
+
} else {
|
|
172
|
+
// Adapter does not implement stream() — eagerly parse and wrap in a
|
|
173
|
+
// reusable AsyncIterable so the rest of the pipeline stays stream-only.
|
|
174
|
+
const inputNode = await adapter.parse(source)
|
|
175
|
+
this.inputNode = createStreamInput(arrayToAsyncIterable(inputNode.schemas), arrayToAsyncIterable(inputNode.operations), inputNode.meta)
|
|
176
|
+
|
|
177
|
+
await this.hooks.emit('kubb:debug', {
|
|
178
|
+
date: new Date(),
|
|
179
|
+
logs: [
|
|
180
|
+
`✓ Adapter '${adapter.name}' resolved InputNode (wrapped as stream)`,
|
|
181
|
+
` • Schemas: ${inputNode.schemas.length}`,
|
|
182
|
+
` • Operations: ${inputNode.operations.length}`,
|
|
183
|
+
],
|
|
184
|
+
})
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
#registerMiddleware<K extends keyof KubbHooks & string>(event: K, middlewareHooks: Middleware['hooks']) {
|
|
189
|
+
const handler = middlewareHooks[event]
|
|
190
|
+
|
|
191
|
+
if (!handler) {
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
this.hooks.on(event, handler)
|
|
196
|
+
this.#middlewareListeners.push([event, handler as (...args: never[]) => void | Promise<void>])
|
|
124
197
|
}
|
|
125
198
|
|
|
126
199
|
/**
|
|
@@ -138,8 +211,8 @@ export class PluginDriver {
|
|
|
138
211
|
*
|
|
139
212
|
* @internal
|
|
140
213
|
*/
|
|
141
|
-
|
|
142
|
-
const { hooks } =
|
|
214
|
+
#registerPlugin(plugin: NormalizedPlugin): void {
|
|
215
|
+
const { hooks } = plugin
|
|
143
216
|
|
|
144
217
|
if (!hooks) return
|
|
145
218
|
|
|
@@ -150,21 +223,21 @@ export class PluginDriver {
|
|
|
150
223
|
const setupHandler = (globalCtx: KubbPluginSetupContext) => {
|
|
151
224
|
const pluginCtx: KubbPluginSetupContext = {
|
|
152
225
|
...globalCtx,
|
|
153
|
-
options:
|
|
226
|
+
options: plugin.options ?? {},
|
|
154
227
|
addGenerator: (gen) => {
|
|
155
|
-
this.registerGenerator(
|
|
228
|
+
this.registerGenerator(plugin.name, gen)
|
|
156
229
|
},
|
|
157
230
|
setResolver: (resolver) => {
|
|
158
|
-
this.setPluginResolver(
|
|
231
|
+
this.setPluginResolver(plugin.name, resolver)
|
|
159
232
|
},
|
|
160
233
|
setTransformer: (visitor) => {
|
|
161
|
-
|
|
234
|
+
plugin.transformer = visitor
|
|
162
235
|
},
|
|
163
236
|
setRenderer: (renderer) => {
|
|
164
|
-
|
|
237
|
+
plugin.renderer = renderer
|
|
165
238
|
},
|
|
166
239
|
setOptions: (opts) => {
|
|
167
|
-
|
|
240
|
+
plugin.options = { ...plugin.options, ...opts }
|
|
168
241
|
},
|
|
169
242
|
injectFile: (userFileNode) => {
|
|
170
243
|
this.fileManager.add(createFile(userFileNode))
|
|
@@ -261,7 +334,7 @@ export class PluginDriver {
|
|
|
261
334
|
this.#trackHookListener('kubb:generate:operations', operationsHandler as (...args: never[]) => void | Promise<void>)
|
|
262
335
|
}
|
|
263
336
|
|
|
264
|
-
this.#
|
|
337
|
+
this.#eventGeneratorPlugins.add(pluginName)
|
|
265
338
|
}
|
|
266
339
|
|
|
267
340
|
/**
|
|
@@ -271,8 +344,8 @@ export class PluginDriver {
|
|
|
271
344
|
* Used by the build loop to decide whether to walk the AST and emit generator events
|
|
272
345
|
* for a plugin that has no static `plugin.generators`.
|
|
273
346
|
*/
|
|
274
|
-
|
|
275
|
-
return this.#
|
|
347
|
+
hasEventGenerators(pluginName: string): boolean {
|
|
348
|
+
return this.#eventGeneratorPlugins.has(pluginName)
|
|
276
349
|
}
|
|
277
350
|
|
|
278
351
|
/**
|
|
@@ -287,18 +360,23 @@ export class PluginDriver {
|
|
|
287
360
|
this.hooks.off(event, handler as never)
|
|
288
361
|
}
|
|
289
362
|
}
|
|
363
|
+
|
|
290
364
|
this.#hookListeners.clear()
|
|
291
|
-
this.#
|
|
365
|
+
this.#eventGeneratorPlugins.clear()
|
|
292
366
|
// Release resolver closures — the driver is rebuilt for each build() call
|
|
293
367
|
// so there is no value in retaining these maps after disposal.
|
|
294
368
|
this.#resolvers.clear()
|
|
295
369
|
this.#defaultResolvers.clear()
|
|
296
|
-
// Release the parsed adapter graph and
|
|
297
|
-
//
|
|
298
|
-
// any FileNodes the caller needs to inspect.
|
|
370
|
+
// Release the FileNode cache, parsed adapter graph, and studio state so
|
|
371
|
+
// memory is reclaimed between builds. The returned `BuildOutput.files`
|
|
372
|
+
// array still references any FileNodes the caller needs to inspect.
|
|
299
373
|
this.fileManager.dispose()
|
|
300
374
|
this.inputNode = undefined
|
|
301
|
-
this
|
|
375
|
+
this.#studio = { source: undefined, isOpen: false, inputNode: undefined }
|
|
376
|
+
|
|
377
|
+
for (const [event, handler] of this.#middlewareListeners) {
|
|
378
|
+
this.hooks.off(event, handler as never)
|
|
379
|
+
}
|
|
302
380
|
}
|
|
303
381
|
|
|
304
382
|
[Symbol.dispose](): void {
|
|
@@ -314,19 +392,10 @@ export class PluginDriver {
|
|
|
314
392
|
handlers.add(handler)
|
|
315
393
|
}
|
|
316
394
|
|
|
317
|
-
#
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
const resolver = defineResolver<PluginFactoryOptions>(() => ({
|
|
324
|
-
name: 'default',
|
|
325
|
-
pluginName,
|
|
326
|
-
}))
|
|
327
|
-
this.#defaultResolvers.set(pluginName, resolver)
|
|
328
|
-
return resolver
|
|
329
|
-
}
|
|
395
|
+
#getDefaultResolver = memoize(
|
|
396
|
+
this.#defaultResolvers,
|
|
397
|
+
(pluginName: string): Resolver => defineResolver<PluginFactoryOptions>(() => ({ name: 'default', pluginName })),
|
|
398
|
+
)
|
|
330
399
|
|
|
331
400
|
/**
|
|
332
401
|
* Merges `partial` with the plugin's default resolver and stores the result.
|
|
@@ -334,7 +403,7 @@ export class PluginDriver {
|
|
|
334
403
|
* get the up-to-date resolver without going through `getResolver()`.
|
|
335
404
|
*/
|
|
336
405
|
setPluginResolver(pluginName: string, partial: Partial<Resolver>): void {
|
|
337
|
-
const defaultResolver = this.#
|
|
406
|
+
const defaultResolver = this.#getDefaultResolver(pluginName)
|
|
338
407
|
const merged = { ...defaultResolver, ...partial }
|
|
339
408
|
this.#resolvers.set(pluginName, merged)
|
|
340
409
|
const plugin = this.plugins.get(pluginName)
|
|
@@ -352,19 +421,19 @@ export class PluginDriver {
|
|
|
352
421
|
getResolver<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Kubb.PluginRegistry[TName]['resolver']
|
|
353
422
|
getResolver<TResolver extends Resolver = Resolver>(pluginName: string): TResolver
|
|
354
423
|
getResolver(pluginName: string): Resolver {
|
|
355
|
-
return this.#resolvers.get(pluginName) ?? this.plugins.get(pluginName)?.resolver ?? this.#
|
|
424
|
+
return this.#resolvers.get(pluginName) ?? this.plugins.get(pluginName)?.resolver ?? this.#getDefaultResolver(pluginName)
|
|
356
425
|
}
|
|
357
426
|
|
|
358
427
|
getContext<TOptions extends PluginFactoryOptions>(plugin: NormalizedPlugin<TOptions>): GeneratorContext<TOptions> & Record<string, unknown> {
|
|
359
428
|
const driver = this
|
|
360
429
|
|
|
361
|
-
|
|
430
|
+
return {
|
|
362
431
|
config: driver.config,
|
|
363
432
|
get root(): string {
|
|
364
433
|
return resolve(driver.config.root, driver.config.output.path)
|
|
365
434
|
},
|
|
366
435
|
getMode(output: { path: string }): 'single' | 'split' {
|
|
367
|
-
return
|
|
436
|
+
return KubbDriver.getMode(resolve(driver.config.root, driver.config.output.path, output.path))
|
|
368
437
|
},
|
|
369
438
|
hooks: driver.hooks,
|
|
370
439
|
plugin,
|
|
@@ -378,9 +447,8 @@ export class PluginDriver {
|
|
|
378
447
|
upsertFile: async (...files: Array<FileNode>) => {
|
|
379
448
|
driver.fileManager.upsert(...files)
|
|
380
449
|
},
|
|
381
|
-
get
|
|
382
|
-
|
|
383
|
-
return { kind: 'Input' as const, schemas: [], operations: [], meta: driver.inputStreamNode?.meta }
|
|
450
|
+
get meta(): InputMeta {
|
|
451
|
+
return driver.inputNode?.meta ?? { circularNames: [], enumNames: [] }
|
|
384
452
|
},
|
|
385
453
|
get adapter(): Adapter | undefined {
|
|
386
454
|
return driver.adapter
|
|
@@ -400,8 +468,8 @@ export class PluginDriver {
|
|
|
400
468
|
info(message: string) {
|
|
401
469
|
driver.hooks.emit('kubb:info', { message })
|
|
402
470
|
},
|
|
403
|
-
openInStudio(options?: DevtoolsOptions) {
|
|
404
|
-
if (!driver.config.devtools || driver.#
|
|
471
|
+
async openInStudio(options?: DevtoolsOptions) {
|
|
472
|
+
if (!driver.config.devtools || driver.#studio.isOpen) {
|
|
405
473
|
return
|
|
406
474
|
}
|
|
407
475
|
|
|
@@ -409,19 +477,19 @@ export class PluginDriver {
|
|
|
409
477
|
throw new Error('Devtools must be an object')
|
|
410
478
|
}
|
|
411
479
|
|
|
412
|
-
if (!driver.
|
|
480
|
+
if (!driver.adapter || !driver.#studio.source) {
|
|
413
481
|
throw new Error('adapter is not defined, make sure you have set the parser in kubb.config.ts')
|
|
414
482
|
}
|
|
415
483
|
|
|
416
|
-
driver.#
|
|
484
|
+
driver.#studio.isOpen = true
|
|
417
485
|
|
|
418
486
|
const studioUrl = driver.config.devtools?.studioUrl ?? DEFAULT_STUDIO_URL
|
|
487
|
+
driver.#studio.inputNode ??= Promise.resolve(driver.adapter.parse(driver.#studio.source))
|
|
488
|
+
const inputNode = await driver.#studio.inputNode
|
|
419
489
|
|
|
420
|
-
return openInStudioFn(
|
|
490
|
+
return openInStudioFn(inputNode, studioUrl, options)
|
|
421
491
|
},
|
|
422
492
|
} as unknown as GeneratorContext<TOptions>
|
|
423
|
-
|
|
424
|
-
return baseContext
|
|
425
493
|
}
|
|
426
494
|
|
|
427
495
|
getPlugin<TName extends keyof Kubb.PluginRegistry>(pluginName: TName): Plugin<Kubb.PluginRegistry[TName]> | undefined
|
|
@@ -460,7 +528,7 @@ export function applyHookResult<TElement = unknown>({
|
|
|
460
528
|
rendererFactory,
|
|
461
529
|
}: {
|
|
462
530
|
result: TElement | Array<FileNode> | void
|
|
463
|
-
driver:
|
|
531
|
+
driver: KubbDriver
|
|
464
532
|
rendererFactory?: RendererFactory<TElement>
|
|
465
533
|
}): void | Promise<void> {
|
|
466
534
|
if (!result) return
|
|
@@ -492,9 +560,28 @@ async function applyAsyncRender<TElement>({
|
|
|
492
560
|
}: {
|
|
493
561
|
renderer: { render(el: TElement): Promise<void>; files: ReadonlyArray<FileNode>; unmount(): void }
|
|
494
562
|
result: TElement
|
|
495
|
-
driver:
|
|
563
|
+
driver: KubbDriver
|
|
496
564
|
}): Promise<void> {
|
|
497
565
|
await renderer.render(result)
|
|
498
566
|
driver.fileManager.upsert(...renderer.files)
|
|
499
567
|
renderer.unmount()
|
|
500
568
|
}
|
|
569
|
+
|
|
570
|
+
function inputToAdapterSource(config: Config): AdapterSource {
|
|
571
|
+
const input = config.input
|
|
572
|
+
if (!input) {
|
|
573
|
+
throw new Error('[kubb] input is required when using an adapter. Provide input.path or input.data in your config.')
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if ('data' in input) {
|
|
577
|
+
return { type: 'data', data: input.data }
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (new URLPath(input.path).isURL) {
|
|
581
|
+
return { type: 'path', path: input.path }
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const resolved = resolve(config.root, input.path)
|
|
585
|
+
|
|
586
|
+
return { type: 'path', path: resolved }
|
|
587
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -16,14 +16,14 @@ export const DEFAULT_BANNER = 'simple' as const
|
|
|
16
16
|
export const DEFAULT_EXTENSION: Record<FileNode['extname'], FileNode['extname'] | ''> = { '.ts': '.ts' }
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Number of file writes to batch in parallel during `flushPendingFiles`.
|
|
20
20
|
*/
|
|
21
|
-
export const
|
|
21
|
+
export const STREAM_FLUSH_EVERY = 50
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* Number of schema/operation nodes to dispatch concurrently during generation.
|
|
25
25
|
*/
|
|
26
|
-
export const
|
|
26
|
+
export const SCHEMA_PARALLEL = 8
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Numeric log-level thresholds used internally to compare verbosity.
|
package/src/createAdapter.ts
CHANGED
|
@@ -73,14 +73,6 @@ export type Adapter<TOptions extends AdapterFactoryOptions = AdapterFactoryOptio
|
|
|
73
73
|
* Validate the document at the given path or URL.
|
|
74
74
|
*/
|
|
75
75
|
validate: (input: string, options?: { throwOnError?: boolean }) => Promise<void>
|
|
76
|
-
/**
|
|
77
|
-
* Lightweight pre-flight count of schemas and operations without parsing AST nodes.
|
|
78
|
-
* The adapter should cache the loaded document so subsequent `parse()` or `stream()` calls
|
|
79
|
-
* do not reload it.
|
|
80
|
-
*
|
|
81
|
-
* Used by the core to decide whether to use `parse()` or `stream()`.
|
|
82
|
-
*/
|
|
83
|
-
count?: (source: AdapterSource) => Promise<{ schemas: number; operations: number }>
|
|
84
76
|
/**
|
|
85
77
|
* Memory-efficient streaming variant of `parse()`.
|
|
86
78
|
*
|