@kubb/core 5.0.0-beta.107 → 5.0.0-beta.109

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.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as __name } from "./rolldown-runtime-C0LytTxp.js";
2
- import { $ as PluginFactoryOptions, A as Kubb, At as DiagnosticDoc, B as Exclude, Bt as Hookable, C as KubbWarnContext, Ct as Reporter, D as CreateKubbOptions, Dt as createReporter, E as UserConfig, Et as UserReporter, F as NodeCache, Ft as PerformanceDiagnostic, G as KubbPluginSetupContext, H as Group, Ht as AdapterFactoryOptions, I as KubbDriver, It as ProblemCode, J as Output, K as KubbPluginStartContext, L as FileManagerHooks, Lt as ProblemDiagnostic, M as Generator, Mt as DiagnosticLocation, N as GeneratorContext, Nt as DiagnosticSeverity, O as GenerateOptions, Ot as logLevel, P as defineGenerator, Pt as Diagnostics, Q as Plugin, R as Parser, Rt as SerializedDiagnostic, S as KubbSuccessContext, St as GenerationResult, T as PostGenerateCommand, Tt as ReporterName, U as Include, Ut as AdapterSource, V as Filter, Vt as Adapter, W as KubbPluginEndContext, Wt as createAdapter, X as OutputOptions, Y as OutputMode, Z as Override, _ as KubbHookStartContext, _t as Renderer, a as KubbBuildEndContext, at as ResolveBannerFile, b as KubbLifecycleStartContext, bt as Storage, c as KubbErrorContext, ct as ResolveOptionsContext, d as KubbFilesProcessingStartContext, dt as ResolverDefault, et as PluginName, f as KubbFilesProcessingUpdateContext, ft as ResolverFile, g as KubbHookLineContext, gt as ResolverPathParams, h as KubbHookEndContext, ht as ResolverPatch, i as Input, it as ResolveBannerContext, j as createKubb, jt as DiagnosticKind, k as GenerateResult, kt as Diagnostic, l as KubbFileProcessingUpdate, lt as ResolvePathOptions, m as KubbGenerationStartContext, mt as ResolverFilePathParams, n as CLIOptions, nt as definePlugin, o as KubbBuildStartContext, ot as ResolveFileOptions, p as KubbGenerationEndContext, pt as ResolverFileParams, q as NormalizedPlugin, r as Config, rt as BannerMeta, s as KubbDiagnosticContext, st as ResolveImportsOptions, t as BuildOutput, tt as ResolvePluginOptions, u as KubbFilesProcessingEndContext, ut as Resolver, v as KubbHooks, vt as RendererFactory, w as PossibleConfig, wt as ReporterContext, x as KubbPluginsEndContext, xt as createStorage, y as KubbInfoContext, yt as createRenderer, z as defineParser, zt as UpdateDiagnostic } from "./types-Dtisidv5.js";
2
+ import { $ as PluginFactoryOptions, A as Kubb, At as DiagnosticDoc, B as Exclude, Bt as Hookable, C as KubbWarnContext, Ct as Reporter, D as CreateKubbOptions, Dt as createReporter, E as UserConfig, Et as UserReporter, F as NodeCache, Ft as PerformanceDiagnostic, G as KubbPluginSetupContext, H as Group, Ht as AdapterFactoryOptions, I as KubbDriver, It as ProblemCode, J as Output, K as KubbPluginStartContext, L as FileManagerHooks, Lt as ProblemDiagnostic, M as Generator, Mt as DiagnosticLocation, N as GeneratorContext, Nt as DiagnosticSeverity, O as GenerateOptions, Ot as logLevel, P as defineGenerator, Pt as Diagnostics, Q as Plugin, R as Parser, Rt as SerializedDiagnostic, S as KubbSuccessContext, St as GenerationResult, T as PostGenerateCommand, Tt as ReporterName, U as Include, Ut as AdapterSource, V as Filter, Vt as Adapter, W as KubbPluginEndContext, Wt as createAdapter, X as OutputOptions, Y as OutputMode, Z as Override, _ as KubbHookStartContext, _t as Renderer, a as KubbBuildEndContext, at as ResolveBannerFile, b as KubbLifecycleStartContext, bt as Storage, c as KubbErrorContext, ct as ResolveOptionsContext, d as KubbFilesProcessingStartContext, dt as ResolverDefault, et as PluginName, f as KubbFilesProcessingUpdateContext, ft as ResolverFile, g as KubbHookLineContext, gt as ResolverPathParams, h as KubbHookEndContext, ht as ResolverPatch, i as Input, it as ResolveBannerContext, j as createKubb, jt as DiagnosticKind, k as GenerateResult, kt as Diagnostic, l as KubbFileProcessingUpdate, lt as ResolvePathOptions, m as KubbGenerationStartContext, mt as ResolverFilePathParams, n as CLIOptions, nt as definePlugin, o as KubbBuildStartContext, ot as ResolveFileOptions, p as KubbGenerationEndContext, pt as ResolverFileParams, q as NormalizedPlugin, r as Config, rt as BannerMeta, s as KubbDiagnosticContext, st as ResolveImportsOptions, t as BuildOutput, tt as ResolvePluginOptions, u as KubbFilesProcessingEndContext, ut as Resolver, v as KubbHooks, vt as RendererFactory, w as PossibleConfig, wt as ReporterContext, x as KubbPluginsEndContext, xt as createStorage, y as KubbInfoContext, yt as createRenderer, z as defineParser, zt as UpdateDiagnostic } from "./types-TqpVzVtY.js";
3
3
  //#region src/applyConfigDefaults.d.ts
4
4
  type ApplyConfigDefaultsOptions<TOutput> = {
5
5
  defaultAdapter: Adapter;
@@ -141,7 +141,8 @@ declare function getInputKind(input: NonNullable<Input>): InputKind;
141
141
  *
142
142
  * Writes are deduplicated and directory-safe:
143
143
  * - leading and trailing whitespace is trimmed before writing
144
- * - the write is skipped when the file content is already identical
144
+ * - the write is skipped when the file already holds that content, ignoring any trailing newline
145
+ * a formatter left behind
145
146
  * - missing parent directories are created automatically
146
147
  * - Bun's native file API is used when running under Bun
147
148
  * - concurrent `writeItem` calls are capped at {@link WRITE_CONCURRENCY} in flight, so a caller
package/dist/index.js CHANGED
@@ -1,11 +1,13 @@
1
- import "./rolldown-runtime-C0LytTxp.js";
2
- import { a as clean, c as toPosixPath, d as getErrorMessage, f as toError, i as Hookable, l as write, n as createNodeCache, o as isPathInside, p as camelCase, r as FileManager, s as toFilePath, t as _usingCtx, u as BuildError } from "./usingCtx-D9_Ee6kn.js";
1
+ import { t as __name } from "./rolldown-runtime-C0LytTxp.js";
2
+ import { a as OPERATION_FILTER_TYPES, c as clean, d as toPosixPath, f as write, g as camelCase, h as toError, i as Hookable, l as isPathInside, m as getErrorMessage, n as createNodeCache, o as diagnosticCode, p as BuildError, r as FileManager, s as inParallel, t as _usingCtx, u as toFilePath } from "./usingCtx-njZUKKsY.js";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
4
  import { stripVTControlCharacters, styleText } from "node:util";
5
- import { hash } from "node:crypto";
5
+ import { createHash, hash } from "node:crypto";
6
6
  import { access, glob, readFile, rm } from "node:fs/promises";
7
7
  import path, { join, relative, resolve } from "node:path";
8
8
  import { ast, collectImportedRefNames, collectUsedSchemaNames, composeMacros, operationDef, schemaDef, transform } from "@kubb/ast";
9
+ import { existsSync } from "node:fs";
10
+ import { tmpdir } from "node:os";
9
11
  import process$1 from "node:process";
10
12
  //#region src/createAdapter.ts
11
13
  /**
@@ -149,130 +151,11 @@ function randomCliColor(text) {
149
151
  return styleText(color, text);
150
152
  }
151
153
  //#endregion
152
- //#region package.json
153
- var version = "5.0.0-beta.107";
154
- //#endregion
155
- //#region src/constants.ts
156
- /**
157
- * Plugin `include` filter types that select operations directly. When one of these is set
158
- * without a `schemaName` include, the generate phase pre-scans operations to compute the set
159
- * of schemas they reach, so unreachable schemas can be pruned for that plugin.
160
- */
161
- const OPERATION_FILTER_TYPES = /* @__PURE__ */ new Set([
162
- "tag",
163
- "operationId",
164
- "path",
165
- "method",
166
- "contentType"
167
- ]);
168
- /**
169
- * Stable codes Kubb attaches to a `Diagnostic`. Each maps to a known failure mode
170
- * and stays stable so it can be referenced in tooling and (later) docs. Reference
171
- * these instead of inlining the string at a throw site.
172
- */
173
- const diagnosticCode = {
174
- /**
175
- * Fallback for an unstructured error with no specific code.
176
- */
177
- unknown: "KUBB_UNKNOWN",
178
- /**
179
- * The file or URL set as `input` could not be read.
180
- */
181
- inputNotFound: "KUBB_INPUT_NOT_FOUND",
182
- /**
183
- * An adapter was configured without an `input`.
184
- */
185
- inputRequired: "KUBB_INPUT_REQUIRED",
186
- /**
187
- * `input` uses the v4 `{ path }` / `{ data }` wrapper, which v5 reads as a parsed
188
- * document instead of a pointer to one.
189
- */
190
- legacyInput: "KUBB_LEGACY_INPUT",
191
- /**
192
- * The parsed `input` carries no `openapi` or `swagger` version, so it is not a
193
- * document the adapter can read.
194
- */
195
- invalidDocument: "KUBB_INVALID_DOCUMENT",
196
- /**
197
- * A `$ref` (or equivalent reference) could not be resolved in the source document.
198
- */
199
- refNotFound: "KUBB_REF_NOT_FOUND",
200
- /**
201
- * A server variable value is not allowed by its `enum`.
202
- */
203
- invalidServerVariable: "KUBB_INVALID_SERVER_VARIABLE",
204
- /**
205
- * A required plugin is missing from the config.
206
- */
207
- pluginNotFound: "KUBB_PLUGIN_NOT_FOUND",
208
- /**
209
- * A plugin threw while generating.
210
- */
211
- pluginFailed: "KUBB_PLUGIN_FAILED",
212
- /**
213
- * A plugin reported a non-fatal warning through `ctx.warn`.
214
- */
215
- pluginWarning: "KUBB_PLUGIN_WARNING",
216
- /**
217
- * A plugin reported an informational message through `ctx.info`.
218
- */
219
- pluginInfo: "KUBB_PLUGIN_INFO",
220
- /**
221
- * A schema uses a `format` Kubb does not map to a specific type. Reserved for
222
- * adapters to emit as a `warning`.
223
- */
224
- unsupportedFormat: "KUBB_UNSUPPORTED_FORMAT",
225
- /**
226
- * A referenced schema or operation is marked `deprecated`. Reserved for adapters
227
- * to emit as an `info`.
228
- */
229
- deprecated: "KUBB_DEPRECATED",
230
- /**
231
- * An adapter is required but the config has none. The build cannot read the input
232
- * without one.
233
- */
234
- adapterRequired: "KUBB_ADAPTER_REQUIRED",
235
- /**
236
- * A resolved output path escapes the output directory, which can stem from a path
237
- * traversal in the spec or a misconfigured `group.name`.
238
- */
239
- pathTraversal: "KUBB_PATH_TRAVERSAL",
240
- /**
241
- * `output.clean` is enabled but `output.path` resolves to the project root or a parent of it,
242
- * so cleaning would delete kubb.config and every source file.
243
- */
244
- cleanRoot: "KUBB_CLEAN_ROOT",
245
- /**
246
- * A plugin's options are invalid, for example `output.mode: 'file'` paired with a `group` option.
247
- */
248
- invalidPluginOptions: "KUBB_INVALID_PLUGIN_OPTIONS",
249
- /**
250
- * A post-generate command (`output.postGenerate`) exited with a failure.
251
- */
252
- postGenerateFailed: "KUBB_POST_GENERATE_FAILED",
253
- /**
254
- * The formatter pass over the generated files failed.
255
- */
256
- formatFailed: "KUBB_FORMAT_FAILED",
257
- /**
258
- * The linter pass over the generated files failed.
259
- */
260
- lintFailed: "KUBB_LINT_FAILED",
261
- /**
262
- * Not a failure. Carries a plugin's elapsed time, summed into the run total.
263
- */
264
- performance: "KUBB_PERFORMANCE",
265
- /**
266
- * Not a failure. A newer Kubb version is available on npm.
267
- */
268
- updateAvailable: "KUBB_UPDATE_AVAILABLE"
269
- };
270
- //#endregion
271
154
  //#region src/Diagnostics.ts
272
155
  /**
273
156
  * Docs major version, derived from the package version so the link tracks the published major.
274
157
  */
275
- const docsMajor = version.split(".")[0] ?? "5";
158
+ const docsMajor = "5.0.0-beta.109".split(".")[0] ?? "5";
276
159
  /**
277
160
  * Builds a type guard that narrows a {@link Diagnostic} to the variant for `kind`. A diagnostic
278
161
  * with no `kind` is treated as a `problem`.
@@ -332,8 +215,18 @@ const diagnosticCatalog = {
332
215
  },
333
216
  [diagnosticCode.inputNotFound]: {
334
217
  title: "Input not found",
335
- cause: "The file or URL set as `input` (or passed as `kubb generate PATH`) could not be read.",
336
- fix: "Check that the path or URL exists and is readable, then set it as `input` or pass it on the CLI."
218
+ cause: "The file set as `input` (or passed as `kubb generate PATH`) could not be read. A URL reports `KUBB_INPUT_REQUEST_FAILED` or `KUBB_INPUT_UNREACHABLE` instead.",
219
+ fix: "Check that the path exists and is readable, then set it as `input` or pass it on the CLI."
220
+ },
221
+ [diagnosticCode.inputRequestFailed]: {
222
+ title: "Input request failed",
223
+ cause: "A URL set as `input` (or reached through a `$ref`) answered with a 4xx or 5xx status instead of the document.",
224
+ fix: "Open the URL to see what the server returns. A 401 or 403 needs credentials Kubb does not send, so download the document and point `input` at the local file. A 404 means the path is wrong, and a 5xx means the server itself failed."
225
+ },
226
+ [diagnosticCode.inputUnreachable]: {
227
+ title: "Input unreachable",
228
+ cause: "A URL set as `input` (or reached through a `$ref`) never answered, so the request failed before a status came back. A refused connection, an unknown host, an expired certificate, and a timeout all land here.",
229
+ fix: "Check that the host is running and reachable from this machine. For a local server, start it and confirm the port matches the one in `input`."
337
230
  },
338
231
  [diagnosticCode.inputRequired]: {
339
232
  title: "Input required",
@@ -1511,22 +1404,25 @@ var KubbDriver = class {
1511
1404
  async run() {
1512
1405
  const { hooks, config, fileManager } = this;
1513
1406
  const diagnostics = [];
1514
- const updateBuffer = [];
1515
1407
  const parsersMap = /* @__PURE__ */ new Map();
1516
1408
  for (const parser of config.parsers) if (parser.extNames) for (const ext of parser.extNames) parsersMap.set(ext, parser);
1409
+ const updateBuffer = [];
1517
1410
  const unhookWrites = fileManager.hooks.addHooks({
1518
1411
  start: async (files) => {
1519
1412
  await hooks.callHook("kubb:files:processing:start", { files });
1520
1413
  },
1521
- update: (item) => {
1522
- updateBuffer.push(item);
1414
+ update: ({ file, processed, total, percentage }) => {
1415
+ updateBuffer.push({
1416
+ file,
1417
+ processed,
1418
+ total,
1419
+ percentage,
1420
+ config
1421
+ });
1523
1422
  },
1524
1423
  end: async (files) => {
1525
1424
  updateBuffer.sort((a, b) => a.processed - b.processed);
1526
- await hooks.callHook("kubb:files:processing:update", { files: updateBuffer.map((item) => ({
1527
- ...item,
1528
- config
1529
- })) });
1425
+ await hooks.callHook("kubb:files:processing:update", { files: updateBuffer });
1530
1426
  updateBuffer.length = 0;
1531
1427
  await hooks.callHook("kubb:files:processing:end", { files });
1532
1428
  }
@@ -1593,7 +1489,8 @@ var KubbDriver = class {
1593
1489
  await hooks.callHook("kubb:plugins:end", this.#withFiles({ config }));
1594
1490
  await fileManager.write(fileManager.files, {
1595
1491
  storage: config.storage,
1596
- parsers: parsersMap
1492
+ parsers: parsersMap,
1493
+ manifest: this.options.manifest
1597
1494
  });
1598
1495
  await hooks.callHook("kubb:build:end", {
1599
1496
  files: this.fileManager.files,
@@ -1954,6 +1851,73 @@ var KubbDriver = class {
1954
1851
  }
1955
1852
  };
1956
1853
  //#endregion
1854
+ //#region src/outputManifest.ts
1855
+ /**
1856
+ * Bumped when the stored shape changes, so an older cache is discarded instead of misread.
1857
+ */
1858
+ const VERSION = 1;
1859
+ function hash$1(value) {
1860
+ return createHash("sha256").update(value).digest("hex");
1861
+ }
1862
+ __name(hash$1, "hash");
1863
+ const MANIFEST_KEY = "output-manifest.json";
1864
+ async function loadEntries({ cache }) {
1865
+ try {
1866
+ const stored = await cache.readItem(MANIFEST_KEY);
1867
+ if (stored === null) return {};
1868
+ const data = JSON.parse(stored);
1869
+ if (data.version !== VERSION) return {};
1870
+ if (typeof data.entries !== "object" || data.entries === null || Array.isArray(data.entries)) return {};
1871
+ return data.entries;
1872
+ } catch {
1873
+ return {};
1874
+ }
1875
+ }
1876
+ /**
1877
+ * Loads the stored manifest, starting empty when it is missing, unreadable, or from an older
1878
+ * version. `storage` holds the generated files, `cache` holds the manifest itself.
1879
+ *
1880
+ * @example
1881
+ * ```ts
1882
+ * const manifest = await createOutputManifest({ storage: config.storage, cache: cacheStorage({ root: config.root }) })
1883
+ * ```
1884
+ */
1885
+ async function createOutputManifest({ storage, cache }) {
1886
+ const entries = await loadEntries({ cache });
1887
+ const tracked = /* @__PURE__ */ new Map();
1888
+ return {
1889
+ isUpToDate({ key, source, disk }) {
1890
+ const entry = entries[key];
1891
+ if (!entry) return false;
1892
+ return entry.source === hash$1(source) && entry.output === hash$1(disk);
1893
+ },
1894
+ track({ key, source }) {
1895
+ tracked.set(key, hash$1(source));
1896
+ },
1897
+ async commit() {
1898
+ try {
1899
+ const next = { ...entries };
1900
+ await inParallel({
1901
+ items: [...tracked],
1902
+ limit: 50,
1903
+ run: async ([key, source]) => {
1904
+ const stored = await storage.readItem(key);
1905
+ if (stored === null) return;
1906
+ next[key] = {
1907
+ source,
1908
+ output: hash$1(stored)
1909
+ };
1910
+ }
1911
+ });
1912
+ await cache.writeItem(MANIFEST_KEY, JSON.stringify({
1913
+ version: VERSION,
1914
+ entries: next
1915
+ }));
1916
+ } catch {}
1917
+ }
1918
+ };
1919
+ }
1920
+ //#endregion
1957
1921
  //#region src/createStorage.ts
1958
1922
  /**
1959
1923
  * Defines a custom storage backend. The builder receives user options and
@@ -2030,7 +1994,8 @@ function createLimiter(concurrency) {
2030
1994
  *
2031
1995
  * Writes are deduplicated and directory-safe:
2032
1996
  * - leading and trailing whitespace is trimmed before writing
2033
- * - the write is skipped when the file content is already identical
1997
+ * - the write is skipped when the file already holds that content, ignoring any trailing newline
1998
+ * a formatter left behind
2034
1999
  * - missing parent directories are created automatically
2035
2000
  * - Bun's native file API is used when running under Bun
2036
2001
  * - concurrent `writeItem` calls are capped at {@link WRITE_CONCURRENCY} in flight, so a caller
@@ -2091,6 +2056,60 @@ const fsStorage = createStorage(() => {
2091
2056
  };
2092
2057
  });
2093
2058
  //#endregion
2059
+ //#region src/storages/cacheStorage.ts
2060
+ /**
2061
+ * Directory Kubb keeps build caches in. A project with a `node_modules` gets
2062
+ * `node_modules/.cache/kubb`, the convention babel and eslint already use, so the cache stays out
2063
+ * of version control. Without one it falls back to the OS temp directory, keyed by root so two
2064
+ * projects sharing that directory keep their own cache.
2065
+ *
2066
+ * @example Inside a project
2067
+ * `resolveCacheDir('/project') // '/project/node_modules/.cache/kubb'`
2068
+ */
2069
+ function resolveCacheDir(root) {
2070
+ const nodeModules = join(root, "node_modules");
2071
+ if (existsSync(nodeModules)) return join(nodeModules, ".cache", "kubb");
2072
+ return join(tmpdir(), "kubb", createHash("sha256").update(root).digest("hex").slice(0, 16));
2073
+ }
2074
+ /**
2075
+ * Filesystem storage for build caches rather than generated code. Keys are plain names resolved
2076
+ * inside {@link resolveCacheDir}, so a caller stores `'x.json'` without knowing where the cache
2077
+ * lives. Kept apart from the configured output storage, which may not be a local disk at all.
2078
+ *
2079
+ * @example
2080
+ * ```ts
2081
+ * const cache = cacheStorage({ root: config.root })
2082
+ * await cache.writeItem('output-manifest.json', JSON.stringify(entries))
2083
+ * ```
2084
+ */
2085
+ const cacheStorage = createStorage(({ root = process.cwd() }) => {
2086
+ const dir = resolveCacheDir(root);
2087
+ const storage = fsStorage();
2088
+ const toPath = (key) => join(dir, key);
2089
+ return {
2090
+ name: "cache",
2091
+ async existsItem(key) {
2092
+ return storage.existsItem(toPath(key));
2093
+ },
2094
+ async readItem(key) {
2095
+ return storage.readItem(toPath(key));
2096
+ },
2097
+ async writeItem(key, value) {
2098
+ return storage.writeItem(toPath(key), value);
2099
+ },
2100
+ async removeItem(key) {
2101
+ return storage.removeItem(toPath(key));
2102
+ },
2103
+ async readKeys(base) {
2104
+ return storage.readKeys(base ? toPath(base) : dir);
2105
+ },
2106
+ async empty(base) {
2107
+ if (!base) return;
2108
+ return storage.empty(toPath(base));
2109
+ }
2110
+ };
2111
+ });
2112
+ //#endregion
2094
2113
  //#region src/createKubb.ts
2095
2114
  function resolveConfig(userConfig) {
2096
2115
  return {
@@ -2109,6 +2128,13 @@ function resolveConfig(userConfig) {
2109
2128
  };
2110
2129
  }
2111
2130
  /**
2131
+ * Whether anything runs over the output directory after the files are written. Only then can the
2132
+ * bytes on disk stop matching what Kubb wrote, which is what the manifest exists to track.
2133
+ */
2134
+ function hasOutputPasses(output) {
2135
+ return Boolean(output.format || output.lint || output.postGenerate?.length);
2136
+ }
2137
+ /**
2112
2138
  * Kubb code-generation instance bound to a single config entry. Resolves the user
2113
2139
  * config in the constructor, so `config` is available right away, and shares `hooks`,
2114
2140
  * `storage`, and `driver` across the `setup → build` lifecycle.
@@ -2130,6 +2156,7 @@ var Kubb = class {
2130
2156
  config;
2131
2157
  #driver = null;
2132
2158
  #storage = null;
2159
+ #manifest = null;
2133
2160
  constructor(userConfig, options = {}) {
2134
2161
  this.config = resolveConfig(userConfig);
2135
2162
  this.hooks = options.hooks ?? new Hookable();
@@ -2147,7 +2174,14 @@ var Kubb = class {
2147
2174
  */
2148
2175
  async setup() {
2149
2176
  const config = this.config;
2150
- const driver = new KubbDriver(config, { hooks: this.hooks });
2177
+ const manifest = hasOutputPasses(config.output) ? await createOutputManifest({
2178
+ storage: config.storage,
2179
+ cache: cacheStorage({ root: config.root })
2180
+ }) : void 0;
2181
+ const driver = new KubbDriver(config, {
2182
+ hooks: this.hooks,
2183
+ manifest
2184
+ });
2151
2185
  this.hooks.setMaxListeners(Math.max(10, config.plugins.length * 4));
2152
2186
  if (config.output.clean) {
2153
2187
  const cleanPath = resolve(config.root, config.output.path);
@@ -2163,6 +2197,7 @@ var Kubb = class {
2163
2197
  await driver.setup();
2164
2198
  this.#driver = driver;
2165
2199
  this.#storage = config.storage;
2200
+ this.#manifest = manifest ?? null;
2166
2201
  }
2167
2202
  /**
2168
2203
  * Runs the full pipeline and throws on any plugin error.
@@ -2250,6 +2285,7 @@ var Kubb = class {
2250
2285
  }) : [];
2251
2286
  const finalDiagnostics = [...diagnostics, ...outputDiagnostics];
2252
2287
  const failed = Diagnostics.hasError(outputDiagnostics);
2288
+ if (!failed) await this.#manifest?.commit();
2253
2289
  await hooks.callHook("kubb:generation:end", {
2254
2290
  config,
2255
2291
  storage,