@kubb/core 5.0.0-beta.20 → 5.0.0-beta.22
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/{KubbDriver-BXSnJ3qM.cjs → KubbDriver-DLha_xyo.cjs} +759 -108
- package/dist/KubbDriver-DLha_xyo.cjs.map +1 -0
- package/dist/{KubbDriver-Cxii_rBp.js → KubbDriver-l31wllgN.js} +737 -92
- package/dist/KubbDriver-l31wllgN.js.map +1 -0
- package/dist/{createKubb-Dcmtjqds.d.ts → createKubb-CYrw_xaR.d.ts} +91 -89
- package/dist/index.cjs +138 -762
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +136 -761
- package/dist/index.js.map +1 -1
- package/dist/mocks.cjs +4 -4
- package/dist/mocks.cjs.map +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/mocks.js +4 -4
- package/dist/mocks.js.map +1 -1
- package/package.json +4 -4
- package/src/FileManager.ts +65 -60
- package/src/FileProcessor.ts +11 -0
- package/src/KubbDriver.ts +368 -28
- package/src/createKubb.ts +144 -646
- package/src/createRenderer.ts +10 -0
- package/src/defineResolver.ts +7 -7
- package/src/mocks.ts +3 -3
- package/src/types.ts +2 -1
- package/dist/KubbDriver-BXSnJ3qM.cjs.map +0 -1
- package/dist/KubbDriver-Cxii_rBp.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,187 +1,9 @@
|
|
|
1
1
|
import "./chunk--u3MIqq1.js";
|
|
2
|
-
import { a as
|
|
3
|
-
import { EventEmitter } from "node:events";
|
|
2
|
+
import { a as FileManager, c as DEFAULT_BANNER, d as logLevel, f as URLPath, i as FileProcessor, l as DEFAULT_EXTENSION, m as BuildError, o as defineResolver, p as AsyncEventEmitter, r as _usingCtx, s as definePlugin, t as KubbDriver, u as DEFAULT_STUDIO_URL } from "./KubbDriver-l31wllgN.js";
|
|
4
3
|
import { access, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
5
4
|
import { dirname, join, resolve } from "node:path";
|
|
6
5
|
import * as ast from "@kubb/ast";
|
|
7
|
-
import { collectUsedSchemaNames, extractStringsFromNodes, transform } from "@kubb/ast";
|
|
8
6
|
import { version } from "node:process";
|
|
9
|
-
//#region ../../internals/utils/src/errors.ts
|
|
10
|
-
/**
|
|
11
|
-
* Thrown when one or more errors occur during a Kubb build.
|
|
12
|
-
* Carries the full list of underlying errors on `errors`.
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```ts
|
|
16
|
-
* throw new BuildError('Build failed', { errors: [err1, err2] })
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
var BuildError = class extends Error {
|
|
20
|
-
errors;
|
|
21
|
-
constructor(message, options) {
|
|
22
|
-
super(message, { cause: options.cause });
|
|
23
|
-
this.name = "BuildError";
|
|
24
|
-
this.errors = options.errors;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Coerces an unknown thrown value to an `Error` instance.
|
|
29
|
-
* Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```ts
|
|
33
|
-
* try { ... } catch(err) {
|
|
34
|
-
* throw new BuildError('Build failed', { cause: toError(err), errors: [] })
|
|
35
|
-
* }
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
function toError(value) {
|
|
39
|
-
return value instanceof Error ? value : new Error(String(value));
|
|
40
|
-
}
|
|
41
|
-
//#endregion
|
|
42
|
-
//#region ../../internals/utils/src/asyncEventEmitter.ts
|
|
43
|
-
/**
|
|
44
|
-
* Typed `EventEmitter` that awaits all async listeners before resolving.
|
|
45
|
-
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* ```ts
|
|
49
|
-
* const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
|
|
50
|
-
* emitter.on('build', async (name) => { console.log(name) })
|
|
51
|
-
* await emitter.emit('build', 'petstore') // all listeners awaited
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
var AsyncEventEmitter = class {
|
|
55
|
-
/**
|
|
56
|
-
* Maximum number of listeners per event before Node emits a memory-leak warning.
|
|
57
|
-
* @default 10
|
|
58
|
-
*/
|
|
59
|
-
constructor(maxListener = 10) {
|
|
60
|
-
this.#emitter.setMaxListeners(maxListener);
|
|
61
|
-
}
|
|
62
|
-
#emitter = new EventEmitter();
|
|
63
|
-
/**
|
|
64
|
-
* Emits `eventName` and awaits all registered listeners sequentially.
|
|
65
|
-
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```ts
|
|
69
|
-
* await emitter.emit('build', 'petstore')
|
|
70
|
-
* ```
|
|
71
|
-
*/
|
|
72
|
-
emit(eventName, ...eventArgs) {
|
|
73
|
-
const listeners = this.#emitter.listeners(eventName);
|
|
74
|
-
if (listeners.length === 0) return;
|
|
75
|
-
return this.#emitAll(eventName, listeners, eventArgs);
|
|
76
|
-
}
|
|
77
|
-
async #emitAll(eventName, listeners, eventArgs) {
|
|
78
|
-
for (const listener of listeners) try {
|
|
79
|
-
await listener(...eventArgs);
|
|
80
|
-
} catch (err) {
|
|
81
|
-
let serializedArgs;
|
|
82
|
-
try {
|
|
83
|
-
serializedArgs = JSON.stringify(eventArgs);
|
|
84
|
-
} catch {
|
|
85
|
-
serializedArgs = String(eventArgs);
|
|
86
|
-
}
|
|
87
|
-
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Registers a persistent listener for `eventName`.
|
|
92
|
-
*
|
|
93
|
-
* @example
|
|
94
|
-
* ```ts
|
|
95
|
-
* emitter.on('build', async (name) => { console.log(name) })
|
|
96
|
-
* ```
|
|
97
|
-
*/
|
|
98
|
-
on(eventName, handler) {
|
|
99
|
-
this.#emitter.on(eventName, handler);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Registers a one-shot listener that removes itself after the first invocation.
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```ts
|
|
106
|
-
* emitter.onOnce('build', async (name) => { console.log(name) })
|
|
107
|
-
* ```
|
|
108
|
-
*/
|
|
109
|
-
onOnce(eventName, handler) {
|
|
110
|
-
const wrapper = (...args) => {
|
|
111
|
-
this.off(eventName, wrapper);
|
|
112
|
-
return handler(...args);
|
|
113
|
-
};
|
|
114
|
-
this.on(eventName, wrapper);
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Removes a previously registered listener.
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* ```ts
|
|
121
|
-
* emitter.off('build', handler)
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
off(eventName, handler) {
|
|
125
|
-
this.#emitter.off(eventName, handler);
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Returns the number of listeners registered for `eventName`.
|
|
129
|
-
*
|
|
130
|
-
* @example
|
|
131
|
-
* ```ts
|
|
132
|
-
* emitter.on('build', handler)
|
|
133
|
-
* emitter.listenerCount('build') // 1
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
listenerCount(eventName) {
|
|
137
|
-
return this.#emitter.listenerCount(eventName);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Removes all listeners from every event channel.
|
|
141
|
-
*
|
|
142
|
-
* @example
|
|
143
|
-
* ```ts
|
|
144
|
-
* emitter.removeAll()
|
|
145
|
-
* ```
|
|
146
|
-
*/
|
|
147
|
-
removeAll() {
|
|
148
|
-
this.#emitter.removeAllListeners();
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
//#endregion
|
|
152
|
-
//#region ../../internals/utils/src/time.ts
|
|
153
|
-
/**
|
|
154
|
-
* Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.
|
|
155
|
-
* Rounds to 2 decimal places for sub-millisecond precision without noise.
|
|
156
|
-
*
|
|
157
|
-
* @example
|
|
158
|
-
* ```ts
|
|
159
|
-
* const start = process.hrtime()
|
|
160
|
-
* doWork()
|
|
161
|
-
* getElapsedMs(start) // 42.35
|
|
162
|
-
* ```
|
|
163
|
-
*/
|
|
164
|
-
function getElapsedMs(hrStart) {
|
|
165
|
-
const [seconds, nanoseconds] = process.hrtime(hrStart);
|
|
166
|
-
const ms = seconds * 1e3 + nanoseconds / 1e6;
|
|
167
|
-
return Math.round(ms * 100) / 100;
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).
|
|
171
|
-
*
|
|
172
|
-
* @example
|
|
173
|
-
* ```ts
|
|
174
|
-
* formatMs(250) // '250ms'
|
|
175
|
-
* formatMs(1500) // '1.50s'
|
|
176
|
-
* formatMs(90000) // '1m 30.0s'
|
|
177
|
-
* ```
|
|
178
|
-
*/
|
|
179
|
-
function formatMs(ms) {
|
|
180
|
-
if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
|
|
181
|
-
if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
|
|
182
|
-
return `${Math.round(ms)}ms`;
|
|
183
|
-
}
|
|
184
|
-
//#endregion
|
|
185
7
|
//#region ../../internals/utils/src/fs.ts
|
|
186
8
|
/**
|
|
187
9
|
* Resolves to `true` when the file or directory at `path` exists.
|
|
@@ -279,7 +101,7 @@ function createAdapter(build) {
|
|
|
279
101
|
}
|
|
280
102
|
//#endregion
|
|
281
103
|
//#region package.json
|
|
282
|
-
var version$1 = "5.0.0-beta.
|
|
104
|
+
var version$1 = "5.0.0-beta.22";
|
|
283
105
|
//#endregion
|
|
284
106
|
//#region src/createStorage.ts
|
|
285
107
|
/**
|
|
@@ -318,62 +140,6 @@ function createStorage(build) {
|
|
|
318
140
|
return (options) => build(options ?? {});
|
|
319
141
|
}
|
|
320
142
|
//#endregion
|
|
321
|
-
//#region src/FileProcessor.ts
|
|
322
|
-
function joinSources(file) {
|
|
323
|
-
const sources = file.sources;
|
|
324
|
-
if (sources.length === 0) return "";
|
|
325
|
-
const parts = [];
|
|
326
|
-
for (const source of sources) {
|
|
327
|
-
const s = extractStringsFromNodes(source.nodes);
|
|
328
|
-
if (s) parts.push(s);
|
|
329
|
-
}
|
|
330
|
-
return parts.join("\n\n");
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Converts a single file to a string using the registered parsers.
|
|
334
|
-
* Falls back to joining source values when no matching parser is found.
|
|
335
|
-
*
|
|
336
|
-
* @internal
|
|
337
|
-
*/
|
|
338
|
-
var FileProcessor = class {
|
|
339
|
-
events = new AsyncEventEmitter();
|
|
340
|
-
parse(file, { parsers, extension } = {}) {
|
|
341
|
-
const parseExtName = extension?.[file.extname] || void 0;
|
|
342
|
-
if (!parsers || !file.extname) return joinSources(file);
|
|
343
|
-
const parser = parsers.get(file.extname);
|
|
344
|
-
if (!parser) return joinSources(file);
|
|
345
|
-
return parser.parse(file, { extname: parseExtName });
|
|
346
|
-
}
|
|
347
|
-
*stream(files, options = {}) {
|
|
348
|
-
const total = files.length;
|
|
349
|
-
if (total === 0) return;
|
|
350
|
-
let processed = 0;
|
|
351
|
-
for (const file of files) {
|
|
352
|
-
const source = this.parse(file, options);
|
|
353
|
-
processed++;
|
|
354
|
-
yield {
|
|
355
|
-
file,
|
|
356
|
-
source,
|
|
357
|
-
processed,
|
|
358
|
-
total,
|
|
359
|
-
percentage: processed / total * 100
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
async run(files, options = {}) {
|
|
364
|
-
await this.events.emit("start", files);
|
|
365
|
-
for (const { file, source, processed, total, percentage } of this.stream(files, options)) await this.events.emit("update", {
|
|
366
|
-
file,
|
|
367
|
-
source,
|
|
368
|
-
processed,
|
|
369
|
-
percentage,
|
|
370
|
-
total
|
|
371
|
-
});
|
|
372
|
-
await this.events.emit("end", files);
|
|
373
|
-
return files;
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
//#endregion
|
|
377
143
|
//#region src/storages/fsStorage.ts
|
|
378
144
|
/**
|
|
379
145
|
* Built-in filesystem storage driver.
|
|
@@ -448,74 +214,12 @@ const fsStorage = createStorage(() => ({
|
|
|
448
214
|
}
|
|
449
215
|
}));
|
|
450
216
|
//#endregion
|
|
451
|
-
//#region \0@oxc-project+runtime@0.129.0/helpers/usingCtx.js
|
|
452
|
-
function _usingCtx() {
|
|
453
|
-
var r = "function" == typeof SuppressedError ? SuppressedError : function(r, e) {
|
|
454
|
-
var n = Error();
|
|
455
|
-
return n.name = "SuppressedError", n.error = r, n.suppressed = e, n;
|
|
456
|
-
};
|
|
457
|
-
var e = {};
|
|
458
|
-
var n = [];
|
|
459
|
-
function using(r, e) {
|
|
460
|
-
if (null != e) {
|
|
461
|
-
if (Object(e) !== e) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
|
|
462
|
-
if (r) var o = e[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
|
|
463
|
-
if (void 0 === o && (o = e[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r)) var t = o;
|
|
464
|
-
if ("function" != typeof o) throw new TypeError("Object is not disposable.");
|
|
465
|
-
t && (o = function o() {
|
|
466
|
-
try {
|
|
467
|
-
t.call(e);
|
|
468
|
-
} catch (r) {
|
|
469
|
-
return Promise.reject(r);
|
|
470
|
-
}
|
|
471
|
-
}), n.push({
|
|
472
|
-
v: e,
|
|
473
|
-
d: o,
|
|
474
|
-
a: r
|
|
475
|
-
});
|
|
476
|
-
} else r && n.push({
|
|
477
|
-
d: e,
|
|
478
|
-
a: r
|
|
479
|
-
});
|
|
480
|
-
return e;
|
|
481
|
-
}
|
|
482
|
-
return {
|
|
483
|
-
e,
|
|
484
|
-
u: using.bind(null, !1),
|
|
485
|
-
a: using.bind(null, !0),
|
|
486
|
-
d: function d() {
|
|
487
|
-
var o;
|
|
488
|
-
var t = this.e;
|
|
489
|
-
var s = 0;
|
|
490
|
-
function next() {
|
|
491
|
-
for (; o = n.pop();) try {
|
|
492
|
-
if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
|
|
493
|
-
if (o.d) {
|
|
494
|
-
var r = o.d.call(o.v);
|
|
495
|
-
if (o.a) return s |= 2, Promise.resolve(r).then(next, err);
|
|
496
|
-
} else s |= 1;
|
|
497
|
-
} catch (r) {
|
|
498
|
-
return err(r);
|
|
499
|
-
}
|
|
500
|
-
if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
|
|
501
|
-
if (t !== e) throw t;
|
|
502
|
-
}
|
|
503
|
-
function err(n) {
|
|
504
|
-
return t = t !== e ? new r(n, t) : n, next();
|
|
505
|
-
}
|
|
506
|
-
return next();
|
|
507
|
-
}
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
//#endregion
|
|
511
217
|
//#region src/createKubb.ts
|
|
512
218
|
/**
|
|
513
219
|
* Builds a `Storage` view scoped to the file paths produced by the current build.
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
* Writing via `setItem` stores the content in the underlying storage and registers the
|
|
518
|
-
* key so subsequent reads and `getKeys` are scoped to this build's output.
|
|
220
|
+
* Reads delegate to the underlying `storage` so source bytes stay where they were
|
|
221
|
+
* written; writes register the key so subsequent reads and `getKeys` are scoped
|
|
222
|
+
* to this build's output.
|
|
519
223
|
*/
|
|
520
224
|
function createSourcesView(storage) {
|
|
521
225
|
const paths = /* @__PURE__ */ new Set();
|
|
@@ -547,9 +251,8 @@ function createSourcesView(storage) {
|
|
|
547
251
|
}
|
|
548
252
|
}))();
|
|
549
253
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
const config = {
|
|
254
|
+
function resolveConfig(userConfig) {
|
|
255
|
+
return {
|
|
553
256
|
...userConfig,
|
|
554
257
|
root: userConfig.root || process.cwd(),
|
|
555
258
|
parsers: userConfig.parsers ?? [],
|
|
@@ -567,422 +270,6 @@ async function setup(userConfig, options = {}) {
|
|
|
567
270
|
} : void 0,
|
|
568
271
|
plugins: userConfig.plugins ?? []
|
|
569
272
|
};
|
|
570
|
-
const driver = new KubbDriver(config, { hooks });
|
|
571
|
-
const storage = createSourcesView(config.storage);
|
|
572
|
-
const diagnosticInfo = getDiagnosticInfo();
|
|
573
|
-
await hooks.emit("kubb:debug", {
|
|
574
|
-
date: /* @__PURE__ */ new Date(),
|
|
575
|
-
logs: [
|
|
576
|
-
"Configuration:",
|
|
577
|
-
` • Name: ${userConfig.name || "unnamed"}`,
|
|
578
|
-
` • Root: ${userConfig.root || process.cwd()}`,
|
|
579
|
-
` • Output: ${userConfig.output?.path || "not specified"}`,
|
|
580
|
-
` • Plugins: ${userConfig.plugins?.length || 0}`,
|
|
581
|
-
"Output Settings:",
|
|
582
|
-
` • Storage: ${config.storage.name}`,
|
|
583
|
-
` • Formatter: ${userConfig.output?.format || "none"}`,
|
|
584
|
-
` • Linter: ${userConfig.output?.lint || "none"}`,
|
|
585
|
-
`Running adapter: ${config.adapter?.name || "none"}`,
|
|
586
|
-
"Environment:",
|
|
587
|
-
Object.entries(diagnosticInfo).map(([key, value]) => ` • ${key}: ${value}`).join("\n")
|
|
588
|
-
]
|
|
589
|
-
});
|
|
590
|
-
try {
|
|
591
|
-
if (isInputPath(userConfig) && !new URLPath(userConfig.input.path).isURL) {
|
|
592
|
-
await exists(userConfig.input.path);
|
|
593
|
-
await hooks.emit("kubb:debug", {
|
|
594
|
-
date: /* @__PURE__ */ new Date(),
|
|
595
|
-
logs: [`✓ Input file validated: ${userConfig.input.path}`]
|
|
596
|
-
});
|
|
597
|
-
}
|
|
598
|
-
} catch (caughtError) {
|
|
599
|
-
if (isInputPath(userConfig)) {
|
|
600
|
-
const error = caughtError;
|
|
601
|
-
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 });
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
if (config.output.clean) {
|
|
605
|
-
await hooks.emit("kubb:debug", {
|
|
606
|
-
date: /* @__PURE__ */ new Date(),
|
|
607
|
-
logs: ["Cleaning output directories", ` • Output: ${config.output.path}`]
|
|
608
|
-
});
|
|
609
|
-
await config.storage.clear(resolve(config.root, config.output.path));
|
|
610
|
-
}
|
|
611
|
-
await driver.setup();
|
|
612
|
-
return {
|
|
613
|
-
config,
|
|
614
|
-
hooks,
|
|
615
|
-
driver,
|
|
616
|
-
storage,
|
|
617
|
-
dispose,
|
|
618
|
-
[Symbol.dispose]: dispose
|
|
619
|
-
};
|
|
620
|
-
function dispose() {
|
|
621
|
-
driver.dispose();
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
async function safeBuild(setupResult) {
|
|
625
|
-
try {
|
|
626
|
-
var _usingCtx$1 = _usingCtx();
|
|
627
|
-
_usingCtx$1.u(setupResult);
|
|
628
|
-
const { driver, hooks, storage } = setupResult;
|
|
629
|
-
const failedPlugins = /* @__PURE__ */ new Set();
|
|
630
|
-
const pluginTimings = /* @__PURE__ */ new Map();
|
|
631
|
-
const config = driver.config;
|
|
632
|
-
const writtenPaths = /* @__PURE__ */ new Set();
|
|
633
|
-
const parsersMap = /* @__PURE__ */ new Map();
|
|
634
|
-
const fileProcessor = new FileProcessor();
|
|
635
|
-
for (const parser of config.parsers) if (parser.extNames) for (const extname of parser.extNames) parsersMap.set(extname, parser);
|
|
636
|
-
async function flushPendingFiles() {
|
|
637
|
-
const files = driver.fileManager.files.filter((f) => !writtenPaths.has(f.path));
|
|
638
|
-
if (files.length === 0) return;
|
|
639
|
-
await hooks.emit("kubb:debug", {
|
|
640
|
-
date: /* @__PURE__ */ new Date(),
|
|
641
|
-
logs: [`Writing ${files.length} files...`]
|
|
642
|
-
});
|
|
643
|
-
await hooks.emit("kubb:files:processing:start", { files });
|
|
644
|
-
const stream = fileProcessor.stream(files, {
|
|
645
|
-
parsers: parsersMap,
|
|
646
|
-
extension: config.output.extension
|
|
647
|
-
});
|
|
648
|
-
const queue = [];
|
|
649
|
-
for (const { file, source, processed, total, percentage } of stream) {
|
|
650
|
-
writtenPaths.add(file.path);
|
|
651
|
-
queue.push((async () => {
|
|
652
|
-
await hooks.emit("kubb:file:processing:update", {
|
|
653
|
-
file,
|
|
654
|
-
source,
|
|
655
|
-
processed,
|
|
656
|
-
total,
|
|
657
|
-
percentage,
|
|
658
|
-
config
|
|
659
|
-
});
|
|
660
|
-
if (source) await storage.setItem(file.path, source);
|
|
661
|
-
})());
|
|
662
|
-
if (queue.length >= 50) await Promise.all(queue.splice(0));
|
|
663
|
-
}
|
|
664
|
-
await Promise.all(queue);
|
|
665
|
-
await hooks.emit("kubb:files:processing:end", { files });
|
|
666
|
-
await hooks.emit("kubb:debug", {
|
|
667
|
-
date: /* @__PURE__ */ new Date(),
|
|
668
|
-
logs: [`✓ File write process completed for ${files.length} files`]
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
async function dispatchOperationsToGenerators(generators, collectedOperations, ctx, rendererFor) {
|
|
672
|
-
for (const gen of generators) {
|
|
673
|
-
if (!gen.operations) continue;
|
|
674
|
-
await applyHookResult({
|
|
675
|
-
result: await gen.operations(collectedOperations, ctx),
|
|
676
|
-
driver,
|
|
677
|
-
rendererFactory: rendererFor(gen)
|
|
678
|
-
});
|
|
679
|
-
}
|
|
680
|
-
await driver.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
|
|
681
|
-
}
|
|
682
|
-
/**
|
|
683
|
-
* Single-pass fan-out: iterates all schemas and operations once, distributing each node
|
|
684
|
-
* to every generator-plugin in parallel. This replaces the N-pass-per-plugin pattern
|
|
685
|
-
* (each plugin getting its own iterator) with one parse pass fanned to all plugins,
|
|
686
|
-
* eliminating the N×parse-time overhead for multi-plugin builds.
|
|
687
|
-
*/
|
|
688
|
-
async function runPlugins(entries) {
|
|
689
|
-
const { schemas, operations } = driver.inputNode;
|
|
690
|
-
const operationFilterTypes = new Set([
|
|
691
|
-
"tag",
|
|
692
|
-
"operationId",
|
|
693
|
-
"path",
|
|
694
|
-
"method",
|
|
695
|
-
"contentType"
|
|
696
|
-
]);
|
|
697
|
-
const states = entries.map(({ plugin, context, hrStart }) => {
|
|
698
|
-
const { exclude, include, override } = plugin.options;
|
|
699
|
-
const hasExclude = Array.isArray(exclude) && exclude.length > 0;
|
|
700
|
-
const hasInclude = Array.isArray(include) && include.length > 0;
|
|
701
|
-
const hasOverride = Array.isArray(override) && override.length > 0;
|
|
702
|
-
return {
|
|
703
|
-
plugin,
|
|
704
|
-
generatorContext: {
|
|
705
|
-
...context,
|
|
706
|
-
resolver: driver.getResolver(plugin.name)
|
|
707
|
-
},
|
|
708
|
-
generators: plugin.generators ?? [],
|
|
709
|
-
hrStart,
|
|
710
|
-
failed: false,
|
|
711
|
-
error: void 0,
|
|
712
|
-
optionsAreStatic: !hasExclude && !hasInclude && !hasOverride,
|
|
713
|
-
allowedSchemaNames: void 0
|
|
714
|
-
};
|
|
715
|
-
});
|
|
716
|
-
const pruningStates = states.filter(({ plugin }) => {
|
|
717
|
-
const { include } = plugin.options;
|
|
718
|
-
return (include?.some(({ type }) => operationFilterTypes.has(type)) ?? false) && !(include?.some(({ type }) => type === "schemaName") ?? false);
|
|
719
|
-
});
|
|
720
|
-
if (pruningStates.length > 0) {
|
|
721
|
-
const allSchemas = [];
|
|
722
|
-
for await (const schema of schemas) allSchemas.push(schema);
|
|
723
|
-
const includedOpsByState = new Map(pruningStates.map((s) => [s, []]));
|
|
724
|
-
for await (const operation of operations) for (const state of pruningStates) {
|
|
725
|
-
const { exclude, include, override } = state.plugin.options;
|
|
726
|
-
if (state.generatorContext.resolver.resolveOptions(operation, {
|
|
727
|
-
options: state.plugin.options,
|
|
728
|
-
exclude,
|
|
729
|
-
include,
|
|
730
|
-
override
|
|
731
|
-
}) !== null) includedOpsByState.get(state)?.push(operation);
|
|
732
|
-
}
|
|
733
|
-
for (const state of pruningStates) state.allowedSchemaNames = collectUsedSchemaNames(includedOpsByState.get(state) ?? [], allSchemas);
|
|
734
|
-
}
|
|
735
|
-
function resolveRendererFor(gen, state) {
|
|
736
|
-
return gen.renderer === null ? void 0 : gen.renderer ?? state.plugin.renderer ?? state.generatorContext.config.renderer;
|
|
737
|
-
}
|
|
738
|
-
async function dispatchSchema(state, node) {
|
|
739
|
-
if (state.failed) return;
|
|
740
|
-
try {
|
|
741
|
-
const { plugin, generatorContext, generators } = state;
|
|
742
|
-
const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
|
|
743
|
-
if (state.allowedSchemaNames !== void 0 && transformedNode.name && !state.allowedSchemaNames.has(transformedNode.name)) return;
|
|
744
|
-
const { exclude, include, override } = plugin.options;
|
|
745
|
-
const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
|
|
746
|
-
options: plugin.options,
|
|
747
|
-
exclude,
|
|
748
|
-
include,
|
|
749
|
-
override
|
|
750
|
-
});
|
|
751
|
-
if (options === null) return;
|
|
752
|
-
const ctx = {
|
|
753
|
-
...generatorContext,
|
|
754
|
-
options
|
|
755
|
-
};
|
|
756
|
-
for (const gen of generators) {
|
|
757
|
-
if (!gen.schema) continue;
|
|
758
|
-
const raw = gen.schema(transformedNode, ctx);
|
|
759
|
-
const applied = applyHookResult({
|
|
760
|
-
result: isPromise(raw) ? await raw : raw,
|
|
761
|
-
driver,
|
|
762
|
-
rendererFactory: resolveRendererFor(gen, state)
|
|
763
|
-
});
|
|
764
|
-
if (isPromise(applied)) await applied;
|
|
765
|
-
}
|
|
766
|
-
await driver.hooks.emit("kubb:generate:schema", transformedNode, ctx);
|
|
767
|
-
} catch (caughtError) {
|
|
768
|
-
state.failed = true;
|
|
769
|
-
state.error = caughtError;
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
async function dispatchOperation(state, node) {
|
|
773
|
-
if (state.failed) return;
|
|
774
|
-
try {
|
|
775
|
-
const { plugin, generatorContext, generators } = state;
|
|
776
|
-
const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
|
|
777
|
-
const { exclude, include, override } = plugin.options;
|
|
778
|
-
const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
|
|
779
|
-
options: plugin.options,
|
|
780
|
-
exclude,
|
|
781
|
-
include,
|
|
782
|
-
override
|
|
783
|
-
});
|
|
784
|
-
if (options === null) return;
|
|
785
|
-
const ctx = {
|
|
786
|
-
...generatorContext,
|
|
787
|
-
options
|
|
788
|
-
};
|
|
789
|
-
for (const gen of generators) {
|
|
790
|
-
if (!gen.operation) continue;
|
|
791
|
-
const raw = gen.operation(transformedNode, ctx);
|
|
792
|
-
const applied = applyHookResult({
|
|
793
|
-
result: isPromise(raw) ? await raw : raw,
|
|
794
|
-
driver,
|
|
795
|
-
rendererFactory: resolveRendererFor(gen, state)
|
|
796
|
-
});
|
|
797
|
-
if (isPromise(applied)) await applied;
|
|
798
|
-
}
|
|
799
|
-
await driver.hooks.emit("kubb:generate:operation", transformedNode, ctx);
|
|
800
|
-
} catch (caughtError) {
|
|
801
|
-
state.failed = true;
|
|
802
|
-
state.error = caughtError;
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
await forBatches(schemas, (nodes) => Promise.all(nodes.flatMap((n) => states.map((state) => dispatchSchema(state, n)))), {
|
|
806
|
-
concurrency: 8,
|
|
807
|
-
flush: flushPendingFiles
|
|
808
|
-
});
|
|
809
|
-
const collectedOperations = [];
|
|
810
|
-
await forBatches(operations, (nodes) => {
|
|
811
|
-
collectedOperations.push(...nodes);
|
|
812
|
-
return Promise.all(nodes.flatMap((n) => states.map((state) => dispatchOperation(state, n))));
|
|
813
|
-
}, {
|
|
814
|
-
concurrency: 8,
|
|
815
|
-
flush: flushPendingFiles
|
|
816
|
-
});
|
|
817
|
-
for (const state of states) {
|
|
818
|
-
if (!state.failed) try {
|
|
819
|
-
const { plugin, generatorContext, generators } = state;
|
|
820
|
-
await dispatchOperationsToGenerators(generators, collectedOperations, {
|
|
821
|
-
...generatorContext,
|
|
822
|
-
options: plugin.options
|
|
823
|
-
}, (gen) => resolveRendererFor(gen, state));
|
|
824
|
-
} catch (caughtError) {
|
|
825
|
-
state.failed = true;
|
|
826
|
-
state.error = caughtError;
|
|
827
|
-
}
|
|
828
|
-
const duration = getElapsedMs(state.hrStart);
|
|
829
|
-
pluginTimings.set(state.plugin.name, duration);
|
|
830
|
-
await driver.hooks.emit("kubb:plugin:end", {
|
|
831
|
-
plugin: state.plugin,
|
|
832
|
-
duration,
|
|
833
|
-
success: !state.failed,
|
|
834
|
-
...state.failed && state.error ? { error: state.error } : {},
|
|
835
|
-
config: driver.config,
|
|
836
|
-
get files() {
|
|
837
|
-
return driver.fileManager.files;
|
|
838
|
-
},
|
|
839
|
-
upsertFile: (...files) => driver.fileManager.upsert(...files)
|
|
840
|
-
});
|
|
841
|
-
if (state.failed && state.error) failedPlugins.add({
|
|
842
|
-
plugin: state.plugin,
|
|
843
|
-
error: state.error
|
|
844
|
-
});
|
|
845
|
-
await driver.hooks.emit("kubb:debug", {
|
|
846
|
-
date: /* @__PURE__ */ new Date(),
|
|
847
|
-
logs: [state.failed ? "✗ Plugin start failed" : `✓ Plugin started successfully (${formatMs(duration)})`]
|
|
848
|
-
});
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
try {
|
|
852
|
-
await driver.emitSetupHooks();
|
|
853
|
-
if (driver.adapter && driver.inputNode) await hooks.emit("kubb:build:start", {
|
|
854
|
-
config,
|
|
855
|
-
adapter: driver.adapter,
|
|
856
|
-
meta: driver.inputNode.meta,
|
|
857
|
-
getPlugin: driver.getPlugin.bind(driver),
|
|
858
|
-
get files() {
|
|
859
|
-
return driver.fileManager.files;
|
|
860
|
-
},
|
|
861
|
-
upsertFile: (...files) => driver.fileManager.upsert(...files)
|
|
862
|
-
});
|
|
863
|
-
const generatorPlugins = [];
|
|
864
|
-
for (const plugin of driver.plugins.values()) {
|
|
865
|
-
const context = driver.getContext(plugin);
|
|
866
|
-
const hrStart = process.hrtime();
|
|
867
|
-
try {
|
|
868
|
-
await hooks.emit("kubb:plugin:start", { plugin });
|
|
869
|
-
await hooks.emit("kubb:debug", {
|
|
870
|
-
date: /* @__PURE__ */ new Date(),
|
|
871
|
-
logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
|
|
872
|
-
});
|
|
873
|
-
} catch (caughtError) {
|
|
874
|
-
const error = caughtError;
|
|
875
|
-
const duration = getElapsedMs(hrStart);
|
|
876
|
-
pluginTimings.set(plugin.name, duration);
|
|
877
|
-
await hooks.emit("kubb:plugin:end", {
|
|
878
|
-
plugin,
|
|
879
|
-
duration,
|
|
880
|
-
success: false,
|
|
881
|
-
error,
|
|
882
|
-
config,
|
|
883
|
-
get files() {
|
|
884
|
-
return driver.fileManager.files;
|
|
885
|
-
},
|
|
886
|
-
upsertFile: (...files) => driver.fileManager.upsert(...files)
|
|
887
|
-
});
|
|
888
|
-
failedPlugins.add({
|
|
889
|
-
plugin,
|
|
890
|
-
error
|
|
891
|
-
});
|
|
892
|
-
continue;
|
|
893
|
-
}
|
|
894
|
-
if (plugin.generators?.length || driver.hasEventGenerators(plugin.name)) {
|
|
895
|
-
generatorPlugins.push({
|
|
896
|
-
plugin,
|
|
897
|
-
context,
|
|
898
|
-
hrStart
|
|
899
|
-
});
|
|
900
|
-
continue;
|
|
901
|
-
}
|
|
902
|
-
const duration = getElapsedMs(hrStart);
|
|
903
|
-
pluginTimings.set(plugin.name, duration);
|
|
904
|
-
await hooks.emit("kubb:plugin:end", {
|
|
905
|
-
plugin,
|
|
906
|
-
duration,
|
|
907
|
-
success: true,
|
|
908
|
-
config,
|
|
909
|
-
get files() {
|
|
910
|
-
return driver.fileManager.files;
|
|
911
|
-
},
|
|
912
|
-
upsertFile: (...files) => driver.fileManager.upsert(...files)
|
|
913
|
-
});
|
|
914
|
-
await hooks.emit("kubb:debug", {
|
|
915
|
-
date: /* @__PURE__ */ new Date(),
|
|
916
|
-
logs: [`✓ Plugin started successfully (${formatMs(duration)})`]
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
|
-
if (generatorPlugins.length > 0) if (driver.inputNode) await withDrain(() => runPlugins(generatorPlugins), flushPendingFiles);
|
|
920
|
-
else for (const { plugin, hrStart } of generatorPlugins) {
|
|
921
|
-
const duration = getElapsedMs(hrStart);
|
|
922
|
-
pluginTimings.set(plugin.name, duration);
|
|
923
|
-
await hooks.emit("kubb:plugin:end", {
|
|
924
|
-
plugin,
|
|
925
|
-
duration,
|
|
926
|
-
success: true,
|
|
927
|
-
config,
|
|
928
|
-
get files() {
|
|
929
|
-
return driver.fileManager.files;
|
|
930
|
-
},
|
|
931
|
-
upsertFile: (...files) => driver.fileManager.upsert(...files)
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
|
-
await hooks.emit("kubb:plugins:end", {
|
|
935
|
-
config,
|
|
936
|
-
get files() {
|
|
937
|
-
return driver.fileManager.files;
|
|
938
|
-
},
|
|
939
|
-
upsertFile: (...files) => driver.fileManager.upsert(...files)
|
|
940
|
-
});
|
|
941
|
-
await flushPendingFiles();
|
|
942
|
-
const files = driver.fileManager.files;
|
|
943
|
-
await hooks.emit("kubb:build:end", {
|
|
944
|
-
files,
|
|
945
|
-
config,
|
|
946
|
-
outputDir: resolve(config.root, config.output.path)
|
|
947
|
-
});
|
|
948
|
-
return {
|
|
949
|
-
failedPlugins,
|
|
950
|
-
files,
|
|
951
|
-
driver,
|
|
952
|
-
pluginTimings,
|
|
953
|
-
storage
|
|
954
|
-
};
|
|
955
|
-
} catch (error) {
|
|
956
|
-
return {
|
|
957
|
-
failedPlugins,
|
|
958
|
-
files: [],
|
|
959
|
-
driver,
|
|
960
|
-
pluginTimings,
|
|
961
|
-
error,
|
|
962
|
-
storage
|
|
963
|
-
};
|
|
964
|
-
}
|
|
965
|
-
} catch (_) {
|
|
966
|
-
_usingCtx$1.e = _;
|
|
967
|
-
} finally {
|
|
968
|
-
_usingCtx$1.d();
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
async function build(setupResult) {
|
|
972
|
-
const { files, driver, failedPlugins, pluginTimings, error, storage } = await safeBuild(setupResult);
|
|
973
|
-
if (error) throw error;
|
|
974
|
-
if (failedPlugins.size > 0) {
|
|
975
|
-
const errors = [...failedPlugins].map(({ error }) => error);
|
|
976
|
-
throw new BuildError(`Build Error with ${failedPlugins.size} failed plugins`, { errors });
|
|
977
|
-
}
|
|
978
|
-
return {
|
|
979
|
-
failedPlugins,
|
|
980
|
-
files,
|
|
981
|
-
driver,
|
|
982
|
-
pluginTimings,
|
|
983
|
-
error: void 0,
|
|
984
|
-
storage
|
|
985
|
-
};
|
|
986
273
|
}
|
|
987
274
|
/**
|
|
988
275
|
* Returns a snapshot of the current runtime environment.
|
|
@@ -1003,56 +290,143 @@ function isInputPath(config) {
|
|
|
1003
290
|
return typeof config?.input === "object" && config.input !== null && "path" in config.input;
|
|
1004
291
|
}
|
|
1005
292
|
/**
|
|
1006
|
-
*
|
|
293
|
+
* Kubb code-generation instance bound to a single config entry. Resolves the user
|
|
294
|
+
* config during `setup()` and shares `hooks`, `storage`, `driver`, and `config` across
|
|
295
|
+
* the `setup → build` lifecycle.
|
|
1007
296
|
*
|
|
1008
|
-
*
|
|
1009
|
-
* `setup()`. The instance then holds shared state (`hooks`, `storage`, `driver`, `config`)
|
|
1010
|
-
* across the `setup → build` lifecycle. Attach event listeners to `kubb.hooks` before
|
|
1011
|
-
* calling `setup()` or `build()`.
|
|
297
|
+
* Attach event listeners to `.hooks` before calling `setup()` or `build()`.
|
|
1012
298
|
*
|
|
1013
299
|
* @example
|
|
1014
300
|
* ```ts
|
|
1015
301
|
* const kubb = createKubb(userConfig)
|
|
1016
|
-
*
|
|
1017
|
-
* kubb.hooks.on('kubb:plugin:end', ({ plugin, duration }) => {
|
|
1018
|
-
* console.log(`${plugin.name} completed in ${duration}ms`)
|
|
1019
|
-
* })
|
|
1020
|
-
*
|
|
302
|
+
* kubb.hooks.on('kubb:plugin:end', ({ plugin, duration }) => console.log(plugin.name, duration))
|
|
1021
303
|
* const { files, failedPlugins } = await kubb.safeBuild()
|
|
1022
304
|
* ```
|
|
1023
305
|
*/
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
306
|
+
var Kubb = class {
|
|
307
|
+
hooks;
|
|
308
|
+
#userConfig;
|
|
309
|
+
#config = null;
|
|
310
|
+
#driver = null;
|
|
311
|
+
#storage = null;
|
|
312
|
+
constructor(userConfig, options = {}) {
|
|
313
|
+
this.#userConfig = userConfig;
|
|
314
|
+
this.hooks = options.hooks ?? new AsyncEventEmitter();
|
|
315
|
+
}
|
|
316
|
+
get storage() {
|
|
317
|
+
if (!this.#storage) throw new Error("[kubb] setup() must be called before accessing storage");
|
|
318
|
+
return this.#storage;
|
|
319
|
+
}
|
|
320
|
+
get driver() {
|
|
321
|
+
if (!this.#driver) throw new Error("[kubb] setup() must be called before accessing driver");
|
|
322
|
+
return this.#driver;
|
|
323
|
+
}
|
|
324
|
+
get config() {
|
|
325
|
+
if (!this.#config) throw new Error("[kubb] setup() must be called before accessing config");
|
|
326
|
+
return this.#config;
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Resolves config and initializes the driver. `build()` calls this automatically.
|
|
330
|
+
*/
|
|
331
|
+
async setup() {
|
|
332
|
+
const config = resolveConfig(this.#userConfig);
|
|
333
|
+
const driver = new KubbDriver(config, { hooks: this.hooks });
|
|
334
|
+
const storage = createSourcesView(config.storage);
|
|
335
|
+
await this.hooks.emit("kubb:debug", {
|
|
336
|
+
date: /* @__PURE__ */ new Date(),
|
|
337
|
+
logs: this.#configLogs(config)
|
|
338
|
+
});
|
|
339
|
+
if (isInputPath(this.#userConfig) && !new URLPath(this.#userConfig.input.path).isURL) try {
|
|
340
|
+
await exists(this.#userConfig.input.path);
|
|
341
|
+
await this.hooks.emit("kubb:debug", {
|
|
342
|
+
date: /* @__PURE__ */ new Date(),
|
|
343
|
+
logs: [`✓ Input file validated: ${this.#userConfig.input.path}`]
|
|
344
|
+
});
|
|
345
|
+
} catch (caughtError) {
|
|
346
|
+
throw new Error(`Cannot read file/URL defined in \`input.path\` or set with \`kubb generate PATH\` in the CLI of your Kubb config ${this.#userConfig.input.path}`, { cause: caughtError });
|
|
1053
347
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
348
|
+
if (config.output.clean) {
|
|
349
|
+
await this.hooks.emit("kubb:debug", {
|
|
350
|
+
date: /* @__PURE__ */ new Date(),
|
|
351
|
+
logs: ["Cleaning output directories", ` • Output: ${config.output.path}`]
|
|
352
|
+
});
|
|
353
|
+
await config.storage.clear(resolve(config.root, config.output.path));
|
|
354
|
+
}
|
|
355
|
+
await driver.setup();
|
|
356
|
+
this.#config = config;
|
|
357
|
+
this.#driver = driver;
|
|
358
|
+
this.#storage = storage;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Runs the full pipeline and throws on any plugin error.
|
|
362
|
+
* Automatically calls `setup()` if needed.
|
|
363
|
+
*/
|
|
364
|
+
async build() {
|
|
365
|
+
const out = await this.safeBuild();
|
|
366
|
+
if (out.error) throw out.error;
|
|
367
|
+
if (out.failedPlugins.size > 0) {
|
|
368
|
+
const errors = [...out.failedPlugins].map(({ error }) => error);
|
|
369
|
+
throw new BuildError(`Build Error with ${out.failedPlugins.size} failed plugins`, { errors });
|
|
370
|
+
}
|
|
371
|
+
return out;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Runs the full pipeline and captures errors in `BuildOutput` instead of throwing.
|
|
375
|
+
* Automatically calls `setup()` if needed.
|
|
376
|
+
*/
|
|
377
|
+
async safeBuild() {
|
|
378
|
+
try {
|
|
379
|
+
var _usingCtx$1 = _usingCtx();
|
|
380
|
+
if (!this.#driver) await this.setup();
|
|
381
|
+
const cleanup = _usingCtx$1.u(this);
|
|
382
|
+
const driver = cleanup.driver;
|
|
383
|
+
const storage = cleanup.storage;
|
|
384
|
+
const { failedPlugins, pluginTimings, error } = await driver.run({ storage });
|
|
385
|
+
return {
|
|
386
|
+
failedPlugins,
|
|
387
|
+
files: driver.fileManager.files,
|
|
388
|
+
driver,
|
|
389
|
+
pluginTimings,
|
|
390
|
+
storage,
|
|
391
|
+
...error ? { error } : {}
|
|
392
|
+
};
|
|
393
|
+
} catch (_) {
|
|
394
|
+
_usingCtx$1.e = _;
|
|
395
|
+
} finally {
|
|
396
|
+
_usingCtx$1.d();
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
dispose() {
|
|
400
|
+
this.#driver?.dispose();
|
|
401
|
+
}
|
|
402
|
+
[Symbol.dispose]() {
|
|
403
|
+
this.dispose();
|
|
404
|
+
}
|
|
405
|
+
#configLogs(config) {
|
|
406
|
+
const u = this.#userConfig;
|
|
407
|
+
const diag = getDiagnosticInfo();
|
|
408
|
+
return [
|
|
409
|
+
"Configuration:",
|
|
410
|
+
` • Name: ${u.name || "unnamed"}`,
|
|
411
|
+
` • Root: ${u.root || process.cwd()}`,
|
|
412
|
+
` • Output: ${u.output?.path || "not specified"}`,
|
|
413
|
+
` • Plugins: ${u.plugins?.length || 0}`,
|
|
414
|
+
"Output Settings:",
|
|
415
|
+
` • Storage: ${config.storage.name}`,
|
|
416
|
+
` • Formatter: ${u.output?.format || "none"}`,
|
|
417
|
+
` • Linter: ${u.output?.lint || "none"}`,
|
|
418
|
+
`Running adapter: ${config.adapter?.name || "none"}`,
|
|
419
|
+
"Environment:",
|
|
420
|
+
Object.entries(diag).map(([key, value]) => ` • ${key}: ${value}`).join("\n")
|
|
421
|
+
];
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
/**
|
|
425
|
+
* Factory for {@link Kubb}. Equivalent to `new Kubb(userConfig, options)` and kept
|
|
426
|
+
* as the canonical public entry point.
|
|
427
|
+
*/
|
|
428
|
+
function createKubb(userConfig, options = {}) {
|
|
429
|
+
return new Kubb(userConfig, options);
|
|
1056
430
|
}
|
|
1057
431
|
//#endregion
|
|
1058
432
|
//#region src/createRenderer.ts
|
|
@@ -1066,6 +440,7 @@ function createKubb(userConfig, options = {}) {
|
|
|
1066
440
|
* return {
|
|
1067
441
|
* async render(element) { await runtime.render(element) },
|
|
1068
442
|
* get files() { return runtime.nodes },
|
|
443
|
+
* dispose() { runtime.unmount() },
|
|
1069
444
|
* unmount(error) { runtime.unmount(error) },
|
|
1070
445
|
* }
|
|
1071
446
|
* })
|