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

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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./chunk--u3MIqq1.js";
2
- import { a as definePlugin, c as DEFAULT_STUDIO_URL, i as defineResolver, l as logLevel, n as applyHookResult, o as DEFAULT_BANNER, r as FileManager, s as DEFAULT_EXTENSION, t as PluginDriver, u as camelCase } from "./PluginDriver-CT33kVoQ.js";
2
+ import { a as definePlugin, c as DEFAULT_STUDIO_URL, i as defineResolver, l as logLevel, n as applyHookResult, o as DEFAULT_BANNER, r as FileManager, s as DEFAULT_EXTENSION, t as PluginDriver, u as camelCase } from "./PluginDriver-uNex0SAr.js";
3
3
  import { EventEmitter } from "node:events";
4
4
  import { access, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
5
5
  import { dirname, join, resolve } from "node:path";
@@ -69,9 +69,12 @@ var AsyncEventEmitter = class {
69
69
  * await emitter.emit('build', 'petstore')
70
70
  * ```
71
71
  */
72
- async emit(eventName, ...eventArgs) {
72
+ emit(eventName, ...eventArgs) {
73
73
  const listeners = this.#emitter.listeners(eventName);
74
74
  if (listeners.length === 0) return;
75
+ return this.#emitAll(eventName, listeners, eventArgs);
76
+ }
77
+ async #emitAll(eventName, listeners, eventArgs) {
75
78
  for (const listener of listeners) try {
76
79
  await listener(...eventArgs);
77
80
  } catch (err) {
@@ -245,6 +248,19 @@ async function clean(path) {
245
248
  });
246
249
  }
247
250
  //#endregion
251
+ //#region ../../internals/utils/src/promise.ts
252
+ /** Returns `true` when `result` is a thenable `Promise`.
253
+ *
254
+ * @example
255
+ * ```ts
256
+ * isPromise(Promise.resolve(1)) // true
257
+ * isPromise(42) // false
258
+ * ```
259
+ */
260
+ function isPromise(result) {
261
+ return result !== null && result !== void 0 && typeof result["then"] === "function";
262
+ }
263
+ //#endregion
248
264
  //#region ../../internals/utils/src/reserved.ts
249
265
  /**
250
266
  * JavaScript and Java reserved words.
@@ -525,7 +541,7 @@ function createAdapter(build) {
525
541
  }
526
542
  //#endregion
527
543
  //#region package.json
528
- var version$1 = "5.0.0-beta.17";
544
+ var version$1 = "5.0.0-beta.19";
529
545
  //#endregion
530
546
  //#region src/createStorage.ts
531
547
  /**
@@ -566,7 +582,14 @@ function createStorage(build) {
566
582
  //#endregion
567
583
  //#region src/FileProcessor.ts
568
584
  function joinSources(file) {
569
- return file.sources.map((item) => extractStringsFromNodes(item.nodes)).filter(Boolean).join("\n\n");
585
+ const sources = file.sources;
586
+ if (sources.length === 0) return "";
587
+ const parts = [];
588
+ for (const source of sources) {
589
+ const s = extractStringsFromNodes(source.nodes);
590
+ if (s) parts.push(s);
591
+ }
592
+ return parts.join("\n\n");
570
593
  }
571
594
  /**
572
595
  * Converts a single file to a string using the registered parsers.
@@ -576,25 +599,19 @@ function joinSources(file) {
576
599
  */
577
600
  var FileProcessor = class {
578
601
  events = new AsyncEventEmitter();
579
- async parse(file, { parsers, extension } = {}) {
602
+ parse(file, { parsers, extension } = {}) {
580
603
  const parseExtName = extension?.[file.extname] || void 0;
581
604
  if (!parsers || !file.extname) return joinSources(file);
582
605
  const parser = parsers.get(file.extname);
583
606
  if (!parser) return joinSources(file);
584
607
  return parser.parse(file, { extname: parseExtName });
585
608
  }
586
- /**
587
- * Streams parsed files one at a time as each is processed.
588
- *
589
- * Unlike `run()`, files are yielded immediately after parsing rather than batched.
590
- * Storage writes can begin as soon as the first file is ready, keeping peak
591
- * memory proportional to one file at a time instead of the full batch.
592
- */
593
- async *stream(files, options = {}) {
609
+ *stream(files, options = {}) {
594
610
  const total = files.length;
611
+ if (total === 0) return;
595
612
  let processed = 0;
596
613
  for (const file of files) {
597
- const source = await this.parse(file, options);
614
+ const source = this.parse(file, options);
598
615
  processed++;
599
616
  yield {
600
617
  file,
@@ -607,7 +624,7 @@ var FileProcessor = class {
607
624
  }
608
625
  async run(files, options = {}) {
609
626
  await this.events.emit("start", files);
610
- for await (const { file, source, processed, total, percentage } of this.stream(files, options)) await this.events.emit("update", {
627
+ for (const { file, source, processed, total, percentage } of this.stream(files, options)) await this.events.emit("update", {
611
628
  file,
612
629
  source,
613
630
  processed,
@@ -693,6 +710,66 @@ const fsStorage = createStorage(() => ({
693
710
  }
694
711
  }));
695
712
  //#endregion
713
+ //#region \0@oxc-project+runtime@0.129.0/helpers/usingCtx.js
714
+ function _usingCtx() {
715
+ var r = "function" == typeof SuppressedError ? SuppressedError : function(r, e) {
716
+ var n = Error();
717
+ return n.name = "SuppressedError", n.error = r, n.suppressed = e, n;
718
+ };
719
+ var e = {};
720
+ var n = [];
721
+ function using(r, e) {
722
+ if (null != e) {
723
+ if (Object(e) !== e) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
724
+ if (r) var o = e[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
725
+ if (void 0 === o && (o = e[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r)) var t = o;
726
+ if ("function" != typeof o) throw new TypeError("Object is not disposable.");
727
+ t && (o = function o() {
728
+ try {
729
+ t.call(e);
730
+ } catch (r) {
731
+ return Promise.reject(r);
732
+ }
733
+ }), n.push({
734
+ v: e,
735
+ d: o,
736
+ a: r
737
+ });
738
+ } else r && n.push({
739
+ d: e,
740
+ a: r
741
+ });
742
+ return e;
743
+ }
744
+ return {
745
+ e,
746
+ u: using.bind(null, !1),
747
+ a: using.bind(null, !0),
748
+ d: function d() {
749
+ var o;
750
+ var t = this.e;
751
+ var s = 0;
752
+ function next() {
753
+ for (; o = n.pop();) try {
754
+ if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
755
+ if (o.d) {
756
+ var r = o.d.call(o.v);
757
+ if (o.a) return s |= 2, Promise.resolve(r).then(next, err);
758
+ } else s |= 1;
759
+ } catch (r) {
760
+ return err(r);
761
+ }
762
+ if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
763
+ if (t !== e) throw t;
764
+ }
765
+ function err(n) {
766
+ return t = t !== e ? new r(n, t) : n, next();
767
+ }
768
+ return next();
769
+ }
770
+ };
771
+ }
772
+ //#endregion
696
773
  //#region src/createKubb.ts
697
774
  /**
698
775
  * Builds a `Storage` view scoped to the file paths produced by the current build.
@@ -821,18 +898,9 @@ async function setup(userConfig, options = {}) {
821
898
  ` • Operations: ${operationCount}`
822
899
  ]
823
900
  });
824
- } else {
825
- driver.inputNode = await config.adapter.parse(source);
826
- await hooks.emit("kubb:debug", {
827
- date: /* @__PURE__ */ new Date(),
828
- logs: [
829
- `✓ Adapter '${config.adapter.name}' resolved InputNode`,
830
- ` • Schemas: ${driver.inputNode.schemas.length}`,
831
- ` • Operations: ${driver.inputNode.operations.length}`
832
- ]
833
- });
834
901
  }
835
- } else {
902
+ }
903
+ if (!driver.inputStreamNode) {
836
904
  driver.inputNode = await config.adapter.parse(source);
837
905
  await hooks.emit("kubb:debug", {
838
906
  date: /* @__PURE__ */ new Date(),
@@ -849,11 +917,13 @@ async function setup(userConfig, options = {}) {
849
917
  hooks,
850
918
  driver,
851
919
  storage,
852
- dispose: () => {
853
- driver.dispose();
854
- for (const [event, handler] of middlewareListeners) hooks.off(event, handler);
855
- }
920
+ dispose,
921
+ [Symbol.dispose]: dispose
856
922
  };
923
+ function dispose() {
924
+ driver.dispose();
925
+ for (const [event, handler] of middlewareListeners) hooks.off(event, handler);
926
+ }
857
927
  }
858
928
  /**
859
929
  * Single-pass fan-out for streaming mode.
@@ -866,84 +936,101 @@ async function setup(userConfig, options = {}) {
866
936
  * Each plugin still gets independent `plugin:start` / `plugin:end` events and its own
867
937
  * timing, but the schema and operation nodes are parsed only once total.
868
938
  */
869
- async function runPluginStreamHooks(inputStreamNode, entries, driver, hooks, config, pluginTimings, failedPlugins, flushPendingFiles) {
939
+ async function runPluginStreamHooks({ entries, driver, pluginTimings, failedPlugins }) {
940
+ const inputStreamNode = driver.inputStreamNode;
870
941
  function resolveRendererFor(gen, state) {
871
942
  return gen.renderer === null ? void 0 : gen.renderer ?? state.plugin.renderer ?? state.generatorContext.config.renderer;
872
943
  }
873
- const states = entries.map(({ plugin, context, hrStart }) => ({
874
- plugin,
875
- generatorContext: {
876
- ...context,
877
- resolver: driver.getResolver(plugin.name)
878
- },
879
- generators: plugin.generators ?? [],
880
- hrStart,
881
- failed: false,
882
- error: void 0
883
- }));
884
- let schemasProcessed = 0;
885
- for await (const node of inputStreamNode.schemas) {
886
- for (const state of states) {
887
- if (state.failed) continue;
888
- try {
889
- const { plugin, generatorContext, generators } = state;
890
- const { exclude, include, override } = plugin.options;
891
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
892
- const options = generatorContext.resolver.resolveOptions(transformedNode, {
893
- options: plugin.options,
894
- exclude,
895
- include,
896
- override
944
+ const states = entries.map(({ plugin, context, hrStart }) => {
945
+ const { exclude, include, override } = plugin.options;
946
+ const hasExclude = Array.isArray(exclude) && exclude.length > 0;
947
+ const hasInclude = Array.isArray(include) && include.length > 0;
948
+ const hasOverride = Array.isArray(override) && override.length > 0;
949
+ return {
950
+ plugin,
951
+ generatorContext: {
952
+ ...context,
953
+ resolver: driver.getResolver(plugin.name)
954
+ },
955
+ generators: plugin.generators ?? [],
956
+ hrStart,
957
+ failed: false,
958
+ error: void 0,
959
+ optionsAreStatic: !hasExclude && !hasInclude && !hasOverride
960
+ };
961
+ });
962
+ async function dispatchSchema(state, node) {
963
+ if (state.failed) return;
964
+ try {
965
+ const { plugin, generatorContext, generators } = state;
966
+ const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
967
+ const { exclude, include, override } = plugin.options;
968
+ const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
969
+ options: plugin.options,
970
+ exclude,
971
+ include,
972
+ override
973
+ });
974
+ if (options === null) return;
975
+ const ctx = {
976
+ ...generatorContext,
977
+ options
978
+ };
979
+ for (const gen of generators) {
980
+ if (!gen.schema) continue;
981
+ const raw = gen.schema(transformedNode, ctx);
982
+ const applied = applyHookResult({
983
+ result: isPromise(raw) ? await raw : raw,
984
+ driver,
985
+ rendererFactory: resolveRendererFor(gen, state)
897
986
  });
898
- if (options === null) continue;
899
- const ctx = {
900
- ...generatorContext,
901
- options
902
- };
903
- for (const gen of generators) {
904
- if (!gen.schema) continue;
905
- await applyHookResult(await gen.schema(transformedNode, ctx), driver, resolveRendererFor(gen, state));
906
- }
907
- await driver.hooks.emit("kubb:generate:schema", transformedNode, ctx);
908
- } catch (caughtError) {
909
- state.failed = true;
910
- state.error = caughtError;
987
+ if (isPromise(applied)) await applied;
911
988
  }
989
+ await driver.hooks.emit("kubb:generate:schema", transformedNode, ctx);
990
+ } catch (caughtError) {
991
+ state.failed = true;
992
+ state.error = caughtError;
912
993
  }
913
- schemasProcessed++;
914
- if (schemasProcessed % 50 === 0) await flushPendingFiles();
915
994
  }
916
- const collectedOperations = [];
917
- for await (const node of inputStreamNode.operations) {
918
- collectedOperations.push(node);
919
- for (const state of states) {
920
- if (state.failed) continue;
921
- try {
922
- const { plugin, generatorContext, generators } = state;
923
- const { exclude, include, override } = plugin.options;
924
- const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
925
- const options = generatorContext.resolver.resolveOptions(transformedNode, {
926
- options: plugin.options,
927
- exclude,
928
- include,
929
- override
995
+ async function dispatchOperation(state, node) {
996
+ if (state.failed) return;
997
+ try {
998
+ const { plugin, generatorContext, generators } = state;
999
+ const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
1000
+ const { exclude, include, override } = plugin.options;
1001
+ const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
1002
+ options: plugin.options,
1003
+ exclude,
1004
+ include,
1005
+ override
1006
+ });
1007
+ if (options === null) return;
1008
+ const ctx = {
1009
+ ...generatorContext,
1010
+ options
1011
+ };
1012
+ for (const gen of generators) {
1013
+ if (!gen.operation) continue;
1014
+ const raw = gen.operation(transformedNode, ctx);
1015
+ const applied = applyHookResult({
1016
+ result: isPromise(raw) ? await raw : raw,
1017
+ driver,
1018
+ rendererFactory: resolveRendererFor(gen, state)
930
1019
  });
931
- if (options === null) continue;
932
- const ctx = {
933
- ...generatorContext,
934
- options
935
- };
936
- for (const gen of generators) {
937
- if (!gen.operation) continue;
938
- await applyHookResult(await gen.operation(transformedNode, ctx), driver, resolveRendererFor(gen, state));
939
- }
940
- await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
941
- } catch (caughtError) {
942
- state.failed = true;
943
- state.error = caughtError;
1020
+ if (isPromise(applied)) await applied;
944
1021
  }
1022
+ await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
1023
+ } catch (caughtError) {
1024
+ state.failed = true;
1025
+ state.error = caughtError;
945
1026
  }
946
1027
  }
1028
+ for await (const node of inputStreamNode.schemas) await Promise.all(states.map((state) => dispatchSchema(state, node)));
1029
+ const collectedOperations = [];
1030
+ for await (const node of inputStreamNode.operations) {
1031
+ collectedOperations.push(node);
1032
+ await Promise.all(states.map((state) => dispatchOperation(state, node)));
1033
+ }
947
1034
  for (const state of states) {
948
1035
  if (!state.failed) try {
949
1036
  const { plugin, generatorContext, generators } = state;
@@ -953,7 +1040,11 @@ async function runPluginStreamHooks(inputStreamNode, entries, driver, hooks, con
953
1040
  };
954
1041
  for (const gen of generators) {
955
1042
  if (!gen.operations) continue;
956
- await applyHookResult(await gen.operations(collectedOperations, ctx), driver, resolveRendererFor(gen, state));
1043
+ await applyHookResult({
1044
+ result: await gen.operations(collectedOperations, ctx),
1045
+ driver,
1046
+ rendererFactory: resolveRendererFor(gen, state)
1047
+ });
957
1048
  }
958
1049
  await driver.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
959
1050
  } catch (caughtError) {
@@ -962,12 +1053,12 @@ async function runPluginStreamHooks(inputStreamNode, entries, driver, hooks, con
962
1053
  }
963
1054
  const duration = getElapsedMs(state.hrStart);
964
1055
  pluginTimings.set(state.plugin.name, duration);
965
- await hooks.emit("kubb:plugin:end", {
1056
+ await driver.hooks.emit("kubb:plugin:end", {
966
1057
  plugin: state.plugin,
967
1058
  duration,
968
1059
  success: !state.failed,
969
1060
  ...state.failed && state.error ? { error: state.error } : {},
970
- config,
1061
+ config: driver.config,
971
1062
  get files() {
972
1063
  return driver.fileManager.files;
973
1064
  },
@@ -977,13 +1068,22 @@ async function runPluginStreamHooks(inputStreamNode, entries, driver, hooks, con
977
1068
  plugin: state.plugin,
978
1069
  error: state.error
979
1070
  });
980
- await hooks.emit("kubb:debug", {
1071
+ await driver.hooks.emit("kubb:debug", {
981
1072
  date: /* @__PURE__ */ new Date(),
982
1073
  logs: [state.failed ? "✗ Plugin start failed" : `✓ Plugin started successfully (${formatMs(duration)})`]
983
1074
  });
984
1075
  }
985
- await flushPendingFiles();
986
1076
  }
1077
+ /**
1078
+ * Walks the AST and dispatches nodes to a plugin's direct AST hooks
1079
+ * (`schema`, `operation`, `operations`).
1080
+ *
1081
+ * When `include` contains only operation-scoped filters (`tag`, `operationId`, `path`,
1082
+ * `method`, `contentType`) and no `schemaName` filter, the function pre-computes the set
1083
+ * of top-level schema names transitively reachable from the included operations and skips
1084
+ * schemas that fall outside that set. This ensures that component schemas referenced
1085
+ * exclusively by excluded operations are not generated.
1086
+ */
987
1087
  async function runPluginAstHooks(plugin, context) {
988
1088
  const { adapter, inputNode, resolver, driver } = context;
989
1089
  const { exclude, include, override } = plugin.options;
@@ -1006,13 +1106,15 @@ async function runPluginAstHooks(plugin, context) {
1006
1106
  ]);
1007
1107
  const hasOperationBasedIncludes = include?.some(({ type }) => operationFilterTypes.has(type)) ?? false;
1008
1108
  const hasSchemaNameIncludes = include?.some(({ type }) => type === "schemaName") ?? false;
1009
- let allowedSchemaNames;
1010
- if (hasOperationBasedIncludes && !hasSchemaNameIncludes) allowedSchemaNames = collectUsedSchemaNames(inputNode.operations.filter((op) => resolver.resolveOptions(op, {
1011
- options: plugin.options,
1012
- exclude,
1013
- include,
1014
- override
1015
- }) !== null), inputNode.schemas);
1109
+ const allowedSchemaNames = (() => {
1110
+ if (!hasOperationBasedIncludes || hasSchemaNameIncludes) return void 0;
1111
+ return collectUsedSchemaNames(inputNode.operations.filter((op) => resolver.resolveOptions(op, {
1112
+ options: plugin.options,
1113
+ exclude,
1114
+ include,
1115
+ override
1116
+ }) !== null), inputNode.schemas);
1117
+ })();
1016
1118
  await walk(inputNode, {
1017
1119
  depth: "shallow",
1018
1120
  async schema(node) {
@@ -1029,7 +1131,13 @@ async function runPluginAstHooks(plugin, context) {
1029
1131
  ...generatorContext,
1030
1132
  options
1031
1133
  };
1032
- await Promise.all(generators.filter((gen) => gen.schema).map((gen) => Promise.resolve(gen.schema(transformedNode, ctx)).then((result) => applyHookResult(result, driver, resolveRenderer(gen)))));
1134
+ await Promise.all(generators.filter((gen) => gen.schema).map(async (gen) => {
1135
+ return applyHookResult({
1136
+ result: await gen.schema(transformedNode, ctx),
1137
+ driver,
1138
+ rendererFactory: resolveRenderer(gen)
1139
+ });
1140
+ }));
1033
1141
  await driver.hooks.emit("kubb:generate:schema", transformedNode, ctx);
1034
1142
  },
1035
1143
  async operation(node) {
@@ -1040,15 +1148,20 @@ async function runPluginAstHooks(plugin, context) {
1040
1148
  include,
1041
1149
  override
1042
1150
  });
1043
- if (options !== null) {
1044
- collectedOperations.push(transformedNode);
1045
- const ctx = {
1046
- ...generatorContext,
1047
- options
1048
- };
1049
- await Promise.all(generators.filter((gen) => gen.operation).map((gen) => Promise.resolve(gen.operation(transformedNode, ctx)).then((result) => applyHookResult(result, driver, resolveRenderer(gen)))));
1050
- await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
1051
- }
1151
+ if (options === null) return;
1152
+ collectedOperations.push(transformedNode);
1153
+ const ctx = {
1154
+ ...generatorContext,
1155
+ options
1156
+ };
1157
+ await Promise.all(generators.filter((gen) => gen.operation).map(async (gen) => {
1158
+ return applyHookResult({
1159
+ result: await gen.operation(transformedNode, ctx),
1160
+ driver,
1161
+ rendererFactory: resolveRenderer(gen)
1162
+ });
1163
+ }));
1164
+ await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
1052
1165
  }
1053
1166
  });
1054
1167
  if (collectedOperations.length > 0) {
@@ -1058,84 +1171,129 @@ async function runPluginAstHooks(plugin, context) {
1058
1171
  };
1059
1172
  for (const gen of generators) {
1060
1173
  if (!gen.operations) continue;
1061
- await applyHookResult(await gen.operations(collectedOperations, ctx), driver, resolveRenderer(gen));
1174
+ await applyHookResult({
1175
+ result: await gen.operations(collectedOperations, ctx),
1176
+ driver,
1177
+ rendererFactory: resolveRenderer(gen)
1178
+ });
1062
1179
  }
1063
1180
  await driver.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
1064
1181
  }
1065
1182
  }
1066
1183
  async function safeBuild(setupResult) {
1067
- const { driver, hooks, storage } = setupResult;
1068
- const failedPlugins = /* @__PURE__ */ new Set();
1069
- const pluginTimings = /* @__PURE__ */ new Map();
1070
- const config = driver.config;
1071
- const writtenPaths = /* @__PURE__ */ new Set();
1072
- const parsersMap = /* @__PURE__ */ new Map();
1073
- for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
1074
- const fileProcessor = new FileProcessor();
1075
- async function flushPendingFiles(snapshot) {
1076
- const files = driver.fileManager.files.filter((f) => !writtenPaths.has(f.path) && (!snapshot || !snapshot.has(f.path)));
1077
- if (files.length === 0) return;
1078
- await hooks.emit("kubb:debug", {
1079
- date: /* @__PURE__ */ new Date(),
1080
- logs: [`Writing ${files.length} files...`]
1081
- });
1082
- await hooks.emit("kubb:files:processing:start", { files });
1083
- const stream = fileProcessor.stream(files, {
1084
- parsers: parsersMap,
1085
- extension: config.output.extension
1086
- });
1087
- for await (const { file, source, processed, total, percentage } of stream) {
1088
- await hooks.emit("kubb:file:processing:update", {
1089
- file,
1090
- source,
1091
- processed,
1092
- total,
1093
- percentage,
1094
- config
1184
+ try {
1185
+ var _usingCtx$1 = _usingCtx();
1186
+ _usingCtx$1.u(setupResult);
1187
+ const { driver, hooks, storage } = setupResult;
1188
+ const failedPlugins = /* @__PURE__ */ new Set();
1189
+ const pluginTimings = /* @__PURE__ */ new Map();
1190
+ const config = driver.config;
1191
+ const writtenPaths = /* @__PURE__ */ new Set();
1192
+ const parsersMap = /* @__PURE__ */ new Map();
1193
+ for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
1194
+ const fileProcessor = new FileProcessor();
1195
+ async function flushPendingFiles() {
1196
+ const files = driver.fileManager.files.filter((f) => !writtenPaths.has(f.path));
1197
+ if (files.length === 0) return;
1198
+ await hooks.emit("kubb:debug", {
1199
+ date: /* @__PURE__ */ new Date(),
1200
+ logs: [`Writing ${files.length} files...`]
1201
+ });
1202
+ await hooks.emit("kubb:files:processing:start", { files });
1203
+ const stream = fileProcessor.stream(files, {
1204
+ parsers: parsersMap,
1205
+ extension: config.output.extension
1206
+ });
1207
+ for (const { file, source, processed, total, percentage } of stream) {
1208
+ await hooks.emit("kubb:file:processing:update", {
1209
+ file,
1210
+ source,
1211
+ processed,
1212
+ total,
1213
+ percentage,
1214
+ config
1215
+ });
1216
+ if (source) await storage.setItem(file.path, source);
1217
+ writtenPaths.add(file.path);
1218
+ }
1219
+ await hooks.emit("kubb:files:processing:end", { files });
1220
+ await hooks.emit("kubb:debug", {
1221
+ date: /* @__PURE__ */ new Date(),
1222
+ logs: [`✓ File write process completed for ${files.length} files`]
1095
1223
  });
1096
- if (source) await storage.setItem(file.path, source);
1097
- writtenPaths.add(file.path);
1098
1224
  }
1099
- await hooks.emit("kubb:files:processing:end", { files });
1100
- await hooks.emit("kubb:debug", {
1101
- date: /* @__PURE__ */ new Date(),
1102
- logs: [`✓ File write process completed for ${files.length} files`]
1103
- });
1104
- }
1105
- try {
1106
- await driver.emitSetupHooks();
1107
- if (driver.adapter && (driver.inputNode || driver.inputStreamNode)) await hooks.emit("kubb:build:start", {
1108
- config,
1109
- adapter: driver.adapter,
1110
- inputNode: driver.inputNode ?? {
1111
- kind: "Input",
1112
- schemas: [],
1113
- operations: [],
1114
- meta: driver.inputStreamNode?.meta
1115
- },
1116
- getPlugin: driver.getPlugin.bind(driver),
1117
- get files() {
1118
- return driver.fileManager.files;
1119
- },
1120
- upsertFile: (...files) => driver.fileManager.upsert(...files)
1121
- });
1122
- const inputStreamNode = driver.inputStreamNode;
1123
- if (inputStreamNode) {
1124
- const streamPluginEntries = [];
1125
- for (const plugin of driver.plugins.values()) {
1225
+ try {
1226
+ await driver.emitSetupHooks();
1227
+ if (driver.adapter && (driver.inputNode || driver.inputStreamNode)) await hooks.emit("kubb:build:start", {
1228
+ config,
1229
+ adapter: driver.adapter,
1230
+ inputNode: driver.inputNode ?? {
1231
+ kind: "Input",
1232
+ schemas: [],
1233
+ operations: [],
1234
+ meta: driver.inputStreamNode?.meta
1235
+ },
1236
+ getPlugin: driver.getPlugin.bind(driver),
1237
+ get files() {
1238
+ return driver.fileManager.files;
1239
+ },
1240
+ upsertFile: (...files) => driver.fileManager.upsert(...files)
1241
+ });
1242
+ if (driver.inputStreamNode) {
1243
+ const streamPluginEntries = [];
1244
+ for (const plugin of driver.plugins.values()) {
1245
+ const context = driver.getContext(plugin);
1246
+ const hrStart = process.hrtime();
1247
+ await hooks.emit("kubb:plugin:start", { plugin });
1248
+ await hooks.emit("kubb:debug", {
1249
+ date: /* @__PURE__ */ new Date(),
1250
+ logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
1251
+ });
1252
+ if (plugin.generators?.length || driver.hasRegisteredGenerators(plugin.name)) {
1253
+ streamPluginEntries.push({
1254
+ plugin,
1255
+ context,
1256
+ hrStart
1257
+ });
1258
+ continue;
1259
+ }
1260
+ const duration = getElapsedMs(hrStart);
1261
+ pluginTimings.set(plugin.name, duration);
1262
+ await hooks.emit("kubb:plugin:end", {
1263
+ plugin,
1264
+ duration,
1265
+ success: true,
1266
+ config,
1267
+ get files() {
1268
+ return driver.fileManager.files;
1269
+ },
1270
+ upsertFile: (...files) => driver.fileManager.upsert(...files)
1271
+ });
1272
+ await hooks.emit("kubb:debug", {
1273
+ date: /* @__PURE__ */ new Date(),
1274
+ logs: [`✓ Plugin started successfully (${formatMs(duration)})`]
1275
+ });
1276
+ }
1277
+ if (streamPluginEntries.length > 0) {
1278
+ await runPluginStreamHooks({
1279
+ entries: streamPluginEntries,
1280
+ driver,
1281
+ pluginTimings,
1282
+ failedPlugins
1283
+ });
1284
+ await flushPendingFiles();
1285
+ }
1286
+ } else for (const plugin of driver.plugins.values()) {
1126
1287
  const context = driver.getContext(plugin);
1127
1288
  const hrStart = process.hrtime();
1128
- await hooks.emit("kubb:plugin:start", { plugin });
1129
- await hooks.emit("kubb:debug", {
1130
- date: /* @__PURE__ */ new Date(),
1131
- logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
1132
- });
1133
- if (plugin.generators?.length || driver.hasRegisteredGenerators(plugin.name)) streamPluginEntries.push({
1134
- plugin,
1135
- context,
1136
- hrStart
1137
- });
1138
- else {
1289
+ try {
1290
+ const timestamp = /* @__PURE__ */ new Date();
1291
+ await hooks.emit("kubb:plugin:start", { plugin });
1292
+ await hooks.emit("kubb:debug", {
1293
+ date: timestamp,
1294
+ logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
1295
+ });
1296
+ if (plugin.generators?.length || driver.hasRegisteredGenerators(plugin.name)) await runPluginAstHooks(plugin, context);
1139
1297
  const duration = getElapsedMs(hrStart);
1140
1298
  pluginTimings.set(plugin.name, duration);
1141
1299
  await hooks.emit("kubb:plugin:end", {
@@ -1152,100 +1310,73 @@ async function safeBuild(setupResult) {
1152
1310
  date: /* @__PURE__ */ new Date(),
1153
1311
  logs: [`✓ Plugin started successfully (${formatMs(duration)})`]
1154
1312
  });
1313
+ } catch (caughtError) {
1314
+ const error = caughtError;
1315
+ const errorTimestamp = /* @__PURE__ */ new Date();
1316
+ const duration = getElapsedMs(hrStart);
1317
+ await hooks.emit("kubb:plugin:end", {
1318
+ plugin,
1319
+ duration,
1320
+ success: false,
1321
+ error,
1322
+ config,
1323
+ get files() {
1324
+ return driver.fileManager.files;
1325
+ },
1326
+ upsertFile: (...files) => driver.fileManager.upsert(...files)
1327
+ });
1328
+ await hooks.emit("kubb:debug", {
1329
+ date: errorTimestamp,
1330
+ logs: [
1331
+ "✗ Plugin start failed",
1332
+ ` • Plugin Name: ${plugin.name}`,
1333
+ ` • Error: ${error.constructor.name} - ${error.message}`,
1334
+ " • Stack Trace:",
1335
+ error.stack || "No stack trace available"
1336
+ ]
1337
+ });
1338
+ failedPlugins.add({
1339
+ plugin,
1340
+ error
1341
+ });
1155
1342
  }
1343
+ await flushPendingFiles();
1156
1344
  }
1157
- if (streamPluginEntries.length > 0) await runPluginStreamHooks(inputStreamNode, streamPluginEntries, driver, hooks, config, pluginTimings, failedPlugins, flushPendingFiles);
1158
- } else for (const plugin of driver.plugins.values()) {
1159
- const context = driver.getContext(plugin);
1160
- const hrStart = process.hrtime();
1161
- try {
1162
- const timestamp = /* @__PURE__ */ new Date();
1163
- await hooks.emit("kubb:plugin:start", { plugin });
1164
- await hooks.emit("kubb:debug", {
1165
- date: timestamp,
1166
- logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
1167
- });
1168
- if (plugin.generators?.length || driver.hasRegisteredGenerators(plugin.name)) await runPluginAstHooks(plugin, context);
1169
- const duration = getElapsedMs(hrStart);
1170
- pluginTimings.set(plugin.name, duration);
1171
- await hooks.emit("kubb:plugin:end", {
1172
- plugin,
1173
- duration,
1174
- success: true,
1175
- config,
1176
- get files() {
1177
- return driver.fileManager.files;
1178
- },
1179
- upsertFile: (...files) => driver.fileManager.upsert(...files)
1180
- });
1181
- await hooks.emit("kubb:debug", {
1182
- date: /* @__PURE__ */ new Date(),
1183
- logs: [`✓ Plugin started successfully (${formatMs(duration)})`]
1184
- });
1185
- } catch (caughtError) {
1186
- const error = caughtError;
1187
- const errorTimestamp = /* @__PURE__ */ new Date();
1188
- const duration = getElapsedMs(hrStart);
1189
- await hooks.emit("kubb:plugin:end", {
1190
- plugin,
1191
- duration,
1192
- success: false,
1193
- error,
1194
- config,
1195
- get files() {
1196
- return driver.fileManager.files;
1197
- },
1198
- upsertFile: (...files) => driver.fileManager.upsert(...files)
1199
- });
1200
- await hooks.emit("kubb:debug", {
1201
- date: errorTimestamp,
1202
- logs: [
1203
- "✗ Plugin start failed",
1204
- ` • Plugin Name: ${plugin.name}`,
1205
- ` • Error: ${error.constructor.name} - ${error.message}`,
1206
- " • Stack Trace:",
1207
- error.stack || "No stack trace available"
1208
- ]
1209
- });
1210
- failedPlugins.add({
1211
- plugin,
1212
- error
1213
- });
1214
- }
1345
+ await hooks.emit("kubb:plugins:end", {
1346
+ config,
1347
+ get files() {
1348
+ return driver.fileManager.files;
1349
+ },
1350
+ upsertFile: (...files) => driver.fileManager.upsert(...files)
1351
+ });
1215
1352
  await flushPendingFiles();
1353
+ const files = driver.fileManager.files;
1354
+ await hooks.emit("kubb:build:end", {
1355
+ files,
1356
+ config,
1357
+ outputDir: resolve(config.root, config.output.path)
1358
+ });
1359
+ return {
1360
+ failedPlugins,
1361
+ files,
1362
+ driver,
1363
+ pluginTimings,
1364
+ storage
1365
+ };
1366
+ } catch (error) {
1367
+ return {
1368
+ failedPlugins,
1369
+ files: [],
1370
+ driver,
1371
+ pluginTimings,
1372
+ error,
1373
+ storage
1374
+ };
1216
1375
  }
1217
- await hooks.emit("kubb:plugins:end", {
1218
- config,
1219
- get files() {
1220
- return driver.fileManager.files;
1221
- },
1222
- upsertFile: (...files) => driver.fileManager.upsert(...files)
1223
- });
1224
- await flushPendingFiles();
1225
- const files = driver.fileManager.files;
1226
- await hooks.emit("kubb:build:end", {
1227
- files,
1228
- config,
1229
- outputDir: resolve(config.root, config.output.path)
1230
- });
1231
- return {
1232
- failedPlugins,
1233
- files,
1234
- driver,
1235
- pluginTimings,
1236
- storage
1237
- };
1238
- } catch (error) {
1239
- return {
1240
- failedPlugins,
1241
- files: [],
1242
- driver,
1243
- pluginTimings,
1244
- error,
1245
- storage
1246
- };
1376
+ } catch (_) {
1377
+ _usingCtx$1.e = _;
1247
1378
  } finally {
1248
- setupResult.dispose();
1379
+ _usingCtx$1.d();
1249
1380
  }
1250
1381
  }
1251
1382
  async function build(setupResult) {
@@ -1353,15 +1484,10 @@ function createKubb(userConfig, options = {}) {
1353
1484
  //#endregion
1354
1485
  //#region src/createRenderer.ts
1355
1486
  /**
1356
- * Creates a renderer factory for use in generator definitions.
1357
- *
1358
- * Wrap your renderer factory function with this helper to register it as the
1359
- * renderer for a generator. Core will call this factory once per render cycle
1360
- * to obtain a fresh renderer instance.
1487
+ * Wraps a renderer factory for use in generator definitions.
1361
1488
  *
1362
1489
  * @example
1363
1490
  * ```ts
1364
- * // packages/renderer-jsx/src/index.ts
1365
1491
  * export const jsxRenderer = createRenderer(() => {
1366
1492
  * const runtime = new Runtime()
1367
1493
  * return {
@@ -1370,14 +1496,6 @@ function createKubb(userConfig, options = {}) {
1370
1496
  * unmount(error) { runtime.unmount(error) },
1371
1497
  * }
1372
1498
  * })
1373
- *
1374
- * // packages/plugin-zod/src/generators/zodGenerator.tsx
1375
- * import { jsxRenderer } from '@kubb/renderer-jsx'
1376
- * export const zodGenerator = defineGenerator<PluginZod>({
1377
- * name: 'zod',
1378
- * renderer: jsxRenderer,
1379
- * schema(node, options) { return <File ...>...</File> },
1380
- * })
1381
1499
  * ```
1382
1500
  */
1383
1501
  function createRenderer(factory) {