@mdbase-dev/connect 0.1.0-beta.21 → 0.1.0-beta.23
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/README.md +108 -38
- package/dist/authorization-url.d.ts +2 -1
- package/dist/authorization-url.js +5 -7
- package/dist/browser/integrity.json +1 -1
- package/dist/browser/mdbase-connect.min.js +3 -3
- package/dist/browser/mdbase-connect.min.js.sha384 +1 -1
- package/dist/collection-client.d.ts +34 -31
- package/dist/collection-client.js +107 -61
- package/dist/connect.d.ts +4 -3
- package/dist/connect.js +53 -38
- package/dist/connection-file-transport.d.ts +31 -0
- package/dist/connection-file-transport.js +42 -0
- package/dist/connection-notifications.js +21 -21
- package/dist/connection-transport.d.ts +2 -0
- package/dist/connection-transport.js +95 -37
- package/dist/connection-types.d.ts +2 -1
- package/dist/connection.d.ts +49 -45
- package/dist/connection.js +73 -33
- package/dist/crypto.d.ts +5 -6
- package/dist/crypto.js +13 -13
- package/dist/errors.d.ts +38 -24
- package/dist/errors.js +130 -71
- package/dist/file-crypto.d.ts +25 -0
- package/dist/file-crypto.js +132 -0
- package/dist/file-sha256.d.ts +12 -0
- package/dist/file-sha256.js +143 -0
- package/dist/file-stream-source.d.ts +17 -0
- package/dist/file-stream-source.js +157 -0
- package/dist/files.d.ts +91 -0
- package/dist/files.js +644 -0
- package/dist/hosted-file-request.d.ts +6 -0
- package/dist/hosted-file-request.js +63 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/internal-types.d.ts +3 -1
- package/dist/local-file-transport.d.ts +30 -0
- package/dist/local-file-transport.js +367 -0
- package/dist/notifications.js +5 -5
- package/dist/operation-helpers.d.ts +2 -2
- package/dist/operation-helpers.js +22 -18
- package/dist/operation-types.d.ts +3 -4
- package/dist/outcomes.d.ts +51 -0
- package/dist/outcomes.js +168 -0
- package/dist/runtime-utils.d.ts +6 -1
- package/dist/runtime-utils.js +90 -11
- package/dist/selection.js +3 -3
- package/dist/session.d.ts +9 -8
- package/dist/session.js +31 -20
- package/package.json +2 -2
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var MdbaseConnect=(()=>{var ie=Object.defineProperty;var Xe=Object.getOwnPropertyDescriptor;var et=Object.getOwnPropertyNames;var tt=Object.prototype.hasOwnProperty;var nt=(n,e)=>{for(var t in e)ie(n,t,{get:e[t],enumerable:!0})},it=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of et(e))!tt.call(n,r)&&r!==t&&ie(n,r,{get:()=>e[r],enumerable:!(i=Xe(e,r))||i.enumerable});return n};var rt=n=>it(ie({},"__esModule",{value:!0}),n);var St={};nt(St,{IndexedDbGrantKeyStore:()=>A,MdbaseBrowserSelection:()=>ge,MdbaseCollectionClient:()=>N,MdbaseConnect:()=>ye,MdbaseConnectError:()=>s,MdbaseConnection:()=>L,MdbaseMemorySelection:()=>me,MdbaseOperationValidationError:()=>J,MdbaseSession:()=>G,MemoryGrantKeyStore:()=>M,RelayCryptoError:()=>f,createPkce:()=>V,decryptRelayResponse:()=>B,encryptRelayRequest:()=>U,isRetryableConnectError:()=>se,parseMdbaseNativeNotificationData:()=>_t,parseMdbasePushPayload:()=>Ze,showMdbasePushNotification:()=>kt,unwrapOperation:()=>O});var x="P256-HKDF-SHA256-AES256GCM";var ot="contract-setup-v1",at=["authorization-activation","encrypted-relay","policy-ack"],Pt=[...at,ot],re=1;var be="mdbase-authority-request-proof-v1",E={version:"x-mdbase-proof-version",timestamp:"x-mdbase-proof-timestamp",nonce:"x-mdbase-proof-nonce",signature:"x-mdbase-proof-signature"};var st="mdbase-connect-keys",P="grant-keys",ae=18446744073709551615n,ct="mdbase-connect relay request key v1",lt="mdbase-connect relay response key v1",we=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,A=class{database=null;async create(e){let t=await Se(e),i=await this.open();return await _e(i,r=>r.add({...t,counter:"0"})),t}async get(e){let t=await this.open(),i=await yt(t.transaction(P).objectStore(P).get(e));return i?{handle:i.handle,agreementPrivateKey:i.agreementPrivateKey,agreementPublicKey:i.agreementPublicKey,signingPrivateKey:i.signingPrivateKey,signingPublicKey:i.signingPublicKey}:null}async nextCounter(e){let t=await this.open();return new Promise((i,r)=>{let a=t.transaction(P,"readwrite"),o=a.objectStore(P),c=o.get(e),l=null;c.onerror=()=>r(c.error),c.onsuccess=()=>{let d=c.result;if(!d){a.abort(),r(new f("missing_grant_key","The encrypted grant key is unavailable."));return}let u=BigInt(d.counter)+1n;if(u>ae){a.abort(),r(new f("counter_exhausted","The encrypted grant must be authorized again."));return}l=u.toString(),o.put({...d,counter:l})},a.onerror=()=>r(a.error),a.onabort=()=>r(a.error??new Error("Key counter transaction aborted.")),a.oncomplete=()=>{l&&i(l)}})}async delete(e){let t=await this.open();await _e(t,i=>i.delete(e))}open(){if(typeof indexedDB>"u")throw new f("key_storage_unavailable","Encrypted relay authorization requires browser IndexedDB or an injected grant key store.");return this.database||(this.database=new Promise((e,t)=>{let i=indexedDB.open(st,1);i.onupgradeneeded=()=>{i.result.objectStoreNames.contains(P)||i.result.createObjectStore(P,{keyPath:"handle"})},i.onerror=()=>t(i.error),i.onsuccess=()=>e(i.result)})),this.database}},M=class{records=new Map;sequence=Promise.resolve();async create(e){if(this.records.has(e))throw new Error(`Grant key already exists: ${e}`);let t=await Se(e);return this.records.set(e,{...t,counter:"0"}),t}async get(e){let t=this.records.get(e);return t?{handle:t.handle,agreementPrivateKey:t.agreementPrivateKey,agreementPublicKey:t.agreementPublicKey,signingPrivateKey:t.signingPrivateKey,signingPublicKey:t.signingPublicKey}:null}nextCounter(e){let t,i,r=new Promise((a,o)=>{t=a,i=o});return this.sequence=this.sequence.then(()=>{let a=this.records.get(e);if(!a)throw new f("missing_grant_key","The encrypted grant key is unavailable.");let o=BigInt(a.counter)+1n;if(o>ae)throw new f("counter_exhausted","The encrypted grant must be authorized again.");a.counter=o.toString(),t(a.counter)}).catch(a=>{i(a)}),r}async delete(e){this.records.delete(e)}};async function ke(n,e,t,i){let r=await ut(n,e,t),a=i.timestamp??Math.floor(Date.now()/1e3),o=i.nonce??crypto.randomUUID(),c=await dt({...i,timestamp:a,nonce:o}),l=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},r.signingPrivateKey,new TextEncoder().encode(c));return{[E.version]:String(re),[E.timestamp]:String(a),[E.nonce]:o,[E.signature]:D(new Uint8Array(l))}}async function dt(n){let e=n.method.toUpperCase(),t=await ve(n.body??""),i=await ve(n.credential);for(let r of[e,n.target,String(n.timestamp),n.nonce])if(!r||r.includes(`
|
|
2
|
-
`)||
|
|
3
|
-
`)}async function U(n,e,t,i,r,a=crypto.randomUUID()){K(t.encryption);let o=await Re(n,e,t.encryption.application_agreement_public_key),c=await n.nextCounter(e),l={binding:t,requestId:a,operation:i,counter:c},d=await Pe(o.agreementPrivateKey,t,"request"),u=new TextEncoder().encode(JSON.stringify(r??{})),p=await crypto.subtle.encrypt({name:"AES-GCM",iv:Ae(c),additionalData:new TextEncoder().encode(Ce(l,"request")),tagLength:128},d,u);return{type:"encrypted_operation_request",...pt(l),ciphertext:D(new Uint8Array(p))}}async function B(n,e,t,i,r){if(!ht(i,r))throw new f("invalid_encrypted_response","Encrypted response metadata does not match its request.");let a=await Re(n,e,t.encryption.application_agreement_public_key),o={binding:t,requestId:i.request_id,operation:i.operation,counter:i.counter},c=await Pe(a.agreementPrivateKey,t,"response");try{let l=await crypto.subtle.decrypt({name:"AES-GCM",iv:Ae(i.counter),additionalData:new TextEncoder().encode(Ce(o,"response")),tagLength:128},c,Oe(Me(r.ciphertext))),d=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(l));if(d?.ok===!0&&"result"in d||d?.ok===!1&&typeof d.error?.code=="string"&&typeof d.error?.message=="string")return d;throw new Error("invalid response body")}catch(l){throw l instanceof f?l:new f("encrypted_response_rejected","The encrypted connector response could not be authenticated.")}}var f=class extends Error{constructor(t,i){super(i);this.code=t}code};async function Se(n){let e=await crypto.subtle.generateKey({name:"ECDH",namedCurve:"P-256"},!0,["deriveBits"]),t=D(new Uint8Array(await crypto.subtle.exportKey("raw",e.publicKey))),i=await crypto.subtle.exportKey("pkcs8",e.privateKey),r=await crypto.subtle.importKey("pkcs8",i,{name:"ECDH",namedCurve:"P-256"},!1,["deriveBits"]),a=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),o=D(new Uint8Array(await crypto.subtle.exportKey("raw",a.publicKey))),c=await crypto.subtle.exportKey("pkcs8",a.privateKey),l=await crypto.subtle.importKey("pkcs8",c,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]);return{handle:n,agreementPrivateKey:r,agreementPublicKey:t,signingPrivateKey:l,signingPublicKey:o}}async function Re(n,e,t){let i=await n.get(e);if(!i||i.agreementPublicKey!==t)throw new f("missing_grant_key","The encrypted grant key is unavailable or does not match the grant.");return i}async function ut(n,e,t){let i=await n.get(e);if(!i||i.signingPublicKey!==t)throw new f("missing_grant_key","The remote authority signing key is unavailable or does not match the grant.");return i}async function Pe(n,e,t){let i,r;try{i=await crypto.subtle.importKey("raw",Oe(oe(e.encryption.connector_agreement_public_key)),{name:"ECDH",namedCurve:"P-256"},!1,[]),r=await crypto.subtle.deriveBits({name:"ECDH",public:i},n,256)}catch{throw new f("invalid_public_key","The connector relay public key is invalid.")}let a=await crypto.subtle.importKey("raw",r,"HKDF",!1,["deriveKey"]),o=new TextEncoder().encode(Ie(e)),c=await crypto.subtle.digest("SHA-256",o);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:c,info:new TextEncoder().encode(t==="request"?ct:lt)},a,{name:"AES-GCM",length:256},!1,t==="request"?["encrypt"]:["decrypt"])}function Ie(n){let e=n.encryption;return["mdbase-connect",1,e.suite,n.grantId,n.applicationId,e.connector_id,e.collection_id,e.scope_epoch,e.key_id].join("|")}function Ce(n,e){return[Ie(n.binding),n.requestId,e,n.operation,n.counter].join("|")}function pt(n){let e=n.binding.encryption;return{protocol_version:1,suite:x,request_id:n.requestId,grant_id:n.binding.grantId,application_id:n.binding.applicationId,connector_id:e.connector_id,collection_id:e.collection_id,operation:n.operation,scope_epoch:e.scope_epoch,key_id:e.key_id,counter:n.counter}}function ht(n,e){return e.type==="encrypted_operation_response"&&typeof e.ciphertext=="string"&&n.protocol_version===e.protocol_version&&n.suite===e.suite&&n.request_id===e.request_id&&n.grant_id===e.grant_id&&n.application_id===e.application_id&&n.connector_id===e.connector_id&&n.collection_id===e.collection_id&&n.operation===e.operation&&n.scope_epoch===e.scope_epoch&&n.key_id===e.key_id&&n.counter===e.counter}function K(n){if(n.protocol_version!==1||n.suite!==x||!Number.isSafeInteger(n.scope_epoch)||n.scope_epoch<=0||typeof n.key_id!="string"||n.key_id.length===0||n.key_id.length>200||n.key_id.includes("|"))throw new f("unsupported_encryption","The grant uses an unsupported relay encryption profile.");if(typeof n.connector_id!="string"||!we.test(n.connector_id)||typeof n.collection_id!="string"||!we.test(n.collection_id))throw new f("unsupported_encryption","The grant uses invalid encrypted relay identities.");oe(n.application_agreement_public_key),oe(n.connector_agreement_public_key)}function Ae(n){let e=BigInt(n);if(e<=0n||e>ae||e.toString()!==n)throw new f("invalid_counter","The encrypted relay counter is invalid.");let t=new Uint8Array(new ArrayBuffer(12));return new DataView(t.buffer).setBigUint64(4,e,!1),t}function D(n){let e="";for(let t of n)e+=String.fromCharCode(t);return btoa(e).replaceAll("+","-").replaceAll("/","_").replace(/=+$/,"")}async function ve(n){let e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(n));return D(new Uint8Array(e))}function Me(n){if(!/^[A-Za-z0-9_-]+$/.test(n))throw new f("invalid_base64","Encrypted relay data is malformed.");let e="=".repeat((4-n.length%4)%4),t=atob(n.replaceAll("-","+").replaceAll("_","/")+e);return Uint8Array.from(t,i=>i.charCodeAt(0))}function oe(n){let e=Me(n);if(e.length!==65||e[0]!==4)throw new f("invalid_public_key","Encrypted relay public keys must be uncompressed P-256 points.");return e}function Oe(n){return Uint8Array.from(n).buffer}function yt(n){return new Promise((e,t)=>{n.onerror=()=>t(n.error),n.onsuccess=()=>e(n.result)})}function _e(n,e){return new Promise((t,i)=>{let r=n.transaction(P,"readwrite"),a=e(r.objectStore(P));a.onerror=()=>i(a.error),r.onerror=()=>i(r.error),r.onabort=()=>i(r.error??new Error("Grant key transaction aborted.")),r.oncomplete=()=>t()})}function q(n,e){return new Promise((t,i)=>{if(e?.aborted){i(e.reason??new DOMException("Aborted","AbortError"));return}let r=setTimeout(t,n);e?.addEventListener("abort",()=>{clearTimeout(r),i(e.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}var s=class extends Error{constructor(t,i,r={}){super(i);this.code=t;this.name="MdbaseConnectError";let a=ft(t,r.status);this.status=r.status,this.retryable=r.retryable??a.retryable,this.requiresAuthorization=r.requiresAuthorization??a.requiresAuthorization,this.outcomeUnknown=r.outcomeUnknown??a.outcomeUnknown,this.recovery=r.recovery??a.recovery,this.details=r.details,r.cause!==void 0&&Object.defineProperty(this,"cause",{value:r.cause,configurable:!0})}code;status;retryable;requiresAuthorization;outcomeUnknown;recovery;details},J=class extends Error{constructor(t,i){super(t.filter(r=>r.severity==="error").map(r=>r.message).join(" ")||t.map(r=>r.message).join(" ")||"The collection rejected this operation.");this.diagnostics=t;this.result=i;this.name="MdbaseOperationValidationError"}diagnostics;result;code="operation_invalid"};function O(n){if(!n.valid)throw new J(n.diagnostics,n.result);return n.result}function se(n){return n instanceof s?n.retryable&&!n.outcomeUnknown:n instanceof TypeError}function ft(n,e){let t=new Set(["authorization_expired","direct_operation_rejected","encryption_required","insufficient_access","missing_grant_key","not_authorized","relay_authorization_expired"]),i=n==="direct_outcome_unknown"||n==="pending_mutation_unresolved",r=t.has(n)||e===401,a=new Set(["connector_offline","discovery_failed","relay_unavailable","sync_failed","temporarily_unavailable","timeout"]),o=e===408||e===425||e===429||e!==void 0&&e>=500,c=!i&&!r&&(a.has(n)||o),l=i?"resolve_outcome":r?"reauthorize":n==="change_cursor_reset"?"refresh":c?"retry":e!==void 0&&e>=400&&e<500?"fix_request":"none";return{retryable:c,requiresAuthorization:r,outcomeUnknown:i,recovery:l}}var N=class{constructor(e){this.transport=e}transport;operation(e,t,i){return this.transport.operation(e,t,i)}describe(){return this.operation("describe",{})}changes(e={},t){return this.operation("changes",e,t)}read(e){return this.operation("read",e)}query(e={},t){return this.operation("query",e,t)}async*queryPages(e={},t={}){let{offset:i,limit:r,snapshot:a,...o}=e,c=mt(i,0),l=Te(t.firstPageSize??r,200),d=Te(t.pageSize??r,1e3),u=a,p=0,h=0;for(;!t.signal?.aborted;){let y=O(await this.query({...o,offset:c,limit:h===0?l:d,...u?{snapshot:u}:{}},{signal:t.signal})),v=y.meta?.snapshot;if(u&&v&&u!==v)throw new s("query_snapshot_changed","The collection query snapshot changed while paging. Refresh the query before continuing.",{recovery:"refresh"});!u&&v&&(u=v),p+=y.results.length;let S=!y.meta?.has_more||y.results.length===0,b={results:y.results,...y.meta?{meta:y.meta}:{},page:h,offset:c,loaded:p,complete:S,...u?{snapshot:u}:{}};if(t.onProgress?.(b),yield b,S)return;c+=y.results.length,h+=1}}async queryAll(e={},t={}){let i=[],r;for await(let a of this.queryPages(e,t))i.push(...a.results),r=a;return{results:i,meta:{...r?.meta??{},total_count:r?.meta?.total_count??i.length,has_more:r?!r.complete:!1,...r?.snapshot?{snapshot:r.snapshot}:{}}}}listViews(){return this.operation("list_views",{})}executeView(e){return this.operation("execute_view",e)}readViewSource(e){return this.operation("read_view_source",e)}createViewSource(e){return this.operation("create_view_source",e)}updateViewSource(e){return this.operation("update_view_source",e)}deleteViewSource(e){return this.operation("delete_view_source",e)}create(e){return this.operation("create",e)}update(e){return this.operation("update",e)}delete(e,t){return this.operation("delete",e,t)}preflightDelete(e,t){return this.operation("delete",{...e,check_backlinks:!0,dry_run:!0},t)}rename(e,t){return this.operation("rename",e,t)}preflightRename(e,t){return this.operation("rename",{...e,dry_run:!0},t)}validate(e={}){return this.operation("validate",e)}readType(e){return this.operation("read_type",e)}createType(e){return this.operation("create_type",e)}updateType(e){return this.operation("update_type",e)}installTypePack(e){return this.operation("install_type_pack",e)}listTimers(e){return this.operation("list_timers",{namespace:e})}putTimer(e){return this.operation("put_timer",e)}cancelTimer(e){return this.operation("cancel_timer",e)}reconcileTimers(e){return this.operation("reconcile_timers",e)}async*watch(e={}){let t=e.cursor,i=Math.max(100,e.pollIntervalMs??1e3),r=gt(e.retry),a=0,o=!1;for(e.onStatus?.({state:"connecting",...t===void 0?{}:{cursor:t}});!e.signal?.aborted;)try{t===void 0&&(t=(await this.changes({},{signal:e.signal})).cursor);let c=await this.changes({after:t,limit:200},{signal:e.signal});if(c.reset){let d=new s("change_cursor_reset","The collection change cursor expired. Refresh collection state before subscribing again.");throw e.onStatus?.({state:"reset_required",cursor:t,error:d}),d}let l=a>0;a=0,(!o||l)&&e.onStatus?.({state:"connected",cursor:t,recovered:l}),o=!0;for(let d of c.events)yield d;t=c.cursor,c.has_more||await q(i,e.signal)}catch(c){if(e.signal?.aborted)return;if(!r||!se(c)||(o=!1,a+=1,r.maxAttempts!==void 0&&a>r.maxAttempts))throw c;let l=Math.min(r.maxDelayMs,Math.round(r.initialDelayMs*r.multiplier**(a-1)));e.onStatus?.({state:"reconnecting",...t===void 0?{}:{cursor:t},attempt:a,retryInMs:l,error:c}),await q(l,e.signal)}}};function gt(n){if(n!==!1)return{initialDelayMs:Math.max(0,n?.initialDelayMs??500),maxDelayMs:Math.max(0,n?.maxDelayMs??15e3),multiplier:Math.max(1,n?.multiplier??2),...n?.maxAttempts===void 0?{}:{maxAttempts:Math.max(0,n.maxAttempts)}}}function mt(n,e){return typeof n=="number"&&Number.isFinite(n)?Math.max(0,Math.floor(n)):e}function Te(n,e){return typeof n=="number"&&Number.isFinite(n)&&n>0?Math.floor(n):e}function R(n){let e=new Uint8Array(n);return crypto.getRandomValues(e),j(e)}function j(n){let e="";for(let t of n)e+=String.fromCharCode(t);return btoa(e).replaceAll("+","-").replaceAll("/","_").replace(/=+$/,"")}function xe(n){let e=n.replaceAll("-","+").replaceAll("_","/").padEnd(Math.ceil(n.length/4)*4,"="),t=atob(e),i=new Uint8Array(new ArrayBuffer(t.length));for(let r=0;r<t.length;r+=1)i[r]=t.charCodeAt(r);return i}function le(n){return{...n,credentials:"omit",targetAddressSpace:"loopback"}}async function F(){if(typeof navigator>"u"||!navigator.permissions?.query)return null;try{return(await navigator.permissions.query({name:"local-network-access"})).state}catch{return null}}function Ee(n){return n===404||n===405||n===426||n>=500}function Q(n,e){return e&&typeof e=="object"&&!Array.isArray(e)&&e.dry_run===!0?!1:n==="sync"&&e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.action==="mutate"||n==="create"||n==="update"||n==="delete"||n==="rename"||n==="create_type"||n==="update_type"||n==="install_type_pack"||n==="put_timer"||n==="cancel_timer"||n==="reconcile_timers"}function k(n){return[...new Set(n)]}function De(n,e){return n.grantId||e.grantId?n.grantId===e.grantId&&n.keyHandle===e.keyHandle&&n.encryption?.key_id===e.encryption?.key_id:n.accessToken===e.accessToken}function I(n){if(n?.aborted)throw new s("operation_cancelled","The operation was cancelled before it changed the collection.",{recovery:"none",cause:n.reason})}function de(n,e,t){return e?.aborted?new s("operation_cancelled",t?"Waiting was cancelled after the mutation was sent. Resume the pending mutation to recover its authoritative result.":"The operation was cancelled before it changed the collection.",{outcomeUnknown:t,recovery:t?"resolve_outcome":"none",cause:n}):t?n instanceof s&&n.outcomeUnknown?n:H(n):n instanceof Error?n:new Error(String(n))}function ue(n,e){return e?.aborted===!0||n instanceof s&&n.code==="operation_cancelled"}function ze(n,e){if(e.dry_run!==!0||e.would_rename!==!0||e.from!==n.from||e.to!==n.to)throw new s("invalid_preflight","The rename preview does not match this mutation. Run the preview again.",{recovery:"fix_request"})}function Ue(n,e){if(e.dry_run!==!0||e.would_delete!==!0||e.path!==n.path)throw new s("invalid_preflight","The delete preview does not match this mutation. Run the preview again.",{recovery:"fix_request"})}function Ke(n,e){if(n.update_refs===!1)return{affectedRecords:0,totalUnits:1,warnings:0};let t=e.references_affected??[];return{affectedRecords:new Set(t.map(i=>i.path)).size,totalUnits:1+t.length,warnings:e.warnings?.length??0}}function qe(n){return{affectedRecords:new Set((n.broken_links??[]).map(e=>e.path)).size,totalUnits:1,warnings:0}}async function Ne(n,e){let t=new TextEncoder().encode(`${n}\0${pe(e??{})}`),i=await crypto.subtle.digest("SHA-256",t);return j(new Uint8Array(i))}function pe(n){return JSON.stringify(ce(n))}function ce(n){return Array.isArray(n)?n.map(e=>ce(e)):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0).sort(([e],[t])=>e<t?-1:e>t?1:0).map(([e,t])=>[e,ce(t)])):n}function H(n){return new s("direct_outcome_unknown","The direct write may have completed, and mdbase could not recover its receipt through the relay. Retry the exact same write to recover safely.",{cause:n})}function je(n){let e=new URL(n);if(e.protocol!=="http:"||!["127.0.0.1","[::1]"].includes(e.hostname)||e.username||e.password||e.pathname!=="/"||e.search||e.hash)throw new s("invalid_loopback_url","loopbackUrl must be an HTTP origin on 127.0.0.1 or ::1.");return e.origin}async function V(){let n=R(32),e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(n));return{verifier:n,challenge:j(new Uint8Array(e))}}function m(n,e,t,i){return new s(he(n)??n?.error?.code??e,n?.error_description??n?.error?.message??t,{status:i,details:n?.error?.details})}function he(n){return typeof n?.error=="string"?n.error:void 0}function Y(n,e){if(!n||typeof n!="object"||Array.isArray(n)||typeof e!="string")return!1;let t=n;if(typeof t.operations_url!="string"||typeof t.sync_url!="string"||typeof t.replica_id!="string"||t.replica_id.length===0||typeof t.access_token!="string"||t.access_token.length===0||t.proof_public_key!==void 0&&(typeof t.proof_public_key!="string"||t.proof_public_key.length===0))return!1;try{let i=new URL(t.operations_url),r=new URL(t.sync_url);return[i,r].every(a=>(a.protocol==="https:"||a.protocol==="http:"&&["localhost","127.0.0.1","[::1]","::1"].includes(a.hostname))&&!a.username&&!a.password&&!a.search&&!a.hash)&&/^\/v1\/authorities\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/operations$/i.test(i.pathname)&&/^\/v1\/authorities\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/sync$/i.test(r.pathname)&&i.origin===r.origin&&i.pathname.split("/")[3]===e&&r.pathname.split("/")[3]===e}catch{return!1}}function Fe(n,e){return Y({operations_url:n?.operationsUrl,sync_url:n?.syncUrl,replica_id:n?.replicaId,access_token:n?.accessToken,proof_public_key:n?.proofPublicKey},e)}function He(n,e){if(!n||typeof n!="object"||Array.isArray(n)||n.collection_id!==e)return!1;try{return K(n),!0}catch{return!1}}function Ve(n){if(typeof n?.device_code!="string"||typeof n?.user_code!="string"||typeof n?.verification_uri!="string"||typeof n?.verification_uri_complete!="string"||!Number.isFinite(n?.expires_in)||!Number.isFinite(n?.interval))throw new s("invalid_device_authorization_response","Connect returned an invalid downloaded application authorization response.");return{userCode:n.user_code,verificationUri:n.verification_uri,verificationUriComplete:n.verification_uri_complete,expiresAt:Date.now()+Math.max(1,n.expires_in)*1e3,intervalSeconds:Math.max(1,n.interval)}}function w(n){if(!n)return null;try{return JSON.parse(n)}catch{return null}}function W(n){if(!n||typeof n!="object"||Array.isArray(n))return null;let e=n;return e.access!=="contract"&&e.access!=="full_collection"||!Array.isArray(e.contracts)||e.contracts.some(t=>!t||typeof t!="object"||t.contract_type!=="record"||typeof t.id!="string"||typeof t.version!="string"||!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(t.version)||!/^sha256:[0-9a-f]{64}$/.test(t.digest)||!t.schema||typeof t.schema!="object"||Array.isArray(t.schema)||!Array.isArray(t.implementations)||t.implementations.some(i=>!i||typeof i!="object"||typeof i.type_name!="string"||!Number.isInteger(i.type_version)||!/^sha256:[0-9a-f]{64}$/.test(i.digest)||!i.fields||typeof i.fields!="object"||Array.isArray(i.fields)||Object.values(i.fields).some(r=>typeof r!="string")))?null:e}function Le(n){return n.endsWith("/")?n.slice(0,-1):n}function $e(){if(typeof location>"u")throw new s("manifest_required","manifest is required outside a browser environment.");if(location.origin==="null")throw new s("manifest_required","Downloaded applications must provide their v1 portable manifest inline.");return new URL("/.well-known/mdbase-app.json",location.origin).href}function Ge(){if(typeof location>"u")throw new s("redirect_uri_required","redirectUri is required outside a browser environment.");return location.href.split(/[?#]/)[0]}function Be(){if(typeof location>"u")throw new s("callback_url_required","callbackUrl is required outside a browser environment.");return location.href}function Je(n){if(n)return new T;if(typeof localStorage>"u")throw new s("storage_required","storage is required outside a browser environment.");try{let e=`mdbase-connect:probe:${R(8)}`;return localStorage.setItem(e,"1"),localStorage.removeItem(e),localStorage}catch{return new T}}var T=class{values=new Map;get length(){return this.values.size}clear(){this.values.clear()}getItem(e){return this.values.get(e)??null}key(e){return[...this.values.keys()][e]??null}removeItem(e){this.values.delete(e)}setItem(e,t){this.values.set(String(e),String(t))}};function Qe(n){return typeof n=="string"||n.distribution!=="portable"?!1:typeof location>"u"||location.origin==="null"||!["http:","https:"].includes(location.protocol)}function Ye(n){let e=pe(n),t=2166136261,i=2654435769;for(let r=0;r<e.length;r+=1){let a=e.charCodeAt(r);t=Math.imul(t^a,16777619),i=Math.imul(i^a,2246822507)}return`${(t>>>0).toString(16).padStart(8,"0")}${(i>>>0).toString(16).padStart(8,"0")}`}var Z=class{constructor(e){this.context=e}context;async registerNotifications(e){let t=await this.context.authorizedToken();if(!t)throw new s("not_authorized","Connect this application before enabling notifications.");let r=(await this.context.register()).notifications?.criteria.map(b=>b.id)??[],a=[...new Set(e.criteria??r)],o=a.find(b=>!r.includes(b));if(o)throw new s("notification_criterion_not_declared",`The application manifest does not declare notification criterion ${o}.`);if(a.length===0)throw new s("notifications_not_declared","This application manifest does not declare any notification criteria.");let c=await fetch(`${this.context.serverUrl}/v1/notifications/vapid-public-key`),l=await c.json();if(!c.ok)throw m(l,"notifications_unavailable","Push notifications are unavailable.",c.status);let d=await e.serviceWorker.pushManager.getSubscription();d||(d=await e.serviceWorker.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:xe(l.public_key)}));let u=d.toJSON();if(!u.endpoint||!u.keys?.p256dh||!u.keys.auth)throw new s("invalid_push_subscription","The browser returned an incomplete push subscription.");let p=w(this.context.storage.getItem(this.context.notificationKey())),h=e.installationId??p?.installationId??R(24),y=await fetch(`${this.context.serverUrl}/v1/notifications/channels`,{method:"POST",headers:{authorization:`Bearer ${t.accessToken}`,"content-type":"application/json"},body:JSON.stringify({installation_id:h,criteria:a,subscription:{endpoint:u.endpoint,expirationTime:u.expirationTime??null,keys:u.keys}})}),v=await y.json();if(!y.ok)throw m(v,"notification_registration_failed","Could not register push notifications.",y.status);p?.channelId&&p.channelId!==v.channel_id&&fetch(`${this.context.serverUrl}/v1/notifications/channels/${p.channelId}`,{method:"DELETE",headers:{authorization:`Bearer ${t.accessToken}`}}).catch(()=>{});let S={channelId:v.channel_id,installationId:h,criteria:a};return this.context.storage.setItem(this.context.notificationKey(),JSON.stringify(S)),S}async registerNativeNotifications(e){let t=await this.context.authorizedToken();if(!t)throw new s("not_authorized","Connect this application before enabling notifications.");let i=await this.context.register();if(i.notifications?.native_delivery?.mode!=="managed_fcm")throw new s("managed_fcm_not_declared","This application does not declare Connect-managed native notifications.");let r=i.notifications.criteria.map(y=>y.id),a=[...new Set(e.criteria??r)],o=a.find(y=>!r.includes(y));if(o)throw new s("notification_criterion_not_declared",`The application manifest does not declare notification criterion ${o}.`);if(a.length===0)throw new s("notifications_not_declared","This application manifest does not declare any notification criteria.");let c=this.context.notificationKey("fcm"),l=w(this.context.storage.getItem(c)),d=e.installationId??l?.installationId??R(24),u=await fetch(`${this.context.serverUrl}/v1/notifications/channels`,{method:"POST",headers:{authorization:`Bearer ${t.accessToken}`,"content-type":"application/json"},body:JSON.stringify({installation_id:d,criteria:a,transport:"fcm",token:e.token})}),p=await u.json();if(!u.ok)throw m(p,"notification_registration_failed","Could not register native notifications.",u.status);l?.channelId&&l.channelId!==p.channel_id&&this.deleteNotificationChannel(l.channelId,t.accessToken).catch(()=>{});let h={channelId:p.channel_id,installationId:d,transport:"fcm",criteria:a};return this.context.storage.setItem(c,JSON.stringify(h)),h}async unregisterNativeNotifications(){let e=this.context.notificationKey("fcm"),t=w(this.context.storage.getItem(e)),i=await this.context.authorizedToken();if(t?.channelId&&!i)throw new s("not_authorized","Reconnect this application before disabling native notifications.");t?.channelId&&i&&await this.deleteNotificationChannel(t.channelId,i.accessToken),this.context.storage.removeItem(e)}async unregisterNotifications(e){let t=w(this.context.storage.getItem(this.context.notificationKey())),i=await this.context.authorizedToken();if(t?.channelId&&!i)throw new s("not_authorized","Reconnect this application before disabling push notifications.");if(t?.channelId&&i){let a=await fetch(`${this.context.serverUrl}/v1/notifications/channels/${t.channelId}`,{method:"DELETE",headers:{authorization:`Bearer ${i.accessToken}`}});if(!a.ok&&a.status!==404){let o=await a.json();throw m(o,"notification_unregistration_failed","Could not unregister push notifications.",a.status)}}this.context.storage.removeItem(this.context.notificationKey()),await(await e?.pushManager.getSubscription())?.unsubscribe()}async deleteNotificationChannel(e,t){let i=await fetch(`${this.context.serverUrl}/v1/notifications/channels/${e}`,{method:"DELETE",headers:{authorization:`Bearer ${t}`}});if(!i.ok&&i.status!==404){let r=await i.json();throw m(r,"notification_unregistration_failed","Could not unregister push notifications.",i.status)}}};var X=class{serverUrl;storage;keyStore;directAccessMode;loopbackUrl;collectionId;internals;onChange;refreshPromise=null;directStatus;currentRoute="relay";directFailures=0;directRetryAt=0;constructor(e){this.serverUrl=e.serverUrl,this.storage=e.storage,this.keyStore=e.keyStore,this.directAccessMode=e.directAccessMode,this.loopbackUrl=e.loopbackUrl,this.collectionId=e.collectionId,this.internals=e.internals,this.onChange=e.onChange,this.directStatus=this.directAccessMode==="disabled"?"disabled":"unavailable"}get directAccess(){return this.currentToken()?.authority?"disabled":this.directStatus}get route(){return this.currentToken()?.authority?"remote":this.currentRoute}notifyStorageChanged(){this.emitConnection()}async checkDirectAccess(){let e=this.currentToken();if(!this.directEligible(e))return this.setDirectStatus("disabled");let t=await F();return t==="denied"?this.setDirectStatus("denied"):(t==="prompt"||t===null)&&this.storage.getItem(this.directPreferenceKey())!=="enabled"?this.setDirectStatus("permission_required"):this.probeDirectAccess()}async requestDirectAccess(){let e=this.currentToken();return this.directCapable(e)?(this.storage.setItem(this.directPreferenceKey(),"enabled"),this.directRetryAt=0,this.probeDirectAccess()):this.setDirectStatus("disabled")}disableDirectAccess(){this.storage.setItem(this.directPreferenceKey(),"disabled"),this.setDirectStatus("disabled"),this.setRoute("relay")}pendingMutation(){let e=w(this.storage.getItem(this.pendingMutationKey())),t=this.currentToken();return!e||!t||e.collectionId!==t.collectionId||e.grantId!==t.grantId||e.keyId!==t.encryption?.key_id?null:{operation:e.operation,createdAt:e.createdAt,resumable:!0}}async resumePendingMutation(e,t){let i=this.pendingMutation();if(!i)throw new s("no_pending_mutation","There is no interrupted mutation to resume.",{recovery:"none"});return this.performOperation(i.operation,e,t)}async performOperation(e,t,i={}){I(i.signal);let r=this.currentToken();if(!r)throw new s("not_authorized","Connect this application before accessing a collection.");if(!r.operations.includes(e))throw new s("insufficient_access",`This connection does not allow ${e}.`,{requiresAuthorization:!0,recovery:"reauthorize",details:{requiredOperations:[e],grantedOperations:[...r.operations],missingOperations:[e]}});let a=await this.shouldAttemptDirect(r);if(!a&&(r=await this.authorizedToken(),!r))throw new s("not_authorized","Reconnect this application to continue.");let o;try{o=await this.sendOperation(r,e,t,a,i)}catch(u){throw de(u,i.signal,Q(e,t)&&this.pendingMutation()!==null)}let c=o.response,l=c.status===409&&(await c.clone().json().catch(()=>null))?.error?.code==="encryption_binding_stale";if((c.status===401||l)&&r.refreshToken){if(o.pendingMutation&&(o.directDeliveryUncertain||o.encryptedRequest&&o.resumingMutation))throw new s("direct_outcome_unknown","The direct operation may have completed, but its encrypted grant changed before the response could be recovered. Refresh before making another change.");o.pendingMutation&&this.clearPendingMutation(),r=await this.refreshAuthorization(),a=await this.shouldAttemptDirect(r);try{o=await this.sendOperation(r,e,t,a,i)}catch(u){throw de(u,i.signal,Q(e,t)&&this.pendingMutation()!==null)}c=o.response}let d=await c.json();if(!c.ok){let u=m(d,"operation_failed","Collection operation failed.",c.status);throw o.pendingMutation&&(o.directDeliveryUncertain||o.encryptedRequest&&o.resumingMutation)?H(u):(o.pendingMutation&&!o.directDeliveryUncertain&&this.clearPendingMutation(),u.code==="direct_operation_rejected"&&u.status===403&&this.invalidateRejectedAuthorization(r),u)}if(o.encryptedRequest){let u=d?.envelope;if(!u||!r.encryption||!r.grantId||!r.keyHandle)throw new s("invalid_encrypted_response","The relay did not return an encrypted connector response.");try{let p=await B(this.keyStore,r.keyHandle,{grantId:r.grantId,applicationId:r.clientId,encryption:r.encryption},o.encryptedRequest,u);if(o.pendingMutation&&this.clearPendingMutation(),!p.ok)throw new s(p.error.code,p.error.message);return p.result}catch(p){throw p instanceof s?p:p instanceof f?new s(p.code,p.message):p}}if(d?.protocol_version!==1||d?.request_id!==o.requestId)throw new s("invalid_operation_response","The collection authority returned a response for a different protocol request.");return o.pendingMutation&&this.clearPendingMutation(),d.result}async performAuthoritySyncRequest(e,t,i,r,a){let o=await this.authorizedToken();if(!o?.authority||o.collectionId!==e||o.authority.replicaId!==t)throw new s("authority_authorization_changed","Reconnect this collection authority before synchronizing.");let c=await this.sendAuthoritySyncRequest(o,i,r,a);if(c.status===401&&o.refreshToken){if(o=await this.refreshAuthorization(),!o.authority||o.collectionId!==e||o.authority.replicaId!==t)throw new s("authority_authorization_changed","Reconnect this collection authority before synchronizing.");c=await this.sendAuthoritySyncRequest(o,i,r,a)}let l=await c.json();if(!c.ok)throw m(l,"sync_failed","Collection synchronization failed.",c.status);return l}async sendAuthoritySyncRequest(e,t,i,r){if(!e.authority)throw new s("not_remote_authority","This authorization has no remote authority endpoint.");let a=`${e.authority.syncUrl}/${i}`,o=r===void 0?void 0:JSON.stringify(r),c=await this.authorityProofHeaders(e,t,a,o,e.authority.accessToken);return fetch(a,{method:t,headers:{authorization:`Bearer ${e.authority.accessToken}`,...r===void 0?{}:{"content-type":"application/json"},...c},...o===void 0?{}:{body:o}})}async sendOperation(e,t,i,r,a={}){let o=i??{},c,l=!1,d=!1,u=crypto.randomUUID(),p=null,h;if(Q(t,i)){if(h=await Ne(t,i),p=w(this.storage.getItem(this.pendingMutationKey())),p){if(p.collectionId!==e.collectionId||p.grantId!==e.grantId||p.keyId!==e.encryption?.key_id||p.operation!==t||p.inputFingerprint!==h)throw new s("pending_mutation_unresolved","A previous write still has an unknown outcome. Retry that exact write before making another change.");u=p.requestId,d=!0}l=!0}if(e.encryption&&!e.authority){if(!e.grantId||!e.keyHandle)throw new s("missing_grant_key","Reconnect this application to restore encrypted access.");try{if(l)if(p){if(!p.envelope)throw new s("pending_mutation_unresolved","The pending write belongs to a different transport. Reconnect before retrying it.");c=p.envelope}else c=await U(this.keyStore,e.keyHandle,{grantId:e.grantId,applicationId:e.clientId,encryption:e.encryption},t,i,u),this.storage.setItem(this.pendingMutationKey(),JSON.stringify({collectionId:e.collectionId,...e.grantId?{grantId:e.grantId}:{},keyId:e.encryption.key_id,operation:t,inputFingerprint:h,requestId:u,envelope:c,createdAt:Date.now()}));else c=await U(this.keyStore,e.keyHandle,{grantId:e.grantId,applicationId:e.clientId,encryption:e.encryption},t,i)}catch(g){throw g instanceof f?new s(g.code,g.message):g}o=c}else o={protocol_version:1,request_id:u,input:o},l&&!p&&this.storage.setItem(this.pendingMutationKey(),JSON.stringify({collectionId:e.collectionId,...e.grantId?{grantId:e.grantId}:{},operation:t,inputFingerprint:h,requestId:u,createdAt:Date.now()}));if(r&&c&&!e.authority){let g=!1;try{let _=await fetch(`${this.loopbackUrl}/v1/operations`,le({method:"POST",headers:{"content-type":"application/mdbase-connect+json"},body:JSON.stringify(c),signal:a.signal}));if(!Ee(_.status))return _.ok&&(this.markDirectAvailable(),this.setRoute("direct")),{response:_,requestId:u,encryptedRequest:c,pendingMutation:l,resumingMutation:d};g=_.status>=500,this.markDirectUnavailable()}catch(_){if(a.signal?.aborted)throw _;g=!0,await F()==="denied"?this.setDirectStatus("denied"):this.markDirectUnavailable()}let te;try{te=e.expiresAt>Date.now()+3e4?e:await this.refreshAuthorization()}catch(_){throw l&&(g||d)?H(_):_}let ne;try{ne=await fetch(`${this.serverUrl}/v1/authorities/${encodeURIComponent(te.collectionId)}/operations/${t}`,{method:"POST",headers:{authorization:`Bearer ${te.accessToken}`,"content-type":"application/json"},body:JSON.stringify(c),signal:a.signal})}catch(_){throw l&&(g||d)?H(_):_}return ne.ok&&this.setRoute("relay"),{response:ne,requestId:u,encryptedRequest:c,directDeliveryUncertain:g,pendingMutation:l,resumingMutation:d}}let y=e.authority?`${e.authority.operationsUrl}/${t}`:`${this.serverUrl}/v1/authorities/${encodeURIComponent(e.collectionId)}/operations/${t}`,v=JSON.stringify(o),S=e.authority?await this.authorityProofHeaders(e,"POST",y,v,e.authority.accessToken):{},b=await fetch(y,{method:"POST",headers:{authorization:`Bearer ${e.authority?.accessToken??e.accessToken}`,"content-type":"application/json",...S},body:v,signal:a.signal});return b.ok&&this.setRoute(e.authority?"remote":"relay"),{response:b,requestId:u,encryptedRequest:c,pendingMutation:l,resumingMutation:d}}directCapable(e){return!(!e||e.authority||!e.encryption||!e.grantId||!e.keyHandle||this.directAccessMode==="disabled"||typeof location<"u"&&e.applicationOrigin&&e.applicationOrigin!==location.origin)}hasResumableMutationTransport(){return!!this.currentToken()}directEligible(e){return e!==null&&this.directCapable(e)&&this.storage.getItem(this.directPreferenceKey())!=="disabled"}async shouldAttemptDirect(e){if(!this.directEligible(e))return!1;if(this.directStatus==="available")return!0;if(this.directStatus==="unavailable"&&Date.now()<this.directRetryAt)return!1;let t=await F();return t==="denied"?(this.setDirectStatus("denied"),!1):(t==="prompt"||t===null)&&this.storage.getItem(this.directPreferenceKey())!=="enabled"?(this.setDirectStatus("permission_required"),!1):(this.setDirectStatus("checking"),!0)}async probeDirectAccess(){this.setDirectStatus("checking");try{let e=await fetch(`${this.loopbackUrl}/v1/ready`,le({method:"GET",cache:"no-store"})),t=await e.json().catch(()=>null);if(e.ok&&t?.service==="mdbase-connect"&&t?.loopback_protocol_version===1&&t?.encrypted_protocol_version===1)return this.markDirectAvailable(),"available"}catch{}return await F()==="denied"?this.setDirectStatus("denied"):(this.markDirectUnavailable(),"unavailable")}markDirectAvailable(){this.directFailures=0,this.directRetryAt=0,this.setDirectStatus("available")}markDirectUnavailable(){this.directFailures+=1,this.directRetryAt=Date.now()+Math.min(6e4,1e3*2**(this.directFailures-1)),this.setDirectStatus("unavailable")}setDirectStatus(e){return this.directStatus!==e&&(this.directStatus=e,this.emitConnection()),e}setRoute(e){this.currentRoute!==e&&(this.currentRoute=e,this.emitConnection())}emitConnection(){this.onChange()}invalidateRejectedAuthorization(e){let t=w(this.storage.getItem(this.tokenKey()));!t||!De(t,e)||(this.internals.removeToken(this.collectionId,t.keyHandle),this.currentRoute="relay",this.directStatus=this.directAccessMode==="disabled"?"disabled":"unavailable",this.emitConnection())}currentToken(){let e=this.storage.getItem(this.tokenKey()),t=w(e),i=r=>(this.internals.removeToken(this.collectionId,typeof r=="string"?r:void 0,"invalid_stored_grant"),null);if(!t)return e&&i(),null;if(t.version!==1||typeof t.accessToken!="string"||t.accessToken.length===0||typeof t.clientId!="string"||t.clientId.length===0||t.collectionId!==this.collectionId||typeof t.collectionName!="string"||t.collectionName.length===0||!Array.isArray(t.operations)||t.operations.some(r=>typeof r!="string")||typeof t.expiresAt!="number"||!Number.isFinite(t.expiresAt)||t.refreshToken!==void 0&&(typeof t.refreshToken!="string"||t.refreshToken.length===0)||t.refreshExpiresAt!==void 0&&(typeof t.refreshExpiresAt!="number"||!Number.isFinite(t.refreshExpiresAt))||!W(t.scope)||t.authority&&!Fe(t.authority,t.collectionId))return i(t.keyHandle);if(this.internals.relayEncryption==="required"){if(t.authority){if(!t.keyHandle||!t.authority.proofPublicKey)return i(t.keyHandle)}else if(!t.grantId||!t.keyHandle||!He(t.encryption,t.collectionId))return i(t.keyHandle)}return t.expiresAt<=Date.now()&&(!t.refreshToken||(t.refreshExpiresAt??0)<=Date.now())?this.directCapable(t)?t:(this.internals.removeToken(this.collectionId,t.keyHandle),null):t}async authorizedToken(){let e=this.currentToken();if(!e)return null;if(e.expiresAt>Date.now()+3e4)return e;if(!e.refreshToken||(e.refreshExpiresAt??0)<=Date.now()){if(this.directCapable(e))throw new s("relay_authorization_expired","Direct access is still available on this computer, but using the relay requires reconnecting this application.");return this.internals.removeToken(this.collectionId,e.keyHandle),null}return this.refreshAuthorization()}refreshAuthorization(){return this.refreshPromise?this.refreshPromise:(this.refreshPromise=this.performRefresh().finally(()=>{this.refreshPromise=null}),this.refreshPromise)}async performRefresh(){let e=this.currentToken();if(!e?.refreshToken)throw new s("not_authorized","Reconnect this application to continue.");if((e.refreshExpiresAt??0)<=Date.now())throw new s("relay_authorization_expired","Direct access is still available on this computer, but using the relay requires reconnecting this application.");let t=e.refreshToken,i=`${this.serverUrl}/oauth/token`,r=new URLSearchParams({grant_type:"refresh_token",refresh_token:e.refreshToken,client_id:e.clientId}).toString(),a=e.authority?await this.authorityProofHeaders(e,"POST",i,r,e.refreshToken):{},o=await fetch(i,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded",...a},body:r}),c=await o.json();if(!o.ok){let l=this.currentToken();if(l?.refreshToken&&l.refreshToken!==t)return l;throw this.directCapable(e)||this.internals.removeToken(this.collectionId,e.keyHandle),m(c,"authorization_expired","Reconnect this application to continue.",o.status)}return this.storeTokenResponse(c,e.clientId,e.keyHandle)}async authorityProofHeaders(e,t,i,r,a){if(!e.authority?.proofPublicKey)return{};if(!e.keyHandle)throw new s("missing_grant_key","Reconnect this application to restore remote authority request signing.");try{let o=new URL(i);return await ke(this.keyStore,e.keyHandle,e.authority.proofPublicKey,{method:t,target:`${o.pathname}${o.search}`,body:r,credential:a})}catch(o){throw o instanceof f?new s(o.code,o.message):o}}storeTokenResponse(e,t,i){if(e.collection_id!==this.collectionId)throw new s("collection_mismatch","The refreshed authorization belongs to a different collection.");let r=this.internals.storeTokenResponse(e,t,i);return this.currentRoute=r.authority?"remote":"relay",this.directStatus=r.authority||this.directAccessMode==="disabled"?"disabled":"unavailable",this.emitConnection(),r}tokenKey(){return this.internals.tokenKey(this.collectionId)}notificationKey(e="web_push"){return this.internals.notificationKey(this.collectionId,e)}pendingMutationKey(){return this.internals.pendingMutationKey(this.collectionId)}clearPendingMutation(){this.storage.removeItem(this.pendingMutationKey())}directPreferenceKey(){return this.internals.directPreferenceKey()}};var C=["describe","changes","read","query"];var L=class{constructor(e,t){this.internals=e;this.collectionId=t;this.transport=new X({serverUrl:e.serverUrl,storage:e.storage,keyStore:e.keyStore,directAccessMode:e.directAccessMode,loopbackUrl:e.loopbackUrl,collectionId:t,internals:e,onChange:()=>this.emitConnection()}),this.collectionClient=new N({operation:(i,r,a)=>this.transport.performOperation(i,r,a)}),this.notifications=new Z({serverUrl:e.serverUrl,storage:e.storage,authorizedToken:()=>this.transport.authorizedToken(),register:()=>this.register(),notificationKey:i=>e.notificationKey(t,i)})}internals;collectionId;collectionClient;notifications;transport;connectionListeners=new Set;get displayName(){return this.transport.currentToken()?.collectionName??`Collection ${this.collectionId.slice(0,8)}`}get operations(){return[...this.transport.currentToken()?.operations??[]]}get scope(){let e=this.transport.currentToken()?.scope;if(!e)throw new s("not_authorized","This collection is no longer authorized for this application.");return e}get directAccess(){return this.transport.directAccess}get route(){return this.transport.route}register(){return this.internals.register()}info(){let e=this.transport.currentToken();return e?{collectionId:e.collectionId,displayName:e.collectionName,operations:[...e.operations],scope:e.scope,route:this.transport.route,directAccess:this.transport.directAccess}:null}authorizationCapabilities(e=C){let t=this.operations,i=k(e).filter(r=>!t.includes(r));return{authorized:this.info()!==null,sufficient:this.info()!==null&&i.length===0,collectionId:this.collectionId,grantedOperations:t,missingOperations:i}}hasOperations(e){return this.authorizationCapabilities(e).sufficient}authorize(e={}){return this.internals.authorize({...e,target:{kind:"collection",collectionId:this.collectionId}})}async requestOperations(e,t={}){let i=this.authorizationCapabilities(e);return i.sufficient?{kind:"unchanged",connection:this}:this.authorize({...t,operations:k([...i.grantedOperations,...i.missingOperations])})}onConnectionChange(e){return this.connectionListeners.add(e),e(this.info()),()=>this.connectionListeners.delete(e)}notifyStorageChanged(){this.transport.notifyStorageChanged()}checkDirectAccess(){return this.transport.checkDirectAccess()}requestDirectAccess(){return this.transport.requestDirectAccess()}disableDirectAccess(){this.transport.disableDirectAccess()}sync(){let e=this.transport.currentToken();if(!e)return null;let t=e.collectionId;if(!e.authority){if(!e.grantId||!e.operations.includes("sync"))return null;let r=e.grantId;return{collectionId:t,replicaId:r,transport:{openSession:()=>this.transport.performOperation("sync",{action:"open_session"}),snapshot:(a,o)=>this.transport.performOperation("sync",{action:"snapshot",snapshot_id:a,...o?{page:o}:{}}),changes:(a,o=200)=>this.transport.performOperation("sync",{action:"changes",after:a,limit:o}),mutate:a=>this.transport.performOperation("sync",{action:"mutate",mutation:a})}}}let i=e.authority.replicaId;return{collectionId:t,replicaId:i,transport:{openSession:()=>this.transport.performAuthoritySyncRequest(t,i,"POST","sessions"),snapshot:(r,a)=>{let o=new URLSearchParams({snapshot_id:r});return a&&o.set("page",a),this.transport.performAuthoritySyncRequest(t,i,"GET",`snapshot?${o}`)},changes:(r,a=200)=>this.transport.performAuthoritySyncRequest(t,i,"GET",`changes?${new URLSearchParams({after:String(r),limit:String(a)})}`),mutate:r=>this.transport.performAuthoritySyncRequest(t,i,"POST","mutations",r)}}}registerNotifications(e){return this.notifications.registerNotifications(e)}registerNativeNotifications(e){return this.notifications.registerNativeNotifications(e)}unregisterNativeNotifications(){return this.notifications.unregisterNativeNotifications()}unregisterNotifications(e){return this.notifications.unregisterNotifications(e)}forget(){let e=this.transport.currentToken();this.internals.removeToken(this.collectionId,e?.keyHandle,"not_authorized"),this.transport.notifyStorageChanged()}describe(){return this.collectionClient.describe()}changes(e={},t){return this.collectionClient.changes(e,t)}read(e){return this.collectionClient.read(e)}query(e={},t){return this.collectionClient.query(e,t)}queryPages(e={},t={}){return this.collectionClient.queryPages(e,t)}queryAll(e={},t={}){return this.collectionClient.queryAll(e,t)}listViews(){return this.collectionClient.listViews()}executeView(e){return this.collectionClient.executeView(e)}readViewSource(e){return this.collectionClient.readViewSource(e)}createViewSource(e){return this.collectionClient.createViewSource(e)}updateViewSource(e){return this.collectionClient.updateViewSource(e)}deleteViewSource(e){return this.collectionClient.deleteViewSource(e)}create(e){return this.collectionClient.create(e)}update(e){return this.collectionClient.update(e)}delete(e,t){return this.collectionClient.delete(e,t)}preflightDelete(e,t){return this.collectionClient.preflightDelete(e,t)}rename(e,t){return this.collectionClient.rename(e,t)}preflightRename(e,t){return this.collectionClient.preflightRename(e,t)}async renameWithProgress(e,t={}){let i=Date.now(),r=this.pendingMutation()?.operation==="rename",a,o=(c,l,d=0)=>{t.onProgress?.({operation:"rename",state:c,elapsedMs:Date.now()-i,cancellable:l,resumed:r,completedUnits:d,...a?{estimate:a}:{}})};try{I(t.signal),o("preflighting",!0);let c=t.preflight??O(await this.preflightRename(e,{signal:t.signal}));ze(e,c),a=Ke(e,c),o("ready",!0),I(t.signal);let l=this.transport.hasResumableMutationTransport();o("applying",l);let d=await this.rename(e,l?{signal:t.signal}:void 0);return o("completed",!1,a.totalUnits),d}catch(c){throw ue(c,t.signal)&&o("cancelled",!1),c}}async deleteWithProgress(e,t={}){let i=Date.now(),r=this.pendingMutation()?.operation==="delete",a,o=(c,l,d=0)=>{t.onProgress?.({operation:"delete",state:c,elapsedMs:Date.now()-i,cancellable:l,resumed:r,completedUnits:d,...a?{estimate:a}:{}})};try{I(t.signal),o("preflighting",!0);let c=t.preflight??O(await this.preflightDelete(e,{signal:t.signal}));Ue(e,c),a=qe(c),o("ready",!0),I(t.signal);let l=this.transport.hasResumableMutationTransport();o("applying",l);let d=await this.delete(e,l?{signal:t.signal}:void 0);return o("completed",!1,a.totalUnits),d}catch(c){throw ue(c,t.signal)&&o("cancelled",!1),c}}pendingMutation(){return this.transport.pendingMutation()}async resumePendingMutation(e,t){return this.transport.resumePendingMutation(e,t)}validate(e={}){return this.collectionClient.validate(e)}readType(e){return this.collectionClient.readType(e)}createType(e){return this.collectionClient.createType(e)}updateType(e){return this.collectionClient.updateType(e)}installTypePack(e){return this.collectionClient.installTypePack(e)}listTimers(e){return this.collectionClient.listTimers(e)}putTimer(e){return this.collectionClient.putTimer(e)}cancelTimer(e){return this.collectionClient.cancelTimer(e)}reconcileTimers(e){return this.collectionClient.reconcileTimers(e)}async*watch(e={}){yield*this.collectionClient.watch(e)}async operation(e,t,i){return this.collectionClient.operation(e,t,i)}emitConnection(){let e=this.info();for(let t of this.connectionListeners)t(e)}};function $(n){for(let e of["code","state","error","error_description"])n.searchParams.delete(e);return n}function ee(n){let e;try{e=new URL(n)}catch{return!1}return e.searchParams.has("state")&&(e.searchParams.has("code")||e.searchParams.has("error"))}function We(n){if(!(n instanceof s)||!n.details||typeof n.details!="object"||Array.isArray(n.details))return;let e=n.details.returnTo;return typeof e=="string"?e:void 0}var G=class{constructor(e,t){this.connect=e;this.operations=k(t.operations??C),this.selection=t.selection,this.autoSelect=t.autoSelect??"only",this.snapshot={status:"unselected",connections:[]},this.refresh()}connect;operations;selection;autoSelect;listeners=new Set;snapshot;snapshotKey="";stopConnections;stopSelection;stopActiveConnection;activeCollectionId=null;unavailableReason="not_authorized";started=!1;refreshing=!1;refreshQueued=!1;transactionDepth=0;callbackPromise=null;async start(){this.started||(this.started=!0,this.stopConnections=this.connect.onConnectionsChange(()=>this.refresh()),this.stopSelection=this.selection.subscribe(()=>{this.unavailableReason="not_authorized",this.refresh()}));let e=this.selection.authorizationCallback();return e?await this.handleAuthorizationCallback(e):this.autoSelectOnlyConnection(),this.refresh(),this.snapshot}destroy(){this.stopConnections?.(),this.stopSelection?.(),this.stopActiveConnection?.(),this.stopConnections=void 0,this.stopSelection=void 0,this.stopActiveConnection=void 0,this.activeCollectionId=null,this.started=!1}getSnapshot(){return this.snapshot}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}select(e,t={}){let i=this.connect.connection(e);if(!i)throw new s("unknown_collection","This collection is not authorized for this application.");return this.unavailableReason="not_authorized",this.selection.select(e,t),this.refresh(),i}clearSelection(e={}){this.unavailableReason="not_authorized",this.selection.select(null,e),this.refresh()}forget(e){this.transactionDepth+=1;try{let t=this.selection.selectedCollectionId()===e;this.connect.connection(e)?.forget(),t&&this.selection.select(null,{history:"replace"})}finally{this.transactionDepth-=1,this.refresh()}}async authorize(e,t={}){let i=this.selection.selectedCollectionId();if(e==="selected"&&!i)throw new s("collection_not_selected","Choose a collection before updating its access.");let r=typeof e=="object"?e.collectionId:e==="selected"?i:null;this.transactionDepth+=1;try{let a=await this.connect.authorize({...t,operations:this.operations,target:r===null?{kind:"choose"}:{kind:"collection",collectionId:r},returnTo:this.selection.authorizationReturnTo()});return a.kind==="connected"&&this.selection.finishAuthorization(a.returnTo,a.connection.collectionId),a}finally{this.transactionDepth-=1,this.refresh()}}async ensureOperations(e){let t=this.snapshot;if(t.status!=="ready")throw new s("collection_not_ready","Choose an authorized collection first.");let i=k(e),r=t.connection.authorizationCapabilities(i);if(r.sufficient)return{kind:"unchanged",connection:t.connection};this.transactionDepth+=1;try{let a=await this.connect.authorize({operations:k([...r.grantedOperations,...r.missingOperations]),target:{kind:"collection",collectionId:t.collectionId},returnTo:this.selection.authorizationReturnTo()});return a.kind==="connected"&&this.selection.finishAuthorization(a.returnTo,a.connection.collectionId),a}finally{this.transactionDepth-=1,this.refresh()}}handleAuthorizationCallback(e){if(!ee(e))return Promise.reject(new s("invalid_callback","This URL is not an authorization callback."));if(this.callbackPromise)return this.callbackPromise;this.transactionDepth+=1;let t=this.connect.completeAuthorization(e).then(i=>(this.unavailableReason="not_authorized",this.selection.finishAuthorization(i.returnTo,i.connection.collectionId),this.refresh(),i.connection)).catch(i=>{let r=We(i);throw this.selection.clearAuthorizationCallback(r),this.refresh(),i}).finally(()=>{this.transactionDepth-=1,this.refresh(),this.callbackPromise===t&&(this.callbackPromise=null)});return this.callbackPromise=t,t}autoSelectOnlyConnection(){if(this.autoSelect!=="only"||this.selection.selectedCollectionId())return;let e=this.connect.connections();e.length===1&&this.selection.select(e[0].collectionId,{history:"replace"})}refresh(){if(this.transactionDepth>0){this.refreshQueued=!0;return}if(this.refreshing){this.refreshQueued=!0;return}this.refreshing=!0;try{do this.refreshQueued=!1,this.refreshOnce();while(this.refreshQueued)}finally{this.refreshing=!1}}refreshOnce(){let e=this.selection.selectedCollectionId(),t=this.connect.connections(),i=e?this.connect.connection(e):null;i?.collectionId!==this.activeCollectionId&&(this.stopActiveConnection?.(),this.activeCollectionId=i?.collectionId??null,this.stopActiveConnection=i?.onConnectionChange(o=>{!o&&this.selection.selectedCollectionId()===i.collectionId&&(this.unavailableReason="authorization_lost"),this.refresh()}));let r;if(!e)r={status:"unselected",connections:t};else if(!i||!i.info())r={status:"unavailable",collectionId:e,reason:this.connect.unavailableReason(e)??this.unavailableReason,connections:t};else{let o=i.info();r={status:"ready",collectionId:e,connection:i,info:o,access:i.authorizationCapabilities(this.operations),connections:t}}let a=bt(r);if(a!==this.snapshotKey){this.snapshot=r,this.snapshotKey=a;for(let o of this.listeners)o()}}};function bt(n){return n.status==="unselected"?JSON.stringify({status:n.status,connections:n.connections}):n.status==="unavailable"?JSON.stringify({status:n.status,collectionId:n.collectionId,reason:n.reason,connections:n.connections}):JSON.stringify({status:n.status,collectionId:n.collectionId,info:n.info,access:n.access,connections:n.connections})}var ye=class{internals;constructor(e){this.internals=new fe(e)}register(){return this.internals.register()}authorize(e={}){return this.internals.authorize(e)}createSession(e){return new G(this,e)}environment(){return this.internals.environment()}completeAuthorization(e=Be()){return this.internals.completeAuthorization(e)}connections(){return this.internals.connections()}connection(e){return this.internals.connection(e)}unavailableReason(e){return this.internals.unavailableReason(e)}onConnectionsChange(e){return this.internals.onConnectionsChange(e)}forgetAll(){for(let e of this.connections())this.connection(e.collectionId)?.forget()}},fe=class{serverUrl;manifest;manifestSource;redirectUri;storage;relayEncryption;keyStore;directAccessMode;loopbackUrl;navigate;credentialStorage;application=null;completionPromises=new Map;connectionCache=new Map;listeners=new Set;invalidatedConnections=new Map;constructor(e){this.serverUrl=Le(e.serverUrl),this.manifest=e.manifest??$e(),this.manifestSource=typeof this.manifest=="string"?this.manifest:this.manifest.distribution==="portable"?`bundle:${this.manifest.id}:${Ye(this.manifest)}`:`bundle:${this.manifest.id}`;let t=Qe(this.manifest);this.redirectUri=e.redirectUri??(typeof this.manifest!="string"&&this.manifest.distribution==="portable"?"":Ge()),this.storage=e.storage??Je(t),this.relayEncryption=e.relayEncryption??"required",this.keyStore=e.keyStore??(t?new M:new A),this.credentialStorage=e.storage||e.keyStore?"custom":this.storage instanceof T?"memory":"persistent",this.directAccessMode=e.directAccess??"auto",this.loopbackUrl=je(e.loopbackUrl??`http://127.0.0.1:${28485}`),this.navigate=e.navigate,typeof window<"u"&&this.storage===window.localStorage&&window.addEventListener("storage",i=>{i.storageArea!==this.storage||!i.key?.startsWith(this.storagePrefix())||(this.connectionCache.get(vt(i.key))?.notifyStorageChanged(),this.emitConnections())})}environment(){let e=typeof this.manifest!="string"&&this.manifest.distribution==="portable"?"portable":this.application?.distribution??"web";return{distribution:e,applicationOrigin:e==="portable"?"null":this.defaultApplicationOrigin(),credentialStorage:this.credentialStorage}}async register(){if(this.application)return this.application;let e=await fetch(`${this.serverUrl}/v1/apps/register`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({manifest:await this.loadManifest()})}),t=await e.json();if(!e.ok)throw m(t,"discovery_failed","Application discovery failed.",e.status);return this.application=t.application,this.application}async loadManifest(){if(typeof this.manifest!="string")return this.manifest;let e=this.manifest,t;try{t=await fetch(e,{headers:{accept:"application/json"}})}catch(i){throw new s("manifest_load_failed","The bundled application declaration could not be loaded.",{cause:i})}if(!t.ok)throw new s("manifest_load_failed",`The bundled application declaration returned HTTP ${t.status}.`,{status:t.status});try{return await t.json()}catch(i){throw new s("invalid_application_manifest","The bundled application declaration is not valid JSON.",{cause:i})}}async authorize(e={}){if(typeof location>"u"&&!this.navigate&&!e.openVerification)throw new s("browser_required","Authorization navigation requires a browser environment.");let i=typeof this.manifest!="string"&&this.manifest.distribution==="portable"&&!e.openVerification&&typeof window<"u"?window.open(`${this.serverUrl}/device`,"mdbase-connect-authorization","popup,width=620,height=760"):null,r;try{r=await this.register()}catch(y){throw i?.close(),y}if(r.distribution==="portable")return this.authorizePortable(r,e,i);i?.close();let{verifier:a,challenge:o}=await V(),c=R(24),l=e.target?.kind==="collection"?e.target.collectionId:void 0,d=this.relayEncryption==="required"?`grant:${r.id}:${c}`:void 0,u=d?await this.keyStore.create(d):void 0,p={version:1,verifier:a,state:c,clientId:r.id,redirectUri:this.redirectUri,relayEncryption:this.relayEncryption,collectionId:l,returnTo:e.returnTo,keyHandle:d,applicationAgreementPublicKey:u?.agreementPublicKey,applicationSigningPublicKey:u?.signingPublicKey};this.storage.setItem(this.pendingKey(c),JSON.stringify(p));let h=new URL(`${this.serverUrl}/oauth/authorize`);return h.searchParams.set("client_id",r.id),h.searchParams.set("redirect_uri",this.redirectUri),h.searchParams.set("code_challenge",o),h.searchParams.set("code_challenge_method","S256"),h.searchParams.set("state",c),h.searchParams.set("operations",k(e.operations??C).join(",")),l&&h.searchParams.set("collection_id",l),u&&(h.searchParams.set("relay_protocol","1"),h.searchParams.set("application_agreement_public_key",u.agreementPublicKey),h.searchParams.set("application_signing_public_key",u.signingPublicKey)),this.navigate?await this.navigate(h.href):location.assign(h.href),{kind:"redirecting"}}async authorizePortable(e,t,i){if(this.relayEncryption!=="required")throw i?.close(),new s("encryption_required","Downloaded applications require encrypted relay authorization.");let{verifier:r,challenge:a}=await V(),o=`grant:${e.id}:${R(24)}`,c=await this.keyStore.create(o),l,d;try{l=await fetch(`${this.serverUrl}/oauth/device_authorization`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:e.id,operations:k(t.operations??C).join(","),...t.target?.kind==="collection"?{collection_id:t.target.collectionId}:{},code_challenge:a,code_challenge_method:"S256",relay_protocol:"1",application_agreement_public_key:c.agreementPublicKey,application_signing_public_key:c.signingPublicKey})}),d=await l.json()}catch(h){throw i?.close(),await this.keyStore.delete(o),new s("device_authorization_failed","Downloaded application authorization could not be started.",{cause:h})}if(!l.ok)throw i?.close(),await this.keyStore.delete(o),m(d,"device_authorization_failed","Downloaded application authorization could not be started.",l.status);let u;try{u=Ve(d)}catch(h){throw i?.close(),await this.keyStore.delete(o),h}if(t.onDeviceCode?.(u),t.openVerification)await t.openVerification(u);else if(i)try{i.location.href=u.verificationUriComplete}catch{}else throw await this.keyStore.delete(o),new s("approval_window_blocked","The approval window was blocked. Show the provided verification link and code, then try again.",{details:u});let p=u.intervalSeconds;try{for(;Date.now()<u.expiresAt;){if(await q(p*1e3,t.signal),t.signal?.aborted)throw new s("authorization_cancelled","Downloaded application authorization was cancelled.");let h;try{h=await fetch(`${this.serverUrl}/oauth/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"urn:ietf:params:oauth:grant-type:device_code",device_code:d.device_code,client_id:e.id,code_verifier:r}),signal:t.signal})}catch(g){if(t.signal?.aborted)throw new s("authorization_cancelled","Downloaded application authorization was cancelled.",{cause:g});continue}let y=await h.json();if(!h.ok){let g=he(y);if(g==="authorization_pending")continue;if(g==="slow_down"){p+=5;continue}throw m(y,"token_exchange_failed","Downloaded application authorization could not be completed.",h.status)}let v=Y(y.authority,y.collection_id),S=y.encryption&&y.encryption.protocol_version===1&&y.encryption.suite===x&&y.encryption.application_agreement_public_key===c.agreementPublicKey;if(y.application_origin!=="null")throw new s("invalid_token_response","Authorization did not bind the portable grant to its opaque application origin.");if(y.authority&&(!v||y.encryption!=null||y.authority.proof_public_key!==c.signingPublicKey))throw new s("invalid_token_response","Authorization returned a remote authority capability that is not bound to this portable grant key.");if(!y.authority&&!S)throw new s("encryption_required","Authorization did not establish the expected key-bound local portable grant.");let b=this.storeTokenResponse(y,e.id,o);if(t.target?.kind==="collection"&&t.target.collectionId!==b.collectionId)throw this.removeToken(b.collectionId,b.keyHandle),new s("collection_mismatch","The approved collection does not match the collection requested by this link.");return i?.close(),{kind:"connected",connection:this.connection(b.collectionId),...t.returnTo?{returnTo:t.returnTo}:{}}}throw new s("expired_token","The downloaded application authorization code expired.")}catch(h){throw i?.close(),await this.keyStore.delete(o),h}}completeAuthorization(e){let t=new URL(e).searchParams.get("state");if(!t)return Promise.reject(new s("invalid_callback","Authorization callback is missing its state."));let i=this.completionPromises.get(t);if(i)return i;let a=this.performAuthorizationCompletion(e,t).finally(()=>{this.completionPromises.get(t)===a&&this.completionPromises.delete(t)});return this.completionPromises.set(t,a),a}async performAuthorizationCompletion(e,t){let i=new URL(e),r=i.searchParams.get("code"),a=this.pendingKey(t),o=w(this.storage.getItem(a));if(!o||o.version!==1||t!==o.state)throw new s("invalid_callback","Authorization callback is missing or does not match this browser session.");if(i.searchParams.has("error"))throw o.keyHandle&&await this.keyStore.delete(o.keyHandle),this.storage.removeItem(a),new s(i.searchParams.get("error")??"access_denied",i.searchParams.get("error_description")??"Collection access was not approved.",{details:o.returnTo?{returnTo:o.returnTo}:void 0});if(!r)throw new s("invalid_callback","Authorization callback is missing its code.");let c=await fetch(`${this.serverUrl}/oauth/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:r,client_id:o.clientId,redirect_uri:o.redirectUri,code_verifier:o.verifier})}),l=await c.json();if(!c.ok)throw m(l,"token_exchange_failed","Authorization could not be completed.",c.status);if(o.relayEncryption==="required"&&!l.authority&&(!l.encryption||!o.keyHandle||l.encryption.application_agreement_public_key!==o.applicationAgreementPublicKey))throw o.keyHandle&&await this.keyStore.delete(o.keyHandle),this.storage.removeItem(a),new s("encryption_required","Authorization did not establish the required encrypted relay grant.");if(l.authority?.proof_public_key){if(!o.keyHandle||!o.applicationSigningPublicKey||l.authority.proof_public_key!==o.applicationSigningPublicKey)throw o.keyHandle&&await this.keyStore.delete(o.keyHandle),this.storage.removeItem(a),new s("invalid_token_response","Authorization returned a remote authority capability bound to another application key.")}else l.authority&&o.keyHandle&&await this.keyStore.delete(o.keyHandle);let d=this.storeTokenResponse(l,o.clientId,l.authority?.proof_public_key?o.keyHandle:l.authority?void 0:o.keyHandle);if(o.collectionId&&o.collectionId!==d.collectionId)throw this.removeToken(d.collectionId,d.keyHandle),this.storage.removeItem(a),new s("collection_mismatch","The approved collection does not match the collection requested by this link.");return this.storage.removeItem(a),{connection:this.connection(d.collectionId),...o.returnTo?{returnTo:o.returnTo}:{}}}connections(){let e=[];for(let t of this.connectionIds()){let i=this.connection(t)?.info();i&&e.push(i)}return e.sort((t,i)=>t.displayName.localeCompare(i.displayName)||t.collectionId.localeCompare(i.collectionId))}connection(e){if(!this.storage.getItem(this.tokenKey(e)))return null;let t=this.connectionCache.get(e);return t||(t=new L(this,e),this.connectionCache.set(e,t)),t.info()?t:null}unavailableReason(e){return this.invalidatedConnections.get(e)??null}onConnectionsChange(e){return this.listeners.add(e),e(this.connections()),()=>this.listeners.delete(e)}storeTokenResponse(e,t,i){let r=e.collection_id;if(typeof r!="string")throw new s("invalid_token_response","Authorization returned no collection ID.");let a=W(e.scope);if(!a)throw new s("invalid_token_response","Authorization returned no valid collection scope.");if(e.authority&&!Y(e.authority,r))throw new s("invalid_token_response","Authorization returned an invalid remote authority capability.");if(e.authority&&e.encryption)throw new s("invalid_token_response","Authorization returned conflicting collection transports.");if(e.encryption){try{K(e.encryption)}catch{throw new s("invalid_token_response","Authorization returned an invalid encrypted relay binding.")}if(e.encryption.collection_id!==r||typeof e.grant_id!="string"||e.grant_id.length===0)throw new s("invalid_token_response","Authorization returned an encrypted relay binding for another grant.")}let o=w(this.storage.getItem(this.tokenKey(r)));if(o?.encryption&&e.encryption&&o.keyHandle&&o.keyHandle===i&&(o.grantId!==e.grant_id||o.encryption.connector_id!==e.encryption.connector_id||o.encryption.connector_agreement_public_key!==e.encryption.connector_agreement_public_key||o.encryption.application_agreement_public_key!==e.encryption.application_agreement_public_key))throw new s("connector_identity_changed","The connector identity changed during authorization renewal. Reauthorize before sending collection data.",{requiresAuthorization:!0,recovery:"reauthorize"});o?.keyHandle&&o.keyHandle!==i&&this.keyStore.delete(o.keyHandle).catch(()=>{});let c={version:1,accessToken:e.access_token,refreshToken:e.refresh_token,clientId:t,collectionId:r,collectionName:e.collection_name??`Collection ${r.slice(0,8)}`,operations:e.operations,scope:a,expiresAt:Date.now()+e.expires_in*1e3,refreshExpiresAt:e.refresh_expires_in?Date.now()+e.refresh_expires_in*1e3:void 0,grantId:e.grant_id,encryption:e.encryption??void 0,applicationOrigin:e.application_origin??this.defaultApplicationOrigin(),keyHandle:i,savedAt:Date.now(),authority:e.authority?{operationsUrl:e.authority.operations_url,syncUrl:e.authority.sync_url,replicaId:e.authority.replica_id,accessToken:e.authority.access_token,proofPublicKey:e.authority.proof_public_key}:void 0};return this.storage.setItem(this.tokenKey(r),JSON.stringify(c)),this.addConnectionId(r),this.invalidatedConnections.delete(r),this.connectionCache.delete(r),this.emitConnections(),c}removeToken(e,t,i="authorization_lost"){this.invalidatedConnections.set(e,i),t&&this.keyStore.delete(t).catch(()=>{}),this.storage.removeItem(this.tokenKey(e)),this.storage.removeItem(this.pendingMutationKey(e));for(let r of["web_push","fcm"])this.storage.removeItem(this.notificationKey(e,r));this.storage.setItem(this.connectionsKey(),JSON.stringify({version:1,collectionIds:this.connectionIds().filter(r=>r!==e)})),this.connectionCache.delete(e),this.emitConnections()}tokenKey(e){return`${this.storagePrefix()}:token:${e}`}pendingMutationKey(e){return`${this.storagePrefix()}:pending-mutation:${e}`}notificationKey(e,t="web_push"){return`${this.storagePrefix()}:notifications:${e}:${t}`}directPreferenceKey(){return`mdbase-connect:direct:${this.defaultApplicationOrigin()}`}defaultApplicationOrigin(){if(typeof this.manifest!="string"&&this.manifest.distribution==="portable"||this.application?.distribution==="portable")return"null";let e=new URL(this.redirectUri);if(["http:","https:"].includes(e.protocol))return e.origin;if(typeof location<"u")return location.origin;if(this.manifest&&typeof this.manifest!="string")return new URL(this.manifest.homepage).origin;try{return new URL(this.manifestSource).origin}catch{return""}}pendingKey(e){return`${this.storagePrefix()}:pending:${e}`}storagePrefix(){return`mdbase-connect:${this.serverUrl}:${this.manifestSource}`}connectionsKey(){return`${this.storagePrefix()}:connections`}connectionIds(){let e=w(this.storage.getItem(this.connectionsKey()));return e?.version===1&&Array.isArray(e.collectionIds)&&e.collectionIds.every(t=>typeof t=="string")?e.collectionIds:[]}addConnectionId(e){this.storage.setItem(this.connectionsKey(),JSON.stringify({version:1,collectionIds:[...new Set([...this.connectionIds(),e])]}))}emitConnections(){let e=this.connections();for(let t of this.listeners)t(e)}};function vt(n){let e=":token:",t=n.lastIndexOf(e);return t<0?"":n.slice(t+e.length)}function Ze(n){if(!n||typeof n!="object")throw new s("invalid_push_payload","The push payload is not an object.");let e=n;if(e.type!=="mdbase.notification"||e.version!==1||typeof e.signal_id!="string"||typeof e.criterion_id!="string"||typeof e.cursor!="string"||!e.presentation||typeof e.presentation.title!="string")throw new s("invalid_push_payload","The push payload is not an mdbase notification.");return e}function _t(n){if(!n||typeof n!="object")throw new s("invalid_push_payload","The native notification data is not an object.");let e=n;if(e.type!=="mdbase.notification"||e.version!==1&&e.version!=="1"||typeof e.signal_id!="string"||typeof e.criterion_id!="string"||typeof e.cursor!="string")throw new s("invalid_push_payload","The native notification data is not an mdbase notification.");return{type:"mdbase.notification",version:1,signal_id:e.signal_id,criterion_id:e.criterion_id,cursor:e.cursor}}function kt(n,e){let t=Ze(e);return n.showNotification(t.presentation.title,{...t.presentation.body?{body:t.presentation.body}:{},...t.presentation.tag?{tag:t.presentation.tag}:{},data:{type:t.type,signal_id:t.signal_id,criterion_id:t.criterion_id,cursor:t.cursor}})}var ge=class{collectionParameter;fallbackPath;listeners=new Set;handlePopState=()=>this.emit();constructor(e={}){this.collectionParameter=e.collectionParameter??"collection",this.fallbackPath=e.fallbackPath??"/"}selectedCollectionId(){return this.currentUrl().searchParams.get(this.collectionParameter)}select(e,t={}){let i=$(this.currentUrl());e?i.searchParams.set(this.collectionParameter,e):i.searchParams.delete(this.collectionParameter);let r=this.browserHistory();r[t.history==="push"?"pushState":"replaceState"](r.state,"",i),this.emit()}authorizationReturnTo(){let e=$(this.currentUrl());return`${e.pathname}${e.search}${e.hash}`}authorizationCallback(){let e=this.currentUrl().href;return ee(e)?e:null}finishAuthorization(e,t){let i=this.safeAppUrl(e??this.fallbackPath);$(i),i.searchParams.set(this.collectionParameter,t),this.browserHistory().replaceState(null,"",i),this.emit()}clearAuthorizationCallback(e){let t=e?this.safeAppUrl(e):this.currentUrl(),i=this.browserHistory();i.replaceState(i.state,"",$(t)),this.emit()}subscribe(e){let t=this.listeners.size===0;return this.listeners.add(e),t&&typeof window<"u"&&window.addEventListener("popstate",this.handlePopState),()=>{this.listeners.delete(e),this.listeners.size===0&&typeof window<"u"&&window.removeEventListener("popstate",this.handlePopState)}}emit(){for(let e of this.listeners)e()}safeAppUrl(e){let t=this.currentUrl(),i=new URL(e,t.origin);return i.origin===t.origin?i:new URL(this.fallbackPath,t.origin)}currentUrl(){if(typeof location>"u")throw new s("browser_required","Browser selection requires a browser environment.");return new URL(location.href)}browserHistory(){if(typeof history>"u")throw new s("browser_required","Browser selection requires a browser environment.");return history}},me=class{collectionId=null;listeners=new Set;selectedCollectionId(){return this.collectionId}select(e){if(e!==this.collectionId){this.collectionId=e;for(let t of this.listeners)t()}}authorizationReturnTo(){}authorizationCallback(){return null}finishAuthorization(e,t){this.select(t)}clearAuthorizationCallback(){}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};return rt(St);})();
|
|
1
|
+
"use strict";var MdbaseConnect=(()=>{var We=Object.defineProperty;var xn=Object.getOwnPropertyDescriptor;var Mn=Object.getOwnPropertyNames;var Fn=Object.prototype.hasOwnProperty;var Un=(n,e)=>{for(var t in e)We(n,t,{get:e[t],enumerable:!0})},Dn=(n,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Mn(e))!Fn.call(n,i)&&i!==t&&We(n,i,{get:()=>e[i],enumerable:!(o=xn(e,i))||o.enumerable});return n};var zn=n=>Dn(We({},"__esModule",{value:!0}),n);var jo={};Un(jo,{ALL_CONNECT_PROBLEM_CODES:()=>lt,AUTHORIZATION_PROBLEM_CODES:()=>J,COLLECTION_CHANGES_PROBLEM_CODES:()=>ut,COLLECTION_DESCRIPTION_PROBLEM_CODES:()=>ge,COLLECTION_MUTATION_PROBLEM_CODES:()=>S,COLLECTION_QUERY_PROBLEM_CODES:()=>dt,COLLECTION_READ_PROBLEM_CODES:()=>U,COLLECTION_SETUP_PROBLEM_CODES:()=>Yt,COLLECTION_TYPE_PROBLEM_CODES:()=>ae,COMMON_OPERATION_PROBLEM_CODES:()=>Gt,ConnectOutcomeError:()=>ze,DIRECT_ACCESS_PROBLEM_CODES:()=>Le,FileTransferCryptoError:()=>L,GrantFileTransferCipher:()=>ie,IndexedDbGrantKeyStore:()=>te,MdbaseBrowserSelection:()=>Ct,MdbaseCollectionClient:()=>be,MdbaseConnect:()=>vt,MdbaseConnectError:()=>v,MdbaseConnection:()=>ke,MdbaseFileClient:()=>Se,MdbaseMemorySelection:()=>Pt,MdbaseSession:()=>Ae,MemoryGrantKeyStore:()=>ne,NOTIFICATION_PROBLEM_CODES:()=>re,REGISTRATION_PROBLEM_CODES:()=>Y,RelayCryptoError:()=>g,SESSION_PROBLEM_CODES:()=>uo,captureConnectOutcome:()=>P,connectError:()=>c,connectFailure:()=>R,connectProblem:()=>E,connectSuccess:()=>A,createPkce:()=>Ce,decryptRelayResponse:()=>oe,encryptRelayRequest:()=>V,isRetryableConnectError:()=>co,operationProblem:()=>ct,parseMdbaseNativeNotificationData:()=>Bo,parseMdbasePushPayload:()=>In,serverConnectError:()=>x,showMdbasePushNotification:()=>Ko,unknownConnectProblem:()=>st,unwrapConnectOutcome:()=>po});var H={access_denied:{category:"authorization",recovery:"reauthorize"},access_paused:{category:"availability",recovery:"resume_connector_access"},approval_window_blocked:{category:"authorization",recovery:"reauthorize"},authority_authorization_changed:{category:"authorization",recovery:"reauthorize"},authorization_cancelled:{category:"cancellation",recovery:"none"},authorization_expired:{category:"authorization",recovery:"reauthorize"},browser_required:{category:"compatibility",recovery:"none"},callback_url_required:{category:"validation",recovery:"fix_request"},change_cursor_reset:{category:"conflict",recovery:"refresh"},collection_access_denied:{category:"authorization",recovery:"reauthorize"},collection_configuration_invalid:{category:"validation",recovery:"repair_collection"},collection_contracts_missing:{category:"compatibility",recovery:"choose_collection"},collection_incompatible:{category:"compatibility",recovery:"choose_collection"},collection_invalid:{category:"validation",recovery:"repair_collection"},collection_kind_unsupported:{category:"compatibility",recovery:"choose_collection"},collection_mismatch:{category:"selection",recovery:"choose_collection"},collection_not_found:{category:"selection",recovery:"choose_collection"},collection_not_ready:{category:"selection",recovery:"choose_collection"},collection_not_selected:{category:"selection",recovery:"choose_collection"},collection_type_registry_invalid:{category:"validation",recovery:"repair_collection"},collection_version_unsupported:{category:"compatibility",recovery:"upgrade_collection"},concurrent_modification:{category:"conflict",recovery:"refresh"},connector_identity_changed:{category:"integrity",recovery:"reauthorize"},connector_offline:{category:"availability",recovery:"retry"},connector_upgrade_required:{category:"compatibility",recovery:"upgrade_connector"},device_authorization_failed:{category:"authorization",recovery:"reauthorize"},direct_operation_rejected:{category:"authorization",recovery:"reauthorize"},discovery_failed:{category:"availability",recovery:"retry"},encrypted_relay_rejected:{category:"authorization",recovery:"reauthorize"},encryption_required:{category:"authorization",recovery:"reauthorize"},expired_token:{category:"authorization",recovery:"reauthorize"},file_changed_during_move:{category:"conflict",recovery:"refresh"},file_changed_during_read:{category:"conflict",recovery:"refresh"},file_move_failed:{category:"internal",recovery:"contact_support"},file_mutation_conflict:{category:"conflict",recovery:"resolve_conflict"},file_not_found:{category:"conflict",recovery:"refresh"},file_source_mismatch:{category:"conflict",recovery:"refresh"},file_upload_incomplete:{category:"conflict",recovery:"retry"},hosted_provider_unavailable:{category:"availability",recovery:"retry"},insufficient_access:{category:"authorization",recovery:"reauthorize"},invalid_application_manifest:{category:"validation",recovery:"fix_request"},invalid_callback:{category:"validation",recovery:"fix_request"},invalid_device_authorization_response:{category:"integrity",recovery:"contact_support"},invalid_encrypted_response:{category:"integrity",recovery:"contact_support"},invalid_loopback_url:{category:"validation",recovery:"fix_request"},invalid_mutation_id:{category:"validation",recovery:"fix_request"},invalid_operation_response:{category:"integrity",recovery:"contact_support"},invalid_path:{category:"validation",recovery:"fix_request"},invalid_preflight:{category:"conflict",recovery:"refresh"},invalid_push_payload:{category:"validation",recovery:"fix_request"},invalid_push_subscription:{category:"validation",recovery:"fix_request"},invalid_request:{category:"validation",recovery:"fix_request"},invalid_token_response:{category:"integrity",recovery:"contact_support"},managed_fcm_not_declared:{category:"compatibility",recovery:"fix_request"},manifest_load_failed:{category:"availability",recovery:"retry"},manifest_required:{category:"validation",recovery:"fix_request"},missing_grant_key:{category:"authorization",recovery:"reauthorize"},no_pending_mutation:{category:"conflict",recovery:"refresh"},not_authorized:{category:"authorization",recovery:"reauthorize"},not_remote_authority:{category:"compatibility",recovery:"choose_collection"},notification_criterion_not_declared:{category:"validation",recovery:"fix_request"},notification_reauthorization_required:{category:"authorization",recovery:"reauthorize"},notification_registration_failed:{category:"availability",recovery:"retry"},notification_unregistration_failed:{category:"availability",recovery:"retry"},notifications_not_declared:{category:"compatibility",recovery:"fix_request"},notifications_unavailable:{category:"availability",recovery:"retry"},operation_cancelled:{category:"cancellation",recovery:"none"},operation_failed:{category:"internal",recovery:"contact_support"},operation_invalid:{category:"validation",recovery:"fix_request"},operation_outcome_unknown:{category:"conflict",recovery:"resolve_outcome"},path_occupied:{category:"conflict",recovery:"resolve_conflict"},pending_mutation_unresolved:{category:"conflict",recovery:"resolve_outcome"},query_snapshot_changed:{category:"conflict",recovery:"refresh"},rate_limited:{category:"availability",recovery:"retry"},redirect_uri_required:{category:"validation",recovery:"fix_request"},reference_updates_unsupported:{category:"compatibility",recovery:"fix_request"},relay_authorization_expired:{category:"authorization",recovery:"reauthorize"},relay_unavailable:{category:"availability",recovery:"retry"},sandbox_unsupported:{category:"compatibility",recovery:"fix_request"},scope_denied:{category:"authorization",recovery:"reauthorize"},stale_file_revision:{category:"conflict",recovery:"refresh"},storage_required:{category:"compatibility",recovery:"none"},sync_failed:{category:"availability",recovery:"retry"},temporarily_unavailable:{category:"availability",recovery:"retry"},timeout:{category:"availability",recovery:"retry"},token_exchange_failed:{category:"availability",recovery:"retry"},type_pack_provision_failed:{category:"validation",recovery:"repair_collection"},unknown_collection:{category:"selection",recovery:"choose_collection"},unsafe_file_path:{category:"validation",recovery:"fix_request"},unsupported_encryption:{category:"compatibility",recovery:"upgrade_application"},unsupported_operation:{category:"compatibility",recovery:"fix_request"}},Ln={access_denied:{type:"object",required:[],properties:{return_to:{type:"string"}}},approval_window_blocked:{type:"object",required:["user_code","verification_uri","verification_uri_complete","expires_at","interval_seconds"],properties:{user_code:{type:"string"},verification_uri:{type:"string"},verification_uri_complete:{type:"string"},expires_at:{type:"integer"},interval_seconds:{type:"integer"}}},collection_configuration_invalid:{type:"object",required:["diagnostics"],properties:{diagnostics:{type:"array",items:{type:"object"}}}},collection_contracts_missing:{type:"object",required:["contracts"],properties:{contracts:{type:"array",items:{type:"object",required:["id","version"],properties:{id:{type:"string"},version:{type:"string"}}}}}},collection_invalid:{type:"object",required:["diagnostics"],properties:{diagnostics:{type:"array",items:{type:"object"}}}},collection_type_registry_invalid:{type:"object",required:["diagnostics"],properties:{diagnostics:{type:"array",items:{type:"object"}}}},collection_version_unsupported:{type:"object",required:["current_version","required_version"],properties:{current_version:{type:"string"},required_version:{type:"string"}}},connector_offline:{type:"object",required:[],properties:{connector_name:{type:"string"}}},insufficient_access:{type:"object",required:["required_operations","granted_operations","missing_operations"],properties:{required_operations:{type:"array",items:{type:"string"}},granted_operations:{type:"array",items:{type:"string"}},missing_operations:{type:"array",items:{type:"string"}}}},operation_invalid:{type:"object",required:["diagnostics"],properties:{diagnostics:{type:"array",items:{type:"object"}},partial_result:{}}},rate_limited:{type:"object",required:[],properties:{retry_after_ms:{type:"integer"}}}};function Rt(n){return Object.hasOwn(H,n)}function he(n){if(!St(n))return!1;let e=n;if(e.problem_version!==1||typeof e.message!="string"||e.message.length===0||e.operation_outcome!==void 0&&e.operation_outcome!=="not_sent"&&e.operation_outcome!=="rejected"&&e.operation_outcome!=="unknown"||e.trace_id!==void 0&&(typeof e.trace_id!="string"||e.trace_id.length===0))return!1;if(e.code==="unknown")return typeof e.server_code=="string"&&e.server_code.length>0&&e.category==="unknown"&&e.recovery==="none";if(typeof e.code!="string"||!Rt(e.code)||e.server_code!==void 0)return!1;let t=H[e.code],o=Ln[e.code],i=o===void 0?e.details===void 0:e.details===void 0?(o.required?.length??0)===0:Ze(e.details,o);return e.category===t.category&&e.recovery===t.recovery&&i}function Ze(n,e){if(e.type===void 0)return!0;if(e.type==="string")return typeof n=="string";if(e.type==="integer")return typeof n=="number"&&Number.isInteger(n);if(e.type==="number")return typeof n=="number"&&Number.isFinite(n);if(e.type==="boolean")return typeof n=="boolean";if(e.type==="array")return Array.isArray(n)&&n.every(o=>Ze(o,e.items??{}));if(!St(n))return!1;if(!e.properties)return!0;let t=n;return!Object.keys(t).every(o=>Object.hasOwn(e.properties,o))||!(e.required??[]).every(o=>Object.hasOwn(t,o))?!1:Object.entries(t).every(([o,i])=>Ze(i,e.properties[o]))}function St(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function et(n,e,t={}){if(Rt(n)){let o=H[n],i={problem_version:1,code:n,category:o.category,recovery:o.recovery,message:e,...t.details===void 0?{}:{details:t.details},...t.operation_outcome===void 0?{}:{operation_outcome:t.operation_outcome},...t.trace_id===void 0?{}:{trace_id:t.trace_id}};if(he(i))return i}return{problem_version:1,code:"unknown",server_code:n,category:"unknown",recovery:"none",message:e,...t.details===void 0?{}:{details:t.details},...t.operation_outcome===void 0?{}:{operation_outcome:t.operation_outcome},...t.trace_id===void 0?{}:{trace_id:t.trace_id}}}var kt=new Uint8Array([77,68,66,70]),Ot=1,At=0,Vo=new Uint8Array([77,68,66,82]);var Tt=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,y=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name="FileFrameError"}};function Nn(n){return n==="upload_chunk"?1:2}function qn(n){if(n===1)return"upload_chunk";if(n===2)return"download_chunk";throw new y("invalid_kind",`Unknown file frame kind ${n}`)}function Bn(n){if(!n||typeof n!="object"||Array.isArray(n))throw new y("invalid_header","File frame header must be a JSON object");return n}function Ee(n,e){let t=n[e];if(typeof t!="string"||t.length===0)throw new y("invalid_header",`File frame header ${e} must be a non-empty string`);return t}function Ie(n,e){let t=Ee(n,e);if(!Tt.test(t))throw new y("invalid_header",`File frame header ${e} must be a UUID`);return t}function $(n,e,t=Number.MAX_SAFE_INTEGER){let o=n[e];if(!Number.isSafeInteger(o)||o<0||o>t)throw new y("invalid_header",`File frame header ${e} is outside its allowed range`);return o}function tt(n){if(n.protocol_version!==1)throw new y("unsupported_version",`Unsupported file transfer protocol ${n.protocol_version}`);if(n.protection!=="grant_aead_v1"&&n.protection!=="transport_tls")throw new y("invalid_header","Unknown file transfer protection");if(n.direction!=="upload"&&n.direction!=="download")throw new y("invalid_header","Unknown file transfer direction");for(let[e,t]of[["grant_id",n.grant_id],["authority_id",n.authority_id],["collection_id",n.collection_id],["transfer_id",n.transfer_id]])if(!Tt.test(t))throw new y("invalid_header",`File frame header ${e} must be a UUID`);for(let[e,t,o]of[["chunk_size",n.chunk_size,4194304],["chunk_index",n.chunk_index,Number.MAX_SAFE_INTEGER],["offset",n.offset,Number.MAX_SAFE_INTEGER],["plaintext_length",n.plaintext_length,4194304],["total_size",n.total_size,Number.MAX_SAFE_INTEGER]])if(!Number.isSafeInteger(t)||t<0||t>o)throw new y("invalid_header",`File frame header ${e} is outside its allowed range`);if(n.chunk_size<64*1024)throw new y("invalid_header","File frame chunk_size is below the protocol minimum");if(!Number.isSafeInteger(n.scope_epoch)||n.scope_epoch<1)throw new y("invalid_header","File frame header scope_epoch must be a positive integer");if(n.protection==="grant_aead_v1"&&!n.key_id)throw new y("invalid_header","AEAD-protected file frames require key_id");return{protocol_version:1,protection:n.protection,grant_id:n.grant_id,authority_id:n.authority_id,collection_id:n.collection_id,transfer_id:n.transfer_id,direction:n.direction,chunk_size:n.chunk_size,chunk_index:n.chunk_index,offset:n.offset,plaintext_length:n.plaintext_length,total_size:n.total_size,scope_epoch:n.scope_epoch,...n.key_id===void 0?{}:{key_id:n.key_id}}}function Kn(n){let e;try{e=new TextDecoder("utf-8",{fatal:!0}).decode(n)}catch{throw new y("invalid_header","File frame header is not valid UTF-8")}let t;try{t=Bn(JSON.parse(e))}catch(d){throw d instanceof y?d:new y("invalid_header","File frame header is not valid JSON")}let o=new Set(["protocol_version","protection","grant_id","authority_id","collection_id","transfer_id","direction","chunk_size","chunk_index","offset","plaintext_length","total_size","scope_epoch","key_id"]);if(Object.keys(t).some(d=>!o.has(d)))throw new y("invalid_header","File frame header contains an unknown field");let i=$(t,"protocol_version");if(i!==1)throw new y("unsupported_version",`Unsupported file transfer protocol ${i}`);let r=Ee(t,"protection"),a=Ee(t,"direction"),s=t.key_id===void 0?void 0:Ee(t,"key_id"),l=tt({protocol_version:1,protection:r,grant_id:Ie(t,"grant_id"),authority_id:Ie(t,"authority_id"),collection_id:Ie(t,"collection_id"),transfer_id:Ie(t,"transfer_id"),direction:a,chunk_size:$(t,"chunk_size",4194304),chunk_index:$(t,"chunk_index"),offset:$(t,"offset"),plaintext_length:$(t,"plaintext_length",4194304),total_size:$(t,"total_size"),scope_epoch:$(t,"scope_epoch"),...s===void 0?{}:{key_id:s}});if(JSON.stringify(l)!==e)throw new y("invalid_header","File frame header must use the canonical field order without duplicate fields or whitespace");return l}function nt(n,e,t){let o=n==="upload_chunk"?"upload":"download";if(e.direction!==o)throw new y("invalid_header",`Frame kind ${n} requires direction ${o}`);let i=e.chunk_index*e.chunk_size;if(!Number.isSafeInteger(i)||e.offset!==i)throw new y("invalid_header","Chunk offset does not match its index and protocol chunk size");if(e.offset+e.plaintext_length>e.total_size)throw new y("invalid_header","Chunk extends past the declared transfer size");let r=e.protection==="grant_aead_v1"?e.plaintext_length+16:e.plaintext_length;if(t!==r)throw new y("invalid_length","Payload length does not match the protected plaintext length")}function jn(n){return n.plaintext_length+(n.protection==="grant_aead_v1"?16:0)}function xe(n,e){let t=tt(e),o=jn(t);nt(n,t,o);let i=new TextEncoder().encode(JSON.stringify(t));if(i.byteLength>16384)throw new y("limit_exceeded","File frame header exceeds the protocol limit");let r=new Uint8Array(16+i.byteLength);r.set(kt,0);let a=new DataView(r.buffer,r.byteOffset,r.byteLength);return a.setUint8(4,Ot),a.setUint8(5,Nn(n)),a.setUint16(6,At,!1),a.setUint32(8,i.byteLength,!1),a.setUint32(12,o,!1),r.set(i,16),r}function It(n){let e=tt(n.header);if(nt(n.kind,e,n.payload.byteLength),n.payload.byteLength>4194320)throw new y("limit_exceeded","File frame payload exceeds the protocol limit");let t=xe(n.kind,e),o=new Uint8Array(t.byteLength+n.payload.byteLength);return o.set(t,0),o.set(n.payload,t.byteLength),o}function Me(n,e={}){if(n.byteLength<16)throw new y("invalid_length","File frame is shorter than its fixed prefix");if(!kt.every((f,h)=>n[h]===f))throw new y("invalid_magic","File frame magic is not MDBF");let t=new DataView(n.buffer,n.byteOffset,n.byteLength),o=t.getUint8(4);if(o!==Ot)throw new y("unsupported_version",`Unsupported file frame version ${o}`);let i=qn(t.getUint8(5));if(t.getUint16(6,!1)!==At)throw new y("unsupported_flags","File frame uses unsupported flags");let r=t.getUint32(8,!1),a=t.getUint32(12,!1),s=e.maxHeaderBytes??16384,l=e.maxPayloadBytes??4194320;if(r===0)throw new y("invalid_length","File frame header must not be empty");if(r>s||a>l)throw new y("limit_exceeded","File frame exceeds the configured decode limits");let d=16+r+a;if(!Number.isSafeInteger(d)||d!==n.byteLength)throw new y("invalid_length","File frame lengths do not match the supplied bytes");let u=16+r,p=Kn(n.subarray(16,u));return nt(i,p,a),{kind:i,header:p,payload:n.slice(u)}}var ee=1;var Et=28485,fe="P256-HKDF-SHA256-AES256GCM";var Hn="contract-setup-v1",$n="file-relay-v1",Vn=["authorization-activation","encrypted-relay","policy-ack"],Yo=[...Vn,Hn,$n],ot=1;var xt="mdbase-authority-request-proof-v1",ye={version:"x-mdbase-proof-version",timestamp:"x-mdbase-proof-timestamp",nonce:"x-mdbase-proof-nonce",signature:"x-mdbase-proof-signature"};var Gn="mdbase-connect-keys",j="grant-keys",rt=18446744073709551615n,Yn="mdbase-connect relay request key v1",Jn="mdbase-connect relay response key v1",Mt=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,te=class{database=null;async create(e){let t=await zt(e),o=await this.open();return await Ut(o,i=>i.add({...t,counter:"0"})),t}async get(e){let t=await this.open(),o=await eo(t.transaction(j).objectStore(j).get(e));return o?{handle:o.handle,agreementPrivateKey:o.agreementPrivateKey,agreementPublicKey:o.agreementPublicKey,signingPrivateKey:o.signingPrivateKey,signingPublicKey:o.signingPublicKey}:null}async nextCounter(e){let t=await this.open();return new Promise((o,i)=>{let r=t.transaction(j,"readwrite"),a=r.objectStore(j),s=a.get(e),l=null;s.onerror=()=>i(s.error),s.onsuccess=()=>{let d=s.result;if(!d){r.abort(),i(new g("missing_grant_key","The encrypted grant key is unavailable."));return}let u=BigInt(d.counter)+1n;if(u>rt){r.abort(),i(new g("counter_exhausted","The encrypted grant must be authorized again."));return}l=u.toString(),a.put({...d,counter:l})},r.onerror=()=>i(r.error),r.onabort=()=>i(r.error??new Error("Key counter transaction aborted.")),r.oncomplete=()=>{l&&o(l)}})}async delete(e){let t=await this.open();await Ut(t,o=>o.delete(e))}open(){if(typeof indexedDB>"u")throw new g("key_storage_unavailable","Encrypted relay authorization requires browser IndexedDB or an injected grant key store.");return this.database||(this.database=new Promise((e,t)=>{let o=indexedDB.open(Gn,1);o.onupgradeneeded=()=>{o.result.objectStoreNames.contains(j)||o.result.createObjectStore(j,{keyPath:"handle"})},o.onerror=()=>t(o.error),o.onsuccess=()=>e(o.result)})),this.database}},ne=class{records=new Map;sequence=Promise.resolve();async create(e){if(this.records.has(e))throw new Error(`Grant key already exists: ${e}`);let t=await zt(e);return this.records.set(e,{...t,counter:"0"}),t}async get(e){let t=this.records.get(e);return t?{handle:t.handle,agreementPrivateKey:t.agreementPrivateKey,agreementPublicKey:t.agreementPublicKey,signingPrivateKey:t.signingPrivateKey,signingPublicKey:t.signingPublicKey}:null}nextCounter(e){let t,o,i=new Promise((r,a)=>{t=r,o=a});return this.sequence=this.sequence.then(()=>{let r=this.records.get(e);if(!r)throw new g("missing_grant_key","The encrypted grant key is unavailable.");let a=BigInt(r.counter)+1n;if(a>rt)throw new g("counter_exhausted","The encrypted grant must be authorized again.");r.counter=a.toString(),t(r.counter)}).catch(r=>{o(r)}),i}async delete(e){this.records.delete(e)}};async function Dt(n,e,t,o){let i=await Xn(n,e,t),r=o.timestamp??Math.floor(Date.now()/1e3),a=o.nonce??crypto.randomUUID(),s=await Qn({...o,timestamp:r,nonce:a}),l=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},i.signingPrivateKey,new TextEncoder().encode(s));return{[ye.version]:String(ot),[ye.timestamp]:String(r),[ye.nonce]:a,[ye.signature]:me(new Uint8Array(l))}}async function Qn(n){let e=n.method.toUpperCase(),t=await Ft(n.body??""),o=await Ft(n.credential);for(let i of[e,n.target,String(n.timestamp),n.nonce])if(!i||i.includes(`
|
|
2
|
+
`)||i.includes("\r"))throw new g("invalid_proof_input","Authority request proof metadata is invalid.");return[xt,ot,e,n.target,t,o,n.timestamp,n.nonce].join(`
|
|
3
|
+
`)}async function V(n,e,t,o,i,r=crypto.randomUUID()){G(t.encryption);let a=await Lt(n,e,t.encryption.application_agreement_public_key),s=await n.nextCounter(e),l={binding:t,requestId:r,operation:o,counter:s},d=await Nt(a.agreementPrivateKey,t,"request"),u=new TextEncoder().encode(JSON.stringify(i??{})),p=await crypto.subtle.encrypt({name:"AES-GCM",iv:Kt(s),additionalData:new TextEncoder().encode(Bt(l,"request")),tagLength:128},d,u);return{type:"encrypted_operation_request",...Wn(l),ciphertext:me(new Uint8Array(p))}}async function oe(n,e,t,o,i){if(!Zn(o,i))throw new g("invalid_encrypted_response","Encrypted response metadata does not match its request.");let r=await Lt(n,e,t.encryption.application_agreement_public_key),a={binding:t,requestId:o.request_id,operation:o.operation,counter:o.counter},s=await Nt(r.agreementPrivateKey,t,"response");try{let l=await crypto.subtle.decrypt({name:"AES-GCM",iv:Kt(o.counter),additionalData:new TextEncoder().encode(Bt(a,"response")),tagLength:128},s,Ht(jt(i.ciphertext))),d=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(l));if(d?.ok===!0&&"result"in d||d?.ok===!1&&he(d.problem))return d;throw new Error("invalid response body")}catch(l){throw l instanceof g?l:new g("encrypted_response_rejected","The encrypted connector response could not be authenticated.")}}var g=class extends Error{constructor(t,o){super(o);this.code=t}code};async function zt(n){let e=await crypto.subtle.generateKey({name:"ECDH",namedCurve:"P-256"},!0,["deriveBits"]),t=me(new Uint8Array(await crypto.subtle.exportKey("raw",e.publicKey))),o=await crypto.subtle.exportKey("pkcs8",e.privateKey),i=await crypto.subtle.importKey("pkcs8",o,{name:"ECDH",namedCurve:"P-256"},!1,["deriveBits"]),r=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),a=me(new Uint8Array(await crypto.subtle.exportKey("raw",r.publicKey))),s=await crypto.subtle.exportKey("pkcs8",r.privateKey),l=await crypto.subtle.importKey("pkcs8",s,{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]);return{handle:n,agreementPrivateKey:i,agreementPublicKey:t,signingPrivateKey:l,signingPublicKey:a}}async function Lt(n,e,t){let o=await n.get(e);if(!o||o.agreementPublicKey!==t)throw new g("missing_grant_key","The encrypted grant key is unavailable or does not match the grant.");return o}async function Xn(n,e,t){let o=await n.get(e);if(!o||o.signingPublicKey!==t)throw new g("missing_grant_key","The remote authority signing key is unavailable or does not match the grant.");return o}async function Nt(n,e,t){let o=await at(n,e.encryption.connector_agreement_public_key),i=await crypto.subtle.importKey("raw",o,"HKDF",!1,["deriveKey"]),r=new TextEncoder().encode(qt(e)),a=await crypto.subtle.digest("SHA-256",r);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:a,info:new TextEncoder().encode(t==="request"?Yn:Jn)},i,{name:"AES-GCM",length:256},!1,t==="request"?["encrypt"]:["decrypt"])}async function at(n,e){try{let t=await crypto.subtle.importKey("raw",Ht(it(e)),{name:"ECDH",namedCurve:"P-256"},!1,[]);return await crypto.subtle.deriveBits({name:"ECDH",public:t},n,256)}catch{throw new g("invalid_public_key","The connector relay public key is invalid.")}}function qt(n){let e=n.encryption;return["mdbase-connect",ee,e.suite,n.grantId,n.applicationId,e.connector_id,e.collection_id,e.scope_epoch,e.key_id].join("|")}function Bt(n,e){return[qt(n.binding),n.requestId,e,n.operation,n.counter].join("|")}function Wn(n){let e=n.binding.encryption;return{protocol_version:ee,suite:fe,request_id:n.requestId,grant_id:n.binding.grantId,application_id:n.binding.applicationId,connector_id:e.connector_id,collection_id:e.collection_id,operation:n.operation,scope_epoch:e.scope_epoch,key_id:e.key_id,counter:n.counter}}function Zn(n,e){return e.type==="encrypted_operation_response"&&typeof e.ciphertext=="string"&&n.protocol_version===e.protocol_version&&n.suite===e.suite&&n.request_id===e.request_id&&n.grant_id===e.grant_id&&n.application_id===e.application_id&&n.connector_id===e.connector_id&&n.collection_id===e.collection_id&&n.operation===e.operation&&n.scope_epoch===e.scope_epoch&&n.key_id===e.key_id&&n.counter===e.counter}function G(n){if(n.protocol_version!==ee||n.suite!==fe||!Number.isSafeInteger(n.scope_epoch)||n.scope_epoch<=0||typeof n.key_id!="string"||n.key_id.length===0||n.key_id.length>200||n.key_id.includes("|"))throw new g("unsupported_encryption","The grant uses an unsupported relay encryption profile.");if(typeof n.connector_id!="string"||!Mt.test(n.connector_id)||typeof n.collection_id!="string"||!Mt.test(n.collection_id))throw new g("unsupported_encryption","The grant uses invalid encrypted relay identities.");it(n.application_agreement_public_key),it(n.connector_agreement_public_key)}function Kt(n){let e=BigInt(n);if(e<=0n||e>rt||e.toString()!==n)throw new g("invalid_counter","The encrypted relay counter is invalid.");let t=new Uint8Array(new ArrayBuffer(12));return new DataView(t.buffer).setBigUint64(4,e,!1),t}function me(n){let e="";for(let t of n)e+=String.fromCharCode(t);return btoa(e).replaceAll("+","-").replaceAll("/","_").replace(/=+$/,"")}async function Ft(n){let e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(n));return me(new Uint8Array(e))}function jt(n){if(!/^[A-Za-z0-9_-]+$/.test(n))throw new g("invalid_base64","Encrypted relay data is malformed.");let e="=".repeat((4-n.length%4)%4),t=atob(n.replaceAll("-","+").replaceAll("_","/")+e);return Uint8Array.from(t,o=>o.charCodeAt(0))}function it(n){let e=jt(n);if(e.length!==65||e[0]!==4)throw new g("invalid_public_key","Encrypted relay public keys must be uncompressed P-256 points.");return e}function Ht(n){return Uint8Array.from(n).buffer}function eo(n){return new Promise((e,t)=>{n.onerror=()=>t(n.error),n.onsuccess=()=>e(n.result)})}function Ut(n,e){return new Promise((t,o)=>{let i=n.transaction(j,"readwrite"),r=e(i.objectStore(j));r.onerror=()=>o(r.error),i.onerror=()=>o(i.error),i.onabort=()=>o(i.error??new Error("Grant key transaction aborted.")),i.oncomplete=()=>t()})}var to="mdbase-connect file chunk key v1",Fe=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,L=class extends Error{constructor(t,o){super(o);this.code=t;this.name="FileTransferCryptoError"}code},ie=class n{constructor(e,t){this.binding=e;this.key=t}binding;key;static async open(e,t,o){$t(o);let i=await e.get(t);if(!i||i.agreementPublicKey!==o.encryption.application_agreement_public_key)throw new g("missing_grant_key","The encrypted grant key is unavailable or does not match the file transfer grant.");let r=await at(i.agreementPrivateKey,o.encryption.connector_agreement_public_key);return n.fromSharedSecret(r,o)}static async fromSharedSecret(e,t){$t(t);let o=await no(e,t);return new n(t,o)}async encryptChunk(e,t,o){if(this.validateHeader(t),o.byteLength!==t.plaintext_length)throw new L("plaintext_length_mismatch","File chunk plaintext length does not match its authenticated header.");let i=xe(e,t),r=await crypto.subtle.encrypt({name:"AES-GCM",iv:Vt(t.chunk_index),additionalData:Ue(i),tagLength:128},this.key,Ue(o));return It({kind:e,header:t,payload:new Uint8Array(r)})}async decryptChunk(e){let t=Me(e);this.validateHeader(t.header);let o=xe(t.kind,t.header);try{let i=await crypto.subtle.decrypt({name:"AES-GCM",iv:Vt(t.header.chunk_index),additionalData:Ue(o),tagLength:128},this.key,Ue(t.payload));return new Uint8Array(i)}catch{throw new L("authentication_failed","The encrypted file chunk could not be authenticated.")}}validateHeader(e){let t=this.binding.encryption;if(e.protocol_version!==1||e.protection!=="grant_aead_v1"||e.grant_id!==this.binding.grantId||e.authority_id!==this.binding.authorityId||e.collection_id!==t.collection_id||e.transfer_id!==this.binding.transferId||e.direction!==this.binding.direction||e.scope_epoch!==t.scope_epoch||e.key_id!==t.key_id)throw new L("header_binding_mismatch","The file frame does not match its transfer encryption binding.")}};async function no(n,e){let t=new TextEncoder().encode(oo(e)),o=await crypto.subtle.digest("SHA-256",t),i=await crypto.subtle.importKey("raw",n,"HKDF",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"HKDF",hash:"SHA-256",salt:o,info:new TextEncoder().encode(to)},i,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}function $t(n){if(G(n.encryption),!Fe.test(n.grantId)||!Fe.test(n.applicationId)||!Fe.test(n.authorityId)||!Fe.test(n.transferId)||n.direction!=="upload"&&n.direction!=="download")throw new L("invalid_binding","The file transfer encryption binding is invalid.")}function oo(n){let e=n.encryption;return["mdbase-connect","file-transfer",1,e.suite,n.grantId,n.applicationId,e.connector_id,n.authorityId,e.collection_id,e.scope_epoch,e.key_id,n.transferId,n.direction].join("|")}function Vt(n){if(!Number.isSafeInteger(n)||n<0)throw new L("invalid_chunk_index","The file chunk index is invalid.");let e=new Uint8Array(new ArrayBuffer(12));return new DataView(e.buffer).setBigUint64(4,BigInt(n),!1),e}function Ue(n){return Uint8Array.from(n).buffer}function _e(n,e){return new Promise((t,o)=>{if(e?.aborted){o(e.reason??new DOMException("Aborted","AbortError"));return}let i=setTimeout(t,n);e?.addEventListener("abort",()=>{clearTimeout(i),o(e.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}var v=class extends Error{constructor(t,o={}){super(t.message,o.cause===void 0?void 0:{cause:o.cause});this.problem=t;this.name="MdbaseConnectError",this.code=t.code,this.status=o.status}problem;code;status;get retryable(){return this.problem.recovery==="retry"&&this.problem.operation_outcome!=="unknown"}get requiresAuthorization(){return this.problem.category==="authorization"}get outcomeUnknown(){return this.problem.operation_outcome==="unknown"}get recovery(){return this.problem.recovery}get details(){return this.problem.details}};function E(n,e,...[t={}]){let o=H[n];return{problem_version:1,code:n,category:o.category,recovery:o.recovery,message:e,...t.details===void 0?{}:{details:t.details},...t.operationOutcome===void 0?{}:{operation_outcome:t.operationOutcome},...t.traceId===void 0?{}:{trace_id:t.traceId}}}function st(n,e,t={}){return et(n,e,{details:t.details,operation_outcome:t.operationOutcome,trace_id:t.traceId})}function c(n,e,...t){let o=t[0];return new v(E(n,e,...t),{status:o?.status,cause:o?.cause})}function x(n,e,t={}){let{status:o,cause:i,...r}=t;return new v(et(n,e,{details:r.details,operation_outcome:r.operationOutcome,trace_id:r.traceId}),{status:o,cause:i})}function ct(n){let e=ro(n.diagnostics),t=lo(n.diagnostics);if(e==="collection_version_unsupported"){let o=ao(n.diagnostics);return E(e,t,{operationOutcome:"rejected",details:o})}return e!=="operation_invalid"?E(e,t,{operationOutcome:"rejected",details:{diagnostics:n.diagnostics}}):E(e,t,{operationOutcome:"rejected",details:{diagnostics:n.diagnostics,partial_result:n.result}})}function ro(n){let e=new Set(n.filter(t=>t.severity==="error").map(t=>t.code));return["migration_required","migration_lossy","unsupported_version"].some(t=>e.has(t))?"collection_version_unsupported":["invalid_config","invalid_configuration","missing_config","missing_spec_version"].some(t=>e.has(t))?"collection_configuration_invalid":["duplicate_type","invalid_contract_definition","invalid_data_contract","invalid_type_definition","invalid_type_path"].some(t=>e.has(t))?"collection_type_registry_invalid":["collection_invalid","collection_open_failed"].some(t=>e.has(t))?"collection_invalid":"operation_invalid"}function ao(n){let e=n.map(t=>t.details).find(t=>so(t));return{current_version:typeof e?.current_version=="string"?e.current_version:"0.2.x",required_version:typeof e?.required_version=="string"?e.required_version:"0.3.0"}}function so(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function co(n){return n instanceof v&&n.retryable}function lo(n){return n.filter(e=>e.severity==="error").map(e=>e.message).join(" ")||n.map(e=>e.message).join(" ")||"The collection rejected this operation."}var Gt=["access_denied","access_paused","authorization_expired","collection_access_denied","connector_identity_changed","connector_offline","connector_upgrade_required","direct_operation_rejected","operation_outcome_unknown","encryption_required","encrypted_relay_rejected","hosted_provider_unavailable","insufficient_access","invalid_encrypted_response","invalid_operation_response","invalid_request","missing_grant_key","not_authorized","operation_cancelled","operation_failed","rate_limited","relay_authorization_expired","relay_unavailable","temporarily_unavailable","timeout","unsupported_operation"],lt=Object.keys(H),Y=["discovery_failed","invalid_application_manifest","invalid_request","manifest_load_failed","rate_limited","temporarily_unavailable","timeout"],J=[...Y,"access_denied","approval_window_blocked","authorization_cancelled","browser_required","collection_access_denied","collection_configuration_invalid","collection_contracts_missing","collection_incompatible","collection_invalid","collection_kind_unsupported","collection_mismatch","collection_not_found","collection_type_registry_invalid","collection_version_unsupported","connector_identity_changed","connector_offline","connector_upgrade_required","device_authorization_failed","encryption_required","expired_token","invalid_callback","invalid_device_authorization_response","invalid_token_response","scope_denied","token_exchange_failed"],re=[...Y,"authorization_expired","invalid_push_subscription","managed_fcm_not_declared","not_authorized","notification_criterion_not_declared","notification_reauthorization_required","notification_registration_failed","notification_unregistration_failed","notifications_not_declared","notifications_unavailable"],Le=["connector_offline","connector_upgrade_required","invalid_operation_response","not_authorized","operation_failed","temporarily_unavailable","timeout"],uo=[...J,"collection_not_ready","collection_not_selected","unknown_collection"],Yt=["collection_configuration_invalid","collection_invalid","collection_type_registry_invalid","collection_version_unsupported"],ge=[...Gt,...Yt],U=[...ge,"invalid_path","operation_invalid"],dt=[...U,"query_snapshot_changed","sandbox_unsupported"],S=[...U,"concurrent_modification","invalid_preflight","pending_mutation_unresolved"],ut=[...ge,"change_cursor_reset"],ae=[...S,"type_pack_provision_failed"];function A(n,e=[]){return{ok:!0,value:n,diagnostics:e}}function R(n){return{ok:!1,problem:n}}async function P(n,e){try{return A(await n())}catch(t){if(!(t instanceof v))throw t;let o=t.problem;return o.code==="unknown"||e.includes(o.code)?R(o):R(st(o.code,o.message,{details:o.details,operationOutcome:o.operation_outcome,traceId:o.trace_id}))}}var ze=class extends Error{constructor(t){super(t.message);this.problem=t;this.name="ConnectOutcomeError"}problem};function po(n){if(!n.ok)throw new ze(n.problem);return n.value}var be=class{constructor(e){this.transport=e}transport;operation(e,t,o){return P(()=>this.transport.operation(e,t,o),lt)}describe(){return this.rawOperation("describe",{},ge)}changes(e={},t){return this.rawOperation("changes",e,ut,t)}read(e){return this.envelopeOperation("read",e,U)}query(e={},t){return this.envelopeOperation("query",e,dt,t)}async*queryPages(e={},t={}){let{offset:o,limit:i,snapshot:r,...a}=e,s=fo(o,0),l=Jt(t.firstPageSize??i,200),d=Jt(t.pageSize??i,1e3),u=r,p=0,f=0;for(;!t.signal?.aborted;){let h=await this.query({...a,offset:s,limit:f===0?l:d,...u?{snapshot:u}:{}},{signal:t.signal});if(!h.ok){yield h;return}let m=h.value,_=m.meta?.snapshot;if(u&&_&&u!==_){yield R(E("query_snapshot_changed","The collection query snapshot changed while paging. Refresh the query before continuing."));return}!u&&_&&(u=_),p+=m.results.length;let w=!m.meta?.has_more||m.results.length===0,b={results:m.results,...m.meta?{meta:m.meta}:{},page:f,offset:s,loaded:p,complete:w,...u?{snapshot:u}:{}};if(t.onProgress?.(b),yield A(b,h.diagnostics),w)return;s+=m.results.length,f+=1}}async queryAll(e={},t={}){let o=[],i,r=[];for await(let a of this.queryPages(e,t)){if(!a.ok)return a;let s=a.value;o.push(...s.results),i=s,r.push(...a.diagnostics)}return A({results:o,meta:{...i?.meta??{},total_count:i?.meta?.total_count??o.length,has_more:i?!i.complete:!1,...i?.snapshot?{snapshot:i.snapshot}:{}}},r)}listViews(){return this.envelopeOperation("list_views",{},U)}executeView(e){return this.envelopeOperation("execute_view",e,U)}readViewSource(e){return this.envelopeOperation("read_view_source",e,U)}createViewSource(e){return this.envelopeOperation("create_view_source",e,S)}updateViewSource(e){return this.envelopeOperation("update_view_source",e,S)}deleteViewSource(e){return this.envelopeOperation("delete_view_source",e,S)}create(e){return this.envelopeOperation("create",e,S)}update(e){return this.envelopeOperation("update",e,S)}delete(e,t){return this.envelopeOperation("delete",e,S,t)}preflightDelete(e,t){return this.envelopeOperation("delete",{...e,check_backlinks:!0,dry_run:!0},S,t)}rename(e,t){return this.envelopeOperation("rename",e,S,t)}preflightRename(e,t){return this.envelopeOperation("rename",{...e,dry_run:!0},S,t)}validate(e={}){return this.envelopeOperation("validate",e,U)}readType(e){return this.envelopeOperation("read_type",e,ae)}createType(e){return this.envelopeOperation("create_type",e,ae)}updateType(e){return this.envelopeOperation("update_type",e,ae)}installTypePack(e){return this.envelopeOperation("install_type_pack",e,ae)}listTimers(e){return this.rawOperation("list_timers",{namespace:e},U)}putTimer(e){return this.rawOperation("put_timer",e,S)}cancelTimer(e){return this.rawOperation("cancel_timer",e,S)}reconcileTimers(e){return this.rawOperation("reconcile_timers",e,S)}async*watch(e={}){let t=e.cursor,o=Math.max(100,e.pollIntervalMs??1e3),i=ho(e.retry),r=0,a=!1;for(e.onStatus?.({state:"connecting",...t===void 0?{}:{cursor:t}});!e.signal?.aborted;){let s=await this.changes(t===void 0?{}:{after:t,limit:200},{signal:e.signal});if(!s.ok){let u=s.problem;if(e.signal?.aborted)return;if(!i||u.recovery!=="retry"){yield s;return}if(a=!1,r+=1,i.maxAttempts!==void 0&&r>i.maxAttempts){yield s;return}let p=Math.min(i.maxDelayMs,Math.round(i.initialDelayMs*i.multiplier**(r-1)));e.onStatus?.({state:"reconnecting",...t===void 0?{}:{cursor:t},attempt:r,retryInMs:p,problem:u});try{await _e(p,e.signal)}catch{if(!e.signal?.aborted)throw c("operation_failed","Watch retry delay failed unexpectedly.")}continue}let l=s.value;if(t===void 0){t=l.cursor;continue}if(l.reset){let u=E("change_cursor_reset","The collection change cursor expired. Refresh collection state before subscribing again.");e.onStatus?.({state:"reset_required",cursor:t,problem:u}),yield R(u);return}let d=r>0;r=0,(!a||d)&&e.onStatus?.({state:"connected",cursor:t,recovered:d}),a=!0;for(let u of l.events)yield A(u);if(t=l.cursor,!l.has_more)try{await _e(o,e.signal)}catch{if(!e.signal?.aborted)throw c("operation_failed","Watch polling delay failed unexpectedly.")}}}rawOperation(e,t,o,i){return P(()=>this.transport.operation(e,t,i),o)}async envelopeOperation(e,t,o,i){let r=await P(()=>this.transport.operation(e,t,i),o);if(!r.ok)return r;let a=r.value;return a.valid?A(a.result,a.diagnostics):R(ct(a))}};function ho(n){if(n!==!1)return{initialDelayMs:Math.max(0,n?.initialDelayMs??500),maxDelayMs:Math.max(0,n?.maxDelayMs??15e3),multiplier:Math.max(1,n?.multiplier??2),...n?.maxAttempts===void 0?{}:{maxAttempts:Math.max(0,n.maxAttempts)}}}function fo(n,e){return typeof n=="number"&&Number.isFinite(n)?Math.max(0,Math.floor(n)):e}function Jt(n,e){return typeof n=="number"&&Number.isFinite(n)&&n>0?Math.floor(n):e}function N(n){let e=new Uint8Array(n);return crypto.getRandomValues(e),ve(e)}function ve(n){let e="";for(let t of n)e+=String.fromCharCode(t);return btoa(e).replaceAll("+","-").replaceAll("/","_").replace(/=+$/,"")}function Qt(n){let e=n.replaceAll("-","+").replaceAll("_","/").padEnd(Math.ceil(n.length/4)*4,"="),t=atob(e),o=new Uint8Array(new ArrayBuffer(t.length));for(let i=0;i<t.length;i+=1)o[i]=t.charCodeAt(i);return o}function Q(n){return{...n,credentials:"omit",targetAddressSpace:"loopback"}}async function we(){if(typeof navigator>"u"||!navigator.permissions?.query)return null;try{return(await navigator.permissions.query({name:"local-network-access"})).state}catch{return null}}function se(n){return n===404||n===405||n===426||n>=500}function Ne(n,e){return e&&typeof e=="object"&&!Array.isArray(e)&&e.dry_run===!0?!1:n==="sync"&&e!==null&&typeof e=="object"&&!Array.isArray(e)&&e.action==="mutate"||n==="create"||n==="update"||n==="delete"||n==="rename"||n==="create_type"||n==="update_type"||n==="install_type_pack"||n==="put_timer"||n==="cancel_timer"||n==="reconcile_timers"}function D(n){return[...new Set(n)]}function Xt(n,e){return n.grantId||e.grantId?n.grantId===e.grantId&&n.keyHandle===e.keyHandle&&n.encryption?.key_id===e.encryption?.key_id:n.accessToken===e.accessToken}function X(n){if(n?.aborted)throw c("operation_cancelled","The operation was cancelled before it changed the collection.",{operationOutcome:"not_sent",cause:n.reason})}function ht(n,e,t,o){return n instanceof v?n:e?.aborted?t?M(n):c("operation_cancelled","The operation was cancelled before it changed the collection.",{operationOutcome:"not_sent",cause:n}):t?M(n):n instanceof TypeError?c(o,o==="hosted_provider_unavailable"?"The hosted collection provider is unavailable.":"The Connect relay is unavailable.",{cause:n}):n instanceof Error?n:new Error(String(n))}function ft(n,e){return e?.aborted===!0||n instanceof v&&n.code==="operation_cancelled"}function Wt(n,e){if(e.dry_run!==!0||e.would_rename!==!0||e.from!==n.from||e.to!==n.to)throw c("invalid_preflight","The rename preview does not match this mutation. Run the preview again.")}function Zt(n,e){if(e.dry_run!==!0||e.would_delete!==!0||e.path!==n.path)throw c("invalid_preflight","The delete preview does not match this mutation. Run the preview again.")}function en(n,e){if(n.update_refs===!1)return{affectedRecords:0,totalUnits:1,warnings:0};let t=e.references_affected??[];return{affectedRecords:new Set(t.map(o=>o.path)).size,totalUnits:1+t.length,warnings:e.warnings?.length??0}}function tn(n){return{affectedRecords:new Set((n.broken_links??[]).map(e=>e.path)).size,totalUnits:1,warnings:0}}async function nn(n,e){let t=new TextEncoder().encode(`${n}\0${yt(e??{})}`),o=await crypto.subtle.digest("SHA-256",t);return ve(new Uint8Array(o))}function yt(n){return JSON.stringify(pt(n))}function pt(n){return Array.isArray(n)?n.map(e=>pt(e)):n&&typeof n=="object"?Object.fromEntries(Object.entries(n).filter(([,e])=>e!==void 0).sort(([e],[t])=>e<t?-1:e>t?1:0).map(([e,t])=>[e,pt(t)])):n}function M(n){return c("operation_outcome_unknown","The write may have completed, but mdbase could not recover its authoritative result. Retry the exact same write to recover safely.",{operationOutcome:"unknown",cause:n})}async function q(n,e,t,o){try{return await fetch(n,e)}catch(i){throw c(t,o,{cause:i})}}function on(n){let e=new URL(n);if(e.protocol!=="http:"||!["127.0.0.1","[::1]"].includes(e.hostname)||e.username||e.password||e.pathname!=="/"||e.search||e.hash)throw c("invalid_loopback_url","loopbackUrl must be an HTTP origin on 127.0.0.1 or ::1.");return e.origin}async function Ce(){let n=N(32),e=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(n));return{verifier:n,challenge:ve(new Uint8Array(e))}}function C(n,e,t,o){return x(Pe(n)??n?.error?.code??e,n?.error_description??n?.error?.message??t,{status:o,details:n?.error?.details})}function Pe(n){return typeof n?.error=="string"?n.error:void 0}function qe(n,e){if(!n||typeof n!="object"||Array.isArray(n)||typeof e!="string")return!1;let t=n;if(typeof t.operations_url!="string"||typeof t.sync_url!="string"||typeof t.files_url!="string"||typeof t.replica_id!="string"||t.replica_id.length===0||typeof t.access_token!="string"||t.access_token.length===0||t.proof_public_key!==void 0&&(typeof t.proof_public_key!="string"||t.proof_public_key.length===0))return!1;try{let o=new URL(t.operations_url),i=new URL(t.sync_url),r=new URL(t.files_url);return[o,i,r].every(a=>(a.protocol==="https:"||a.protocol==="http:"&&["localhost","127.0.0.1","[::1]","::1"].includes(a.hostname))&&!a.username&&!a.password&&!a.search&&!a.hash)&&/^\/v1\/authorities\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/operations$/i.test(o.pathname)&&/^\/v1\/authorities\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/sync$/i.test(i.pathname)&&/^\/v1\/authorities\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\/files$/i.test(r.pathname)&&o.origin===i.origin&&o.origin===r.origin&&o.pathname.split("/")[3]===e&&i.pathname.split("/")[3]===e&&r.pathname.split("/")[3]===e}catch{return!1}}function rn(n,e){return qe({operations_url:n?.operationsUrl,sync_url:n?.syncUrl,files_url:n?.filesUrl,replica_id:n?.replicaId,access_token:n?.accessToken,proof_public_key:n?.proofPublicKey},e)}function Be(n){if(!n||typeof n!="object"||Array.isArray(n))return!1;let e=n,t=e.actions;if(e.kind!=="files"||e.protocol_version!==1||!Array.isArray(t)||t.length===0||t.length>6||new Set(t).size!==t.length||t.some(i=>!["list","read","add","replace","move","delete"].includes(i)))return!1;let o=e.scope;return!o||typeof o!="object"||Array.isArray(o)?!1:o.kind==="collection"?Object.keys(o).length===1:o.kind==="selected_folders"&&Object.keys(o).length===2&&Array.isArray(o.folders)&&o.folders.length>0&&o.folders.length<=100&&new Set(o.folders).size===o.folders.length&&o.folders.every(i=>typeof i=="string"&&i.length>0&&i.length<=1024&&yo(i))}function yo(n){let e=new Set([".mdbase",".git","node_modules","_contracts","_schemas","_types","_views"]);return!n.startsWith("/")&&!n.endsWith("/")&&!n.includes("\\")&&n.split("/").every(t=>{let o=t.split(".")[0]?.toUpperCase()??"";return t!==""&&t!=="."&&t!==".."&&!t.startsWith(".")&&!t.endsWith(" ")&&!t.endsWith(".")&&!/[<>:"|?*]/.test(t)&&!e.has(t.toLowerCase())&&!["CON","PRN","AUX","NUL"].includes(o)&&!/^(COM|LPT)[1-9]$/.test(o)})}function an(n,e){if(!n||typeof n!="object"||Array.isArray(n)||n.collection_id!==e)return!1;try{return G(n),!0}catch{return!1}}function sn(n){if(typeof n?.device_code!="string"||typeof n?.user_code!="string"||typeof n?.verification_uri!="string"||typeof n?.verification_uri_complete!="string"||!Number.isFinite(n?.expires_in)||!Number.isFinite(n?.interval))throw c("invalid_device_authorization_response","Connect returned an invalid downloaded application authorization response.");return{userCode:n.user_code,verificationUri:n.verification_uri,verificationUriComplete:n.verification_uri_complete,expiresAt:Date.now()+Math.max(1,n.expires_in)*1e3,intervalSeconds:Math.max(1,n.interval)}}function I(n){if(!n)return null;try{return JSON.parse(n)}catch{return null}}function Ke(n){if(!n||typeof n!="object"||Array.isArray(n))return null;let e=n;return e.access!=="contract"&&e.access!=="full_collection"||!Array.isArray(e.contracts)||e.contracts.some(t=>!t||typeof t!="object"||t.contract_type!=="record"||typeof t.id!="string"||typeof t.version!="string"||!/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(t.version)||!/^sha256:[0-9a-f]{64}$/.test(t.digest)||!t.schema||typeof t.schema!="object"||Array.isArray(t.schema)||!Array.isArray(t.implementations)||t.implementations.some(o=>!o||typeof o!="object"||typeof o.type_name!="string"||!Number.isInteger(o.type_version)||!/^sha256:[0-9a-f]{64}$/.test(o.digest)||!o.fields||typeof o.fields!="object"||Array.isArray(o.fields)||Object.values(o.fields).some(i=>typeof i!="string")))?null:e}function cn(n){return n.endsWith("/")?n.slice(0,-1):n}function ln(){if(typeof location>"u")throw c("manifest_required","manifest is required outside a browser environment.");if(location.origin==="null")throw c("manifest_required","Downloaded applications must provide their v1 portable manifest inline.");return new URL("/.well-known/mdbase-app.json",location.origin).href}function dn(){if(typeof location>"u")throw c("redirect_uri_required","redirectUri is required outside a browser environment.");return location.href.split(/[?#]/)[0]}function un(){if(typeof location>"u")throw c("callback_url_required","callbackUrl is required outside a browser environment.");return location.href}function pn(n){if(n)return new ce;if(typeof localStorage>"u")throw c("storage_required","storage is required outside a browser environment.");try{let e=`mdbase-connect:probe:${N(8)}`;return localStorage.setItem(e,"1"),localStorage.removeItem(e),localStorage}catch{return new ce}}var ce=class{values=new Map;get length(){return this.values.size}clear(){this.values.clear()}getItem(e){return this.values.get(e)??null}key(e){return[...this.values.keys()][e]??null}removeItem(e){this.values.delete(e)}setItem(e,t){this.values.set(String(e),String(t))}};function hn(n){return typeof n=="string"||n.distribution!=="portable"?!1:typeof location>"u"||location.origin==="null"||!["http:","https:"].includes(location.protocol)}function fn(n){let e=yt(n),t=2166136261,o=2654435769;for(let i=0;i<e.length;i+=1){let r=e.charCodeAt(i);t=Math.imul(t^r,16777619),o=Math.imul(o^r,2246822507)}return`${(t>>>0).toString(16).padStart(8,"0")}${(o>>>0).toString(16).padStart(8,"0")}`}var je=class{constructor(e){this.context=e}context;async registerNotifications(e){let t=await this.context.authorizedToken();if(!t)throw c("not_authorized","Connect this application before enabling notifications.");let i=(await this.context.register()).notifications?.criteria.map(w=>w.id)??[],r=[...new Set(e.criteria??i)],a=r.find(w=>!i.includes(w));if(a)throw c("notification_criterion_not_declared",`The application manifest does not declare notification criterion ${a}.`);if(r.length===0)throw c("notifications_not_declared","This application manifest does not declare any notification criteria.");let s=await q(`${this.context.serverUrl}/v1/notifications/vapid-public-key`,void 0,"notifications_unavailable","Push notifications are unavailable."),l=await s.json();if(!s.ok)throw C(l,"notifications_unavailable","Push notifications are unavailable.",s.status);let d=await e.serviceWorker.pushManager.getSubscription();d||(d=await e.serviceWorker.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:Qt(l.public_key)}));let u=d.toJSON();if(!u.endpoint||!u.keys?.p256dh||!u.keys.auth)throw c("invalid_push_subscription","The browser returned an incomplete push subscription.");let p=I(this.context.storage.getItem(this.context.notificationKey())),f=e.installationId??p?.installationId??N(24),h=await q(`${this.context.serverUrl}/v1/notifications/channels`,{method:"POST",headers:{authorization:`Bearer ${t.accessToken}`,"content-type":"application/json"},body:JSON.stringify({installation_id:f,criteria:r,subscription:{endpoint:u.endpoint,expirationTime:u.expirationTime??null,keys:u.keys}})},"notification_registration_failed","Could not register push notifications."),m=await h.json();if(!h.ok)throw C(m,"notification_registration_failed","Could not register push notifications.",h.status);p?.channelId&&p.channelId!==m.channel_id&&fetch(`${this.context.serverUrl}/v1/notifications/channels/${p.channelId}`,{method:"DELETE",headers:{authorization:`Bearer ${t.accessToken}`}}).catch(()=>{});let _={channelId:m.channel_id,installationId:f,criteria:r};return this.context.storage.setItem(this.context.notificationKey(),JSON.stringify(_)),_}async registerNativeNotifications(e){let t=await this.context.authorizedToken();if(!t)throw c("not_authorized","Connect this application before enabling notifications.");let o=await this.context.register();if(o.notifications?.native_delivery?.mode!=="managed_fcm")throw c("managed_fcm_not_declared","This application does not declare Connect-managed native notifications.");let i=o.notifications.criteria.map(h=>h.id),r=[...new Set(e.criteria??i)],a=r.find(h=>!i.includes(h));if(a)throw c("notification_criterion_not_declared",`The application manifest does not declare notification criterion ${a}.`);if(r.length===0)throw c("notifications_not_declared","This application manifest does not declare any notification criteria.");let s=this.context.notificationKey("fcm"),l=I(this.context.storage.getItem(s)),d=e.installationId??l?.installationId??N(24),u=await q(`${this.context.serverUrl}/v1/notifications/channels`,{method:"POST",headers:{authorization:`Bearer ${t.accessToken}`,"content-type":"application/json"},body:JSON.stringify({installation_id:d,criteria:r,transport:"fcm",token:e.token})},"notification_registration_failed","Could not register native notifications."),p=await u.json();if(!u.ok)throw C(p,"notification_registration_failed","Could not register native notifications.",u.status);l?.channelId&&l.channelId!==p.channel_id&&this.deleteNotificationChannel(l.channelId,t.accessToken).catch(()=>{});let f={channelId:p.channel_id,installationId:d,transport:"fcm",criteria:r};return this.context.storage.setItem(s,JSON.stringify(f)),f}async unregisterNativeNotifications(){let e=this.context.notificationKey("fcm"),t=I(this.context.storage.getItem(e)),o=await this.context.authorizedToken();if(t?.channelId&&!o)throw c("not_authorized","Reconnect this application before disabling native notifications.");t?.channelId&&o&&await this.deleteNotificationChannel(t.channelId,o.accessToken),this.context.storage.removeItem(e)}async unregisterNotifications(e){let t=I(this.context.storage.getItem(this.context.notificationKey())),o=await this.context.authorizedToken();if(t?.channelId&&!o)throw c("not_authorized","Reconnect this application before disabling push notifications.");if(t?.channelId&&o){let r=await q(`${this.context.serverUrl}/v1/notifications/channels/${t.channelId}`,{method:"DELETE",headers:{authorization:`Bearer ${o.accessToken}`}},"notification_unregistration_failed","Could not unregister push notifications.");if(!r.ok&&r.status!==404){let a=await r.json();throw C(a,"notification_unregistration_failed","Could not unregister push notifications.",r.status)}}this.context.storage.removeItem(this.context.notificationKey()),await(await e?.pushManager.getSubscription())?.unsubscribe()}async deleteNotificationChannel(e,t){let o=await q(`${this.context.serverUrl}/v1/notifications/channels/${e}`,{method:"DELETE",headers:{authorization:`Bearer ${t}`}},"notification_unregistration_failed","Could not unregister push notifications.");if(!o.ok&&o.status!==404){let i=await o.json();throw C(i,"notification_unregistration_failed","Could not unregister push notifications.",o.status)}}};async function He(n,e,t,o,i,r){if(!n.authority)throw c("not_remote_authority","This authorization has no remote authority endpoint.");let a=t===""||t.startsWith("?")?t:`/${t}`,s=`${n.authority.filesUrl}${a}`,l=o===void 0?void 0:JSON.stringify(o),d=await r(n,e,s,l,n.authority.accessToken);return fetch(s,{method:e,redirect:"error",headers:{authorization:`Bearer ${n.authority.accessToken}`,...l===void 0?{}:{"content-type":"application/json"},...d},...l===void 0?{}:{body:l},...i?{signal:i}:{}})}async function yn(n,e,t,o,i,r,a){let s=n,l=await He(s,e,t,o,i,a);if(l.status===401&&s.refreshToken){if(s=await r(),!s.authority||!s.fileCapability)throw c("authority_authorization_changed","Reconnect this collection before accessing its files.");l=await He(s,e,t,o,i,a)}let d=await l.json().catch(()=>({}));if(!l.ok)throw C(d,"operation_failed","Collection file request failed.",l.status);return d}async function mn(n,e,t,o,i,r){let a=n,s=await He(a,"GET",e,void 0,o,r);if(s.status===401&&a.refreshToken){if(a=await i(),!a.authority||!a.fileCapability)throw c("authority_authorization_changed","Reconnect this collection before accessing its files.");s=await He(a,"GET",e,void 0,o,r)}if(!s.ok){let d=await s.json().catch(()=>({}));throw C(d,"operation_failed","Collection file range request failed.",s.status)}let l=s.headers.get("content-length");if(l===null||!/^(0|[1-9][0-9]*)$/u.test(l)||Number(l)!==t)throw await s.body?.cancel().catch(()=>{}),c("invalid_operation_response","The hosted file response declared an unexpected byte length.");if(!s.body)throw c("invalid_operation_response","The hosted file response did not contain a byte stream.");return s.body}var $e=class{constructor(e){this.options=e}options;async control(e,t,o,i,r){le(e);let a=wo(t,o,i),s=await this.encryptControl(e,a),l;if(await this.options.shouldAttemptDirect(e)){try{l=await fetch(`${this.options.loopbackUrl}/v1/files/control`,Q({method:"POST",headers:{"content-type":"application/mdbase-connect+json"},body:JSON.stringify(s),signal:r}))}catch(d){if(r?.aborted)throw d;this.options.onDirectUnavailable()}if(l&&!se(l.status))return l.ok&&this.options.onDirectAvailable(),this.decryptControlResponse(e,s,l);l&&this.options.onDirectUnavailable()}return l=await this.sendRelayControl(e,s,r),await _o(l,e)&&(e=await this.options.refreshAuthorization(),mt(e),s=await this.encryptControl(e,a),l=await this.sendRelayControl(e,s,r)),l.ok&&this.options.onRelayAvailable(),this.decryptControlResponse(e,s,l)}async decryptControlResponse(e,t,o){let i=await o.json().catch(()=>({}));if(!o.ok)throw C(i,"operation_failed","Collection file request failed.",o.status);let r=i?.envelope;if(!r)throw c("invalid_encrypted_response","The connector omitted its encrypted file response.");let a=await oe(this.options.keyStore,e.keyHandle,_t(e),t,r);return a.ok||vo(a.problem),a.result}async uploadChunk(e,t,o,i){let a=await this.localFileToken(e,"upload"),s=await _n(this.options.keyStore,a,e,t,o),l;if(await this.options.shouldAttemptDirect(a)){try{l=await fetch(`${this.options.loopbackUrl}/v1/files/upload`,Q(gn(s,i)))}catch(d){if(i?.aborted)throw d;this.options.onDirectUnavailable()}if(l&&!se(l.status))return l.ok&&this.options.onDirectAvailable(),mo(l,"Encrypted file chunk upload failed.");l&&this.options.onDirectUnavailable()}if(l=await this.sendRelayUpload(a,s,i),l.status===401&&a.refreshToken&&(a=await this.options.refreshAuthorization(),mt(a),s=await _n(this.options.keyStore,a,e,t,o),l=await this.sendRelayUpload(a,s,i)),!l.ok){let d=await l.json().catch(()=>({}));throw C(d,"operation_failed","Encrypted file chunk upload failed.",l.status)}this.options.onRelayAvailable()}async downloadChunk(e,t,o){let i=await this.localFileToken(e,"download"),r;if(await this.options.shouldAttemptDirect(i)){try{r=await fetch(`${this.options.loopbackUrl}/v1/files/download/${encodeURIComponent(i.grantId)}/${encodeURIComponent(e.transfer_id)}/${t}`,Q({method:"GET",signal:o}))}catch(a){if(o?.aborted)throw a;this.options.onDirectUnavailable()}if(r&&!se(r.status))return r.ok&&this.options.onDirectAvailable(),this.decryptDownloadResponse(i,e,t,r);r&&this.options.onDirectUnavailable()}return r=await this.sendRelayDownload(i,e,t,o),r.status===401&&i.refreshToken&&(i=await this.options.refreshAuthorization(),mt(i),r=await this.sendRelayDownload(i,e,t,o)),r.ok&&this.options.onRelayAvailable(),this.decryptDownloadResponse(i,e,t,r)}async decryptDownloadResponse(e,t,o,i){if(!i.ok){let s=await i.json().catch(()=>({}));throw C(s,"operation_failed","Encrypted file chunk download failed.",i.status)}if(i.headers.get("content-type")?.split(";",1)[0]!=="application/mdbase-connect-file")throw c("invalid_operation_response","The connector returned an invalid file response media type.");let r=new Uint8Array(await i.arrayBuffer()),a;try{bo(t,o,r),a=await(await vn(this.options.keyStore,e,t)).decryptChunk(r)}catch(s){throw s instanceof v?s:c("invalid_operation_response","The connector returned an invalid encrypted file frame.",{cause:s})}if(a.byteLength!==gt(t,o))throw c("invalid_operation_response","The connector returned a truncated file chunk.");return a}encryptControl(e,t){return le(e),V(this.options.keyStore,e.keyHandle,_t(e),"file_control",t)}sendRelayControl(e,t,o){return fetch(`${this.options.serverUrl}/v1/authorities/${encodeURIComponent(e.collectionId)}/files/control`,{method:"POST",headers:{authorization:`Bearer ${e.accessToken}`,"content-type":"application/json"},body:JSON.stringify(t),signal:o})}sendRelayUpload(e,t,o){return fetch(`${this.options.serverUrl}/v1/authorities/${encodeURIComponent(e.collectionId)}/files/upload`,{...gn(t,o),headers:{authorization:`Bearer ${e.accessToken}`,"content-type":"application/mdbase-connect-file"}})}sendRelayDownload(e,t,o,i){return fetch(`${this.options.serverUrl}/v1/authorities/${encodeURIComponent(e.collectionId)}/files/download/${encodeURIComponent(t.transfer_id)}/${o}`,{method:"GET",headers:{authorization:`Bearer ${e.accessToken}`},signal:i})}async localFileToken(e,t){let o=await this.options.authorizedToken();if(!o||o.authority||!o.fileCapability||!o.encryption||!o.grantId||!o.keyHandle||e.direction!==t||e.protection!=="grant_aead_v1")throw c("not_authorized","This connection cannot use encrypted local file delivery.");return Ve(e),o}};function mt(n){if(n.authority||!n.fileCapability)throw c("not_authorized","This connection cannot use encrypted local file delivery.");le(n)}async function _n(n,e,t,o,i){let r=go(e,t,o,i.byteLength);return(await vn(n,e,t)).encryptChunk("upload_chunk",r,i)}function gn(n,e){return{method:"POST",headers:{"content-type":"application/mdbase-connect-file"},body:Uint8Array.from(n).buffer,signal:e}}async function mo(n,e){if(n.ok)return;let t=await n.json().catch(()=>({}));throw C(t,"operation_failed",e,n.status)}async function _o(n,e){return e.refreshToken?n.status===401?!0:n.status!==409?!1:(await n.clone().json().catch(()=>null))?.error?.code==="encryption_binding_stale":!1}function le(n){if(!n.encryption||!n.grantId||!n.keyHandle)throw c("missing_grant_key","Reconnect this application to restore encrypted file access.")}function _t(n){return le(n),{grantId:n.grantId,applicationId:n.clientId,encryption:n.encryption}}function vn(n,e,t){return le(e),ie.open(n,e.keyHandle,{..._t(e),authorityId:e.encryption.connector_id,transferId:t.transfer_id,direction:t.direction})}function go(n,e,t,o){le(n);let i=Ve(e),r=gt(e,t);if(o!==r)throw c("invalid_request","The file chunk has the wrong byte length.");return{protocol_version:1,protection:"grant_aead_v1",grant_id:n.grantId,authority_id:n.encryption.connector_id,collection_id:n.collectionId,transfer_id:e.transfer_id,direction:e.direction,chunk_size:i,chunk_index:t,offset:t*i,plaintext_length:o,total_size:e.total_size,scope_epoch:n.encryption.scope_epoch,key_id:n.encryption.key_id}}function bo(n,e,t){let o=Me(t),i=gt(n,e),r=Ve(n);if(o.kind!=="download_chunk"||o.header.chunk_index!==e||o.header.chunk_size!==r||o.header.offset!==e*r||o.header.plaintext_length!==i||o.header.total_size!==n.total_size)throw c("invalid_operation_response","The connector returned a file frame for a different chunk.")}function vo(n){throw x(n.code==="unknown"?n.server_code:n.code,n.message,{details:n.details,operationOutcome:n.operation_outcome??"rejected",traceId:n.trace_id})}function wo(n,e,t){if(n==="GET"&&(e===""||e.startsWith("?"))){let i=new URLSearchParams(e.startsWith("?")?e.slice(1):e),r=i.get("limit");return{protocol_version:1,type:"list_files",...i.get("folder")?{folder:i.get("folder")}:{},...i.get("after")?{after:i.get("after")}:{},...r?{limit:Number(r)}:{}}}let o=e.split("/");if(n==="GET"&&o.length===2&&o[0]==="transfers")return bn("get_file_transfer_status",o[1]);if(n==="DELETE"&&o.length===2&&o[0]==="transfers")return bn("abort_file_transfer",o[1]);if(n==="POST"&&Co(t)){let i=e==="uploads"?"open_file_upload":e==="downloads"?"open_file_download":o.length===3&&o[0]==="uploads"&&o[2]==="commit"?"commit_file_upload":o.length===2&&o[1]==="move"&&t.file_id===decodeURIComponent(o[0])?"move_file":o.length===2&&o[1]==="delete"&&t.file_id===decodeURIComponent(o[0])?"delete_file":null;if(i&&t.type===i)return{...t}}throw c("invalid_request","The file control request path is invalid.")}function bn(n,e){return{protocol_version:1,type:n,transfer_id:decodeURIComponent(e)}}function Ve(n){if(n.strategy.kind!=="framed_chunks"||!Number.isSafeInteger(n.strategy.chunk_size)||n.strategy.chunk_size<=0)throw c("invalid_operation_response","The connector returned an invalid framed transfer strategy.");return n.strategy.chunk_size}function gt(n,e){let t=Ve(n);if(!Number.isSafeInteger(e)||e<0||!Number.isSafeInteger(n.total_size)||n.total_size<0)throw c("invalid_request","The file chunk index is invalid.");let o=e*t;if(!Number.isSafeInteger(o)||o>=n.total_size)throw c("invalid_request","The file chunk index is outside the transfer.");return Math.min(t,n.total_size-o)}function Co(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}var Ge=class{constructor(e){this.options=e;this.local=new $e(e)}options;local;async control(e,t="",o,i){let r=await this.requireFileToken();return r.authority?yn(r,e,t,o,i,this.options.refreshAuthorization,this.options.authorityProofHeaders):this.local.control(r,e,t,o,i)}uploadChunk(e,t,o,i){return this.local.uploadChunk(e,t,o,i)}downloadChunk(e,t,o){return this.local.downloadChunk(e,t,o)}async downloadHostedPart(e,t,o,i){let r=await this.requireFileToken();if(!r.authority)throw c("not_remote_authority","Hosted file delivery requires a remote authority endpoint.");return mn(r,`downloads/${encodeURIComponent(e.transfer_id)}/parts/${t}`,o,i,this.options.refreshAuthorization,this.options.authorityProofHeaders)}async requireFileToken(){let e=await this.options.authorizedToken();if(!e?.fileCapability)throw c("not_authorized","This connection has no file capability.");return e}};var Ye=class{serverUrl;storage;keyStore;directAccessMode;loopbackUrl;collectionId;internals;onChange;files;refreshPromise=null;directStatus;currentRoute="relay";directFailures=0;directRetryAt=0;constructor(e){this.serverUrl=e.serverUrl,this.storage=e.storage,this.keyStore=e.keyStore,this.directAccessMode=e.directAccessMode,this.loopbackUrl=e.loopbackUrl,this.collectionId=e.collectionId,this.internals=e.internals,this.onChange=e.onChange,this.files=new Ge({keyStore:this.keyStore,serverUrl:this.serverUrl,loopbackUrl:this.loopbackUrl,authorizedToken:()=>this.authorizedToken(),refreshAuthorization:()=>this.refreshAuthorization(),shouldAttemptDirect:t=>this.shouldAttemptDirect(t),onDirectAvailable:()=>{this.markDirectAvailable(),this.setRoute("direct")},onDirectUnavailable:()=>this.markDirectUnavailable(),onRelayAvailable:()=>this.setRoute("relay"),authorityProofHeaders:(t,o,i,r,a)=>this.authorityProofHeaders(t,o,i,r,a)}),this.directStatus=this.directAccessMode==="disabled"?"disabled":"unavailable"}get directAccess(){return this.currentToken()?.authority?"disabled":this.directStatus}get route(){return this.currentToken()?.authority?"remote":this.currentRoute}notifyStorageChanged(){this.emitConnection()}async checkDirectAccess(){let e=this.currentToken();if(!this.directEligible(e))return this.setDirectStatus("disabled");let t=await we();return t==="denied"?this.setDirectStatus("denied"):(t==="prompt"||t===null)&&this.storage.getItem(this.directPreferenceKey())!=="enabled"?this.setDirectStatus("permission_required"):this.probeDirectAccess()}async requestDirectAccess(){let e=this.currentToken();return this.directCapable(e)?(this.storage.setItem(this.directPreferenceKey(),"enabled"),this.directRetryAt=0,this.probeDirectAccess()):this.setDirectStatus("disabled")}disableDirectAccess(){this.storage.setItem(this.directPreferenceKey(),"disabled"),this.setDirectStatus("disabled"),this.setRoute("relay")}pendingMutation(){let e=I(this.storage.getItem(this.pendingMutationKey())),t=this.currentToken();return!e||!t||e.collectionId!==t.collectionId||e.grantId!==t.grantId||e.keyId!==t.encryption?.key_id?null:{operation:e.operation,createdAt:e.createdAt,resumable:!0}}async resumePendingMutation(e,t){let o=this.pendingMutation();if(!o)throw c("no_pending_mutation","There is no interrupted mutation to resume.");return this.performOperation(o.operation,e,t)}async performOperation(e,t,o={}){X(o.signal);let i=this.currentToken();if(!i)throw c("not_authorized","Connect this application before accessing a collection.");if(!i.operations.includes(e))throw c("insufficient_access",`This connection does not allow ${e}.`,{details:{required_operations:[e],granted_operations:[...i.operations],missing_operations:[e]}});let r=await this.shouldAttemptDirect(i);if(!r&&(i=await this.authorizedToken(),!i))throw c("not_authorized","Reconnect this application to continue.");let a;try{a=await this.sendOperation(i,e,t,r,o)}catch(u){throw ht(u,o.signal,Ne(e,t)&&this.pendingMutation()!==null,i.authority?"hosted_provider_unavailable":"relay_unavailable")}let s=a.response,l=s.status===409&&(await s.clone().json().catch(()=>null))?.error?.code==="encryption_binding_stale";if((s.status===401||l)&&i.refreshToken){if(a.pendingMutation&&(a.directDeliveryUncertain||a.encryptedRequest&&a.resumingMutation))throw c("operation_outcome_unknown","The direct operation may have completed, but its encrypted grant changed before the response could be recovered. Refresh before making another change.",{operationOutcome:"unknown"});a.pendingMutation&&this.clearPendingMutation(),i=await this.refreshAuthorization(),r=await this.shouldAttemptDirect(i);try{a=await this.sendOperation(i,e,t,r,o)}catch(u){throw ht(u,o.signal,Ne(e,t)&&this.pendingMutation()!==null,i.authority?"hosted_provider_unavailable":"relay_unavailable")}s=a.response}let d;try{d=await s.json()}catch(u){throw a.pendingMutation?M(u):c("invalid_operation_response","The collection authority returned a response that is not valid JSON.",{cause:u})}if(!s.ok){let u=C(d,"operation_failed","Collection operation failed.",s.status);throw a.pendingMutation&&(a.directDeliveryUncertain||a.encryptedRequest&&a.resumingMutation)?M(u):(a.pendingMutation&&!a.directDeliveryUncertain&&this.clearPendingMutation(),u.code==="direct_operation_rejected"&&u.status===403&&this.invalidateRejectedAuthorization(i),u)}if(a.encryptedRequest){let u=d?.envelope;if(!u||!i.encryption||!i.grantId||!i.keyHandle)throw a.pendingMutation?M(new Error("Encrypted operation response was missing its envelope.")):c("invalid_encrypted_response","The relay did not return an encrypted connector response.");try{let p=await oe(this.keyStore,i.keyHandle,{grantId:i.grantId,applicationId:i.clientId,encryption:i.encryption},a.encryptedRequest,u);if(a.pendingMutation&&this.clearPendingMutation(),!p.ok)throw x(p.problem.code==="unknown"?p.problem.server_code:p.problem.code,p.problem.message,{details:p.problem.details,operationOutcome:p.problem.operation_outcome??"rejected",traceId:p.problem.trace_id});return p.result}catch(p){throw p instanceof v?p:p instanceof g?a.pendingMutation?M(p):x(p.code,p.message):p}}if(d?.protocol_version!==1||d?.request_id!==a.requestId)throw a.pendingMutation?M(new Error("Operation response protocol or request ID did not match.")):c("invalid_operation_response","The collection authority returned a response for a different protocol request.");if(d.ok===!1)throw he(d.problem)?(a.pendingMutation&&this.clearPendingMutation(),new v(d.problem)):a.pendingMutation?M(new Error("Operation rejection did not contain a canonical problem.")):c("invalid_operation_response","The collection authority returned an invalid operation problem.");if(d.ok!==!0||!("result"in d))throw a.pendingMutation?M(new Error("Successful operation response did not contain a result.")):c("invalid_operation_response","The collection authority returned an incomplete operation response.");return a.pendingMutation&&this.clearPendingMutation(),d.result}async performAuthoritySyncRequest(e,t,o,i,r){let a=await this.authorizedToken();if(!a?.authority||a.collectionId!==e||a.authority.replicaId!==t)throw c("authority_authorization_changed","Reconnect this collection authority before synchronizing.");let s=await this.sendAuthoritySyncRequest(a,o,i,r);if(s.status===401&&a.refreshToken){if(a=await this.refreshAuthorization(),!a.authority||a.collectionId!==e||a.authority.replicaId!==t)throw c("authority_authorization_changed","Reconnect this collection authority before synchronizing.");s=await this.sendAuthoritySyncRequest(a,o,i,r)}let l=await s.json();if(!s.ok)throw C(l,"sync_failed","Collection synchronization failed.",s.status);return l}async sendAuthoritySyncRequest(e,t,o,i){if(!e.authority)throw c("not_remote_authority","This authorization has no remote authority endpoint.");let r=`${e.authority.syncUrl}/${o}`,a=i===void 0?void 0:JSON.stringify(i),s=await this.authorityProofHeaders(e,t,r,a,e.authority.accessToken);return fetch(r,{method:t,headers:{authorization:`Bearer ${e.authority.accessToken}`,...i===void 0?{}:{"content-type":"application/json"},...s},...a===void 0?{}:{body:a}})}async sendOperation(e,t,o,i,r={}){let a=o??{},s,l=!1,d=!1,u=crypto.randomUUID(),p=null,f;if(Ne(t,o)){if(f=await nn(t,o),p=I(this.storage.getItem(this.pendingMutationKey())),p){if(p.collectionId!==e.collectionId||p.grantId!==e.grantId||p.keyId!==e.encryption?.key_id||p.operation!==t||p.inputFingerprint!==f)throw c("pending_mutation_unresolved","A previous write still has an unknown outcome. Retry that exact write before making another change.");u=p.requestId,d=!0}l=!0}if(e.encryption&&!e.authority){if(!e.grantId||!e.keyHandle)throw c("missing_grant_key","Reconnect this application to restore encrypted access.");try{if(l)if(p){if(!p.envelope)throw c("pending_mutation_unresolved","The pending write belongs to a different transport. Reconnect before retrying it.");s=p.envelope}else s=await V(this.keyStore,e.keyHandle,{grantId:e.grantId,applicationId:e.clientId,encryption:e.encryption},t,o,u),this.storage.setItem(this.pendingMutationKey(),JSON.stringify({collectionId:e.collectionId,...e.grantId?{grantId:e.grantId}:{},keyId:e.encryption.key_id,operation:t,inputFingerprint:f,requestId:u,envelope:s,createdAt:Date.now()}));else s=await V(this.keyStore,e.keyHandle,{grantId:e.grantId,applicationId:e.clientId,encryption:e.encryption},t,o)}catch(b){throw b instanceof g?x(b.code,b.message):b}a=s}else a={protocol_version:1,request_id:u,input:a},l&&!p&&this.storage.setItem(this.pendingMutationKey(),JSON.stringify({collectionId:e.collectionId,...e.grantId?{grantId:e.grantId}:{},operation:t,inputFingerprint:f,requestId:u,createdAt:Date.now()}));if(i&&s&&!e.authority){let b=!1;try{let k=await fetch(`${this.loopbackUrl}/v1/operations`,Q({method:"POST",headers:{"content-type":"application/mdbase-connect+json"},body:JSON.stringify(s),signal:r.signal}));if(!se(k.status))return k.ok&&(this.markDirectAvailable(),this.setRoute("direct")),{response:k,requestId:u,encryptedRequest:s,pendingMutation:l,resumingMutation:d};b=k.status>=500,this.markDirectUnavailable()}catch(k){if(r.signal?.aborted)throw k;b=!0,await we()==="denied"?this.setDirectStatus("denied"):this.markDirectUnavailable()}let F;try{F=e.expiresAt>Date.now()+3e4?e:await this.refreshAuthorization()}catch(k){throw l&&(b||d)?M(k):k}let T;try{T=await fetch(`${this.serverUrl}/v1/authorities/${encodeURIComponent(F.collectionId)}/operations/${t}`,{method:"POST",headers:{authorization:`Bearer ${F.accessToken}`,"content-type":"application/json"},body:JSON.stringify(s),signal:r.signal})}catch(k){throw l&&(b||d)?M(k):k}return T.ok&&this.setRoute("relay"),{response:T,requestId:u,encryptedRequest:s,directDeliveryUncertain:b,pendingMutation:l,resumingMutation:d}}let h=e.authority?`${e.authority.operationsUrl}/${t}`:`${this.serverUrl}/v1/authorities/${encodeURIComponent(e.collectionId)}/operations/${t}`,m=JSON.stringify(a),_=e.authority?await this.authorityProofHeaders(e,"POST",h,m,e.authority.accessToken):{},w=await fetch(h,{method:"POST",headers:{authorization:`Bearer ${e.authority?.accessToken??e.accessToken}`,"content-type":"application/json",..._},body:m,signal:r.signal});return w.ok&&this.setRoute(e.authority?"remote":"relay"),{response:w,requestId:u,encryptedRequest:s,pendingMutation:l,resumingMutation:d}}directCapable(e){return!(!e||e.authority||!e.encryption||!e.grantId||!e.keyHandle||this.directAccessMode==="disabled"||typeof location<"u"&&e.applicationOrigin&&e.applicationOrigin!==location.origin)}hasResumableMutationTransport(){return!!this.currentToken()}directEligible(e){return e!==null&&this.directCapable(e)&&this.storage.getItem(this.directPreferenceKey())!=="disabled"}async shouldAttemptDirect(e){if(!this.directEligible(e))return!1;if(this.directStatus==="available")return!0;if(this.directStatus==="unavailable"&&Date.now()<this.directRetryAt)return!1;let t=await we();return t==="denied"?(this.setDirectStatus("denied"),!1):(t==="prompt"||t===null)&&this.storage.getItem(this.directPreferenceKey())!=="enabled"?(this.setDirectStatus("permission_required"),!1):(this.setDirectStatus("checking"),!0)}async probeDirectAccess(){this.setDirectStatus("checking");try{let e=await fetch(`${this.loopbackUrl}/v1/ready`,Q({method:"GET",cache:"no-store"})),t=await e.json().catch(()=>null);if(e.ok&&t?.service==="mdbase-connect"&&t?.loopback_protocol_version===1&&t?.encrypted_protocol_version===1)return this.markDirectAvailable(),"available"}catch{}return await we()==="denied"?this.setDirectStatus("denied"):(this.markDirectUnavailable(),"unavailable")}markDirectAvailable(){this.directFailures=0,this.directRetryAt=0,this.setDirectStatus("available")}markDirectUnavailable(){this.directFailures+=1,this.directRetryAt=Date.now()+Math.min(6e4,1e3*2**(this.directFailures-1)),this.setDirectStatus("unavailable")}setDirectStatus(e){return this.directStatus!==e&&(this.directStatus=e,this.emitConnection()),e}setRoute(e){this.currentRoute!==e&&(this.currentRoute=e,this.emitConnection())}emitConnection(){this.onChange()}invalidateRejectedAuthorization(e){let t=I(this.storage.getItem(this.tokenKey()));!t||!Xt(t,e)||(this.internals.removeToken(this.collectionId,t.keyHandle),this.currentRoute="relay",this.directStatus=this.directAccessMode==="disabled"?"disabled":"unavailable",this.emitConnection())}currentToken(){let e=this.storage.getItem(this.tokenKey()),t=I(e),o=i=>(this.internals.removeToken(this.collectionId,typeof i=="string"?i:void 0,"invalid_stored_grant"),null);if(!t)return e&&o(),null;if(t.version!==1||typeof t.accessToken!="string"||t.accessToken.length===0||typeof t.clientId!="string"||t.clientId.length===0||t.collectionId!==this.collectionId||typeof t.collectionName!="string"||t.collectionName.length===0||!Array.isArray(t.operations)||t.operations.some(i=>typeof i!="string")||typeof t.expiresAt!="number"||!Number.isFinite(t.expiresAt)||t.refreshToken!==void 0&&(typeof t.refreshToken!="string"||t.refreshToken.length===0)||t.refreshExpiresAt!==void 0&&(typeof t.refreshExpiresAt!="number"||!Number.isFinite(t.refreshExpiresAt))||!Ke(t.scope)||t.fileCapability&&!Be(t.fileCapability)||t.authority&&!rn(t.authority,t.collectionId))return o(t.keyHandle);if(this.internals.relayEncryption==="required"){if(t.authority){if(!t.keyHandle||!t.authority.proofPublicKey)return o(t.keyHandle)}else if(!t.grantId||!t.keyHandle||!an(t.encryption,t.collectionId))return o(t.keyHandle)}return t.expiresAt<=Date.now()&&(!t.refreshToken||(t.refreshExpiresAt??0)<=Date.now())?this.directCapable(t)?t:(this.internals.removeToken(this.collectionId,t.keyHandle),null):t}async authorizedToken(){let e=this.currentToken();if(!e)return null;if(e.expiresAt>Date.now()+3e4)return e;if(!e.refreshToken||(e.refreshExpiresAt??0)<=Date.now()){if(this.directCapable(e))throw c("relay_authorization_expired","Direct access is still available on this computer, but using the relay requires reconnecting this application.");return this.internals.removeToken(this.collectionId,e.keyHandle),null}return this.refreshAuthorization()}refreshAuthorization(){return this.refreshPromise?this.refreshPromise:(this.refreshPromise=this.performRefresh().finally(()=>{this.refreshPromise=null}),this.refreshPromise)}async performRefresh(){let e=this.currentToken();if(!e?.refreshToken)throw c("not_authorized","Reconnect this application to continue.");if((e.refreshExpiresAt??0)<=Date.now())throw c("relay_authorization_expired","Direct access is still available on this computer, but using the relay requires reconnecting this application.");let t=e.refreshToken,o=`${this.serverUrl}/oauth/token`,i=new URLSearchParams({grant_type:"refresh_token",refresh_token:e.refreshToken,client_id:e.clientId}).toString(),r=e.authority?await this.authorityProofHeaders(e,"POST",o,i,e.refreshToken):{},a=await fetch(o,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded",...r},body:i}),s=await a.json();if(!a.ok){let l=this.currentToken();if(l?.refreshToken&&l.refreshToken!==t)return l;throw this.directCapable(e)||this.internals.removeToken(this.collectionId,e.keyHandle),(Pe(s)??s?.error?.code)==="invalid_grant"?c("authorization_expired",s?.error_description??s?.error?.message??"Reconnect this application to continue.",{status:a.status}):C(s,"authorization_expired","Reconnect this application to continue.",a.status)}return this.storeTokenResponse(s,e.clientId,e.keyHandle)}async authorityProofHeaders(e,t,o,i,r){if(!e.authority?.proofPublicKey)return{};if(!e.keyHandle)throw c("missing_grant_key","Reconnect this application to restore remote authority request signing.");try{let a=new URL(o);return await Dt(this.keyStore,e.keyHandle,e.authority.proofPublicKey,{method:t,target:`${a.pathname}${a.search}`,body:i,credential:r})}catch(a){throw a instanceof g?x(a.code,a.message):a}}storeTokenResponse(e,t,o){if(e.collection_id!==this.collectionId)throw c("collection_mismatch","The refreshed authorization belongs to a different collection.");let i=this.internals.storeTokenResponse(e,t,o);return this.currentRoute=i.authority?"remote":"relay",this.directStatus=i.authority||this.directAccessMode==="disabled"?"disabled":"unavailable",this.emitConnection(),i}tokenKey(){return this.internals.tokenKey(this.collectionId)}notificationKey(e="web_push"){return this.internals.notificationKey(this.collectionId,e)}pendingMutationKey(){return this.internals.pendingMutationKey(this.collectionId)}clearPendingMutation(){this.storage.removeItem(this.pendingMutationKey())}directPreferenceKey(){return this.internals.directPreferenceKey()}};var Po=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),Ro=new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),de=class{state=Ro.slice();block=new Uint8Array(64);words=new Uint32Array(64);blockLength=0;byteLength=0;finished=!1;update(e){if(this.finished)throw new Error("SHA-256 digest is already finalized.");if(this.byteLength+=e.byteLength,!Number.isSafeInteger(this.byteLength))throw new Error("SHA-256 input exceeds the safe browser byte range.");let t=0;if(this.blockLength>0){let o=Math.min(64-this.blockLength,e.byteLength);this.block.set(e.subarray(0,o),this.blockLength),this.blockLength+=o,t+=o,this.blockLength===64&&(this.compress(this.block),this.blockLength=0)}for(;t+64<=e.byteLength;)this.compress(e.subarray(t,t+64)),t+=64;return t<e.byteLength&&(this.block.set(e.subarray(t),0),this.blockLength=e.byteLength-t),this}digestHex(){if(this.finished)throw new Error("SHA-256 digest is already finalized.");this.finished=!0,this.block[this.blockLength]=128,this.block.fill(0,this.blockLength+1),this.blockLength>=56&&(this.compress(this.block),this.block.fill(0));let e=this.byteLength*8,t=Math.floor(e/4294967296),o=e>>>0;return wn(this.block,56,t),wn(this.block,60,o),this.compress(this.block),[...this.state].map(i=>i.toString(16).padStart(8,"0")).join("")}compress(e){let t=this.words;for(let p=0;p<16;p+=1){let f=p*4;t[p]=(e[f]<<24|e[f+1]<<16|e[f+2]<<8|e[f+3])>>>0}for(let p=16;p<64;p+=1){let f=t[p-15],h=t[p-2],m=z(f,7)^z(f,18)^f>>>3,_=z(h,17)^z(h,19)^h>>>10;t[p]=t[p-16]+m+t[p-7]+_>>>0}let o=this.state[0],i=this.state[1],r=this.state[2],a=this.state[3],s=this.state[4],l=this.state[5],d=this.state[6],u=this.state[7];for(let p=0;p<64;p+=1){let f=z(s,6)^z(s,11)^z(s,25),h=s&l^~s&d,m=u+f+h+Po[p]+t[p]>>>0,_=z(o,2)^z(o,13)^z(o,22),w=o&i^o&r^i&r,b=_+w>>>0;u=d,d=l,l=s,s=a+m>>>0,a=r,r=i,i=o,o=m+b>>>0}this.state[0]=this.state[0]+o>>>0,this.state[1]=this.state[1]+i>>>0,this.state[2]=this.state[2]+r>>>0,this.state[3]=this.state[3]+a>>>0,this.state[4]=this.state[4]+s>>>0,this.state[5]=this.state[5]+l>>>0,this.state[6]=this.state[6]+d>>>0,this.state[7]=this.state[7]+u>>>0}};function z(n,e){return n>>>e|n<<32-e}function wn(n,e,t){n[e]=t>>>24,n[e+1]=t>>>16,n[e+2]=t>>>8,n[e+3]=t}var Je=class{constructor(e,t){this.signal=t;this.iterator=So(e)}signal;iterator;remainder=new Uint8Array;remainderOffset=0;maxSourceChunkBytes=null;iteratorClosing=!1;ended=!1;setMaxSourceChunkBytes(e){this.maxSourceChunkBytes=e}async read(e){let t=new Uint8Array(e),o=0;for(;o<e;){if(this.remainderOffset===this.remainder.byteLength){let r=await this.nextSourceChunk();if(r.done)throw this.ended=!0,c("invalid_request","Streamed file bytes ended before the declared size.");if(!(r.value instanceof Uint8Array))throw c("invalid_request","A streamed file chunk was not a Uint8Array.");if(this.maxSourceChunkBytes===null)throw new Error("Stream source was read before upload negotiation completed.");if(r.value.byteLength>this.maxSourceChunkBytes)throw c("invalid_request",`A streamed file chunk exceeded the negotiated ${this.maxSourceChunkBytes}-byte upload part size.`);if(this.remainder=r.value,this.remainderOffset=0,this.remainder.byteLength===0)continue}let i=Math.min(e-o,this.remainder.byteLength-this.remainderOffset);t.set(this.remainder.subarray(this.remainderOffset,this.remainderOffset+i),o),o+=i,this.remainderOffset+=i}return t}async expectEnd(){if(this.remainderOffset<this.remainder.byteLength)throw c("invalid_request","Streamed file bytes exceed the declared size.");for(;!this.ended;){let e=await this.nextSourceChunk();if(e.done){this.ended=!0;return}if(!(e.value instanceof Uint8Array))throw c("invalid_request","A streamed file chunk was not a Uint8Array.");if(e.value.byteLength>0)throw c("invalid_request","Streamed file bytes exceed the declared size.")}}async close(){this.ended=!0,this.closeIterator()}async nextSourceChunk(){Cn(this.signal);let e=this.iterator.next(),t=this.signal;if(!t)return e;let o=()=>{},i=new Promise((r,a)=>{let s=()=>{this.closeIterator(),a(Pn(t))};t.addEventListener("abort",s,{once:!0}),o=()=>t.removeEventListener("abort",s),t.aborted&&s()});try{let r=await Promise.race([e,i]);return Cn(t),r}finally{o()}}closeIterator(){if(!this.iteratorClosing){this.iteratorClosing=!0;try{this.iterator.return?.()?.catch(()=>{})}catch{}}}};function So(n){if(typeof n.getReader=="function"){let t=n.getReader(),o=!1,i=()=>{o||(o=!0,t.releaseLock())};return{async next(){if(o)return{done:!0,value:void 0};let r=await t.read();return r.done&&i(),r},async return(){if(!o)try{await t.cancel()}finally{i()}return{done:!0,value:void 0}}}}let e=n;if(typeof e[Symbol.asyncIterator]!="function")throw c("invalid_request","Streamed files require a readable byte stream.");return e[Symbol.asyncIterator]()}function Cn(n){if(n?.aborted)throw Pn(n)}function Pn(n){return c("operation_cancelled","The file transfer was cancelled.",{operationOutcome:"not_sent",cause:n?.reason})}var Rn=1024*1024,ko=4,Sn=8,ue=3,kn=64*1024*1024,Oo=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu,Ao=/^sha256:[0-9a-f]{64}$/u,Se=class{constructor(e,t,o,i){this.capability=e;this.request=t;this.framed=o;this.hosted=i}capability;request;framed;hosted;async*list(e={}){this.requireAction("list");let t;do{W(e.signal);let o=new URLSearchParams({protocol_version:String(1),...e.folder?{folder:e.folder}:{},...t?{after:t}:{},...e.pageSize?{limit:String(Mo(e.pageSize))}:{}}),i=await this.request("GET",`?${o.toString()}`,void 0,e.signal);if(i.protocol_version!==1||i.type!=="files_page"||!Array.isArray(i.files))throw c("invalid_operation_response","The authority returned an invalid file page.");for(let r of i.files)W(e.signal),yield r;t=i.next}while(t)}async upload(e,t,o={}){this.requireAction(o.ifRevision?"replace":"add");let i=Io(t,o.mediaType),r=On(o.concurrency),a=await To(i,o.signal,s=>{o.onProgress?.({phase:"hashing",transferredBytes:s,totalBytes:i.size})});return this.uploadKnownSource(e,i.size,`sha256:${a}`,(o.mediaType??i.type)||void 0,o,r,async(s,l,d)=>i.slice(l,l+d))}async uploadStream(e,t,o={}){if(this.requireAction(o.ifRevision?"replace":"add"),!Number.isSafeInteger(t.size)||t.size<0)throw c("invalid_request","Streamed file size must be a non-negative safe integer.");if(!Ao.test(t.contentDigest))throw c("invalid_request","Streamed files require a lowercase SHA-256 content digest.");let i=new Je(t.stream,o.signal),r=new de;return this.uploadKnownSource(e,t.size,t.contentDigest,o.mediaType??t.mediaType,o,1,async(a,s,l)=>{let d=await i.read(l);return r.update(d),d},async()=>{if(await i.expectEnd(),`sha256:${r.digestHex()}`!==t.contentDigest)throw c("invalid_request","Streamed file bytes do not match the declared SHA-256 digest.")},()=>i.close(),a=>i.setMaxSourceChunkBytes(a))}async uploadKnownSource(e,t,o,i,r,a,s,l,d,u){let p=r.transferId??crypto.randomUUID();if(!Oo.test(p))throw c("invalid_request","File transfer ID must be a UUID.");let f=!1;try{let h=await this.request("POST","uploads",{protocol_version:1,type:"open_file_upload",transfer_id:p,path:e,size:t,content_digest:o,...i?{media_type:i}:{},...r.ifRevision?{if_revision:r.ifRevision}:{}},r.signal);if(An(h,p,"upload"),h.total_size!==t||h.strategy.kind==="object_ranges")throw c("invalid_operation_response","The authority returned an incompatible upload strategy.");let m=h.strategy.kind==="framed_chunks";if(m&&!this.framed)throw c("invalid_operation_response","Encrypted file chunk delivery is unavailable.");let _=h.strategy.kind==="object_put"?Math.max(1,t):h.strategy.kind==="framed_chunks"?h.strategy.chunk_size:h.strategy.part_size,w=h.strategy.kind==="object_put"?1:Math.ceil(t/_);if(u?.(_),!m&&h.received.length===w){let O=await this.tryReplayUploadCommit(p,h.strategy.kind==="object_multipart"?h.uploaded_parts:void 0,r.signal);if(O)return f=!0,O.file}let b=new Set(h.received),F=new Map((h.uploaded_parts??[]).map(O=>[O.part_number-1,O])),T=[...b].reduce((O,pe)=>O+Uo(t,_,pe),0),k=await Lo(w,a,async O=>{let pe=O*_,Te=Math.min(_,Math.max(0,t-pe)),Xe=await s(O,pe,Te);if(Eo(Xe)!==Te)throw c("invalid_request","Streamed file bytes ended before the declared size.");if(b.has(O))return F.get(O)??null;let En=m?await bt(async()=>this.framed.uploadChunk(h,O,await xo(Xe),r.signal),r.signal).then(()=>null):await this.uploadPart(p,O,pe,Xe,Te,h.strategy.kind==="object_multipart",r.signal);return T+=Te,r.onProgress?.({phase:"uploading",transferredBytes:T,totalBytes:t}),En});await l?.();let K=await this.commitUpload(p,h.strategy.kind==="object_multipart"?k.filter(O=>O!==null):void 0,r.signal);if(K.protocol_version!==1||K.type!=="file_upload_committed"||K.transfer_id!==p||K.file.path!==e||K.file.size!==t||K.file.content_digest!==o)throw c("invalid_operation_response","The authority returned an invalid file receipt.");return f=!0,K.file}catch(h){throw Re(h)}finally{await d?.().catch(()=>{}),!f&&r.transferId===void 0&&await this.abort(p)}}async download(e,t={}){if(e.size>kn)throw c("invalid_request",`download() buffers at most ${kn} bytes; use downloadStream() for larger files.`);let o=await this.downloadStream(e,t),i=[],r=o.getReader();for(;;){let a=await r.read();if(a.done)break;i.push(a.value)}return new Blob(i.map(a=>{let s=new Uint8Array(a.byteLength);return s.set(a),s.buffer}),{type:e.media_type??""})}async downloadStream(e,t={}){this.requireAction("read"),On(t.concurrency);let o=crypto.randomUUID(),i;try{if(i=await this.request("POST","downloads",{protocol_version:1,type:"open_file_download",transfer_id:o,file_id:e.file_id,revision:e.revision},t.signal),An(i,o,"download"),i.total_size!==e.size||i.strategy.kind!=="object_ranges"&&i.strategy.kind!=="framed_chunks")throw c("invalid_operation_response","The authority returned an incompatible download session.");if(i.strategy.kind==="framed_chunks"&&!this.framed)throw c("invalid_operation_response","Encrypted file chunk delivery is unavailable.");if(i.strategy.kind==="object_ranges"&&e.size>0&&!this.hosted)throw c("invalid_operation_response","Authenticated hosted file delivery is unavailable.")}catch(_){throw await this.abort(o),Re(_)}let r=i.strategy.kind==="framed_chunks"?i.strategy.chunk_size:i.strategy.part_size,a=Math.ceil(e.size/r),s=new de,l=0,d=0,u=null,p=0,f=!1,h=async()=>{f||(f=!0,await u?.cancel().catch(()=>{}),u=null,await this.abort(o))},m=()=>{if(p!==e.size||`sha256:${s.digestHex()}`!==e.content_digest)throw c("invalid_operation_response","Downloaded file bytes failed integrity verification.")};return new ReadableStream({pull:async _=>{try{if(W(t.signal),i.strategy.kind==="object_ranges")for(;;){if(!u){if(l>=a){m(),await h(),_.close();return}let k=l*r;d=Math.min(r,e.size-k),u=(await bt(()=>this.hosted.downloadPart(i,l,d,t.signal),t.signal)).getReader()}let T=await u.read();if(T.done){if(u.releaseLock(),u=null,d!==0)throw c("invalid_operation_response","A hosted file range ended before its declared byte length.");l+=1;continue}if(!(T.value instanceof Uint8Array))throw c("invalid_operation_response","A hosted file range returned a non-byte chunk.");if(T.value.byteLength!==0){if(T.value.byteLength>d)throw c("invalid_operation_response","A hosted file range exceeded its declared byte length.");d-=T.value.byteLength,s.update(T.value),p+=T.value.byteLength,t.onProgress?.({phase:"downloading",transferredBytes:p,totalBytes:e.size}),_.enqueue(T.value);return}}if(l>=a){m(),await h(),_.close();return}let w=l*r,b=Math.min(r,e.size-w),F=await bt(()=>this.framed.downloadChunk(i,l,t.signal),t.signal);if(F.byteLength!==b)throw c("invalid_operation_response","A file chunk had the wrong byte length.");s.update(F),p+=F.byteLength,l+=1,t.onProgress?.({phase:"downloading",transferredBytes:p,totalBytes:e.size}),l===a&&m(),_.enqueue(F),l===a&&(await h(),_.close())}catch(w){await h(),_.error(Re(w))}},cancel:h})}async downloadBytes(e,t={}){return new Uint8Array(await(await this.download(e,t)).arrayBuffer())}async move(e,t,o={}){this.requireAction("move");let i=o.mutationId??crypto.randomUUID(),r;try{r=await this.request("POST",`${encodeURIComponent(e.file_id)}/move`,{protocol_version:1,type:"move_file",mutation_id:i,file_id:e.file_id,if_revision:o.ifRevision??e.revision,from_path:e.path,path:t,update_references:!1},o.signal)}catch(a){throw Re(a)}if(r.protocol_version!==1||r.type!=="file_moved"||r.mutation_id!==i||r.file.file_id!==e.file_id||r.file.path!==t)throw c("invalid_operation_response","The authority returned an invalid file move receipt.");return r.file}async delete(e,t={}){this.requireAction("delete");let o=t.mutationId??crypto.randomUUID(),i;try{i=await this.request("POST",`${encodeURIComponent(e.file_id)}/delete`,{protocol_version:1,type:"delete_file",mutation_id:o,file_id:e.file_id,if_revision:t.ifRevision??e.revision,path:e.path},t.signal)}catch(r){throw Re(r)}if(i.protocol_version!==1||i.type!=="file_deleted"||i.mutation_id!==o||i.file_id!==e.file_id||i.previous_path!==e.path)throw c("invalid_operation_response","The authority returned an invalid file delete receipt.");return i}async uploadPart(e,t,o,i,r,a,s){for(let l=1;l<=ue;l+=1){W(s);try{let d=await this.request("POST",`uploads/${encodeURIComponent(e)}/parts`,{protocol_version:1,type:"prepare_file_upload_part",transfer_id:e,part_number:t+1,content_length:r},s);Do(d,e,t,o,r,"PUT");let u=await fetch(d.url,{method:d.method,headers:zo(d.headers),body:i,redirect:"error",signal:s});if(!u.ok)throw new Error(`Object upload failed with HTTP ${u.status}.`);let p=u.headers.get("etag");if(a&&!p)throw new Error("Multipart object upload did not return an ETag.");return{part_number:t+1,etag:p??""}}catch(d){if(s?.aborted||l===ue)throw d}}throw new Error("Unreachable upload retry state.")}async tryReplayUploadCommit(e,t,o){try{return await this.commitUpload(e,t,o)}catch(i){if(i instanceof v&&i.code==="file_upload_incomplete")return null;throw i}}async commitUpload(e,t,o){let i;for(let r=1;r<=ue;r+=1){W(o);try{return await this.request("POST",`uploads/${encodeURIComponent(e)}/commit`,{protocol_version:1,type:"commit_file_upload",transfer_id:e,...t===void 0?{}:{parts:t}},o)}catch(a){if(i=a,o?.aborted||a instanceof v||r===ue)throw a}}throw i}requireAction(e){if(!this.capability()?.actions.includes(e))throw c("not_authorized",`This connection is not authorized to ${e} files.`)}async abort(e){await this.request("DELETE",`transfers/${encodeURIComponent(e)}`).catch(()=>{})}};async function To(n,e,t){let o=new de;for(let i=0;i<n.size;i+=Rn){W(e);let r=new Uint8Array(await n.slice(i,i+Rn).arrayBuffer());o.update(r),t(Math.min(n.size,i+r.byteLength))}return n.size===0&&t(0),o.digestHex()}function Io(n,e){if(n instanceof Blob)return e&&e!==n.type?n.slice(0,n.size,e):n;if(n instanceof ArrayBuffer)return new Blob([n],{type:e});let t=new Uint8Array(n.byteLength);return t.set(new Uint8Array(n.buffer,n.byteOffset,n.byteLength)),new Blob([t.buffer],{type:e})}function Eo(n){return n instanceof Blob?n.size:n.byteLength}async function xo(n){return n instanceof Blob?new Uint8Array(await n.arrayBuffer()):n}function On(n=ko){if(!Number.isInteger(n)||n<1||n>Sn)throw c("invalid_request",`File concurrency must be between 1 and ${Sn}.`);return n}function Mo(n){if(!Number.isInteger(n)||n<1||n>1e3)throw c("invalid_request","File page size must be between 1 and 1000.");return n}function An(n,e,t){if(n.protocol_version!==1||n.type!=="file_transfer"||n.transfer_id!==e||n.direction!==t||!Number.isSafeInteger(n.total_size)||n.total_size<0||!Array.isArray(n.received)||!Fo(n))throw c("invalid_operation_response","The authority returned an invalid file transfer session.");let o=n.strategy.kind==="framed_chunks"?n.strategy.chunk_size:n.strategy.kind==="object_put"?Math.max(1,n.total_size):n.strategy.part_size,i=n.strategy.kind==="object_put"?1:Math.ceil(n.total_size/o);if(new Set(n.received).size!==n.received.length||n.received.some(a=>!Number.isSafeInteger(a)||a<0||a>=i))throw c("invalid_operation_response","The authority returned invalid transfer progress.");let r=n.uploaded_parts??[];if(!Array.isArray(r)||r.some((a,s)=>!Number.isSafeInteger(a?.part_number)||a.part_number<1||a.part_number>i||typeof a.etag!="string"||a.etag.length===0||a.etag.length>255||s>0&&r[s-1].part_number>=a.part_number)||(n.strategy.kind==="object_multipart"?r.length!==n.received.length||r.some((a,s)=>a.part_number-1!==n.received[s]):r.length!==0))throw c("invalid_operation_response","The authority returned invalid uploaded part receipts.")}function Fo(n){return n.strategy.kind==="framed_chunks"?n.protection==="grant_aead_v1"&&Number.isSafeInteger(n.strategy.chunk_size)&&n.strategy.chunk_size>0:n.protection!=="transport_tls"?!1:n.strategy.kind==="object_put"?!0:Number.isSafeInteger(n.strategy.part_size)&&n.strategy.part_size>0}function Uo(n,e,t){return Math.min(e,Math.max(0,n-t*e))}async function bt(n,e){for(let t=1;t<=ue;t+=1){W(e);try{return await n()}catch(o){if(e?.aborted||t===ue)throw o}}throw new Error("Unreachable file chunk retry state.")}function Do(n,e,t,o,i,r){let a;try{a=new URL(n.url)}catch{throw c("invalid_operation_response","The authority returned an invalid object URL.")}if(n.protocol_version!==1||n.type!=="file_part"||n.transfer_id!==e||n.part_index!==t||n.offset!==o||n.content_length!==i||n.method.toUpperCase()!==r||a.protocol!=="https:"&&!(a.protocol==="http:"&&["localhost","127.0.0.1","[::1]","::1"].includes(a.hostname))||a.username||a.password)throw c("invalid_operation_response","The authority returned an invalid prepared file part.")}function zo(n){let e=new Headers;for(let[t,o]of Object.entries(n))["host","content-length"].includes(t.toLowerCase())||e.set(t,o);return e}async function Lo(n,e,t){let o=new Array(n),i=0;return await Promise.all(Array.from({length:Math.min(n,e)},async()=>{for(;i<n;){let r=i;i+=1,o[r]=await t(r)}})),o}function W(n){if(n?.aborted)throw c("operation_cancelled","The file transfer was cancelled.",{operationOutcome:"not_sent",cause:n.reason})}function Re(n){return n instanceof v?n:typeof DOMException<"u"&&n instanceof DOMException&&n.name==="AbortError"?c("operation_cancelled","The file transfer was cancelled.",{operationOutcome:"not_sent",cause:n}):c("temporarily_unavailable","The file transfer could not be completed.",{cause:n})}var Z=["describe","changes","read","query"];var ke=class{constructor(e,t){this.internals=e;this.collectionId=t;this.transport=new Ye({serverUrl:e.serverUrl,storage:e.storage,keyStore:e.keyStore,directAccessMode:e.directAccessMode,loopbackUrl:e.loopbackUrl,collectionId:t,internals:e,onChange:()=>this.emitConnection()}),this.files=new Se(()=>this.fileCapability,(o,i,r,a)=>this.transport.files.control(o,i,r,a),{uploadChunk:(o,i,r,a)=>this.transport.files.uploadChunk(o,i,r,a),downloadChunk:(o,i,r)=>this.transport.files.downloadChunk(o,i,r)},{downloadPart:(o,i,r,a)=>this.transport.files.downloadHostedPart(o,i,r,a)}),this.collectionClient=new be({operation:(o,i,r)=>this.transport.performOperation(o,i,r)}),this.notifications=new je({serverUrl:e.serverUrl,storage:e.storage,authorizedToken:()=>this.transport.authorizedToken(),register:()=>this.internals.register(),notificationKey:o=>e.notificationKey(t,o)})}internals;collectionId;collectionClient;notifications;transport;files;connectionListeners=new Set;get displayName(){return this.transport.currentToken()?.collectionName??`Collection ${this.collectionId.slice(0,8)}`}get operations(){return[...this.transport.currentToken()?.operations??[]]}get scope(){return this.transport.currentToken()?.scope??null}get fileCapability(){return this.transport.currentToken()?.fileCapability??null}get directAccess(){return this.transport.directAccess}get route(){return this.transport.route}register(){return P(()=>this.internals.register(),Y)}info(){let e=this.transport.currentToken();return e?{collectionId:e.collectionId,displayName:e.collectionName,operations:[...e.operations],scope:e.scope,...e.fileCapability?{fileCapability:e.fileCapability}:{},route:this.transport.route,directAccess:this.transport.directAccess}:null}authorizationCapabilities(e=Z){let t=this.operations,o=D(e).filter(i=>!t.includes(i));return{authorized:this.info()!==null,sufficient:this.info()!==null&&o.length===0,collectionId:this.collectionId,grantedOperations:t,missingOperations:o}}hasOperations(e){return this.authorizationCapabilities(e).sufficient}authorize(e={}){return P(()=>this.internals.authorize({...e,target:{kind:"collection",collectionId:this.collectionId}}),J)}async requestOperations(e,t={}){let o=this.authorizationCapabilities(e);return o.sufficient?A({kind:"unchanged",connection:this}):this.authorize({...t,operations:D([...o.grantedOperations,...o.missingOperations])})}onConnectionChange(e){return this.connectionListeners.add(e),e(this.info()),()=>this.connectionListeners.delete(e)}notifyStorageChanged(){this.transport.notifyStorageChanged()}checkDirectAccess(){return P(()=>this.transport.checkDirectAccess(),Le)}requestDirectAccess(){return P(()=>this.transport.requestDirectAccess(),Le)}disableDirectAccess(){this.transport.disableDirectAccess()}sync(){let e=this.transport.currentToken();if(!e)return null;let t=e.collectionId;if(!e.authority){if(!e.grantId||!e.operations.includes("sync"))return null;let i=e.grantId;return{collectionId:t,replicaId:i,transport:{openSession:()=>this.transport.performOperation("sync",{action:"open_session"}),snapshot:(r,a)=>this.transport.performOperation("sync",{action:"snapshot",snapshot_id:r,...a?{page:a}:{}}),changes:(r,a=200)=>this.transport.performOperation("sync",{action:"changes",after:r,limit:a}),mutate:r=>this.transport.performOperation("sync",{action:"mutate",mutation:r})}}}let o=e.authority.replicaId;return{collectionId:t,replicaId:o,transport:{openSession:()=>this.transport.performAuthoritySyncRequest(t,o,"POST","sessions"),snapshot:(i,r)=>{let a=new URLSearchParams({snapshot_id:i});return r&&a.set("page",r),this.transport.performAuthoritySyncRequest(t,o,"GET",`snapshot?${a}`)},changes:(i,r=200)=>this.transport.performAuthoritySyncRequest(t,o,"GET",`changes?${new URLSearchParams({after:String(i),limit:String(r)})}`),mutate:i=>this.transport.performAuthoritySyncRequest(t,o,"POST","mutations",i)}}}registerNotifications(e){return P(()=>this.notifications.registerNotifications(e),re)}registerNativeNotifications(e){return P(()=>this.notifications.registerNativeNotifications(e),re)}unregisterNativeNotifications(){return P(()=>this.notifications.unregisterNativeNotifications(),re)}unregisterNotifications(e){return P(()=>this.notifications.unregisterNotifications(e),re)}forget(){let e=this.transport.currentToken();this.internals.removeToken(this.collectionId,e?.keyHandle,"not_authorized"),this.transport.notifyStorageChanged()}describe(){return this.collectionClient.describe()}changes(e={},t){return this.collectionClient.changes(e,t)}read(e){return this.collectionClient.read(e)}query(e={},t){return this.collectionClient.query(e,t)}queryPages(e={},t={}){return this.collectionClient.queryPages(e,t)}queryAll(e={},t={}){return this.collectionClient.queryAll(e,t)}listViews(){return this.collectionClient.listViews()}executeView(e){return this.collectionClient.executeView(e)}readViewSource(e){return this.collectionClient.readViewSource(e)}createViewSource(e){return this.collectionClient.createViewSource(e)}updateViewSource(e){return this.collectionClient.updateViewSource(e)}deleteViewSource(e){return this.collectionClient.deleteViewSource(e)}create(e){return this.collectionClient.create(e)}update(e){return this.collectionClient.update(e)}delete(e,t){return this.collectionClient.delete(e,t)}preflightDelete(e,t){return this.collectionClient.preflightDelete(e,t)}rename(e,t){return this.collectionClient.rename(e,t)}preflightRename(e,t){return this.collectionClient.preflightRename(e,t)}async renameWithProgress(e,t={}){let o=Date.now(),i=this.pendingMutation()?.operation==="rename",r,a=(s,l,d=0)=>{t.onProgress?.({operation:"rename",state:s,elapsedMs:Date.now()-o,cancellable:l,resumed:i,completedUnits:d,...r?{estimate:r}:{}})};try{X(t.signal),a("preflighting",!0);let s=t.preflight?A(t.preflight):await this.preflightRename(e,{signal:t.signal});if(!s.ok)return s;let l=s.value;try{Wt(e,l)}catch(p){if(p instanceof v)return R(p.problem);throw p}r=en(e,l),a("ready",!0),X(t.signal);let d=this.transport.hasResumableMutationTransport();a("applying",d);let u=await this.rename(e,d?{signal:t.signal}:void 0);return u.ok&&a("completed",!1,r.totalUnits),u}catch(s){if(ft(s,t.signal)&&a("cancelled",!1),s instanceof v)return R(s.problem);throw s}}async deleteWithProgress(e,t={}){let o=Date.now(),i=this.pendingMutation()?.operation==="delete",r,a=(s,l,d=0)=>{t.onProgress?.({operation:"delete",state:s,elapsedMs:Date.now()-o,cancellable:l,resumed:i,completedUnits:d,...r?{estimate:r}:{}})};try{X(t.signal),a("preflighting",!0);let s=t.preflight?A(t.preflight):await this.preflightDelete(e,{signal:t.signal});if(!s.ok)return s;let l=s.value;try{Zt(e,l)}catch(p){if(p instanceof v)return R(p.problem);throw p}r=tn(l),a("ready",!0),X(t.signal);let d=this.transport.hasResumableMutationTransport();a("applying",d);let u=await this.delete(e,d?{signal:t.signal}:void 0);return u.ok&&a("completed",!1,r.totalUnits),u}catch(s){if(ft(s,t.signal)&&a("cancelled",!1),s instanceof v)return R(s.problem);throw s}}pendingMutation(){return this.transport.pendingMutation()}resumePendingMutation(e,t){return P(()=>this.transport.resumePendingMutation(e,t),S)}validate(e={}){return this.collectionClient.validate(e)}readType(e){return this.collectionClient.readType(e)}createType(e){return this.collectionClient.createType(e)}updateType(e){return this.collectionClient.updateType(e)}installTypePack(e){return this.collectionClient.installTypePack(e)}listTimers(e){return this.collectionClient.listTimers(e)}putTimer(e){return this.collectionClient.putTimer(e)}cancelTimer(e){return this.collectionClient.cancelTimer(e)}reconcileTimers(e){return this.collectionClient.reconcileTimers(e)}watch(e={}){return this.collectionClient.watch(e)}operation(e,t,o){return this.collectionClient.operation(e,t,o)}emitConnection(){let e=this.info();for(let t of this.connectionListeners)t(e)}};function Oe(n){for(let e of["code","state","error","error_description"])n.searchParams.delete(e);return n}function Qe(n){let e;try{e=new URL(n)}catch{return!1}return e.searchParams.has("state")&&(e.searchParams.has("code")||e.searchParams.has("error"))}function Tn(n){if(!n.details||typeof n.details!="object"||Array.isArray(n.details))return;let e=n.details.return_to;return typeof e=="string"?e:void 0}var Ae=class{constructor(e,t){this.connect=e;this.operations=D(t.operations??Z),this.selection=t.selection,this.autoSelect=t.autoSelect??"only",this.snapshot={status:"unselected",connections:[]},this.refresh()}connect;operations;selection;autoSelect;listeners=new Set;snapshot;snapshotKey="";stopConnections;stopSelection;stopActiveConnection;activeCollectionId=null;unavailableReason="not_authorized";started=!1;refreshing=!1;refreshQueued=!1;transactionDepth=0;callbackPromise=null;async start(){this.started||(this.started=!0,this.stopConnections=this.connect.onConnectionsChange(()=>this.refresh()),this.stopSelection=this.selection.subscribe(()=>{this.unavailableReason="not_authorized",this.refresh()}));let e=this.selection.authorizationCallback();if(e){let t=await this.handleAuthorizationCallback(e);if(!t.ok)return t}else this.autoSelectOnlyConnection();return this.refresh(),A(this.snapshot)}destroy(){this.stopConnections?.(),this.stopSelection?.(),this.stopActiveConnection?.(),this.stopConnections=void 0,this.stopSelection=void 0,this.stopActiveConnection=void 0,this.activeCollectionId=null,this.started=!1}getSnapshot(){return this.snapshot}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}select(e,t={}){let o=this.connect.connection(e);return o?(this.unavailableReason="not_authorized",this.selection.select(e,t),this.refresh(),A(o)):R(E("unknown_collection","This collection is not authorized for this application."))}clearSelection(e={}){this.unavailableReason="not_authorized",this.selection.select(null,e),this.refresh()}forget(e){this.transactionDepth+=1;try{let t=this.selection.selectedCollectionId()===e;this.connect.connection(e)?.forget(),t&&this.selection.select(null,{history:"replace"})}finally{this.transactionDepth-=1,this.refresh()}}async authorize(e,t={}){let o=this.selection.selectedCollectionId();if(e==="selected"&&!o)return R(E("collection_not_selected","Choose a collection before updating its access."));let i=typeof e=="object"?e.collectionId:e==="selected"?o:null;this.transactionDepth+=1;try{let r=await this.connect.authorize({...t,operations:this.operations,target:i===null?{kind:"choose"}:{kind:"collection",collectionId:i},returnTo:this.selection.authorizationReturnTo()});return r.ok&&r.value.kind==="connected"&&this.selection.finishAuthorization(r.value.returnTo,r.value.connection.collectionId),r}finally{this.transactionDepth-=1,this.refresh()}}async ensureOperations(e){let t=this.snapshot;if(t.status!=="ready")return R(E("collection_not_ready","Choose an authorized collection first."));let o=D(e),i=t.connection.authorizationCapabilities(o);if(i.sufficient)return A({kind:"unchanged",connection:t.connection});this.transactionDepth+=1;try{let r=await this.connect.authorize({operations:D([...i.grantedOperations,...i.missingOperations]),target:{kind:"collection",collectionId:t.collectionId},returnTo:this.selection.authorizationReturnTo()});return r.ok&&r.value.kind==="connected"&&this.selection.finishAuthorization(r.value.returnTo,r.value.connection.collectionId),r}finally{this.transactionDepth-=1,this.refresh()}}handleAuthorizationCallback(e){if(!Qe(e))return Promise.resolve(R(E("invalid_callback","This URL is not an authorization callback.")));if(this.callbackPromise)return this.callbackPromise;this.transactionDepth+=1;let t=this.connect.completeAuthorization(e).then(o=>{if(!o.ok){let r=Tn(o.problem);return this.selection.clearAuthorizationCallback(r),this.refresh(),o}let i=o.value;return this.unavailableReason="not_authorized",this.selection.finishAuthorization(i.returnTo,i.connection.collectionId),this.refresh(),A(i.connection,o.diagnostics)}).catch(o=>{throw this.selection.clearAuthorizationCallback(),this.refresh(),o}).finally(()=>{this.transactionDepth-=1,this.refresh(),this.callbackPromise===t&&(this.callbackPromise=null)});return this.callbackPromise=t,t}autoSelectOnlyConnection(){if(this.autoSelect!=="only"||this.selection.selectedCollectionId())return;let e=this.connect.connections();e.length===1&&this.selection.select(e[0].collectionId,{history:"replace"})}refresh(){if(this.transactionDepth>0){this.refreshQueued=!0;return}if(this.refreshing){this.refreshQueued=!0;return}this.refreshing=!0;try{do this.refreshQueued=!1,this.refreshOnce();while(this.refreshQueued)}finally{this.refreshing=!1}}refreshOnce(){let e=this.selection.selectedCollectionId(),t=this.connect.connections(),o=e?this.connect.connection(e):null;o?.collectionId!==this.activeCollectionId&&(this.stopActiveConnection?.(),this.activeCollectionId=o?.collectionId??null,this.stopActiveConnection=o?.onConnectionChange(a=>{!a&&this.selection.selectedCollectionId()===o.collectionId&&(this.unavailableReason="authorization_lost"),this.refresh()}));let i;if(!e)i={status:"unselected",connections:t};else if(!o||!o.info())i={status:"unavailable",collectionId:e,reason:this.connect.unavailableReason(e)??this.unavailableReason,connections:t};else{let a=o.info();i={status:"ready",collectionId:e,connection:o,info:a,access:o.authorizationCapabilities(this.operations),connections:t}}let r=No(i);if(r!==this.snapshotKey){this.snapshot=i,this.snapshotKey=r;for(let a of this.listeners)a()}}};function No(n){return n.status==="unselected"?JSON.stringify({status:n.status,connections:n.connections}):n.status==="unavailable"?JSON.stringify({status:n.status,collectionId:n.collectionId,reason:n.reason,connections:n.connections}):JSON.stringify({status:n.status,collectionId:n.collectionId,info:n.info,access:n.access,connections:n.connections})}var vt=class{internals;constructor(e){this.internals=new wt(e)}register(){return P(()=>this.internals.register(),Y)}authorize(e={}){return P(()=>this.internals.authorize(e),J)}createSession(e){return new Ae(this,e)}environment(){return this.internals.environment()}completeAuthorization(e){return P(()=>this.internals.completeAuthorization(e??un()),J)}connections(){return this.internals.connections()}connection(e){return this.internals.connection(e)}unavailableReason(e){return this.internals.unavailableReason(e)}onConnectionsChange(e){return this.internals.onConnectionsChange(e)}forgetAll(){for(let e of this.connections())this.connection(e.collectionId)?.forget()}},wt=class{serverUrl;manifest;manifestSource;redirectUri;storage;relayEncryption;keyStore;directAccessMode;loopbackUrl;navigate;credentialStorage;application=null;completionPromises=new Map;connectionCache=new Map;listeners=new Set;invalidatedConnections=new Map;constructor(e){this.serverUrl=cn(e.serverUrl),this.manifest=e.manifest??ln(),this.manifestSource=typeof this.manifest=="string"?this.manifest:this.manifest.distribution==="portable"?`bundle:${this.manifest.id}:${fn(this.manifest)}`:`bundle:${this.manifest.id}`;let t=hn(this.manifest);this.redirectUri=e.redirectUri??(typeof this.manifest!="string"&&this.manifest.distribution==="portable"?"":dn()),this.storage=e.storage??pn(t),this.relayEncryption=e.relayEncryption??"required",this.keyStore=e.keyStore??(t?new ne:new te),this.credentialStorage=e.storage||e.keyStore?"custom":this.storage instanceof ce?"memory":"persistent",this.directAccessMode=e.directAccess??"auto",this.loopbackUrl=on(e.loopbackUrl??`http://127.0.0.1:${Et}`),this.navigate=e.navigate,typeof window<"u"&&this.storage===window.localStorage&&window.addEventListener("storage",o=>{o.storageArea!==this.storage||!o.key?.startsWith(this.storagePrefix())||(this.connectionCache.get(qo(o.key))?.notifyStorageChanged(),this.emitConnections())})}environment(){let e=typeof this.manifest!="string"&&this.manifest.distribution==="portable"?"portable":this.application?.distribution??"web";return{distribution:e,applicationOrigin:e==="portable"?"null":this.defaultApplicationOrigin(),credentialStorage:this.credentialStorage}}async register(){if(this.application)return this.application;let e=await q(`${this.serverUrl}/v1/apps/register`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({manifest:await this.loadManifest()})},"temporarily_unavailable","Application registration is temporarily unavailable."),t=await e.json();if(!e.ok)throw C(t,"discovery_failed","Application discovery failed.",e.status);return this.application=t.application,this.application}async loadManifest(){if(typeof this.manifest!="string")return this.manifest;let e=this.manifest,t;try{t=await fetch(e,{headers:{accept:"application/json"}})}catch(o){throw c("manifest_load_failed","The bundled application declaration could not be loaded.",{cause:o})}if(!t.ok)throw c("manifest_load_failed",`The bundled application declaration returned HTTP ${t.status}.`,{status:t.status});try{return await t.json()}catch(o){throw c("invalid_application_manifest","The bundled application declaration is not valid JSON.",{cause:o})}}async authorize(e={}){if(typeof location>"u"&&!this.navigate&&!e.openVerification)throw c("browser_required","Authorization navigation requires a browser environment.");let o=typeof this.manifest!="string"&&this.manifest.distribution==="portable"&&!e.openVerification&&typeof window<"u"?window.open(`${this.serverUrl}/device`,"mdbase-connect-authorization","popup,width=620,height=760"):null,i;try{i=await this.register()}catch(h){throw o?.close(),h}if(i.distribution==="portable")return this.authorizePortable(i,e,o);o?.close();let{verifier:r,challenge:a}=await Ce(),s=N(24),l=e.target?.kind==="collection"?e.target.collectionId:void 0,d=this.relayEncryption==="required"?`grant:${i.id}:${s}`:void 0,u=d?await this.keyStore.create(d):void 0,p={version:1,verifier:r,state:s,clientId:i.id,redirectUri:this.redirectUri,relayEncryption:this.relayEncryption,collectionId:l,returnTo:e.returnTo,keyHandle:d,applicationAgreementPublicKey:u?.agreementPublicKey,applicationSigningPublicKey:u?.signingPublicKey};this.storage.setItem(this.pendingKey(s),JSON.stringify(p));let f=new URL(`${this.serverUrl}/oauth/authorize`);return f.searchParams.set("client_id",i.id),f.searchParams.set("redirect_uri",this.redirectUri),f.searchParams.set("code_challenge",a),f.searchParams.set("code_challenge_method","S256"),f.searchParams.set("state",s),f.searchParams.set("operations",D(e.operations??Z).join(",")),l&&f.searchParams.set("collection_id",l),u&&(f.searchParams.set("relay_protocol","1"),f.searchParams.set("application_agreement_public_key",u.agreementPublicKey),f.searchParams.set("application_signing_public_key",u.signingPublicKey)),this.navigate?await this.navigate(f.href):location.assign(f.href),{kind:"redirecting"}}async authorizePortable(e,t,o){if(this.relayEncryption!=="required")throw o?.close(),c("encryption_required","Downloaded applications require encrypted relay authorization.");let{verifier:i,challenge:r}=await Ce(),a=`grant:${e.id}:${N(24)}`,s=await this.keyStore.create(a),l,d;try{l=await fetch(`${this.serverUrl}/oauth/device_authorization`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({client_id:e.id,operations:D(t.operations??Z).join(","),...t.target?.kind==="collection"?{collection_id:t.target.collectionId}:{},code_challenge:r,code_challenge_method:"S256",relay_protocol:"1",application_agreement_public_key:s.agreementPublicKey,application_signing_public_key:s.signingPublicKey})}),d=await l.json()}catch(f){throw o?.close(),await this.keyStore.delete(a),c("device_authorization_failed","Downloaded application authorization could not be started.",{cause:f})}if(!l.ok)throw o?.close(),await this.keyStore.delete(a),C(d,"device_authorization_failed","Downloaded application authorization could not be started.",l.status);let u;try{u=sn(d)}catch(f){throw o?.close(),await this.keyStore.delete(a),f}if(t.onDeviceCode?.(u),t.openVerification)await t.openVerification(u);else if(o)try{o.location.href=u.verificationUriComplete}catch{}else throw await this.keyStore.delete(a),c("approval_window_blocked","The approval window was blocked. Show the provided verification link and code, then try again.",{details:{user_code:u.userCode,verification_uri:u.verificationUri,verification_uri_complete:u.verificationUriComplete,expires_at:u.expiresAt,interval_seconds:u.intervalSeconds}});let p=u.intervalSeconds;try{for(;Date.now()<u.expiresAt;){if(await _e(p*1e3,t.signal),t.signal?.aborted)throw c("authorization_cancelled","Downloaded application authorization was cancelled.");let f;try{f=await fetch(`${this.serverUrl}/oauth/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"urn:ietf:params:oauth:grant-type:device_code",device_code:d.device_code,client_id:e.id,code_verifier:i}),signal:t.signal})}catch(b){if(t.signal?.aborted)throw c("authorization_cancelled","Downloaded application authorization was cancelled.",{cause:b});continue}let h=await f.json();if(!f.ok){let b=Pe(h);if(b==="authorization_pending")continue;if(b==="slow_down"){p+=5;continue}throw C(h,"token_exchange_failed","Downloaded application authorization could not be completed.",f.status)}let m=qe(h.authority,h.collection_id),_=h.encryption&&h.encryption.protocol_version===ee&&h.encryption.suite===fe&&h.encryption.application_agreement_public_key===s.agreementPublicKey;if(h.application_origin!=="null")throw c("invalid_token_response","Authorization did not bind the portable grant to its opaque application origin.");if(h.authority&&(!m||h.encryption!=null||h.authority.proof_public_key!==s.signingPublicKey))throw c("invalid_token_response","Authorization returned a remote authority capability that is not bound to this portable grant key.");if(!h.authority&&!_)throw c("encryption_required","Authorization did not establish the expected key-bound local portable grant.");let w=this.storeTokenResponse(h,e.id,a);if(t.target?.kind==="collection"&&t.target.collectionId!==w.collectionId)throw this.removeToken(w.collectionId,w.keyHandle),c("collection_mismatch","The approved collection does not match the collection requested by this link.");return o?.close(),{kind:"connected",connection:this.connection(w.collectionId),...t.returnTo?{returnTo:t.returnTo}:{}}}throw c("expired_token","The downloaded application authorization code expired.")}catch(f){throw o?.close(),await this.keyStore.delete(a),f}}completeAuthorization(e){let t=new URL(e).searchParams.get("state");if(!t)return Promise.reject(c("invalid_callback","Authorization callback is missing its state."));let o=this.completionPromises.get(t);if(o)return o;let r=this.performAuthorizationCompletion(e,t).finally(()=>{this.completionPromises.get(t)===r&&this.completionPromises.delete(t)});return this.completionPromises.set(t,r),r}async performAuthorizationCompletion(e,t){let o=new URL(e),i=o.searchParams.get("code"),r=this.pendingKey(t),a=I(this.storage.getItem(r));if(!a||a.version!==1||t!==a.state)throw c("invalid_callback","Authorization callback is missing or does not match this browser session.");if(o.searchParams.has("error"))throw a.keyHandle&&await this.keyStore.delete(a.keyHandle),this.storage.removeItem(r),x(o.searchParams.get("error")??"access_denied",o.searchParams.get("error_description")??"Collection access was not approved.",{details:a.returnTo?{return_to:a.returnTo}:void 0});if(!i)throw c("invalid_callback","Authorization callback is missing its code.");let s=await q(`${this.serverUrl}/oauth/token`,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:i,client_id:a.clientId,redirect_uri:a.redirectUri,code_verifier:a.verifier})},"temporarily_unavailable","Authorization completion is temporarily unavailable."),l=await s.json();if(!s.ok)throw C(l,"token_exchange_failed","Authorization could not be completed.",s.status);if(a.relayEncryption==="required"&&!l.authority&&(!l.encryption||!a.keyHandle||l.encryption.application_agreement_public_key!==a.applicationAgreementPublicKey))throw a.keyHandle&&await this.keyStore.delete(a.keyHandle),this.storage.removeItem(r),c("encryption_required","Authorization did not establish the required encrypted relay grant.");if(l.authority?.proof_public_key){if(!a.keyHandle||!a.applicationSigningPublicKey||l.authority.proof_public_key!==a.applicationSigningPublicKey)throw a.keyHandle&&await this.keyStore.delete(a.keyHandle),this.storage.removeItem(r),c("invalid_token_response","Authorization returned a remote authority capability bound to another application key.")}else l.authority&&a.keyHandle&&await this.keyStore.delete(a.keyHandle);let d=this.storeTokenResponse(l,a.clientId,l.authority?.proof_public_key?a.keyHandle:l.authority?void 0:a.keyHandle);if(a.collectionId&&a.collectionId!==d.collectionId)throw this.removeToken(d.collectionId,d.keyHandle),this.storage.removeItem(r),c("collection_mismatch","The approved collection does not match the collection requested by this link.");return this.storage.removeItem(r),{connection:this.connection(d.collectionId),...a.returnTo?{returnTo:a.returnTo}:{}}}connections(){let e=[];for(let t of this.connectionIds()){let o=this.connection(t)?.info();o&&e.push(o)}return e.sort((t,o)=>t.displayName.localeCompare(o.displayName)||t.collectionId.localeCompare(o.collectionId))}connection(e){if(!this.storage.getItem(this.tokenKey(e)))return null;let t=this.connectionCache.get(e);return t||(t=new ke(this,e),this.connectionCache.set(e,t)),t.info()?t:null}unavailableReason(e){return this.invalidatedConnections.get(e)??null}onConnectionsChange(e){return this.listeners.add(e),e(this.connections()),()=>this.listeners.delete(e)}storeTokenResponse(e,t,o){let i=e.collection_id;if(typeof i!="string")throw c("invalid_token_response","Authorization returned no collection ID.");let r=Ke(e.scope);if(!r)throw c("invalid_token_response","Authorization returned no valid collection scope.");if(e.authority&&!qe(e.authority,i))throw c("invalid_token_response","Authorization returned an invalid remote authority capability.");if(e.authority&&e.encryption)throw c("invalid_token_response","Authorization returned conflicting collection transports.");if(e.file_capability!==null&&e.file_capability!==void 0&&!Be(e.file_capability))throw c("invalid_token_response","Authorization returned an invalid file capability.");if(e.encryption){try{G(e.encryption)}catch{throw c("invalid_token_response","Authorization returned an invalid encrypted relay binding.")}if(e.encryption.collection_id!==i||typeof e.grant_id!="string"||e.grant_id.length===0)throw c("invalid_token_response","Authorization returned an encrypted relay binding for another grant.")}let a=I(this.storage.getItem(this.tokenKey(i)));if(a?.encryption&&e.encryption&&a.keyHandle&&a.keyHandle===o&&(a.grantId!==e.grant_id||a.encryption.connector_id!==e.encryption.connector_id||a.encryption.connector_agreement_public_key!==e.encryption.connector_agreement_public_key||a.encryption.application_agreement_public_key!==e.encryption.application_agreement_public_key))throw c("connector_identity_changed","The connector identity changed during authorization renewal. Reauthorize before sending collection data.");a?.keyHandle&&a.keyHandle!==o&&this.keyStore.delete(a.keyHandle).catch(()=>{});let s={version:1,accessToken:e.access_token,refreshToken:e.refresh_token,clientId:t,collectionId:i,collectionName:e.collection_name??`Collection ${i.slice(0,8)}`,operations:e.operations,scope:r,expiresAt:Date.now()+e.expires_in*1e3,refreshExpiresAt:e.refresh_expires_in?Date.now()+e.refresh_expires_in*1e3:void 0,grantId:e.grant_id,encryption:e.encryption??void 0,fileCapability:e.file_capability??void 0,applicationOrigin:e.application_origin??this.defaultApplicationOrigin(),keyHandle:o,savedAt:Date.now(),authority:e.authority?{operationsUrl:e.authority.operations_url,syncUrl:e.authority.sync_url,filesUrl:e.authority.files_url,replicaId:e.authority.replica_id,accessToken:e.authority.access_token,proofPublicKey:e.authority.proof_public_key}:void 0};return this.storage.setItem(this.tokenKey(i),JSON.stringify(s)),this.addConnectionId(i),this.invalidatedConnections.delete(i),this.connectionCache.delete(i),this.emitConnections(),s}removeToken(e,t,o="authorization_lost"){this.invalidatedConnections.set(e,o),t&&this.keyStore.delete(t).catch(()=>{}),this.storage.removeItem(this.tokenKey(e)),this.storage.removeItem(this.pendingMutationKey(e));for(let i of["web_push","fcm"])this.storage.removeItem(this.notificationKey(e,i));this.storage.setItem(this.connectionsKey(),JSON.stringify({version:1,collectionIds:this.connectionIds().filter(i=>i!==e)})),this.connectionCache.delete(e),this.emitConnections()}tokenKey(e){return`${this.storagePrefix()}:token:${e}`}pendingMutationKey(e){return`${this.storagePrefix()}:pending-mutation:${e}`}notificationKey(e,t="web_push"){return`${this.storagePrefix()}:notifications:${e}:${t}`}directPreferenceKey(){return`mdbase-connect:direct:${this.defaultApplicationOrigin()}`}defaultApplicationOrigin(){if(typeof this.manifest!="string"&&this.manifest.distribution==="portable"||this.application?.distribution==="portable")return"null";let e=new URL(this.redirectUri);if(["http:","https:"].includes(e.protocol))return e.origin;if(typeof location<"u")return location.origin;if(this.manifest&&typeof this.manifest!="string")return new URL(this.manifest.homepage).origin;try{return new URL(this.manifestSource).origin}catch{return""}}pendingKey(e){return`${this.storagePrefix()}:pending:${e}`}storagePrefix(){return`mdbase-connect:${this.serverUrl}:${this.manifestSource}`}connectionsKey(){return`${this.storagePrefix()}:connections`}connectionIds(){let e=I(this.storage.getItem(this.connectionsKey()));return e?.version===1&&Array.isArray(e.collectionIds)&&e.collectionIds.every(t=>typeof t=="string")?e.collectionIds:[]}addConnectionId(e){this.storage.setItem(this.connectionsKey(),JSON.stringify({version:1,collectionIds:[...new Set([...this.connectionIds(),e])]}))}emitConnections(){let e=this.connections();for(let t of this.listeners)t(e)}};function qo(n){let e=":token:",t=n.lastIndexOf(e);return t<0?"":n.slice(t+e.length)}function In(n){if(!n||typeof n!="object")throw c("invalid_push_payload","The push payload is not an object.");let e=n;if(e.type!=="mdbase.notification"||e.version!==1||typeof e.signal_id!="string"||typeof e.criterion_id!="string"||typeof e.cursor!="string"||!e.presentation||typeof e.presentation.title!="string")throw c("invalid_push_payload","The push payload is not an mdbase notification.");return e}function Bo(n){if(!n||typeof n!="object")throw c("invalid_push_payload","The native notification data is not an object.");let e=n;if(e.type!=="mdbase.notification"||e.version!==1&&e.version!=="1"||typeof e.signal_id!="string"||typeof e.criterion_id!="string"||typeof e.cursor!="string")throw c("invalid_push_payload","The native notification data is not an mdbase notification.");return{type:"mdbase.notification",version:1,signal_id:e.signal_id,criterion_id:e.criterion_id,cursor:e.cursor}}function Ko(n,e){let t=In(e);return n.showNotification(t.presentation.title,{...t.presentation.body?{body:t.presentation.body}:{},...t.presentation.tag?{tag:t.presentation.tag}:{},data:{type:t.type,signal_id:t.signal_id,criterion_id:t.criterion_id,cursor:t.cursor}})}var Ct=class{collectionParameter;fallbackPath;listeners=new Set;handlePopState=()=>this.emit();constructor(e={}){this.collectionParameter=e.collectionParameter??"collection",this.fallbackPath=e.fallbackPath??"/"}selectedCollectionId(){return this.currentUrl().searchParams.get(this.collectionParameter)}select(e,t={}){let o=Oe(this.currentUrl());e?o.searchParams.set(this.collectionParameter,e):o.searchParams.delete(this.collectionParameter);let i=this.browserHistory();i[t.history==="push"?"pushState":"replaceState"](i.state,"",o),this.emit()}authorizationReturnTo(){let e=Oe(this.currentUrl());return`${e.pathname}${e.search}${e.hash}`}authorizationCallback(){let e=this.currentUrl().href;return Qe(e)?e:null}finishAuthorization(e,t){let o=this.safeAppUrl(e??this.fallbackPath);Oe(o),o.searchParams.set(this.collectionParameter,t),this.browserHistory().replaceState(null,"",o),this.emit()}clearAuthorizationCallback(e){let t=e?this.safeAppUrl(e):this.currentUrl(),o=this.browserHistory();o.replaceState(o.state,"",Oe(t)),this.emit()}subscribe(e){let t=this.listeners.size===0;return this.listeners.add(e),t&&typeof window<"u"&&window.addEventListener("popstate",this.handlePopState),()=>{this.listeners.delete(e),this.listeners.size===0&&typeof window<"u"&&window.removeEventListener("popstate",this.handlePopState)}}emit(){for(let e of this.listeners)e()}safeAppUrl(e){let t=this.currentUrl(),o=new URL(e,t.origin);return o.origin===t.origin?o:new URL(this.fallbackPath,t.origin)}currentUrl(){if(typeof location>"u")throw c("browser_required","Browser selection requires a browser environment.");return new URL(location.href)}browserHistory(){if(typeof history>"u")throw c("browser_required","Browser selection requires a browser environment.");return history}},Pt=class{collectionId=null;listeners=new Set;selectedCollectionId(){return this.collectionId}select(e){if(e!==this.collectionId){this.collectionId=e;for(let t of this.listeners)t()}}authorizationReturnTo(){}authorizationCallback(){return null}finishAuthorization(e,t){this.select(t)}clearAuthorizationCallback(){}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};return zn(jo);})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
sha384-
|
|
1
|
+
sha384-5i/BVtYUAqTluHzqWtHkb2tI4mKjuOsQMdAKhtXjddN95BAkTPOpub7++MQX+fU0
|