@kubb/core 5.0.0-beta.17 → 5.0.0-beta.18

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/mocks.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_PluginDriver = require("./PluginDriver-C5hyNJfM.cjs");
2
+ const require_PluginDriver = require("./PluginDriver-Bc-k8EUQ.cjs");
3
3
  let node_path = require("node:path");
4
4
  let _kubb_ast = require("@kubb/ast");
5
5
  //#region src/mocks.ts
package/dist/mocks.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as __name } from "./chunk--u3MIqq1.js";
2
- import { H as NormalizedPlugin, K as PluginFactoryOptions, P as PluginDriver, bt as AdapterFactoryOptions, j as Generator, r as Config, yt as Adapter } from "./createKubb-ZgT1MTxG.js";
2
+ import { H as NormalizedPlugin, K as PluginFactoryOptions, P as PluginDriver, bt as AdapterFactoryOptions, j as Generator, r as Config, yt as Adapter } from "./createKubb-DajERI4b.js";
3
3
  import { InputNode, OperationNode, SchemaNode, Visitor } from "@kubb/ast";
4
4
 
5
5
  //#region src/mocks.d.ts
package/dist/mocks.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import { n as applyHookResult, r as FileManager, t as PluginDriver } from "./PluginDriver-CT33kVoQ.js";
2
+ import { n as applyHookResult, r as FileManager, t as PluginDriver } from "./PluginDriver-T4-THx8t.js";
3
3
  import { resolve } from "node:path";
4
4
  import { transform } from "@kubb/ast";
5
5
  //#region src/mocks.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/core",
3
- "version": "5.0.0-beta.17",
3
+ "version": "5.0.0-beta.18",
4
4
  "description": "Core engine for Kubb's plugin-based code generation system. Provides the plugin driver, file manager, defineConfig, and build orchestration used by every Kubb plugin.",
5
5
  "keywords": [
6
6
  "code-generator",
@@ -58,14 +58,14 @@
58
58
  "dependencies": {
59
59
  "fflate": "^0.8.2",
60
60
  "tinyexec": "^1.1.2",
61
- "@kubb/ast": "5.0.0-beta.17"
61
+ "@kubb/ast": "5.0.0-beta.18"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@internals/utils": "0.0.0",
65
- "@kubb/renderer-jsx": "5.0.0-beta.17"
65
+ "@kubb/renderer-jsx": "5.0.0-beta.18"
66
66
  },
67
67
  "peerDependencies": {
68
- "@kubb/renderer-jsx": "5.0.0-beta.17"
68
+ "@kubb/renderer-jsx": "5.0.0-beta.18"
69
69
  },
70
70
  "size-limit": [
71
71
  {
@@ -99,6 +99,10 @@ export class FileManager {
99
99
  this.clear()
100
100
  }
101
101
 
102
+ [Symbol.dispose](): void {
103
+ this.dispose()
104
+ }
105
+
102
106
  /**
103
107
  * All stored files, sorted by path length (shorter paths first).
104
108
  */
@@ -302,6 +302,10 @@ export class PluginDriver {
302
302
  this.inputStreamNode = undefined
303
303
  }
304
304
 
305
+ [Symbol.dispose](): void {
306
+ this.dispose()
307
+ }
308
+
305
309
  #trackHookListener(event: keyof KubbHooks, handler: (...args: never[]) => void | Promise<void>): void {
306
310
  let handlers = this.#hookListeners.get(event)
307
311
  if (!handlers) {
@@ -467,7 +471,13 @@ export async function applyHookResult<TElement = unknown>(
467
471
  }
468
472
 
469
473
  const renderer = rendererFactory()
470
- await renderer.render(result)
471
- driver.fileManager.upsert(...renderer.files)
474
+ if (renderer.stream) {
475
+ for await (const file of renderer.stream(result)) {
476
+ driver.fileManager.upsert(file)
477
+ }
478
+ } else {
479
+ await renderer.render(result)
480
+ driver.fileManager.upsert(...renderer.files)
481
+ }
472
482
  renderer.unmount()
473
483
  }
package/src/createKubb.ts CHANGED
@@ -778,6 +778,7 @@ type SetupResult = {
778
778
  storage: Storage
779
779
  config: Config
780
780
  dispose: () => void
781
+ [Symbol.dispose](): void
781
782
  }
782
783
 
783
784
  /**
@@ -975,12 +976,15 @@ async function setup(userConfig: UserConfig, options: SetupOptions = {}): Promis
975
976
  hooks,
976
977
  driver,
977
978
  storage,
978
- dispose: () => {
979
- driver.dispose()
980
- for (const [event, handler] of middlewareListeners) {
981
- hooks.off(event, handler as never)
982
- }
983
- },
979
+ dispose,
980
+ [Symbol.dispose]: dispose,
981
+ }
982
+
983
+ function dispose() {
984
+ driver.dispose()
985
+ for (const [event, handler] of middlewareListeners) {
986
+ hooks.off(event, handler as never)
987
+ }
984
988
  }
985
989
  }
986
990
 
@@ -1202,7 +1206,10 @@ async function runPluginAstHooks(plugin: NormalizedPlugin, context: GeneratorCon
1202
1206
  await Promise.all(
1203
1207
  generators
1204
1208
  .filter((gen) => gen.schema)
1205
- .map((gen) => Promise.resolve(gen.schema!(transformedNode, ctx)).then((result) => applyHookResult(result, driver, resolveRenderer(gen)))),
1209
+ .map(async (gen) => {
1210
+ const result = await gen.schema!(transformedNode, ctx)
1211
+ return applyHookResult(result, driver, resolveRenderer(gen))
1212
+ }),
1206
1213
  )
1207
1214
 
1208
1215
  await driver.hooks.emit('kubb:generate:schema', transformedNode, ctx)
@@ -1223,7 +1230,10 @@ async function runPluginAstHooks(plugin: NormalizedPlugin, context: GeneratorCon
1223
1230
  await Promise.all(
1224
1231
  generators
1225
1232
  .filter((gen) => gen.operation)
1226
- .map((gen) => Promise.resolve(gen.operation!(transformedNode, ctx)).then((result) => applyHookResult(result, driver, resolveRenderer(gen)))),
1233
+ .map(async (gen) => {
1234
+ const result = await gen.operation!(transformedNode, ctx)
1235
+ return applyHookResult(result, driver, resolveRenderer(gen))
1236
+ }),
1227
1237
  )
1228
1238
 
1229
1239
  await driver.hooks.emit('kubb:generate:operation', transformedNode, ctx)
@@ -1245,6 +1255,7 @@ async function runPluginAstHooks(plugin: NormalizedPlugin, context: GeneratorCon
1245
1255
  }
1246
1256
 
1247
1257
  async function safeBuild(setupResult: SetupResult): Promise<BuildOutput> {
1258
+ using _cleanup = setupResult
1248
1259
  const { driver, hooks, storage } = setupResult
1249
1260
 
1250
1261
  const failedPlugins = new Set<{ plugin: Plugin; error: Error }>()
@@ -1455,8 +1466,6 @@ async function safeBuild(setupResult: SetupResult): Promise<BuildOutput> {
1455
1466
  error: error as Error,
1456
1467
  storage,
1457
1468
  }
1458
- } finally {
1459
- setupResult.dispose()
1460
1469
  }
1461
1470
  }
1462
1471
 
@@ -3,37 +3,47 @@ import type { FileNode } from '@kubb/ast'
3
3
  /**
4
4
  * Minimal interface any Kubb renderer must satisfy.
5
5
  *
6
- * The generic `TElement` is the type of the element the renderer accepts
7
- * e.g. `KubbReactElement` for `@kubb/renderer-jsx`, or a custom type for
8
- * your own renderer. Defaults to `unknown` so that generators which do not
9
- * care about the element type continue to work without specifying it.
10
- *
11
- * This allows core to drive rendering without a hard dependency on
12
- * `@kubb/renderer-jsx` or any specific renderer implementation.
6
+ * `TElement` is the type the renderer accepts, for example `KubbReactElement`
7
+ * for `@kubb/renderer-jsx` or a custom type for your own renderer. Defaults to
8
+ * `unknown` so generators that don't care about the element type work without
9
+ * specifying it.
13
10
  */
14
11
  export type Renderer<TElement = unknown> = {
12
+ /**
13
+ * Renders `element` and populates {@link files} with the resulting {@link FileNode} objects.
14
+ * Called once per render cycle; must resolve before {@link files} is read.
15
+ */
15
16
  render(element: TElement): Promise<void>
17
+ /**
18
+ * Tears down the renderer and releases any held resources.
19
+ * Pass an `Error` to signal a failure, a number for an exit code, or omit for a clean shutdown.
20
+ */
16
21
  unmount(error?: Error | number | null): void
22
+ /**
23
+ * Accumulated {@link FileNode} results produced by the last {@link render} call.
24
+ * Not populated when {@link stream} is implemented.
25
+ */
17
26
  readonly files: Array<FileNode>
27
+ /**
28
+ * When present, core calls this instead of {@link render} and {@link files},
29
+ * forwarding each file to `FileManager` as soon as it is ready.
30
+ * Implementing this method enables per-file streaming without buffering the full result set.
31
+ */
32
+ stream?(element: TElement): AsyncIterable<FileNode>
18
33
  }
19
34
 
20
35
  /**
21
- * A factory function that produces a fresh {@link Renderer} per render.
36
+ * A factory function that produces a fresh {@link Renderer} per render cycle.
22
37
  *
23
38
  * Generators use this to declare which renderer handles their output.
24
39
  */
25
40
  export type RendererFactory<TElement = unknown> = () => Renderer<TElement>
26
41
 
27
42
  /**
28
- * Creates a renderer factory for use in generator definitions.
29
- *
30
- * Wrap your renderer factory function with this helper to register it as the
31
- * renderer for a generator. Core will call this factory once per render cycle
32
- * to obtain a fresh renderer instance.
43
+ * Wraps a renderer factory for use in generator definitions.
33
44
  *
34
45
  * @example
35
46
  * ```ts
36
- * // packages/renderer-jsx/src/index.ts
37
47
  * export const jsxRenderer = createRenderer(() => {
38
48
  * const runtime = new Runtime()
39
49
  * return {
@@ -42,14 +52,6 @@ export type RendererFactory<TElement = unknown> = () => Renderer<TElement>
42
52
  * unmount(error) { runtime.unmount(error) },
43
53
  * }
44
54
  * })
45
- *
46
- * // packages/plugin-zod/src/generators/zodGenerator.tsx
47
- * import { jsxRenderer } from '@kubb/renderer-jsx'
48
- * export const zodGenerator = defineGenerator<PluginZod>({
49
- * name: 'zod',
50
- * renderer: jsxRenderer,
51
- * schema(node, options) { return <File ...>...</File> },
52
- * })
53
55
  * ```
54
56
  */
55
57
  export function createRenderer<TElement = unknown>(factory: RendererFactory<TElement>): RendererFactory<TElement> {