@kubb/cli 5.0.0-beta.82 → 5.0.0-beta.85
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/{Telemetry-ugO-B77y.js → Telemetry-Cuzoes9Y.js} +6 -2
- package/dist/Telemetry-Cuzoes9Y.js.map +1 -0
- package/dist/{Telemetry-jtbchpQE.cjs → Telemetry-CwQYBgsg.cjs} +11 -1
- package/dist/Telemetry-CwQYBgsg.cjs.map +1 -0
- package/dist/{generate-D5AWn6lH.js → generate-C1bIl1nH.js} +34 -24
- package/dist/generate-C1bIl1nH.js.map +1 -0
- package/dist/{generate-DfzX98Lx.cjs → generate-Cgmty90l.cjs} +34 -23
- package/dist/generate-Cgmty90l.cjs.map +1 -0
- package/dist/index.cjs +28 -192
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +29 -193
- package/dist/index.js.map +1 -1
- package/dist/{init-hKT7f8_b.cjs → init-DqgB69HY.cjs} +9 -10
- package/dist/init-DqgB69HY.cjs.map +1 -0
- package/dist/{init-GU5uRenE.js → init-EnhDxlBB.js} +10 -10
- package/dist/init-EnhDxlBB.js.map +1 -0
- package/dist/{mcp-B3TSdKiQ.js → mcp-5DDTiwIA.js} +6 -6
- package/dist/mcp-5DDTiwIA.js.map +1 -0
- package/dist/{mcp-B5ppXTnU.cjs → mcp-DYmjmXQb.cjs} +5 -6
- package/dist/mcp-DYmjmXQb.cjs.map +1 -0
- package/dist/{package-BBBrKion.cjs → package-B57sF1X0.cjs} +2 -2
- package/dist/package-B57sF1X0.cjs.map +1 -0
- package/dist/package-CQbxcw7I.js +6 -0
- package/dist/package-CQbxcw7I.js.map +1 -0
- package/dist/{run-DXEMoDFa.cjs → run-3qq_Q4Tg.cjs} +4 -4
- package/dist/run-3qq_Q4Tg.cjs.map +1 -0
- package/dist/{run-Bz6ZUrhp.cjs → run-B9FN0sHW.cjs} +2 -2
- package/dist/run-B9FN0sHW.cjs.map +1 -0
- package/dist/{run-CPBFfbI7.js → run-BFhNcn8b.js} +4 -10
- package/dist/run-BFhNcn8b.js.map +1 -0
- package/dist/{run-B0HOqTrU.js → run-CCsw-Y-v.js} +226 -268
- package/dist/run-CCsw-Y-v.js.map +1 -0
- package/dist/{run-BBLhhWZu.js → run-D0Gs_UzJ.js} +2 -2
- package/dist/run-D0Gs_UzJ.js.map +1 -0
- package/dist/{run-C4k6vPeY.cjs → run-DT9pRBLX.cjs} +228 -269
- package/dist/run-DT9pRBLX.cjs.map +1 -0
- package/dist/{run-DYkciQ4u.cjs → run-DYzUPE7Z.cjs} +4 -10
- package/dist/run-DYzUPE7Z.cjs.map +1 -0
- package/dist/{run-44Zxh8Ec.js → run-yMRylOST.js} +3 -3
- package/dist/run-yMRylOST.js.map +1 -0
- package/dist/{tools-D0UogMU3.js → tools-B23ltmWP.js} +3 -3
- package/dist/tools-B23ltmWP.js.map +1 -0
- package/dist/{tools-CZT9wSA6.cjs → tools-CeIABV0T.cjs} +3 -3
- package/dist/tools-CeIABV0T.cjs.map +1 -0
- package/dist/{validate-CbWRcTMP.cjs → validate-BTVjxR4L.cjs} +8 -9
- package/dist/validate-BTVjxR4L.cjs.map +1 -0
- package/dist/{validate-BMaesb7k.js → validate-CZFmahWd.js} +9 -9
- package/dist/validate-CZFmahWd.js.map +1 -0
- package/package.json +8 -7
- package/dist/Telemetry-jtbchpQE.cjs.map +0 -1
- package/dist/Telemetry-ugO-B77y.js.map +0 -1
- package/dist/defineCommand-Bo3yZTWI.cjs +0 -36
- package/dist/defineCommand-Bo3yZTWI.cjs.map +0 -1
- package/dist/defineCommand-DMEeqliP.js +0 -31
- package/dist/defineCommand-DMEeqliP.js.map +0 -1
- package/dist/generate-D5AWn6lH.js.map +0 -1
- package/dist/generate-DfzX98Lx.cjs.map +0 -1
- package/dist/init-GU5uRenE.js.map +0 -1
- package/dist/init-hKT7f8_b.cjs.map +0 -1
- package/dist/mcp-B3TSdKiQ.js.map +0 -1
- package/dist/mcp-B5ppXTnU.cjs.map +0 -1
- package/dist/package-BBBrKion.cjs.map +0 -1
- package/dist/package-DSkZlfZS.js +0 -6
- package/dist/package-DSkZlfZS.js.map +0 -1
- package/dist/run-44Zxh8Ec.js.map +0 -1
- package/dist/run-B0HOqTrU.js.map +0 -1
- package/dist/run-BBLhhWZu.js.map +0 -1
- package/dist/run-Bz6ZUrhp.cjs.map +0 -1
- package/dist/run-C4k6vPeY.cjs.map +0 -1
- package/dist/run-CPBFfbI7.js.map +0 -1
- package/dist/run-DXEMoDFa.cjs.map +0 -1
- package/dist/run-DYkciQ4u.cjs.map +0 -1
- package/dist/tools-CZT9wSA6.cjs.map +0 -1
- package/dist/tools-D0UogMU3.js.map +0 -1
- package/dist/validate-BMaesb7k.js.map +0 -1
- package/dist/validate-CbWRcTMP.cjs.map +0 -1
|
@@ -1,129 +1,21 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-Bx3C2hgW.cjs");
|
|
2
|
+
const require_Telemetry = require("./Telemetry-CwQYBgsg.cjs");
|
|
2
3
|
const require_errors = require("./errors-gxFK0vrp.cjs");
|
|
3
|
-
const
|
|
4
|
-
const require_tools = require("./tools-
|
|
5
|
-
const require_package = require("./package-BBBrKion.cjs");
|
|
4
|
+
const require_package = require("./package-B57sF1X0.cjs");
|
|
5
|
+
const require_tools = require("./tools-CeIABV0T.cjs");
|
|
6
6
|
let node_util = require("node:util");
|
|
7
|
-
|
|
8
|
-
let
|
|
7
|
+
require("node:crypto");
|
|
8
|
+
let node_process = require("node:process");
|
|
9
|
+
node_process = require_rolldown_runtime.__toESM(node_process, 1);
|
|
9
10
|
let node_fs = require("node:fs");
|
|
10
11
|
let node_path = require("node:path");
|
|
11
12
|
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
12
|
-
let node_process = require("node:process");
|
|
13
|
-
node_process = require_rolldown_runtime.__toESM(node_process, 1);
|
|
14
13
|
let _clack_prompts = require("@clack/prompts");
|
|
15
14
|
_clack_prompts = require_rolldown_runtime.__toESM(_clack_prompts, 1);
|
|
16
15
|
let _kubb_core = require("@kubb/core");
|
|
17
16
|
let jiti = require("jiti");
|
|
18
17
|
let tinyexec = require("tinyexec");
|
|
19
18
|
let unconfig = require("unconfig");
|
|
20
|
-
//#region ../../internals/utils/src/asyncEventEmitter.ts
|
|
21
|
-
/**
|
|
22
|
-
* Typed `EventEmitter` that awaits all async listeners before resolving.
|
|
23
|
-
* Wraps Node's `EventEmitter` with full TypeScript event-map inference.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```ts
|
|
27
|
-
* const emitter = new AsyncEventEmitter<{ build: [name: string] }>()
|
|
28
|
-
* emitter.on('build', async (name) => { console.log(name) })
|
|
29
|
-
* await emitter.emit('build', 'petstore') // all listeners awaited
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
var AsyncEventEmitter = class {
|
|
33
|
-
/**
|
|
34
|
-
* Maximum number of listeners per event before Node emits a memory-leak warning.
|
|
35
|
-
* @default 10
|
|
36
|
-
*/
|
|
37
|
-
constructor(maxListener = 10) {
|
|
38
|
-
this.#emitter.setMaxListeners(maxListener);
|
|
39
|
-
}
|
|
40
|
-
#emitter = new node_events.EventEmitter();
|
|
41
|
-
/**
|
|
42
|
-
* Emits `eventName` and awaits all registered listeners sequentially.
|
|
43
|
-
* Throws if any listener rejects, wrapping the cause with the event name and serialized arguments.
|
|
44
|
-
*
|
|
45
|
-
* @example
|
|
46
|
-
* ```ts
|
|
47
|
-
* await emitter.emit('build', 'petstore')
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
emit(eventName, ...eventArgs) {
|
|
51
|
-
const listeners = this.#emitter.listeners(eventName);
|
|
52
|
-
if (listeners.length === 0) return;
|
|
53
|
-
return this.#emitAll(eventName, listeners, eventArgs);
|
|
54
|
-
}
|
|
55
|
-
async #emitAll(eventName, listeners, eventArgs) {
|
|
56
|
-
for (const listener of listeners) try {
|
|
57
|
-
await listener(...eventArgs);
|
|
58
|
-
} catch (err) {
|
|
59
|
-
let serializedArgs;
|
|
60
|
-
try {
|
|
61
|
-
serializedArgs = JSON.stringify(eventArgs);
|
|
62
|
-
} catch {
|
|
63
|
-
serializedArgs = String(eventArgs);
|
|
64
|
-
}
|
|
65
|
-
throw new Error(`Error in async listener for "${eventName}" with eventArgs ${serializedArgs}`, { cause: require_errors.toError(err) });
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Registers a persistent listener for `eventName`.
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```ts
|
|
73
|
-
* emitter.on('build', async (name) => { console.log(name) })
|
|
74
|
-
* ```
|
|
75
|
-
*/
|
|
76
|
-
on(eventName, handler) {
|
|
77
|
-
this.#emitter.on(eventName, handler);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Removes a previously registered listener.
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```ts
|
|
84
|
-
* emitter.off('build', handler)
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
off(eventName, handler) {
|
|
88
|
-
this.#emitter.off(eventName, handler);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Returns the number of listeners registered for `eventName`.
|
|
92
|
-
*
|
|
93
|
-
* @example
|
|
94
|
-
* ```ts
|
|
95
|
-
* emitter.on('build', handler)
|
|
96
|
-
* emitter.listenerCount('build') // 1
|
|
97
|
-
* ```
|
|
98
|
-
*/
|
|
99
|
-
listenerCount(eventName) {
|
|
100
|
-
return this.#emitter.listenerCount(eventName);
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Raises or lowers the per-event listener ceiling before Node warns about a memory leak.
|
|
104
|
-
* Set this above the expected listener count when many listeners attach by design.
|
|
105
|
-
*
|
|
106
|
-
* @example
|
|
107
|
-
* ```ts
|
|
108
|
-
* emitter.setMaxListeners(40)
|
|
109
|
-
* ```
|
|
110
|
-
*/
|
|
111
|
-
setMaxListeners(max) {
|
|
112
|
-
this.#emitter.setMaxListeners(max);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Removes all listeners from every event channel.
|
|
116
|
-
*
|
|
117
|
-
* @example
|
|
118
|
-
* ```ts
|
|
119
|
-
* emitter.removeAll()
|
|
120
|
-
* ```
|
|
121
|
-
*/
|
|
122
|
-
removeAll() {
|
|
123
|
-
this.#emitter.removeAllListeners();
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
//#endregion
|
|
127
19
|
//#region ../../internals/utils/src/time.ts
|
|
128
20
|
/**
|
|
129
21
|
* Calculates elapsed time in milliseconds from a high-resolution `process.hrtime` start time.
|
|
@@ -268,6 +160,43 @@ function formatMsWithColor(ms) {
|
|
|
268
160
|
return (0, node_util.styleText)("red", formatted);
|
|
269
161
|
}
|
|
270
162
|
//#endregion
|
|
163
|
+
//#region ../../internals/utils/src/promise.ts
|
|
164
|
+
/**
|
|
165
|
+
* Wraps `run` so invocations never overlap: a trigger that lands while a run is in flight
|
|
166
|
+
* marks it dirty and runs once more after it finishes, no matter how many triggers arrived.
|
|
167
|
+
* Useful for event-driven reruns (a file watcher, a queue drain) where bursts should
|
|
168
|
+
* coalesce into a single trailing run.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* const rebuild = createSerialRunner({
|
|
173
|
+
* run: () => build(),
|
|
174
|
+
* onError: (error) => log.error(error.message),
|
|
175
|
+
* })
|
|
176
|
+
* watcher.on('change', () => void rebuild())
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
function createSerialRunner({ run, onError }) {
|
|
180
|
+
let running = false;
|
|
181
|
+
let dirty = false;
|
|
182
|
+
return async () => {
|
|
183
|
+
if (running) {
|
|
184
|
+
dirty = true;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
running = true;
|
|
188
|
+
do {
|
|
189
|
+
dirty = false;
|
|
190
|
+
try {
|
|
191
|
+
await run();
|
|
192
|
+
} catch (error) {
|
|
193
|
+
onError(require_errors.toError(error));
|
|
194
|
+
}
|
|
195
|
+
} while (dirty);
|
|
196
|
+
running = false;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//#endregion
|
|
271
200
|
//#region src/loggers/defineLogger.ts
|
|
272
201
|
/**
|
|
273
202
|
* Type-safe helper for authoring a {@link Logger}.
|
|
@@ -376,20 +305,18 @@ const clackLogger = defineLogger({
|
|
|
376
305
|
_clack_prompts.log.warn(text);
|
|
377
306
|
});
|
|
378
307
|
context.on("kubb:error", ({ error }) => {
|
|
379
|
-
const caused = require_errors.toCause(error);
|
|
380
308
|
const text = [(0, node_util.styleText)("red", "✗"), error.message].join(" ");
|
|
381
309
|
if (state.isSpinning) {
|
|
382
310
|
stopSpinner(getMessage(text));
|
|
383
311
|
return;
|
|
384
312
|
}
|
|
385
313
|
_clack_prompts.log.error(getMessage(text));
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
for (const frame of frames) _clack_prompts.log.message(getMessage((0, node_util.styleText)("dim", frame
|
|
389
|
-
if (
|
|
390
|
-
_clack_prompts.log.message((0, node_util.styleText)("dim",
|
|
391
|
-
const
|
|
392
|
-
for (const frame of frames) _clack_prompts.log.message(getMessage(` ${(0, node_util.styleText)("dim", frame.trim())}`));
|
|
314
|
+
const frames = logLevel >= _kubb_core.logLevel.verbose ? formatErrorFrames(error) : null;
|
|
315
|
+
if (frames) {
|
|
316
|
+
for (const frame of frames.frames) _clack_prompts.log.message(getMessage((0, node_util.styleText)("dim", frame)));
|
|
317
|
+
if (frames.cause) {
|
|
318
|
+
_clack_prompts.log.message((0, node_util.styleText)("dim", frames.cause.header));
|
|
319
|
+
for (const frame of frames.cause.frames) _clack_prompts.log.message(getMessage(` ${(0, node_util.styleText)("dim", frame)}`));
|
|
393
320
|
}
|
|
394
321
|
}
|
|
395
322
|
});
|
|
@@ -589,16 +516,14 @@ const plainLogger = defineLogger({
|
|
|
589
516
|
console.log(text);
|
|
590
517
|
});
|
|
591
518
|
context.on("kubb:error", ({ error }) => {
|
|
592
|
-
const caused = require_errors.toCause(error);
|
|
593
519
|
const text = getMessage(["✗", error.message].join(" "));
|
|
594
520
|
console.log(text);
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
for (const frame of frames) console.log(getMessage(frame
|
|
598
|
-
if (
|
|
599
|
-
console.log(
|
|
600
|
-
const
|
|
601
|
-
for (const frame of frames) console.log(getMessage(` ${frame.trim()}`));
|
|
521
|
+
const frames = logLevel >= _kubb_core.logLevel.verbose ? formatErrorFrames(error) : null;
|
|
522
|
+
if (frames) {
|
|
523
|
+
for (const frame of frames.frames) console.log(getMessage(frame));
|
|
524
|
+
if (frames.cause) {
|
|
525
|
+
console.log(frames.cause.header);
|
|
526
|
+
for (const frame of frames.cause.frames) console.log(getMessage(` ${frame}`));
|
|
602
527
|
}
|
|
603
528
|
}
|
|
604
529
|
});
|
|
@@ -685,6 +610,22 @@ function formatMessage(message, logLevel) {
|
|
|
685
610
|
return message;
|
|
686
611
|
}
|
|
687
612
|
/**
|
|
613
|
+
* First stack frames for verbose error output, including an optional `cause` chain.
|
|
614
|
+
*/
|
|
615
|
+
function formatErrorFrames(error) {
|
|
616
|
+
if (!error.stack) return null;
|
|
617
|
+
const frames = error.stack.split("\n").slice(1, 4).map((frame) => frame.trim());
|
|
618
|
+
const caused = require_errors.toCause(error);
|
|
619
|
+
if (!caused?.stack) return { frames };
|
|
620
|
+
return {
|
|
621
|
+
frames,
|
|
622
|
+
cause: {
|
|
623
|
+
header: `└─ caused by ${caused.message}`,
|
|
624
|
+
frames: caused.stack.split("\n").slice(1, 4).map((frame) => frame.trim())
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
688
629
|
* Build the progress summary line shown by the clack logger.
|
|
689
630
|
* Returns null when there is nothing to display.
|
|
690
631
|
*/
|
|
@@ -745,9 +686,6 @@ function createHookTimer() {
|
|
|
745
686
|
if (!hrStart) return;
|
|
746
687
|
starts.delete(id);
|
|
747
688
|
return getElapsedMs(hrStart);
|
|
748
|
-
},
|
|
749
|
-
clear() {
|
|
750
|
-
starts.clear();
|
|
751
689
|
}
|
|
752
690
|
};
|
|
753
691
|
}
|
|
@@ -760,14 +698,6 @@ function createHookTimer() {
|
|
|
760
698
|
function formatCommandWithArgs(command, args) {
|
|
761
699
|
return args?.length ? `${command} ${args.join(" ")}` : command;
|
|
762
700
|
}
|
|
763
|
-
function detectLogger() {
|
|
764
|
-
if (require_Telemetry.canUseTTY()) return "clack";
|
|
765
|
-
return "plain";
|
|
766
|
-
}
|
|
767
|
-
const logMapper = {
|
|
768
|
-
clack: clackLogger,
|
|
769
|
-
plain: plainLogger
|
|
770
|
-
};
|
|
771
701
|
/**
|
|
772
702
|
* Bridges a {@link Reporter} onto the run's event emitter: calls `report` with each config's
|
|
773
703
|
* {@link GenerationResult} on `kubb:generation:end`. The reporter never touches the emitter.
|
|
@@ -801,10 +731,7 @@ async function setupReporters(context, { logLevel, reporters }) {
|
|
|
801
731
|
for (const reporter of reporters) {
|
|
802
732
|
if (reporter.name === "cli") {
|
|
803
733
|
if (hasJson) continue;
|
|
804
|
-
|
|
805
|
-
const logger = logMapper[type];
|
|
806
|
-
if (!logger) throw new Error(`Unknown adapter type: ${type}`);
|
|
807
|
-
await logger.install(context, { logLevel });
|
|
734
|
+
await (require_Telemetry.canUseTTY() ? clackLogger : plainLogger).install(context, { logLevel });
|
|
808
735
|
}
|
|
809
736
|
installReporter(context, reporter, ctx);
|
|
810
737
|
}
|
|
@@ -915,6 +842,34 @@ async function getConfigs({ configPath, input, watch, logLevel }) {
|
|
|
915
842
|
}))
|
|
916
843
|
};
|
|
917
844
|
}
|
|
845
|
+
let hookSequence = 0;
|
|
846
|
+
/**
|
|
847
|
+
* Returns a process-unique id that correlates a hook's `kubb:hook:start` and `kubb:hook:end`
|
|
848
|
+
* events, which loggers use to key their per-hook state.
|
|
849
|
+
*/
|
|
850
|
+
function createHookId() {
|
|
851
|
+
hookSequence += 1;
|
|
852
|
+
return `hook-${hookSequence}`;
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Returns `true` when `latest` is a newer semver version than `current`. Compares each numeric
|
|
856
|
+
* part, so `5.10.0` beats `5.9.0` where a plain string comparison would not. Prerelease
|
|
857
|
+
* suffixes are ignored, and a malformed version never reports an update.
|
|
858
|
+
*
|
|
859
|
+
* @example Double-digit minor
|
|
860
|
+
* `isNewerVersion('5.9.0', '5.10.0') // true`
|
|
861
|
+
*
|
|
862
|
+
* @example String comparison would get this wrong the other way
|
|
863
|
+
* `isNewerVersion('5.10.0', '5.9.0') // false`
|
|
864
|
+
*/
|
|
865
|
+
function isNewerVersion(current, latest) {
|
|
866
|
+
const release = (value) => value.split("-")[0] ?? "";
|
|
867
|
+
const isNumeric = (value) => /^\d+(\.\d+)*$/.test(value);
|
|
868
|
+
const currentRelease = release(current);
|
|
869
|
+
const latestRelease = release(latest);
|
|
870
|
+
if (!isNumeric(currentRelease) || !isNumeric(latestRelease)) return false;
|
|
871
|
+
return currentRelease.localeCompare(latestRelease, void 0, { numeric: true }) < 0;
|
|
872
|
+
}
|
|
918
873
|
/**
|
|
919
874
|
* Tokenizes a shell command string, respecting single and double quotes.
|
|
920
875
|
*
|
|
@@ -928,44 +883,48 @@ function tokenize(command) {
|
|
|
928
883
|
return (command.match(/[^\s"']+|"([^"]*)"|'([^']*)'/g) ?? []).map((token) => token.replace(/^["']|["']$/g, ""));
|
|
929
884
|
}
|
|
930
885
|
/**
|
|
931
|
-
* Runs the `done` hooks defined in a Kubb config in sequence
|
|
886
|
+
* Runs the `done` hooks defined in a Kubb config in sequence and returns each hook's outcome,
|
|
887
|
+
* so the caller can turn failures into diagnostics.
|
|
932
888
|
*/
|
|
933
889
|
async function executeHooks({ configHooks, hooks }) {
|
|
934
890
|
const commands = Array.isArray(configHooks.done) ? configHooks.done : [configHooks.done].filter(Boolean);
|
|
891
|
+
const results = [];
|
|
935
892
|
for (const command of commands) {
|
|
936
893
|
const [cmd, ...args] = tokenize(command);
|
|
937
894
|
if (!cmd) continue;
|
|
938
|
-
const hookId = (
|
|
895
|
+
const hookId = createHookId();
|
|
939
896
|
const commandWithArgs = [cmd, ...args].join(" ");
|
|
940
897
|
await hooks.emit("kubb:hook:start", {
|
|
941
898
|
id: hookId,
|
|
942
899
|
command: cmd,
|
|
943
900
|
args
|
|
944
901
|
});
|
|
945
|
-
await runHook({
|
|
902
|
+
results.push(await runHook({
|
|
946
903
|
id: hookId,
|
|
947
904
|
command: cmd,
|
|
948
905
|
args,
|
|
949
906
|
commandWithArgs,
|
|
950
907
|
hooks
|
|
951
|
-
});
|
|
908
|
+
}));
|
|
952
909
|
}
|
|
910
|
+
return results;
|
|
953
911
|
}
|
|
954
912
|
/**
|
|
955
|
-
* Spawns a hook command and
|
|
956
|
-
* A non-zero exit
|
|
913
|
+
* Spawns a hook command and returns its outcome, mirroring it through `kubb:hook:end` for the
|
|
914
|
+
* loggers. A non-zero exit returns `success: false` rather than throwing, so the caller can turn
|
|
957
915
|
* it into a diagnostic. Other spawn errors do the same. Output is streamed through `kubb:hook:line`
|
|
958
916
|
* only while a listener is attached.
|
|
959
917
|
*/
|
|
960
918
|
async function runHook({ id, command, args, commandWithArgs, hooks }) {
|
|
961
|
-
const emitEnd = (
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
919
|
+
const emitEnd = async (result) => {
|
|
920
|
+
await hooks.emit("kubb:hook:end", {
|
|
921
|
+
command,
|
|
922
|
+
args,
|
|
923
|
+
id,
|
|
924
|
+
...result
|
|
925
|
+
});
|
|
926
|
+
return result;
|
|
927
|
+
};
|
|
969
928
|
const stream = hooks.listenerCount("kubb:hook:line") > 0;
|
|
970
929
|
try {
|
|
971
930
|
const proc = (0, tinyexec.x)(command, [...args ?? []], {
|
|
@@ -978,15 +937,20 @@ async function runHook({ id, command, args, commandWithArgs, hooks }) {
|
|
|
978
937
|
});
|
|
979
938
|
await proc;
|
|
980
939
|
await hooks.emit("kubb:success", { message: `${(0, node_util.styleText)("dim", commandWithArgs)} successfully executed` });
|
|
981
|
-
|
|
940
|
+
return emitEnd({
|
|
941
|
+
success: true,
|
|
942
|
+
error: null
|
|
943
|
+
});
|
|
982
944
|
} catch (err) {
|
|
983
|
-
if (!(err instanceof tinyexec.NonZeroExitError)) {
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
}
|
|
945
|
+
if (!(err instanceof tinyexec.NonZeroExitError)) return emitEnd({
|
|
946
|
+
success: false,
|
|
947
|
+
error: require_errors.toError(err)
|
|
948
|
+
});
|
|
987
949
|
const stderr = err.output?.stderr ?? "";
|
|
988
950
|
const stdout = err.output?.stdout ?? "";
|
|
989
|
-
|
|
951
|
+
return emitEnd({
|
|
952
|
+
success: false,
|
|
953
|
+
error: /* @__PURE__ */ new Error(`Hook execute failed: ${commandWithArgs}`),
|
|
990
954
|
stdout,
|
|
991
955
|
stderr
|
|
992
956
|
});
|
|
@@ -994,7 +958,9 @@ async function runHook({ id, command, args, commandWithArgs, hooks }) {
|
|
|
994
958
|
}
|
|
995
959
|
/**
|
|
996
960
|
* Starts a file watcher on the given paths and calls `cb` on any change.
|
|
997
|
-
* Ignores `.git` and `node_modules` directories.
|
|
961
|
+
* Ignores `.git` and `node_modules` directories. Event bursts (an editor save emits several)
|
|
962
|
+
* are debounced into one build, and builds never overlap: changes during a build queue exactly
|
|
963
|
+
* one rebuild.
|
|
998
964
|
*/
|
|
999
965
|
async function startWatcher(path, cb, log = {
|
|
1000
966
|
info: console.log,
|
|
@@ -1003,7 +969,8 @@ async function startWatcher(path, cb, log = {
|
|
|
1003
969
|
const { watch } = await import("chokidar");
|
|
1004
970
|
const watcher = watch(path, {
|
|
1005
971
|
ignorePermissionErrors: true,
|
|
1006
|
-
ignored: require_Telemetry.WATCHER_IGNORED_PATHS
|
|
972
|
+
ignored: require_Telemetry.WATCHER_IGNORED_PATHS,
|
|
973
|
+
ignoreInitial: true
|
|
1007
974
|
});
|
|
1008
975
|
node_process.default.once("SIGINT", () => {
|
|
1009
976
|
watcher.close();
|
|
@@ -1011,36 +978,28 @@ async function startWatcher(path, cb, log = {
|
|
|
1011
978
|
node_process.default.once("SIGTERM", () => {
|
|
1012
979
|
watcher.close();
|
|
1013
980
|
});
|
|
1014
|
-
|
|
981
|
+
const runBuild = createSerialRunner({
|
|
982
|
+
run: () => cb(path),
|
|
983
|
+
onError: () => log.error((0, node_util.styleText)("red", "Watcher failed"))
|
|
984
|
+
});
|
|
985
|
+
let debounceTimer = null;
|
|
986
|
+
watcher.on("all", (type, file) => {
|
|
1015
987
|
log.info((0, node_util.styleText)("yellow", (0, node_util.styleText)("bold", `Change detected: ${type} ${file}`)));
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
}
|
|
988
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
989
|
+
debounceTimer = setTimeout(() => {
|
|
990
|
+
debounceTimer = null;
|
|
991
|
+
runBuild();
|
|
992
|
+
}, 100);
|
|
1021
993
|
});
|
|
1022
994
|
}
|
|
1023
995
|
//#endregion
|
|
1024
996
|
//#region src/runners/generate/run.ts
|
|
1025
997
|
/**
|
|
1026
|
-
*
|
|
1027
|
-
* so
|
|
998
|
+
* Runs one formatter or linter pass over the output directory. Returns the failure instead of
|
|
999
|
+
* throwing, so the caller can turn it into a coded diagnostic. Failures never render here:
|
|
1000
|
+
* the caller emits them through `Diagnostics.emit`, like every other diagnostic.
|
|
1028
1001
|
*/
|
|
1029
|
-
function
|
|
1030
|
-
return new Promise((resolve, reject) => {
|
|
1031
|
-
const handler = (ctx) => {
|
|
1032
|
-
if (ctx.id !== hookId) return;
|
|
1033
|
-
hooks.off("kubb:hook:end", handler);
|
|
1034
|
-
if (!ctx.success) {
|
|
1035
|
-
reject(ctx.error ?? new Error(fallbackErrorMessage));
|
|
1036
|
-
return;
|
|
1037
|
-
}
|
|
1038
|
-
Promise.resolve(onSuccess()).then(resolve).catch(reject);
|
|
1039
|
-
};
|
|
1040
|
-
hooks.on("kubb:hook:end", handler);
|
|
1041
|
-
});
|
|
1042
|
-
}
|
|
1043
|
-
async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, configName, outputPath, logLevel, hooks, onStart, onEnd }) {
|
|
1002
|
+
async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefix, noToolMessage, outputPath, logLevel, hooks, onStart, onEnd }) {
|
|
1044
1003
|
await onStart();
|
|
1045
1004
|
let resolvedTool = toolValue;
|
|
1046
1005
|
if (resolvedTool === "auto") {
|
|
@@ -1051,38 +1010,38 @@ async function runToolPass({ toolValue, detect, toolMap, toolLabel, successPrefi
|
|
|
1051
1010
|
await hooks.emit("kubb:info", { message: `Auto-detected ${toolLabel}: ${(0, node_util.styleText)("dim", resolvedTool)}` });
|
|
1052
1011
|
}
|
|
1053
1012
|
}
|
|
1054
|
-
let toolError;
|
|
1013
|
+
let toolError = null;
|
|
1055
1014
|
if (resolvedTool && resolvedTool !== "auto" && resolvedTool in toolMap && (0, node_fs.existsSync)(outputPath)) {
|
|
1056
1015
|
const toolConfig = toolMap[resolvedTool];
|
|
1057
|
-
const hookId = (0, node_crypto.hash)("sha256", [configName, resolvedTool].filter(Boolean).join("-"), "hex");
|
|
1058
1016
|
const successMessage = [
|
|
1059
1017
|
`${successPrefix} with ${(0, node_util.styleText)("dim", resolvedTool)}`,
|
|
1060
1018
|
logLevel >= _kubb_core.logLevel.info ? `on ${(0, node_util.styleText)("dim", outputPath)}` : void 0,
|
|
1061
1019
|
"successfully"
|
|
1062
1020
|
].filter(Boolean).join(" ");
|
|
1063
1021
|
try {
|
|
1022
|
+
const hookId = createHookId();
|
|
1064
1023
|
const hookArgs = toolConfig.args(outputPath);
|
|
1065
1024
|
const commandWithArgs = [toolConfig.command, ...hookArgs].join(" ");
|
|
1066
|
-
const hookEndPromise = waitForHookEnd(hooks, hookId, () => hooks.emit("kubb:success", { message: successMessage }), toolConfig.errorMessage);
|
|
1067
1025
|
await hooks.emit("kubb:hook:start", {
|
|
1068
1026
|
id: hookId,
|
|
1069
1027
|
command: toolConfig.command,
|
|
1070
1028
|
args: hookArgs
|
|
1071
1029
|
});
|
|
1072
|
-
runHook({
|
|
1030
|
+
const result = await runHook({
|
|
1073
1031
|
id: hookId,
|
|
1074
1032
|
command: toolConfig.command,
|
|
1075
1033
|
args: hookArgs,
|
|
1076
1034
|
commandWithArgs,
|
|
1077
1035
|
hooks
|
|
1078
|
-
})
|
|
1079
|
-
await
|
|
1036
|
+
});
|
|
1037
|
+
if (result.success) await hooks.emit("kubb:success", { message: successMessage });
|
|
1038
|
+
else toolError = result.error ?? new Error(toolConfig.errorMessage);
|
|
1080
1039
|
} catch (caughtError) {
|
|
1081
1040
|
toolError = require_errors.toError(caughtError);
|
|
1082
1041
|
}
|
|
1083
1042
|
}
|
|
1084
1043
|
await onEnd();
|
|
1085
|
-
|
|
1044
|
+
return toolError;
|
|
1086
1045
|
}
|
|
1087
1046
|
async function generate(options) {
|
|
1088
1047
|
const { input, hooks, logLevel } = options;
|
|
@@ -1093,8 +1052,7 @@ async function generate(options) {
|
|
|
1093
1052
|
input: inputPath ? {
|
|
1094
1053
|
...options.config.input,
|
|
1095
1054
|
path: inputPath
|
|
1096
|
-
} : options.config.input
|
|
1097
|
-
...options.config.output
|
|
1055
|
+
} : options.config.input
|
|
1098
1056
|
};
|
|
1099
1057
|
const kubb = (0, _kubb_core.createKubb)(config, { hooks });
|
|
1100
1058
|
await hooks.emit("kubb:generation:start", { config });
|
|
@@ -1141,67 +1099,60 @@ async function generate(options) {
|
|
|
1141
1099
|
}
|
|
1142
1100
|
const outputPath = node_path.default.resolve(config.root, config.output.path);
|
|
1143
1101
|
const outputDiagnostics = [];
|
|
1144
|
-
const
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
"
|
|
1163
|
-
"biome",
|
|
1164
|
-
"eslint"
|
|
1165
|
-
]),
|
|
1166
|
-
toolMap: require_tools.linters,
|
|
1167
|
-
toolLabel: "linter",
|
|
1168
|
-
successPrefix: "Linting",
|
|
1169
|
-
noToolMessage: "No linter found (oxlint, biome, or eslint). Skipping linting.",
|
|
1170
|
-
onStart: () => hooks.emit("kubb:lint:start"),
|
|
1171
|
-
onEnd: () => hooks.emit("kubb:lint:end")
|
|
1172
|
-
}].filter(Boolean);
|
|
1173
|
-
for (const { code, ...pass } of toolPasses) try {
|
|
1174
|
-
await runToolPass({
|
|
1175
|
-
...pass,
|
|
1176
|
-
configName: config.name,
|
|
1102
|
+
const reportOutputFailure = async (code, label, error) => {
|
|
1103
|
+
const diagnostic = outputDiagnostic(code, label, error);
|
|
1104
|
+
outputDiagnostics.push(diagnostic);
|
|
1105
|
+
await _kubb_core.Diagnostics.emit(hooks, diagnostic);
|
|
1106
|
+
};
|
|
1107
|
+
if (config.output.format) {
|
|
1108
|
+
const error = await runToolPass({
|
|
1109
|
+
toolValue: config.output.format,
|
|
1110
|
+
detect: () => require_tools.detectTool([
|
|
1111
|
+
"oxfmt",
|
|
1112
|
+
"biome",
|
|
1113
|
+
"prettier"
|
|
1114
|
+
]),
|
|
1115
|
+
toolMap: require_tools.formatters,
|
|
1116
|
+
toolLabel: "formatter",
|
|
1117
|
+
successPrefix: "Formatting",
|
|
1118
|
+
noToolMessage: "No formatter found (oxfmt, biome, or prettier). Skipping formatting.",
|
|
1119
|
+
onStart: () => hooks.emit("kubb:format:start"),
|
|
1120
|
+
onEnd: () => hooks.emit("kubb:format:end"),
|
|
1177
1121
|
outputPath,
|
|
1178
1122
|
logLevel,
|
|
1179
1123
|
hooks
|
|
1180
1124
|
});
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
await
|
|
1125
|
+
if (error) await reportOutputFailure(_kubb_core.Diagnostics.code.formatFailed, "formatter", error);
|
|
1126
|
+
}
|
|
1127
|
+
if (config.output.lint) {
|
|
1128
|
+
const error = await runToolPass({
|
|
1129
|
+
toolValue: config.output.lint,
|
|
1130
|
+
detect: () => require_tools.detectTool([
|
|
1131
|
+
"oxlint",
|
|
1132
|
+
"biome",
|
|
1133
|
+
"eslint"
|
|
1134
|
+
]),
|
|
1135
|
+
toolMap: require_tools.linters,
|
|
1136
|
+
toolLabel: "linter",
|
|
1137
|
+
successPrefix: "Linting",
|
|
1138
|
+
noToolMessage: "No linter found (oxlint, biome, or eslint). Skipping linting.",
|
|
1139
|
+
onStart: () => hooks.emit("kubb:lint:start"),
|
|
1140
|
+
onEnd: () => hooks.emit("kubb:lint:end"),
|
|
1141
|
+
outputPath,
|
|
1142
|
+
logLevel,
|
|
1143
|
+
hooks
|
|
1144
|
+
});
|
|
1145
|
+
if (error) await reportOutputFailure(_kubb_core.Diagnostics.code.lintFailed, "linter", error);
|
|
1185
1146
|
}
|
|
1186
1147
|
if (config.hooks) {
|
|
1187
1148
|
await hooks.emit("kubb:hooks:start");
|
|
1188
|
-
const
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
};
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
await
|
|
1195
|
-
configHooks: config.hooks,
|
|
1196
|
-
hooks
|
|
1197
|
-
});
|
|
1198
|
-
} finally {
|
|
1199
|
-
hooks.off("kubb:hook:end", onHookEnd);
|
|
1200
|
-
}
|
|
1201
|
-
for (const error of hookFailures) {
|
|
1202
|
-
const diagnostic = outputDiagnostic(_kubb_core.Diagnostics.code.hookFailed, "Post-generate hook", error);
|
|
1203
|
-
outputDiagnostics.push(diagnostic);
|
|
1204
|
-
await _kubb_core.Diagnostics.emit(hooks, diagnostic);
|
|
1149
|
+
const hookResults = await executeHooks({
|
|
1150
|
+
configHooks: config.hooks,
|
|
1151
|
+
hooks
|
|
1152
|
+
});
|
|
1153
|
+
for (const result of hookResults) {
|
|
1154
|
+
if (result.success) continue;
|
|
1155
|
+
await reportOutputFailure(_kubb_core.Diagnostics.code.hookFailed, "Post-generate hook", result.error ?? /* @__PURE__ */ new Error("Post-generate hook failed"));
|
|
1205
1156
|
}
|
|
1206
1157
|
await hooks.emit("kubb:hooks:end");
|
|
1207
1158
|
}
|
|
@@ -1238,8 +1189,8 @@ function outputDiagnostic(code, label, caughtError) {
|
|
|
1238
1189
|
}
|
|
1239
1190
|
async function checkForUpdate(hooks) {
|
|
1240
1191
|
try {
|
|
1241
|
-
const data = await (await fetch(require_Telemetry.KUBB_NPM_PACKAGE_URL)).json();
|
|
1242
|
-
if (data.version && require_package.version
|
|
1192
|
+
const data = await (await fetch(require_Telemetry.KUBB_NPM_PACKAGE_URL, { signal: AbortSignal.timeout(require_Telemetry.UPDATE_CHECK_TIMEOUT_MS) })).json();
|
|
1193
|
+
if (data.version && isNewerVersion(require_package.version, data.version)) await _kubb_core.Diagnostics.emit(hooks, _kubb_core.Diagnostics.update({
|
|
1243
1194
|
currentVersion: require_package.version,
|
|
1244
1195
|
latestVersion: data.version
|
|
1245
1196
|
}));
|
|
@@ -1252,7 +1203,7 @@ async function checkForUpdate(hooks) {
|
|
|
1252
1203
|
*/
|
|
1253
1204
|
async function run({ input, configPath, logLevel: logLevelKey, watch, reporters: cliReporters }) {
|
|
1254
1205
|
const logLevel = _kubb_core.logLevel[logLevelKey] ?? _kubb_core.logLevel.info;
|
|
1255
|
-
const hooks = new AsyncEventEmitter();
|
|
1206
|
+
const hooks = new _kubb_core.AsyncEventEmitter();
|
|
1256
1207
|
let configs;
|
|
1257
1208
|
let resolvedConfigPath;
|
|
1258
1209
|
try {
|
|
@@ -1290,19 +1241,27 @@ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters:
|
|
|
1290
1241
|
info: relativeConfigPath
|
|
1291
1242
|
});
|
|
1292
1243
|
let anyFailed = false;
|
|
1293
|
-
for (const config of configs) if (config.input && "path" in config.input && watch)
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1244
|
+
for (const config of configs) if (config.input && "path" in config.input && watch) {
|
|
1245
|
+
const watchedPaths = [input || config.input.path];
|
|
1246
|
+
const build = async (paths) => {
|
|
1247
|
+
await generate({
|
|
1248
|
+
input,
|
|
1249
|
+
config,
|
|
1250
|
+
logLevel,
|
|
1251
|
+
hooks
|
|
1252
|
+
});
|
|
1253
|
+
_clack_prompts.log.step((0, node_util.styleText)("yellow", `Watching for changes in ${paths.join(" and ")}`));
|
|
1254
|
+
};
|
|
1255
|
+
try {
|
|
1256
|
+
await build(watchedPaths);
|
|
1257
|
+
} catch (buildError) {
|
|
1258
|
+
await hooks.emit("kubb:error", { error: require_errors.toError(buildError) });
|
|
1259
|
+
}
|
|
1260
|
+
await startWatcher(watchedPaths, build, {
|
|
1261
|
+
info: (msg) => _clack_prompts.log.info(msg),
|
|
1262
|
+
error: (msg) => _clack_prompts.log.error(msg)
|
|
1299
1263
|
});
|
|
1300
|
-
|
|
1301
|
-
}, {
|
|
1302
|
-
info: (msg) => _clack_prompts.log.info(msg),
|
|
1303
|
-
error: (msg) => _clack_prompts.log.error(msg)
|
|
1304
|
-
});
|
|
1305
|
-
else try {
|
|
1264
|
+
} else try {
|
|
1306
1265
|
if (!await generate({
|
|
1307
1266
|
input,
|
|
1308
1267
|
config,
|
|
@@ -1323,4 +1282,4 @@ async function run({ input, configPath, logLevel: logLevelKey, watch, reporters:
|
|
|
1323
1282
|
//#endregion
|
|
1324
1283
|
exports.run = run;
|
|
1325
1284
|
|
|
1326
|
-
//# sourceMappingURL=run-
|
|
1285
|
+
//# sourceMappingURL=run-DT9pRBLX.cjs.map
|