@pyric/cli 0.1.0-alpha.28 → 0.1.0-alpha.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assurance/.generated/conformance-verdicts.d.ts +16 -0
- package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
- package/dist/assurance/.generated/conformance-verdicts.js +16 -0
- package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
- package/dist/bridge/surface/methods/assurance/replaySession.d.ts.map +1 -1
- package/dist/bridge/surface/methods/assurance/replaySession.js +18 -6
- package/dist/bridge/surface/methods/assurance/replaySession.js.map +1 -1
- package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
- package/dist/conformance/.generated/can-i-use.js +1 -1
- package/dist/conformance/.generated/can-i-use.js.map +1 -1
- package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
- package/dist/conformance/.generated/conformance-docs.js +1 -1
- package/dist/conformance/.generated/conformance-docs.js.map +1 -1
- package/dist/serve/site-ui/_astro/{RulesCodeEditor.kBYcclwV.js → RulesCodeEditor.Cp_-FK3b.js} +1 -1
- package/dist/serve/site-ui/_astro/app.C--T2qDK.js +151 -0
- package/dist/serve/site-ui/_astro/app.DqyhRyrU.js +1 -0
- package/dist/serve/site-ui/_astro/{chess-showcase.CZe_3fJZ.js → chess-showcase.CVhCNUi_.js} +1 -1
- package/dist/serve/site-ui/_astro/{example-runtime.CXSZXHZF.js → example-runtime.zC1l-Yka.js} +1 -1
- package/dist/serve/site-ui/_astro/{sandbox-controls.Bp5PoonS.js → sandbox-controls.Bv6lfpIe.js} +39 -39
- package/dist/serve/site-ui/_astro/{seed.BO5CXcqE.js → seed.B4vza_Bv.js} +1 -1
- package/dist/serve/site-ui/_astro/{writes.DHSW22XD.js → writes.Bg0YEEA7.js} +1 -1
- package/dist/serve/site-ui/auth/index.html +1 -1
- package/dist/serve/site-ui/docs/database-compat/index.html +17 -17
- package/dist/serve/site-ui/docs/database-compat.md +17 -17
- package/dist/serve/site-ui/docs/index.json +10 -10
- package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +119 -119
- package/dist/serve/site-ui/docs/pyric-rules-reference-api.md +53 -53
- package/dist/serve/site-ui/docs/rules-compat/index.html +67 -3
- package/dist/serve/site-ui/docs/rules-compat.md +67 -3
- package/dist/serve/site-ui/docs/secure/rtdb-rules-standard-library/index.html +17 -4
- package/dist/serve/site-ui/docs/secure/rtdb-rules-standard-library.md +19 -4
- package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +4 -4
- package/dist/serve/site-ui/docs/secure/simulate-and-lint.md +8 -8
- package/dist/serve/site-ui/examples/chess/index.html +1 -1
- package/dist/serve/site-ui/firestore/index.html +1 -1
- package/dist/serve/site-ui/rtdb/index.html +1 -1
- package/dist/serve/site-ui/settings/index.html +1 -1
- package/dist/serve/site-ui/storage/index.html +1 -1
- package/dist/serve/site-ui/studio/index.html +1 -1
- package/dist/serve/site-ui/traffic/index.html +1 -1
- package/dist/serve/worker/client/rtdb-info.d.ts +0 -2
- package/dist/serve/worker/client/rtdb-info.d.ts.map +1 -1
- package/dist/serve/worker/client/rtdb-info.js +4 -17
- package/dist/serve/worker/client/rtdb-info.js.map +1 -1
- package/dist/serve/worker/client/rtdb-reads.d.ts.map +1 -1
- package/dist/serve/worker/client/rtdb-reads.js +3 -5
- package/dist/serve/worker/client/rtdb-reads.js.map +1 -1
- package/package.json +4 -4
- package/src/assurance/.generated/conformance-verdicts.ts +16 -0
- package/src/bridge/surface/methods/assurance/replaySession.ts +19 -6
- package/src/conformance/.generated/can-i-use.ts +1 -1
- package/src/conformance/.generated/conformance-docs.ts +1 -1
- package/src/serve/worker/client/rtdb-info.ts +4 -17
- package/src/serve/worker/client/rtdb-reads.ts +3 -4
- package/dist/serve/site-ui/_astro/app.BCNb6gMq.js +0 -1
- package/dist/serve/site-ui/_astro/app.DhoRPDdN.js +0 -147
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{s as f,
|
|
1
|
+
import{s as f,b8 as h,b9 as w}from"./sandbox-controls.Bv6lfpIe.js";import{s as o,d as s}from"./writes.Bg0YEEA7.js";import{s as n,a as A,b as y,u as m,r as d}from"./app.C--T2qDK.js";import"./index.DBy5LfQW.js";import"./index.DNyk7q8W.js";class g{static serverTimestamp(){return{__type:"serverTimestamp"}}static increment(a){return{__type:"increment",value:a}}static arrayUnion(...a){return{__type:"arrayUnion",values:a}}static arrayRemove(...a){return{__type:"arrayRemove",values:a}}static delete(){return{__type:"deleteField"}}}function p(){return g.serverTimestamp()}async function b(t){n.createUser(t,{uid:"alice",email:"alice@gmail.com",displayName:"Alice Nguyen",emailVerified:!0,photoUrl:"https://lh3.googleusercontent.com/a/alice",providerUserInfo:[{providerId:"google.com"}],customClaims:{plan:"pro"}}),n.createUser(t,{uid:"bob",email:"bob@example.com",password:"pyric-demo",displayName:"Bob Carter",emailVerified:!0,customClaims:{role:"editor"}}),n.createUser(t,{uid:"carol",email:"carol@example.com",displayName:"Carol Diaz",emailVerified:!1}),await A(t),await y(t)}const v=new w(37.7749,-122.4194);async function R(t){const a=Date.now(),i=e=>h.fromMillis(a-e*6e4),l=[{id:"alice",name:"Alice Nguyen",email:"alice@gmail.com",plan:"pro"},{id:"bob",name:"Bob Carter",email:"bob@example.com",plan:"free"},{id:"carol",name:"Carol Diaz",email:"carol@example.com",plan:"free"}];for(const e of l)await o(s(t,"users",e.id),{name:e.name,email:e.email,plan:e.plan,createdAt:p()});const r=["alice","bob","carol"],c=["Ship the redesign","Reply to carol","Buy milk","Draft the launch post","Review the rules","Plan offsite","Renew the domain","Read the spec","Fix the flaky test","Call the bank","Water the plants","Book the flights"];for(let e=0;e<c.length;e++){const u=r[e%r.length];await o(s(t,"notes",`note-${String(e+1).padStart(2,"0")}`),{title:c[e],done:e%3===0,pinned:e===0,priority:e%3+1,ownerId:u,ownerRef:`users/${u}`,tags:e%2===0?["work","urgent"]:["personal"],meta:{source:e%2===0?"app":"import",revision:e+1,flags:{starred:e%4===0,archived:!1}},location:e%3===0?v:null,createdAt:i(120-e*7),updatedAt:p()})}await o(s(t,"posts","post-hello"),{title:"Hello world",body:"First post from the seeded sandbox.",authorRef:"users/alice",published:!0,publishedAt:i(8)}),await o(s(t,"posts","post-draft"),{title:"Draft: roadmap",body:"Unpublished draft.",authorRef:"users/bob",published:!1})}async function C(t){const a=new TextEncoder,l=Uint8Array.from(atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="),r=>r.charCodeAt(0));await m(d(t,"avatars/alice.png"),l,{contentType:"image/png"}),await m(d(t,"notes/note-01/attachment.txt"),a.encode(`Attachment for the redesign note.
|
|
2
2
|
`),{contentType:"text/plain"})}const U=`rules_version = '2';
|
|
3
3
|
service cloud.firestore {
|
|
4
4
|
match /databases/{database}/documents {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as jt,b9 as ve,aO as ne,aB as f,ba as _t,bb as Tt,b7 as le,bc as Pt,bd as qt,be as M,aJ as K,bf as Vt,bg as Mt,ay as et,bh as Re,ax as Oe,bi as P,bj as ke,bk as j,aP as tt,bl as ce,bm as It,bn as $t,U as nt,G as w,aA as T,aL as zt,bo as Lt,bp as Qt,bq as Ut,P as Ee,F as I,br as Fe,C as Wt,D as Nt,b6 as Bt,b8 as Gt,bs as Ht,bt as Yt,N as Jt,ab as Xt,bu as Kt,Q as Zt,bv as en,bw as tn}from"./sandbox-controls.Bp5PoonS.js";const nn=Symbol.for("pyric.remote.sandbox");function Ce(e){return e!=null&&e[nn]===!0}let Z;function ts(e){Z=e}function st(e){return Z?.resolve(e,!1)}function sn(){if(!Z)throw new TypeError("No default sandbox app registry is installed - import and initialize pyric/app before calling a service factory without an app.");return Z.defaultApp()}function Me(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function rn(e,t,n,s){const r={collectionGroup:e.split("/").filter(Boolean).at(-1)??"",queryScope:t?"COLLECTION_GROUP":"COLLECTION",filters:[],orders:[]},i=(o,a)=>{const c=Me(o);if(!c||a>12||r.filters.length>=64){r.unsupported="This query exceeds the index checker’s supported limits.";return}if(c.kind==="and"&&Array.isArray(c.filters)){c.filters.forEach(u=>i(u,a+1));return}if(c.kind!=="where"||typeof c.field!="string"||typeof c.op!="string"){r.unsupported="This query uses a filter the index checker does not support yet.";return}r.filters.push({field:c.field,op:c.op})};n.forEach(o=>i(o,0));for(const o of s.slice(0,64)){const a=Me(o);if(!a||typeof a.field!="string"||a.direction!=="asc"&&a.direction!=="desc"){r.unsupported="This sort order cannot be checked yet.";continue}r.orders.push({field:a.field,direction:a.direction})}return s.length>64&&(r.unsupported="This query exceeds the index checker’s supported limits."),r}async function se(e,t,n){try{const s=await t();return e.complete(n?.()),s}catch(s){throw e.fail(),s}}const Ie=new Set;function on(e){return Ie.add(e),()=>{Ie.delete(e)}}function ns(e={}){return jt()}function $(e){return e.replace(/^\/+|\/+$/g,"").split("/")}function rt(e){return $(e).length%2===0&&$(e).length>0}function Ae(e){return $(e).length%2===1}function re(e){const t=$(e);return t[t.length-1]??""}function it(e){return $(e).slice(0,-1).join("/")}function ot(e,t){const n=t!==void 0,s=n?ve(t):void 0;return{id:e.id,ref:e,exists:n,data:()=>n?s:void 0,get:r=>ne(s,r)}}const $e=200,B=10,an=4;function cn(e){return e.length<=$e?{type:"string",value:e}:{type:"string",value:e.slice(0,$e),truncated:!0}}function at(e,t){const n=e*1e3+Math.floor(t/1e6);if(!Number.isFinite(n))return{type:"opaque"};try{return{type:"timestamp",iso:new Date(n).toISOString()}}catch{return{type:"opaque"}}}function un(e){if(typeof e!="object"||e===null)return{type:"opaque"};const t=e;return typeof t.path=="string"?{type:"reference",path:t.path}:t.type==="timestamp"&&typeof t.seconds=="number"&&typeof t.nanoseconds=="number"?at(t.seconds,t.nanoseconds):t.type==="geo-point"&&typeof t.latitude=="number"&&typeof t.longitude=="number"?{type:"geoPoint",latitude:t.latitude,longitude:t.longitude}:t.type==="bytes"&&Array.isArray(t.values)?{type:"bytes",length:t.values.length}:t.type==="vector"&&Array.isArray(t.values)?{type:"vector",length:t.values.length}:{type:"opaque"}}function he(e,t){if(e===null)return{type:"null"};if(typeof e=="string")return cn(e);if(typeof e=="number")return{type:"number",value:e};if(typeof e=="boolean")return{type:"boolean",value:e};if(typeof e!="object")return{type:"opaque"};if(t>=an)return{type:"opaque"};const n=e;if(n.type==="registered-firestore-value")return un(n.value);if(n.type==="timestamp"&&typeof n.seconds=="number"&&typeof n.nanoseconds=="number")return at(n.seconds,n.nanoseconds);if(n.type==="bytes"&&Array.isArray(n.values))return{type:"bytes",length:n.values.length};if(n.type==="array"&&Array.isArray(n.values)){const s=n.values.slice(0,B).map(r=>he(r,t+1));return n.values.length>B?{type:"array",values:s,truncated:!0}:{type:"array",values:s}}if(n.type==="map"&&Array.isArray(n.entries)){const s=n.entries.slice(0,B).filter(r=>Array.isArray(r)&&typeof r[0]=="string").map(([r,i])=>[r,he(i,t+1)]);return n.entries.length>B?{type:"map",entries:s,truncated:!0}:{type:"map",entries:s}}return{type:"opaque"}}function ze(e){return he(e,0)}function fe(e){if(e===null||typeof e!="object")return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(n=>fe(n)).join(",")}]`;const t=e;return`{${Object.keys(t).sort().map(n=>`${JSON.stringify(n)}:${fe(t[n])}`).join(",")}}`}function dn(e){if(e!==null&&typeof e=="object"){const n="type"in e&&e.type==="timestamp",s="seconds"in e&&typeof e.seconds=="number",r="nanoseconds"in e&&typeof e.nanoseconds=="number";return n&&s&&r}return!1}function E(e){return new f({code:"invalid-argument",message:e})}function pe(e,t,n,s=!1,r=!1){if(e===null||typeof e=="string"||typeof e=="boolean")return{comparison:e,execution:e};if(typeof e=="number")return{comparison:e,execution:e};if(typeof e>"u"||typeof e=="bigint"||typeof e=="function"||typeof e=="symbol")throw E(`Unsupported Firestore query value: ${typeof e}.`);if(typeof e!="object")throw E("Unsupported Firestore query value.");const u=_t(e);if(u!==void 0){const m=Tt(e);if(m!==void 0&&n!==void 0&&m!==n)throw E("Document reference belongs to a different Firestore database.");if(dn(u)){const p=Math.floor(u.nanoseconds/1e3)*1e3,g=new le(u.seconds,p);return{comparison:{type:"registered-firestore-value",value:Object.freeze({type:"timestamp",seconds:g.seconds,nanoseconds:p})},execution:g}}return{comparison:{type:"registered-firestore-value",value:u},execution:Pt(e)}}if(e instanceof Date){const m=e.getTime();if(!Number.isFinite(m))throw E("Invalid Date query value.");const S=Math.floor(m/1e3),p=Object.freeze({seconds:S,nanoseconds:Math.floor((m-S*1e3)*1e6)}),g={type:"timestamp",...p};return qt(p,g,()=>Object.freeze({...p})),{comparison:{type:"registered-firestore-value",value:g},execution:p}}if(e instanceof Uint8Array){const m=e.slice();return{comparison:{type:"bytes",values:Array.from(m)},execution:m}}if(t.has(e))throw E("Cyclic query operands are not Firestore values.");const b=Object.getPrototypeOf(e);if(b!==Object.prototype&&b!==null&&!Array.isArray(e))throw E("Firestore query maps must be plain objects.");t.add(e);try{if(Array.isArray(e)){if(r&&!s)throw E("Nested arrays are not supported.");const g=e.map(q=>pe(q,t,n,s,!0)),N=g.map(q=>q.execution);return M(N,K(e)),{comparison:{type:"array",values:g.map(q=>q.comparison)},execution:N}}const O=Object.keys(e).sort().map(p=>({key:p,captured:pe(e[p],t,n,s,!1)})),S=Object.fromEntries(O.map(({key:p,captured:g})=>[p,g.execution]));return M(S,K(e)),{comparison:{type:"map",entries:O.map(({key:p,captured:g})=>[p,g.comparison])},execution:S}}finally{t.delete(e)}}function ct(e,t,n=!1){try{const s=pe(e,new Set,t,n);return Object.freeze({kind:"canonical",value:s.comparison,executionValue:s.execution})}catch(s){if(s instanceof f)throw s;const r=s instanceof Error?s.message:String(s);throw E(`Invalid Firestore query value: ${r}`)}}function ut(e,t){return Vt(e.value,t.value)}const ln=["<","<=","==","!=",">=",">","in","not-in","array-contains","array-contains-any"],hn=new Set(ln);function fn(e,t){if(!hn.has(e))throw new f({code:"invalid-argument",message:"Unsupported Firestore filter operator."});if((e==="in"||e==="not-in"||e==="array-contains-any")&&!Array.isArray(t))throw new f({code:"invalid-argument",message:`Firestore ${e} filter requires an array operand.`})}function H(e,t){if(e.kind==="where"){fn(e.op,e.value);const s="comparisonValue"in e,r=e.op==="in"||e.op==="not-in",i=s?e.comparisonValue:ct(e.value,t,r);return Object.freeze({kind:"where",field:e.field,op:e.op,value:i.executionValue,comparisonValue:i})}return Object.freeze({kind:e.kind,filters:Object.freeze(e.filters.map(s=>H(s,t)))})}function G(e,t,n,s){const r=e.map(i=>ct(i,s));return Object.freeze({values:Object.freeze(r.map(i=>i.executionValue)),comparisonValues:Object.freeze(r),inclusive:t,fromSnapshot:n})}function dt(e,t){return e.length!==t.length?!1:e.every((n,s)=>{const r=t[s];return n.kind!==r.kind?!1:n.kind==="where"&&r.kind==="where"?n.field===r.field&&n.op===r.op&&ut(n.comparisonValue,r.comparisonValue):n.kind!=="where"&&r.kind!=="where"&&dt(n.filters,r.filters)})}function Le(e,t){return e===void 0||t===void 0?e===t:e.inclusive===t.inclusive&&e.comparisonValues.length===t.comparisonValues.length&&e.comparisonValues.every((n,s)=>ut(n,t.comparisonValues[s]))}function pn(e,t){return e.kind!==t.kind?!1:e.kind==="collection"&&t.kind==="collection"?e.path===t.path:e.kind==="collection-group"&&t.kind==="collection-group"&&e.collectionId===t.collectionId}function lt(e){return e.kind==="where"?Object.freeze({kind:e.kind,field:e.field,op:e.op,value:e.value}):Object.freeze({kind:e.kind,filters:Object.freeze(e.filters.map(lt))})}function Qe(e){if(e!==void 0)return Object.freeze({values:e.values,inclusive:e.inclusive,fromSnapshot:e.fromSnapshot})}function mn(e,t){return dt(e.filters,t.filters)&&e.orders.length===t.orders.length&&e.orders.every((n,s)=>{const r=t.orders[s];return n.field===r.field&&n.direction===r.direction})&&e.limitCount===t.limitCount&&e.limitFromEnd===t.limitFromEnd&&Le(e.start,t.start)&&Le(e.end,t.end)}const ht="__name__";function Ue(e,t){const n=e.data();if(n===void 0)throw new f({code:"not-found",message:`Snapshot-based cursors require an existing document — got an empty snapshot for ${e.id??"<unknown>"}.`});return t.map(s=>s.field===ht?e.ref:n[s.field])}class z{env;auth;collectionPath;clauses;orders;limitCount;limitFromEnd;start;end;bypassRules;documentRef;constructor(t){this.env=t.env,this.auth=t.auth,this.collectionPath=t.collectionPath,this.documentRef=t.documentRef,this.clauses=Object.freeze((t.clauses??[]).map(n=>H(n))),this.orders=Object.freeze((t.orders??[]).map(n=>Object.freeze({...n}))),this.limitCount=t.limitCount,this.limitFromEnd=t.limitFromEnd??!1,this.start=t.start===void 0?void 0:Object.freeze({...t.start,values:Object.freeze(t.start.comparisonValues.map(n=>n.executionValue)),comparisonValues:t.start.comparisonValues}),this.end=t.end===void 0?void 0:Object.freeze({...t.end,values:Object.freeze(t.end.comparisonValues.map(n=>n.executionValue)),comparisonValues:t.end.comparisonValues}),this.bypassRules=t.bypassRules??!1}where(t,n,s){return this.clone({clauses:[...this.clauses,H({kind:"where",field:t,op:n,value:s})]})}applyFilter(t){return this.clone({clauses:[...this.clauses,H(t)]})}orderBy(t,n="asc"){if(n!=="asc"&&n!=="desc")throw new f({code:"invalid-argument",message:"orderBy() direction must be 'asc' or 'desc'."});return this.clone({orders:[...this.orders,{field:t,direction:n}]})}limit(t){return We(t),this.clone({limitCount:t,limitFromEnd:!1})}limitToLast(t){return We(t),this.clone({limitCount:t,limitFromEnd:!0})}startCursor(t,n){return this.clone({start:G(this.normalizeExplicitCursorValues(t),n,!1)})}endCursor(t,n){return this.clone({end:G(this.normalizeExplicitCursorValues(t),n,!1)})}startCursorFromSnapshot(t,n){return this.clone({start:G(Ue(t,this.normalizedOrders()),n,!0)})}endCursorFromSnapshot(t,n){return this.clone({end:G(Ue(t,this.normalizedOrders()),n,!0)})}isStructurallyEqual(t){return t instanceof z?this.env===t.env&&this.bypassRules===t.bypassRules&&pn(this.queryScope(),t.queryScope())&&mn(this.comparableExecutionSpec(),t.comparableExecutionSpec()):!1}clone(t){return new z({env:this.env,auth:this.auth,collectionPath:this.collectionPath,documentRef:this.documentRef,clauses:t.clauses??this.clauses,orders:t.orders??this.orders,limitCount:"limitCount"in t?t.limitCount:this.limitCount,limitFromEnd:t.limitFromEnd??this.limitFromEnd,start:"start"in t?t.start:this.start,end:"end"in t?t.end:this.end,bypassRules:this.bypassRules})}queryScope(){return{kind:"collection",path:this.collectionPath}}sdkActivitySource(){const t=this.queryScope();return{service:"firestore",target:t.kind==="collection"?t.path:t.collectionId,key:fe({scope:t,query:this.activityQuery()}),isQuery:!0,indexQuery:rn(t.kind==="collection"?t.path:t.collectionId,t.kind==="collection-group",this.clauses,this.orders)}}readQueryRows(t){const n=t?.auth!==void 0?t.auth:this.auth;let s;try{s=this.env.runQuery({scope:this.queryScope(),auth:n,execution:this.executionSpec(),bypassRules:this.bypassRules,activityQuery:this.activityQuery()})}catch(r){const i=r?.simError;throw i?new f(i):r}if(!s.allowed)throw new f(s.error);return s.docs}activityQuery(){const t=s=>s.kind==="where"?{kind:"where",field:s.field,op:s.op,value:K(s.value),display:ze(s.comparisonValue.value)}:{kind:s.kind,filters:s.filters.map(t)},n=s=>s===void 0?null:{values:s.values.map(r=>K(r)),display:s.comparisonValues.map(r=>ze(r.value)),inclusive:s.inclusive,fromSnapshot:s.fromSnapshot};return{scope:this.activityScope(),filters:this.clauses.map(t),orderBy:this.orders.map(s=>({...s})),limit:this.limitCount??null,limitFromEnd:this.limitFromEnd,start:n(this.start),end:n(this.end)}}activityScope(){return{kind:"collection"}}normalizedOrders(){return Mt(this.executionSpec())}normalizeExplicitCursorValues(t){const n=this.orders;return t.map((s,r)=>{if(n[r]?.field!==ht)return s;if(typeof s!="string")throw new f({code:"invalid-argument",message:"Expected a string for a document ID cursor value."});const i=s.includes("/")?s:`${this.collectionPath}/${s}`;return this.documentRef(i)})}executionSpec(){const t={filters:Object.freeze(this.clauses.map(lt)),orders:this.orders,limitCount:this.limitCount,limitFromEnd:this.limitFromEnd,start:Qe(this.start),end:Qe(this.end)};return Object.freeze(t)}comparableExecutionSpec(){return{filters:this.clauses,orders:this.orders,limitCount:this.limitCount,limitFromEnd:this.limitFromEnd,start:this.start,end:this.end}}snapshotScope(){return this.queryScope()}snapshotConstraints(){return Object.freeze({execution:this.executionSpec(),activityQuery:this.activityQuery()})}async get(t){const s=this.readQueryRows(t).map(r=>{const i=this.documentRef(r.path),o=ve(r.data);return{id:i.id,ref:i,exists:!0,data:()=>o,get:a=>ne(o,a)}});return{size:s.length,empty:s.length===0,docs:s,forEach:et(s)}}async aggregate(t,n){const s=this.readQueryRows(n),r={};for(const i of Object.keys(t))r[i]=bn(t[i],s);return{data:()=>r}}}function yn(e,t){if(!t.includes("."))return e[t];let n=e;for(const s of t.split(".")){if(typeof n!="object"||n===null||Array.isArray(n))return;n=n[s]}return n}function bn(e,t){if(e.kind==="count")return t.length;let n=0,s=0;for(const r of t){const i=yn(r.data,e.field);typeof i=="number"&&Number.isFinite(i)&&(n+=i,s++)}return e.kind==="sum"?n:s===0?null:n/s}function We(e){if(!Number.isFinite(e))throw new f({code:"invalid-argument",message:"Query limit must be a finite number."})}function D(e,t){if(e.error)throw new f(e.error);const n=e.debugMessages.length>0?e.debugMessages.join("; "):"(no debug message)";throw new f(j("permission-denied",`${t}: ${n}`))}class gn{env;auth;bypassRules;collectionRef;id;path;constructor(t,n,s,r=!1,i){this.env=t,this.auth=n,this.bypassRules=r,this.collectionRef=i,this.path=s,this.id=re(s),M(this,Re("reference",s)),Oe(this,s,t)}get parent(){return this.collectionRef(it(this.path))}collection(t){return this.collectionRef(`${this.path}/${t}`)}async get(t){const n=this.env.execute({method:"get",path:this.path,auth:t?.auth!==void 0?t.auth:this.auth,bypassRules:this.bypassRules});n.allowed||D(n,"get denied");const s=n.data===void 0||n.data===null?void 0:n.data;return ot(this,s)}async create(t,n){const s=this.env.execute({method:"create",path:this.path,data:t,auth:n?.auth!==void 0?n.auth:this.auth,bypassRules:this.bypassRules});s.allowed||D(s,"create denied")}async set(t,n){const s=n?.auth!==void 0?n.auth:this.auth;if(n?.mergeFields!==void 0){const i=n.mergeFields.map(u=>String(u)),a=this.env.getDocument(this.path)===null?"create":"update",c=this.env.execute({method:a,path:this.path,data:t,auth:s,merge:{mergeFields:i},bypassRules:this.bypassRules});c.allowed||D(c,`set denied (as ${a})`);return}if(n?.merge===!0){const o=this.env.getDocument(this.path)===null?"create":"update",a=this.env.execute({method:o,path:this.path,data:t,auth:s,merge:!0,bypassRules:this.bypassRules});a.allowed||D(a,`set denied (as ${o})`);return}const r=this.env.execute({method:"set",path:this.path,data:t,auth:s,bypassRules:this.bypassRules});r.allowed||D(r,"set denied")}update(t,...n){const{fields:s,options:r}=P(t,n);return this.commitUpdate(s,r)}async commitUpdate(t,n){const s=this.env.execute({method:"update",path:this.path,data:ke(t),auth:n?.auth!==void 0?n.auth:this.auth,bypassRules:this.bypassRules});s.allowed||D(s,"update denied")}async delete(t){const n=this.env.execute({method:"delete",path:this.path,auth:t?.auth!==void 0?t.auth:this.auth,bypassRules:this.bypassRules});n.allowed||D(n,"delete denied")}}function V(e,t,n,s){return new gn(e,t,n,s,r=>new ft(e,t,r,s))}class ft extends z{id;path;constructor(t,n,s,r=!1){super({env:t,auth:n,collectionPath:s,bypassRules:r,documentRef:i=>V(t,n,i,r)}),this.path=s,this.id=re(s)}doc(t){const n=t??tt();return V(this.env,this.auth,`${this.path}/${n}`,this.bypassRules)}async add(t,n){const s=n?.auth!==void 0?n.auth:this.auth,{path:r,result:i}=this.env.createWithAutoId(this.path,t,s,this.bypassRules);if(!i.allowed){if(i.error)throw new f(i.error);let o="(no debug message)";throw i.debugMessages.length>0&&(o=i.debugMessages.join("; ")),new f(j("permission-denied",`set denied: ${o}`))}return V(this.env,this.auth,r,this.bypassRules)}}class De extends z{collectionId;constructor(t){super({...t,collectionPath:"",documentRef:n=>V(t.env,t.auth,n,t.bypassRules??!1)}),this.collectionId=t.collectionId}clone(t){return new De({env:this.env,auth:this.auth,collectionId:this.collectionId,clauses:t.clauses??this.clauses,orders:t.orders??this.orders,limitCount:"limitCount"in t?t.limitCount:this.limitCount,limitFromEnd:t.limitFromEnd??this.limitFromEnd,start:"start"in t?t.start:this.start,end:"end"in t?t.end:this.end,bypassRules:this.bypassRules})}queryScope(){return{kind:"collection-group",collectionId:this.collectionId}}activityScope(){return{kind:"collection-group"}}}class wn{env;auth;bypassRules;ops=[];constructor(t,n,s=!1){this.env=t,this.auth=n,this.bypassRules=s}create(t,n){return this.ops.push({method:"create",path:t.path,data:ce(n)}),this}set(t,n,s){const r={method:"set",path:t.path,data:ce(n)},i=s?.mergeFields;return i!==void 0?r.merge={mergeFields:[...i]}:s?.merge===!0&&(r.merge=!0),this.ops.push(r),this}update(t,n,...s){const{fields:r}=P(n,s);return this.ops.push({method:"update",path:t.path,data:ce(ke(r))}),this}delete(t){return this.ops.push({method:"delete",path:t.path}),this}async commit(t){if(this.ops.length===0)return;const s=t?.auth,r=s!==void 0,i=this.env.batch(this.ops,r?s:this.auth,this.bypassRules),{allowed:o,error:a}=i;if(o)return;if(a!==void 0)throw new f(a);const y=i.results.find(d=>!d.allowed)?.debugMessages.join("; ")??"batch denied";throw new f(j("permission-denied",`batch failed: ${y}`))}}function xn(e){return typeof e.where=="function"}class Sn{simTx;constructor(t){this.simTx=t}async get(t){if(xn(t)){const i=await t.get();return i.size>0&&this.simTx.getAll(...i.docs.map(a=>a.ref.path)),i}const r=this.simTx.get(t.path).data();return ot(t,r)}create(t,n){return this.simTx.create(t.path,n),this}set(t,n,s){const r=s?.mergeFields;if(r!==void 0)return this.simTx.set(t.path,n,{mergeFields:r}),this;const o=s?.merge===!0;return this.simTx.set(t.path,n,o?!0:void 0),this}update(t,n,...s){const{fields:r}=P(n,s);return this.simTx.update(t.path,ke(r)),this}delete(t){return this.simTx.delete(t.path),this}}class vn{env;auth;bypassRules;provenance;constructor(t,n,s=!1,r){this.env=t,this.auth=n,this.bypassRules=s,this.provenance=r}collection(t){if(!Ae(t))throw new f(j("invalid-argument",`collection path must have an odd number of segments: ${t}`));return new ft(this.env,this.auth,t,this.bypassRules)}doc(t){if(!rt(t))throw new f(j("invalid-argument",`document path must have an even number of segments: ${t}`));return V(this.env,this.auth,t,this.bypassRules)}collectionGroup(t){if(t.length===0||t.includes("/"))throw new f(j("invalid-argument",`collection group id must be a single non-empty segment with no '/': ${t}`));return new De({env:this.env,auth:this.auth,collectionId:t,bypassRules:this.bypassRules})}batch(){return new wn(this.env,this.auth,this.bypassRules)}async runTransaction(t,n){let s;try{s=await this.env.transaction(r=>{const i=new Sn(r);return t(i)},{auth:n?.auth!==void 0?n.auth:this.auth,bypassRules:this.bypassRules,provenance:this.provenance,maxAttempts:n?.maxAttempts})}catch(r){throw r instanceof It?new f(r.simError):r instanceof $t?new f(r.simError):r}if(!s.allowed){if(s.error)throw new f(s.error);const i=s.writes.find(o=>!o.allowed)?.debugMessages.join("; ")??"transaction denied at commit";throw new f(j("permission-denied",`transaction failed: ${i}`))}return s.returnValue}}function Rn(e,t){return new vn(e,t?.auth??null,t?.bypassRules??!1,t?.provenance)}const On=Symbol("pyric/sandbox/context"),kn=Symbol("pyric/sandbox/bypassRules");let me=null;function ss(e){me=e}const En=Symbol.for("pyric.firestore.modular-value");function Ne(e){return En in e}function Fn(e){const t=e;return typeof t.path=="string"&&t.path.length>0||typeof t.collectionPath=="string"&&t.collectionPath.length>0||typeof t.snapshotScope=="function"}function Cn(e){const t=e.trim();if(!t)return[];const n=t.indexOf(": ");if(n!==-1){const r=t.slice(n+2).trim().split("; ").map(i=>i.trim()).filter(i=>i.length>0);if(r.length>0)return r}return[t]}function Be(e,t){if(e instanceof f===!1)return e;const s=e.code;if(s==="permission-denied"===!1)return new w(s,e.message);const i={engine:"firestore",auth:t.auth,reasons:Cn(e.message)},o=e.simError;if(o!==void 0){if(o.queryProof!==void 0&&(i.queryProof=o.queryProof),o.request!==void 0){const l=o.request;i.request={method:l.method,path:l.path},l.resourceData!==void 0&&(i.request.resourceData=l.resourceData),l.updateMask!==void 0&&(i.request.updateMask=l.updateMask)}if(o.resource!==void 0&&(i.resource={data:o.resource.data,exists:o.resource.exists}),o.query!==void 0&&(i.query=o.query),o.rule!==void 0&&(i.rule=o.rule),o.repro!==void 0&&(i.repro=o.repro),o.remediation!==void 0)return new w({code:s,message:e.message,denialContext:i,remediation:o.remediation})}return new w(s,e.message,i)}function ee(e,t,n=!1){return new Proxy(e,{get(s,r,i){if(r===On)return t;if(r===kn)return n;if(r==="onSnapshot"&&me!==null&&!(r in s)&&Fn(s))return(...a)=>me(i,...a);const o=Reflect.get(s,r,i);return typeof o!="function"?o:function(...a){let c;try{const u=()=>o.apply(s,a);c=typeof t.sandbox.runWithProvenance=="function"?t.sandbox.runWithProvenance(nt(t.operationContext),u):u()}catch(u){throw Be(u,t)}return c instanceof Promise?c.then(u=>u&&typeof u=="object"&&!Ne(u)?ee(u,t,n):u).catch(u=>{throw Be(u,t)}):c&&typeof c=="object"&&!Ne(c)?ee(c,t,n):c}}})}function pt(e,t=!1){if(Ce(e.sandbox))throw new Error("pyric/sandbox/admin-firestore: internal — a remote sandbox context reached the local engine builder; remote dispatch should have handled it. Please report this.");const n=()=>Rn(T(e.sandbox),{auth:e.auth,bypassRules:t,provenance:nt(e.operationContext)});return{collection(s){return n().collection(s)},doc(s){return n().doc(s)},collectionGroup(s){return n().collectionGroup(s)},batch(){return n().batch()},runTransaction(s,r){return n().runTransaction(s,r)},setRules(s){return T(e.sandbox).deployRules(s)},seed(s){const r=T(e.sandbox);return r.seed({rules:r.getRules(),documents:s?.documents??{}})},snapshot(){return T(e.sandbox).snapshot()}}}function ye(e){if(e instanceof w)return e;if(e!==null&&typeof e=="object"){const t=e;if(typeof t.code=="string"&&typeof t.message=="string"){const n=t.denialContext!==null&&typeof t.denialContext=="object"?t.denialContext:void 0;return new w(t.code,t.message,n)}}return e}function k(e){return new w("invalid-argument",e)}async function x(e,t){try{return await e.sandbox.channel.op({...t,actAs:e.lens})}catch(n){throw ye(n)}}const An=new Set(["serverTimestamp","increment","arrayUnion","arrayRemove","deleteField"]);function Dn(e){return e!==null&&typeof e=="object"&&typeof e.__type=="string"&&An.has(e.__type)}function jn(e){switch(e.__type){case"serverTimestamp":return{__sentinel:"serverTimestamp"};case"increment":return{__sentinel:"increment",n:e.value};case"arrayUnion":return{__sentinel:"arrayUnion",values:e.values.map(v)};case"arrayRemove":return{__sentinel:"arrayRemove",values:e.values.map(v)};case"deleteField":return{__sentinel:"deleteField"}}}function v(e){if(e===null||typeof e!="object")return e;if(Dn(e))return jn(e);if(e instanceof le)return e.toJSON();if(e instanceof Date)return le.fromDate(e).toJSON();if(Array.isArray(e))return e.map(v);const t=Object.getPrototypeOf(e);if(t!==Object.prototype&&t!==null){const s=e.toJSON;if(typeof s=="function")return s.call(e);throw k(`remote Firestore: cannot serialize a ${t.constructor?.name??"class"} instance for the wire — use plain data, Timestamp, Date, or FieldValue sentinels.`)}const n={};for(const[s,r]of Object.entries(e))n[s]=v(r);return n}function _(e){return v(e)}function je(e){return e.map(t=>({path:[...t.path],value:v(t.value)}))}function be(e){return zt(JSON.parse(e.json),e.valueEncoding)}function mt(e){return ve(be(e))}function yt(e,t){const n=t.exists&&t.data?mt(t.data):void 0;return{id:e.id,ref:e,exists:t.exists,data:()=>n,get:s=>ne(n,s)}}function bt(e,t){const n=t.docs.map(s=>{const r=s.path??s.id,i=te(e,r),o=s.data?mt(s.data):{};return{id:i.id,ref:i,exists:!0,data:()=>o,get:a=>ne(o,a)}});return{size:n.length,empty:n.length===0,docs:n,forEach:et(n)}}const _e=Symbol("pyric/sandbox/admin-firestore/remoteSnapshotRegistrar");function rs(e){if(e===null||typeof e!="object")return;const t=e[_e];return typeof t=="function"?t:void 0}let ge=null;function is(e){ge=e}function gt(...e){if(ge===null)throw new w("failed-precondition","remote Firestore: onSnapshot is not wired yet — import pyric-admin/firestore (or pyric/sandbox/admin-firestore) before subscribing.");return ge(this,...e)}function wt(e,t,n,s,r){const i=n.includeMetadataChanges!==!0;let o;function a(u){const y=ye(u);r!==void 0?r(y):console.error("pyric remote Firestore: uncaught onSnapshot error:",y)}let c;try{c=e.sandbox.channel.subscribe({target:t,actAs:e.lens},u=>{if(s===void 0)return;let d;try{const l=u,b=l.docs;if(Array.isArray(b)){const m=b.map(O=>{const S=O.data,p=S!==void 0;return{path:O.path??O.id,data:p?be(S):{}}});d=Lt({path:xt(t)},m,{excludesMetadataChanges:i},o),o=m}else{const m=l.id;if(typeof m=="string"){const S=l.path??m,p=l.data,N=l.exists===!0&&p!==void 0?be(p):null;d=Qt(S,N)}}}catch(l){c(),a(l);return}d!==void 0&&s(d)},a)}catch(u){throw ye(u)}return c}function xt(e){switch(e.__ref){case"query":return xt(e.source);case"group":return e.collectionId;default:return e.path}}const St=Symbol("pyric/sandbox/admin-firestore/remoteQueryState");function _n(e){if(!(e===null||typeof e!="object"))return e[St]}function vt(e){return e.kind==="where"?(Rt(e.op),{kind:"where",field:e.field,op:e.op,value:v(e.value)}):{kind:e.kind,filters:e.filters.map(vt)}}const Tn=new Set(["<","<=","==","!=",">=",">","in","not-in","array-contains","array-contains-any"]);function Rt(e){if(!Tn.has(e))throw k(`invalid where operator: ${String(e)}`)}function Y(e){const t=[...e.filters];for(const n of e.orders)t.push({kind:"orderBy",field:n.field,direction:n.direction});return e.start&&t.push({kind:e.start.inclusive?"startAt":"startAfter",values:e.start.values.map(v)}),e.end&&t.push({kind:e.end.inclusive?"endAt":"endBefore",values:e.end.values.map(v)}),e.limitCount!==void 0&&t.push(e.limitFromEnd?{kind:"limitToLast",n:e.limitCount}:{kind:"limit",n:e.limitCount}),t.length===0?e.source:{__ref:"query",source:e.source,constraints:t}}function Ge(e,t,n){if(t.length===0)throw k(`${n}(snapshot) on a remote sandbox requires at least one explicit orderBy() clause — the relay protocol has no document-key cursor.`);if(t.some(r=>r.field==="__name__"))throw k(`${n}(snapshot) on a remote sandbox does not support orderBy('__name__') — the relay protocol has no document-key cursor, and __name__ is not a data field a value cursor can carry. Order by a real document field instead.`);const s=e.data();if(s===void 0)throw new w("not-found",`Snapshot-based cursors require an existing document — got an empty snapshot for ${e.id??"<unknown>"}.`);return t.map(r=>s[r.field])}function Te(e,t){const n=r=>Te(e,{...t,...r});return{[St]:t,where(r,i,o){return Rt(i),n({filters:[...t.filters,{kind:"where",field:r,op:i,value:v(o)}]})},applyFilter(r){return n({filters:[...t.filters,vt(r)]})},orderBy(r,i="asc"){return n({orders:[...t.orders,{field:r,direction:i}]})},limit(r){return n({limitCount:r,limitFromEnd:!1})},limitToLast(r){return n({limitCount:r,limitFromEnd:!0})},startCursor(r,i){return n({start:{values:[...r],inclusive:i}})},endCursor(r,i){return n({end:{values:[...r],inclusive:i}})},startCursorFromSnapshot(r,i){return n({start:{values:Ge(r,t.orders,i?"startAt":"startAfter"),inclusive:i}})},endCursorFromSnapshot(r,i){return n({end:{values:Ge(r,t.orders,i?"endAt":"endBefore"),inclusive:i}})},async get(r){J(t);const i=await x(e,{method:"getDocs",source:Y(t)});return bt(e,i)},async aggregate(r){J(t);const i=await x(e,{method:"aggregate",source:Y(t),spec:r});return{data:()=>i.data}},[_e]:(r,i,o)=>(J(t),wt(e,Y(t),r,i,o)),onSnapshot:gt}}function J(e){if(e.limitFromEnd&&e.orders.length===0)throw k("limitToLast() queries require at least one orderBy clause.")}function we(e,t){const n=Te(e,{source:{__ref:"collection",path:t},filters:[],orders:[],limitFromEnd:!1});return Object.assign(Object.create(Object.getPrototypeOf(n)),n,{id:re(t),path:t,doc(r){const i=r??tt();return te(e,`${t}/${i}`)},async add(r,i){const o=await x(e,{method:"addDoc",collectionPath:t,data:_(r)});return te(e,o.path)}})}function te(e,t){const n={id:re(t),path:t,get parent(){return we(e,it(t))},collection(s){const r=`${t}/${s}`;if(!Ae(r))throw k(`collection path must have an odd number of segments: ${r}`);return we(e,r)},async get(s){const r=await x(e,{method:"getDoc",path:t});return yt(n,r)},async create(s,r){await x(e,{method:"batchCommit",writes:[{method:"create",path:t,data:_(s)}]})},async set(s,r){await x(e,{method:"setDoc",path:t,data:_(s),...He(r)?{options:He(r)}:{}})},update(s,...r){const{fields:i}=P(s,r),o=je(i);return x(e,{method:"updateDoc",path:t,fields:o}).then(()=>{})},async delete(s){await x(e,{method:"deleteDoc",path:t})},[_e]:(s,r,i)=>wt(e,{__ref:"doc",path:t},s,r,i),onSnapshot:gt};return n}function He(e){if(!e)return;const t={};return e.merge!==void 0&&(t.merge=e.merge),e.mergeFields!==void 0&&(t.mergeFields=[...e.mergeFields]),t.merge!==void 0||t.mergeFields!==void 0?t:void 0}function Ot(e){if(e===void 0)return;const t={};return"merge"in e&&e.merge!==void 0&&(t.merge=e.merge),"mergeFields"in e&&e.mergeFields!==void 0&&(t.mergeFields=e.mergeFields.map(n=>String(n))),t}function Pn(e){const t=[];let n=!1;const s={create(i,o){return r(),t.push({method:"create",path:i.path,data:_(o)}),s},set(i,o,a){r();const c={method:"set",path:i.path,data:_(o)},u=Ot(a);return u!==void 0&&(c.options=u),t.push(c),s},update(i,o,...a){r();const{fields:c}=P(o,a);return t.push({method:"update",path:i.path,fields:je(c)}),s},delete(i){return r(),t.push({method:"delete",path:i.path}),s},async commit(i){r(),n=!0,await x(e,{method:"batchCommit",writes:t})}};function r(){if(n)throw new w("failed-precondition","WriteBatch has already been committed.")}return s}const qn=5;async function Vn(e,t,n=qn){for(let s=0;s<n;s++){const r=[],i=[],o=()=>{if(i.length>0)throw new w("failed-precondition",Ut)},a={get(d){o();const h=_n(d);return h!==void 0?u(h):c(d)},create(d,h){return i.push({method:"create",path:d.path,data:_(h)}),a},set(d,h,l){const b={method:"set",path:d.path,data:_(h)},A=Ot(l);return A!==void 0&&(b.options=A),i.push(b),a},update(d,h,...l){const{fields:b}=P(h,l);return i.push({method:"update",path:d.path,fields:je(b)}),a},delete(d){return i.push({method:"delete",path:d.path}),a}};async function c(d){const h=await x(e,{method:"getDoc",path:d.path});return r.push({path:h.path??d.path,data:h.exists&&h.data?h.data:null}),yt(d,h)}async function u(d){J(d);const h=await x(e,{method:"getDocs",source:Y(d)});for(const l of h.docs)r.push({path:l.path??l.id,data:l.data??null});return bt(e,h)}const y=await t(a);try{return await x(e,{method:"txnCommit",reads:r,writes:i}),y}catch(d){if(d instanceof w&&d.code==="aborted")continue;throw d}}throw new w("aborted",`Transaction failed after ${n} attempts due to repeated conflicts. Another writer is concurrently updating the same documents.`)}function ue(e,t){return new w("unimplemented",`SandboxFirestore.${e} is not available on a remote sandbox — its return value is synchronous and the data lives in the browser worker. ${t}`)}function kt(e,t){const n={sandbox:e,lens:t};return{collection(s){if(!Ae(s))throw k(`collection path must have an odd number of segments: ${s}`);return we(n,s)},doc(s){if(!rt(s))throw k(`document path must have an even number of segments: ${s}`);return te(n,s)},collectionGroup(s){if(s.length===0||s.includes("/"))throw k(`collection group id must be a single non-empty segment with no '/': ${s}`);return Te(n,{source:{__ref:"group",collectionId:s},filters:[],orders:[],limitFromEnd:!1})},batch(){return Pn(n)},runTransaction(s,r){return Vn(n,s,r?.maxAttempts)},setRules(){throw ue("setRules","Deploy rules asynchronously through the relay instead: `await sandbox.channel.op({ method: 'setFirestoreRules', source })`.")},seed(){throw ue("seed","The relay has no atomic seed op; write seed docs through this handle (`db.doc(path).set(data)` / `db.batch()`), or drive `sandbox.channel.op({ method: 'admin.setDocument', path, data })` per document.")},snapshot(){throw ue("snapshot","Read the worker state asynchronously instead: `await sandbox.channel.op({ method: 'admin.readState' })`.")}}}const Ye=new WeakMap;function Et(e){const t=Ye.get(e);if(t)return t;const n=Ce(e.sandbox)?kt(e.sandbox,Mn(e.auth)):ee(pt(e),e);return Ye.set(e,n),n}function Mn(e){if(e==null)return{mode:"anon"};const t={mode:"as",uid:e.uid};return e.token!==void 0&&(t.token=e.token),e.tenant!==void 0&&(t.tenant=e.tenant),t}const Je=new WeakMap;function In(e){const t=$n(e)?e:e.withAuth(null),n=Je.get(t);if(n)return n;const s=t.operationContext.authLens.mode==="admin"?t:Ee(t,{source:t.operationContext.source,authLens:{mode:"admin"},...t.operationContext.planId===void 0?{}:{planId:t.operationContext.planId}}),r=Ce(s.sandbox)?kt(s.sandbox,{mode:"admin"}):ee(pt(s,!0),s,!0);return Je.set(t,r),r}function $n(e){return e!==null&&typeof e=="object"&&"sandbox"in e&&typeof e.withAuth=="function"}function zn(e){return e instanceof Error&&"code"in e&&typeof e.code=="string"}function Ln(e){if(e instanceof I||!zn(e))return e;const t={};e.denialContext!==void 0&&(t.denialContext=e.denialContext),e.remediation!==void 0&&(t.remediation=e.remediation);const n=new I(e.code,e.message,Object.keys(t).length===0?void 0:t);e.denialContext!==void 0&&Object.assign(n,{denialContext:e.denialContext}),e.remediation!==void 0&&Object.assign(n,{remediation:e.remediation});for(const s of["request","resource","query","rule","queryProof"])e[s]!==void 0&&Object.assign(n,{[s]:e[s]});return n}async function ie(e){try{return await e()}catch(t){throw Ln(t)}}class Qn{static[Symbol.hasInstance](t){return!!(t&&typeof t=="object"&&"id"in t&&"path"in t&&typeof t.path=="string"&&!("docs"in t)&&!("exists"in t)&&!("doc"in t)&&!("add"in t))}}function Ft(e,t){const n=R(e);if(t===null)return n;const r=C(e),i=Ve(n,r,t);return Fe(n,i),xe(i)}function xe(e){function t(n){return Ft(e,n)}return Object.assign(e,{withConverter:t})}function X(e,t,n,s=null){function r(c){return c===null?Xe(a,null):Xe(a,c)}const i=R(e),o=Ve(i,n,s),a=Object.assign(o,{withConverter:r});return M(a,Re("reference",t)),Oe(i,t,n),Fe(i,a),a}function os(e,...t){const n=C(e),s=F in e,r=s?void 0:qe(e),i=U(n);if(s){if(t.length===0)throw new TypeError("doc(db, path) requires at least one path segment.");const l=t.join("/"),b=i.doc(l),A=Q(b,n,m=>m.doc(l));return X(A,l,n)}const o=R(e),a=t.length===0;let c;a?c=o.doc():c=o.doc(t.join("/"));const u=c.path,y=Q(c,n,h=>h.doc(u));return r!=null?X(y,u,n,r):X(y,u,n)}function as(e,...t){const n=C(e),s=F in e;if(t.length===0)throw new TypeError("collection() requires at least one path segment.");if(s){const c=t.join("/"),u=xe(U(n).collection(c));return Q(u,n,y=>y.collection(c))}const r=R(e),i=t.join("/"),o=xe(r.collection(i)),a=o.path;return Q(o,n,c=>c.collection(a))}function Xe(e,t){const n=C(e),s=R(e);return s instanceof Qn?X(s,s.path,n,t):Ft(e,t)}class Un{started=!1;networkEnabled=!0;persistenceMode;pending=new Set;cachedPaths=new Set;cachedQueries=new WeakSet;syncObservers=new Set;syncScheduled=!1;markStarted(){this.started=!0}enablePersistence(t){if(this.started||this.persistenceMode!==void 0)throw new I("failed-precondition","Firestore has already been started and persistence can no longer be enabled.");this.persistenceMode=t,this.started=!0}disableNetwork(){this.started=!0,this.networkEnabled=!1}async enableNetwork(){this.started=!0,this.networkEnabled=!0;for(const t of this.pending)t.localDone&&t.resolve(t.value);await Promise.all([...this.pending].map(t=>t.promise))}runWrite(t,n){if(this.started=!0,n&&this.cachedPaths.add(n),this.networkEnabled)return t();let s,r;const i=new Promise((a,c)=>{s=a,r=c}),o={path:n,promise:i,localDone:!1,resolve:s,reject:r};return this.pending.add(o),t().then(a=>{o.localDone=!0,o.value=a,this.networkEnabled&&o.resolve(a)},a=>o.reject(a)),i.then(()=>this.pending.delete(o),()=>this.pending.delete(o)),i}waitForPendingWrites(){this.started=!0;const t=[...this.pending].map(n=>n.promise);return Promise.all(t).then(()=>{})}cachePath(t){this.started=!0,this.cachedPaths.add(t)}assertPathCached(t){if(this.started=!0,!this.cachedPaths.has(t))throw new I("unavailable","Failed to get document from cache. (However, this document may exist on the server.)")}cacheQuery(t){this.started=!0,this.cachedQueries.add(t)}hasCachedQuery(t){return this.started=!0,this.cachedQueries.has(t)||this.cachedPaths.size>0}snapshotMetadata(t){return Object.freeze({fromCache:!this.networkEnabled,hasPendingWrites:[...this.pending].some(n=>n.path===t)})}querySnapshotMetadata(){return Object.freeze({fromCache:!this.networkEnabled,hasPendingWrites:this.pending.size>0})}addSnapshotsInSyncObserver(t){return this.syncObservers.add(t),t(),()=>this.syncObservers.delete(t)}notifySnapshotDelivered(){this.syncScheduled||this.syncObservers.size===0||(this.syncScheduled=!0,queueMicrotask(()=>{this.syncScheduled=!1;for(const t of[...this.syncObservers])t()}))}}const Ke=new WeakMap;function L(e){let t=Ke.get(e);return t||(t=new Un,Ke.set(e,t)),t}function oe(e,t,n,s,r){const i=R(t),o=typeof i.sdkActivitySource=="function"?i.sdkActivitySource():{service:"firestore",target:i.path,key:`doc:${i.path}`};return Wt.begin({app:e.activityApp??e,source:o,method:n,kind:s,owners:Nt(r?.owner,r?.owners)})}const F=Symbol("pyric/firestore/target");function U(e){return e.kind==="sandbox"?e.db:e.getDb()}const ae=new WeakMap;function Wn(e,t){return ae.set(e,t),e}const W=new WeakMap;function Nn(e,t,n){return ae.set(e,t),W.set(e,n),e}function Pe(e,t){const n=R(t);if(e.kind==="sandbox")return n;const s=W.get(n);if(!s)throw new TypeError("pyric/firestore: live ref missing rebuild closure — was it produced by a factory in this package?");return s(U(e))}function Bn(e,t){const n=R(t);if(e.kind==="sandbox")return n;const s=W.get(n);if(!s)throw new TypeError("pyric/firestore: live collection ref missing rebuild closure.");return s(U(e))}function cs(e,t){const n=R(t);if(e.kind==="sandbox")return n;const s=W.get(n);if(!s)throw new TypeError("pyric/firestore: live query missing rebuild closure.");return s(U(e))}function Q(e,t,n){return t.kind==="sandbox-live"?Nn(e,t,n):Wn(e,t)}function us(e){const t=R(e),n=W.get(t);return n||(()=>t)}function C(e){const t=Gn(e);return t.assertUsable?.(),t}function Gn(e){let t;if(F in e?t=e[F]:t=ae.get(e),!t)throw new TypeError("pyric/firestore: unrecognized reference — was it produced by a factory in this package?");return t}const Hn=Symbol.for("pyric.firestore.modular-value"),Ct=new WeakMap,At=new WeakMap;function qe(e){return Ct.get(e)}function R(e){return At.get(e)??e}function Ve(e,t,n){const s={id:e.id??"",path:e.path??""};return Object.defineProperty(s,Hn,{value:!0}),Ct.set(s,n),At.set(s,e),ae.set(s,t),s}function Yn(e){return e instanceof Kt?Array.from(e.value):null}function Se(e,t){if(e instanceof Yt)return t?.create(e.path)??e;if(e instanceof Jt)return Bt.fromUint8Array(e.data);if(e instanceof Xt)return new Gt(e.lat,e.lng);const i=Yn(e);if(i!==null)return Ht(i);if(Array.isArray(e))return e.map(u=>Se(u,t));if(e!==null&&typeof e=="object"){const u=Object.getPrototypeOf(e);if(u===Object.prototype||u===null){const d={};for(const[h,l]of Object.entries(e))d[h]=Se(l,t);return d}}return e}function ds(e,t){if(e!==void 0)return Se(e,t)}function Jn(e){if(e===void 0)return Jn(sn());const t=st(e);if(t)return t.service("firestore/default",()=>{const{sandbox:n,session:s}=t,r=de();t.onDelete(r.terminate);const i=t.authScope;i&&(r.own(s.onCurrentUserChanged(a=>{T(n).reevaluateLiveListeners(a,i)})),r.own(on(a=>{const c=a?.mode==="anon"?null:a?.mode==="as"?{uid:a.uid,...a.tenant?{tenant:a.tenant}:{}}:s.currentUser;T(n).reevaluateLiveListeners(c,i)})));const o={kind:"sandbox-live",activityApp:e,sandbox:n,getDb:Ze(n,()=>s.currentUser),authScope:i,...r};return{[F]:o,app:e}});if(Dt(e)){const n=Et(e),s={kind:"sandbox",activityApp:e,db:n,sandbox:e.sandbox,...de()};return{[F]:s}}if(Kn(e)){const n={kind:"sandbox-live",activityApp:e,sandbox:e,getDb:Ze(e),...de()};return{[F]:n}}throw new TypeError("pyric/firestore is a sandbox-only mirror. Package resolution must leave firebase/firestore unchanged for production; activate pyric sandbox or @pyric/cli/register before importing to select the sandbox.")}function de(){let e=!1;const t=new Set;return{own(n){return e?(n(),()=>{}):(t.add(n),()=>t.delete(n))},assertUsable(){if(e)throw new I("failed-precondition","The client has already been terminated.")},terminate(){if(!e){e=!0;for(const n of t)n();t.clear()}}}}function Xn(e){const t=st(e);if(t){t.assertAlive();const o=t.sandbox;return Xn(Ee(o.withAuth(null),{source:{kind:"app"},authLens:{mode:"admin"}}))}const n=Dt(e)?e:e.withAuth(null),s=n.sandbox,i={kind:"sandbox",db:In(n),sandbox:s};return{[F]:i}}function Dt(e){return e instanceof Zt}function Kn(e){if(e===null||typeof e!="object")return!1;const t=e;return typeof t.withAuth=="function"&&typeof t.onCurrentUserChanged=="function"&&"currentUser"in t&&"admin"in t}function Ze(e,t=()=>e.currentUser){return()=>{const n=t(),s=Ee(e.withAuth(n),{source:{kind:"app"},authLens:{mode:"app-session"}});return Et(s)}}function Zn(e,t,n,s){const r=en(e,t,n,s);if(r.length===0)return[{}];const i=[];for(const o of r)i.push(new tn(...o.path),o.value);return i}async function ls(e,t,n){const s=C(e);return se(oe(s,e,"setDoc","operation"),async()=>{const r=qe(e),i=r?r.toFirestore(t):t;return L(s).runWrite(()=>ie(()=>Pe(s,e).set(i,n)),e.path)})}function hs(e,t,...n){const s=C(e),r=Zn("updateDoc",e.path,t,n);return se(oe(s,e,"updateDoc","operation"),async()=>L(s).runWrite(()=>ie(()=>Pe(s,e).update(...r)),e.path))}async function fs(e){const t=C(e);return se(oe(t,e,"deleteDoc","operation"),async()=>L(t).runWrite(()=>ie(()=>Pe(t,e).delete()),e.path))}async function ps(e,t){const n=C(e);return se(oe(n,e,"addDoc","operation"),async()=>{const s=qe(e),r=s?s.toFirestore(t):t,i=await L(n).runWrite(async()=>{const c=await ie(()=>Bn(n,e).add(r));return L(n).cachePath(c.path),c}),o=i.path,a=Q(i,n,c=>c.doc(o));if(M(a,Re("reference",o)),Oe(a,o,n,a),s){const c=Ve(a,n,s);return Fe(a,c),c}return a})}export{us as A,kn as B,On as C,Ln as D,xe as E,Q as F,Ft as G,as as H,ps as I,hs as J,fs as K,ts as L,rn as M,se as N,Xn as O,ln as Q,F as T,sn as a,fe as b,L as c,os as d,qe as e,ds as f,Jn as g,At as h,ns as i,U as j,W as k,ct as l,ut as m,oe as n,C as o,cs as p,Pe as q,st as r,ls as s,Wn as t,R as u,ss as v,ie as w,is as x,rs as y,Be as z};
|
|
1
|
+
import{c as jt,ba as ve,aP as ne,aC as f,bb as _t,bc as Tt,b8 as le,bd as Pt,be as qt,bf as M,aK as K,bg as Vt,bh as Mt,az as et,bi as Re,ay as Oe,bj as P,bk as ke,bl as j,aQ as tt,bm as ce,bn as It,bo as zt,V as nt,H as w,aB as T,aM as $t,bp as Lt,bq as Qt,br as Wt,Q as Ee,F as I,bs as Fe,D as Ut,E as Nt,b7 as Bt,b9 as Gt,bt as Ht,bu as Yt,O as Jt,ac as Xt,bv as Kt,T as Zt,bw as en,bx as tn}from"./sandbox-controls.Bv6lfpIe.js";const nn=Symbol.for("pyric.remote.sandbox");function Ce(e){return e!=null&&e[nn]===!0}let Z;function ts(e){Z=e}function st(e){return Z?.resolve(e,!1)}function sn(){if(!Z)throw new TypeError("No default sandbox app registry is installed - import and initialize pyric/app before calling a service factory without an app.");return Z.defaultApp()}function Me(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function rn(e,t,n,s){const r={collectionGroup:e.split("/").filter(Boolean).at(-1)??"",queryScope:t?"COLLECTION_GROUP":"COLLECTION",filters:[],orders:[]},i=(o,a)=>{const c=Me(o);if(!c||a>12||r.filters.length>=64){r.unsupported="This query exceeds the index checker’s supported limits.";return}if(c.kind==="and"&&Array.isArray(c.filters)){c.filters.forEach(u=>i(u,a+1));return}if(c.kind!=="where"||typeof c.field!="string"||typeof c.op!="string"){r.unsupported="This query uses a filter the index checker does not support yet.";return}r.filters.push({field:c.field,op:c.op})};n.forEach(o=>i(o,0));for(const o of s.slice(0,64)){const a=Me(o);if(!a||typeof a.field!="string"||a.direction!=="asc"&&a.direction!=="desc"){r.unsupported="This sort order cannot be checked yet.";continue}r.orders.push({field:a.field,direction:a.direction})}return s.length>64&&(r.unsupported="This query exceeds the index checker’s supported limits."),r}async function se(e,t,n){try{const s=await t();return e.complete(n?.()),s}catch(s){throw e.fail(),s}}const Ie=new Set;function on(e){return Ie.add(e),()=>{Ie.delete(e)}}function ns(e={}){return jt()}function z(e){return e.replace(/^\/+|\/+$/g,"").split("/")}function rt(e){return z(e).length%2===0&&z(e).length>0}function Ae(e){return z(e).length%2===1}function re(e){const t=z(e);return t[t.length-1]??""}function it(e){return z(e).slice(0,-1).join("/")}function ot(e,t){const n=t!==void 0,s=n?ve(t):void 0;return{id:e.id,ref:e,exists:n,data:()=>n?s:void 0,get:r=>ne(s,r)}}const ze=200,B=10,an=4;function cn(e){return e.length<=ze?{type:"string",value:e}:{type:"string",value:e.slice(0,ze),truncated:!0}}function at(e,t){const n=e*1e3+Math.floor(t/1e6);if(!Number.isFinite(n))return{type:"opaque"};try{return{type:"timestamp",iso:new Date(n).toISOString()}}catch{return{type:"opaque"}}}function un(e){if(typeof e!="object"||e===null)return{type:"opaque"};const t=e;return typeof t.path=="string"?{type:"reference",path:t.path}:t.type==="timestamp"&&typeof t.seconds=="number"&&typeof t.nanoseconds=="number"?at(t.seconds,t.nanoseconds):t.type==="geo-point"&&typeof t.latitude=="number"&&typeof t.longitude=="number"?{type:"geoPoint",latitude:t.latitude,longitude:t.longitude}:t.type==="bytes"&&Array.isArray(t.values)?{type:"bytes",length:t.values.length}:t.type==="vector"&&Array.isArray(t.values)?{type:"vector",length:t.values.length}:{type:"opaque"}}function he(e,t){if(e===null)return{type:"null"};if(typeof e=="string")return cn(e);if(typeof e=="number")return{type:"number",value:e};if(typeof e=="boolean")return{type:"boolean",value:e};if(typeof e!="object")return{type:"opaque"};if(t>=an)return{type:"opaque"};const n=e;if(n.type==="registered-firestore-value")return un(n.value);if(n.type==="timestamp"&&typeof n.seconds=="number"&&typeof n.nanoseconds=="number")return at(n.seconds,n.nanoseconds);if(n.type==="bytes"&&Array.isArray(n.values))return{type:"bytes",length:n.values.length};if(n.type==="array"&&Array.isArray(n.values)){const s=n.values.slice(0,B).map(r=>he(r,t+1));return n.values.length>B?{type:"array",values:s,truncated:!0}:{type:"array",values:s}}if(n.type==="map"&&Array.isArray(n.entries)){const s=n.entries.slice(0,B).filter(r=>Array.isArray(r)&&typeof r[0]=="string").map(([r,i])=>[r,he(i,t+1)]);return n.entries.length>B?{type:"map",entries:s,truncated:!0}:{type:"map",entries:s}}return{type:"opaque"}}function $e(e){return he(e,0)}function fe(e){if(e===null||typeof e!="object")return JSON.stringify(e);if(Array.isArray(e))return`[${e.map(n=>fe(n)).join(",")}]`;const t=e;return`{${Object.keys(t).sort().map(n=>`${JSON.stringify(n)}:${fe(t[n])}`).join(",")}}`}function dn(e){if(e!==null&&typeof e=="object"){const n="type"in e&&e.type==="timestamp",s="seconds"in e&&typeof e.seconds=="number",r="nanoseconds"in e&&typeof e.nanoseconds=="number";return n&&s&&r}return!1}function E(e){return new f({code:"invalid-argument",message:e})}function pe(e,t,n,s=!1,r=!1){if(e===null||typeof e=="string"||typeof e=="boolean")return{comparison:e,execution:e};if(typeof e=="number")return{comparison:e,execution:e};if(typeof e>"u"||typeof e=="bigint"||typeof e=="function"||typeof e=="symbol")throw E(`Unsupported Firestore query value: ${typeof e}.`);if(typeof e!="object")throw E("Unsupported Firestore query value.");const u=_t(e);if(u!==void 0){const m=Tt(e);if(m!==void 0&&n!==void 0&&m!==n)throw E("Document reference belongs to a different Firestore database.");if(dn(u)){const p=Math.floor(u.nanoseconds/1e3)*1e3,g=new le(u.seconds,p);return{comparison:{type:"registered-firestore-value",value:Object.freeze({type:"timestamp",seconds:g.seconds,nanoseconds:p})},execution:g}}return{comparison:{type:"registered-firestore-value",value:u},execution:Pt(e)}}if(e instanceof Date){const m=e.getTime();if(!Number.isFinite(m))throw E("Invalid Date query value.");const S=Math.floor(m/1e3),p=Object.freeze({seconds:S,nanoseconds:Math.floor((m-S*1e3)*1e6)}),g={type:"timestamp",...p};return qt(p,g,()=>Object.freeze({...p})),{comparison:{type:"registered-firestore-value",value:g},execution:p}}if(e instanceof Uint8Array){const m=e.slice();return{comparison:{type:"bytes",values:Array.from(m)},execution:m}}if(t.has(e))throw E("Cyclic query operands are not Firestore values.");const b=Object.getPrototypeOf(e);if(b!==Object.prototype&&b!==null&&!Array.isArray(e))throw E("Firestore query maps must be plain objects.");t.add(e);try{if(Array.isArray(e)){if(r&&!s)throw E("Nested arrays are not supported.");const g=e.map(q=>pe(q,t,n,s,!0)),N=g.map(q=>q.execution);return M(N,K(e)),{comparison:{type:"array",values:g.map(q=>q.comparison)},execution:N}}const O=Object.keys(e).sort().map(p=>({key:p,captured:pe(e[p],t,n,s,!1)})),S=Object.fromEntries(O.map(({key:p,captured:g})=>[p,g.execution]));return M(S,K(e)),{comparison:{type:"map",entries:O.map(({key:p,captured:g})=>[p,g.comparison])},execution:S}}finally{t.delete(e)}}function ct(e,t,n=!1){try{const s=pe(e,new Set,t,n);return Object.freeze({kind:"canonical",value:s.comparison,executionValue:s.execution})}catch(s){if(s instanceof f)throw s;const r=s instanceof Error?s.message:String(s);throw E(`Invalid Firestore query value: ${r}`)}}function ut(e,t){return Vt(e.value,t.value)}const ln=["<","<=","==","!=",">=",">","in","not-in","array-contains","array-contains-any"],hn=new Set(ln);function fn(e,t){if(!hn.has(e))throw new f({code:"invalid-argument",message:"Unsupported Firestore filter operator."});if((e==="in"||e==="not-in"||e==="array-contains-any")&&!Array.isArray(t))throw new f({code:"invalid-argument",message:`Firestore ${e} filter requires an array operand.`})}function H(e,t){if(e.kind==="where"){fn(e.op,e.value);const s="comparisonValue"in e,r=e.op==="in"||e.op==="not-in",i=s?e.comparisonValue:ct(e.value,t,r);return Object.freeze({kind:"where",field:e.field,op:e.op,value:i.executionValue,comparisonValue:i})}return Object.freeze({kind:e.kind,filters:Object.freeze(e.filters.map(s=>H(s,t)))})}function G(e,t,n,s){const r=e.map(i=>ct(i,s));return Object.freeze({values:Object.freeze(r.map(i=>i.executionValue)),comparisonValues:Object.freeze(r),inclusive:t,fromSnapshot:n})}function dt(e,t){return e.length!==t.length?!1:e.every((n,s)=>{const r=t[s];return n.kind!==r.kind?!1:n.kind==="where"&&r.kind==="where"?n.field===r.field&&n.op===r.op&&ut(n.comparisonValue,r.comparisonValue):n.kind!=="where"&&r.kind!=="where"&&dt(n.filters,r.filters)})}function Le(e,t){return e===void 0||t===void 0?e===t:e.inclusive===t.inclusive&&e.comparisonValues.length===t.comparisonValues.length&&e.comparisonValues.every((n,s)=>ut(n,t.comparisonValues[s]))}function pn(e,t){return e.kind!==t.kind?!1:e.kind==="collection"&&t.kind==="collection"?e.path===t.path:e.kind==="collection-group"&&t.kind==="collection-group"&&e.collectionId===t.collectionId}function lt(e){return e.kind==="where"?Object.freeze({kind:e.kind,field:e.field,op:e.op,value:e.value}):Object.freeze({kind:e.kind,filters:Object.freeze(e.filters.map(lt))})}function Qe(e){if(e!==void 0)return Object.freeze({values:e.values,inclusive:e.inclusive,fromSnapshot:e.fromSnapshot})}function mn(e,t){return dt(e.filters,t.filters)&&e.orders.length===t.orders.length&&e.orders.every((n,s)=>{const r=t.orders[s];return n.field===r.field&&n.direction===r.direction})&&e.limitCount===t.limitCount&&e.limitFromEnd===t.limitFromEnd&&Le(e.start,t.start)&&Le(e.end,t.end)}const ht="__name__";function We(e,t){const n=e.data();if(n===void 0)throw new f({code:"not-found",message:`Snapshot-based cursors require an existing document — got an empty snapshot for ${e.id??"<unknown>"}.`});return t.map(s=>s.field===ht?e.ref:n[s.field])}class ${env;auth;collectionPath;clauses;orders;limitCount;limitFromEnd;start;end;bypassRules;documentRef;constructor(t){this.env=t.env,this.auth=t.auth,this.collectionPath=t.collectionPath,this.documentRef=t.documentRef,this.clauses=Object.freeze((t.clauses??[]).map(n=>H(n))),this.orders=Object.freeze((t.orders??[]).map(n=>Object.freeze({...n}))),this.limitCount=t.limitCount,this.limitFromEnd=t.limitFromEnd??!1,this.start=t.start===void 0?void 0:Object.freeze({...t.start,values:Object.freeze(t.start.comparisonValues.map(n=>n.executionValue)),comparisonValues:t.start.comparisonValues}),this.end=t.end===void 0?void 0:Object.freeze({...t.end,values:Object.freeze(t.end.comparisonValues.map(n=>n.executionValue)),comparisonValues:t.end.comparisonValues}),this.bypassRules=t.bypassRules??!1}where(t,n,s){return this.clone({clauses:[...this.clauses,H({kind:"where",field:t,op:n,value:s})]})}applyFilter(t){return this.clone({clauses:[...this.clauses,H(t)]})}orderBy(t,n="asc"){if(n!=="asc"&&n!=="desc")throw new f({code:"invalid-argument",message:"orderBy() direction must be 'asc' or 'desc'."});return this.clone({orders:[...this.orders,{field:t,direction:n}]})}limit(t){return Ue(t),this.clone({limitCount:t,limitFromEnd:!1})}limitToLast(t){return Ue(t),this.clone({limitCount:t,limitFromEnd:!0})}startCursor(t,n){return this.clone({start:G(this.normalizeExplicitCursorValues(t),n,!1)})}endCursor(t,n){return this.clone({end:G(this.normalizeExplicitCursorValues(t),n,!1)})}startCursorFromSnapshot(t,n){return this.clone({start:G(We(t,this.normalizedOrders()),n,!0)})}endCursorFromSnapshot(t,n){return this.clone({end:G(We(t,this.normalizedOrders()),n,!0)})}isStructurallyEqual(t){return t instanceof $?this.env===t.env&&this.bypassRules===t.bypassRules&&pn(this.queryScope(),t.queryScope())&&mn(this.comparableExecutionSpec(),t.comparableExecutionSpec()):!1}clone(t){return new $({env:this.env,auth:this.auth,collectionPath:this.collectionPath,documentRef:this.documentRef,clauses:t.clauses??this.clauses,orders:t.orders??this.orders,limitCount:"limitCount"in t?t.limitCount:this.limitCount,limitFromEnd:t.limitFromEnd??this.limitFromEnd,start:"start"in t?t.start:this.start,end:"end"in t?t.end:this.end,bypassRules:this.bypassRules})}queryScope(){return{kind:"collection",path:this.collectionPath}}sdkActivitySource(){const t=this.queryScope();return{service:"firestore",target:t.kind==="collection"?t.path:t.collectionId,key:fe({scope:t,query:this.activityQuery()}),isQuery:!0,indexQuery:rn(t.kind==="collection"?t.path:t.collectionId,t.kind==="collection-group",this.clauses,this.orders)}}readQueryRows(t){const n=t?.auth!==void 0?t.auth:this.auth;let s;try{s=this.env.runQuery({scope:this.queryScope(),auth:n,execution:this.executionSpec(),bypassRules:this.bypassRules,activityQuery:this.activityQuery()})}catch(r){const i=r?.simError;throw i?new f(i):r}if(!s.allowed)throw new f(s.error);return s.docs}activityQuery(){const t=s=>s.kind==="where"?{kind:"where",field:s.field,op:s.op,value:K(s.value),display:$e(s.comparisonValue.value)}:{kind:s.kind,filters:s.filters.map(t)},n=s=>s===void 0?null:{values:s.values.map(r=>K(r)),display:s.comparisonValues.map(r=>$e(r.value)),inclusive:s.inclusive,fromSnapshot:s.fromSnapshot};return{scope:this.activityScope(),filters:this.clauses.map(t),orderBy:this.orders.map(s=>({...s})),limit:this.limitCount??null,limitFromEnd:this.limitFromEnd,start:n(this.start),end:n(this.end)}}activityScope(){return{kind:"collection"}}normalizedOrders(){return Mt(this.executionSpec())}normalizeExplicitCursorValues(t){const n=this.orders;return t.map((s,r)=>{if(n[r]?.field!==ht)return s;if(typeof s!="string")throw new f({code:"invalid-argument",message:"Expected a string for a document ID cursor value."});const i=s.includes("/")?s:`${this.collectionPath}/${s}`;return this.documentRef(i)})}executionSpec(){const t={filters:Object.freeze(this.clauses.map(lt)),orders:this.orders,limitCount:this.limitCount,limitFromEnd:this.limitFromEnd,start:Qe(this.start),end:Qe(this.end)};return Object.freeze(t)}comparableExecutionSpec(){return{filters:this.clauses,orders:this.orders,limitCount:this.limitCount,limitFromEnd:this.limitFromEnd,start:this.start,end:this.end}}snapshotScope(){return this.queryScope()}snapshotConstraints(){return Object.freeze({execution:this.executionSpec(),activityQuery:this.activityQuery()})}async get(t){const s=this.readQueryRows(t).map(r=>{const i=this.documentRef(r.path),o=ve(r.data);return{id:i.id,ref:i,exists:!0,data:()=>o,get:a=>ne(o,a)}});return{size:s.length,empty:s.length===0,docs:s,forEach:et(s)}}async aggregate(t,n){const s=this.readQueryRows(n),r={};for(const i of Object.keys(t))r[i]=bn(t[i],s);return{data:()=>r}}}function yn(e,t){if(!t.includes("."))return e[t];let n=e;for(const s of t.split(".")){if(typeof n!="object"||n===null||Array.isArray(n))return;n=n[s]}return n}function bn(e,t){if(e.kind==="count")return t.length;let n=0,s=0;for(const r of t){const i=yn(r.data,e.field);typeof i=="number"&&Number.isFinite(i)&&(n+=i,s++)}return e.kind==="sum"?n:s===0?null:n/s}function Ue(e){if(!Number.isFinite(e))throw new f({code:"invalid-argument",message:"Query limit must be a finite number."})}function D(e,t){if(e.error)throw new f(e.error);const n=e.debugMessages.length>0?e.debugMessages.join("; "):"(no debug message)";throw new f(j("permission-denied",`${t}: ${n}`))}class gn{env;auth;bypassRules;collectionRef;id;path;constructor(t,n,s,r=!1,i){this.env=t,this.auth=n,this.bypassRules=r,this.collectionRef=i,this.path=s,this.id=re(s),M(this,Re("reference",s)),Oe(this,s,t)}get parent(){return this.collectionRef(it(this.path))}collection(t){return this.collectionRef(`${this.path}/${t}`)}async get(t){const n=this.env.execute({method:"get",path:this.path,auth:t?.auth!==void 0?t.auth:this.auth,bypassRules:this.bypassRules});n.allowed||D(n,"get denied");const s=n.data===void 0||n.data===null?void 0:n.data;return ot(this,s)}async create(t,n){const s=this.env.execute({method:"create",path:this.path,data:t,auth:n?.auth!==void 0?n.auth:this.auth,bypassRules:this.bypassRules});s.allowed||D(s,"create denied")}async set(t,n){const s=n?.auth!==void 0?n.auth:this.auth;if(n?.mergeFields!==void 0){const i=n.mergeFields.map(u=>String(u)),a=this.env.getDocument(this.path)===null?"create":"update",c=this.env.execute({method:a,path:this.path,data:t,auth:s,merge:{mergeFields:i},bypassRules:this.bypassRules});c.allowed||D(c,`set denied (as ${a})`);return}if(n?.merge===!0){const o=this.env.getDocument(this.path)===null?"create":"update",a=this.env.execute({method:o,path:this.path,data:t,auth:s,merge:!0,bypassRules:this.bypassRules});a.allowed||D(a,`set denied (as ${o})`);return}const r=this.env.execute({method:"set",path:this.path,data:t,auth:s,bypassRules:this.bypassRules});r.allowed||D(r,"set denied")}update(t,...n){const{fields:s,options:r}=P(t,n);return this.commitUpdate(s,r)}async commitUpdate(t,n){const s=this.env.execute({method:"update",path:this.path,data:ke(t),auth:n?.auth!==void 0?n.auth:this.auth,bypassRules:this.bypassRules});s.allowed||D(s,"update denied")}async delete(t){const n=this.env.execute({method:"delete",path:this.path,auth:t?.auth!==void 0?t.auth:this.auth,bypassRules:this.bypassRules});n.allowed||D(n,"delete denied")}}function V(e,t,n,s){return new gn(e,t,n,s,r=>new ft(e,t,r,s))}class ft extends ${id;path;constructor(t,n,s,r=!1){super({env:t,auth:n,collectionPath:s,bypassRules:r,documentRef:i=>V(t,n,i,r)}),this.path=s,this.id=re(s)}doc(t){const n=t??tt();return V(this.env,this.auth,`${this.path}/${n}`,this.bypassRules)}async add(t,n){const s=n?.auth!==void 0?n.auth:this.auth,{path:r,result:i}=this.env.createWithAutoId(this.path,t,s,this.bypassRules);if(!i.allowed){if(i.error)throw new f(i.error);let o="(no debug message)";throw i.debugMessages.length>0&&(o=i.debugMessages.join("; ")),new f(j("permission-denied",`set denied: ${o}`))}return V(this.env,this.auth,r,this.bypassRules)}}class De extends ${collectionId;constructor(t){super({...t,collectionPath:"",documentRef:n=>V(t.env,t.auth,n,t.bypassRules??!1)}),this.collectionId=t.collectionId}clone(t){return new De({env:this.env,auth:this.auth,collectionId:this.collectionId,clauses:t.clauses??this.clauses,orders:t.orders??this.orders,limitCount:"limitCount"in t?t.limitCount:this.limitCount,limitFromEnd:t.limitFromEnd??this.limitFromEnd,start:"start"in t?t.start:this.start,end:"end"in t?t.end:this.end,bypassRules:this.bypassRules})}queryScope(){return{kind:"collection-group",collectionId:this.collectionId}}activityScope(){return{kind:"collection-group"}}}class wn{env;auth;bypassRules;ops=[];constructor(t,n,s=!1){this.env=t,this.auth=n,this.bypassRules=s}create(t,n){return this.ops.push({method:"create",path:t.path,data:ce(n)}),this}set(t,n,s){const r={method:"set",path:t.path,data:ce(n)},i=s?.mergeFields;return i!==void 0?r.merge={mergeFields:[...i]}:s?.merge===!0&&(r.merge=!0),this.ops.push(r),this}update(t,n,...s){const{fields:r}=P(n,s);return this.ops.push({method:"update",path:t.path,data:ce(ke(r))}),this}delete(t){return this.ops.push({method:"delete",path:t.path}),this}async commit(t){if(this.ops.length===0)return;const s=t?.auth,r=s!==void 0,i=this.env.batch(this.ops,r?s:this.auth,this.bypassRules),{allowed:o,error:a}=i;if(o)return;if(a!==void 0)throw new f(a);const y=i.results.find(d=>!d.allowed)?.debugMessages.join("; ")??"batch denied";throw new f(j("permission-denied",`batch failed: ${y}`))}}function xn(e){return typeof e.where=="function"}class Sn{simTx;constructor(t){this.simTx=t}async get(t){if(xn(t)){const i=await t.get();return i.size>0&&this.simTx.getAll(...i.docs.map(a=>a.ref.path)),i}const r=this.simTx.get(t.path).data();return ot(t,r)}create(t,n){return this.simTx.create(t.path,n),this}set(t,n,s){const r=s?.mergeFields;if(r!==void 0)return this.simTx.set(t.path,n,{mergeFields:r}),this;const o=s?.merge===!0;return this.simTx.set(t.path,n,o?!0:void 0),this}update(t,n,...s){const{fields:r}=P(n,s);return this.simTx.update(t.path,ke(r)),this}delete(t){return this.simTx.delete(t.path),this}}class vn{env;auth;bypassRules;provenance;constructor(t,n,s=!1,r){this.env=t,this.auth=n,this.bypassRules=s,this.provenance=r}collection(t){if(!Ae(t))throw new f(j("invalid-argument",`collection path must have an odd number of segments: ${t}`));return new ft(this.env,this.auth,t,this.bypassRules)}doc(t){if(!rt(t))throw new f(j("invalid-argument",`document path must have an even number of segments: ${t}`));return V(this.env,this.auth,t,this.bypassRules)}collectionGroup(t){if(t.length===0||t.includes("/"))throw new f(j("invalid-argument",`collection group id must be a single non-empty segment with no '/': ${t}`));return new De({env:this.env,auth:this.auth,collectionId:t,bypassRules:this.bypassRules})}batch(){return new wn(this.env,this.auth,this.bypassRules)}async runTransaction(t,n){let s;try{s=await this.env.transaction(r=>{const i=new Sn(r);return t(i)},{auth:n?.auth!==void 0?n.auth:this.auth,bypassRules:this.bypassRules,provenance:this.provenance,maxAttempts:n?.maxAttempts})}catch(r){throw r instanceof It?new f(r.simError):r instanceof zt?new f(r.simError):r}if(!s.allowed){if(s.error)throw new f(s.error);const i=s.writes.find(o=>!o.allowed)?.debugMessages.join("; ")??"transaction denied at commit";throw new f(j("permission-denied",`transaction failed: ${i}`))}return s.returnValue}}function Rn(e,t){return new vn(e,t?.auth??null,t?.bypassRules??!1,t?.provenance)}const On=Symbol("pyric/sandbox/context"),kn=Symbol("pyric/sandbox/bypassRules");let me=null;function ss(e){me=e}const En=Symbol.for("pyric.firestore.modular-value");function Ne(e){return En in e}function Fn(e){const t=e;return typeof t.path=="string"&&t.path.length>0||typeof t.collectionPath=="string"&&t.collectionPath.length>0||typeof t.snapshotScope=="function"}function Cn(e){const t=e.trim();if(!t)return[];const n=t.indexOf(": ");if(n!==-1){const r=t.slice(n+2).trim().split("; ").map(i=>i.trim()).filter(i=>i.length>0);if(r.length>0)return r}return[t]}function Be(e,t){if(e instanceof f===!1)return e;const s=e.code;if(s==="permission-denied"===!1)return new w(s,e.message);const i={engine:"firestore",auth:t.auth,reasons:Cn(e.message)},o=e.simError;if(o!==void 0){if(o.queryProof!==void 0&&(i.queryProof=o.queryProof),o.request!==void 0){const l=o.request;i.request={method:l.method,path:l.path},l.resourceData!==void 0&&(i.request.resourceData=l.resourceData),l.updateMask!==void 0&&(i.request.updateMask=l.updateMask)}if(o.resource!==void 0&&(i.resource={data:o.resource.data,exists:o.resource.exists}),o.query!==void 0&&(i.query=o.query),o.rule!==void 0&&(i.rule=o.rule),o.repro!==void 0&&(i.repro=o.repro),o.remediation!==void 0)return new w({code:s,message:e.message,denialContext:i,remediation:o.remediation})}return new w(s,e.message,i)}function ee(e,t,n=!1){return new Proxy(e,{get(s,r,i){if(r===On)return t;if(r===kn)return n;if(r==="onSnapshot"&&me!==null&&!(r in s)&&Fn(s))return(...a)=>me(i,...a);const o=Reflect.get(s,r,i);return typeof o!="function"?o:function(...a){let c;try{const u=()=>o.apply(s,a);c=typeof t.sandbox.runWithProvenance=="function"?t.sandbox.runWithProvenance(nt(t.operationContext),u):u()}catch(u){throw Be(u,t)}return c instanceof Promise?c.then(u=>u&&typeof u=="object"&&!Ne(u)?ee(u,t,n):u).catch(u=>{throw Be(u,t)}):c&&typeof c=="object"&&!Ne(c)?ee(c,t,n):c}}})}function pt(e,t=!1){if(Ce(e.sandbox))throw new Error("pyric/sandbox/admin-firestore: internal — a remote sandbox context reached the local engine builder; remote dispatch should have handled it. Please report this.");const n=()=>Rn(T(e.sandbox),{auth:e.auth,bypassRules:t,provenance:nt(e.operationContext)});return{collection(s){return n().collection(s)},doc(s){return n().doc(s)},collectionGroup(s){return n().collectionGroup(s)},batch(){return n().batch()},runTransaction(s,r){return n().runTransaction(s,r)},setRules(s){return T(e.sandbox).deployRules(s)},seed(s){const r=T(e.sandbox);return r.seed({rules:r.getRules(),documents:s?.documents??{}})},snapshot(){return T(e.sandbox).snapshot()}}}function ye(e){if(e instanceof w)return e;if(e!==null&&typeof e=="object"){const t=e;if(typeof t.code=="string"&&typeof t.message=="string"){const n=t.denialContext!==null&&typeof t.denialContext=="object"?t.denialContext:void 0;return new w(t.code,t.message,n)}}return e}function k(e){return new w("invalid-argument",e)}async function x(e,t){try{return await e.sandbox.channel.op({...t,actAs:e.lens})}catch(n){throw ye(n)}}const An=new Set(["serverTimestamp","increment","arrayUnion","arrayRemove","deleteField"]);function Dn(e){return e!==null&&typeof e=="object"&&typeof e.__type=="string"&&An.has(e.__type)}function jn(e){switch(e.__type){case"serverTimestamp":return{__sentinel:"serverTimestamp"};case"increment":return{__sentinel:"increment",n:e.value};case"arrayUnion":return{__sentinel:"arrayUnion",values:e.values.map(v)};case"arrayRemove":return{__sentinel:"arrayRemove",values:e.values.map(v)};case"deleteField":return{__sentinel:"deleteField"}}}function v(e){if(e===null||typeof e!="object")return e;if(Dn(e))return jn(e);if(e instanceof le)return e.toJSON();if(e instanceof Date)return le.fromDate(e).toJSON();if(Array.isArray(e))return e.map(v);const t=Object.getPrototypeOf(e);if(t!==Object.prototype&&t!==null){const s=e.toJSON;if(typeof s=="function")return s.call(e);throw k(`remote Firestore: cannot serialize a ${t.constructor?.name??"class"} instance for the wire — use plain data, Timestamp, Date, or FieldValue sentinels.`)}const n={};for(const[s,r]of Object.entries(e))n[s]=v(r);return n}function _(e){return v(e)}function je(e){return e.map(t=>({path:[...t.path],value:v(t.value)}))}function be(e){return $t(JSON.parse(e.json),e.valueEncoding)}function mt(e){return ve(be(e))}function yt(e,t){const n=t.exists&&t.data?mt(t.data):void 0;return{id:e.id,ref:e,exists:t.exists,data:()=>n,get:s=>ne(n,s)}}function bt(e,t){const n=t.docs.map(s=>{const r=s.path??s.id,i=te(e,r),o=s.data?mt(s.data):{};return{id:i.id,ref:i,exists:!0,data:()=>o,get:a=>ne(o,a)}});return{size:n.length,empty:n.length===0,docs:n,forEach:et(n)}}const _e=Symbol("pyric/sandbox/admin-firestore/remoteSnapshotRegistrar");function rs(e){if(e===null||typeof e!="object")return;const t=e[_e];return typeof t=="function"?t:void 0}let ge=null;function is(e){ge=e}function gt(...e){if(ge===null)throw new w("failed-precondition","remote Firestore: onSnapshot is not wired yet — import pyric-admin/firestore (or pyric/sandbox/admin-firestore) before subscribing.");return ge(this,...e)}function wt(e,t,n,s,r){const i=n.includeMetadataChanges!==!0;let o;function a(u){const y=ye(u);r!==void 0?r(y):console.error("pyric remote Firestore: uncaught onSnapshot error:",y)}let c;try{c=e.sandbox.channel.subscribe({target:t,actAs:e.lens},u=>{if(s===void 0)return;let d;try{const l=u,b=l.docs;if(Array.isArray(b)){const m=b.map(O=>{const S=O.data,p=S!==void 0;return{path:O.path??O.id,data:p?be(S):{}}});d=Lt({path:xt(t)},m,{excludesMetadataChanges:i},o),o=m}else{const m=l.id;if(typeof m=="string"){const S=l.path??m,p=l.data,N=l.exists===!0&&p!==void 0?be(p):null;d=Qt(S,N)}}}catch(l){c(),a(l);return}d!==void 0&&s(d)},a)}catch(u){throw ye(u)}return c}function xt(e){switch(e.__ref){case"query":return xt(e.source);case"group":return e.collectionId;default:return e.path}}const St=Symbol("pyric/sandbox/admin-firestore/remoteQueryState");function _n(e){if(!(e===null||typeof e!="object"))return e[St]}function vt(e){return e.kind==="where"?(Rt(e.op),{kind:"where",field:e.field,op:e.op,value:v(e.value)}):{kind:e.kind,filters:e.filters.map(vt)}}const Tn=new Set(["<","<=","==","!=",">=",">","in","not-in","array-contains","array-contains-any"]);function Rt(e){if(!Tn.has(e))throw k(`invalid where operator: ${String(e)}`)}function Y(e){const t=[...e.filters];for(const n of e.orders)t.push({kind:"orderBy",field:n.field,direction:n.direction});return e.start&&t.push({kind:e.start.inclusive?"startAt":"startAfter",values:e.start.values.map(v)}),e.end&&t.push({kind:e.end.inclusive?"endAt":"endBefore",values:e.end.values.map(v)}),e.limitCount!==void 0&&t.push(e.limitFromEnd?{kind:"limitToLast",n:e.limitCount}:{kind:"limit",n:e.limitCount}),t.length===0?e.source:{__ref:"query",source:e.source,constraints:t}}function Ge(e,t,n){if(t.length===0)throw k(`${n}(snapshot) on a remote sandbox requires at least one explicit orderBy() clause — the relay protocol has no document-key cursor.`);if(t.some(r=>r.field==="__name__"))throw k(`${n}(snapshot) on a remote sandbox does not support orderBy('__name__') — the relay protocol has no document-key cursor, and __name__ is not a data field a value cursor can carry. Order by a real document field instead.`);const s=e.data();if(s===void 0)throw new w("not-found",`Snapshot-based cursors require an existing document — got an empty snapshot for ${e.id??"<unknown>"}.`);return t.map(r=>s[r.field])}function Te(e,t){const n=r=>Te(e,{...t,...r});return{[St]:t,where(r,i,o){return Rt(i),n({filters:[...t.filters,{kind:"where",field:r,op:i,value:v(o)}]})},applyFilter(r){return n({filters:[...t.filters,vt(r)]})},orderBy(r,i="asc"){return n({orders:[...t.orders,{field:r,direction:i}]})},limit(r){return n({limitCount:r,limitFromEnd:!1})},limitToLast(r){return n({limitCount:r,limitFromEnd:!0})},startCursor(r,i){return n({start:{values:[...r],inclusive:i}})},endCursor(r,i){return n({end:{values:[...r],inclusive:i}})},startCursorFromSnapshot(r,i){return n({start:{values:Ge(r,t.orders,i?"startAt":"startAfter"),inclusive:i}})},endCursorFromSnapshot(r,i){return n({end:{values:Ge(r,t.orders,i?"endAt":"endBefore"),inclusive:i}})},async get(r){J(t);const i=await x(e,{method:"getDocs",source:Y(t)});return bt(e,i)},async aggregate(r){J(t);const i=await x(e,{method:"aggregate",source:Y(t),spec:r});return{data:()=>i.data}},[_e]:(r,i,o)=>(J(t),wt(e,Y(t),r,i,o)),onSnapshot:gt}}function J(e){if(e.limitFromEnd&&e.orders.length===0)throw k("limitToLast() queries require at least one orderBy clause.")}function we(e,t){const n=Te(e,{source:{__ref:"collection",path:t},filters:[],orders:[],limitFromEnd:!1});return Object.assign(Object.create(Object.getPrototypeOf(n)),n,{id:re(t),path:t,doc(r){const i=r??tt();return te(e,`${t}/${i}`)},async add(r,i){const o=await x(e,{method:"addDoc",collectionPath:t,data:_(r)});return te(e,o.path)}})}function te(e,t){const n={id:re(t),path:t,get parent(){return we(e,it(t))},collection(s){const r=`${t}/${s}`;if(!Ae(r))throw k(`collection path must have an odd number of segments: ${r}`);return we(e,r)},async get(s){const r=await x(e,{method:"getDoc",path:t});return yt(n,r)},async create(s,r){await x(e,{method:"batchCommit",writes:[{method:"create",path:t,data:_(s)}]})},async set(s,r){await x(e,{method:"setDoc",path:t,data:_(s),...He(r)?{options:He(r)}:{}})},update(s,...r){const{fields:i}=P(s,r),o=je(i);return x(e,{method:"updateDoc",path:t,fields:o}).then(()=>{})},async delete(s){await x(e,{method:"deleteDoc",path:t})},[_e]:(s,r,i)=>wt(e,{__ref:"doc",path:t},s,r,i),onSnapshot:gt};return n}function He(e){if(!e)return;const t={};return e.merge!==void 0&&(t.merge=e.merge),e.mergeFields!==void 0&&(t.mergeFields=[...e.mergeFields]),t.merge!==void 0||t.mergeFields!==void 0?t:void 0}function Ot(e){if(e===void 0)return;const t={};return"merge"in e&&e.merge!==void 0&&(t.merge=e.merge),"mergeFields"in e&&e.mergeFields!==void 0&&(t.mergeFields=e.mergeFields.map(n=>String(n))),t}function Pn(e){const t=[];let n=!1;const s={create(i,o){return r(),t.push({method:"create",path:i.path,data:_(o)}),s},set(i,o,a){r();const c={method:"set",path:i.path,data:_(o)},u=Ot(a);return u!==void 0&&(c.options=u),t.push(c),s},update(i,o,...a){r();const{fields:c}=P(o,a);return t.push({method:"update",path:i.path,fields:je(c)}),s},delete(i){return r(),t.push({method:"delete",path:i.path}),s},async commit(i){r(),n=!0,await x(e,{method:"batchCommit",writes:t})}};function r(){if(n)throw new w("failed-precondition","WriteBatch has already been committed.")}return s}const qn=5;async function Vn(e,t,n=qn){for(let s=0;s<n;s++){const r=[],i=[],o=()=>{if(i.length>0)throw new w("failed-precondition",Wt)},a={get(d){o();const h=_n(d);return h!==void 0?u(h):c(d)},create(d,h){return i.push({method:"create",path:d.path,data:_(h)}),a},set(d,h,l){const b={method:"set",path:d.path,data:_(h)},A=Ot(l);return A!==void 0&&(b.options=A),i.push(b),a},update(d,h,...l){const{fields:b}=P(h,l);return i.push({method:"update",path:d.path,fields:je(b)}),a},delete(d){return i.push({method:"delete",path:d.path}),a}};async function c(d){const h=await x(e,{method:"getDoc",path:d.path});return r.push({path:h.path??d.path,data:h.exists&&h.data?h.data:null}),yt(d,h)}async function u(d){J(d);const h=await x(e,{method:"getDocs",source:Y(d)});for(const l of h.docs)r.push({path:l.path??l.id,data:l.data??null});return bt(e,h)}const y=await t(a);try{return await x(e,{method:"txnCommit",reads:r,writes:i}),y}catch(d){if(d instanceof w&&d.code==="aborted")continue;throw d}}throw new w("aborted",`Transaction failed after ${n} attempts due to repeated conflicts. Another writer is concurrently updating the same documents.`)}function ue(e,t){return new w("unimplemented",`SandboxFirestore.${e} is not available on a remote sandbox — its return value is synchronous and the data lives in the browser worker. ${t}`)}function kt(e,t){const n={sandbox:e,lens:t};return{collection(s){if(!Ae(s))throw k(`collection path must have an odd number of segments: ${s}`);return we(n,s)},doc(s){if(!rt(s))throw k(`document path must have an even number of segments: ${s}`);return te(n,s)},collectionGroup(s){if(s.length===0||s.includes("/"))throw k(`collection group id must be a single non-empty segment with no '/': ${s}`);return Te(n,{source:{__ref:"group",collectionId:s},filters:[],orders:[],limitFromEnd:!1})},batch(){return Pn(n)},runTransaction(s,r){return Vn(n,s,r?.maxAttempts)},setRules(){throw ue("setRules","Deploy rules asynchronously through the relay instead: `await sandbox.channel.op({ method: 'setFirestoreRules', source })`.")},seed(){throw ue("seed","The relay has no atomic seed op; write seed docs through this handle (`db.doc(path).set(data)` / `db.batch()`), or drive `sandbox.channel.op({ method: 'admin.setDocument', path, data })` per document.")},snapshot(){throw ue("snapshot","Read the worker state asynchronously instead: `await sandbox.channel.op({ method: 'admin.readState' })`.")}}}const Ye=new WeakMap;function Et(e){const t=Ye.get(e);if(t)return t;const n=Ce(e.sandbox)?kt(e.sandbox,Mn(e.auth)):ee(pt(e),e);return Ye.set(e,n),n}function Mn(e){if(e==null)return{mode:"anon"};const t={mode:"as",uid:e.uid};return e.token!==void 0&&(t.token=e.token),e.tenant!==void 0&&(t.tenant=e.tenant),t}const Je=new WeakMap;function In(e){const t=zn(e)?e:e.withAuth(null),n=Je.get(t);if(n)return n;const s=t.operationContext.authLens.mode==="admin"?t:Ee(t,{source:t.operationContext.source,authLens:{mode:"admin"},...t.operationContext.planId===void 0?{}:{planId:t.operationContext.planId}}),r=Ce(s.sandbox)?kt(s.sandbox,{mode:"admin"}):ee(pt(s,!0),s,!0);return Je.set(t,r),r}function zn(e){return e!==null&&typeof e=="object"&&"sandbox"in e&&typeof e.withAuth=="function"}function $n(e){return e instanceof Error&&"code"in e&&typeof e.code=="string"}function Ln(e){if(e instanceof I||!$n(e))return e;const t={};e.denialContext!==void 0&&(t.denialContext=e.denialContext),e.remediation!==void 0&&(t.remediation=e.remediation);const n=new I(e.code,e.message,Object.keys(t).length===0?void 0:t);e.denialContext!==void 0&&Object.assign(n,{denialContext:e.denialContext}),e.remediation!==void 0&&Object.assign(n,{remediation:e.remediation});for(const s of["request","resource","query","rule","queryProof"])e[s]!==void 0&&Object.assign(n,{[s]:e[s]});return n}async function ie(e){try{return await e()}catch(t){throw Ln(t)}}class Qn{static[Symbol.hasInstance](t){return!!(t&&typeof t=="object"&&"id"in t&&"path"in t&&typeof t.path=="string"&&!("docs"in t)&&!("exists"in t)&&!("doc"in t)&&!("add"in t))}}function Ft(e,t){const n=R(e);if(t===null)return n;const r=C(e),i=Ve(n,r,t);return Fe(n,i),xe(i)}function xe(e){function t(n){return Ft(e,n)}return Object.assign(e,{withConverter:t})}function X(e,t,n,s=null){function r(c){return c===null?Xe(a,null):Xe(a,c)}const i=R(e),o=Ve(i,n,s),a=Object.assign(o,{withConverter:r});return M(a,Re("reference",t)),Oe(i,t,n),Fe(i,a),a}function os(e,...t){const n=C(e),s=F in e,r=s?void 0:qe(e),i=W(n);if(s){if(t.length===0)throw new TypeError("doc(db, path) requires at least one path segment.");const l=t.join("/"),b=i.doc(l),A=Q(b,n,m=>m.doc(l));return X(A,l,n)}const o=R(e),a=t.length===0;let c;a?c=o.doc():c=o.doc(t.join("/"));const u=c.path,y=Q(c,n,h=>h.doc(u));return r!=null?X(y,u,n,r):X(y,u,n)}function as(e,...t){const n=C(e),s=F in e;if(t.length===0)throw new TypeError("collection() requires at least one path segment.");if(s){const c=t.join("/"),u=xe(W(n).collection(c));return Q(u,n,y=>y.collection(c))}const r=R(e),i=t.join("/"),o=xe(r.collection(i)),a=o.path;return Q(o,n,c=>c.collection(a))}function Xe(e,t){const n=C(e),s=R(e);return s instanceof Qn?X(s,s.path,n,t):Ft(e,t)}class Wn{started=!1;networkEnabled=!0;persistenceMode;pending=new Set;cachedPaths=new Set;cachedQueries=new WeakSet;syncObservers=new Set;syncScheduled=!1;markStarted(){this.started=!0}enablePersistence(t){if(this.started||this.persistenceMode!==void 0)throw new I("failed-precondition","Firestore has already been started and persistence can no longer be enabled.");this.persistenceMode=t,this.started=!0}disableNetwork(){this.started=!0,this.networkEnabled=!1}async enableNetwork(){this.started=!0,this.networkEnabled=!0;for(const t of this.pending)t.localDone&&t.resolve(t.value);await Promise.all([...this.pending].map(t=>t.promise))}runWrite(t,n){if(this.started=!0,n&&this.cachedPaths.add(n),this.networkEnabled)return t();let s,r;const i=new Promise((a,c)=>{s=a,r=c}),o={path:n,promise:i,localDone:!1,resolve:s,reject:r};return this.pending.add(o),t().then(a=>{o.localDone=!0,o.value=a,this.networkEnabled&&o.resolve(a)},a=>o.reject(a)),i.then(()=>this.pending.delete(o),()=>this.pending.delete(o)),i}waitForPendingWrites(){this.started=!0;const t=[...this.pending].map(n=>n.promise);return Promise.all(t).then(()=>{})}cachePath(t){this.started=!0,this.cachedPaths.add(t)}assertPathCached(t){if(this.started=!0,!this.cachedPaths.has(t))throw new I("unavailable","Failed to get document from cache. (However, this document may exist on the server.)")}cacheQuery(t){this.started=!0,this.cachedQueries.add(t)}hasCachedQuery(t){return this.started=!0,this.cachedQueries.has(t)||this.cachedPaths.size>0}snapshotMetadata(t){return Object.freeze({fromCache:!this.networkEnabled,hasPendingWrites:[...this.pending].some(n=>n.path===t)})}querySnapshotMetadata(){return Object.freeze({fromCache:!this.networkEnabled,hasPendingWrites:this.pending.size>0})}addSnapshotsInSyncObserver(t){return this.syncObservers.add(t),t(),()=>this.syncObservers.delete(t)}notifySnapshotDelivered(){this.syncScheduled||this.syncObservers.size===0||(this.syncScheduled=!0,queueMicrotask(()=>{this.syncScheduled=!1;for(const t of[...this.syncObservers])t()}))}}const Ke=new WeakMap;function L(e){let t=Ke.get(e);return t||(t=new Wn,Ke.set(e,t)),t}function oe(e,t,n,s,r){const i=R(t),o=typeof i.sdkActivitySource=="function"?i.sdkActivitySource():{service:"firestore",target:i.path,key:`doc:${i.path}`};return Ut.begin({app:e.activityApp??e,source:o,method:n,kind:s,owners:Nt(r?.owner,r?.owners)})}const F=Symbol("pyric/firestore/target");function W(e){return e.kind==="sandbox"?e.db:e.getDb()}const ae=new WeakMap;function Un(e,t){return ae.set(e,t),e}const U=new WeakMap;function Nn(e,t,n){return ae.set(e,t),U.set(e,n),e}function Pe(e,t){const n=R(t);if(e.kind==="sandbox")return n;const s=U.get(n);if(!s)throw new TypeError("pyric/firestore: live ref missing rebuild closure — was it produced by a factory in this package?");return s(W(e))}function Bn(e,t){const n=R(t);if(e.kind==="sandbox")return n;const s=U.get(n);if(!s)throw new TypeError("pyric/firestore: live collection ref missing rebuild closure.");return s(W(e))}function cs(e,t){const n=R(t);if(e.kind==="sandbox")return n;const s=U.get(n);if(!s)throw new TypeError("pyric/firestore: live query missing rebuild closure.");return s(W(e))}function Q(e,t,n){return t.kind==="sandbox-live"?Nn(e,t,n):Un(e,t)}function us(e){const t=R(e),n=U.get(t);return n||(()=>t)}function C(e){const t=Gn(e);return t.assertUsable?.(),t}function Gn(e){let t;if(F in e?t=e[F]:t=ae.get(e),!t)throw new TypeError("pyric/firestore: unrecognized reference — was it produced by a factory in this package?");return t}const Hn=Symbol.for("pyric.firestore.modular-value"),Ct=new WeakMap,At=new WeakMap;function qe(e){return Ct.get(e)}function R(e){return At.get(e)??e}function Ve(e,t,n){const s={id:e.id??"",path:e.path??""};return Object.defineProperty(s,Hn,{value:!0}),Ct.set(s,n),At.set(s,e),ae.set(s,t),s}function Yn(e){return e instanceof Kt?Array.from(e.value):null}function Se(e,t){if(e instanceof Yt)return t?.create(e.path)??e;if(e instanceof Jt)return Bt.fromUint8Array(e.data);if(e instanceof Xt)return new Gt(e.lat,e.lng);const i=Yn(e);if(i!==null)return Ht(i);if(Array.isArray(e))return e.map(u=>Se(u,t));if(e!==null&&typeof e=="object"){const u=Object.getPrototypeOf(e);if(u===Object.prototype||u===null){const d={};for(const[h,l]of Object.entries(e))d[h]=Se(l,t);return d}}return e}function ds(e,t){if(e!==void 0)return Se(e,t)}function Jn(e){if(e===void 0)return Jn(sn());const t=st(e);if(t)return t.service("firestore/default",()=>{const{sandbox:n,session:s}=t,r=de();t.onDelete(r.terminate);const i=t.authScope;i&&(r.own(s.onCurrentUserChanged(a=>{T(n).reevaluateLiveListeners(a,i)})),r.own(on(a=>{const c=a?.mode==="anon"?null:a?.mode==="as"?{uid:a.uid,...a.tenant?{tenant:a.tenant}:{}}:s.currentUser;T(n).reevaluateLiveListeners(c,i)})));const o={kind:"sandbox-live",activityApp:e,sandbox:n,getDb:Ze(n,()=>s.currentUser),authScope:i,...r};return{[F]:o,app:e}});if(Dt(e)){const n=Et(e),s={kind:"sandbox",activityApp:e,db:n,sandbox:e.sandbox,...de()};return{[F]:s}}if(Kn(e)){const n={kind:"sandbox-live",activityApp:e,sandbox:e,getDb:Ze(e),...de()};return{[F]:n}}throw new TypeError("pyric/firestore is a sandbox-only mirror. Package resolution must leave firebase/firestore unchanged for production; activate pyric sandbox or @pyric/cli/register before importing to select the sandbox.")}function de(){let e=!1;const t=new Set;return{own(n){return e?(n(),()=>{}):(t.add(n),()=>t.delete(n))},assertUsable(){if(e)throw new I("failed-precondition","The client has already been terminated.")},terminate(){if(!e){e=!0;for(const n of t)n();t.clear()}}}}function Xn(e){const t=st(e);if(t){t.assertAlive();const o=t.sandbox;return Xn(Ee(o.withAuth(null),{source:{kind:"app"},authLens:{mode:"admin"}}))}const n=Dt(e)?e:e.withAuth(null),s=n.sandbox,i={kind:"sandbox",db:In(n),sandbox:s};return{[F]:i}}function Dt(e){return e instanceof Zt}function Kn(e){if(e===null||typeof e!="object")return!1;const t=e;return typeof t.withAuth=="function"&&typeof t.onCurrentUserChanged=="function"&&"currentUser"in t&&"admin"in t}function Ze(e,t=()=>e.currentUser){return()=>{const n=t(),s=Ee(e.withAuth(n),{source:{kind:"app"},authLens:{mode:"app-session"}});return Et(s)}}function Zn(e,t,n,s){const r=en(e,t,n,s);if(r.length===0)return[{}];const i=[];for(const o of r)i.push(new tn(...o.path),o.value);return i}async function ls(e,t,n){const s=C(e);return se(oe(s,e,"setDoc","operation"),async()=>{const r=qe(e),i=r?r.toFirestore(t):t;return L(s).runWrite(()=>ie(()=>Pe(s,e).set(i,n)),e.path)})}function hs(e,t,...n){const s=C(e),r=Zn("updateDoc",e.path,t,n);return se(oe(s,e,"updateDoc","operation"),async()=>L(s).runWrite(()=>ie(()=>Pe(s,e).update(...r)),e.path))}async function fs(e){const t=C(e);return se(oe(t,e,"deleteDoc","operation"),async()=>L(t).runWrite(()=>ie(()=>Pe(t,e).delete()),e.path))}async function ps(e,t){const n=C(e);return se(oe(n,e,"addDoc","operation"),async()=>{const s=qe(e),r=s?s.toFirestore(t):t,i=await L(n).runWrite(async()=>{const c=await ie(()=>Bn(n,e).add(r));return L(n).cachePath(c.path),c}),o=i.path,a=Q(i,n,c=>c.doc(o));if(M(a,Re("reference",o)),Oe(a,o,n,a),s){const c=Ve(a,n,s);return Fe(a,c),c}return a})}export{us as A,kn as B,On as C,Ln as D,xe as E,Q as F,Ft as G,as as H,ps as I,hs as J,fs as K,ts as L,rn as M,se as N,Xn as O,ln as Q,F as T,sn as a,fe as b,L as c,os as d,qe as e,ds as f,Jn as g,At as h,ns as i,W as j,U as k,ct as l,ut as m,oe as n,C as o,cs as p,Pe as q,st as r,ls as s,Un as t,R as u,ss as v,ie as w,is as x,rs as y,Be as z};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</script><link rel="preconnect" href="https://use.typekit.net" crossorigin><link rel="stylesheet" href="https://use.typekit.net/jwb3ycu.css"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/_studio_.CzyEuvVS.css">
|
|
7
7
|
<style>html{scrollbar-gutter:stable}
|
|
8
8
|
</style>
|
|
9
|
-
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.
|
|
9
|
+
<link rel="stylesheet" href="/__pyric/ui/_astro/app.8TtSeQQX.css"></head> <body> <div id="root" data-astro-cid-w5sm6wlz> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="b1btC" component-url="/__pyric/ui/_astro/app.DqyhRyrU.js" component-export="StudioApp" renderer-url="/__pyric/ui/_astro/client.D2ORs4B-.js" props="{"data-astro-cid-w5sm6wlz":[0,true]}" ssr client="only" opts="{"name":"StudioApp","value":"react"}" await-children><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
10
10
|
Starting Pyric Studio…
|
|
11
11
|
</p><template data-astro-template="fallback"><p class="studio-loading" aria-live="polite" data-astro-cid-w5sm6wlz>
|
|
12
12
|
Starting Pyric Studio…
|
|
@@ -56,15 +56,15 @@ html{scrollbar-gutter:stable}
|
|
|
56
56
|
</details>
|
|
57
57
|
<details class="compat-row" data-status="ok">
|
|
58
58
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>set(ref, value)</code> replaces the value at the path</span></span></summary>
|
|
59
|
-
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
59
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L126" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("round-trips a primitive value" + "round-trips nested objects"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code></a> (prod observation blocked on rules; sandbox locks the contract directly)</div></div>
|
|
60
60
|
</details>
|
|
61
61
|
<details class="compat-row" data-status="ok">
|
|
62
62
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>set(ref, null)</code> deletes the subtree at the path</span></span></summary>
|
|
63
|
-
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
63
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L161" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("set(ref, null) deletes the path"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></a></div></div>
|
|
64
64
|
</details>
|
|
65
65
|
<details class="compat-row" data-status="ok">
|
|
66
66
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>remove(ref)</code> is equivalent to <code>set(ref, null)</code> (same end state)</span></span></summary>
|
|
67
|
-
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
67
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L161" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("remove and set(null) produce identical end-state"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></a></div></div>
|
|
68
68
|
</details>
|
|
69
69
|
<details class="compat-row" data-status="ok">
|
|
70
70
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>update(ref, patch)</code> shallow-merges top-level keys at the ref's path</span></span></summary>
|
|
@@ -84,7 +84,7 @@ html{scrollbar-gutter:stable}
|
|
|
84
84
|
</details>
|
|
85
85
|
<details class="compat-row" data-status="ok">
|
|
86
86
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref)</code> mints a 20-char auto-id key starting with <code>-</code>, lexicographically sortable</span></span></summary>
|
|
87
|
-
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
87
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L347" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("mints 20-char keys starting with \"-\"" + "sequential push keys are lex-sortable"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-push-autoid-format.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-push-autoid-format.json</code></a></div></div>
|
|
88
88
|
</details>
|
|
89
89
|
<details class="compat-row" data-status="ok">
|
|
90
90
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref, value)</code> writes <code>value</code> at the new child path</span></span></summary>
|
|
@@ -100,7 +100,7 @@ html{scrollbar-gutter:stable}
|
|
|
100
100
|
</details>
|
|
101
101
|
<details class="compat-row" data-status="ok">
|
|
102
102
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> resolves to a number (epoch ms) on read-back</span></span></summary>
|
|
103
|
-
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
103
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L383" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("resolves to a number on read-back"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json</code></a> (prod observation blocked on rules; sandbox locks the contract directly)</div></div>
|
|
104
104
|
</details>
|
|
105
105
|
<details class="compat-row" data-status="ok">
|
|
106
106
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> sentinels resolve when nested inside multi-path update payloads</span></span></summary>
|
|
@@ -108,11 +108,11 @@ html{scrollbar-gutter:stable}
|
|
|
108
108
|
</details>
|
|
109
109
|
<details class="compat-row" data-status="ok">
|
|
110
110
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied write throws a plain <code>Error</code> (NOT a <code>FirebaseError</code>) with <code>.code === 'PERMISSION_DENIED'</code> (uppercase snake-case) and <code>.message === 'PERMISSION_DENIED: Permission denied'</code></span></span></summary>
|
|
111
|
-
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
111
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L414" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("rules-denied set throws a plain Error with PERMISSION_DENIED code"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></a> (against blockingfun, fb-js-sdk 12.13.0). The sandbox adds an own enumerable <code>denialContext</code> (engine <code>rtdb</code>, the deciding rule, bindings and request) to the same plain <code>Error</code>; <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/denial-context.test.ts#L24" target="_blank" rel="noopener noreferrer"><code>unit:denial-context.test.ts</code></a> asserts class, name, code and message are unchanged for every denied operation, and the worker bridge test asserts served pages receive the context. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/cli/test/serve/worker/rtdb-denial-context.test.ts#L34" target="_blank" rel="noopener noreferrer"><code>rtdb-denial-context.test.ts</code></a>)</div></div>
|
|
112
112
|
</details>
|
|
113
113
|
<details class="compat-row" data-status="ok">
|
|
114
114
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied read throws the same plain-<code>Error</code> <code>PERMISSION_DENIED</code> shape as a denied write</span></span></summary>
|
|
115
|
-
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
115
|
+
<div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L414" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("rules-denied get throws the same plain Error shape"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></a> (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/denial-context.test.ts#L13" target="_blank" rel="noopener noreferrer"><code>denial-context.test.ts</code></a>)</div></div>
|
|
116
116
|
</details>
|
|
117
117
|
<details class="compat-row" data-status="ok">
|
|
118
118
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied remove throws the same plain-<code>Error</code> <code>PERMISSION_DENIED</code> shape</span></span></summary>
|
|
@@ -180,15 +180,15 @@ html{scrollbar-gutter:stable}
|
|
|
180
180
|
</details>
|
|
181
181
|
<details class="compat-row" data-status="ok">
|
|
182
182
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.setRules(db, rulesJson)</code> deploys rules to the in-process simulator; <code>setRules(db, null)</code> clears rules (default-allow)</span></span></summary>
|
|
183
|
-
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
183
|
+
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L42" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.setRules(db, null) clears rules"). Each rule expression of the deployed ruleset is parsed once, on its first evaluation, and later writes, multi-path updates, reads, and <code>simulate()</code> calls on a compiled ruleset reuse that parse; the next <code>setRules</code> call parses the new ruleset (<a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/sandbox/rules-parse-count.test.ts#L49" target="_blank" rel="noopener noreferrer"><code>unit:database/sandbox/rules-parse-count.test.ts</code></a>).</div></div>
|
|
184
184
|
</details>
|
|
185
185
|
<details class="compat-row" data-status="ok">
|
|
186
186
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.setData(db, { '/path': value })</code> bulk-loads data, bypassing rules</span></span></summary>
|
|
187
|
-
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
187
|
+
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L592" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.setData seeds the tree (rule-bypass)")</div></div>
|
|
188
188
|
</details>
|
|
189
189
|
<details class="compat-row" data-status="ok">
|
|
190
190
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.snapshotState(db)</code> dumps the full tree as a plain JSON object</span></span></summary>
|
|
191
|
-
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
191
|
+
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L58" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.snapshotState dumps the full tree")</div></div>
|
|
192
192
|
</details>
|
|
193
193
|
<details class="compat-row" data-status="ok">
|
|
194
194
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>query(ref, ...constraints)</code> + ordering/range constraints</span></span></summary>
|
|
@@ -348,27 +348,27 @@ html{scrollbar-gutter:stable}
|
|
|
348
348
|
</details>
|
|
349
349
|
<details class="compat-row" data-status="ok">
|
|
350
350
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Child-listener callbacks receive Firebase's <code>previousChildName</code> second argument, including initial replay and ordered-query movement.</span></span></summary>
|
|
351
|
-
<div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-child-previous-name.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-child-previous-name</code></a> captures initial replay plus add/change/remove/move predecessor values; replayed by <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#
|
|
351
|
+
<div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-child-previous-name.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-child-previous-name</code></a> captures initial replay plus add/change/remove/move predecessor values; replayed by <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#L27" target="_blank" rel="noopener noreferrer"><code>unit:modular/listener-lifecycle-cdd.test.ts</code></a>.</div></div>
|
|
352
352
|
</details>
|
|
353
353
|
<details class="compat-row" data-status="ok">
|
|
354
354
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Value and child listener overloads accept a cancellation callback and deliver Firebase-shaped permission errors when a listen is denied or revoked; a callbackless listener that loses auth access is terminal and does not resurrect after sign-in.</span></span></summary>
|
|
355
|
-
<div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-listener-cancellation.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-listener-cancellation</code></a> captures all five registrars returning normally, asynchronous initial-denial cancellation, one revocation callback each, and the Error/PERMISSION_DENIED/message shape; replayed in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#
|
|
355
|
+
<div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-listener-cancellation.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-listener-cancellation</code></a> captures all five registrars returning normally, asynchronous initial-denial cancellation, one revocation callback each, and the Error/PERMISSION_DENIED/message shape; replayed in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#L29" target="_blank" rel="noopener noreferrer"><code>unit:modular/listener-lifecycle-cdd.test.ts</code></a>. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/denial-context.test.ts#L19" target="_blank" rel="noopener noreferrer"><code>denial-context.test.ts</code></a>)</div></div>
|
|
356
356
|
</details>
|
|
357
357
|
<details class="compat-row" data-status="ok">
|
|
358
358
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">All child-listener functions accept <code>Query</code> inputs; add/change/remove events respect the active query window.</span></span></summary>
|
|
359
|
-
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#
|
|
359
|
+
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#L548" target="_blank" rel="noopener noreferrer"><code>unit:modular/listener-lifecycle-cdd.test.ts</code></a> and <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L18" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> cover initial windows plus entering, leaving, and changing members.</div></div>
|
|
360
360
|
</details>
|
|
361
361
|
<details class="compat-row" data-status="ok">
|
|
362
362
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildMoved</code> fires when an ordered child changes position and co-fires with <code>child_changed</code> when Firebase does, preserving the captured <code>previousChildName</code> sequence.</span></span></summary>
|
|
363
|
-
<div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-child-previous-name.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-child-previous-name</code></a> and the modular oracle suite replay ordered movement, co-fire behavior, and predecessor sequencing. As <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-childchanged-cofire-with-childmoved.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-childchanged-cofire-with-childmoved</code></a> records for a same-rank change of the ordered field, a child moves whenever its indexed value changes; <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/priority-listeners.test.ts#L12" target="_blank" rel="noopener noreferrer"><code>unit:modular/priority-listeners.test.ts</code></a> pins this for object values under <code>orderByValue()</code> and <code>orderByChild()</code>, which sort equal while differing. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildmoved-previouschildname-sequencing.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-onchildmoved-previouschildname-sequencing</code></a>, <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#
|
|
363
|
+
<div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-child-previous-name.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-child-previous-name</code></a> and the modular oracle suite replay ordered movement, co-fire behavior, and predecessor sequencing. As <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-childchanged-cofire-with-childmoved.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-childchanged-cofire-with-childmoved</code></a> records for a same-rank change of the ordered field, a child moves whenever its indexed value changes; <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/priority-listeners.test.ts#L12" target="_blank" rel="noopener noreferrer"><code>unit:modular/priority-listeners.test.ts</code></a> pins this for object values under <code>orderByValue()</code> and <code>orderByChild()</code>, which sort equal while differing. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildmoved-previouschildname-sequencing.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-onchildmoved-previouschildname-sequencing</code></a>, <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#L27" target="_blank" rel="noopener noreferrer"><code>listener-lifecycle-cdd.test.ts</code></a>, <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-listeners.test.ts#L178" target="_blank" rel="noopener noreferrer"><code>oracle-conformance-listeners.test.ts</code></a>)</div></div>
|
|
364
364
|
</details>
|
|
365
365
|
<details class="compat-row" data-status="ok">
|
|
366
366
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Child listener overloads accept <code>ListenOptions</code> directly or after a cancellation callback; <code>onlyOnce</code> stops delivery after Firebase's captured initial/event batch.</span></span></summary>
|
|
367
|
-
<div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-child-listener-only-once.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-child-listener-only-once</code></a> captures all four listener families, both overload shapes, the existing-child replay batch, and one-shot post-registration delivery; replayed by <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#
|
|
367
|
+
<div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-child-listener-only-once.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-child-listener-only-once</code></a> captures all four listener families, both overload shapes, the existing-child replay batch, and one-shot post-registration delivery; replayed by <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#L28" target="_blank" rel="noopener noreferrer"><code>unit:modular/listener-lifecycle-cdd.test.ts</code></a>.</div></div>
|
|
368
368
|
</details>
|
|
369
369
|
<details class="compat-row" data-status="ok">
|
|
370
370
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>.validate</code> rules are enforced on modular sandbox writes through <code>set</code>, atomic <code>update</code>, and <code>runTransaction</code>; a descendant validation failure rejects the operation without changing state.</span></span></summary>
|
|
371
|
-
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#
|
|
371
|
+
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L8" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> executes all three write paths against a required-child <code>.validate</code> rule and proves each rejects without committing state. The shared <code>SimulateHandler</code> behavior is production-locked by RTDB rules corpus rows #4 and #15.</div></div>
|
|
372
372
|
</details>
|
|
373
373
|
<details class="compat-row" data-status="ok">
|
|
374
374
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onDisconnect(ref)</code> returns the Firebase-shaped five-method handle; registration methods and <code>cancel()</code> return acknowledged Promises</span></span></summary>
|
|
@@ -658,7 +658,7 @@ html{scrollbar-gutter:stable}
|
|
|
658
658
|
</details>
|
|
659
659
|
<details class="compat-row" data-status="ok">
|
|
660
660
|
<summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">The returned value from <code>onValue(ref, cb)</code> is the unsubscribe function (NOT an object); calling it removes the listener</span></span></summary>
|
|
661
|
-
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#
|
|
661
|
+
<div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/listener-lifecycle-cdd.test.ts#L489" target="_blank" rel="noopener noreferrer"><code>unit:modular/listener-lifecycle-cdd.test.ts</code></a> asserts the return is a function and that invoking it stops subsequent delivery; production behavior is adjacent to oracle-backed row #131.</div></div>
|
|
662
662
|
</details>
|
|
663
663
|
</div>
|
|
664
664
|
<h3 id="onchildadded--onchildchanged--onchildremoved--onchildmoved"><code>onChildAdded</code> / <code>onChildChanged</code> / <code>onChildRemoved</code> / <code>onChildMoved</code></h3>
|