@tinycloud/web-sdk 3.12.0-beta.1 → 3.12.0-beta.2

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.
@@ -389,7 +389,22 @@ export declare class TinyCloudWeb {
389
389
  restoreSession(address?: string): Promise<SessionRestoreResult>;
390
390
  /** One node read for the restored session, held to {@link spaceHostingCapMs}; past it, or on any failure, the answer stays unknown. */
391
391
  private probeSpaceHosting;
392
+ private spaceHostingInFlight?;
393
+ /**
394
+ * Host a restored session's primary space only when the node reports it
395
+ * missing. Reuses that session and its existing creation confirmation.
396
+ * Call from a user gesture so the approval popup can open.
397
+ */
392
398
  private restoredSessionNotHosted;
399
+ /**
400
+ * Ensure the primary space is hosted, asking for approval only when needed.
401
+ * Resolves `"hosted"` when the node reports hosting or the space is created;
402
+ * resolves `"not-hosted"` when creation is unavailable or declined; and
403
+ * resolves `"unknown"` when the node has no hosting answer.
404
+ * Rejects with `Error("Space hosting was cancelled by sign-out.")` if sign-out
405
+ * happens during the hosting run. Call from a user gesture so the approval popup can open.
406
+ */
407
+ ensureSpaceHosted(): Promise<SpaceHosting>;
393
408
  clearPersistedSession(address?: string): Promise<void>;
394
409
  private configuredManifestPermissions;
395
410
  /**
@@ -1 +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})();
1
+ (()=>{"use strict";var e={d:(t,a)=>{for(var s in a)e.o(a,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:a[s]})},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:()=>u,createPrimarySpace:()=>w});var a=new WeakMap,s=5e3,o="tinycloud.kv/list",n="tinycloud.kv/metadata",r="tinycloud.kv/get",i="tinycloud.space/info",c=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=>c(e)?`${d(e)}.tinycloud-space-probe`:e;async function h(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(s)});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 u(e){const t=function({spaceId:e,operations:t,covers:a}){const s=t.filter(t=>!t.caveats?.length&&a(t,{spaceId:e,service:t.service,path:t.path,action:t.action})),h=(t,o)=>s.filter(s=>a(s,{spaceId:e,service:t,path:s.path,action:o}));return[...h("kv",o).map(e=>({service:"kv",path:c(e.path)?d(e.path):e.path,action:o,headers:{"x-tinycloud-limit":"1"}})),...h("kv",n).map(e=>({service:"kv",path:p(e.path),action:n})),...h("space",i).map(()=>({service:"space",path:"",action:i,body:"{}"})),...h("kv",r).map(e=>({service:"kv",path:p(e.path),action:r}))].find(t=>s.some(s=>a(s,{spaceId:e,service:t.service,path:t.path,action:t.action})))}(e);if(!t)return"unknown";const u=`${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(u))return"hosted";let l=await h(e,t);if("refused"===l){try{await e.activate(AbortSignal.timeout(s))}catch{return"unknown"}l=await h(e,t)}return"hosted"===l&&a.set(e.scope,(a.get(e.scope)??new Set).add(u)),"refused"===l?"unknown":l}function l(e){const t=e.error?.trim();return t?`${e.status} - ${t}`:`${e.status}`}async function w({handler:e,session:t,context:a,currentSession:s,signerAddress:o,resolveHost:n,domain:r,hostName:i,guard:c,host:d,onHosted:p,activate:h,signal:u}){const w=()=>{if(u?.throwIfAborted(),t&&s?.()!==t)throw new Error("Space hosting session changed")};if(w(),t&&o&&(await o()).toLowerCase()!==t.address.toLowerCase())return;w();const f=a??(t&&{address:t.address,chainId:t.chainId,spaceId:t.spaceId,host:await(n?.())??i??""});if(!f)throw new Error("Space hosting requires a session context");w(),await c(f),w();const v=await e.confirmSpaceCreation(f);if(w(),!v)return;try{const e=await d(f,w,e=>({address:f.address,chainId:f.chainId,domain:r??"",issuedAt:(new Date).toISOString(),spaceId:f.spaceId,peerId:e}));if(!e.success)throw Object.assign(new Error(`Failed to create space ${f.spaceId}: ${l(e)}`),{cause:e})}catch(t){throw e.onSpaceCreationFailed?.(f,t instanceof Error?t:new Error(String(t))),t}w(),p(f),await new Promise(e=>setTimeout(e,100)),w();const y=await h(f);if(w(),!y.success){const t=Object.assign(new Error(`Failed to activate session after creating space: ${l(y)}`),{cause:y});throw e.onSpaceCreationFailed?.(f,t),t}e.onSpaceCreated?.(f)}module.exports=t})();
@@ -1 +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};
1
+ var e=new WeakMap,t="tinycloud.kv/list",a="tinycloud.kv/metadata",s="tinycloud.kv/get",n="tinycloud.space/info",o=e=>""===e||e.endsWith("/")||e.endsWith("/*")||e.endsWith("/**"),i=e=>e.endsWith("/**")?e.slice(0,-2):e.endsWith("/*")?e.slice(0,-1):"/"===e?"":e,c=e=>o(e)?`${i(e)}.tinycloud-space-probe`:e;async function r(e,t){try{const{spaceId:a}=e,s=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(5e3)});return s.ok?(s.body instanceof ReadableStream&&await s.body.cancel().catch(()=>{}),"hosted"):401===s.status||403===s.status?"refused":404===s.status?/space not found/i.test(await s.text())?"not-hosted":"hosted":"unknown"}catch{return"unknown"}}async function d(d){const h=function({spaceId:e,operations:r,covers:d}){const h=r.filter(t=>!t.caveats?.length&&d(t,{spaceId:e,service:t.service,path:t.path,action:t.action})),p=(t,a)=>h.filter(s=>d(s,{spaceId:e,service:t,path:s.path,action:a}));return[...p("kv",t).map(e=>({service:"kv",path:o(e.path)?i(e.path):e.path,action:t,headers:{"x-tinycloud-limit":"1"}})),...p("kv",a).map(e=>({service:"kv",path:c(e.path),action:a})),...p("space",n).map(()=>({service:"space",path:"",action:n,body:"{}"})),...p("kv",s).map(e=>({service:"kv",path:c(e.path),action:s}))].find(t=>h.some(a=>d(a,{spaceId:e,service:t.service,path:t.path,action:t.action})))}(d);if(!h)return"unknown";const p=`${d.host} ${d.spaceId.replace(/^(tinycloud:pkh:eip155:\d+:)(0x[0-9a-fA-F]{40})/,(e,t,a)=>t+a.toLowerCase())}`;if(e.get(d.scope)?.has(p))return"hosted";let u=await r(d,h);if("refused"===u){try{await d.activate(AbortSignal.timeout(5e3))}catch{return"unknown"}u=await r(d,h)}return"hosted"===u&&e.set(d.scope,(e.get(d.scope)??new Set).add(p)),"refused"===u?"unknown":u}function h(e){const t=e.error?.trim();return t?`${e.status} - ${t}`:`${e.status}`}async function p({handler:e,session:t,context:a,currentSession:s,signerAddress:n,resolveHost:o,domain:i,hostName:c,guard:r,host:d,onHosted:p,activate:u,signal:w}){const f=()=>{if(w?.throwIfAborted(),t&&s?.()!==t)throw new Error("Space hosting session changed")};if(f(),t&&n&&(await n()).toLowerCase()!==t.address.toLowerCase())return;f();const l=a??(t&&{address:t.address,chainId:t.chainId,spaceId:t.spaceId,host:await(o?.())??c??""});if(!l)throw new Error("Space hosting requires a session context");f(),await r(l),f();const v=await e.confirmSpaceCreation(l);if(f(),!v)return;try{const e=await d(l,f,e=>({address:l.address,chainId:l.chainId,domain:i??"",issuedAt:(new Date).toISOString(),spaceId:l.spaceId,peerId:e}));if(!e.success)throw Object.assign(new Error(`Failed to create space ${l.spaceId}: ${h(e)}`),{cause:e})}catch(t){throw e.onSpaceCreationFailed?.(l,t instanceof Error?t:new Error(String(t))),t}f(),p(l),await new Promise(e=>setTimeout(e,100)),f();const g=await u(l);if(f(),!g.success){const t=Object.assign(new Error(`Failed to activate session after creating space: ${h(g)}`),{cause:g});throw e.onSpaceCreationFailed?.(l,t),t}e.onSpaceCreated?.(l)}export{d as askSpaceHosting,p as createPrimarySpace};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinycloud/web-sdk",
3
- "version": "3.12.0-beta.1",
3
+ "version": "3.12.0-beta.2",
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.12.0-beta.1",
69
+ "@tinycloud/node-sdk": "3.12.0-beta.2",
70
70
  "@tinycloud/replica": "0.4.4",
71
71
  "@tinycloud/sdk-core": "3.11.0",
72
72
  "@tinycloud/share-envelope": "1.5.0",