@tinycloud/cli 1.3.1-beta.0 → 1.3.2-beta.0
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.js +2180 -356
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +6550 -4941
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +7 -7
- package/skills/tc-cli/REFERENCE.md +2 -0
package/dist/index.js
CHANGED
|
@@ -266,11 +266,11 @@ function warningLine(warnings) {
|
|
|
266
266
|
const subject = warnings.length === 1 ? "A stored grant was" : `${warnings.length} stored grants were`;
|
|
267
267
|
return `${subject} not used (${which}). Approve access again when a command needs it; remove the old grant with ${CLI_NAME2} auth grants remove <cid>.`;
|
|
268
268
|
}
|
|
269
|
-
function outputError(
|
|
269
|
+
function outputError(code5, message, hint, details = {}) {
|
|
270
270
|
const { meta, warnings = [], setup, recovery, progress } = details;
|
|
271
271
|
if (!shouldOutputJson()) {
|
|
272
272
|
process.stderr.write(
|
|
273
|
-
`${theme.error("\u2717")} ${theme.label(safeInline(
|
|
273
|
+
`${theme.error("\u2717")} ${theme.label(safeInline(code5))}: ${safeBlock(message)}
|
|
274
274
|
`
|
|
275
275
|
);
|
|
276
276
|
if (hint) {
|
|
@@ -283,7 +283,7 @@ function outputError(code4, message, hint, details = {}) {
|
|
|
283
283
|
`);
|
|
284
284
|
} else {
|
|
285
285
|
const payload = {
|
|
286
|
-
error: { code:
|
|
286
|
+
error: { code: code5, message }
|
|
287
287
|
};
|
|
288
288
|
if (hint) payload.error.hint = hint;
|
|
289
289
|
if (recovery) payload.error.recovery = recovery;
|
|
@@ -305,11 +305,11 @@ function operationWarnings(value) {
|
|
|
305
305
|
if (!Array.isArray(value)) return [];
|
|
306
306
|
return value.flatMap((warning) => {
|
|
307
307
|
if (warning === null || typeof warning !== "object") return [];
|
|
308
|
-
const { code:
|
|
309
|
-
if (typeof
|
|
308
|
+
const { code: code5, reason, grantCid } = warning;
|
|
309
|
+
if (typeof code5 !== "string" || !WARNING_CODE.test(code5) || typeof reason !== "string" || !WARNING_REASON.test(reason)) {
|
|
310
310
|
return [];
|
|
311
311
|
}
|
|
312
|
-
return [{ code:
|
|
312
|
+
return [{ code: code5, reason, ...typeof grantCid === "string" && DELEGATION_CID.test(grantCid) ? { grantCid } : {} }];
|
|
313
313
|
});
|
|
314
314
|
}
|
|
315
315
|
function isInteractive() {
|
|
@@ -340,17 +340,17 @@ function storageRejection(error) {
|
|
|
340
340
|
let node = error;
|
|
341
341
|
for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null; depth += 1) {
|
|
342
342
|
const record2 = node;
|
|
343
|
-
let
|
|
343
|
+
let code5;
|
|
344
344
|
if (record2.code === "STORAGE_QUOTA_EXCEEDED" || record2.code === "STORAGE_LIMIT_REACHED") {
|
|
345
|
-
|
|
345
|
+
code5 = record2.code;
|
|
346
346
|
} else if (record2.code !== void 0) {
|
|
347
347
|
return void 0;
|
|
348
348
|
} else if (isStorageStatus(record2)) {
|
|
349
|
-
|
|
349
|
+
code5 = storageCodeFromText(record2.message);
|
|
350
350
|
}
|
|
351
|
-
if (
|
|
351
|
+
if (code5) {
|
|
352
352
|
const account = accountTotals(record2) ?? accountTotals(record2.meta) ?? accountTotals(record2.metadata);
|
|
353
|
-
return account ? { code:
|
|
353
|
+
return account ? { code: code5, account } : { code: code5 };
|
|
354
354
|
}
|
|
355
355
|
node = record2.cause;
|
|
356
356
|
}
|
|
@@ -434,22 +434,22 @@ function setActiveProfileName(name) {
|
|
|
434
434
|
}
|
|
435
435
|
function nodeRetryError(error) {
|
|
436
436
|
if (typeof error !== "object" || error === null) return void 0;
|
|
437
|
-
const { code:
|
|
438
|
-
if (
|
|
437
|
+
const { code: code5, meta, metadata } = error;
|
|
438
|
+
if (code5 !== "NODE_BUSY" && code5 !== "REQUEST_TIMEOUT" && code5 !== "OUTCOME_UNKNOWN") return void 0;
|
|
439
439
|
const details = typeof meta === "object" && meta !== null ? meta : typeof metadata === "object" && metadata !== null ? metadata : {};
|
|
440
440
|
const retryAfterMs = details.retryAfterMs;
|
|
441
441
|
const wait = typeof retryAfterMs === "number" && Number.isFinite(retryAfterMs) && retryAfterMs >= 0 ? `in ${Math.max(1, Math.ceil(retryAfterMs / 1e3))} s` : "shortly";
|
|
442
|
-
if (
|
|
442
|
+
if (code5 === "OUTCOME_UNKNOWN") {
|
|
443
443
|
return new CLIError(
|
|
444
|
-
|
|
444
|
+
code5,
|
|
445
445
|
"Outcome unknown: the node may have applied the write. Check before retrying.",
|
|
446
446
|
ExitCode.NODE_ERROR,
|
|
447
447
|
{ ...details, hint: "Read the data back before running the command again; repeating a write that already applied can duplicate it." }
|
|
448
448
|
);
|
|
449
449
|
}
|
|
450
450
|
return new CLIError(
|
|
451
|
-
|
|
452
|
-
|
|
451
|
+
code5,
|
|
452
|
+
code5 === "NODE_BUSY" ? `The node is busy, try again ${wait}.` : `The node timed out before applying anything, try again ${wait}.`,
|
|
453
453
|
ExitCode.NODE_ERROR,
|
|
454
454
|
details
|
|
455
455
|
);
|
|
@@ -661,9 +661,9 @@ var init_errors = __esm({
|
|
|
661
661
|
init_warnings();
|
|
662
662
|
GRANT_REVOKED_EXIT_CODE = ExitCode.PERMISSION_DENIED;
|
|
663
663
|
CLIError = class extends Error {
|
|
664
|
-
constructor(
|
|
664
|
+
constructor(code5, message, exitCode = ExitCode.ERROR, metadata) {
|
|
665
665
|
super(message);
|
|
666
|
-
this.code =
|
|
666
|
+
this.code = code5;
|
|
667
667
|
this.exitCode = exitCode;
|
|
668
668
|
this.metadata = metadata;
|
|
669
669
|
this.name = "CLIError";
|
|
@@ -1182,12 +1182,12 @@ var init_md = __esm({
|
|
|
1182
1182
|
_cloneInto(to) {
|
|
1183
1183
|
to || (to = new this.constructor());
|
|
1184
1184
|
to.set(...this.get());
|
|
1185
|
-
const { blockLen, buffer, length:
|
|
1185
|
+
const { blockLen, buffer, length: length5, finished, destroyed, pos } = this;
|
|
1186
1186
|
to.destroyed = destroyed;
|
|
1187
1187
|
to.finished = finished;
|
|
1188
|
-
to.length =
|
|
1188
|
+
to.length = length5;
|
|
1189
1189
|
to.pos = pos;
|
|
1190
|
-
if (
|
|
1190
|
+
if (length5 % blockLen)
|
|
1191
1191
|
to.buffer.set(buffer);
|
|
1192
1192
|
return to;
|
|
1193
1193
|
}
|
|
@@ -1924,13 +1924,13 @@ var init_blake2 = __esm({
|
|
|
1924
1924
|
return res;
|
|
1925
1925
|
}
|
|
1926
1926
|
_cloneInto(to) {
|
|
1927
|
-
const { buffer, length:
|
|
1927
|
+
const { buffer, length: length5, finished, destroyed, outputLen, pos } = this;
|
|
1928
1928
|
to || (to = new this.constructor({ dkLen: outputLen }));
|
|
1929
1929
|
to.set(...this.get());
|
|
1930
1930
|
to.buffer.set(buffer);
|
|
1931
1931
|
to.destroyed = destroyed;
|
|
1932
1932
|
to.finished = finished;
|
|
1933
|
-
to.length =
|
|
1933
|
+
to.length = length5;
|
|
1934
1934
|
to.pos = pos;
|
|
1935
1935
|
to.outputLen = outputLen;
|
|
1936
1936
|
return to;
|
|
@@ -2165,13 +2165,13 @@ function _abool2(value, title = "") {
|
|
|
2165
2165
|
}
|
|
2166
2166
|
return value;
|
|
2167
2167
|
}
|
|
2168
|
-
function _abytes2(value,
|
|
2168
|
+
function _abytes2(value, length5, title = "") {
|
|
2169
2169
|
const bytes = isBytes(value);
|
|
2170
2170
|
const len = value?.length;
|
|
2171
|
-
const needsLen =
|
|
2172
|
-
if (!bytes || needsLen && len !==
|
|
2171
|
+
const needsLen = length5 !== void 0;
|
|
2172
|
+
if (!bytes || needsLen && len !== length5) {
|
|
2173
2173
|
const prefix = title && `"${title}" `;
|
|
2174
|
-
const ofLen = needsLen ? ` of length ${
|
|
2174
|
+
const ofLen = needsLen ? ` of length ${length5}` : "";
|
|
2175
2175
|
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
2176
2176
|
throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
|
|
2177
2177
|
}
|
|
@@ -2787,15 +2787,15 @@ var init_curve = __esm({
|
|
|
2787
2787
|
const { windows, windowSize } = calcWOpts(W, this.bits);
|
|
2788
2788
|
const points = [];
|
|
2789
2789
|
let p = point;
|
|
2790
|
-
let
|
|
2790
|
+
let base5 = p;
|
|
2791
2791
|
for (let window = 0; window < windows; window++) {
|
|
2792
|
-
|
|
2793
|
-
points.push(
|
|
2792
|
+
base5 = p;
|
|
2793
|
+
points.push(base5);
|
|
2794
2794
|
for (let i = 1; i < windowSize; i++) {
|
|
2795
|
-
|
|
2796
|
-
points.push(
|
|
2795
|
+
base5 = base5.add(p);
|
|
2796
|
+
points.push(base5);
|
|
2797
2797
|
}
|
|
2798
|
-
p =
|
|
2798
|
+
p = base5.double();
|
|
2799
2799
|
}
|
|
2800
2800
|
return points;
|
|
2801
2801
|
}
|
|
@@ -3770,10 +3770,10 @@ var init_dist = __esm({
|
|
|
3770
3770
|
[REPLICA_ERROR] = true;
|
|
3771
3771
|
code;
|
|
3772
3772
|
detail;
|
|
3773
|
-
constructor(
|
|
3773
|
+
constructor(code5, message, detail, options) {
|
|
3774
3774
|
super(message, options);
|
|
3775
3775
|
this.name = "ReplicaError";
|
|
3776
|
-
this.code =
|
|
3776
|
+
this.code = code5;
|
|
3777
3777
|
if (detail !== void 0) this.detail = detail;
|
|
3778
3778
|
}
|
|
3779
3779
|
};
|
|
@@ -4059,10 +4059,10 @@ var init_profile_gate = __esm({
|
|
|
4059
4059
|
[REPLICA_ERROR2] = true;
|
|
4060
4060
|
code;
|
|
4061
4061
|
detail;
|
|
4062
|
-
constructor(
|
|
4062
|
+
constructor(code5, message, detail, options) {
|
|
4063
4063
|
super(message, options);
|
|
4064
4064
|
this.name = "ReplicaError";
|
|
4065
|
-
this.code =
|
|
4065
|
+
this.code = code5;
|
|
4066
4066
|
if (detail !== void 0) this.detail = detail;
|
|
4067
4067
|
}
|
|
4068
4068
|
};
|
|
@@ -4083,8 +4083,8 @@ import { dirname as dirname3, join as join22, resolve as resolve2 } from "path";
|
|
|
4083
4083
|
import { constants as fsConstants3 } from "fs";
|
|
4084
4084
|
import { lstat, open as open3, readdir as readdir3, rmdir, unlink } from "fs/promises";
|
|
4085
4085
|
import { join as join7, parse, resolve, sep } from "path";
|
|
4086
|
-
function isReplicaError(error,
|
|
4087
|
-
return typeof error === "object" && error !== null && error[REPLICA_ERROR3] === true && (
|
|
4086
|
+
function isReplicaError(error, code5) {
|
|
4087
|
+
return typeof error === "object" && error !== null && error[REPLICA_ERROR3] === true && (code5 === void 0 || error.code === code5);
|
|
4088
4088
|
}
|
|
4089
4089
|
function assertFolderPrefix3(prefix) {
|
|
4090
4090
|
const validFolder = typeof prefix === "string" && prefix.length > 0 && !prefix.startsWith("/") && !prefix.includes("//") && prefix.endsWith("/");
|
|
@@ -4572,9 +4572,9 @@ function entryOf(row) {
|
|
|
4572
4572
|
}
|
|
4573
4573
|
function storageError(error, action) {
|
|
4574
4574
|
if (isReplicaError(error)) return error;
|
|
4575
|
-
const
|
|
4575
|
+
const code5 = errnoOf(error);
|
|
4576
4576
|
const message = error instanceof Error ? error.message : String(error);
|
|
4577
|
-
if (
|
|
4577
|
+
if (code5 === "ENOSPC" || code5 === "EDQUOT" || /SQLITE_FULL|database or disk is full/i.test(`${String(code5)} ${message}`)) {
|
|
4578
4578
|
return new ReplicaError3(ReplicaErrorCode3.STORAGE_FULL, `${action}: the local disk is full.`, void 0, { cause: error });
|
|
4579
4579
|
}
|
|
4580
4580
|
return new ReplicaError3(ReplicaErrorCode3.STORAGE_ERROR, `${action}: ${message}`, void 0, { cause: error });
|
|
@@ -4748,10 +4748,10 @@ var init_sqlite = __esm({
|
|
|
4748
4748
|
[REPLICA_ERROR3] = true;
|
|
4749
4749
|
code;
|
|
4750
4750
|
detail;
|
|
4751
|
-
constructor(
|
|
4751
|
+
constructor(code5, message, detail, options) {
|
|
4752
4752
|
super(message, options);
|
|
4753
4753
|
this.name = "ReplicaError";
|
|
4754
|
-
this.code =
|
|
4754
|
+
this.code = code5;
|
|
4755
4755
|
if (detail !== void 0) this.detail = detail;
|
|
4756
4756
|
}
|
|
4757
4757
|
};
|
|
@@ -5327,8 +5327,8 @@ CREATE TABLE IF NOT EXISTS grant_install (
|
|
|
5327
5327
|
if (this.#readonlySnapshot) {
|
|
5328
5328
|
throw new ReplicaError3(ReplicaErrorCode3.STORAGE_ERROR, "A read-only replica snapshot cannot mutate the shared database.");
|
|
5329
5329
|
}
|
|
5330
|
-
const
|
|
5331
|
-
if (
|
|
5330
|
+
const read5 = activeReadSection.getStore();
|
|
5331
|
+
if (read5?.active && read5.controller === this) {
|
|
5332
5332
|
throw new ReplicaError3(
|
|
5333
5333
|
ReplicaErrorCode3.STORAGE_ERROR,
|
|
5334
5334
|
"mutation attempted on the same controller while its readTransaction section is active; this would deadlock"
|
|
@@ -6325,7 +6325,7 @@ function assertApprovedEntry(profile, path, actual, recorded) {
|
|
|
6325
6325
|
throw refuseUnsafeReplicaPath(profile, `legacy path "${path}" changed since the recorded inventory`);
|
|
6326
6326
|
}
|
|
6327
6327
|
}
|
|
6328
|
-
function assertRecordedChild(profile, name, layout, inventory,
|
|
6328
|
+
function assertRecordedChild(profile, name, layout, inventory, empty5) {
|
|
6329
6329
|
const prefix = `replicas/${name}/`;
|
|
6330
6330
|
const root = inventory.roots.get(`replicas/${name}`);
|
|
6331
6331
|
if (!root || root.dev !== layout.rootIdentity.dev || root.ino !== layout.rootIdentity.ino) {
|
|
@@ -6344,7 +6344,7 @@ function assertRecordedChild(profile, name, layout, inventory, empty4) {
|
|
|
6344
6344
|
}
|
|
6345
6345
|
const database = [...layout.knownEntries, ...layout.unknownEntries].some((entry) => entry.path === "replica.db");
|
|
6346
6346
|
const missingWasApproved = inventory.missingDatabases.has(prefix + "replica.db");
|
|
6347
|
-
if (missingWasApproved && database || !database && !
|
|
6347
|
+
if (missingWasApproved && database || !database && !empty5 && !missingWasApproved) {
|
|
6348
6348
|
throw refuseUnsafeReplicaPath(profile, `replica entry "${name}" has a different database than was approved`);
|
|
6349
6349
|
}
|
|
6350
6350
|
}
|
|
@@ -6426,8 +6426,8 @@ async function removeProfileReplicas(profile, options = {}) {
|
|
|
6426
6426
|
const removed = [];
|
|
6427
6427
|
const opened = [];
|
|
6428
6428
|
try {
|
|
6429
|
-
for (const { entry, identity, empty:
|
|
6430
|
-
if (!
|
|
6429
|
+
for (const { entry, identity, empty: empty5 } of checked) {
|
|
6430
|
+
if (!empty5) continue;
|
|
6431
6431
|
await pinned.assertNamed();
|
|
6432
6432
|
const current = await safeReplicaEntry(profile, root, entry);
|
|
6433
6433
|
if (current.identity.dev !== identity.dev || current.identity.ino !== identity.ino) {
|
|
@@ -6454,8 +6454,8 @@ async function removeProfileReplicas(profile, options = {}) {
|
|
|
6454
6454
|
await removeEmptyRoot(removed);
|
|
6455
6455
|
return removed;
|
|
6456
6456
|
}
|
|
6457
|
-
for (const { entry, empty:
|
|
6458
|
-
if (
|
|
6457
|
+
for (const { entry, empty: empty5, identity, layout } of checked) {
|
|
6458
|
+
if (empty5 || !layout?.knownEntries.some((item) => item.path === "replica.db")) continue;
|
|
6459
6459
|
await pinned.assertNamed();
|
|
6460
6460
|
const { path: entryPath, identity: expectedDirectory } = await safeReplicaEntry(profile, root, entry);
|
|
6461
6461
|
if (expectedDirectory.dev !== identity.dev || expectedDirectory.ino !== identity.ino) {
|
|
@@ -6488,8 +6488,8 @@ async function removeProfileReplicas(profile, options = {}) {
|
|
|
6488
6488
|
}
|
|
6489
6489
|
opened[opened.length - 1].lease = lease;
|
|
6490
6490
|
}
|
|
6491
|
-
for (const { entry, empty:
|
|
6492
|
-
if (
|
|
6491
|
+
for (const { entry, empty: empty5, path, layout } of checked) {
|
|
6492
|
+
if (empty5) continue;
|
|
6493
6493
|
await pinned.assertNamed();
|
|
6494
6494
|
const replica = opened.find(({ name }) => name === entry.name);
|
|
6495
6495
|
try {
|
|
@@ -6811,14 +6811,14 @@ async function recoverPendingLogout(name) {
|
|
|
6811
6811
|
if (report.failed.length || report.remaining) {
|
|
6812
6812
|
throw new CLIError(
|
|
6813
6813
|
"REPLICA_PURGE_FAILED",
|
|
6814
|
-
`A durable logout is pending (${report.failed.map(({ code:
|
|
6814
|
+
`A durable logout is pending (${report.failed.map(({ code: code5 }) => code5).join(", ") || `${report.remaining} intents remaining`}). Network restore and replica reads remain blocked; retry this command to complete credential and replica cleanup.`,
|
|
6815
6815
|
ExitCode.ERROR,
|
|
6816
6816
|
{ failed: report.failed, remaining: report.remaining }
|
|
6817
6817
|
);
|
|
6818
6818
|
}
|
|
6819
6819
|
}
|
|
6820
6820
|
function refuseRestoredGate(report) {
|
|
6821
|
-
if (report.failed.some(({ code:
|
|
6821
|
+
if (report.failed.some(({ code: code5 }) => code5 === "gate_restored")) {
|
|
6822
6822
|
throw new CLIError("REPLICA_GATED", RESTORED_GATE_MESSAGE, ExitCode.ERROR, { failed: report.failed });
|
|
6823
6823
|
}
|
|
6824
6824
|
}
|
|
@@ -19891,19 +19891,19 @@ function mailboxCredentialCommitment(target) {
|
|
|
19891
19891
|
credentialType: EMAIL_CREDENTIAL_TYPE
|
|
19892
19892
|
};
|
|
19893
19893
|
}
|
|
19894
|
-
function prepareAddressedShare(
|
|
19894
|
+
function prepareAddressedShare(request2) {
|
|
19895
19895
|
try {
|
|
19896
|
-
canonicalShareFilename2(
|
|
19896
|
+
canonicalShareFilename2(request2.filename);
|
|
19897
19897
|
} catch {
|
|
19898
19898
|
throw new TypeError("addressed filename is invalid");
|
|
19899
19899
|
}
|
|
19900
|
-
if (
|
|
19901
|
-
if (
|
|
19902
|
-
if (
|
|
19903
|
-
const target = normalizeShareTarget(
|
|
19900
|
+
if (request2.actions.length === 0 || request2.policyActions.length === 0) throw new TypeError("addressed share actions are empty");
|
|
19901
|
+
if (request2.policyActions.some((action) => !OWNER_SHARE_ACTIONS.has(action))) throw new TypeError("addressed share action is not supported");
|
|
19902
|
+
if (request2.deliveryEmail !== void 0 && !isEnvelopeDeliveryEmail(request2.deliveryEmail)) throw new TypeError("delivery email is not a valid envelope address");
|
|
19903
|
+
const target = normalizeShareTarget(request2.target);
|
|
19904
19904
|
if (target.kind === "bearer") throw new TypeError("addressed target is required");
|
|
19905
19905
|
if (target.kind === "recipientDid") return { target };
|
|
19906
|
-
if (target.kind === "emailDomain" &&
|
|
19906
|
+
if (target.kind === "emailDomain" && request2.deliveryEmail !== void 0 && (request2.deliveryEmail !== request2.deliveryEmail.toLowerCase() || !request2.deliveryEmail.endsWith(`@${target.domain}`))) {
|
|
19907
19907
|
throw new TypeError("email-domain delivery address must be a lowercase mailbox at the domain");
|
|
19908
19908
|
}
|
|
19909
19909
|
return { target, credentialRequirement: mailboxCredentialCommitment(target) };
|
|
@@ -20217,9 +20217,9 @@ var cache22 = /* @__PURE__ */ new WeakMap();
|
|
|
20217
20217
|
function baseCache22(cid2) {
|
|
20218
20218
|
const baseCache32 = cache22.get(cid2);
|
|
20219
20219
|
if (baseCache32 == null) {
|
|
20220
|
-
const
|
|
20221
|
-
cache22.set(cid2,
|
|
20222
|
-
return
|
|
20220
|
+
const baseCache42 = /* @__PURE__ */ new Map();
|
|
20221
|
+
cache22.set(cid2, baseCache42);
|
|
20222
|
+
return baseCache42;
|
|
20223
20223
|
}
|
|
20224
20224
|
return baseCache32;
|
|
20225
20225
|
}
|
|
@@ -20887,6 +20887,9 @@ function parseNativeShareUrl(value) {
|
|
|
20887
20887
|
return token;
|
|
20888
20888
|
}
|
|
20889
20889
|
|
|
20890
|
+
// ../share-envelope/dist/index.js
|
|
20891
|
+
init_sha2();
|
|
20892
|
+
|
|
20890
20893
|
// ../../node_modules/zod/v3/external.js
|
|
20891
20894
|
var external_exports3 = {};
|
|
20892
20895
|
__export(external_exports3, {
|
|
@@ -21881,8 +21884,8 @@ function isValidJWT3(jwt, alg) {
|
|
|
21881
21884
|
const [header] = jwt.split(".");
|
|
21882
21885
|
if (!header)
|
|
21883
21886
|
return false;
|
|
21884
|
-
const
|
|
21885
|
-
const decoded = JSON.parse(atob(
|
|
21887
|
+
const base645 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "=");
|
|
21888
|
+
const decoded = JSON.parse(atob(base645));
|
|
21886
21889
|
if (typeof decoded !== "object" || decoded === null)
|
|
21887
21890
|
return false;
|
|
21888
21891
|
if ("typ" in decoded && decoded?.typ !== "JWT")
|
|
@@ -24536,23 +24539,23 @@ var ZodEffects3 = class extends ZodType3 {
|
|
|
24536
24539
|
}
|
|
24537
24540
|
if (effect.type === "transform") {
|
|
24538
24541
|
if (ctx.common.async === false) {
|
|
24539
|
-
const
|
|
24542
|
+
const base5 = this._def.schema._parseSync({
|
|
24540
24543
|
data: ctx.data,
|
|
24541
24544
|
path: ctx.path,
|
|
24542
24545
|
parent: ctx
|
|
24543
24546
|
});
|
|
24544
|
-
if (!isValid3(
|
|
24547
|
+
if (!isValid3(base5))
|
|
24545
24548
|
return INVALID3;
|
|
24546
|
-
const result = effect.transform(
|
|
24549
|
+
const result = effect.transform(base5.value, checkCtx);
|
|
24547
24550
|
if (result instanceof Promise) {
|
|
24548
24551
|
throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
|
|
24549
24552
|
}
|
|
24550
24553
|
return { status: status.value, value: result };
|
|
24551
24554
|
} else {
|
|
24552
|
-
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((
|
|
24553
|
-
if (!isValid3(
|
|
24555
|
+
return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base5) => {
|
|
24556
|
+
if (!isValid3(base5))
|
|
24554
24557
|
return INVALID3;
|
|
24555
|
-
return Promise.resolve(effect.transform(
|
|
24558
|
+
return Promise.resolve(effect.transform(base5.value, checkCtx)).then((result) => ({
|
|
24556
24559
|
status: status.value,
|
|
24557
24560
|
value: result
|
|
24558
24561
|
}));
|
|
@@ -25785,6 +25788,10 @@ function encodeCID3(version2, code22, multihash) {
|
|
|
25785
25788
|
var cidSymbol3 = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
|
|
25786
25789
|
var code3 = 85;
|
|
25787
25790
|
var SHA256_CODE3 = 18;
|
|
25791
|
+
async function computeCid2(bytes) {
|
|
25792
|
+
const digest = create3(SHA256_CODE3, sha256(new Uint8Array(bytes)));
|
|
25793
|
+
return CID3.create(1, code3, digest).toString();
|
|
25794
|
+
}
|
|
25788
25795
|
function isCanonicalRawCid3(cidString) {
|
|
25789
25796
|
let cid;
|
|
25790
25797
|
try {
|
|
@@ -25818,6 +25825,9 @@ var base64urlpad3 = rfc46483({
|
|
|
25818
25825
|
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
|
|
25819
25826
|
bitsPerChar: 6
|
|
25820
25827
|
});
|
|
25828
|
+
function toBase64Url2(bytes) {
|
|
25829
|
+
return base64url3.baseEncode(bytes);
|
|
25830
|
+
}
|
|
25821
25831
|
function fromBase64Url3(text) {
|
|
25822
25832
|
const bytes = base64url3.baseDecode(text);
|
|
25823
25833
|
if (base64url3.baseEncode(bytes) !== text) {
|
|
@@ -26315,7 +26325,71 @@ function canonicalMailbox2(value) {
|
|
|
26315
26325
|
if (local.length > 64 || !/^[a-z0-9#$&'*+/=?^_`{|}~-]+(?:\.[a-z0-9#$&'*+/=?^_`{|}~-]+)*$/.test(local) || !isCanonicalEmailDomain2(domain)) return void 0;
|
|
26316
26326
|
return Object.freeze({ email, domain });
|
|
26317
26327
|
}
|
|
26328
|
+
var KEY_LENGTH22 = 32;
|
|
26318
26329
|
var MAX_INLINE_BYTES3 = 256 * 1024;
|
|
26330
|
+
function assertCanonicalCid2(cidString) {
|
|
26331
|
+
const cid = CID3.parse(cidString);
|
|
26332
|
+
if (cid.version !== 1 || cid.code !== code3 || cid.multihash.code !== 18 || // sha2-256 (0x12) only, at the link layer too
|
|
26333
|
+
cid.toString() !== cidString) {
|
|
26334
|
+
throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
|
|
26335
|
+
}
|
|
26336
|
+
}
|
|
26337
|
+
async function encodeSealedInlineShareUrl2(parts) {
|
|
26338
|
+
if (!isCanonicalHttpsOrigin3(parts.origin)) throw new TypeError("origin must be a canonical https origin");
|
|
26339
|
+
if (parts.ciphertext.byteLength === 0 || parts.ciphertext.byteLength > MAX_INLINE_BYTES3) throw new RangeError("inline ciphertext is outside the allowed size");
|
|
26340
|
+
if (parts.key32.byteLength !== KEY_LENGTH22) throw new TypeError("inline key must be 32 bytes");
|
|
26341
|
+
const ciphertextCid = await computeCid2(parts.ciphertext);
|
|
26342
|
+
const payload = canonicalize3({
|
|
26343
|
+
v: 2,
|
|
26344
|
+
c: toBase64Url2(parts.ciphertext),
|
|
26345
|
+
cid: ciphertextCid,
|
|
26346
|
+
k: toBase64Url2(parts.key32)
|
|
26347
|
+
});
|
|
26348
|
+
const payloadBytes = new TextEncoder().encode(payload);
|
|
26349
|
+
if (payloadBytes.byteLength > MAX_INLINE_BYTES3 * 2) throw new RangeError("inline URL is too large");
|
|
26350
|
+
return `${parts.origin}/s/inline#v=2&p=${toBase64Url2(payloadBytes)}`;
|
|
26351
|
+
}
|
|
26352
|
+
async function parseSealedInlineShareUrl2(url, options = {}) {
|
|
26353
|
+
const parsed = new URL(url);
|
|
26354
|
+
if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("sealed inline share URL must be canonical HTTPS without userinfo");
|
|
26355
|
+
if (!isCanonicalHttpsOrigin3(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("sealed inline share URL origin is not trusted");
|
|
26356
|
+
if (parsed.pathname !== "/s/inline" || parsed.search !== "") throw new TypeError("not a Node sealed-inline share URL");
|
|
26357
|
+
if (url !== `${parsed.origin}/s/inline${parsed.hash}`) throw new TypeError("sealed inline share URL is not lexically canonical");
|
|
26358
|
+
const prefix = "#v=2&p=";
|
|
26359
|
+
if (!parsed.hash.startsWith(prefix)) throw new TypeError("sealed inline URL is missing its canonical fragment");
|
|
26360
|
+
const encoded = parsed.hash.slice(prefix.length);
|
|
26361
|
+
if (encoded.length === 0 || parsed.hash !== `${prefix}${encoded}`) throw new TypeError("sealed inline URL fragment is not canonical");
|
|
26362
|
+
let payloadBytes;
|
|
26363
|
+
try {
|
|
26364
|
+
payloadBytes = fromBase64Url3(encoded);
|
|
26365
|
+
} catch {
|
|
26366
|
+
throw new TypeError("sealed inline payload is not canonical base64url");
|
|
26367
|
+
}
|
|
26368
|
+
if (payloadBytes.byteLength === 0 || payloadBytes.byteLength > MAX_INLINE_BYTES3 * 2) throw new TypeError("sealed inline payload is too large");
|
|
26369
|
+
const payloadText = new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes);
|
|
26370
|
+
let value;
|
|
26371
|
+
try {
|
|
26372
|
+
value = JSON.parse(payloadText);
|
|
26373
|
+
} catch {
|
|
26374
|
+
throw new TypeError("sealed inline payload is not valid JSON");
|
|
26375
|
+
}
|
|
26376
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize3(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
|
|
26377
|
+
const record2 = value;
|
|
26378
|
+
if (Object.keys(record2).length !== 4 || record2.v !== 2 || typeof record2.c !== "string" || typeof record2.cid !== "string" || typeof record2.k !== "string") throw new TypeError("sealed inline payload has invalid fields");
|
|
26379
|
+
let ciphertext;
|
|
26380
|
+
let key32;
|
|
26381
|
+
try {
|
|
26382
|
+
ciphertext = fromBase64Url3(record2.c);
|
|
26383
|
+
key32 = fromBase64Url3(record2.k);
|
|
26384
|
+
} catch {
|
|
26385
|
+
throw new TypeError("sealed inline payload has invalid base64url material");
|
|
26386
|
+
}
|
|
26387
|
+
if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES3) throw new TypeError("sealed inline ciphertext is outside the allowed size");
|
|
26388
|
+
if (key32.byteLength !== KEY_LENGTH22) throw new TypeError("sealed inline key must be 32 bytes");
|
|
26389
|
+
assertCanonicalCid2(record2.cid);
|
|
26390
|
+
if (await computeCid2(ciphertext) !== record2.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
|
|
26391
|
+
return { kind: "inline", ciphertextCid: record2.cid, ciphertext, key32 };
|
|
26392
|
+
}
|
|
26319
26393
|
|
|
26320
26394
|
// src/commands/share.ts
|
|
26321
26395
|
import { ProfileLockTimeoutError as ProfileLockTimeoutError2 } from "@tinycloud/operations/state";
|
|
@@ -26366,16 +26440,16 @@ function statusOf(error, depth = 0) {
|
|
|
26366
26440
|
return direct ?? (depth === 0 ? statusOf(fields.cause, 1) : void 0);
|
|
26367
26441
|
}
|
|
26368
26442
|
function codeOf(error) {
|
|
26369
|
-
const
|
|
26370
|
-
return typeof
|
|
26443
|
+
const code5 = record(error)?.code;
|
|
26444
|
+
return typeof code5 === "string" && /^[A-Z][A-Z0-9_]{2,63}$/.test(code5) ? code5 : void 0;
|
|
26371
26445
|
}
|
|
26372
26446
|
function classifyShareFailure(error, loginHint) {
|
|
26373
26447
|
const status = statusOf(error);
|
|
26374
26448
|
const verdict = authorizationVerdictOf2(error);
|
|
26375
26449
|
const message = error instanceof Error ? error.message : "";
|
|
26376
|
-
const
|
|
26450
|
+
const code5 = codeOf(error);
|
|
26377
26451
|
const detail = (text) => {
|
|
26378
|
-
const parts = [status === void 0 ? void 0 : `HTTP ${status}`,
|
|
26452
|
+
const parts = [status === void 0 ? void 0 : `HTTP ${status}`, code5].filter((part) => part !== void 0);
|
|
26379
26453
|
return parts.length === 0 ? text : `${text} (${parts.join(", ")})`;
|
|
26380
26454
|
};
|
|
26381
26455
|
if (verdict === "unauthenticated" || status === 401) {
|
|
@@ -26414,8 +26488,8 @@ function authorizationRequiredJson(result) {
|
|
|
26414
26488
|
next: "complete authorization through the configured authority adapter, then retry with the required proof"
|
|
26415
26489
|
};
|
|
26416
26490
|
}
|
|
26417
|
-
function publishHuman(
|
|
26418
|
-
process.stdout.write(`${
|
|
26491
|
+
function publishHuman(url) {
|
|
26492
|
+
process.stdout.write(`${url}
|
|
26419
26493
|
`);
|
|
26420
26494
|
}
|
|
26421
26495
|
function inspectHuman(result) {
|
|
@@ -26584,10 +26658,10 @@ function kvArtifactStore(kv) {
|
|
|
26584
26658
|
throw new ArtifactError("storage", `could not write ${key}: ${errorCode(written.error) ?? "unknown error"}`, { cause: written.error });
|
|
26585
26659
|
},
|
|
26586
26660
|
async get(key) {
|
|
26587
|
-
const
|
|
26588
|
-
if (
|
|
26589
|
-
if (errorCode(
|
|
26590
|
-
throw new ArtifactError("storage", `could not read ${key}: ${errorCode(
|
|
26661
|
+
const read5 = await kv.get(key, { binary: true });
|
|
26662
|
+
if (read5.ok) return new Uint8Array(read5.data.data);
|
|
26663
|
+
if (errorCode(read5.error) === "KV_NOT_FOUND") return void 0;
|
|
26664
|
+
throw new ArtifactError("storage", `could not read ${key}: ${errorCode(read5.error) ?? "unknown error"}`, { cause: read5.error });
|
|
26591
26665
|
},
|
|
26592
26666
|
async list(prefix) {
|
|
26593
26667
|
const keys = [];
|
|
@@ -26605,206 +26679,1904 @@ function kvArtifactStore(kv) {
|
|
|
26605
26679
|
};
|
|
26606
26680
|
}
|
|
26607
26681
|
|
|
26608
|
-
//
|
|
26609
|
-
|
|
26610
|
-
|
|
26611
|
-
|
|
26612
|
-
|
|
26613
|
-
|
|
26614
|
-
}
|
|
26615
|
-
};
|
|
26616
|
-
var ShareHistoryRetryError = class extends Error {
|
|
26617
|
-
constructor(profile) {
|
|
26618
|
-
super("sender history changed during the operation");
|
|
26619
|
-
this.profile = profile;
|
|
26620
|
-
this.name = "ShareHistoryRetryError";
|
|
26682
|
+
// ../share-envelope/dist/short-link.js
|
|
26683
|
+
init_sha2();
|
|
26684
|
+
var empty4 = new Uint8Array(0);
|
|
26685
|
+
function equals6(aa, bb) {
|
|
26686
|
+
if (aa === bb) {
|
|
26687
|
+
return true;
|
|
26621
26688
|
}
|
|
26622
|
-
|
|
26623
|
-
|
|
26624
|
-
var ShareHistoryUnreadableError = class extends Error {
|
|
26625
|
-
constructor() {
|
|
26626
|
-
super("share history is unavailable");
|
|
26627
|
-
this.name = "ShareHistoryUnreadableError";
|
|
26689
|
+
if (aa.byteLength !== bb.byteLength) {
|
|
26690
|
+
return false;
|
|
26628
26691
|
}
|
|
26629
|
-
|
|
26630
|
-
|
|
26631
|
-
|
|
26632
|
-
|
|
26633
|
-
this.name = "ShareHistoryReadError";
|
|
26692
|
+
for (let ii = 0; ii < aa.byteLength; ii++) {
|
|
26693
|
+
if (aa[ii] !== bb[ii]) {
|
|
26694
|
+
return false;
|
|
26695
|
+
}
|
|
26634
26696
|
}
|
|
26635
|
-
|
|
26636
|
-
var HISTORY_WRITE_ERROR_CODES = { EACCES: true, EPERM: true, EROFS: true, ENOSPC: true, EDQUOT: true, EIO: true };
|
|
26637
|
-
function shareHistoryReason(error) {
|
|
26638
|
-
if (error instanceof ShareHistoryUnreadableError) return "HISTORY_UNREADABLE";
|
|
26639
|
-
if (error instanceof ShareHistoryReadError) return "HISTORY_READ_FAILED";
|
|
26640
|
-
const code4 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
|
|
26641
|
-
return typeof code4 === "string" && HISTORY_WRITE_ERROR_CODES[code4] === true ? "HISTORY_WRITE_FAILED" : "HISTORY_UNAVAILABLE";
|
|
26642
|
-
}
|
|
26643
|
-
|
|
26644
|
-
// src/share/space-not-ready.ts
|
|
26645
|
-
function isSpaceNotFound(error) {
|
|
26646
|
-
if (typeof error !== "object" || error === null) return false;
|
|
26647
|
-
const message = "message" in error && typeof error.message === "string" ? error.message : "";
|
|
26648
|
-
if (!/space not found/i.test(message)) return false;
|
|
26649
|
-
const meta = "meta" in error && typeof error.meta === "object" && error.meta !== null ? error.meta : void 0;
|
|
26650
|
-
const status = meta !== void 0 && "status" in meta ? meta.status : void 0;
|
|
26651
|
-
return status === 404 || /\b404\b/.test(message);
|
|
26652
|
-
}
|
|
26653
|
-
function spaceNotReadyFailure(cause) {
|
|
26654
|
-
return new SharePublishAuthorityError({ kind: "space-not-ready" }, { cause });
|
|
26655
|
-
}
|
|
26656
|
-
function failIfSpaceNotReady(result) {
|
|
26657
|
-
if (!result.ok && isSpaceNotFound(result.error)) throw spaceNotReadyFailure(result.error);
|
|
26658
|
-
}
|
|
26659
|
-
function artifactSpaceNotReady(error) {
|
|
26660
|
-
return error instanceof ArtifactError && isSpaceNotFound(error.cause) ? spaceNotReadyFailure(error.cause) : error;
|
|
26661
|
-
}
|
|
26662
|
-
|
|
26663
|
-
// src/share/adapters.ts
|
|
26664
|
-
init_storage();
|
|
26665
|
-
init_profiles();
|
|
26666
|
-
init_constants();
|
|
26667
|
-
init_errors();
|
|
26668
|
-
init_session_expired();
|
|
26669
|
-
import { chmod as chmod4, link as link3, open as open8, readFile as readFile7, stat as stat5, unlink as unlink5 } from "fs/promises";
|
|
26670
|
-
import { dirname as dirname5, join as join12 } from "path";
|
|
26671
|
-
import { createHash } from "crypto";
|
|
26672
|
-
import { writeJsonAtomic as writeJsonAtomic2 } from "@tinycloud/operations/state";
|
|
26673
|
-
import { withoutBearer } from "@tinycloud/operations/delegation-binding";
|
|
26674
|
-
import {
|
|
26675
|
-
LocationRecordValidationError,
|
|
26676
|
-
LocationRegistryHttpError,
|
|
26677
|
-
parseSignedCompactUcanAttenuation,
|
|
26678
|
-
parseSignedSiweCacao,
|
|
26679
|
-
revokePolicyRootV3,
|
|
26680
|
-
signCompactUcanAuthorization
|
|
26681
|
-
} from "@tinycloud/sdk-core";
|
|
26682
|
-
import { extractSiweExpiration, InvalidRestoredSessionError } from "@tinycloud/node-sdk";
|
|
26683
|
-
function requiredKvAction(meta) {
|
|
26684
|
-
if (meta === null || typeof meta !== "object" || !("requiredAction" in meta)) return void 0;
|
|
26685
|
-
const action = meta.requiredAction;
|
|
26686
|
-
return action === "tinycloud.kv/put" || action === "tinycloud.kv/get" || action === "tinycloud.kv/list" ? action : void 0;
|
|
26687
|
-
}
|
|
26688
|
-
function throwKvUploadFailure(error) {
|
|
26689
|
-
const rejection = storageRejection(error);
|
|
26690
|
-
if (rejection) throw new SharePublishAuthorityError({ kind: "storage-full", ...rejection });
|
|
26691
|
-
throw new SharePublishAuthorityError({ kind: "upload-failed" });
|
|
26692
|
-
}
|
|
26693
|
-
var DEFAULT_SHARE_ORIGIN = "https://share.tinycloud.xyz";
|
|
26694
|
-
var MIN_DOMAIN_DELIVERY_VERSION = "1.17.3";
|
|
26695
|
-
function supportsDomainDelivery(version2) {
|
|
26696
|
-
if (typeof version2 !== "string") return false;
|
|
26697
|
-
const normalized = version2.trim();
|
|
26698
|
-
if (normalized.length > 128) return false;
|
|
26699
|
-
const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.exec(normalized);
|
|
26700
|
-
if (match === null) return false;
|
|
26701
|
-
if (match[4] !== void 0 && /(?:^|\.)0[0-9]+(?:\.|$)/.test(match[4])) return false;
|
|
26702
|
-
const major = Number(match[1]);
|
|
26703
|
-
const minor = Number(match[2]);
|
|
26704
|
-
const patch = Number(match[3]);
|
|
26705
|
-
if (!Number.isSafeInteger(major) || !Number.isSafeInteger(minor) || !Number.isSafeInteger(patch)) return false;
|
|
26706
|
-
if (major !== 1) return major > 1;
|
|
26707
|
-
if (minor !== 17) return minor > 17;
|
|
26708
|
-
if (patch !== 3) return patch > 3;
|
|
26709
|
-
return match[4] === void 0;
|
|
26710
|
-
}
|
|
26711
|
-
function displayedNodeVersion(version2) {
|
|
26712
|
-
if (typeof version2 !== "string") return "(unrecognized)";
|
|
26713
|
-
const trimmed = version2.trim();
|
|
26714
|
-
return /^[A-Za-z0-9.+_-]{1,64}$/.test(trimmed) ? trimmed : "(unrecognized)";
|
|
26715
|
-
}
|
|
26716
|
-
var URI_SAFE_FILENAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
26717
|
-
function safeStorageFilename(filename) {
|
|
26718
|
-
if (URI_SAFE_FILENAME.test(filename) && !filename.includes("..")) return filename;
|
|
26719
|
-
const dot = filename.lastIndexOf(".");
|
|
26720
|
-
const extension = dot >= 0 && /^[A-Za-z0-9]{1,16}$/.test(filename.slice(dot + 1)) ? filename.slice(dot + 1) : "";
|
|
26721
|
-
const stem = (extension === "" ? filename : filename.slice(0, dot)).normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(extension === "" ? /[^A-Za-z0-9_-]+/g : /[^A-Za-z0-9._-]+/g, "-").replace(/\.{2,}/g, ".").replace(/-{2,}/g, "-").slice(0, 100).replace(/^[^A-Za-z0-9]+|[-.]+$/g, "");
|
|
26722
|
-
return `${stem === "" ? "share" : stem}${extension === "" ? "" : `.${extension}`}`;
|
|
26723
|
-
}
|
|
26724
|
-
function scopeDeniedFromArtifactError(error, capability, authority) {
|
|
26725
|
-
const cause = error instanceof ArtifactError ? error.cause : void 0;
|
|
26726
|
-
const code4 = typeof cause === "object" && cause !== null && "code" in cause ? cause.code : void 0;
|
|
26727
|
-
if (code4 !== "AUTH_UNAUTHORIZED" && code4 !== "PERMISSION_DENIED") return void 0;
|
|
26728
|
-
const meta = typeof cause === "object" && cause !== null && "meta" in cause ? cause.meta : void 0;
|
|
26729
|
-
const requiredAction = requiredKvAction(meta);
|
|
26730
|
-
return new SharePublishAuthorityError({
|
|
26731
|
-
kind: "scope-denied",
|
|
26732
|
-
capability,
|
|
26733
|
-
...requiredAction === void 0 ? {} : { requiredAction },
|
|
26734
|
-
localKey: authority.localKey,
|
|
26735
|
-
profileName: authority.profileName
|
|
26736
|
-
});
|
|
26697
|
+
return true;
|
|
26737
26698
|
}
|
|
26738
|
-
|
|
26739
|
-
|
|
26740
|
-
return
|
|
26741
|
-
}
|
|
26742
|
-
|
|
26699
|
+
function coerce6(o) {
|
|
26700
|
+
if (o instanceof Uint8Array && o.constructor.name === "Uint8Array") {
|
|
26701
|
+
return o;
|
|
26702
|
+
}
|
|
26703
|
+
if (o instanceof ArrayBuffer) {
|
|
26704
|
+
return new Uint8Array(o);
|
|
26705
|
+
}
|
|
26706
|
+
if (ArrayBuffer.isView(o)) {
|
|
26707
|
+
return new Uint8Array(o.buffer, o.byteOffset, o.byteLength);
|
|
26743
26708
|
}
|
|
26709
|
+
throw new Error("Unknown type, must be binary type");
|
|
26744
26710
|
}
|
|
26745
|
-
function
|
|
26746
|
-
|
|
26747
|
-
|
|
26748
|
-
|
|
26749
|
-
|
|
26750
|
-
|
|
26751
|
-
|
|
26752
|
-
}
|
|
26753
|
-
|
|
26754
|
-
|
|
26755
|
-
|
|
26756
|
-
|
|
26757
|
-
|
|
26758
|
-
const encrypted = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, await key(), secret));
|
|
26759
|
-
const value = new Uint8Array(iv.length + encrypted.length);
|
|
26760
|
-
value.set(iv);
|
|
26761
|
-
value.set(encrypted, iv.length);
|
|
26762
|
-
return value;
|
|
26763
|
-
};
|
|
26764
|
-
const decode10 = async (value) => JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await crypto.subtle.decrypt({ name: "AES-GCM", iv: value.slice(0, 12) }, await key(), value.slice(12))));
|
|
26765
|
-
return {
|
|
26766
|
-
async put(record2) {
|
|
26767
|
-
return serial(async () => {
|
|
26768
|
-
records.set(record2.shareId, await encode6(record2));
|
|
26769
|
-
});
|
|
26770
|
-
},
|
|
26771
|
-
async update(shareId, change) {
|
|
26772
|
-
return serial(async () => {
|
|
26773
|
-
const value = records.get(shareId);
|
|
26774
|
-
if (value === void 0) return void 0;
|
|
26775
|
-
const updated = await change(await decode10(value));
|
|
26776
|
-
records.set(shareId, await encode6(updated));
|
|
26777
|
-
return updated;
|
|
26778
|
-
});
|
|
26779
|
-
},
|
|
26780
|
-
async list() {
|
|
26781
|
-
return serial(() => Promise.all([...records.values()].map(decode10)));
|
|
26782
|
-
},
|
|
26783
|
-
async get(shareId) {
|
|
26784
|
-
return serial(async () => {
|
|
26785
|
-
const value = records.get(shareId);
|
|
26786
|
-
return value === void 0 ? void 0 : decode10(value);
|
|
26787
|
-
});
|
|
26788
|
-
},
|
|
26789
|
-
async delete(shareId) {
|
|
26790
|
-
return serial(async () => {
|
|
26791
|
-
records.delete(shareId);
|
|
26792
|
-
});
|
|
26711
|
+
function base4(ALPHABET, name) {
|
|
26712
|
+
if (ALPHABET.length >= 255) {
|
|
26713
|
+
throw new TypeError("Alphabet too long");
|
|
26714
|
+
}
|
|
26715
|
+
var BASE_MAP = new Uint8Array(256);
|
|
26716
|
+
for (var j = 0; j < BASE_MAP.length; j++) {
|
|
26717
|
+
BASE_MAP[j] = 255;
|
|
26718
|
+
}
|
|
26719
|
+
for (var i = 0; i < ALPHABET.length; i++) {
|
|
26720
|
+
var x = ALPHABET.charAt(i);
|
|
26721
|
+
var xc = x.charCodeAt(0);
|
|
26722
|
+
if (BASE_MAP[xc] !== 255) {
|
|
26723
|
+
throw new TypeError(x + " is ambiguous");
|
|
26793
26724
|
}
|
|
26794
|
-
|
|
26795
|
-
}
|
|
26796
|
-
var
|
|
26797
|
-
var
|
|
26798
|
-
var
|
|
26799
|
-
|
|
26800
|
-
|
|
26801
|
-
|
|
26802
|
-
|
|
26803
|
-
|
|
26804
|
-
|
|
26805
|
-
}
|
|
26806
|
-
|
|
26807
|
-
|
|
26725
|
+
BASE_MAP[xc] = i;
|
|
26726
|
+
}
|
|
26727
|
+
var BASE = ALPHABET.length;
|
|
26728
|
+
var LEADER = ALPHABET.charAt(0);
|
|
26729
|
+
var FACTOR = Math.log(BASE) / Math.log(256);
|
|
26730
|
+
var iFACTOR = Math.log(256) / Math.log(BASE);
|
|
26731
|
+
function encode33(source) {
|
|
26732
|
+
if (source instanceof Uint8Array)
|
|
26733
|
+
;
|
|
26734
|
+
else if (ArrayBuffer.isView(source)) {
|
|
26735
|
+
source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
|
|
26736
|
+
} else if (Array.isArray(source)) {
|
|
26737
|
+
source = Uint8Array.from(source);
|
|
26738
|
+
}
|
|
26739
|
+
if (!(source instanceof Uint8Array)) {
|
|
26740
|
+
throw new TypeError("Expected Uint8Array");
|
|
26741
|
+
}
|
|
26742
|
+
if (source.length === 0) {
|
|
26743
|
+
return "";
|
|
26744
|
+
}
|
|
26745
|
+
var zeroes = 0;
|
|
26746
|
+
var length23 = 0;
|
|
26747
|
+
var pbegin = 0;
|
|
26748
|
+
var pend = source.length;
|
|
26749
|
+
while (pbegin !== pend && source[pbegin] === 0) {
|
|
26750
|
+
pbegin++;
|
|
26751
|
+
zeroes++;
|
|
26752
|
+
}
|
|
26753
|
+
var size = (pend - pbegin) * iFACTOR + 1 >>> 0;
|
|
26754
|
+
var b58 = new Uint8Array(size);
|
|
26755
|
+
while (pbegin !== pend) {
|
|
26756
|
+
var carry = source[pbegin];
|
|
26757
|
+
var i2 = 0;
|
|
26758
|
+
for (var it1 = size - 1; (carry !== 0 || i2 < length23) && it1 !== -1; it1--, i2++) {
|
|
26759
|
+
carry += 256 * b58[it1] >>> 0;
|
|
26760
|
+
b58[it1] = carry % BASE >>> 0;
|
|
26761
|
+
carry = carry / BASE >>> 0;
|
|
26762
|
+
}
|
|
26763
|
+
if (carry !== 0) {
|
|
26764
|
+
throw new Error("Non-zero carry");
|
|
26765
|
+
}
|
|
26766
|
+
length23 = i2;
|
|
26767
|
+
pbegin++;
|
|
26768
|
+
}
|
|
26769
|
+
var it2 = size - length23;
|
|
26770
|
+
while (it2 !== size && b58[it2] === 0) {
|
|
26771
|
+
it2++;
|
|
26772
|
+
}
|
|
26773
|
+
var str = LEADER.repeat(zeroes);
|
|
26774
|
+
for (; it2 < size; ++it2) {
|
|
26775
|
+
str += ALPHABET.charAt(b58[it2]);
|
|
26776
|
+
}
|
|
26777
|
+
return str;
|
|
26778
|
+
}
|
|
26779
|
+
function decodeUnsafe(source) {
|
|
26780
|
+
if (typeof source !== "string") {
|
|
26781
|
+
throw new TypeError("Expected String");
|
|
26782
|
+
}
|
|
26783
|
+
if (source.length === 0) {
|
|
26784
|
+
return new Uint8Array();
|
|
26785
|
+
}
|
|
26786
|
+
var psz = 0;
|
|
26787
|
+
if (source[psz] === " ") {
|
|
26788
|
+
return;
|
|
26789
|
+
}
|
|
26790
|
+
var zeroes = 0;
|
|
26791
|
+
var length23 = 0;
|
|
26792
|
+
while (source[psz] === LEADER) {
|
|
26793
|
+
zeroes++;
|
|
26794
|
+
psz++;
|
|
26795
|
+
}
|
|
26796
|
+
var size = (source.length - psz) * FACTOR + 1 >>> 0;
|
|
26797
|
+
var b256 = new Uint8Array(size);
|
|
26798
|
+
while (source[psz]) {
|
|
26799
|
+
var carry = BASE_MAP[source.charCodeAt(psz)];
|
|
26800
|
+
if (carry === 255) {
|
|
26801
|
+
return;
|
|
26802
|
+
}
|
|
26803
|
+
var i2 = 0;
|
|
26804
|
+
for (var it3 = size - 1; (carry !== 0 || i2 < length23) && it3 !== -1; it3--, i2++) {
|
|
26805
|
+
carry += BASE * b256[it3] >>> 0;
|
|
26806
|
+
b256[it3] = carry % 256 >>> 0;
|
|
26807
|
+
carry = carry / 256 >>> 0;
|
|
26808
|
+
}
|
|
26809
|
+
if (carry !== 0) {
|
|
26810
|
+
throw new Error("Non-zero carry");
|
|
26811
|
+
}
|
|
26812
|
+
length23 = i2;
|
|
26813
|
+
psz++;
|
|
26814
|
+
}
|
|
26815
|
+
if (source[psz] === " ") {
|
|
26816
|
+
return;
|
|
26817
|
+
}
|
|
26818
|
+
var it4 = size - length23;
|
|
26819
|
+
while (it4 !== size && b256[it4] === 0) {
|
|
26820
|
+
it4++;
|
|
26821
|
+
}
|
|
26822
|
+
var vch = new Uint8Array(zeroes + (size - it4));
|
|
26823
|
+
var j2 = zeroes;
|
|
26824
|
+
while (it4 !== size) {
|
|
26825
|
+
vch[j2++] = b256[it4++];
|
|
26826
|
+
}
|
|
26827
|
+
return vch;
|
|
26828
|
+
}
|
|
26829
|
+
function decode53(string) {
|
|
26830
|
+
var buffer = decodeUnsafe(string);
|
|
26831
|
+
if (buffer) {
|
|
26832
|
+
return buffer;
|
|
26833
|
+
}
|
|
26834
|
+
throw new Error(`Non-${name} character`);
|
|
26835
|
+
}
|
|
26836
|
+
return {
|
|
26837
|
+
encode: encode33,
|
|
26838
|
+
decodeUnsafe,
|
|
26839
|
+
decode: decode53
|
|
26840
|
+
};
|
|
26841
|
+
}
|
|
26842
|
+
var src4 = base4;
|
|
26843
|
+
var _brrp__multiformats_scope_baseX4 = src4;
|
|
26844
|
+
var base_x_default4 = _brrp__multiformats_scope_baseX4;
|
|
26845
|
+
var Encoder4 = class {
|
|
26846
|
+
name;
|
|
26847
|
+
prefix;
|
|
26848
|
+
baseEncode;
|
|
26849
|
+
constructor(name, prefix, baseEncode) {
|
|
26850
|
+
this.name = name;
|
|
26851
|
+
this.prefix = prefix;
|
|
26852
|
+
this.baseEncode = baseEncode;
|
|
26853
|
+
}
|
|
26854
|
+
encode(bytes) {
|
|
26855
|
+
if (bytes instanceof Uint8Array) {
|
|
26856
|
+
return `${this.prefix}${this.baseEncode(bytes)}`;
|
|
26857
|
+
} else {
|
|
26858
|
+
throw Error("Unknown type, must be binary type");
|
|
26859
|
+
}
|
|
26860
|
+
}
|
|
26861
|
+
};
|
|
26862
|
+
var Decoder4 = class {
|
|
26863
|
+
name;
|
|
26864
|
+
prefix;
|
|
26865
|
+
baseDecode;
|
|
26866
|
+
prefixCodePoint;
|
|
26867
|
+
constructor(name, prefix, baseDecode) {
|
|
26868
|
+
this.name = name;
|
|
26869
|
+
this.prefix = prefix;
|
|
26870
|
+
const prefixCodePoint = prefix.codePointAt(0);
|
|
26871
|
+
if (prefixCodePoint === void 0) {
|
|
26872
|
+
throw new Error("Invalid prefix character");
|
|
26873
|
+
}
|
|
26874
|
+
this.prefixCodePoint = prefixCodePoint;
|
|
26875
|
+
this.baseDecode = baseDecode;
|
|
26876
|
+
}
|
|
26877
|
+
decode(text) {
|
|
26878
|
+
if (typeof text === "string") {
|
|
26879
|
+
if (text.codePointAt(0) !== this.prefixCodePoint) {
|
|
26880
|
+
throw Error(`Unable to decode multibase string ${JSON.stringify(text)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`);
|
|
26881
|
+
}
|
|
26882
|
+
return this.baseDecode(text.slice(this.prefix.length));
|
|
26883
|
+
} else {
|
|
26884
|
+
throw Error("Can only multibase decode strings");
|
|
26885
|
+
}
|
|
26886
|
+
}
|
|
26887
|
+
or(decoder) {
|
|
26888
|
+
return or4(this, decoder);
|
|
26889
|
+
}
|
|
26890
|
+
};
|
|
26891
|
+
var ComposedDecoder4 = class {
|
|
26892
|
+
decoders;
|
|
26893
|
+
constructor(decoders) {
|
|
26894
|
+
this.decoders = decoders;
|
|
26895
|
+
}
|
|
26896
|
+
or(decoder) {
|
|
26897
|
+
return or4(this, decoder);
|
|
26898
|
+
}
|
|
26899
|
+
decode(input) {
|
|
26900
|
+
const prefix = input[0];
|
|
26901
|
+
const decoder = this.decoders[prefix];
|
|
26902
|
+
if (decoder != null) {
|
|
26903
|
+
return decoder.decode(input);
|
|
26904
|
+
} else {
|
|
26905
|
+
throw RangeError(`Unable to decode multibase string ${JSON.stringify(input)}, only inputs prefixed with ${Object.keys(this.decoders)} are supported`);
|
|
26906
|
+
}
|
|
26907
|
+
}
|
|
26908
|
+
};
|
|
26909
|
+
function or4(left, right) {
|
|
26910
|
+
return new ComposedDecoder4({
|
|
26911
|
+
...left.decoders ?? { [left.prefix]: left },
|
|
26912
|
+
...right.decoders ?? { [right.prefix]: right }
|
|
26913
|
+
});
|
|
26914
|
+
}
|
|
26915
|
+
var Codec4 = class {
|
|
26916
|
+
name;
|
|
26917
|
+
prefix;
|
|
26918
|
+
baseEncode;
|
|
26919
|
+
baseDecode;
|
|
26920
|
+
encoder;
|
|
26921
|
+
decoder;
|
|
26922
|
+
constructor(name, prefix, baseEncode, baseDecode) {
|
|
26923
|
+
this.name = name;
|
|
26924
|
+
this.prefix = prefix;
|
|
26925
|
+
this.baseEncode = baseEncode;
|
|
26926
|
+
this.baseDecode = baseDecode;
|
|
26927
|
+
this.encoder = new Encoder4(name, prefix, baseEncode);
|
|
26928
|
+
this.decoder = new Decoder4(name, prefix, baseDecode);
|
|
26929
|
+
}
|
|
26930
|
+
encode(input) {
|
|
26931
|
+
return this.encoder.encode(input);
|
|
26932
|
+
}
|
|
26933
|
+
decode(input) {
|
|
26934
|
+
return this.decoder.decode(input);
|
|
26935
|
+
}
|
|
26936
|
+
};
|
|
26937
|
+
function from4({ name, prefix, encode: encode33, decode: decode53 }) {
|
|
26938
|
+
return new Codec4(name, prefix, encode33, decode53);
|
|
26939
|
+
}
|
|
26940
|
+
function baseX4({ name, prefix, alphabet }) {
|
|
26941
|
+
const { encode: encode33, decode: decode53 } = base_x_default4(alphabet, name);
|
|
26942
|
+
return from4({
|
|
26943
|
+
prefix,
|
|
26944
|
+
name,
|
|
26945
|
+
encode: encode33,
|
|
26946
|
+
decode: (text) => coerce6(decode53(text))
|
|
26947
|
+
});
|
|
26948
|
+
}
|
|
26949
|
+
function decode10(string, alphabetIdx, bitsPerChar, name) {
|
|
26950
|
+
let end = string.length;
|
|
26951
|
+
while (string[end - 1] === "=") {
|
|
26952
|
+
--end;
|
|
26953
|
+
}
|
|
26954
|
+
const out = new Uint8Array(end * bitsPerChar / 8 | 0);
|
|
26955
|
+
let bits = 0;
|
|
26956
|
+
let buffer = 0;
|
|
26957
|
+
let written = 0;
|
|
26958
|
+
for (let i = 0; i < end; ++i) {
|
|
26959
|
+
const value = alphabetIdx[string[i]];
|
|
26960
|
+
if (value === void 0) {
|
|
26961
|
+
throw new SyntaxError(`Non-${name} character`);
|
|
26962
|
+
}
|
|
26963
|
+
buffer = buffer << bitsPerChar | value;
|
|
26964
|
+
bits += bitsPerChar;
|
|
26965
|
+
if (bits >= 8) {
|
|
26966
|
+
bits -= 8;
|
|
26967
|
+
out[written++] = 255 & buffer >> bits;
|
|
26968
|
+
}
|
|
26969
|
+
}
|
|
26970
|
+
if (bits >= bitsPerChar || (255 & buffer << 8 - bits) !== 0) {
|
|
26971
|
+
throw new SyntaxError("Unexpected end of data");
|
|
26972
|
+
}
|
|
26973
|
+
return out;
|
|
26974
|
+
}
|
|
26975
|
+
function encode6(data, alphabet, bitsPerChar) {
|
|
26976
|
+
const pad = alphabet[alphabet.length - 1] === "=";
|
|
26977
|
+
const mask = (1 << bitsPerChar) - 1;
|
|
26978
|
+
let out = "";
|
|
26979
|
+
let bits = 0;
|
|
26980
|
+
let buffer = 0;
|
|
26981
|
+
for (let i = 0; i < data.length; ++i) {
|
|
26982
|
+
buffer = buffer << 8 | data[i];
|
|
26983
|
+
bits += 8;
|
|
26984
|
+
while (bits > bitsPerChar) {
|
|
26985
|
+
bits -= bitsPerChar;
|
|
26986
|
+
out += alphabet[mask & buffer >> bits];
|
|
26987
|
+
}
|
|
26988
|
+
}
|
|
26989
|
+
if (bits !== 0) {
|
|
26990
|
+
out += alphabet[mask & buffer << bitsPerChar - bits];
|
|
26991
|
+
}
|
|
26992
|
+
if (pad) {
|
|
26993
|
+
while ((out.length * bitsPerChar & 7) !== 0) {
|
|
26994
|
+
out += "=";
|
|
26995
|
+
}
|
|
26996
|
+
}
|
|
26997
|
+
return out;
|
|
26998
|
+
}
|
|
26999
|
+
function createAlphabetIdx4(alphabet) {
|
|
27000
|
+
const alphabetIdx = {};
|
|
27001
|
+
for (let i = 0; i < alphabet.length; ++i) {
|
|
27002
|
+
alphabetIdx[alphabet[i]] = i;
|
|
27003
|
+
}
|
|
27004
|
+
return alphabetIdx;
|
|
27005
|
+
}
|
|
27006
|
+
function rfc46484({ name, prefix, bitsPerChar, alphabet }) {
|
|
27007
|
+
const alphabetIdx = createAlphabetIdx4(alphabet);
|
|
27008
|
+
return from4({
|
|
27009
|
+
prefix,
|
|
27010
|
+
name,
|
|
27011
|
+
encode(input) {
|
|
27012
|
+
return encode6(input, alphabet, bitsPerChar);
|
|
27013
|
+
},
|
|
27014
|
+
decode(input) {
|
|
27015
|
+
return decode10(input, alphabetIdx, bitsPerChar, name);
|
|
27016
|
+
}
|
|
27017
|
+
});
|
|
27018
|
+
}
|
|
27019
|
+
var base644 = rfc46484({
|
|
27020
|
+
prefix: "m",
|
|
27021
|
+
name: "base64",
|
|
27022
|
+
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
|
|
27023
|
+
bitsPerChar: 6
|
|
27024
|
+
});
|
|
27025
|
+
var base64pad4 = rfc46484({
|
|
27026
|
+
prefix: "M",
|
|
27027
|
+
name: "base64pad",
|
|
27028
|
+
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
|
27029
|
+
bitsPerChar: 6
|
|
27030
|
+
});
|
|
27031
|
+
var base64url4 = rfc46484({
|
|
27032
|
+
prefix: "u",
|
|
27033
|
+
name: "base64url",
|
|
27034
|
+
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
|
|
27035
|
+
bitsPerChar: 6
|
|
27036
|
+
});
|
|
27037
|
+
var base64urlpad4 = rfc46484({
|
|
27038
|
+
prefix: "U",
|
|
27039
|
+
name: "base64urlpad",
|
|
27040
|
+
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
|
|
27041
|
+
bitsPerChar: 6
|
|
27042
|
+
});
|
|
27043
|
+
function toBase64Url3(bytes) {
|
|
27044
|
+
return base64url4.baseEncode(bytes);
|
|
27045
|
+
}
|
|
27046
|
+
function fromBase64Url4(text) {
|
|
27047
|
+
const bytes = base64url4.baseDecode(text);
|
|
27048
|
+
if (base64url4.baseEncode(bytes) !== text) {
|
|
27049
|
+
throw new TypeError("non-canonical base64url input");
|
|
27050
|
+
}
|
|
27051
|
+
return bytes;
|
|
27052
|
+
}
|
|
27053
|
+
var base324 = rfc46484({
|
|
27054
|
+
prefix: "b",
|
|
27055
|
+
name: "base32",
|
|
27056
|
+
alphabet: "abcdefghijklmnopqrstuvwxyz234567",
|
|
27057
|
+
bitsPerChar: 5
|
|
27058
|
+
});
|
|
27059
|
+
var base32upper4 = rfc46484({
|
|
27060
|
+
prefix: "B",
|
|
27061
|
+
name: "base32upper",
|
|
27062
|
+
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
|
|
27063
|
+
bitsPerChar: 5
|
|
27064
|
+
});
|
|
27065
|
+
var base32pad4 = rfc46484({
|
|
27066
|
+
prefix: "c",
|
|
27067
|
+
name: "base32pad",
|
|
27068
|
+
alphabet: "abcdefghijklmnopqrstuvwxyz234567=",
|
|
27069
|
+
bitsPerChar: 5
|
|
27070
|
+
});
|
|
27071
|
+
var base32padupper4 = rfc46484({
|
|
27072
|
+
prefix: "C",
|
|
27073
|
+
name: "base32padupper",
|
|
27074
|
+
alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
|
|
27075
|
+
bitsPerChar: 5
|
|
27076
|
+
});
|
|
27077
|
+
var base32hex4 = rfc46484({
|
|
27078
|
+
prefix: "v",
|
|
27079
|
+
name: "base32hex",
|
|
27080
|
+
alphabet: "0123456789abcdefghijklmnopqrstuv",
|
|
27081
|
+
bitsPerChar: 5
|
|
27082
|
+
});
|
|
27083
|
+
var base32hexupper4 = rfc46484({
|
|
27084
|
+
prefix: "V",
|
|
27085
|
+
name: "base32hexupper",
|
|
27086
|
+
alphabet: "0123456789ABCDEFGHIJKLMNOPQRSTUV",
|
|
27087
|
+
bitsPerChar: 5
|
|
27088
|
+
});
|
|
27089
|
+
var base32hexpad4 = rfc46484({
|
|
27090
|
+
prefix: "t",
|
|
27091
|
+
name: "base32hexpad",
|
|
27092
|
+
alphabet: "0123456789abcdefghijklmnopqrstuv=",
|
|
27093
|
+
bitsPerChar: 5
|
|
27094
|
+
});
|
|
27095
|
+
var base32hexpadupper4 = rfc46484({
|
|
27096
|
+
prefix: "T",
|
|
27097
|
+
name: "base32hexpadupper",
|
|
27098
|
+
alphabet: "0123456789ABCDEFGHIJKLMNOPQRSTUV=",
|
|
27099
|
+
bitsPerChar: 5
|
|
27100
|
+
});
|
|
27101
|
+
var base32z4 = rfc46484({
|
|
27102
|
+
prefix: "h",
|
|
27103
|
+
name: "base32z",
|
|
27104
|
+
alphabet: "ybndrfg8ejkmcpqxot1uwisza345h769",
|
|
27105
|
+
bitsPerChar: 5
|
|
27106
|
+
});
|
|
27107
|
+
var base364 = baseX4({
|
|
27108
|
+
prefix: "k",
|
|
27109
|
+
name: "base36",
|
|
27110
|
+
alphabet: "0123456789abcdefghijklmnopqrstuvwxyz"
|
|
27111
|
+
});
|
|
27112
|
+
var base36upper4 = baseX4({
|
|
27113
|
+
prefix: "K",
|
|
27114
|
+
name: "base36upper",
|
|
27115
|
+
alphabet: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
27116
|
+
});
|
|
27117
|
+
var base58btc4 = baseX4({
|
|
27118
|
+
name: "base58btc",
|
|
27119
|
+
prefix: "z",
|
|
27120
|
+
alphabet: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
|
27121
|
+
});
|
|
27122
|
+
var base58flickr4 = baseX4({
|
|
27123
|
+
name: "base58flickr",
|
|
27124
|
+
prefix: "Z",
|
|
27125
|
+
alphabet: "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
|
|
27126
|
+
});
|
|
27127
|
+
var encode_14 = encode24;
|
|
27128
|
+
var MSB4 = 128;
|
|
27129
|
+
var REST4 = 127;
|
|
27130
|
+
var MSBALL4 = ~REST4;
|
|
27131
|
+
var INT4 = Math.pow(2, 31);
|
|
27132
|
+
function encode24(num, out, offset) {
|
|
27133
|
+
out = out || [];
|
|
27134
|
+
offset = offset || 0;
|
|
27135
|
+
var oldOffset = offset;
|
|
27136
|
+
while (num >= INT4) {
|
|
27137
|
+
out[offset++] = num & 255 | MSB4;
|
|
27138
|
+
num /= 128;
|
|
27139
|
+
}
|
|
27140
|
+
while (num & MSBALL4) {
|
|
27141
|
+
out[offset++] = num & 255 | MSB4;
|
|
27142
|
+
num >>>= 7;
|
|
27143
|
+
}
|
|
27144
|
+
out[offset] = num | 0;
|
|
27145
|
+
encode24.bytes = offset - oldOffset + 1;
|
|
27146
|
+
return out;
|
|
27147
|
+
}
|
|
27148
|
+
var decode24 = read4;
|
|
27149
|
+
var MSB$14 = 128;
|
|
27150
|
+
var REST$14 = 127;
|
|
27151
|
+
function read4(buf, offset) {
|
|
27152
|
+
var res = 0, offset = offset || 0, shift = 0, counter = offset, b, l = buf.length;
|
|
27153
|
+
do {
|
|
27154
|
+
if (counter >= l) {
|
|
27155
|
+
read4.bytes = 0;
|
|
27156
|
+
throw new RangeError("Could not decode varint");
|
|
27157
|
+
}
|
|
27158
|
+
b = buf[counter++];
|
|
27159
|
+
res += shift < 28 ? (b & REST$14) << shift : (b & REST$14) * Math.pow(2, shift);
|
|
27160
|
+
shift += 7;
|
|
27161
|
+
} while (b >= MSB$14);
|
|
27162
|
+
read4.bytes = counter - offset;
|
|
27163
|
+
return res;
|
|
27164
|
+
}
|
|
27165
|
+
var N14 = Math.pow(2, 7);
|
|
27166
|
+
var N24 = Math.pow(2, 14);
|
|
27167
|
+
var N34 = Math.pow(2, 21);
|
|
27168
|
+
var N44 = Math.pow(2, 28);
|
|
27169
|
+
var N54 = Math.pow(2, 35);
|
|
27170
|
+
var N64 = Math.pow(2, 42);
|
|
27171
|
+
var N74 = Math.pow(2, 49);
|
|
27172
|
+
var N84 = Math.pow(2, 56);
|
|
27173
|
+
var N94 = Math.pow(2, 63);
|
|
27174
|
+
var length4 = function(value) {
|
|
27175
|
+
return value < N14 ? 1 : value < N24 ? 2 : value < N34 ? 3 : value < N44 ? 4 : value < N54 ? 5 : value < N64 ? 6 : value < N74 ? 7 : value < N84 ? 8 : value < N94 ? 9 : 10;
|
|
27176
|
+
};
|
|
27177
|
+
var varint4 = {
|
|
27178
|
+
encode: encode_14,
|
|
27179
|
+
decode: decode24,
|
|
27180
|
+
encodingLength: length4
|
|
27181
|
+
};
|
|
27182
|
+
var _brrp_varint4 = varint4;
|
|
27183
|
+
var varint_default4 = _brrp_varint4;
|
|
27184
|
+
function decode34(data, offset = 0) {
|
|
27185
|
+
const code22 = varint_default4.decode(data, offset);
|
|
27186
|
+
return [code22, varint_default4.decode.bytes];
|
|
27187
|
+
}
|
|
27188
|
+
function encodeTo4(int, target, offset = 0) {
|
|
27189
|
+
varint_default4.encode(int, target, offset);
|
|
27190
|
+
return target;
|
|
27191
|
+
}
|
|
27192
|
+
function encodingLength4(int) {
|
|
27193
|
+
return varint_default4.encodingLength(int);
|
|
27194
|
+
}
|
|
27195
|
+
function create4(code22, digest) {
|
|
27196
|
+
const size = digest.byteLength;
|
|
27197
|
+
const sizeOffset = encodingLength4(code22);
|
|
27198
|
+
const digestOffset = sizeOffset + encodingLength4(size);
|
|
27199
|
+
const bytes = new Uint8Array(digestOffset + size);
|
|
27200
|
+
encodeTo4(code22, bytes, 0);
|
|
27201
|
+
encodeTo4(size, bytes, sizeOffset);
|
|
27202
|
+
bytes.set(digest, digestOffset);
|
|
27203
|
+
return new Digest4(code22, size, digest, bytes);
|
|
27204
|
+
}
|
|
27205
|
+
function decode44(multihash) {
|
|
27206
|
+
const bytes = coerce6(multihash);
|
|
27207
|
+
const [code22, sizeOffset] = decode34(bytes);
|
|
27208
|
+
const [size, digestOffset] = decode34(bytes.subarray(sizeOffset));
|
|
27209
|
+
const digest = bytes.subarray(sizeOffset + digestOffset);
|
|
27210
|
+
if (digest.byteLength !== size) {
|
|
27211
|
+
throw new Error("Incorrect length");
|
|
27212
|
+
}
|
|
27213
|
+
return new Digest4(code22, size, digest, bytes);
|
|
27214
|
+
}
|
|
27215
|
+
function equals24(a, b) {
|
|
27216
|
+
if (a === b) {
|
|
27217
|
+
return true;
|
|
27218
|
+
} else {
|
|
27219
|
+
const data = b;
|
|
27220
|
+
return a.code === data.code && a.size === data.size && data.bytes instanceof Uint8Array && equals6(a.bytes, data.bytes);
|
|
27221
|
+
}
|
|
27222
|
+
}
|
|
27223
|
+
var Digest4 = class {
|
|
27224
|
+
code;
|
|
27225
|
+
size;
|
|
27226
|
+
digest;
|
|
27227
|
+
bytes;
|
|
27228
|
+
/**
|
|
27229
|
+
* Creates a multihash digest.
|
|
27230
|
+
*/
|
|
27231
|
+
constructor(code22, size, digest, bytes) {
|
|
27232
|
+
this.code = code22;
|
|
27233
|
+
this.size = size;
|
|
27234
|
+
this.digest = digest;
|
|
27235
|
+
this.bytes = bytes;
|
|
27236
|
+
}
|
|
27237
|
+
};
|
|
27238
|
+
function format4(link4, base23) {
|
|
27239
|
+
const { bytes, version: version2 } = link4;
|
|
27240
|
+
switch (version2) {
|
|
27241
|
+
case 0:
|
|
27242
|
+
return toStringV04(bytes, baseCache4(link4), base23 ?? base58btc4.encoder);
|
|
27243
|
+
default:
|
|
27244
|
+
return toStringV14(bytes, baseCache4(link4), base23 ?? base324.encoder);
|
|
27245
|
+
}
|
|
27246
|
+
}
|
|
27247
|
+
var cache4 = /* @__PURE__ */ new WeakMap();
|
|
27248
|
+
function baseCache4(cid) {
|
|
27249
|
+
const baseCache23 = cache4.get(cid);
|
|
27250
|
+
if (baseCache23 == null) {
|
|
27251
|
+
const baseCache32 = /* @__PURE__ */ new Map();
|
|
27252
|
+
cache4.set(cid, baseCache32);
|
|
27253
|
+
return baseCache32;
|
|
27254
|
+
}
|
|
27255
|
+
return baseCache23;
|
|
27256
|
+
}
|
|
27257
|
+
var CID4 = class _CID4 {
|
|
27258
|
+
code;
|
|
27259
|
+
version;
|
|
27260
|
+
multihash;
|
|
27261
|
+
bytes;
|
|
27262
|
+
"/";
|
|
27263
|
+
/**
|
|
27264
|
+
* @param version - Version of the CID
|
|
27265
|
+
* @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
|
|
27266
|
+
* @param multihash - (Multi)hash of the of the content.
|
|
27267
|
+
*/
|
|
27268
|
+
constructor(version2, code22, multihash, bytes) {
|
|
27269
|
+
this.code = code22;
|
|
27270
|
+
this.version = version2;
|
|
27271
|
+
this.multihash = multihash;
|
|
27272
|
+
this.bytes = bytes;
|
|
27273
|
+
this["/"] = bytes;
|
|
27274
|
+
}
|
|
27275
|
+
/**
|
|
27276
|
+
* Signalling `cid.asCID === cid` has been replaced with `cid['/'] === cid.bytes`
|
|
27277
|
+
* please either use `CID.asCID(cid)` or switch to new signalling mechanism
|
|
27278
|
+
*
|
|
27279
|
+
* @deprecated
|
|
27280
|
+
*/
|
|
27281
|
+
get asCID() {
|
|
27282
|
+
return this;
|
|
27283
|
+
}
|
|
27284
|
+
// ArrayBufferView
|
|
27285
|
+
get byteOffset() {
|
|
27286
|
+
return this.bytes.byteOffset;
|
|
27287
|
+
}
|
|
27288
|
+
// ArrayBufferView
|
|
27289
|
+
get byteLength() {
|
|
27290
|
+
return this.bytes.byteLength;
|
|
27291
|
+
}
|
|
27292
|
+
toV0() {
|
|
27293
|
+
switch (this.version) {
|
|
27294
|
+
case 0: {
|
|
27295
|
+
return this;
|
|
27296
|
+
}
|
|
27297
|
+
case 1: {
|
|
27298
|
+
const { code: code22, multihash } = this;
|
|
27299
|
+
if (code22 !== DAG_PB_CODE4) {
|
|
27300
|
+
throw new Error("Cannot convert a non dag-pb CID to CIDv0");
|
|
27301
|
+
}
|
|
27302
|
+
if (multihash.code !== SHA_256_CODE4) {
|
|
27303
|
+
throw new Error("Cannot convert non sha2-256 multihash CID to CIDv0");
|
|
27304
|
+
}
|
|
27305
|
+
return _CID4.createV0(multihash);
|
|
27306
|
+
}
|
|
27307
|
+
default: {
|
|
27308
|
+
throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`);
|
|
27309
|
+
}
|
|
27310
|
+
}
|
|
27311
|
+
}
|
|
27312
|
+
toV1() {
|
|
27313
|
+
switch (this.version) {
|
|
27314
|
+
case 0: {
|
|
27315
|
+
const { code: code22, digest } = this.multihash;
|
|
27316
|
+
const multihash = create4(code22, digest);
|
|
27317
|
+
return _CID4.createV1(this.code, multihash);
|
|
27318
|
+
}
|
|
27319
|
+
case 1: {
|
|
27320
|
+
return this;
|
|
27321
|
+
}
|
|
27322
|
+
default: {
|
|
27323
|
+
throw Error(`Can not convert CID version ${this.version} to version 1. This is a bug please report`);
|
|
27324
|
+
}
|
|
27325
|
+
}
|
|
27326
|
+
}
|
|
27327
|
+
equals(other) {
|
|
27328
|
+
return _CID4.equals(this, other);
|
|
27329
|
+
}
|
|
27330
|
+
static equals(self, other) {
|
|
27331
|
+
const unknown = other;
|
|
27332
|
+
return unknown != null && self.code === unknown.code && self.version === unknown.version && equals24(self.multihash, unknown.multihash);
|
|
27333
|
+
}
|
|
27334
|
+
toString(base23) {
|
|
27335
|
+
return format4(this, base23);
|
|
27336
|
+
}
|
|
27337
|
+
toJSON() {
|
|
27338
|
+
return { "/": format4(this) };
|
|
27339
|
+
}
|
|
27340
|
+
link() {
|
|
27341
|
+
return this;
|
|
27342
|
+
}
|
|
27343
|
+
[Symbol.toStringTag] = "CID";
|
|
27344
|
+
// Legacy
|
|
27345
|
+
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
27346
|
+
return `CID(${this.toString()})`;
|
|
27347
|
+
}
|
|
27348
|
+
/**
|
|
27349
|
+
* Takes any input `value` and returns a `CID` instance if it was
|
|
27350
|
+
* a `CID` otherwise returns `null`. If `value` is instanceof `CID`
|
|
27351
|
+
* it will return value back. If `value` is not instance of this CID
|
|
27352
|
+
* class, but is compatible CID it will return new instance of this
|
|
27353
|
+
* `CID` class. Otherwise returns null.
|
|
27354
|
+
*
|
|
27355
|
+
* This allows two different incompatible versions of CID library to
|
|
27356
|
+
* co-exist and interop as long as binary interface is compatible.
|
|
27357
|
+
*/
|
|
27358
|
+
static asCID(input) {
|
|
27359
|
+
if (input == null) {
|
|
27360
|
+
return null;
|
|
27361
|
+
}
|
|
27362
|
+
const value = input;
|
|
27363
|
+
if (value instanceof _CID4) {
|
|
27364
|
+
return value;
|
|
27365
|
+
} else if (value["/"] != null && value["/"] === value.bytes || value.asCID === value) {
|
|
27366
|
+
const { version: version2, code: code22, multihash, bytes } = value;
|
|
27367
|
+
return new _CID4(version2, code22, multihash, bytes ?? encodeCID4(version2, code22, multihash.bytes));
|
|
27368
|
+
} else if (value[cidSymbol4] === true) {
|
|
27369
|
+
const { version: version2, multihash, code: code22 } = value;
|
|
27370
|
+
const digest = decode44(multihash);
|
|
27371
|
+
return _CID4.create(version2, code22, digest);
|
|
27372
|
+
} else {
|
|
27373
|
+
return null;
|
|
27374
|
+
}
|
|
27375
|
+
}
|
|
27376
|
+
/**
|
|
27377
|
+
* @param version - Version of the CID
|
|
27378
|
+
* @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
|
|
27379
|
+
* @param digest - (Multi)hash of the of the content.
|
|
27380
|
+
*/
|
|
27381
|
+
static create(version2, code22, digest) {
|
|
27382
|
+
if (typeof code22 !== "number") {
|
|
27383
|
+
throw new Error("String codecs are no longer supported");
|
|
27384
|
+
}
|
|
27385
|
+
if (!(digest.bytes instanceof Uint8Array)) {
|
|
27386
|
+
throw new Error("Invalid digest");
|
|
27387
|
+
}
|
|
27388
|
+
switch (version2) {
|
|
27389
|
+
case 0: {
|
|
27390
|
+
if (code22 !== DAG_PB_CODE4) {
|
|
27391
|
+
throw new Error(`Version 0 CID must use dag-pb (code: ${DAG_PB_CODE4}) block encoding`);
|
|
27392
|
+
} else {
|
|
27393
|
+
return new _CID4(version2, code22, digest, digest.bytes);
|
|
27394
|
+
}
|
|
27395
|
+
}
|
|
27396
|
+
case 1: {
|
|
27397
|
+
const bytes = encodeCID4(version2, code22, digest.bytes);
|
|
27398
|
+
return new _CID4(version2, code22, digest, bytes);
|
|
27399
|
+
}
|
|
27400
|
+
default: {
|
|
27401
|
+
throw new Error("Invalid version");
|
|
27402
|
+
}
|
|
27403
|
+
}
|
|
27404
|
+
}
|
|
27405
|
+
/**
|
|
27406
|
+
* Simplified version of `create` for CIDv0.
|
|
27407
|
+
*/
|
|
27408
|
+
static createV0(digest) {
|
|
27409
|
+
return _CID4.create(0, DAG_PB_CODE4, digest);
|
|
27410
|
+
}
|
|
27411
|
+
/**
|
|
27412
|
+
* Simplified version of `create` for CIDv1.
|
|
27413
|
+
*
|
|
27414
|
+
* @param code - Content encoding format code.
|
|
27415
|
+
* @param digest - Multihash of the content.
|
|
27416
|
+
*/
|
|
27417
|
+
static createV1(code22, digest) {
|
|
27418
|
+
return _CID4.create(1, code22, digest);
|
|
27419
|
+
}
|
|
27420
|
+
/**
|
|
27421
|
+
* Decoded a CID from its binary representation. The byte array must contain
|
|
27422
|
+
* only the CID with no additional bytes.
|
|
27423
|
+
*
|
|
27424
|
+
* An error will be thrown if the bytes provided do not contain a valid
|
|
27425
|
+
* binary representation of a CID.
|
|
27426
|
+
*/
|
|
27427
|
+
static decode(bytes) {
|
|
27428
|
+
const [cid, remainder] = _CID4.decodeFirst(bytes);
|
|
27429
|
+
if (remainder.length !== 0) {
|
|
27430
|
+
throw new Error("Incorrect length");
|
|
27431
|
+
}
|
|
27432
|
+
return cid;
|
|
27433
|
+
}
|
|
27434
|
+
/**
|
|
27435
|
+
* Decoded a CID from its binary representation at the beginning of a byte
|
|
27436
|
+
* array.
|
|
27437
|
+
*
|
|
27438
|
+
* Returns an array with the first element containing the CID and the second
|
|
27439
|
+
* element containing the remainder of the original byte array. The remainder
|
|
27440
|
+
* will be a zero-length byte array if the provided bytes only contained a
|
|
27441
|
+
* binary CID representation.
|
|
27442
|
+
*/
|
|
27443
|
+
static decodeFirst(bytes) {
|
|
27444
|
+
const specs = _CID4.inspectBytes(bytes);
|
|
27445
|
+
const prefixSize = specs.size - specs.multihashSize;
|
|
27446
|
+
const multihashBytes = coerce6(bytes.subarray(prefixSize, prefixSize + specs.multihashSize));
|
|
27447
|
+
if (multihashBytes.byteLength !== specs.multihashSize) {
|
|
27448
|
+
throw new Error("Incorrect length");
|
|
27449
|
+
}
|
|
27450
|
+
const digestBytes = multihashBytes.subarray(specs.multihashSize - specs.digestSize);
|
|
27451
|
+
const digest = new Digest4(specs.multihashCode, specs.digestSize, digestBytes, multihashBytes);
|
|
27452
|
+
const cid = specs.version === 0 ? _CID4.createV0(digest) : _CID4.createV1(specs.codec, digest);
|
|
27453
|
+
return [cid, bytes.subarray(specs.size)];
|
|
27454
|
+
}
|
|
27455
|
+
/**
|
|
27456
|
+
* Inspect the initial bytes of a CID to determine its properties.
|
|
27457
|
+
*
|
|
27458
|
+
* Involves decoding up to 4 varints. Typically this will require only 4 to 6
|
|
27459
|
+
* bytes but for larger multicodec code values and larger multihash digest
|
|
27460
|
+
* lengths these varints can be quite large. It is recommended that at least
|
|
27461
|
+
* 10 bytes be made available in the `initialBytes` argument for a complete
|
|
27462
|
+
* inspection.
|
|
27463
|
+
*/
|
|
27464
|
+
static inspectBytes(initialBytes) {
|
|
27465
|
+
let offset = 0;
|
|
27466
|
+
const next = () => {
|
|
27467
|
+
const [i, length23] = decode34(initialBytes.subarray(offset));
|
|
27468
|
+
offset += length23;
|
|
27469
|
+
return i;
|
|
27470
|
+
};
|
|
27471
|
+
let version2 = next();
|
|
27472
|
+
let codec = DAG_PB_CODE4;
|
|
27473
|
+
if (version2 === 18) {
|
|
27474
|
+
version2 = 0;
|
|
27475
|
+
offset = 0;
|
|
27476
|
+
} else {
|
|
27477
|
+
codec = next();
|
|
27478
|
+
}
|
|
27479
|
+
if (version2 !== 0 && version2 !== 1) {
|
|
27480
|
+
throw new RangeError(`Invalid CID version ${version2}`);
|
|
27481
|
+
}
|
|
27482
|
+
const prefixSize = offset;
|
|
27483
|
+
const multihashCode = next();
|
|
27484
|
+
const digestSize = next();
|
|
27485
|
+
const size = offset + digestSize;
|
|
27486
|
+
const multihashSize = size - prefixSize;
|
|
27487
|
+
return { version: version2, codec, multihashCode, digestSize, multihashSize, size };
|
|
27488
|
+
}
|
|
27489
|
+
/**
|
|
27490
|
+
* Takes cid in a string representation and creates an instance. If `base`
|
|
27491
|
+
* decoder is not provided will use a default from the configuration. It will
|
|
27492
|
+
* throw an error if encoding of the CID is not compatible with supplied (or
|
|
27493
|
+
* a default decoder).
|
|
27494
|
+
*/
|
|
27495
|
+
static parse(source, base23) {
|
|
27496
|
+
const [prefix, bytes] = parseCIDtoBytes4(source, base23);
|
|
27497
|
+
const cid = _CID4.decode(bytes);
|
|
27498
|
+
if (cid.version === 0 && source[0] !== "Q") {
|
|
27499
|
+
throw Error("Version 0 CID string must not include multibase prefix");
|
|
27500
|
+
}
|
|
27501
|
+
baseCache4(cid).set(prefix, source);
|
|
27502
|
+
return cid;
|
|
27503
|
+
}
|
|
27504
|
+
};
|
|
27505
|
+
function parseCIDtoBytes4(source, base23) {
|
|
27506
|
+
switch (source[0]) {
|
|
27507
|
+
// CIDv0 is parsed differently
|
|
27508
|
+
case "Q": {
|
|
27509
|
+
const decoder = base23 ?? base58btc4;
|
|
27510
|
+
return [
|
|
27511
|
+
base58btc4.prefix,
|
|
27512
|
+
decoder.decode(`${base58btc4.prefix}${source}`)
|
|
27513
|
+
];
|
|
27514
|
+
}
|
|
27515
|
+
case base58btc4.prefix: {
|
|
27516
|
+
const decoder = base23 ?? base58btc4;
|
|
27517
|
+
return [base58btc4.prefix, decoder.decode(source)];
|
|
27518
|
+
}
|
|
27519
|
+
case base324.prefix: {
|
|
27520
|
+
const decoder = base23 ?? base324;
|
|
27521
|
+
return [base324.prefix, decoder.decode(source)];
|
|
27522
|
+
}
|
|
27523
|
+
case base364.prefix: {
|
|
27524
|
+
const decoder = base23 ?? base364;
|
|
27525
|
+
return [base364.prefix, decoder.decode(source)];
|
|
27526
|
+
}
|
|
27527
|
+
default: {
|
|
27528
|
+
if (base23 == null) {
|
|
27529
|
+
throw Error("To parse non base32, base36 or base58btc encoded CID multibase decoder must be provided");
|
|
27530
|
+
}
|
|
27531
|
+
return [source[0], base23.decode(source)];
|
|
27532
|
+
}
|
|
27533
|
+
}
|
|
27534
|
+
}
|
|
27535
|
+
function toStringV04(bytes, cache23, base23) {
|
|
27536
|
+
const { prefix } = base23;
|
|
27537
|
+
if (prefix !== base58btc4.prefix) {
|
|
27538
|
+
throw Error(`Cannot string encode V0 in ${base23.name} encoding`);
|
|
27539
|
+
}
|
|
27540
|
+
const cid = cache23.get(prefix);
|
|
27541
|
+
if (cid == null) {
|
|
27542
|
+
const cid2 = base23.encode(bytes).slice(1);
|
|
27543
|
+
cache23.set(prefix, cid2);
|
|
27544
|
+
return cid2;
|
|
27545
|
+
} else {
|
|
27546
|
+
return cid;
|
|
27547
|
+
}
|
|
27548
|
+
}
|
|
27549
|
+
function toStringV14(bytes, cache23, base23) {
|
|
27550
|
+
const { prefix } = base23;
|
|
27551
|
+
const cid = cache23.get(prefix);
|
|
27552
|
+
if (cid == null) {
|
|
27553
|
+
const cid2 = base23.encode(bytes);
|
|
27554
|
+
cache23.set(prefix, cid2);
|
|
27555
|
+
return cid2;
|
|
27556
|
+
} else {
|
|
27557
|
+
return cid;
|
|
27558
|
+
}
|
|
27559
|
+
}
|
|
27560
|
+
var DAG_PB_CODE4 = 112;
|
|
27561
|
+
var SHA_256_CODE4 = 18;
|
|
27562
|
+
function encodeCID4(version2, code22, multihash) {
|
|
27563
|
+
const codeOffset = encodingLength4(version2);
|
|
27564
|
+
const hashOffset = codeOffset + encodingLength4(code22);
|
|
27565
|
+
const bytes = new Uint8Array(hashOffset + multihash.byteLength);
|
|
27566
|
+
encodeTo4(version2, bytes, 0);
|
|
27567
|
+
encodeTo4(code22, bytes, codeOffset);
|
|
27568
|
+
bytes.set(multihash, hashOffset);
|
|
27569
|
+
return bytes;
|
|
27570
|
+
}
|
|
27571
|
+
var cidSymbol4 = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
|
|
27572
|
+
var code4 = 85;
|
|
27573
|
+
var SHA256_CODE4 = 18;
|
|
27574
|
+
async function computeCid3(bytes) {
|
|
27575
|
+
const digest = create4(SHA256_CODE4, sha256(new Uint8Array(bytes)));
|
|
27576
|
+
return CID4.create(1, code4, digest).toString();
|
|
27577
|
+
}
|
|
27578
|
+
function isCanonicalRawCid4(cidString) {
|
|
27579
|
+
let cid;
|
|
27580
|
+
try {
|
|
27581
|
+
cid = CID4.parse(cidString);
|
|
27582
|
+
} catch {
|
|
27583
|
+
return false;
|
|
27584
|
+
}
|
|
27585
|
+
return cid.version === 1 && cid.code === code4 && cid.multihash.code === SHA256_CODE4 && cid.toString() === cidString;
|
|
27586
|
+
}
|
|
27587
|
+
function isPlainRecord4(value) {
|
|
27588
|
+
const proto = Object.getPrototypeOf(value);
|
|
27589
|
+
return proto === Object.prototype || proto === null;
|
|
27590
|
+
}
|
|
27591
|
+
function assertNoLoneSurrogates4(text) {
|
|
27592
|
+
for (let i = 0; i < text.length; i++) {
|
|
27593
|
+
const unit = text.charCodeAt(i);
|
|
27594
|
+
if (unit >= 56320 && unit <= 57343) {
|
|
27595
|
+
throw new TypeError(
|
|
27596
|
+
`cannot canonicalize string with unpaired low surrogate at index ${i}`
|
|
27597
|
+
);
|
|
27598
|
+
}
|
|
27599
|
+
if (unit >= 55296 && unit <= 56319) {
|
|
27600
|
+
const next = text.charCodeAt(i + 1);
|
|
27601
|
+
if (!(next >= 56320 && next <= 57343)) {
|
|
27602
|
+
throw new TypeError(
|
|
27603
|
+
`cannot canonicalize string with unpaired high surrogate at index ${i}`
|
|
27604
|
+
);
|
|
27605
|
+
}
|
|
27606
|
+
i++;
|
|
27607
|
+
}
|
|
27608
|
+
}
|
|
27609
|
+
}
|
|
27610
|
+
function serializeString4(text) {
|
|
27611
|
+
assertNoLoneSurrogates4(text);
|
|
27612
|
+
return JSON.stringify(text);
|
|
27613
|
+
}
|
|
27614
|
+
function serialize4(value) {
|
|
27615
|
+
if (value === null) return "null";
|
|
27616
|
+
switch (typeof value) {
|
|
27617
|
+
case "boolean":
|
|
27618
|
+
return JSON.stringify(value);
|
|
27619
|
+
case "string":
|
|
27620
|
+
return serializeString4(value);
|
|
27621
|
+
case "number":
|
|
27622
|
+
if (!Number.isFinite(value)) {
|
|
27623
|
+
throw new TypeError(`cannot canonicalize non-finite number: ${value}`);
|
|
27624
|
+
}
|
|
27625
|
+
return JSON.stringify(value);
|
|
27626
|
+
case "object":
|
|
27627
|
+
break;
|
|
27628
|
+
default:
|
|
27629
|
+
throw new TypeError(`cannot canonicalize value of type ${typeof value}`);
|
|
27630
|
+
}
|
|
27631
|
+
if (Array.isArray(value)) {
|
|
27632
|
+
return `[${value.map((item) => serialize4(item)).join(",")}]`;
|
|
27633
|
+
}
|
|
27634
|
+
if (!isPlainRecord4(value)) {
|
|
27635
|
+
throw new TypeError("cannot canonicalize non-plain object");
|
|
27636
|
+
}
|
|
27637
|
+
const keys = Object.keys(value).sort();
|
|
27638
|
+
const members = [];
|
|
27639
|
+
for (const key of keys) {
|
|
27640
|
+
const member = value[key];
|
|
27641
|
+
if (member === void 0) continue;
|
|
27642
|
+
members.push(`${serializeString4(key)}:${serialize4(member)}`);
|
|
27643
|
+
}
|
|
27644
|
+
return `{${members.join(",")}}`;
|
|
27645
|
+
}
|
|
27646
|
+
function canonicalize4(value) {
|
|
27647
|
+
return serialize4(value);
|
|
27648
|
+
}
|
|
27649
|
+
function decodeBase64UrlOrNull4(value) {
|
|
27650
|
+
try {
|
|
27651
|
+
return fromBase64Url4(value);
|
|
27652
|
+
} catch {
|
|
27653
|
+
return null;
|
|
27654
|
+
}
|
|
27655
|
+
}
|
|
27656
|
+
var base64UrlString4 = () => external_exports3.string().refine((value) => decodeBase64UrlOrNull4(value) !== null, {
|
|
27657
|
+
message: "expected strictly-decodable unpadded base64url"
|
|
27658
|
+
});
|
|
27659
|
+
function isCanonicalHttpsOrigin4(value) {
|
|
27660
|
+
let url;
|
|
27661
|
+
try {
|
|
27662
|
+
url = new URL(value);
|
|
27663
|
+
} catch {
|
|
27664
|
+
return false;
|
|
27665
|
+
}
|
|
27666
|
+
return url.protocol === "https:" && url.origin === value;
|
|
27667
|
+
}
|
|
27668
|
+
var sessionJwkCommonFields4 = {
|
|
27669
|
+
alg: external_exports3.string().min(1).optional(),
|
|
27670
|
+
use: external_exports3.string().min(1).optional(),
|
|
27671
|
+
key_ops: external_exports3.array(external_exports3.string().min(1)).optional(),
|
|
27672
|
+
kid: external_exports3.string().min(1).optional(),
|
|
27673
|
+
ext: external_exports3.boolean().optional()
|
|
27674
|
+
};
|
|
27675
|
+
var okpPrivateJwkSchema4 = external_exports3.object({
|
|
27676
|
+
kty: external_exports3.literal("OKP"),
|
|
27677
|
+
crv: external_exports3.string().min(1),
|
|
27678
|
+
x: base64UrlString4(),
|
|
27679
|
+
d: base64UrlString4(),
|
|
27680
|
+
...sessionJwkCommonFields4
|
|
27681
|
+
}).strict();
|
|
27682
|
+
var ecPrivateJwkSchema4 = external_exports3.object({
|
|
27683
|
+
kty: external_exports3.literal("EC"),
|
|
27684
|
+
crv: external_exports3.string().min(1),
|
|
27685
|
+
x: base64UrlString4(),
|
|
27686
|
+
y: base64UrlString4(),
|
|
27687
|
+
d: base64UrlString4(),
|
|
27688
|
+
...sessionJwkCommonFields4
|
|
27689
|
+
}).strict();
|
|
27690
|
+
var sessionJwkSchema4 = external_exports3.discriminatedUnion("kty", [
|
|
27691
|
+
okpPrivateJwkSchema4,
|
|
27692
|
+
ecPrivateJwkSchema4
|
|
27693
|
+
]);
|
|
27694
|
+
var policyTargetSchema4 = external_exports3.object({
|
|
27695
|
+
kind: external_exports3.literal("policy"),
|
|
27696
|
+
policyCid: external_exports3.string().min(1),
|
|
27697
|
+
/** Canonical policy bytes, base64url-encoded (bytes are not JSON). */
|
|
27698
|
+
policyBytes: base64UrlString4()
|
|
27699
|
+
}).strict();
|
|
27700
|
+
var bearerKeyTargetSchema4 = external_exports3.object({
|
|
27701
|
+
kind: external_exports3.literal("bearerKey"),
|
|
27702
|
+
sessionJwk: sessionJwkSchema4
|
|
27703
|
+
}).strict();
|
|
27704
|
+
var recipientDidTargetSchema4 = external_exports3.object({
|
|
27705
|
+
kind: external_exports3.literal("recipientDid"),
|
|
27706
|
+
did: external_exports3.string().regex(/^did:[a-z0-9]+:.+$/, "expected a DID")
|
|
27707
|
+
}).strict();
|
|
27708
|
+
var authorizationTargetSchema4 = external_exports3.discriminatedUnion("kind", [
|
|
27709
|
+
policyTargetSchema4,
|
|
27710
|
+
bearerKeyTargetSchema4,
|
|
27711
|
+
recipientDidTargetSchema4
|
|
27712
|
+
]);
|
|
27713
|
+
function isCanonicalResourcePath4(value) {
|
|
27714
|
+
if (value.length === 0) return false;
|
|
27715
|
+
if (/[\u0000-\u001f\u007f\\]/.test(value)) return false;
|
|
27716
|
+
if (/%2f|%5c|%2e/i.test(value)) return false;
|
|
27717
|
+
return value.split("/").every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
|
|
27718
|
+
}
|
|
27719
|
+
function isCanonicalPathSegment4(value) {
|
|
27720
|
+
return isCanonicalResourcePath4(value) && !value.includes("/");
|
|
27721
|
+
}
|
|
27722
|
+
var resourceSelectorSchema4 = external_exports3.object({
|
|
27723
|
+
kind: external_exports3.union([external_exports3.literal("exact"), external_exports3.literal("prefix")]),
|
|
27724
|
+
path: external_exports3.string().min(1)
|
|
27725
|
+
}).strict().superRefine((selector, ctx) => {
|
|
27726
|
+
const body = selector.kind === "prefix" && selector.path.endsWith("/") ? selector.path.slice(0, -1) : selector.path;
|
|
27727
|
+
if (!isCanonicalResourcePath4(body)) {
|
|
27728
|
+
ctx.addIssue({
|
|
27729
|
+
code: external_exports3.ZodIssueCode.custom,
|
|
27730
|
+
path: ["path"],
|
|
27731
|
+
message: "expected a canonical resource path (non-empty segments, no . or .. segments, no //, no backslash, no %2f/%5c/%2e, no control chars)"
|
|
27732
|
+
});
|
|
27733
|
+
}
|
|
27734
|
+
});
|
|
27735
|
+
var targetSchema4 = external_exports3.object({
|
|
27736
|
+
origin: external_exports3.string().refine(isCanonicalHttpsOrigin4, {
|
|
27737
|
+
message: "expected a canonical https origin (https://host[:port], nothing else)"
|
|
27738
|
+
}),
|
|
27739
|
+
nodeAudience: external_exports3.string().min(1),
|
|
27740
|
+
spaceId: external_exports3.string().refine(isCanonicalPathSegment4, {
|
|
27741
|
+
message: "expected a single canonical path segment (spaceId joins the resource URI; separators/traversal would alias grants)"
|
|
27742
|
+
}),
|
|
27743
|
+
resource: resourceSelectorSchema4
|
|
27744
|
+
}).strict();
|
|
27745
|
+
var displaySchema4 = external_exports3.object({
|
|
27746
|
+
senderName: external_exports3.string().optional(),
|
|
27747
|
+
filename: external_exports3.string().optional(),
|
|
27748
|
+
recipientHint: external_exports3.string().optional(),
|
|
27749
|
+
/**
|
|
27750
|
+
* Presentation preference only (viewer spec §1): may narrow, never widen;
|
|
27751
|
+
* capabilities always win.
|
|
27752
|
+
*/
|
|
27753
|
+
mode: external_exports3.union([external_exports3.literal("document"), external_exports3.literal("source"), external_exports3.literal("folder")]).optional()
|
|
27754
|
+
}).strict();
|
|
27755
|
+
var contentPointerSchema4 = external_exports3.object({
|
|
27756
|
+
cid: external_exports3.string().refine(isCanonicalRawCid4, {
|
|
27757
|
+
message: "expected a canonical CIDv1 raw sha2-256 base32 CID"
|
|
27758
|
+
}),
|
|
27759
|
+
key: external_exports3.string().refine((value) => decodeBase64UrlOrNull4(value)?.length === 32, {
|
|
27760
|
+
message: "expected base64url decoding to exactly 32 bytes"
|
|
27761
|
+
})
|
|
27762
|
+
}).strict();
|
|
27763
|
+
var signatureSchema4 = external_exports3.object({
|
|
27764
|
+
/** did:key of the sender's ed25519 signing key. */
|
|
27765
|
+
signerDid: external_exports3.string().regex(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/, "expected a did:key"),
|
|
27766
|
+
algorithm: external_exports3.literal("Ed25519"),
|
|
27767
|
+
/** base64url-encoded ed25519 signature over the JCS bytes of all other fields. */
|
|
27768
|
+
value: external_exports3.string().refine((value) => decodeBase64UrlOrNull4(value)?.length === 64, {
|
|
27769
|
+
message: "expected base64url decoding to exactly 64 bytes"
|
|
27770
|
+
})
|
|
27771
|
+
}).strict();
|
|
27772
|
+
var unsignedShareEnvelopeSchema4 = external_exports3.object({
|
|
27773
|
+
version: external_exports3.literal(1),
|
|
27774
|
+
shareId: external_exports3.string().min(1),
|
|
27775
|
+
/** Full signed delegation chain, opaque serialized form. */
|
|
27776
|
+
delegation: external_exports3.string().min(1),
|
|
27777
|
+
authorizationTarget: authorizationTargetSchema4,
|
|
27778
|
+
target: targetSchema4,
|
|
27779
|
+
display: displaySchema4,
|
|
27780
|
+
/** ISO 8601 UTC datetime. Advisory here; enforcement is the delegation's. */
|
|
27781
|
+
expiry: external_exports3.string().datetime(),
|
|
27782
|
+
/** Bearer-slice sealed-content pointer (see contentPointerSchema). */
|
|
27783
|
+
content: contentPointerSchema4.optional()
|
|
27784
|
+
}).strict();
|
|
27785
|
+
var shareEnvelopeSchema4 = unsignedShareEnvelopeSchema4.extend({ signature: signatureSchema4 }).strict();
|
|
27786
|
+
var recipientMatcherSchema4 = external_exports3.discriminatedUnion("kind", [
|
|
27787
|
+
external_exports3.object({ kind: external_exports3.literal("exactEmail"), value: external_exports3.string().min(3).regex(/^[^@\s]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/) }).strict(),
|
|
27788
|
+
external_exports3.object({ kind: external_exports3.literal("emailDomain"), value: external_exports3.string().regex(/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/) }).strict(),
|
|
27789
|
+
external_exports3.object({ kind: external_exports3.literal("recipientDid"), value: external_exports3.string().regex(/^did:[a-z0-9]+:.+$/) }).strict(),
|
|
27790
|
+
external_exports3.object({ kind: external_exports3.literal("policyDigest"), value: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/) }).strict(),
|
|
27791
|
+
external_exports3.object({ kind: external_exports3.literal("bearer") }).strict()
|
|
27792
|
+
]);
|
|
27793
|
+
var shareActionSchema4 = external_exports3.union([external_exports3.literal("read"), external_exports3.literal("list"), external_exports3.literal("edit")]);
|
|
27794
|
+
var kvContentSourceSchema4 = external_exports3.object({
|
|
27795
|
+
kind: external_exports3.literal("kv"),
|
|
27796
|
+
space: external_exports3.string().min(1),
|
|
27797
|
+
path: external_exports3.string().min(1),
|
|
27798
|
+
action: external_exports3.literal("tinycloud.kv/get")
|
|
27799
|
+
}).strict();
|
|
27800
|
+
var sqlContentSourceSchema4 = external_exports3.object({
|
|
27801
|
+
kind: external_exports3.literal("sql"),
|
|
27802
|
+
space: external_exports3.string().min(1),
|
|
27803
|
+
database: external_exports3.string().min(1),
|
|
27804
|
+
path: external_exports3.string().min(1),
|
|
27805
|
+
statement: external_exports3.string().min(1),
|
|
27806
|
+
arguments: external_exports3.record(external_exports3.string(), external_exports3.number().int()),
|
|
27807
|
+
argumentsDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
|
|
27808
|
+
action: external_exports3.literal("tinycloud.sql/read")
|
|
27809
|
+
}).strict();
|
|
27810
|
+
var contentSourceSchema4 = external_exports3.discriminatedUnion("kind", [kvContentSourceSchema4, sqlContentSourceSchema4]);
|
|
27811
|
+
var v2TargetSchema4 = external_exports3.object({
|
|
27812
|
+
origin: external_exports3.string().refine(isCanonicalHttpsOrigin4, { message: "expected a canonical https origin" }),
|
|
27813
|
+
nodeAudience: external_exports3.string().min(1),
|
|
27814
|
+
spaceId: external_exports3.string().refine(isCanonicalPathSegment4, { message: "expected a canonical space id" })
|
|
27815
|
+
}).strict();
|
|
27816
|
+
var shareDecryptionSchema4 = external_exports3.object({
|
|
27817
|
+
networkId: external_exports3.string().min(1),
|
|
27818
|
+
action: external_exports3.literal("tinycloud.encryption/decrypt")
|
|
27819
|
+
}).strict();
|
|
27820
|
+
var ownerAuthoritySchema4 = external_exports3.object({
|
|
27821
|
+
registrationCid: external_exports3.string().min(1),
|
|
27822
|
+
shareCid: external_exports3.string().min(1),
|
|
27823
|
+
envelopeCid: external_exports3.string().min(1),
|
|
27824
|
+
enforcementDelegation: external_exports3.record(external_exports3.string(), external_exports3.unknown()),
|
|
27825
|
+
outerEnvelope: external_exports3.record(external_exports3.string(), external_exports3.unknown()),
|
|
27826
|
+
/** Node-signed registration evidence; required by trusted policy adapters. */
|
|
27827
|
+
registrationReceipt: external_exports3.object({
|
|
27828
|
+
registration: external_exports3.record(external_exports3.string(), external_exports3.unknown()),
|
|
27829
|
+
proof: external_exports3.record(external_exports3.string(), external_exports3.unknown())
|
|
27830
|
+
}).strict().optional()
|
|
27831
|
+
}).strict();
|
|
27832
|
+
var contentMetadataSchema4 = external_exports3.object({
|
|
27833
|
+
mediaType: external_exports3.string().min(1).max(128).optional(),
|
|
27834
|
+
byteLength: external_exports3.number().int().nonnegative().max(100 * 1024 * 1024).optional(),
|
|
27835
|
+
filename: external_exports3.string().min(1).max(255).optional(),
|
|
27836
|
+
encoding: external_exports3.literal("utf-8").optional(),
|
|
27837
|
+
/** Encrypted presentation discriminator. The fixed entry point is index.html. */
|
|
27838
|
+
artifact: external_exports3.literal("html").optional()
|
|
27839
|
+
}).strict();
|
|
27840
|
+
var deliveryEmailSchema4 = external_exports3.string().email();
|
|
27841
|
+
var unsignedShareEnvelopeV2BaseSchema4 = external_exports3.object({
|
|
27842
|
+
version: external_exports3.literal(2),
|
|
27843
|
+
shareId: external_exports3.string().min(1),
|
|
27844
|
+
recipientMatcher: recipientMatcherSchema4,
|
|
27845
|
+
deliveryEmail: deliveryEmailSchema4.optional(),
|
|
27846
|
+
actions: external_exports3.array(shareActionSchema4).min(1).max(3),
|
|
27847
|
+
resource: resourceSelectorSchema4,
|
|
27848
|
+
target: v2TargetSchema4,
|
|
27849
|
+
delegationCid: external_exports3.string().min(1),
|
|
27850
|
+
authorityMaterialHandle: external_exports3.string().min(1),
|
|
27851
|
+
authorityMaterialDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
|
|
27852
|
+
decryption: shareDecryptionSchema4.optional(),
|
|
27853
|
+
contentSource: contentSourceSchema4,
|
|
27854
|
+
contentSourceDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
|
|
27855
|
+
authorizationTarget: authorizationTargetSchema4,
|
|
27856
|
+
display: displaySchema4,
|
|
27857
|
+
expiry: external_exports3.string().datetime(),
|
|
27858
|
+
encrypted: external_exports3.boolean(),
|
|
27859
|
+
content: contentPointerSchema4.optional(),
|
|
27860
|
+
metadata: contentMetadataSchema4,
|
|
27861
|
+
ownerAuthority: ownerAuthoritySchema4.optional()
|
|
27862
|
+
}).strict();
|
|
27863
|
+
function validateV2Invariants4(value, ctx) {
|
|
27864
|
+
const actions = [...value.actions];
|
|
27865
|
+
if (new Set(actions).size !== actions.length) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["actions"], message: "actions must be unique" });
|
|
27866
|
+
if (actions.some((action, index) => action !== ["read", "list", "edit"].filter((candidate) => actions.includes(candidate))[index])) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["actions"], message: "actions must be canonically ordered" });
|
|
27867
|
+
if (!value.encrypted && value.recipientMatcher.kind !== "policyDigest") ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["recipientMatcher"], message: "safe plaintext must carry only a matcher digest" });
|
|
27868
|
+
if (!value.encrypted && value.authorizationTarget.kind !== "policy") ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["encrypted"], message: "unencrypted content requires a policy target" });
|
|
27869
|
+
if (!value.encrypted && value.content !== void 0) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["content"], message: "policy-only plaintext cannot carry content" });
|
|
27870
|
+
if (value.encrypted && (value.metadata.mediaType === void 0 || value.metadata.filename === void 0 || value.metadata.byteLength === void 0)) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["metadata"], message: "encrypted shares must describe their content" });
|
|
27871
|
+
if (!value.encrypted && Object.keys(value.metadata).length !== 0) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["metadata"], message: "policy-only plaintext cannot describe content" });
|
|
27872
|
+
if (!value.encrypted && value.metadata.encoding !== void 0) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["metadata", "encoding"], message: "policy-only plaintext cannot carry content encoding" });
|
|
27873
|
+
if (value.metadata.artifact === "html" && (!value.encrypted || value.resource.kind !== "prefix" || !value.actions.includes("read") || !value.actions.includes("list"))) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["metadata", "artifact"], message: "html artifacts require an encrypted readable prefix" });
|
|
27874
|
+
if (!value.encrypted && (value.display.senderName !== void 0 || value.display.filename !== void 0 || value.display.recipientHint !== void 0)) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["display"], message: "policy-only plaintext cannot carry display metadata" });
|
|
27875
|
+
if (!value.encrypted && value.deliveryEmail !== void 0) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["deliveryEmail"], message: "policy-only plaintext cannot carry delivery metadata" });
|
|
27876
|
+
if (value.recipientMatcher.kind === "exactEmail" && value.deliveryEmail !== void 0 && value.deliveryEmail !== value.recipientMatcher.value) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["deliveryEmail"], message: "delivery email must match the exact matcher" });
|
|
27877
|
+
if (value.recipientMatcher.kind === "emailDomain" && value.deliveryEmail !== void 0 && value.deliveryEmail.toLowerCase().endsWith(`@${value.recipientMatcher.value}`) === false) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["deliveryEmail"], message: "delivery email must belong to the matcher domain" });
|
|
27878
|
+
if (value.contentSource.kind === "kv" && value.contentSource.action !== "tinycloud.kv/get") ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["contentSource"], message: "source action mismatch" });
|
|
27879
|
+
if (value.contentSource.kind === "sql" && value.contentSource.action !== "tinycloud.sql/read") ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["contentSource"], message: "source action mismatch" });
|
|
27880
|
+
}
|
|
27881
|
+
var unsignedShareEnvelopeV2Schema4 = unsignedShareEnvelopeV2BaseSchema4.superRefine(validateV2Invariants4);
|
|
27882
|
+
var shareEnvelopeV2Schema4 = unsignedShareEnvelopeV2BaseSchema4.extend({ signature: signatureSchema4 }).strict().superRefine(validateV2Invariants4);
|
|
27883
|
+
var unifiedResourceSchema4 = external_exports3.string().refine((value) => {
|
|
27884
|
+
const marker = value.indexOf("/kv/");
|
|
27885
|
+
if (marker < 1) return false;
|
|
27886
|
+
const space = value.slice(0, marker);
|
|
27887
|
+
const legacy = space.startsWith("tinycloud://");
|
|
27888
|
+
if (legacy ? /[:/?#%]/.test(space.slice("tinycloud://".length)) : !space.startsWith("tinycloud:") || /[/?#%]/.test(space)) return false;
|
|
27889
|
+
const path = value.slice(marker + 4);
|
|
27890
|
+
return !path.startsWith("/") && !path.endsWith("/") && !path.includes("//") && path.split("/").every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
|
|
27891
|
+
}, { message: "expected canonical TinyCloud KV resource" });
|
|
27892
|
+
var unifiedEncryptionNetworkSchema4 = external_exports3.string().refine((value) => {
|
|
27893
|
+
if (!value.startsWith("urn:tinycloud:encryption:")) return false;
|
|
27894
|
+
const rest = value.slice("urn:tinycloud:encryption:".length);
|
|
27895
|
+
const separator = rest.lastIndexOf(":");
|
|
27896
|
+
const owner = separator < 0 ? "" : rest.slice(0, separator);
|
|
27897
|
+
const network = separator < 0 ? "" : rest.slice(separator + 1);
|
|
27898
|
+
return owner.startsWith("did:") && owner.length > 4 && network.length > 0 && !/[:/%?#\s]/.test(network);
|
|
27899
|
+
}, { message: "expected canonical TinyCloud encryption network" });
|
|
27900
|
+
var unifiedKvCapabilitySchema4 = external_exports3.object({
|
|
27901
|
+
kind: external_exports3.literal("kv"),
|
|
27902
|
+
resource: unifiedResourceSchema4,
|
|
27903
|
+
selector: external_exports3.union([external_exports3.literal("exact"), external_exports3.literal("prefix")]),
|
|
27904
|
+
actions: external_exports3.array(external_exports3.union([
|
|
27905
|
+
external_exports3.literal("tinycloud.kv/get"),
|
|
27906
|
+
external_exports3.literal("tinycloud.kv/list"),
|
|
27907
|
+
external_exports3.literal("tinycloud.kv/metadata"),
|
|
27908
|
+
external_exports3.literal("tinycloud.kv/put")
|
|
27909
|
+
])).min(1)
|
|
27910
|
+
}).strict();
|
|
27911
|
+
var unifiedEncryptionCapabilitySchema4 = external_exports3.object({
|
|
27912
|
+
kind: external_exports3.literal("encryption"),
|
|
27913
|
+
resource: unifiedEncryptionNetworkSchema4,
|
|
27914
|
+
action: external_exports3.literal("tinycloud.encryption/decrypt")
|
|
27915
|
+
}).strict();
|
|
27916
|
+
var unifiedCapabilitySchema4 = external_exports3.union([unifiedKvCapabilitySchema4, unifiedEncryptionCapabilitySchema4]);
|
|
27917
|
+
var unifiedContentSourceSchema4 = external_exports3.object({
|
|
27918
|
+
shareId: external_exports3.string().min(1),
|
|
27919
|
+
kvResource: unifiedResourceSchema4,
|
|
27920
|
+
selector: external_exports3.union([external_exports3.literal("exact"), external_exports3.literal("prefix")]),
|
|
27921
|
+
encryptionNetwork: unifiedEncryptionNetworkSchema4,
|
|
27922
|
+
encryptedSymmetricKeyDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/),
|
|
27923
|
+
keyVersion: external_exports3.number().int().positive(),
|
|
27924
|
+
mode: external_exports3.union([external_exports3.literal("mutable"), external_exports3.literal("immutable")]),
|
|
27925
|
+
initialCiphertextDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/).optional()
|
|
27926
|
+
}).strict();
|
|
27927
|
+
var unifiedPolicyV1Schema4 = external_exports3.object({
|
|
27928
|
+
schema: external_exports3.literal("xyz.tinycloud.policy/policy/v1"),
|
|
27929
|
+
policyId: external_exports3.string().regex(/^pol_[a-z2-7]+$/),
|
|
27930
|
+
ownerDid: external_exports3.string().min(1),
|
|
27931
|
+
createdAt: external_exports3.string().datetime({ offset: true }),
|
|
27932
|
+
expiresAt: external_exports3.string().datetime({ offset: true }).optional(),
|
|
27933
|
+
contentSource: unifiedContentSourceSchema4,
|
|
27934
|
+
capabilityCeiling: external_exports3.array(unifiedCapabilitySchema4).min(2),
|
|
27935
|
+
signature: external_exports3.object({ suite: external_exports3.string().min(1), signerDid: external_exports3.string().min(1), value: external_exports3.string().min(1) }).strict()
|
|
27936
|
+
}).strict();
|
|
27937
|
+
var policyCredentialRequirementV1Schema4 = external_exports3.object({
|
|
27938
|
+
type: external_exports3.literal("TinyCloudPolicyCredentialRequirement"),
|
|
27939
|
+
version: external_exports3.literal(1),
|
|
27940
|
+
requirementDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
|
|
27941
|
+
descriptorDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
|
|
27942
|
+
issuerDid: external_exports3.string().min(1),
|
|
27943
|
+
issuerKid: external_exports3.string().min(1),
|
|
27944
|
+
profile: external_exports3.object({ id: external_exports3.string().min(1), version: external_exports3.literal(1) }).strict(),
|
|
27945
|
+
credentialType: external_exports3.object({ id: external_exports3.string().min(1), version: external_exports3.literal(1) }).strict()
|
|
27946
|
+
}).strict();
|
|
27947
|
+
var unifiedPolicyV2Schema4 = external_exports3.object({
|
|
27948
|
+
schema: external_exports3.literal("xyz.tinycloud.policy/policy/v2"),
|
|
27949
|
+
policyId: external_exports3.string().regex(/^pol_[a-z2-7]+$/),
|
|
27950
|
+
ownerDid: external_exports3.string().min(1),
|
|
27951
|
+
createdAt: external_exports3.string().datetime({ offset: true }),
|
|
27952
|
+
expiresAt: external_exports3.string().datetime({ offset: true }).optional(),
|
|
27953
|
+
contentSource: unifiedContentSourceSchema4,
|
|
27954
|
+
capabilityCeiling: external_exports3.array(unifiedCapabilitySchema4).min(2),
|
|
27955
|
+
credentialRequirement: policyCredentialRequirementV1Schema4,
|
|
27956
|
+
signature: external_exports3.object({ suite: external_exports3.literal("Ed25519"), signerDid: external_exports3.string().min(1), value: external_exports3.string().min(1) }).strict()
|
|
27957
|
+
}).strict();
|
|
27958
|
+
var unifiedPolicySchema4 = external_exports3.discriminatedUnion("schema", [
|
|
27959
|
+
unifiedPolicyV1Schema4,
|
|
27960
|
+
unifiedPolicyV2Schema4
|
|
27961
|
+
]);
|
|
27962
|
+
var unifiedRootSchema4 = external_exports3.object({
|
|
27963
|
+
cid: external_exports3.string().min(1),
|
|
27964
|
+
authorization: external_exports3.string().regex(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/),
|
|
27965
|
+
role: external_exports3.union([external_exports3.literal("policy-authority"), external_exports3.literal("policy-enforcement")])
|
|
27966
|
+
}).strict();
|
|
27967
|
+
var attestedEnforcerBindingV2Schema4 = external_exports3.object({
|
|
27968
|
+
schema: external_exports3.literal("xyz.tinycloud.policy/attested-enforcer/v2"),
|
|
27969
|
+
enforcerDid: external_exports3.string().regex(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/),
|
|
27970
|
+
nodeAudience: external_exports3.string().min(1),
|
|
27971
|
+
attestationBindingDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/),
|
|
27972
|
+
issuedAt: external_exports3.string().datetime({ offset: true }),
|
|
27973
|
+
expiresAt: external_exports3.string().datetime({ offset: true }),
|
|
27974
|
+
signature: external_exports3.object({ suite: external_exports3.literal("Ed25519"), signerDid: external_exports3.string().min(1), value: base64UrlString4() }).strict()
|
|
27975
|
+
}).strict();
|
|
27976
|
+
var v3TargetSchema4 = external_exports3.object({
|
|
27977
|
+
origin: external_exports3.string().refine(isCanonicalHttpsOrigin4, { message: "expected a canonical https origin" }),
|
|
27978
|
+
nodeAudience: external_exports3.string().min(1),
|
|
27979
|
+
spaceId: external_exports3.string().refine(isCanonicalPathSegment4, { message: "expected a canonical space id" })
|
|
27980
|
+
}).strict();
|
|
27981
|
+
var ARTIFACT_ID_PATTERN4 = /^[a-z0-9][a-z0-9_-]{2,62}$/;
|
|
27982
|
+
var artifactPinSchema4 = external_exports3.object({
|
|
27983
|
+
v: external_exports3.literal(1),
|
|
27984
|
+
artifactId: external_exports3.string().regex(ARTIFACT_ID_PATTERN4),
|
|
27985
|
+
version: external_exports3.number().int().min(1).max(Number.MAX_SAFE_INTEGER),
|
|
27986
|
+
/** SHA-256 (lowercase hex) of the exact `manifest.json` bytes. The manifest itself stays an owner-side record. */
|
|
27987
|
+
manifestSha256: external_exports3.string().regex(/^[0-9a-f]{64}$/),
|
|
27988
|
+
/** An addressed share reads one exact file, so exactly one entry: the stored bytes (ciphertext) it will fetch. */
|
|
27989
|
+
files: external_exports3.array(external_exports3.object({
|
|
27990
|
+
path: external_exports3.string().min(1).max(255),
|
|
27991
|
+
sha256: external_exports3.string().regex(/^[0-9a-f]{64}$/),
|
|
27992
|
+
bytes: external_exports3.number().int().nonnegative()
|
|
27993
|
+
}).strict()).length(1)
|
|
27994
|
+
}).strict();
|
|
27995
|
+
var unsignedShareEnvelopeV3BaseSchema4 = external_exports3.object({
|
|
27996
|
+
version: external_exports3.literal(3),
|
|
27997
|
+
shareId: external_exports3.string().min(1),
|
|
27998
|
+
recipientMatcher: recipientMatcherSchema4,
|
|
27999
|
+
deliveryEmail: deliveryEmailSchema4.optional(),
|
|
28000
|
+
actions: external_exports3.array(shareActionSchema4).min(1).max(3),
|
|
28001
|
+
resource: resourceSelectorSchema4,
|
|
28002
|
+
target: v3TargetSchema4,
|
|
28003
|
+
policy: unifiedPolicySchema4,
|
|
28004
|
+
policyCid: external_exports3.string().min(1),
|
|
28005
|
+
policyRoot: unifiedRootSchema4,
|
|
28006
|
+
enforcementRoot: unifiedRootSchema4,
|
|
28007
|
+
attestedEnforcerBinding: attestedEnforcerBindingV2Schema4,
|
|
28008
|
+
contentSource: unifiedContentSourceSchema4,
|
|
28009
|
+
contentSourceDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/),
|
|
28010
|
+
encryptionNetwork: unifiedEncryptionNetworkSchema4,
|
|
28011
|
+
expiry: external_exports3.string().datetime({ offset: true }),
|
|
28012
|
+
display: displaySchema4,
|
|
28013
|
+
encrypted: external_exports3.literal(true),
|
|
28014
|
+
metadata: contentMetadataSchema4,
|
|
28015
|
+
/**
|
|
28016
|
+
* TC-1428: an owner-signed statement that this share reads one write-once artifact version. Additive: absent on
|
|
28017
|
+
* every other share, and covered by the envelope signature because the signature spans the whole unsigned object.
|
|
28018
|
+
* The shape is checked here; its binding to the content source is `verifyArtifactShare` in share-sdk.
|
|
28019
|
+
*/
|
|
28020
|
+
artifactPin: artifactPinSchema4.optional()
|
|
28021
|
+
}).strict();
|
|
28022
|
+
function validateV3Invariants4(value, ctx) {
|
|
28023
|
+
const actions = [...value.actions];
|
|
28024
|
+
if (new Set(actions).size !== actions.length || actions.some((action, index) => action !== ["read", "list", "edit"].filter((candidate) => actions.includes(candidate))[index])) {
|
|
28025
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["actions"], message: "actions must be unique and canonically ordered" });
|
|
28026
|
+
}
|
|
28027
|
+
if (value.policyRoot.role !== "policy-authority" || value.enforcementRoot.role !== "policy-enforcement") {
|
|
28028
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policyRoot", "role"], message: "root roles are fixed" });
|
|
28029
|
+
}
|
|
28030
|
+
if (value.policyCid.length === 0 || value.policyCid === value.policyRoot.cid || value.policyCid === value.enforcementRoot.cid) {
|
|
28031
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policyCid"], message: "policy CID must be distinct from both roots" });
|
|
28032
|
+
}
|
|
28033
|
+
if (value.contentSource.encryptionNetwork !== value.encryptionNetwork) {
|
|
28034
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["encryptionNetwork"], message: "encryption network is not bound to the source" });
|
|
28035
|
+
}
|
|
28036
|
+
if (value.attestedEnforcerBinding.nodeAudience !== value.target.nodeAudience || value.attestedEnforcerBinding.signature.signerDid !== value.attestedEnforcerBinding.nodeAudience || Date.parse(value.attestedEnforcerBinding.expiresAt) < Date.parse(value.expiry)) {
|
|
28037
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["attestedEnforcerBinding"], message: "enforcer binding does not cover the target and share lifetime" });
|
|
28038
|
+
}
|
|
28039
|
+
if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
|
|
28040
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["contentSource"], message: "content source is not bound to policy" });
|
|
28041
|
+
}
|
|
28042
|
+
if (value.policy.signature.suite !== "Ed25519" || value.policy.signature.signerDid !== value.policy.ownerDid) {
|
|
28043
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policy", "signature"], message: "policy must be signed by its owner" });
|
|
28044
|
+
}
|
|
28045
|
+
const kvCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "kv");
|
|
28046
|
+
const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === value.encryptionNetwork && capability.action === "tinycloud.encryption/decrypt");
|
|
28047
|
+
if (value.policy.capabilityCeiling.length !== 2 || kvCapabilities.length !== 1 || decryptCapabilities.length !== 1 || kvCapabilities[0]?.resource !== value.contentSource.kvResource || kvCapabilities[0]?.selector !== value.contentSource.selector) {
|
|
28048
|
+
ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain exact decrypt network" });
|
|
28049
|
+
}
|
|
28050
|
+
}
|
|
28051
|
+
var unsignedShareEnvelopeV3Schema4 = unsignedShareEnvelopeV3BaseSchema4.superRefine(validateV3Invariants4);
|
|
28052
|
+
var shareEnvelopeV3Schema4 = unsignedShareEnvelopeV3BaseSchema4.extend({ signature: signatureSchema4 }).strict().superRefine(validateV3Invariants4);
|
|
28053
|
+
var KEY_LENGTH3 = 32;
|
|
28054
|
+
var MAX_INLINE_BYTES4 = 256 * 1024;
|
|
28055
|
+
function assertCanonicalCid3(cidString) {
|
|
28056
|
+
const cid = CID4.parse(cidString);
|
|
28057
|
+
if (cid.version !== 1 || cid.code !== code4 || cid.multihash.code !== 18 || // sha2-256 (0x12) only, at the link layer too
|
|
28058
|
+
cid.toString() !== cidString) {
|
|
28059
|
+
throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
|
|
28060
|
+
}
|
|
28061
|
+
}
|
|
28062
|
+
async function parseSealedInlineShareUrl3(url, options = {}) {
|
|
28063
|
+
const parsed = new URL(url);
|
|
28064
|
+
if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("sealed inline share URL must be canonical HTTPS without userinfo");
|
|
28065
|
+
if (!isCanonicalHttpsOrigin4(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("sealed inline share URL origin is not trusted");
|
|
28066
|
+
if (parsed.pathname !== "/s/inline" || parsed.search !== "") throw new TypeError("not a Node sealed-inline share URL");
|
|
28067
|
+
if (url !== `${parsed.origin}/s/inline${parsed.hash}`) throw new TypeError("sealed inline share URL is not lexically canonical");
|
|
28068
|
+
const prefix = "#v=2&p=";
|
|
28069
|
+
if (!parsed.hash.startsWith(prefix)) throw new TypeError("sealed inline URL is missing its canonical fragment");
|
|
28070
|
+
const encoded = parsed.hash.slice(prefix.length);
|
|
28071
|
+
if (encoded.length === 0 || parsed.hash !== `${prefix}${encoded}`) throw new TypeError("sealed inline URL fragment is not canonical");
|
|
28072
|
+
let payloadBytes;
|
|
28073
|
+
try {
|
|
28074
|
+
payloadBytes = fromBase64Url4(encoded);
|
|
28075
|
+
} catch {
|
|
28076
|
+
throw new TypeError("sealed inline payload is not canonical base64url");
|
|
28077
|
+
}
|
|
28078
|
+
if (payloadBytes.byteLength === 0 || payloadBytes.byteLength > MAX_INLINE_BYTES4 * 2) throw new TypeError("sealed inline payload is too large");
|
|
28079
|
+
const payloadText = new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes);
|
|
28080
|
+
let value;
|
|
28081
|
+
try {
|
|
28082
|
+
value = JSON.parse(payloadText);
|
|
28083
|
+
} catch {
|
|
28084
|
+
throw new TypeError("sealed inline payload is not valid JSON");
|
|
28085
|
+
}
|
|
28086
|
+
if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize4(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
|
|
28087
|
+
const record2 = value;
|
|
28088
|
+
if (Object.keys(record2).length !== 4 || record2.v !== 2 || typeof record2.c !== "string" || typeof record2.cid !== "string" || typeof record2.k !== "string") throw new TypeError("sealed inline payload has invalid fields");
|
|
28089
|
+
let ciphertext;
|
|
28090
|
+
let key32;
|
|
28091
|
+
try {
|
|
28092
|
+
ciphertext = fromBase64Url4(record2.c);
|
|
28093
|
+
key32 = fromBase64Url4(record2.k);
|
|
28094
|
+
} catch {
|
|
28095
|
+
throw new TypeError("sealed inline payload has invalid base64url material");
|
|
28096
|
+
}
|
|
28097
|
+
if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES4) throw new TypeError("sealed inline ciphertext is outside the allowed size");
|
|
28098
|
+
if (key32.byteLength !== KEY_LENGTH3) throw new TypeError("sealed inline key must be 32 bytes");
|
|
28099
|
+
assertCanonicalCid3(record2.cid);
|
|
28100
|
+
if (await computeCid3(ciphertext) !== record2.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
|
|
28101
|
+
return { kind: "inline", ciphertextCid: record2.cid, ciphertext, key32 };
|
|
28102
|
+
}
|
|
28103
|
+
var SHORT_LINK_ID_PATTERN = /^[a-z2-7]{26}$/;
|
|
28104
|
+
function assertShortLinkId(id) {
|
|
28105
|
+
if (!SHORT_LINK_ID_PATTERN.test(id)) throw new TypeError("short link id must be 26 lowercase base32 characters");
|
|
28106
|
+
}
|
|
28107
|
+
function parseShortShareUrl(url, options = {}) {
|
|
28108
|
+
let parsed;
|
|
28109
|
+
try {
|
|
28110
|
+
parsed = new URL(url);
|
|
28111
|
+
} catch {
|
|
28112
|
+
throw new TypeError("short share URL is not a URL");
|
|
28113
|
+
}
|
|
28114
|
+
if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("short share URL must be canonical HTTPS without userinfo");
|
|
28115
|
+
if (!isCanonicalHttpsOrigin4(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("short share URL origin is not trusted");
|
|
28116
|
+
if (parsed.search !== "") throw new TypeError("short share URL must not have a query string");
|
|
28117
|
+
const match = /^\/s\/([A-Za-z2-7]{26})$/.exec(parsed.pathname);
|
|
28118
|
+
if (match === null) throw new TypeError("not a short share URL path");
|
|
28119
|
+
const id = match[1].toLowerCase();
|
|
28120
|
+
const fragment = /^#v=3&k=([A-Za-z0-9_-]{43})&c=([a-z2-7]+)$/.exec(parsed.hash);
|
|
28121
|
+
if (fragment === null) throw new TypeError("short share URL fragment is not canonical");
|
|
28122
|
+
const k = fragment[1];
|
|
28123
|
+
const ciphertextCid = fragment[2];
|
|
28124
|
+
if (url !== `${parsed.origin}${parsed.pathname}${parsed.hash}`) throw new TypeError("short share URL is not lexically canonical");
|
|
28125
|
+
let key32;
|
|
28126
|
+
try {
|
|
28127
|
+
key32 = fromBase64Url4(k);
|
|
28128
|
+
} catch {
|
|
28129
|
+
throw new TypeError("short share URL key is not canonical base64url");
|
|
28130
|
+
}
|
|
28131
|
+
if (key32.byteLength !== KEY_LENGTH3) throw new TypeError("short share URL key must be 32 bytes");
|
|
28132
|
+
try {
|
|
28133
|
+
assertCanonicalCid3(ciphertextCid);
|
|
28134
|
+
} catch {
|
|
28135
|
+
throw new TypeError("short share URL CID is not canonical");
|
|
28136
|
+
}
|
|
28137
|
+
return { kind: "short", origin: parsed.origin, id, k, key32, ciphertextCid };
|
|
28138
|
+
}
|
|
28139
|
+
async function splitInlineToShort(inlineUrl, id) {
|
|
28140
|
+
assertShortLinkId(id);
|
|
28141
|
+
const inline = await parseSealedInlineShareUrl3(inlineUrl);
|
|
28142
|
+
const origin = new URL(inlineUrl).origin;
|
|
28143
|
+
return `${origin}/s/${id}#v=3&k=${toBase64Url3(inline.key32)}&c=${inline.ciphertextCid}`;
|
|
28144
|
+
}
|
|
28145
|
+
async function rebuildInlineFromShort(shortUrl, ciphertextB64Url) {
|
|
28146
|
+
const short = parseShortShareUrl(shortUrl);
|
|
28147
|
+
let ciphertext;
|
|
28148
|
+
try {
|
|
28149
|
+
ciphertext = fromBase64Url4(ciphertextB64Url);
|
|
28150
|
+
} catch {
|
|
28151
|
+
throw new TypeError("short link ciphertext is not canonical base64url");
|
|
28152
|
+
}
|
|
28153
|
+
if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES4) throw new TypeError("short link ciphertext is outside the allowed size");
|
|
28154
|
+
if (await computeCid3(ciphertext) !== short.ciphertextCid) throw new TypeError("short link ciphertext does not match the link's CID");
|
|
28155
|
+
return { v: 2, c: ciphertextB64Url, cid: short.ciphertextCid, k: short.k };
|
|
28156
|
+
}
|
|
28157
|
+
|
|
28158
|
+
// src/share/short-links.ts
|
|
28159
|
+
var MAX_SHORT_LINK_BYTES = 128 * 1024;
|
|
28160
|
+
var REQUEST_TIMEOUT_MS = 1e4;
|
|
28161
|
+
var DELETE_TOKEN = /^[A-Za-z0-9_-]{43}$/;
|
|
28162
|
+
var ShortLinkError = class extends Error {
|
|
28163
|
+
constructor(code5, message, options) {
|
|
28164
|
+
super(message, options);
|
|
28165
|
+
this.code = code5;
|
|
28166
|
+
this.name = "ShortLinkError";
|
|
28167
|
+
}
|
|
28168
|
+
};
|
|
28169
|
+
function shortLinkTokenKey(shareId) {
|
|
28170
|
+
return `xyz.tinycloud.share/shares/${shareId}/.short-link.json`;
|
|
28171
|
+
}
|
|
28172
|
+
async function readCapped(response, max) {
|
|
28173
|
+
if (response.body === null) return new Uint8Array(0);
|
|
28174
|
+
const reader = response.body.getReader();
|
|
28175
|
+
const chunks = [];
|
|
28176
|
+
let total = 0;
|
|
28177
|
+
for (; ; ) {
|
|
28178
|
+
const { done, value } = await reader.read();
|
|
28179
|
+
if (done) break;
|
|
28180
|
+
total += value.byteLength;
|
|
28181
|
+
if (total > max) {
|
|
28182
|
+
await reader.cancel().catch(() => void 0);
|
|
28183
|
+
throw new ShortLinkError("too-large", "the short-link service returned too many bytes");
|
|
28184
|
+
}
|
|
28185
|
+
chunks.push(value);
|
|
28186
|
+
}
|
|
28187
|
+
const bytes = new Uint8Array(total);
|
|
28188
|
+
let offset = 0;
|
|
28189
|
+
for (const chunk of chunks) {
|
|
28190
|
+
bytes.set(chunk, offset);
|
|
28191
|
+
offset += chunk.byteLength;
|
|
28192
|
+
}
|
|
28193
|
+
return bytes;
|
|
28194
|
+
}
|
|
28195
|
+
function parseShortLinkRecord(bytes) {
|
|
28196
|
+
let value;
|
|
28197
|
+
try {
|
|
28198
|
+
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
28199
|
+
} catch {
|
|
28200
|
+
return void 0;
|
|
28201
|
+
}
|
|
28202
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
28203
|
+
const record2 = value;
|
|
28204
|
+
if (typeof record2.id !== "string" || !SHORT_LINK_ID_PATTERN.test(record2.id)) return void 0;
|
|
28205
|
+
if (typeof record2.deleteToken !== "string" || !DELETE_TOKEN.test(record2.deleteToken)) return void 0;
|
|
28206
|
+
return { id: record2.id, deleteToken: record2.deleteToken };
|
|
28207
|
+
}
|
|
28208
|
+
function serializeShortLinkRecord(record2) {
|
|
28209
|
+
return new TextEncoder().encode(JSON.stringify({ id: record2.id, deleteToken: record2.deleteToken }));
|
|
28210
|
+
}
|
|
28211
|
+
function request(init, timeoutMs) {
|
|
28212
|
+
return { ...init, credentials: "omit", redirect: "error", referrerPolicy: "no-referrer", signal: AbortSignal.timeout(timeoutMs) };
|
|
28213
|
+
}
|
|
28214
|
+
async function send(fetchFn, url, init, timeoutMs) {
|
|
28215
|
+
try {
|
|
28216
|
+
return await fetchFn(url, request(init, timeoutMs));
|
|
28217
|
+
} catch (error) {
|
|
28218
|
+
throw new ShortLinkError("unavailable", "the short-link service could not be reached", { cause: error });
|
|
28219
|
+
}
|
|
28220
|
+
}
|
|
28221
|
+
function statusError(response) {
|
|
28222
|
+
if (response.status === 429) return new ShortLinkError("rate-limited", "the short-link service is rate limiting this client");
|
|
28223
|
+
if (response.status === 503) return new ShortLinkError("capacity", "the short-link service is at capacity");
|
|
28224
|
+
if (response.status === 404) return new ShortLinkError("not-found", "the short link has expired, was revoked, or never existed");
|
|
28225
|
+
if (response.status >= 400 && response.status < 500) return new ShortLinkError("rejected", `the short-link service rejected the request (HTTP ${response.status})`);
|
|
28226
|
+
return new ShortLinkError("unavailable", `the short-link service failed (HTTP ${response.status})`);
|
|
28227
|
+
}
|
|
28228
|
+
function createShortLinkClient(origin, fetchFn = globalThis.fetch, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
28229
|
+
const base5 = `${origin}/api/share-links`;
|
|
28230
|
+
return {
|
|
28231
|
+
async create(ciphertext, expiresAt) {
|
|
28232
|
+
if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_SHORT_LINK_BYTES) throw new ShortLinkError("too-large", "the sealed share is too large for a short link");
|
|
28233
|
+
const expectedCid = await computeCid2(ciphertext);
|
|
28234
|
+
const response = await send(fetchFn, base5, {
|
|
28235
|
+
method: "POST",
|
|
28236
|
+
headers: { "content-type": "application/json", accept: "application/json" },
|
|
28237
|
+
body: JSON.stringify({ ciphertext: toBase64Url2(ciphertext), expiresAt: expiresAt.toISOString() })
|
|
28238
|
+
}, timeoutMs);
|
|
28239
|
+
if (response.status !== 201) throw statusError(response);
|
|
28240
|
+
let value;
|
|
28241
|
+
try {
|
|
28242
|
+
value = await response.json();
|
|
28243
|
+
} catch {
|
|
28244
|
+
throw new ShortLinkError("invalid-response", "the short-link service returned an unreadable response");
|
|
28245
|
+
}
|
|
28246
|
+
const body = typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
28247
|
+
if (typeof body.id !== "string" || !SHORT_LINK_ID_PATTERN.test(body.id)) throw new ShortLinkError("invalid-response", "the short-link service returned an invalid id");
|
|
28248
|
+
if (typeof body.deleteToken !== "string" || !DELETE_TOKEN.test(body.deleteToken) || fromBase64Url3(body.deleteToken).byteLength !== 32) {
|
|
28249
|
+
throw new ShortLinkError("invalid-response", "the short-link service returned an invalid delete token");
|
|
28250
|
+
}
|
|
28251
|
+
if (body.cid !== expectedCid) throw new ShortLinkError("invalid-response", "the short-link service stored different bytes than were sent");
|
|
28252
|
+
return { id: body.id, deleteToken: body.deleteToken };
|
|
28253
|
+
},
|
|
28254
|
+
async fetchCiphertext(id) {
|
|
28255
|
+
if (!SHORT_LINK_ID_PATTERN.test(id)) throw new ShortLinkError("not-found", "the short link has expired, was revoked, or never existed");
|
|
28256
|
+
const response = await send(fetchFn, `${base5}/${id}`, { method: "GET", headers: { accept: "application/octet-stream" } }, timeoutMs);
|
|
28257
|
+
if (response.status !== 200) throw statusError(response);
|
|
28258
|
+
if ((response.headers.get("content-type") ?? "").split(";", 1)[0].trim().toLowerCase() !== "application/octet-stream") {
|
|
28259
|
+
await response.body?.cancel().catch(() => void 0);
|
|
28260
|
+
throw new ShortLinkError("invalid-response", "the short-link service did not return sealed bytes");
|
|
28261
|
+
}
|
|
28262
|
+
const declared = Number(response.headers.get("content-length") ?? "0");
|
|
28263
|
+
if (declared > MAX_SHORT_LINK_BYTES) {
|
|
28264
|
+
await response.body?.cancel().catch(() => void 0);
|
|
28265
|
+
throw new ShortLinkError("too-large", "the short-link service returned too many bytes");
|
|
28266
|
+
}
|
|
28267
|
+
const bytes = await readCapped(response, MAX_SHORT_LINK_BYTES);
|
|
28268
|
+
if (bytes.byteLength === 0) throw new ShortLinkError("invalid-response", "the short-link service returned no bytes");
|
|
28269
|
+
return bytes;
|
|
28270
|
+
},
|
|
28271
|
+
async delete(record2) {
|
|
28272
|
+
const response = await send(fetchFn, `${base5}/${record2.id}`, { method: "DELETE", headers: { authorization: `Bearer ${record2.deleteToken}` } }, timeoutMs);
|
|
28273
|
+
if (response.status === 204) return "deleted";
|
|
28274
|
+
if (response.status === 404) return "absent";
|
|
28275
|
+
throw statusError(response);
|
|
28276
|
+
}
|
|
28277
|
+
};
|
|
28278
|
+
}
|
|
28279
|
+
async function shortenInlineLink(input) {
|
|
28280
|
+
const inline = await parseSealedInlineShareUrl2(input.inlineUrl);
|
|
28281
|
+
const record2 = await input.client.create(inline.ciphertext, input.expiresAt);
|
|
28282
|
+
try {
|
|
28283
|
+
await input.tokens.write(input.shareId, record2);
|
|
28284
|
+
} catch (error) {
|
|
28285
|
+
await input.client.delete(record2).catch(() => void 0);
|
|
28286
|
+
throw new ShortLinkError("token-store-failed", "the short link's delete token could not be saved", { cause: error });
|
|
28287
|
+
}
|
|
28288
|
+
return splitInlineToShort(input.inlineUrl, record2.id);
|
|
28289
|
+
}
|
|
28290
|
+
async function resolveShortLink(link4, options) {
|
|
28291
|
+
let short;
|
|
28292
|
+
try {
|
|
28293
|
+
short = parseShortShareUrl(link4);
|
|
28294
|
+
} catch {
|
|
28295
|
+
return link4;
|
|
28296
|
+
}
|
|
28297
|
+
if (short.origin !== options.expectedOrigin) throw new ShortLinkError("rejected", "the short link is not from the trusted Share origin");
|
|
28298
|
+
const ciphertext = await createShortLinkClient(options.expectedOrigin, options.fetchFn).fetchCiphertext(short.id);
|
|
28299
|
+
let payload;
|
|
28300
|
+
try {
|
|
28301
|
+
payload = await rebuildInlineFromShort(link4, toBase64Url2(ciphertext));
|
|
28302
|
+
} catch (error) {
|
|
28303
|
+
throw new ShortLinkError("invalid-response", "the short-link service returned bytes that do not match the link", { cause: error });
|
|
28304
|
+
}
|
|
28305
|
+
return encodeSealedInlineShareUrl2({ origin: short.origin, ciphertext: fromBase64Url3(payload.c), key32: fromBase64Url3(payload.k) });
|
|
28306
|
+
}
|
|
28307
|
+
function kvErrorCode(error) {
|
|
28308
|
+
return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
28309
|
+
}
|
|
28310
|
+
function kvShortLinkTokenStore(kv) {
|
|
28311
|
+
return {
|
|
28312
|
+
async read(shareId) {
|
|
28313
|
+
const read5 = await (await kv()).get(shortLinkTokenKey(shareId), { binary: true });
|
|
28314
|
+
if (read5.ok) return parseShortLinkRecord(new Uint8Array(read5.data.data));
|
|
28315
|
+
if (kvErrorCode(read5.error) === "KV_NOT_FOUND") return void 0;
|
|
28316
|
+
throw new Error(`could not read the short-link token (${kvErrorCode(read5.error) ?? "unknown error"})`);
|
|
28317
|
+
},
|
|
28318
|
+
async write(shareId, record2) {
|
|
28319
|
+
const written = await (await kv()).put(shortLinkTokenKey(shareId), serializeShortLinkRecord(record2), { contentType: "application/json" });
|
|
28320
|
+
if (!written.ok) throw new Error(`could not write the short-link token (${kvErrorCode(written.error) ?? "unknown error"})`);
|
|
28321
|
+
},
|
|
28322
|
+
async remove(shareId) {
|
|
28323
|
+
const removed = await (await kv()).delete(shortLinkTokenKey(shareId));
|
|
28324
|
+
if (!removed.ok && kvErrorCode(removed.error) !== "KV_NOT_FOUND") throw new Error(`could not remove the short-link token (${kvErrorCode(removed.error) ?? "unknown error"})`);
|
|
28325
|
+
}
|
|
28326
|
+
};
|
|
28327
|
+
}
|
|
28328
|
+
function isInlineLink(link4) {
|
|
28329
|
+
if (link4 === void 0) return false;
|
|
28330
|
+
try {
|
|
28331
|
+
return new URL(link4).pathname === "/s/inline";
|
|
28332
|
+
} catch {
|
|
28333
|
+
return false;
|
|
28334
|
+
}
|
|
28335
|
+
}
|
|
28336
|
+
function createShareShortLinks(input) {
|
|
28337
|
+
const tokens = (spaceId) => kvShortLinkTokenStore(() => input.kvForSpace(spaceId));
|
|
28338
|
+
const client = (inlineUrl) => createShortLinkClient(new URL(inlineUrl).origin, input.fetchFn, input.timeoutMs);
|
|
28339
|
+
return {
|
|
28340
|
+
async shorten(published) {
|
|
28341
|
+
if (published.link.kind !== "policy" || !isInlineLink(published.url)) throw new ShortLinkError("rejected", "only addressed shares get a short link");
|
|
28342
|
+
return shortenInlineLink({
|
|
28343
|
+
inlineUrl: published.url,
|
|
28344
|
+
shareId: published.metadata.shareId,
|
|
28345
|
+
expiresAt: new Date(published.metadata.expiresAt),
|
|
28346
|
+
client: client(published.url),
|
|
28347
|
+
tokens: tokens(published.metadata.target.spaceId)
|
|
28348
|
+
});
|
|
28349
|
+
},
|
|
28350
|
+
async linkFor(record2) {
|
|
28351
|
+
if (!isInlineLink(record2.link)) return void 0;
|
|
28352
|
+
const inlineUrl = record2.link;
|
|
28353
|
+
const stored = await tokens(record2.target.spaceId).read(record2.shareId).catch(() => void 0);
|
|
28354
|
+
return stored === void 0 ? void 0 : splitInlineToShort(inlineUrl, stored.id).catch(() => void 0);
|
|
28355
|
+
},
|
|
28356
|
+
async discard(record2) {
|
|
28357
|
+
if (!isInlineLink(record2.link)) return "none";
|
|
28358
|
+
return discardShortLink(record2.shareId, client(record2.link), tokens(record2.target.spaceId));
|
|
28359
|
+
},
|
|
28360
|
+
resolve: (link4, expectedOrigin) => resolveShortLink(link4, { expectedOrigin, ...input.fetchFn === void 0 ? {} : { fetchFn: input.fetchFn } })
|
|
28361
|
+
};
|
|
28362
|
+
}
|
|
28363
|
+
async function discardShortLink(shareId, client, tokens) {
|
|
28364
|
+
let record2;
|
|
28365
|
+
try {
|
|
28366
|
+
record2 = await tokens.read(shareId);
|
|
28367
|
+
} catch {
|
|
28368
|
+
return "failed";
|
|
28369
|
+
}
|
|
28370
|
+
if (record2 === void 0) return "none";
|
|
28371
|
+
try {
|
|
28372
|
+
await client.delete(record2);
|
|
28373
|
+
} catch {
|
|
28374
|
+
return "failed";
|
|
28375
|
+
}
|
|
28376
|
+
await tokens.remove(shareId).catch(() => void 0);
|
|
28377
|
+
return "deleted";
|
|
28378
|
+
}
|
|
28379
|
+
|
|
28380
|
+
// src/share/errors.ts
|
|
28381
|
+
var SharePublishAuthorityError = class extends Error {
|
|
28382
|
+
constructor(failure, options) {
|
|
28383
|
+
super(failure.kind, options);
|
|
28384
|
+
this.failure = failure;
|
|
28385
|
+
this.name = "SharePublishAuthorityError";
|
|
28386
|
+
}
|
|
28387
|
+
};
|
|
28388
|
+
var ShareHistoryRetryError = class extends Error {
|
|
28389
|
+
constructor(profile) {
|
|
28390
|
+
super("sender history changed during the operation");
|
|
28391
|
+
this.profile = profile;
|
|
28392
|
+
this.name = "ShareHistoryRetryError";
|
|
28393
|
+
}
|
|
28394
|
+
code = "SHARE_HISTORY_RETRY";
|
|
28395
|
+
};
|
|
28396
|
+
var ShareHistoryUnreadableError = class extends Error {
|
|
28397
|
+
constructor() {
|
|
28398
|
+
super("share history is unavailable");
|
|
28399
|
+
this.name = "ShareHistoryUnreadableError";
|
|
28400
|
+
}
|
|
28401
|
+
};
|
|
28402
|
+
var ShareHistoryReadError = class extends Error {
|
|
28403
|
+
constructor() {
|
|
28404
|
+
super("share history could not be read");
|
|
28405
|
+
this.name = "ShareHistoryReadError";
|
|
28406
|
+
}
|
|
28407
|
+
};
|
|
28408
|
+
var HISTORY_WRITE_ERROR_CODES = { EACCES: true, EPERM: true, EROFS: true, ENOSPC: true, EDQUOT: true, EIO: true };
|
|
28409
|
+
function shareHistoryReason(error) {
|
|
28410
|
+
if (error instanceof ShareHistoryUnreadableError) return "HISTORY_UNREADABLE";
|
|
28411
|
+
if (error instanceof ShareHistoryReadError) return "HISTORY_READ_FAILED";
|
|
28412
|
+
const code5 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
|
|
28413
|
+
return typeof code5 === "string" && HISTORY_WRITE_ERROR_CODES[code5] === true ? "HISTORY_WRITE_FAILED" : "HISTORY_UNAVAILABLE";
|
|
28414
|
+
}
|
|
28415
|
+
|
|
28416
|
+
// src/share/space-not-ready.ts
|
|
28417
|
+
function isSpaceNotFound(error) {
|
|
28418
|
+
if (typeof error !== "object" || error === null) return false;
|
|
28419
|
+
const message = "message" in error && typeof error.message === "string" ? error.message : "";
|
|
28420
|
+
if (!/space not found/i.test(message)) return false;
|
|
28421
|
+
const meta = "meta" in error && typeof error.meta === "object" && error.meta !== null ? error.meta : void 0;
|
|
28422
|
+
const status = meta !== void 0 && "status" in meta ? meta.status : void 0;
|
|
28423
|
+
return status === 404 || /\b404\b/.test(message);
|
|
28424
|
+
}
|
|
28425
|
+
function spaceNotReadyFailure(cause) {
|
|
28426
|
+
return new SharePublishAuthorityError({ kind: "space-not-ready" }, { cause });
|
|
28427
|
+
}
|
|
28428
|
+
function failIfSpaceNotReady(result) {
|
|
28429
|
+
if (!result.ok && isSpaceNotFound(result.error)) throw spaceNotReadyFailure(result.error);
|
|
28430
|
+
}
|
|
28431
|
+
function artifactSpaceNotReady(error) {
|
|
28432
|
+
return error instanceof ArtifactError && isSpaceNotFound(error.cause) ? spaceNotReadyFailure(error.cause) : error;
|
|
28433
|
+
}
|
|
28434
|
+
|
|
28435
|
+
// src/share/adapters.ts
|
|
28436
|
+
init_storage();
|
|
28437
|
+
init_profiles();
|
|
28438
|
+
init_constants();
|
|
28439
|
+
init_errors();
|
|
28440
|
+
init_session_expired();
|
|
28441
|
+
import { chmod as chmod4, link as link3, open as open8, readFile as readFile7, stat as stat5, unlink as unlink5 } from "fs/promises";
|
|
28442
|
+
import { dirname as dirname5, join as join12 } from "path";
|
|
28443
|
+
import { createHash } from "crypto";
|
|
28444
|
+
import { writeJsonAtomic as writeJsonAtomic2 } from "@tinycloud/operations/state";
|
|
28445
|
+
import { withoutBearer } from "@tinycloud/operations/delegation-binding";
|
|
28446
|
+
import {
|
|
28447
|
+
LocationRecordValidationError,
|
|
28448
|
+
LocationRegistryHttpError,
|
|
28449
|
+
parseSignedCompactUcanAttenuation,
|
|
28450
|
+
parseSignedSiweCacao,
|
|
28451
|
+
revokePolicyRootV3,
|
|
28452
|
+
signCompactUcanAuthorization
|
|
28453
|
+
} from "@tinycloud/sdk-core";
|
|
28454
|
+
import { extractSiweExpiration, InvalidRestoredSessionError } from "@tinycloud/node-sdk";
|
|
28455
|
+
function requiredKvAction(meta) {
|
|
28456
|
+
if (meta === null || typeof meta !== "object" || !("requiredAction" in meta)) return void 0;
|
|
28457
|
+
const action = meta.requiredAction;
|
|
28458
|
+
return action === "tinycloud.kv/put" || action === "tinycloud.kv/get" || action === "tinycloud.kv/list" ? action : void 0;
|
|
28459
|
+
}
|
|
28460
|
+
function throwKvUploadFailure(error) {
|
|
28461
|
+
const rejection = storageRejection(error);
|
|
28462
|
+
if (rejection) throw new SharePublishAuthorityError({ kind: "storage-full", ...rejection });
|
|
28463
|
+
throw new SharePublishAuthorityError({ kind: "upload-failed" });
|
|
28464
|
+
}
|
|
28465
|
+
var DEFAULT_SHARE_ORIGIN = "https://share.tinycloud.xyz";
|
|
28466
|
+
var MIN_DOMAIN_DELIVERY_VERSION = "1.17.3";
|
|
28467
|
+
function supportsDomainDelivery(version2) {
|
|
28468
|
+
if (typeof version2 !== "string") return false;
|
|
28469
|
+
const normalized = version2.trim();
|
|
28470
|
+
if (normalized.length > 128) return false;
|
|
28471
|
+
const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.exec(normalized);
|
|
28472
|
+
if (match === null) return false;
|
|
28473
|
+
if (match[4] !== void 0 && /(?:^|\.)0[0-9]+(?:\.|$)/.test(match[4])) return false;
|
|
28474
|
+
const major = Number(match[1]);
|
|
28475
|
+
const minor = Number(match[2]);
|
|
28476
|
+
const patch = Number(match[3]);
|
|
28477
|
+
if (!Number.isSafeInteger(major) || !Number.isSafeInteger(minor) || !Number.isSafeInteger(patch)) return false;
|
|
28478
|
+
if (major !== 1) return major > 1;
|
|
28479
|
+
if (minor !== 17) return minor > 17;
|
|
28480
|
+
if (patch !== 3) return patch > 3;
|
|
28481
|
+
return match[4] === void 0;
|
|
28482
|
+
}
|
|
28483
|
+
function displayedNodeVersion(version2) {
|
|
28484
|
+
if (typeof version2 !== "string") return "(unrecognized)";
|
|
28485
|
+
const trimmed = version2.trim();
|
|
28486
|
+
return /^[A-Za-z0-9.+_-]{1,64}$/.test(trimmed) ? trimmed : "(unrecognized)";
|
|
28487
|
+
}
|
|
28488
|
+
var URI_SAFE_FILENAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
28489
|
+
function safeStorageFilename(filename) {
|
|
28490
|
+
if (URI_SAFE_FILENAME.test(filename) && !filename.includes("..")) return filename;
|
|
28491
|
+
const dot = filename.lastIndexOf(".");
|
|
28492
|
+
const extension = dot >= 0 && /^[A-Za-z0-9]{1,16}$/.test(filename.slice(dot + 1)) ? filename.slice(dot + 1) : "";
|
|
28493
|
+
const stem = (extension === "" ? filename : filename.slice(0, dot)).normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(extension === "" ? /[^A-Za-z0-9_-]+/g : /[^A-Za-z0-9._-]+/g, "-").replace(/\.{2,}/g, ".").replace(/-{2,}/g, "-").slice(0, 100).replace(/^[^A-Za-z0-9]+|[-.]+$/g, "");
|
|
28494
|
+
return `${stem === "" ? "share" : stem}${extension === "" ? "" : `.${extension}`}`;
|
|
28495
|
+
}
|
|
28496
|
+
function scopeDeniedFromArtifactError(error, capability, authority) {
|
|
28497
|
+
const cause = error instanceof ArtifactError ? error.cause : void 0;
|
|
28498
|
+
const code5 = typeof cause === "object" && cause !== null && "code" in cause ? cause.code : void 0;
|
|
28499
|
+
if (code5 !== "AUTH_UNAUTHORIZED" && code5 !== "PERMISSION_DENIED") return void 0;
|
|
28500
|
+
const meta = typeof cause === "object" && cause !== null && "meta" in cause ? cause.meta : void 0;
|
|
28501
|
+
const requiredAction = requiredKvAction(meta);
|
|
28502
|
+
return new SharePublishAuthorityError({
|
|
28503
|
+
kind: "scope-denied",
|
|
28504
|
+
capability,
|
|
28505
|
+
...requiredAction === void 0 ? {} : { requiredAction },
|
|
28506
|
+
localKey: authority.localKey,
|
|
28507
|
+
profileName: authority.profileName
|
|
28508
|
+
});
|
|
28509
|
+
}
|
|
28510
|
+
async function storeArtifactVersion(kv, version2, authority) {
|
|
28511
|
+
try {
|
|
28512
|
+
return await publishArtifactVersion(kvArtifactStore(kv), version2);
|
|
28513
|
+
} catch (error) {
|
|
28514
|
+
throw scopeDeniedFromArtifactError(error, "KV upload", authority) ?? artifactSpaceNotReady(error);
|
|
28515
|
+
}
|
|
28516
|
+
}
|
|
28517
|
+
function createEncryptedSessionHistory() {
|
|
28518
|
+
const records = /* @__PURE__ */ new Map();
|
|
28519
|
+
let operation = Promise.resolve();
|
|
28520
|
+
const serial = (action) => {
|
|
28521
|
+
const next = operation.then(action, action);
|
|
28522
|
+
operation = next.then(() => void 0, () => void 0);
|
|
28523
|
+
return next;
|
|
28524
|
+
};
|
|
28525
|
+
let keyPromise;
|
|
28526
|
+
const key = async () => keyPromise ??= crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
28527
|
+
const encode7 = async (record2) => {
|
|
28528
|
+
const secret = new TextEncoder().encode(JSON.stringify(record2));
|
|
28529
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
28530
|
+
const encrypted = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, await key(), secret));
|
|
28531
|
+
const value = new Uint8Array(iv.length + encrypted.length);
|
|
28532
|
+
value.set(iv);
|
|
28533
|
+
value.set(encrypted, iv.length);
|
|
28534
|
+
return value;
|
|
28535
|
+
};
|
|
28536
|
+
const decode11 = async (value) => JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await crypto.subtle.decrypt({ name: "AES-GCM", iv: value.slice(0, 12) }, await key(), value.slice(12))));
|
|
28537
|
+
return {
|
|
28538
|
+
async put(record2) {
|
|
28539
|
+
return serial(async () => {
|
|
28540
|
+
records.set(record2.shareId, await encode7(record2));
|
|
28541
|
+
});
|
|
28542
|
+
},
|
|
28543
|
+
async update(shareId, change) {
|
|
28544
|
+
return serial(async () => {
|
|
28545
|
+
const value = records.get(shareId);
|
|
28546
|
+
if (value === void 0) return void 0;
|
|
28547
|
+
const updated = await change(await decode11(value));
|
|
28548
|
+
records.set(shareId, await encode7(updated));
|
|
28549
|
+
return updated;
|
|
28550
|
+
});
|
|
28551
|
+
},
|
|
28552
|
+
async list() {
|
|
28553
|
+
return serial(() => Promise.all([...records.values()].map(decode11)));
|
|
28554
|
+
},
|
|
28555
|
+
async get(shareId) {
|
|
28556
|
+
return serial(async () => {
|
|
28557
|
+
const value = records.get(shareId);
|
|
28558
|
+
return value === void 0 ? void 0 : decode11(value);
|
|
28559
|
+
});
|
|
28560
|
+
},
|
|
28561
|
+
async delete(shareId) {
|
|
28562
|
+
return serial(async () => {
|
|
28563
|
+
records.delete(shareId);
|
|
28564
|
+
});
|
|
28565
|
+
}
|
|
28566
|
+
};
|
|
28567
|
+
}
|
|
28568
|
+
var SHARE_HISTORY_FILE = "share-history-v2.json";
|
|
28569
|
+
var SHARE_HISTORY_LEGACY_FILE = "share-history-v1.bin";
|
|
28570
|
+
var PRIVATE_HISTORY_MODE = 384;
|
|
28571
|
+
async function signShareHistoryBytes(bytes, profile) {
|
|
28572
|
+
const context = await ProfileManager.resolveContext({ profile });
|
|
28573
|
+
if (context.profile !== profile) throw new ShareHistoryRetryError(profile);
|
|
28574
|
+
const { ensureAuthenticated: ensureAuthenticated2 } = await Promise.resolve().then(() => (init_sdk(), sdk_exports));
|
|
28575
|
+
const signer = await ensureAuthenticated2(context);
|
|
28576
|
+
return signer.signSessionBytes(bytes);
|
|
28577
|
+
}
|
|
28578
|
+
function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
28579
|
+
const HISTORY_VERSION = 2;
|
|
26808
28580
|
const identityChanged = new Error("share history profile or key changed");
|
|
26809
28581
|
const saltChanged = new Error("share history salt changed");
|
|
26810
28582
|
let operation = Promise.resolve();
|
|
@@ -26880,7 +28652,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
26880
28652
|
if (salt.length < 16) throw new ShareHistoryUnreadableError();
|
|
26881
28653
|
return salt;
|
|
26882
28654
|
};
|
|
26883
|
-
const
|
|
28655
|
+
const read5 = async (profile, ready) => {
|
|
26884
28656
|
const file = await readIfPresent(await path(profile));
|
|
26885
28657
|
if (file === void 0) {
|
|
26886
28658
|
const legacy = await readIfPresent(await legacyPath(profile));
|
|
@@ -26969,7 +28741,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
26969
28741
|
false,
|
|
26970
28742
|
["encrypt", "decrypt"]
|
|
26971
28743
|
);
|
|
26972
|
-
await
|
|
28744
|
+
await read5(profile, { salt, key, legacyKey: keys.legacyKey });
|
|
26973
28745
|
return true;
|
|
26974
28746
|
} catch (error) {
|
|
26975
28747
|
if (error instanceof ShareHistoryUnreadableError) return false;
|
|
@@ -27008,7 +28780,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
27008
28780
|
return {
|
|
27009
28781
|
async put(record2) {
|
|
27010
28782
|
return locked(async (profile, ready) => {
|
|
27011
|
-
const values = await
|
|
28783
|
+
const values = await read5(profile, ready);
|
|
27012
28784
|
const index = values.findIndex((value) => value.shareId === record2.shareId);
|
|
27013
28785
|
if (index >= 0) values[index] = record2;
|
|
27014
28786
|
else values.push(record2);
|
|
@@ -27017,7 +28789,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
27017
28789
|
},
|
|
27018
28790
|
async update(shareId, change) {
|
|
27019
28791
|
return locked(async (profile, ready) => {
|
|
27020
|
-
const values = await
|
|
28792
|
+
const values = await read5(profile, ready);
|
|
27021
28793
|
const index = values.findIndex((record2) => record2.shareId === shareId);
|
|
27022
28794
|
if (index < 0) return void 0;
|
|
27023
28795
|
const updated = await change(values[index]);
|
|
@@ -27027,14 +28799,14 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
|
|
|
27027
28799
|
}, true);
|
|
27028
28800
|
},
|
|
27029
28801
|
async list() {
|
|
27030
|
-
return locked((profile, ready) =>
|
|
28802
|
+
return locked((profile, ready) => read5(profile, ready));
|
|
27031
28803
|
},
|
|
27032
28804
|
async get(shareId) {
|
|
27033
|
-
return locked(async (profile, ready) => (await
|
|
28805
|
+
return locked(async (profile, ready) => (await read5(profile, ready)).find((record2) => record2.shareId === shareId));
|
|
27034
28806
|
},
|
|
27035
28807
|
async delete(shareId) {
|
|
27036
28808
|
return locked(async (profile, ready) => {
|
|
27037
|
-
await write(profile, (await
|
|
28809
|
+
await write(profile, (await read5(profile, ready)).filter((record2) => record2.shareId !== shareId), ready);
|
|
27038
28810
|
}, true);
|
|
27039
28811
|
},
|
|
27040
28812
|
quarantineUnreadable
|
|
@@ -27057,13 +28829,19 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27057
28829
|
};
|
|
27058
28830
|
let configPromise;
|
|
27059
28831
|
const publicConfig = async () => configPromise ??= (async () => {
|
|
27060
|
-
|
|
27061
|
-
|
|
27062
|
-
|
|
27063
|
-
|
|
27064
|
-
|
|
27065
|
-
|
|
27066
|
-
|
|
28832
|
+
let response;
|
|
28833
|
+
try {
|
|
28834
|
+
response = await fetchFn(`${origin}/.well-known/tinycloud-share/config.json`, {
|
|
28835
|
+
headers: { accept: "application/json" },
|
|
28836
|
+
credentials: "omit",
|
|
28837
|
+
redirect: "error",
|
|
28838
|
+
referrerPolicy: "no-referrer",
|
|
28839
|
+
signal: AbortSignal.timeout(1e4)
|
|
28840
|
+
});
|
|
28841
|
+
} catch (error) {
|
|
28842
|
+
throw new SharePublishAuthorityError({ kind: "share-service-unavailable", origin }, { cause: error });
|
|
28843
|
+
}
|
|
28844
|
+
if (!response.ok) throw new SharePublishAuthorityError({ kind: "share-service-unavailable", origin });
|
|
27067
28845
|
const value = await response.json();
|
|
27068
28846
|
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("share public config is invalid");
|
|
27069
28847
|
const object3 = value;
|
|
@@ -27085,8 +28863,8 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27085
28863
|
return await ensureAuthenticated2(context);
|
|
27086
28864
|
} catch (error) {
|
|
27087
28865
|
const profileConfig = await ProfileManager.getProfile(profile).catch(() => void 0);
|
|
27088
|
-
const
|
|
27089
|
-
if (error instanceof InvalidRestoredSessionError ||
|
|
28866
|
+
const code5 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
|
|
28867
|
+
if (error instanceof InvalidRestoredSessionError || code5 === "AUTH_EXPIRED" || isSessionExpiredError(error)) {
|
|
27090
28868
|
throw new SharePublishAuthorityError({
|
|
27091
28869
|
kind: "owner-space-unresolved",
|
|
27092
28870
|
localKey: profileConfig?.authMethod === "local",
|
|
@@ -27213,8 +28991,8 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27213
28991
|
});
|
|
27214
28992
|
failIfSpaceNotReady(written);
|
|
27215
28993
|
if (!written.ok) {
|
|
27216
|
-
const
|
|
27217
|
-
if (
|
|
28994
|
+
const code5 = typeof written.error === "object" && written.error !== null && "code" in written.error ? written.error.code : void 0;
|
|
28995
|
+
if (code5 === "AUTH_UNAUTHORIZED" || code5 === "PERMISSION_DENIED") {
|
|
27218
28996
|
const requiredAction = requiredKvAction(written.error.meta);
|
|
27219
28997
|
throw new SharePublishAuthorityError({
|
|
27220
28998
|
kind: "scope-denied",
|
|
@@ -27235,8 +29013,8 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27235
29013
|
viewerOrigin: config.shareOrigin
|
|
27236
29014
|
});
|
|
27237
29015
|
} catch (error) {
|
|
27238
|
-
const
|
|
27239
|
-
if (
|
|
29016
|
+
const code5 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
|
|
29017
|
+
if (code5 === "AUTH_UNAUTHORIZED" || code5 === "PERMISSION_DENIED") {
|
|
27240
29018
|
throw new SharePublishAuthorityError({
|
|
27241
29019
|
kind: "scope-denied",
|
|
27242
29020
|
capability: "sharing delegation",
|
|
@@ -27313,8 +29091,8 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27313
29091
|
const stored = await node.kvForSpace(ownerSpaceId).put(resourcePath, storedBytes, { contentType: "application/vnd.tinycloud.encrypted-envelope+json" });
|
|
27314
29092
|
failIfSpaceNotReady(stored);
|
|
27315
29093
|
if (!stored.ok) {
|
|
27316
|
-
const
|
|
27317
|
-
if (
|
|
29094
|
+
const code5 = typeof stored.error === "object" && stored.error !== null && "code" in stored.error ? stored.error.code : void 0;
|
|
29095
|
+
if (code5 === "AUTH_UNAUTHORIZED" || code5 === "PERMISSION_DENIED") {
|
|
27318
29096
|
const requiredAction = requiredKvAction(stored.error.meta);
|
|
27319
29097
|
throw new SharePublishAuthorityError({
|
|
27320
29098
|
kind: "scope-denied",
|
|
@@ -27366,9 +29144,9 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27366
29144
|
// transport hop, so the CLI supplies only owner signing material.
|
|
27367
29145
|
authority: {
|
|
27368
29146
|
ownerDid: node.credentialHolderDid,
|
|
27369
|
-
createOwnerRoot: (
|
|
29147
|
+
createOwnerRoot: (request2) => node.createUnifiedOwnerRoot(request2),
|
|
27370
29148
|
sign: (bytes) => node.signSessionBytes(bytes),
|
|
27371
|
-
registerPolicy: (
|
|
29149
|
+
registerPolicy: (request2) => node.registerPolicy(request2)
|
|
27372
29150
|
}
|
|
27373
29151
|
});
|
|
27374
29152
|
if (expiryClamped) Object.defineProperty(published.metadata, "expiryClamped", { value: true, enumerable: true });
|
|
@@ -27377,9 +29155,9 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27377
29155
|
}
|
|
27378
29156
|
return published;
|
|
27379
29157
|
} };
|
|
27380
|
-
const delivery = { deliver: input.deliver ?? (async (
|
|
27381
|
-
const record2 =
|
|
27382
|
-
if (record2 === void 0 || record2.link === void 0 || record2.deliveryMaterial === void 0 ||
|
|
29158
|
+
const delivery = { deliver: input.deliver ?? (async (request2) => {
|
|
29159
|
+
const record2 = request2.record;
|
|
29160
|
+
if (record2 === void 0 || record2.link === void 0 || record2.deliveryMaterial === void 0 || request2.idempotencyKey === void 0) throw new Error("share delivery history is incomplete");
|
|
27383
29161
|
const expiry = shareDeliveryWindowExpiresAt(record2);
|
|
27384
29162
|
if (expiry <= Date.now()) throw new ShareNotifyError("share delivery authorization window has expired", "delivery-window-expired");
|
|
27385
29163
|
const authorizationExpiresAt = new Date(expiry).toISOString();
|
|
@@ -27390,19 +29168,19 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27390
29168
|
envelopeKey: record2.deliveryMaterial.envelopeKey,
|
|
27391
29169
|
shareCid: record2.deliveryMaterial.shareCid,
|
|
27392
29170
|
resourcePath: record2.resource.path,
|
|
27393
|
-
recipientEmail:
|
|
29171
|
+
recipientEmail: request2.recipient,
|
|
27394
29172
|
shareUrl: record2.link,
|
|
27395
29173
|
documentName: record2.filename ?? "share.md",
|
|
27396
29174
|
expiresAt: authorizationExpiresAt,
|
|
27397
29175
|
deliveryAudience: config.credentialsOrigin,
|
|
27398
|
-
idempotencyKey:
|
|
29176
|
+
idempotencyKey: request2.idempotencyKey
|
|
27399
29177
|
});
|
|
27400
29178
|
await deliverCredentialInvitation({
|
|
27401
29179
|
credentialsOrigin: config.credentialsOrigin,
|
|
27402
29180
|
receipt,
|
|
27403
29181
|
shareUrl: record2.link,
|
|
27404
29182
|
fetchFn,
|
|
27405
|
-
signal:
|
|
29183
|
+
signal: request2.signal
|
|
27406
29184
|
});
|
|
27407
29185
|
return "delivered";
|
|
27408
29186
|
}) };
|
|
@@ -27482,16 +29260,16 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27482
29260
|
{ status: response.status }
|
|
27483
29261
|
);
|
|
27484
29262
|
}),
|
|
27485
|
-
revokePolicyRoot: input.revokePolicyRoot ?? (async (
|
|
29263
|
+
revokePolicyRoot: input.revokePolicyRoot ?? (async (request2) => {
|
|
27486
29264
|
const node = await authenticatedNode();
|
|
27487
29265
|
const activeNode = await node.activeNodeIdentity();
|
|
27488
|
-
if (
|
|
29266
|
+
if (request2.nodeOrigin !== activeNode.origin || request2.nodeAudience !== activeNode.nodeDid || request2.ownerDid !== node.credentialHolderDid) {
|
|
27489
29267
|
throw new Error("share Policy/v3 revocation is not bound to the active owner node");
|
|
27490
29268
|
}
|
|
27491
29269
|
await revokePolicyRootV3({
|
|
27492
29270
|
nodeOrigin: activeNode.origin,
|
|
27493
|
-
rootCid:
|
|
27494
|
-
targetRole:
|
|
29271
|
+
rootCid: request2.rootCid,
|
|
29272
|
+
targetRole: request2.targetRole,
|
|
27495
29273
|
ownerDid: node.credentialHolderDid,
|
|
27496
29274
|
issuerDid: node.credentialHolderDid,
|
|
27497
29275
|
nodeAudience: activeNode.nodeDid,
|
|
@@ -27535,6 +29313,10 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27535
29313
|
list: (prefix) => mapped(() => store.list(prefix))
|
|
27536
29314
|
};
|
|
27537
29315
|
};
|
|
29316
|
+
const shortLinks = createShareShortLinks({
|
|
29317
|
+
kvForSpace: async (spaceId) => (await authenticatedNode()).kvForSpace(spaceId),
|
|
29318
|
+
fetchFn
|
|
29319
|
+
});
|
|
27538
29320
|
return {
|
|
27539
29321
|
targetAdapter,
|
|
27540
29322
|
records: input.profileName === void 0 ? createEncryptedSessionHistory() : createEncryptedProfileHistory(profileName, signShareHistoryBytes),
|
|
@@ -27542,7 +29324,8 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
27542
29324
|
revocation,
|
|
27543
29325
|
assertDomainDelivery,
|
|
27544
29326
|
nativeReader,
|
|
27545
|
-
artifactStore
|
|
29327
|
+
artifactStore,
|
|
29328
|
+
shortLinks
|
|
27546
29329
|
};
|
|
27547
29330
|
}
|
|
27548
29331
|
async function selectedProfileName() {
|
|
@@ -27898,7 +29681,7 @@ var SCRIPT_END = /<\/script/gi;
|
|
|
27898
29681
|
var STYLE_END = /<\/style/gi;
|
|
27899
29682
|
function scanMarkup(html, options) {
|
|
27900
29683
|
const checkReferences = options.references;
|
|
27901
|
-
const
|
|
29684
|
+
const length5 = html.length;
|
|
27902
29685
|
let index = 0;
|
|
27903
29686
|
let comments = 0;
|
|
27904
29687
|
const malformed = (detail) => {
|
|
@@ -27909,7 +29692,7 @@ function scanMarkup(html, options) {
|
|
|
27909
29692
|
comments += 1;
|
|
27910
29693
|
if (comments > MAX_ARTIFACT_COMMENTS) fail("limit", "artifact page has too many comments");
|
|
27911
29694
|
};
|
|
27912
|
-
while (index <
|
|
29695
|
+
while (index < length5) {
|
|
27913
29696
|
const open10 = html.indexOf("<", index);
|
|
27914
29697
|
if (open10 === -1) return;
|
|
27915
29698
|
index = open10 + 1;
|
|
@@ -27953,8 +29736,8 @@ function scanMarkup(html, options) {
|
|
|
27953
29736
|
const attributes = /* @__PURE__ */ new Map();
|
|
27954
29737
|
let attributeCount = 0;
|
|
27955
29738
|
for (; ; ) {
|
|
27956
|
-
while (index <
|
|
27957
|
-
if (index >=
|
|
29739
|
+
while (index < length5 && SKIPPED.test(html[index])) index += 1;
|
|
29740
|
+
if (index >= length5) {
|
|
27958
29741
|
if (malformed("artifact output has an unterminated tag")) return;
|
|
27959
29742
|
return;
|
|
27960
29743
|
}
|
|
@@ -27965,11 +29748,11 @@ function scanMarkup(html, options) {
|
|
|
27965
29748
|
ATTRIBUTE_NAME.lastIndex = index;
|
|
27966
29749
|
const rawName = ATTRIBUTE_NAME.exec(html)[0];
|
|
27967
29750
|
index = ATTRIBUTE_NAME.lastIndex;
|
|
27968
|
-
while (index <
|
|
29751
|
+
while (index < length5 && SPACE.test(html[index])) index += 1;
|
|
27969
29752
|
let rawValue = "";
|
|
27970
29753
|
if (html[index] === "=") {
|
|
27971
29754
|
index += 1;
|
|
27972
|
-
while (index <
|
|
29755
|
+
while (index < length5 && SPACE.test(html[index])) index += 1;
|
|
27973
29756
|
const quote = html[index];
|
|
27974
29757
|
if (quote === '"' || quote === "'") {
|
|
27975
29758
|
const close = html.indexOf(quote, index + 1);
|
|
@@ -27994,7 +29777,7 @@ function scanMarkup(html, options) {
|
|
|
27994
29777
|
checkAttribute(name, decoded);
|
|
27995
29778
|
if (isHrefAnimation(tag, name, decoded)) unsupportedOutput("artifact svg animates a resource reference");
|
|
27996
29779
|
if (!attributes.has(name)) attributes.set(name, decoded);
|
|
27997
|
-
} else if (index <
|
|
29780
|
+
} else if (index < length5 && html[index] !== ">" && !SKIPPED.test(html[index])) {
|
|
27998
29781
|
index += 1;
|
|
27999
29782
|
}
|
|
28000
29783
|
}
|
|
@@ -28017,7 +29800,7 @@ function scanMarkup(html, options) {
|
|
|
28017
29800
|
} else if (tag === "style" && checkReferences) {
|
|
28018
29801
|
STYLE_END.lastIndex = index;
|
|
28019
29802
|
const close = STYLE_END.exec(html);
|
|
28020
|
-
assertOnlyInlineCssReferences(html.slice(index, close === null ?
|
|
29803
|
+
assertOnlyInlineCssReferences(html.slice(index, close === null ? length5 : close.index));
|
|
28021
29804
|
}
|
|
28022
29805
|
}
|
|
28023
29806
|
}
|
|
@@ -28121,26 +29904,26 @@ function requiredFile(context, basePath, reference) {
|
|
|
28121
29904
|
return { file, resolved };
|
|
28122
29905
|
}
|
|
28123
29906
|
var CSS_REFERENCE_NAMES = /* @__PURE__ */ new Set(["url", "image-set", "-webkit-image-set", "src", "import"]);
|
|
28124
|
-
function isCssIdentifierCode(
|
|
28125
|
-
return
|
|
29907
|
+
function isCssIdentifierCode(code5) {
|
|
29908
|
+
return code5 >= 128 || code5 >= 48 && code5 <= 57 || code5 >= 65 && code5 <= 90 || code5 >= 97 && code5 <= 122 || code5 === 95 || code5 === 45;
|
|
28126
29909
|
}
|
|
28127
29910
|
function normalizeCssEscapes(source) {
|
|
28128
29911
|
let output = "";
|
|
28129
29912
|
let index = 0;
|
|
28130
|
-
const
|
|
28131
|
-
while (index <
|
|
29913
|
+
const length5 = source.length;
|
|
29914
|
+
while (index < length5) {
|
|
28132
29915
|
const char = source[index];
|
|
28133
29916
|
if (char === "/" && source[index + 1] === "*") {
|
|
28134
29917
|
const end = source.indexOf("*/", index + 2);
|
|
28135
|
-
const stop = end === -1 ?
|
|
29918
|
+
const stop = end === -1 ? length5 : end + 2;
|
|
28136
29919
|
output += source.slice(index, stop);
|
|
28137
29920
|
index = stop;
|
|
28138
29921
|
continue;
|
|
28139
29922
|
}
|
|
28140
29923
|
if (char === '"' || char === "'") {
|
|
28141
29924
|
let cursor = index + 1;
|
|
28142
|
-
while (cursor <
|
|
28143
|
-
const stop = Math.min(source[cursor] === char ? cursor + 1 : cursor,
|
|
29925
|
+
while (cursor < length5 && source[cursor] !== char && source[cursor] !== "\n") cursor += source[cursor] === "\\" ? 2 : 1;
|
|
29926
|
+
const stop = Math.min(source[cursor] === char ? cursor + 1 : cursor, length5);
|
|
28144
29927
|
output += source.slice(index, stop);
|
|
28145
29928
|
index = stop;
|
|
28146
29929
|
continue;
|
|
@@ -28149,7 +29932,7 @@ function normalizeCssEscapes(source) {
|
|
|
28149
29932
|
let cursor = index;
|
|
28150
29933
|
let decoded = "";
|
|
28151
29934
|
let escaped = false;
|
|
28152
|
-
while (cursor <
|
|
29935
|
+
while (cursor < length5) {
|
|
28153
29936
|
if (source[cursor] === "\\") {
|
|
28154
29937
|
const next = source[cursor + 1];
|
|
28155
29938
|
if (next === void 0) {
|
|
@@ -28193,15 +29976,15 @@ function assertOnlyInlineCssReferences(css) {
|
|
|
28193
29976
|
if (/@import/i.test(text)) fail("unsupported", "artifact css still imports a stylesheet");
|
|
28194
29977
|
if (/(?:^|[^\w-])(?:-webkit-)?image-set\s*\(/i.test(text) || /(?:^|[^\w-])src\s*\(/i.test(text)) fail("unsupported", "artifact css uses an unsupported resource function");
|
|
28195
29978
|
const opened = text.match(/url\(/gi)?.length ?? 0;
|
|
28196
|
-
let
|
|
29979
|
+
let read5 = 0;
|
|
28197
29980
|
for (const match of text.matchAll(/url\([ \t\n\r\f]*(?:"([^"]*)"|'([^']*)'|([^)"' \t\n\r\f]*))[ \t\n\r\f]*\)/gi)) {
|
|
28198
|
-
|
|
29981
|
+
read5 += 1;
|
|
28199
29982
|
const value = match[1] ?? match[2] ?? match[3] ?? "";
|
|
28200
29983
|
if (!isInlineReference(value) || value.includes("\\")) {
|
|
28201
29984
|
throw new ArtifactBundleError("unsupported", "artifact css references a resource", void 0, value);
|
|
28202
29985
|
}
|
|
28203
29986
|
}
|
|
28204
|
-
if (
|
|
29987
|
+
if (read5 !== opened) fail("unsupported", "artifact css has a url() that cannot be read");
|
|
28205
29988
|
}
|
|
28206
29989
|
async function transformCss(sourceText, basePath, context) {
|
|
28207
29990
|
if (context.cssStack.length > MAX_ARTIFACT_CSS_IMPORT_DEPTH) fail("limit", "artifact stylesheet import depth exceeded");
|
|
@@ -28487,8 +30270,8 @@ function isWithinFolder(root, candidate) {
|
|
|
28487
30270
|
}
|
|
28488
30271
|
var CHANGED = "changed while it was read";
|
|
28489
30272
|
function isRaceError(error) {
|
|
28490
|
-
const
|
|
28491
|
-
return
|
|
30273
|
+
const code5 = error?.code;
|
|
30274
|
+
return code5 === "ENOENT" || code5 === "ENOTDIR" || code5 === "ELOOP";
|
|
28492
30275
|
}
|
|
28493
30276
|
var PROC_FD = "/proc/self/fd";
|
|
28494
30277
|
async function linuxDescriptorPath(fd) {
|
|
@@ -28645,11 +30428,11 @@ async function readHtmlFolder(directory, limit) {
|
|
|
28645
30428
|
continue;
|
|
28646
30429
|
}
|
|
28647
30430
|
if (files.length >= MAX_ARTIFACT_FILES) throw limitError(`folder has more than ${MAX_ARTIFACT_FILES} files`);
|
|
28648
|
-
const
|
|
28649
|
-
if (
|
|
28650
|
-
total +=
|
|
28651
|
-
files.push({ path: path.normalize("NFC"), bytes:
|
|
28652
|
-
} else problems.push(
|
|
30431
|
+
const read5 = await readRegularFile(root, child, path, limit - total, limit);
|
|
30432
|
+
if (read5 instanceof Uint8Array) {
|
|
30433
|
+
total += read5.byteLength;
|
|
30434
|
+
files.push({ path: path.normalize("NFC"), bytes: read5 });
|
|
30435
|
+
} else problems.push(read5);
|
|
28653
30436
|
}
|
|
28654
30437
|
}
|
|
28655
30438
|
};
|
|
@@ -28762,9 +30545,9 @@ function shareHistoryRecoverError(error) {
|
|
|
28762
30545
|
if (error instanceof ShareHistoryReadError) {
|
|
28763
30546
|
return new CLIError("SHARE_HISTORY_RECOVER_FAILED", "could not read the unreadable sender history to move it aside", 1, { hint: "The original history file was not deleted. Check read permission on the history file, then retry." });
|
|
28764
30547
|
}
|
|
28765
|
-
const
|
|
28766
|
-
if (
|
|
28767
|
-
return new CLIError("SHARE_HISTORY_RECOVER_FAILED", `could not move the unreadable sender history aside (${
|
|
30548
|
+
const code5 = error instanceof Error ? error.code : void 0;
|
|
30549
|
+
if (code5 !== void 0 && SHARE_HISTORY_RECOVER_FS_ERRNO[code5] === true) {
|
|
30550
|
+
return new CLIError("SHARE_HISTORY_RECOVER_FAILED", `could not move the unreadable sender history aside (${code5})`, 1, { hint: "The original history file was not deleted. Check write permission on the profile directory, then retry." });
|
|
28768
30551
|
}
|
|
28769
30552
|
return shareCliError(error);
|
|
28770
30553
|
}
|
|
@@ -28833,6 +30616,10 @@ function shareCliError(error, operation = "publish") {
|
|
|
28833
30616
|
if (failure.kind === "registry-unavailable") {
|
|
28834
30617
|
return new CLIError("UNAVAILABLE", "the TinyCloud location registry could not be reached, so nothing was shared; try again shortly", 4);
|
|
28835
30618
|
}
|
|
30619
|
+
if (failure.kind === "share-service-unavailable") {
|
|
30620
|
+
const outcome = operation === "publish" ? "nothing was shared" : "no invitation was sent";
|
|
30621
|
+
return new CLIError("SHARE_SERVICE_UNAVAILABLE", `the Share service at ${failure.origin} could not be reached, so ${outcome}; try again shortly`, 4);
|
|
30622
|
+
}
|
|
28836
30623
|
if (failure.kind === "node-info-unavailable") {
|
|
28837
30624
|
const outcome = operation === "publish" ? "nothing was shared and no invitation was sent" : "no invitation was sent";
|
|
28838
30625
|
return new CLIError("UNAVAILABLE", `could not verify TinyCloud node 1.17.3 domain delivery support; ${outcome}. Check the node and retry`, 4);
|
|
@@ -28858,19 +30645,26 @@ function shareCliError(error, operation = "publish") {
|
|
|
28858
30645
|
return new CLIError("UPLOAD_FAILED", "share source upload failed; nothing was shared", 4);
|
|
28859
30646
|
}
|
|
28860
30647
|
}
|
|
30648
|
+
if (error instanceof ShortLinkError) {
|
|
30649
|
+
if (error.code === "not-found") return new CLIError("NOT_FOUND", "this short link has expired, was revoked, or never existed", 4);
|
|
30650
|
+
if (error.code === "rejected") return new CLIError("ORIGIN_MISMATCH", "this short link is not from the trusted Share origin", 5);
|
|
30651
|
+
if (error.code === "too-large") return new CLIError("MAX_BYTES_EXCEEDED", "the Share short-link service returned too many bytes", 7);
|
|
30652
|
+
if (error.code === "invalid-response") return new CLIError("CID_MISMATCH", "the Share short-link service returned content that does not match the link", 5);
|
|
30653
|
+
return new CLIError("UNAVAILABLE", "the Share short-link service is unavailable; try again shortly", 4);
|
|
30654
|
+
}
|
|
28861
30655
|
if (error instanceof ShareNotifyError) {
|
|
28862
30656
|
return new CLIError("INVALID_ARGUMENT", error.message, 2);
|
|
28863
30657
|
}
|
|
28864
30658
|
if (error instanceof SharePublishError) {
|
|
28865
30659
|
const exit = error.code === "authority-required" ? 3 : error.code === "max-bytes-exceeded" ? 7 : 2;
|
|
28866
|
-
const
|
|
28867
|
-
return new CLIError(
|
|
30660
|
+
const code5 = error.code === "authority-required" ? "AUTH_REQUIRED" : error.code === "max-bytes-exceeded" ? "MAX_BYTES_EXCEEDED" : "INVALID_ARGUMENT";
|
|
30661
|
+
return new CLIError(code5, error.message, exit);
|
|
28868
30662
|
}
|
|
28869
30663
|
if (error instanceof ShareReceiveError) {
|
|
28870
30664
|
const verification = /* @__PURE__ */ new Set(["cid-mismatch", "decrypt-failed", "envelope-invalid", "origin-mismatch", "signature-invalid", "capability-invalid", "content-integrity-failed"]);
|
|
28871
30665
|
const exit = error.code === "max-bytes-exceeded" ? 7 : verification.has(error.code) ? 5 : error.code === "expired" || error.code === "fetch-failed" ? 4 : error.code === "invalid-link" || error.code === "unsupported-target" ? 2 : 2;
|
|
28872
|
-
const
|
|
28873
|
-
return new CLIError(
|
|
30666
|
+
const code5 = error.code === "fetch-failed" ? "NOT_FOUND" : error.code.replaceAll("-", "_").toUpperCase();
|
|
30667
|
+
return new CLIError(code5, error.message, exit);
|
|
28874
30668
|
}
|
|
28875
30669
|
const storageFull = storageFullError(error);
|
|
28876
30670
|
if (storageFull) return storageFull;
|
|
@@ -28898,12 +30692,36 @@ function inputUrl(value, stdin) {
|
|
|
28898
30692
|
if (value === void 0 || value.length === 0) throw new CLIError("INVALID_ARGUMENT", "a share URL or - is required", 2);
|
|
28899
30693
|
return Promise.resolve(value);
|
|
28900
30694
|
}
|
|
30695
|
+
function resolveLink(link4, expectedOrigin) {
|
|
30696
|
+
return shareServices.shortLinks?.resolve(link4, expectedOrigin) ?? resolveShortLink(link4, { expectedOrigin });
|
|
30697
|
+
}
|
|
30698
|
+
var SHORT_LINK_WARNING = {
|
|
30699
|
+
"rate-limited": "the short-link service is rate limiting this client",
|
|
30700
|
+
capacity: "the short-link service is at capacity",
|
|
30701
|
+
rejected: "the short-link service refused this share",
|
|
30702
|
+
unavailable: "the short-link service could not be reached",
|
|
30703
|
+
"invalid-response": "the short-link service answered incorrectly",
|
|
30704
|
+
"not-found": "the short-link service lost the link",
|
|
30705
|
+
"too-large": "this share is too large for a short link",
|
|
30706
|
+
"token-store-failed": "the short link's delete token could not be saved"
|
|
30707
|
+
};
|
|
30708
|
+
async function linkToShow(result, longLink) {
|
|
30709
|
+
if (longLink || result.link.kind !== "policy" || shareServices.shortLinks === void 0) return { url: result.url };
|
|
30710
|
+
try {
|
|
30711
|
+
return { url: await shareServices.shortLinks.shorten(result) };
|
|
30712
|
+
} catch (error) {
|
|
30713
|
+
const code5 = error instanceof ShortLinkError ? error.code : "unavailable";
|
|
30714
|
+
process.stderr.write(`Warning: no short link (${SHORT_LINK_WARNING[code5]}); printing the long link instead. It works, but it is long and some mail clients may break it.
|
|
30715
|
+
`);
|
|
30716
|
+
return { url: result.url, shortLinkError: code5 };
|
|
30717
|
+
}
|
|
30718
|
+
}
|
|
28901
30719
|
async function inspectShareInputOnce(value, stdin, expectedOrigin, dependencies = {}) {
|
|
28902
30720
|
const link4 = stdin || value === "-" ? await (dependencies.read ?? readBoundedUrlStdin)() : await inputUrl(value, false);
|
|
28903
30721
|
try {
|
|
28904
30722
|
parseNativeShareUrl(link4);
|
|
28905
30723
|
} catch {
|
|
28906
|
-
return (dependencies.inspect ?? inspectShare)(link4, { expectedOrigin });
|
|
30724
|
+
return (dependencies.inspect ?? inspectShare)(await resolveLink(link4, expectedOrigin), { expectedOrigin });
|
|
28907
30725
|
}
|
|
28908
30726
|
throw new CLIError("UNSUPPORTED_LINK", "native bearer links are opaque; receive the link to verify access", 2);
|
|
28909
30727
|
}
|
|
@@ -28977,7 +30795,7 @@ function assertAggregateInputLimit(inputs, maxBytes) {
|
|
|
28977
30795
|
}
|
|
28978
30796
|
function registerShareCommand(program2) {
|
|
28979
30797
|
const share = program2.command("share").description("Publish and consume TinyCloud Share links");
|
|
28980
|
-
share.command("publish <files...>").description("Publish one or more bounded files as a Share, or a folder with an index.html as one self-contained page (anyone links only)").option("--name <filename>", "Filename for stdin input, or the published .html name of a folder").option("--to <target>", "Share target", "anyone").option("--notify", "Email an exact-email recipient, or a domain mailbox on node 1.17.3+").option("--notify-to <address>", "Mailbox to invite for --to domain:<name> --notify (node 1.17.3+)").option("--expires <duration>", "Share lifetime").option("--max-bytes <bytes>", "Bound input bytes").option("--media-type <type>", "Media type for a single input").option("--action <actions...>", "Addressed permission: read, list, or edit").option("--prefix", "Publish multiple inputs beneath one addressed prefix").option("--binary", "Allow non-UTF-8 bearer content").option("--artifact <id>", 'Publish as the next write-once version of an artifact ("new" starts one); the share is pinned to that version').addOption(new Option("--ongoing").hideHelp()).option("--note <text>", "Note stored with the artifact version").option("--json", "Print versioned redacted JSON").option("--viewer-origin <origin>", "Canonical HTTPS viewer origin", SHARE_ORIGIN).action(async (files, options, command) => {
|
|
30798
|
+
share.command("publish <files...>").description("Publish one or more bounded files as a Share, or a folder with an index.html as one self-contained page (anyone links only)").option("--name <filename>", "Filename for stdin input, or the published .html name of a folder").option("--to <target>", "Share target", "anyone").option("--notify", "Email an exact-email recipient, or a domain mailbox on node 1.17.3+").option("--notify-to <address>", "Mailbox to invite for --to domain:<name> --notify (node 1.17.3+)").option("--expires <duration>", "Share lifetime").option("--max-bytes <bytes>", "Bound input bytes").option("--media-type <type>", "Media type for a single input").option("--action <actions...>", "Addressed permission: read, list, or edit").option("--prefix", "Publish multiple inputs beneath one addressed prefix").option("--binary", "Allow non-UTF-8 bearer content").option("--artifact <id>", 'Publish as the next write-once version of an artifact ("new" starts one); the share is pinned to that version').addOption(new Option("--ongoing").hideHelp()).option("--note <text>", "Note stored with the artifact version").option("--json", "Print versioned redacted JSON").option("--long-link", "Print the long self-contained link instead of a short link (addressed shares)").option("--viewer-origin <origin>", "Canonical HTTPS viewer origin", SHARE_ORIGIN).action(async (files, options, command) => {
|
|
28981
30799
|
try {
|
|
28982
30800
|
const json = jsonOutput(options, command);
|
|
28983
30801
|
if (options.ongoing === true) throw new CLIError("UNSUPPORTED_TARGET", ONGOING_UNAVAILABLE, 2);
|
|
@@ -29038,7 +30856,7 @@ function registerShareCommand(program2) {
|
|
|
29038
30856
|
notify: options.notify === true,
|
|
29039
30857
|
// The artifact request rides on the adapter call rather than through `publishTargetShare`, whose code is part of
|
|
29040
30858
|
// the browser bundles (the web-sdk size ceiling counts every byte it carries).
|
|
29041
|
-
targetAdapter: artifact === void 0 || shareServices.targetAdapter === void 0 ? shareServices.targetAdapter : { publish: (
|
|
30859
|
+
targetAdapter: artifact === void 0 || shareServices.targetAdapter === void 0 ? shareServices.targetAdapter : { publish: (request2) => shareServices.targetAdapter.publish({ ...request2, artifact }) }
|
|
29042
30860
|
});
|
|
29043
30861
|
if ("state" in result) {
|
|
29044
30862
|
if (json) {
|
|
@@ -29058,11 +30876,12 @@ function registerShareCommand(program2) {
|
|
|
29058
30876
|
}
|
|
29059
30877
|
if (result.metadata.expiryClamped === true) process.stderr.write(`Share expiry clamped to session expiry (${result.metadata.expiresAt}).
|
|
29060
30878
|
`);
|
|
29061
|
-
|
|
30879
|
+
const shown = await linkToShow(result, options.longLink === true);
|
|
30880
|
+
if (json) writeJson2({ ...redactPublishedShare(result), history: history2, expiryClamped: result.metadata.expiryClamped === true, ...artifact === void 0 || result.metadata.artifact === void 0 ? {} : { artifactId: result.metadata.artifact.id, version: result.metadata.artifact.version, mode: result.metadata.artifact.mode }, ...notification === void 0 ? {} : { notification }, ...shown.shortLinkError === void 0 ? {} : { shortLinkError: shown.shortLinkError } });
|
|
29062
30881
|
else {
|
|
29063
30882
|
if (result.metadata.artifact !== void 0) process.stderr.write(`Artifact ${result.metadata.artifact.id} v${result.metadata.artifact.version} (${result.metadata.artifact.mode})
|
|
29064
30883
|
`);
|
|
29065
|
-
publishHuman(
|
|
30884
|
+
publishHuman(shown.url);
|
|
29066
30885
|
}
|
|
29067
30886
|
} catch (error) {
|
|
29068
30887
|
return handleError(shareCliError(error));
|
|
@@ -29138,7 +30957,7 @@ function registerShareCommand(program2) {
|
|
|
29138
30957
|
else receiveHuman(output2);
|
|
29139
30958
|
return;
|
|
29140
30959
|
}
|
|
29141
|
-
const result = await receiveShare(link4, {
|
|
30960
|
+
const result = await receiveShare(await resolveLink(link4, options.viewerOrigin), {
|
|
29142
30961
|
expectedOrigin: options.viewerOrigin,
|
|
29143
30962
|
...maxBytes === void 0 ? {} : { maxContentBlobBytes: maxBytes }
|
|
29144
30963
|
});
|
|
@@ -29177,7 +30996,9 @@ function registerShareCommand(program2) {
|
|
|
29177
30996
|
const json = jsonOutput(options, command);
|
|
29178
30997
|
if (options.revealLink && json) throw new CLIError("INVALID_ARGUMENT", "--reveal-link cannot be combined with --json", 2);
|
|
29179
30998
|
if (shareServices.records === void 0) throw new CLIError("AUTH_REQUIRED", "sender history storage is not configured", 3);
|
|
29180
|
-
const
|
|
30999
|
+
const record2 = options.revealLink === true ? await shareServices.records.get(id) : void 0;
|
|
31000
|
+
const link4 = record2 === void 0 ? void 0 : await shareServices.shortLinks?.linkFor(record2);
|
|
31001
|
+
const result = await showShare({ storage: shareServices.records, shareId: id, revealLink: options.revealLink === true, ...link4 === void 0 ? {} : { link: link4 } });
|
|
29181
31002
|
if (json) writeJson2({ protocol: "tinycloud-share", version: 1, share: result });
|
|
29182
31003
|
else writeJson2(result);
|
|
29183
31004
|
} catch (error) {
|
|
@@ -29221,7 +31042,9 @@ function registerShareCommand(program2) {
|
|
|
29221
31042
|
if (result.state === "unsupported") {
|
|
29222
31043
|
throw new CLIError("UNSUPPORTED_TARGET", result.reason, 2);
|
|
29223
31044
|
}
|
|
29224
|
-
|
|
31045
|
+
const shortLink = await shareServices.shortLinks?.discard(record2) ?? "none";
|
|
31046
|
+
if (shortLink === "failed") process.stderr.write("Warning: the share is revoked, but its short link could not be removed; it stops resolving when the share expires.\n");
|
|
31047
|
+
if (json) writeJson2({ protocol: "tinycloud-share", version: 1, result, ...shortLink === "none" ? {} : { shortLink } });
|
|
29225
31048
|
else process.stdout.write(`${result.state}
|
|
29226
31049
|
`);
|
|
29227
31050
|
} catch (error) {
|
|
@@ -29309,7 +31132,8 @@ configureShareCommandServices({
|
|
|
29309
31132
|
assertDomainDelivery: shareAuthority.assertDomainDelivery,
|
|
29310
31133
|
revocation: shareAuthority.revocation,
|
|
29311
31134
|
nativeReader: shareAuthority.nativeReader,
|
|
29312
|
-
artifactStore: shareAuthority.artifactStore
|
|
31135
|
+
artifactStore: shareAuthority.artifactStore,
|
|
31136
|
+
shortLinks: shareAuthority.shortLinks
|
|
29313
31137
|
});
|
|
29314
31138
|
var argv = process.argv.slice(2);
|
|
29315
31139
|
var globalLongOptionsWithValues = { "--profile": true, "--host": true };
|
|
@@ -29355,8 +31179,8 @@ ${theme.muted("Repo:")} ${theme.accent("https://github.com/tinycloudlabs/web-sdk
|
|
|
29355
31179
|
});
|
|
29356
31180
|
var commandToken = firstCommandToken(argv);
|
|
29357
31181
|
if (argv[0] === "courier") {
|
|
29358
|
-
const
|
|
29359
|
-
if (
|
|
31182
|
+
const code5 = await (await loadCourierEntry()).runCourier(argv.slice(1));
|
|
31183
|
+
if (code5 !== 0) process.exit(code5);
|
|
29360
31184
|
} else if (commandToken === "courier") {
|
|
29361
31185
|
process.stderr.write(`${TC_OPTIONS_BEFORE_COURIER}
|
|
29362
31186
|
`);
|