@tinycloud/web-sdk 3.11.0 → 3.12.0-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.
@@ -17,7 +17,7 @@ import { type BrowserProvider, type BrowserWalletProvider } from "../adapters/br
17
17
  import { type TinyCloudUI, type UiConfig } from "../ui";
18
18
  import { RPCProviders, ClientConfig } from "../providers";
19
19
  import type { NotificationConfig } from "../notifications/types";
20
- import type { PortableDelegation, DelegatedAccess } from "@tinycloud/node-sdk/core";
20
+ import type { PortableDelegation, DelegatedAccess, SpaceHosting } from "@tinycloud/node-sdk/core";
21
21
  import { CredentialsService } from "../credentials";
22
22
  import { ShareReceiverService, type ShareReceiverServiceOptions } from "../share";
23
23
  declare global {
@@ -181,6 +181,11 @@ export interface SessionRestoreResult {
181
181
  session?: ClientSession;
182
182
  error?: Error;
183
183
  }
184
+ /** A session storage that can fence a signed-out session (BrowserSessionStorage); others rely on the in-memory block. */
185
+ export type FenceCapableStorage = ISessionStorage & {
186
+ markSignedOut?: (address: string, signature: string) => void;
187
+ isSignedOut?: (address: string, signature: string) => boolean;
188
+ };
184
189
  /**
185
190
  * Result of receiving a share link.
186
191
  */
@@ -195,6 +200,8 @@ export interface ShareReceiveResult<T = unknown> {
195
200
  export declare class TinyCloudWeb {
196
201
  private openkeySignInInFlight;
197
202
  private prepareSignInToken;
203
+ /** How long a restore waits for the node's hosting answer. */
204
+ private spaceHostingCapMs;
198
205
  private preparedSignIn?;
199
206
  private invalidatePreparedSignIn;
200
207
  /** The connected wallet's raw EIP-1193 provider. */
@@ -231,6 +238,7 @@ export declare class TinyCloudWeb {
231
238
  private signOutInFlight;
232
239
  private persistedRestoreBlocked;
233
240
  private signOutCleanupFailed;
241
+ private remoteSignOutTimeoutMs;
234
242
  private readonly pendingRestoreAddresses;
235
243
  private _secrets;
236
244
  private _credentialsService?;
@@ -329,6 +337,8 @@ export declare class TinyCloudWeb {
329
337
  get delegations(): DelegationManager;
330
338
  get capabilityRegistry(): ICapabilityKeyRegistry;
331
339
  get spaceId(): string | undefined;
340
+ /** The node's last answer for whether the primary space is hosted (`"unknown"` until it has answered). */
341
+ get spaceHosting(): SpaceHosting;
332
342
  get accountSpaceId(): string | undefined;
333
343
  get account(): AccountService;
334
344
  get hosts(): string[];
@@ -377,6 +387,9 @@ export declare class TinyCloudWeb {
377
387
  private trackRestoreAddress;
378
388
  private untrackRestoreAddress;
379
389
  restoreSession(address?: string): Promise<SessionRestoreResult>;
390
+ /** One node read for the restored session, held to {@link spaceHostingCapMs}; past it, or on any failure, the answer stays unknown. */
391
+ private probeSpaceHosting;
392
+ private restoredSessionNotHosted;
380
393
  clearPersistedSession(address?: string): Promise<void>;
381
394
  private configuredManifestPermissions;
382
395
  /**
@@ -399,6 +412,12 @@ export declare class TinyCloudWeb {
399
412
  * unavailable until a fresh sign-in; prior persisted sessions cannot restore.
400
413
  */
401
414
  signOut: () => Promise<void>;
415
+ /**
416
+ * Clears the stored session for `address` only while it is the signing-out session (`ownSignature`); a newer
417
+ * session saved for the same address is left alone. The session is fenced first, so that a clear that fails
418
+ * cannot let a reload restore it.
419
+ */
420
+ private clearOwnPersistedSession;
402
421
  session: () => ClientSession | undefined;
403
422
  address: () => string | undefined;
404
423
  chainId: () => number | undefined;
@@ -0,0 +1,3 @@
1
+ /** Space hosting probe and space creation, loaded when the first hosting check or creation runs. */
2
+ export { askSpaceHosting, createPrimarySpace } from "@tinycloud/node-sdk/space-hosting";
3
+ //# sourceMappingURL=space-hosting-entry.d.ts.map
@@ -0,0 +1 @@
1
+ (()=>{"use strict";var e={d:(t,a)=>{for(var n in a)e.o(a,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:a[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{askSpaceHosting:()=>h,createPrimarySpace:()=>f});var a=new WeakMap,n=5e3,o="tinycloud.kv/list",c="tinycloud.kv/metadata",s="tinycloud.kv/get",i="tinycloud.space/info",r=e=>""===e||e.endsWith("/")||e.endsWith("/*")||e.endsWith("/**"),d=e=>e.endsWith("/**")?e.slice(0,-2):e.endsWith("/*")?e.slice(0,-1):"/"===e?"":e,p=e=>r(e)?`${d(e)}.tinycloud-space-probe`:e;async function u(e,t){try{const{spaceId:a}=e,o=await e.fetch(`${e.host}/invoke`,{method:"POST",headers:{...e.sign([{spaceId:a,service:t.service,path:t.path,action:t.action}]),...t.headers},body:t.body,signal:AbortSignal.timeout(n)});return o.ok?(o.body instanceof ReadableStream&&await o.body.cancel().catch(()=>{}),"hosted"):401===o.status||403===o.status?"refused":404===o.status?/space not found/i.test(await o.text())?"not-hosted":"hosted":"unknown"}catch{return"unknown"}}async function h(e){const t=function({spaceId:e,operations:t,covers:a}){const n=t.filter(t=>!t.caveats?.length&&a(t,{spaceId:e,service:t.service,path:t.path,action:t.action})),u=(t,o)=>n.filter(n=>a(n,{spaceId:e,service:t,path:n.path,action:o}));return[...u("kv",o).map(e=>({service:"kv",path:r(e.path)?d(e.path):e.path,action:o,headers:{"x-tinycloud-limit":"1"}})),...u("kv",c).map(e=>({service:"kv",path:p(e.path),action:c})),...u("space",i).map(()=>({service:"space",path:"",action:i,body:"{}"})),...u("kv",s).map(e=>({service:"kv",path:p(e.path),action:s}))].find(t=>n.some(n=>a(n,{spaceId:e,service:t.service,path:t.path,action:t.action})))}(e);if(!t)return"unknown";const h=`${e.host} ${e.spaceId.replace(/^(tinycloud:pkh:eip155:\d+:)(0x[0-9a-fA-F]{40})/,(e,t,a)=>t+a.toLowerCase())}`;if(a.get(e.scope)?.has(h))return"hosted";let l=await u(e,t);if("refused"===l){try{await e.activate(AbortSignal.timeout(n))}catch{return"unknown"}l=await u(e,t)}return"hosted"===l&&a.set(e.scope,(a.get(e.scope)??new Set).add(h)),"refused"===l?"unknown":l}function l(e){const t=e.error?.trim();return t?`${e.status} - ${t}`:`${e.status}`}async function f({handler:e,context:t,guard:a,host:n,onHosted:o,activate:c}){if(await a(),!await e.confirmSpaceCreation(t))return;try{const e=await n();if(!e.success)throw Object.assign(new Error(`Failed to create space ${t.spaceId}: ${l(e)}`),{cause:e})}catch(a){throw e.onSpaceCreationFailed?.(t,a instanceof Error?a:new Error(String(a))),a}o(),await new Promise(e=>setTimeout(e,100));const s=await c();if(!s.success){const a=Object.assign(new Error(`Failed to activate session after creating space: ${l(s)}`),{cause:s});throw e.onSpaceCreationFailed?.(t,a),a}e.onSpaceCreated?.(t)}module.exports=t})();
@@ -0,0 +1 @@
1
+ var t=new WeakMap,e="tinycloud.kv/list",a="tinycloud.kv/metadata",n="tinycloud.kv/get",s="tinycloud.space/info",c=t=>""===t||t.endsWith("/")||t.endsWith("/*")||t.endsWith("/**"),i=t=>t.endsWith("/**")?t.slice(0,-2):t.endsWith("/*")?t.slice(0,-1):"/"===t?"":t,o=t=>c(t)?`${i(t)}.tinycloud-space-probe`:t;async function r(t,e){try{const{spaceId:a}=t,n=await t.fetch(`${t.host}/invoke`,{method:"POST",headers:{...t.sign([{spaceId:a,service:e.service,path:e.path,action:e.action}]),...e.headers},body:e.body,signal:AbortSignal.timeout(5e3)});return n.ok?(n.body instanceof ReadableStream&&await n.body.cancel().catch(()=>{}),"hosted"):401===n.status||403===n.status?"refused":404===n.status?/space not found/i.test(await n.text())?"not-hosted":"hosted":"unknown"}catch{return"unknown"}}async function d(d){const p=function({spaceId:t,operations:r,covers:d}){const p=r.filter(e=>!e.caveats?.length&&d(e,{spaceId:t,service:e.service,path:e.path,action:e.action})),h=(e,a)=>p.filter(n=>d(n,{spaceId:t,service:e,path:n.path,action:a}));return[...h("kv",e).map(t=>({service:"kv",path:c(t.path)?i(t.path):t.path,action:e,headers:{"x-tinycloud-limit":"1"}})),...h("kv",a).map(t=>({service:"kv",path:o(t.path),action:a})),...h("space",s).map(()=>({service:"space",path:"",action:s,body:"{}"})),...h("kv",n).map(t=>({service:"kv",path:o(t.path),action:n}))].find(e=>p.some(a=>d(a,{spaceId:t,service:e.service,path:e.path,action:e.action})))}(d);if(!p)return"unknown";const h=`${d.host} ${d.spaceId.replace(/^(tinycloud:pkh:eip155:\d+:)(0x[0-9a-fA-F]{40})/,(t,e,a)=>e+a.toLowerCase())}`;if(t.get(d.scope)?.has(h))return"hosted";let u=await r(d,p);if("refused"===u){try{await d.activate(AbortSignal.timeout(5e3))}catch{return"unknown"}u=await r(d,p)}return"hosted"===u&&t.set(d.scope,(t.get(d.scope)??new Set).add(h)),"refused"===u?"unknown":u}function p(t){const e=t.error?.trim();return e?`${t.status} - ${e}`:`${t.status}`}async function h({handler:t,context:e,guard:a,host:n,onHosted:s,activate:c}){if(await a(),!await t.confirmSpaceCreation(e))return;try{const t=await n();if(!t.success)throw Object.assign(new Error(`Failed to create space ${e.spaceId}: ${p(t)}`),{cause:t})}catch(a){throw t.onSpaceCreationFailed?.(e,a instanceof Error?a:new Error(String(a))),a}s(),await new Promise(t=>setTimeout(t,100));const i=await c();if(!i.success){const a=Object.assign(new Error(`Failed to activate session after creating space: ${p(i)}`),{cause:i});throw t.onSpaceCreationFailed?.(e,a),a}t.onSpaceCreated?.(e)}export{d as askSpaceHosting,h as createPrimarySpace};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinycloud/web-sdk",
3
- "version": "3.11.0",
3
+ "version": "3.12.0-beta.1",
4
4
  "description": "A set of tools and utilities to help you build your app with TinyCloud.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -66,7 +66,7 @@
66
66
  "@multiformats/multiaddr": "^13.0.1",
67
67
  "@multiformats/multiaddr-to-uri": "^12.0.0",
68
68
  "@noble/curves": "^1.9.7",
69
- "@tinycloud/node-sdk": "3.11.0",
69
+ "@tinycloud/node-sdk": "3.12.0-beta.1",
70
70
  "@tinycloud/replica": "0.4.4",
71
71
  "@tinycloud/sdk-core": "3.11.0",
72
72
  "@tinycloud/share-envelope": "1.5.0",