@tinycloud/node-sdk 3.2.0 → 3.2.1-beta.1
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/{WasmKeyProvider-6_YwgSkd.d.cts → WasmKeyProvider-DRlOpvpG.d.cts} +56 -13
- package/dist/{WasmKeyProvider-6_YwgSkd.d.ts → WasmKeyProvider-DRlOpvpG.d.ts} +56 -13
- package/dist/core.cjs +138 -31
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +138 -31
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +137 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +137 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -18494,6 +18494,11 @@ var NodeUserAuthorization = class {
|
|
|
18494
18494
|
this._nodeFeatures = [];
|
|
18495
18495
|
this._nodeFeaturesKnown = false;
|
|
18496
18496
|
this._lastActivationSkippedSpaceIds = [];
|
|
18497
|
+
/**
|
|
18498
|
+
* Spaces the sign-in activation reported hosted. Only the first POST of a
|
|
18499
|
+
* delegation lists them: the node answers a repeat with empty lists.
|
|
18500
|
+
*/
|
|
18501
|
+
this._lastActivationActivatedSpaceIds = [];
|
|
18497
18502
|
this.wasm = config.wasmBindings;
|
|
18498
18503
|
this.signer = config.signer;
|
|
18499
18504
|
this.signStrategy = config.signStrategy ?? defaultSignStrategy;
|
|
@@ -18623,6 +18628,7 @@ var NodeUserAuthorization = class {
|
|
|
18623
18628
|
this._nodeInfoIdentity = void 0;
|
|
18624
18629
|
this.tinycloudHosts = hosts && hosts.length > 0 ? [...hosts] : void 0;
|
|
18625
18630
|
this._lastActivationSkippedSpaceIds = [];
|
|
18631
|
+
this._lastActivationActivatedSpaceIds = [];
|
|
18626
18632
|
if (!session) {
|
|
18627
18633
|
this._session = void 0;
|
|
18628
18634
|
this._tinyCloudSession = void 0;
|
|
@@ -18717,6 +18723,9 @@ var NodeUserAuthorization = class {
|
|
|
18717
18723
|
get lastActivationSkippedSpaceIds() {
|
|
18718
18724
|
return [...this._lastActivationSkippedSpaceIds];
|
|
18719
18725
|
}
|
|
18726
|
+
get lastActivationActivatedSpaceIds() {
|
|
18727
|
+
return [...this._lastActivationActivatedSpaceIds];
|
|
18728
|
+
}
|
|
18720
18729
|
/**
|
|
18721
18730
|
* Compute the `abilities` map the WASM `prepareSession` call should
|
|
18722
18731
|
* see at sign-in time.
|
|
@@ -19212,8 +19221,10 @@ var NodeUserAuthorization = class {
|
|
|
19212
19221
|
recordActivationSkippedSpaces(result, primarySpaceId) {
|
|
19213
19222
|
if (result.success) {
|
|
19214
19223
|
this._lastActivationSkippedSpaceIds = result.skipped ?? [];
|
|
19224
|
+
this._lastActivationActivatedSpaceIds = result.activated ?? [];
|
|
19215
19225
|
return;
|
|
19216
19226
|
}
|
|
19227
|
+
this._lastActivationActivatedSpaceIds = [];
|
|
19217
19228
|
this._lastActivationSkippedSpaceIds = result.status === 404 ? [primarySpaceId] : [];
|
|
19218
19229
|
}
|
|
19219
19230
|
async createBootstrapSession(options) {
|
|
@@ -20943,10 +20954,26 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
20943
20954
|
* hosting is confirmed against the session that was active at the time.
|
|
20944
20955
|
*/
|
|
20945
20956
|
this.confirmedHostedSpaceIds = /* @__PURE__ */ new Set();
|
|
20957
|
+
/**
|
|
20958
|
+
* Owned space ids known to be hosted for the current session: the sign-in
|
|
20959
|
+
* activation listed them as `activated`, or this session hosted them. Unlike
|
|
20960
|
+
* {@link confirmedHostedSpaceIds}, nothing here is inferred from a space being
|
|
20961
|
+
* merely absent from `skipped`. Read by {@link ensureOwnedSpaceHosted}.
|
|
20962
|
+
*/
|
|
20963
|
+
this.hostedOwnedSpaceIds = /* @__PURE__ */ new Set();
|
|
20964
|
+
/**
|
|
20965
|
+
* In-flight host delegations, so concurrent callers share one approval per
|
|
20966
|
+
* space. `waiters` counts callers still waiting; the request is cancelled
|
|
20967
|
+
* once every caller with a signal has aborted and none waits without one.
|
|
20968
|
+
*/
|
|
20969
|
+
this.ownedSpaceHosts = /* @__PURE__ */ new Map();
|
|
20946
20970
|
/** Serializes account-registry writes for the active node instance. */
|
|
20947
20971
|
this.accountRegistryTail = Promise.resolve();
|
|
20948
|
-
/**
|
|
20949
|
-
|
|
20972
|
+
/**
|
|
20973
|
+
* Hang guard for the background registry sync. It is off the sign-in path,
|
|
20974
|
+
* so it must outlast a slow but healthy sync (9–18 s on prod 1.20.2, TC-998).
|
|
20975
|
+
*/
|
|
20976
|
+
this.accountRegistryDeadlineMs = 3e4;
|
|
20950
20977
|
/**
|
|
20951
20978
|
* True when the last signIn() detected an interactive signer and skipped
|
|
20952
20979
|
* client-side bootstrap. Apps can read this to know whether bootstrap was
|
|
@@ -21541,6 +21568,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21541
21568
|
"Cannot signIn() in session-only mode. Provide a privateKey in config to create your own space."
|
|
21542
21569
|
);
|
|
21543
21570
|
}
|
|
21571
|
+
this.pendingAccountRegistrySync?.controller.abort();
|
|
21544
21572
|
await this.accountRegistryTail;
|
|
21545
21573
|
await this.wasmBindings.ensureInitialized?.();
|
|
21546
21574
|
const address = (0, import_sdk_core9.canonicalizeAddress)(await this.signer.getAddress());
|
|
@@ -21561,8 +21589,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21561
21589
|
this._serviceContext = void 0;
|
|
21562
21590
|
this.runtimePermissionGrants = [];
|
|
21563
21591
|
this.confirmedHostedSpaceIds.clear();
|
|
21592
|
+
this.hostedOwnedSpaceIds.clear();
|
|
21564
21593
|
await this.tc.signIn(options);
|
|
21594
|
+
this.cancelOwnedSpaceHosts();
|
|
21565
21595
|
this.syncResolvedHostFromAuth();
|
|
21596
|
+
for (const spaceId of this.auth.lastActivationActivatedSpaceIds ?? []) {
|
|
21597
|
+
this.hostedOwnedSpaceIds.add(spaceId);
|
|
21598
|
+
}
|
|
21566
21599
|
this.replicationDelegateSession = void 0;
|
|
21567
21600
|
this.replicationScopeError = void 0;
|
|
21568
21601
|
if (this.replicationRuntime) await (await this.replicationRuntime).unbind();
|
|
@@ -21587,10 +21620,20 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21587
21620
|
}
|
|
21588
21621
|
if (!bootstrapped) {
|
|
21589
21622
|
this.scheduleAccountRegistrySync();
|
|
21590
|
-
await this.accountRegistryTail;
|
|
21591
21623
|
}
|
|
21592
21624
|
this.notificationHandler.success("Successfully signed in");
|
|
21593
21625
|
}
|
|
21626
|
+
/**
|
|
21627
|
+
* Wait for the account-registry sync that {@link signIn} starts in the
|
|
21628
|
+
* background (account index, this app's manifest record, space list).
|
|
21629
|
+
* Resolves once it has finished, failed or hit its hang guard; it never
|
|
21630
|
+
* rejects, and failures are logged as warnings. `signIn()` does not wait for
|
|
21631
|
+
* it, so call this only when you need the registry written, or before a first
|
|
21632
|
+
* write against a SQLite-backed node older than 1.20.2 (TC-899).
|
|
21633
|
+
*/
|
|
21634
|
+
async waitForAccountRegistrySync() {
|
|
21635
|
+
await this.accountRegistryTail;
|
|
21636
|
+
}
|
|
21594
21637
|
ownedSpaceId(name) {
|
|
21595
21638
|
if (!this._address) {
|
|
21596
21639
|
throw new Error("Cannot resolve owned space before sign-in");
|
|
@@ -21730,6 +21773,13 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
21730
21773
|
* A marker written before a canonical space was added triggers one bounded repair.
|
|
21731
21774
|
*/
|
|
21732
21775
|
isAcceptedBootstrapCompletionMarker(value, canonicalStepIds) {
|
|
21776
|
+
if (typeof value === "string") {
|
|
21777
|
+
try {
|
|
21778
|
+
value = JSON.parse(value);
|
|
21779
|
+
} catch {
|
|
21780
|
+
return false;
|
|
21781
|
+
}
|
|
21782
|
+
}
|
|
21733
21783
|
if (typeof value !== "object" || value === null) return false;
|
|
21734
21784
|
const entries = Object.entries(value);
|
|
21735
21785
|
const markerValue = (name) => entries.find(([key2]) => key2 === name)?.[1];
|
|
@@ -22189,17 +22239,17 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22189
22239
|
clearTimeout(deadline);
|
|
22190
22240
|
}
|
|
22191
22241
|
});
|
|
22192
|
-
this.pendingAccountRegistrySync = { session, promise };
|
|
22193
|
-
const
|
|
22242
|
+
this.pendingAccountRegistrySync = { session, promise, controller };
|
|
22243
|
+
const settle = () => {
|
|
22244
|
+
clearTimeout(deadline);
|
|
22194
22245
|
if (this.pendingAccountRegistrySync?.promise === promise) {
|
|
22195
22246
|
this.pendingAccountRegistrySync = void 0;
|
|
22196
22247
|
}
|
|
22197
22248
|
};
|
|
22198
|
-
void promise.then(
|
|
22199
|
-
|
|
22200
|
-
(
|
|
22201
|
-
|
|
22202
|
-
);
|
|
22249
|
+
void promise.then(settle, (error) => {
|
|
22250
|
+
settle();
|
|
22251
|
+
console.warn("TinyCloud account registry sync failed", error);
|
|
22252
|
+
});
|
|
22203
22253
|
}
|
|
22204
22254
|
enqueueAccountRegistryOperation(session, task) {
|
|
22205
22255
|
const operation = this.accountRegistryTail.then(async () => {
|
|
@@ -22237,10 +22287,15 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22237
22287
|
}
|
|
22238
22288
|
async withAccountRegistryRetry(task, signal) {
|
|
22239
22289
|
const delays = [250, 1e3, 3e3];
|
|
22290
|
+
const stopped = (detail) => {
|
|
22291
|
+
if (signal.reason instanceof DOMException && signal.reason.name === "TimeoutError") {
|
|
22292
|
+
console.warn("TinyCloud account registry sync stopped: deadline exceeded", detail);
|
|
22293
|
+
}
|
|
22294
|
+
};
|
|
22240
22295
|
let lastError;
|
|
22241
22296
|
for (let attempt = 0; attempt < delays.length; attempt += 1) {
|
|
22242
22297
|
if (signal.aborted) {
|
|
22243
|
-
|
|
22298
|
+
stopped(signal.reason);
|
|
22244
22299
|
return;
|
|
22245
22300
|
}
|
|
22246
22301
|
try {
|
|
@@ -22248,7 +22303,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22248
22303
|
return;
|
|
22249
22304
|
} catch (error) {
|
|
22250
22305
|
if (signal.aborted) {
|
|
22251
|
-
|
|
22306
|
+
stopped(error);
|
|
22252
22307
|
return;
|
|
22253
22308
|
}
|
|
22254
22309
|
const verdict = (0, import_sdk_core9.authorizationVerdictOf)(error);
|
|
@@ -22341,7 +22396,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22341
22396
|
if (!session) {
|
|
22342
22397
|
throw new Error("Owned space hosting requires an active session");
|
|
22343
22398
|
}
|
|
22344
|
-
if (this.confirmedHostedSpaceIds.has(spaceId)) {
|
|
22399
|
+
if (this.confirmedHostedSpaceIds.has(spaceId) || this.hostedOwnedSpaceIds.has(spaceId)) {
|
|
22345
22400
|
return;
|
|
22346
22401
|
}
|
|
22347
22402
|
const host = this.hosts[0] ?? this.config.host;
|
|
@@ -22359,8 +22414,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22359
22414
|
{ cause: activation }
|
|
22360
22415
|
);
|
|
22361
22416
|
}
|
|
22362
|
-
const
|
|
22363
|
-
const created = signal ? await authorization.hostOwnedSpaceResult(spaceId, void 0, signal) : await authorization.hostOwnedSpaceResult(spaceId);
|
|
22417
|
+
const created = await this.hostOwnedSpaceOnce(spaceId, signal);
|
|
22364
22418
|
if (!created.success) {
|
|
22365
22419
|
throw Object.assign(
|
|
22366
22420
|
new Error(`Failed to create owned space ${spaceId}: ${describeHostFailure2(created)}`),
|
|
@@ -22377,7 +22431,10 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22377
22431
|
{ cause: retry }
|
|
22378
22432
|
);
|
|
22379
22433
|
}
|
|
22380
|
-
this.
|
|
22434
|
+
if (this.auth.tinyCloudSession === session) {
|
|
22435
|
+
this.confirmedHostedSpaceIds.add(spaceId);
|
|
22436
|
+
this.hostedOwnedSpaceIds.add(spaceId);
|
|
22437
|
+
}
|
|
22381
22438
|
}
|
|
22382
22439
|
/**
|
|
22383
22440
|
* Host one of this user's owned spaces by name (e.g. `"applications"`).
|
|
@@ -22409,7 +22466,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22409
22466
|
if (!host) {
|
|
22410
22467
|
throw new Error("Owned space hosting requires a TinyCloud host");
|
|
22411
22468
|
}
|
|
22412
|
-
const hosted = await this.
|
|
22469
|
+
const hosted = await this.hostOwnedSpaceOnce(spaceId);
|
|
22413
22470
|
if (!hosted.success) {
|
|
22414
22471
|
throw Object.assign(
|
|
22415
22472
|
new Error(`Failed to host owned space ${spaceId}: ${describeHostFailure2(hosted)}`),
|
|
@@ -22428,6 +22485,7 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22428
22485
|
{ cause: activation }
|
|
22429
22486
|
);
|
|
22430
22487
|
}
|
|
22488
|
+
if (this.auth?.tinyCloudSession === session) this.hostedOwnedSpaceIds.add(spaceId);
|
|
22431
22489
|
try {
|
|
22432
22490
|
await this.enqueueAccountRegistryOperation(session, async () => {
|
|
22433
22491
|
await this.account.spaces.register({
|
|
@@ -22455,18 +22513,19 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22455
22513
|
* registered on the node.
|
|
22456
22514
|
*
|
|
22457
22515
|
* Calling this resolves `name` to the owner's owned-space URI
|
|
22458
|
-
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It
|
|
22459
|
-
*
|
|
22460
|
-
*
|
|
22461
|
-
* already
|
|
22462
|
-
*
|
|
22463
|
-
*
|
|
22464
|
-
*
|
|
22465
|
-
*
|
|
22516
|
+
* (`tinycloud:pkh:eip155:<chain>:<addr>:<name>`). It returns WITHOUT
|
|
22517
|
+
* submitting a host delegation when the space is known to be hosted: the
|
|
22518
|
+
* sign-in activation listed it as `activated` (any space the session's recap
|
|
22519
|
+
* covers), this session already hosted it, or the account-space spaces
|
|
22520
|
+
* registry (`account/spaces/{space_id}`, the canonical KV source of truth,
|
|
22521
|
+
* fronted by a best-effort SQLite index) has its record. Otherwise it falls
|
|
22522
|
+
* through to {@link hostOwnedSpace}, which asks for a signature; a host
|
|
22523
|
+
* already in flight for the same space (e.g. from the background registry
|
|
22524
|
+
* sync) is shared rather than asked for twice.
|
|
22466
22525
|
*
|
|
22467
|
-
*
|
|
22468
|
-
*
|
|
22469
|
-
*
|
|
22526
|
+
* Hosting is still needed when the space really isn't hosted, or when the
|
|
22527
|
+
* session's recap doesn't cover it and the registry has no record; the host
|
|
22528
|
+
* SIWE is idempotent server-side. Must be called after {@link signIn}.
|
|
22470
22529
|
*
|
|
22471
22530
|
* @param name - The owned space name (e.g. `"secrets"`).
|
|
22472
22531
|
* @returns The hosted owned-space URI.
|
|
@@ -22475,13 +22534,57 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22475
22534
|
if (!this.auth || !this.auth.tinyCloudSession) {
|
|
22476
22535
|
throw new Error("Not signed in. Call signIn() first.");
|
|
22477
22536
|
}
|
|
22478
|
-
await this.accountRegistryTail;
|
|
22479
22537
|
const spaceId = this.ownedSpaceId(name);
|
|
22480
|
-
if (await this.isOwnedSpaceRegistered(spaceId)) {
|
|
22538
|
+
if (this.hostedOwnedSpaceIds.has(spaceId) || await this.isOwnedSpaceRegistered(spaceId)) {
|
|
22481
22539
|
return spaceId;
|
|
22482
22540
|
}
|
|
22483
22541
|
return this.hostOwnedSpace(name);
|
|
22484
22542
|
}
|
|
22543
|
+
/**
|
|
22544
|
+
* Submit the host delegation for an owned space, sharing one in-flight
|
|
22545
|
+
* request (and so one approval) between concurrent callers in this session,
|
|
22546
|
+
* such as the background registry sync and {@link ensureOwnedSpaceHosted}.
|
|
22547
|
+
* Each caller's `signal` releases only its own wait; the request itself is
|
|
22548
|
+
* cancelled once no caller is left waiting, or when the session is replaced
|
|
22549
|
+
* ({@link cancelOwnedSpaceHosts}), so a late approval is discarded.
|
|
22550
|
+
*/
|
|
22551
|
+
hostOwnedSpaceOnce(spaceId, signal) {
|
|
22552
|
+
if (signal?.aborted) return Promise.reject(signal.reason);
|
|
22553
|
+
let entry = this.ownedSpaceHosts.get(spaceId);
|
|
22554
|
+
if (!entry) {
|
|
22555
|
+
const controller = new AbortController();
|
|
22556
|
+
const promise = this.auth.hostOwnedSpaceResult(spaceId, void 0, controller.signal);
|
|
22557
|
+
const created = { promise, controller, waiters: 0 };
|
|
22558
|
+
this.ownedSpaceHosts.set(spaceId, created);
|
|
22559
|
+
const forget = () => {
|
|
22560
|
+
if (this.ownedSpaceHosts.get(spaceId) === created) this.ownedSpaceHosts.delete(spaceId);
|
|
22561
|
+
};
|
|
22562
|
+
promise.then(forget, forget);
|
|
22563
|
+
entry = created;
|
|
22564
|
+
}
|
|
22565
|
+
if (!signal) {
|
|
22566
|
+
entry.waiters = Number.POSITIVE_INFINITY;
|
|
22567
|
+
return entry.promise;
|
|
22568
|
+
}
|
|
22569
|
+
entry.waiters += 1;
|
|
22570
|
+
const shared = entry;
|
|
22571
|
+
return new Promise((resolve, reject2) => {
|
|
22572
|
+
const onAbort = () => {
|
|
22573
|
+
reject2(signal.reason);
|
|
22574
|
+
shared.waiters -= 1;
|
|
22575
|
+
if (shared.waiters !== 0) return;
|
|
22576
|
+
shared.controller.abort(signal.reason);
|
|
22577
|
+
if (this.ownedSpaceHosts.get(spaceId) === shared) this.ownedSpaceHosts.delete(spaceId);
|
|
22578
|
+
};
|
|
22579
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
22580
|
+
shared.promise.then(resolve, reject2).finally(() => signal.removeEventListener("abort", onAbort));
|
|
22581
|
+
});
|
|
22582
|
+
}
|
|
22583
|
+
/** Session replacement: cancel the replaced session's in-flight hosts and forget them. */
|
|
22584
|
+
cancelOwnedSpaceHosts() {
|
|
22585
|
+
for (const { controller } of this.ownedSpaceHosts.values()) controller.abort();
|
|
22586
|
+
this.ownedSpaceHosts.clear();
|
|
22587
|
+
}
|
|
22485
22588
|
/** Resolve and authenticate the owner encoded by an owned-space URI. */
|
|
22486
22589
|
credentialSpaceOwnerDid(spaceId) {
|
|
22487
22590
|
const ownerDid = this.ownerDidFromSpaceId(spaceId);
|
|
@@ -22724,6 +22827,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22724
22827
|
sessionExpiry: stagedSessionExpiry,
|
|
22725
22828
|
recap: stagedRecap
|
|
22726
22829
|
});
|
|
22830
|
+
this.pendingAccountRegistrySync?.controller.abort();
|
|
22831
|
+
await this.accountRegistryTail;
|
|
22727
22832
|
const oldGraph = this._serviceGraph;
|
|
22728
22833
|
const oldCore = this.tc;
|
|
22729
22834
|
this.sessionManager = stagedManager;
|
|
@@ -22757,6 +22862,8 @@ var _TinyCloudNode = class _TinyCloudNode {
|
|
|
22757
22862
|
this._recapOperationsCache = stagedPrimary.cache;
|
|
22758
22863
|
this.runtimePermissionGrants = stagedPrimary.grants;
|
|
22759
22864
|
this.confirmedHostedSpaceIds.clear();
|
|
22865
|
+
this.hostedOwnedSpaceIds.clear();
|
|
22866
|
+
this.cancelOwnedSpaceHosts();
|
|
22760
22867
|
this._restoredNodeFeatures = restoredNodeFeatures;
|
|
22761
22868
|
if (this.auth) {
|
|
22762
22869
|
this.auth.installRestoredSession(stagedManager, stagedTcSession, [stagedHost], restoredNodeFeatures);
|