@kubb/core 5.0.0-beta.108 → 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.cjs +188 -173
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +159 -143
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.js +1 -1
- package/dist/{types-C_JCC5Dl.d.ts → types-TqpVzVtY.d.ts} +48 -7
- package/dist/{usingCtx-lve4tKsy.cjs → usingCtx-BdYw7ICK.cjs} +234 -21
- package/dist/usingCtx-BdYw7ICK.cjs.map +1 -0
- package/dist/{usingCtx-D9_Ee6kn.js → usingCtx-njZUKKsY.js} +217 -22
- package/dist/usingCtx-njZUKKsY.js.map +1 -0
- package/package.json +2 -2
- package/dist/usingCtx-D9_Ee6kn.js.map +0 -1
- package/dist/usingCtx-lve4tKsy.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_usingCtx = require("./usingCtx-
|
|
2
|
+
const require_usingCtx = require("./usingCtx-BdYw7ICK.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");
|
|
@@ -7,6 +7,8 @@ let node_fs_promises = require("node:fs/promises");
|
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
node_path = require_usingCtx.__toESM(node_path, 1);
|
|
9
9
|
let _kubb_ast = require("@kubb/ast");
|
|
10
|
+
let node_fs = require("node:fs");
|
|
11
|
+
let node_os = require("node:os");
|
|
10
12
|
let node_process = require("node:process");
|
|
11
13
|
node_process = require_usingCtx.__toESM(node_process, 1);
|
|
12
14
|
//#region src/createAdapter.ts
|
|
@@ -151,140 +153,11 @@ function randomCliColor(text) {
|
|
|
151
153
|
return (0, node_util.styleText)(color, text);
|
|
152
154
|
}
|
|
153
155
|
//#endregion
|
|
154
|
-
//#region package.json
|
|
155
|
-
var version = "5.0.0-beta.108";
|
|
156
|
-
//#endregion
|
|
157
|
-
//#region src/constants.ts
|
|
158
|
-
/**
|
|
159
|
-
* Plugin `include` filter types that select operations directly. When one of these is set
|
|
160
|
-
* without a `schemaName` include, the generate phase pre-scans operations to compute the set
|
|
161
|
-
* of schemas they reach, so unreachable schemas can be pruned for that plugin.
|
|
162
|
-
*/
|
|
163
|
-
const OPERATION_FILTER_TYPES = /* @__PURE__ */ new Set([
|
|
164
|
-
"tag",
|
|
165
|
-
"operationId",
|
|
166
|
-
"path",
|
|
167
|
-
"method",
|
|
168
|
-
"contentType"
|
|
169
|
-
]);
|
|
170
|
-
/**
|
|
171
|
-
* Stable codes Kubb attaches to a `Diagnostic`. Each maps to a known failure mode
|
|
172
|
-
* and stays stable so it can be referenced in tooling and (later) docs. Reference
|
|
173
|
-
* these instead of inlining the string at a throw site.
|
|
174
|
-
*/
|
|
175
|
-
const diagnosticCode = {
|
|
176
|
-
/**
|
|
177
|
-
* Fallback for an unstructured error with no specific code.
|
|
178
|
-
*/
|
|
179
|
-
unknown: "KUBB_UNKNOWN",
|
|
180
|
-
/**
|
|
181
|
-
* The file or URL set as `input` could not be read.
|
|
182
|
-
*/
|
|
183
|
-
inputNotFound: "KUBB_INPUT_NOT_FOUND",
|
|
184
|
-
/**
|
|
185
|
-
* A URL set as `input` (or referenced by a `$ref`) answered with a 4xx or 5xx status
|
|
186
|
-
* instead of the document.
|
|
187
|
-
*/
|
|
188
|
-
inputRequestFailed: "KUBB_INPUT_REQUEST_FAILED",
|
|
189
|
-
/**
|
|
190
|
-
* A URL set as `input` (or referenced by a `$ref`) never answered, so the request failed
|
|
191
|
-
* before a status was returned.
|
|
192
|
-
*/
|
|
193
|
-
inputUnreachable: "KUBB_INPUT_UNREACHABLE",
|
|
194
|
-
/**
|
|
195
|
-
* An adapter was configured without an `input`.
|
|
196
|
-
*/
|
|
197
|
-
inputRequired: "KUBB_INPUT_REQUIRED",
|
|
198
|
-
/**
|
|
199
|
-
* `input` uses the v4 `{ path }` / `{ data }` wrapper, which v5 reads as a parsed
|
|
200
|
-
* document instead of a pointer to one.
|
|
201
|
-
*/
|
|
202
|
-
legacyInput: "KUBB_LEGACY_INPUT",
|
|
203
|
-
/**
|
|
204
|
-
* The parsed `input` carries no `openapi` or `swagger` version, so it is not a
|
|
205
|
-
* document the adapter can read.
|
|
206
|
-
*/
|
|
207
|
-
invalidDocument: "KUBB_INVALID_DOCUMENT",
|
|
208
|
-
/**
|
|
209
|
-
* A `$ref` (or equivalent reference) could not be resolved in the source document.
|
|
210
|
-
*/
|
|
211
|
-
refNotFound: "KUBB_REF_NOT_FOUND",
|
|
212
|
-
/**
|
|
213
|
-
* A server variable value is not allowed by its `enum`.
|
|
214
|
-
*/
|
|
215
|
-
invalidServerVariable: "KUBB_INVALID_SERVER_VARIABLE",
|
|
216
|
-
/**
|
|
217
|
-
* A required plugin is missing from the config.
|
|
218
|
-
*/
|
|
219
|
-
pluginNotFound: "KUBB_PLUGIN_NOT_FOUND",
|
|
220
|
-
/**
|
|
221
|
-
* A plugin threw while generating.
|
|
222
|
-
*/
|
|
223
|
-
pluginFailed: "KUBB_PLUGIN_FAILED",
|
|
224
|
-
/**
|
|
225
|
-
* A plugin reported a non-fatal warning through `ctx.warn`.
|
|
226
|
-
*/
|
|
227
|
-
pluginWarning: "KUBB_PLUGIN_WARNING",
|
|
228
|
-
/**
|
|
229
|
-
* A plugin reported an informational message through `ctx.info`.
|
|
230
|
-
*/
|
|
231
|
-
pluginInfo: "KUBB_PLUGIN_INFO",
|
|
232
|
-
/**
|
|
233
|
-
* A schema uses a `format` Kubb does not map to a specific type. Reserved for
|
|
234
|
-
* adapters to emit as a `warning`.
|
|
235
|
-
*/
|
|
236
|
-
unsupportedFormat: "KUBB_UNSUPPORTED_FORMAT",
|
|
237
|
-
/**
|
|
238
|
-
* A referenced schema or operation is marked `deprecated`. Reserved for adapters
|
|
239
|
-
* to emit as an `info`.
|
|
240
|
-
*/
|
|
241
|
-
deprecated: "KUBB_DEPRECATED",
|
|
242
|
-
/**
|
|
243
|
-
* An adapter is required but the config has none. The build cannot read the input
|
|
244
|
-
* without one.
|
|
245
|
-
*/
|
|
246
|
-
adapterRequired: "KUBB_ADAPTER_REQUIRED",
|
|
247
|
-
/**
|
|
248
|
-
* A resolved output path escapes the output directory, which can stem from a path
|
|
249
|
-
* traversal in the spec or a misconfigured `group.name`.
|
|
250
|
-
*/
|
|
251
|
-
pathTraversal: "KUBB_PATH_TRAVERSAL",
|
|
252
|
-
/**
|
|
253
|
-
* `output.clean` is enabled but `output.path` resolves to the project root or a parent of it,
|
|
254
|
-
* so cleaning would delete kubb.config and every source file.
|
|
255
|
-
*/
|
|
256
|
-
cleanRoot: "KUBB_CLEAN_ROOT",
|
|
257
|
-
/**
|
|
258
|
-
* A plugin's options are invalid, for example `output.mode: 'file'` paired with a `group` option.
|
|
259
|
-
*/
|
|
260
|
-
invalidPluginOptions: "KUBB_INVALID_PLUGIN_OPTIONS",
|
|
261
|
-
/**
|
|
262
|
-
* A post-generate command (`output.postGenerate`) exited with a failure.
|
|
263
|
-
*/
|
|
264
|
-
postGenerateFailed: "KUBB_POST_GENERATE_FAILED",
|
|
265
|
-
/**
|
|
266
|
-
* The formatter pass over the generated files failed.
|
|
267
|
-
*/
|
|
268
|
-
formatFailed: "KUBB_FORMAT_FAILED",
|
|
269
|
-
/**
|
|
270
|
-
* The linter pass over the generated files failed.
|
|
271
|
-
*/
|
|
272
|
-
lintFailed: "KUBB_LINT_FAILED",
|
|
273
|
-
/**
|
|
274
|
-
* Not a failure. Carries a plugin's elapsed time, summed into the run total.
|
|
275
|
-
*/
|
|
276
|
-
performance: "KUBB_PERFORMANCE",
|
|
277
|
-
/**
|
|
278
|
-
* Not a failure. A newer Kubb version is available on npm.
|
|
279
|
-
*/
|
|
280
|
-
updateAvailable: "KUBB_UPDATE_AVAILABLE"
|
|
281
|
-
};
|
|
282
|
-
//#endregion
|
|
283
156
|
//#region src/Diagnostics.ts
|
|
284
157
|
/**
|
|
285
158
|
* Docs major version, derived from the package version so the link tracks the published major.
|
|
286
159
|
*/
|
|
287
|
-
const docsMajor =
|
|
160
|
+
const docsMajor = "5.0.0-beta.109".split(".")[0] ?? "5";
|
|
288
161
|
/**
|
|
289
162
|
* Builds a type guard that narrows a {@link Diagnostic} to the variant for `kind`. A diagnostic
|
|
290
163
|
* with no `kind` is treated as a `problem`.
|
|
@@ -337,122 +210,122 @@ const severityStyle = {
|
|
|
337
210
|
* and `Diagnostics.docsUrl` for the matching kubb.dev page.
|
|
338
211
|
*/
|
|
339
212
|
const diagnosticCatalog = {
|
|
340
|
-
[diagnosticCode.unknown]: {
|
|
213
|
+
[require_usingCtx.diagnosticCode.unknown]: {
|
|
341
214
|
title: "Unknown error",
|
|
342
215
|
cause: "An error was thrown without a stable Kubb code, so it is reported as-is.",
|
|
343
216
|
fix: "Read the underlying message and stack. If it comes from a plugin or adapter, check its configuration; otherwise report it as a possible Kubb bug."
|
|
344
217
|
},
|
|
345
|
-
[diagnosticCode.inputNotFound]: {
|
|
218
|
+
[require_usingCtx.diagnosticCode.inputNotFound]: {
|
|
346
219
|
title: "Input not found",
|
|
347
220
|
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.",
|
|
348
221
|
fix: "Check that the path exists and is readable, then set it as `input` or pass it on the CLI."
|
|
349
222
|
},
|
|
350
|
-
[diagnosticCode.inputRequestFailed]: {
|
|
223
|
+
[require_usingCtx.diagnosticCode.inputRequestFailed]: {
|
|
351
224
|
title: "Input request failed",
|
|
352
225
|
cause: "A URL set as `input` (or reached through a `$ref`) answered with a 4xx or 5xx status instead of the document.",
|
|
353
226
|
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."
|
|
354
227
|
},
|
|
355
|
-
[diagnosticCode.inputUnreachable]: {
|
|
228
|
+
[require_usingCtx.diagnosticCode.inputUnreachable]: {
|
|
356
229
|
title: "Input unreachable",
|
|
357
230
|
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.",
|
|
358
231
|
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`."
|
|
359
232
|
},
|
|
360
|
-
[diagnosticCode.inputRequired]: {
|
|
233
|
+
[require_usingCtx.diagnosticCode.inputRequired]: {
|
|
361
234
|
title: "Input required",
|
|
362
235
|
cause: "An adapter is configured but no `input` was provided.",
|
|
363
236
|
fix: "Set `input` to a file path, a URL, an inline spec (JSON/YAML string), or a parsed object in your Kubb config."
|
|
364
237
|
},
|
|
365
|
-
[diagnosticCode.legacyInput]: {
|
|
238
|
+
[require_usingCtx.diagnosticCode.legacyInput]: {
|
|
366
239
|
title: "Legacy input shape",
|
|
367
240
|
cause: "`input` is a `{ path }` or `{ data }` wrapper, which v4 used to point at a document and v5 reads as the document itself.",
|
|
368
241
|
fix: "Unwrap it: `input: { path: \"./petStore.yaml\" }` becomes `input: \"./petStore.yaml\"`, and `input: { data: spec }` becomes `input: spec`."
|
|
369
242
|
},
|
|
370
|
-
[diagnosticCode.invalidDocument]: {
|
|
243
|
+
[require_usingCtx.diagnosticCode.invalidDocument]: {
|
|
371
244
|
title: "Invalid document",
|
|
372
245
|
cause: "The parsed `input` has no `openapi` or `swagger` version field, so it is not an OpenAPI or Swagger document.",
|
|
373
246
|
fix: "Point `input` at a document that declares `openapi` or `swagger`, and check that a passed object is the spec itself rather than a wrapper around it."
|
|
374
247
|
},
|
|
375
|
-
[diagnosticCode.refNotFound]: {
|
|
248
|
+
[require_usingCtx.diagnosticCode.refNotFound]: {
|
|
376
249
|
title: "Reference not found",
|
|
377
250
|
cause: "A `$ref` could not be resolved in the source document.",
|
|
378
251
|
fix: "Add the missing definition (for example under `components.schemas`) or fix the `$ref`. Run `kubb validate` to check the spec."
|
|
379
252
|
},
|
|
380
|
-
[diagnosticCode.invalidServerVariable]: {
|
|
253
|
+
[require_usingCtx.diagnosticCode.invalidServerVariable]: {
|
|
381
254
|
title: "Invalid server variable",
|
|
382
255
|
cause: "A server variable value is not allowed by its `enum`.",
|
|
383
256
|
fix: "Use one of the values listed in the server variable `enum`, or update the spec."
|
|
384
257
|
},
|
|
385
|
-
[diagnosticCode.pluginNotFound]: {
|
|
258
|
+
[require_usingCtx.diagnosticCode.pluginNotFound]: {
|
|
386
259
|
title: "Plugin not found",
|
|
387
260
|
cause: "A plugin that another plugin depends on is missing from the config.",
|
|
388
261
|
fix: "Add the required plugin to the `plugins` array in kubb.config.ts, or remove the dependency on it."
|
|
389
262
|
},
|
|
390
|
-
[diagnosticCode.pluginFailed]: {
|
|
263
|
+
[require_usingCtx.diagnosticCode.pluginFailed]: {
|
|
391
264
|
title: "Plugin failed",
|
|
392
265
|
cause: "A plugin threw while generating, or reported an error through `ctx.error`.",
|
|
393
266
|
fix: "Read the underlying error and check the plugin options and the schema or operation it failed on."
|
|
394
267
|
},
|
|
395
|
-
[diagnosticCode.pluginWarning]: {
|
|
268
|
+
[require_usingCtx.diagnosticCode.pluginWarning]: {
|
|
396
269
|
title: "Plugin warning",
|
|
397
270
|
cause: "A plugin reported a non-fatal warning through `ctx.warn`.",
|
|
398
271
|
fix: "Review the message. It does not fail the build; adjust the plugin options or input if the warning is unwanted."
|
|
399
272
|
},
|
|
400
|
-
[diagnosticCode.pluginInfo]: {
|
|
273
|
+
[require_usingCtx.diagnosticCode.pluginInfo]: {
|
|
401
274
|
title: "Plugin info",
|
|
402
275
|
cause: "A plugin reported an informational message through `ctx.info`.",
|
|
403
276
|
fix: "Informational only. No action is required."
|
|
404
277
|
},
|
|
405
|
-
[diagnosticCode.unsupportedFormat]: {
|
|
278
|
+
[require_usingCtx.diagnosticCode.unsupportedFormat]: {
|
|
406
279
|
title: "Unsupported format",
|
|
407
280
|
cause: "A schema uses a `format` Kubb does not map to a specific type, so it falls back to the base type.",
|
|
408
281
|
fix: "Use a format Kubb supports, or handle the custom format with a parser or plugin."
|
|
409
282
|
},
|
|
410
|
-
[diagnosticCode.deprecated]: {
|
|
283
|
+
[require_usingCtx.diagnosticCode.deprecated]: {
|
|
411
284
|
title: "Deprecated",
|
|
412
285
|
cause: "A referenced schema or operation is marked `deprecated`.",
|
|
413
286
|
fix: "Migrate off the deprecated definition if the warning is unwanted."
|
|
414
287
|
},
|
|
415
|
-
[diagnosticCode.adapterRequired]: {
|
|
288
|
+
[require_usingCtx.diagnosticCode.adapterRequired]: {
|
|
416
289
|
title: "Adapter required",
|
|
417
290
|
cause: "An action needs an adapter but none is configured.",
|
|
418
291
|
fix: "Set `adapter` in kubb.config.ts, for example `adapterOas()`."
|
|
419
292
|
},
|
|
420
|
-
[diagnosticCode.pathTraversal]: {
|
|
293
|
+
[require_usingCtx.diagnosticCode.pathTraversal]: {
|
|
421
294
|
title: "Path traversal",
|
|
422
295
|
cause: "A resolved output path escaped the output directory, which can stem from a path traversal in the spec or a misconfigured `group.name`.",
|
|
423
296
|
fix: "Keep generated paths within the output directory. Review the `group.name` function and the names coming from the spec."
|
|
424
297
|
},
|
|
425
|
-
[diagnosticCode.cleanRoot]: {
|
|
298
|
+
[require_usingCtx.diagnosticCode.cleanRoot]: {
|
|
426
299
|
title: "Clean targets the project root",
|
|
427
300
|
cause: "`output.clean` is enabled and `output.path` resolves to the project root or a parent of it, so cleaning would delete `kubb.config` and every source file.",
|
|
428
301
|
fix: "Point `output.path` at a subdirectory such as `./src/gen` so clean only removes generated code, or disable `output.clean`."
|
|
429
302
|
},
|
|
430
|
-
[diagnosticCode.invalidPluginOptions]: {
|
|
303
|
+
[require_usingCtx.diagnosticCode.invalidPluginOptions]: {
|
|
431
304
|
title: "Invalid plugin options",
|
|
432
305
|
cause: "A plugin was configured with options that cannot be honored, for example `output.mode: 'file'` paired with a `group` option.",
|
|
433
306
|
fix: "Fix the plugin options. A single-file output has nothing to group, so remove the `group` option or use `output.mode: 'directory'`."
|
|
434
307
|
},
|
|
435
|
-
[diagnosticCode.postGenerateFailed]: {
|
|
308
|
+
[require_usingCtx.diagnosticCode.postGenerateFailed]: {
|
|
436
309
|
title: "Post-generate command failed",
|
|
437
310
|
cause: "A post-generate command (`output.postGenerate`) exited with a non-zero status.",
|
|
438
311
|
fix: "Check the command is installed and correct, and run it manually to see the error."
|
|
439
312
|
},
|
|
440
|
-
[diagnosticCode.formatFailed]: {
|
|
313
|
+
[require_usingCtx.diagnosticCode.formatFailed]: {
|
|
441
314
|
title: "Format failed",
|
|
442
315
|
cause: "The formatter pass over the generated files failed.",
|
|
443
316
|
fix: "Check the formatter (oxfmt, biome, or prettier) is installed and its config is valid, then run it manually on the output."
|
|
444
317
|
},
|
|
445
|
-
[diagnosticCode.lintFailed]: {
|
|
318
|
+
[require_usingCtx.diagnosticCode.lintFailed]: {
|
|
446
319
|
title: "Lint failed",
|
|
447
320
|
cause: "The linter pass over the generated files failed.",
|
|
448
321
|
fix: "Check the linter (oxlint, biome, or eslint) is installed and its config is valid, then run it manually on the output."
|
|
449
322
|
},
|
|
450
|
-
[diagnosticCode.performance]: {
|
|
323
|
+
[require_usingCtx.diagnosticCode.performance]: {
|
|
451
324
|
title: "Performance",
|
|
452
325
|
cause: "Not a failure. Records a plugin’s elapsed time, summed into the run total.",
|
|
453
326
|
fix: "No action. This is an informational metric."
|
|
454
327
|
},
|
|
455
|
-
[diagnosticCode.updateAvailable]: {
|
|
328
|
+
[require_usingCtx.diagnosticCode.updateAvailable]: {
|
|
456
329
|
title: "Update available",
|
|
457
330
|
cause: "A newer Kubb version is published on npm than the one running.",
|
|
458
331
|
fix: "Update the `@kubb/*` packages, for example `npm install -g @kubb/cli`, to get the latest fixes."
|
|
@@ -472,7 +345,7 @@ var Diagnostics = class Diagnostics {
|
|
|
472
345
|
/**
|
|
473
346
|
* The diagnostic code catalog, exposed as `Diagnostics.code` (e.g. `Diagnostics.code.refNotFound`).
|
|
474
347
|
*/
|
|
475
|
-
static code = diagnosticCode;
|
|
348
|
+
static code = require_usingCtx.diagnosticCode;
|
|
476
349
|
/**
|
|
477
350
|
* Type guard for a build {@link ProblemDiagnostic}.
|
|
478
351
|
*/
|
|
@@ -553,7 +426,7 @@ var Diagnostics = class Diagnostics {
|
|
|
553
426
|
current = current.cause;
|
|
554
427
|
}
|
|
555
428
|
return {
|
|
556
|
-
code: diagnosticCode.unknown,
|
|
429
|
+
code: require_usingCtx.diagnosticCode.unknown,
|
|
557
430
|
severity: "error",
|
|
558
431
|
message: root ? root.message : require_usingCtx.getErrorMessage(error),
|
|
559
432
|
cause: root
|
|
@@ -565,7 +438,7 @@ var Diagnostics = class Diagnostics {
|
|
|
565
438
|
static performance({ plugin, duration }) {
|
|
566
439
|
return {
|
|
567
440
|
kind: "performance",
|
|
568
|
-
code: diagnosticCode.performance,
|
|
441
|
+
code: require_usingCtx.diagnosticCode.performance,
|
|
569
442
|
severity: "info",
|
|
570
443
|
message: `${plugin} generated in ${Math.round(duration)}ms`,
|
|
571
444
|
plugin,
|
|
@@ -578,7 +451,7 @@ var Diagnostics = class Diagnostics {
|
|
|
578
451
|
static update({ currentVersion, latestVersion }) {
|
|
579
452
|
return {
|
|
580
453
|
kind: "update",
|
|
581
|
-
code: diagnosticCode.updateAvailable,
|
|
454
|
+
code: require_usingCtx.diagnosticCode.updateAvailable,
|
|
582
455
|
severity: "info",
|
|
583
456
|
message: `Update available: v${currentVersion} → v${latestVersion}. Run \`npm install -g @kubb/cli\` to update.`,
|
|
584
457
|
currentVersion,
|
|
@@ -671,7 +544,7 @@ var Diagnostics = class Diagnostics {
|
|
|
671
544
|
...problem?.location ? { location: problem.location } : {},
|
|
672
545
|
...problem?.help ? { help: problem.help } : {},
|
|
673
546
|
...problem?.plugin ? { plugin: problem.plugin } : {},
|
|
674
|
-
...diagnostic.code === diagnosticCode.unknown ? {} : { docsUrl: Diagnostics.docsUrl(diagnostic.code) }
|
|
547
|
+
...diagnostic.code === require_usingCtx.diagnosticCode.unknown ? {} : { docsUrl: Diagnostics.docsUrl(diagnostic.code) }
|
|
675
548
|
};
|
|
676
549
|
}
|
|
677
550
|
/**
|
|
@@ -691,7 +564,7 @@ var Diagnostics = class Diagnostics {
|
|
|
691
564
|
const details = [];
|
|
692
565
|
if (problem?.location && "pointer" in problem.location) details.push(` ${(0, node_util.styleText)("dim", "at:")} ${(0, node_util.styleText)("cyan", problem.location.pointer)}`);
|
|
693
566
|
if (problem?.help) details.push(` ${(0, node_util.styleText)("cyan", "fix:")} ${problem.help}`);
|
|
694
|
-
if (code !== diagnosticCode.unknown) details.push(` ${(0, node_util.styleText)("dim", "see:")} ${(0, node_util.styleText)("cyan", Diagnostics.docsUrl(code))}`);
|
|
567
|
+
if (code !== require_usingCtx.diagnosticCode.unknown) details.push(` ${(0, node_util.styleText)("dim", "see:")} ${(0, node_util.styleText)("cyan", Diagnostics.docsUrl(code))}`);
|
|
695
568
|
return {
|
|
696
569
|
headline,
|
|
697
570
|
details
|
|
@@ -716,7 +589,7 @@ var Diagnostics = class Diagnostics {
|
|
|
716
589
|
function normalizeOutput({ output, group, pluginName }) {
|
|
717
590
|
const mode = output.mode ?? "file";
|
|
718
591
|
if (mode === "file" && group) throw new Diagnostics.Error({
|
|
719
|
-
code: diagnosticCode.invalidPluginOptions,
|
|
592
|
+
code: require_usingCtx.diagnosticCode.invalidPluginOptions,
|
|
720
593
|
severity: "error",
|
|
721
594
|
message: `Plugin "${pluginName}" sets \`output.mode: 'file'\` but also configures a \`group\` option.`,
|
|
722
595
|
help: "A single-file output has nothing to group. Remove the `group` option, or use `output.mode: 'directory'` to organize files into subdirectories.",
|
|
@@ -1533,22 +1406,25 @@ var KubbDriver = class {
|
|
|
1533
1406
|
async run() {
|
|
1534
1407
|
const { hooks, config, fileManager } = this;
|
|
1535
1408
|
const diagnostics = [];
|
|
1536
|
-
const updateBuffer = [];
|
|
1537
1409
|
const parsersMap = /* @__PURE__ */ new Map();
|
|
1538
1410
|
for (const parser of config.parsers) if (parser.extNames) for (const ext of parser.extNames) parsersMap.set(ext, parser);
|
|
1411
|
+
const updateBuffer = [];
|
|
1539
1412
|
const unhookWrites = fileManager.hooks.addHooks({
|
|
1540
1413
|
start: async (files) => {
|
|
1541
1414
|
await hooks.callHook("kubb:files:processing:start", { files });
|
|
1542
1415
|
},
|
|
1543
|
-
update: (
|
|
1544
|
-
updateBuffer.push(
|
|
1416
|
+
update: ({ file, processed, total, percentage }) => {
|
|
1417
|
+
updateBuffer.push({
|
|
1418
|
+
file,
|
|
1419
|
+
processed,
|
|
1420
|
+
total,
|
|
1421
|
+
percentage,
|
|
1422
|
+
config
|
|
1423
|
+
});
|
|
1545
1424
|
},
|
|
1546
1425
|
end: async (files) => {
|
|
1547
1426
|
updateBuffer.sort((a, b) => a.processed - b.processed);
|
|
1548
|
-
await hooks.callHook("kubb:files:processing:update", { files: updateBuffer
|
|
1549
|
-
...item,
|
|
1550
|
-
config
|
|
1551
|
-
})) });
|
|
1427
|
+
await hooks.callHook("kubb:files:processing:update", { files: updateBuffer });
|
|
1552
1428
|
updateBuffer.length = 0;
|
|
1553
1429
|
await hooks.callHook("kubb:files:processing:end", { files });
|
|
1554
1430
|
}
|
|
@@ -1615,7 +1491,8 @@ var KubbDriver = class {
|
|
|
1615
1491
|
await hooks.callHook("kubb:plugins:end", this.#withFiles({ config }));
|
|
1616
1492
|
await fileManager.write(fileManager.files, {
|
|
1617
1493
|
storage: config.storage,
|
|
1618
|
-
parsers: parsersMap
|
|
1494
|
+
parsers: parsersMap,
|
|
1495
|
+
manifest: this.options.manifest
|
|
1619
1496
|
});
|
|
1620
1497
|
await hooks.callHook("kubb:build:end", {
|
|
1621
1498
|
files: this.fileManager.files,
|
|
@@ -1694,7 +1571,7 @@ var KubbDriver = class {
|
|
|
1694
1571
|
const allowedSchemaNamesByPlugin = /* @__PURE__ */ new Map();
|
|
1695
1572
|
for (const { plugin } of entries) {
|
|
1696
1573
|
const { exclude, include, override } = plugin.options;
|
|
1697
|
-
if (!((include?.some(({ type }) => OPERATION_FILTER_TYPES.has(type)) ?? false) && !(include?.some(({ type }) => type === "schemaName") ?? false))) continue;
|
|
1574
|
+
if (!((include?.some(({ type }) => require_usingCtx.OPERATION_FILTER_TYPES.has(type)) ?? false) && !(include?.some(({ type }) => type === "schemaName") ?? false))) continue;
|
|
1698
1575
|
const resolver = this.getResolver(plugin.name);
|
|
1699
1576
|
const includedOps = operations.filter((operation) => resolver.default.options(operation, {
|
|
1700
1577
|
options: plugin.options,
|
|
@@ -1976,6 +1853,72 @@ var KubbDriver = class {
|
|
|
1976
1853
|
}
|
|
1977
1854
|
};
|
|
1978
1855
|
//#endregion
|
|
1856
|
+
//#region src/outputManifest.ts
|
|
1857
|
+
/**
|
|
1858
|
+
* Bumped when the stored shape changes, so an older cache is discarded instead of misread.
|
|
1859
|
+
*/
|
|
1860
|
+
const VERSION = 1;
|
|
1861
|
+
function hash(value) {
|
|
1862
|
+
return (0, node_crypto.createHash)("sha256").update(value).digest("hex");
|
|
1863
|
+
}
|
|
1864
|
+
const MANIFEST_KEY = "output-manifest.json";
|
|
1865
|
+
async function loadEntries({ cache }) {
|
|
1866
|
+
try {
|
|
1867
|
+
const stored = await cache.readItem(MANIFEST_KEY);
|
|
1868
|
+
if (stored === null) return {};
|
|
1869
|
+
const data = JSON.parse(stored);
|
|
1870
|
+
if (data.version !== VERSION) return {};
|
|
1871
|
+
if (typeof data.entries !== "object" || data.entries === null || Array.isArray(data.entries)) return {};
|
|
1872
|
+
return data.entries;
|
|
1873
|
+
} catch {
|
|
1874
|
+
return {};
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
/**
|
|
1878
|
+
* Loads the stored manifest, starting empty when it is missing, unreadable, or from an older
|
|
1879
|
+
* version. `storage` holds the generated files, `cache` holds the manifest itself.
|
|
1880
|
+
*
|
|
1881
|
+
* @example
|
|
1882
|
+
* ```ts
|
|
1883
|
+
* const manifest = await createOutputManifest({ storage: config.storage, cache: cacheStorage({ root: config.root }) })
|
|
1884
|
+
* ```
|
|
1885
|
+
*/
|
|
1886
|
+
async function createOutputManifest({ storage, cache }) {
|
|
1887
|
+
const entries = await loadEntries({ cache });
|
|
1888
|
+
const tracked = /* @__PURE__ */ new Map();
|
|
1889
|
+
return {
|
|
1890
|
+
isUpToDate({ key, source, disk }) {
|
|
1891
|
+
const entry = entries[key];
|
|
1892
|
+
if (!entry) return false;
|
|
1893
|
+
return entry.source === hash(source) && entry.output === hash(disk);
|
|
1894
|
+
},
|
|
1895
|
+
track({ key, source }) {
|
|
1896
|
+
tracked.set(key, hash(source));
|
|
1897
|
+
},
|
|
1898
|
+
async commit() {
|
|
1899
|
+
try {
|
|
1900
|
+
const next = { ...entries };
|
|
1901
|
+
await require_usingCtx.inParallel({
|
|
1902
|
+
items: [...tracked],
|
|
1903
|
+
limit: 50,
|
|
1904
|
+
run: async ([key, source]) => {
|
|
1905
|
+
const stored = await storage.readItem(key);
|
|
1906
|
+
if (stored === null) return;
|
|
1907
|
+
next[key] = {
|
|
1908
|
+
source,
|
|
1909
|
+
output: hash(stored)
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
});
|
|
1913
|
+
await cache.writeItem(MANIFEST_KEY, JSON.stringify({
|
|
1914
|
+
version: VERSION,
|
|
1915
|
+
entries: next
|
|
1916
|
+
}));
|
|
1917
|
+
} catch {}
|
|
1918
|
+
}
|
|
1919
|
+
};
|
|
1920
|
+
}
|
|
1921
|
+
//#endregion
|
|
1979
1922
|
//#region src/createStorage.ts
|
|
1980
1923
|
/**
|
|
1981
1924
|
* Defines a custom storage backend. The builder receives user options and
|
|
@@ -2052,7 +1995,8 @@ function createLimiter(concurrency) {
|
|
|
2052
1995
|
*
|
|
2053
1996
|
* Writes are deduplicated and directory-safe:
|
|
2054
1997
|
* - leading and trailing whitespace is trimmed before writing
|
|
2055
|
-
* - the write is skipped when the file content
|
|
1998
|
+
* - the write is skipped when the file already holds that content, ignoring any trailing newline
|
|
1999
|
+
* a formatter left behind
|
|
2056
2000
|
* - missing parent directories are created automatically
|
|
2057
2001
|
* - Bun's native file API is used when running under Bun
|
|
2058
2002
|
* - concurrent `writeItem` calls are capped at {@link WRITE_CONCURRENCY} in flight, so a caller
|
|
@@ -2113,6 +2057,60 @@ const fsStorage = createStorage(() => {
|
|
|
2113
2057
|
};
|
|
2114
2058
|
});
|
|
2115
2059
|
//#endregion
|
|
2060
|
+
//#region src/storages/cacheStorage.ts
|
|
2061
|
+
/**
|
|
2062
|
+
* Directory Kubb keeps build caches in. A project with a `node_modules` gets
|
|
2063
|
+
* `node_modules/.cache/kubb`, the convention babel and eslint already use, so the cache stays out
|
|
2064
|
+
* of version control. Without one it falls back to the OS temp directory, keyed by root so two
|
|
2065
|
+
* projects sharing that directory keep their own cache.
|
|
2066
|
+
*
|
|
2067
|
+
* @example Inside a project
|
|
2068
|
+
* `resolveCacheDir('/project') // '/project/node_modules/.cache/kubb'`
|
|
2069
|
+
*/
|
|
2070
|
+
function resolveCacheDir(root) {
|
|
2071
|
+
const nodeModules = (0, node_path.join)(root, "node_modules");
|
|
2072
|
+
if ((0, node_fs.existsSync)(nodeModules)) return (0, node_path.join)(nodeModules, ".cache", "kubb");
|
|
2073
|
+
return (0, node_path.join)((0, node_os.tmpdir)(), "kubb", (0, node_crypto.createHash)("sha256").update(root).digest("hex").slice(0, 16));
|
|
2074
|
+
}
|
|
2075
|
+
/**
|
|
2076
|
+
* Filesystem storage for build caches rather than generated code. Keys are plain names resolved
|
|
2077
|
+
* inside {@link resolveCacheDir}, so a caller stores `'x.json'` without knowing where the cache
|
|
2078
|
+
* lives. Kept apart from the configured output storage, which may not be a local disk at all.
|
|
2079
|
+
*
|
|
2080
|
+
* @example
|
|
2081
|
+
* ```ts
|
|
2082
|
+
* const cache = cacheStorage({ root: config.root })
|
|
2083
|
+
* await cache.writeItem('output-manifest.json', JSON.stringify(entries))
|
|
2084
|
+
* ```
|
|
2085
|
+
*/
|
|
2086
|
+
const cacheStorage = createStorage(({ root = process.cwd() }) => {
|
|
2087
|
+
const dir = resolveCacheDir(root);
|
|
2088
|
+
const storage = fsStorage();
|
|
2089
|
+
const toPath = (key) => (0, node_path.join)(dir, key);
|
|
2090
|
+
return {
|
|
2091
|
+
name: "cache",
|
|
2092
|
+
async existsItem(key) {
|
|
2093
|
+
return storage.existsItem(toPath(key));
|
|
2094
|
+
},
|
|
2095
|
+
async readItem(key) {
|
|
2096
|
+
return storage.readItem(toPath(key));
|
|
2097
|
+
},
|
|
2098
|
+
async writeItem(key, value) {
|
|
2099
|
+
return storage.writeItem(toPath(key), value);
|
|
2100
|
+
},
|
|
2101
|
+
async removeItem(key) {
|
|
2102
|
+
return storage.removeItem(toPath(key));
|
|
2103
|
+
},
|
|
2104
|
+
async readKeys(base) {
|
|
2105
|
+
return storage.readKeys(base ? toPath(base) : dir);
|
|
2106
|
+
},
|
|
2107
|
+
async empty(base) {
|
|
2108
|
+
if (!base) return;
|
|
2109
|
+
return storage.empty(toPath(base));
|
|
2110
|
+
}
|
|
2111
|
+
};
|
|
2112
|
+
});
|
|
2113
|
+
//#endregion
|
|
2116
2114
|
//#region src/createKubb.ts
|
|
2117
2115
|
function resolveConfig(userConfig) {
|
|
2118
2116
|
return {
|
|
@@ -2131,6 +2129,13 @@ function resolveConfig(userConfig) {
|
|
|
2131
2129
|
};
|
|
2132
2130
|
}
|
|
2133
2131
|
/**
|
|
2132
|
+
* Whether anything runs over the output directory after the files are written. Only then can the
|
|
2133
|
+
* bytes on disk stop matching what Kubb wrote, which is what the manifest exists to track.
|
|
2134
|
+
*/
|
|
2135
|
+
function hasOutputPasses(output) {
|
|
2136
|
+
return Boolean(output.format || output.lint || output.postGenerate?.length);
|
|
2137
|
+
}
|
|
2138
|
+
/**
|
|
2134
2139
|
* Kubb code-generation instance bound to a single config entry. Resolves the user
|
|
2135
2140
|
* config in the constructor, so `config` is available right away, and shares `hooks`,
|
|
2136
2141
|
* `storage`, and `driver` across the `setup → build` lifecycle.
|
|
@@ -2152,6 +2157,7 @@ var Kubb = class {
|
|
|
2152
2157
|
config;
|
|
2153
2158
|
#driver = null;
|
|
2154
2159
|
#storage = null;
|
|
2160
|
+
#manifest = null;
|
|
2155
2161
|
constructor(userConfig, options = {}) {
|
|
2156
2162
|
this.config = resolveConfig(userConfig);
|
|
2157
2163
|
this.hooks = options.hooks ?? new require_usingCtx.Hookable();
|
|
@@ -2169,7 +2175,14 @@ var Kubb = class {
|
|
|
2169
2175
|
*/
|
|
2170
2176
|
async setup() {
|
|
2171
2177
|
const config = this.config;
|
|
2172
|
-
const
|
|
2178
|
+
const manifest = hasOutputPasses(config.output) ? await createOutputManifest({
|
|
2179
|
+
storage: config.storage,
|
|
2180
|
+
cache: cacheStorage({ root: config.root })
|
|
2181
|
+
}) : void 0;
|
|
2182
|
+
const driver = new KubbDriver(config, {
|
|
2183
|
+
hooks: this.hooks,
|
|
2184
|
+
manifest
|
|
2185
|
+
});
|
|
2173
2186
|
this.hooks.setMaxListeners(Math.max(10, config.plugins.length * 4));
|
|
2174
2187
|
if (config.output.clean) {
|
|
2175
2188
|
const cleanPath = (0, node_path.resolve)(config.root, config.output.path);
|
|
@@ -2185,6 +2198,7 @@ var Kubb = class {
|
|
|
2185
2198
|
await driver.setup();
|
|
2186
2199
|
this.#driver = driver;
|
|
2187
2200
|
this.#storage = config.storage;
|
|
2201
|
+
this.#manifest = manifest ?? null;
|
|
2188
2202
|
}
|
|
2189
2203
|
/**
|
|
2190
2204
|
* Runs the full pipeline and throws on any plugin error.
|
|
@@ -2272,6 +2286,7 @@ var Kubb = class {
|
|
|
2272
2286
|
}) : [];
|
|
2273
2287
|
const finalDiagnostics = [...diagnostics, ...outputDiagnostics];
|
|
2274
2288
|
const failed = Diagnostics.hasError(outputDiagnostics);
|
|
2289
|
+
if (!failed) await this.#manifest?.commit();
|
|
2275
2290
|
await hooks.callHook("kubb:generation:end", {
|
|
2276
2291
|
config,
|
|
2277
2292
|
storage,
|