@graffiti-garden/wrapper-data-guard 0.2.6 → 0.2.8

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.
@@ -1,2 +1,2 @@
1
- import"./chunk-ZI3DQDJT.js";var S=class{};var te={type:"object",properties:{value:{type:"object"},channels:{type:"array",items:{type:"string"}},allowed:{type:"array",items:{type:"string"},nullable:!0},url:{type:"string"},actor:{type:"string"}},additionalProperties:!1,required:["value","channels","actor","url"]},be={...te,required:["value","channels"]};var I=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorForbidden",Object.setPrototypeOf(this,e.prototype)}},R=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorNotFound",Object.setPrototypeOf(this,e.prototype)}},T=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorInvalidSchema",Object.setPrototypeOf(this,e.prototype)}},N=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorSchemaMismatch",Object.setPrototypeOf(this,e.prototype)}},L=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorTooLarge",Object.setPrototypeOf(this,e.prototype)}},P=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorNotAcceptable",Object.setPrototypeOf(this,e.prototype)}},D=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorCursorExpired",Object.setPrototypeOf(this,e.prototype)}};var g=class extends Error{code;constructor(e,t){super(t),this.name="PenpalError",this.code=e}},re=e=>({name:e.name,message:e.message,stack:e.stack,penpalCode:e instanceof g?e.code:void 0}),se=({name:e,message:t,stack:r,penpalCode:s})=>{let o=s?new g(s,t):new Error(t);return o.name=e,o.stack=r,o},oe=Symbol("Reply"),ne=class{value;transferables;#t=oe;constructor(e,t){this.value=e,this.transferables=t?.transferables}},A="penpal",Y=e=>typeof e=="object"&&e!==null,ie=e=>typeof e=="function",ae=e=>Y(e)&&e.namespace==="penpal",U=e=>e.type==="SYN",K=e=>e.type==="ACK1",k=e=>e.type==="ACK2",ce=e=>e.type==="CALL",de=e=>e.type==="REPLY",le=e=>e.type==="DESTROY",ue=(e,t)=>{let r=e.reduce((s,o)=>{if(!(!Y(s)||!Object.hasOwn(s,o)))return s[o]},t);return ie(r)?r:void 0},w=e=>e.join("."),F=(e,t,r)=>({namespace:A,channel:e,type:"REPLY",callId:t,isError:!0,...r instanceof Error?{value:re(r),isSerializedErrorInstance:!0}:{value:r}}),he=(e,t,r,s)=>{let o=!1,d=async h=>{if(o||!ce(h))return;s?.(`Received ${w(h.methodPath)}() call`,h);let{methodPath:c,args:l,id:f}=h,a,n;try{let i=ue(c,t);if(!i)throw new g("METHOD_NOT_FOUND",`Method \`${w(c)}\` is not found.`);let m=await i(...l);m instanceof ne&&(n=m.transferables,m=await m.value),a={namespace:A,channel:r,type:"REPLY",callId:f,value:m}}catch(i){a=F(r,f,i)}if(!o)try{s?.(`Sending ${w(c)}() reply`,a),e.sendMessage(a,n)}catch(i){throw i.name==="DataCloneError"&&(a=F(r,f,i),s?.(`Sending ${w(c)}() reply`,a),e.sendMessage(a)),i}},p=h=>{d(h).catch(c=>{console.error(c)})};return e.addMessageHandler(p),()=>{o=!0,e.removeMessageHandler(p)}},V=crypto.randomUUID?.bind(crypto)??(()=>new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-")),fe=Symbol("CallOptions"),H=class{transferables;timeout;#t=fe;constructor(e){this.transferables=e?.transferables,this.timeout=e?.timeout}},pe=new Set(["apply","call","bind"]),J=(e,t,r=[])=>new Proxy(r.length?()=>{}:Object.create(null),{get(s,o){if(o!=="then")return r.length&&pe.has(o)?Reflect.get(s,o):J(e,t,[...r,o])},apply(s,o,d){return e(r,d)}}),z=e=>new g("CONNECTION_DESTROYED",`Method call ${w(e)}() failed due to destroyed connection`),ge=(e,t,r)=>{let s=!1,o=new Map,d=c=>{if(!de(c))return;let{callId:l,value:f,isError:a,isSerializedErrorInstance:n}=c,i=o.get(l);i&&(o.delete(l),clearTimeout(i.timeoutId),r?.(`Received ${w(i.methodPath)}() reply`,c),a?i.reject(n?se(f):f):i.resolve(f))};return e.addMessageHandler(d),{remoteProxy:J((c,l)=>{if(s)throw z(c);let f=V(),a=l[l.length-1],n=a instanceof H,{timeout:i,transferables:m}=n?a:{},y=n?l.slice(0,-1):l;return new Promise((x,E)=>{let v=i!==void 0?globalThis.setTimeout(()=>{o.delete(f),E(new g("METHOD_CALL_TIMEOUT",`Method call ${w(c)}() timed out after ${i}ms`))},i):void 0;o.set(f,{methodPath:c,resolve:x,reject:E,timeoutId:v});try{let M={namespace:A,channel:t,type:"CALL",id:f,methodPath:c,args:y};r?.(`Sending ${w(c)}() call`,M),e.sendMessage(M,m)}catch(M){o.delete(f),clearTimeout(v),E(new g("TRANSMISSION_FAILED",M.message))}})},r),destroy:()=>{s=!0,e.removeMessageHandler(d);for(let{methodPath:c,reject:l,timeoutId:f}of o.values())clearTimeout(f),l(z(c));o.clear()}}},me=({messenger:e,methods:t,timeout:r,channel:s,log:o})=>{let d=V(),p,h=[],c=!1,l=!1,{promise:f,resolve:a,reject:n}=Promise.withResolvers(),i=r!==void 0?setTimeout(()=>{y(new g("CONNECTION_TIMEOUT",`Connection timed out after ${r}ms`))},r):void 0,m=()=>{clearTimeout(i);for(let u of h.splice(0))u()},y=u=>{l||(l=!0,m(),n(u))},x=()=>{y(new g("CONNECTION_DESTROYED","Connection destroyed"))},E=()=>{if(l||c)return;h.push(he(e,t,s,o));let{remoteProxy:u,destroy:_}=ge(e,s,o);h.push(_),clearTimeout(i),c=!0,a(u)},v=u=>{if(l)return!1;o?.(`Sending handshake ${u.type}`,u);try{return e.sendMessage(u),!0}catch(_){return y(new g("TRANSMISSION_FAILED",_.message)),!1}},M=()=>v({namespace:A,type:"SYN",channel:s,participantId:d}),Q=u=>{o?.("Received handshake SYN",u),u.participantId!==p&&(p=u.participantId,M()&&d>p&&v({namespace:"penpal",channel:s,type:"ACK1"}))},Z=u=>{o?.("Received handshake ACK1",u),v({namespace:"penpal",channel:s,type:"ACK2"})&&E()},ee=u=>{o?.("Received handshake ACK2",u),E()},j=u=>{l||(U(u)?Q(u):K(u)?Z(u):k(u)&&ee(u))};return e.addMessageHandler(j),h.push(()=>e.removeMessageHandler(j)),M(),{promise:f,destroy:x}},ye=e=>{let t=!1,r;return(...s)=>(t||(t=!0,r=e(...s)),r)},$=new WeakSet,W=()=>new g("CONNECTION_DESTROYED","Connection destroyed"),q=({messenger:e,methods:t={},timeout:r,channel:s,log:o})=>{if(!e)throw new g("INVALID_ARGUMENT","messenger must be defined");if($.has(e))throw new g("INVALID_ARGUMENT","A messenger can only be used for a single connection");$.add(e);let d=Promise.withResolvers(),p=!1,h,c=()=>{let a={namespace:A,channel:s,type:"DESTROY"};try{e.sendMessage(a)}catch{}},l=ye((a,n)=>{p=!0,n&&c(),e.destroy(),h?.(),d.reject(a),o?.("Connection destroyed")}),f=a=>ae(a)&&a.channel===s;return(async()=>{try{e.initialize({log:o,validateReceivedMessage:f}),e.addMessageHandler(i=>{le(i)&&l(W(),!1)});let a=me({messenger:e,methods:t,timeout:r,channel:s,log:o});h=a.destroy;let n=await a.promise;if(p){a.destroy();return}d.resolve(n)}catch(a){l(a,!0)}})(),{promise:d.promise,destroy:()=>{l(W(),!0)}}},B=class{#t;#s;#i;#a;#o;#r=new Set;#e;constructor({remoteWindow:e,allowedOrigins:t}){if(!e)throw new g("INVALID_ARGUMENT","remoteWindow must be defined");this.#t=e,this.#s=t?.length?t:[window.origin]}initialize=({log:e,validateReceivedMessage:t})=>{this.#i=e,this.#a=t,window.addEventListener("message",this.#l)};sendMessage=(e,t)=>{if(U(e)){let r=this.#c(e);this.#t.postMessage(e,{targetOrigin:r,...t===void 0?{}:{transfer:t}});return}if(K(e)){let r=this.#c(e);this.#t.postMessage(e,{targetOrigin:r,...t===void 0?{}:{transfer:t}});return}if(k(e)){let{port1:r,port2:s}=new MessageChannel;this.#d(r);let o=[s,...t||[]],d=this.#c(e);try{this.#t.postMessage(e,{targetOrigin:d,transfer:o})}catch(p){throw this.#n(),s.close(),p}return}if(this.#e){this.#e.postMessage(e,{...t===void 0?{}:{transfer:t}});return}throw new g("TRANSMISSION_FAILED","Cannot send message because the MessagePort is not connected")};addMessageHandler=e=>{this.#r.add(e)};removeMessageHandler=e=>{this.#r.delete(e)};destroy=()=>{window.removeEventListener("message",this.#l),this.#n(),this.#r.clear()};#h=e=>this.#s.some(t=>t instanceof RegExp?new RegExp(t).test(e):t===e||t==="*");#c=e=>{if(U(e))return"*";if(!this.#o)throw new g("TRANSMISSION_FAILED","Cannot send message because the remote origin is not established");return this.#o==="null"&&this.#s.includes("*")?"*":this.#o};#n=()=>{this.#e?.removeEventListener("message",this.#u),this.#e?.close(),this.#e=void 0};#d=e=>{this.#n(),this.#e=e,this.#e.addEventListener("message",this.#u),this.#e.start()};#l=({source:e,origin:t,ports:r,data:s})=>{if(e===this.#t&&this.#a?.(s)){if(!this.#h(t)){this.#i?.(`Received a message from origin \`${t}\` which did not match allowed origins \`[${this.#s.join(", ")}]\``);return}if(U(s)&&(this.#n(),this.#o=t),k(s)){let o=r[0];if(!o){this.#i?.("Ignoring ACK2 because it did not include a MessagePort");return}this.#d(o)}for(let o of this.#r)o(s)}};#u=({data:e})=>{if(this.#a?.(e))for(let t of this.#r)t(e)}};var we=["post","get","delete","deleteMedia","login","logout","actorToHandle","handleToActor"],Me=[D,I,T,P,R,N,L],C,G=class extends S{sessionEvents=new EventTarget;connection;remote_;remoteClient;sessions=new Map;initialized=!1;destroyed=!1;constructor(t){if(super(),C){let r=C;return window.setTimeout(()=>r.replayInitialization(),0),r}this.connection=q({messenger:new B({remoteWindow:t.remoteWindow,allowedOrigins:t.allowedOrigins??["*"]}),channel:t.channel,timeout:t.timeout,methods:{sessionEvent:(r,s)=>{if(r==="login"){let o=s;o.error||this.sessions.set(o.session.actor,o.session)}else if(r==="logout"){let o=s;o.error||this.sessions.delete(o.actor)}else r==="initialized"&&(this.initialized=!0,s=void 0);this.sessionEvents.dispatchEvent(new CustomEvent(r,{detail:s}))}}}),this.remote_=this.connection.promise.then(r=>{let s=Ee(r);return this.remoteClient=s,s}),window.setTimeout(()=>{this.remote_.then(r=>r.initialize()).catch(()=>{})},0);for(let r of we)this[r]=async(...s)=>{let d=(await this.remote())[r];return d(...O(s))};C=this}destroy(){this.destroyed||(this.destroyed=!0,C===this&&(C=void 0),this.remoteClient?.destroy().catch(()=>{}),this.connection.destroy())}replayInitialization(){if(!this.destroyed){for(let t of this.sessions.values())this.sessionEvents.dispatchEvent(new CustomEvent("login",{detail:{session:t}}));this.initialized&&this.sessionEvents.dispatchEvent(new CustomEvent("initialized",{detail:void 0}))}}getMedia=async(...t)=>{let r=await(await this.remote()).getMedia(...O(t));return{...r,data:new Blob([r.data.buffer],{type:r.data.type})}};postMedia=async(t,r)=>{let s=await t.data.arrayBuffer();return(await this.remote()).postMedia({...O(t),data:{buffer:s,type:t.data.type}},O(r),new H({transferables:[s]}))};remoteStream(t){let r=`graffiti-rpc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`,s=this.remote_;return(async function*(){let o=await s;try{for(await t(o,r);;){let d=await o.streamNext(r);if(d.done)return d.value;yield d.value}}finally{await o.streamReturn(r)}})()}discover=(...t)=>this.remoteStream((r,s)=>r.discover(s,...O(t)));continueDiscover=(...t)=>this.remoteStream((r,s)=>r.continueDiscover(s,...O(t)));remote(){if(this.destroyed)throw new Error("Graffiti RPC client has been destroyed.");return this.remote_}};function O(e){return JSON.parse(JSON.stringify(e))}function Ee(e){return new Proxy(e,{get(t,r){let s=Reflect.get(t,r);return typeof s=="function"?(...o)=>s(...o).catch(ve):s}})}function ve(e){if(e instanceof Error){let t=Me.find(({name:r})=>r===e.name);t&&Object.setPrototypeOf(e,t.prototype)}throw e}var b,Se=1e4,X=class extends S{sessionEvents;hostUrl;iframe;rpc;onMessage;connectionTimeout;destroyed=!1;constructor(t={}){if(super(),b)return b;let r=new URL(t.hostUrl?.toString()??"https://guard.graffiti.garden/",document.baseURI),s=document.createElement("iframe");s.title="Graffiti Guard",s.allow="storage-access",s.sandbox.add("allow-scripts","allow-same-origin","allow-storage-access-by-user-activation","allow-downloads","allow-forms","allow-popups","allow-top-navigation-by-user-activation"),s.src=r.href,s.setAttribute("aria-hidden","true"),Object.assign(s.style,{background:"transparent",border:"0",display:"none",height:CSS.supports("height","100svh")?"100svh":"100vh",inset:"0",position:"fixed",width:"100%",zIndex:"2147483647"});let o=!1,d=!1;s.addEventListener("load",()=>{s.contentWindow?.postMessage({type:"graffiti-guard:connect",pageUrl:window.location.href},r.origin)});let p=()=>{o||d||(d=!0,window.alert(`This app could not connect to its data service at ${r.origin}. The service may be offline, or your browser may be blocking its security certificate. Open that address directly, then reload this page.`))};s.addEventListener("error",p),document.body.append(s);let h=s.contentWindow;if(!h)throw s.remove(),new Error("Graffiti Guard iframe did not create a content window.");let c=new G({remoteWindow:h,allowedOrigins:[r.origin],channel:t.channel,timeout:t.timeout}),l=window.setTimeout(p,t.timeout??Se),f=()=>{o=!0,window.clearTimeout(l)},a=n=>{if(!(n.source!==h||n.origin!==r.origin||!n.data||typeof n.data!="object")&&(f(),n.data.type!=="graffiti-guard:connected"))if(n.data.type==="graffiti-guard:set-visible"&&typeof n.data.visible=="boolean")s.style.display=n.data.visible?"block":"none",s.setAttribute("aria-hidden",String(!n.data.visible)),n.data.visible&&(s.focus(),h.postMessage({type:"graffiti-guard:shown"},r.origin));else if(n.data.type==="graffiti-guard:open-storage-setup"&&typeof n.data.url=="string")try{let i=new URL(n.data.url),m=new URLSearchParams(i.hash.slice(1));if(i.origin!==r.origin||m.get("guardStorageSetup")!=="1"&&i.searchParams.get("guardStorageSetup")!=="1")return;window.location.assign(i)}catch{}else n.data.type==="graffiti-guard:open-audit"&&typeof n.data.actor=="string"&&Array.isArray(n.data.source)&&window.location.assign(this.auditUrl(n.data))};return window.addEventListener("message",a),this.hostUrl=r,this.iframe=s,this.rpc=c,this.sessionEvents=c.sessionEvents,this.onMessage=a,this.connectionTimeout=l,b=new Proxy(this,{get(n,i,m){if(Reflect.has(n,i))return Reflect.get(n,i,m);let y=Reflect.get(c,i,c);return typeof y=="function"?y.bind(c):y}}),b}login=t=>{let r=new URL(this.hostUrl),s=new URLSearchParams({guardLogin:"1",redirectUrl:window.location.href});return t&&s.set("suggestedActor",t),r.hash=s.toString(),window.location.assign(r.href),Promise.resolve()};auditUrl(t){let r=new URL(this.hostUrl),s=new URLSearchParams({redirectUrl:window.location.href,source:JSON.stringify(t?.source??[])});return t?.actor&&s.set("actor",t.actor),r.hash=s.toString(),r.href}destroy(){this.destroyed||(this.destroyed=!0,window.clearTimeout(this.connectionTimeout),window.removeEventListener("message",this.onMessage),this.rpc.destroy(),this.iframe.remove(),b===this&&(b=void 0))}};export{X as GraffitiGuarded};
1
+ import"./chunk-ZI3DQDJT.js";var S=class{};var re={type:"object",properties:{value:{type:"object"},channels:{type:"array",items:{type:"string"}},allowed:{type:"array",items:{type:"string"},nullable:!0},url:{type:"string"},actor:{type:"string"}},additionalProperties:!1,required:["value","channels","actor","url"]},Te={...re,required:["value","channels"]};var R=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorForbidden",Object.setPrototypeOf(this,e.prototype)}},N=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorNotFound",Object.setPrototypeOf(this,e.prototype)}},I=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorInvalidSchema",Object.setPrototypeOf(this,e.prototype)}},L=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorSchemaMismatch",Object.setPrototypeOf(this,e.prototype)}},U=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorTooLarge",Object.setPrototypeOf(this,e.prototype)}},D=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorNotAcceptable",Object.setPrototypeOf(this,e.prototype)}},P=class e extends Error{constructor(t){super(t),this.name="GraffitiErrorCursorExpired",Object.setPrototypeOf(this,e.prototype)}};var m=class extends Error{code;constructor(e,t){super(t),this.name="PenpalError",this.code=e}},se=e=>({name:e.name,message:e.message,stack:e.stack,penpalCode:e instanceof m?e.code:void 0}),ne=({name:e,message:t,stack:r,penpalCode:s})=>{let n=s?new m(s,t):new Error(t);return n.name=e,n.stack=r,n},ie=Symbol("Reply"),oe=class{value;transferables;#t=ie;constructor(e,t){this.value=e,this.transferables=t?.transferables}},A="penpal",Y=e=>typeof e=="object"&&e!==null,ae=e=>typeof e=="function",ce=e=>Y(e)&&e.namespace==="penpal",k=e=>e.type==="SYN",K=e=>e.type==="ACK1",_=e=>e.type==="ACK2",de=e=>e.type==="CALL",le=e=>e.type==="REPLY",ue=e=>e.type==="DESTROY",he=(e,t)=>{let r=e.reduce((s,n)=>{if(!(!Y(s)||!Object.hasOwn(s,n)))return s[n]},t);return ae(r)?r:void 0},v=e=>e.join("."),j=(e,t,r)=>({namespace:A,channel:e,type:"REPLY",callId:t,isError:!0,...r instanceof Error?{value:se(r),isSerializedErrorInstance:!0}:{value:r}}),fe=(e,t,r,s)=>{let n=!1,i=async f=>{if(n||!de(f))return;s?.(`Received ${v(f.methodPath)}() call`,f);let{methodPath:c,args:d,id:u}=f,o,p;try{let l=he(c,t);if(!l)throw new m("METHOD_NOT_FOUND",`Method \`${v(c)}\` is not found.`);let a=await l(...d);a instanceof oe&&(p=a.transferables,a=await a.value),o={namespace:A,channel:r,type:"REPLY",callId:u,value:a}}catch(l){o=j(r,u,l)}if(!n)try{s?.(`Sending ${v(c)}() reply`,o),e.sendMessage(o,p)}catch(l){throw l.name==="DataCloneError"&&(o=j(r,u,l),s?.(`Sending ${v(c)}() reply`,o),e.sendMessage(o)),l}},g=f=>{i(f).catch(c=>{console.error(c)})};return e.addMessageHandler(g),()=>{n=!0,e.removeMessageHandler(g)}},V=crypto.randomUUID?.bind(crypto)??(()=>new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-")),pe=Symbol("CallOptions"),H=class{transferables;timeout;#t=pe;constructor(e){this.transferables=e?.transferables,this.timeout=e?.timeout}},ge=new Set(["apply","call","bind"]),B=(e,t,r=[])=>new Proxy(r.length?()=>{}:Object.create(null),{get(s,n){if(n!=="then")return r.length&&ge.has(n)?Reflect.get(s,n):B(e,t,[...r,n])},apply(s,n,i){return e(r,i)}}),z=e=>new m("CONNECTION_DESTROYED",`Method call ${v(e)}() failed due to destroyed connection`),me=(e,t,r)=>{let s=!1,n=new Map,i=c=>{if(!le(c))return;let{callId:d,value:u,isError:o,isSerializedErrorInstance:p}=c,l=n.get(d);l&&(n.delete(d),clearTimeout(l.timeoutId),r?.(`Received ${v(l.methodPath)}() reply`,c),o?l.reject(p?ne(u):u):l.resolve(u))};return e.addMessageHandler(i),{remoteProxy:B((c,d)=>{if(s)throw z(c);let u=V(),o=d[d.length-1],p=o instanceof H,{timeout:l,transferables:a}=p?o:{},y=p?d.slice(0,-1):d;return new Promise((M,w)=>{let b=l!==void 0?globalThis.setTimeout(()=>{n.delete(u),w(new m("METHOD_CALL_TIMEOUT",`Method call ${v(c)}() timed out after ${l}ms`))},l):void 0;n.set(u,{methodPath:c,resolve:M,reject:w,timeoutId:b});try{let E={namespace:A,channel:t,type:"CALL",id:u,methodPath:c,args:y};r?.(`Sending ${v(c)}() call`,E),e.sendMessage(E,a)}catch(E){n.delete(u),clearTimeout(b),w(new m("TRANSMISSION_FAILED",E.message))}})},r),destroy:()=>{s=!0,e.removeMessageHandler(i);for(let{methodPath:c,reject:d,timeoutId:u}of n.values())clearTimeout(u),d(z(c));n.clear()}}},ye=({messenger:e,methods:t,timeout:r,channel:s,log:n})=>{let i=V(),g,f=[],c=!1,d=!1,{promise:u,resolve:o,reject:p}=Promise.withResolvers(),l=r!==void 0?setTimeout(()=>{y(new m("CONNECTION_TIMEOUT",`Connection timed out after ${r}ms`))},r):void 0,a=()=>{clearTimeout(l);for(let h of f.splice(0))h()},y=h=>{d||(d=!0,a(),p(h))},M=()=>{y(new m("CONNECTION_DESTROYED","Connection destroyed"))},w=()=>{if(d||c)return;f.push(fe(e,t,s,n));let{remoteProxy:h,destroy:x}=me(e,s,n);f.push(x),clearTimeout(l),c=!0,o(h)},b=h=>{if(d)return!1;n?.(`Sending handshake ${h.type}`,h);try{return e.sendMessage(h),!0}catch(x){return y(new m("TRANSMISSION_FAILED",x.message)),!1}},E=()=>b({namespace:A,type:"SYN",channel:s,participantId:i}),Z=h=>{n?.("Received handshake SYN",h),h.participantId!==g&&(g=h.participantId,E()&&i>g&&b({namespace:"penpal",channel:s,type:"ACK1"}))},ee=h=>{n?.("Received handshake ACK1",h),b({namespace:"penpal",channel:s,type:"ACK2"})&&w()},te=h=>{n?.("Received handshake ACK2",h),w()},F=h=>{d||(k(h)?Z(h):K(h)?ee(h):_(h)&&te(h))};return e.addMessageHandler(F),f.push(()=>e.removeMessageHandler(F)),E(),{promise:u,destroy:M}},we=e=>{let t=!1,r;return(...s)=>(t||(t=!0,r=e(...s)),r)},$=new WeakSet,W=()=>new m("CONNECTION_DESTROYED","Connection destroyed"),J=({messenger:e,methods:t={},timeout:r,channel:s,log:n})=>{if(!e)throw new m("INVALID_ARGUMENT","messenger must be defined");if($.has(e))throw new m("INVALID_ARGUMENT","A messenger can only be used for a single connection");$.add(e);let i=Promise.withResolvers(),g=!1,f,c=()=>{let o={namespace:A,channel:s,type:"DESTROY"};try{e.sendMessage(o)}catch{}},d=we((o,p)=>{g=!0,p&&c(),e.destroy(),f?.(),i.reject(o),n?.("Connection destroyed")}),u=o=>ce(o)&&o.channel===s;return(async()=>{try{e.initialize({log:n,validateReceivedMessage:u}),e.addMessageHandler(l=>{ue(l)&&d(W(),!1)});let o=ye({messenger:e,methods:t,timeout:r,channel:s,log:n});f=o.destroy;let p=await o.promise;if(g){o.destroy();return}i.resolve(p)}catch(o){d(o,!0)}})(),{promise:i.promise,destroy:()=>{d(W(),!0)}}},q=class{#t;#s;#o;#a;#n;#r=new Set;#e;constructor({remoteWindow:e,allowedOrigins:t}){if(!e)throw new m("INVALID_ARGUMENT","remoteWindow must be defined");this.#t=e,this.#s=t?.length?t:[window.origin]}initialize=({log:e,validateReceivedMessage:t})=>{this.#o=e,this.#a=t,window.addEventListener("message",this.#l)};sendMessage=(e,t)=>{if(k(e)){let r=this.#c(e);this.#t.postMessage(e,{targetOrigin:r,...t===void 0?{}:{transfer:t}});return}if(K(e)){let r=this.#c(e);this.#t.postMessage(e,{targetOrigin:r,...t===void 0?{}:{transfer:t}});return}if(_(e)){let{port1:r,port2:s}=new MessageChannel;this.#d(r);let n=[s,...t||[]],i=this.#c(e);try{this.#t.postMessage(e,{targetOrigin:i,transfer:n})}catch(g){throw this.#i(),s.close(),g}return}if(this.#e){this.#e.postMessage(e,{...t===void 0?{}:{transfer:t}});return}throw new m("TRANSMISSION_FAILED","Cannot send message because the MessagePort is not connected")};addMessageHandler=e=>{this.#r.add(e)};removeMessageHandler=e=>{this.#r.delete(e)};destroy=()=>{window.removeEventListener("message",this.#l),this.#i(),this.#r.clear()};#h=e=>this.#s.some(t=>t instanceof RegExp?new RegExp(t).test(e):t===e||t==="*");#c=e=>{if(k(e))return"*";if(!this.#n)throw new m("TRANSMISSION_FAILED","Cannot send message because the remote origin is not established");return this.#n==="null"&&this.#s.includes("*")?"*":this.#n};#i=()=>{this.#e?.removeEventListener("message",this.#u),this.#e?.close(),this.#e=void 0};#d=e=>{this.#i(),this.#e=e,this.#e.addEventListener("message",this.#u),this.#e.start()};#l=({source:e,origin:t,ports:r,data:s})=>{if(e===this.#t&&this.#a?.(s)){if(!this.#h(t)){this.#o?.(`Received a message from origin \`${t}\` which did not match allowed origins \`[${this.#s.join(", ")}]\``);return}if(k(s)&&(this.#i(),this.#n=t),_(s)){let n=r[0];if(!n){this.#o?.("Ignoring ACK2 because it did not include a MessagePort");return}this.#d(n)}for(let n of this.#r)n(s)}};#u=({data:e})=>{if(this.#a?.(e))for(let t of this.#r)t(e)}};var ve=["post","get","delete","deleteMedia","login","logout","actorToHandle","handleToActor"],Me=[P,R,I,D,N,L,U],C,G=class extends S{sessionEvents=new EventTarget;connection;remote_;remoteClient;sessions=new Map;initialized=!1;destroyed=!1;constructor(t){if(super(),C){let r=C;return window.setTimeout(()=>r.replayInitialization(),0),r}this.connection=J({messenger:new q({remoteWindow:t.remoteWindow,allowedOrigins:t.allowedOrigins??["*"]}),channel:t.channel,timeout:t.timeout,methods:{sessionEvent:(r,s)=>{if(r==="login"){let n=s;n.error||this.sessions.set(n.session.actor,n.session)}else if(r==="logout"){let n=s;n.error||this.sessions.delete(n.actor)}else r==="initialized"&&(this.initialized=!0,s=void 0);this.sessionEvents.dispatchEvent(new CustomEvent(r,{detail:s}))}}}),this.remote_=this.connection.promise.then(r=>{let s=Ee(r);return this.remoteClient=s,s}),window.setTimeout(()=>{this.remote_.then(r=>r.initialize()).catch(()=>{})},0);for(let r of ve)this[r]=async(...s)=>{let i=(await this.remote())[r];return i(...O(s))};C=this}destroy(){this.destroyed||(this.destroyed=!0,C===this&&(C=void 0),this.remoteClient?.destroy().catch(()=>{}),this.connection.destroy())}replayInitialization(){if(!this.destroyed){for(let t of this.sessions.values())this.sessionEvents.dispatchEvent(new CustomEvent("login",{detail:{session:t}}));this.initialized&&this.sessionEvents.dispatchEvent(new CustomEvent("initialized",{detail:void 0}))}}getMedia=async(...t)=>{let r=await(await this.remote()).getMedia(...O(t));return{...r,data:new Blob([r.data.buffer],{type:r.data.type})}};postMedia=async(t,r)=>{let s=await t.data.arrayBuffer();return(await this.remote()).postMedia({...O(t),data:{buffer:s,type:t.data.type}},O(r),new H({transferables:[s]}))};remoteStream(t){let r=`graffiti-rpc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`,s=this.remote_;return(async function*(){let n=await s;try{for(await t(n,r);;){let i=await n.streamNext(r);if(i.done)return i.value;yield i.value}}finally{await n.streamReturn(r)}})()}discover=(...t)=>this.remoteStream((r,s)=>r.discover(s,...O(t)));continueDiscover=(...t)=>this.remoteStream((r,s)=>r.continueDiscover(s,...O(t)));remote(){if(this.destroyed)throw new Error("Graffiti RPC client has been destroyed.");return this.remote_}};function O(e){return JSON.parse(JSON.stringify(e))}function Ee(e){return new Proxy(e,{get(t,r){let s=Reflect.get(t,r);return typeof s=="function"?(...n)=>s(...n).catch(be):s}})}function be(e){if(e instanceof Error){let t=Me.find(({name:r})=>r===e.name);t&&Object.setPrototypeOf(e,t.prototype)}throw e}var T,Se=1e4,X="graffiti-guard-login:",Q=class extends S{sessionEvents;hostUrl;iframe;rpc;onMessage;connectionTimeout;destroyed=!1;returnFocus=null;backgroundInert=new Map;backgroundObserver;constructor(t={}){if(super(),T)return T;let r=new URL(t.hostUrl?.toString()??"https://guard.graffiti.garden/",document.baseURI),s=X+r.origin,n=sessionStorage.getItem(s),i=document.createElement("iframe");i.title="Graffiti Guard",i.allow="storage-access",i.sandbox.add("allow-scripts","allow-same-origin","allow-storage-access-by-user-activation","allow-downloads","allow-forms","allow-popups","allow-top-navigation-by-user-activation"),i.src=r.href,i.setAttribute("aria-hidden","true"),Object.assign(i.style,{background:"transparent",border:"0",display:"none",height:CSS.supports("height","100svh")?"100svh":"100vh",inset:"0",position:"fixed",width:"100%",zIndex:"2147483647"});let g=!1,f=!1;i.addEventListener("load",()=>{i.contentWindow?.postMessage({type:"graffiti-guard:connect",pageUrl:window.location.href,...n?{loginNonce:n}:{}},r.origin)});let c=()=>{g||f||(f=!0,window.alert(`This app could not connect to its data service at ${r.origin}. The service may be offline, or your browser may be blocking its security certificate. Open that address directly, then reload this page.`))};i.addEventListener("error",c),document.body.append(i);let d=i.contentWindow;if(!d)throw i.remove(),new Error("Graffiti Guard iframe did not create a content window.");let u=new G({remoteWindow:d,allowedOrigins:[r.origin],channel:t.channel,timeout:t.timeout});this.sessionEvents=u.sessionEvents,this.sessionEvents.addEventListener("initialized",()=>{sessionStorage.getItem(s)===n&&sessionStorage.removeItem(s)},{once:!0});let o=window.setTimeout(c,t.timeout??Se),p=()=>{g=!0,window.clearTimeout(o)},l=a=>{if(!(a.source!==d||a.origin!==r.origin||!a.data||typeof a.data!="object")&&(p(),a.data.type!=="graffiti-guard:connected"))if(a.data.type==="graffiti-guard:set-visible"&&typeof a.data.visible=="boolean")this.setGuardVisible(a.data.visible),a.data.visible&&d.postMessage({type:"graffiti-guard:shown"},r.origin);else if(a.data.type==="graffiti-guard:open-storage-setup"&&typeof a.data.url=="string")try{let y=new URL(a.data.url),M=new URLSearchParams(y.hash.slice(1));if(y.origin!==r.origin||M.get("guardStorageSetup")!=="1"&&y.searchParams.get("guardStorageSetup")!=="1")return;window.location.assign(y)}catch{}else a.data.type==="graffiti-guard:open-audit"&&typeof a.data.actor=="string"&&Array.isArray(a.data.source)&&window.location.assign(this.auditUrl(a.data))};return window.addEventListener("message",l),this.hostUrl=r,this.iframe=i,this.rpc=u,this.onMessage=l,this.connectionTimeout=o,T=new Proxy(this,{get(a,y,M){if(Reflect.has(a,y))return Reflect.get(a,y,M);let w=Reflect.get(u,y,u);return typeof w=="function"?w.bind(u):w}}),T}login=t=>{let r=new URL(this.hostUrl),s=new URLSearchParams({guardLogin:"1",redirectUrl:window.location.href});t?.actor&&s.set("suggestedActor",t.actor);let n=crypto.randomUUID();return sessionStorage.setItem(X+this.hostUrl.origin,n),s.set("loginNonce",n),t?.state!==void 0&&s.set("state",t.state),r.hash=s.toString(),window.location.assign(r.href),Promise.resolve()};auditUrl(t){let r=new URL(this.hostUrl),s=new URLSearchParams({redirectUrl:window.location.href,source:JSON.stringify(t?.source??[])});return t?.actor&&s.set("actor",t.actor),r.hash=s.toString(),r.href}setGuardVisible(t){if(t){if(this.iframe.style.display==="block")return;let s=document.activeElement;this.returnFocus=s instanceof HTMLElement&&s!==this.iframe?s:null,this.inertBackground(),this.backgroundObserver=new MutationObserver(()=>this.inertBackground()),this.backgroundObserver.observe(document.body,{childList:!0}),this.iframe.style.display="block",this.iframe.setAttribute("aria-hidden","false"),this.iframe.focus();return}if(this.iframe.style.display==="none")return;this.iframe.style.display="none",this.iframe.setAttribute("aria-hidden","true"),this.backgroundObserver?.disconnect(),this.backgroundObserver=void 0;for(let[s,n]of this.backgroundInert)s.inert=n;this.backgroundInert.clear();let r=this.returnFocus;if(this.returnFocus=null,r?.isConnected&&!r.inert&&r!==document.body)r.focus({preventScroll:!0});else{let s=document.body.getAttribute("tabindex");document.body.tabIndex=-1,document.body.focus({preventScroll:!0}),s===null?document.body.removeAttribute("tabindex"):document.body.setAttribute("tabindex",s)}}inertBackground(){for(let t of Array.from(document.body.children))t===this.iframe||!(t instanceof HTMLElement)||(this.backgroundInert.has(t)||this.backgroundInert.set(t,t.inert),t.inert=!0)}destroy(){this.destroyed||(this.destroyed=!0,window.clearTimeout(this.connectionTimeout),window.removeEventListener("message",this.onMessage),this.iframe.style.display==="block"&&this.setGuardVisible(!1),this.rpc.destroy(),this.iframe.remove(),T===this&&(T=void 0))}};export{Q as GraffitiGuarded};
2
2
  //# sourceMappingURL=index.js.map