@kubb/studio 5.11.6 → 5.12.1
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 +128 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +125 -9
- package/dist/index.js.map +1 -1
- package/dist/{protocol-dCzUP4dH.d.ts → protocol-CG1bPO_H.d.cts} +28 -21
- package/dist/{protocol-dCzUP4dH.d.cts → protocol-CG1bPO_H.d.ts} +28 -21
- package/dist/protocol.cjs +1 -0
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +1 -1
- package/dist/protocol.d.ts +1 -1
- package/dist/protocol.js +1 -0
- package/dist/protocol.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as PublishedSnapshot, G as SnapshotUploadMetadata, O as InstalledExtensions, a as AgentConnectInfo, c as AgentPermissions, d as ConfigEditOutcome, s as AgentPermission, u as ConfigEdit } from "./protocol-
|
|
1
|
+
import { F as PublishedSnapshot, G as SnapshotUploadMetadata, O as InstalledExtensions, a as AgentConnectInfo, c as AgentPermissions, d as ConfigEditOutcome, s as AgentPermission, u as ConfigEdit } from "./protocol-CG1bPO_H.cjs";
|
|
2
2
|
import { Config, Hookable, KubbHooks } from "@kubb/core";
|
|
3
3
|
//#region src/connect.d.ts
|
|
4
4
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as PublishedSnapshot, G as SnapshotUploadMetadata, O as InstalledExtensions, a as AgentConnectInfo, c as AgentPermissions, d as ConfigEditOutcome, s as AgentPermission, u as ConfigEdit } from "./protocol-
|
|
1
|
+
import { F as PublishedSnapshot, G as SnapshotUploadMetadata, O as InstalledExtensions, a as AgentConnectInfo, c as AgentPermissions, d as ConfigEditOutcome, s as AgentPermission, u as ConfigEdit } from "./protocol-CG1bPO_H.js";
|
|
2
2
|
import { Config, Hookable, KubbHooks } from "@kubb/core";
|
|
3
3
|
//#region src/connect.d.ts
|
|
4
4
|
/**
|
package/dist/index.js
CHANGED
|
@@ -6,14 +6,19 @@ import path, { dirname, isAbsolute, join, relative, resolve, sep } from "node:pa
|
|
|
6
6
|
import process$1 from "node:process";
|
|
7
7
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
8
8
|
import { pathToFileURL } from "node:url";
|
|
9
|
+
import { Readable, Transform } from "node:stream";
|
|
9
10
|
import { existsSync } from "node:fs";
|
|
10
11
|
import { mkdir, mkdir as mkdir$1, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
11
|
-
import { Diagnostics, Hookable, cacheStorage, createKubb, fsStorage, getInputKind, isPackageName, readInstalledPackages, resolveCacheDir, resolveMeta } from "@kubb/core";
|
|
12
|
+
import { Diagnostics, Hookable, cacheStorage, checkoutGitInput, createKubb, fsStorage, getInputKind, isPackageName, isPublicAddress, readInstalledPackages, resolveCacheDir, resolveMeta } from "@kubb/core";
|
|
12
13
|
import { RpcTarget, newWebSocketRpcSession } from "capnweb";
|
|
13
14
|
import { detectCodeFormat, parseExpression, parseModule } from "magicast";
|
|
14
15
|
import { structuredPatch } from "diff";
|
|
15
16
|
import { stripVTControlCharacters } from "node:util";
|
|
16
17
|
import { ast } from "@kubb/ast";
|
|
18
|
+
import dns from "node:dns";
|
|
19
|
+
import http from "node:http";
|
|
20
|
+
import https from "node:https";
|
|
21
|
+
import net from "node:net";
|
|
17
22
|
import { ofetch } from "ofetch";
|
|
18
23
|
import { gzipSync } from "node:zlib";
|
|
19
24
|
//#endregion
|
|
@@ -196,7 +201,7 @@ function getElapsedMs(hrStart) {
|
|
|
196
201
|
}
|
|
197
202
|
//#endregion
|
|
198
203
|
//#region package.json
|
|
199
|
-
var version = "5.
|
|
204
|
+
var version = "5.12.1";
|
|
200
205
|
//#endregion
|
|
201
206
|
//#region src/resolveConfig.ts
|
|
202
207
|
/**
|
|
@@ -1842,6 +1847,106 @@ function createGenerationStream(hooks, jobId) {
|
|
|
1842
1847
|
};
|
|
1843
1848
|
}
|
|
1844
1849
|
//#endregion
|
|
1850
|
+
//#region src/publicFetch.ts
|
|
1851
|
+
const MAX_REDIRECTS = 5;
|
|
1852
|
+
const MAX_BYTES = 52428800;
|
|
1853
|
+
const REDIRECTS = /* @__PURE__ */ new Set([
|
|
1854
|
+
301,
|
|
1855
|
+
302,
|
|
1856
|
+
303,
|
|
1857
|
+
307,
|
|
1858
|
+
308
|
|
1859
|
+
]);
|
|
1860
|
+
const NO_BODY = /* @__PURE__ */ new Set([
|
|
1861
|
+
204,
|
|
1862
|
+
205,
|
|
1863
|
+
304
|
|
1864
|
+
]);
|
|
1865
|
+
function notPublic(host) {
|
|
1866
|
+
return /* @__PURE__ */ new Error(`${host} is not a public address, so a managed agent does not fetch from it`);
|
|
1867
|
+
}
|
|
1868
|
+
function createLookup(blocked) {
|
|
1869
|
+
return (hostname, options, callback) => {
|
|
1870
|
+
dns.lookup(hostname, {
|
|
1871
|
+
...options,
|
|
1872
|
+
all: true
|
|
1873
|
+
}, (error, addresses) => {
|
|
1874
|
+
if (error) return callback(error, "", 0);
|
|
1875
|
+
const found = addresses;
|
|
1876
|
+
if (!found.length || found.some(({ address }) => !isPublicAddress(address, blocked))) return callback(notPublic(hostname), "", 0);
|
|
1877
|
+
return options.all ? callback(null, found) : callback(null, found[0].address, found[0].family);
|
|
1878
|
+
});
|
|
1879
|
+
};
|
|
1880
|
+
}
|
|
1881
|
+
function request({ url, blocked, signal }) {
|
|
1882
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") return Promise.reject(/* @__PURE__ */ new Error(`Only http and https URLs are fetched, not ${url.protocol}`));
|
|
1883
|
+
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
1884
|
+
if (net.isIP(host) && !isPublicAddress(host, blocked)) return Promise.reject(notPublic(host));
|
|
1885
|
+
return new Promise((resolve, reject) => {
|
|
1886
|
+
const req = (url.protocol === "https:" ? https.request : http.request)(url, {
|
|
1887
|
+
method: "GET",
|
|
1888
|
+
lookup: createLookup(blocked),
|
|
1889
|
+
signal: signal ?? void 0,
|
|
1890
|
+
headers: { "accept-encoding": "identity" }
|
|
1891
|
+
}, (res) => {
|
|
1892
|
+
const headers = new Headers();
|
|
1893
|
+
for (const [key, value] of Object.entries(res.headers)) for (const item of [value].flat()) if (item !== void 0) headers.append(key, item);
|
|
1894
|
+
let total = 0;
|
|
1895
|
+
const limit = new Transform({ transform(chunk, _encoding, done) {
|
|
1896
|
+
total += chunk.length;
|
|
1897
|
+
done(total > MAX_BYTES ? /* @__PURE__ */ new Error("The response is larger than 50 MB") : null, chunk);
|
|
1898
|
+
} });
|
|
1899
|
+
res.on("error", (error) => limit.destroy(error));
|
|
1900
|
+
res.pipe(limit);
|
|
1901
|
+
const body = NO_BODY.has(res.statusCode ?? 0) ? null : Readable.toWeb(limit);
|
|
1902
|
+
resolve(new Response(body, {
|
|
1903
|
+
status: res.statusCode,
|
|
1904
|
+
statusText: res.statusMessage,
|
|
1905
|
+
headers
|
|
1906
|
+
}));
|
|
1907
|
+
});
|
|
1908
|
+
req.on("error", reject);
|
|
1909
|
+
req.end();
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
/**
|
|
1913
|
+
* Builds a `fetch` that only reaches addresses `blocked` does not list. It follows redirects itself
|
|
1914
|
+
* and checks every hop, and takes GET requests only, since that is all a spec load needs.
|
|
1915
|
+
*/
|
|
1916
|
+
function createPublicFetch(blocked) {
|
|
1917
|
+
const publicFetch = async (input, init) => {
|
|
1918
|
+
if (typeof input !== "string" && !(input instanceof URL)) throw new TypeError("A managed agent fetches by URL only");
|
|
1919
|
+
if (init?.method && init.method.toUpperCase() !== "GET") throw new TypeError("A managed agent only sends GET requests");
|
|
1920
|
+
let url = new URL(input);
|
|
1921
|
+
for (let hop = 0; hop <= MAX_REDIRECTS; hop++) {
|
|
1922
|
+
const response = await request({
|
|
1923
|
+
url,
|
|
1924
|
+
blocked,
|
|
1925
|
+
signal: init?.signal
|
|
1926
|
+
});
|
|
1927
|
+
const location = response.headers.get("location");
|
|
1928
|
+
if (!REDIRECTS.has(response.status) || !location) return response;
|
|
1929
|
+
await response.body?.cancel();
|
|
1930
|
+
url = new URL(location, url);
|
|
1931
|
+
}
|
|
1932
|
+
throw new Error(`Stopped after ${MAX_REDIRECTS} redirects from ${String(input)}`);
|
|
1933
|
+
};
|
|
1934
|
+
return publicFetch;
|
|
1935
|
+
}
|
|
1936
|
+
/**
|
|
1937
|
+
* Runs `run` with the global `fetch` limited to public addresses, then puts the original back.
|
|
1938
|
+
* A managed agent runs one job at a time, so nothing else shares the window.
|
|
1939
|
+
*/
|
|
1940
|
+
async function withPublicFetch(run) {
|
|
1941
|
+
const original = globalThis.fetch;
|
|
1942
|
+
globalThis.fetch = createPublicFetch();
|
|
1943
|
+
try {
|
|
1944
|
+
return await run();
|
|
1945
|
+
} finally {
|
|
1946
|
+
globalThis.fetch = original;
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
//#endregion
|
|
1845
1950
|
//#region src/url.ts
|
|
1846
1951
|
/**
|
|
1847
1952
|
* Hosted Kubb Studio URL, used when a host passes none.
|
|
@@ -1878,6 +1983,11 @@ const OPEN_TIMEOUT_MS = 5e3;
|
|
|
1878
1983
|
const MAX_RETRY_DELAY_MS = 3e4;
|
|
1879
1984
|
const DISK_SNAPSHOT_MAX_FILES = 1e4;
|
|
1880
1985
|
const SANDBOX_GENERATION_TTL_MS = 9e5;
|
|
1986
|
+
const MANAGED_INPUT_KINDS = /* @__PURE__ */ new Set([
|
|
1987
|
+
"inline",
|
|
1988
|
+
"url",
|
|
1989
|
+
"git"
|
|
1990
|
+
]);
|
|
1881
1991
|
/** Extensions `kubb` ships with, so they count as installed without being a direct dependency. */
|
|
1882
1992
|
const BUILT_IN_PACKAGES = [
|
|
1883
1993
|
"@kubb/adapter-oas",
|
|
@@ -1964,6 +2074,9 @@ var Agent = class extends RpcTarget {
|
|
|
1964
2074
|
get #sandbox() {
|
|
1965
2075
|
return this.#session.info?.sandbox === true;
|
|
1966
2076
|
}
|
|
2077
|
+
get #managed() {
|
|
2078
|
+
return this.#session.info?.managed === true;
|
|
2079
|
+
}
|
|
1967
2080
|
get #permissions() {
|
|
1968
2081
|
const { permissions } = this.#options;
|
|
1969
2082
|
return this.#sandbox ? {
|
|
@@ -2159,8 +2272,9 @@ var Agent = class extends RpcTarget {
|
|
|
2159
2272
|
*/
|
|
2160
2273
|
async #generate({ input, root, outputRoot, signal }) {
|
|
2161
2274
|
const { jobId, config: patch } = input;
|
|
2162
|
-
const studioInput = this.#sandbox ? patch?.input : void 0;
|
|
2275
|
+
const studioInput = this.#sandbox || this.#managed ? patch?.input : void 0;
|
|
2163
2276
|
if (this.#sandbox && (typeof studioInput !== "string" || !studioInput.trim() || getInputKind(studioInput) !== "inline")) return this.#refuse({ message: AgentMessage.SANDBOX_INPUT_ONLY });
|
|
2277
|
+
if (this.#managed && studioInput !== void 0 && !MANAGED_INPUT_KINDS.has(getInputKind(studioInput))) return this.#refuse({ message: AgentMessage.MANAGED_INPUT_KIND });
|
|
2164
2278
|
const [configs, extensions] = await Promise.all([this.#options.loadConfigs(), this.#installedExtensions()]);
|
|
2165
2279
|
const config = pickConfig(configs, patch?.config);
|
|
2166
2280
|
if (!config) return this.#refuse({ message: AgentMessage.CONFIG_ENTRY_NOT_FOUND });
|
|
@@ -2189,12 +2303,13 @@ var Agent = class extends RpcTarget {
|
|
|
2189
2303
|
throw error;
|
|
2190
2304
|
});
|
|
2191
2305
|
const activePlugins = plugins ?? config.plugins;
|
|
2192
|
-
if (patch?.input && !this.#sandbox) await emit(this.#options.hooks, "kubb:warn", { message: "Ignored the spec from Studio: generating from a Studio spec is only available to a sandbox agent" });
|
|
2193
|
-
const
|
|
2306
|
+
if (patch?.input && !this.#sandbox && !this.#managed) await emit(this.#options.hooks, "kubb:warn", { message: "Ignored the spec from Studio: generating from a Studio spec is only available to a sandbox or managed agent" });
|
|
2307
|
+
const checkout = this.#managed && studioInput !== void 0 && getInputKind(studioInput) === "git" ? await checkoutGitInput(studioInput, signal, { publicOnly: true }).catch((error) => this.#refuse({ message: getErrorMessage(error) })) : void 0;
|
|
2308
|
+
const run = () => generate({
|
|
2194
2309
|
config: {
|
|
2195
2310
|
...config,
|
|
2196
2311
|
root,
|
|
2197
|
-
input: studioInput ?? config.input,
|
|
2312
|
+
input: checkout?.path ?? studioInput ?? config.input,
|
|
2198
2313
|
storage: outputRoot ? stagingStorage({
|
|
2199
2314
|
root,
|
|
2200
2315
|
directory: outputRoot
|
|
@@ -2206,11 +2321,12 @@ var Agent = class extends RpcTarget {
|
|
|
2206
2321
|
hooks: this.#options.hooks,
|
|
2207
2322
|
signal,
|
|
2208
2323
|
allowExec: this.#permissions.allowWrite && this.#permissions.allowExec
|
|
2209
|
-
})
|
|
2324
|
+
});
|
|
2325
|
+
const files = await (this.#managed ? withPublicFetch(run) : run()).catch(async (error) => {
|
|
2210
2326
|
await this.#generations.drop(jobId);
|
|
2211
2327
|
await this.#logCommand("generate", getErrorMessage(error), input.requestedBy, true);
|
|
2212
2328
|
throw error;
|
|
2213
|
-
});
|
|
2329
|
+
}).finally(() => checkout?.dispose());
|
|
2214
2330
|
const output = await this.#generations.keep({
|
|
2215
2331
|
jobId,
|
|
2216
2332
|
files,
|
|
@@ -2478,7 +2594,7 @@ function reportedInput(input) {
|
|
|
2478
2594
|
if (typeof input !== "string") return void 0;
|
|
2479
2595
|
const kind = getInputKind(input);
|
|
2480
2596
|
if (kind === "inline") return void 0;
|
|
2481
|
-
if (kind !== "url") return input;
|
|
2597
|
+
if (kind !== "url" && kind !== "git" || !URL.canParse(input)) return input;
|
|
2482
2598
|
const url = new URL(input);
|
|
2483
2599
|
url.username = "";
|
|
2484
2600
|
url.password = "";
|