@kubb/studio 5.12.1 → 5.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +158 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +157 -5
- package/dist/index.js.map +1 -1
- package/dist/{protocol-CG1bPO_H.d.ts → protocol-DhNrwhqp.d.cts} +34 -2
- package/dist/{protocol-CG1bPO_H.d.cts → protocol-DhNrwhqp.d.ts} +34 -2
- package/dist/protocol.cjs +4 -0
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +2 -2
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.js +4 -0
- package/dist/protocol.js.map +1 -1
- package/package.json +5 -4
package/dist/index.cjs
CHANGED
|
@@ -23,20 +23,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
const require_protocol = require("./protocol.cjs");
|
|
25
25
|
let node_crypto = require("node:crypto");
|
|
26
|
+
let node_fs = require("node:fs");
|
|
27
|
+
let node_module = require("node:module");
|
|
26
28
|
let node_os = require("node:os");
|
|
27
29
|
let node_path = require("node:path");
|
|
28
30
|
node_path = __toESM(node_path, 1);
|
|
29
31
|
let node_process = require("node:process");
|
|
30
32
|
node_process = __toESM(node_process, 1);
|
|
31
33
|
let node_timers_promises = require("node:timers/promises");
|
|
32
|
-
let
|
|
33
|
-
let node_stream = require("node:stream");
|
|
34
|
-
let node_fs = require("node:fs");
|
|
34
|
+
let tinyexec = require("tinyexec");
|
|
35
35
|
let node_fs_promises = require("node:fs/promises");
|
|
36
36
|
let _kubb_core = require("@kubb/core");
|
|
37
37
|
let capnweb = require("capnweb");
|
|
38
38
|
let magicast = require("magicast");
|
|
39
|
-
let
|
|
39
|
+
let node_url = require("node:url");
|
|
40
40
|
let diff = require("diff");
|
|
41
41
|
let node_util = require("node:util");
|
|
42
42
|
let _kubb_ast = require("@kubb/ast");
|
|
@@ -48,6 +48,7 @@ let node_https = require("node:https");
|
|
|
48
48
|
node_https = __toESM(node_https, 1);
|
|
49
49
|
let node_net = require("node:net");
|
|
50
50
|
node_net = __toESM(node_net, 1);
|
|
51
|
+
let node_stream = require("node:stream");
|
|
51
52
|
let ofetch = require("ofetch");
|
|
52
53
|
let node_zlib = require("node:zlib");
|
|
53
54
|
//#region ../../internals/utils/src/casing.ts
|
|
@@ -229,7 +230,7 @@ function getElapsedMs(hrStart) {
|
|
|
229
230
|
}
|
|
230
231
|
//#endregion
|
|
231
232
|
//#region package.json
|
|
232
|
-
var version = "5.12.
|
|
233
|
+
var version = "5.12.2";
|
|
233
234
|
//#endregion
|
|
234
235
|
//#region src/resolveConfig.ts
|
|
235
236
|
/**
|
|
@@ -2041,6 +2042,43 @@ var IncompatibleAgentError = class extends Error {
|
|
|
2041
2042
|
this.name = "IncompatibleAgentError";
|
|
2042
2043
|
}
|
|
2043
2044
|
};
|
|
2045
|
+
const INSTALL_TIMEOUT_MS = 3e5;
|
|
2046
|
+
/** `owner/slug` or `slug`, as `kubb add` takes it. Checked before it becomes an argument. */
|
|
2047
|
+
const REGISTRY_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*(?:\/[a-z0-9]+(?:-[a-z0-9]+)*)?$/;
|
|
2048
|
+
/** The CLI the project depends on, so `kubb add` installs next to what the config imports. */
|
|
2049
|
+
function findKubbBin(root) {
|
|
2050
|
+
const require$1 = (0, node_module.createRequire)(node_path.default.resolve(root, "package.json"));
|
|
2051
|
+
const names = ["kubb", "@kubb/cli"];
|
|
2052
|
+
return (require$1.resolve.paths("kubb") ?? []).flatMap((dir) => names.map((name) => node_path.default.join(dir, name, "bin", "kubb.js"))).find((bin) => (0, node_fs.existsSync)(bin));
|
|
2053
|
+
}
|
|
2054
|
+
/** Runs a `kubb` command without a shell, and keeps the end of its output for the failure reason. */
|
|
2055
|
+
async function runKubb({ bin, args, cwd, signal }) {
|
|
2056
|
+
try {
|
|
2057
|
+
const { stdout, stderr, exitCode } = await (0, tinyexec.x)(node_process.default.execPath, [bin, ...args], {
|
|
2058
|
+
signal,
|
|
2059
|
+
timeout: INSTALL_TIMEOUT_MS,
|
|
2060
|
+
throwOnError: false,
|
|
2061
|
+
nodeOptions: {
|
|
2062
|
+
cwd,
|
|
2063
|
+
env: {
|
|
2064
|
+
...node_process.default.env,
|
|
2065
|
+
NO_COLOR: "1",
|
|
2066
|
+
FORCE_COLOR: "0"
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
});
|
|
2070
|
+
const output = `${stdout}\n${stderr}`.trim().split("\n").slice(-20).join("\n");
|
|
2071
|
+
return {
|
|
2072
|
+
failed: exitCode !== 0,
|
|
2073
|
+
output: output || `kubb ${args[0]} exited with ${exitCode ?? "a signal"}`
|
|
2074
|
+
};
|
|
2075
|
+
} catch (error) {
|
|
2076
|
+
return {
|
|
2077
|
+
failed: true,
|
|
2078
|
+
output: `kubb ${args[0]} did not run: ${getErrorMessage(error)}`
|
|
2079
|
+
};
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2044
2082
|
function emit(hooks, name, ...args) {
|
|
2045
2083
|
return Promise.resolve(hooks.callHook(name, ...args)).catch(() => {});
|
|
2046
2084
|
}
|
|
@@ -2111,6 +2149,8 @@ var Agent = class extends capnweb.RpcTarget {
|
|
|
2111
2149
|
...permissions,
|
|
2112
2150
|
allowWrite: false,
|
|
2113
2151
|
allowConfigEdit: false,
|
|
2152
|
+
allowInstall: false,
|
|
2153
|
+
allowUpdate: false,
|
|
2114
2154
|
allowRead: true,
|
|
2115
2155
|
allowReadAst: true
|
|
2116
2156
|
} : permissions;
|
|
@@ -2262,6 +2302,8 @@ var Agent = class extends capnweb.RpcTarget {
|
|
|
2262
2302
|
message: "Connection is closed"
|
|
2263
2303
|
});
|
|
2264
2304
|
if (this.#session.active) return this.#refuse({ message: require_protocol.AgentMessage.GENERATION_IN_PROGRESS });
|
|
2305
|
+
if (this.#session.install) return this.#refuse({ message: require_protocol.AgentMessage.INSTALL_IN_PROGRESS });
|
|
2306
|
+
if (this.#session.saving) return this.#refuse({ message: require_protocol.AgentMessage.SAVE_IN_PROGRESS });
|
|
2265
2307
|
const settled = Promise.withResolvers();
|
|
2266
2308
|
this.#session.active = {
|
|
2267
2309
|
jobId: input.jobId,
|
|
@@ -2402,7 +2444,9 @@ var Agent = class extends capnweb.RpcTarget {
|
|
|
2402
2444
|
await this.#warn({ message: "Ignored save: editing kubb.config.ts was not granted" });
|
|
2403
2445
|
return refuse("the agent was not granted permission to edit kubb.config.ts");
|
|
2404
2446
|
}
|
|
2405
|
-
|
|
2447
|
+
const busy = this.#busy();
|
|
2448
|
+
if (busy) return refuse(busy);
|
|
2449
|
+
this.#session.saving = true;
|
|
2406
2450
|
try {
|
|
2407
2451
|
const { outcomes, changed } = await writeConfigEdits({
|
|
2408
2452
|
filePath: configFile,
|
|
@@ -2418,6 +2462,110 @@ var Agent = class extends capnweb.RpcTarget {
|
|
|
2418
2462
|
} catch (error) {
|
|
2419
2463
|
await emit(this.#options.hooks, "studio:error", { error: toError(error) });
|
|
2420
2464
|
return refuse(getErrorMessage(error));
|
|
2465
|
+
} finally {
|
|
2466
|
+
this.#session.saving = false;
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
/**
|
|
2470
|
+
* Installs a registry extension into the project with `kubb add <id> --yes`, which also adds a
|
|
2471
|
+
* plugin to `kubb.config.ts`. Studio calls `connect()` again afterwards to see the result.
|
|
2472
|
+
*/
|
|
2473
|
+
async installExtension(input) {
|
|
2474
|
+
this.#assertConnected();
|
|
2475
|
+
const { root, configFile, kubbBin = findKubbBin(root) } = this.#options;
|
|
2476
|
+
const refuse = async (reason, permission) => {
|
|
2477
|
+
await this.#warn({
|
|
2478
|
+
message: `Ignored install: ${reason}`,
|
|
2479
|
+
permission
|
|
2480
|
+
});
|
|
2481
|
+
return {
|
|
2482
|
+
installed: false,
|
|
2483
|
+
reason
|
|
2484
|
+
};
|
|
2485
|
+
};
|
|
2486
|
+
if (typeof input?.id !== "string" || !REGISTRY_ID.test(input.id)) return refuse("the message carried no registry id");
|
|
2487
|
+
if (!this.#permissions.allowInstall) return refuse("installing extensions was not granted", require_protocol.AgentPermission.INSTALL);
|
|
2488
|
+
if (!this.#permissions.allowConfigEdit) return refuse("editing kubb.config.ts was not granted", require_protocol.AgentPermission.CONFIG_EDIT);
|
|
2489
|
+
const busy = this.#busy();
|
|
2490
|
+
if (busy) return refuse(busy);
|
|
2491
|
+
if (!kubbBin) return refuse("kubb is not installed in the project");
|
|
2492
|
+
const { failed, output } = await this.#runKubb({
|
|
2493
|
+
bin: kubbBin,
|
|
2494
|
+
args: [
|
|
2495
|
+
"add",
|
|
2496
|
+
input.id,
|
|
2497
|
+
"--yes",
|
|
2498
|
+
"--config",
|
|
2499
|
+
configFile
|
|
2500
|
+
]
|
|
2501
|
+
});
|
|
2502
|
+
await this.#logCommand("installExtension", `${failed ? "failed to install" : "installed"} ${input.id}`, input.requestedBy, failed);
|
|
2503
|
+
return failed ? {
|
|
2504
|
+
installed: false,
|
|
2505
|
+
reason: output
|
|
2506
|
+
} : { installed: true };
|
|
2507
|
+
}
|
|
2508
|
+
/**
|
|
2509
|
+
* Moves installed extensions to the registry's version with `kubb update [ids] --yes`, which
|
|
2510
|
+
* installs packages and leaves `kubb.config.ts` alone. Studio calls `connect()` again afterwards.
|
|
2511
|
+
*/
|
|
2512
|
+
async updateExtensions(input) {
|
|
2513
|
+
this.#assertConnected();
|
|
2514
|
+
const { root, kubbBin = findKubbBin(root) } = this.#options;
|
|
2515
|
+
const refuse = async (reason, permission) => {
|
|
2516
|
+
await this.#warn({
|
|
2517
|
+
message: `Ignored update: ${reason}`,
|
|
2518
|
+
permission
|
|
2519
|
+
});
|
|
2520
|
+
return {
|
|
2521
|
+
updated: false,
|
|
2522
|
+
reason
|
|
2523
|
+
};
|
|
2524
|
+
};
|
|
2525
|
+
const ids = input?.ids ?? [];
|
|
2526
|
+
if (!Array.isArray(ids) || !ids.every((id) => typeof id === "string" && REGISTRY_ID.test(id))) return refuse("the message carried an invalid registry id");
|
|
2527
|
+
if (!this.#permissions.allowUpdate) return refuse("updating extensions was not granted", require_protocol.AgentPermission.UPDATE);
|
|
2528
|
+
const busy = this.#busy();
|
|
2529
|
+
if (busy) return refuse(busy);
|
|
2530
|
+
if (!kubbBin) return refuse("kubb is not installed in the project");
|
|
2531
|
+
const { failed, output } = await this.#runKubb({
|
|
2532
|
+
bin: kubbBin,
|
|
2533
|
+
args: [
|
|
2534
|
+
"update",
|
|
2535
|
+
...ids,
|
|
2536
|
+
"--yes"
|
|
2537
|
+
]
|
|
2538
|
+
});
|
|
2539
|
+
await this.#logCommand("updateExtensions", `${failed ? "failed to update" : "updated"} ${ids.join(", ") || "all extensions"}`, input?.requestedBy, failed);
|
|
2540
|
+
return failed ? {
|
|
2541
|
+
updated: false,
|
|
2542
|
+
reason: output
|
|
2543
|
+
} : { updated: true };
|
|
2544
|
+
}
|
|
2545
|
+
/** Why a command that touches the project cannot start right now. */
|
|
2546
|
+
#busy() {
|
|
2547
|
+
if (this.#session.active) return "a generation is in progress";
|
|
2548
|
+
if (this.#session.install) return "an install or update is in progress";
|
|
2549
|
+
if (this.#session.saving) return "a save is in progress";
|
|
2550
|
+
}
|
|
2551
|
+
/** Runs `kubb` in the project while holding off saves and generations, and ends it when the socket closes. */
|
|
2552
|
+
async #runKubb({ bin, args }) {
|
|
2553
|
+
const controller = new AbortController();
|
|
2554
|
+
const settled = Promise.withResolvers();
|
|
2555
|
+
this.#session.install = {
|
|
2556
|
+
abort: () => controller.abort(),
|
|
2557
|
+
settled: settled.promise
|
|
2558
|
+
};
|
|
2559
|
+
try {
|
|
2560
|
+
return await runKubb({
|
|
2561
|
+
bin,
|
|
2562
|
+
args,
|
|
2563
|
+
cwd: this.#options.root,
|
|
2564
|
+
signal: controller.signal
|
|
2565
|
+
});
|
|
2566
|
+
} finally {
|
|
2567
|
+
this.#session.install = void 0;
|
|
2568
|
+
settled.resolve();
|
|
2421
2569
|
}
|
|
2422
2570
|
}
|
|
2423
2571
|
/**
|
|
@@ -2602,6 +2750,8 @@ async function runSession({ options, openRpc, url, instanceId }) {
|
|
|
2602
2750
|
await emit(hooks, "studio:warn", { message: "Canceled the running generation: the connection to Kubb Studio closed" });
|
|
2603
2751
|
}
|
|
2604
2752
|
await active?.settled;
|
|
2753
|
+
session.install?.abort();
|
|
2754
|
+
await session.install?.settled;
|
|
2605
2755
|
await agent.clear();
|
|
2606
2756
|
return {
|
|
2607
2757
|
...close,
|
|
@@ -2670,6 +2820,8 @@ async function runAgent({ options, openRpc }) {
|
|
|
2670
2820
|
permissions: {
|
|
2671
2821
|
allowWrite: false,
|
|
2672
2822
|
allowConfigEdit: false,
|
|
2823
|
+
allowInstall: false,
|
|
2824
|
+
allowUpdate: false,
|
|
2673
2825
|
allowExec: false,
|
|
2674
2826
|
allowRead: false,
|
|
2675
2827
|
allowReadAst: false,
|