@zuzjs/flare-admin 0.1.5 → 0.1.6

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 CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var re=require('fs'),k=require('path'),url=require('url'),Y=require('ws');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var re__default=/*#__PURE__*/_interopDefault(re);var k__default=/*#__PURE__*/_interopDefault(k);var Y__default=/*#__PURE__*/_interopDefault(Y);/* @zuzjs/flare-admin */
2
- var ee=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,l=ee();var D=(i=>(i.Upload="upload",i.Download="download",i.Delete="delete",i.Edit="edit",i))(D||{});function B(r){let e=[];for(let[t,n]of Object.entries(r))if(typeof n=="string"){let i=n.match(/^(>=|<=|!=|>|<|==)\s*(.+)$/);if(i){let[,s,o]=i;e.push({field:t,op:s,value:te(o.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 te(r){return isNaN(Number(r))?r==="true"?true:r==="false"?false:r==="null"?null:r:Number(r)}function U(){return Math.random().toString(36).slice(2,12)+Date.now().toString(36)}function ne(r,e){let t=r.dataMapper;if(!t||typeof t!="object")return null;let n=t[e];return typeof n=="function"?n:null}function L(r,e,t){let n=ne(r,e);if(!n||t==null||typeof t!="object")return t;try{return n(t)}catch{return t}}function $(r,e,t){if(!e||typeof e!="object"||!Array.isArray(t)||t.length===0)return e;let n=e;for(let i of t){let s=String(i?.as??"").trim();if(!s)continue;let o=Array.isArray(i?.joins)?i.joins:[],a=n[s],d=a;Array.isArray(a)?d=a.map(c=>$(r,c,o)):a&&typeof a=="object"&&(d=$(r,a,o)),d=Array.isArray(d)?d.map(c=>L(r,s,c)):L(r,s,d),d!==a&&(n===e&&(n={...n}),n[s]=d);}return n}function A(r,e,t,n){let i=Array.isArray(n?.joins)?n.joins:[],s=o=>{let a=$(r,o,i);return L(r,e,a)};return Array.isArray(t)?t.map(o=>s(o)):s(t)}var se=()=>typeof process<"u"&&!!process.versions?.node,g=r=>{if(r.transport==="http")return false;let e=!!(r.grpcUrl&&r.grpcUrl.trim().length>0),t=se();if(r.transport==="grpc"){if(!e)throw new Error("[flare-admin][grpc] transport=grpc requires grpcUrl");if(!t)throw new Error("[flare-admin][grpc] transport=grpc requires Node.js runtime");return true}return e&&t},S=r=>{try{return JSON.stringify(r??{})}catch{return "{}"}},w=r=>r?.field&&r?.op?{queryFilter:{field:String(r.field),op:String(r.op),valueJson:S(r.value)}}:Array.isArray(r?.or)?{orFilter:{or:r.or.map(e=>w(e))}}:Array.isArray(r?.and)?{andFilter:{and:r.and.map(e=>w(e))}}:{queryFilter:{field:"",op:"==",valueJson:"null"}},x=r=>{if(!(!r||!Array.isArray(r.values)))return {valuesJson:r.values.map(e=>S(e))}},H=r=>({from:r.from,localField:r.localField,foreignField:r.foreignField,as:r.as,single:!!r.single,where:Array.isArray(r.where)?r.where.map(w):[],orderBy:Array.isArray(r.orderBy)?r.orderBy.map(e=>({field:e.field,dir:e.dir??"asc"})):[],limit:r.limit??0,offset:r.offset??0,select:Array.isArray(r.select)?r.select:[],joins:Array.isArray(r.joins)?r.joins.map(H):[]}),oe=r=>({where:Array.isArray(r.where)?r.where.map(w):[],orderBy:Array.isArray(r.orderBy)?r.orderBy.map(e=>({field:e.field,dir:e.dir??"asc"})):[],limit:r.limit??0,offset:r.offset??0,startAt:x(r.startAt),startAfter:x(r.startAfter),endAt:x(r.endAt),endBefore:x(r.endBefore),aggregate:Array.isArray(r.aggregate)?r.aggregate.map(e=>({fn:e.fn,field:e.field??"",alias:e.alias??""})):[],groupBy:r.groupBy?{fields:r.groupBy.fields??[]}:void 0,having:Array.isArray(r.having)?r.having.map(e=>({field:e.field,op:e.op,value:e.value})):[],joins:Array.isArray(r.joins)?r.joins.map(H):[],select:Array.isArray(r.select)?r.select:[],distinctField:r.distinctField??""});async function m(r){let e=await import('@grpc/grpc-js'),t=await import('@grpc/proto-loader'),n=k__default.default.dirname(url.fileURLToPath(l)),i=[k__default.default.resolve(n,"../../proto"),k__default.default.resolve(n,"../proto"),k__default.default.resolve(process.cwd(),"proto")],s=i.find(u=>re__default.default.existsSync(k__default.default.join(u,"flare.proto")))??i[0],o=k__default.default.join(s,"flare.proto"),a=await t.load(o,{keepCase:false,longs:String,enums:String,defaults:true,oneofs:true,includeDirs:[s]}),c=e.loadPackageDefinition(a).flare;return new c.AdminService(r,e.credentials.createInsecure())}function h(r,e,t){return new Promise((n,i)=>{r[e](t,(s,o)=>{if(s)return i(s);n(o??{});});})}function f(r,e){if(r.error)throw new Error(`[flare-admin][grpc] ${e} failed: ${r.errorDescription||r.error}`)}async function G(r,e,t){if(!g(r))return null;let n=await m(r.grpcUrl),i=await h(n,"AdminQuery",{app_id:r.appId,admin_key:r.adminKey,collection:e,query:oe(t)});f(i,"admin_query");try{let s=JSON.parse(i.dataJson||"[]");return Array.isArray(s)?s:[]}catch{return []}}async function M(r,e,t){if(!g(r))return null;let n=await m(r.grpcUrl),i=await h(n,"CreateCustomToken",{app_id:r.appId,admin_key:r.adminKey,uid:e,role:t.role??"user",claims_json:S(t.claims??{}),ttl:t.ttl??r.defaultTtl});if(f(i,"create_custom_token"),!i.token)throw new Error("[flare-admin][grpc] create_custom_token returned empty token");return String(i.token)}async function Q(r,e,t){if(!g(r))return null;let n=await m(r.grpcUrl),i=await h(n,"CreateAuthTicket",{app_id:r.appId,admin_key:r.adminKey,uid:e,role:t.role??"user",email:t.email??"",sid:t.sid??"",tag:t.tag??"",ttl_seconds:t.ttlSeconds??0,ip:t.ip??""});return f(i,"create_auth_ticket"),{ticket:String(i.ticket??""),tag:String(i.tag??""),uuid:String(i.uuid??""),expires_at:String(i.expiresAt??""),one_time:!!(i.oneTime??true),uid:String(i.uid??e),role:String(i.role??t.role??"user"),ip:String(i.ip??"unknown")}}async function z(r,e,t){if(!g(r))return;let n=await m(r.grpcUrl),i=await h(n,"GetDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,doc_id:t});if(f(i,"get_document"),!i.found)return null;try{return JSON.parse(i.dataJson||"{}")}catch{return {}}}async function K(r,e,t){if(!g(r))return null;let n=await m(r.grpcUrl),i=await h(n,"CreateDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,data_json:S(t)});return f(i,"create_document"),String(i.id??"")}async function W(r,e,t,n){if(!g(r))return null;let i=await m(r.grpcUrl),s=await h(i,"ReplaceDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,doc_id:t,data_json:S(n)});return f(s,"replace_document"),true}async function V(r,e,t,n){if(!g(r))return null;let i=await m(r.grpcUrl),s=await h(i,"UpdateDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,doc_id:t,data_json:S(n)});return f(s,"update_document"),true}async function Z(r,e,t){if(!g(r))return null;let n=await m(r.grpcUrl),i=await h(n,"DeleteDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,doc_id:t});return f(i,"delete_document"),!!i.deleted}async function X(r,e,t){if(!g(r))return null;let n=await m(r.grpcUrl),i=await h(n,"DeleteMany",{app_id:r.appId,admin_key:r.adminKey,collection:e,where:(t??[]).map(w)});return f(i,"delete_many"),Number(i.deleted??0)}var y=class{constructor(e,t,n){this.cfg=e;this.collection=t;this.id=n;}get baseUrl(){return `${this.cfg.serverUrl}/admin/db/${this.cfg.appId}/${this.collection}/${this.id}`}get headers(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`}}async request(e,t){let n;try{n=await fetch(this.baseUrl,{method:e,headers:this.headers,...t!==void 0?{body:JSON.stringify(t)}:{}});}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`[flare-admin] Network error (${e} ${this.baseUrl}): ${o}`)}let i=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] ${e} ${this.baseUrl} failed (HTTP ${n.status}): `+(i.error??"Unknown error"));return i}async get(){let e=await z(this.cfg,this.collection,this.id);if(e!==void 0)return e===null?null:A(this.cfg,this.collection,e)??null;let t;try{t=await fetch(this.baseUrl,{headers:this.headers});}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${o}`)}if(t.status===404)return null;let n=await t.json().catch(()=>({}));if(!t.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${t.status}): `+(n.error??"Unknown error"));return A(this.cfg,this.collection,n.data)??null}async set(e){await W(this.cfg,this.collection,this.id,e)===null&&await this.request("PUT",e);}async update(e){await V(this.cfg,this.collection,this.id,e)===null&&await this.request("PATCH",e);}async delete(){await Z(this.cfg,this.collection,this.id)===null&&await this.request("DELETE");}parent(){return new b(this.cfg,this.collection)}};var b=class r{constructor(e,t){this.cfg=e;this.name=t;this.sq={};this.opts={allowSensitiveAuthUserFields:true};}get baseUrl(){return `${this.cfg.serverUrl}/admin/db/${this.cfg.appId}/${this.name}`}get headers(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`}}clone(e){let t=new r(this.cfg,this.name);return t.sq={...this.sq,...e},t.opts={...this.opts},t}allowSensitiveAuthUserFields(e=true){let t=this.clone({});return t.opts.allowSensitiveAuthUserFields=!!e,t}normalizeFilterValue(e,t){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(t)?t:[t]:t}toQueryFilters(e){return B(e).map(n=>typeof n=="object"&&n!=null&&"field"in n&&"op"in n?{...n,value:this.normalizeFilterValue(n.op,n.value)}:n)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let t=[...this.sq.where??[]];if(t.length===0)return this.clone({where:[{or:e}]});let n=t[0];if(t.length===1&&typeof n=="object"&&n!=null&&"or"in n)return this.clone({where:[{or:[...n.or,...e]}]});let s=t.length===1?t[0]:{and:t};return this.clone({where:[{or:[s,...e]}]})}appendFilters(e,t){return t==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,t,n,i){return this.appendFilters([{field:e,op:t,value:this.normalizeFilterValue(t,n)}],i)}where(e){return this.appendFilters(this.toQueryFilters(e),"and")}and(e){return this.appendFilters(this.toQueryFilters(e),"and")}or(e){return this.appendFilters(this.toQueryFilters(e),"or")}in(e,t){return this.appendOperatorFilter(e,"in",t,"and")}andIn(e,t){return this.appendOperatorFilter(e,"in",t,"and")}orIn(e,t){return this.appendOperatorFilter(e,"in",t,"or")}notIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"and")}andNotIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"and")}orNotIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"or")}arrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"and")}andArrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"and")}orArrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"or")}arrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"and")}andArrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"and")}orArrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"or")}some(e,t){return this.appendOperatorFilter(e,"elem-match",t,"and")}andSome(e,t){return this.appendOperatorFilter(e,"elem-match",t,"and")}orSome(e,t){return this.appendOperatorFilter(e,"elem-match",t,"or")}like(e,t){return this.appendOperatorFilter(e,"like",t,"and")}andLike(e,t){return this.appendOperatorFilter(e,"like",t,"and")}orLike(e,t){return this.appendOperatorFilter(e,"like",t,"or")}notLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"and")}andNotLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"and")}orNotLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"or")}exists(e){return this.appendOperatorFilter(e,"exists",true,"and")}andExists(e){return this.appendOperatorFilter(e,"exists",true,"and")}orExists(e){return this.appendOperatorFilter(e,"exists",true,"or")}notExists(e){return this.appendOperatorFilter(e,"not-exists",true,"and")}andNotExists(e){return this.appendOperatorFilter(e,"not-exists",true,"and")}orNotExists(e){return this.appendOperatorFilter(e,"not-exists",true,"or")}latest(){return this.clone({orderBy:[...this.sq.orderBy??[],{field:"_seq",dir:"desc"}]})}newest(){return this.latest()}oldest(){return this.clone({orderBy:[...this.sq.orderBy??[],{field:"_seq",dir:"asc"}]})}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}]})}buildStructuredJoin(e,t){let n={from:String(e??""),localField:String(t?.source??""),foreignField:String(t?.target??""),as:String(t?.as??""),single:t?.single};return Array.isArray(t?.where)&&(n.where=t.where),Array.isArray(t?.orderBy)&&(n.orderBy=t.orderBy),typeof t?.limit=="number"&&(n.limit=t.limit),typeof t?.offset=="number"&&(n.offset=t.offset),Array.isArray(t?.select)&&(n.select=t.select),Array.isArray(t?.joins)&&(n.joins=t.joins.map(i=>this.buildStructuredJoin(String(i?.collection??""),i))),n}cloneStructuredJoin(e){let t={...e};return Array.isArray(e.where)&&(t.where=e.where.map(n=>({...n}))),Array.isArray(e.orderBy)&&(t.orderBy=e.orderBy.map(n=>({...n}))),Array.isArray(e.select)&&(t.select=[...e.select]),Array.isArray(e.joins)&&(t.joins=e.joins.map(n=>this.cloneStructuredJoin(n))),t}appendNestedJoinByAlias(e,t,n){for(let i of e){if(i.as===t)return i.joins=[...i.joins??[],n],true;if(Array.isArray(i.joins)&&this.appendNestedJoinByAlias(i.joins,t,n))return true}return false}parseRelationRef(e){let n=String(e??"").trim().match(/^([A-Za-z0-9_.]+)\s*->\s*([A-Za-z0-9_]+)\.([A-Za-z0-9_.]+)(?:\s+as\s+([A-Za-z0-9_]+))?$/i);if(!n)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:n[1],collection:n[2],target:n[3],alias:n[4]}}join(e,t){let n=this.buildStructuredJoin(e,t);return this.clone({joins:[...this.sq.joins??[],n]})}joinNested(e,t,n){let i=String(e??"").trim();if(!i)throw new Error("joinNested requires parentAlias");let s=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(s.length===0)throw new Error(`joinNested parent alias "${i}" not found`);let o=this.buildStructuredJoin(t,n);if(!this.appendNestedJoinByAlias(s,i,o))throw new Error(`joinNested parent alias "${i}" not found`);return this.clone({joins:s})}Join(e,t){return this.join(e,t)}JoinNested(e,t,n){return this.joinNested(e,t,n)}withRelation(e,t={}){let n=this.parseRelationRef(e);return this.join(n.collection,{...t,source:n.source,target:n.target,as:t.as??n.alias??n.collection})}select(...e){return this.clone({select:e})}distinctField(e){return this.clone({distinctField:e})}vectorSearch(e){return this.clone({vectorSearch:e})}getRawQuery(){let e={...this.sq};return Array.isArray(this.sq.where)&&(e.where=this.sq.where.map(t=>({...t}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(t=>({...t}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(t=>({...t}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(t=>({...t}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(t=>this.cloneStructuredJoin(t))),this.sq.groupBy?.fields&&(e.groupBy={fields:[...this.sq.groupBy.fields]}),this.sq.startAt?.values&&(e.startAt={values:[...this.sq.startAt.values]}),this.sq.startAfter?.values&&(e.startAfter={values:[...this.sq.startAfter.values]}),this.sq.endAt?.values&&(e.endAt={values:[...this.sq.endAt.values]}),this.sq.endBefore?.values&&(e.endBefore={values:[...this.sq.endBefore.values]}),{collection:this.name,query:e}}async get(){let e=await G(this.cfg,this.name,this.sq);if(e)return A(this.cfg,this.name,e,this.sq)??[];let t=new URL(this.baseUrl);t.searchParams.set("query",JSON.stringify(this.sq)),t.searchParams.set("allowSensitiveAuthUserFields",this.opts.allowSensitiveAuthUserFields?"1":"0");let n;try{n=await fetch(t.toString(),{headers:this.headers});}catch(o){let a=o instanceof Error?o.message:String(o);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${a}`)}let i=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${n.status}): ${i.error??"Unknown error"}`);return A(this.cfg,this.name,i.data,this.sq)??[]}async first(){let e=await this.get();return e.length>0?e[0]:null}async last(){let e=await this.get();return e.length>0?e[e.length-1]:null}async add(e){let t=await K(this.cfg,this.name,e);if(t!==null)return new y(this.cfg,this.name,t);let n;try{n=await fetch(this.baseUrl,{method:"POST",headers:this.headers,body:JSON.stringify(e)});}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}): ${o}`)}let i=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] POST ${this.baseUrl} failed (HTTP ${n.status}): ${i.error??"Unknown error"}`);return new y(this.cfg,this.name,i.id)}async deleteMany(){let e=await X(this.cfg,this.name,this.sq.where??[]);if(e!==null)return e;let t;try{t=await fetch(this.baseUrl,{method:"DELETE",headers:this.headers,body:JSON.stringify({where:this.sq.where??[]})});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (DELETE ${this.baseUrl}): ${s}`)}let n=await t.json().catch(()=>({}));if(!t.ok)throw new Error(`[flare-admin] DELETE ${this.baseUrl} failed (HTTP ${t.status}): ${n.error??"Unknown error"}`);return n.deleted??0}doc(e){return new y(this.cfg,this.name,e)}};var C=class{constructor(e){this.cfg=e;}collection(e){return new b(this.cfg,e)}};var v=class{constructor(e){this.cfg=e;}async createCustomToken(e,t={}){if(g(this.cfg)){let a=await M(this.cfg,String(e),t);if(!a)throw new Error("[flare-admin][grpc] create_custom_token returned empty token");return a}let n=`${this.cfg.serverUrl.replace(/\/$/,"")}/admin/token`,i=JSON.stringify({appId:this.cfg.appId,uid:String(e),role:t.role??"user",claims:t.claims??{},ttl:t.ttl??this.cfg.defaultTtl}),s;try{s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`},body:i});}catch(a){let d=a instanceof Error?a.message:String(a);throw new Error(`[flare-admin] Could not reach FlareServer at "${n}": ${d}
3
- Make sure FLARE_URL is set correctly and the server is running.`)}let o;try{o=await s.json();}catch{throw new Error(`[flare-admin] Server returned non-JSON response (status ${s.status})`)}if(!s.ok)throw new Error(`[flare-admin] createCustomToken failed (HTTP ${s.status}): `+(o.error??"Unknown error"));if(typeof o.token!="string")throw new Error('[flare-admin] Server response missing "token" field');return o.token}async getTicket(e,t={}){if(g(this.cfg)){let d=await Q(this.cfg,String(e),t);if(!d)throw new Error("[flare-admin][grpc] create_auth_ticket returned empty payload");return d}let n=`${this.cfg.serverUrl.replace(/\/$/,"")}/admin/ticket`,i=JSON.stringify({appId:this.cfg.appId,uid:String(e),role:t.role??"user",email:t.email,sid:t.sid,tag:t.tag,ttlSeconds:t.ttlSeconds,ip:t.ip}),s;try{s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`},body:i});}catch(d){let c=d instanceof Error?d.message:String(d);throw new Error(`[flare-admin] Could not reach FlareServer at "${n}": ${c}
4
- Make sure FLARE_URL is set correctly and the server is running.`)}let o;try{o=await s.json();}catch{throw new Error(`[flare-admin] Server returned non-JSON response (status ${s.status})`)}if(!s.ok)throw new Error(`[flare-admin] getTicket failed (HTTP ${s.status}): `+(o.error??"Unknown error"));let a=o.ticket;if(!a||typeof a.ticket!="string")throw new Error('[flare-admin] Server response missing "ticket" object');return {ticket:String(a.ticket),tag:String(a.tag??""),uuid:String(a.uuid??""),expires_at:String(a.expires_at??""),one_time:!!(a.one_time??true),uid:String(a.uid??String(e)),role:String(a.role??t.role??"user"),ip:String(a.ip??"unknown")}}};var T=class{constructor(e){this.cfg=e;}get baseUrl(){return `${this.cfg.serverUrl.replace(/\/$/,"")}/admin/notify/${this.cfg.appId}`}get headers(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`}}async send(e){let t;try{t=await fetch(`${this.baseUrl}/send`,{method:"POST",headers:this.headers,body:JSON.stringify(e??{})});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}/send): ${s}`)}let n=await t.json().catch(()=>({}));if(!t.ok)throw new Error(`[flare-admin] Notification send failed (HTTP ${t.status}): `+(n.error??"Unknown error"));return {sent:!!n.sent,appId:String(n.appId??this.cfg.appId),targetCount:Number(n.targetCount??0),successCount:Number(n.successCount??0),failureCount:Number(n.failureCount??0),invalidatedTokenCount:Number(n.invalidatedTokenCount??0),dryRun:!!n.dryRun}}async tokens(){let e;try{e=await fetch(`${this.baseUrl}/tokens`,{method:"GET",headers:this.headers});}catch(n){let i=n instanceof Error?n.message:String(n);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}/tokens): ${i}`)}let t=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] Tokens fetch failed (HTTP ${e.status}): `+(t.error??"Unknown error"));return {appId:String(t.appId??this.cfg.appId),hasPushGateway:!!t.hasPushGateway,total:Number(t.total??0),tokens:Array.isArray(t.tokens)?t.tokens:[]}}};var E=class{constructor(e){this.cfg=e;}base(e){return `${this.cfg.serverUrl.replace(/\/$/,"")}/admin/storage/${encodeURIComponent(this.cfg.appId)}${e}`}get headers(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`}}async jsonRequest(e,t,n){let i,s=this.base(t);try{i=await fetch(s,{method:e,headers:this.headers,...n!==void 0?{body:JSON.stringify(n)}:{}});}catch(a){let d=a instanceof Error?a.message:String(a);throw new Error(`[flare-admin] Network error (${e} ${s}): ${d}`)}let o=await i.json().catch(()=>({}));if(!i.ok)throw new Error(`[flare-admin] ${e} ${s} failed (HTTP ${i.status}): `+(o.error??"Unknown error"));return o}async request(e,t,n){return this.jsonRequest(e,t,n)}async servers(){let e=await this.jsonRequest("GET","/servers");return Array.isArray(e.servers)?e.servers:[]}async createServer(e){let t=await this.jsonRequest("POST","/servers",e??{});return {ok:!!(t.ok??true),serverId:String(t.serverId??"")}}async patchServer(e,t){let n=String(e??"").trim();if(!n)throw new Error("storage server id is required");let i=await this.jsonRequest("POST",`/servers/${encodeURIComponent(n)}`,t??{});return {ok:!!(i.ok??true),serverId:String(i.serverId??n)}}async deleteServer(e){let t=String(e??"").trim();if(!t)throw new Error("storage server id is required");let n=await this.jsonRequest("DELETE",`/servers/${encodeURIComponent(t)}`);return {ok:!!(n.ok??true),serverId:String(n.serverId??t),removedObjects:Number(n.removedObjects??0)}}async awsConfig(e){let t=String(e??"").trim();if(!t)throw new Error("storage server id is required");return (await this.jsonRequest("GET",`/servers/${encodeURIComponent(t)}/aws`)).aws??{}}async uploadObject(e){return await this.jsonRequest("POST","/object/upload",e??{})}async downloadObject(e){return await this.jsonRequest("POST","/object/download",e??{})}async deleteObject(e){return await this.jsonRequest("POST","/object/delete",e??{})}async createSignedUrl(e){return await this.jsonRequest("POST","/signed-url",e??{})}async setRules(e){let t=await this.jsonRequest("POST","/rules",{...e?.rules?{rules:e.rules}:{},...typeof e?.rulesDsl=="string"?{rulesDsl:e.rulesDsl}:{},...e?.rulesHistoryPolicy?{rulesHistoryPolicy:e.rulesHistoryPolicy}:{}});return {id:String(t.id??this.cfg.appId)}}async validateRules(e){let t=await this.jsonRequest("POST","/rules/validate",{rulesDsl:e});return {valid:!!t.valid,diagnostics:Array.isArray(t.diagnostics)?t.diagnostics:[],rulesCount:Number(t.rulesCount??0)}}async rulesHistory(){let e=await this.jsonRequest("GET","/rules/history");return {history:Array.isArray(e.history)?e.history:[],policy:e.policy??{maxEntries:30,maxAgeDays:365},restoreEvents:Array.isArray(e.restoreEvents)?e.restoreEvents:[]}}async restoreRules(e){let t=String(e??"").trim();if(!t)throw new Error("historyId is required");let n=await this.jsonRequest("POST","/rules/restore",{historyId:t});return {id:String(n.id??this.cfg.appId),rulesText:String(n.rulesText??"")}}};function J(r){if(typeof Buffer<"u")return Buffer.from(r).toString("base64");let e="";for(let t=0;t<r.length;t++)e+=String.fromCharCode(r[t]);return btoa(e)}async function ae(r){return r===void 0?"":typeof r=="string"?J(new TextEncoder().encode(r)):Buffer&&Buffer.isBuffer(r)?r.toString("base64"):r instanceof Uint8Array?J(r):r instanceof ArrayBuffer?J(new Uint8Array(r)):""}function ce(r){return Buffer?Buffer.from(String(r)).toString("base64"):btoa(String(r))}function de(r){try{let e=Buffer?Buffer.from(r,"base64").toString():atob(r),t=parseInt(e,10);return isNaN(t)?0:t}catch{return 0}}function le(r){return (String(r??"").split("/").pop()??"download").replace(/["\\\r\n]/g,"")||"download"}var R=class{constructor(e){this._bucketCache=new Map;this._bucketListLoaded=false;this._bucketListPromise=null;this._svc=e;}async _ensureBuckets(){if(!this._bucketListLoaded)return this._bucketListPromise||(this._bucketListPromise=this._loadBuckets().then(()=>{this._bucketListLoaded=true;}).catch(e=>{throw this._bucketListPromise=null,e}).finally(()=>{this._bucketListPromise=null;})),this._bucketListPromise}async _loadBuckets(){let e=await this.listBuckets();for(let t of e)this._bucketCache.set(t.bucket,t.id);}_invalidateCache(){this._bucketCache.clear(),this._bucketListLoaded=false,this._bucketListPromise=null;}async _resolveBucketId(e,t){let n=this._bucketCache.get(e);if(n)return n;await this._ensureBuckets();let i=this._bucketCache.get(e);if(i)return i;if(t)return (await this.createBucket(e)).id;throw new Error(`Bucket "${e}" not found. Create it first with createBucket("${e}").`)}async createBucket(e,t={}){let n=e.trim();if(!n)throw new Error("bucket name is required");await this._ensureBuckets();let i=this._bucketCache.get(n);if(i){let d=(await this.listBuckets()).find(c=>c.id===i);if(d)return d}let s;try{s=await this._svc.createServer({name:n,kind:t.kind??"managed",bucket:n,prefix:t.prefix,region:t.region,endpoint:t.endpoint,accessKey:t.accessKey,secretKey:t.secretKey,dataDir:t.dataDir,forcePathStyle:t.forcePathStyle});}catch(a){if((a instanceof Error?a.message:String(a)).includes("bucket_conflict")){this._invalidateCache(),await this._ensureBuckets();let c=this._bucketCache.get(n);if(c){let p=(await this.listBuckets()).find(q=>q.id===c);if(p)return p}}throw a}let o={id:s.serverId,name:n,bucket:n,kind:t.kind??"managed",prefix:t.prefix};return this._bucketCache.set(n,o.id),o}async listBuckets(){let t=(await this._svc.servers()).map(n=>({id:n.id,name:n.name,bucket:n.bucket,kind:n.kind,region:n.region,endpoint:n.endpoint,prefix:n.prefix,frozen:n.frozen,readOnly:n.readOnly,createdAt:n.createdAt,updatedAt:n.updatedAt}));this._bucketCache.clear();for(let n of t)this._bucketCache.set(n.bucket,n.id);return this._bucketListLoaded=true,t}async deleteBucket(e){let t=await this._resolveBucketId(e,false),n=await this._svc.deleteServer(t);return this._bucketCache.delete(e),{ok:n.ok,removedObjects:n.removedObjects}}async deleteBuckets(e){let t=[],n={};return await Promise.all(e.map(async i=>{try{await this.deleteBucket(i),t.push(i);}catch(s){n[i]=s instanceof Error?s.message:String(s);}})),{ok:Object.keys(n).length===0,deleted:t,errors:n}}async getBucketLocation(e){let n=(await this.listBuckets()).find(i=>i.bucket===e||i.name===e);if(!n)throw new Error(`Bucket "${e}" not found`);return {bucket:n.bucket,kind:n.kind,region:n.region,endpoint:n.endpoint}}async putObject(e){let t=await this._resolveBucketId(e.bucket,true);if(e.contentBase64!==void 0){let c=await this._svc.uploadObject({serverId:t,path:e.key,contentBase64:e.contentBase64,contentType:e.contentType,encrypt:e.encrypt});return {ok:c.ok,bucket:e.bucket,key:String(c.path??e.key),size:Number(c.size??0),encrypted:!!c.encrypted}}let n=4*1024*1024,i=e.base64MaxBytes??n,s;if(typeof e.body=="string"?s=new TextEncoder().encode(e.body).length:(e.body instanceof Uint8Array||e.body instanceof ArrayBuffer||Buffer&&Buffer.isBuffer(e.body))&&(s=e.body.byteLength),s!==void 0&&s>i){let c=await this.createSignedUrl({bucket:e.bucket,key:e.key,action:"upload",expiresInSeconds:300,sizeBytes:s,contentType:e.contentType,encrypt:e.encrypt}),u;typeof e.body=="string"?u=new TextEncoder().encode(e.body):u=e.body;let p=await fetch(c.url,{method:c.method??"PUT",headers:{...e.contentType?{"Content-Type":e.contentType}:{}},body:u});if(!p.ok){let q=await p.text().catch(()=>"");throw new Error(`[flare-admin] Signed-URL upload failed (HTTP ${p.status}): ${q}`)}return {ok:true,bucket:e.bucket,key:e.key,size:s??0,encrypted:!!(e.encrypt??true)}}let a=await ae(e.body),d=await this._svc.uploadObject({serverId:t,path:e.key,contentBase64:a,contentType:e.contentType,encrypt:e.encrypt});return {ok:d.ok,bucket:e.bucket,key:String(d.path??e.key),size:Number(d.size??0),encrypted:!!d.encrypted}}async getObject(e){let t=await this._resolveBucketId(e.bucket,false),n=await this._svc.downloadObject({serverId:t,path:e.key,decrypt:e.decrypt});return {ok:n.ok,bucket:e.bucket,key:String(n.path??e.key),contentBase64:String(n.contentBase64??""),contentType:String(n.contentType??"application/octet-stream"),size:Number(n.size??0),encrypted:!!n.encrypted}}async getObjectUrl(e){return (await this.createSignedUrl({bucket:e.bucket,key:e.key,action:"download",decrypt:e.decrypt,expiresInSeconds:e.expiresInSeconds,forceDownload:e.forceDownload,allowedOrigins:e.allowedOrigins,embedOnly:e.embedOnly})).url}async downloadObject(e){let t=e.forceDownload??true,n=await this.getObjectUrl({...e,forceDownload:t}),i=e.filename??le(e.key),s=globalThis.document;if(!s)return {ok:true,url:n,filename:i,triggered:false};let o=s.createElement("a");return o.href=n,e.openInNewTab?o.target="_blank":o.download=i,o.rel="noopener noreferrer",s.body?.appendChild(o),o.click(),o.remove(),{ok:true,url:n,filename:i,triggered:true}}async headObject(e){let t=await this._resolveBucketId(e.bucket,false),n=await this._svc.request("POST","/object/head",{serverId:t,path:e.key});return {bucket:e.bucket,key:String(n.path??e.key),size:Number(n.size??0),contentType:String(n.contentType??"application/octet-stream"),encrypted:!!n.encrypted,createdAt:n.createdAt,updatedAt:n.updatedAt}}async headObjects(e){return Promise.all(e.keys.map(t=>this.headObject({bucket:e.bucket,key:t})))}async listObjects(e){let t=await this._resolveBucketId(e.bucket,false),n=e.cursor?de(e.cursor):0,i=Math.max(1,Math.min(e.limit??100,1e3)),s=await this._svc.request("POST","/object/list",{serverId:t,prefix:e.prefix,limit:i,skip:n}),o=Array.isArray(s.objects)?s.objects:[],a=!!s.hasMore,d=Number(s.count??o.length);return {bucket:e.bucket,objects:o.map(c=>({bucket:e.bucket,key:String(c.path??c.key??""),size:Number(c.size??0),contentType:String(c.contentType??"application/octet-stream"),encrypted:!!c.encrypted,createdAt:c.createdAt,updatedAt:c.updatedAt})),count:d,hasMore:a,cursor:a?ce(n+o.length):void 0}}async copyObject(e){let[t,n]=await Promise.all([this._resolveBucketId(e.sourceBucket,false),this._resolveBucketId(e.destBucket,true)]);return {ok:!!((await this._svc.request("POST","/object/copy",{serverId:t,path:e.sourceKey,destServerId:n,destPath:e.destKey})).ok??true)}}async copyObjects(e){let t={};return await Promise.all(e.map(async n=>{try{await this.copyObject(n);}catch(i){t[`${n.sourceBucket}/${n.sourceKey}`]=i instanceof Error?i.message:String(i);}})),{ok:Object.keys(t).length===0,errors:t}}async deleteObject(e){return this._svc.deleteObject(e)}async deleteObjects(e){let t=await this._resolveBucketId(e.bucket,false),n=await this._svc.request("POST","/object/delete-many",{serverId:t,paths:e.keys});return {ok:!!(n.ok??true),deleted:Array.isArray(n.deleted)?n.deleted:e.keys,errors:n.errors??{}}}async createSignedUrl(e){let t=await this._resolveBucketId(e.bucket,false);return await this._svc.request("POST","/signed-url",{serverId:t,path:e.key,action:e.action,expiresInSeconds:e.expiresInSeconds,sizeBytes:e.sizeBytes,contentType:e.contentType,encrypt:e.encrypt,decrypt:e.decrypt,forceDownload:e.forceDownload,allowedOrigins:e.allowedOrigins,embedOnly:e.embedOnly})}};var O=class{constructor(e){this.cfg=e;this.ws=null;this.pendingAcks=new Map;this.subscriptions=new Map;this.activeSubscriptions=new Map;this.subscriptionErrorHandlers=new Map;this.subscriptionPermissionHandlers=new Map;this.subscriptionLastErrors=new Map;this.connected=false;this.shouldReconnect=true;this.reconnectDelay=2e3;let t=e.serverUrl.replace(/^http/,"ws");this.wsUrl=`${t}/?appId=${encodeURIComponent(e.appId)}&adminKey=${encodeURIComponent(e.adminKey)}`,this._readyPromise=new Promise(n=>{this._readyResolve=n;}),this._connect();}ready(){return this._readyPromise}disconnect(){this.shouldReconnect=false,this.ws?.close(1e3,"Admin disconnect"),this.ws=null,this.connected=false;}send(e,t){return new Promise((n,i)=>{let s=U(),o={id:s,type:e,ts:Date.now(),...t},a=setTimeout(()=>{this.pendingAcks.delete(s),i(new Error(`[flare-admin] WS request timeout (${e})`));},1e4);this.pendingAcks.set(s,c=>{clearTimeout(a),c.type==="error"?i(new Error(`[flare-admin] Server error: ${c.message}`)):n(c);});let d=()=>this.ws?.send(JSON.stringify(o));this.connected&&this.ws?.readyState===Y__default.default.OPEN?d():this.ready().then(d).catch(i);})}subscribe(e,t,n,i,s={}){let o=U(),a={baseId:o,liveId:o,collection:e,docId:t,structuredQuery:n,callback:i,options:s};this.activeSubscriptions.set(o,a),this.subscriptionErrorHandlers.set(o,new Set),this.subscriptionPermissionHandlers.set(o,new Set),this.activateSubscription(a);let d=()=>{let p=this.activeSubscriptions.get(o)?.liveId??o;this.activeSubscriptions.delete(o),this.subscriptions.delete(o),this.subscriptions.delete(p),this.subscriptionErrorHandlers.delete(o),this.subscriptionPermissionHandlers.delete(o),this.subscriptionLastErrors.delete(o),this.connected&&this.send("unsubscribe",{subscriptionId:p}).catch(()=>{});},c=d;return c.unsubscribe=d,c.onError=u=>{this.subscriptionErrorHandlers.get(o)?.add(u);let p=this.subscriptionLastErrors.get(o);if(p)try{u(p);}catch{}return c},c.onPermissionDenied=u=>{this.subscriptionPermissionHandlers.get(o)?.add(u);let p=this.subscriptionLastErrors.get(o);if(p?.permissionDenied)try{u(p);}catch{}return c},c.catch=u=>c.onError(u),c}activateSubscription(e){let t=()=>{this.subscriptions.set(e.liveId,e.callback);let n={collection:e.collection};e.docId&&(n.docId=e.docId),e.structuredQuery&&(n.query=e.structuredQuery),e.options.skipSnapshot&&(n.skipSnapshot=true),this.send("subscribe",n).then(i=>{let s=i.subscriptionId;if(s&&s!==e.liveId){let o=this.subscriptions.get(e.liveId);o&&(this.subscriptions.delete(e.liveId),this.subscriptions.set(s,o),e.liveId=s);}}).catch(()=>{this.subscriptions.delete(e.liveId),this.emitSubscriptionError(e.baseId,this.toSubscriptionError(new Error("Subscribe failed")));});};this.connected?t():this.ready().then(t).catch(n=>{this.emitSubscriptionError(e.baseId,this.toSubscriptionError(n));});}async replayActiveSubscriptions(){if(!this.connected)return;let e=Array.from(this.activeSubscriptions.values());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&&n!==t.baseId&&await this.send("unsubscribe",{subscriptionId:n}).catch(()=>{}),this.activateSubscription(t);}}toSubscriptionError(e){let t=e instanceof Error?e.message:String(e??"Unknown subscription error"),n=t.match(/^\[([^\]]+)\]\s*(.*)$/),i=n?.[1],s=(n?.[2]??t).trim()||t,o=i==="PERMISSION_DENIED"||t.includes("PERMISSION_DENIED");return {code:i,message:s,permissionDenied:o,raw:e}}emitSubscriptionError(e,t){this.subscriptionLastErrors.set(e,t);let n=this.subscriptionErrorHandlers.get(e);if(n)for(let i of n)try{i(t);}catch{}if(t.permissionDenied){let i=this.subscriptionPermissionHandlers.get(e);if(i)for(let s of i)try{s(t);}catch{}}}_connect(){this._readyPromise=new Promise(e=>{this._readyResolve=e;}),this.ws=new Y__default.default(this.wsUrl),this.ws.on("message",e=>{let t;try{t=JSON.parse(e.toString());}catch{return}this._handle(t);}),this.ws.on("close",e=>{this.connected=false,this.shouldReconnect&&e!==1e3&&setTimeout(()=>{this.reconnectDelay=Math.min(this.reconnectDelay*2,3e4),this._connect();},this.reconnectDelay);}),this.ws.on("error",()=>{});}_handle(e){let t=e.type;if(t==="auth_ok"){this.connected||(this.connected=true,this.reconnectDelay=2e3,this._readyResolve(),this.replayActiveSubscriptions().catch(()=>{}));return}if(t==="ack"||t==="pong"||t==="call_response"){let n=e.correlationId??e.id,i=this.pendingAcks.get(n);i&&(i(e),this.pendingAcks.delete(n));return}if(t==="error"){let n=e.correlationId;if(n){let i=this.pendingAcks.get(n);i&&(i(e),this.pendingAcks.delete(n));let s=Array.from(this.activeSubscriptions.values()).find(o=>o.liveId===n||o.baseId===n);if(s){let o=this.toSubscriptionError(new Error(`[${String(e.code??"ERROR")}] ${String(e.message??"Unknown error")}`));this.emitSubscriptionError(s.baseId,o);}}return}if(t==="snapshot"||t==="change"){let n=e.subscriptionId,i=this.subscriptions.get(n);if(i){let s=Array.from(this.activeSubscriptions.values()).find(d=>d.liveId===n),o=String(e.collection??s?.collection??""),a=t==="change"&&e.operation==="delete"?null:A(this.cfg,o,e.data,s?.structuredQuery);i({subscriptionId:n,collection:o,docId:e.docId,data:a,type:t==="snapshot"?"snapshot":"change",operation:e.operation});}}}};var j=class{constructor(e,t,n){this.conn=e;this.collection=t;this.id=n;}onSnapshot(e){let t=()=>{};return t=this.conn.subscribe(this.collection,this.id,void 0,n=>{n.type==="snapshot"&&(e(n),t());}),t}};var I=class r{constructor(e,t){this.conn=e;this.name=t;this.sq={};}clone(e){let t=new r(this.conn,this.name);return t.sq={...this.sq,...e},t}normalizeFilterValue(e,t){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(t)?t:[t]:t}toQueryFilters(e){return B(e).map(n=>typeof n=="object"&&n!=null&&"field"in n&&"op"in n?{...n,value:this.normalizeFilterValue(n.op,n.value)}:n)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let t=[...this.sq.where??[]];if(t.length===0)return this.clone({where:[{or:e}]});let n=t[0];if(t.length===1&&typeof n=="object"&&n!=null&&"or"in n)return this.clone({where:[{or:[...n.or,...e]}]});let s=t.length===1?t[0]:{and:t};return this.clone({where:[{or:[s,...e]}]})}appendFilters(e,t){return t==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,t,n,i){return this.appendFilters([{field:e,op:t,value:this.normalizeFilterValue(t,n)}],i)}where(e){return this.appendFilters(this.toQueryFilters(e),"and")}and(e){return this.appendFilters(this.toQueryFilters(e),"and")}or(e){return this.appendFilters(this.toQueryFilters(e),"or")}in(e,t){return this.appendOperatorFilter(e,"in",t,"and")}andIn(e,t){return this.appendOperatorFilter(e,"in",t,"and")}orIn(e,t){return this.appendOperatorFilter(e,"in",t,"or")}notIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"and")}andNotIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"and")}orNotIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"or")}arrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"and")}andArrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"and")}orArrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"or")}arrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"and")}andArrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"and")}orArrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"or")}some(e,t){return this.appendOperatorFilter(e,"elem-match",t,"and")}andSome(e,t){return this.appendOperatorFilter(e,"elem-match",t,"and")}orSome(e,t){return this.appendOperatorFilter(e,"elem-match",t,"or")}like(e,t){return this.appendOperatorFilter(e,"like",t,"and")}andLike(e,t){return this.appendOperatorFilter(e,"like",t,"and")}orLike(e,t){return this.appendOperatorFilter(e,"like",t,"or")}notLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"and")}andNotLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"and")}orNotLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"or")}exists(e){return this.appendOperatorFilter(e,"exists",true,"and")}andExists(e){return this.appendOperatorFilter(e,"exists",true,"and")}orExists(e){return this.appendOperatorFilter(e,"exists",true,"or")}notExists(e){return this.appendOperatorFilter(e,"not-exists",true,"and")}andNotExists(e){return this.appendOperatorFilter(e,"not-exists",true,"and")}orNotExists(e){return this.appendOperatorFilter(e,"not-exists",true,"or")}latest(){return this.clone({orderBy:[...this.sq.orderBy??[],{field:"_seq",dir:"desc"}]})}newest(){return this.latest()}oldest(){return this.clone({orderBy:[...this.sq.orderBy??[],{field:"_seq",dir:"asc"}]})}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}]})}buildStructuredJoin(e,t){let n={from:String(e??""),localField:String(t?.source??""),foreignField:String(t?.target??""),as:String(t?.as??""),single:t?.single};return Array.isArray(t?.where)&&(n.where=t.where),Array.isArray(t?.orderBy)&&(n.orderBy=t.orderBy),typeof t?.limit=="number"&&(n.limit=t.limit),typeof t?.offset=="number"&&(n.offset=t.offset),Array.isArray(t?.select)&&(n.select=t.select),Array.isArray(t?.joins)&&(n.joins=t.joins.map(i=>this.buildStructuredJoin(String(i?.collection??""),i))),n}cloneStructuredJoin(e){let t={...e};return Array.isArray(e.where)&&(t.where=e.where.map(n=>({...n}))),Array.isArray(e.orderBy)&&(t.orderBy=e.orderBy.map(n=>({...n}))),Array.isArray(e.select)&&(t.select=[...e.select]),Array.isArray(e.joins)&&(t.joins=e.joins.map(n=>this.cloneStructuredJoin(n))),t}appendNestedJoinByAlias(e,t,n){for(let i of e){if(i.as===t)return i.joins=[...i.joins??[],n],true;if(Array.isArray(i.joins)&&this.appendNestedJoinByAlias(i.joins,t,n))return true}return false}parseRelationRef(e){let n=String(e??"").trim().match(/^([A-Za-z0-9_.]+)\s*->\s*([A-Za-z0-9_]+)\.([A-Za-z0-9_.]+)(?:\s+as\s+([A-Za-z0-9_]+))?$/i);if(!n)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:n[1],collection:n[2],target:n[3],alias:n[4]}}join(e,t){let n=this.buildStructuredJoin(e,t);return this.clone({joins:[...this.sq.joins??[],n]})}joinNested(e,t,n){let i=String(e??"").trim();if(!i)throw new Error("joinNested requires parentAlias");let s=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(s.length===0)throw new Error(`joinNested parent alias "${i}" not found`);let o=this.buildStructuredJoin(t,n);if(!this.appendNestedJoinByAlias(s,i,o))throw new Error(`joinNested parent alias "${i}" not found`);return this.clone({joins:s})}Join(e,t){return this.join(e,t)}JoinNested(e,t,n){return this.joinNested(e,t,n)}withRelation(e,t={}){let n=this.parseRelationRef(e);return this.join(n.collection,{...t,source:n.source,target:n.target,as:t.as??n.alias??n.collection})}select(...e){return this.clone({select:e})}distinctField(e){return this.clone({distinctField:e})}vectorSearch(e){return this.clone({vectorSearch:e})}doc(e){return new j(this.conn,this.name,e)}getRawQuery(){let e={...this.sq};return Array.isArray(this.sq.where)&&(e.where=this.sq.where.map(t=>({...t}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(t=>({...t}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(t=>({...t}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(t=>({...t}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(t=>this.cloneStructuredJoin(t))),this.sq.groupBy?.fields&&(e.groupBy={fields:[...this.sq.groupBy.fields]}),this.sq.startAt?.values&&(e.startAt={values:[...this.sq.startAt.values]}),this.sq.startAfter?.values&&(e.startAfter={values:[...this.sq.startAfter.values]}),this.sq.endAt?.values&&(e.endAt={values:[...this.sq.endAt.values]}),this.sq.endBefore?.values&&(e.endBefore={values:[...this.sq.endBefore.values]}),{collection:this.name,query:e}}onSnapshot(e){let t=this._buildSq(),n=()=>{};return n=this.conn.subscribe(this.name,void 0,t,i=>{i.type==="snapshot"&&(e(i),n());}),n}onDocAdded(e){let t=this._buildSq();return this.conn.subscribe(this.name,void 0,t,n=>{n.type==="change"&&n.operation==="insert"&&n.data!=null&&e(n.data,n.docId);},{skipSnapshot:true})}onDocUpdated(e){let t=this._buildSq();return this.conn.subscribe(this.name,void 0,t,n=>{n.type==="change"&&(n.operation==="update"||n.operation==="replace")&&n.data!=null&&e(n.data,n.docId);},{skipSnapshot:true})}onDocDeleted(e){let t=this._buildSq();return this.conn.subscribe(this.name,void 0,t,n=>{n.type==="change"&&n.operation==="delete"&&e(n.docId);},{skipSnapshot:true})}onDocChanged(e){let t=this._buildSq();return this.conn.subscribe(this.name,void 0,t,n=>{n.type==="change"&&e(n.data??null,n.docId,n.operation);},{skipSnapshot:true})}_buildSq(){let e={};return this.sq.where&&this.sq.where.length>0&&(e.where=this.sq.where),this.sq.orderBy&&this.sq.orderBy.length>0&&(e.orderBy=this.sq.orderBy),this.sq.limit!==void 0&&(e.limit=this.sq.limit),this.sq.offset!==void 0&&(e.offset=this.sq.offset),this.sq.startAt&&(e.startAt=this.sq.startAt),this.sq.startAfter&&(e.startAfter=this.sq.startAfter),this.sq.endAt&&(e.endAt=this.sq.endAt),this.sq.endBefore&&(e.endBefore=this.sq.endBefore),this.sq.aggregate&&this.sq.aggregate.length>0&&(e.aggregate=this.sq.aggregate),this.sq.groupBy&&(e.groupBy=this.sq.groupBy),this.sq.having&&this.sq.having.length>0&&(e.having=this.sq.having),this.sq.joins&&this.sq.joins.length>0&&(e.joins=this.sq.joins),this.sq.vectorSearch&&(e.vectorSearch=this.sq.vectorSearch),this.sq.select&&this.sq.select.length>0&&(e.select=this.sq.select),this.sq.distinctField&&(e.distinctField=this.sq.distinctField),e}};var F=class{constructor(e){this._ws=new O(e);}collection(e){return new I(this._ws,e)}ready(){return this._ws.ready()}disconnect(){this._ws.disconnect();}};var _t="ServerTimeStamp",qt={$serverTimestamp:true};var N=class{constructor(e){this.cfg={defaultTtl:"24h",transport:"auto",...e,serverUrl:e.serverUrl.replace(/\/$/,""),grpcUrl:e.grpcUrl??"",dataMapper:e.dataMapper??{}};}auth(){return this._auth??(this._auth=new v(this.cfg))}db(){return this._db??(this._db=new C(this.cfg))}connection(){return this._conn??(this._conn=new F(this.cfg))}notifications(){return this._notifications??(this._notifications=new T(this.cfg))}storageService(){return this._storage??(this._storage=new E(this.cfg))}storage(){return this._storageS3||(this._storageS3=new R(this.storageService())),this._storageS3}s3(){return this.storage()}async createSignedUrl(e){return await this.s3().createSignedUrl(e)}createBucket(e,t){return this.s3().createBucket(e,t)}listBuckets(){return this.s3().listBuckets()}deleteBucket(e){return this.s3().deleteBucket(e)}deleteBuckets(e){return this.s3().deleteBuckets(e)}getBucketLocation(e){return this.s3().getBucketLocation(e)}putObject(e){return this.s3().putObject(e)}getObject(e){return this.s3().getObject(e)}getObjectUrl(e){return this.s3().getObjectUrl(e)}downloadObject(e){return this.s3().downloadObject(e)}headObject(e){return this.s3().headObject(e)}headObjects(e){return this.s3().headObjects(e)}listObjects(e){return this.s3().listObjects(e)}copyObject(e){return this.s3().copyObject(e)}copyObjects(e){return this.s3().copyObjects(e)}deleteObjects(e){return this.s3().deleteObjects(e)}},_=new Map;function Gt(r,e="[DEFAULT]"){if(_.has(e))return _.get(e);let t=new N(r);return _.set(e,t),t}function P(r="[DEFAULT]"){let e=_.get(r);if(!e)throw new Error(`[flare-admin] No app named "${r}" found. Call connectApp() before getApp().`);return e}function Mt(r="[DEFAULT]"){return P(r).auth()}function Qt(r="[DEFAULT]"){return P(r).db()}function zt(r="[DEFAULT]"){return P(r).connection()}function Kt(r="[DEFAULT]"){return P(r).notifications()}function Wt(r="[DEFAULT]"){return P(r).storage()}exports.AdminCollectionReference=b;exports.AdminDocumentReference=y;exports.AdminLiveCollectionReference=I;exports.AdminLiveDocumentReference=j;exports.AdminStorageSignedAction=D;exports.FlareAdminApp=N;exports.FlareAdminAuthService=v;exports.FlareAdminConnection=F;exports.FlareAdminDbService=C;exports.FlareAdminNotificationsService=T;exports.FlareAdminStorageS3=R;exports.FlareAdminWsConnection=O;exports.ServerTimeStamp=_t;exports.ServerTimeStampField=qt;exports.auth=Mt;exports.connectApp=Gt;exports.connection=zt;exports.db=Qt;exports.getApp=P;exports.notifications=Kt;exports.storage=Wt;
1
+ 'use strict';var ve=require('fs'),O=require('path'),url=require('url'),ye=require('ws');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var ve__default=/*#__PURE__*/_interopDefault(ve);var O__default=/*#__PURE__*/_interopDefault(O);var ye__default=/*#__PURE__*/_interopDefault(ye);/* @zuzjs/flare-admin */
2
+ var ke=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,m=ke();var V=(i=>(i.Upload="upload",i.Download="download",i.Delete="delete",i.Edit="edit",i))(V||{});function M(r){let e=[];for(let[t,n]of Object.entries(r))if(typeof n=="string"){let i=n.match(/^(>=|<=|!=|>|<|==)\s*(.+)$/);if(i){let[,s,o]=i;e.push({field:t,op:s,value:we(o.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 we(r){return isNaN(Number(r))?r==="true"?true:r==="false"?false:r==="null"?null:r:Number(r)}function Z(){return Math.random().toString(36).slice(2,12)+Date.now().toString(36)}function Ce(r,e){let t=r.dataMapper;if(!t||typeof t!="object")return null;let n=t[e];return typeof n=="function"?n:null}function X(r,e,t){let n=Ce(r,e);if(!n||t==null||typeof t!="object")return t;try{return n(t)}catch{return t}}function Y(r,e,t){if(!e||typeof e!="object"||!Array.isArray(t)||t.length===0)return e;let n=e;for(let i of t){let s=String(i?.as??"").trim();if(!s)continue;let o=Array.isArray(i?.joins)?i.joins:[],a=n[s],d=a;Array.isArray(a)?d=a.map(c=>Y(r,c,o)):a&&typeof a=="object"&&(d=Y(r,a,o)),d=Array.isArray(d)?d.map(c=>X(r,s,c)):X(r,s,d),d!==a&&(n===e&&(n={...n}),n[s]=d);}return n}function C(r,e,t,n){let i=Array.isArray(n?.joins)?n.joins:[],s=o=>{let a=Y(r,o,i);return X(r,e,a)};return Array.isArray(t)?t.map(o=>s(o)):s(t)}var Re=()=>typeof process<"u"&&!!process.versions?.node,h=r=>{if(r.transport==="http")return false;let e=!!(r.grpcUrl&&r.grpcUrl.trim().length>0),t=Re();if(r.transport==="grpc"){if(!e)throw new Error("[flare-admin][grpc] transport=grpc requires grpcUrl");if(!t)throw new Error("[flare-admin][grpc] transport=grpc requires Node.js runtime");return true}return e&&t},I=r=>{try{return JSON.stringify(r??{})}catch{return "{}"}},P=r=>r?.field&&r?.op?{queryFilter:{field:String(r.field),op:String(r.op),valueJson:I(r.value)}}:Array.isArray(r?.or)?{orFilter:{or:r.or.map(e=>P(e))}}:Array.isArray(r?.and)?{andFilter:{and:r.and.map(e=>P(e))}}:{queryFilter:{field:"",op:"==",valueJson:"null"}},G=r=>{if(!(!r||!Array.isArray(r.values)))return {valuesJson:r.values.map(e=>I(e))}},ae=r=>({from:r.from,localField:r.localField,foreignField:r.foreignField,as:r.as,single:!!r.single,where:Array.isArray(r.where)?r.where.map(P):[],orderBy:Array.isArray(r.orderBy)?r.orderBy.map(e=>({field:e.field,dir:e.dir??"asc"})):[],limit:r.limit??0,offset:r.offset??0,select:Array.isArray(r.select)?r.select:[],joins:Array.isArray(r.joins)?r.joins.map(ae):[]}),Oe=r=>({where:Array.isArray(r.where)?r.where.map(P):[],orderBy:Array.isArray(r.orderBy)?r.orderBy.map(e=>({field:e.field,dir:e.dir??"asc"})):[],limit:r.limit??0,offset:r.offset??0,startAt:G(r.startAt),startAfter:G(r.startAfter),endAt:G(r.endAt),endBefore:G(r.endBefore),aggregate:Array.isArray(r.aggregate)?r.aggregate.map(e=>({fn:e.fn,field:e.field??"",alias:e.alias??""})):[],groupBy:r.groupBy?{fields:r.groupBy.fields??[]}:void 0,having:Array.isArray(r.having)?r.having.map(e=>({field:e.field,op:e.op,value:e.value})):[],joins:Array.isArray(r.joins)?r.joins.map(ae):[],select:Array.isArray(r.select)?r.select:[],distinctField:r.distinctField??""});async function b(r){let e=await import('@grpc/grpc-js'),t=await import('@grpc/proto-loader'),n=O__default.default.dirname(url.fileURLToPath(m)),i=[O__default.default.resolve(n,"../../proto"),O__default.default.resolve(n,"../proto"),O__default.default.resolve(process.cwd(),"proto")],s=i.find(p=>ve__default.default.existsSync(O__default.default.join(p,"flare.proto")))??i[0],o=O__default.default.join(s,"flare.proto"),a=await t.load(o,{keepCase:false,longs:String,enums:String,defaults:true,oneofs:true,includeDirs:[s]}),c=e.loadPackageDefinition(a).flare;return new c.AdminService(r,e.credentials.createInsecure())}function S(r,e,t){return new Promise((n,i)=>{r[e](t,(s,o)=>{if(s)return i(s);n(o??{});});})}function k(r,e){if(r.error)throw new Error(`[flare-admin][grpc] ${e} failed: ${r.errorDescription||r.error}`)}async function ce(r,e,t){if(!h(r))return null;let n=await b(r.grpcUrl),i=await S(n,"AdminQuery",{app_id:r.appId,admin_key:r.adminKey,collection:e,query:Oe(t)});k(i,"admin_query");try{let s=JSON.parse(i.dataJson||"[]");return Array.isArray(s)?s:[]}catch{return []}}async function de(r,e,t){if(!h(r))return null;let n=await b(r.grpcUrl),i=await S(n,"CreateCustomToken",{app_id:r.appId,admin_key:r.adminKey,uid:e,role:t.role??"user",claims_json:I(t.claims??{}),ttl:t.ttl??r.defaultTtl});if(k(i,"create_custom_token"),!i.token)throw new Error("[flare-admin][grpc] create_custom_token returned empty token");return String(i.token)}async function le(r,e,t){if(!h(r))return null;let n=await b(r.grpcUrl),i=await S(n,"CreateAuthTicket",{app_id:r.appId,admin_key:r.adminKey,uid:e,role:t.role??"user",email:t.email??"",sid:t.sid??"",tag:t.tag??"",ttl_seconds:t.ttlSeconds??0,ip:t.ip??""});return k(i,"create_auth_ticket"),{ticket:String(i.ticket??""),tag:String(i.tag??""),uuid:String(i.uuid??""),expires_at:String(i.expiresAt??""),one_time:!!(i.oneTime??true),uid:String(i.uid??e),role:String(i.role??t.role??"user"),ip:String(i.ip??"unknown")}}async function ue(r,e,t){if(!h(r))return;let n=await b(r.grpcUrl),i=await S(n,"GetDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,doc_id:t});if(k(i,"get_document"),!i.found)return null;try{return JSON.parse(i.dataJson||"{}")}catch{return {}}}async function me(r,e,t){if(!h(r))return null;let n=await b(r.grpcUrl),i=await S(n,"CreateDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,data_json:I(t)});return k(i,"create_document"),String(i.id??"")}async function pe(r,e,t,n){if(!h(r))return null;let i=await b(r.grpcUrl),s=await S(i,"ReplaceDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,doc_id:t,data_json:I(n)});return k(s,"replace_document"),true}async function ge(r,e,t,n){if(!h(r))return null;let i=await b(r.grpcUrl),s=await S(i,"UpdateDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,doc_id:t,data_json:I(n)});return k(s,"update_document"),true}async function he(r,e,t){if(!h(r))return null;let n=await b(r.grpcUrl),i=await S(n,"DeleteDocument",{app_id:r.appId,admin_key:r.adminKey,collection:e,doc_id:t});return k(i,"delete_document"),!!i.deleted}async function fe(r,e,t){if(!h(r))return null;let n=await b(r.grpcUrl),i=await S(n,"DeleteMany",{app_id:r.appId,admin_key:r.adminKey,collection:e,where:(t??[]).map(P)});return k(i,"delete_many"),Number(i.deleted??0)}var Ae=r=>r.replace(/\/$/,""),Ie=r=>{let e=String(r.httpBase??"").trim();return Ae(e||r.serverUrl)},f=(r,e)=>{let t=Ie(r),n=e.startsWith("/")?e:`/${e}`;return `${t}${n}`};var T=class{constructor(e,t,n){this.cfg=e;this.collection=t;this.id=n;}get baseUrl(){return f(this.cfg,`/admin/db/${this.cfg.appId}/${this.collection}/${this.id}`)}get headers(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`}}async request(e,t){let n;try{n=await fetch(this.baseUrl,{method:e,headers:this.headers,...t!==void 0?{body:JSON.stringify(t)}:{}});}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`[flare-admin] Network error (${e} ${this.baseUrl}): ${o}`)}let i=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] ${e} ${this.baseUrl} failed (HTTP ${n.status}): `+(i.error??"Unknown error"));return i}async get(){let e=await ue(this.cfg,this.collection,this.id);if(e!==void 0)return e===null?null:C(this.cfg,this.collection,e)??null;let t;try{t=await fetch(this.baseUrl,{headers:this.headers});}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${o}`)}if(t.status===404)return null;let n=await t.json().catch(()=>({}));if(!t.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${t.status}): `+(n.error??"Unknown error"));return C(this.cfg,this.collection,n.data)??null}async set(e){await pe(this.cfg,this.collection,this.id,e)===null&&await this.request("PUT",e);}async update(e){await ge(this.cfg,this.collection,this.id,e)===null&&await this.request("PATCH",e);}async delete(){await he(this.cfg,this.collection,this.id)===null&&await this.request("DELETE");}parent(){return new R(this.cfg,this.collection)}};var R=class r{constructor(e,t){this.cfg=e;this.name=t;this.sq={};this.opts={allowSensitiveAuthUserFields:true};}get baseUrl(){return f(this.cfg,`/admin/db/${this.cfg.appId}/${this.name}`)}get headers(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`}}clone(e){let t=new r(this.cfg,this.name);return t.sq={...this.sq,...e},t.opts={...this.opts},t}allowSensitiveAuthUserFields(e=true){let t=this.clone({});return t.opts.allowSensitiveAuthUserFields=!!e,t}normalizeFilterValue(e,t){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(t)?t:[t]:t}toQueryFilters(e){return M(e).map(n=>typeof n=="object"&&n!=null&&"field"in n&&"op"in n?{...n,value:this.normalizeFilterValue(n.op,n.value)}:n)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let t=[...this.sq.where??[]];if(t.length===0)return this.clone({where:[{or:e}]});let n=t[0];if(t.length===1&&typeof n=="object"&&n!=null&&"or"in n)return this.clone({where:[{or:[...n.or,...e]}]});let s=t.length===1?t[0]:{and:t};return this.clone({where:[{or:[s,...e]}]})}appendFilters(e,t){return t==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,t,n,i){return this.appendFilters([{field:e,op:t,value:this.normalizeFilterValue(t,n)}],i)}where(e){return this.appendFilters(this.toQueryFilters(e),"and")}and(e){return this.appendFilters(this.toQueryFilters(e),"and")}or(e){return this.appendFilters(this.toQueryFilters(e),"or")}in(e,t){return this.appendOperatorFilter(e,"in",t,"and")}andIn(e,t){return this.appendOperatorFilter(e,"in",t,"and")}orIn(e,t){return this.appendOperatorFilter(e,"in",t,"or")}notIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"and")}andNotIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"and")}orNotIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"or")}arrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"and")}andArrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"and")}orArrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"or")}arrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"and")}andArrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"and")}orArrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"or")}some(e,t){return this.appendOperatorFilter(e,"elem-match",t,"and")}andSome(e,t){return this.appendOperatorFilter(e,"elem-match",t,"and")}orSome(e,t){return this.appendOperatorFilter(e,"elem-match",t,"or")}like(e,t){return this.appendOperatorFilter(e,"like",t,"and")}andLike(e,t){return this.appendOperatorFilter(e,"like",t,"and")}orLike(e,t){return this.appendOperatorFilter(e,"like",t,"or")}notLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"and")}andNotLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"and")}orNotLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"or")}exists(e){return this.appendOperatorFilter(e,"exists",true,"and")}andExists(e){return this.appendOperatorFilter(e,"exists",true,"and")}orExists(e){return this.appendOperatorFilter(e,"exists",true,"or")}notExists(e){return this.appendOperatorFilter(e,"not-exists",true,"and")}andNotExists(e){return this.appendOperatorFilter(e,"not-exists",true,"and")}orNotExists(e){return this.appendOperatorFilter(e,"not-exists",true,"or")}latest(){return this.clone({orderBy:[...this.sq.orderBy??[],{field:"_seq",dir:"desc"}]})}newest(){return this.latest()}oldest(){return this.clone({orderBy:[...this.sq.orderBy??[],{field:"_seq",dir:"asc"}]})}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}]})}buildStructuredJoin(e,t){let n={from:String(e??""),localField:String(t?.source??""),foreignField:String(t?.target??""),as:String(t?.as??""),single:t?.single};return Array.isArray(t?.where)&&(n.where=t.where),Array.isArray(t?.orderBy)&&(n.orderBy=t.orderBy),typeof t?.limit=="number"&&(n.limit=t.limit),typeof t?.offset=="number"&&(n.offset=t.offset),Array.isArray(t?.select)&&(n.select=t.select),Array.isArray(t?.joins)&&(n.joins=t.joins.map(i=>this.buildStructuredJoin(String(i?.collection??""),i))),n}cloneStructuredJoin(e){let t={...e};return Array.isArray(e.where)&&(t.where=e.where.map(n=>({...n}))),Array.isArray(e.orderBy)&&(t.orderBy=e.orderBy.map(n=>({...n}))),Array.isArray(e.select)&&(t.select=[...e.select]),Array.isArray(e.joins)&&(t.joins=e.joins.map(n=>this.cloneStructuredJoin(n))),t}appendNestedJoinByAlias(e,t,n){for(let i of e){if(i.as===t)return i.joins=[...i.joins??[],n],true;if(Array.isArray(i.joins)&&this.appendNestedJoinByAlias(i.joins,t,n))return true}return false}parseRelationRef(e){let n=String(e??"").trim().match(/^([A-Za-z0-9_.]+)\s*->\s*([A-Za-z0-9_]+)\.([A-Za-z0-9_.]+)(?:\s+as\s+([A-Za-z0-9_]+))?$/i);if(!n)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:n[1],collection:n[2],target:n[3],alias:n[4]}}join(e,t){let n=this.buildStructuredJoin(e,t);return this.clone({joins:[...this.sq.joins??[],n]})}joinNested(e,t,n){let i=String(e??"").trim();if(!i)throw new Error("joinNested requires parentAlias");let s=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(s.length===0)throw new Error(`joinNested parent alias "${i}" not found`);let o=this.buildStructuredJoin(t,n);if(!this.appendNestedJoinByAlias(s,i,o))throw new Error(`joinNested parent alias "${i}" not found`);return this.clone({joins:s})}Join(e,t){return this.join(e,t)}JoinNested(e,t,n){return this.joinNested(e,t,n)}withRelation(e,t={}){let n=this.parseRelationRef(e);return this.join(n.collection,{...t,source:n.source,target:n.target,as:t.as??n.alias??n.collection})}select(...e){return this.clone({select:e})}distinctField(e){return this.clone({distinctField:e})}vectorSearch(e){return this.clone({vectorSearch:e})}getRawQuery(){let e={...this.sq};return Array.isArray(this.sq.where)&&(e.where=this.sq.where.map(t=>({...t}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(t=>({...t}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(t=>({...t}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(t=>({...t}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(t=>this.cloneStructuredJoin(t))),this.sq.groupBy?.fields&&(e.groupBy={fields:[...this.sq.groupBy.fields]}),this.sq.startAt?.values&&(e.startAt={values:[...this.sq.startAt.values]}),this.sq.startAfter?.values&&(e.startAfter={values:[...this.sq.startAfter.values]}),this.sq.endAt?.values&&(e.endAt={values:[...this.sq.endAt.values]}),this.sq.endBefore?.values&&(e.endBefore={values:[...this.sq.endBefore.values]}),{collection:this.name,query:e}}async get(){let e=await ce(this.cfg,this.name,this.sq);if(e)return C(this.cfg,this.name,e,this.sq)??[];let t=new URL(this.baseUrl);t.searchParams.set("query",JSON.stringify(this.sq)),t.searchParams.set("allowSensitiveAuthUserFields",this.opts.allowSensitiveAuthUserFields?"1":"0");let n;try{n=await fetch(t.toString(),{headers:this.headers});}catch(o){let a=o instanceof Error?o.message:String(o);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${a}`)}let i=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${n.status}): ${i.error??"Unknown error"}`);return C(this.cfg,this.name,i.data,this.sq)??[]}async first(){let e=await this.get();return e.length>0?e[0]:null}async last(){let e=await this.get();return e.length>0?e[e.length-1]:null}async add(e){let t=await me(this.cfg,this.name,e);if(t!==null)return new T(this.cfg,this.name,t);let n;try{n=await fetch(this.baseUrl,{method:"POST",headers:this.headers,body:JSON.stringify(e)});}catch(s){let o=s instanceof Error?s.message:String(s);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}): ${o}`)}let i=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] POST ${this.baseUrl} failed (HTTP ${n.status}): ${i.error??"Unknown error"}`);return new T(this.cfg,this.name,i.id)}async deleteMany(){let e=await fe(this.cfg,this.name,this.sq.where??[]);if(e!==null)return e;let t;try{t=await fetch(this.baseUrl,{method:"DELETE",headers:this.headers,body:JSON.stringify({where:this.sq.where??[]})});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (DELETE ${this.baseUrl}): ${s}`)}let n=await t.json().catch(()=>({}));if(!t.ok)throw new Error(`[flare-admin] DELETE ${this.baseUrl} failed (HTTP ${t.status}): ${n.error??"Unknown error"}`);return n.deleted??0}doc(e){return new T(this.cfg,this.name,e)}};var x=class{constructor(e){this.cfg=e;}collection(e){return new R(this.cfg,e)}};var B=class{constructor(e){this.cfg=e;}async createCustomToken(e,t={}){if(h(this.cfg)){let a=await de(this.cfg,String(e),t);if(!a)throw new Error("[flare-admin][grpc] create_custom_token returned empty token");return a}let n=f(this.cfg,"/admin/token"),i=JSON.stringify({appId:this.cfg.appId,uid:String(e),role:t.role??"user",claims:t.claims??{},ttl:t.ttl??this.cfg.defaultTtl}),s;try{s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`},body:i});}catch(a){let d=a instanceof Error?a.message:String(a);throw new Error(`[flare-admin] Could not reach FlareServer at "${n}": ${d}
3
+ Make sure FLARE_URL is set correctly and the server is running.`)}let o;try{o=await s.json();}catch{throw new Error(`[flare-admin] Server returned non-JSON response (status ${s.status})`)}if(!s.ok)throw new Error(`[flare-admin] createCustomToken failed (HTTP ${s.status}): `+(o.error??"Unknown error"));if(typeof o.token!="string")throw new Error('[flare-admin] Server response missing "token" field');return o.token}async getTicket(e,t={}){if(h(this.cfg)){let d=await le(this.cfg,String(e),t);if(!d)throw new Error("[flare-admin][grpc] create_auth_ticket returned empty payload");return d}let n=f(this.cfg,"/admin/ticket"),i=JSON.stringify({appId:this.cfg.appId,uid:String(e),role:t.role??"user",email:t.email,sid:t.sid,tag:t.tag,ttlSeconds:t.ttlSeconds,ip:t.ip}),s;try{s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`},body:i});}catch(d){let c=d instanceof Error?d.message:String(d);throw new Error(`[flare-admin] Could not reach FlareServer at "${n}": ${c}
4
+ Make sure FLARE_URL is set correctly and the server is running.`)}let o;try{o=await s.json();}catch{throw new Error(`[flare-admin] Server returned non-JSON response (status ${s.status})`)}if(!s.ok)throw new Error(`[flare-admin] getTicket failed (HTTP ${s.status}): `+(o.error??"Unknown error"));let a=o.ticket;if(!a||typeof a.ticket!="string")throw new Error('[flare-admin] Server response missing "ticket" object');return {ticket:String(a.ticket),tag:String(a.tag??""),uuid:String(a.uuid??""),expires_at:String(a.expires_at??""),one_time:!!(a.one_time??true),uid:String(a.uid??String(e)),role:String(a.role??t.role??"user"),ip:String(a.ip??"unknown")}}};var _=class{constructor(e){this.cfg=e;}get baseUrl(){return f(this.cfg,`/admin/notify/${this.cfg.appId}`)}get headers(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`}}async send(e){let t;try{t=await fetch(`${this.baseUrl}/send`,{method:"POST",headers:this.headers,body:JSON.stringify(e??{})});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}/send): ${s}`)}let n=await t.json().catch(()=>({}));if(!t.ok)throw new Error(`[flare-admin] Notification send failed (HTTP ${t.status}): `+(n.error??"Unknown error"));return {sent:!!n.sent,appId:String(n.appId??this.cfg.appId),targetCount:Number(n.targetCount??0),successCount:Number(n.successCount??0),failureCount:Number(n.failureCount??0),invalidatedTokenCount:Number(n.invalidatedTokenCount??0),dryRun:!!n.dryRun}}async tokens(){let e;try{e=await fetch(`${this.baseUrl}/tokens`,{method:"GET",headers:this.headers});}catch(n){let i=n instanceof Error?n.message:String(n);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}/tokens): ${i}`)}let t=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] Tokens fetch failed (HTTP ${e.status}): `+(t.error??"Unknown error"));return {appId:String(t.appId??this.cfg.appId),hasPushGateway:!!t.hasPushGateway,total:Number(t.total??0),tokens:Array.isArray(t.tokens)?t.tokens:[]}}};var Q=class{constructor(e){this.cfg=e;}base(e){return f(this.cfg,`/admin/storage/${encodeURIComponent(this.cfg.appId)}${e}`)}get headers(){return {"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`}}async jsonRequest(e,t,n){let i,s=this.base(t);try{i=await fetch(s,{method:e,headers:this.headers,...n!==void 0?{body:JSON.stringify(n)}:{}});}catch(a){let d=a instanceof Error?a.message:String(a);throw new Error(`[flare-admin] Network error (${e} ${s}): ${d}`)}let o=await i.json().catch(()=>({}));if(!i.ok)throw new Error(`[flare-admin] ${e} ${s} failed (HTTP ${i.status}): `+(o.error??"Unknown error"));return o}async request(e,t,n){return this.jsonRequest(e,t,n)}async servers(){let e=await this.jsonRequest("GET","/servers");return Array.isArray(e.servers)?e.servers:[]}async createServer(e){let t=await this.jsonRequest("POST","/servers",e??{});return {ok:!!(t.ok??true),serverId:String(t.serverId??"")}}async patchServer(e,t){let n=String(e??"").trim();if(!n)throw new Error("storage server id is required");let i=await this.jsonRequest("POST",`/servers/${encodeURIComponent(n)}`,t??{});return {ok:!!(i.ok??true),serverId:String(i.serverId??n)}}async deleteServer(e){let t=String(e??"").trim();if(!t)throw new Error("storage server id is required");let n=await this.jsonRequest("DELETE",`/servers/${encodeURIComponent(t)}`);return {ok:!!(n.ok??true),serverId:String(n.serverId??t),removedObjects:Number(n.removedObjects??0)}}async awsConfig(e){let t=String(e??"").trim();if(!t)throw new Error("storage server id is required");return (await this.jsonRequest("GET",`/servers/${encodeURIComponent(t)}/aws`)).aws??{}}async uploadObject(e){return await this.jsonRequest("POST","/object/upload",e??{})}async downloadObject(e){return await this.jsonRequest("POST","/object/download",e??{})}async deleteObject(e){return await this.jsonRequest("POST","/object/delete",e??{})}async createSignedUrl(e){return await this.jsonRequest("POST","/signed-url",e??{})}async setRules(e){let t=await this.jsonRequest("POST","/rules",{...e?.rules?{rules:e.rules}:{},...typeof e?.rulesDsl=="string"?{rulesDsl:e.rulesDsl}:{},...e?.rulesHistoryPolicy?{rulesHistoryPolicy:e.rulesHistoryPolicy}:{}});return {id:String(t.id??this.cfg.appId)}}async validateRules(e){let t=await this.jsonRequest("POST","/rules/validate",{rulesDsl:e});return {valid:!!t.valid,diagnostics:Array.isArray(t.diagnostics)?t.diagnostics:[],rulesCount:Number(t.rulesCount??0)}}async rulesHistory(){let e=await this.jsonRequest("GET","/rules/history");return {history:Array.isArray(e.history)?e.history:[],policy:e.policy??{maxEntries:30,maxAgeDays:365},restoreEvents:Array.isArray(e.restoreEvents)?e.restoreEvents:[]}}async restoreRules(e){let t=String(e??"").trim();if(!t)throw new Error("historyId is required");let n=await this.jsonRequest("POST","/rules/restore",{historyId:t});return {id:String(n.id??this.cfg.appId),rulesText:String(n.rulesText??"")}}};function ee(r){if(typeof Buffer<"u")return Buffer.from(r).toString("base64");let e="";for(let t=0;t<r.length;t++)e+=String.fromCharCode(r[t]);return btoa(e)}async function je(r){return r===void 0?"":typeof r=="string"?ee(new TextEncoder().encode(r)):Buffer&&Buffer.isBuffer(r)?r.toString("base64"):r instanceof Uint8Array?ee(r):r instanceof ArrayBuffer?ee(new Uint8Array(r)):""}function Fe(r){return Buffer?Buffer.from(String(r)).toString("base64"):btoa(String(r))}function Pe(r){try{let e=Buffer?Buffer.from(r,"base64").toString():atob(r),t=parseInt(e,10);return isNaN(t)?0:t}catch{return 0}}function xe(r){return (String(r??"").split("/").pop()??"download").replace(/["\\\r\n]/g,"")||"download"}var E=class{constructor(e){this._bucketCache=new Map;this._bucketListLoaded=false;this._bucketListPromise=null;this._svc=e;}async _ensureBuckets(){if(!this._bucketListLoaded)return this._bucketListPromise||(this._bucketListPromise=this._loadBuckets().then(()=>{this._bucketListLoaded=true;}).catch(e=>{throw this._bucketListPromise=null,e}).finally(()=>{this._bucketListPromise=null;})),this._bucketListPromise}async _loadBuckets(){let e=await this.listBuckets();for(let t of e)this._bucketCache.set(t.bucket,t.id);}_invalidateCache(){this._bucketCache.clear(),this._bucketListLoaded=false,this._bucketListPromise=null;}async _resolveBucketId(e,t){let n=this._bucketCache.get(e);if(n)return n;await this._ensureBuckets();let i=this._bucketCache.get(e);if(i)return i;if(t)return (await this.createBucket(e)).id;throw new Error(`Bucket "${e}" not found. Create it first with createBucket("${e}").`)}async createBucket(e,t={}){let n=e.trim();if(!n)throw new Error("bucket name is required");await this._ensureBuckets();let i=this._bucketCache.get(n);if(i){let d=(await this.listBuckets()).find(c=>c.id===i);if(d)return d}let s;try{s=await this._svc.createServer({name:n,kind:t.kind??"managed",bucket:n,prefix:t.prefix,region:t.region,endpoint:t.endpoint,accessKey:t.accessKey,secretKey:t.secretKey,dataDir:t.dataDir,forcePathStyle:t.forcePathStyle});}catch(a){if((a instanceof Error?a.message:String(a)).includes("bucket_conflict")){this._invalidateCache(),await this._ensureBuckets();let c=this._bucketCache.get(n);if(c){let u=(await this.listBuckets()).find(y=>y.id===c);if(u)return u}}throw a}let o={id:s.serverId,name:n,bucket:n,kind:t.kind??"managed",prefix:t.prefix};return this._bucketCache.set(n,o.id),o}async listBuckets(){let t=(await this._svc.servers()).map(n=>({id:n.id,name:n.name,bucket:n.bucket,kind:n.kind,region:n.region,endpoint:n.endpoint,prefix:n.prefix,frozen:n.frozen,readOnly:n.readOnly,createdAt:n.createdAt,updatedAt:n.updatedAt}));this._bucketCache.clear();for(let n of t)this._bucketCache.set(n.bucket,n.id);return this._bucketListLoaded=true,t}async deleteBucket(e){let t=await this._resolveBucketId(e,false),n=await this._svc.deleteServer(t);return this._bucketCache.delete(e),{ok:n.ok,removedObjects:n.removedObjects}}async deleteBuckets(e){let t=[],n={};return await Promise.all(e.map(async i=>{try{await this.deleteBucket(i),t.push(i);}catch(s){n[i]=s instanceof Error?s.message:String(s);}})),{ok:Object.keys(n).length===0,deleted:t,errors:n}}async getBucketLocation(e){let n=(await this.listBuckets()).find(i=>i.bucket===e||i.name===e);if(!n)throw new Error(`Bucket "${e}" not found`);return {bucket:n.bucket,kind:n.kind,region:n.region,endpoint:n.endpoint}}async putObject(e){let t=await this._resolveBucketId(e.bucket,true);if(e.contentBase64!==void 0){let c=await this._svc.uploadObject({serverId:t,path:e.key,contentBase64:e.contentBase64,contentType:e.contentType,encrypt:e.encrypt});return {ok:c.ok,bucket:e.bucket,key:String(c.path??e.key),size:Number(c.size??0),encrypted:!!c.encrypted}}let n=4*1024*1024,i=e.base64MaxBytes??n,s;if(typeof e.body=="string"?s=new TextEncoder().encode(e.body).length:(e.body instanceof Uint8Array||e.body instanceof ArrayBuffer||Buffer&&Buffer.isBuffer(e.body))&&(s=e.body.byteLength),s!==void 0&&s>i){let c=await this.createSignedUrl({bucket:e.bucket,key:e.key,action:"upload",expiresInSeconds:300,sizeBytes:s,contentType:e.contentType,encrypt:e.encrypt}),p;typeof e.body=="string"?p=new TextEncoder().encode(e.body):p=e.body;let u=await fetch(c.url,{method:c.method??"PUT",headers:{...e.contentType?{"Content-Type":e.contentType}:{}},body:p});if(!u.ok){let y=await u.text().catch(()=>"");throw new Error(`[flare-admin] Signed-URL upload failed (HTTP ${u.status}): ${y}`)}return {ok:true,bucket:e.bucket,key:e.key,size:s??0,encrypted:!!(e.encrypt??true)}}let a=await je(e.body),d=await this._svc.uploadObject({serverId:t,path:e.key,contentBase64:a,contentType:e.contentType,encrypt:e.encrypt});return {ok:d.ok,bucket:e.bucket,key:String(d.path??e.key),size:Number(d.size??0),encrypted:!!d.encrypted}}async getObject(e){let t=await this._resolveBucketId(e.bucket,false),n=await this._svc.downloadObject({serverId:t,path:e.key,decrypt:e.decrypt});return {ok:n.ok,bucket:e.bucket,key:String(n.path??e.key),contentBase64:String(n.contentBase64??""),contentType:String(n.contentType??"application/octet-stream"),size:Number(n.size??0),encrypted:!!n.encrypted}}async getObjectUrl(e){return (await this.createSignedUrl({bucket:e.bucket,key:e.key,action:"download",decrypt:e.decrypt,expiresInSeconds:e.expiresInSeconds,forceDownload:e.forceDownload,allowedOrigins:e.allowedOrigins,embedOnly:e.embedOnly})).url}async downloadObject(e){let t=e.forceDownload??true,n=await this.getObjectUrl({...e,forceDownload:t}),i=e.filename??xe(e.key),s=globalThis.document;if(!s)return {ok:true,url:n,filename:i,triggered:false};let o=s.createElement("a");return o.href=n,e.openInNewTab?o.target="_blank":o.download=i,o.rel="noopener noreferrer",s.body?.appendChild(o),o.click(),o.remove(),{ok:true,url:n,filename:i,triggered:true}}async headObject(e){let t=await this._resolveBucketId(e.bucket,false),n=await this._svc.request("POST","/object/head",{serverId:t,path:e.key});return {bucket:e.bucket,key:String(n.path??e.key),size:Number(n.size??0),contentType:String(n.contentType??"application/octet-stream"),encrypted:!!n.encrypted,createdAt:n.createdAt,updatedAt:n.updatedAt}}async headObjects(e){return Promise.all(e.keys.map(t=>this.headObject({bucket:e.bucket,key:t})))}async listObjects(e){let t=await this._resolveBucketId(e.bucket,false),n=e.cursor?Pe(e.cursor):0,i=Math.max(1,Math.min(e.limit??100,1e3)),s=await this._svc.request("POST","/object/list",{serverId:t,prefix:e.prefix,limit:i,skip:n}),o=Array.isArray(s.objects)?s.objects:[],a=!!s.hasMore,d=Number(s.count??o.length);return {bucket:e.bucket,objects:o.map(c=>({bucket:e.bucket,key:String(c.path??c.key??""),size:Number(c.size??0),contentType:String(c.contentType??"application/octet-stream"),encrypted:!!c.encrypted,createdAt:c.createdAt,updatedAt:c.updatedAt})),count:d,hasMore:a,cursor:a?Fe(n+o.length):void 0}}async copyObject(e){let[t,n]=await Promise.all([this._resolveBucketId(e.sourceBucket,false),this._resolveBucketId(e.destBucket,true)]);return {ok:!!((await this._svc.request("POST","/object/copy",{serverId:t,path:e.sourceKey,destServerId:n,destPath:e.destKey})).ok??true)}}async copyObjects(e){let t={};return await Promise.all(e.map(async n=>{try{await this.copyObject(n);}catch(i){t[`${n.sourceBucket}/${n.sourceKey}`]=i instanceof Error?i.message:String(i);}})),{ok:Object.keys(t).length===0,errors:t}}async deleteObject(e){return this._svc.deleteObject(e)}async deleteObjects(e){let t=await this._resolveBucketId(e.bucket,false),n=await this._svc.request("POST","/object/delete-many",{serverId:t,paths:e.keys});return {ok:!!(n.ok??true),deleted:Array.isArray(n.deleted)?n.deleted:e.keys,errors:n.errors??{}}}async createSignedUrl(e){let t=await this._resolveBucketId(e.bucket,false);return await this._svc.request("POST","/signed-url",{serverId:t,path:e.key,action:e.action,expiresInSeconds:e.expiresInSeconds,sizeBytes:e.sizeBytes,contentType:e.contentType,encrypt:e.encrypt,decrypt:e.decrypt,forceDownload:e.forceDownload,allowedOrigins:e.allowedOrigins,embedOnly:e.embedOnly})}};var D=class{constructor(e,t,n){this.conn=e;this.collection=t;this.id=n;}onSnapshot(e){let t=()=>{};return t=this.conn.subscribe(this.collection,this.id,void 0,n=>{n.type==="snapshot"&&(e(n),t());}),t}};var q=class r{constructor(e,t){this.conn=e;this.name=t;this.sq={};}clone(e){let t=new r(this.conn,this.name);return t.sq={...this.sq,...e},t}normalizeFilterValue(e,t){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(t)?t:[t]:t}toQueryFilters(e){return M(e).map(n=>typeof n=="object"&&n!=null&&"field"in n&&"op"in n?{...n,value:this.normalizeFilterValue(n.op,n.value)}:n)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let t=[...this.sq.where??[]];if(t.length===0)return this.clone({where:[{or:e}]});let n=t[0];if(t.length===1&&typeof n=="object"&&n!=null&&"or"in n)return this.clone({where:[{or:[...n.or,...e]}]});let s=t.length===1?t[0]:{and:t};return this.clone({where:[{or:[s,...e]}]})}appendFilters(e,t){return t==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,t,n,i){return this.appendFilters([{field:e,op:t,value:this.normalizeFilterValue(t,n)}],i)}where(e){return this.appendFilters(this.toQueryFilters(e),"and")}and(e){return this.appendFilters(this.toQueryFilters(e),"and")}or(e){return this.appendFilters(this.toQueryFilters(e),"or")}in(e,t){return this.appendOperatorFilter(e,"in",t,"and")}andIn(e,t){return this.appendOperatorFilter(e,"in",t,"and")}orIn(e,t){return this.appendOperatorFilter(e,"in",t,"or")}notIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"and")}andNotIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"and")}orNotIn(e,t){return this.appendOperatorFilter(e,"not-in",t,"or")}arrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"and")}andArrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"and")}orArrayContains(e,t){return this.appendOperatorFilter(e,"array-contains",t,"or")}arrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"and")}andArrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"and")}orArrayContainsAny(e,t){return this.appendOperatorFilter(e,"array-contains-any",t,"or")}some(e,t){return this.appendOperatorFilter(e,"elem-match",t,"and")}andSome(e,t){return this.appendOperatorFilter(e,"elem-match",t,"and")}orSome(e,t){return this.appendOperatorFilter(e,"elem-match",t,"or")}like(e,t){return this.appendOperatorFilter(e,"like",t,"and")}andLike(e,t){return this.appendOperatorFilter(e,"like",t,"and")}orLike(e,t){return this.appendOperatorFilter(e,"like",t,"or")}notLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"and")}andNotLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"and")}orNotLike(e,t){return this.appendOperatorFilter(e,"not-like",t,"or")}exists(e){return this.appendOperatorFilter(e,"exists",true,"and")}andExists(e){return this.appendOperatorFilter(e,"exists",true,"and")}orExists(e){return this.appendOperatorFilter(e,"exists",true,"or")}notExists(e){return this.appendOperatorFilter(e,"not-exists",true,"and")}andNotExists(e){return this.appendOperatorFilter(e,"not-exists",true,"and")}orNotExists(e){return this.appendOperatorFilter(e,"not-exists",true,"or")}latest(){return this.clone({orderBy:[...this.sq.orderBy??[],{field:"_seq",dir:"desc"}]})}newest(){return this.latest()}oldest(){return this.clone({orderBy:[...this.sq.orderBy??[],{field:"_seq",dir:"asc"}]})}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}]})}buildStructuredJoin(e,t){let n={from:String(e??""),localField:String(t?.source??""),foreignField:String(t?.target??""),as:String(t?.as??""),single:t?.single};return Array.isArray(t?.where)&&(n.where=t.where),Array.isArray(t?.orderBy)&&(n.orderBy=t.orderBy),typeof t?.limit=="number"&&(n.limit=t.limit),typeof t?.offset=="number"&&(n.offset=t.offset),Array.isArray(t?.select)&&(n.select=t.select),Array.isArray(t?.joins)&&(n.joins=t.joins.map(i=>this.buildStructuredJoin(String(i?.collection??""),i))),n}cloneStructuredJoin(e){let t={...e};return Array.isArray(e.where)&&(t.where=e.where.map(n=>({...n}))),Array.isArray(e.orderBy)&&(t.orderBy=e.orderBy.map(n=>({...n}))),Array.isArray(e.select)&&(t.select=[...e.select]),Array.isArray(e.joins)&&(t.joins=e.joins.map(n=>this.cloneStructuredJoin(n))),t}appendNestedJoinByAlias(e,t,n){for(let i of e){if(i.as===t)return i.joins=[...i.joins??[],n],true;if(Array.isArray(i.joins)&&this.appendNestedJoinByAlias(i.joins,t,n))return true}return false}parseRelationRef(e){let n=String(e??"").trim().match(/^([A-Za-z0-9_.]+)\s*->\s*([A-Za-z0-9_]+)\.([A-Za-z0-9_.]+)(?:\s+as\s+([A-Za-z0-9_]+))?$/i);if(!n)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:n[1],collection:n[2],target:n[3],alias:n[4]}}join(e,t){let n=this.buildStructuredJoin(e,t);return this.clone({joins:[...this.sq.joins??[],n]})}joinNested(e,t,n){let i=String(e??"").trim();if(!i)throw new Error("joinNested requires parentAlias");let s=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(s.length===0)throw new Error(`joinNested parent alias "${i}" not found`);let o=this.buildStructuredJoin(t,n);if(!this.appendNestedJoinByAlias(s,i,o))throw new Error(`joinNested parent alias "${i}" not found`);return this.clone({joins:s})}Join(e,t){return this.join(e,t)}JoinNested(e,t,n){return this.joinNested(e,t,n)}withRelation(e,t={}){let n=this.parseRelationRef(e);return this.join(n.collection,{...t,source:n.source,target:n.target,as:t.as??n.alias??n.collection})}select(...e){return this.clone({select:e})}distinctField(e){return this.clone({distinctField:e})}vectorSearch(e){return this.clone({vectorSearch:e})}doc(e){return new D(this.conn,this.name,e)}getRawQuery(){let e={...this.sq};return Array.isArray(this.sq.where)&&(e.where=this.sq.where.map(t=>({...t}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(t=>({...t}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(t=>({...t}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(t=>({...t}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(t=>this.cloneStructuredJoin(t))),this.sq.groupBy?.fields&&(e.groupBy={fields:[...this.sq.groupBy.fields]}),this.sq.startAt?.values&&(e.startAt={values:[...this.sq.startAt.values]}),this.sq.startAfter?.values&&(e.startAfter={values:[...this.sq.startAfter.values]}),this.sq.endAt?.values&&(e.endAt={values:[...this.sq.endAt.values]}),this.sq.endBefore?.values&&(e.endBefore={values:[...this.sq.endBefore.values]}),{collection:this.name,query:e}}onSnapshot(e){let t=this._buildSq(),n=()=>{};return n=this.conn.subscribe(this.name,void 0,t,i=>{i.type==="snapshot"&&(e(i),n());}),n}stream(e={}){let t=this._buildSq(),n=new Set,i=[],s=new Map,o=Math.max(0,Number(e.flushMs??24)),a=Math.max(1,Number(e.maxBatchSize??200)),d=e.insertAt??"end",c=typeof e.maxDocs=="number"&&e.maxDocs>0?Math.floor(e.maxDocs):void 0,p=String(e.idField??"id"),u=[],y=false,j=false,J=0,F,$=()=>{s.clear();for(let l=0;l<u.length;l+=1){let g=ne(u[l]);g&&s.set(g,l);}},ne=(l,g)=>{if(g)return g;if(l==null)return;if(typeof e.getId=="function"){let w=e.getId(l);if(typeof w=="string"&&w.length>0)return w}let A=l?.[p]??l?._id??l?.docId;if(typeof A=="string"&&A.length>0)return A},re=()=>{c==null||u.length<=c||(u=u.slice(0,c));},ie=()=>{typeof e.sort=="function"&&(u=u.slice().sort(e.sort));},se=(l,g)=>{J+=1;let A=u.slice(),w={reason:l,batchSize:g,version:J,ready:j};for(let H of Array.from(n))try{H(A,w);}catch{}},z=()=>{F!=null&&(clearTimeout(F),F=void 0);},be=l=>{if(l.operation==="delete"){let H=s.get(l.docId??"");if(H==null)return;u.splice(H,1),$();return}let g=l.data;if(g==null)return;let A=ne(g,l.docId);if(!A)return;let w=s.get(A);if(typeof w=="number"){u[w]=g;return}d==="start"?u.unshift(g):u.push(g),re(),$();},oe=()=>{if(y||i.length===0)return;z();let l=i.splice(0,i.length);for(let g of l)be(g);ie(),$(),se("change-batch",l.length);},Se=()=>{y||F!=null||(F=setTimeout(oe,o));},K=this.conn.subscribe(this.name,void 0,t,l=>{if(!y){if(l.type==="snapshot"){u=Array.isArray(l.data)?[...l.data]:[],j=true,z(),i.length=0,ie(),re(),$(),se("snapshot",0);return}if(i.push({docId:l.docId,operation:l.operation,data:l.data??null}),i.length>=a){oe();return}Se();}}),W={subscribe(l,g=true){if(n.add(l),g){let A={reason:j?"change-batch":"snapshot",batchSize:0,version:J,ready:j};try{l(u.slice(),A);}catch{}}return ()=>{n.delete(l);}},getSnapshot(){return u.slice()},isReady(){return j},getVersion(){return J},close:()=>{y||(y=true,z(),i.length=0,n.clear(),K());},onError(l){return K.onError(l),W},onPermissionDenied(l){return K.onPermissionDenied(l),W}};return W}asStore(e={}){let t=this.stream(e);return {subscribe:n=>t.subscribe(()=>{n();},false),getSnapshot:()=>t.getSnapshot(),getServerSnapshot:()=>[],stream:t,destroy:()=>{t.close();}}}onDocAdded(e){let t=this._buildSq();return this.conn.subscribe(this.name,void 0,t,n=>{n.type==="change"&&n.operation==="insert"&&n.data!=null&&e(n.data,n.docId);},{skipSnapshot:true})}onDocUpdated(e){let t=this._buildSq();return this.conn.subscribe(this.name,void 0,t,n=>{n.type==="change"&&(n.operation==="update"||n.operation==="replace")&&n.data!=null&&e(n.data,n.docId);},{skipSnapshot:true})}onDocDeleted(e){let t=this._buildSq();return this.conn.subscribe(this.name,void 0,t,n=>{n.type==="change"&&n.operation==="delete"&&e(n.docId);},{skipSnapshot:true})}onDocChanged(e){let t=this._buildSq();return this.conn.subscribe(this.name,void 0,t,n=>{n.type==="change"&&e(n.data??null,n.docId,n.operation);},{skipSnapshot:true})}_buildSq(){let e={};return this.sq.where&&this.sq.where.length>0&&(e.where=this.sq.where),this.sq.orderBy&&this.sq.orderBy.length>0&&(e.orderBy=this.sq.orderBy),this.sq.limit!==void 0&&(e.limit=this.sq.limit),this.sq.offset!==void 0&&(e.offset=this.sq.offset),this.sq.startAt&&(e.startAt=this.sq.startAt),this.sq.startAfter&&(e.startAfter=this.sq.startAfter),this.sq.endAt&&(e.endAt=this.sq.endAt),this.sq.endBefore&&(e.endBefore=this.sq.endBefore),this.sq.aggregate&&this.sq.aggregate.length>0&&(e.aggregate=this.sq.aggregate),this.sq.groupBy&&(e.groupBy=this.sq.groupBy),this.sq.having&&this.sq.having.length>0&&(e.having=this.sq.having),this.sq.joins&&this.sq.joins.length>0&&(e.joins=this.sq.joins),this.sq.vectorSearch&&(e.vectorSearch=this.sq.vectorSearch),this.sq.select&&this.sq.select.length>0&&(e.select=this.sq.select),this.sq.distinctField&&(e.distinctField=this.sq.distinctField),e}};var L=class{constructor(e){this.cfg=e;this.ws=null;this.pendingAcks=new Map;this.subscriptions=new Map;this.activeSubscriptions=new Map;this.subscriptionErrorHandlers=new Map;this.subscriptionPermissionHandlers=new Map;this.subscriptionLastErrors=new Map;this.connected=false;this.shouldReconnect=true;this.reconnectDelay=2e3;this._state="disconnected";this._stateListeners=[];let t=e.serverUrl.replace(/^http/,"ws");this.wsUrl=`${t}/?appId=${encodeURIComponent(e.appId)}&adminKey=${encodeURIComponent(e.adminKey)}`,this._readyPromise=new Promise(n=>{this._readyResolve=n;}),this._setState("connecting"),this._connect();}ready(){return this._readyPromise}get connectionState(){return this._state}onConnectionStateChange(e){return this._stateListeners.push(e),()=>{this._stateListeners=this._stateListeners.filter(t=>t!==e);}}disconnect(){this.shouldReconnect=false,this.ws?.close(1e3,"Admin disconnect"),this.ws=null,this.connected=false,this._setState("disconnected");}send(e,t){return new Promise((n,i)=>{let s=Z(),o={id:s,type:e,ts:Date.now(),...t},a=setTimeout(()=>{this.pendingAcks.delete(s),i(new Error(`[flare-admin] WS request timeout (${e})`));},1e4);this.pendingAcks.set(s,c=>{clearTimeout(a),c.type==="error"?i(new Error(`[flare-admin] Server error: ${c.message}`)):n(c);});let d=()=>this.ws?.send(JSON.stringify(o));this.connected&&this.ws?.readyState===ye__default.default.OPEN?d():this.ready().then(d).catch(i);})}subscribe(e,t,n,i,s={}){let o=Z(),a={baseId:o,liveId:o,collection:e,docId:t,structuredQuery:n,callback:i,options:s};this.activeSubscriptions.set(o,a),this.subscriptionErrorHandlers.set(o,new Set),this.subscriptionPermissionHandlers.set(o,new Set),this.activateSubscription(a);let d=()=>{let u=this.activeSubscriptions.get(o)?.liveId??o;this.activeSubscriptions.delete(o),this.subscriptions.delete(o),this.subscriptions.delete(u),this.subscriptionErrorHandlers.delete(o),this.subscriptionPermissionHandlers.delete(o),this.subscriptionLastErrors.delete(o),this.connected&&this.send("unsubscribe",{subscriptionId:u}).catch(()=>{});},c=d;return c.unsubscribe=d,c.onError=p=>{this.subscriptionErrorHandlers.get(o)?.add(p);let u=this.subscriptionLastErrors.get(o);if(u)try{p(u);}catch{}return c},c.onPermissionDenied=p=>{this.subscriptionPermissionHandlers.get(o)?.add(p);let u=this.subscriptionLastErrors.get(o);if(u?.permissionDenied)try{p(u);}catch{}return c},c.catch=p=>c.onError(p),c}activateSubscription(e){let t=()=>{this.subscriptions.set(e.liveId,e.callback);let n={collection:e.collection};e.docId&&(n.docId=e.docId),e.structuredQuery&&(n.query=e.structuredQuery),e.options.skipSnapshot&&(n.skipSnapshot=true),this.send("subscribe",n).then(i=>{let s=i.subscriptionId;if(s&&s!==e.liveId){let o=this.subscriptions.get(e.liveId);o&&(this.subscriptions.delete(e.liveId),this.subscriptions.set(s,o),e.liveId=s);}}).catch(()=>{this.subscriptions.delete(e.liveId),this.emitSubscriptionError(e.baseId,this.toSubscriptionError(new Error("Subscribe failed")));});};this.connected?t():this.ready().then(t).catch(n=>{this.emitSubscriptionError(e.baseId,this.toSubscriptionError(n));});}async replayActiveSubscriptions(){if(!this.connected)return;let e=Array.from(this.activeSubscriptions.values());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&&n!==t.baseId&&await this.send("unsubscribe",{subscriptionId:n}).catch(()=>{}),this.activateSubscription(t);}}toSubscriptionError(e){let t=e instanceof Error?e.message:String(e??"Unknown subscription error"),n=t.match(/^\[([^\]]+)\]\s*(.*)$/),i=n?.[1],s=(n?.[2]??t).trim()||t,o=i==="PERMISSION_DENIED"||t.includes("PERMISSION_DENIED");return {code:i,message:s,permissionDenied:o,raw:e}}emitSubscriptionError(e,t){this.subscriptionLastErrors.set(e,t);let n=this.subscriptionErrorHandlers.get(e);if(n)for(let i of n)try{i(t);}catch{}if(t.permissionDenied){let i=this.subscriptionPermissionHandlers.get(e);if(i)for(let s of i)try{s(t);}catch{}}}_setState(e){if(this._state!==e){this._state=e;for(let t of this._stateListeners.slice())try{t(e);}catch{}}}_connect(){this._readyPromise=new Promise(e=>{this._readyResolve=e;}),this.ws=new ye__default.default(this.wsUrl),this.ws.on("message",e=>{let t;try{t=JSON.parse(e.toString());}catch{return}this._handle(t);}),this.ws.on("close",e=>{this.connected=false,this.shouldReconnect&&e!==1e3?(this._setState("reconnecting"),setTimeout(()=>{this.reconnectDelay=Math.min(this.reconnectDelay*2,3e4),this._connect();},this.reconnectDelay)):this._setState("disconnected");}),this.ws.on("error",()=>{this._setState("error");});}_handle(e){let t=e.type;if(t==="auth_ok"){this.connected||(this.connected=true,this.reconnectDelay=2e3,this._setState("connected"),this._readyResolve(),this.replayActiveSubscriptions().catch(()=>{}));return}if(t==="ack"||t==="pong"||t==="call_response"){let n=e.correlationId??e.id,i=this.pendingAcks.get(n);i&&(i(e),this.pendingAcks.delete(n));return}if(t==="error"){let n=e.correlationId;if(n){let i=this.pendingAcks.get(n);i&&(i(e),this.pendingAcks.delete(n));let s=Array.from(this.activeSubscriptions.values()).find(o=>o.liveId===n||o.baseId===n);if(s){let o=this.toSubscriptionError(new Error(`[${String(e.code??"ERROR")}] ${String(e.message??"Unknown error")}`));this.emitSubscriptionError(s.baseId,o);}}return}if(t==="snapshot"||t==="change"){let n=e.subscriptionId,i=this.subscriptions.get(n);if(i){let s=Array.from(this.activeSubscriptions.values()).find(d=>d.liveId===n),o=String(e.collection??s?.collection??""),a=t==="change"&&e.operation==="delete"?null:C(this.cfg,o,e.data,s?.structuredQuery);i({subscriptionId:n,collection:o,docId:e.docId,data:a,type:t==="snapshot"?"snapshot":"change",operation:e.operation});}}}};var U=class{constructor(e){this._ws=new L(e);}collection(e){return new q(this._ws,e)}ready(){return this._ws.ready()}get connectionState(){return this._ws.connectionState}onConnectionStateChange(e){return this._ws.onConnectionStateChange(e)}disconnect(){this._ws.disconnect();}};var mn="ServerTimeStamp",pn={$serverTimestamp:true};var te=class{constructor(e){this.cfg={defaultTtl:"24h",transport:"auto",...e,serverUrl:e.serverUrl.replace(/\/$/,""),httpBase:e.httpBase?.replace(/\/$/,"")??"",grpcUrl:e.grpcUrl??"",dataMapper:e.dataMapper??{}};}auth(){return this._auth??(this._auth=new B(this.cfg))}db(){return this._db??(this._db=new x(this.cfg))}live(){return this._conn??(this._conn=new U(this.cfg))}notifications(){return this._notifications??(this._notifications=new _(this.cfg))}storageService(){return this._storage??(this._storage=new Q(this.cfg))}storage(){return this._storageS3||(this._storageS3=new E(this.storageService())),this._storageS3}s3(){return this.storage()}async createSignedUrl(e){return await this.s3().createSignedUrl(e)}createBucket(e,t){return this.s3().createBucket(e,t)}listBuckets(){return this.s3().listBuckets()}deleteBucket(e){return this.s3().deleteBucket(e)}deleteBuckets(e){return this.s3().deleteBuckets(e)}getBucketLocation(e){return this.s3().getBucketLocation(e)}putObject(e){return this.s3().putObject(e)}getObject(e){return this.s3().getObject(e)}getObjectUrl(e){return this.s3().getObjectUrl(e)}downloadObject(e){return this.s3().downloadObject(e)}headObject(e){return this.s3().headObject(e)}headObjects(e){return this.s3().headObjects(e)}listObjects(e){return this.s3().listObjects(e)}copyObject(e){return this.s3().copyObject(e)}copyObjects(e){return this.s3().copyObjects(e)}deleteObjects(e){return this.s3().deleteObjects(e)}onConnectionStateChange(e){return this.live().onConnectionStateChange(e)}disconnect(){this._conn?.disconnect(),this._conn=void 0;}},v=new Map;function kn(r,e="[DEFAULT]"){if(v.has(e))return v.get(e);let t=new te(r);return v.set(e,t),t}function N(r="[DEFAULT]"){let e=v.get(r);if(!e)throw new Error(`[flare-admin] No app named "${r}" found. Call connectApp() before getApp().`);return e}function wn(r="[DEFAULT]"){let e=v.get(r);return e?(e.disconnect(),v.delete(r),true):false}function Cn(){for(let r of v.values())r.disconnect();v.clear();}function vn(r="[DEFAULT]"){return N(r).auth()}function Tn(r="[DEFAULT]"){return N(r).db()}function Rn(r="[DEFAULT]"){return N(r).live()}function On(r="[DEFAULT]"){return N(r).notifications()}function In(r="[DEFAULT]"){return N(r).storage()}exports.AdminCollectionReference=R;exports.AdminDocumentReference=T;exports.AdminLiveCollectionReference=q;exports.AdminLiveDocumentReference=D;exports.AdminStorageSignedAction=V;exports.FlareAdminApp=te;exports.FlareAdminAuthService=B;exports.FlareAdminConnection=U;exports.FlareAdminDbService=x;exports.FlareAdminNotificationsService=_;exports.FlareAdminStorageS3=E;exports.FlareAdminWsConnection=L;exports.ServerTimeStamp=mn;exports.ServerTimeStampField=pn;exports.auth=vn;exports.connectApp=kn;exports.db=Tn;exports.disconnectAllApps=Cn;exports.disconnectApp=wn;exports.getApp=N;exports.live=Rn;exports.notifications=On;exports.storage=In;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,5 @@
1
+ type AdminConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting' | 'error';
2
+ type AdminConnectionStateListener = (state: AdminConnectionState) => void;
1
3
  interface FlareAdminConfig {
2
4
  /**
3
5
  * Base URL of your FlareServer instance.
@@ -16,6 +18,8 @@ interface FlareAdminConfig {
16
18
  grpcUrl?: string;
17
19
  /** Transport preference for supported operations. */
18
20
  transport?: "auto" | "http" | "grpc";
21
+ /** Optional HTTP base URL override for admin HTTP APIs. */
22
+ httpBase?: string;
19
23
  /** Default token TTL, e.g. "24h" */
20
24
  defaultTtl?: string;
21
25
  /**
@@ -597,6 +601,39 @@ type AdminDocAddedCallback<T = unknown> = (data: T, docId: string) => void;
597
601
  type AdminDocUpdatedCallback<T = unknown> = (data: T, docId: string) => void;
598
602
  type AdminDocDeletedCallback = (docId: string) => void;
599
603
  type AdminDocChangedCallback<T = unknown> = (data: T | null, docId: string, operation: "insert" | "update" | "delete" | "replace") => void;
604
+ type AdminStreamFlushReason = "snapshot" | "change-batch";
605
+ interface AdminCollectionStreamOptions<T = unknown> {
606
+ flushMs?: number;
607
+ maxBatchSize?: number;
608
+ idField?: keyof T & string;
609
+ getId?: (doc: T) => string | undefined;
610
+ insertAt?: "start" | "end";
611
+ maxDocs?: number;
612
+ sort?: (a: T, b: T) => number;
613
+ }
614
+ interface AdminCollectionStreamMeta {
615
+ reason: AdminStreamFlushReason;
616
+ batchSize: number;
617
+ version: number;
618
+ ready: boolean;
619
+ }
620
+ type AdminCollectionStreamListener<T = unknown> = (rows: readonly T[], meta: AdminCollectionStreamMeta) => void;
621
+ interface AdminCollectionStream<T = unknown> {
622
+ subscribe: (listener: AdminCollectionStreamListener<T>, emitCurrent?: boolean) => () => void;
623
+ getSnapshot: () => readonly T[];
624
+ isReady: () => boolean;
625
+ getVersion: () => number;
626
+ close: () => void;
627
+ onError: (callback: AdminSubscriptionErrorCallback) => AdminCollectionStream<T>;
628
+ onPermissionDenied: (callback: AdminSubscriptionErrorCallback) => AdminCollectionStream<T>;
629
+ }
630
+ interface AdminCollectionExternalStore<T = unknown> {
631
+ subscribe: (onStoreChange: () => void) => () => void;
632
+ getSnapshot: () => readonly T[];
633
+ getServerSnapshot: () => readonly T[];
634
+ stream: AdminCollectionStream<T>;
635
+ destroy: () => void;
636
+ }
600
637
  interface AdminSubscribeOptions {
601
638
  skipSnapshot?: boolean;
602
639
  }
@@ -987,6 +1024,8 @@ declare class AdminLiveCollectionReference<T = Record<string, unknown>> {
987
1024
  query: StructuredQuery;
988
1025
  };
989
1026
  onSnapshot(callback: AdminSnapshotCallback<T[]>): () => void;
1027
+ stream(options?: AdminCollectionStreamOptions<T>): AdminCollectionStream<T>;
1028
+ asStore(options?: AdminCollectionStreamOptions<T>): AdminCollectionExternalStore<T>;
990
1029
  onDocAdded(callback: AdminDocAddedCallback<T>): () => void;
991
1030
  onDocUpdated(callback: AdminDocUpdatedCallback<T>): () => void;
992
1031
  onDocDeleted(callback: AdminDocDeletedCallback): () => void;
@@ -1023,6 +1062,19 @@ declare class FlareAdminConnection {
1023
1062
  collection<T = Record<string, unknown>>(name: string): AdminLiveCollectionReference<T>;
1024
1063
  /** Wait until the WebSocket is open and authenticated. */
1025
1064
  ready(): Promise<void>;
1065
+ /** Current connection state. */
1066
+ get connectionState(): AdminConnectionState;
1067
+ /**
1068
+ * Subscribe to connection state changes.
1069
+ * Returns an unsubscribe function.
1070
+ *
1071
+ * @example
1072
+ * const unsub = admin.live().onConnectionStateChange((state) => {
1073
+ * console.log("connection:", state);
1074
+ * });
1075
+ * // state: 'connecting' | 'connected' | 'disconnected' | 'reconnecting' | 'error'
1076
+ */
1077
+ onConnectionStateChange(listener: AdminConnectionStateListener): () => void;
1026
1078
  /** Close the WebSocket connection permanently (no reconnect). */
1027
1079
  disconnect(): void;
1028
1080
  }
@@ -1044,12 +1096,21 @@ declare class FlareAdminWsConnection {
1044
1096
  private connected;
1045
1097
  private shouldReconnect;
1046
1098
  private reconnectDelay;
1099
+ private _state;
1100
+ private _stateListeners;
1047
1101
  private readonly wsUrl;
1048
1102
  private _readyResolve;
1049
1103
  private _readyPromise;
1050
1104
  constructor(cfg: Required<FlareAdminConfig>);
1051
1105
  /** Resolves once the WS is open and AUTH_OK is received from the server. */
1052
1106
  ready(): Promise<void>;
1107
+ /** Current connection state. */
1108
+ get connectionState(): AdminConnectionState;
1109
+ /**
1110
+ * Subscribe to connection state changes.
1111
+ * Returns an unsubscribe function.
1112
+ */
1113
+ onConnectionStateChange(listener: AdminConnectionStateListener): () => void;
1053
1114
  /** Close the connection permanently (no reconnect). */
1054
1115
  disconnect(): void;
1055
1116
  /**
@@ -1066,6 +1127,7 @@ declare class FlareAdminWsConnection {
1066
1127
  private replayActiveSubscriptions;
1067
1128
  private toSubscriptionError;
1068
1129
  private emitSubscriptionError;
1130
+ private _setState;
1069
1131
  private _connect;
1070
1132
  private _handle;
1071
1133
  }
@@ -1084,48 +1146,6 @@ declare const ServerTimeStampField: {
1084
1146
  readonly $serverTimestamp: true;
1085
1147
  };
1086
1148
 
1087
- /**
1088
- * @zuzjs/flare-admin
1089
- *
1090
- * Server-side admin SDK for FlareServer.
1091
- * Runs only on your backend, never in a browser.
1092
- *
1093
- * ─── Quick start ──────────────────────────────────────────────────────────────
1094
- *
1095
- * import { connectApp } from "@zuzjs/flare-admin";
1096
- *
1097
- * const admin = connectApp({
1098
- * serverUrl: process.env.FLARE_URL!,
1099
- * appId: process.env.FLARE_APP_ID!,
1100
- * adminKey: process.env.FLARE_ADMIN_KEY!,
1101
- * });
1102
- *
1103
- * // Mint a custom auth token (for use by the browser client)
1104
- * const token = await admin.auth().createCustomToken(String(user.id), {
1105
- * role: user.isAdmin ? "admin" : "user",
1106
- * claims: { email: user.email, plan: user.plan },
1107
- * });
1108
- *
1109
- * // One-shot DB queries (bypasses security rules)
1110
- * const users = await admin.db().collection("users").get();
1111
- * await admin.db().collection("users").doc("alice").set({ name: "Alice" });
1112
- *
1113
- * // Rich queries
1114
- * const seniors = await admin.db()
1115
- * .collection("users")
1116
- * .where({ age: ">= 60" })
1117
- * .orderBy("name")
1118
- * .limit(10)
1119
- * .get();
1120
- *
1121
- * // Real-time subscriptions over WebSocket
1122
- * const unsub = admin.connection()
1123
- * .collection("orders")
1124
- * .where({ status: "pending" })
1125
- * .orderBy("createdAt", "desc")
1126
- * .onSnapshot((snap) => console.log(snap));
1127
- */
1128
-
1129
1149
  /**
1130
1150
  * A FlareAdmin application instance.
1131
1151
  * Create one with `connectApp()` and keep it as a module-level singleton.
@@ -1172,7 +1192,7 @@ declare class FlareAdminApp {
1172
1192
  * `groupBy`, `having`, `Join`, `select`, `distinctField`, `vectorSearch`.
1173
1193
  *
1174
1194
  * @example
1175
- * const unsub = admin.connection()
1195
+ * const unsub = admin.live()
1176
1196
  * .collection("orders")
1177
1197
  * .where({ status: "pending" })
1178
1198
  * .orderBy("createdAt", "desc")
@@ -1182,15 +1202,15 @@ declare class FlareAdminApp {
1182
1202
  * else console.log(snap.operation, snap.data);
1183
1203
  * });
1184
1204
  *
1185
- * const unsub2 = admin.connection()
1205
+ * const unsub2 = admin.live()
1186
1206
  * .collection("users").doc("alice")
1187
1207
  * .onSnapshot((snap) => console.log(snap.data));
1188
1208
  *
1189
1209
  * unsub();
1190
1210
  * unsub2();
1191
- * admin.connection().disconnect();
1211
+ * admin.live().disconnect();
1192
1212
  */
1193
- connection(): FlareAdminConnection;
1213
+ live(): FlareAdminConnection;
1194
1214
  /**
1195
1215
  * Access push notification management APIs.
1196
1216
  */
@@ -1243,6 +1263,25 @@ declare class FlareAdminApp {
1243
1263
  deleted: string[];
1244
1264
  errors: Record<string, string>;
1245
1265
  }>;
1266
+ /**
1267
+ * Subscribe to WebSocket connection state changes.
1268
+ * Initializes the live connection if not already open.
1269
+ * Returns an unsubscribe function.
1270
+ *
1271
+ * @example
1272
+ * const unsub = admin.onConnectionStateChange((state) => {
1273
+ * console.log("connection:", state);
1274
+ * // state: 'connecting' | 'connected' | 'disconnected' | 'reconnecting' | 'error'
1275
+ * });
1276
+ * // Later:
1277
+ * unsub();
1278
+ */
1279
+ onConnectionStateChange(listener: (state: AdminConnectionState) => void): () => void;
1280
+ /**
1281
+ * Disconnect realtime resources tied to this app instance.
1282
+ * Safe to call multiple times.
1283
+ */
1284
+ disconnect(): void;
1246
1285
  }
1247
1286
  /**
1248
1287
  * Initialize a FlareAdmin app instance.
@@ -1264,6 +1303,15 @@ declare function connectApp(config: FlareAdminConfig, name?: string): FlareAdmin
1264
1303
  * @throws If the app has not been initialized yet.
1265
1304
  */
1266
1305
  declare function getApp(name?: string): FlareAdminApp;
1306
+ /**
1307
+ * Disconnect and remove an initialized app by name.
1308
+ * Returns true when an app existed and was removed.
1309
+ */
1310
+ declare function disconnectApp(name?: string): boolean;
1311
+ /**
1312
+ * Disconnect and clear all initialized apps.
1313
+ */
1314
+ declare function disconnectAllApps(): void;
1267
1315
  /**
1268
1316
  * Get the auth service from the default app.
1269
1317
  * Equivalent to `getApp().auth()`.
@@ -1284,15 +1332,15 @@ declare function auth(name?: string): FlareAdminAuth;
1284
1332
  declare function db(name?: string): FlareAdminDb;
1285
1333
  /**
1286
1334
  * Get the real-time WebSocket connection from the default app.
1287
- * Equivalent to `getApp().connection()`.
1335
+ * Equivalent to `getApp().live()`.
1288
1336
  *
1289
1337
  * @example
1290
- * import { connection } from "@zuzjs/flare-admin";
1291
- * const unsub = connection().collection("users")
1338
+ * import { live } from "@zuzjs/flare-admin";
1339
+ * const unsub = live().collection("users")
1292
1340
  * .where({ role: "admin" })
1293
1341
  * .onSnapshot((snap) => console.log(snap));
1294
1342
  */
1295
- declare function connection(name?: string): FlareAdminConnection;
1343
+ declare function live(name?: string): FlareAdminConnection;
1296
1344
  /**
1297
1345
  * Get the notifications service from the default app.
1298
1346
  * Equivalent to `getApp().notifications()`.
@@ -1300,4 +1348,4 @@ declare function connection(name?: string): FlareAdminConnection;
1300
1348
  declare function notifications(name?: string): FlareAdminNotifications;
1301
1349
  declare function storage(name?: string): FlareAdminStorageS3;
1302
1350
 
1303
- export { AdminCollectionReference, type AdminCopyObjectInput, type AdminDeleteObjectsInput, type AdminDocAddedCallback, type AdminDocChangedCallback, type AdminDocDeletedCallback, type AdminDocUpdatedCallback, AdminDocumentReference, type AdminDownloadObjectInput, type AdminDownloadObjectResult, type AdminGetObjectInput, type AdminGetObjectResult, type AdminGetObjectUrlInput, type AdminHeadObjectInput, type AdminHeadObjectsInput, type AdminListObjectsInput, type AdminListObjectsResult, AdminLiveCollectionReference, AdminLiveDocumentReference, type AdminPushSendInput, type AdminPushSendResult, type AdminPushToken, type AdminPutObjectInput, type AdminPutObjectResult, type AdminSnapshotCallback, type AdminSnapshotData, type AdminStorageAwsConfig, type AdminStorageBucket, type AdminStorageBucketInput, type AdminStorageDeleteInput, type AdminStorageDownloadInput, type AdminStorageObjectMeta, type AdminStorageObjectResult, type AdminStorageRulesHistoryResult, type AdminStorageRulesPolicy, type AdminStorageServer, type AdminStorageServerInput, type AdminStorageServerPatchInput, AdminStorageSignedAction, type AdminStorageSignedUrlInput, type AdminStorageSignedUrlResult, type AdminStorageUploadInput, type AdminSubscriptionError, type AdminSubscriptionErrorCallback, type AdminSubscriptionHandle, type AggregateFunction, type AggregateSpec, type AnyFilter, type CreateCustomTokenOptions, type CursorValue, FlareAdminApp, type FlareAdminAuth, FlareAdminAuthService, type FlareAdminConfig, FlareAdminConnection, type FlareAdminDb, FlareAdminDbService, type FlareAdminNotifications, FlareAdminNotificationsService, type FlareAdminStorage, FlareAdminStorageS3, FlareAdminWsConnection, type GroupByClause, type HavingClause, type JoinClause, type OrFilter, type OrderByClause, type QueryOperator, ServerTimeStamp, ServerTimeStampField, type StructuredQuery, type VectorSearchClause, type WhereCondition, type WhereFilter, auth, connectApp, connection, db, getApp, notifications, storage };
1351
+ export { AdminCollectionReference, type AdminConnectionState, type AdminConnectionStateListener, type AdminCopyObjectInput, type AdminDeleteObjectsInput, type AdminDocAddedCallback, type AdminDocChangedCallback, type AdminDocDeletedCallback, type AdminDocUpdatedCallback, AdminDocumentReference, type AdminDownloadObjectInput, type AdminDownloadObjectResult, type AdminGetObjectInput, type AdminGetObjectResult, type AdminGetObjectUrlInput, type AdminHeadObjectInput, type AdminHeadObjectsInput, type AdminListObjectsInput, type AdminListObjectsResult, AdminLiveCollectionReference, AdminLiveDocumentReference, type AdminPushSendInput, type AdminPushSendResult, type AdminPushToken, type AdminPutObjectInput, type AdminPutObjectResult, type AdminSnapshotCallback, type AdminSnapshotData, type AdminStorageAwsConfig, type AdminStorageBucket, type AdminStorageBucketInput, type AdminStorageDeleteInput, type AdminStorageDownloadInput, type AdminStorageObjectMeta, type AdminStorageObjectResult, type AdminStorageRulesHistoryResult, type AdminStorageRulesPolicy, type AdminStorageServer, type AdminStorageServerInput, type AdminStorageServerPatchInput, AdminStorageSignedAction, type AdminStorageSignedUrlInput, type AdminStorageSignedUrlResult, type AdminStorageUploadInput, type AdminSubscriptionError, type AdminSubscriptionErrorCallback, type AdminSubscriptionHandle, type AggregateFunction, type AggregateSpec, type AnyFilter, type CreateCustomTokenOptions, type CursorValue, FlareAdminApp, type FlareAdminAuth, FlareAdminAuthService, type FlareAdminConfig, FlareAdminConnection, type FlareAdminDb, FlareAdminDbService, type FlareAdminNotifications, FlareAdminNotificationsService, type FlareAdminStorage, FlareAdminStorageS3, FlareAdminWsConnection, type GroupByClause, type HavingClause, type JoinClause, type OrFilter, type OrderByClause, type QueryOperator, ServerTimeStamp, ServerTimeStampField, type StructuredQuery, type VectorSearchClause, type WhereCondition, type WhereFilter, auth, connectApp, db, disconnectAllApps, disconnectApp, getApp, live, notifications, storage };