@tinycloud/sdk-core 3.3.0-beta.18 → 3.3.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +346 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +200 -3
- package/dist/index.d.ts +200 -3
- package/dist/index.js +346 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -86,6 +86,10 @@ __export(index_exports, {
|
|
|
86
86
|
DEFAULT_LOCAL_NODE_URL: () => DEFAULT_LOCAL_NODE_URL,
|
|
87
87
|
DEFAULT_MANIFEST_SPACE: () => DEFAULT_MANIFEST_SPACE,
|
|
88
88
|
DEFAULT_MANIFEST_VERSION: () => DEFAULT_MANIFEST_VERSION,
|
|
89
|
+
DEFAULT_NEW_USER_HOST: () => DEFAULT_NEW_USER_HOST,
|
|
90
|
+
DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS: () => DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS,
|
|
91
|
+
DEFAULT_REGISTRY_OWNER_CHAIN_ID: () => DEFAULT_REGISTRY_OWNER_CHAIN_ID,
|
|
92
|
+
DEFAULT_REGISTRY_SEQUENCE_STORAGE_KEY: () => DEFAULT_REGISTRY_SEQUENCE_STORAGE_KEY,
|
|
89
93
|
DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
90
94
|
DEFAULT_TINYCLOUD_FALLBACK_HOST: () => DEFAULT_TINYCLOUD_FALLBACK_HOST,
|
|
91
95
|
DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL: () => DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
|
|
@@ -142,6 +146,8 @@ __export(index_exports, {
|
|
|
142
146
|
NATIVE_PROJECTION_V1_DOMAIN: () => NATIVE_PROJECTION_V1_DOMAIN,
|
|
143
147
|
NETWORK_NAME_PATTERN: () => import_sdk_services9.NETWORK_NAME_PATTERN,
|
|
144
148
|
NetworkIdError: () => import_sdk_services9.NetworkIdError,
|
|
149
|
+
NodeNotFoundError: () => NodeNotFoundError,
|
|
150
|
+
NodeRegistryEntryExistsError: () => NodeRegistryEntryExistsError,
|
|
145
151
|
OPENKEY_ACTION_ID_SEPARATOR: () => OPENKEY_ACTION_ID_SEPARATOR,
|
|
146
152
|
OWNER_NODE_BINDING_TIMEOUT_MS: () => OWNER_NODE_BINDING_TIMEOUT_MS,
|
|
147
153
|
OpenKeyManageKeyError: () => OpenKeyManageKeyError,
|
|
@@ -181,6 +187,7 @@ __export(index_exports, {
|
|
|
181
187
|
ROOT_STATUS_RENEWAL_V1_DOMAIN: () => ROOT_STATUS_RENEWAL_V1_DOMAIN,
|
|
182
188
|
ROOT_STATUS_V1_DOMAIN: () => ROOT_STATUS_V1_DOMAIN,
|
|
183
189
|
RegistryLookupInputError: () => RegistryLookupInputError,
|
|
190
|
+
RegistryUnavailableError: () => RegistryUnavailableError,
|
|
184
191
|
SECRETS_SPACE: () => SECRETS_SPACE,
|
|
185
192
|
SECRET_NAME_RE: () => import_sdk_services9.SECRET_NAME_RE,
|
|
186
193
|
SECRET_RECORDS_SCHEMA: () => import_bootstrap4.SECRET_RECORDS_SCHEMA,
|
|
@@ -250,6 +257,7 @@ __export(index_exports, {
|
|
|
250
257
|
admitPolicyCredentialV4: () => admitPolicyCredentialV4,
|
|
251
258
|
appSecretScope: () => import_sdk_services9.appSecretScope,
|
|
252
259
|
applyPrefix: () => applyPrefix,
|
|
260
|
+
assertSpaceCreationAllowed: () => assertSpaceCreationAllowed,
|
|
253
261
|
authorizationVerdictOf: () => import_sdk_services9.authorizationVerdictOf,
|
|
254
262
|
bootstrapEncryptionNetworkId: () => import_bootstrap4.bootstrapEncryptionNetworkId,
|
|
255
263
|
bootstrapSpaceId: () => import_bootstrap4.bootstrapSpaceId,
|
|
@@ -298,7 +306,9 @@ __export(index_exports, {
|
|
|
298
306
|
createEmailDomainCredentialRequirement: () => createEmailDomainCredentialRequirement,
|
|
299
307
|
createHolderBinding: () => createHolderBinding,
|
|
300
308
|
createInMemoryLocalNodeIdentityStore: () => createInMemoryLocalNodeIdentityStore,
|
|
309
|
+
createInMemoryRegistrySequenceStore: () => createInMemoryRegistrySequenceStore,
|
|
301
310
|
createLocalStorageLocalNodeIdentityStore: () => createLocalStorageLocalNodeIdentityStore,
|
|
311
|
+
createLocalStorageRegistrySequenceStore: () => createLocalStorageRegistrySequenceStore,
|
|
302
312
|
createOpenKeyCallbackSigningStrategy: () => createOpenKeyCallbackSigningStrategy,
|
|
303
313
|
createOpenKeyManageKeySigningStrategy: () => createOpenKeyManageKeySigningStrategy,
|
|
304
314
|
createPolicyEnforcementDelegation: () => createPolicyEnforcementDelegation,
|
|
@@ -382,6 +392,7 @@ __export(index_exports, {
|
|
|
382
392
|
jcsCanonicalize: () => jcsCanonicalize,
|
|
383
393
|
loadManifest: () => loadManifest,
|
|
384
394
|
locationPayloadForRecord: () => locationPayloadForRecord,
|
|
395
|
+
lookupOwnerRegistryVerdict: () => lookupOwnerRegistryVerdict,
|
|
385
396
|
mailboxBelongsToDomain: () => import_share_envelope.mailboxBelongsToDomain,
|
|
386
397
|
makePkhSpaceId: () => makePkhSpaceId,
|
|
387
398
|
makePublicSpaceId: () => makePublicSpaceId,
|
|
@@ -430,11 +441,14 @@ __export(index_exports, {
|
|
|
430
441
|
publishLocationRecord: () => publishLocationRecord,
|
|
431
442
|
recapCaveatsEqual: () => recapCaveatsEqual,
|
|
432
443
|
registerPolicyV3: () => registerPolicyV3,
|
|
444
|
+
registryOwnerSubjectV1: () => registryOwnerSubjectV1,
|
|
433
445
|
renewPolicyRootStatusV3: () => renewPolicyRootStatusV3,
|
|
434
446
|
requestTinyCloudManageKeyScope: () => requestTinyCloudManageKeyScope,
|
|
435
447
|
resolveCloudLocation: () => resolveCloudLocation,
|
|
448
|
+
resolveFailClosedTinyCloudHosts: () => resolveFailClosedTinyCloudHosts,
|
|
436
449
|
resolveManifest: () => resolveManifest,
|
|
437
450
|
resolveManifestKnowledgeRoot: () => resolveManifestKnowledgeRoot,
|
|
451
|
+
resolveOwnerHosts: () => resolveOwnerHosts,
|
|
438
452
|
resolveSecretListPrefix: () => import_sdk_services9.resolveSecretListPrefix,
|
|
439
453
|
resolveSecretPath: () => import_sdk_services9.resolveSecretPath,
|
|
440
454
|
resolveTinyCloudHosts: () => resolveTinyCloudHosts,
|
|
@@ -18710,11 +18724,16 @@ async function resolveTinyCloudHosts(subject, options2 = {}) {
|
|
|
18710
18724
|
fetch: fetchFn,
|
|
18711
18725
|
verifyRecords: options2.verifyRecords
|
|
18712
18726
|
});
|
|
18713
|
-
|
|
18714
|
-
|
|
18715
|
-
|
|
18716
|
-
|
|
18727
|
+
const hosts = location.multiaddrs.map((addr) => multiaddrToHttpUrl(addr));
|
|
18728
|
+
if (location.source === "fallback" && !fallbackDeprecationWarned) {
|
|
18729
|
+
fallbackDeprecationWarned = true;
|
|
18730
|
+
console.warn(
|
|
18731
|
+
`[tinycloud:location] Deprecated: no registry host for this account, using fallback ${hosts[0]}. The silent fallback will be removed in a future major; opt in to registryPolicy "fail-closed" now.`
|
|
18732
|
+
);
|
|
18733
|
+
}
|
|
18734
|
+
return { hosts, location };
|
|
18717
18735
|
}
|
|
18736
|
+
var fallbackDeprecationWarned = false;
|
|
18718
18737
|
function memoizeFetch(fetchFn) {
|
|
18719
18738
|
const cache2 = /* @__PURE__ */ new Map();
|
|
18720
18739
|
return (async (input, init) => {
|
|
@@ -18927,11 +18946,18 @@ function publishedHttpOrigins(record2) {
|
|
|
18927
18946
|
return origins;
|
|
18928
18947
|
}
|
|
18929
18948
|
async function boundedResponseText(response, label, maxBytes) {
|
|
18949
|
+
const bytes2 = await boundedResponseBytes(response, maxBytes);
|
|
18950
|
+
if (bytes2 === null) {
|
|
18951
|
+
throw new LocationRecordValidationError(`${label} response is too large`);
|
|
18952
|
+
}
|
|
18953
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes2);
|
|
18954
|
+
}
|
|
18955
|
+
async function boundedResponseBytes(response, maxBytes) {
|
|
18930
18956
|
const declaredLength = response.headers.get("content-length");
|
|
18931
18957
|
if (declaredLength !== null && (!/^\d+$/.test(declaredLength) || Number(declaredLength) > maxBytes)) {
|
|
18932
|
-
|
|
18958
|
+
return null;
|
|
18933
18959
|
}
|
|
18934
|
-
if (response.body === null) return
|
|
18960
|
+
if (response.body === null) return new Uint8Array();
|
|
18935
18961
|
const reader = response.body.getReader();
|
|
18936
18962
|
const chunks = [];
|
|
18937
18963
|
let total = 0;
|
|
@@ -18943,7 +18969,7 @@ async function boundedResponseText(response, label, maxBytes) {
|
|
|
18943
18969
|
total += value.byteLength;
|
|
18944
18970
|
if (total > maxBytes) {
|
|
18945
18971
|
await reader.cancel().catch(() => void 0);
|
|
18946
|
-
|
|
18972
|
+
return null;
|
|
18947
18973
|
}
|
|
18948
18974
|
chunks.push(value);
|
|
18949
18975
|
}
|
|
@@ -18956,7 +18982,7 @@ async function boundedResponseText(response, label, maxBytes) {
|
|
|
18956
18982
|
bytes2.set(chunk, offset);
|
|
18957
18983
|
offset += chunk.byteLength;
|
|
18958
18984
|
}
|
|
18959
|
-
return
|
|
18985
|
+
return bytes2;
|
|
18960
18986
|
}
|
|
18961
18987
|
function boundedSignal(parent, timeoutMs) {
|
|
18962
18988
|
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
@@ -19635,4 +19661,316 @@ function multiaddrOrigin(address) {
|
|
|
19635
19661
|
return null;
|
|
19636
19662
|
}
|
|
19637
19663
|
}
|
|
19664
|
+
|
|
19665
|
+
// src/registry-policy.ts
|
|
19666
|
+
var DEFAULT_REGISTRY_OWNER_CHAIN_ID = 1;
|
|
19667
|
+
var DEFAULT_NEW_USER_HOST = DEFAULT_TINYCLOUD_FALLBACK_HOST;
|
|
19668
|
+
var DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS = 3e3;
|
|
19669
|
+
var DEFAULT_REGISTRY_SEQUENCE_STORAGE_KEY = "tinycloud.registrySequences.v1";
|
|
19670
|
+
var MAX_SUBJECT_LENGTH = 74;
|
|
19671
|
+
function registryOwnerSubjectV1(address, registryChainId = DEFAULT_REGISTRY_OWNER_CHAIN_ID) {
|
|
19672
|
+
return pkhDid(address, registryChainId);
|
|
19673
|
+
}
|
|
19674
|
+
function createInMemoryRegistrySequenceStore() {
|
|
19675
|
+
const sequences = /* @__PURE__ */ new Map();
|
|
19676
|
+
return {
|
|
19677
|
+
get: (subject) => sequences.get(subject),
|
|
19678
|
+
set: (subject, sequence) => {
|
|
19679
|
+
if ((sequences.get(subject) ?? -1) < sequence) sequences.set(subject, sequence);
|
|
19680
|
+
}
|
|
19681
|
+
};
|
|
19682
|
+
}
|
|
19683
|
+
function createLocalStorageRegistrySequenceStore(storage, storageKey = DEFAULT_REGISTRY_SEQUENCE_STORAGE_KEY) {
|
|
19684
|
+
const backing = storage ?? defaultWebStorage();
|
|
19685
|
+
const memory = createInMemoryRegistrySequenceStore();
|
|
19686
|
+
if (!backing) {
|
|
19687
|
+
return memory;
|
|
19688
|
+
}
|
|
19689
|
+
const read2 = () => {
|
|
19690
|
+
const sequences = /* @__PURE__ */ new Map();
|
|
19691
|
+
const raw = backing.getItem(storageKey);
|
|
19692
|
+
if (raw === null) return sequences;
|
|
19693
|
+
let parsed;
|
|
19694
|
+
try {
|
|
19695
|
+
parsed = JSON.parse(raw);
|
|
19696
|
+
} catch {
|
|
19697
|
+
parsed = void 0;
|
|
19698
|
+
}
|
|
19699
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
19700
|
+
for (const [subject, sequence] of Object.entries(parsed)) {
|
|
19701
|
+
if (!isSequence(sequence)) break;
|
|
19702
|
+
sequences.set(subject, sequence);
|
|
19703
|
+
}
|
|
19704
|
+
if (sequences.size === Object.keys(parsed).length) return sequences;
|
|
19705
|
+
}
|
|
19706
|
+
throw new Error(`Corrupt registry sequence store "${storageKey}"`);
|
|
19707
|
+
};
|
|
19708
|
+
return {
|
|
19709
|
+
get: async (subject) => {
|
|
19710
|
+
const sequence = Math.max(read2().get(subject) ?? -1, await memory.get(subject) ?? -1);
|
|
19711
|
+
return sequence < 0 ? void 0 : sequence;
|
|
19712
|
+
},
|
|
19713
|
+
set: async (subject, sequence) => {
|
|
19714
|
+
await memory.set(subject, sequence);
|
|
19715
|
+
const sequences = read2();
|
|
19716
|
+
if ((sequences.get(subject) ?? -1) >= sequence) return;
|
|
19717
|
+
sequences.set(subject, sequence);
|
|
19718
|
+
backing.setItem(storageKey, JSON.stringify(Object.fromEntries(sequences)));
|
|
19719
|
+
}
|
|
19720
|
+
};
|
|
19721
|
+
}
|
|
19722
|
+
function isSequence(value) {
|
|
19723
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
19724
|
+
}
|
|
19725
|
+
async function resolveOwnerHosts(subject, options2 = {}) {
|
|
19726
|
+
if (typeof subject !== "string" || // Bounds the work below; covers any did:pkh with a safe-integer chain ID.
|
|
19727
|
+
subject.length > MAX_SUBJECT_LENGTH || !isCanonicalSubject(subject)) {
|
|
19728
|
+
throw new RegistryLookupInputError(
|
|
19729
|
+
"invalid-subject",
|
|
19730
|
+
"subject must be did:pkh:eip155:<chainId>:<EIP-55 address> or an Ed25519 did:key"
|
|
19731
|
+
);
|
|
19732
|
+
}
|
|
19733
|
+
const store = options2.sequenceStore;
|
|
19734
|
+
const remembered = store === void 0 ? void 0 : await store.get(subject);
|
|
19735
|
+
const registryUrl = options2.registryUrl ?? DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL;
|
|
19736
|
+
const url = `${registryUrl.replace(/\/$/, "")}/v1/locations/${encodeURIComponent(subject)}`;
|
|
19737
|
+
const observed = await observeRegistry(
|
|
19738
|
+
url,
|
|
19739
|
+
options2.fetch ?? globalThis.fetch,
|
|
19740
|
+
options2.timeoutMs ?? DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS
|
|
19741
|
+
);
|
|
19742
|
+
if (observed.kind === "oversize" || observed.kind === "invalid-utf8") {
|
|
19743
|
+
const oversize = observed.kind === "oversize";
|
|
19744
|
+
return {
|
|
19745
|
+
status: "unavailable",
|
|
19746
|
+
subject,
|
|
19747
|
+
source: "offchain",
|
|
19748
|
+
reason: oversize ? "oversize-response" : "malformed-response",
|
|
19749
|
+
message: oversize ? "location registry response is too large" : "location registry response is not UTF-8",
|
|
19750
|
+
hosts: []
|
|
19751
|
+
};
|
|
19752
|
+
}
|
|
19753
|
+
const verdict = await classifyRegistryLookup(subject, observed, {
|
|
19754
|
+
rememberedSequence: remembered ?? null
|
|
19755
|
+
});
|
|
19756
|
+
if (store !== void 0 && verdict.status === "registered" && (remembered === void 0 || verdict.sequence > remembered)) {
|
|
19757
|
+
try {
|
|
19758
|
+
await store.set(subject, verdict.sequence);
|
|
19759
|
+
} catch (error) {
|
|
19760
|
+
if (!sequenceWriteWarned) {
|
|
19761
|
+
sequenceWriteWarned = true;
|
|
19762
|
+
console.warn("[tinycloud:registry] could not remember the registry sequence:", error);
|
|
19763
|
+
}
|
|
19764
|
+
}
|
|
19765
|
+
}
|
|
19766
|
+
return verdict;
|
|
19767
|
+
}
|
|
19768
|
+
var sequenceWriteWarned = false;
|
|
19769
|
+
async function observeRegistry(url, fetchFn, timeoutMs) {
|
|
19770
|
+
const controller = new AbortController();
|
|
19771
|
+
let cancelTimer = () => void 0;
|
|
19772
|
+
const timedOut = new Promise((resolve) => {
|
|
19773
|
+
const timer = setTimeout(() => {
|
|
19774
|
+
controller.abort();
|
|
19775
|
+
resolve({ kind: "timeout" });
|
|
19776
|
+
}, timeoutMs);
|
|
19777
|
+
cancelTimer = () => clearTimeout(timer);
|
|
19778
|
+
});
|
|
19779
|
+
try {
|
|
19780
|
+
return await Promise.race([readRegistry(url, fetchFn, controller.signal), timedOut]);
|
|
19781
|
+
} finally {
|
|
19782
|
+
cancelTimer();
|
|
19783
|
+
}
|
|
19784
|
+
}
|
|
19785
|
+
async function readRegistry(url, fetchFn, signal) {
|
|
19786
|
+
let response;
|
|
19787
|
+
try {
|
|
19788
|
+
response = await fetchFn(url, {
|
|
19789
|
+
redirect: "error",
|
|
19790
|
+
headers: { accept: "application/json" },
|
|
19791
|
+
signal
|
|
19792
|
+
});
|
|
19793
|
+
} catch {
|
|
19794
|
+
return { kind: "network-error" };
|
|
19795
|
+
}
|
|
19796
|
+
if (response.status !== 200 && response.status !== 404) {
|
|
19797
|
+
await response.body?.cancel().catch(() => void 0);
|
|
19798
|
+
return { kind: "http", status: response.status, body: "" };
|
|
19799
|
+
}
|
|
19800
|
+
let bytes2;
|
|
19801
|
+
try {
|
|
19802
|
+
bytes2 = await boundedResponseBytes(response, REGISTRY_LOOKUP_MAX_BODY_BYTES);
|
|
19803
|
+
} catch {
|
|
19804
|
+
return { kind: "network-error" };
|
|
19805
|
+
}
|
|
19806
|
+
if (bytes2 === null) return { kind: "oversize" };
|
|
19807
|
+
try {
|
|
19808
|
+
return {
|
|
19809
|
+
kind: "http",
|
|
19810
|
+
status: response.status,
|
|
19811
|
+
body: new TextDecoder("utf-8", { fatal: true }).decode(bytes2)
|
|
19812
|
+
};
|
|
19813
|
+
} catch {
|
|
19814
|
+
return { kind: "invalid-utf8" };
|
|
19815
|
+
}
|
|
19816
|
+
}
|
|
19817
|
+
var NodeNotFoundError = class extends Error {
|
|
19818
|
+
constructor(subject, verdict) {
|
|
19819
|
+
super(
|
|
19820
|
+
verdict.status === "registered" ? `No usable TinyCloud host is registered for ${subject}` : `${subject} is not registered and newUserHost is null`
|
|
19821
|
+
);
|
|
19822
|
+
this.subject = subject;
|
|
19823
|
+
this.verdict = verdict;
|
|
19824
|
+
this.code = "node_not_found";
|
|
19825
|
+
this.name = "NodeNotFoundError";
|
|
19826
|
+
}
|
|
19827
|
+
};
|
|
19828
|
+
var RegistryUnavailableError = class extends Error {
|
|
19829
|
+
constructor(subject, verdict, detail = {}) {
|
|
19830
|
+
super(`Location registry unavailable for ${subject}: ${detail.message ?? verdict?.message}`);
|
|
19831
|
+
this.subject = subject;
|
|
19832
|
+
this.verdict = verdict;
|
|
19833
|
+
this.code = "registry_unavailable";
|
|
19834
|
+
this.name = "RegistryUnavailableError";
|
|
19835
|
+
if (detail.cause !== void 0) this.cause = detail.cause;
|
|
19836
|
+
}
|
|
19837
|
+
};
|
|
19838
|
+
var NodeRegistryEntryExistsError = class extends Error {
|
|
19839
|
+
constructor(subject, host, verdict) {
|
|
19840
|
+
super(`The registry entry for ${subject} does not list ${host}`);
|
|
19841
|
+
this.subject = subject;
|
|
19842
|
+
this.host = host;
|
|
19843
|
+
this.verdict = verdict;
|
|
19844
|
+
this.code = "node_registry_entry_exists";
|
|
19845
|
+
this.name = "NodeRegistryEntryExistsError";
|
|
19846
|
+
this.registeredHosts = secureRecordHosts(verdict);
|
|
19847
|
+
}
|
|
19848
|
+
};
|
|
19849
|
+
async function lookupOwnerRegistryVerdict(subject, options2 = {}) {
|
|
19850
|
+
if (options2.registryUrl === null) {
|
|
19851
|
+
throw new RegistryUnavailableError(subject, void 0, {
|
|
19852
|
+
message: "no location registry is configured"
|
|
19853
|
+
});
|
|
19854
|
+
}
|
|
19855
|
+
try {
|
|
19856
|
+
return await resolveOwnerHosts(subject, {
|
|
19857
|
+
registryUrl: options2.registryUrl,
|
|
19858
|
+
sequenceStore: options2.sequenceStore,
|
|
19859
|
+
fetch: options2.fetch,
|
|
19860
|
+
timeoutMs: options2.timeoutMs
|
|
19861
|
+
});
|
|
19862
|
+
} catch (error) {
|
|
19863
|
+
throw new RegistryUnavailableError(subject, void 0, {
|
|
19864
|
+
message: error instanceof Error ? error.message : String(error),
|
|
19865
|
+
cause: error
|
|
19866
|
+
});
|
|
19867
|
+
}
|
|
19868
|
+
}
|
|
19869
|
+
async function resolveFailClosedTinyCloudHosts(address, options2 = {}) {
|
|
19870
|
+
const newUserHost = options2.newUserHost === null ? null : exactHttpOrigin(options2.newUserHost ?? DEFAULT_NEW_USER_HOST, "newUserHost");
|
|
19871
|
+
const subject = registryOwnerSubjectV1(address, options2.registryChainId);
|
|
19872
|
+
const resolve = async () => {
|
|
19873
|
+
let verdict;
|
|
19874
|
+
let unavailable;
|
|
19875
|
+
try {
|
|
19876
|
+
verdict = await lookupOwnerRegistryVerdict(subject, options2);
|
|
19877
|
+
} catch (error) {
|
|
19878
|
+
if (!(error instanceof RegistryUnavailableError)) throw error;
|
|
19879
|
+
unavailable = error;
|
|
19880
|
+
}
|
|
19881
|
+
if (options2.autoDiscoverLocalNode ?? true) {
|
|
19882
|
+
const linkNames = verdict?.status === "registered" ? secureRecordHosts(verdict).flatMap((host) => LOCAL_LINK_ORIGIN.exec(host)?.[1] ?? []) : [];
|
|
19883
|
+
for (const candidate of [
|
|
19884
|
+
{ localNodeUrl: options2.localNodeUrl, localLinkName: options2.localLinkName },
|
|
19885
|
+
...linkNames.map((localLinkName) => ({ localLinkName }))
|
|
19886
|
+
]) {
|
|
19887
|
+
const local = await discoverLocalTinyCloudNode({
|
|
19888
|
+
...candidate,
|
|
19889
|
+
expectedNodeDid: options2.expectedNodeDid,
|
|
19890
|
+
identityStore: options2.localNodeIdentityStore,
|
|
19891
|
+
fetch: options2.fetch
|
|
19892
|
+
});
|
|
19893
|
+
if (local) return { hosts: [local.url], ...verdict === void 0 ? {} : { verdict } };
|
|
19894
|
+
}
|
|
19895
|
+
}
|
|
19896
|
+
if (verdict === void 0) throw unavailable;
|
|
19897
|
+
return { hosts: hostsForVerdict(verdict, newUserHost), verdict };
|
|
19898
|
+
};
|
|
19899
|
+
for (let attempt = 1; ; attempt++) {
|
|
19900
|
+
let failure;
|
|
19901
|
+
try {
|
|
19902
|
+
return await resolve();
|
|
19903
|
+
} catch (error) {
|
|
19904
|
+
if (!(error instanceof NodeNotFoundError) && !(error instanceof RegistryUnavailableError)) {
|
|
19905
|
+
throw error;
|
|
19906
|
+
}
|
|
19907
|
+
failure = error;
|
|
19908
|
+
}
|
|
19909
|
+
if (!options2.onNodeNotFound) throw failure;
|
|
19910
|
+
const decision = await options2.onNodeNotFound({ error: failure, attempt });
|
|
19911
|
+
switch (decision?.action) {
|
|
19912
|
+
case "retry":
|
|
19913
|
+
continue;
|
|
19914
|
+
case "use-host":
|
|
19915
|
+
return {
|
|
19916
|
+
hosts: [exactHttpOrigin(decision.host, "onNodeNotFound host")],
|
|
19917
|
+
...failure.verdict === void 0 ? {} : { verdict: failure.verdict }
|
|
19918
|
+
};
|
|
19919
|
+
case "abort":
|
|
19920
|
+
throw failure;
|
|
19921
|
+
default:
|
|
19922
|
+
throw new TypeError("onNodeNotFound returned an unknown action");
|
|
19923
|
+
}
|
|
19924
|
+
}
|
|
19925
|
+
}
|
|
19926
|
+
var LOCAL_LINK_ORIGIN = /^https:\/\/([a-z0-9-]+)\.local\.tinycloud\.link$/;
|
|
19927
|
+
function secureRecordHosts(verdict) {
|
|
19928
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
19929
|
+
for (const host of verdict.hosts) {
|
|
19930
|
+
for (const url of host.urls) {
|
|
19931
|
+
try {
|
|
19932
|
+
hosts.add(exactHttpOrigin(url, "registry host"));
|
|
19933
|
+
} catch {
|
|
19934
|
+
}
|
|
19935
|
+
}
|
|
19936
|
+
}
|
|
19937
|
+
return [...hosts];
|
|
19938
|
+
}
|
|
19939
|
+
function hostsForVerdict(verdict, newUserHost) {
|
|
19940
|
+
switch (verdict.status) {
|
|
19941
|
+
case "registered": {
|
|
19942
|
+
const hosts = secureRecordHosts(verdict);
|
|
19943
|
+
if (hosts.length === 0) throw new NodeNotFoundError(verdict.subject, verdict);
|
|
19944
|
+
return hosts;
|
|
19945
|
+
}
|
|
19946
|
+
case "unregistered":
|
|
19947
|
+
if (newUserHost === null) throw new NodeNotFoundError(verdict.subject, verdict);
|
|
19948
|
+
return [newUserHost];
|
|
19949
|
+
case "unavailable":
|
|
19950
|
+
throw new RegistryUnavailableError(verdict.subject, verdict);
|
|
19951
|
+
}
|
|
19952
|
+
}
|
|
19953
|
+
function assertSpaceCreationAllowed(verdict, host) {
|
|
19954
|
+
switch (verdict.status) {
|
|
19955
|
+
case "unregistered":
|
|
19956
|
+
return;
|
|
19957
|
+
case "unavailable":
|
|
19958
|
+
throw new RegistryUnavailableError(verdict.subject, verdict);
|
|
19959
|
+
case "registered": {
|
|
19960
|
+
const origin2 = httpOrigin(host);
|
|
19961
|
+
if (origin2 !== void 0 && secureRecordHosts(verdict).includes(origin2)) {
|
|
19962
|
+
return;
|
|
19963
|
+
}
|
|
19964
|
+
throw new NodeRegistryEntryExistsError(verdict.subject, host, verdict);
|
|
19965
|
+
}
|
|
19966
|
+
}
|
|
19967
|
+
}
|
|
19968
|
+
function httpOrigin(host) {
|
|
19969
|
+
try {
|
|
19970
|
+
const url = new URL(host);
|
|
19971
|
+
return url.protocol === "https:" || url.protocol === "http:" ? url.origin : void 0;
|
|
19972
|
+
} catch {
|
|
19973
|
+
return void 0;
|
|
19974
|
+
}
|
|
19975
|
+
}
|
|
19638
19976
|
//# sourceMappingURL=index.cjs.map
|