@kubb/studio 5.6.1 → 5.6.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 +84 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -13
- package/dist/index.js +85 -99
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -220,28 +220,18 @@ type CreateSnapshotOptions = Omit<SnapshotUploadMetadata, 'hashes' | 'peerDepend
|
|
|
220
220
|
*/
|
|
221
221
|
apiKey: string;
|
|
222
222
|
/**
|
|
223
|
-
* The project's Kubb config
|
|
224
|
-
* formatter, the linter, and `output.postGenerate`.
|
|
223
|
+
* The project's Kubb config, generated like `kubb generate`: formatter, linter, and `output.postGenerate` included.
|
|
225
224
|
*/
|
|
226
225
|
config: Config;
|
|
227
226
|
hooks?: Hookable<KubbHooks>;
|
|
228
227
|
signal?: AbortSignal;
|
|
229
228
|
};
|
|
230
229
|
/**
|
|
231
|
-
* Generates the project, packs it as an npm tarball, and publishes it to Studio in one
|
|
232
|
-
* `POST /api/snapshots` request.
|
|
230
|
+
* Generates the project, packs it as an npm tarball, and publishes it to Studio in one `POST /api/snapshots` request.
|
|
233
231
|
*
|
|
234
232
|
* @example
|
|
235
233
|
* ```ts
|
|
236
|
-
* const
|
|
237
|
-
* apiKey: process.env.KUBB_TOKEN!,
|
|
238
|
-
* config,
|
|
239
|
-
* id: 'gh:123:pr-4',
|
|
240
|
-
* name: 'acme/api#4',
|
|
241
|
-
* packageName: '@acme/api',
|
|
242
|
-
* version: '1.0.0',
|
|
243
|
-
* })
|
|
244
|
-
* console.log(snapshot.url, snapshot.changes)
|
|
234
|
+
* const { url } = await createSnapshot({ apiKey: process.env.KUBB_TOKEN!, config, id: 'gh:123:pr-4', name: 'acme/api#4', packageName: '@acme/api', version: '1.0.0' })
|
|
245
235
|
* ```
|
|
246
236
|
*/
|
|
247
237
|
export declare function createSnapshot({ studioUrl, apiKey, config, hooks, signal, ...metadata }: CreateSnapshotOptions): Promise<PublishedSnapshot>;
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ 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";
|
|
6
6
|
import { tmpdir } from "node:os";
|
|
7
|
-
import path, { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
7
|
+
import path, { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
8
8
|
import process$1 from "node:process";
|
|
9
9
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
10
10
|
import { pathToFileURL } from "node:url";
|
|
@@ -192,7 +192,7 @@ function getElapsedMs(hrStart) {
|
|
|
192
192
|
}
|
|
193
193
|
//#endregion
|
|
194
194
|
//#region package.json
|
|
195
|
-
var version = "5.6.
|
|
195
|
+
var version = "5.6.2";
|
|
196
196
|
//#endregion
|
|
197
197
|
//#region src/resolveConfig.ts
|
|
198
198
|
/**
|
|
@@ -1034,19 +1034,21 @@ async function generate({ config, hooks, signal, allowExec }) {
|
|
|
1034
1034
|
lint: false,
|
|
1035
1035
|
postGenerate: []
|
|
1036
1036
|
};
|
|
1037
|
-
const
|
|
1037
|
+
const kubb = createKubb({
|
|
1038
1038
|
...config,
|
|
1039
1039
|
output
|
|
1040
1040
|
}, {
|
|
1041
1041
|
hooks,
|
|
1042
1042
|
signal
|
|
1043
|
-
})
|
|
1043
|
+
});
|
|
1044
|
+
const result = await kubb.generate();
|
|
1044
1045
|
if (!result.success) throw generationFailure(result.diagnostics);
|
|
1046
|
+
const { storage, root } = kubb.config;
|
|
1045
1047
|
return {
|
|
1046
|
-
storage
|
|
1047
|
-
root
|
|
1048
|
+
storage,
|
|
1049
|
+
root,
|
|
1048
1050
|
paths: new Set(result.files.map((file) => relativeStoragePath({
|
|
1049
|
-
root
|
|
1051
|
+
root,
|
|
1050
1052
|
filePath: file.path
|
|
1051
1053
|
})))
|
|
1052
1054
|
};
|
|
@@ -1991,29 +1993,24 @@ const gzipAsync = promisify(gzip);
|
|
|
1991
1993
|
const UPLOAD_TIMEOUT_MS = 12e4;
|
|
1992
1994
|
const BUNDLED_DEPENDENCIES = ["@kubb/plugin-barrel"];
|
|
1993
1995
|
/**
|
|
1994
|
-
* Maps a generated file
|
|
1995
|
-
* `src`/`dist` segment and any `..`/empty path segment so a crafted file name cannot escape the
|
|
1996
|
-
* `package/` root.
|
|
1996
|
+
* Maps a generated file to its path in the package, from its `src`/`dist` segment on, without `..` parts that could escape it.
|
|
1997
1997
|
*/
|
|
1998
1998
|
function packagePath(filePath) {
|
|
1999
1999
|
const normalized = filePath.replaceAll("\\", "/");
|
|
2000
|
-
return
|
|
2000
|
+
return (normalized.match(/\/(?:src|dist)\/.*$/)?.[0] ?? normalized).split("/").filter((part) => part && part !== "." && part !== "..").join("/");
|
|
2001
2001
|
}
|
|
2002
2002
|
/**
|
|
2003
|
-
* Splits a
|
|
2004
|
-
* fit, the 155-byte USTAR `prefix` field that extends it. Throws rather than silently truncating
|
|
2005
|
-
* a path the format cannot address (max 256 bytes: 100 name + 1 separator + 155 prefix).
|
|
2003
|
+
* Splits a tar path into the 100-byte USTAR `name` and the 155-byte `prefix`, and throws for a path that fits neither.
|
|
2006
2004
|
*/
|
|
2007
2005
|
function splitEntryPath(path) {
|
|
2008
|
-
if (Buffer.byteLength(path
|
|
2006
|
+
if (Buffer.byteLength(path) <= 100) return {
|
|
2009
2007
|
name: path,
|
|
2010
2008
|
prefix: ""
|
|
2011
2009
|
};
|
|
2012
|
-
for (let i = path.
|
|
2013
|
-
if (path[i] !== "/") continue;
|
|
2010
|
+
for (let i = path.lastIndexOf("/"); i > 0; i = path.lastIndexOf("/", i - 1)) {
|
|
2014
2011
|
const prefix = path.slice(0, i);
|
|
2015
2012
|
const name = path.slice(i + 1);
|
|
2016
|
-
if (Buffer.byteLength(prefix
|
|
2013
|
+
if (Buffer.byteLength(prefix) <= 155 && Buffer.byteLength(name) <= 100) return {
|
|
2017
2014
|
name,
|
|
2018
2015
|
prefix
|
|
2019
2016
|
};
|
|
@@ -2023,21 +2020,23 @@ function splitEntryPath(path) {
|
|
|
2023
2020
|
function header(path, size) {
|
|
2024
2021
|
const { name, prefix } = splitEntryPath(path);
|
|
2025
2022
|
const value = Buffer.alloc(512);
|
|
2026
|
-
value.write(name
|
|
2027
|
-
value.write("0000644\0", 100
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2023
|
+
value.write(name);
|
|
2024
|
+
value.write("0000644\0", 100);
|
|
2025
|
+
for (const offset of [
|
|
2026
|
+
108,
|
|
2027
|
+
116,
|
|
2028
|
+
265,
|
|
2029
|
+
297
|
|
2030
|
+
]) value.write("0000000\0", offset);
|
|
2031
|
+
value.write(`${size.toString(8).padStart(11, "0")}\0`, 124);
|
|
2032
|
+
value.write("03560116604\0", 136);
|
|
2032
2033
|
value.fill(32, 148, 156);
|
|
2033
|
-
value.write("0", 156
|
|
2034
|
-
value.write("ustar\0", 257
|
|
2035
|
-
value.write("00", 263
|
|
2036
|
-
value.write(
|
|
2037
|
-
value.
|
|
2038
|
-
value.write(
|
|
2039
|
-
const checksum = [...value].reduce((sum, byte) => sum + byte, 0);
|
|
2040
|
-
value.write(`${checksum.toString(8).padStart(6, "0")}\0 `, 148, "ascii");
|
|
2034
|
+
value.write("0", 156);
|
|
2035
|
+
value.write("ustar\0", 257);
|
|
2036
|
+
value.write("00", 263);
|
|
2037
|
+
value.write(prefix, 345);
|
|
2038
|
+
const checksum = value.reduce((sum, byte) => sum + byte, 0);
|
|
2039
|
+
value.write(`${checksum.toString(8).padStart(6, "0")}\0 `, 148);
|
|
2041
2040
|
return value;
|
|
2042
2041
|
}
|
|
2043
2042
|
/**
|
|
@@ -2045,31 +2044,29 @@ function header(path, size) {
|
|
|
2045
2044
|
* generated sources, a `tsdown`-built `dist/` (esm + cjs), and a `package.json` manifest.
|
|
2046
2045
|
*/
|
|
2047
2046
|
async function createSnapshotPackage({ files, packageInfo }) {
|
|
2047
|
+
const sources = /* @__PURE__ */ new Map();
|
|
2048
|
+
for (const [name, content] of Object.entries(files)) {
|
|
2049
|
+
const path = packagePath(name);
|
|
2050
|
+
const owner = sources.get(path)?.name;
|
|
2051
|
+
if (owner) throw new Error(`Snapshot has two generated files that sanitize to the same path "package/${path}": "${owner}" and "${name}"`);
|
|
2052
|
+
sources.set(path, {
|
|
2053
|
+
name,
|
|
2054
|
+
content
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2048
2057
|
const root = await mkdtemp(join(tmpdir(), "kubb-snapshot-"));
|
|
2049
2058
|
const dist = join(root, "dist");
|
|
2050
|
-
const resolvedPaths = Object.entries(files).map(([name, content]) => ({
|
|
2051
|
-
name,
|
|
2052
|
-
content,
|
|
2053
|
-
target: packagePath(name)
|
|
2054
|
-
}));
|
|
2055
|
-
const targetOwners = /* @__PURE__ */ new Map();
|
|
2056
|
-
for (const { name, target } of resolvedPaths) {
|
|
2057
|
-
const owner = targetOwners.get(target);
|
|
2058
|
-
if (owner) throw new Error(`Snapshot has two generated files that sanitize to the same path "${target}": "${owner}" and "${name}"`);
|
|
2059
|
-
targetOwners.set(target, name);
|
|
2060
|
-
}
|
|
2061
2059
|
try {
|
|
2062
2060
|
await mkdir(dist);
|
|
2063
|
-
await Promise.all(
|
|
2064
|
-
|
|
2065
|
-
await
|
|
2066
|
-
await writeFile(path, content);
|
|
2061
|
+
await Promise.all([...sources].map(async ([path, { content }]) => {
|
|
2062
|
+
await mkdir(dirname(join(root, path)), { recursive: true });
|
|
2063
|
+
await writeFile(join(root, path), content);
|
|
2067
2064
|
}));
|
|
2068
|
-
const
|
|
2069
|
-
if (
|
|
2065
|
+
const entry = [...sources.keys()].filter((path) => /\.(?:[cm]?[jt]sx?)$/.test(path)).map((path) => join(root, path));
|
|
2066
|
+
if (entry.length) {
|
|
2070
2067
|
const { build } = await import("tsdown");
|
|
2071
2068
|
await build({
|
|
2072
|
-
entry
|
|
2069
|
+
entry,
|
|
2073
2070
|
outDir: dist,
|
|
2074
2071
|
format: ["esm", "cjs"],
|
|
2075
2072
|
dts: false,
|
|
@@ -2080,38 +2077,38 @@ async function createSnapshotPackage({ files, packageInfo }) {
|
|
|
2080
2077
|
fixedExtension: true
|
|
2081
2078
|
});
|
|
2082
2079
|
}
|
|
2083
|
-
const
|
|
2084
|
-
const
|
|
2085
|
-
const
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
...barrelExport,
|
|
2101
|
-
"./*": {
|
|
2102
|
-
import: "./dist/*.mjs",
|
|
2103
|
-
require: "./dist/*.cjs"
|
|
2104
|
-
}
|
|
2080
|
+
const built = await fsStorage().readKeys(dist);
|
|
2081
|
+
const hasBarrel = built.includes("index.mjs") && built.includes("index.cjs");
|
|
2082
|
+
const manifest = {
|
|
2083
|
+
...packageInfo,
|
|
2084
|
+
type: "module",
|
|
2085
|
+
...hasBarrel ? {
|
|
2086
|
+
main: "./dist/index.cjs",
|
|
2087
|
+
module: "./dist/index.mjs"
|
|
2088
|
+
} : {},
|
|
2089
|
+
exports: {
|
|
2090
|
+
...hasBarrel ? { ".": {
|
|
2091
|
+
import: "./dist/index.mjs",
|
|
2092
|
+
require: "./dist/index.cjs"
|
|
2093
|
+
} } : {},
|
|
2094
|
+
"./*": {
|
|
2095
|
+
import: "./dist/*.mjs",
|
|
2096
|
+
require: "./dist/*.cjs"
|
|
2105
2097
|
}
|
|
2106
|
-
}
|
|
2107
|
-
...Object.fromEntries(resolvedPaths.map(({ content, target }) => [target, content])),
|
|
2108
|
-
...Object.fromEntries(builtEntries)
|
|
2098
|
+
}
|
|
2109
2099
|
};
|
|
2110
|
-
const chunks = [
|
|
2111
|
-
|
|
2100
|
+
const chunks = [...new Map([
|
|
2101
|
+
["package.json", JSON.stringify(manifest, null, 2)],
|
|
2102
|
+
...[...sources].map(([path, { content }]) => [path, content]),
|
|
2103
|
+
...await Promise.all(built.map(async (key) => [`dist/${key}`, await readFile(join(dist, key), "utf8")]))
|
|
2104
|
+
])].flatMap(([path, content]) => {
|
|
2112
2105
|
const bytes = Buffer.from(content);
|
|
2113
|
-
|
|
2114
|
-
|
|
2106
|
+
return [
|
|
2107
|
+
header(`package/${path}`, bytes.length),
|
|
2108
|
+
bytes,
|
|
2109
|
+
Buffer.alloc((512 - bytes.length % 512) % 512)
|
|
2110
|
+
];
|
|
2111
|
+
});
|
|
2115
2112
|
return await gzipAsync(Buffer.concat([...chunks, Buffer.alloc(1024)]));
|
|
2116
2113
|
} finally {
|
|
2117
2114
|
await rm(root, {
|
|
@@ -2120,25 +2117,12 @@ async function createSnapshotPackage({ files, packageInfo }) {
|
|
|
2120
2117
|
});
|
|
2121
2118
|
}
|
|
2122
2119
|
}
|
|
2123
|
-
function failureMessage({ status, _data }) {
|
|
2124
|
-
const upgrade = _data?.data?.upgradeUrl ? ` Upgrade at ${_data.data.upgradeUrl}.` : "";
|
|
2125
|
-
return `Kubb Studio refused the snapshot (status ${status})${_data?.message ? `: ${_data.message}` : ""}.${upgrade}`;
|
|
2126
|
-
}
|
|
2127
2120
|
/**
|
|
2128
|
-
* Generates the project, packs it as an npm tarball, and publishes it to Studio in one
|
|
2129
|
-
* `POST /api/snapshots` request.
|
|
2121
|
+
* Generates the project, packs it as an npm tarball, and publishes it to Studio in one `POST /api/snapshots` request.
|
|
2130
2122
|
*
|
|
2131
2123
|
* @example
|
|
2132
2124
|
* ```ts
|
|
2133
|
-
* const
|
|
2134
|
-
* apiKey: process.env.KUBB_TOKEN!,
|
|
2135
|
-
* config,
|
|
2136
|
-
* id: 'gh:123:pr-4',
|
|
2137
|
-
* name: 'acme/api#4',
|
|
2138
|
-
* packageName: '@acme/api',
|
|
2139
|
-
* version: '1.0.0',
|
|
2140
|
-
* })
|
|
2141
|
-
* console.log(snapshot.url, snapshot.changes)
|
|
2125
|
+
* const { url } = await createSnapshot({ apiKey: process.env.KUBB_TOKEN!, config, id: 'gh:123:pr-4', name: 'acme/api#4', packageName: '@acme/api', version: '1.0.0' })
|
|
2142
2126
|
* ```
|
|
2143
2127
|
*/
|
|
2144
2128
|
async function createSnapshot({ studioUrl = defaultStudioUrl, apiKey, config, hooks, signal, ...metadata }) {
|
|
@@ -2178,7 +2162,7 @@ async function createSnapshot({ studioUrl = defaultStudioUrl, apiKey, config, ho
|
|
|
2178
2162
|
}));
|
|
2179
2163
|
body.set("tarball", new Blob([new Uint8Array(bytes)], { type: "application/gzip" }), "snapshot.tgz");
|
|
2180
2164
|
const timeout = AbortSignal.timeout(UPLOAD_TIMEOUT_MS);
|
|
2181
|
-
const
|
|
2165
|
+
const { ok, status, _data } = await ofetch.raw(url.href, {
|
|
2182
2166
|
method: "POST",
|
|
2183
2167
|
headers: { "x-api-key": apiKey },
|
|
2184
2168
|
body,
|
|
@@ -2186,10 +2170,12 @@ async function createSnapshot({ studioUrl = defaultStudioUrl, apiKey, config, ho
|
|
|
2186
2170
|
signal: signal ? AbortSignal.any([signal, timeout]) : timeout,
|
|
2187
2171
|
ignoreResponseError: true
|
|
2188
2172
|
});
|
|
2189
|
-
if (!
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2173
|
+
if (!ok) {
|
|
2174
|
+
const upgrade = _data?.data?.upgradeUrl ? ` Upgrade at ${_data.data.upgradeUrl}.` : "";
|
|
2175
|
+
throw new Error(`Kubb Studio refused the snapshot (status ${status})${_data?.message ? `: ${_data.message}` : ""}.${upgrade}`);
|
|
2176
|
+
}
|
|
2177
|
+
if (!_data?.snapshot) throw new Error(`Kubb Studio returned no snapshot (status ${status})`);
|
|
2178
|
+
return _data.snapshot;
|
|
2193
2179
|
}
|
|
2194
2180
|
//#endregion
|
|
2195
2181
|
export { IncompatibleAgentError, InvalidAgentTokenError, PairingCanceledError, PairingDeniedError, PairingExpiredError, connectAgent, createSnapshot, defaultStudioUrl, pairAgent };
|