@zuzjs/flare-admin 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -4
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +7 -0
- package/dist/index.js +2 -2
- package/dist/lib/dataMapper.d.ts +2 -0
- package/dist/types/index.d.ts +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @zuzjs/flare-admin
|
|
2
2
|
|
|
3
|
-
> Server-side admin SDK for [FlareServer](https://
|
|
3
|
+
> Server-side admin SDK for [FlareServer](https://flare.zuz.com.pk) — the self-hosted Firebase alternative.
|
|
4
4
|
> Works like `firebase-admin`: runs **only on your backend**, never in a browser.
|
|
5
5
|
|
|
6
6
|
---
|
|
@@ -22,7 +22,7 @@ admin.auth()
|
|
|
22
22
|
socket elevated ✓
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
**No MongoDB URI is ever shared.** The SDK talks to FlareServer's `/admin/token` REST endpoint using only the `adminKey`. This works identically whether you self-host Flare or use it as SaaS at `https://
|
|
25
|
+
**No MongoDB URI is ever shared.** The SDK talks to FlareServer's `/admin/token` REST endpoint using only the `adminKey`. This works identically whether you self-host Flare or use it as SaaS at `https://flare.zuz.com.pk`.
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
@@ -55,7 +55,7 @@ This prints two configs:
|
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
# .env (server-side only)
|
|
58
|
-
FLARE_URL=
|
|
58
|
+
FLARE_URL=hhttps://flare.zuzcdn.net # your FlareServer URL
|
|
59
59
|
FLARE_APP_ID=my-app
|
|
60
60
|
FLARE_ADMIN_KEY=FA_ADMIN_xxxxxxxxxxxx
|
|
61
61
|
```
|
|
@@ -102,7 +102,7 @@ app.post("/login", async (req, res) => {
|
|
|
102
102
|
import FlareClient from "@zuzjs/flare";
|
|
103
103
|
|
|
104
104
|
const flare = new FlareClient({
|
|
105
|
-
endpoint: "
|
|
105
|
+
endpoint: "https://flare.zuzcdn.net",
|
|
106
106
|
appId: "my-app",
|
|
107
107
|
apiKey: "FA_xxxxxxxx", // browser-safe key
|
|
108
108
|
});
|
|
@@ -204,6 +204,51 @@ Important:
|
|
|
204
204
|
- This option is admin-only.
|
|
205
205
|
- Normal client/system query paths cannot enable sensitive auth-user fields.
|
|
206
206
|
|
|
207
|
+
## Data Mapper (Admin)
|
|
208
|
+
|
|
209
|
+
You can pass `dataMapper` in `connectApp(...)` to shape inbound data in admin SDK reads.
|
|
210
|
+
|
|
211
|
+
Mapping rules:
|
|
212
|
+
- Base collection rows use the mapper key matching the collection name.
|
|
213
|
+
- Join payload rows use the mapper key matching join `as`.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const admin = connectApp({
|
|
217
|
+
serverUrl: process.env.FLARE_URL!,
|
|
218
|
+
appId: process.env.FLARE_APP_ID!,
|
|
219
|
+
adminKey: process.env.FLARE_ADMIN_KEY!,
|
|
220
|
+
dataMapper: {
|
|
221
|
+
boards: (row) => ({
|
|
222
|
+
id: row.id,
|
|
223
|
+
name: row.name,
|
|
224
|
+
description: row.description,
|
|
225
|
+
createdAt: new Date(row.createdAt ?? row.created_at),
|
|
226
|
+
}),
|
|
227
|
+
team: (row) => ({
|
|
228
|
+
id: row.id,
|
|
229
|
+
name: row.authMeta?.additionalParams?.name || "Unknown",
|
|
230
|
+
email: row.email,
|
|
231
|
+
createdAt: new Date(row.createdAt ?? row.created_at),
|
|
232
|
+
}),
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const rows = await admin.db()
|
|
237
|
+
.collection("boards")
|
|
238
|
+
.where({ boardId: "123" })
|
|
239
|
+
.join("users", {
|
|
240
|
+
source: "team.uid",
|
|
241
|
+
target: "uid",
|
|
242
|
+
as: "team",
|
|
243
|
+
})
|
|
244
|
+
.get();
|
|
245
|
+
|
|
246
|
+
// rows[*] is mapped by dataMapper.boards
|
|
247
|
+
// rows[*].team[*] is mapped by dataMapper.team (join alias)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Tip: for `as: "team"`, define `dataMapper.team`.
|
|
251
|
+
|
|
207
252
|
---
|
|
208
253
|
|
|
209
254
|
## Query Builder Parity (Admin)
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var
|
|
2
|
-
function v(o){let e=[];for(let[n,r]of Object.entries(o))if(typeof r=="string"){let t=r.match(/^(>=|<=|!=|>|<|==)\s*(.+)$/);if(t){let[,i,s]=t;e.push({field:n,op:i,value:q(s.trim())});}else e.push({field:n,op:"==",value:r});}else Array.isArray(r)?e.push({field:n,op:"in",value:r}):e.push({field:n,op:"==",value:r});return e}function q(o){return isNaN(Number(o))?o==="true"?true:o==="false"?false:o==="null"?null:o:Number(o)}function k(){return Math.random().toString(36).slice(2,12)+Date.now().toString(36)}var m=class{constructor(e,n,r){this.cfg=e;this.collection=n;this.id=r;}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,n){let r;try{r=await fetch(this.baseUrl,{method:e,headers:this.headers,...n!==void 0?{body:JSON.stringify(n)}:{}});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (${e} ${this.baseUrl}): ${s}`)}let t=await r.json().catch(()=>({}));if(!r.ok)throw new Error(`[flare-admin] ${e} ${this.baseUrl} failed (HTTP ${r.status}): `+(t.error??"Unknown error"));return t}async get(){let e;try{e=await fetch(this.baseUrl,{headers:this.headers});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${t}`)}if(e.status===404)return null;let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${e.status}): `+(n.error??"Unknown error"));return n.data??null}async set(e){await this.request("PUT",e);}async update(e){await this.request("PATCH",e);}async delete(){await this.request("DELETE");}parent(){return new p(this.cfg,this.collection)}};var p=class o{constructor(e,n){this.cfg=e;this.name=n;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 n=new o(this.cfg,this.name);return n.sq={...this.sq,...e},n.opts={...this.opts},n}allowSensitiveAuthUserFields(e=true){let n=this.clone({});return n.opts.allowSensitiveAuthUserFields=!!e,n}normalizeFilterValue(e,n){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(n)?n:[n]:n}toQueryFilters(e){return v(e).map(r=>typeof r=="object"&&r!=null&&"field"in r&&"op"in r?{...r,value:this.normalizeFilterValue(r.op,r.value)}:r)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let n=[...this.sq.where??[]];if(n.length===0)return this.clone({where:[{or:e}]});let r=n[0];if(n.length===1&&typeof r=="object"&&r!=null&&"or"in r)return this.clone({where:[{or:[...r.or,...e]}]});let i=n.length===1?n[0]:{and:n};return this.clone({where:[{or:[i,...e]}]})}appendFilters(e,n){return n==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,n,r,t){return this.appendFilters([{field:e,op:n,value:this.normalizeFilterValue(n,r)}],t)}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,n){return this.appendOperatorFilter(e,"in",n,"and")}andIn(e,n){return this.appendOperatorFilter(e,"in",n,"and")}orIn(e,n){return this.appendOperatorFilter(e,"in",n,"or")}notIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}andNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}orNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"or")}arrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}andArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}orArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"or")}arrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}andArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}orArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"or")}some(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}andSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}orSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"or")}like(e,n){return this.appendOperatorFilter(e,"like",n,"and")}andLike(e,n){return this.appendOperatorFilter(e,"like",n,"and")}orLike(e,n){return this.appendOperatorFilter(e,"like",n,"or")}notLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}andNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}orNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"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,n="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:n}]})}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,n){return this.aggregate({fn:"sum",field:e,alias:n??`sum_${e}`})}avg(e,n){return this.aggregate({fn:"avg",field:e,alias:n??`avg_${e}`})}min(e,n){return this.aggregate({fn:"min",field:e,alias:n??`min_${e}`})}max(e,n){return this.aggregate({fn:"max",field:e,alias:n??`max_${e}`})}distinct(e,n){return this.aggregate({fn:"distinct",field:e,alias:n??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,n,r){return this.clone({having:[...this.sq.having??[],{field:e,op:n,value:r}]})}buildStructuredJoin(e,n){let r={from:String(e??""),localField:String(n?.source??""),foreignField:String(n?.target??""),as:String(n?.as??""),single:n?.single};return Array.isArray(n?.where)&&(r.where=n.where),Array.isArray(n?.orderBy)&&(r.orderBy=n.orderBy),typeof n?.limit=="number"&&(r.limit=n.limit),typeof n?.offset=="number"&&(r.offset=n.offset),Array.isArray(n?.select)&&(r.select=n.select),Array.isArray(n?.joins)&&(r.joins=n.joins.map(t=>this.buildStructuredJoin(String(t?.collection??""),t))),r}cloneStructuredJoin(e){let n={...e};return Array.isArray(e.where)&&(n.where=e.where.map(r=>({...r}))),Array.isArray(e.orderBy)&&(n.orderBy=e.orderBy.map(r=>({...r}))),Array.isArray(e.select)&&(n.select=[...e.select]),Array.isArray(e.joins)&&(n.joins=e.joins.map(r=>this.cloneStructuredJoin(r))),n}appendNestedJoinByAlias(e,n,r){for(let t of e){if(t.as===n)return t.joins=[...t.joins??[],r],true;if(Array.isArray(t.joins)&&this.appendNestedJoinByAlias(t.joins,n,r))return true}return false}parseRelationRef(e){let r=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(!r)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:r[1],collection:r[2],target:r[3],alias:r[4]}}join(e,n){let r=this.buildStructuredJoin(e,n);return this.clone({joins:[...this.sq.joins??[],r]})}joinNested(e,n,r){let t=String(e??"").trim();if(!t)throw new Error("joinNested requires parentAlias");let i=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(i.length===0)throw new Error(`joinNested parent alias "${t}" not found`);let s=this.buildStructuredJoin(n,r);if(!this.appendNestedJoinByAlias(i,t,s))throw new Error(`joinNested parent alias "${t}" not found`);return this.clone({joins:i})}Join(e,n){return this.join(e,n)}JoinNested(e,n,r){return this.joinNested(e,n,r)}withRelation(e,n={}){let r=this.parseRelationRef(e);return this.join(r.collection,{...n,source:r.source,target:r.target,as:n.as??r.alias??r.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(n=>({...n}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(n=>({...n}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(n=>({...n}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(n=>({...n}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(n=>this.cloneStructuredJoin(n))),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=new URL(this.baseUrl);e.searchParams.set("query",JSON.stringify(this.sq)),e.searchParams.set("allowSensitiveAuthUserFields",this.opts.allowSensitiveAuthUserFields?"1":"0");let n;try{n=await fetch(e.toString(),{headers:this.headers});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${n.status}): ${r.error??"Unknown error"}`);return r.data??[]}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 n;try{n=await fetch(this.baseUrl,{method:"POST",headers:this.headers,body:JSON.stringify(e)});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] POST ${this.baseUrl} failed (HTTP ${n.status}): ${r.error??"Unknown error"}`);return new m(this.cfg,this.name,r.id)}async deleteMany(){let e;try{e=await fetch(this.baseUrl,{method:"DELETE",headers:this.headers,body:JSON.stringify({where:this.sq.where??[]})});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (DELETE ${this.baseUrl}): ${t}`)}let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] DELETE ${this.baseUrl} failed (HTTP ${e.status}): ${n.error??"Unknown error"}`);return n.deleted??0}doc(e){return new m(this.cfg,this.name,e)}};var f=class{constructor(e){this.cfg=e;}collection(e){return new p(this.cfg,e)}};var g=class{constructor(e){this.cfg=e;}async createCustomToken(e,n={}){let r=`${this.cfg.serverUrl.replace(/\/$/,"")}/admin/token`,t=JSON.stringify({appId:this.cfg.appId,uid:String(e),role:n.role??"user",claims:n.claims??{},ttl:n.ttl??this.cfg.defaultTtl}),i;try{i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`},body:t});}catch(a){let h=a instanceof Error?a.message:String(a);throw new Error(`[flare-admin] Could not reach FlareServer at "${r}": ${h}
|
|
3
|
-
Make sure FLARE_URL is set correctly and the server is running.`)}let s;try{s=await i.json();}catch{throw new Error(`[flare-admin] Server returned non-JSON response (status ${i.status})`)}if(!i.ok)throw new Error(`[flare-admin] createCustomToken failed (HTTP ${i.status}): `+(s.error??"Unknown error"));if(typeof s.token!="string")throw new Error('[flare-admin] Server response missing "token" field');return s.token}};var A=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 n;try{n=await fetch(`${this.baseUrl}/send`,{method:"POST",headers:this.headers,body:JSON.stringify(e??{})});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}/send): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] Notification send failed (HTTP ${n.status}): `+(r.error??"Unknown error"));return {sent:!!r.sent,appId:String(r.appId??this.cfg.appId),targetCount:Number(r.targetCount??0),successCount:Number(r.successCount??0),failureCount:Number(r.failureCount??0),invalidatedTokenCount:Number(r.invalidatedTokenCount??0),dryRun:!!r.dryRun}}async tokens(){let e;try{e=await fetch(`${this.baseUrl}/tokens`,{method:"GET",headers:this.headers});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}/tokens): ${t}`)}let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] Tokens fetch failed (HTTP ${e.status}): `+(n.error??"Unknown error"));return {appId:String(n.appId??this.cfg.appId),hasPushGateway:!!n.hasPushGateway,total:Number(n.total??0),tokens:Array.isArray(n.tokens)?n.tokens:[]}}};var y=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 n=e.serverUrl.replace(/^http/,"ws");this.wsUrl=`${n}/?appId=${encodeURIComponent(e.appId)}&adminKey=${encodeURIComponent(e.adminKey)}`,this._readyPromise=new Promise(r=>{this._readyResolve=r;}),this._connect();}ready(){return this._readyPromise}disconnect(){this.shouldReconnect=false,this.ws?.close(1e3,"Admin disconnect"),this.ws=null,this.connected=false;}send(e,n){return new Promise((r,t)=>{let i=k(),s={id:i,type:e,ts:Date.now(),...n},a=setTimeout(()=>{this.pendingAcks.delete(i),t(new Error(`[flare-admin] WS request timeout (${e})`));},1e4);this.pendingAcks.set(i,c=>{clearTimeout(a),c.type==="error"?t(new Error(`[flare-admin] Server error: ${c.message}`)):r(c);});let h=()=>this.ws?.send(JSON.stringify(s));this.connected&&this.ws?.readyState===F__default.default.OPEN?h():this.ready().then(h).catch(t);})}subscribe(e,n,r,t,i={}){let s=k(),a={baseId:s,liveId:s,collection:e,docId:n,structuredQuery:r,callback:t,options:i};this.activeSubscriptions.set(s,a),this.subscriptionErrorHandlers.set(s,new Set),this.subscriptionPermissionHandlers.set(s,new Set),this.activateSubscription(a);let h=()=>{let u=this.activeSubscriptions.get(s)?.liveId??s;this.activeSubscriptions.delete(s),this.subscriptions.delete(s),this.subscriptions.delete(u),this.subscriptionErrorHandlers.delete(s),this.subscriptionPermissionHandlers.delete(s),this.subscriptionLastErrors.delete(s),this.connected&&this.send("unsubscribe",{subscriptionId:u}).catch(()=>{});},c=h;return c.unsubscribe=h,c.onError=d=>{this.subscriptionErrorHandlers.get(s)?.add(d);let u=this.subscriptionLastErrors.get(s);if(u)try{d(u);}catch{}return c},c.onPermissionDenied=d=>{this.subscriptionPermissionHandlers.get(s)?.add(d);let u=this.subscriptionLastErrors.get(s);if(u?.permissionDenied)try{d(u);}catch{}return c},c.catch=d=>c.onError(d),c}activateSubscription(e){let n=()=>{this.subscriptions.set(e.liveId,e.callback);let r={collection:e.collection};e.docId&&(r.docId=e.docId),e.structuredQuery&&(r.query=e.structuredQuery),e.options.skipSnapshot&&(r.skipSnapshot=true),this.send("subscribe",r).then(t=>{let i=t.subscriptionId;if(i&&i!==e.liveId){let s=this.subscriptions.get(e.liveId);s&&(this.subscriptions.delete(e.liveId),this.subscriptions.set(i,s),e.liveId=i);}}).catch(()=>{this.subscriptions.delete(e.liveId),this.emitSubscriptionError(e.baseId,this.toSubscriptionError(new Error("Subscribe failed")));});};this.connected?n():this.ready().then(n).catch(r=>{this.emitSubscriptionError(e.baseId,this.toSubscriptionError(r));});}async replayActiveSubscriptions(){if(!this.connected)return;let e=Array.from(this.activeSubscriptions.values());for(let n of e){if(!this.activeSubscriptions.has(n.baseId))continue;let r=n.liveId;this.subscriptions.delete(r),n.liveId=n.baseId,r&&r!==n.baseId&&await this.send("unsubscribe",{subscriptionId:r}).catch(()=>{}),this.activateSubscription(n);}}toSubscriptionError(e){let n=e instanceof Error?e.message:String(e??"Unknown subscription error"),r=n.match(/^\[([^\]]+)\]\s*(.*)$/),t=r?.[1],i=(r?.[2]??n).trim()||n,s=t==="PERMISSION_DENIED"||n.includes("PERMISSION_DENIED");return {code:t,message:i,permissionDenied:s,raw:e}}emitSubscriptionError(e,n){this.subscriptionLastErrors.set(e,n);let r=this.subscriptionErrorHandlers.get(e);if(r)for(let t of r)try{t(n);}catch{}if(n.permissionDenied){let t=this.subscriptionPermissionHandlers.get(e);if(t)for(let i of t)try{i(n);}catch{}}}_connect(){this._readyPromise=new Promise(e=>{this._readyResolve=e;}),this.ws=new F__default.default(this.wsUrl),this.ws.on("message",e=>{let n;try{n=JSON.parse(e.toString());}catch{return}this._handle(n);}),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 n=e.type;if(n==="auth_ok"){this.connected||(this.connected=true,this.reconnectDelay=2e3,this._readyResolve(),this.replayActiveSubscriptions().catch(()=>{}));return}if(n==="ack"||n==="pong"||n==="call_response"){let r=e.correlationId??e.id,t=this.pendingAcks.get(r);t&&(t(e),this.pendingAcks.delete(r));return}if(n==="error"){let r=e.correlationId;if(r){let t=this.pendingAcks.get(r);t&&(t(e),this.pendingAcks.delete(r));let i=Array.from(this.activeSubscriptions.values()).find(s=>s.liveId===r||s.baseId===r);if(i){let s=this.toSubscriptionError(new Error(`[${String(e.code??"ERROR")}] ${String(e.message??"Unknown error")}`));this.emitSubscriptionError(i.baseId,s);}}return}if(n==="snapshot"||n==="change"){let r=e.subscriptionId,t=this.subscriptions.get(r);t&&t({subscriptionId:r,collection:e.collection,docId:e.docId,data:e.data,type:n==="snapshot"?"snapshot":"change",operation:e.operation});}}};var w=class{constructor(e,n,r){this.conn=e;this.collection=n;this.id=r;}onSnapshot(e){let n=()=>{};return n=this.conn.subscribe(this.collection,this.id,void 0,r=>{r.type==="snapshot"&&(e(r),n());}),n}};var C=class o{constructor(e,n){this.conn=e;this.name=n;this.sq={};}clone(e){let n=new o(this.conn,this.name);return n.sq={...this.sq,...e},n}normalizeFilterValue(e,n){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(n)?n:[n]:n}toQueryFilters(e){return v(e).map(r=>typeof r=="object"&&r!=null&&"field"in r&&"op"in r?{...r,value:this.normalizeFilterValue(r.op,r.value)}:r)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let n=[...this.sq.where??[]];if(n.length===0)return this.clone({where:[{or:e}]});let r=n[0];if(n.length===1&&typeof r=="object"&&r!=null&&"or"in r)return this.clone({where:[{or:[...r.or,...e]}]});let i=n.length===1?n[0]:{and:n};return this.clone({where:[{or:[i,...e]}]})}appendFilters(e,n){return n==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,n,r,t){return this.appendFilters([{field:e,op:n,value:this.normalizeFilterValue(n,r)}],t)}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,n){return this.appendOperatorFilter(e,"in",n,"and")}andIn(e,n){return this.appendOperatorFilter(e,"in",n,"and")}orIn(e,n){return this.appendOperatorFilter(e,"in",n,"or")}notIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}andNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}orNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"or")}arrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}andArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}orArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"or")}arrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}andArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}orArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"or")}some(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}andSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}orSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"or")}like(e,n){return this.appendOperatorFilter(e,"like",n,"and")}andLike(e,n){return this.appendOperatorFilter(e,"like",n,"and")}orLike(e,n){return this.appendOperatorFilter(e,"like",n,"or")}notLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}andNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}orNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"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,n="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:n}]})}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,n){return this.aggregate({fn:"sum",field:e,alias:n??`sum_${e}`})}avg(e,n){return this.aggregate({fn:"avg",field:e,alias:n??`avg_${e}`})}min(e,n){return this.aggregate({fn:"min",field:e,alias:n??`min_${e}`})}max(e,n){return this.aggregate({fn:"max",field:e,alias:n??`max_${e}`})}distinct(e,n){return this.aggregate({fn:"distinct",field:e,alias:n??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,n,r){return this.clone({having:[...this.sq.having??[],{field:e,op:n,value:r}]})}buildStructuredJoin(e,n){let r={from:String(e??""),localField:String(n?.source??""),foreignField:String(n?.target??""),as:String(n?.as??""),single:n?.single};return Array.isArray(n?.where)&&(r.where=n.where),Array.isArray(n?.orderBy)&&(r.orderBy=n.orderBy),typeof n?.limit=="number"&&(r.limit=n.limit),typeof n?.offset=="number"&&(r.offset=n.offset),Array.isArray(n?.select)&&(r.select=n.select),Array.isArray(n?.joins)&&(r.joins=n.joins.map(t=>this.buildStructuredJoin(String(t?.collection??""),t))),r}cloneStructuredJoin(e){let n={...e};return Array.isArray(e.where)&&(n.where=e.where.map(r=>({...r}))),Array.isArray(e.orderBy)&&(n.orderBy=e.orderBy.map(r=>({...r}))),Array.isArray(e.select)&&(n.select=[...e.select]),Array.isArray(e.joins)&&(n.joins=e.joins.map(r=>this.cloneStructuredJoin(r))),n}appendNestedJoinByAlias(e,n,r){for(let t of e){if(t.as===n)return t.joins=[...t.joins??[],r],true;if(Array.isArray(t.joins)&&this.appendNestedJoinByAlias(t.joins,n,r))return true}return false}parseRelationRef(e){let r=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(!r)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:r[1],collection:r[2],target:r[3],alias:r[4]}}join(e,n){let r=this.buildStructuredJoin(e,n);return this.clone({joins:[...this.sq.joins??[],r]})}joinNested(e,n,r){let t=String(e??"").trim();if(!t)throw new Error("joinNested requires parentAlias");let i=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(i.length===0)throw new Error(`joinNested parent alias "${t}" not found`);let s=this.buildStructuredJoin(n,r);if(!this.appendNestedJoinByAlias(i,t,s))throw new Error(`joinNested parent alias "${t}" not found`);return this.clone({joins:i})}Join(e,n){return this.join(e,n)}JoinNested(e,n,r){return this.joinNested(e,n,r)}withRelation(e,n={}){let r=this.parseRelationRef(e);return this.join(r.collection,{...n,source:r.source,target:r.target,as:n.as??r.alias??r.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 w(this.conn,this.name,e)}getRawQuery(){let e={...this.sq};return Array.isArray(this.sq.where)&&(e.where=this.sq.where.map(n=>({...n}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(n=>({...n}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(n=>({...n}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(n=>({...n}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(n=>this.cloneStructuredJoin(n))),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 n=this._buildSq(),r=()=>{};return r=this.conn.subscribe(this.name,void 0,n,t=>{t.type==="snapshot"&&(e(t),r());}),r}onDocAdded(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&r.operation==="insert"&&r.data!=null&&e(r.data,r.docId);},{skipSnapshot:true})}onDocUpdated(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&(r.operation==="update"||r.operation==="replace")&&r.data!=null&&e(r.data,r.docId);},{skipSnapshot:true})}onDocDeleted(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&r.operation==="delete"&&e(r.docId);},{skipSnapshot:true})}onDocChanged(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&e(r.data??null,r.docId,r.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 b=class{constructor(e){this._ws=new y(e);}collection(e){return new C(this._ws,e)}ready(){return this._ws.ready()}disconnect(){this._ws.disconnect();}};var T=class{constructor(e){this.cfg={defaultTtl:"24h",...e,serverUrl:e.serverUrl.replace(/\/$/,"")};}auth(){return this._auth??(this._auth=new g(this.cfg))}db(){return this._db??(this._db=new f(this.cfg))}connection(){return this._conn??(this._conn=new b(this.cfg))}notifications(){return this._notifications??(this._notifications=new A(this.cfg))}},S=new Map;function le(o,e="[DEFAULT]"){if(S.has(e))return S.get(e);let n=new T(o);return S.set(e,n),n}function R(o="[DEFAULT]"){let e=S.get(o);if(!e)throw new Error(`[flare-admin] No app named "${o}" found. Call connectApp() before getApp().`);return e}function de(o="[DEFAULT]"){return R(o).auth()}function ue(o="[DEFAULT]"){return R(o).db()}function he(o="[DEFAULT]"){return R(o).connection()}function pe(o="[DEFAULT]"){return R(o).notifications()}exports.AdminCollectionReference=p;exports.AdminDocumentReference=m;exports.AdminLiveCollectionReference=C;exports.AdminLiveDocumentReference=w;exports.FlareAdminApp=T;exports.FlareAdminAuthService=g;exports.FlareAdminConnection=b;exports.FlareAdminDbService=f;exports.FlareAdminNotificationsService=A;exports.FlareAdminWsConnection=y;exports.auth=de;exports.connectApp=le;exports.connection=he;exports.db=ue;exports.getApp=R;exports.notifications=pe;
|
|
1
|
+
'use strict';var O=require('ws');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var O__default=/*#__PURE__*/_interopDefault(O);/* @zuzjs/flare-admin */
|
|
2
|
+
function S(o){let e=[];for(let[n,r]of Object.entries(o))if(typeof r=="string"){let t=r.match(/^(>=|<=|!=|>|<|==)\s*(.+)$/);if(t){let[,i,s]=t;e.push({field:n,op:i,value:L(s.trim())});}else e.push({field:n,op:"==",value:r});}else Array.isArray(r)?e.push({field:n,op:"in",value:r}):e.push({field:n,op:"==",value:r});return e}function L(o){return isNaN(Number(o))?o==="true"?true:o==="false"?false:o==="null"?null:o:Number(o)}function T(){return Math.random().toString(36).slice(2,12)+Date.now().toString(36)}function I(o,e){let n=o.dataMapper;if(!n||typeof n!="object")return null;let r=n[e];return typeof r=="function"?r:null}function F(o,e,n){let r=I(o,e);if(!r||n==null||typeof n!="object")return n;try{return r(n)}catch{return n}}function q(o,e,n){if(!e||typeof e!="object"||!Array.isArray(n)||n.length===0)return e;let r=e;for(let t of n){let i=String(t?.as??"").trim();if(!i)continue;let s=Array.isArray(t?.joins)?t.joins:[],a=r[i],c=a;Array.isArray(a)?c=a.map(l=>q(o,l,s)):a&&typeof a=="object"&&(c=q(o,a,s)),c=Array.isArray(c)?c.map(l=>F(o,i,l)):F(o,i,c),c!==a&&(r===e&&(r={...r}),r[i]=c);}return r}function m(o,e,n,r){let t=Array.isArray(r?.joins)?r.joins:[],i=s=>{let a=q(o,s,t);return F(o,e,a)};return Array.isArray(n)?n.map(s=>i(s)):i(n)}var f=class{constructor(e,n,r){this.cfg=e;this.collection=n;this.id=r;}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,n){let r;try{r=await fetch(this.baseUrl,{method:e,headers:this.headers,...n!==void 0?{body:JSON.stringify(n)}:{}});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (${e} ${this.baseUrl}): ${s}`)}let t=await r.json().catch(()=>({}));if(!r.ok)throw new Error(`[flare-admin] ${e} ${this.baseUrl} failed (HTTP ${r.status}): `+(t.error??"Unknown error"));return t}async get(){let e;try{e=await fetch(this.baseUrl,{headers:this.headers});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${i}`)}if(e.status===404)return null;let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${e.status}): `+(n.error??"Unknown error"));return m(this.cfg,this.collection,n.data)??null}async set(e){await this.request("PUT",e);}async update(e){await this.request("PATCH",e);}async delete(){await this.request("DELETE");}parent(){return new p(this.cfg,this.collection)}};var p=class o{constructor(e,n){this.cfg=e;this.name=n;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 n=new o(this.cfg,this.name);return n.sq={...this.sq,...e},n.opts={...this.opts},n}allowSensitiveAuthUserFields(e=true){let n=this.clone({});return n.opts.allowSensitiveAuthUserFields=!!e,n}normalizeFilterValue(e,n){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(n)?n:[n]:n}toQueryFilters(e){return S(e).map(r=>typeof r=="object"&&r!=null&&"field"in r&&"op"in r?{...r,value:this.normalizeFilterValue(r.op,r.value)}:r)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let n=[...this.sq.where??[]];if(n.length===0)return this.clone({where:[{or:e}]});let r=n[0];if(n.length===1&&typeof r=="object"&&r!=null&&"or"in r)return this.clone({where:[{or:[...r.or,...e]}]});let i=n.length===1?n[0]:{and:n};return this.clone({where:[{or:[i,...e]}]})}appendFilters(e,n){return n==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,n,r,t){return this.appendFilters([{field:e,op:n,value:this.normalizeFilterValue(n,r)}],t)}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,n){return this.appendOperatorFilter(e,"in",n,"and")}andIn(e,n){return this.appendOperatorFilter(e,"in",n,"and")}orIn(e,n){return this.appendOperatorFilter(e,"in",n,"or")}notIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}andNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}orNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"or")}arrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}andArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}orArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"or")}arrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}andArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}orArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"or")}some(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}andSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}orSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"or")}like(e,n){return this.appendOperatorFilter(e,"like",n,"and")}andLike(e,n){return this.appendOperatorFilter(e,"like",n,"and")}orLike(e,n){return this.appendOperatorFilter(e,"like",n,"or")}notLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}andNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}orNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"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,n="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:n}]})}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,n){return this.aggregate({fn:"sum",field:e,alias:n??`sum_${e}`})}avg(e,n){return this.aggregate({fn:"avg",field:e,alias:n??`avg_${e}`})}min(e,n){return this.aggregate({fn:"min",field:e,alias:n??`min_${e}`})}max(e,n){return this.aggregate({fn:"max",field:e,alias:n??`max_${e}`})}distinct(e,n){return this.aggregate({fn:"distinct",field:e,alias:n??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,n,r){return this.clone({having:[...this.sq.having??[],{field:e,op:n,value:r}]})}buildStructuredJoin(e,n){let r={from:String(e??""),localField:String(n?.source??""),foreignField:String(n?.target??""),as:String(n?.as??""),single:n?.single};return Array.isArray(n?.where)&&(r.where=n.where),Array.isArray(n?.orderBy)&&(r.orderBy=n.orderBy),typeof n?.limit=="number"&&(r.limit=n.limit),typeof n?.offset=="number"&&(r.offset=n.offset),Array.isArray(n?.select)&&(r.select=n.select),Array.isArray(n?.joins)&&(r.joins=n.joins.map(t=>this.buildStructuredJoin(String(t?.collection??""),t))),r}cloneStructuredJoin(e){let n={...e};return Array.isArray(e.where)&&(n.where=e.where.map(r=>({...r}))),Array.isArray(e.orderBy)&&(n.orderBy=e.orderBy.map(r=>({...r}))),Array.isArray(e.select)&&(n.select=[...e.select]),Array.isArray(e.joins)&&(n.joins=e.joins.map(r=>this.cloneStructuredJoin(r))),n}appendNestedJoinByAlias(e,n,r){for(let t of e){if(t.as===n)return t.joins=[...t.joins??[],r],true;if(Array.isArray(t.joins)&&this.appendNestedJoinByAlias(t.joins,n,r))return true}return false}parseRelationRef(e){let r=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(!r)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:r[1],collection:r[2],target:r[3],alias:r[4]}}join(e,n){let r=this.buildStructuredJoin(e,n);return this.clone({joins:[...this.sq.joins??[],r]})}joinNested(e,n,r){let t=String(e??"").trim();if(!t)throw new Error("joinNested requires parentAlias");let i=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(i.length===0)throw new Error(`joinNested parent alias "${t}" not found`);let s=this.buildStructuredJoin(n,r);if(!this.appendNestedJoinByAlias(i,t,s))throw new Error(`joinNested parent alias "${t}" not found`);return this.clone({joins:i})}Join(e,n){return this.join(e,n)}JoinNested(e,n,r){return this.joinNested(e,n,r)}withRelation(e,n={}){let r=this.parseRelationRef(e);return this.join(r.collection,{...n,source:r.source,target:r.target,as:n.as??r.alias??r.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(n=>({...n}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(n=>({...n}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(n=>({...n}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(n=>({...n}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(n=>this.cloneStructuredJoin(n))),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=new URL(this.baseUrl);e.searchParams.set("query",JSON.stringify(this.sq)),e.searchParams.set("allowSensitiveAuthUserFields",this.opts.allowSensitiveAuthUserFields?"1":"0");let n;try{n=await fetch(e.toString(),{headers:this.headers});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${s}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${n.status}): ${r.error??"Unknown error"}`);return m(this.cfg,this.name,r.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 n;try{n=await fetch(this.baseUrl,{method:"POST",headers:this.headers,body:JSON.stringify(e)});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] POST ${this.baseUrl} failed (HTTP ${n.status}): ${r.error??"Unknown error"}`);return new f(this.cfg,this.name,r.id)}async deleteMany(){let e;try{e=await fetch(this.baseUrl,{method:"DELETE",headers:this.headers,body:JSON.stringify({where:this.sq.where??[]})});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (DELETE ${this.baseUrl}): ${t}`)}let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] DELETE ${this.baseUrl} failed (HTTP ${e.status}): ${n.error??"Unknown error"}`);return n.deleted??0}doc(e){return new f(this.cfg,this.name,e)}};var g=class{constructor(e){this.cfg=e;}collection(e){return new p(this.cfg,e)}};var A=class{constructor(e){this.cfg=e;}async createCustomToken(e,n={}){let r=`${this.cfg.serverUrl.replace(/\/$/,"")}/admin/token`,t=JSON.stringify({appId:this.cfg.appId,uid:String(e),role:n.role??"user",claims:n.claims??{},ttl:n.ttl??this.cfg.defaultTtl}),i;try{i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`},body:t});}catch(a){let c=a instanceof Error?a.message:String(a);throw new Error(`[flare-admin] Could not reach FlareServer at "${r}": ${c}
|
|
3
|
+
Make sure FLARE_URL is set correctly and the server is running.`)}let s;try{s=await i.json();}catch{throw new Error(`[flare-admin] Server returned non-JSON response (status ${i.status})`)}if(!i.ok)throw new Error(`[flare-admin] createCustomToken failed (HTTP ${i.status}): `+(s.error??"Unknown error"));if(typeof s.token!="string")throw new Error('[flare-admin] Server response missing "token" field');return s.token}};var y=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 n;try{n=await fetch(`${this.baseUrl}/send`,{method:"POST",headers:this.headers,body:JSON.stringify(e??{})});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}/send): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] Notification send failed (HTTP ${n.status}): `+(r.error??"Unknown error"));return {sent:!!r.sent,appId:String(r.appId??this.cfg.appId),targetCount:Number(r.targetCount??0),successCount:Number(r.successCount??0),failureCount:Number(r.failureCount??0),invalidatedTokenCount:Number(r.invalidatedTokenCount??0),dryRun:!!r.dryRun}}async tokens(){let e;try{e=await fetch(`${this.baseUrl}/tokens`,{method:"GET",headers:this.headers});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}/tokens): ${t}`)}let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] Tokens fetch failed (HTTP ${e.status}): `+(n.error??"Unknown error"));return {appId:String(n.appId??this.cfg.appId),hasPushGateway:!!n.hasPushGateway,total:Number(n.total??0),tokens:Array.isArray(n.tokens)?n.tokens:[]}}};var C=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 n=e.serverUrl.replace(/^http/,"ws");this.wsUrl=`${n}/?appId=${encodeURIComponent(e.appId)}&adminKey=${encodeURIComponent(e.adminKey)}`,this._readyPromise=new Promise(r=>{this._readyResolve=r;}),this._connect();}ready(){return this._readyPromise}disconnect(){this.shouldReconnect=false,this.ws?.close(1e3,"Admin disconnect"),this.ws=null,this.connected=false;}send(e,n){return new Promise((r,t)=>{let i=T(),s={id:i,type:e,ts:Date.now(),...n},a=setTimeout(()=>{this.pendingAcks.delete(i),t(new Error(`[flare-admin] WS request timeout (${e})`));},1e4);this.pendingAcks.set(i,l=>{clearTimeout(a),l.type==="error"?t(new Error(`[flare-admin] Server error: ${l.message}`)):r(l);});let c=()=>this.ws?.send(JSON.stringify(s));this.connected&&this.ws?.readyState===O__default.default.OPEN?c():this.ready().then(c).catch(t);})}subscribe(e,n,r,t,i={}){let s=T(),a={baseId:s,liveId:s,collection:e,docId:n,structuredQuery:r,callback:t,options:i};this.activeSubscriptions.set(s,a),this.subscriptionErrorHandlers.set(s,new Set),this.subscriptionPermissionHandlers.set(s,new Set),this.activateSubscription(a);let c=()=>{let h=this.activeSubscriptions.get(s)?.liveId??s;this.activeSubscriptions.delete(s),this.subscriptions.delete(s),this.subscriptions.delete(h),this.subscriptionErrorHandlers.delete(s),this.subscriptionPermissionHandlers.delete(s),this.subscriptionLastErrors.delete(s),this.connected&&this.send("unsubscribe",{subscriptionId:h}).catch(()=>{});},l=c;return l.unsubscribe=c,l.onError=u=>{this.subscriptionErrorHandlers.get(s)?.add(u);let h=this.subscriptionLastErrors.get(s);if(h)try{u(h);}catch{}return l},l.onPermissionDenied=u=>{this.subscriptionPermissionHandlers.get(s)?.add(u);let h=this.subscriptionLastErrors.get(s);if(h?.permissionDenied)try{u(h);}catch{}return l},l.catch=u=>l.onError(u),l}activateSubscription(e){let n=()=>{this.subscriptions.set(e.liveId,e.callback);let r={collection:e.collection};e.docId&&(r.docId=e.docId),e.structuredQuery&&(r.query=e.structuredQuery),e.options.skipSnapshot&&(r.skipSnapshot=true),this.send("subscribe",r).then(t=>{let i=t.subscriptionId;if(i&&i!==e.liveId){let s=this.subscriptions.get(e.liveId);s&&(this.subscriptions.delete(e.liveId),this.subscriptions.set(i,s),e.liveId=i);}}).catch(()=>{this.subscriptions.delete(e.liveId),this.emitSubscriptionError(e.baseId,this.toSubscriptionError(new Error("Subscribe failed")));});};this.connected?n():this.ready().then(n).catch(r=>{this.emitSubscriptionError(e.baseId,this.toSubscriptionError(r));});}async replayActiveSubscriptions(){if(!this.connected)return;let e=Array.from(this.activeSubscriptions.values());for(let n of e){if(!this.activeSubscriptions.has(n.baseId))continue;let r=n.liveId;this.subscriptions.delete(r),n.liveId=n.baseId,r&&r!==n.baseId&&await this.send("unsubscribe",{subscriptionId:r}).catch(()=>{}),this.activateSubscription(n);}}toSubscriptionError(e){let n=e instanceof Error?e.message:String(e??"Unknown subscription error"),r=n.match(/^\[([^\]]+)\]\s*(.*)$/),t=r?.[1],i=(r?.[2]??n).trim()||n,s=t==="PERMISSION_DENIED"||n.includes("PERMISSION_DENIED");return {code:t,message:i,permissionDenied:s,raw:e}}emitSubscriptionError(e,n){this.subscriptionLastErrors.set(e,n);let r=this.subscriptionErrorHandlers.get(e);if(r)for(let t of r)try{t(n);}catch{}if(n.permissionDenied){let t=this.subscriptionPermissionHandlers.get(e);if(t)for(let i of t)try{i(n);}catch{}}}_connect(){this._readyPromise=new Promise(e=>{this._readyResolve=e;}),this.ws=new O__default.default(this.wsUrl),this.ws.on("message",e=>{let n;try{n=JSON.parse(e.toString());}catch{return}this._handle(n);}),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 n=e.type;if(n==="auth_ok"){this.connected||(this.connected=true,this.reconnectDelay=2e3,this._readyResolve(),this.replayActiveSubscriptions().catch(()=>{}));return}if(n==="ack"||n==="pong"||n==="call_response"){let r=e.correlationId??e.id,t=this.pendingAcks.get(r);t&&(t(e),this.pendingAcks.delete(r));return}if(n==="error"){let r=e.correlationId;if(r){let t=this.pendingAcks.get(r);t&&(t(e),this.pendingAcks.delete(r));let i=Array.from(this.activeSubscriptions.values()).find(s=>s.liveId===r||s.baseId===r);if(i){let s=this.toSubscriptionError(new Error(`[${String(e.code??"ERROR")}] ${String(e.message??"Unknown error")}`));this.emitSubscriptionError(i.baseId,s);}}return}if(n==="snapshot"||n==="change"){let r=e.subscriptionId,t=this.subscriptions.get(r);if(t){let i=Array.from(this.activeSubscriptions.values()).find(c=>c.liveId===r),s=String(e.collection??i?.collection??""),a=n==="change"&&e.operation==="delete"?null:m(this.cfg,s,e.data,i?.structuredQuery);t({subscriptionId:r,collection:s,docId:e.docId,data:a,type:n==="snapshot"?"snapshot":"change",operation:e.operation});}}}};var w=class{constructor(e,n,r){this.conn=e;this.collection=n;this.id=r;}onSnapshot(e){let n=()=>{};return n=this.conn.subscribe(this.collection,this.id,void 0,r=>{r.type==="snapshot"&&(e(r),n());}),n}};var b=class o{constructor(e,n){this.conn=e;this.name=n;this.sq={};}clone(e){let n=new o(this.conn,this.name);return n.sq={...this.sq,...e},n}normalizeFilterValue(e,n){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(n)?n:[n]:n}toQueryFilters(e){return S(e).map(r=>typeof r=="object"&&r!=null&&"field"in r&&"op"in r?{...r,value:this.normalizeFilterValue(r.op,r.value)}:r)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let n=[...this.sq.where??[]];if(n.length===0)return this.clone({where:[{or:e}]});let r=n[0];if(n.length===1&&typeof r=="object"&&r!=null&&"or"in r)return this.clone({where:[{or:[...r.or,...e]}]});let i=n.length===1?n[0]:{and:n};return this.clone({where:[{or:[i,...e]}]})}appendFilters(e,n){return n==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,n,r,t){return this.appendFilters([{field:e,op:n,value:this.normalizeFilterValue(n,r)}],t)}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,n){return this.appendOperatorFilter(e,"in",n,"and")}andIn(e,n){return this.appendOperatorFilter(e,"in",n,"and")}orIn(e,n){return this.appendOperatorFilter(e,"in",n,"or")}notIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}andNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}orNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"or")}arrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}andArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}orArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"or")}arrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}andArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}orArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"or")}some(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}andSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}orSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"or")}like(e,n){return this.appendOperatorFilter(e,"like",n,"and")}andLike(e,n){return this.appendOperatorFilter(e,"like",n,"and")}orLike(e,n){return this.appendOperatorFilter(e,"like",n,"or")}notLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}andNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}orNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"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,n="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:n}]})}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,n){return this.aggregate({fn:"sum",field:e,alias:n??`sum_${e}`})}avg(e,n){return this.aggregate({fn:"avg",field:e,alias:n??`avg_${e}`})}min(e,n){return this.aggregate({fn:"min",field:e,alias:n??`min_${e}`})}max(e,n){return this.aggregate({fn:"max",field:e,alias:n??`max_${e}`})}distinct(e,n){return this.aggregate({fn:"distinct",field:e,alias:n??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,n,r){return this.clone({having:[...this.sq.having??[],{field:e,op:n,value:r}]})}buildStructuredJoin(e,n){let r={from:String(e??""),localField:String(n?.source??""),foreignField:String(n?.target??""),as:String(n?.as??""),single:n?.single};return Array.isArray(n?.where)&&(r.where=n.where),Array.isArray(n?.orderBy)&&(r.orderBy=n.orderBy),typeof n?.limit=="number"&&(r.limit=n.limit),typeof n?.offset=="number"&&(r.offset=n.offset),Array.isArray(n?.select)&&(r.select=n.select),Array.isArray(n?.joins)&&(r.joins=n.joins.map(t=>this.buildStructuredJoin(String(t?.collection??""),t))),r}cloneStructuredJoin(e){let n={...e};return Array.isArray(e.where)&&(n.where=e.where.map(r=>({...r}))),Array.isArray(e.orderBy)&&(n.orderBy=e.orderBy.map(r=>({...r}))),Array.isArray(e.select)&&(n.select=[...e.select]),Array.isArray(e.joins)&&(n.joins=e.joins.map(r=>this.cloneStructuredJoin(r))),n}appendNestedJoinByAlias(e,n,r){for(let t of e){if(t.as===n)return t.joins=[...t.joins??[],r],true;if(Array.isArray(t.joins)&&this.appendNestedJoinByAlias(t.joins,n,r))return true}return false}parseRelationRef(e){let r=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(!r)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:r[1],collection:r[2],target:r[3],alias:r[4]}}join(e,n){let r=this.buildStructuredJoin(e,n);return this.clone({joins:[...this.sq.joins??[],r]})}joinNested(e,n,r){let t=String(e??"").trim();if(!t)throw new Error("joinNested requires parentAlias");let i=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(i.length===0)throw new Error(`joinNested parent alias "${t}" not found`);let s=this.buildStructuredJoin(n,r);if(!this.appendNestedJoinByAlias(i,t,s))throw new Error(`joinNested parent alias "${t}" not found`);return this.clone({joins:i})}Join(e,n){return this.join(e,n)}JoinNested(e,n,r){return this.joinNested(e,n,r)}withRelation(e,n={}){let r=this.parseRelationRef(e);return this.join(r.collection,{...n,source:r.source,target:r.target,as:n.as??r.alias??r.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 w(this.conn,this.name,e)}getRawQuery(){let e={...this.sq};return Array.isArray(this.sq.where)&&(e.where=this.sq.where.map(n=>({...n}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(n=>({...n}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(n=>({...n}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(n=>({...n}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(n=>this.cloneStructuredJoin(n))),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 n=this._buildSq(),r=()=>{};return r=this.conn.subscribe(this.name,void 0,n,t=>{t.type==="snapshot"&&(e(t),r());}),r}onDocAdded(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&r.operation==="insert"&&r.data!=null&&e(r.data,r.docId);},{skipSnapshot:true})}onDocUpdated(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&(r.operation==="update"||r.operation==="replace")&&r.data!=null&&e(r.data,r.docId);},{skipSnapshot:true})}onDocDeleted(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&r.operation==="delete"&&e(r.docId);},{skipSnapshot:true})}onDocChanged(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&e(r.data??null,r.docId,r.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 v=class{constructor(e){this._ws=new C(e);}collection(e){return new b(this._ws,e)}ready(){return this._ws.ready()}disconnect(){this._ws.disconnect();}};var E=class{constructor(e){this.cfg={defaultTtl:"24h",...e,serverUrl:e.serverUrl.replace(/\/$/,""),dataMapper:e.dataMapper??{}};}auth(){return this._auth??(this._auth=new A(this.cfg))}db(){return this._db??(this._db=new g(this.cfg))}connection(){return this._conn??(this._conn=new v(this.cfg))}notifications(){return this._notifications??(this._notifications=new y(this.cfg))}},R=new Map;function ye(o,e="[DEFAULT]"){if(R.has(e))return R.get(e);let n=new E(o);return R.set(e,n),n}function k(o="[DEFAULT]"){let e=R.get(o);if(!e)throw new Error(`[flare-admin] No app named "${o}" found. Call connectApp() before getApp().`);return e}function Ce(o="[DEFAULT]"){return k(o).auth()}function we(o="[DEFAULT]"){return k(o).db()}function be(o="[DEFAULT]"){return k(o).connection()}function ve(o="[DEFAULT]"){return k(o).notifications()}exports.AdminCollectionReference=p;exports.AdminDocumentReference=f;exports.AdminLiveCollectionReference=b;exports.AdminLiveDocumentReference=w;exports.FlareAdminApp=E;exports.FlareAdminAuthService=A;exports.FlareAdminConnection=v;exports.FlareAdminDbService=g;exports.FlareAdminNotificationsService=y;exports.FlareAdminWsConnection=C;exports.auth=Ce;exports.connectApp=ye;exports.connection=be;exports.db=we;exports.getApp=k;exports.notifications=ve;
|
package/dist/index.d.cts
CHANGED
|
@@ -14,7 +14,14 @@ interface FlareAdminConfig {
|
|
|
14
14
|
adminKey: string;
|
|
15
15
|
/** Default token TTL, e.g. "24h" */
|
|
16
16
|
defaultTtl?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional per-collection mapper registry for shaping inbound data.
|
|
19
|
+
* Keys can be base collection names or join aliases (`as`).
|
|
20
|
+
*/
|
|
21
|
+
dataMapper?: FlareAdminDataMapperRegistry;
|
|
17
22
|
}
|
|
23
|
+
type FlareAdminDataMapperFn<TRow = any, TMapped = any> = (row: TRow) => TMapped;
|
|
24
|
+
type FlareAdminDataMapperRegistry = Record<string, FlareAdminDataMapperFn<any, any>>;
|
|
18
25
|
interface CreateCustomTokenOptions {
|
|
19
26
|
role?: "user" | "admin" | "anon";
|
|
20
27
|
claims?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import q from'ws';function S(o){let e=[];for(let[n,r]of Object.entries(o))if(typeof r=="string"){let t=r.match(/^(>=|<=|!=|>|<|==)\s*(.+)$/);if(t){let[,i,s]=t;e.push({field:n,op:i,value:E(s.trim())});}else e.push({field:n,op:"==",value:r});}else Array.isArray(r)?e.push({field:n,op:"in",value:r}):e.push({field:n,op:"==",value:r});return e}function E(o){return isNaN(Number(o))?o==="true"?true:o==="false"?false:o==="null"?null:o:Number(o)}function T(){return Math.random().toString(36).slice(2,12)+Date.now().toString(36)}var f=class{constructor(e,n,r){this.cfg=e;this.collection=n;this.id=r;}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,n){let r;try{r=await fetch(this.baseUrl,{method:e,headers:this.headers,...n!==void 0?{body:JSON.stringify(n)}:{}});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (${e} ${this.baseUrl}): ${s}`)}let t=await r.json().catch(()=>({}));if(!r.ok)throw new Error(`[flare-admin] ${e} ${this.baseUrl} failed (HTTP ${r.status}): `+(t.error??"Unknown error"));return t}async get(){let e;try{e=await fetch(this.baseUrl,{headers:this.headers});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${t}`)}if(e.status===404)return null;let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${e.status}): `+(n.error??"Unknown error"));return n.data??null}async set(e){await this.request("PUT",e);}async update(e){await this.request("PATCH",e);}async delete(){await this.request("DELETE");}parent(){return new m(this.cfg,this.collection)}};var m=class o{constructor(e,n){this.cfg=e;this.name=n;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 n=new o(this.cfg,this.name);return n.sq={...this.sq,...e},n.opts={...this.opts},n}allowSensitiveAuthUserFields(e=true){let n=this.clone({});return n.opts.allowSensitiveAuthUserFields=!!e,n}normalizeFilterValue(e,n){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(n)?n:[n]:n}toQueryFilters(e){return S(e).map(r=>typeof r=="object"&&r!=null&&"field"in r&&"op"in r?{...r,value:this.normalizeFilterValue(r.op,r.value)}:r)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let n=[...this.sq.where??[]];if(n.length===0)return this.clone({where:[{or:e}]});let r=n[0];if(n.length===1&&typeof r=="object"&&r!=null&&"or"in r)return this.clone({where:[{or:[...r.or,...e]}]});let i=n.length===1?n[0]:{and:n};return this.clone({where:[{or:[i,...e]}]})}appendFilters(e,n){return n==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,n,r,t){return this.appendFilters([{field:e,op:n,value:this.normalizeFilterValue(n,r)}],t)}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,n){return this.appendOperatorFilter(e,"in",n,"and")}andIn(e,n){return this.appendOperatorFilter(e,"in",n,"and")}orIn(e,n){return this.appendOperatorFilter(e,"in",n,"or")}notIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}andNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}orNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"or")}arrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}andArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}orArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"or")}arrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}andArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}orArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"or")}some(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}andSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}orSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"or")}like(e,n){return this.appendOperatorFilter(e,"like",n,"and")}andLike(e,n){return this.appendOperatorFilter(e,"like",n,"and")}orLike(e,n){return this.appendOperatorFilter(e,"like",n,"or")}notLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}andNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}orNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"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,n="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:n}]})}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,n){return this.aggregate({fn:"sum",field:e,alias:n??`sum_${e}`})}avg(e,n){return this.aggregate({fn:"avg",field:e,alias:n??`avg_${e}`})}min(e,n){return this.aggregate({fn:"min",field:e,alias:n??`min_${e}`})}max(e,n){return this.aggregate({fn:"max",field:e,alias:n??`max_${e}`})}distinct(e,n){return this.aggregate({fn:"distinct",field:e,alias:n??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,n,r){return this.clone({having:[...this.sq.having??[],{field:e,op:n,value:r}]})}buildStructuredJoin(e,n){let r={from:String(e??""),localField:String(n?.source??""),foreignField:String(n?.target??""),as:String(n?.as??""),single:n?.single};return Array.isArray(n?.where)&&(r.where=n.where),Array.isArray(n?.orderBy)&&(r.orderBy=n.orderBy),typeof n?.limit=="number"&&(r.limit=n.limit),typeof n?.offset=="number"&&(r.offset=n.offset),Array.isArray(n?.select)&&(r.select=n.select),Array.isArray(n?.joins)&&(r.joins=n.joins.map(t=>this.buildStructuredJoin(String(t?.collection??""),t))),r}cloneStructuredJoin(e){let n={...e};return Array.isArray(e.where)&&(n.where=e.where.map(r=>({...r}))),Array.isArray(e.orderBy)&&(n.orderBy=e.orderBy.map(r=>({...r}))),Array.isArray(e.select)&&(n.select=[...e.select]),Array.isArray(e.joins)&&(n.joins=e.joins.map(r=>this.cloneStructuredJoin(r))),n}appendNestedJoinByAlias(e,n,r){for(let t of e){if(t.as===n)return t.joins=[...t.joins??[],r],true;if(Array.isArray(t.joins)&&this.appendNestedJoinByAlias(t.joins,n,r))return true}return false}parseRelationRef(e){let r=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(!r)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:r[1],collection:r[2],target:r[3],alias:r[4]}}join(e,n){let r=this.buildStructuredJoin(e,n);return this.clone({joins:[...this.sq.joins??[],r]})}joinNested(e,n,r){let t=String(e??"").trim();if(!t)throw new Error("joinNested requires parentAlias");let i=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(i.length===0)throw new Error(`joinNested parent alias "${t}" not found`);let s=this.buildStructuredJoin(n,r);if(!this.appendNestedJoinByAlias(i,t,s))throw new Error(`joinNested parent alias "${t}" not found`);return this.clone({joins:i})}Join(e,n){return this.join(e,n)}JoinNested(e,n,r){return this.joinNested(e,n,r)}withRelation(e,n={}){let r=this.parseRelationRef(e);return this.join(r.collection,{...n,source:r.source,target:r.target,as:n.as??r.alias??r.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(n=>({...n}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(n=>({...n}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(n=>({...n}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(n=>({...n}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(n=>this.cloneStructuredJoin(n))),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=new URL(this.baseUrl);e.searchParams.set("query",JSON.stringify(this.sq)),e.searchParams.set("allowSensitiveAuthUserFields",this.opts.allowSensitiveAuthUserFields?"1":"0");let n;try{n=await fetch(e.toString(),{headers:this.headers});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${n.status}): ${r.error??"Unknown error"}`);return r.data??[]}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 n;try{n=await fetch(this.baseUrl,{method:"POST",headers:this.headers,body:JSON.stringify(e)});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] POST ${this.baseUrl} failed (HTTP ${n.status}): ${r.error??"Unknown error"}`);return new f(this.cfg,this.name,r.id)}async deleteMany(){let e;try{e=await fetch(this.baseUrl,{method:"DELETE",headers:this.headers,body:JSON.stringify({where:this.sq.where??[]})});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (DELETE ${this.baseUrl}): ${t}`)}let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] DELETE ${this.baseUrl} failed (HTTP ${e.status}): ${n.error??"Unknown error"}`);return n.deleted??0}doc(e){return new f(this.cfg,this.name,e)}};var g=class{constructor(e){this.cfg=e;}collection(e){return new m(this.cfg,e)}};var A=class{constructor(e){this.cfg=e;}async createCustomToken(e,n={}){let r=`${this.cfg.serverUrl.replace(/\/$/,"")}/admin/token`,t=JSON.stringify({appId:this.cfg.appId,uid:String(e),role:n.role??"user",claims:n.claims??{},ttl:n.ttl??this.cfg.defaultTtl}),i;try{i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`},body:t});}catch(a){let p=a instanceof Error?a.message:String(a);throw new Error(`[flare-admin] Could not reach FlareServer at "${r}": ${p}
|
|
2
|
-
Make sure FLARE_URL is set correctly and the server is running.`)}let s;try{s=await i.json();}catch{throw new Error(`[flare-admin] Server returned non-JSON response (status ${i.status})`)}if(!i.ok)throw new Error(`[flare-admin] createCustomToken failed (HTTP ${i.status}): `+(s.error??"Unknown error"));if(typeof s.token!="string")throw new Error('[flare-admin] Server response missing "token" field');return s.token}};var y=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 n;try{n=await fetch(`${this.baseUrl}/send`,{method:"POST",headers:this.headers,body:JSON.stringify(e??{})});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}/send): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] Notification send failed (HTTP ${n.status}): `+(r.error??"Unknown error"));return {sent:!!r.sent,appId:String(r.appId??this.cfg.appId),targetCount:Number(r.targetCount??0),successCount:Number(r.successCount??0),failureCount:Number(r.failureCount??0),invalidatedTokenCount:Number(r.invalidatedTokenCount??0),dryRun:!!r.dryRun}}async tokens(){let e;try{e=await fetch(`${this.baseUrl}/tokens`,{method:"GET",headers:this.headers});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}/tokens): ${t}`)}let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] Tokens fetch failed (HTTP ${e.status}): `+(n.error??"Unknown error"));return {appId:String(n.appId??this.cfg.appId),hasPushGateway:!!n.hasPushGateway,total:Number(n.total??0),tokens:Array.isArray(n.tokens)?n.tokens:[]}}};var w=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 n=e.serverUrl.replace(/^http/,"ws");this.wsUrl=`${n}/?appId=${encodeURIComponent(e.appId)}&adminKey=${encodeURIComponent(e.adminKey)}`,this._readyPromise=new Promise(r=>{this._readyResolve=r;}),this._connect();}ready(){return this._readyPromise}disconnect(){this.shouldReconnect=false,this.ws?.close(1e3,"Admin disconnect"),this.ws=null,this.connected=false;}send(e,n){return new Promise((r,t)=>{let i=T(),s={id:i,type:e,ts:Date.now(),...n},a=setTimeout(()=>{this.pendingAcks.delete(i),t(new Error(`[flare-admin] WS request timeout (${e})`));},1e4);this.pendingAcks.set(i,c=>{clearTimeout(a),c.type==="error"?t(new Error(`[flare-admin] Server error: ${c.message}`)):r(c);});let p=()=>this.ws?.send(JSON.stringify(s));this.connected&&this.ws?.readyState===q.OPEN?p():this.ready().then(p).catch(t);})}subscribe(e,n,r,t,i={}){let s=T(),a={baseId:s,liveId:s,collection:e,docId:n,structuredQuery:r,callback:t,options:i};this.activeSubscriptions.set(s,a),this.subscriptionErrorHandlers.set(s,new Set),this.subscriptionPermissionHandlers.set(s,new Set),this.activateSubscription(a);let p=()=>{let h=this.activeSubscriptions.get(s)?.liveId??s;this.activeSubscriptions.delete(s),this.subscriptions.delete(s),this.subscriptions.delete(h),this.subscriptionErrorHandlers.delete(s),this.subscriptionPermissionHandlers.delete(s),this.subscriptionLastErrors.delete(s),this.connected&&this.send("unsubscribe",{subscriptionId:h}).catch(()=>{});},c=p;return c.unsubscribe=p,c.onError=u=>{this.subscriptionErrorHandlers.get(s)?.add(u);let h=this.subscriptionLastErrors.get(s);if(h)try{u(h);}catch{}return c},c.onPermissionDenied=u=>{this.subscriptionPermissionHandlers.get(s)?.add(u);let h=this.subscriptionLastErrors.get(s);if(h?.permissionDenied)try{u(h);}catch{}return c},c.catch=u=>c.onError(u),c}activateSubscription(e){let n=()=>{this.subscriptions.set(e.liveId,e.callback);let r={collection:e.collection};e.docId&&(r.docId=e.docId),e.structuredQuery&&(r.query=e.structuredQuery),e.options.skipSnapshot&&(r.skipSnapshot=true),this.send("subscribe",r).then(t=>{let i=t.subscriptionId;if(i&&i!==e.liveId){let s=this.subscriptions.get(e.liveId);s&&(this.subscriptions.delete(e.liveId),this.subscriptions.set(i,s),e.liveId=i);}}).catch(()=>{this.subscriptions.delete(e.liveId),this.emitSubscriptionError(e.baseId,this.toSubscriptionError(new Error("Subscribe failed")));});};this.connected?n():this.ready().then(n).catch(r=>{this.emitSubscriptionError(e.baseId,this.toSubscriptionError(r));});}async replayActiveSubscriptions(){if(!this.connected)return;let e=Array.from(this.activeSubscriptions.values());for(let n of e){if(!this.activeSubscriptions.has(n.baseId))continue;let r=n.liveId;this.subscriptions.delete(r),n.liveId=n.baseId,r&&r!==n.baseId&&await this.send("unsubscribe",{subscriptionId:r}).catch(()=>{}),this.activateSubscription(n);}}toSubscriptionError(e){let n=e instanceof Error?e.message:String(e??"Unknown subscription error"),r=n.match(/^\[([^\]]+)\]\s*(.*)$/),t=r?.[1],i=(r?.[2]??n).trim()||n,s=t==="PERMISSION_DENIED"||n.includes("PERMISSION_DENIED");return {code:t,message:i,permissionDenied:s,raw:e}}emitSubscriptionError(e,n){this.subscriptionLastErrors.set(e,n);let r=this.subscriptionErrorHandlers.get(e);if(r)for(let t of r)try{t(n);}catch{}if(n.permissionDenied){let t=this.subscriptionPermissionHandlers.get(e);if(t)for(let i of t)try{i(n);}catch{}}}_connect(){this._readyPromise=new Promise(e=>{this._readyResolve=e;}),this.ws=new q(this.wsUrl),this.ws.on("message",e=>{let n;try{n=JSON.parse(e.toString());}catch{return}this._handle(n);}),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 n=e.type;if(n==="auth_ok"){this.connected||(this.connected=true,this.reconnectDelay=2e3,this._readyResolve(),this.replayActiveSubscriptions().catch(()=>{}));return}if(n==="ack"||n==="pong"||n==="call_response"){let r=e.correlationId??e.id,t=this.pendingAcks.get(r);t&&(t(e),this.pendingAcks.delete(r));return}if(n==="error"){let r=e.correlationId;if(r){let t=this.pendingAcks.get(r);t&&(t(e),this.pendingAcks.delete(r));let i=Array.from(this.activeSubscriptions.values()).find(s=>s.liveId===r||s.baseId===r);if(i){let s=this.toSubscriptionError(new Error(`[${String(e.code??"ERROR")}] ${String(e.message??"Unknown error")}`));this.emitSubscriptionError(i.baseId,s);}}return}if(n==="snapshot"||n==="change"){let r=e.subscriptionId,t=this.subscriptions.get(r);t&&t({subscriptionId:r,collection:e.collection,docId:e.docId,data:e.data,type:n==="snapshot"?"snapshot":"change",operation:e.operation});}}};var C=class{constructor(e,n,r){this.conn=e;this.collection=n;this.id=r;}onSnapshot(e){let n=()=>{};return n=this.conn.subscribe(this.collection,this.id,void 0,r=>{r.type==="snapshot"&&(e(r),n());}),n}};var b=class o{constructor(e,n){this.conn=e;this.name=n;this.sq={};}clone(e){let n=new o(this.conn,this.name);return n.sq={...this.sq,...e},n}normalizeFilterValue(e,n){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(n)?n:[n]:n}toQueryFilters(e){return S(e).map(r=>typeof r=="object"&&r!=null&&"field"in r&&"op"in r?{...r,value:this.normalizeFilterValue(r.op,r.value)}:r)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let n=[...this.sq.where??[]];if(n.length===0)return this.clone({where:[{or:e}]});let r=n[0];if(n.length===1&&typeof r=="object"&&r!=null&&"or"in r)return this.clone({where:[{or:[...r.or,...e]}]});let i=n.length===1?n[0]:{and:n};return this.clone({where:[{or:[i,...e]}]})}appendFilters(e,n){return n==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,n,r,t){return this.appendFilters([{field:e,op:n,value:this.normalizeFilterValue(n,r)}],t)}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,n){return this.appendOperatorFilter(e,"in",n,"and")}andIn(e,n){return this.appendOperatorFilter(e,"in",n,"and")}orIn(e,n){return this.appendOperatorFilter(e,"in",n,"or")}notIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}andNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}orNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"or")}arrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}andArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}orArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"or")}arrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}andArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}orArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"or")}some(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}andSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}orSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"or")}like(e,n){return this.appendOperatorFilter(e,"like",n,"and")}andLike(e,n){return this.appendOperatorFilter(e,"like",n,"and")}orLike(e,n){return this.appendOperatorFilter(e,"like",n,"or")}notLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}andNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}orNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"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,n="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:n}]})}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,n){return this.aggregate({fn:"sum",field:e,alias:n??`sum_${e}`})}avg(e,n){return this.aggregate({fn:"avg",field:e,alias:n??`avg_${e}`})}min(e,n){return this.aggregate({fn:"min",field:e,alias:n??`min_${e}`})}max(e,n){return this.aggregate({fn:"max",field:e,alias:n??`max_${e}`})}distinct(e,n){return this.aggregate({fn:"distinct",field:e,alias:n??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,n,r){return this.clone({having:[...this.sq.having??[],{field:e,op:n,value:r}]})}buildStructuredJoin(e,n){let r={from:String(e??""),localField:String(n?.source??""),foreignField:String(n?.target??""),as:String(n?.as??""),single:n?.single};return Array.isArray(n?.where)&&(r.where=n.where),Array.isArray(n?.orderBy)&&(r.orderBy=n.orderBy),typeof n?.limit=="number"&&(r.limit=n.limit),typeof n?.offset=="number"&&(r.offset=n.offset),Array.isArray(n?.select)&&(r.select=n.select),Array.isArray(n?.joins)&&(r.joins=n.joins.map(t=>this.buildStructuredJoin(String(t?.collection??""),t))),r}cloneStructuredJoin(e){let n={...e};return Array.isArray(e.where)&&(n.where=e.where.map(r=>({...r}))),Array.isArray(e.orderBy)&&(n.orderBy=e.orderBy.map(r=>({...r}))),Array.isArray(e.select)&&(n.select=[...e.select]),Array.isArray(e.joins)&&(n.joins=e.joins.map(r=>this.cloneStructuredJoin(r))),n}appendNestedJoinByAlias(e,n,r){for(let t of e){if(t.as===n)return t.joins=[...t.joins??[],r],true;if(Array.isArray(t.joins)&&this.appendNestedJoinByAlias(t.joins,n,r))return true}return false}parseRelationRef(e){let r=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(!r)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:r[1],collection:r[2],target:r[3],alias:r[4]}}join(e,n){let r=this.buildStructuredJoin(e,n);return this.clone({joins:[...this.sq.joins??[],r]})}joinNested(e,n,r){let t=String(e??"").trim();if(!t)throw new Error("joinNested requires parentAlias");let i=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(i.length===0)throw new Error(`joinNested parent alias "${t}" not found`);let s=this.buildStructuredJoin(n,r);if(!this.appendNestedJoinByAlias(i,t,s))throw new Error(`joinNested parent alias "${t}" not found`);return this.clone({joins:i})}Join(e,n){return this.join(e,n)}JoinNested(e,n,r){return this.joinNested(e,n,r)}withRelation(e,n={}){let r=this.parseRelationRef(e);return this.join(r.collection,{...n,source:r.source,target:r.target,as:n.as??r.alias??r.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 C(this.conn,this.name,e)}getRawQuery(){let e={...this.sq};return Array.isArray(this.sq.where)&&(e.where=this.sq.where.map(n=>({...n}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(n=>({...n}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(n=>({...n}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(n=>({...n}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(n=>this.cloneStructuredJoin(n))),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 n=this._buildSq(),r=()=>{};return r=this.conn.subscribe(this.name,void 0,n,t=>{t.type==="snapshot"&&(e(t),r());}),r}onDocAdded(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&r.operation==="insert"&&r.data!=null&&e(r.data,r.docId);},{skipSnapshot:true})}onDocUpdated(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&(r.operation==="update"||r.operation==="replace")&&r.data!=null&&e(r.data,r.docId);},{skipSnapshot:true})}onDocDeleted(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&r.operation==="delete"&&e(r.docId);},{skipSnapshot:true})}onDocChanged(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&e(r.data??null,r.docId,r.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 v=class{constructor(e){this._ws=new w(e);}collection(e){return new b(this._ws,e)}ready(){return this._ws.ready()}disconnect(){this._ws.disconnect();}};var F=class{constructor(e){this.cfg={defaultTtl:"24h",...e,serverUrl:e.serverUrl.replace(/\/$/,"")};}auth(){return this._auth??(this._auth=new A(this.cfg))}db(){return this._db??(this._db=new g(this.cfg))}connection(){return this._conn??(this._conn=new v(this.cfg))}notifications(){return this._notifications??(this._notifications=new y(this.cfg))}},R=new Map;function de(o,e="[DEFAULT]"){if(R.has(e))return R.get(e);let n=new F(o);return R.set(e,n),n}function k(o="[DEFAULT]"){let e=R.get(o);if(!e)throw new Error(`[flare-admin] No app named "${o}" found. Call connectApp() before getApp().`);return e}function ue(o="[DEFAULT]"){return k(o).auth()}function he(o="[DEFAULT]"){return k(o).db()}function pe(o="[DEFAULT]"){return k(o).connection()}function me(o="[DEFAULT]"){return k(o).notifications()}export{m as AdminCollectionReference,f as AdminDocumentReference,b as AdminLiveCollectionReference,C as AdminLiveDocumentReference,F as FlareAdminApp,A as FlareAdminAuthService,v as FlareAdminConnection,g as FlareAdminDbService,y as FlareAdminNotificationsService,w as FlareAdminWsConnection,ue as auth,de as connectApp,pe as connection,he as db,k as getApp,me as notifications};
|
|
1
|
+
import L from'ws';function R(o){let e=[];for(let[n,r]of Object.entries(o))if(typeof r=="string"){let t=r.match(/^(>=|<=|!=|>|<|==)\s*(.+)$/);if(t){let[,i,s]=t;e.push({field:n,op:i,value:I(s.trim())});}else e.push({field:n,op:"==",value:r});}else Array.isArray(r)?e.push({field:n,op:"in",value:r}):e.push({field:n,op:"==",value:r});return e}function I(o){return isNaN(Number(o))?o==="true"?true:o==="false"?false:o==="null"?null:o:Number(o)}function F(){return Math.random().toString(36).slice(2,12)+Date.now().toString(36)}function B(o,e){let n=o.dataMapper;if(!n||typeof n!="object")return null;let r=n[e];return typeof r=="function"?r:null}function q(o,e,n){let r=B(o,e);if(!r||n==null||typeof n!="object")return n;try{return r(n)}catch{return n}}function E(o,e,n){if(!e||typeof e!="object"||!Array.isArray(n)||n.length===0)return e;let r=e;for(let t of n){let i=String(t?.as??"").trim();if(!i)continue;let s=Array.isArray(t?.joins)?t.joins:[],a=r[i],c=a;Array.isArray(a)?c=a.map(l=>E(o,l,s)):a&&typeof a=="object"&&(c=E(o,a,s)),c=Array.isArray(c)?c.map(l=>q(o,i,l)):q(o,i,c),c!==a&&(r===e&&(r={...r}),r[i]=c);}return r}function f(o,e,n,r){let t=Array.isArray(r?.joins)?r.joins:[],i=s=>{let a=E(o,s,t);return q(o,e,a)};return Array.isArray(n)?n.map(s=>i(s)):i(n)}var g=class{constructor(e,n,r){this.cfg=e;this.collection=n;this.id=r;}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,n){let r;try{r=await fetch(this.baseUrl,{method:e,headers:this.headers,...n!==void 0?{body:JSON.stringify(n)}:{}});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (${e} ${this.baseUrl}): ${s}`)}let t=await r.json().catch(()=>({}));if(!r.ok)throw new Error(`[flare-admin] ${e} ${this.baseUrl} failed (HTTP ${r.status}): `+(t.error??"Unknown error"));return t}async get(){let e;try{e=await fetch(this.baseUrl,{headers:this.headers});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${i}`)}if(e.status===404)return null;let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${e.status}): `+(n.error??"Unknown error"));return f(this.cfg,this.collection,n.data)??null}async set(e){await this.request("PUT",e);}async update(e){await this.request("PATCH",e);}async delete(){await this.request("DELETE");}parent(){return new m(this.cfg,this.collection)}};var m=class o{constructor(e,n){this.cfg=e;this.name=n;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 n=new o(this.cfg,this.name);return n.sq={...this.sq,...e},n.opts={...this.opts},n}allowSensitiveAuthUserFields(e=true){let n=this.clone({});return n.opts.allowSensitiveAuthUserFields=!!e,n}normalizeFilterValue(e,n){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(n)?n:[n]:n}toQueryFilters(e){return R(e).map(r=>typeof r=="object"&&r!=null&&"field"in r&&"op"in r?{...r,value:this.normalizeFilterValue(r.op,r.value)}:r)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let n=[...this.sq.where??[]];if(n.length===0)return this.clone({where:[{or:e}]});let r=n[0];if(n.length===1&&typeof r=="object"&&r!=null&&"or"in r)return this.clone({where:[{or:[...r.or,...e]}]});let i=n.length===1?n[0]:{and:n};return this.clone({where:[{or:[i,...e]}]})}appendFilters(e,n){return n==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,n,r,t){return this.appendFilters([{field:e,op:n,value:this.normalizeFilterValue(n,r)}],t)}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,n){return this.appendOperatorFilter(e,"in",n,"and")}andIn(e,n){return this.appendOperatorFilter(e,"in",n,"and")}orIn(e,n){return this.appendOperatorFilter(e,"in",n,"or")}notIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}andNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}orNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"or")}arrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}andArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}orArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"or")}arrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}andArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}orArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"or")}some(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}andSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}orSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"or")}like(e,n){return this.appendOperatorFilter(e,"like",n,"and")}andLike(e,n){return this.appendOperatorFilter(e,"like",n,"and")}orLike(e,n){return this.appendOperatorFilter(e,"like",n,"or")}notLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}andNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}orNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"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,n="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:n}]})}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,n){return this.aggregate({fn:"sum",field:e,alias:n??`sum_${e}`})}avg(e,n){return this.aggregate({fn:"avg",field:e,alias:n??`avg_${e}`})}min(e,n){return this.aggregate({fn:"min",field:e,alias:n??`min_${e}`})}max(e,n){return this.aggregate({fn:"max",field:e,alias:n??`max_${e}`})}distinct(e,n){return this.aggregate({fn:"distinct",field:e,alias:n??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,n,r){return this.clone({having:[...this.sq.having??[],{field:e,op:n,value:r}]})}buildStructuredJoin(e,n){let r={from:String(e??""),localField:String(n?.source??""),foreignField:String(n?.target??""),as:String(n?.as??""),single:n?.single};return Array.isArray(n?.where)&&(r.where=n.where),Array.isArray(n?.orderBy)&&(r.orderBy=n.orderBy),typeof n?.limit=="number"&&(r.limit=n.limit),typeof n?.offset=="number"&&(r.offset=n.offset),Array.isArray(n?.select)&&(r.select=n.select),Array.isArray(n?.joins)&&(r.joins=n.joins.map(t=>this.buildStructuredJoin(String(t?.collection??""),t))),r}cloneStructuredJoin(e){let n={...e};return Array.isArray(e.where)&&(n.where=e.where.map(r=>({...r}))),Array.isArray(e.orderBy)&&(n.orderBy=e.orderBy.map(r=>({...r}))),Array.isArray(e.select)&&(n.select=[...e.select]),Array.isArray(e.joins)&&(n.joins=e.joins.map(r=>this.cloneStructuredJoin(r))),n}appendNestedJoinByAlias(e,n,r){for(let t of e){if(t.as===n)return t.joins=[...t.joins??[],r],true;if(Array.isArray(t.joins)&&this.appendNestedJoinByAlias(t.joins,n,r))return true}return false}parseRelationRef(e){let r=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(!r)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:r[1],collection:r[2],target:r[3],alias:r[4]}}join(e,n){let r=this.buildStructuredJoin(e,n);return this.clone({joins:[...this.sq.joins??[],r]})}joinNested(e,n,r){let t=String(e??"").trim();if(!t)throw new Error("joinNested requires parentAlias");let i=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(i.length===0)throw new Error(`joinNested parent alias "${t}" not found`);let s=this.buildStructuredJoin(n,r);if(!this.appendNestedJoinByAlias(i,t,s))throw new Error(`joinNested parent alias "${t}" not found`);return this.clone({joins:i})}Join(e,n){return this.join(e,n)}JoinNested(e,n,r){return this.joinNested(e,n,r)}withRelation(e,n={}){let r=this.parseRelationRef(e);return this.join(r.collection,{...n,source:r.source,target:r.target,as:n.as??r.alias??r.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(n=>({...n}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(n=>({...n}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(n=>({...n}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(n=>({...n}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(n=>this.cloneStructuredJoin(n))),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=new URL(this.baseUrl);e.searchParams.set("query",JSON.stringify(this.sq)),e.searchParams.set("allowSensitiveAuthUserFields",this.opts.allowSensitiveAuthUserFields?"1":"0");let n;try{n=await fetch(e.toString(),{headers:this.headers});}catch(i){let s=i instanceof Error?i.message:String(i);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}): ${s}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] GET ${this.baseUrl} failed (HTTP ${n.status}): ${r.error??"Unknown error"}`);return f(this.cfg,this.name,r.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 n;try{n=await fetch(this.baseUrl,{method:"POST",headers:this.headers,body:JSON.stringify(e)});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] POST ${this.baseUrl} failed (HTTP ${n.status}): ${r.error??"Unknown error"}`);return new g(this.cfg,this.name,r.id)}async deleteMany(){let e;try{e=await fetch(this.baseUrl,{method:"DELETE",headers:this.headers,body:JSON.stringify({where:this.sq.where??[]})});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (DELETE ${this.baseUrl}): ${t}`)}let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] DELETE ${this.baseUrl} failed (HTTP ${e.status}): ${n.error??"Unknown error"}`);return n.deleted??0}doc(e){return new g(this.cfg,this.name,e)}};var A=class{constructor(e){this.cfg=e;}collection(e){return new m(this.cfg,e)}};var y=class{constructor(e){this.cfg=e;}async createCustomToken(e,n={}){let r=`${this.cfg.serverUrl.replace(/\/$/,"")}/admin/token`,t=JSON.stringify({appId:this.cfg.appId,uid:String(e),role:n.role??"user",claims:n.claims??{},ttl:n.ttl??this.cfg.defaultTtl}),i;try{i=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.cfg.adminKey}`},body:t});}catch(a){let c=a instanceof Error?a.message:String(a);throw new Error(`[flare-admin] Could not reach FlareServer at "${r}": ${c}
|
|
2
|
+
Make sure FLARE_URL is set correctly and the server is running.`)}let s;try{s=await i.json();}catch{throw new Error(`[flare-admin] Server returned non-JSON response (status ${i.status})`)}if(!i.ok)throw new Error(`[flare-admin] createCustomToken failed (HTTP ${i.status}): `+(s.error??"Unknown error"));if(typeof s.token!="string")throw new Error('[flare-admin] Server response missing "token" field');return s.token}};var C=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 n;try{n=await fetch(`${this.baseUrl}/send`,{method:"POST",headers:this.headers,body:JSON.stringify(e??{})});}catch(t){let i=t instanceof Error?t.message:String(t);throw new Error(`[flare-admin] Network error (POST ${this.baseUrl}/send): ${i}`)}let r=await n.json().catch(()=>({}));if(!n.ok)throw new Error(`[flare-admin] Notification send failed (HTTP ${n.status}): `+(r.error??"Unknown error"));return {sent:!!r.sent,appId:String(r.appId??this.cfg.appId),targetCount:Number(r.targetCount??0),successCount:Number(r.successCount??0),failureCount:Number(r.failureCount??0),invalidatedTokenCount:Number(r.invalidatedTokenCount??0),dryRun:!!r.dryRun}}async tokens(){let e;try{e=await fetch(`${this.baseUrl}/tokens`,{method:"GET",headers:this.headers});}catch(r){let t=r instanceof Error?r.message:String(r);throw new Error(`[flare-admin] Network error (GET ${this.baseUrl}/tokens): ${t}`)}let n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(`[flare-admin] Tokens fetch failed (HTTP ${e.status}): `+(n.error??"Unknown error"));return {appId:String(n.appId??this.cfg.appId),hasPushGateway:!!n.hasPushGateway,total:Number(n.total??0),tokens:Array.isArray(n.tokens)?n.tokens:[]}}};var w=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 n=e.serverUrl.replace(/^http/,"ws");this.wsUrl=`${n}/?appId=${encodeURIComponent(e.appId)}&adminKey=${encodeURIComponent(e.adminKey)}`,this._readyPromise=new Promise(r=>{this._readyResolve=r;}),this._connect();}ready(){return this._readyPromise}disconnect(){this.shouldReconnect=false,this.ws?.close(1e3,"Admin disconnect"),this.ws=null,this.connected=false;}send(e,n){return new Promise((r,t)=>{let i=F(),s={id:i,type:e,ts:Date.now(),...n},a=setTimeout(()=>{this.pendingAcks.delete(i),t(new Error(`[flare-admin] WS request timeout (${e})`));},1e4);this.pendingAcks.set(i,l=>{clearTimeout(a),l.type==="error"?t(new Error(`[flare-admin] Server error: ${l.message}`)):r(l);});let c=()=>this.ws?.send(JSON.stringify(s));this.connected&&this.ws?.readyState===L.OPEN?c():this.ready().then(c).catch(t);})}subscribe(e,n,r,t,i={}){let s=F(),a={baseId:s,liveId:s,collection:e,docId:n,structuredQuery:r,callback:t,options:i};this.activeSubscriptions.set(s,a),this.subscriptionErrorHandlers.set(s,new Set),this.subscriptionPermissionHandlers.set(s,new Set),this.activateSubscription(a);let c=()=>{let p=this.activeSubscriptions.get(s)?.liveId??s;this.activeSubscriptions.delete(s),this.subscriptions.delete(s),this.subscriptions.delete(p),this.subscriptionErrorHandlers.delete(s),this.subscriptionPermissionHandlers.delete(s),this.subscriptionLastErrors.delete(s),this.connected&&this.send("unsubscribe",{subscriptionId:p}).catch(()=>{});},l=c;return l.unsubscribe=c,l.onError=h=>{this.subscriptionErrorHandlers.get(s)?.add(h);let p=this.subscriptionLastErrors.get(s);if(p)try{h(p);}catch{}return l},l.onPermissionDenied=h=>{this.subscriptionPermissionHandlers.get(s)?.add(h);let p=this.subscriptionLastErrors.get(s);if(p?.permissionDenied)try{h(p);}catch{}return l},l.catch=h=>l.onError(h),l}activateSubscription(e){let n=()=>{this.subscriptions.set(e.liveId,e.callback);let r={collection:e.collection};e.docId&&(r.docId=e.docId),e.structuredQuery&&(r.query=e.structuredQuery),e.options.skipSnapshot&&(r.skipSnapshot=true),this.send("subscribe",r).then(t=>{let i=t.subscriptionId;if(i&&i!==e.liveId){let s=this.subscriptions.get(e.liveId);s&&(this.subscriptions.delete(e.liveId),this.subscriptions.set(i,s),e.liveId=i);}}).catch(()=>{this.subscriptions.delete(e.liveId),this.emitSubscriptionError(e.baseId,this.toSubscriptionError(new Error("Subscribe failed")));});};this.connected?n():this.ready().then(n).catch(r=>{this.emitSubscriptionError(e.baseId,this.toSubscriptionError(r));});}async replayActiveSubscriptions(){if(!this.connected)return;let e=Array.from(this.activeSubscriptions.values());for(let n of e){if(!this.activeSubscriptions.has(n.baseId))continue;let r=n.liveId;this.subscriptions.delete(r),n.liveId=n.baseId,r&&r!==n.baseId&&await this.send("unsubscribe",{subscriptionId:r}).catch(()=>{}),this.activateSubscription(n);}}toSubscriptionError(e){let n=e instanceof Error?e.message:String(e??"Unknown subscription error"),r=n.match(/^\[([^\]]+)\]\s*(.*)$/),t=r?.[1],i=(r?.[2]??n).trim()||n,s=t==="PERMISSION_DENIED"||n.includes("PERMISSION_DENIED");return {code:t,message:i,permissionDenied:s,raw:e}}emitSubscriptionError(e,n){this.subscriptionLastErrors.set(e,n);let r=this.subscriptionErrorHandlers.get(e);if(r)for(let t of r)try{t(n);}catch{}if(n.permissionDenied){let t=this.subscriptionPermissionHandlers.get(e);if(t)for(let i of t)try{i(n);}catch{}}}_connect(){this._readyPromise=new Promise(e=>{this._readyResolve=e;}),this.ws=new L(this.wsUrl),this.ws.on("message",e=>{let n;try{n=JSON.parse(e.toString());}catch{return}this._handle(n);}),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 n=e.type;if(n==="auth_ok"){this.connected||(this.connected=true,this.reconnectDelay=2e3,this._readyResolve(),this.replayActiveSubscriptions().catch(()=>{}));return}if(n==="ack"||n==="pong"||n==="call_response"){let r=e.correlationId??e.id,t=this.pendingAcks.get(r);t&&(t(e),this.pendingAcks.delete(r));return}if(n==="error"){let r=e.correlationId;if(r){let t=this.pendingAcks.get(r);t&&(t(e),this.pendingAcks.delete(r));let i=Array.from(this.activeSubscriptions.values()).find(s=>s.liveId===r||s.baseId===r);if(i){let s=this.toSubscriptionError(new Error(`[${String(e.code??"ERROR")}] ${String(e.message??"Unknown error")}`));this.emitSubscriptionError(i.baseId,s);}}return}if(n==="snapshot"||n==="change"){let r=e.subscriptionId,t=this.subscriptions.get(r);if(t){let i=Array.from(this.activeSubscriptions.values()).find(c=>c.liveId===r),s=String(e.collection??i?.collection??""),a=n==="change"&&e.operation==="delete"?null:f(this.cfg,s,e.data,i?.structuredQuery);t({subscriptionId:r,collection:s,docId:e.docId,data:a,type:n==="snapshot"?"snapshot":"change",operation:e.operation});}}}};var b=class{constructor(e,n,r){this.conn=e;this.collection=n;this.id=r;}onSnapshot(e){let n=()=>{};return n=this.conn.subscribe(this.collection,this.id,void 0,r=>{r.type==="snapshot"&&(e(r),n());}),n}};var v=class o{constructor(e,n){this.conn=e;this.name=n;this.sq={};}clone(e){let n=new o(this.conn,this.name);return n.sq={...this.sq,...e},n}normalizeFilterValue(e,n){return e==="in"||e==="not-in"||e==="array-contains-any"?Array.isArray(n)?n:[n]:n}toQueryFilters(e){return R(e).map(r=>typeof r=="object"&&r!=null&&"field"in r&&"op"in r?{...r,value:this.normalizeFilterValue(r.op,r.value)}:r)}appendAndFilters(e){return this.clone({where:[...this.sq.where??[],...e]})}appendOrFilters(e){let n=[...this.sq.where??[]];if(n.length===0)return this.clone({where:[{or:e}]});let r=n[0];if(n.length===1&&typeof r=="object"&&r!=null&&"or"in r)return this.clone({where:[{or:[...r.or,...e]}]});let i=n.length===1?n[0]:{and:n};return this.clone({where:[{or:[i,...e]}]})}appendFilters(e,n){return n==="or"?this.appendOrFilters(e):this.appendAndFilters(e)}appendOperatorFilter(e,n,r,t){return this.appendFilters([{field:e,op:n,value:this.normalizeFilterValue(n,r)}],t)}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,n){return this.appendOperatorFilter(e,"in",n,"and")}andIn(e,n){return this.appendOperatorFilter(e,"in",n,"and")}orIn(e,n){return this.appendOperatorFilter(e,"in",n,"or")}notIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}andNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"and")}orNotIn(e,n){return this.appendOperatorFilter(e,"not-in",n,"or")}arrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}andArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"and")}orArrayContains(e,n){return this.appendOperatorFilter(e,"array-contains",n,"or")}arrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}andArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"and")}orArrayContainsAny(e,n){return this.appendOperatorFilter(e,"array-contains-any",n,"or")}some(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}andSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"and")}orSome(e,n){return this.appendOperatorFilter(e,"elem-match",n,"or")}like(e,n){return this.appendOperatorFilter(e,"like",n,"and")}andLike(e,n){return this.appendOperatorFilter(e,"like",n,"and")}orLike(e,n){return this.appendOperatorFilter(e,"like",n,"or")}notLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}andNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"and")}orNotLike(e,n){return this.appendOperatorFilter(e,"not-like",n,"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,n="asc"){return this.clone({orderBy:[...this.sq.orderBy??[],{field:e,dir:n}]})}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,n){return this.aggregate({fn:"sum",field:e,alias:n??`sum_${e}`})}avg(e,n){return this.aggregate({fn:"avg",field:e,alias:n??`avg_${e}`})}min(e,n){return this.aggregate({fn:"min",field:e,alias:n??`min_${e}`})}max(e,n){return this.aggregate({fn:"max",field:e,alias:n??`max_${e}`})}distinct(e,n){return this.aggregate({fn:"distinct",field:e,alias:n??`distinct_${e}`})}groupBy(...e){return this.clone({groupBy:{fields:e}})}having(e,n,r){return this.clone({having:[...this.sq.having??[],{field:e,op:n,value:r}]})}buildStructuredJoin(e,n){let r={from:String(e??""),localField:String(n?.source??""),foreignField:String(n?.target??""),as:String(n?.as??""),single:n?.single};return Array.isArray(n?.where)&&(r.where=n.where),Array.isArray(n?.orderBy)&&(r.orderBy=n.orderBy),typeof n?.limit=="number"&&(r.limit=n.limit),typeof n?.offset=="number"&&(r.offset=n.offset),Array.isArray(n?.select)&&(r.select=n.select),Array.isArray(n?.joins)&&(r.joins=n.joins.map(t=>this.buildStructuredJoin(String(t?.collection??""),t))),r}cloneStructuredJoin(e){let n={...e};return Array.isArray(e.where)&&(n.where=e.where.map(r=>({...r}))),Array.isArray(e.orderBy)&&(n.orderBy=e.orderBy.map(r=>({...r}))),Array.isArray(e.select)&&(n.select=[...e.select]),Array.isArray(e.joins)&&(n.joins=e.joins.map(r=>this.cloneStructuredJoin(r))),n}appendNestedJoinByAlias(e,n,r){for(let t of e){if(t.as===n)return t.joins=[...t.joins??[],r],true;if(Array.isArray(t.joins)&&this.appendNestedJoinByAlias(t.joins,n,r))return true}return false}parseRelationRef(e){let r=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(!r)throw new Error(`Invalid relation format: "${e}". Expected "source.path->collection.target"`);return {source:r[1],collection:r[2],target:r[3],alias:r[4]}}join(e,n){let r=this.buildStructuredJoin(e,n);return this.clone({joins:[...this.sq.joins??[],r]})}joinNested(e,n,r){let t=String(e??"").trim();if(!t)throw new Error("joinNested requires parentAlias");let i=(this.sq.joins??[]).map(a=>this.cloneStructuredJoin(a));if(i.length===0)throw new Error(`joinNested parent alias "${t}" not found`);let s=this.buildStructuredJoin(n,r);if(!this.appendNestedJoinByAlias(i,t,s))throw new Error(`joinNested parent alias "${t}" not found`);return this.clone({joins:i})}Join(e,n){return this.join(e,n)}JoinNested(e,n,r){return this.joinNested(e,n,r)}withRelation(e,n={}){let r=this.parseRelationRef(e);return this.join(r.collection,{...n,source:r.source,target:r.target,as:n.as??r.alias??r.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 b(this.conn,this.name,e)}getRawQuery(){let e={...this.sq};return Array.isArray(this.sq.where)&&(e.where=this.sq.where.map(n=>({...n}))),Array.isArray(this.sq.orderBy)&&(e.orderBy=this.sq.orderBy.map(n=>({...n}))),Array.isArray(this.sq.aggregate)&&(e.aggregate=this.sq.aggregate.map(n=>({...n}))),Array.isArray(this.sq.having)&&(e.having=this.sq.having.map(n=>({...n}))),Array.isArray(this.sq.select)&&(e.select=[...this.sq.select]),Array.isArray(this.sq.joins)&&(e.joins=this.sq.joins.map(n=>this.cloneStructuredJoin(n))),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 n=this._buildSq(),r=()=>{};return r=this.conn.subscribe(this.name,void 0,n,t=>{t.type==="snapshot"&&(e(t),r());}),r}onDocAdded(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&r.operation==="insert"&&r.data!=null&&e(r.data,r.docId);},{skipSnapshot:true})}onDocUpdated(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&(r.operation==="update"||r.operation==="replace")&&r.data!=null&&e(r.data,r.docId);},{skipSnapshot:true})}onDocDeleted(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&r.operation==="delete"&&e(r.docId);},{skipSnapshot:true})}onDocChanged(e){let n=this._buildSq();return this.conn.subscribe(this.name,void 0,n,r=>{r.type==="change"&&e(r.data??null,r.docId,r.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 S=class{constructor(e){this._ws=new w(e);}collection(e){return new v(this._ws,e)}ready(){return this._ws.ready()}disconnect(){this._ws.disconnect();}};var O=class{constructor(e){this.cfg={defaultTtl:"24h",...e,serverUrl:e.serverUrl.replace(/\/$/,""),dataMapper:e.dataMapper??{}};}auth(){return this._auth??(this._auth=new y(this.cfg))}db(){return this._db??(this._db=new A(this.cfg))}connection(){return this._conn??(this._conn=new S(this.cfg))}notifications(){return this._notifications??(this._notifications=new C(this.cfg))}},k=new Map;function Ce(o,e="[DEFAULT]"){if(k.has(e))return k.get(e);let n=new O(o);return k.set(e,n),n}function T(o="[DEFAULT]"){let e=k.get(o);if(!e)throw new Error(`[flare-admin] No app named "${o}" found. Call connectApp() before getApp().`);return e}function we(o="[DEFAULT]"){return T(o).auth()}function be(o="[DEFAULT]"){return T(o).db()}function ve(o="[DEFAULT]"){return T(o).connection()}function Se(o="[DEFAULT]"){return T(o).notifications()}export{m as AdminCollectionReference,g as AdminDocumentReference,v as AdminLiveCollectionReference,b as AdminLiveDocumentReference,O as FlareAdminApp,y as FlareAdminAuthService,S as FlareAdminConnection,A as FlareAdminDbService,C as FlareAdminNotificationsService,w as FlareAdminWsConnection,we as auth,Ce as connectApp,ve as connection,be as db,T as getApp,Se as notifications};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -14,7 +14,14 @@ export interface FlareAdminConfig {
|
|
|
14
14
|
adminKey: string;
|
|
15
15
|
/** Default token TTL, e.g. "24h" */
|
|
16
16
|
defaultTtl?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional per-collection mapper registry for shaping inbound data.
|
|
19
|
+
* Keys can be base collection names or join aliases (`as`).
|
|
20
|
+
*/
|
|
21
|
+
dataMapper?: FlareAdminDataMapperRegistry;
|
|
17
22
|
}
|
|
23
|
+
export type FlareAdminDataMapperFn<TRow = any, TMapped = any> = (row: TRow) => TMapped;
|
|
24
|
+
export type FlareAdminDataMapperRegistry = Record<string, FlareAdminDataMapperFn<any, any>>;
|
|
18
25
|
export interface CreateCustomTokenOptions {
|
|
19
26
|
role?: "user" | "admin" | "anon";
|
|
20
27
|
claims?: Record<string, unknown>;
|