@kubb/core 5.0.0-beta.61 → 5.0.0-beta.63
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/{diagnostics-DiaUv_iK.d.ts → diagnostics-IjkPEgAO.d.ts} +41 -33
- package/dist/index.cjs +33 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -6
- package/dist/index.js +34 -47
- package/dist/index.js.map +1 -1
- package/dist/memoryStorage-CUj1hrxa.cjs.map +1 -1
- package/dist/memoryStorage-CWFzAz4o.js.map +1 -1
- package/dist/mocks.cjs +1 -1
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.ts +2 -2
- package/dist/mocks.js +1 -1
- package/dist/mocks.js.map +1 -1
- package/package.json +4 -4
- package/src/FileManager.ts +3 -3
- package/src/KubbDriver.ts +24 -33
- package/src/Transform.ts +1 -1
- package/src/createAdapter.ts +2 -2
- package/src/createKubb.ts +2 -3
- package/src/createReporter.ts +4 -4
- package/src/createStorage.ts +2 -2
- package/src/defineGenerator.ts +8 -7
- package/src/defineParser.ts +3 -2
- package/src/definePlugin.ts +8 -7
- package/src/diagnostics.ts +3 -3
- package/src/mocks.ts +1 -1
- package/src/reporters/fileReporter.ts +4 -5
- package/src/types.ts +1 -1
package/src/KubbDriver.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { resolve } from 'node:path'
|
|
|
2
2
|
import { arrayToAsyncIterable, type AsyncEventEmitter, forBatches, getElapsedMs, isPromise, memoize, Url } from '@internals/utils'
|
|
3
3
|
import * as factory from '@kubb/ast/factory'
|
|
4
4
|
import { collectUsedSchemaNames } from '@kubb/ast/utils'
|
|
5
|
-
import type { FileNode, InputMeta, InputNode, OperationNode, SchemaNode } from '@kubb/ast'
|
|
5
|
+
import type { Enforce, FileNode, InputMeta, InputNode, OperationNode, SchemaNode } from '@kubb/ast'
|
|
6
6
|
import { OPERATION_FILTER_TYPES, SCHEMA_PARALLEL } from './constants.ts'
|
|
7
7
|
import { type Diagnostic, Diagnostics, type ProblemDiagnostic } from './diagnostics.ts'
|
|
8
8
|
import type { RendererFactory } from './createRenderer.ts'
|
|
@@ -45,7 +45,7 @@ type RequirePluginContext = {
|
|
|
45
45
|
requiredBy?: string
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
function enforceOrder(enforce:
|
|
48
|
+
function enforceOrder(enforce: Enforce | undefined): number {
|
|
49
49
|
return enforce === 'pre' ? -1 : enforce === 'post' ? 1 : 0
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -108,6 +108,12 @@ export class KubbDriver {
|
|
|
108
108
|
this.#listeners.push([event, handler as HookListener<Array<unknown>, unknown>])
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Normalizes every configured plugin, orders them, and registers their lifecycle handlers.
|
|
113
|
+
* A plugin that another lists as a dependency runs first, then `enforce: 'pre'` before
|
|
114
|
+
* `'post'`. When the config has an adapter, the adapter source is resolved from the input
|
|
115
|
+
* so `run` can parse it later.
|
|
116
|
+
*/
|
|
111
117
|
async setup() {
|
|
112
118
|
const normalized: Array<NormalizedPlugin> = this.config.plugins.map((rawPlugin) => this.#normalizePlugin(rawPlugin as Plugin))
|
|
113
119
|
|
|
@@ -139,8 +145,9 @@ export class KubbDriver {
|
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
/**
|
|
142
|
-
*
|
|
143
|
-
* its lifecycle handlers
|
|
148
|
+
* Builds a `NormalizedPlugin` from a hook-style plugin, filling in default
|
|
149
|
+
* options and copying `apply` when present. Registering its lifecycle handlers
|
|
150
|
+
* on the `AsyncEventEmitter` is done separately by `#registerPlugin`.
|
|
144
151
|
*/
|
|
145
152
|
#normalizePlugin(plugin: Plugin): NormalizedPlugin {
|
|
146
153
|
const normalized: NormalizedPlugin = {
|
|
@@ -250,7 +257,7 @@ export class KubbDriver {
|
|
|
250
257
|
* Emits the `kubb:plugin:setup` event so that all registered hook-style plugin listeners
|
|
251
258
|
* can configure generators, resolvers, macros and renderers before `buildStart` runs.
|
|
252
259
|
*
|
|
253
|
-
*
|
|
260
|
+
* Called once from `run` before the plugin execution loop begins.
|
|
254
261
|
*/
|
|
255
262
|
async emitSetupHooks(): Promise<void> {
|
|
256
263
|
const noop = () => {}
|
|
@@ -282,37 +289,21 @@ export class KubbDriver {
|
|
|
282
289
|
* Call this method inside `addGenerator()` (in `kubb:plugin:setup`) to wire up a generator.
|
|
283
290
|
*/
|
|
284
291
|
registerGenerator(pluginName: string, generator: Generator): void {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if (ctx.plugin.name !== pluginName) return
|
|
288
|
-
const result = await generator.schema!(node, ctx)
|
|
289
|
-
|
|
290
|
-
await this.dispatch({ result, renderer: generator.renderer })
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
this.#trackListener('kubb:generate:schema', schemaHandler)
|
|
294
|
-
}
|
|
292
|
+
const register = <TNode>(event: keyof KubbHooks & string, method: ((node: TNode, ctx: GeneratorContext) => unknown) | undefined): void => {
|
|
293
|
+
if (!method) return
|
|
295
294
|
|
|
296
|
-
|
|
297
|
-
const operationHandler = async (node: OperationNode, ctx: GeneratorContext) => {
|
|
295
|
+
const handler = async (node: TNode, ctx: GeneratorContext) => {
|
|
298
296
|
if (ctx.plugin.name !== pluginName) return
|
|
299
|
-
|
|
300
|
-
const result = await generator.operation!(node, ctx)
|
|
297
|
+
const result = await method(node, ctx)
|
|
301
298
|
await this.dispatch({ result, renderer: generator.renderer })
|
|
302
299
|
}
|
|
303
300
|
|
|
304
|
-
this.#trackListener(
|
|
301
|
+
this.#trackListener(event, handler as HookListener<KubbHooks[typeof event], unknown>)
|
|
305
302
|
}
|
|
306
303
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const result = await generator.operations!(nodes, ctx)
|
|
311
|
-
await this.dispatch({ result, renderer: generator.renderer })
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
this.#trackListener('kubb:generate:operations', operationsHandler)
|
|
315
|
-
}
|
|
304
|
+
register('kubb:generate:schema', generator.schema)
|
|
305
|
+
register('kubb:generate:operation', generator.operation)
|
|
306
|
+
register('kubb:generate:operations', generator.operations)
|
|
316
307
|
|
|
317
308
|
this.#eventGeneratorPlugins.add(pluginName)
|
|
318
309
|
}
|
|
@@ -422,8 +413,8 @@ export class KubbDriver {
|
|
|
422
413
|
}
|
|
423
414
|
|
|
424
415
|
// Stream every node through the transform registry and into each plugin's generators.
|
|
425
|
-
//
|
|
426
|
-
// `kubb:plugin:end` directly.
|
|
416
|
+
// When there are no entries it returns early. When `inputNode` is missing it still
|
|
417
|
+
// closes out each entry's `kubb:plugin:end` directly.
|
|
427
418
|
diagnostics.push(...(await this.#runGenerators(generatorPlugins, () => processor.flush())))
|
|
428
419
|
// Wait for the last in-flight batch and write anything still pending.
|
|
429
420
|
await processor.drain()
|
|
@@ -480,8 +471,8 @@ export class KubbDriver {
|
|
|
480
471
|
* That ordering is what drives the CLI's `Plugins N/M` counter. Without it the bar would
|
|
481
472
|
* sit at the initial value until the very end of the run.
|
|
482
473
|
*
|
|
483
|
-
* When `
|
|
484
|
-
*
|
|
474
|
+
* When `this.inputNode` is `null`, every entry still gets a `kubb:plugin:end` so
|
|
475
|
+
* post-plugin listeners (the barrel writer and friends) complete.
|
|
485
476
|
*/
|
|
486
477
|
async #runGenerators(
|
|
487
478
|
entries: Array<{ plugin: NormalizedPlugin; context: Omit<GeneratorContext, 'options'>; hrStart: ReturnType<typeof process.hrtime> }>,
|
package/src/Transform.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { composeMacros, transform } from '@kubb/ast'
|
|
|
10
10
|
* leaves the tree untouched, so callers can detect a no-op by identity.
|
|
11
11
|
*
|
|
12
12
|
* Registration order matches the order setup hooks fire, which the driver has already sorted by
|
|
13
|
-
* `enforce` and dependency edges. The registry preserves that order
|
|
13
|
+
* `enforce` and dependency edges. The registry preserves that order. Macro `enforce` only reorders
|
|
14
14
|
* within a single plugin's list.
|
|
15
15
|
*/
|
|
16
16
|
export class Transform {
|
package/src/createAdapter.ts
CHANGED
|
@@ -112,12 +112,12 @@ type AdapterBuilder<T extends AdapterFactoryOptions> = (options: T['options']) =
|
|
|
112
112
|
* options,
|
|
113
113
|
* document: null,
|
|
114
114
|
* async parse(_source) {
|
|
115
|
-
* // Convert
|
|
115
|
+
* // Convert the source (path or inline data) into an InputNode.
|
|
116
116
|
* return ast.factory.createInput()
|
|
117
117
|
* },
|
|
118
118
|
* getImports: () => [],
|
|
119
119
|
* async validate() {
|
|
120
|
-
* // Throw
|
|
120
|
+
* // Throw here when the spec is invalid.
|
|
121
121
|
* },
|
|
122
122
|
* }))
|
|
123
123
|
* ```
|
package/src/createKubb.ts
CHANGED
|
@@ -74,9 +74,8 @@ type CreateKubbOptions = {
|
|
|
74
74
|
* config in the constructor, so `config` is available right away, and shares `hooks`,
|
|
75
75
|
* `storage`, and `driver` across the `setup → build` lifecycle.
|
|
76
76
|
*
|
|
77
|
-
* `createKubb` takes a plain
|
|
78
|
-
*
|
|
79
|
-
* fingerprinted and validated against the shipped JSON schema.
|
|
77
|
+
* `createKubb` takes a plain config object (the shape `defineConfig` produces),
|
|
78
|
+
* not a fluent builder.
|
|
80
79
|
*
|
|
81
80
|
* Attach event listeners to `.hooks` before calling `setup()` or `build()`.
|
|
82
81
|
*
|
package/src/createReporter.ts
CHANGED
|
@@ -44,13 +44,13 @@ export type GenerationResult = {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* Render
|
|
48
|
-
*
|
|
47
|
+
* Render settings passed alongside the {@link GenerationResult}. These are not part of the run
|
|
48
|
+
* data, such as the output verbosity.
|
|
49
49
|
*/
|
|
50
50
|
export type ReporterContext = {
|
|
51
51
|
/**
|
|
52
52
|
* Output verbosity. Use the `logLevel` constants exported from `@kubb/core`
|
|
53
|
-
* (`silent`, `error`, `warn`, `info`, `verbose
|
|
53
|
+
* (`silent`, `error`, `warn`, `info`, `verbose`).
|
|
54
54
|
*/
|
|
55
55
|
logLevel: (typeof logLevel)[keyof typeof logLevel]
|
|
56
56
|
}
|
|
@@ -71,7 +71,7 @@ export type Reporter = {
|
|
|
71
71
|
report: (result: GenerationResult, context: ReporterContext) => void | Promise<void>
|
|
72
72
|
/**
|
|
73
73
|
* Optional finalizer called once after the run's last config. The host wires it to
|
|
74
|
-
* `kubb:lifecycle:end`. {@link createReporter} closes it over the
|
|
74
|
+
* `kubb:lifecycle:end`. {@link createReporter} closes it over the values that `report` returned.
|
|
75
75
|
*/
|
|
76
76
|
drain?: (context: ReporterContext) => void | Promise<void>
|
|
77
77
|
}
|
package/src/createStorage.ts
CHANGED
|
@@ -34,8 +34,8 @@ export type Storage = {
|
|
|
34
34
|
*/
|
|
35
35
|
clear(base?: string): Promise<void>
|
|
36
36
|
/**
|
|
37
|
-
* Optional teardown hook
|
|
38
|
-
*
|
|
37
|
+
* Optional teardown hook for a backend to flush buffers, close connections,
|
|
38
|
+
* or release file locks.
|
|
39
39
|
*/
|
|
40
40
|
dispose?(): Promise<void>
|
|
41
41
|
}
|
package/src/defineGenerator.ts
CHANGED
|
@@ -9,11 +9,11 @@ import type { Resolver } from './defineResolver.ts'
|
|
|
9
9
|
import type { Config } from './types.ts'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* Context
|
|
12
|
+
* Context passed to a generator's `schema`, `operation`, and `operations` methods.
|
|
13
13
|
*
|
|
14
|
-
* The adapter
|
|
15
|
-
*
|
|
16
|
-
* filtering for
|
|
14
|
+
* The driver sets `adapter` on the context before it runs a generator, so methods can read it
|
|
15
|
+
* without a null check. `ctx.options` carries the per-node options after exclude/include/override
|
|
16
|
+
* filtering for `schema` and `operation`, or the plugin-level options for `operations`.
|
|
17
17
|
*/
|
|
18
18
|
export type GeneratorContext<TOptions extends PluginFactoryOptions = PluginFactoryOptions> = {
|
|
19
19
|
/**
|
|
@@ -109,9 +109,10 @@ export type GeneratorContext<TOptions extends PluginFactoryOptions = PluginFacto
|
|
|
109
109
|
/**
|
|
110
110
|
* Declares a named generator unit that walks the AST and emits files.
|
|
111
111
|
*
|
|
112
|
-
*
|
|
113
|
-
* JSX-based generators require a `renderer` factory.
|
|
114
|
-
* `ctx.upsertFile()` manually and return `null` to
|
|
112
|
+
* `schema` runs for each schema node and `operation` for each operation node. `operations` runs
|
|
113
|
+
* once after every operation node is walked. JSX-based generators require a `renderer` factory.
|
|
114
|
+
* Return `Array<FileNode>` directly, or call `ctx.upsertFile()` manually and return `null` to
|
|
115
|
+
* bypass rendering.
|
|
115
116
|
*
|
|
116
117
|
* @note Generators are consumed by plugins and registered via `ctx.addGenerator()` in `kubb:plugin:setup`.
|
|
117
118
|
*
|
package/src/defineParser.ts
CHANGED
|
@@ -15,8 +15,9 @@ export type Parser<TMeta extends object = object, TNode = unknown> = {
|
|
|
15
15
|
*/
|
|
16
16
|
name: string
|
|
17
17
|
/**
|
|
18
|
-
* File extensions this parser handles.
|
|
19
|
-
*
|
|
18
|
+
* File extensions this parser handles. The driver registers the parser for each
|
|
19
|
+
* extension in this list. A parser with `undefined` here is not registered, so
|
|
20
|
+
* files of an unclaimed extension fall back to joining their sources verbatim.
|
|
20
21
|
*
|
|
21
22
|
* @example
|
|
22
23
|
* `['.ts', '.js']`
|
package/src/definePlugin.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FileNode, HttpMethod, Macro, UserFileNode } from '@kubb/ast'
|
|
1
|
+
import type { Enforce, FileNode, HttpMethod, Macro, UserFileNode } from '@kubb/ast'
|
|
2
2
|
import { diagnosticCode } from './constants.ts'
|
|
3
3
|
import type { Generator } from './defineGenerator.ts'
|
|
4
4
|
import type { BannerMeta, Resolver } from './defineResolver.ts'
|
|
@@ -79,8 +79,8 @@ export type Group = {
|
|
|
79
79
|
*/
|
|
80
80
|
type: 'tag' | 'path'
|
|
81
81
|
/**
|
|
82
|
-
* Returns the subdirectory name from the group key. Defaults to the
|
|
83
|
-
*
|
|
82
|
+
* Returns the subdirectory name from the group key. Defaults to the camelCased tag for
|
|
83
|
+
* `tag` groups, or the camelCased first path segment for `path` groups.
|
|
84
84
|
*/
|
|
85
85
|
name?: (context: { group: string }) => string
|
|
86
86
|
}
|
|
@@ -169,11 +169,12 @@ type ByPath = {
|
|
|
169
169
|
|
|
170
170
|
type ByMethod = {
|
|
171
171
|
/**
|
|
172
|
-
* Filter by HTTP method: `'
|
|
172
|
+
* Filter by HTTP method: `'GET'`, `'POST'`, `'PUT'`, `'PATCH'`, `'DELETE'`, `'HEAD'`, `'OPTIONS'`, `'TRACE'`.
|
|
173
173
|
*/
|
|
174
174
|
type: 'method'
|
|
175
175
|
/**
|
|
176
|
-
* HTTP method to match
|
|
176
|
+
* HTTP method to match, as one of the `HttpMethod` values (`'GET'`, `'POST'`, `'PUT'`,
|
|
177
|
+
* `'PATCH'`, `'DELETE'`, `'HEAD'`, `'OPTIONS'`, `'TRACE'`) or a regex.
|
|
177
178
|
*/
|
|
178
179
|
pattern: HttpMethod | RegExp
|
|
179
180
|
}
|
|
@@ -347,11 +348,11 @@ export type Plugin<TFactory extends PluginFactoryOptions = PluginFactoryOptions>
|
|
|
347
348
|
*
|
|
348
349
|
* - `'pre'` runs before all normal plugins.
|
|
349
350
|
* - `'post'` runs after all normal plugins.
|
|
350
|
-
* - `undefined` (default)
|
|
351
|
+
* - `undefined` (default) runs in declaration order among normal plugins.
|
|
351
352
|
*
|
|
352
353
|
* Dependency constraints always take precedence over `enforce`.
|
|
353
354
|
*/
|
|
354
|
-
enforce?:
|
|
355
|
+
enforce?: Enforce
|
|
355
356
|
/**
|
|
356
357
|
* The options passed by the user when calling the plugin factory.
|
|
357
358
|
*/
|
package/src/diagnostics.ts
CHANGED
|
@@ -235,7 +235,7 @@ const severityStyle: Record<DiagnosticSeverity, { glyph: string; color: 'red' |
|
|
|
235
235
|
/**
|
|
236
236
|
* A {@link Diagnostic} reduced to its JSON-safe fields plus a `docsUrl`, for
|
|
237
237
|
* machine-readable output (the `--reporter json` report, the MCP tools). Drops the
|
|
238
|
-
* non-serializable `cause` and the `
|
|
238
|
+
* non-serializable `cause` and the `kind`/`duration` bookkeeping.
|
|
239
239
|
*/
|
|
240
240
|
export type SerializedDiagnostic = {
|
|
241
241
|
code: DiagnosticCode
|
|
@@ -541,8 +541,8 @@ export class Diagnostics {
|
|
|
541
541
|
}
|
|
542
542
|
|
|
543
543
|
/**
|
|
544
|
-
* Counts `problem` diagnostics by severity for the run summary. `
|
|
545
|
-
* diagnostics are ignored.
|
|
544
|
+
* Counts `problem` diagnostics by severity for the run summary. `performance` and
|
|
545
|
+
* `update` diagnostics are ignored.
|
|
546
546
|
*/
|
|
547
547
|
static count(diagnostics: ReadonlyArray<Diagnostic>): { errors: number; warnings: number; infos: number } {
|
|
548
548
|
let errors = 0
|
package/src/mocks.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { memoryStorage } from './storages/memoryStorage.ts'
|
|
|
11
11
|
import type { Adapter, AdapterFactoryOptions, Config, Generator, GeneratorContext, NormalizedPlugin, PluginFactoryOptions, RendererFactory } from './types.ts'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Creates a minimal `
|
|
14
|
+
* Creates a minimal `KubbDriver` mock for unit tests.
|
|
15
15
|
*/
|
|
16
16
|
export function createMockedPluginDriver(options: { name?: string; plugin?: NormalizedPlugin; config?: Config } = {}): KubbDriver {
|
|
17
17
|
const fileManager = new FileManager()
|
|
@@ -74,12 +74,11 @@ function buildTimingSection(report: Report): Array<string> {
|
|
|
74
74
|
* The `file` reporter. Writes a config's {@link Report} to `.kubb/kubb-<name>-<timestamp>.log` as a
|
|
75
75
|
* plain-text document: a `# <name> — <timestamp>` header, a `## Summary` with the same counts the
|
|
76
76
|
* cli and json reporters expose, a `## Problems` section in the miette block format, and a
|
|
77
|
-
* `## Timings` section. Selected with `--reporter file` (or `reporters: ['file']`)
|
|
78
|
-
* old `--debug` flag.
|
|
77
|
+
* `## Timings` section. Selected with `--reporter file` (or `reporters: ['file']`).
|
|
79
78
|
*
|
|
80
|
-
* @note
|
|
81
|
-
*
|
|
82
|
-
*
|
|
79
|
+
* @note It captures the collected diagnostics once a config finishes, not the live
|
|
80
|
+
* `kubb:info`/`kubb:plugin` event stream. Color is stripped so the file stays plain text even when
|
|
81
|
+
* the run is attached to a TTY.
|
|
83
82
|
*/
|
|
84
83
|
export const fileReporter = createReporter({
|
|
85
84
|
name: 'file',
|
package/src/types.ts
CHANGED
|
@@ -149,7 +149,7 @@ export type Config<TInput = Input> = {
|
|
|
149
149
|
*
|
|
150
150
|
* @example
|
|
151
151
|
* ```ts
|
|
152
|
-
* format: 'auto' // auto-detect
|
|
152
|
+
* format: 'auto' // auto-detect oxfmt, biome, or prettier
|
|
153
153
|
* format: 'prettier' // force prettier
|
|
154
154
|
* format: false // skip formatting
|
|
155
155
|
* ```
|