midsummer-sol 0.3.4 → 0.3.7
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/package.json +1 -1
- package/sol-mcp.js +201 -19
- package/sol.js +239 -31
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "midsummer-sol",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "Sol — agent-native version control (a new git). CLI, MCP server, and no-filesystem SDK.",
|
|
5
5
|
"bin": { "sol": "./sol.js", "sol-mcp": "./sol-mcp.js", "sol-secret-mcp": "./sol-secret-mcp.js" },
|
|
6
6
|
"main": "./index.js",
|
package/sol-mcp.js
CHANGED
|
@@ -3036,6 +3036,7 @@ __export(exports_lib, {
|
|
|
3036
3036
|
allLocalNodes: () => allLocalNodes,
|
|
3037
3037
|
addInclude: () => addInclude,
|
|
3038
3038
|
actor: () => actor,
|
|
3039
|
+
acquireLockAt: () => acquireLockAt,
|
|
3039
3040
|
acquireLock: () => acquireLock,
|
|
3040
3041
|
LazyStore: () => LazyStore,
|
|
3041
3042
|
DEFAULT_IGNORE: () => DEFAULT_IGNORE
|
|
@@ -3269,9 +3270,9 @@ function pidAlive(pid) {
|
|
|
3269
3270
|
return e?.code === "EPERM";
|
|
3270
3271
|
}
|
|
3271
3272
|
}
|
|
3272
|
-
function
|
|
3273
|
-
const
|
|
3274
|
-
const
|
|
3273
|
+
function acquireLockAt(lockFile, opts = {}) {
|
|
3274
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 15000);
|
|
3275
|
+
const onTimeout = opts.onTimeout ?? "die";
|
|
3275
3276
|
for (;; ) {
|
|
3276
3277
|
try {
|
|
3277
3278
|
writeFileSync5(lockFile, String(process.pid), { flag: "wx" });
|
|
@@ -3294,8 +3295,11 @@ function acquireLock() {
|
|
|
3294
3295
|
} catch {
|
|
3295
3296
|
continue;
|
|
3296
3297
|
}
|
|
3297
|
-
if (Date.now() > deadline)
|
|
3298
|
-
|
|
3298
|
+
if (Date.now() > deadline) {
|
|
3299
|
+
if (onTimeout === "undefined")
|
|
3300
|
+
return;
|
|
3301
|
+
die(opts.timeoutMsg ?? "repo is locked by another sol process (timed out)");
|
|
3302
|
+
}
|
|
3299
3303
|
sleepSync(25);
|
|
3300
3304
|
}
|
|
3301
3305
|
}
|
|
@@ -3311,6 +3315,9 @@ function acquireLock() {
|
|
|
3311
3315
|
process.on("exit", release);
|
|
3312
3316
|
return release;
|
|
3313
3317
|
}
|
|
3318
|
+
function acquireLock() {
|
|
3319
|
+
return acquireLockAt(join5(lockDir(), "lock"));
|
|
3320
|
+
}
|
|
3314
3321
|
function loadStore() {
|
|
3315
3322
|
return new LazyStore(objectsDir());
|
|
3316
3323
|
}
|
|
@@ -4156,9 +4163,12 @@ var init_lib = __esm(() => {
|
|
|
4156
4163
|
var exports_remote = {};
|
|
4157
4164
|
__export(exports_remote, {
|
|
4158
4165
|
writeBundle: () => writeBundle,
|
|
4166
|
+
splitLeafPacks: () => splitLeafPacks,
|
|
4159
4167
|
saveRemote: () => saveRemote,
|
|
4160
4168
|
remoteRefs: () => remoteRefs,
|
|
4161
4169
|
remotePushPack: () => remotePushPack,
|
|
4170
|
+
remotePushGiantLeaf: () => remotePushGiantLeaf,
|
|
4171
|
+
remotePushBlobs: () => remotePushBlobs,
|
|
4162
4172
|
remotePush: () => remotePush,
|
|
4163
4173
|
remotePromote: () => remotePromote,
|
|
4164
4174
|
remoteHead: () => remoteHead,
|
|
@@ -4182,12 +4192,13 @@ __export(exports_remote, {
|
|
|
4182
4192
|
loadRemote: () => loadRemote,
|
|
4183
4193
|
forksList: () => forksList,
|
|
4184
4194
|
forkMeta: () => forkMeta,
|
|
4195
|
+
classifyNodes: () => classifyNodes,
|
|
4185
4196
|
accessSet: () => accessSet,
|
|
4186
4197
|
accessGet: () => accessGet
|
|
4187
4198
|
});
|
|
4188
4199
|
import { appendFileSync as appendFileSync4, existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
|
|
4189
4200
|
import { join as join6 } from "node:path";
|
|
4190
|
-
import { gzipSync as gzipSync3 } from "node:zlib";
|
|
4201
|
+
import { gunzipSync as gunzipSync3, gzipSync as gzipSync3 } from "node:zlib";
|
|
4191
4202
|
async function call(cfg, token, path, init) {
|
|
4192
4203
|
const res = await fetch(endpoint(cfg, path), {
|
|
4193
4204
|
...init,
|
|
@@ -4197,6 +4208,147 @@ async function call(cfg, token, path, init) {
|
|
|
4197
4208
|
throw new Error(`remote ${path} -> ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
|
|
4198
4209
|
return res.json();
|
|
4199
4210
|
}
|
|
4211
|
+
function decodePackLine(line) {
|
|
4212
|
+
const map = JSON.parse(gunzipSync3(Buffer.from(line, "base64")).toString("utf8"));
|
|
4213
|
+
return Object.values(map);
|
|
4214
|
+
}
|
|
4215
|
+
async function exportStreaming(cfg, token) {
|
|
4216
|
+
const res = await fetch(endpoint(cfg, "/export?stream=1"), {
|
|
4217
|
+
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }
|
|
4218
|
+
});
|
|
4219
|
+
if (!res.ok)
|
|
4220
|
+
throw new Error(`remote /export -> ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
|
|
4221
|
+
if (!res.body)
|
|
4222
|
+
return res.json();
|
|
4223
|
+
const reader = res.body.getReader();
|
|
4224
|
+
const td = new TextDecoder;
|
|
4225
|
+
let buf = "";
|
|
4226
|
+
let header;
|
|
4227
|
+
const nodes = [];
|
|
4228
|
+
const consumeLine = (line) => {
|
|
4229
|
+
if (line === "")
|
|
4230
|
+
return;
|
|
4231
|
+
if (!header) {
|
|
4232
|
+
header = JSON.parse(line);
|
|
4233
|
+
if (Array.isArray(header.nodes))
|
|
4234
|
+
for (const n of header.nodes)
|
|
4235
|
+
nodes.push(n);
|
|
4236
|
+
return;
|
|
4237
|
+
}
|
|
4238
|
+
for (const n of decodePackLine(line))
|
|
4239
|
+
nodes.push(n);
|
|
4240
|
+
};
|
|
4241
|
+
for (;; ) {
|
|
4242
|
+
const { done, value } = await reader.read();
|
|
4243
|
+
if (value)
|
|
4244
|
+
buf += td.decode(value, { stream: true });
|
|
4245
|
+
let nl;
|
|
4246
|
+
while ((nl = buf.indexOf(`
|
|
4247
|
+
`)) >= 0) {
|
|
4248
|
+
consumeLine(buf.slice(0, nl));
|
|
4249
|
+
buf = buf.slice(nl + 1);
|
|
4250
|
+
}
|
|
4251
|
+
if (done)
|
|
4252
|
+
break;
|
|
4253
|
+
}
|
|
4254
|
+
buf += td.decode();
|
|
4255
|
+
if (buf.length)
|
|
4256
|
+
consumeLine(buf);
|
|
4257
|
+
if (!header)
|
|
4258
|
+
throw new Error("remote /export returned an empty stream");
|
|
4259
|
+
return { ...header, nodes };
|
|
4260
|
+
}
|
|
4261
|
+
function classifyNodes(nodes) {
|
|
4262
|
+
const trees = [];
|
|
4263
|
+
const leaves = [];
|
|
4264
|
+
let total = 0;
|
|
4265
|
+
for (const n of nodes) {
|
|
4266
|
+
total += nodeBytes(n);
|
|
4267
|
+
(n.kind === "tree" ? trees : leaves).push(n);
|
|
4268
|
+
}
|
|
4269
|
+
return { trees, leaves, total };
|
|
4270
|
+
}
|
|
4271
|
+
function splitLeafPacks(leaves, maxBytes) {
|
|
4272
|
+
const packs = [];
|
|
4273
|
+
let cur = [];
|
|
4274
|
+
let size = 0;
|
|
4275
|
+
for (const n of leaves) {
|
|
4276
|
+
const b = nodeBytes(n);
|
|
4277
|
+
if (cur.length && size + b > maxBytes) {
|
|
4278
|
+
packs.push(cur);
|
|
4279
|
+
cur = [];
|
|
4280
|
+
size = 0;
|
|
4281
|
+
}
|
|
4282
|
+
cur.push(n);
|
|
4283
|
+
size += b;
|
|
4284
|
+
}
|
|
4285
|
+
if (cur.length)
|
|
4286
|
+
packs.push(cur);
|
|
4287
|
+
return packs;
|
|
4288
|
+
}
|
|
4289
|
+
async function pool(tasks, limit) {
|
|
4290
|
+
const out = new Array(tasks.length);
|
|
4291
|
+
let next = 0;
|
|
4292
|
+
const worker = async () => {
|
|
4293
|
+
for (;; ) {
|
|
4294
|
+
const i = next++;
|
|
4295
|
+
if (i >= tasks.length)
|
|
4296
|
+
return;
|
|
4297
|
+
out[i] = await tasks[i]();
|
|
4298
|
+
}
|
|
4299
|
+
};
|
|
4300
|
+
await Promise.all(Array.from({ length: Math.min(limit, tasks.length) }, worker));
|
|
4301
|
+
return out;
|
|
4302
|
+
}
|
|
4303
|
+
async function retryTransient(fn, attempts = 5) {
|
|
4304
|
+
let last;
|
|
4305
|
+
for (let i = 0;i < attempts; i++) {
|
|
4306
|
+
try {
|
|
4307
|
+
return await fn();
|
|
4308
|
+
} catch (e) {
|
|
4309
|
+
last = e;
|
|
4310
|
+
const m = e instanceof Error ? e.message : String(e);
|
|
4311
|
+
if (!/-> 5dd|reset|fetch failed|network|ECONN|terminated|timeout/i.test(m))
|
|
4312
|
+
throw e;
|
|
4313
|
+
await new Promise((r) => setTimeout(r, 400 * (i + 1)));
|
|
4314
|
+
}
|
|
4315
|
+
}
|
|
4316
|
+
throw last;
|
|
4317
|
+
}
|
|
4318
|
+
function canonicalPackBytesClient(entries) {
|
|
4319
|
+
const sorted = [...entries].sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
|
|
4320
|
+
const obj = {};
|
|
4321
|
+
for (const [h, n] of sorted)
|
|
4322
|
+
obj[h] = n;
|
|
4323
|
+
return JSON.stringify(obj);
|
|
4324
|
+
}
|
|
4325
|
+
async function remotePushGiantLeaf(cfg, token, node) {
|
|
4326
|
+
const hash = hashNode(node);
|
|
4327
|
+
const body = canonicalPackBytesClient([[hash, node]]);
|
|
4328
|
+
const packId = hashString(body);
|
|
4329
|
+
const packBody = gzipSync3(Buffer.from(body, "utf8")).toString("base64");
|
|
4330
|
+
const path = `/push/blobs?giant=${encodeURIComponent(hash)}&packId=${encodeURIComponent(packId)}`;
|
|
4331
|
+
return retryTransient(() => call(cfg, token, path, { method: "POST", body: packBody }));
|
|
4332
|
+
}
|
|
4333
|
+
async function remotePushPack(cfg, token, body) {
|
|
4334
|
+
const { trees, leaves, total } = classifyNodes(body.nodes);
|
|
4335
|
+
if (total <= SMALL_PUSH_BYTES) {
|
|
4336
|
+
return retryTransient(() => call(cfg, token, "/push/pack", { method: "POST", body: gzipSync3(JSON.stringify(body)), headers: { "content-encoding": "gzip" } }));
|
|
4337
|
+
}
|
|
4338
|
+
const giants = leaves.filter((n) => nodeBytes(n) > GIANT_LEAF_BYTES);
|
|
4339
|
+
const normal = leaves.filter((n) => nodeBytes(n) <= GIANT_LEAF_BYTES);
|
|
4340
|
+
const blobPacks = splitLeafPacks(normal, BLOB_PACK_BYTES);
|
|
4341
|
+
const tasks = [
|
|
4342
|
+
...blobPacks.map((pack) => () => remotePushBlobs(cfg, token, pack)),
|
|
4343
|
+
...giants.map((node) => () => remotePushGiantLeaf(cfg, token, node))
|
|
4344
|
+
];
|
|
4345
|
+
await pool(tasks, BLOB_PACK_CONCURRENCY);
|
|
4346
|
+
return retryTransient(() => call(cfg, token, "/push/pack", {
|
|
4347
|
+
method: "POST",
|
|
4348
|
+
body: gzipSync3(JSON.stringify({ ...body, nodes: trees })),
|
|
4349
|
+
headers: { "content-encoding": "gzip" }
|
|
4350
|
+
}));
|
|
4351
|
+
}
|
|
4200
4352
|
function loadRemote(solDir2) {
|
|
4201
4353
|
const p = join6(solDir2, "remote.json");
|
|
4202
4354
|
return existsSync6(p) ? JSON.parse(readFileSync6(p, "utf8")) : undefined;
|
|
@@ -4217,9 +4369,13 @@ async function writeBundle(solDir2, bundle, from = 0) {
|
|
|
4217
4369
|
writeFileSync6(join6(solDir2, "HEAD"), JSON.stringify({ head: bundle.head, seq: bundle.seq, logTip: bundle.tip }));
|
|
4218
4370
|
return fresh.length;
|
|
4219
4371
|
}
|
|
4220
|
-
var endpoint = (cfg, path) => `${cfg.url.replace(/\/+$/, "")}${path}${path.includes("?") ? "&" : "?"}repo=${encodeURIComponent(cfg.repo)}`, remoteHead = (cfg, token) => call(cfg, token, "/head"), remoteGate = (cfg, token, branch) => call(cfg, token, `/head?gateState=true${branch ? `&branch=${encodeURIComponent(branch)}` : ""}`), remoteExport = (cfg, token) =>
|
|
4372
|
+
var endpoint = (cfg, path) => `${cfg.url.replace(/\/+$/, "")}${path}${path.includes("?") ? "&" : "?"}repo=${encodeURIComponent(cfg.repo)}`, remoteHead = (cfg, token) => call(cfg, token, "/head"), remoteGate = (cfg, token, branch) => call(cfg, token, `/head?gateState=true${branch ? `&branch=${encodeURIComponent(branch)}` : ""}`), remoteExport = (cfg, token) => exportStreaming(cfg, token), remoteRefs = (cfg, token) => call(cfg, token, "/refs"), remotePush = (cfg, token, body) => call(cfg, token, "/push", { method: "POST", body: JSON.stringify(body) }), remotePromote = (cfg, token, branch) => call(cfg, token, "/promote", { method: "POST", body: JSON.stringify({ branch }) }), SMALL_PUSH_BYTES, BLOB_PACK_BYTES, BLOB_PACK_CONCURRENCY = 6, GIANT_LEAF_BYTES, nodeBytes = (n) => JSON.stringify(n).length, remotePushBlobs = (cfg, token, nodes) => retryTransient(() => call(cfg, token, "/push/blobs", { method: "POST", body: gzipSync3(JSON.stringify({ nodes })), headers: { "content-encoding": "gzip" } })), mrOpen = (cfg, token, body) => call(cfg, token, "/mr", { method: "POST", body: JSON.stringify(body) }), mrList = (cfg, token) => call(cfg, token, "/mrs"), mrDiff = (cfg, token, id) => call(cfg, token, `/mr/diff?id=${id}`), mrGet = (cfg, token, id) => call(cfg, token, `/mr?id=${id}`), mrAction = (cfg, token, action, body) => call(cfg, token, `/mr/${action}`, { method: "POST", body: JSON.stringify(body) }), accessGet = (cfg, token) => call(cfg, token, "/access"), ownerSet = (cfg, token, ownerHandle) => call(cfg, token, "/owner", { method: "POST", body: JSON.stringify({ ownerHandle }) }), accessSet = (cfg, token, body) => call(cfg, token, "/access", { method: "POST", body: JSON.stringify(body) }), policyCheck = (cfg, token, paths) => call(cfg, token, "/policy/check", { method: "POST", body: JSON.stringify({ paths }) }), policyGet = (cfg, token) => call(cfg, token, "/policy"), policyUpsert = (cfg, token, rule) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "upsert", rule }) }), policyRemove = (cfg, token, pattern) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "remove", pattern }) }), recipientsForPath = (cfg, token, path) => call(cfg, token, `/recipients?path=${encodeURIComponent(path)}`), recipientsForAudience = (cfg, token, audience, recovery) => call(cfg, token, `/recipients?audience=${encodeURIComponent(JSON.stringify(audience))}${recovery?.length ? `&recovery=${encodeURIComponent(recovery.join(","))}` : ""}`), remoteEnvPush = (cfg, token, bundle) => call(cfg, token, "/env/push", { method: "POST", body: JSON.stringify(bundle) }), remoteEnvAnchor = (cfg, token) => call(cfg, token, "/env/anchor"), remoteEnvPull = (cfg, token) => call(cfg, token, "/env/pull"), forkMeta = (cfg, token, parent) => call(cfg, token, "/fork-meta", { method: "POST", body: JSON.stringify({ parent }) }), forksList = (cfg, token) => call(cfg, token, "/forks"), saveRemote = (solDir2, cfg) => writeFileSync6(join6(solDir2, "remote.json"), JSON.stringify(cfg, null, 2));
|
|
4221
4373
|
var init_remote = __esm(() => {
|
|
4222
4374
|
init_file_store2();
|
|
4375
|
+
init_store();
|
|
4376
|
+
SMALL_PUSH_BYTES = 24 * 1024 * 1024;
|
|
4377
|
+
BLOB_PACK_BYTES = 16 * 1024 * 1024;
|
|
4378
|
+
GIANT_LEAF_BYTES = 24 * 1024 * 1024;
|
|
4223
4379
|
});
|
|
4224
4380
|
|
|
4225
4381
|
// src/bin/test-gate.ts
|
|
@@ -9620,21 +9776,41 @@ function tokenClaims(token) {
|
|
|
9620
9776
|
return {};
|
|
9621
9777
|
}
|
|
9622
9778
|
}
|
|
9623
|
-
|
|
9624
|
-
if (!existsSync20(CRED_PATH))
|
|
9625
|
-
return;
|
|
9626
|
-
let creds;
|
|
9779
|
+
function readCreds() {
|
|
9627
9780
|
try {
|
|
9628
|
-
|
|
9781
|
+
return JSON.parse(readFileSync20(CRED_PATH, "utf8"));
|
|
9629
9782
|
} catch {
|
|
9630
9783
|
return;
|
|
9631
9784
|
}
|
|
9632
|
-
|
|
9785
|
+
}
|
|
9786
|
+
function accessTokenFresh(accessToken) {
|
|
9787
|
+
if (!accessToken)
|
|
9788
|
+
return false;
|
|
9789
|
+
const exp = tokenClaims(accessToken).exp;
|
|
9790
|
+
return typeof exp === "number" && exp * 1000 > Date.now() + 30000;
|
|
9791
|
+
}
|
|
9792
|
+
async function loadStoredToken() {
|
|
9793
|
+
if (!existsSync20(CRED_PATH))
|
|
9633
9794
|
return;
|
|
9634
|
-
|
|
9635
|
-
if (
|
|
9795
|
+
let creds = readCreds();
|
|
9796
|
+
if (!creds?.accessToken)
|
|
9797
|
+
return;
|
|
9798
|
+
if (accessTokenFresh(creds.accessToken))
|
|
9799
|
+
return creds.accessToken;
|
|
9800
|
+
if (!(creds.refreshToken && creds.webUrl))
|
|
9636
9801
|
return creds.accessToken;
|
|
9637
|
-
|
|
9802
|
+
const release = acquireLockAt(join19(dirname5(CRED_PATH), "credentials.lock"), {
|
|
9803
|
+
timeoutMs: 1e4,
|
|
9804
|
+
onTimeout: "undefined"
|
|
9805
|
+
});
|
|
9806
|
+
try {
|
|
9807
|
+
if (release) {
|
|
9808
|
+
const fresh = readCreds();
|
|
9809
|
+
if (fresh?.accessToken && accessTokenFresh(fresh.accessToken))
|
|
9810
|
+
return fresh.accessToken;
|
|
9811
|
+
if (fresh)
|
|
9812
|
+
creds = fresh;
|
|
9813
|
+
}
|
|
9638
9814
|
try {
|
|
9639
9815
|
const res = await fetch(`${creds.webUrl}/api/auth/refresh`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ refreshToken: creds.refreshToken }) });
|
|
9640
9816
|
if (res.ok) {
|
|
@@ -9645,8 +9821,10 @@ async function loadStoredToken() {
|
|
|
9645
9821
|
}
|
|
9646
9822
|
}
|
|
9647
9823
|
} catch {}
|
|
9824
|
+
return creds.accessToken;
|
|
9825
|
+
} finally {
|
|
9826
|
+
release?.();
|
|
9648
9827
|
}
|
|
9649
|
-
return creds.accessToken;
|
|
9650
9828
|
}
|
|
9651
9829
|
function authExpired() {
|
|
9652
9830
|
return die("session expired — run `sol auth login` (or set SOL_TOKEN)");
|
|
@@ -12389,8 +12567,12 @@ WARNING: "${path}" was committed as PLAINTEXT before this seal — the pre-seal
|
|
|
12389
12567
|
const days = Number(patAction) || 90;
|
|
12390
12568
|
const name = (Number(patAction) ? args[2] : patAction) || undefined;
|
|
12391
12569
|
const res = await fetch(`${creds.webUrl}/api/auth/pat`, { method: "POST", headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }, body: JSON.stringify({ days, ...name ? { name } : {} }) });
|
|
12392
|
-
if (!res.ok)
|
|
12393
|
-
|
|
12570
|
+
if (!res.ok) {
|
|
12571
|
+
const reason = await res.json().then((b) => b?.error?.detail || b?.error?.message).catch(() => {
|
|
12572
|
+
return;
|
|
12573
|
+
});
|
|
12574
|
+
die(`could not mint a PAT (${res.status})${reason ? `: ${reason}` : ""}`);
|
|
12575
|
+
}
|
|
12394
12576
|
const out = await res.json();
|
|
12395
12577
|
console.log(`
|
|
12396
12578
|
Personal Access Token "${out.name}" (id ${out.id}, expires in ${days} days) — store it now, it is not shown again:
|
package/sol.js
CHANGED
|
@@ -2269,6 +2269,7 @@ __export(exports_lib, {
|
|
|
2269
2269
|
allLocalNodes: () => allLocalNodes,
|
|
2270
2270
|
addInclude: () => addInclude,
|
|
2271
2271
|
actor: () => actor,
|
|
2272
|
+
acquireLockAt: () => acquireLockAt,
|
|
2272
2273
|
acquireLock: () => acquireLock,
|
|
2273
2274
|
LazyStore: () => LazyStore,
|
|
2274
2275
|
DEFAULT_IGNORE: () => DEFAULT_IGNORE
|
|
@@ -2502,9 +2503,9 @@ function pidAlive(pid) {
|
|
|
2502
2503
|
return e?.code === "EPERM";
|
|
2503
2504
|
}
|
|
2504
2505
|
}
|
|
2505
|
-
function
|
|
2506
|
-
const
|
|
2507
|
-
const
|
|
2506
|
+
function acquireLockAt(lockFile, opts = {}) {
|
|
2507
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 15000);
|
|
2508
|
+
const onTimeout = opts.onTimeout ?? "die";
|
|
2508
2509
|
for (;; ) {
|
|
2509
2510
|
try {
|
|
2510
2511
|
writeFileSync4(lockFile, String(process.pid), { flag: "wx" });
|
|
@@ -2527,8 +2528,11 @@ function acquireLock() {
|
|
|
2527
2528
|
} catch {
|
|
2528
2529
|
continue;
|
|
2529
2530
|
}
|
|
2530
|
-
if (Date.now() > deadline)
|
|
2531
|
-
|
|
2531
|
+
if (Date.now() > deadline) {
|
|
2532
|
+
if (onTimeout === "undefined")
|
|
2533
|
+
return;
|
|
2534
|
+
die(opts.timeoutMsg ?? "repo is locked by another sol process (timed out)");
|
|
2535
|
+
}
|
|
2532
2536
|
sleepSync(25);
|
|
2533
2537
|
}
|
|
2534
2538
|
}
|
|
@@ -2544,6 +2548,9 @@ function acquireLock() {
|
|
|
2544
2548
|
process.on("exit", release);
|
|
2545
2549
|
return release;
|
|
2546
2550
|
}
|
|
2551
|
+
function acquireLock() {
|
|
2552
|
+
return acquireLockAt(join4(lockDir(), "lock"));
|
|
2553
|
+
}
|
|
2547
2554
|
function loadStore() {
|
|
2548
2555
|
return new LazyStore(objectsDir());
|
|
2549
2556
|
}
|
|
@@ -3389,9 +3396,12 @@ var init_lib = __esm(() => {
|
|
|
3389
3396
|
var exports_remote = {};
|
|
3390
3397
|
__export(exports_remote, {
|
|
3391
3398
|
writeBundle: () => writeBundle,
|
|
3399
|
+
splitLeafPacks: () => splitLeafPacks,
|
|
3392
3400
|
saveRemote: () => saveRemote,
|
|
3393
3401
|
remoteRefs: () => remoteRefs,
|
|
3394
3402
|
remotePushPack: () => remotePushPack,
|
|
3403
|
+
remotePushGiantLeaf: () => remotePushGiantLeaf,
|
|
3404
|
+
remotePushBlobs: () => remotePushBlobs,
|
|
3395
3405
|
remotePush: () => remotePush,
|
|
3396
3406
|
remotePromote: () => remotePromote,
|
|
3397
3407
|
remoteHead: () => remoteHead,
|
|
@@ -3415,12 +3425,13 @@ __export(exports_remote, {
|
|
|
3415
3425
|
loadRemote: () => loadRemote,
|
|
3416
3426
|
forksList: () => forksList,
|
|
3417
3427
|
forkMeta: () => forkMeta,
|
|
3428
|
+
classifyNodes: () => classifyNodes,
|
|
3418
3429
|
accessSet: () => accessSet,
|
|
3419
3430
|
accessGet: () => accessGet
|
|
3420
3431
|
});
|
|
3421
3432
|
import { appendFileSync as appendFileSync3, existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
|
|
3422
3433
|
import { join as join5 } from "node:path";
|
|
3423
|
-
import { gzipSync as gzipSync2 } from "node:zlib";
|
|
3434
|
+
import { gunzipSync as gunzipSync2, gzipSync as gzipSync2 } from "node:zlib";
|
|
3424
3435
|
async function call(cfg, token, path, init) {
|
|
3425
3436
|
const res = await fetch(endpoint(cfg, path), {
|
|
3426
3437
|
...init,
|
|
@@ -3430,6 +3441,147 @@ async function call(cfg, token, path, init) {
|
|
|
3430
3441
|
throw new Error(`remote ${path} -> ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
|
|
3431
3442
|
return res.json();
|
|
3432
3443
|
}
|
|
3444
|
+
function decodePackLine(line) {
|
|
3445
|
+
const map = JSON.parse(gunzipSync2(Buffer.from(line, "base64")).toString("utf8"));
|
|
3446
|
+
return Object.values(map);
|
|
3447
|
+
}
|
|
3448
|
+
async function exportStreaming(cfg, token) {
|
|
3449
|
+
const res = await fetch(endpoint(cfg, "/export?stream=1"), {
|
|
3450
|
+
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }
|
|
3451
|
+
});
|
|
3452
|
+
if (!res.ok)
|
|
3453
|
+
throw new Error(`remote /export -> ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
|
|
3454
|
+
if (!res.body)
|
|
3455
|
+
return res.json();
|
|
3456
|
+
const reader = res.body.getReader();
|
|
3457
|
+
const td = new TextDecoder;
|
|
3458
|
+
let buf = "";
|
|
3459
|
+
let header;
|
|
3460
|
+
const nodes = [];
|
|
3461
|
+
const consumeLine = (line) => {
|
|
3462
|
+
if (line === "")
|
|
3463
|
+
return;
|
|
3464
|
+
if (!header) {
|
|
3465
|
+
header = JSON.parse(line);
|
|
3466
|
+
if (Array.isArray(header.nodes))
|
|
3467
|
+
for (const n of header.nodes)
|
|
3468
|
+
nodes.push(n);
|
|
3469
|
+
return;
|
|
3470
|
+
}
|
|
3471
|
+
for (const n of decodePackLine(line))
|
|
3472
|
+
nodes.push(n);
|
|
3473
|
+
};
|
|
3474
|
+
for (;; ) {
|
|
3475
|
+
const { done, value } = await reader.read();
|
|
3476
|
+
if (value)
|
|
3477
|
+
buf += td.decode(value, { stream: true });
|
|
3478
|
+
let nl;
|
|
3479
|
+
while ((nl = buf.indexOf(`
|
|
3480
|
+
`)) >= 0) {
|
|
3481
|
+
consumeLine(buf.slice(0, nl));
|
|
3482
|
+
buf = buf.slice(nl + 1);
|
|
3483
|
+
}
|
|
3484
|
+
if (done)
|
|
3485
|
+
break;
|
|
3486
|
+
}
|
|
3487
|
+
buf += td.decode();
|
|
3488
|
+
if (buf.length)
|
|
3489
|
+
consumeLine(buf);
|
|
3490
|
+
if (!header)
|
|
3491
|
+
throw new Error("remote /export returned an empty stream");
|
|
3492
|
+
return { ...header, nodes };
|
|
3493
|
+
}
|
|
3494
|
+
function classifyNodes(nodes) {
|
|
3495
|
+
const trees = [];
|
|
3496
|
+
const leaves = [];
|
|
3497
|
+
let total = 0;
|
|
3498
|
+
for (const n of nodes) {
|
|
3499
|
+
total += nodeBytes(n);
|
|
3500
|
+
(n.kind === "tree" ? trees : leaves).push(n);
|
|
3501
|
+
}
|
|
3502
|
+
return { trees, leaves, total };
|
|
3503
|
+
}
|
|
3504
|
+
function splitLeafPacks(leaves, maxBytes) {
|
|
3505
|
+
const packs = [];
|
|
3506
|
+
let cur = [];
|
|
3507
|
+
let size = 0;
|
|
3508
|
+
for (const n of leaves) {
|
|
3509
|
+
const b = nodeBytes(n);
|
|
3510
|
+
if (cur.length && size + b > maxBytes) {
|
|
3511
|
+
packs.push(cur);
|
|
3512
|
+
cur = [];
|
|
3513
|
+
size = 0;
|
|
3514
|
+
}
|
|
3515
|
+
cur.push(n);
|
|
3516
|
+
size += b;
|
|
3517
|
+
}
|
|
3518
|
+
if (cur.length)
|
|
3519
|
+
packs.push(cur);
|
|
3520
|
+
return packs;
|
|
3521
|
+
}
|
|
3522
|
+
async function pool(tasks, limit) {
|
|
3523
|
+
const out = new Array(tasks.length);
|
|
3524
|
+
let next = 0;
|
|
3525
|
+
const worker = async () => {
|
|
3526
|
+
for (;; ) {
|
|
3527
|
+
const i = next++;
|
|
3528
|
+
if (i >= tasks.length)
|
|
3529
|
+
return;
|
|
3530
|
+
out[i] = await tasks[i]();
|
|
3531
|
+
}
|
|
3532
|
+
};
|
|
3533
|
+
await Promise.all(Array.from({ length: Math.min(limit, tasks.length) }, worker));
|
|
3534
|
+
return out;
|
|
3535
|
+
}
|
|
3536
|
+
async function retryTransient(fn, attempts = 5) {
|
|
3537
|
+
let last;
|
|
3538
|
+
for (let i = 0;i < attempts; i++) {
|
|
3539
|
+
try {
|
|
3540
|
+
return await fn();
|
|
3541
|
+
} catch (e) {
|
|
3542
|
+
last = e;
|
|
3543
|
+
const m = e instanceof Error ? e.message : String(e);
|
|
3544
|
+
if (!/-> 5dd|reset|fetch failed|network|ECONN|terminated|timeout/i.test(m))
|
|
3545
|
+
throw e;
|
|
3546
|
+
await new Promise((r) => setTimeout(r, 400 * (i + 1)));
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
throw last;
|
|
3550
|
+
}
|
|
3551
|
+
function canonicalPackBytesClient(entries) {
|
|
3552
|
+
const sorted = [...entries].sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
|
|
3553
|
+
const obj = {};
|
|
3554
|
+
for (const [h, n] of sorted)
|
|
3555
|
+
obj[h] = n;
|
|
3556
|
+
return JSON.stringify(obj);
|
|
3557
|
+
}
|
|
3558
|
+
async function remotePushGiantLeaf(cfg, token, node) {
|
|
3559
|
+
const hash = hashNode(node);
|
|
3560
|
+
const body = canonicalPackBytesClient([[hash, node]]);
|
|
3561
|
+
const packId = hashString(body);
|
|
3562
|
+
const packBody = gzipSync2(Buffer.from(body, "utf8")).toString("base64");
|
|
3563
|
+
const path = `/push/blobs?giant=${encodeURIComponent(hash)}&packId=${encodeURIComponent(packId)}`;
|
|
3564
|
+
return retryTransient(() => call(cfg, token, path, { method: "POST", body: packBody }));
|
|
3565
|
+
}
|
|
3566
|
+
async function remotePushPack(cfg, token, body) {
|
|
3567
|
+
const { trees, leaves, total } = classifyNodes(body.nodes);
|
|
3568
|
+
if (total <= SMALL_PUSH_BYTES) {
|
|
3569
|
+
return retryTransient(() => call(cfg, token, "/push/pack", { method: "POST", body: gzipSync2(JSON.stringify(body)), headers: { "content-encoding": "gzip" } }));
|
|
3570
|
+
}
|
|
3571
|
+
const giants = leaves.filter((n) => nodeBytes(n) > GIANT_LEAF_BYTES);
|
|
3572
|
+
const normal = leaves.filter((n) => nodeBytes(n) <= GIANT_LEAF_BYTES);
|
|
3573
|
+
const blobPacks = splitLeafPacks(normal, BLOB_PACK_BYTES);
|
|
3574
|
+
const tasks = [
|
|
3575
|
+
...blobPacks.map((pack) => () => remotePushBlobs(cfg, token, pack)),
|
|
3576
|
+
...giants.map((node) => () => remotePushGiantLeaf(cfg, token, node))
|
|
3577
|
+
];
|
|
3578
|
+
await pool(tasks, BLOB_PACK_CONCURRENCY);
|
|
3579
|
+
return retryTransient(() => call(cfg, token, "/push/pack", {
|
|
3580
|
+
method: "POST",
|
|
3581
|
+
body: gzipSync2(JSON.stringify({ ...body, nodes: trees })),
|
|
3582
|
+
headers: { "content-encoding": "gzip" }
|
|
3583
|
+
}));
|
|
3584
|
+
}
|
|
3433
3585
|
function loadRemote(solDir2) {
|
|
3434
3586
|
const p = join5(solDir2, "remote.json");
|
|
3435
3587
|
return existsSync5(p) ? JSON.parse(readFileSync5(p, "utf8")) : undefined;
|
|
@@ -3450,9 +3602,13 @@ async function writeBundle(solDir2, bundle, from = 0) {
|
|
|
3450
3602
|
writeFileSync5(join5(solDir2, "HEAD"), JSON.stringify({ head: bundle.head, seq: bundle.seq, logTip: bundle.tip }));
|
|
3451
3603
|
return fresh.length;
|
|
3452
3604
|
}
|
|
3453
|
-
var endpoint = (cfg, path) => `${cfg.url.replace(/\/+$/, "")}${path}${path.includes("?") ? "&" : "?"}repo=${encodeURIComponent(cfg.repo)}`, remoteHead = (cfg, token) => call(cfg, token, "/head"), remoteGate = (cfg, token, branch) => call(cfg, token, `/head?gateState=true${branch ? `&branch=${encodeURIComponent(branch)}` : ""}`), remoteExport = (cfg, token) =>
|
|
3605
|
+
var endpoint = (cfg, path) => `${cfg.url.replace(/\/+$/, "")}${path}${path.includes("?") ? "&" : "?"}repo=${encodeURIComponent(cfg.repo)}`, remoteHead = (cfg, token) => call(cfg, token, "/head"), remoteGate = (cfg, token, branch) => call(cfg, token, `/head?gateState=true${branch ? `&branch=${encodeURIComponent(branch)}` : ""}`), remoteExport = (cfg, token) => exportStreaming(cfg, token), remoteRefs = (cfg, token) => call(cfg, token, "/refs"), remotePush = (cfg, token, body) => call(cfg, token, "/push", { method: "POST", body: JSON.stringify(body) }), remotePromote = (cfg, token, branch) => call(cfg, token, "/promote", { method: "POST", body: JSON.stringify({ branch }) }), SMALL_PUSH_BYTES, BLOB_PACK_BYTES, BLOB_PACK_CONCURRENCY = 6, GIANT_LEAF_BYTES, nodeBytes = (n) => JSON.stringify(n).length, remotePushBlobs = (cfg, token, nodes) => retryTransient(() => call(cfg, token, "/push/blobs", { method: "POST", body: gzipSync2(JSON.stringify({ nodes })), headers: { "content-encoding": "gzip" } })), mrOpen = (cfg, token, body) => call(cfg, token, "/mr", { method: "POST", body: JSON.stringify(body) }), mrList = (cfg, token) => call(cfg, token, "/mrs"), mrDiff = (cfg, token, id) => call(cfg, token, `/mr/diff?id=${id}`), mrGet = (cfg, token, id) => call(cfg, token, `/mr?id=${id}`), mrAction = (cfg, token, action, body) => call(cfg, token, `/mr/${action}`, { method: "POST", body: JSON.stringify(body) }), accessGet = (cfg, token) => call(cfg, token, "/access"), ownerSet = (cfg, token, ownerHandle) => call(cfg, token, "/owner", { method: "POST", body: JSON.stringify({ ownerHandle }) }), accessSet = (cfg, token, body) => call(cfg, token, "/access", { method: "POST", body: JSON.stringify(body) }), policyCheck = (cfg, token, paths) => call(cfg, token, "/policy/check", { method: "POST", body: JSON.stringify({ paths }) }), policyGet = (cfg, token) => call(cfg, token, "/policy"), policyUpsert = (cfg, token, rule) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "upsert", rule }) }), policyRemove = (cfg, token, pattern) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "remove", pattern }) }), recipientsForPath = (cfg, token, path) => call(cfg, token, `/recipients?path=${encodeURIComponent(path)}`), recipientsForAudience = (cfg, token, audience, recovery) => call(cfg, token, `/recipients?audience=${encodeURIComponent(JSON.stringify(audience))}${recovery?.length ? `&recovery=${encodeURIComponent(recovery.join(","))}` : ""}`), remoteEnvPush = (cfg, token, bundle) => call(cfg, token, "/env/push", { method: "POST", body: JSON.stringify(bundle) }), remoteEnvAnchor = (cfg, token) => call(cfg, token, "/env/anchor"), remoteEnvPull = (cfg, token) => call(cfg, token, "/env/pull"), forkMeta = (cfg, token, parent) => call(cfg, token, "/fork-meta", { method: "POST", body: JSON.stringify({ parent }) }), forksList = (cfg, token) => call(cfg, token, "/forks"), saveRemote = (solDir2, cfg) => writeFileSync5(join5(solDir2, "remote.json"), JSON.stringify(cfg, null, 2));
|
|
3454
3606
|
var init_remote = __esm(() => {
|
|
3455
3607
|
init_file_store();
|
|
3608
|
+
init_store();
|
|
3609
|
+
SMALL_PUSH_BYTES = 24 * 1024 * 1024;
|
|
3610
|
+
BLOB_PACK_BYTES = 16 * 1024 * 1024;
|
|
3611
|
+
GIANT_LEAF_BYTES = 24 * 1024 * 1024;
|
|
3456
3612
|
});
|
|
3457
3613
|
|
|
3458
3614
|
// src/bin/test-gate.ts
|
|
@@ -9388,21 +9544,41 @@ function tokenClaims(token) {
|
|
|
9388
9544
|
return {};
|
|
9389
9545
|
}
|
|
9390
9546
|
}
|
|
9391
|
-
|
|
9392
|
-
if (!existsSync19(CRED_PATH))
|
|
9393
|
-
return;
|
|
9394
|
-
let creds;
|
|
9547
|
+
function readCreds() {
|
|
9395
9548
|
try {
|
|
9396
|
-
|
|
9549
|
+
return JSON.parse(readFileSync19(CRED_PATH, "utf8"));
|
|
9397
9550
|
} catch {
|
|
9398
9551
|
return;
|
|
9399
9552
|
}
|
|
9400
|
-
|
|
9553
|
+
}
|
|
9554
|
+
function accessTokenFresh(accessToken) {
|
|
9555
|
+
if (!accessToken)
|
|
9556
|
+
return false;
|
|
9557
|
+
const exp = tokenClaims(accessToken).exp;
|
|
9558
|
+
return typeof exp === "number" && exp * 1000 > Date.now() + 30000;
|
|
9559
|
+
}
|
|
9560
|
+
async function loadStoredToken() {
|
|
9561
|
+
if (!existsSync19(CRED_PATH))
|
|
9562
|
+
return;
|
|
9563
|
+
let creds = readCreds();
|
|
9564
|
+
if (!creds?.accessToken)
|
|
9401
9565
|
return;
|
|
9402
|
-
|
|
9403
|
-
if (typeof exp === "number" && exp * 1000 > Date.now() + 30000)
|
|
9566
|
+
if (accessTokenFresh(creds.accessToken))
|
|
9404
9567
|
return creds.accessToken;
|
|
9405
|
-
if (creds.refreshToken && creds.webUrl)
|
|
9568
|
+
if (!(creds.refreshToken && creds.webUrl))
|
|
9569
|
+
return creds.accessToken;
|
|
9570
|
+
const release = acquireLockAt(join18(dirname5(CRED_PATH), "credentials.lock"), {
|
|
9571
|
+
timeoutMs: 1e4,
|
|
9572
|
+
onTimeout: "undefined"
|
|
9573
|
+
});
|
|
9574
|
+
try {
|
|
9575
|
+
if (release) {
|
|
9576
|
+
const fresh = readCreds();
|
|
9577
|
+
if (fresh?.accessToken && accessTokenFresh(fresh.accessToken))
|
|
9578
|
+
return fresh.accessToken;
|
|
9579
|
+
if (fresh)
|
|
9580
|
+
creds = fresh;
|
|
9581
|
+
}
|
|
9406
9582
|
try {
|
|
9407
9583
|
const res = await fetch(`${creds.webUrl}/api/auth/refresh`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ refreshToken: creds.refreshToken }) });
|
|
9408
9584
|
if (res.ok) {
|
|
@@ -9413,8 +9589,10 @@ async function loadStoredToken() {
|
|
|
9413
9589
|
}
|
|
9414
9590
|
}
|
|
9415
9591
|
} catch {}
|
|
9592
|
+
return creds.accessToken;
|
|
9593
|
+
} finally {
|
|
9594
|
+
release?.();
|
|
9416
9595
|
}
|
|
9417
|
-
return creds.accessToken;
|
|
9418
9596
|
}
|
|
9419
9597
|
function authExpired() {
|
|
9420
9598
|
return die("session expired — run `sol auth login` (or set SOL_TOKEN)");
|
|
@@ -12157,8 +12335,12 @@ WARNING: "${path}" was committed as PLAINTEXT before this seal — the pre-seal
|
|
|
12157
12335
|
const days = Number(patAction) || 90;
|
|
12158
12336
|
const name = (Number(patAction) ? args[2] : patAction) || undefined;
|
|
12159
12337
|
const res = await fetch(`${creds.webUrl}/api/auth/pat`, { method: "POST", headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }, body: JSON.stringify({ days, ...name ? { name } : {} }) });
|
|
12160
|
-
if (!res.ok)
|
|
12161
|
-
|
|
12338
|
+
if (!res.ok) {
|
|
12339
|
+
const reason = await res.json().then((b) => b?.error?.detail || b?.error?.message).catch(() => {
|
|
12340
|
+
return;
|
|
12341
|
+
});
|
|
12342
|
+
die(`could not mint a PAT (${res.status})${reason ? `: ${reason}` : ""}`);
|
|
12343
|
+
}
|
|
12162
12344
|
const out = await res.json();
|
|
12163
12345
|
console.log(`
|
|
12164
12346
|
Personal Access Token "${out.name}" (id ${out.id}, expires in ${days} days) — store it now, it is not shown again:
|
|
@@ -13672,21 +13854,41 @@ function tokenClaims2(token) {
|
|
|
13672
13854
|
return {};
|
|
13673
13855
|
}
|
|
13674
13856
|
}
|
|
13675
|
-
|
|
13676
|
-
if (!existsSync20(CRED_PATH2))
|
|
13677
|
-
return;
|
|
13678
|
-
let creds;
|
|
13857
|
+
function readCreds2() {
|
|
13679
13858
|
try {
|
|
13680
|
-
|
|
13859
|
+
return JSON.parse(readFileSync20(CRED_PATH2, "utf8"));
|
|
13681
13860
|
} catch {
|
|
13682
13861
|
return;
|
|
13683
13862
|
}
|
|
13684
|
-
|
|
13863
|
+
}
|
|
13864
|
+
function accessTokenFresh2(accessToken) {
|
|
13865
|
+
if (!accessToken)
|
|
13866
|
+
return false;
|
|
13867
|
+
const exp = tokenClaims2(accessToken).exp;
|
|
13868
|
+
return typeof exp === "number" && exp * 1000 > Date.now() + 30000;
|
|
13869
|
+
}
|
|
13870
|
+
async function loadStoredToken2() {
|
|
13871
|
+
if (!existsSync20(CRED_PATH2))
|
|
13872
|
+
return;
|
|
13873
|
+
let creds = readCreds2();
|
|
13874
|
+
if (!creds?.accessToken)
|
|
13685
13875
|
return;
|
|
13686
|
-
|
|
13687
|
-
if (typeof exp === "number" && exp * 1000 > Date.now() + 30000)
|
|
13876
|
+
if (accessTokenFresh2(creds.accessToken))
|
|
13688
13877
|
return creds.accessToken;
|
|
13689
|
-
if (creds.refreshToken && creds.webUrl)
|
|
13878
|
+
if (!(creds.refreshToken && creds.webUrl))
|
|
13879
|
+
return creds.accessToken;
|
|
13880
|
+
const release = acquireLockAt(join20(dirname7(CRED_PATH2), "credentials.lock"), {
|
|
13881
|
+
timeoutMs: 1e4,
|
|
13882
|
+
onTimeout: "undefined"
|
|
13883
|
+
});
|
|
13884
|
+
try {
|
|
13885
|
+
if (release) {
|
|
13886
|
+
const fresh = readCreds2();
|
|
13887
|
+
if (fresh?.accessToken && accessTokenFresh2(fresh.accessToken))
|
|
13888
|
+
return fresh.accessToken;
|
|
13889
|
+
if (fresh)
|
|
13890
|
+
creds = fresh;
|
|
13891
|
+
}
|
|
13690
13892
|
try {
|
|
13691
13893
|
const res = await fetch(`${creds.webUrl}/api/auth/refresh`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ refreshToken: creds.refreshToken }) });
|
|
13692
13894
|
if (res.ok) {
|
|
@@ -13697,8 +13899,10 @@ async function loadStoredToken2() {
|
|
|
13697
13899
|
}
|
|
13698
13900
|
}
|
|
13699
13901
|
} catch {}
|
|
13902
|
+
return creds.accessToken;
|
|
13903
|
+
} finally {
|
|
13904
|
+
release?.();
|
|
13700
13905
|
}
|
|
13701
|
-
return creds.accessToken;
|
|
13702
13906
|
}
|
|
13703
13907
|
function authExpired2() {
|
|
13704
13908
|
return die("session expired — run `sol auth login` (or set SOL_TOKEN)");
|
|
@@ -16441,8 +16645,12 @@ WARNING: "${path}" was committed as PLAINTEXT before this seal — the pre-seal
|
|
|
16441
16645
|
const days = Number(patAction) || 90;
|
|
16442
16646
|
const name = (Number(patAction) ? args[2] : patAction) || undefined;
|
|
16443
16647
|
const res = await fetch(`${creds.webUrl}/api/auth/pat`, { method: "POST", headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }, body: JSON.stringify({ days, ...name ? { name } : {} }) });
|
|
16444
|
-
if (!res.ok)
|
|
16445
|
-
|
|
16648
|
+
if (!res.ok) {
|
|
16649
|
+
const reason = await res.json().then((b) => b?.error?.detail || b?.error?.message).catch(() => {
|
|
16650
|
+
return;
|
|
16651
|
+
});
|
|
16652
|
+
die(`could not mint a PAT (${res.status})${reason ? `: ${reason}` : ""}`);
|
|
16653
|
+
}
|
|
16446
16654
|
const out = await res.json();
|
|
16447
16655
|
console.log(`
|
|
16448
16656
|
Personal Access Token "${out.name}" (id ${out.id}, expires in ${days} days) — store it now, it is not shown again:
|