@kubb/core 5.0.0-beta.75 → 5.0.0-beta.8

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_PluginDriver = require("./PluginDriver-BXibeQk-.cjs");
2
+ const require_PluginDriver = require("./PluginDriver-Cu1Kj9S-.cjs");
3
3
  let node_events = require("node:events");
4
4
  let node_fs_promises = require("node:fs/promises");
5
5
  let node_path = require("node:path");
@@ -524,6 +524,9 @@ function createAdapter(build) {
524
524
  return (options) => build(options ?? {});
525
525
  }
526
526
  //#endregion
527
+ //#region package.json
528
+ var version = "5.0.0-beta.8";
529
+ //#endregion
527
530
  //#region ../../node_modules/.pnpm/yocto-queue@1.2.2/node_modules/yocto-queue/index.js
528
531
  var Node = class {
529
532
  value;
@@ -735,12 +738,6 @@ function createStorage(build) {
735
738
  //#endregion
736
739
  //#region src/storages/fsStorage.ts
737
740
  /**
738
- * Detects the filesystem error used to indicate that a path does not exist.
739
- */
740
- function isMissingPathError(error) {
741
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
742
- }
743
- /**
744
741
  * Built-in filesystem storage driver.
745
742
  *
746
743
  * This is the default storage when no `storage` option is configured in the root config.
@@ -771,17 +768,15 @@ const fsStorage = createStorage(() => ({
771
768
  try {
772
769
  await (0, node_fs_promises.access)((0, node_path.resolve)(key));
773
770
  return true;
774
- } catch (error) {
775
- if (isMissingPathError(error)) return false;
776
- throw new Error(`Failed to access storage item "${key}"`, { cause: error });
771
+ } catch (_error) {
772
+ return false;
777
773
  }
778
774
  },
779
775
  async getItem(key) {
780
776
  try {
781
777
  return await (0, node_fs_promises.readFile)((0, node_path.resolve)(key), "utf8");
782
- } catch (error) {
783
- if (isMissingPathError(error)) return null;
784
- throw new Error(`Failed to read storage item "${key}"`, { cause: error });
778
+ } catch (_error) {
779
+ return null;
785
780
  }
786
781
  },
787
782
  async setItem(key, value) {
@@ -797,9 +792,8 @@ const fsStorage = createStorage(() => ({
797
792
  let entries;
798
793
  try {
799
794
  entries = await (0, node_fs_promises.readdir)(dir, { withFileTypes: true });
800
- } catch (error) {
801
- if (isMissingPathError(error)) return;
802
- throw new Error(`Failed to list storage keys under "${resolvedBase}"`, { cause: error });
795
+ } catch (_error) {
796
+ return;
803
797
  }
804
798
  for (const entry of entries) {
805
799
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
@@ -816,37 +810,31 @@ const fsStorage = createStorage(() => ({
816
810
  }
817
811
  }));
818
812
  //#endregion
819
- //#region package.json
820
- var version = "5.0.0-beta.75";
821
- //#endregion
822
- //#region src/utils/diagnostics.ts
823
- /**
824
- * Returns a snapshot of the current runtime environment.
825
- *
826
- * Useful for attaching context to debug logs and error reports so that
827
- * issues can be reproduced without manual information gathering.
828
- */
829
- function getDiagnosticInfo() {
830
- return {
831
- nodeVersion: node_process.version,
832
- KubbVersion: version,
833
- platform: process.platform,
834
- arch: process.arch,
835
- cwd: process.cwd()
836
- };
837
- }
838
- //#endregion
839
- //#region src/utils/isInputPath.ts
840
- function isInputPath(config) {
841
- return typeof config?.input === "object" && config.input !== null && "path" in config.input;
842
- }
843
- //#endregion
844
813
  //#region src/createKubb.ts
845
814
  async function setup(userConfig, options = {}) {
846
815
  const hooks = options.hooks ?? new AsyncEventEmitter();
816
+ const config = {
817
+ ...userConfig,
818
+ root: userConfig.root || process.cwd(),
819
+ parsers: userConfig.parsers ?? [],
820
+ adapter: userConfig.adapter,
821
+ output: {
822
+ format: false,
823
+ lint: false,
824
+ extension: require_PluginDriver.DEFAULT_EXTENSION,
825
+ defaultBanner: require_PluginDriver.DEFAULT_BANNER,
826
+ ...userConfig.output
827
+ },
828
+ storage: userConfig.storage ?? fsStorage(),
829
+ devtools: userConfig.devtools ? {
830
+ studioUrl: require_PluginDriver.DEFAULT_STUDIO_URL,
831
+ ...typeof userConfig.devtools === "boolean" ? {} : userConfig.devtools
832
+ } : void 0,
833
+ plugins: userConfig.plugins ?? []
834
+ };
835
+ const driver = new require_PluginDriver.PluginDriver(config, { hooks });
847
836
  const sources = /* @__PURE__ */ new Map();
848
837
  const diagnosticInfo = getDiagnosticInfo();
849
- if (Array.isArray(userConfig.input)) await hooks.emit("kubb:warn", { message: "This feature is still under development — use with caution" });
850
838
  await hooks.emit("kubb:debug", {
851
839
  date: /* @__PURE__ */ new Date(),
852
840
  logs: [
@@ -856,7 +844,7 @@ async function setup(userConfig, options = {}) {
856
844
  ` • Output: ${userConfig.output?.path || "not specified"}`,
857
845
  ` • Plugins: ${userConfig.plugins?.length || 0}`,
858
846
  "Output Settings:",
859
- ` • Storage: ${userConfig.storage ? `custom(${userConfig.storage.name})` : userConfig.output?.write === false ? "disabled" : "filesystem (default)"}`,
847
+ ` • Storage: ${config.storage.name}`,
860
848
  ` • Formatter: ${userConfig.output?.format || "none"}`,
861
849
  ` • Linter: ${userConfig.output?.lint || "none"}`,
862
850
  "Environment:",
@@ -877,73 +865,56 @@ async function setup(userConfig, options = {}) {
877
865
  throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${userConfig.input.path}`, { cause: error });
878
866
  }
879
867
  }
880
- if (!userConfig.adapter) throw new Error("Adapter should be defined");
881
- const config = {
882
- ...userConfig,
883
- root: userConfig.root || process.cwd(),
884
- parsers: userConfig.parsers ?? [],
885
- adapter: userConfig.adapter,
886
- output: {
887
- format: false,
888
- lint: false,
889
- write: true,
890
- extension: require_PluginDriver.DEFAULT_EXTENSION,
891
- defaultBanner: require_PluginDriver.DEFAULT_BANNER,
892
- ...userConfig.output
893
- },
894
- devtools: userConfig.devtools ? {
895
- studioUrl: require_PluginDriver.DEFAULT_STUDIO_URL,
896
- ...typeof userConfig.devtools === "boolean" ? {} : userConfig.devtools
897
- } : void 0,
898
- plugins: userConfig.plugins
899
- };
900
- const storage = config.output.write === false ? null : config.storage ?? fsStorage();
901
868
  if (config.output.clean) {
902
869
  await hooks.emit("kubb:debug", {
903
870
  date: /* @__PURE__ */ new Date(),
904
871
  logs: ["Cleaning output directories", ` • Output: ${config.output.path}`]
905
872
  });
906
- await storage?.clear((0, node_path.resolve)(config.root, config.output.path));
873
+ await config.storage.clear((0, node_path.resolve)(config.root, config.output.path));
907
874
  }
908
- const driver = new require_PluginDriver.PluginDriver(config, { hooks });
909
875
  function registerMiddlewareHook(event, middlewareHooks) {
910
876
  const handler = middlewareHooks[event];
911
877
  if (handler) hooks.on(event, handler);
912
878
  }
913
879
  for (const middleware of config.middleware ?? []) for (const event of Object.keys(middleware.hooks)) registerMiddlewareHook(event, middleware.hooks);
914
- const adapter = config.adapter;
915
- if (!adapter) throw new Error("No adapter configured. Please provide an adapter in your kubb.config.ts.");
916
- const source = inputToAdapterSource(config);
917
- await hooks.emit("kubb:debug", {
918
- date: /* @__PURE__ */ new Date(),
919
- logs: [`Running adapter: ${adapter.name}`]
920
- });
921
- driver.adapter = adapter;
922
- driver.inputNode = await adapter.parse(source);
923
- await hooks.emit("kubb:debug", {
924
- date: /* @__PURE__ */ new Date(),
925
- logs: [
926
- `✓ Adapter '${adapter.name}' resolved InputNode`,
927
- ` • Schemas: ${driver.inputNode.schemas.length}`,
928
- ` • Operations: ${driver.inputNode.operations.length}`
929
- ]
930
- });
880
+ if (config.adapter) {
881
+ const source = inputToAdapterSource(config);
882
+ await hooks.emit("kubb:debug", {
883
+ date: /* @__PURE__ */ new Date(),
884
+ logs: [`Running adapter: ${config.adapter.name}`]
885
+ });
886
+ driver.adapter = config.adapter;
887
+ driver.inputNode = await config.adapter.parse(source);
888
+ await hooks.emit("kubb:debug", {
889
+ date: /* @__PURE__ */ new Date(),
890
+ logs: [
891
+ `✓ Adapter '${config.adapter.name}' resolved InputNode`,
892
+ ` • Schemas: ${driver.inputNode.schemas.length}`,
893
+ ` • Operations: ${driver.inputNode.operations.length}`
894
+ ]
895
+ });
896
+ }
931
897
  return {
932
898
  config,
933
899
  hooks,
934
900
  driver,
935
- sources,
936
- storage
901
+ sources
937
902
  };
938
903
  }
939
904
  /**
940
905
  * Walks the AST and dispatches nodes to a plugin's direct AST hooks
941
906
  * (`schema`, `operation`, `operations`).
907
+ *
908
+ * When `include` contains only operation-scoped filters (`tag`, `operationId`, `path`,
909
+ * `method`, `contentType`) and no `schemaName` filter, the function pre-computes the set
910
+ * of top-level schema names transitively reachable from the included operations and skips
911
+ * schemas that fall outside that set. This ensures that component schemas referenced
912
+ * exclusively by excluded operations are not generated.
942
913
  */
943
914
  async function runPluginAstHooks(plugin, context) {
944
915
  const { adapter, inputNode, resolver, driver } = context;
945
916
  const { exclude, include, override } = plugin.options;
946
- if (!adapter || !inputNode) throw new Error(`[${plugin.name}] No adapter found. Add an OAS adapter (e.g. pluginOas()) before this plugin in your Kubb config.`);
917
+ if (!adapter || !inputNode) throw new Error(`[${plugin.name}] No adapter found. Add an OAS adapter (e.g. adapterOas()) before this plugin in your Kubb config.`);
947
918
  function resolveRenderer(gen) {
948
919
  return gen.renderer === null ? void 0 : gen.renderer ?? plugin.renderer ?? context.config.renderer;
949
920
  }
@@ -953,10 +924,27 @@ async function runPluginAstHooks(plugin, context) {
953
924
  ...context,
954
925
  resolver: driver.getResolver(plugin.name)
955
926
  };
927
+ const operationFilterTypes = new Set([
928
+ "tag",
929
+ "operationId",
930
+ "path",
931
+ "method",
932
+ "contentType"
933
+ ]);
934
+ const hasOperationBasedIncludes = include?.some(({ type }) => operationFilterTypes.has(type)) ?? false;
935
+ const hasSchemaNameIncludes = include?.some(({ type }) => type === "schemaName") ?? false;
936
+ let allowedSchemaNames;
937
+ if (hasOperationBasedIncludes && !hasSchemaNameIncludes) allowedSchemaNames = (0, _kubb_ast.collectUsedSchemaNames)(inputNode.operations.filter((op) => resolver.resolveOptions(op, {
938
+ options: plugin.options,
939
+ exclude,
940
+ include,
941
+ override
942
+ }) !== null), inputNode.schemas);
956
943
  await (0, _kubb_ast.walk)(inputNode, {
957
944
  depth: "shallow",
958
945
  async schema(node) {
959
946
  const transformedNode = plugin.transformer ? (0, _kubb_ast.transform)(node, plugin.transformer) : node;
947
+ if (allowedSchemaNames !== void 0 && transformedNode.name && !allowedSchemaNames.has(transformedNode.name)) return;
960
948
  const options = resolver.resolveOptions(transformedNode, {
961
949
  options: plugin.options,
962
950
  exclude,
@@ -1009,7 +997,7 @@ async function runPluginAstHooks(plugin, context) {
1009
997
  }
1010
998
  }
1011
999
  async function safeBuild(setupResult) {
1012
- const { driver, hooks, sources, storage } = setupResult;
1000
+ const { driver, hooks, sources } = setupResult;
1013
1001
  const failedPlugins = /* @__PURE__ */ new Set();
1014
1002
  const pluginTimings = /* @__PURE__ */ new Map();
1015
1003
  const config = driver.config;
@@ -1100,6 +1088,7 @@ async function safeBuild(setupResult) {
1100
1088
  });
1101
1089
  await fileProcessor.run(files, {
1102
1090
  parsers: parsersMap,
1091
+ mode: "parallel",
1103
1092
  extension: config.output.extension,
1104
1093
  onStart: async (processingFiles) => {
1105
1094
  await hooks.emit("kubb:files:processing:start", { files: processingFiles });
@@ -1114,7 +1103,7 @@ async function safeBuild(setupResult) {
1114
1103
  config
1115
1104
  });
1116
1105
  if (source) {
1117
- await storage?.setItem(file.path, source);
1106
+ await config.storage.setItem(file.path, source);
1118
1107
  sources.set(file.path, source);
1119
1108
  }
1120
1109
  },
@@ -1167,22 +1156,38 @@ async function build(setupResult) {
1167
1156
  sources
1168
1157
  };
1169
1158
  }
1170
- function inputToAdapterSource(config) {
1171
- if (Array.isArray(config.input)) return {
1172
- type: "paths",
1173
- paths: config.input.map((i) => new URLPath(i.path).isURL ? i.path : (0, node_path.resolve)(config.root, i.path))
1159
+ /**
1160
+ * Returns a snapshot of the current runtime environment.
1161
+ *
1162
+ * Useful for attaching context to debug logs and error reports so that
1163
+ * issues can be reproduced without manual information gathering.
1164
+ */
1165
+ function getDiagnosticInfo() {
1166
+ return {
1167
+ nodeVersion: node_process.version,
1168
+ KubbVersion: version,
1169
+ platform: process.platform,
1170
+ arch: process.arch,
1171
+ cwd: process.cwd()
1174
1172
  };
1175
- if ("data" in config.input) return {
1173
+ }
1174
+ function isInputPath(config) {
1175
+ return typeof config?.input === "object" && config.input !== null && "path" in config.input;
1176
+ }
1177
+ function inputToAdapterSource(config) {
1178
+ const input = config.input;
1179
+ if (!input) throw new Error("[kubb] input is required when using an adapter. Provide input.path or input.data in your config.");
1180
+ if ("data" in input) return {
1176
1181
  type: "data",
1177
- data: config.input.data
1182
+ data: input.data
1178
1183
  };
1179
- if (new URLPath(config.input.path).isURL) return {
1184
+ if (new URLPath(input.path).isURL) return {
1180
1185
  type: "path",
1181
- path: config.input.path
1186
+ path: input.path
1182
1187
  };
1183
1188
  return {
1184
1189
  type: "path",
1185
- path: (0, node_path.resolve)(config.root, config.input.path)
1190
+ path: (0, node_path.resolve)(config.root, input.path)
1186
1191
  };
1187
1192
  }
1188
1193
  /**
@@ -1282,7 +1287,11 @@ function defineGenerator(generator) {
1282
1287
  /**
1283
1288
  * Wraps a logger definition into a typed {@link Logger}.
1284
1289
  *
1285
- * @example
1290
+ * The optional second type parameter `TInstallReturn` allows loggers to return
1291
+ * a value from `install` — for example, a sink factory that the caller can
1292
+ * forward to hook execution.
1293
+ *
1294
+ * @example Basic logger
1286
1295
  * ```ts
1287
1296
  * export const myLogger = defineLogger({
1288
1297
  * name: 'my-logger',
@@ -1292,6 +1301,17 @@ function defineGenerator(generator) {
1292
1301
  * },
1293
1302
  * })
1294
1303
  * ```
1304
+ *
1305
+ * @example Logger that returns a hook sink factory
1306
+ * ```ts
1307
+ * export const myLogger = defineLogger<LoggerOptions, HookSinkFactory>({
1308
+ * name: 'my-logger',
1309
+ * install(context, options) {
1310
+ * // … register event handlers …
1311
+ * return (commandWithArgs) => ({ onStdout: console.log })
1312
+ * },
1313
+ * })
1314
+ * ```
1295
1315
  */
1296
1316
  function defineLogger(logger) {
1297
1317
  return logger;
@@ -1362,34 +1382,6 @@ function defineParser(parser) {
1362
1382
  return parser;
1363
1383
  }
1364
1384
  //#endregion
1365
- //#region src/definePlugin.ts
1366
- /**
1367
- * Wraps a factory function and returns a typed `Plugin` with lifecycle handlers grouped under `hooks`.
1368
- *
1369
- * Handlers live in a single `hooks` object (inspired by Astro integrations).
1370
- * All lifecycle events from `KubbHooks` are available for subscription.
1371
- *
1372
- * @note For real plugins, use a `PluginFactoryOptions` type parameter to get type-safe context in `kubb:plugin:setup`.
1373
- * Plugin names should follow the convention `plugin-<feature>` (e.g., `plugin-react-query`, `plugin-zod`).
1374
- *
1375
- * @example
1376
- * ```ts
1377
- * import { definePlugin } from '@kubb/core'
1378
- *
1379
- * export const pluginTs = definePlugin((options: { prefix?: string } = {}) => ({
1380
- * name: 'plugin-ts',
1381
- * hooks: {
1382
- * 'kubb:plugin:setup'(ctx) {
1383
- * ctx.setResolver(resolverTs)
1384
- * },
1385
- * },
1386
- * }))
1387
- * ```
1388
- */
1389
- function definePlugin(factory) {
1390
- return (options) => factory(options ?? {});
1391
- }
1392
- //#endregion
1393
1385
  //#region src/storages/memoryStorage.ts
1394
1386
  /**
1395
1387
  * In-memory storage driver. Useful for testing and dry-run scenarios where
@@ -1459,7 +1451,7 @@ exports.defineGenerator = defineGenerator;
1459
1451
  exports.defineLogger = defineLogger;
1460
1452
  exports.defineMiddleware = defineMiddleware;
1461
1453
  exports.defineParser = defineParser;
1462
- exports.definePlugin = definePlugin;
1454
+ exports.definePlugin = require_PluginDriver.definePlugin;
1463
1455
  exports.defineResolver = require_PluginDriver.defineResolver;
1464
1456
  exports.fsStorage = fsStorage;
1465
1457
  exports.isInputPath = isInputPath;