@kubb/core 5.0.0-beta.103 → 5.0.0-beta.104

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.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_usingCtx = require("./usingCtx-CO6pGcST.cjs");
2
+ const require_usingCtx = require("./usingCtx-BYOZEkiy.cjs");
3
3
  let node_async_hooks = require("node:async_hooks");
4
4
  let node_util = require("node:util");
5
5
  let node_crypto = require("node:crypto");
@@ -151,7 +151,7 @@ function randomCliColor(text) {
151
151
  }
152
152
  //#endregion
153
153
  //#region package.json
154
- var version = "5.0.0-beta.103";
154
+ var version = "5.0.0-beta.104";
155
155
  //#endregion
156
156
  //#region src/constants.ts
157
157
  /**
@@ -847,28 +847,24 @@ var Resolver = class Resolver {
847
847
  * schemas (`targetName`) import the emitted name. Names and paths go through the top-level
848
848
  * `name` and `file`, so import entries follow the plugin's conventions, and a per-call
849
849
  * `name` override wins over both.
850
+ *
851
+ * The subtree scan runs through `collectImportedRefNames`, which memoizes by node identity, so a
852
+ * schema shared across the ts, zod, and faker plugins is walked once and every plugin's resolver
853
+ * reads the same ref set instead of re-scanning it per plugin.
850
854
  */
851
855
  imports(options) {
852
856
  const { node, root, output, group, extname = ".ts", name } = options;
853
857
  const resolveName = name ?? ((schemaName) => this.name(schemaName));
854
- const seen = /* @__PURE__ */ new Set();
855
- return (0, _kubb_ast.collectSync)(node, { schema: (schemaNode) => {
856
- const schemaRef = (0, _kubb_ast.narrowSchema)(schemaNode, "ref");
857
- if (!schemaRef?.ref) return null;
858
- const schemaName = (0, _kubb_ast.resolveRefName)(schemaRef);
859
- if (!schemaName || seen.has(schemaName)) return null;
860
- seen.add(schemaName);
861
- return _kubb_ast.ast.factory.createImport({
862
- name: [resolveName(schemaName)],
863
- path: this.file({
864
- name: schemaName,
865
- extname,
866
- root,
867
- output,
868
- group
869
- }).path
870
- });
871
- } });
858
+ return (0, _kubb_ast.collectImportedRefNames)(node).map((schemaName) => _kubb_ast.ast.factory.createImport({
859
+ name: [resolveName(schemaName)],
860
+ path: this.file({
861
+ name: schemaName,
862
+ extname,
863
+ root,
864
+ output,
865
+ group
866
+ }).path
867
+ }));
872
868
  }
873
869
  /**
874
870
  * Folds each `override` over `base`, left to right, and returns a new resolver with helpers
@@ -1592,16 +1588,20 @@ var KubbDriver = class {
1592
1588
  }));
1593
1589
  }
1594
1590
  /**
1595
- * Runs schemas and operations through every plugin's generators. Each node is run
1596
- * through the plugin's macros (from `this.#transforms`) before the generator sees it,
1597
- * so plugins stay isolated and the hot path stays per-node. Schemas run before operations
1598
- * so file output stays deterministic across runs.
1599
- * A failing plugin contributes an error diagnostic so the rest of the build continues.
1600
- * Every plugin also contributes a `timing` diagnostic.
1591
+ * Runs schemas and operations through every plugin's generators. The walk is node-outer: each
1592
+ * schema is visited once and each operation once, and the node fans out to the matching
1593
+ * generators of every plugin in dependency order. A per-node cache (`createNodeCache`) is created
1594
+ * once per node and shared by all of that node's plugins, so node-derived work is computed once
1595
+ * and reused instead of recomputed per plugin. Each node still runs through the plugin's macros
1596
+ * (from `this.#transforms`) and its exclude/include/override filters before that plugin's
1597
+ * generator sees it, so plugins stay isolated. Schemas run before operations so file output
1598
+ * stays deterministic across runs. A generator with a `match` predicate that resolves `false`
1599
+ * for a node is skipped for that node, without calling `schema`/`operation`.
1601
1600
  *
1602
- * Plugins are processed one at a time, in full, so `kubb:plugin:end` fires as each one
1603
- * completes rather than all at once at the end. That ordering drives the CLI's
1604
- * `Plugins N/M` counter.
1601
+ * A failing plugin is dropped from the remaining walk, contributes an error diagnostic, and no
1602
+ * longer aborts the other plugins. `kubb:plugin:end` and each plugin's `timing` diagnostic fire
1603
+ * in dependency order once the walk finishes, driving the CLI's `Plugins N/M` counter. The
1604
+ * `operations` batch fires once per plugin after the single operation walk.
1605
1605
  *
1606
1606
  * When `this.inputNode` is `null`, every entry still gets a `kubb:plugin:end` so
1607
1607
  * post-plugin listeners (the barrel writer and friends) complete.
@@ -1639,105 +1639,133 @@ var KubbDriver = class {
1639
1639
  }) !== null);
1640
1640
  allowedSchemaNamesByPlugin.set(plugin.name, (0, _kubb_ast.collectUsedSchemaNames)(includedOps, schemas));
1641
1641
  }
1642
- for (const { plugin, context, hrStart } of entries) {
1642
+ const states = entries.map(({ plugin, context, hrStart }) => {
1643
1643
  const generatorContext = {
1644
1644
  ...context,
1645
1645
  resolver: this.getResolver(plugin.name)
1646
1646
  };
1647
1647
  const { exclude, include, override } = plugin.options;
1648
- const optionsAreStatic = !exclude?.length && !include?.length && !override?.length;
1649
- const allowedSchemaNames = allowedSchemaNamesByPlugin.get(plugin.name) ?? null;
1650
1648
  const generators = plugin.generators ?? [];
1651
- const schemaGenerators = generators.filter((generator) => generator.schema);
1652
- const operationGenerators = generators.filter((generator) => generator.operation);
1653
- const operationsGenerators = generators.filter((generator) => generator.operations);
1654
- let error = null;
1655
- const resolveForPlugin = (node) => {
1656
- const transformedNode = transforms.applyTo(plugin.name, node);
1657
- if (optionsAreStatic) return {
1658
- transformedNode,
1659
- options: plugin.options
1660
- };
1661
- const options = generatorContext.resolver.default.options(transformedNode, {
1662
- options: plugin.options,
1663
- exclude,
1664
- include,
1665
- override
1666
- });
1667
- if (options === null) return null;
1668
- return {
1669
- transformedNode,
1670
- options
1671
- };
1649
+ return {
1650
+ plugin,
1651
+ hrStart,
1652
+ generatorContext,
1653
+ exclude,
1654
+ include,
1655
+ override,
1656
+ optionsAreStatic: !exclude?.length && !include?.length && !override?.length,
1657
+ allowedSchemaNames: allowedSchemaNamesByPlugin.get(plugin.name) ?? null,
1658
+ schemaGenerators: generators.filter((generator) => generator.schema),
1659
+ operationGenerators: generators.filter((generator) => generator.operation),
1660
+ operationsGenerators: generators.filter((generator) => generator.operations),
1661
+ pluginOperations: [],
1662
+ error: null
1672
1663
  };
1673
- if (schemaGenerators.length) for (const node of schemas) {
1674
- if (error) break;
1664
+ });
1665
+ const resolveForPlugin = (state, node) => {
1666
+ const transformedNode = transforms.applyTo(state.plugin.name, node);
1667
+ if (state.optionsAreStatic) return {
1668
+ transformedNode,
1669
+ options: state.plugin.options
1670
+ };
1671
+ const options = state.generatorContext.resolver.default.options(transformedNode, {
1672
+ options: state.plugin.options,
1673
+ exclude: state.exclude,
1674
+ include: state.include,
1675
+ override: state.override
1676
+ });
1677
+ if (options === null) return null;
1678
+ return {
1679
+ transformedNode,
1680
+ options
1681
+ };
1682
+ };
1683
+ for (const node of schemas) {
1684
+ const cache = require_usingCtx.createNodeCache();
1685
+ for (const state of states) {
1686
+ if (state.error || !state.schemaGenerators.length) continue;
1675
1687
  try {
1676
- const resolved = resolveForPlugin(node);
1688
+ const resolved = resolveForPlugin(state, node);
1677
1689
  if (!resolved) continue;
1678
1690
  const { transformedNode, options } = resolved;
1679
- if (allowedSchemaNames !== null && transformedNode.name && !allowedSchemaNames.has(transformedNode.name)) continue;
1691
+ if (state.allowedSchemaNames !== null && transformedNode.name && !state.allowedSchemaNames.has(transformedNode.name)) continue;
1680
1692
  const ctx = {
1681
- ...generatorContext,
1682
- options
1693
+ ...state.generatorContext,
1694
+ options,
1695
+ cache
1683
1696
  };
1684
- for (const generator of schemaGenerators) await this.dispatch({
1685
- result: await generator.schema(transformedNode, ctx),
1686
- renderer: generator.renderer
1687
- });
1697
+ for (const generator of state.schemaGenerators) {
1698
+ if (!(generator.match ? await generator.match(transformedNode, ctx) : true)) continue;
1699
+ await this.dispatch({
1700
+ result: await generator.schema(transformedNode, ctx),
1701
+ renderer: generator.renderer
1702
+ });
1703
+ }
1688
1704
  await this.hooks.callHook("kubb:generate:schema", transformedNode, ctx);
1689
1705
  } catch (caughtError) {
1690
- error = require_usingCtx.toError(caughtError);
1706
+ state.error = require_usingCtx.toError(caughtError);
1691
1707
  }
1692
1708
  }
1693
- const pluginOperations = [];
1694
- if (operationGenerators.length || operationsGenerators.length) for (const node of operations) {
1695
- if (error) break;
1709
+ }
1710
+ for (const node of operations) {
1711
+ const cache = require_usingCtx.createNodeCache();
1712
+ for (const state of states) {
1713
+ if (state.error || !state.operationGenerators.length && !state.operationsGenerators.length) continue;
1696
1714
  try {
1697
- const resolved = resolveForPlugin(node);
1715
+ const resolved = resolveForPlugin(state, node);
1698
1716
  if (!resolved) continue;
1699
- pluginOperations.push(resolved.transformedNode);
1700
- if (operationGenerators.length) {
1717
+ state.pluginOperations.push(resolved.transformedNode);
1718
+ if (state.operationGenerators.length) {
1701
1719
  const ctx = {
1702
- ...generatorContext,
1703
- options: resolved.options
1720
+ ...state.generatorContext,
1721
+ options: resolved.options,
1722
+ cache
1704
1723
  };
1705
- for (const generator of operationGenerators) await this.dispatch({
1706
- result: await generator.operation(resolved.transformedNode, ctx),
1707
- renderer: generator.renderer
1708
- });
1724
+ for (const generator of state.operationGenerators) {
1725
+ if (!(generator.match ? await generator.match(resolved.transformedNode, ctx) : true)) continue;
1726
+ await this.dispatch({
1727
+ result: await generator.operation(resolved.transformedNode, ctx),
1728
+ renderer: generator.renderer
1729
+ });
1730
+ }
1709
1731
  await this.hooks.callHook("kubb:generate:operation", resolved.transformedNode, ctx);
1710
1732
  }
1711
1733
  } catch (caughtError) {
1712
- error = require_usingCtx.toError(caughtError);
1734
+ state.error = require_usingCtx.toError(caughtError);
1713
1735
  }
1714
1736
  }
1715
- if (!error && operationsGenerators.length) try {
1737
+ }
1738
+ for (const state of states) {
1739
+ if (state.error || !state.operationsGenerators.length) continue;
1740
+ try {
1716
1741
  const ctx = {
1717
- ...generatorContext,
1718
- options: plugin.options
1742
+ ...state.generatorContext,
1743
+ options: state.plugin.options,
1744
+ cache: require_usingCtx.createNodeCache()
1719
1745
  };
1720
- for (const generator of operationsGenerators) await this.dispatch({
1721
- result: await generator.operations(pluginOperations, ctx),
1746
+ for (const generator of state.operationsGenerators) await this.dispatch({
1747
+ result: await generator.operations(state.pluginOperations, ctx),
1722
1748
  renderer: generator.renderer
1723
1749
  });
1724
- await this.hooks.callHook("kubb:generate:operations", pluginOperations, ctx);
1750
+ await this.hooks.callHook("kubb:generate:operations", state.pluginOperations, ctx);
1725
1751
  } catch (caughtError) {
1726
- error = require_usingCtx.toError(caughtError);
1752
+ state.error = require_usingCtx.toError(caughtError);
1727
1753
  }
1728
- const duration = getElapsedMs(hrStart);
1754
+ }
1755
+ for (const state of states) {
1756
+ const duration = getElapsedMs(state.hrStart);
1729
1757
  await this.#emitPluginEnd({
1730
- plugin,
1758
+ plugin: state.plugin,
1731
1759
  duration,
1732
- success: !error,
1733
- error: error ?? void 0
1760
+ success: !state.error,
1761
+ error: state.error ?? void 0
1734
1762
  });
1735
- if (error) diagnostics.push({
1736
- ...Diagnostics.from(error),
1737
- plugin: plugin.name
1763
+ if (state.error) diagnostics.push({
1764
+ ...Diagnostics.from(state.error),
1765
+ plugin: state.plugin.name
1738
1766
  });
1739
1767
  diagnostics.push(Diagnostics.performance({
1740
- plugin: plugin.name,
1768
+ plugin: state.plugin.name,
1741
1769
  duration
1742
1770
  }));
1743
1771
  }