@kubb/core 5.0.0-beta.20 → 5.0.0-beta.21
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-BBRa5CH2.cjs} +745 -105
- package/dist/KubbDriver-BBRa5CH2.cjs.map +1 -0
- package/dist/{KubbDriver-Cxii_rBp.js → KubbDriver-Cq1isv2P.js} +723 -89
- package/dist/KubbDriver-Cq1isv2P.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 +2 -2
- 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 +356 -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
|
@@ -1,8 +1,152 @@
|
|
|
1
1
|
import "./chunk--u3MIqq1.js";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
2
3
|
import path, { extname, resolve } from "node:path";
|
|
3
|
-
import { createFile, createStreamInput, isOperationNode, isSchemaNode } from "@kubb/ast";
|
|
4
|
+
import { collectUsedSchemaNames, createFile, createStreamInput, extractStringsFromNodes, isOperationNode, isSchemaNode, transform } from "@kubb/ast";
|
|
4
5
|
import { deflateSync } from "fflate";
|
|
5
6
|
import { x } from "tinyexec";
|
|
7
|
+
//#region ../../internals/utils/src/errors.ts
|
|
8
|
+
/**
|
|
9
|
+
* Thrown when one or more errors occur during a Kubb build.
|
|
10
|
+
* Carries the full list of underlying errors on `errors`.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* throw new BuildError('Build failed', { errors: [err1, err2] })
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
var BuildError = class extends Error {
|
|
18
|
+
errors;
|
|
19
|
+
constructor(message, options) {
|
|
20
|
+
super(message, { cause: options.cause });
|
|
21
|
+
this.name = "BuildError";
|
|
22
|
+
this.errors = options.errors;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Coerces an unknown thrown value to an `Error` instance.
|
|
27
|
+
* Returns the value as-is when it is already an `Error`; otherwise wraps it with `String(value)`.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* try { ... } catch(err) {
|
|
32
|
+
* throw new BuildError('Build failed', { cause: toError(err), errors: [] })
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
function toError(value) {
|
|
37
|
+
return value instanceof Error ? value : new Error(String(value));
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region ../../internals/utils/src/asyncEventEmitter.ts
|
|
41
|
+
/**
|
|
42
|
+
* Typed `EventEmitter` that awaits all async listeners before resolving.
|
|
43
|
+
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
|
|
48
|
+
* emitter.on('build', async (name) => { console.log(name) })
|
|
49
|
+
* await emitter.emit('build', 'petstore') // all listeners awaited
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
var AsyncEventEmitter = class {
|
|
53
|
+
/**
|
|
54
|
+
* Maximum number of listeners per event before Node emits a memory-leak warning.
|
|
55
|
+
* @default 10
|
|
56
|
+
*/
|
|
57
|
+
constructor(maxListener = 10) {
|
|
58
|
+
this.#emitter.setMaxListeners(maxListener);
|
|
59
|
+
}
|
|
60
|
+
#emitter = new EventEmitter();
|
|
61
|
+
/**
|
|
62
|
+
* Emits `eventName` and awaits all registered listeners sequentially.
|
|
63
|
+
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* await emitter.emit('build', 'petstore')
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
emit(eventName, ...eventArgs) {
|
|
71
|
+
const listeners = this.#emitter.listeners(eventName);
|
|
72
|
+
if (listeners.length === 0) return;
|
|
73
|
+
return this.#emitAll(eventName, listeners, eventArgs);
|
|
74
|
+
}
|
|
75
|
+
async #emitAll(eventName, listeners, eventArgs) {
|
|
76
|
+
for (const listener of listeners) try {
|
|
77
|
+
await listener(...eventArgs);
|
|
78
|
+
} catch (err) {
|
|
79
|
+
let serializedArgs;
|
|
80
|
+
try {
|
|
81
|
+
serializedArgs = JSON.stringify(eventArgs);
|
|
82
|
+
} catch {
|
|
83
|
+
serializedArgs = String(eventArgs);
|
|
84
|
+
}
|
|
85
|
+
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: toError(err) });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Registers a persistent listener for `eventName`.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* emitter.on('build', async (name) => { console.log(name) })
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
on(eventName, handler) {
|
|
97
|
+
this.#emitter.on(eventName, handler);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Registers a one-shot listener that removes itself after the first invocation.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* emitter.onOnce('build', async (name) => { console.log(name) })
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
onOnce(eventName, handler) {
|
|
108
|
+
const wrapper = (...args) => {
|
|
109
|
+
this.off(eventName, wrapper);
|
|
110
|
+
return handler(...args);
|
|
111
|
+
};
|
|
112
|
+
this.on(eventName, wrapper);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Removes a previously registered listener.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* emitter.off('build', handler)
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
off(eventName, handler) {
|
|
123
|
+
this.#emitter.off(eventName, handler);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Returns the number of listeners registered for `eventName`.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* emitter.on('build', handler)
|
|
131
|
+
* emitter.listenerCount('build') // 1
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
listenerCount(eventName) {
|
|
135
|
+
return this.#emitter.listenerCount(eventName);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Removes all listeners from every event channel.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* emitter.removeAll()
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
removeAll() {
|
|
146
|
+
this.#emitter.removeAllListeners();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
//#endregion
|
|
6
150
|
//#region ../../internals/utils/src/casing.ts
|
|
7
151
|
/**
|
|
8
152
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -67,6 +211,39 @@ function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
|
67
211
|
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
68
212
|
}
|
|
69
213
|
//#endregion
|
|
214
|
+
//#region ../../internals/utils/src/time.ts
|
|
215
|
+
/**
|
|
216
|
+
* Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.
|
|
217
|
+
* Rounds to 2 decimal places for sub-millisecond precision without noise.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* const start = process.hrtime()
|
|
222
|
+
* doWork()
|
|
223
|
+
* getElapsedMs(start) // 42.35
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
function getElapsedMs(hrStart) {
|
|
227
|
+
const [seconds, nanoseconds] = process.hrtime(hrStart);
|
|
228
|
+
const ms = seconds * 1e3 + nanoseconds / 1e6;
|
|
229
|
+
return Math.round(ms * 100) / 100;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Converts a millisecond duration into a human-readable string (`ms`, `s`, or `m s`).
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```ts
|
|
236
|
+
* formatMs(250) // '250ms'
|
|
237
|
+
* formatMs(1500) // '1.50s'
|
|
238
|
+
* formatMs(90000) // '1m 30.0s'
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
function formatMs(ms) {
|
|
242
|
+
if (ms >= 6e4) return `${Math.floor(ms / 6e4)}m ${(ms % 6e4 / 1e3).toFixed(1)}s`;
|
|
243
|
+
if (ms >= 1e3) return `${(ms / 1e3).toFixed(2)}s`;
|
|
244
|
+
return `${Math.round(ms)}ms`;
|
|
245
|
+
}
|
|
246
|
+
//#endregion
|
|
70
247
|
//#region ../../internals/utils/src/promise.ts
|
|
71
248
|
function* chunks(arr, size) {
|
|
72
249
|
for (let i = 0; i < arr.length; i += size) yield arr.slice(i, i + size);
|
|
@@ -109,22 +286,6 @@ async function forBatches(source, process, options) {
|
|
|
109
286
|
if (flush) await flush();
|
|
110
287
|
}
|
|
111
288
|
}
|
|
112
|
-
/**
|
|
113
|
-
* Runs `work`, passing `flush` as its periodic-flush callback, then calls
|
|
114
|
-
* `flush` once more to drain any items that did not cross a flush boundary.
|
|
115
|
-
*
|
|
116
|
-
* @example
|
|
117
|
-
* ```ts
|
|
118
|
-
* await withDrain(
|
|
119
|
-
* (flush) => processItems(items, { flush }),
|
|
120
|
-
* () => writeRemainingFiles(),
|
|
121
|
-
* )
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
async function withDrain(work, flush) {
|
|
125
|
-
await work(flush);
|
|
126
|
-
await flush();
|
|
127
|
-
}
|
|
128
289
|
/** Returns `true` when `result` is a thenable `Promise`.
|
|
129
290
|
*
|
|
130
291
|
* @example
|
|
@@ -787,13 +948,13 @@ function buildDefaultBanner({ title, description, version, config }) {
|
|
|
787
948
|
* @example Disabled default banner
|
|
788
949
|
* ```ts
|
|
789
950
|
* defaultResolveBanner(undefined, { config: { output: { defaultBanner: false }, ...config } })
|
|
790
|
-
* // →
|
|
951
|
+
* // → null
|
|
791
952
|
* ```
|
|
792
953
|
*/
|
|
793
954
|
function defaultResolveBanner(meta, { output, config }) {
|
|
794
955
|
if (typeof output?.banner === "function") return output.banner(meta);
|
|
795
956
|
if (typeof output?.banner === "string") return output.banner;
|
|
796
|
-
if (config.output.defaultBanner === false) return;
|
|
957
|
+
if (config.output.defaultBanner === false) return null;
|
|
797
958
|
return buildDefaultBanner({
|
|
798
959
|
title: meta?.title,
|
|
799
960
|
version: meta?.version,
|
|
@@ -822,6 +983,7 @@ function defaultResolveBanner(meta, { output, config }) {
|
|
|
822
983
|
function defaultResolveFooter(meta, { output }) {
|
|
823
984
|
if (typeof output?.footer === "function") return output.footer(meta);
|
|
824
985
|
if (typeof output?.footer === "string") return output.footer;
|
|
986
|
+
return null;
|
|
825
987
|
}
|
|
826
988
|
/**
|
|
827
989
|
* Defines a resolver for a plugin, injecting built-in defaults for name casing,
|
|
@@ -932,111 +1094,241 @@ function mergeFile(a, b) {
|
|
|
932
1094
|
...a,
|
|
933
1095
|
banner: b.banner,
|
|
934
1096
|
footer: b.footer,
|
|
935
|
-
sources:
|
|
936
|
-
imports:
|
|
937
|
-
exports:
|
|
1097
|
+
sources: a.sources.length ? b.sources.length ? [...a.sources, ...b.sources] : a.sources : b.sources,
|
|
1098
|
+
imports: a.imports.length ? b.imports.length ? [...a.imports, ...b.imports] : a.imports : b.imports,
|
|
1099
|
+
exports: a.exports.length ? b.exports.length ? [...a.exports, ...b.exports] : a.exports : b.exports
|
|
938
1100
|
};
|
|
939
1101
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
return
|
|
1102
|
+
function isIndexPath(path) {
|
|
1103
|
+
return path.endsWith("/index.ts") || path === "index.ts";
|
|
1104
|
+
}
|
|
1105
|
+
function compareFiles(a, b) {
|
|
1106
|
+
const lenDiff = a.path.length - b.path.length;
|
|
1107
|
+
if (lenDiff !== 0) return lenDiff;
|
|
1108
|
+
const aIsIndex = isIndexPath(a.path);
|
|
1109
|
+
const bIsIndex = isIndexPath(b.path);
|
|
1110
|
+
if (aIsIndex && !bIsIndex) return 1;
|
|
1111
|
+
if (!aIsIndex && bIsIndex) return -1;
|
|
1112
|
+
return 0;
|
|
951
1113
|
}
|
|
952
1114
|
/**
|
|
953
|
-
* In-memory file store for generated files.
|
|
954
|
-
*
|
|
955
|
-
*
|
|
956
|
-
* The `files` getter returns all stored files sorted by path length (shortest first).
|
|
1115
|
+
* In-memory file store for generated files. Files sharing a `path` are merged
|
|
1116
|
+
* (sources/imports/exports concatenated). The `files` getter is sorted by
|
|
1117
|
+
* path length (barrel `index.ts` last within a bucket).
|
|
957
1118
|
*
|
|
958
1119
|
* @example
|
|
959
1120
|
* ```ts
|
|
960
|
-
* import { FileManager } from '@kubb/core'
|
|
961
|
-
*
|
|
962
1121
|
* const manager = new FileManager()
|
|
963
1122
|
* manager.upsert(myFile)
|
|
964
|
-
*
|
|
1123
|
+
* manager.files // sorted view
|
|
965
1124
|
* ```
|
|
966
1125
|
*/
|
|
967
1126
|
var FileManager = class {
|
|
968
1127
|
#cache = /* @__PURE__ */ new Map();
|
|
969
|
-
#
|
|
1128
|
+
#sorted = null;
|
|
1129
|
+
#onUpsert = null;
|
|
970
1130
|
/**
|
|
971
|
-
*
|
|
972
|
-
*
|
|
973
|
-
*
|
|
1131
|
+
* Registers a callback invoked with the resolved {@link FileNode} on every
|
|
1132
|
+
* `add` / `upsert`. Used by the build loop to track newly written files
|
|
1133
|
+
* without keeping its own scan-based diff. Single subscriber by design —
|
|
1134
|
+
* setting again replaces the previous callback. Pass `null` to detach.
|
|
974
1135
|
*/
|
|
1136
|
+
setOnUpsert(callback) {
|
|
1137
|
+
this.#onUpsert = callback;
|
|
1138
|
+
}
|
|
975
1139
|
add(...files) {
|
|
976
1140
|
return this.#store(files, false);
|
|
977
1141
|
}
|
|
978
|
-
/**
|
|
979
|
-
* Adds or merges one or more files.
|
|
980
|
-
* If a file with the same path already exists in the cache, its
|
|
981
|
-
* sources/imports/exports are merged into the incoming file.
|
|
982
|
-
*/
|
|
983
1142
|
upsert(...files) {
|
|
984
1143
|
return this.#store(files, true);
|
|
985
1144
|
}
|
|
986
1145
|
#store(files, mergeExisting) {
|
|
987
|
-
const
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
|
|
1146
|
+
const batch = files.length > 1 ? this.#dedupe(files) : files;
|
|
1147
|
+
const resolved = [];
|
|
1148
|
+
for (const file of batch) {
|
|
1149
|
+
const existing = this.#cache.get(file.path);
|
|
1150
|
+
const merged = existing && mergeExisting ? createFile(mergeFile(existing, file)) : file;
|
|
1151
|
+
this.#cache.set(merged.path, merged);
|
|
1152
|
+
resolved.push(merged);
|
|
1153
|
+
this.#onUpsert?.(merged);
|
|
993
1154
|
}
|
|
994
|
-
this.#
|
|
995
|
-
return
|
|
1155
|
+
if (resolved.length > 0) this.#sorted = null;
|
|
1156
|
+
return resolved;
|
|
1157
|
+
}
|
|
1158
|
+
#dedupe(files) {
|
|
1159
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1160
|
+
for (const file of files) {
|
|
1161
|
+
const prev = seen.get(file.path);
|
|
1162
|
+
seen.set(file.path, prev ? mergeFile(prev, file) : file);
|
|
1163
|
+
}
|
|
1164
|
+
return [...seen.values()];
|
|
996
1165
|
}
|
|
997
1166
|
getByPath(path) {
|
|
998
1167
|
return this.#cache.get(path) ?? null;
|
|
999
1168
|
}
|
|
1000
1169
|
deleteByPath(path) {
|
|
1001
|
-
this.#cache.delete(path);
|
|
1002
|
-
this.#
|
|
1170
|
+
if (!this.#cache.delete(path)) return;
|
|
1171
|
+
this.#sorted = null;
|
|
1003
1172
|
}
|
|
1004
1173
|
clear() {
|
|
1005
1174
|
this.#cache.clear();
|
|
1006
|
-
this.#
|
|
1175
|
+
this.#sorted = null;
|
|
1007
1176
|
}
|
|
1008
1177
|
/**
|
|
1009
|
-
* Releases all stored files. Called by the core after `kubb:build:end
|
|
1010
|
-
* free the per-plugin FileNode caches for the rest of the process lifetime.
|
|
1178
|
+
* Releases all stored files. Called by the core after `kubb:build:end`.
|
|
1011
1179
|
*/
|
|
1012
1180
|
dispose() {
|
|
1013
1181
|
this.clear();
|
|
1182
|
+
this.#onUpsert = null;
|
|
1014
1183
|
}
|
|
1015
1184
|
[Symbol.dispose]() {
|
|
1016
1185
|
this.dispose();
|
|
1017
1186
|
}
|
|
1018
1187
|
/**
|
|
1019
|
-
* All stored files
|
|
1188
|
+
* All stored files in stable sort order (shortest path first, barrel files
|
|
1189
|
+
* last within a length bucket). Returns a cached view — do not mutate.
|
|
1020
1190
|
*/
|
|
1021
1191
|
get files() {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1192
|
+
return this.#sorted ??= [...this.#cache.values()].sort(compareFiles);
|
|
1193
|
+
}
|
|
1194
|
+
};
|
|
1195
|
+
//#endregion
|
|
1196
|
+
//#region src/FileProcessor.ts
|
|
1197
|
+
function joinSources(file) {
|
|
1198
|
+
const sources = file.sources;
|
|
1199
|
+
if (sources.length === 0) return "";
|
|
1200
|
+
const parts = [];
|
|
1201
|
+
for (const source of sources) {
|
|
1202
|
+
const s = extractStringsFromNodes(source.nodes);
|
|
1203
|
+
if (s) parts.push(s);
|
|
1204
|
+
}
|
|
1205
|
+
return parts.join("\n\n");
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Converts a single file to a string using the registered parsers.
|
|
1209
|
+
* Falls back to joining source values when no matching parser is found.
|
|
1210
|
+
*
|
|
1211
|
+
* @internal
|
|
1212
|
+
*/
|
|
1213
|
+
var FileProcessor = class {
|
|
1214
|
+
events = new AsyncEventEmitter();
|
|
1215
|
+
parse(file, { parsers, extension } = {}) {
|
|
1216
|
+
const parseExtName = extension?.[file.extname] || void 0;
|
|
1217
|
+
if (!parsers || !file.extname) return joinSources(file);
|
|
1218
|
+
const parser = parsers.get(file.extname);
|
|
1219
|
+
if (!parser) return joinSources(file);
|
|
1220
|
+
return parser.parse(file, { extname: parseExtName });
|
|
1221
|
+
}
|
|
1222
|
+
*stream(files, options = {}) {
|
|
1223
|
+
const total = files.length;
|
|
1224
|
+
if (total === 0) return;
|
|
1225
|
+
let processed = 0;
|
|
1226
|
+
for (const file of files) {
|
|
1227
|
+
const source = this.parse(file, options);
|
|
1228
|
+
processed++;
|
|
1229
|
+
yield {
|
|
1230
|
+
file,
|
|
1231
|
+
source,
|
|
1232
|
+
processed,
|
|
1233
|
+
total,
|
|
1234
|
+
percentage: processed / total * 100
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
async run(files, options = {}) {
|
|
1239
|
+
await this.events.emit("start", files);
|
|
1240
|
+
for (const { file, source, processed, total, percentage } of this.stream(files, options)) await this.events.emit("update", {
|
|
1241
|
+
file,
|
|
1242
|
+
source,
|
|
1243
|
+
processed,
|
|
1244
|
+
percentage,
|
|
1245
|
+
total
|
|
1031
1246
|
});
|
|
1032
|
-
|
|
1247
|
+
await this.events.emit("end", files);
|
|
1248
|
+
return files;
|
|
1249
|
+
}
|
|
1250
|
+
/**
|
|
1251
|
+
* Clears all registered event listeners.
|
|
1252
|
+
*/
|
|
1253
|
+
dispose() {
|
|
1254
|
+
this.events.removeAll();
|
|
1255
|
+
}
|
|
1256
|
+
[Symbol.dispose]() {
|
|
1257
|
+
this.dispose();
|
|
1033
1258
|
}
|
|
1034
1259
|
};
|
|
1035
1260
|
//#endregion
|
|
1261
|
+
//#region \0@oxc-project+runtime@0.129.0/helpers/usingCtx.js
|
|
1262
|
+
function _usingCtx() {
|
|
1263
|
+
var r = "function" == typeof SuppressedError ? SuppressedError : function(r, e) {
|
|
1264
|
+
var n = Error();
|
|
1265
|
+
return n.name = "SuppressedError", n.error = r, n.suppressed = e, n;
|
|
1266
|
+
};
|
|
1267
|
+
var e = {};
|
|
1268
|
+
var n = [];
|
|
1269
|
+
function using(r, e) {
|
|
1270
|
+
if (null != e) {
|
|
1271
|
+
if (Object(e) !== e) throw new TypeError("using declarations can only be used with objects, functions, null, or undefined.");
|
|
1272
|
+
if (r) var o = e[Symbol.asyncDispose || Symbol["for"]("Symbol.asyncDispose")];
|
|
1273
|
+
if (void 0 === o && (o = e[Symbol.dispose || Symbol["for"]("Symbol.dispose")], r)) var t = o;
|
|
1274
|
+
if ("function" != typeof o) throw new TypeError("Object is not disposable.");
|
|
1275
|
+
t && (o = function o() {
|
|
1276
|
+
try {
|
|
1277
|
+
t.call(e);
|
|
1278
|
+
} catch (r) {
|
|
1279
|
+
return Promise.reject(r);
|
|
1280
|
+
}
|
|
1281
|
+
}), n.push({
|
|
1282
|
+
v: e,
|
|
1283
|
+
d: o,
|
|
1284
|
+
a: r
|
|
1285
|
+
});
|
|
1286
|
+
} else r && n.push({
|
|
1287
|
+
d: e,
|
|
1288
|
+
a: r
|
|
1289
|
+
});
|
|
1290
|
+
return e;
|
|
1291
|
+
}
|
|
1292
|
+
return {
|
|
1293
|
+
e,
|
|
1294
|
+
u: using.bind(null, !1),
|
|
1295
|
+
a: using.bind(null, !0),
|
|
1296
|
+
d: function d() {
|
|
1297
|
+
var o;
|
|
1298
|
+
var t = this.e;
|
|
1299
|
+
var s = 0;
|
|
1300
|
+
function next() {
|
|
1301
|
+
for (; o = n.pop();) try {
|
|
1302
|
+
if (!o.a && 1 === s) return s = 0, n.push(o), Promise.resolve().then(next);
|
|
1303
|
+
if (o.d) {
|
|
1304
|
+
var r = o.d.call(o.v);
|
|
1305
|
+
if (o.a) return s |= 2, Promise.resolve(r).then(next, err);
|
|
1306
|
+
} else s |= 1;
|
|
1307
|
+
} catch (r) {
|
|
1308
|
+
return err(r);
|
|
1309
|
+
}
|
|
1310
|
+
if (1 === s) return t !== e ? Promise.reject(t) : Promise.resolve();
|
|
1311
|
+
if (t !== e) throw t;
|
|
1312
|
+
}
|
|
1313
|
+
function err(n) {
|
|
1314
|
+
return t = t !== e ? new r(n, t) : n, next();
|
|
1315
|
+
}
|
|
1316
|
+
return next();
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
}
|
|
1320
|
+
//#endregion
|
|
1036
1321
|
//#region src/KubbDriver.ts
|
|
1037
1322
|
function enforceOrder(enforce) {
|
|
1038
1323
|
return enforce === "pre" ? -1 : enforce === "post" ? 1 : 0;
|
|
1039
1324
|
}
|
|
1325
|
+
const OPERATION_FILTER_TYPES = new Set([
|
|
1326
|
+
"tag",
|
|
1327
|
+
"operationId",
|
|
1328
|
+
"path",
|
|
1329
|
+
"method",
|
|
1330
|
+
"contentType"
|
|
1331
|
+
]);
|
|
1040
1332
|
var KubbDriver = class KubbDriver {
|
|
1041
1333
|
config;
|
|
1042
1334
|
options;
|
|
@@ -1056,8 +1348,8 @@ var KubbDriver = class KubbDriver {
|
|
|
1056
1348
|
* The streaming `InputStreamNode` produced by the adapter.
|
|
1057
1349
|
* Always set after adapter setup — parse-only adapters are wrapped automatically.
|
|
1058
1350
|
*/
|
|
1059
|
-
inputNode =
|
|
1060
|
-
adapter =
|
|
1351
|
+
inputNode = null;
|
|
1352
|
+
adapter = null;
|
|
1061
1353
|
/**
|
|
1062
1354
|
* Studio session state, kept together so `dispose()` can reset it atomically.
|
|
1063
1355
|
*
|
|
@@ -1068,9 +1360,9 @@ var KubbDriver = class KubbDriver {
|
|
|
1068
1360
|
* per studio session, even when `openInStudio()` is called multiple times.
|
|
1069
1361
|
*/
|
|
1070
1362
|
#studio = {
|
|
1071
|
-
source:
|
|
1363
|
+
source: null,
|
|
1072
1364
|
isOpen: false,
|
|
1073
|
-
inputNode:
|
|
1365
|
+
inputNode: null
|
|
1074
1366
|
};
|
|
1075
1367
|
#middlewareListeners = [];
|
|
1076
1368
|
/**
|
|
@@ -1079,6 +1371,7 @@ var KubbDriver = class KubbDriver {
|
|
|
1079
1371
|
* add files; this property gives direct read/write access when needed.
|
|
1080
1372
|
*/
|
|
1081
1373
|
fileManager = new FileManager();
|
|
1374
|
+
#fileProcessor = new FileProcessor();
|
|
1082
1375
|
plugins = /* @__PURE__ */ new Map();
|
|
1083
1376
|
/**
|
|
1084
1377
|
* Tracks which plugins have generators registered via `addGenerator()` (event-based path).
|
|
@@ -1091,7 +1384,7 @@ var KubbDriver = class KubbDriver {
|
|
|
1091
1384
|
constructor(config, options) {
|
|
1092
1385
|
this.config = config;
|
|
1093
1386
|
this.options = options;
|
|
1094
|
-
this.adapter = config.adapter;
|
|
1387
|
+
this.adapter = config.adapter ?? null;
|
|
1095
1388
|
}
|
|
1096
1389
|
async setup() {
|
|
1097
1390
|
const normalized = this.config.plugins.map((rawPlugin) => this.#normalizePlugin(rawPlugin));
|
|
@@ -1302,6 +1595,334 @@ var KubbDriver = class KubbDriver {
|
|
|
1302
1595
|
return this.#eventGeneratorPlugins.has(pluginName);
|
|
1303
1596
|
}
|
|
1304
1597
|
/**
|
|
1598
|
+
* Runs the full plugin pipeline. Returns timings/failures collected so far even
|
|
1599
|
+
* when an outer hook throws — the orchestrator preserves partial state by capturing
|
|
1600
|
+
* the error into `error` instead of propagating.
|
|
1601
|
+
*/
|
|
1602
|
+
async run({ storage }) {
|
|
1603
|
+
const hooks = this.hooks;
|
|
1604
|
+
const config = this.config;
|
|
1605
|
+
const failedPlugins = /* @__PURE__ */ new Set();
|
|
1606
|
+
const pluginTimings = /* @__PURE__ */ new Map();
|
|
1607
|
+
const parsersMap = /* @__PURE__ */ new Map();
|
|
1608
|
+
for (const parser of config.parsers) if (parser.extNames) for (const ext of parser.extNames) parsersMap.set(ext, parser);
|
|
1609
|
+
const pendingFiles = /* @__PURE__ */ new Map();
|
|
1610
|
+
this.fileManager.setOnUpsert((file) => {
|
|
1611
|
+
pendingFiles.set(file.path, file);
|
|
1612
|
+
});
|
|
1613
|
+
try {
|
|
1614
|
+
const flushPending = async () => {
|
|
1615
|
+
if (pendingFiles.size === 0) return;
|
|
1616
|
+
const files = [...pendingFiles.values()];
|
|
1617
|
+
pendingFiles.clear();
|
|
1618
|
+
await hooks.emit("kubb:debug", {
|
|
1619
|
+
date: /* @__PURE__ */ new Date(),
|
|
1620
|
+
logs: [`Writing ${files.length} files...`]
|
|
1621
|
+
});
|
|
1622
|
+
await hooks.emit("kubb:files:processing:start", { files });
|
|
1623
|
+
const items = [...this.#fileProcessor.stream(files, {
|
|
1624
|
+
parsers: parsersMap,
|
|
1625
|
+
extension: config.output.extension
|
|
1626
|
+
})];
|
|
1627
|
+
await hooks.emit("kubb:files:processing:update", { files: items.map(({ file, source, processed, total, percentage }) => ({
|
|
1628
|
+
file,
|
|
1629
|
+
source,
|
|
1630
|
+
processed,
|
|
1631
|
+
total,
|
|
1632
|
+
percentage,
|
|
1633
|
+
config
|
|
1634
|
+
})) });
|
|
1635
|
+
const queue = [];
|
|
1636
|
+
for (const { file, source } of items) if (source) {
|
|
1637
|
+
queue.push(storage.setItem(file.path, source));
|
|
1638
|
+
if (queue.length >= 50) await Promise.all(queue.splice(0));
|
|
1639
|
+
}
|
|
1640
|
+
await Promise.all(queue);
|
|
1641
|
+
await hooks.emit("kubb:files:processing:end", { files });
|
|
1642
|
+
await hooks.emit("kubb:debug", {
|
|
1643
|
+
date: /* @__PURE__ */ new Date(),
|
|
1644
|
+
logs: [`✓ File write process completed for ${files.length} files`]
|
|
1645
|
+
});
|
|
1646
|
+
};
|
|
1647
|
+
await this.emitSetupHooks();
|
|
1648
|
+
if (this.adapter && this.inputNode) await hooks.emit("kubb:build:start", Object.assign({
|
|
1649
|
+
config,
|
|
1650
|
+
adapter: this.adapter,
|
|
1651
|
+
meta: this.inputNode.meta,
|
|
1652
|
+
getPlugin: this.getPlugin.bind(this)
|
|
1653
|
+
}, this.#filesPayload()));
|
|
1654
|
+
const generatorPlugins = [];
|
|
1655
|
+
for (const plugin of this.plugins.values()) {
|
|
1656
|
+
const context = this.getContext(plugin);
|
|
1657
|
+
const hrStart = process.hrtime();
|
|
1658
|
+
try {
|
|
1659
|
+
await hooks.emit("kubb:plugin:start", { plugin });
|
|
1660
|
+
await hooks.emit("kubb:debug", {
|
|
1661
|
+
date: /* @__PURE__ */ new Date(),
|
|
1662
|
+
logs: ["Starting plugin...", ` • Plugin Name: ${plugin.name}`]
|
|
1663
|
+
});
|
|
1664
|
+
} catch (caughtError) {
|
|
1665
|
+
const error = caughtError;
|
|
1666
|
+
const duration = getElapsedMs(hrStart);
|
|
1667
|
+
pluginTimings.set(plugin.name, duration);
|
|
1668
|
+
await this.#emitPluginEnd({
|
|
1669
|
+
plugin,
|
|
1670
|
+
duration,
|
|
1671
|
+
success: false,
|
|
1672
|
+
error
|
|
1673
|
+
});
|
|
1674
|
+
failedPlugins.add({
|
|
1675
|
+
plugin,
|
|
1676
|
+
error
|
|
1677
|
+
});
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
if (plugin.generators?.length || this.hasEventGenerators(plugin.name)) {
|
|
1681
|
+
generatorPlugins.push({
|
|
1682
|
+
plugin,
|
|
1683
|
+
context,
|
|
1684
|
+
hrStart
|
|
1685
|
+
});
|
|
1686
|
+
continue;
|
|
1687
|
+
}
|
|
1688
|
+
const duration = getElapsedMs(hrStart);
|
|
1689
|
+
pluginTimings.set(plugin.name, duration);
|
|
1690
|
+
await this.#emitPluginEnd({
|
|
1691
|
+
plugin,
|
|
1692
|
+
duration,
|
|
1693
|
+
success: true
|
|
1694
|
+
});
|
|
1695
|
+
await hooks.emit("kubb:debug", {
|
|
1696
|
+
date: /* @__PURE__ */ new Date(),
|
|
1697
|
+
logs: [`✓ Plugin started successfully (${formatMs(duration)})`]
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
if (generatorPlugins.length > 0) if (this.inputNode) {
|
|
1701
|
+
const { timings, failed } = await this.#runGenerators(generatorPlugins, flushPending);
|
|
1702
|
+
await flushPending();
|
|
1703
|
+
for (const [name, duration] of timings) pluginTimings.set(name, duration);
|
|
1704
|
+
for (const entry of failed) failedPlugins.add(entry);
|
|
1705
|
+
} else for (const { plugin, hrStart } of generatorPlugins) {
|
|
1706
|
+
const duration = getElapsedMs(hrStart);
|
|
1707
|
+
pluginTimings.set(plugin.name, duration);
|
|
1708
|
+
await this.#emitPluginEnd({
|
|
1709
|
+
plugin,
|
|
1710
|
+
duration,
|
|
1711
|
+
success: true
|
|
1712
|
+
});
|
|
1713
|
+
}
|
|
1714
|
+
await hooks.emit("kubb:plugins:end", Object.assign({ config }, this.#filesPayload()));
|
|
1715
|
+
await flushPending();
|
|
1716
|
+
const files = this.fileManager.files;
|
|
1717
|
+
await hooks.emit("kubb:build:end", {
|
|
1718
|
+
files,
|
|
1719
|
+
config,
|
|
1720
|
+
outputDir: resolve(config.root, config.output.path)
|
|
1721
|
+
});
|
|
1722
|
+
return {
|
|
1723
|
+
failedPlugins,
|
|
1724
|
+
pluginTimings
|
|
1725
|
+
};
|
|
1726
|
+
} catch (caughtError) {
|
|
1727
|
+
return {
|
|
1728
|
+
failedPlugins,
|
|
1729
|
+
pluginTimings,
|
|
1730
|
+
error: caughtError
|
|
1731
|
+
};
|
|
1732
|
+
} finally {
|
|
1733
|
+
this.fileManager.setOnUpsert(null);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
#filesPayload() {
|
|
1737
|
+
const driver = this;
|
|
1738
|
+
return {
|
|
1739
|
+
get files() {
|
|
1740
|
+
return driver.fileManager.files;
|
|
1741
|
+
},
|
|
1742
|
+
upsertFile: (...files) => driver.fileManager.upsert(...files)
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
#emitPluginEnd({ plugin, duration, success, error }) {
|
|
1746
|
+
return this.hooks.emit("kubb:plugin:end", Object.assign({
|
|
1747
|
+
plugin,
|
|
1748
|
+
duration,
|
|
1749
|
+
success,
|
|
1750
|
+
...error ? { error } : {},
|
|
1751
|
+
config: this.config
|
|
1752
|
+
}, this.#filesPayload()));
|
|
1753
|
+
}
|
|
1754
|
+
async #runGenerators(entries, flushPending) {
|
|
1755
|
+
const timings = /* @__PURE__ */ new Map();
|
|
1756
|
+
const failed = /* @__PURE__ */ new Set();
|
|
1757
|
+
const driver = this;
|
|
1758
|
+
const { schemas, operations } = this.inputNode;
|
|
1759
|
+
const states = entries.map(({ plugin, context, hrStart }) => {
|
|
1760
|
+
const { exclude, include, override } = plugin.options;
|
|
1761
|
+
const hasExclude = Array.isArray(exclude) && exclude.length > 0;
|
|
1762
|
+
const hasInclude = Array.isArray(include) && include.length > 0;
|
|
1763
|
+
const hasOverride = Array.isArray(override) && override.length > 0;
|
|
1764
|
+
return {
|
|
1765
|
+
plugin,
|
|
1766
|
+
generatorContext: {
|
|
1767
|
+
...context,
|
|
1768
|
+
resolver: this.getResolver(plugin.name)
|
|
1769
|
+
},
|
|
1770
|
+
generators: plugin.generators ?? [],
|
|
1771
|
+
hrStart,
|
|
1772
|
+
failed: false,
|
|
1773
|
+
error: null,
|
|
1774
|
+
optionsAreStatic: !hasExclude && !hasInclude && !hasOverride,
|
|
1775
|
+
allowedSchemaNames: null
|
|
1776
|
+
};
|
|
1777
|
+
});
|
|
1778
|
+
const emitsSchemaHook = this.hooks.listenerCount("kubb:generate:schema") > 0;
|
|
1779
|
+
const emitsOperationHook = this.hooks.listenerCount("kubb:generate:operation") > 0;
|
|
1780
|
+
const pruningStates = states.filter(({ plugin }) => {
|
|
1781
|
+
const { include } = plugin.options;
|
|
1782
|
+
return (include?.some(({ type }) => OPERATION_FILTER_TYPES.has(type)) ?? false) && !(include?.some(({ type }) => type === "schemaName") ?? false);
|
|
1783
|
+
});
|
|
1784
|
+
if (pruningStates.length > 0) {
|
|
1785
|
+
const allSchemas = [];
|
|
1786
|
+
for await (const schema of schemas) allSchemas.push(schema);
|
|
1787
|
+
const includedOpsByState = new Map(pruningStates.map((s) => [s, []]));
|
|
1788
|
+
for await (const operation of operations) for (const state of pruningStates) {
|
|
1789
|
+
const { exclude, include, override } = state.plugin.options;
|
|
1790
|
+
if (state.generatorContext.resolver.resolveOptions(operation, {
|
|
1791
|
+
options: state.plugin.options,
|
|
1792
|
+
exclude,
|
|
1793
|
+
include,
|
|
1794
|
+
override
|
|
1795
|
+
}) !== null) includedOpsByState.get(state)?.push(operation);
|
|
1796
|
+
}
|
|
1797
|
+
for (const state of pruningStates) {
|
|
1798
|
+
state.allowedSchemaNames = collectUsedSchemaNames(includedOpsByState.get(state) ?? [], allSchemas);
|
|
1799
|
+
includedOpsByState.delete(state);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
const resolveRendererFor = (gen, state) => gen.renderer === null ? void 0 : gen.renderer ?? state.plugin.renderer ?? state.generatorContext.config.renderer;
|
|
1803
|
+
const dispatchSchema = async (state, node) => {
|
|
1804
|
+
if (state.failed) return;
|
|
1805
|
+
try {
|
|
1806
|
+
const { plugin, generatorContext, generators } = state;
|
|
1807
|
+
const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
|
|
1808
|
+
if (state.allowedSchemaNames !== null && transformedNode.name && !state.allowedSchemaNames.has(transformedNode.name)) return;
|
|
1809
|
+
const { exclude, include, override } = plugin.options;
|
|
1810
|
+
const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
|
|
1811
|
+
options: plugin.options,
|
|
1812
|
+
exclude,
|
|
1813
|
+
include,
|
|
1814
|
+
override
|
|
1815
|
+
});
|
|
1816
|
+
if (options === null) return;
|
|
1817
|
+
const ctx = {
|
|
1818
|
+
...generatorContext,
|
|
1819
|
+
options
|
|
1820
|
+
};
|
|
1821
|
+
for (const gen of generators) {
|
|
1822
|
+
if (!gen.schema) continue;
|
|
1823
|
+
const raw = gen.schema(transformedNode, ctx);
|
|
1824
|
+
const applied = applyHookResult({
|
|
1825
|
+
result: isPromise(raw) ? await raw : raw,
|
|
1826
|
+
driver,
|
|
1827
|
+
rendererFactory: resolveRendererFor(gen, state)
|
|
1828
|
+
});
|
|
1829
|
+
if (isPromise(applied)) await applied;
|
|
1830
|
+
}
|
|
1831
|
+
if (emitsSchemaHook) await this.hooks.emit("kubb:generate:schema", transformedNode, ctx);
|
|
1832
|
+
} catch (caughtError) {
|
|
1833
|
+
state.failed = true;
|
|
1834
|
+
state.error = caughtError;
|
|
1835
|
+
}
|
|
1836
|
+
};
|
|
1837
|
+
const dispatchOperation = async (state, node) => {
|
|
1838
|
+
if (state.failed) return;
|
|
1839
|
+
try {
|
|
1840
|
+
const { plugin, generatorContext, generators } = state;
|
|
1841
|
+
const transformedNode = plugin.transformer ? transform(node, plugin.transformer) : node;
|
|
1842
|
+
const { exclude, include, override } = plugin.options;
|
|
1843
|
+
const options = state.optionsAreStatic ? plugin.options : generatorContext.resolver.resolveOptions(transformedNode, {
|
|
1844
|
+
options: plugin.options,
|
|
1845
|
+
exclude,
|
|
1846
|
+
include,
|
|
1847
|
+
override
|
|
1848
|
+
});
|
|
1849
|
+
if (options === null) return;
|
|
1850
|
+
const ctx = {
|
|
1851
|
+
...generatorContext,
|
|
1852
|
+
options
|
|
1853
|
+
};
|
|
1854
|
+
for (const gen of generators) {
|
|
1855
|
+
if (!gen.operation) continue;
|
|
1856
|
+
const raw = gen.operation(transformedNode, ctx);
|
|
1857
|
+
const applied = applyHookResult({
|
|
1858
|
+
result: isPromise(raw) ? await raw : raw,
|
|
1859
|
+
driver,
|
|
1860
|
+
rendererFactory: resolveRendererFor(gen, state)
|
|
1861
|
+
});
|
|
1862
|
+
if (isPromise(applied)) await applied;
|
|
1863
|
+
}
|
|
1864
|
+
if (emitsOperationHook) await this.hooks.emit("kubb:generate:operation", transformedNode, ctx);
|
|
1865
|
+
} catch (caughtError) {
|
|
1866
|
+
state.failed = true;
|
|
1867
|
+
state.error = caughtError;
|
|
1868
|
+
}
|
|
1869
|
+
};
|
|
1870
|
+
const needsCollectedOperations = this.hooks.listenerCount("kubb:generate:operations") > 0 || states.some((s) => s.generators.some((g) => !!g.operations));
|
|
1871
|
+
const collectedOperations = needsCollectedOperations ? [] : void 0;
|
|
1872
|
+
await forBatches(schemas, (nodes) => Promise.all(nodes.flatMap((n) => states.map((state) => dispatchSchema(state, n)))), {
|
|
1873
|
+
concurrency: 8,
|
|
1874
|
+
flush: flushPending
|
|
1875
|
+
});
|
|
1876
|
+
await forBatches(operations, (nodes) => {
|
|
1877
|
+
if (needsCollectedOperations) collectedOperations.push(...nodes);
|
|
1878
|
+
return Promise.all(nodes.flatMap((n) => states.map((state) => dispatchOperation(state, n))));
|
|
1879
|
+
}, {
|
|
1880
|
+
concurrency: 8,
|
|
1881
|
+
flush: flushPending
|
|
1882
|
+
});
|
|
1883
|
+
for (const state of states) {
|
|
1884
|
+
if (!state.failed && needsCollectedOperations) try {
|
|
1885
|
+
const { plugin, generatorContext, generators } = state;
|
|
1886
|
+
const ctx = {
|
|
1887
|
+
...generatorContext,
|
|
1888
|
+
options: plugin.options
|
|
1889
|
+
};
|
|
1890
|
+
for (const gen of generators) {
|
|
1891
|
+
if (!gen.operations) continue;
|
|
1892
|
+
await applyHookResult({
|
|
1893
|
+
result: await gen.operations(collectedOperations, ctx),
|
|
1894
|
+
driver,
|
|
1895
|
+
rendererFactory: resolveRendererFor(gen, state)
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
await this.hooks.emit("kubb:generate:operations", collectedOperations, ctx);
|
|
1899
|
+
} catch (caughtError) {
|
|
1900
|
+
state.failed = true;
|
|
1901
|
+
state.error = caughtError;
|
|
1902
|
+
}
|
|
1903
|
+
const duration = getElapsedMs(state.hrStart);
|
|
1904
|
+
timings.set(state.plugin.name, duration);
|
|
1905
|
+
await this.#emitPluginEnd({
|
|
1906
|
+
plugin: state.plugin,
|
|
1907
|
+
duration,
|
|
1908
|
+
success: !state.failed,
|
|
1909
|
+
error: state.failed && state.error ? state.error : void 0
|
|
1910
|
+
});
|
|
1911
|
+
if (state.failed && state.error) failed.add({
|
|
1912
|
+
plugin: state.plugin,
|
|
1913
|
+
error: state.error
|
|
1914
|
+
});
|
|
1915
|
+
await this.hooks.emit("kubb:debug", {
|
|
1916
|
+
date: /* @__PURE__ */ new Date(),
|
|
1917
|
+
logs: [state.failed ? "✗ Plugin start failed" : `✓ Plugin started successfully (${formatMs(duration)})`]
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
return {
|
|
1921
|
+
timings,
|
|
1922
|
+
failed
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
/**
|
|
1305
1926
|
* Unregisters all plugin lifecycle listeners from the shared event emitter.
|
|
1306
1927
|
* Called at the end of a build to prevent listener leaks across repeated builds.
|
|
1307
1928
|
*
|
|
@@ -1314,11 +1935,12 @@ var KubbDriver = class KubbDriver {
|
|
|
1314
1935
|
this.#resolvers.clear();
|
|
1315
1936
|
this.#defaultResolvers.clear();
|
|
1316
1937
|
this.fileManager.dispose();
|
|
1317
|
-
this.
|
|
1938
|
+
this.#fileProcessor.dispose();
|
|
1939
|
+
this.inputNode = null;
|
|
1318
1940
|
this.#studio = {
|
|
1319
|
-
source:
|
|
1941
|
+
source: null,
|
|
1320
1942
|
isOpen: false,
|
|
1321
|
-
inputNode:
|
|
1943
|
+
inputNode: null
|
|
1322
1944
|
};
|
|
1323
1945
|
for (const [event, handler] of this.#middlewareListeners) this.hooks.off(event, handler);
|
|
1324
1946
|
}
|
|
@@ -1438,10 +2060,15 @@ function applyHookResult({ result, driver, rendererFactory }) {
|
|
|
1438
2060
|
}
|
|
1439
2061
|
if (!rendererFactory) return;
|
|
1440
2062
|
const renderer = rendererFactory();
|
|
1441
|
-
if (renderer.stream) {
|
|
1442
|
-
|
|
1443
|
-
|
|
2063
|
+
if (renderer.stream) try {
|
|
2064
|
+
var _usingCtx$1 = _usingCtx();
|
|
2065
|
+
const r = _usingCtx$1.u(renderer);
|
|
2066
|
+
for (const file of r.stream(result)) driver.fileManager.upsert(file);
|
|
1444
2067
|
return;
|
|
2068
|
+
} catch (_) {
|
|
2069
|
+
_usingCtx$1.e = _;
|
|
2070
|
+
} finally {
|
|
2071
|
+
_usingCtx$1.d();
|
|
1445
2072
|
}
|
|
1446
2073
|
return applyAsyncRender({
|
|
1447
2074
|
renderer,
|
|
@@ -1450,9 +2077,16 @@ function applyHookResult({ result, driver, rendererFactory }) {
|
|
|
1450
2077
|
});
|
|
1451
2078
|
}
|
|
1452
2079
|
async function applyAsyncRender({ renderer, result, driver }) {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
2080
|
+
try {
|
|
2081
|
+
var _usingCtx3 = _usingCtx();
|
|
2082
|
+
const r = _usingCtx3.u(renderer);
|
|
2083
|
+
await r.render(result);
|
|
2084
|
+
driver.fileManager.upsert(...r.files);
|
|
2085
|
+
} catch (_) {
|
|
2086
|
+
_usingCtx3.e = _;
|
|
2087
|
+
} finally {
|
|
2088
|
+
_usingCtx3.d();
|
|
2089
|
+
}
|
|
1456
2090
|
}
|
|
1457
2091
|
function inputToAdapterSource(config) {
|
|
1458
2092
|
const input = config.input;
|
|
@@ -1471,6 +2105,6 @@ function inputToAdapterSource(config) {
|
|
|
1471
2105
|
};
|
|
1472
2106
|
}
|
|
1473
2107
|
//#endregion
|
|
1474
|
-
export {
|
|
2108
|
+
export { FileManager as a, DEFAULT_BANNER as c, logLevel as d, URLPath as f, FileProcessor as i, DEFAULT_EXTENSION as l, BuildError as m, applyHookResult as n, defineResolver as o, AsyncEventEmitter as p, _usingCtx as r, definePlugin as s, KubbDriver as t, DEFAULT_STUDIO_URL as u };
|
|
1475
2109
|
|
|
1476
|
-
//# sourceMappingURL=KubbDriver-
|
|
2110
|
+
//# sourceMappingURL=KubbDriver-Cq1isv2P.js.map
|