@tinycloud/sdk-core 2.8.0-beta.0 → 2.9.0-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.cjs +267 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +112 -2
- package/dist/index.d.ts +112 -2
- package/dist/index.js +259 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -69,6 +69,8 @@ __export(index_exports, {
|
|
|
69
69
|
DEFAULT_EXPIRY: () => DEFAULT_EXPIRY,
|
|
70
70
|
DEFAULT_KEY_VERSION: () => import_sdk_services7.DEFAULT_KEY_VERSION,
|
|
71
71
|
DEFAULT_KNOWLEDGE_ROOT: () => DEFAULT_KNOWLEDGE_ROOT,
|
|
72
|
+
DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY: () => DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY,
|
|
73
|
+
DEFAULT_LOCAL_NODE_URL: () => DEFAULT_LOCAL_NODE_URL,
|
|
72
74
|
DEFAULT_MANIFEST_SPACE: () => DEFAULT_MANIFEST_SPACE,
|
|
73
75
|
DEFAULT_MANIFEST_VERSION: () => DEFAULT_MANIFEST_VERSION,
|
|
74
76
|
DEFAULT_SIGNED_READ_URL_EXPIRY_MS: () => DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
@@ -103,6 +105,9 @@ __export(index_exports, {
|
|
|
103
105
|
KV: () => import_bootstrap3.KV,
|
|
104
106
|
KVService: () => import_sdk_services7.KVService,
|
|
105
107
|
LISTEN_SQL_STATEMENT_CATALOG: () => LISTEN_SQL_STATEMENT_CATALOG,
|
|
108
|
+
LOCAL_LINK_HOST_SUFFIX: () => LOCAL_LINK_HOST_SUFFIX,
|
|
109
|
+
LOCAL_LINK_PROBE_TIMEOUT_MS: () => LOCAL_LINK_PROBE_TIMEOUT_MS,
|
|
110
|
+
LOCAL_LOOPBACK_PROBE_TIMEOUT_MS: () => LOCAL_LOOPBACK_PROBE_TIMEOUT_MS,
|
|
106
111
|
LocationRecordValidationError: () => LocationRecordValidationError,
|
|
107
112
|
ManifestValidationError: () => ManifestValidationError,
|
|
108
113
|
NETWORK_NAME_PATTERN: () => import_sdk_services7.NETWORK_NAME_PATTERN,
|
|
@@ -198,6 +203,8 @@ __export(index_exports, {
|
|
|
198
203
|
createAndSignPolicyStatus: () => createAndSignPolicyStatus,
|
|
199
204
|
createAndSignSignedObject: () => createAndSignSignedObject,
|
|
200
205
|
createCapabilityKeyRegistry: () => createCapabilityKeyRegistry,
|
|
206
|
+
createInMemoryLocalNodeIdentityStore: () => createInMemoryLocalNodeIdentityStore,
|
|
207
|
+
createLocalStorageLocalNodeIdentityStore: () => createLocalStorageLocalNodeIdentityStore,
|
|
201
208
|
createOpenKeyCallbackSigningStrategy: () => createOpenKeyCallbackSigningStrategy,
|
|
202
209
|
createSharingService: () => createSharingService,
|
|
203
210
|
createSpaceService: () => createSpaceService,
|
|
@@ -213,6 +220,7 @@ __export(index_exports, {
|
|
|
213
220
|
didCacheKey: () => didCacheKey,
|
|
214
221
|
didEquals: () => didEquals,
|
|
215
222
|
disableTinyCloudDebug: () => import_sdk_services7.disableTinyCloudDebug,
|
|
223
|
+
discoverLocalTinyCloudNode: () => discoverLocalTinyCloudNode,
|
|
216
224
|
discoverNetwork: () => import_sdk_services7.discoverNetwork,
|
|
217
225
|
enableTinyCloudDebug: () => import_sdk_services7.enableTinyCloudDebug,
|
|
218
226
|
encryptToNetwork: () => import_sdk_services7.encryptToNetwork,
|
|
@@ -12449,6 +12457,54 @@ var import_ed255193 = require("@noble/curves/ed25519");
|
|
|
12449
12457
|
var import_viem5 = require("viem");
|
|
12450
12458
|
var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
12451
12459
|
var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
12460
|
+
var DEFAULT_LOCAL_NODE_URL = "http://127.0.0.1:8000";
|
|
12461
|
+
var LOCAL_LOOPBACK_PROBE_TIMEOUT_MS = 250;
|
|
12462
|
+
var LOCAL_LINK_PROBE_TIMEOUT_MS = 750;
|
|
12463
|
+
var LOCAL_LINK_HOST_SUFFIX = ".local.tinycloud.link";
|
|
12464
|
+
function createInMemoryLocalNodeIdentityStore() {
|
|
12465
|
+
const pins = /* @__PURE__ */ new Map();
|
|
12466
|
+
return {
|
|
12467
|
+
get: (url) => pins.get(url),
|
|
12468
|
+
set: (url, nodeDid) => {
|
|
12469
|
+
pins.set(url, nodeDid);
|
|
12470
|
+
}
|
|
12471
|
+
};
|
|
12472
|
+
}
|
|
12473
|
+
var DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY = "tinycloud.localNodePins.v1";
|
|
12474
|
+
function defaultWebStorage() {
|
|
12475
|
+
try {
|
|
12476
|
+
return globalThis.localStorage;
|
|
12477
|
+
} catch {
|
|
12478
|
+
return void 0;
|
|
12479
|
+
}
|
|
12480
|
+
}
|
|
12481
|
+
function createLocalStorageLocalNodeIdentityStore(storage, storageKey = DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY) {
|
|
12482
|
+
const backing = storage ?? defaultWebStorage();
|
|
12483
|
+
if (!backing) {
|
|
12484
|
+
return createInMemoryLocalNodeIdentityStore();
|
|
12485
|
+
}
|
|
12486
|
+
const readPins = () => {
|
|
12487
|
+
const raw = backing.getItem(storageKey);
|
|
12488
|
+
if (!raw) return {};
|
|
12489
|
+
try {
|
|
12490
|
+
const parsed = JSON.parse(raw);
|
|
12491
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
12492
|
+
return parsed;
|
|
12493
|
+
}
|
|
12494
|
+
} catch {
|
|
12495
|
+
}
|
|
12496
|
+
backing.removeItem(storageKey);
|
|
12497
|
+
return {};
|
|
12498
|
+
};
|
|
12499
|
+
return {
|
|
12500
|
+
get: (url) => readPins()[url],
|
|
12501
|
+
set: (url, nodeDid) => {
|
|
12502
|
+
const pins = readPins();
|
|
12503
|
+
pins[url] = nodeDid;
|
|
12504
|
+
backing.setItem(storageKey, JSON.stringify(pins));
|
|
12505
|
+
}
|
|
12506
|
+
};
|
|
12507
|
+
}
|
|
12452
12508
|
var LocationRecordValidationError = class extends Error {
|
|
12453
12509
|
constructor(message) {
|
|
12454
12510
|
super(`Location record validation failed: ${message}`);
|
|
@@ -12575,6 +12631,33 @@ async function resolveCloudLocation(subject, options2 = {}) {
|
|
|
12575
12631
|
};
|
|
12576
12632
|
}
|
|
12577
12633
|
async function resolveTinyCloudHosts(subject, options2 = {}) {
|
|
12634
|
+
const hasExplicitHosts = options2.explicitHosts !== void 0 && options2.explicitHosts.length > 0;
|
|
12635
|
+
const fetchFn = memoizeFetch(options2.fetch ?? globalThis.fetch);
|
|
12636
|
+
if (!hasExplicitHosts && (options2.autoDiscoverLocalNode ?? true)) {
|
|
12637
|
+
const local = await discoverLocalTinyCloudNode({
|
|
12638
|
+
subject,
|
|
12639
|
+
autoDiscoverLocalNode: true,
|
|
12640
|
+
localNodeUrl: options2.localNodeUrl,
|
|
12641
|
+
localLinkName: options2.localLinkName,
|
|
12642
|
+
registryUrl: options2.registryUrl,
|
|
12643
|
+
expectedNodeDid: options2.expectedNodeDid,
|
|
12644
|
+
identityStore: options2.localNodeIdentityStore,
|
|
12645
|
+
verifyRecords: options2.verifyRecords,
|
|
12646
|
+
fetch: fetchFn
|
|
12647
|
+
});
|
|
12648
|
+
if (local) {
|
|
12649
|
+
const multiaddrs = [httpUrlToMultiaddr(local.url)];
|
|
12650
|
+
const candidate = { source: local.source, multiaddrs };
|
|
12651
|
+
const location2 = {
|
|
12652
|
+
subject,
|
|
12653
|
+
source: local.source,
|
|
12654
|
+
multiaddrs,
|
|
12655
|
+
attempts: [{ source: local.source, candidate }],
|
|
12656
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
12657
|
+
};
|
|
12658
|
+
return { hosts: [local.url], location: location2 };
|
|
12659
|
+
}
|
|
12660
|
+
}
|
|
12578
12661
|
const location = await resolveCloudLocation(subject, {
|
|
12579
12662
|
explicitMultiaddrs: hostsToMultiaddrs(options2.explicitHosts),
|
|
12580
12663
|
blockchain: options2.blockchain,
|
|
@@ -12582,7 +12665,7 @@ async function resolveTinyCloudHosts(subject, options2 = {}) {
|
|
|
12582
12665
|
fallbackMultiaddrs: hostsToMultiaddrs(
|
|
12583
12666
|
options2.fallbackHosts === null ? void 0 : options2.fallbackHosts ?? [DEFAULT_TINYCLOUD_FALLBACK_HOST]
|
|
12584
12667
|
),
|
|
12585
|
-
fetch:
|
|
12668
|
+
fetch: fetchFn,
|
|
12586
12669
|
verifyRecords: options2.verifyRecords
|
|
12587
12670
|
});
|
|
12588
12671
|
return {
|
|
@@ -12590,6 +12673,181 @@ async function resolveTinyCloudHosts(subject, options2 = {}) {
|
|
|
12590
12673
|
location
|
|
12591
12674
|
};
|
|
12592
12675
|
}
|
|
12676
|
+
function memoizeFetch(fetchFn) {
|
|
12677
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
12678
|
+
return (async (input, init) => {
|
|
12679
|
+
const key = String(input);
|
|
12680
|
+
let cached = cache2.get(key);
|
|
12681
|
+
if (!cached) {
|
|
12682
|
+
cached = fetchFn(input, init);
|
|
12683
|
+
cache2.set(key, cached);
|
|
12684
|
+
}
|
|
12685
|
+
const response = await cached;
|
|
12686
|
+
return response.clone();
|
|
12687
|
+
});
|
|
12688
|
+
}
|
|
12689
|
+
async function discoverLocalTinyCloudNode(options2 = {}) {
|
|
12690
|
+
if ((options2.autoDiscoverLocalNode ?? true) === false) {
|
|
12691
|
+
return null;
|
|
12692
|
+
}
|
|
12693
|
+
const fetchFn = options2.fetch ?? globalThis.fetch;
|
|
12694
|
+
const identityStore = options2.identityStore ?? defaultLocalNodeIdentityStore;
|
|
12695
|
+
const staticCandidates = [
|
|
12696
|
+
{
|
|
12697
|
+
source: "local-loopback",
|
|
12698
|
+
url: options2.localNodeUrl ?? DEFAULT_LOCAL_NODE_URL,
|
|
12699
|
+
timeoutMs: LOCAL_LOOPBACK_PROBE_TIMEOUT_MS
|
|
12700
|
+
}
|
|
12701
|
+
];
|
|
12702
|
+
if (options2.localLinkName) {
|
|
12703
|
+
if (isValidDnsLabel(options2.localLinkName)) {
|
|
12704
|
+
staticCandidates.push({
|
|
12705
|
+
source: "local-link",
|
|
12706
|
+
url: `https://${options2.localLinkName}${LOCAL_LINK_HOST_SUFFIX}`,
|
|
12707
|
+
timeoutMs: LOCAL_LINK_PROBE_TIMEOUT_MS
|
|
12708
|
+
});
|
|
12709
|
+
} else {
|
|
12710
|
+
debugLog(
|
|
12711
|
+
`localLinkName "${options2.localLinkName}" is not a valid DNS label; skipping`
|
|
12712
|
+
);
|
|
12713
|
+
}
|
|
12714
|
+
}
|
|
12715
|
+
for (const candidate of staticCandidates) {
|
|
12716
|
+
const adopted = await probeAndVerifyLocalCandidate(
|
|
12717
|
+
candidate,
|
|
12718
|
+
fetchFn,
|
|
12719
|
+
identityStore,
|
|
12720
|
+
options2.expectedNodeDid
|
|
12721
|
+
);
|
|
12722
|
+
if (adopted) {
|
|
12723
|
+
return adopted;
|
|
12724
|
+
}
|
|
12725
|
+
}
|
|
12726
|
+
const registryCandidates = await fetchRegistryLocalLinkCandidates(
|
|
12727
|
+
options2,
|
|
12728
|
+
fetchFn,
|
|
12729
|
+
staticCandidates
|
|
12730
|
+
);
|
|
12731
|
+
for (const candidate of registryCandidates) {
|
|
12732
|
+
const adopted = await probeAndVerifyLocalCandidate(
|
|
12733
|
+
candidate,
|
|
12734
|
+
fetchFn,
|
|
12735
|
+
identityStore,
|
|
12736
|
+
options2.expectedNodeDid
|
|
12737
|
+
);
|
|
12738
|
+
if (adopted) {
|
|
12739
|
+
return adopted;
|
|
12740
|
+
}
|
|
12741
|
+
}
|
|
12742
|
+
return null;
|
|
12743
|
+
}
|
|
12744
|
+
var defaultLocalNodeIdentityStore = createInMemoryLocalNodeIdentityStore();
|
|
12745
|
+
function debugLog(message) {
|
|
12746
|
+
console.debug(`[tinycloud:location] ${message}`);
|
|
12747
|
+
}
|
|
12748
|
+
async function probeAndVerifyLocalCandidate(candidate, fetchFn, identityStore, expectedNodeDid) {
|
|
12749
|
+
const healthy = await probeHealthz(candidate.url, candidate.timeoutMs, fetchFn);
|
|
12750
|
+
if (!healthy) {
|
|
12751
|
+
return null;
|
|
12752
|
+
}
|
|
12753
|
+
const info = await fetchLocalNodeInfo(candidate.url, candidate.timeoutMs, fetchFn);
|
|
12754
|
+
if (!info?.nodeDid) {
|
|
12755
|
+
debugLog(`local node at ${candidate.url} did not report a nodeId DID; skipping`);
|
|
12756
|
+
return null;
|
|
12757
|
+
}
|
|
12758
|
+
const pinnedNodeDid = await identityStore.get(candidate.url);
|
|
12759
|
+
const expected = expectedNodeDid ?? pinnedNodeDid;
|
|
12760
|
+
if (expected !== void 0 && expected !== info.nodeDid) {
|
|
12761
|
+
debugLog(
|
|
12762
|
+
`local node DID mismatch at ${candidate.url}: expected ${expected}, got ${info.nodeDid}`
|
|
12763
|
+
);
|
|
12764
|
+
return null;
|
|
12765
|
+
}
|
|
12766
|
+
if (pinnedNodeDid === void 0 || expectedNodeDid !== void 0) {
|
|
12767
|
+
await identityStore.set(candidate.url, info.nodeDid);
|
|
12768
|
+
}
|
|
12769
|
+
return { source: candidate.source, url: candidate.url, nodeDid: info.nodeDid };
|
|
12770
|
+
}
|
|
12771
|
+
async function fetchRegistryLocalLinkCandidates(options2, fetchFn, existingCandidates) {
|
|
12772
|
+
if (!options2.subject || options2.registryUrl === null) {
|
|
12773
|
+
return [];
|
|
12774
|
+
}
|
|
12775
|
+
const registryUrl = options2.registryUrl ?? DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL;
|
|
12776
|
+
try {
|
|
12777
|
+
const record = await fetchLocationRecord(registryUrl, options2.subject, fetchFn);
|
|
12778
|
+
if (!record) {
|
|
12779
|
+
return [];
|
|
12780
|
+
}
|
|
12781
|
+
const shouldVerify = options2.verifyRecords ?? true;
|
|
12782
|
+
if (shouldVerify && !await verifyLocationRecord(record)) {
|
|
12783
|
+
debugLog(
|
|
12784
|
+
`registry record signature invalid for ${options2.subject}; skipping local-link lookup`
|
|
12785
|
+
);
|
|
12786
|
+
return [];
|
|
12787
|
+
}
|
|
12788
|
+
return extractLocalLinkUrls(record).filter((url) => !existingCandidates.some((c) => c.url === url)).map((url) => ({
|
|
12789
|
+
source: "local-link",
|
|
12790
|
+
url,
|
|
12791
|
+
timeoutMs: LOCAL_LINK_PROBE_TIMEOUT_MS
|
|
12792
|
+
}));
|
|
12793
|
+
} catch {
|
|
12794
|
+
return [];
|
|
12795
|
+
}
|
|
12796
|
+
}
|
|
12797
|
+
function extractLocalLinkUrls(record) {
|
|
12798
|
+
if (!record) {
|
|
12799
|
+
return [];
|
|
12800
|
+
}
|
|
12801
|
+
const urls = [];
|
|
12802
|
+
for (const addr of record.multiaddrs) {
|
|
12803
|
+
let url;
|
|
12804
|
+
try {
|
|
12805
|
+
url = multiaddrToHttpUrl(addr);
|
|
12806
|
+
} catch {
|
|
12807
|
+
continue;
|
|
12808
|
+
}
|
|
12809
|
+
if (isLocalLinkUrl(url)) {
|
|
12810
|
+
urls.push(url);
|
|
12811
|
+
}
|
|
12812
|
+
}
|
|
12813
|
+
return urls;
|
|
12814
|
+
}
|
|
12815
|
+
var DNS_LABEL_REGEX = /^[a-z0-9]([a-z0-9-]{1,30}[a-z0-9])?$/;
|
|
12816
|
+
function isValidDnsLabel(value) {
|
|
12817
|
+
return DNS_LABEL_REGEX.test(value);
|
|
12818
|
+
}
|
|
12819
|
+
function isLocalLinkUrl(url) {
|
|
12820
|
+
try {
|
|
12821
|
+
const parsed = new URL(url);
|
|
12822
|
+
return parsed.protocol === "https:" && parsed.hostname.endsWith(LOCAL_LINK_HOST_SUFFIX);
|
|
12823
|
+
} catch {
|
|
12824
|
+
return false;
|
|
12825
|
+
}
|
|
12826
|
+
}
|
|
12827
|
+
async function probeHealthz(url, timeoutMs, fetchFn) {
|
|
12828
|
+
try {
|
|
12829
|
+
const response = await fetchFn(`${url.replace(/\/$/, "")}/healthz`, {
|
|
12830
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
12831
|
+
});
|
|
12832
|
+
return response.ok;
|
|
12833
|
+
} catch {
|
|
12834
|
+
return false;
|
|
12835
|
+
}
|
|
12836
|
+
}
|
|
12837
|
+
async function fetchLocalNodeInfo(url, timeoutMs, fetchFn) {
|
|
12838
|
+
try {
|
|
12839
|
+
const response = await fetchFn(`${url.replace(/\/$/, "")}/info`, {
|
|
12840
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
12841
|
+
});
|
|
12842
|
+
if (!response.ok) {
|
|
12843
|
+
return null;
|
|
12844
|
+
}
|
|
12845
|
+
const body = await response.json();
|
|
12846
|
+
return { nodeDid: body.nodeId };
|
|
12847
|
+
} catch {
|
|
12848
|
+
return null;
|
|
12849
|
+
}
|
|
12850
|
+
}
|
|
12593
12851
|
function multiaddrToHttpUrl(input) {
|
|
12594
12852
|
const uri = multiaddrToUri(multiaddr(input));
|
|
12595
12853
|
if (!uri.startsWith("http://") && !uri.startsWith("https://")) {
|
|
@@ -12866,6 +13124,8 @@ function decodeBase64Url(value) {
|
|
|
12866
13124
|
DEFAULT_EXPIRY,
|
|
12867
13125
|
DEFAULT_KEY_VERSION,
|
|
12868
13126
|
DEFAULT_KNOWLEDGE_ROOT,
|
|
13127
|
+
DEFAULT_LOCAL_NODE_PIN_STORAGE_KEY,
|
|
13128
|
+
DEFAULT_LOCAL_NODE_URL,
|
|
12869
13129
|
DEFAULT_MANIFEST_SPACE,
|
|
12870
13130
|
DEFAULT_MANIFEST_VERSION,
|
|
12871
13131
|
DEFAULT_SIGNED_READ_URL_EXPIRY_MS,
|
|
@@ -12900,6 +13160,9 @@ function decodeBase64Url(value) {
|
|
|
12900
13160
|
KV,
|
|
12901
13161
|
KVService,
|
|
12902
13162
|
LISTEN_SQL_STATEMENT_CATALOG,
|
|
13163
|
+
LOCAL_LINK_HOST_SUFFIX,
|
|
13164
|
+
LOCAL_LINK_PROBE_TIMEOUT_MS,
|
|
13165
|
+
LOCAL_LOOPBACK_PROBE_TIMEOUT_MS,
|
|
12903
13166
|
LocationRecordValidationError,
|
|
12904
13167
|
ManifestValidationError,
|
|
12905
13168
|
NETWORK_NAME_PATTERN,
|
|
@@ -12995,6 +13258,8 @@ function decodeBase64Url(value) {
|
|
|
12995
13258
|
createAndSignPolicyStatus,
|
|
12996
13259
|
createAndSignSignedObject,
|
|
12997
13260
|
createCapabilityKeyRegistry,
|
|
13261
|
+
createInMemoryLocalNodeIdentityStore,
|
|
13262
|
+
createLocalStorageLocalNodeIdentityStore,
|
|
12998
13263
|
createOpenKeyCallbackSigningStrategy,
|
|
12999
13264
|
createSharingService,
|
|
13000
13265
|
createSpaceService,
|
|
@@ -13010,6 +13275,7 @@ function decodeBase64Url(value) {
|
|
|
13010
13275
|
didCacheKey,
|
|
13011
13276
|
didEquals,
|
|
13012
13277
|
disableTinyCloudDebug,
|
|
13278
|
+
discoverLocalTinyCloudNode,
|
|
13013
13279
|
discoverNetwork,
|
|
13014
13280
|
enableTinyCloudDebug,
|
|
13015
13281
|
encryptToNetwork,
|