@kubb/studio 5.9.4 → 5.9.6
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/README.md +2 -2
- package/dist/index.cjs +69 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +70 -7
- package/dist/index.js.map +1 -1
- package/dist/{protocol-gXoAXvT3.d.ts → protocol-ixLkhvRJ.d.ts} +21 -2
- package/dist/protocol.cjs +4 -0
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.js +3 -1
- package/dist/protocol.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __name } from "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
-
import {
|
|
2
|
+
import { M as PublishedSnapshot, V as SnapshotUploadMetadata, a as AgentConnectInfo, c as ConfigEdit, l as ConfigEditOutcome, o as AgentPermissions, w as InstalledExtensions } from "./protocol-ixLkhvRJ.js";
|
|
3
3
|
import { Config, Hookable, KubbHooks } from "@kubb/core";
|
|
4
4
|
//#region src/connect.d.ts
|
|
5
5
|
/**
|
|
@@ -46,7 +46,7 @@ declare global {
|
|
|
46
46
|
* A finished command and what it did, such as `applied 2/3 edits to kubb.config.ts`.
|
|
47
47
|
*/
|
|
48
48
|
'studio:command': [ctx: {
|
|
49
|
-
command: 'generate' | 'saveConfig' | 'readFiles';
|
|
49
|
+
command: 'generate' | 'saveConfig' | 'readFiles' | 'readInput';
|
|
50
50
|
info: string;
|
|
51
51
|
}];
|
|
52
52
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
-
import { AGENT_INSTANCE_HEADER, AGENT_SOCKET_PATH, AgentCloseCode, GENERATION_GONE_MESSAGE, MAX_PAGE_LINES, MAX_SNAPSHOT_BYTES, generationEventTypes } from "./protocol.js";
|
|
2
|
+
import { AGENT_INSTANCE_HEADER, AGENT_SOCKET_PATH, AgentCloseCode, GENERATION_GONE_MESSAGE, MAX_PAGE_LINES, MAX_SNAPSHOT_BYTES, NO_INPUT_MESSAGE, READ_NOT_ALLOWED_MESSAGE, generationEventTypes } from "./protocol.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { createHash, hash, randomUUID } from "node:crypto";
|
|
5
5
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
@@ -13,6 +13,7 @@ import { Diagnostics, Hookable, cacheStorage, createKubb, fsStorage, getInputKin
|
|
|
13
13
|
import { RpcTarget, newWebSocketRpcSession } from "capnweb";
|
|
14
14
|
import { detectCodeFormat, parseExpression, parseModule } from "magicast";
|
|
15
15
|
import { stripVTControlCharacters } from "node:util";
|
|
16
|
+
import { ast } from "@kubb/ast";
|
|
16
17
|
import { ofetch } from "ofetch";
|
|
17
18
|
import { gzipSync } from "node:zlib";
|
|
18
19
|
//#region ../../internals/utils/src/casing.ts
|
|
@@ -152,7 +153,7 @@ function getElapsedMs(hrStart) {
|
|
|
152
153
|
}
|
|
153
154
|
//#endregion
|
|
154
155
|
//#region package.json
|
|
155
|
-
var version = "5.9.
|
|
156
|
+
var version = "5.9.6";
|
|
156
157
|
//#endregion
|
|
157
158
|
//#region src/resolveConfig.ts
|
|
158
159
|
/**
|
|
@@ -1083,7 +1084,10 @@ function relativeStoragePath({ root, filePath }) {
|
|
|
1083
1084
|
* The content fingerprint Studio compares snapshots by. Agent runs and CI uploads must agree on it.
|
|
1084
1085
|
*/
|
|
1085
1086
|
const hashOf = (content) => createHash("sha1").update(content).digest("hex").slice(0, 16);
|
|
1086
|
-
|
|
1087
|
+
/**
|
|
1088
|
+
* The bytes `entries` keep on disk: output, written files, and kept input.
|
|
1089
|
+
*/
|
|
1090
|
+
const totalBytes = (entries) => entries.reduce((sum, { output, disk, inputBytes }) => sum + output.bytes + (disk?.bytes ?? 0) + (inputBytes ?? 0), 0);
|
|
1087
1091
|
function positiveNumber(value) {
|
|
1088
1092
|
const parsed = Number(value);
|
|
1089
1093
|
return value && Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
@@ -1126,7 +1130,11 @@ async function generate({ config, hooks, signal, allowExec }) {
|
|
|
1126
1130
|
hooks,
|
|
1127
1131
|
signal
|
|
1128
1132
|
});
|
|
1129
|
-
|
|
1133
|
+
let input = null;
|
|
1134
|
+
const unhook = kubb.hooks.hook("kubb:build:end", (ctx) => {
|
|
1135
|
+
if (ctx.config === kubb.config) input = kubb.driver.inputNode;
|
|
1136
|
+
});
|
|
1137
|
+
const result = await kubb.generate().finally(unhook);
|
|
1130
1138
|
if (!result.success) throw generationFailure(result.diagnostics);
|
|
1131
1139
|
const { storage, root } = kubb.config;
|
|
1132
1140
|
return {
|
|
@@ -1135,7 +1143,8 @@ async function generate({ config, hooks, signal, allowExec }) {
|
|
|
1135
1143
|
paths: new Set(result.files.map((file) => relativeStoragePath({
|
|
1136
1144
|
root,
|
|
1137
1145
|
filePath: file.path
|
|
1138
|
-
})))
|
|
1146
|
+
}))),
|
|
1147
|
+
input
|
|
1139
1148
|
};
|
|
1140
1149
|
}
|
|
1141
1150
|
/**
|
|
@@ -1216,6 +1225,33 @@ function createGenerationStore({ storage, maxCount, maxMb, ttlMs, now = Date.now
|
|
|
1216
1225
|
return {
|
|
1217
1226
|
keep,
|
|
1218
1227
|
drop,
|
|
1228
|
+
/**
|
|
1229
|
+
* Keeps the `InputNode` of `jobId` and returns its size in bytes, or 0 when it keeps none. A ref schema loses
|
|
1230
|
+
* the copy of its target, which `input.schemas` holds: with it, a large spec outgrows what `JSON.stringify` can return.
|
|
1231
|
+
*/
|
|
1232
|
+
async keepInput({ jobId, input, maxSetMb }) {
|
|
1233
|
+
if (!input) return 0;
|
|
1234
|
+
let json;
|
|
1235
|
+
try {
|
|
1236
|
+
json = JSON.stringify(ast.transform(input, { schema: (node) => node.type === "ref" && node.schema ? {
|
|
1237
|
+
...node,
|
|
1238
|
+
schema: void 0
|
|
1239
|
+
} : void 0 }));
|
|
1240
|
+
} catch {
|
|
1241
|
+
return 0;
|
|
1242
|
+
}
|
|
1243
|
+
const bytes = Buffer.byteLength(json);
|
|
1244
|
+
if (bytes > maxSetMb * MB) return 0;
|
|
1245
|
+
await storage.writeItem(`${dirOf(jobId)}input.json`, json);
|
|
1246
|
+
return bytes;
|
|
1247
|
+
},
|
|
1248
|
+
/**
|
|
1249
|
+
* The input `keepInput` kept for `jobId`, or `undefined` when there is none.
|
|
1250
|
+
*/
|
|
1251
|
+
async readInput(jobId) {
|
|
1252
|
+
const stored = await storage.readItem(`${dirOf(jobId)}input.json`);
|
|
1253
|
+
return stored === null ? void 0 : JSON.parse(stored);
|
|
1254
|
+
},
|
|
1219
1255
|
get: async (jobId) => (await load()).find((generation) => generation.jobId === jobId && isLive(generation)),
|
|
1220
1256
|
async add(generation) {
|
|
1221
1257
|
const current = await load();
|
|
@@ -1666,6 +1702,7 @@ var Agent = class extends RpcTarget {
|
|
|
1666
1702
|
}
|
|
1667
1703
|
});
|
|
1668
1704
|
}
|
|
1705
|
+
/** Runs one job and keeps its output, and its input with `allowRead`, for later reads. */
|
|
1669
1706
|
async #runGeneration(input, controller) {
|
|
1670
1707
|
this.#assertConnected();
|
|
1671
1708
|
if (this.#session.closed) throw new Error("Connection is closed");
|
|
@@ -1753,11 +1790,17 @@ var Agent = class extends RpcTarget {
|
|
|
1753
1790
|
files,
|
|
1754
1791
|
maxSetMb: this.#limits.maxMb
|
|
1755
1792
|
});
|
|
1793
|
+
const inputBytes = await this.#generations.keepInput({
|
|
1794
|
+
jobId,
|
|
1795
|
+
input: this.#permissions.allowRead ? files.input : null,
|
|
1796
|
+
maxSetMb: this.#limits.maxMb
|
|
1797
|
+
});
|
|
1756
1798
|
if (!output.paths.length && Object.keys(output.hashes).length) await this.#warn({ message: "Kept only the hashes of this generation: its output is too large to keep" });
|
|
1757
1799
|
await this.#generations.add({
|
|
1758
1800
|
jobId,
|
|
1759
1801
|
output,
|
|
1760
|
-
disk
|
|
1802
|
+
disk,
|
|
1803
|
+
inputBytes
|
|
1761
1804
|
});
|
|
1762
1805
|
await this.#logCommand("generate", `${activePlugins.length} plugin${activePlugins.length === 1 ? "" : "s"}, ${this.#permissions.allowWrite ? "written to disk" : "in memory"}${studioInput !== void 0 ? ", from a Studio spec" : ""}`);
|
|
1763
1806
|
return {
|
|
@@ -1809,10 +1852,30 @@ var Agent = class extends RpcTarget {
|
|
|
1809
1852
|
return refuse(getErrorMessage(error));
|
|
1810
1853
|
}
|
|
1811
1854
|
}
|
|
1855
|
+
/**
|
|
1856
|
+
* Returns the Kubb AST a kept job parsed its spec into. Refused without `allowRead`.
|
|
1857
|
+
*/
|
|
1858
|
+
async readInput(input) {
|
|
1859
|
+
this.#assertConnected();
|
|
1860
|
+
if (!this.#permissions.allowRead) return this.#refuse({
|
|
1861
|
+
message: READ_NOT_ALLOWED_MESSAGE,
|
|
1862
|
+
permission: "allowRead"
|
|
1863
|
+
});
|
|
1864
|
+
if (typeof input.jobId !== "string" || !input.jobId) return this.#refuse({ message: "The request must name a job" });
|
|
1865
|
+
const generation = await this.#generations.get(input.jobId);
|
|
1866
|
+
if (!generation) return this.#refuse({ message: GENERATION_GONE_MESSAGE });
|
|
1867
|
+
const kept = generation.inputBytes ? await this.#generations.readInput(input.jobId) : void 0;
|
|
1868
|
+
if (!kept) return this.#refuse({ message: NO_INPUT_MESSAGE });
|
|
1869
|
+
await this.#logCommand("readInput", "read the API input");
|
|
1870
|
+
return { input: kept };
|
|
1871
|
+
}
|
|
1872
|
+
/**
|
|
1873
|
+
* Returns the requested files of a kept job, one page of lines at a time. Refused without `allowRead`.
|
|
1874
|
+
*/
|
|
1812
1875
|
async readFiles(input) {
|
|
1813
1876
|
this.#assertConnected();
|
|
1814
1877
|
if (!this.#permissions.allowRead) return this.#refuse({
|
|
1815
|
-
message:
|
|
1878
|
+
message: READ_NOT_ALLOWED_MESSAGE,
|
|
1816
1879
|
permission: "allowRead"
|
|
1817
1880
|
});
|
|
1818
1881
|
if (!Array.isArray(input.paths) || typeof input.jobId !== "string" || !input.jobId) return this.#refuse({ message: "The request must name a job and carry paths" });
|