@zuzjs/flare 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +859 -163
- package/dist/index.d.ts +859 -163
- package/dist/index.js +2 -2
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {uuid2}from'@zuzjs/core';export{AuthGuard,Dropbox,Google}from'@zuzjs/auth';var v=(c=>(c.SUBSCRIBE="subscribe",c.UNSUBSCRIBE="unsubscribe",c.WRITE="write",c.DELETE="delete",c.AUTH="auth",c.PING="ping",c.OFFLINE_SYNC="offline_sync",c.CALL="call",c))(v||{}),S=(c=>(c.SNAPSHOT="snapshot",c.CHANGE="change",c.ERROR="error",c.ACK="ack",c.PONG="pong",c.AUTH_OK="auth_ok",c.OFFLINE_ACK="offline_ack",c.CALL_RESPONSE="call_response",c))(S||{});function w(r){let e=[];for(let[t,i]of Object.entries(r))if(typeof i=="string"){let o=i.match(/^(>=|<=|!=|>|<|==)\s*(.+)$/);if(o){let[,n,s]=o;e.push({field:t,op:n,value:R(s.trim())});}else e.push({field:t,op:"==",value:i});}else Array.isArray(i)?e.push({field:t,op:"in",value:i}):e.push({field:t,op:"==",value:i});return e}function R(r){if(!isNaN(Number(r)))return Number(r);if(r==="true")return true;if(r==="false")return false;if(r==="null")return null;if(r!=="undefined")return r}var a=class{constructor(e,t,i){this.client=e;this.collection=t;this.legacyId=i;}whereCondition;updateData;setData;deleteOp=false;promise;where(e){return this.whereCondition=e,this}update(e){return this.updateData=e,this}set(e){return this.setData=e,this}delete(){return this.deleteOp=true,this}getDocId(){if(this.legacyId)return this.legacyId;if(this.whereCondition&&this.whereCondition.id){let e=this.whereCondition.id;if(typeof e=="string")return e}throw new Error('Document ID not specified. Use .where({ id: "..." }) or doc(collection, id)')}async execute(){return this._execute()}async _execute(){let e=this.getDocId();if(this.deleteOp){await this.client.send("delete",{collection:this.collection,docId:e});return}if(this.updateData){await this.client.send("write",{collection:this.collection,docId:e,data:this.updateData,merge:true});return}if(this.setData){await this.client.send("write",{collection:this.collection,docId:e,data:this.setData,merge:false});return}return this.get()}then(e,t){return this.promise||(this.promise=this._execute()),this.promise.then(e,t)}async get(){let e=this.getDocId(),t=uuid2(18);return new Promise((i,o)=>{let n=this.client.subscribe(t,this.collection,e,void 0,s=>{s.type==="snapshot"&&(n(),i(s.data));});setTimeout(()=>{n(),o(new Error("Document fetch timeout"));},1e4);})}onSnapshot(e){let t=this.getDocId(),i=uuid2(18);return this.client.subscribe(i,this.collection,t,void 0,e)}},h=class{constructor(e,t,i){this.client=e;this.collection=t;this.id=i;}async get(){return new a(this.client,this.collection,this.id).get()}async set(e){await this.client.send("write",{collection:this.collection,docId:this.id,data:e,merge:false});}async update(e){await this.client.send("write",{collection:this.collection,docId:this.id,data:e,merge:true});}async delete(){await this.client.send("delete",{collection:this.collection,docId:this.id});}onSnapshot(e){let t=uuid2(18);return this.client.subscribe(t,this.collection,this.id,void 0,e)}},g=class r{constructor(e,t){this.client=e;this.collection=t;}queries=[];promise;doc(e){return new h(this.client,this.collection,e)}where(e){let t=new r(this.client,this.collection),i=w(e);return t.queries=[...this.queries,...i],t}async get(){return this._execute()}async _execute(){let e=uuid2(18);return new Promise((t,i)=>{let o=this.queries.length>0?this.queries:void 0,n=this.client.subscribe(e,this.collection,void 0,o,s=>{s.type==="snapshot"&&(n(),t(Array.isArray(s.data)?s.data:[s.data]));});setTimeout(()=>{n(),i(new Error("Collection fetch timeout"));},1e4);})}then(e,t){return this.promise||(this.promise=this._execute()),this.promise.then(e,t)}onSnapshot(e){let t=uuid2(18),i=this.queries.length>0?this.queries:void 0;return this.client.subscribe(t,this.collection,void 0,i,e)}async add(e){let t=uuid2(18),i=this.doc(t);return await i.set(e),i}update(e){return new a(this.client,this.collection).update(e)}delete(){return new a(this.client,this.collection).delete()}};async function I(r){let e=r.replace(/-----BEGIN PUBLIC KEY-----/,"").replace(/-----END PUBLIC KEY-----/,"").replace(/\s+/g,""),t=typeof atob<"u"?atob(e):Buffer.from(e,"base64").toString("binary"),i=new Uint8Array(t.length);for(let n=0;n<t.length;n++)i[n]=t.charCodeAt(n);return (globalThis.crypto??(await import('crypto')).webcrypto).subtle.importKey("spki",i.buffer,{name:"RSA-OAEP",hash:"SHA-256"},false,["encrypt"])}async function E(r,e){let t=await I(e),i=new TextEncoder().encode(JSON.stringify(r)),n=await(globalThis.crypto??(await import('crypto')).webcrypto).subtle.encrypt({name:"RSA-OAEP"},t,i),s=typeof btoa<"u"?btoa(String.fromCharCode(...new Uint8Array(n))):Buffer.from(n).toString("base64");return JSON.stringify({enc:"rsa",data:s})}var y=class{socket=null;reconnectInterval;maxReconnectDelay;isConnected=false;shouldReconnect=true;options;messageQueue=[];heartbeatInterval=null;connectionTimeout=null;constructor(e){this.options=e,this.reconnectInterval=e.reconnectDelay||2,this.maxReconnectDelay=e.maxReconnectDelay||60,this.log("Transport initialized",e.url);}connect(){if(this.socket){this.log("Socket already exists, skipping connection");return}this.log("Connecting to",this.options.url),this.socket=new WebSocket(this.options.url),this.connectionTimeout=setTimeout(()=>{this.isConnected||(this.log("Connection timeout"),this.socket?.close(),this.handleReconnect());},1e4),this.socket.onopen=()=>{this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.isConnected=true,this.reconnectInterval=this.options.reconnectDelay||2,this.log("Connected to server"),this.options.onOpen?.(),this.startHeartbeat(),this.flushQueue();},this.socket.onmessage=e=>{try{let t=JSON.parse(e.data);this.options.onMessage(t);}catch(t){this.log("Parse error",t),this.options.onError?.(t);}},this.socket.onerror=e=>{this.log("WebSocket error",e),this.options.onError?.(new Error("WebSocket error"));},this.socket.onclose=e=>{this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.isConnected=false,this.socket=null,this.stopHeartbeat(),this.log("Connection closed",e.code,e.reason),this.options.onClose?.(),e.code!==1e3&&this.shouldReconnect&&this.options.autoReconnect&&this.handleReconnect();};}handleReconnect(){let e=this.reconnectInterval*1e3;this.log(`Reconnecting in ${this.reconnectInterval}s...`),setTimeout(()=>{this.reconnectInterval=Math.min(this.reconnectInterval*2,this.maxReconnectDelay),this.connect();},e);}startHeartbeat(){this.heartbeatInterval=setInterval(()=>{this.isConnected&&this.send({type:"ping",id:Date.now().toString(),ts:Date.now()});},3e4);}stopHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null);}flushQueue(){for(this.log("Flushing message queue",this.messageQueue.length);this.messageQueue.length>0;){let e=this.messageQueue.shift();e&&this.send(e);}}send(e){if(this.socket&&this.socket.readyState===WebSocket.OPEN){let t=i=>{try{this.socket.send(i),this.log("Sent message",e);}catch(o){this.log("Send error",o),this.messageQueue.push(e);}};this.options.publicKey?E(e,this.options.publicKey).then(t).catch(i=>{this.log("RSA encrypt error \u2014 sending plaintext",i),t(JSON.stringify(e));}):t(JSON.stringify(e));}else this.log("Socket not ready, queueing message"),this.messageQueue.push(e);}disconnect(){this.shouldReconnect=false,this.stopHeartbeat(),this.socket&&(this.socket.close(1e3,"Client disconnect"),this.socket=null),this.isConnected=false,this.log("Disconnected");}get connected(){return this.isConnected}log(...e){this.options.debug&&console.log("[FlareTransport]",...e);}};var b=class{transport;config;pendingAcks=new Map;subscriptions=new Map;offlineQueue=[];currentState="disconnected";connectionListeners=[];errorListeners=[];authToken;userId;isDebug=false;constructor(e){this.config={autoReconnect:true,reconnectDelay:2,maxReconnectDelay:60,debug:false,connectionTimeout:1e4,...e},this.isDebug=this.config.debug||false;let{hostname:t,port:i,protocol:o}=new URL(this.config.endpoint),n=o==="https:",c=`${n?"wss":"ws"}://${t}:${i||(n?"443":"80")}/?appId=${this.config.appId}${this.config.apiKey?`&apiKey=${this.config.apiKey}`:""}`;this.transport=new y({url:c,publicKey:this.config.publicKey,autoReconnect:this.config.autoReconnect,reconnectDelay:this.config.reconnectDelay,maxReconnectDelay:this.config.maxReconnectDelay,onMessage:m=>this.handleIncoming(m),onOpen:()=>this.onConnected(),onClose:()=>this.onDisconnected(),onError:m=>this.handleTransportError(m),debug:this.isDebug}),this.log("FlareClient initialized",e);}connect(){this.setState("connecting"),this.transport.connect();}disconnect(){this.transport.disconnect(),this.setState("disconnected");}collection(e){return new g(this,e)}doc(e,t){return t!==void 0?new h(this,e,t):new a(this,e)}async auth(e){let t=await this.send("auth",{token:e});if(t.type==="auth_ok")return this.authToken=e,this.userId=t.uid,this.log("Authentication successful",t.uid),{uid:t.uid,token:e};throw new Error("Authentication failed")}signOut(){this.authToken=void 0,this.userId=void 0,this.log("Signed out");}get currentUser(){return this.userId}get connectionState(){return this.currentState}get isConnected(){return this.currentState==="connected"}onConnectionStateChange(e){return this.connectionListeners.push(e),()=>{this.connectionListeners=this.connectionListeners.filter(t=>t!==e);}}onError(e){return this.errorListeners.push(e),()=>{this.errorListeners=this.errorListeners.filter(t=>t!==e);}}async ping(){let e=Date.now();return await this.send("ping",{}),Date.now()-e}async call(e,t={}){let i=await this.send("call",{topic:e,payload:t});if(!i.success)throw new Error(i.error??`CALL "${e}" failed`);return i.result}async syncOffline(){if(this.offlineQueue.length===0)return;this.log("Syncing offline operations",this.offlineQueue.length);let e=[...this.offlineQueue];this.offlineQueue.length=0;let t=await this.send("offline_sync",{operations:e});t.conflicts&&t.conflicts.length>0&&(this.log("Offline sync conflicts",t.conflicts),t.conflicts.forEach(i=>{let o=e.find(n=>n.id===i.operationId);o&&this.offlineQueue.push(o);}));}handleTransportError(e){this.log("Transport error",e),this.errorListeners.forEach(t=>{try{t(e);}catch(i){this.log("Error listener error",i);}});}onConnected(){this.setState("connected"),this.log("Connected to FlareServer"),this.offlineQueue.length>0&&this.syncOffline().catch(e=>{this.log("Offline sync failed",e);});}onDisconnected(){this.currentState!=="disconnected"&&this.setState("reconnecting"),this.log("Disconnected from FlareServer");}setState(e){this.currentState!==e&&(this.currentState=e,this.log("Connection state changed",e),this.connectionListeners.forEach(t=>{try{t(e);}catch(i){this.log("Connection listener error",i);}}));}handleIncoming(e){if(this.log("Received message",e.type,e),e.type==="ack"||e.type==="pong"||e.type==="auth_ok"||e.type==="call_response"){let t=this.pendingAcks.get(e.correlationId||e.id);t&&(t(e),this.pendingAcks.delete(e.correlationId||e.id));return}if(e.type==="error"){this.log("Server error",e.code,e.message);let t=new Error(`[${e.code}] ${e.message}`);if(this.errorListeners.forEach(i=>{try{i(t);}catch(o){this.log("Error listener error",o);}}),e.correlationId){let i=this.pendingAcks.get(e.correlationId);i&&(i(e),this.pendingAcks.delete(e.correlationId));}return}if(e.type==="snapshot"||e.type==="change"){let t=this.subscriptions.get(e.subscriptionId);if(t){let i={subscriptionId:e.subscriptionId,collection:e.collection,docId:e.docId,data:e.data,type:e.type==="snapshot"?"snapshot":"change",operation:e.operation};try{t(i);}catch(o){this.log("Subscription callback error",o);}}}}async send(e,t){return new Promise((i,o)=>{let n=uuid2(18),s={id:n,type:e,ts:Date.now(),...t};this.pendingAcks.set(n,d=>{d.type==="error"?o(new Error(`[${d.code}] ${d.message}`)):i(d);}),this.isConnected?this.transport.send(s):(this.log("Queueing message for offline",s),this.offlineQueue.push(s),o(new Error("Not connected - message queued"))),setTimeout(()=>{this.pendingAcks.has(n)&&(this.pendingAcks.delete(n),o(new Error("Request timeout")));},this.config.connectionTimeout);})}subscribe(e,t,i,o,n){return this.log("Creating subscription",e,t,i),this.subscriptions.set(e,n),this.send("subscribe",{collection:t,docId:i,query:o}).then(s=>{s.subscriptionId&&(this.subscriptions.delete(e),this.subscriptions.set(s.subscriptionId,n));}).catch(s=>{this.log("Subscription failed",s),this.subscriptions.delete(e);}),()=>{this.log("Unsubscribing",e),this.subscriptions.delete(e),this.isConnected&&this.send("unsubscribe",{subscriptionId:e}).catch(s=>this.log("Unsubscribe failed",s));}}log(...e){this.isDebug&&console.log("[FlareClient]",...e);}},T=b;var C=class extends Error{constructor(t,i,o){super(t);this.code=i;this.cause=o;this.name="ZuzFlareError";}};var l=null,$=r=>(l||(l=new T(r),l.connect()),l),G=()=>l,J=()=>{l&&(l.disconnect(),l=null);};var M=T;
|
|
2
|
-
export{
|
|
1
|
+
import {Credentials,Anonymous,Google,GitHub,Facebook,Dropbox,Apple,Twitter,AuthGuard}from'@zuzjs/auth';export{Anonymous,Apple,AuthGuard,Credentials,Dropbox,Facebook,GitHub,Google,Providers,Twitter,setupProvider}from'@zuzjs/auth';import {uuid2,withGet,withPut,withPatch,withPost}from'@zuzjs/core';var l=class extends Error{constructor(t,n,i){super(t);this.code=n;this.cause=i;this.name="ZuzFlareError";}};var V={AuthenticationFailed:"AUTHENTICATION_FAILED",WriteFailed:"WRITE_FAILED",QueryFailed:"QUERY_FAILED",ParseError:"PARSE_ERROR"},h=V;var z=(d=>(d.SUBSCRIBE="subscribe",d.UNSUBSCRIBE="unsubscribe",d.WRITE="write",d.DELETE="delete",d.AUTH="auth",d.PING="ping",d.OFFLINE_SYNC="offline_sync",d.CALL="call",d.QUERY="query",d.PRESENCE_JOIN="presence_join",d.PRESENCE_LEAVE="presence_leave",d.PRESENCE_HEARTBEAT="presence_heartbeat",d))(z||{}),Y=(d=>(d.SNAPSHOT="snapshot",d.CHANGE="change",d.ERROR="error",d.ACK="ack",d.PONG="pong",d.AUTH_OK="auth_ok",d.OFFLINE_ACK="offline_ack",d.CALL_RESPONSE="call_response",d.QUERY_RESULT="query_result",d.PRESENCE_STATE="presence_state",d.PRESENCE_JOIN="presence_join",d.PRESENCE_LEAVE="presence_leave",d))(Y||{});function _(o){let e=[];for(let[t,n]of Object.entries(o))if(typeof n=="string"){let i=n.match(/^(>=|<=|!=|>|<|==)\s*(.+)$/);if(i){let[,s,r]=i;e.push({field:t,op:s,value:B(r.trim())});}else e.push({field:t,op:"==",value:n});}else Array.isArray(n)?e.push({field:t,op:"in",value:n}):e.push({field:t,op:"==",value:n});return e}function B(o){if(!isNaN(Number(o)))return Number(o);if(o==="true")return true;if(o==="false")return false;if(o==="null")return null;if(o!=="undefined")return o}var k=class{constructor(e,t,n){this.client=e;this.collection=t;this.legacyId=n;}whereCondition;updateData;setData;deleteOp=false;promise;where(e){return this.whereCondition=e,this}update(e){return this.updateData=e,this}set(e){return this.setData=e,this}delete(){return this.deleteOp=true,this}getDocId(){if(this.legacyId)return this.legacyId;if(this.whereCondition&&this.whereCondition.id){let e=this.whereCondition.id;if(typeof e=="string")return e}throw new l('Document ID not specified. Use .where({ id: "..." }) or doc(collection, id)',h.QueryFailed)}async execute(){return this._execute()}async _execute(){let e=this.getDocId();if(this.deleteOp){await this.client.send("delete",{collection:this.collection,docId:e});return}if(this.updateData){await this.client.send("write",{collection:this.collection,docId:e,data:this.updateData,merge:true});return}if(this.setData){await this.client.send("write",{collection:this.collection,docId:e,data:this.setData,merge:false});return}return this.get()}then(e,t){return this.promise||(this.promise=this._execute()),this.promise.then(e,t)}async get(){let e=this.getDocId(),t=uuid2(18);return new Promise((n,i)=>{let s=this.client.subscribe(t,this.collection,e,void 0,r=>{r.type==="snapshot"&&(s(),n(r.data));});setTimeout(()=>{s(),i(new Error("Document fetch timeout"));},1e4);})}onSnapshot(e){let t=this.getDocId(),n=uuid2(18);return this.client.subscribe(n,this.collection,t,void 0,e)}};var F=class{constructor(e,t,n){this.client=e;this.collection=t;this.id=n;}async get(){return new k(this.client,this.collection,this.id).get()}async set(e){await this.client.send("write",{collection:this.collection,docId:this.id,data:e,merge:false});}async update(e){await this.client.send("write",{collection:this.collection,docId:this.id,data:e,merge:true});}async delete(){await this.client.send("delete",{collection:this.collection,docId:this.id});}onSnapshot(e){let t=uuid2(18),n=()=>{};return n=this.client.subscribe(t,this.collection,this.id,void 0,i=>{i.type==="snapshot"&&(e(i),n());}),n}onDocUpdated(e){let t=uuid2(18);return this.client.subscribe(t,this.collection,this.id,void 0,n=>{n.type==="change"&&(n.operation==="update"||n.operation==="replace")&&n.data&&e(n.data,n.docId);},{skipSnapshot:true})}onDocModified(e){return this.onDocUpdated(e)}onDocChange(e){return this.onDocUpdated(e)}onDocDeleted(e){let t=uuid2(18);return this.client.subscribe(t,this.collection,this.id,void 0,n=>{n.type==="change"&&n.operation==="delete"&&e(n.docId);},{skipSnapshot:true})}onDocChanged(e){let t=uuid2(18);return this.client.subscribe(t,this.collection,this.id,void 0,n=>{n.type==="change"&&e(n.data??null,n.docId,n.operation);},{skipSnapshot:true})}},T=F;var D=class o{constructor(e,t){this.client=e;this.collection=t;}sq={};promise;doc(e){return new T(this.client,this.collection,e)}clone(e){let t=new o(this.client,this.collection);return t.sq={...this.sq,...e},t}where(e,t,n){let i;return typeof e=="string"?i=[{field:e,op:t,value:n}]:i=_(e),this.clone({where:[...this.sq.where??[],...i]})}orWhere(e){return this.clone({where:[...this.sq.where??[],{or:e}]})}orderBy(e,t="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:t}]})}limit(e){return this.clone({limit:e})}offset(e){return this.clone({offset:e})}startAt(...e){return this.clone({startAt:{values:e}})}startAfter(...e){return this.clone({startAfter:{values:e}})}endAt(...e){return this.clone({endAt:{values:e}})}endBefore(...e){return this.clone({endBefore:{values:e}})}aggregate(...e){return this.clone({aggregate:[...this.sq.aggregate??[],...e]})}count(e="count"){return this.aggregate({fn:"count",alias:e})}sum(e,t){return this.aggregate({fn:"sum",field:e,alias:t??`sum_${e}`})}avg(e,t){return this.aggregate({fn:"avg",field:e,alias:t??`avg_${e}`})}min(e,t){return this.aggregate({fn:"min",field:e,alias:t??`min_${e}`})}max(e,t){return this.aggregate({fn:"max",field:e,alias:t??`max_${e}`})}distinct(e,t){return this.aggregate({fn:"distinct",field:e,alias:t??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,t,n){return this.clone({having:[...this.sq.having??[],{field:e,op:t,value:n}]})}join(e){return this.clone({joins:[...this.sq.joins??[],e]})}select(...e){return this.clone({select:e})}distinctField(e){return this.clone({distinctField:e})}vectorSearch(e){return this.clone({vectorSearch:e})}async get(){return this._execute()}_isStructured(){return !!(this.sq.orderBy?.length||this.sq.aggregate?.length||this.sq.groupBy||this.sq.having?.length||this.sq.joins?.length||this.sq.vectorSearch||this.sq.distinctField||this.sq.offset||this.sq.startAt||this.sq.startAfter||this.sq.endAt||this.sq.endBefore||this.sq.select?.length)}async _execute(){return this._isStructured()?this._executeQuery():this._executeSubscribe()}async _executeQuery(){return (await this.client.send("query",{collection:this.collection,query:this.sq})).data??[]}async _executeSubscribe(){let e=uuid2(18);return new Promise((t,n)=>{let i=Object.keys(this.sq).length>0?this.sq:void 0,s=this.client.subscribe(e,this.collection,void 0,i,r=>{r.type==="snapshot"&&(s(),t(r.data));});setTimeout(()=>{s(),n(new Error("Collection fetch timeout"));},1e4);})}then(e,t){return this.promise||(this.promise=this._execute()),this.promise.then(e,t)}onSnapshot(e){let t=uuid2(18),n=Object.keys(this.sq).length>0?this.sq:void 0,i=()=>{};return i=this.client.subscribe(t,this.collection,void 0,n,s=>{s.type==="snapshot"&&(e(s),i());}),i}onDocAdded(e){let t=uuid2(18),n=Object.keys(this.sq).length>0?this.sq:void 0;return this.client.subscribe(t,this.collection,void 0,n,i=>{i.type==="change"&&i.operation==="insert"&&i.data!=null&&e(i.data,i.docId);},{skipSnapshot:true})}onDocUpdated(e){let t=uuid2(18),n=Object.keys(this.sq).length>0?this.sq:void 0;return this.client.subscribe(t,this.collection,void 0,n,i=>{i.type==="change"&&(i.operation==="update"||i.operation==="replace")&&i.data!=null&&e(i.data,i.docId);},{skipSnapshot:true})}onDocModified(e){return this.onDocUpdated(e)}onDocChange(e){return this.onDocUpdated(e)}onDocDeleted(e){let t=uuid2(18),n=Object.keys(this.sq).length>0?this.sq:void 0;return this.client.subscribe(t,this.collection,void 0,n,i=>{i.type==="change"&&i.operation==="delete"&&e(i.docId);},{skipSnapshot:true})}onDocChanged(e){let t=uuid2(18),n=Object.keys(this.sq).length>0?this.sq:void 0;return this.client.subscribe(t,this.collection,void 0,n,i=>{i.type==="change"&&e(i.data??null,i.docId,i.operation);},{skipSnapshot:true})}async add(e){let t=uuid2(18),n=this.doc(t);return await n.set(e),n}update(e){return new k(this.client,this.collection).update(e)}delete(){return new k(this.client,this.collection).delete()}},N=D;async function Z(o){let e=o.replace(/-----BEGIN PUBLIC KEY-----/,"").replace(/-----END PUBLIC KEY-----/,"").replace(/\s+/g,""),t=typeof atob<"u"?atob(e):Buffer.from(e,"base64").toString("binary"),n=new Uint8Array(t.length);for(let s=0;s<t.length;s++)n[s]=t.charCodeAt(s);return (globalThis.crypto??(await import('crypto')).webcrypto).subtle.importKey("spki",n.buffer,{name:"RSA-OAEP",hash:"SHA-256"},false,["encrypt"])}async function X(o,e){let t=await Z(e),n=new TextEncoder().encode(JSON.stringify(o)),s=await(globalThis.crypto??(await import('crypto')).webcrypto).subtle.encrypt({name:"RSA-OAEP"},t,n),r=typeof btoa<"u"?btoa(String.fromCharCode(...new Uint8Array(s))):Buffer.from(s).toString("base64");return JSON.stringify({enc:"rsa",data:r})}var w=class{socket=null;reconnectInterval;maxReconnectDelay;isConnected=false;shouldReconnect=true;options;messageQueue=[];heartbeatInterval=null;connectionTimeout=null;constructor(e){this.options=e,this.reconnectInterval=e.reconnectDelay||2,this.maxReconnectDelay=e.maxReconnectDelay||60,this.log("Transport initialized",e.url);}connect(){if(this.socket){this.log("Socket already exists, skipping connection");return}this.log("Connecting to",this.options.url),this.socket=new WebSocket(this.options.url),this.connectionTimeout=setTimeout(()=>{this.isConnected||(this.log("Connection timeout"),this.socket?.close(),this.handleReconnect());},1e4),this.socket.onopen=()=>{this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.isConnected=true,this.reconnectInterval=this.options.reconnectDelay||2,this.log("Connected to server"),this.options.onOpen?.(),this.startHeartbeat(),this.flushQueue();},this.socket.onmessage=e=>{try{let t=JSON.parse(e.data);this.options.onMessage(t);}catch(t){this.log("Parse error",t),this.options.onError?.(t);}},this.socket.onerror=e=>{this.log("WebSocket error",e),this.options.onError?.(new Error("WebSocket error"));},this.socket.onclose=e=>{this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.isConnected=false,this.socket=null,this.stopHeartbeat(),this.log("Connection closed",e.code,e.reason),this.options.onClose?.(),e.code!==1e3&&this.shouldReconnect&&this.options.autoReconnect&&this.handleReconnect();};}handleReconnect(){let e=this.reconnectInterval*1e3;this.log(`Reconnecting in ${this.reconnectInterval}s...`),setTimeout(()=>{this.reconnectInterval=Math.min(this.reconnectInterval*2,this.maxReconnectDelay),this.connect();},e);}startHeartbeat(){this.heartbeatInterval=setInterval(()=>{this.isConnected&&this.send({type:"ping",id:Date.now().toString(),ts:Date.now()});},3e4);}stopHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null);}flushQueue(){for(this.log("Flushing message queue",this.messageQueue.length);this.messageQueue.length>0;){let e=this.messageQueue.shift();e&&this.send(e);}}send(e){if(this.socket&&this.socket.readyState===WebSocket.OPEN){let t=n=>{try{this.socket.send(n),this.log("Sent message",e);}catch(i){this.log("Send error",i),this.messageQueue.push(e);}};this.options.publicKey?X(e,this.options.publicKey).then(t).catch(n=>{this.log("RSA encrypt error \u2014 sending plaintext",n),t(JSON.stringify(e));}):t(JSON.stringify(e));}else this.log("Socket not ready, queueing message"),this.messageQueue.push(e);}disconnect(){this.shouldReconnect=false,this.stopHeartbeat(),this.socket&&(this.socket.close(1e3,"Client disconnect"),this.socket=null),this.isConnected=false,this.log("Disconnected");}get connected(){return this.isConnected}log(...e){this.options.debug&&console.log("[FlareTransport]",...e);}};var v=class{transport;config;pendingAcks=new Map;subscriptions=new Map;activeSubscriptions=new Map;offlineQueue=[];currentState="disconnected";connectionListeners=[];errorListeners=[];isDebug=false;socketAuthUid="anon";pendingSubscriptionReplay=false;subscriptionReplayPromise=Promise.resolve();requestTraceSeq=0;requestTimingEnabled=true;presenceCallbacks=new Map;presenceJoinCbs=new Map;presenceLeaveCbs=new Map;presenceHeartbeatTimer;embedder;vectorSchema=new Map;throwFetchFlareError(e,t,n){let i=e,s=typeof i?.error=="string"&&i.error.length>0?i.error:n,r=typeof i?.message=="string"&&i.message.length>0?i.message:t;throw new l(r,s,e)}nowMs(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}normalizeHeaders(e){if(!e)return {};let t={};if(e instanceof Headers)e.forEach((n,i)=>{t[i]=n;});else if(Array.isArray(e))for(let[n,i]of e)t[String(n)]=String(i);else for(let[n,i]of Object.entries(e))t[String(n)]=String(i);return t}redactHeaders(e){let t={...e};for(let n of Object.keys(t)){let i=n.toLowerCase();(i==="authorization"||i==="x-flare-csrf"||i==="x-csrf-token")&&(t[n]="[redacted]");}return t}logHttpTiming(...e){this.requestTimingEnabled&&this.log("[FlareClient][http]",...e);}mergeHeaders(e,t){if(!e)return t;if(e instanceof Headers){let n=new Headers(e);for(let[i,s]of Object.entries(t))n.set(i,s);return n}return Array.isArray(e)?[...e,...Object.entries(t)]:{...e,...t}}async timedFetch(e,t,n){let i=++this.requestTraceSeq,s=this.nowMs(),r=String(n?.method??"GET").toUpperCase(),a=this.redactHeaders(this.normalizeHeaders(n?.headers));this.logHttpTiming(`#${i} ${e} start`,{method:r,url:t,headers:a,hasBody:!!n?.body});try{let c=this.mergeHeaders(n?.headers,{"x-flare-request-id":String(i)}),f=this.normalizeHeaders(c),E=this.redactHeaders(f),p={timeout:Math.ceil((this.config.connectionTimeout??1e4)/1e3),ignoreKind:!0,headers:f,withCredentials:n?.credentials==="include",returnRawResponse:!0,appendCookiesToBody:!1,appendTimestamp:!1};this.logHttpTiming(`#${i} ${e} request`,{method:r,url:t,headers:E,hasBody:!!n?.body});let d=n?.body,x=r.toUpperCase(),C=x==="GET"?await withGet(t,p):x==="PUT"?await withPut(t,d,p):x==="PATCH"?await withPatch(t,d,p):await withPost(t,d,p),M=C?.headers??{},H={status:Number(C?.status??0),ok:Number(C?.status??0)>=200&&Number(C?.status??0)<300,headers:{get:j=>{let Q=j.toLowerCase();for(let[J,G]of Object.entries(M))if(J.toLowerCase()===Q)return String(G);return null}},json:async()=>C?.data??{}},q=this.nowMs()-s;return this.logHttpTiming(`#${i} ${e} response`,{status:H.status,networkMs:Number(q.toFixed(2))}),{response:H,requestId:i,startedAtMs:s,networkMs:q,method:r,url:t}}catch(c){let f=this.nowMs()-s;throw this.logHttpTiming(`#${i} ${e} failed`,{networkMs:Number(f.toFixed(2)),message:c?.message??String(c)}),c}}async parseJsonWithTiming(e,t){let n=this.nowMs(),i=await t.response.json().catch(()=>({})),s=this.nowMs()-n,r=this.nowMs()-t.startedAtMs;return this.logHttpTiming(`#${t.requestId} ${e} complete`,{method:t.method,url:t.url,status:t.response.status,networkMs:Number(t.networkMs.toFixed(2)),parseMs:Number(s.toFixed(2)),totalMs:Number(r.toFixed(2))}),i}getHttpBase(){if(this.config.httpBase)return this.config.httpBase.replace(/\/$/,"");let e=new URL(this.config.endpoint);return `${e.protocol}//${e.host}`}log(...e){this.isDebug&&console.log("[FlareClient]",...e);}constructor(e){this.config={autoReconnect:true,reconnectDelay:2,maxReconnectDelay:60,debug:false,connectionTimeout:1e4,...e},this.isDebug=this.config.debug||false,this.requestTimingEnabled=this.config.requestTiming??true;let{hostname:t,port:n,protocol:i}=new URL(this.config.endpoint),s=i==="https:",c=`${s?"wss":"ws"}://${t}:${n||(s?"443":"80")}/?appId=${this.config.appId}${this.config.apiKey?`&apiKey=${this.config.apiKey}`:""}`;this.transport=new w({url:c,publicKey:this.config.publicKey,autoReconnect:this.config.autoReconnect,reconnectDelay:this.config.reconnectDelay,maxReconnectDelay:this.config.maxReconnectDelay,onMessage:f=>this.handleIncoming(f),onOpen:()=>this.onConnected(),onClose:()=>this.onDisconnected(),onError:f=>this.handleTransportError(f),debug:this.isDebug});}connect(){this.setState("connecting"),this.transport.connect();}disconnect(){this.transport.disconnect(),this.setState("disconnected");}get connectionState(){return this.currentState}get isConnected(){return this.currentState==="connected"}onConnectionStateChange(e){return this.connectionListeners.push(e),()=>{this.connectionListeners=this.connectionListeners.filter(t=>t!==e);}}onError(e){return this.errorListeners.push(e),()=>{this.errorListeners=this.errorListeners.filter(t=>t!==e);}}collection(e){return new N(this,e)}doc(e,t){return t!==void 0?new T(this,e,t):new k(this,e)}async ping(){let e=Date.now();return await this.send("ping",{}),Date.now()-e}async call(e,t={}){let n=await this.send("call",{topic:e,payload:t});if(!n.success)throw new l(n.error??`CALL "${e}" failed`,h.QueryFailed);return n.result}async query(e,t={}){return (await this.send("query",{collection:e,query:t})).data??[]}setEmbedder(e){this.embedder=e;}markVectorField(e,t,n={dimensions:1536}){this.vectorSchema.has(e)||this.vectorSchema.set(e,new Map),this.vectorSchema.get(e).set(t,n);}async embedVectorFields(e,t){let n=this.vectorSchema.get(e);if(!n)return t;let i={...t};for(let[s,r]of n){let a=i[s];if(typeof a=="string"){let c=r.embed??this.embedder;if(!c){this.log(`[vector] No embedder for field "${s}" \u2014 storing raw text`);continue}i[s]=await c(a);}}return i}async joinPresence(e,t){return await this.send("presence_join",{room:e,meta:t}),this._startPresenceHeartbeat(e,t),()=>this.leavePresence(e)}async leavePresence(e){await this.send("presence_leave",{room:e}),this._stopPresenceHeartbeat();}onPresenceState(e,t){return this.presenceCallbacks.has(e)||this.presenceCallbacks.set(e,[]),this.presenceCallbacks.get(e).push(t),()=>{let n=this.presenceCallbacks.get(e)??[];this.presenceCallbacks.set(e,n.filter(i=>i!==t));}}onPresenceJoin(e,t){return this.presenceJoinCbs.has(e)||this.presenceJoinCbs.set(e,[]),this.presenceJoinCbs.get(e).push(t),()=>{let n=this.presenceJoinCbs.get(e)??[];this.presenceJoinCbs.set(e,n.filter(i=>i!==t));}}onPresenceLeave(e,t){return this.presenceLeaveCbs.has(e)||this.presenceLeaveCbs.set(e,[]),this.presenceLeaveCbs.get(e).push(t),()=>{let n=this.presenceLeaveCbs.get(e)??[];this.presenceLeaveCbs.set(e,n.filter(i=>i!==t));}}_startPresenceHeartbeat(e,t){this.presenceHeartbeatTimer||(this.presenceHeartbeatTimer=setInterval(()=>{this.isConnected&&this.send("presence_heartbeat",{meta:t}).catch(()=>{});},2e4));}_stopPresenceHeartbeat(){this.presenceHeartbeatTimer&&(clearInterval(this.presenceHeartbeatTimer),this.presenceHeartbeatTimer=void 0);}async syncOffline(){if(this.offlineQueue.length===0)return;this.log("Syncing offline operations",this.offlineQueue.length);let e=[...this.offlineQueue];this.offlineQueue.length=0;let t=await this.send("offline_sync",{operations:e});t.conflicts&&t.conflicts.length>0&&(this.log("Offline sync conflicts",t.conflicts),t.conflicts.forEach(n=>{let i=e.find(s=>s.id===n.operationId);i&&this.offlineQueue.push(i);}));}async activateSubscription(e){if(!this.isConnected){this.pendingSubscriptionReplay=true;return}this.subscriptions.set(e.liveId,e.callback);try{let t=await this.send("subscribe",{collection:e.collection,docId:e.docId,query:e.query,skipSnapshot:e.options.skipSnapshot});if(!this.activeSubscriptions.has(e.baseId)){this.subscriptions.delete(e.liveId);return}t.subscriptionId&&t.subscriptionId!==e.liveId&&(this.subscriptions.delete(e.liveId),e.liveId=t.subscriptionId,this.subscriptions.set(e.liveId,e.callback),this.log("Subscription remapped",e.baseId,"\u2192",e.liveId));}catch(t){this.subscriptions.delete(e.liveId),this.pendingSubscriptionReplay=true,this.log("Subscription failed",t);}}async replayActiveSubscriptions(){if(!this.isConnected){this.pendingSubscriptionReplay=true;return}let e=Array.from(this.activeSubscriptions.values());if(e.length===0){this.pendingSubscriptionReplay=false;return}this.pendingSubscriptionReplay=false,this.subscriptionReplayPromise=this.subscriptionReplayPromise.then(async()=>{for(let t of e){if(!this.activeSubscriptions.has(t.baseId))continue;let n=t.liveId;this.subscriptions.delete(n),t.liveId=t.baseId,n&&await this.send("unsubscribe",{subscriptionId:n}).catch(()=>{}),await this.activateSubscription(t);}}).catch(t=>{this.pendingSubscriptionReplay=true,this.log("Subscription replay failed",t);}),await this.subscriptionReplayPromise;}subscribe(e,t,n,i,s,r={}){this.log("Creating subscription",e,t,n);let a={baseId:e,liveId:e,collection:t,docId:n,query:i,callback:s,options:r};return this.activeSubscriptions.set(e,a),this.activateSubscription(a).catch(c=>{this.log("Subscription activation failed",c);}),()=>{let f=this.activeSubscriptions.get(e)?.liveId??e;this.log("Unsubscribing",f),this.activeSubscriptions.delete(e),this.subscriptions.delete(f),this.isConnected&&this.send("unsubscribe",{subscriptionId:f}).catch(E=>this.log("Unsubscribe failed",E));}}async send(e,t){return e==="write"&&t.collection&&t.data&&(t={...t,data:await this.embedVectorFields(t.collection,t.data)}),new Promise((n,i)=>{let s=uuid2(18),r={id:s,type:e,ts:Date.now(),...t};this.pendingAcks.set(s,a=>{a.type==="error"?i(new Error(`[${a.code}] ${a.message}`)):n(a);}),this.isConnected?this.transport.send(r):(this.log("Queueing message for offline",r),this.offlineQueue.push(r),i(new Error("Not connected - message queued"))),setTimeout(()=>{this.pendingAcks.has(s)&&(this.pendingAcks.delete(s),i(new Error("Request timeout")));},this.config.connectionTimeout);})}handleTransportError(e){this.log("Transport error",e),this.errorListeners.forEach(t=>{try{t(e);}catch(n){this.log("Error listener error",n);}});}onConnected(){this.setState("connected"),this.log("Connected to FlareServer"),this.activeSubscriptions.size>0&&(this.pendingSubscriptionReplay=true),this.offlineQueue.length>0&&this.syncOffline().catch(e=>{this.log("Offline sync failed",e);});}onDisconnected(){this.currentState!=="disconnected"&&this.setState("reconnecting"),this.activeSubscriptions.size>0&&(this.pendingSubscriptionReplay=true),this.log("Disconnected from FlareServer");}setState(e){this.currentState!==e&&(this.currentState=e,this.log("Connection state changed",e),this.connectionListeners.forEach(t=>{try{t(e);}catch(n){this.log("Connection listener error",n);}}));}handleIncoming(e){if(this.log("Received message",e.type,e),e.type==="ack"||e.type==="pong"||e.type==="auth_ok"||e.type==="call_response"||e.type==="query_result"){let t=this.pendingAcks.get(e.correlationId||e.id);t&&(t(e),this.pendingAcks.delete(e.correlationId||e.id));return}if(e.type==="error"){this.log("Server error",e.code,e.message);let t=new Error(`[${e.code}] ${e.message}`);if(this.errorListeners.forEach(n=>{try{n(t);}catch(i){this.log("Error listener error",i);}}),e.correlationId){let n=this.pendingAcks.get(e.correlationId);n&&(n(e),this.pendingAcks.delete(e.correlationId));}return}if(e.type==="presence_state"){(this.presenceCallbacks.get(e.room)??[]).forEach(n=>{try{n(e.members);}catch{}});return}if(e.type==="presence_join"){(this.presenceJoinCbs.get(e.room)??[]).forEach(n=>{try{n(e);}catch{}});return}if(e.type==="presence_leave"){(this.presenceLeaveCbs.get(e.room)??[]).forEach(n=>{try{n(e.uid);}catch{}});return}if(e.type==="snapshot"){let t=this.subscriptions.get(e.subscriptionId);if(t){let n={type:"snapshot",subscriptionId:e.subscriptionId,collection:e.collection,data:Array.isArray(e.data)?e.data:e.data!=null?[e.data]:[]};try{t(n);}catch(i){this.log("Subscription callback error",i);}}return}if(e.type==="change"){let t=this.subscriptions.get(e.subscriptionId);if(t){let n={type:"change",subscriptionId:e.subscriptionId,collection:e.collection,docId:e.docId,operation:e.operation,data:e.operation==="delete"?null:e.data};try{t(n);}catch(i){this.log("Subscription callback error",i);}}}}};var A=class extends v{authToken;userId;authGuard;authConfig;csrfToken;csrfInitPromise;csrfBootstrapAttempted=false;authSession=null;authStateListeners=[];authConfigListeners=[];getDefaultCsrfCookieName(){return `__flare_csrf_${this.config.appId.replace(/[^a-zA-Z0-9_-]/g,"_")}`}getCsrfCookieName(){return this.authConfig?.cookie?.csrfTokenName??this.getDefaultCsrfCookieName()}getCsrfToken(){return this.getCookieValue(this.getCsrfCookieName())??this.csrfToken??null}getCookieValue(e){if(typeof document>"u")return null;let t=document.cookie.split(";").map(i=>i.trim()).find(i=>i.startsWith(`${e}=`)||i.startsWith(`${encodeURIComponent(e)}=`));if(!t)return null;let n=t.indexOf("=");return n>=0?decodeURIComponent(t.slice(n+1)):null}extractCsrfToken(e,t){let n=e,i=typeof n?.csrfToken=="string"?String(n.csrfToken):typeof n?.csrf_token=="string"?String(n.csrf_token):void 0;if(i)return i;if(!t)return;let s=t.headers.get("x-flare-csrf")??t.headers.get("x-csrf-token")??t.headers.get("csrf-token");return typeof s=="string"&&s.length>0?s:void 0}getCsrfHeaders(){let e=this.getCsrfToken();return e?{"x-flare-csrf":e}:{}}setCsrfToken(e){this.csrfToken=e,this.csrfBootstrapAttempted=true,this.log("CSRF token injected",{length:e.length});}async ensureCsrfProtection(){if(this.getCsrfToken()){this.csrfBootstrapAttempted=true;return}if(this.config.httpBase){this.csrfBootstrapAttempted=true;return}this.csrfBootstrapAttempted||(this.csrfInitPromise||(this.csrfBootstrapAttempted=true,this.csrfInitPromise=this.loadAuthConfig().then(()=>{}).finally(()=>{this.csrfInitPromise=void 0;})),await this.csrfInitPromise,this.getCsrfToken()||this.log("CSRF token unavailable after auth config load",{hasAuthConfig:!!this.authConfig,csrfCookieName:this.getCsrfCookieName()}));}async loadAuthConfig(){let e=this.getHttpBase(),t=new URLSearchParams({appId:this.config.appId});this.config.apiKey&&t.set("apiKey",this.config.apiKey);let n=`${e}/auth/config?${t.toString()}`,i=await this.timedFetch("loadAuthConfig",n,{credentials:"include",headers:this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}}),s=await this.parseJsonWithTiming("loadAuthConfig",i);return i.response.ok||this.throwFetchFlareError(s,"Failed to load auth config",h.QueryFailed),this.authConfig=s,this.csrfToken=this.extractCsrfToken(s,i.response)??this.csrfToken,this.authConfigListeners.forEach(r=>{try{r(this.authConfig);}catch(a){this.log("Auth config listener error",a);}}),this.authConfig}async fetchAuthConfig(){return this.authConfig?this.authConfig:this.loadAuthConfig()}onAuthConfigLoaded(e){return this.authConfigListeners.push(e),this.authConfig&&e(this.authConfig),()=>{this.authConfigListeners=this.authConfigListeners.filter(t=>t!==e);}}setAuthSession(e){this.authSession=e,e?(this.authToken=e.accessToken,this.userId=e.uid):(this.authToken=void 0,this.userId=void 0),this.authStateListeners.forEach(t=>{try{t(this.authSession);}catch(n){this.log("Auth state listener error",n);}});}onAuthStateChanged(e){this.authStateListeners.push(e);try{e(this.authSession);}catch(t){this.log("Auth state listener error during initialization",t);}return ()=>{this.authStateListeners=this.authStateListeners.filter(t=>t!==e);}}onAuthStateChange(e){return this.onAuthStateChanged(e)}get currentUser(){return this.userId}getCurrentUser(){return this.currentUser}async syncSocketAuth(e){if(!this.isConnected)return;let t=await this.send("auth",e?{token:e}:{});if(t.type!=="auth_ok")throw new l("Socket auth sync failed",h.AuthenticationFailed);if(!e||t.uid==="anon"){this.authToken=void 0,this.userId=void 0,await this.updateSocketIdentity("anon");return}this.authToken=typeof t.token=="string"?t.token:e,this.userId=typeof t.uid=="string"?t.uid:this.userId,await this.updateSocketIdentity(typeof t.uid=="string"?t.uid:this.userId);}async updateSocketIdentity(e,t=false){let n=typeof e=="string"&&e.length>0?e:"anon",i=n!==this.socketAuthUid;this.socketAuthUid=n,(i||t||this.pendingSubscriptionReplay)&&this.activeSubscriptions.size>0&&await this.replayActiveSubscriptions();}onConnected(){super.onConnected(),this.authSession?.accessToken&&this.syncSocketAuth(this.authSession.accessToken).catch(e=>{this.log("Socket auth sync failed after connect",e);});}handleIncoming(e){if(e.type==="auth_ok"&&!e.correlationId){let t=typeof e.token=="string"?e.token:void 0,n=typeof e.uid=="string"?e.uid:void 0;this.updateSocketIdentity(n,this.pendingSubscriptionReplay).catch(i=>{this.log("Socket identity update failed",i);}),t&&n&&n!=="anon"&&n!=="__admin__"?this.fetchAuthMe(t).then(i=>{this.setAuthSession({uid:n,accessToken:t,refreshToken:this.authSession?.refreshToken??null,email:i?.email??null,emailVerified:i?.email_verified});}).catch(()=>{this.setAuthSession({uid:n,accessToken:t,refreshToken:this.authSession?.refreshToken??null});}):n==="anon"&&this.authSession&&this.setAuthSession(null);}super.handleIncoming(e);}async auth(e){let t=await this.send("auth",{token:e});if(t.type==="auth_ok"){let n=t.token??e;this.authToken=n,this.userId=t.uid;let i=await this.fetchAuthMe(n).catch(()=>null);return console.log("--profile",i),this.setAuthSession({uid:t.uid??t.id,accessToken:n,refreshToken:this.authSession?.refreshToken??null,email:i?.email??null,emailVerified:i?.email_verified}),await this.updateSocketIdentity(t.uid),this.log("Authentication successful",t.uid),{uid:t.uid,token:t.token??e}}throw new l("Authentication failed",h.AuthenticationFailed)}async signInWithEmailAndPassword(e,t,n){try{let i=await this.requestEmailPasswordToken(e,t,n?.scope),s=await this.auth(i.access_token),r=await this.fetchAuthMe(i.access_token).catch(()=>null);return this.setAuthSession({uid:s.uid,accessToken:i.access_token,refreshToken:i.refresh_token,provider:i.provider,email:r?.email??e,emailVerified:r?.email_verified}),this.log("Credentials sign-in successful",s.uid),{...s,kind:i.kind,accessToken:i.access_token,refreshToken:i.refresh_token,authToken:i}}catch(i){let s=/invalid_email|user.not.found|no user/i.test(i?.message??"");if(n?.createIfMissing&&s){let r=await this.createUserWithEmail(e,t,{scope:n.scope,signInIfAllowed:true});if("verificationRequired"in r&&r.verificationRequired)throw new l("Email verification required before sign-in",h.AuthenticationFailed);return {uid:r.uid,token:r.token,accessToken:r.accessToken,refreshToken:r.refreshToken,authToken:r.authToken,created:true}}throw i instanceof l?i:new l(i instanceof Error?i.message:"Sign-in with email/password failed",i.error??i.code??h.AuthenticationFailed,i)}}async signInWithEmail(e,t,n){return this.signInWithEmailAndPassword(e,t,n)}async createUserWithEmail(e,t,n){let i=await this.registerWithEmail(e,t,n);if(i.verification_required)return {kind:i.kind,verificationRequired:true,emailSent:!!i.email_sent,preview:i.preview};let s=String(i.access_token??"");if(!s)throw new l("User created but no access token returned",h.AuthenticationFailed);let r={access_token:s,refresh_token:i.refresh_token?String(i.refresh_token):null,expires_in:i.expires_in?Number(i.expires_in):null,token_type:String(i.token_type??"Bearer"),scope:i.scope?String(i.scope):null,profile:null,provider:"credentials"},a=await this.auth(s),c=await this.fetchAuthMe(s).catch(()=>null);return this.setAuthSession({uid:a.uid,accessToken:s,refreshToken:r.refresh_token,provider:"credentials",email:c?.email??e,emailVerified:c?.email_verified}),{...a,accessToken:s,refreshToken:r.refresh_token,authToken:r,verificationRequired:false,emailSent:!!i.email_sent,preview:i.preview}}async createUserWithEmailAndPassword(e,t,n){return this.createUserWithEmail(e,t,n)}async signInOrCreateWithEmail(e,t,n){try{return {...await this.signInWithEmailAndPassword(e,t,{scope:n?.scope}),created:!1}}catch(i){if(!/invalid_email|user.not.found|no user/i.test(i?.message??""))throw i;let r=await this.createUserWithEmail(e,t,{scope:n?.scope,additionalParams:n?.additionalParams,signInIfAllowed:true});return "verificationRequired"in r&&r.verificationRequired?{...r,created:true}:{...r,created:true}}}async signInOrCreateWithEmailAndPassword(e,t,n){return this.signInOrCreateWithEmail(e,t,n)}async sendEmailVerification(e){let t=this.getHttpBase();await this.ensureCsrfProtection();let n=await this.timedFetch("sendEmailVerification",`${t}/auth/verify/send?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:JSON.stringify({email:e,appId:this.config.appId,apiKey:this.config.apiKey})}),i=await this.parseJsonWithTiming("sendEmailVerification",n);return n.response.ok||this.throwFetchFlareError(i,"Failed to send verification email",h.AuthenticationFailed),i}async verifyEmailWithCode(e,t){let n=this.getHttpBase();await this.ensureCsrfProtection();let i=await this.timedFetch("verifyEmailWithCode",`${n}/auth/verify/confirm?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:JSON.stringify({email:e,code:t,appId:this.config.appId,apiKey:this.config.apiKey})}),s=await this.parseJsonWithTiming("verifyEmailWithCode",i);return i.response.ok||this.throwFetchFlareError(s,"Email verification failed",h.AuthenticationFailed),s}async confirmEmailLink(e,t){let n=this.getHttpBase();await this.ensureCsrfProtection();let i=await this.timedFetch("confirmEmailLink",`${n}/auth/verify/confirm?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:JSON.stringify({token:e,email:t,appId:this.config.appId,apiKey:this.config.apiKey})}),s=await this.parseJsonWithTiming("confirmEmailLink",i);return i.response.ok||this.throwFetchFlareError(s,"Email link verification failed",h.AuthenticationFailed),s}async sendAccountRecovery(e){let t=this.getHttpBase();await this.ensureCsrfProtection();let n=await this.timedFetch("sendAccountRecovery",`${t}/auth/recover/send?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:JSON.stringify({email:e,appId:this.config.appId,apiKey:this.config.apiKey})}),i=await this.parseJsonWithTiming("sendAccountRecovery",n);return n.response.ok||this.throwFetchFlareError(i,"Failed to send recovery email",h.AuthenticationFailed),i}async recoverAccountWithCode(e,t,n){let i=this.getHttpBase();await this.ensureCsrfProtection();let s=await this.timedFetch("recoverAccountWithCode",`${i}/auth/recover/confirm?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:JSON.stringify({email:e,code:t,newPassword:n,appId:this.config.appId,apiKey:this.config.apiKey})}),r=await this.parseJsonWithTiming("recoverAccountWithCode",s);return s.response.ok||this.throwFetchFlareError(r,"Account recovery failed",h.AuthenticationFailed),r}async recoverAccountWithToken(e,t){let n=this.getHttpBase();await this.ensureCsrfProtection();let i=await this.timedFetch("recoverAccountWithToken",`${n}/auth/recover/confirm?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:JSON.stringify({token:e,newPassword:t,appId:this.config.appId,apiKey:this.config.apiKey})}),s=await this.parseJsonWithTiming("recoverAccountWithToken",i);return i.response.ok||this.throwFetchFlareError(s,"Account recovery failed",h.AuthenticationFailed),s}async signIn(e,t,n){let i=typeof e?.signIn=="function",s=i?e:await this.getAuthGuard(),r=i?t:e,a=i?n:t;return s.signIn(r,a)}async signInWithGoogle(e){return this.signIn("google",e)}async signInWithGitHub(e){return this.signIn("github",e)}async signInWithFacebook(e){return this.signIn("facebook",e)}async signInWithDropbox(e){return this.signIn("dropbox",e)}async handleSignInRedirect(e,t=false){let n=typeof e?.handleRedirect=="function",i=n?e:await this.getAuthGuard(),s=n?t:typeof e=="boolean"?e:false,r=await i.handleRedirect(s);if(!r||!r.access_token||!r.provider)return null;let a=await this.exchangeProviderToken(r.provider,r.access_token),c=await this.auth(a.token),f=await this.fetchAuthMe(a.token).catch(()=>null);return this.setAuthSession({uid:c.uid,accessToken:a.token,refreshToken:r.refresh_token,provider:r.provider,email:f?.email??null,emailVerified:f?.email_verified}),{...c,authToken:r,provider:r.provider}}async exchangeProviderToken(e,t){let n=`${this.getHttpBase()}/auth/exchange`;await this.ensureCsrfProtection();let i=await this.timedFetch("exchangeProviderToken",n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders()},body:JSON.stringify({appId:this.config.appId,client_id:this.config.apiKey,provider:e,access_token:t})}),s=await this.parseJsonWithTiming("exchangeProviderToken",i);if(i.response.ok||this.throwFetchFlareError(s,"OAuth token exchange failed",h.AuthenticationFailed),!s?.token)throw new l("OAuth token exchange failed",h.ParseError,s);return {token:String(s.token)}}async getAuthGuard(){if(this.authGuard)return this.authGuard;let e=await this.fetchAuthConfig();if(!e.enabled)throw new l("Authentication is disabled for this app",h.AuthenticationFailed);let t=this.getHttpBase(),n=`${t}/auth/oauth/token?appId=${encodeURIComponent(this.config.appId)}`,i=[],s=(r,a)=>({...a,token_url:n,tokenParams:{...a.tokenParams??{},provider:r}});if(e.providers.credentials?.enabled&&i.push({...Credentials({clientId:this.config.apiKey}),token_url:`${t}/auth/token?appId=${encodeURIComponent(this.config.appId)}`,createUserUrl:`${t}/auth/register?appId=${encodeURIComponent(this.config.appId)}`,createUserGrantType:"create_user"}),e.providers.anonymous?.enabled&&i.push({...Anonymous({clientId:this.config.apiKey}),token_url:`${t}/auth/token?appId=${encodeURIComponent(this.config.appId)}`}),e.providers.google?.enabled&&e.providers.google.clientId&&i.push(s("google",Google({clientId:e.providers.google.clientId,scopes:e.providers.google.scopes}))),e.providers.github?.enabled&&e.providers.github.clientId&&i.push(s("github",GitHub({clientId:e.providers.github.clientId,scopes:e.providers.github.scopes}))),e.providers.facebook?.enabled&&e.providers.facebook.clientId&&i.push(s("facebook",Facebook({clientId:e.providers.facebook.clientId,scopes:e.providers.facebook.scopes}))),e.providers.dropbox?.enabled&&e.providers.dropbox.clientId&&i.push(s("dropbox",Dropbox({clientId:e.providers.dropbox.clientId,scopes:e.providers.dropbox.scopes}))),e.providers.apple?.enabled&&e.providers.apple.clientId&&i.push(s("apple",Apple({clientId:e.providers.apple.clientId,scopes:e.providers.apple.scopes}))),e.providers.twitter?.enabled&&e.providers.twitter.clientId&&i.push(s("twitter",Twitter({clientId:e.providers.twitter.clientId,scopes:e.providers.twitter.scopes}))),i.length===0)throw new l("No authentication providers are enabled for this app",h.AuthenticationFailed);return this.authGuard=new AuthGuard({providers:i,redirectUri:e.redirectUri}),this.authGuard}async refreshAuthSession(e){let t=this.getHttpBase();await this.ensureCsrfProtection();let n=await this.timedFetch("refreshAuthSession",`${t}/auth/refresh?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:JSON.stringify({appId:this.config.appId,apiKey:this.config.apiKey,...e?{refresh_token:e}:{}})}),i=await this.parseJsonWithTiming("refreshAuthSession",n);if(!n.response.ok){if(n.response.status===401)return this.setAuthSession(null),await this.syncSocketAuth(null).catch(()=>{}),null;this.throwFetchFlareError(i,"Failed to refresh auth session",h.AuthenticationFailed);}let s=String(i.access_token??"");if(!s)throw new l("Refresh succeeded but no access token was returned",h.ParseError);await this.fetchAuthMe(s).catch(c=>{console.log("--fetchAuthMe error",c);});let r=await this.fetchAuthMe(s).catch(()=>null),a={uid:String(r?.id??this.authSession?.uid??this.userId??""),accessToken:s,refreshToken:i.refresh_token?String(i.refresh_token):this.authSession?.refreshToken??null,provider:this.authSession?.provider,email:r?.email??this.authSession?.email??null,emailVerified:r?.email_verified};return this.setAuthSession(a),await this.syncSocketAuth(s).catch(()=>{}),a}async issueSsrToken(e=120){let t=this.getHttpBase();await this.ensureCsrfProtection();let n=await this.timedFetch("issueSsrToken",`${t}/auth/ssr/token?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:JSON.stringify({appId:this.config.appId,apiKey:this.config.apiKey,ttlSeconds:e})}),i=await this.parseJsonWithTiming("issueSsrToken",n);n.response.ok||this.throwFetchFlareError(i,"Failed to mint SSR token",h.AuthenticationFailed);let s=String(i.token??"");if(!s)throw new l("SSR token response is missing token",h.ParseError,i);return {token:s,token_type:String(i.token_type??"Bearer"),expires_in:Number(i.expires_in??0),uid:String(i.uid??""),role:String(i.role??"user"),...typeof i.email=="string"?{email:i.email}:{}}}async signOut(){try{if(this.authSession?.accessToken||this.authSession?.refreshToken){let e=this.getHttpBase();await this.ensureCsrfProtection(),await this.timedFetch("signOut",`${e}/auth/logout?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{},...this.authSession?.accessToken?{Authorization:`Bearer ${this.authSession.accessToken}`}:{}},body:JSON.stringify({appId:this.config.appId,apiKey:this.config.apiKey,refresh_token:this.authSession?.refreshToken})}).catch(()=>{});}}finally{this.setAuthSession(null),await this.syncSocketAuth(null).catch(()=>{});}this.log("Signed out");}async registerWithEmail(e,t,n){let i=this.getHttpBase();await this.ensureCsrfProtection();let s=new URLSearchParams;s.set("appId",this.config.appId),s.set("client_id",this.config.apiKey??""),s.set("grant_type","create_user"),s.set("email",e),s.set("password",t),n?.scope?.length&&s.set("scope",n.scope.join(" ")),n?.additionalParams&&s.set("additional_params",JSON.stringify(n.additionalParams));let r=await this.timedFetch("registerWithEmail",`${i}/auth/register?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:s.toString()}),a=await this.parseJsonWithTiming("registerWithEmail",r);return !r.response.ok&&r.response.status!==202&&this.throwFetchFlareError(a,"User creation failed",h.WriteFailed),a}async requestEmailPasswordToken(e,t,n){let i=this.getHttpBase();await this.ensureCsrfProtection();let s=new URLSearchParams;s.set("appId",this.config.appId),s.set("client_id",this.config.apiKey??""),s.set("grant_type","password"),s.set("email",e),s.set("password",t),n?.length&&s.set("scope",n.join(" "));let r=await this.timedFetch("requestEmailPasswordToken",`${i}/auth/token?appId=${encodeURIComponent(this.config.appId)}`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded",...this.getCsrfHeaders(),...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}},body:s.toString()}),a=await this.parseJsonWithTiming("requestEmailPasswordToken",r);return r.response.ok||this.throwFetchFlareError(a,"Sign-in with email/password failed",h.AuthenticationFailed),{kind:String(a.kind),access_token:String(a.access_token??""),refresh_token:a.refresh_token?String(a.refresh_token):null,expires_in:a.expires_in?Number(a.expires_in):null,token_type:String(a.token_type??"Bearer"),scope:a.scope?String(a.scope):null,profile:null,provider:"credentials"}}async fetchAuthMe(e){let t=this.getHttpBase(),n=new URLSearchParams({appId:this.config.appId});this.config.apiKey&&n.set("apiKey",this.config.apiKey);let i=`${t}/auth/me?${n.toString()}`,s=await this.timedFetch("fetchAuthMe",i,{credentials:"include",headers:{Authorization:`Bearer ${e}`,...this.config.apiKey?{"x-flare-api-key":this.config.apiKey}:{}}}),r=await this.parseJsonWithTiming("fetchAuthMe",s);return s.response.ok||this.throwFetchFlareError(r,"Failed to fetch profile",h.QueryFailed),r}};var O=class extends A{constructor(e){super(e),this.log("FlareClient initialized",e);}},U=O;function L(o){return `__flare_csrf_${o.replace(/[^a-zA-Z0-9_-]/g,"_")}`}function ge(o){return `__flare_csrf_${o.replace(/[^a-zA-Z0-9_-]/g,"_")}`}function P(o,e){let t=e.toLowerCase();for(let[n,i]of Object.entries(o??{}))if(n.toLowerCase()===t&&typeof i=="string")return i}function me(o){let e=P(o,"set-cookie");if(typeof e=="string"&&e.length>0)return [e];for(let[t,n]of Object.entries(o??{}))if(t.toLowerCase()==="set-cookie"&&Array.isArray(n))return n.filter(i=>typeof i=="string");return []}function ye(o,e){for(let t of o){let n=t.split(";").map(c=>c.trim()),[i]=n;if(!i)continue;let s=i.indexOf("=");if(s<=0)continue;let r=decodeURIComponent(i.slice(0,s)),a=i.slice(s+1);if(r===e)return decodeURIComponent(a)}}async function ke(o){let e=new URL("/auth/config",o.endpoint);return e.searchParams.set("appId",o.appId),o.apiKey&&e.searchParams.set("apiKey",o.apiKey),await withGet(e.toString(),{ignoreKind:true,withCredentials:true,returnRawResponse:true,headers:o.apiKey?{"x-flare-api-key":o.apiKey}:{},appendCookiesToBody:false,appendTimestamp:false}).catch(()=>null)}async function $(o){let e=await ke(o),t=e?.data,n=e?.headers??{},i=P(n,"x-flare-csrf")??P(n,"x-csrf-token")??P(n,"csrf-token");if(typeof i=="string"&&i.length>0)return {csrfToken:i,...t};let s=t?.cookie?.csrfTokenName,r=s&&s.length>0?s:ge(o.appId),a=me(n),c=ye(a,r);if(typeof c=="string"&&c.length>0)return {csrfToken:c,...t}}function W(o,e,t){return `${encodeURIComponent(o)}=${encodeURIComponent(e)}; HttpOnly; SameSite=Strict; Path=/; Max-Age=${t}`}function be(o){let e=o.proxyCookieName??L(o.appId),t=o.proxyCookieMaxAge??3600;return async function(i){let s=await $(o),r=s?.csrfToken,a=new Headers({"Content-Type":"application/json"});return r&&a.set("Set-Cookie",W(e,r,t)),new Response(JSON.stringify({csrfToken:r??null,...s}),{status:200,headers:a})}}function Ce(o){let e=o.proxyCookieName??L(o.appId),t=o.proxyCookieMaxAge??3600;return async function(i,s){if(i.method!=="GET"&&i.method!=="HEAD"){s.status(405).json({error:"Method not allowed"});return}let a=(await $(o))?.csrfToken;a&&s.setHeader("Set-Cookie",W(e,a,t)),s.status(200).json({csrfToken:a??null});}}function Te(o,e,t){let n=t??L(e);if(o instanceof Request){let r=(o.headers.get("cookie")??"").split(";").map(c=>c.trim()).find(c=>c.startsWith(`${encodeURIComponent(n)}=`)||c.startsWith(`${n}=`));if(!r)return null;let a=r.indexOf("=");return a>=0?decodeURIComponent(r.slice(a+1)):null}let{cookies:i}=o;return typeof i?.get=="function"?i.get(n)?.value??null:i&&typeof i=="object"?i[n]??null:null}function Se(o,e){let t={};return o&&(t["x-flare-csrf"]=o),e?.accessToken&&(t.Authorization=`Bearer ${e.accessToken}`),e?.apiKey&&(t["x-flare-api-key"]=e.apiKey),t}var Ie=(p=>(p.authEmailNotVerified="auth/email-not-verified",p.authEmailAlreadyVerified="auth/email-already-verified",p.authInvalidToken="auth/invalid-token",p.authUserDisabled="auth/user-disabled",p.authUserNotFound="auth/user-not-found",p.authWrongPassword="auth/wrong-password",p.authEmailAlreadyInUse="auth/email-already-in-use",p.authInvalidEmail="auth/invalid-email",p.authWeakPassword="auth/weak-password",p.authTooManyRequests="auth/too-many-requests",p.authInternalError="auth/internal-error",p))(Ie||{});var we=(u=>(u.health="health",u.authConfig="auth_config",u.authRegistration="auth/registration",u.authRegistrationVerificationRequired="auth/registration-verification-required",u.authSession="auth/session",u.authExchange="auth/exchange",u.authLogout="auth/logout",u.authSsrBridge="auth/ssr_bridge",u.authSsrVerify="auth/ssr_verify",u.accountRecovery="account/recovery",u.emailVerification="email/verification",u.verificationDispatch="verification/dispatch",u.authProfile="auth/profile",u.adminToken="admin/token",u.documentDelete="document/delete",u.documentsDelete="documents/delete",u.documents="documents",u.document="document",u.documentCreate="document/create",u.documentUpdate="document/update",u.oauthProviderResponse="oauth_provider_response",u.success="success",u.response="response",u))(we||{});var y=null,S=null,R=null,ve=o=>JSON.stringify({endpoint:o.endpoint,appId:o.appId,apiKey:o.apiKey,publicKey:o.publicKey,autoReconnect:o.autoReconnect,reconnectDelay:o.reconnectDelay,maxReconnectDelay:o.maxReconnectDelay}),It=o=>{let e=ve(o);return y&&R!==e&&(y.disconnect(),y=null,S=null,R=null),y||(y=new U(o),R=e,y.connect(),S=new Proxy(y,{get(t,n,i){if(n==="onAuthStateChange")return t.onAuthStateChanged.bind(t);if(n==="onAuthConfigLoaded")return t.onAuthConfigLoaded.bind(t);let s=Reflect.get(t,n,i);return typeof s=="function"?s.bind(t):s}})),S??y},wt=()=>S??y,vt=()=>{y&&(y.disconnect(),y=null,S=null,R=null);},At=U;
|
|
2
|
+
export{N as CollectionReference,k as DocumentQueryBuilder,T as DocumentReference,z as FlareAction,l as FlareError,Ie as FlareErrors,Y as FlareEvent,we as FlareResponseCodes,Se as buildFlareHeaders,It as connectApp,be as createCsrfProxy,Ce as createCsrfProxyHandler,At as default,vt as disconnectFlare,Te as extractCsrfFromRequest,wt as getFlare,B as parseValue,_ as parseWhereCondition};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zuzjs/flare",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"core",
|
|
6
6
|
"zuz",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"reflect-metadata"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@zuzjs/auth": "^0.1.
|
|
45
|
-
"@zuzjs/core": "^0.3.
|
|
44
|
+
"@zuzjs/auth": "^0.1.9",
|
|
45
|
+
"@zuzjs/core": "^0.3.13"
|
|
46
46
|
}
|
|
47
47
|
}
|