cvx-kit 0.1.18 → 0.1.20

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.
@@ -1,2 +1,2 @@
1
- import{scalarMatches as e}from"./planner.mjs";import{CursorError as t}from"./cursors.mjs";import{executeStream as n,rethrowQueryError as r}from"./execution.mjs";import{z as i}from"zod";import{EmptyStream as a,getIndexFields as o,stream as s}from"convex-helpers/server/stream";var c=class extends Error{code;constructor(e){super(e),this.code=e,this.name=`RelationshipError`}};function l(e,t){for(let n of Object.values(e)){if(t>=4)throw new c(`INVALID_RELATION`);n!==!0&&l(n,t+1)}}function u(u,f,p,m,h){let g=p.metadata,_=i.object({cursor:i.string(),ancestors:i.array(i.string()).max(3)}).strict(),v=e=>`base`in e?e.base:e;function y(e,t){p.assertUnchanged();let n=g.declarations[e]?.[t];if(!n)throw new c(`INVALID_RELATION`);return n}let b=(e,t)=>!t||e[t.discriminator]===t.tag,x=i.string();function S(e,t){if(!t)return!0;let n=x.safeParse(e);return n.success&&f.db.normalizeId(t.table,n.data)!==null}function C(e,t){if(!t||!b(t,e.sourceGuard))return;let n=t[v(e.from).field];return S(n,e.sourceMember)&&S(n,e.targetMember)?n:void 0}function w(e,t,n){let r=t===`_id`?{name:`by_id`,fields:[`_id`]}:g.tables[e].indexes.find(e=>{let r=e.fields.indexOf(t);return r>=0&&e.fields.slice(0,r).every(e=>e===n?.discriminator)});if(!r)throw new c(`INVALID_RELATION`);return r}function T(e,t,n,r,i){let a=t===`_id`?[{name:`by_id`,fields:[`_id`]}]:g.tables[e].indexes,o=e=>e===t||e===i?.discriminator||n.bindings.has(e),s=e=>e.fields.includes(t)&&e.fields.slice(0,e.fields.indexOf(t)).every(o),l=e=>{let t=0;for(let n of e.fields){if(!o(n))break;t++}return t},u=r.find(e=>e.value!==null&&e.value!==void 0);if(u){let e=a.find(e=>e.name===u.index&&s(e));if(!e)throw Error(`Explicit index "${u.index}" is incompatible with declared relationship lookup`);return e}let d=a.filter(s).sort((e,t)=>l(t)-l(e)||e.name.localeCompare(t.name)||e.fields.join(`\0`).localeCompare(t.fields.join(`\0`)));if(!d.length)throw new c(`INVALID_RELATION`);return d[0]}function E(e,t,n,r,i){let a=[];for(let o of e.fields)if(o===t)a.push({field:o,value:n});else if(o===i?.discriminator)a.push({field:o,value:i.tag});else if(r?.bindings.has(o))a.push({field:o,value:r.bindings.get(o)});else break;return a}async function D(e,t){if(p.beforeLeaf(e),t==null||!f.db.normalizeId(e,t))return null;let n=await f.db.get(e,t);return p.assertUnchanged(),n&&p.validateDocument(e,n),n}async function*O(e,t,n,r,i,a){if(f.expand(r,0),n==null||!S(n,a))return;if(t===`_id`){let o=await D(e,n);o&&b(o,i)&&S(o[t],a)&&(f.expand(r),yield o);return}p.beforeLeaf(e);let o=w(e,t,i),s=f.leafQuery(e).withIndex(o.name,e=>{let r=e;for(let e of E(o,t,n,void 0,i))r=r.eq(e.field,e.value);return r})[Symbol.asyncIterator]();try{for(;;){p.assertUnchanged(),p.beforeLeaf(e);let n=await s.next();if(p.assertUnchanged(),n.done)return;let o=await f.authorize(e,n.value);p.assertUnchanged(),o&&(p.validateDocument(e,n.value),b(n.value,i)&&S(n.value[t],a)&&(f.expand(r),yield n.value))}}finally{await s.return?.()}}async function*k(e,t,n){f.expand(n,0);let r=C(e,t);if(r!=null){if(`base`in e.from&&`base`in e.to)for await(let t of O(e.from.junction.table,e.from.junction.field,r,n,e.junctionGuard))yield*O(e.target,e.to.base.field,t[e.to.junction.field],n,e.targetGuard);else yield*O(e.target,v(e.to).field,r,n,e.targetGuard,e.targetMember)}}async function A(e,t,n){let r=null;for await(let i of k(e,t,n)){if(r)throw new c(`AMBIGUOUS_RELATION`);r=i}return r}async function j(t,n,r,i=0){if(f.expand(i,0),p.assertUnchanged(),g.tables[t].variant&&p.validateDocument(t,n),d(r))return e(r,n);if(r.kind===`variant`)return n[r.discriminator]===r.tag&&j(t,n,r.child,i);if(r.kind===`scalar`)return e(r,n);if(r.kind===`not`)return!await j(t,n,r.child,i);if(r.kind===`and`||r.kind===`or`){for(let e of r.children){let a=await j(t,n,e,i);if(r.kind===`and`&&!a)return!1;if(r.kind===`or`&&a)return!0}return r.kind===`and`}if(r.kind!==`relation`)throw new c(`INVALID_RELATION`);let a=y(t,r.name);if(r.mode===`one`){let e=await A(a,n,i+1);return r.predicate===null?e===null:e!==null&&await j(a.target,e,r.predicate,i+1)}for await(let e of k(a,n,i+1))if(await j(a.target,e,r.predicate,i+1))return r.mode===`some`;return r.mode===`none`}async function M(e,t,n,r,i=[],a=0,o=[]){f.expand(a,0);let s=p.complete(e,t,!0,{kind:`and`,children:[]});for(let[c,l]of Object.entries(n)){let n=y(e,c),u=l===!0?{}:l;if(n.cardinality===`one`){let e=await A(n,t,a+1);s[c]=e?await M(n.target,e,u,r,[...i,c],a+1,[...o,t._id]):null}else s[c]=await P(e,t,c,u,{numItems:r.numItems,cursor:null,order:r.order},[],[],[...i,c],a+1,[...o,t._id])}return s}function N(e,n,r,i,a,o,s,u){p.page(y(e,n).target,r),l(r,s.length);let d=y(e,n);if(d.cardinality!==`many`)throw new c(`INVALID_RELATION`);let g=d.targetGuard?{fields:{[d.targetGuard.discriminator]:d.targetGuard.tag}}:void 0,b=p.plan(d.target,i,[],g?[...o,g]:o),x=d.from,S=d.to,C=`base`in x&&`base`in S?{table:x.junction.table,field:x.junction.field,targetField:S.base.field,targetReference:S.junction.field}:null,E=C?C.table:d.target,D=C?C.field:v(S).field,O=T(d.target,C?C.targetField:D,b,a,d.targetGuard),k=C?w(E,D,d.junctionGuard):O,A={...h,table:E,index:k.name,order:b.args.order??`asc`,clientFilters:b.clientIdentity,serverFilters:{predicates:b.serverIdentity,selection:r,scope:{...f.scope},rootTable:h.table,lookupIndex:O.name,guards:{source:d.sourceGuard?{...d.sourceGuard}:null,target:d.targetGuard?{...d.targetGuard}:null,junction:d.junctionGuard?{...d.junctionGuard}:null},...(d.sourceMember||d.targetMember)&&{members:{source:d.sourceMember?{...d.sourceMember}:null,target:d.targetMember?{...d.targetMember}:null}}},relationPath:s,parent:u};function j(e){try{return _.parse(JSON.parse(m.open(e,A)))}catch{throw new t}}return{declared:d,plan:b,through:C,sourceTable:E,field:D,index:k,targetIndex:O,binding:A,open:j}}async function P(e,t,r,i,c,l=[],d=[],h=[r],g=1,_=[],y=N(e,r,i,c,l,d,h,_[0]??t._id),x){f.expand(g,0);let{declared:w,plan:T,through:O,sourceTable:k,field:A,index:P,targetIndex:F,binding:I}=y,L=C(w,t),R={...T.args,...x??{cursor:null}},z={...T,index:P,prefix:L==null?[]:O?E(P,A,L,void 0,w.junctionGuard):E(P,A,L,T,w.targetGuard),unsatisfiable:L==null||T.unsatisfiable},B=O&&O.targetField!==`_id`,V=await n(u,f,k,z,p,m,I,R,async(e,t)=>{if(t&&p.validateDocument(B?w.target:k,e),!t||O&&!B&&!b(e,w.junctionGuard))return null;f.expand(g);let n;return n=O&&!B?await D(w.target,e[O.targetReference]):e,!n||!b(n,w.targetGuard)||!S(n[v(w.to).field],w.targetMember)||!await j(w.target,n,T.residual,g)?null:M(w.target,n,i,T.args,h,g,_)},e=>m.seal(JSON.stringify({cursor:e,ancestors:_.slice(1)}),I),B?(e,t)=>{let n=u,r=o(w.target,F.name,n);return e.flatMap(async e=>{f.expand(g);let i=await f.authorize(k,e);p.assertUnchanged(),i&&p.validateDocument(k,e);let o=e[O.targetReference];return!i||!b(e,w.junctionGuard)||o==null?new a(T.args.order??`asc`,r):s(t,n).query(w.target).withIndex(F.name,e=>{let t=e,n=E(F,O.targetField,o,T,w.targetGuard);for(let e of n)t=t.eq(e.field,e.value);return t}).order(T.args.order??`asc`)},r)}:void 0,B?w.target:k);return p.assertUnchanged(),p.page(w.target,i).parse(V)}async function F(e,n,i,a,o,s,l){if(!i.length||i.length>4||!f.db.normalizeId(e,n))throw new c(`INVALID_RELATION`);let u=e,d=i.map(e=>{let t=y(u,e);return u=t.target,t}),p=d.at(-1),m=N(p.source,i.at(-1),a,o,s,l,i,n),h=o.cursor===null?null:m.open(o.cursor),g=o.endCursor==null?null:m.open(o.endCursor),_=h?.ancestors??g?.ancestors??[];if(_.length!==i.length-1||h&&g&&JSON.stringify(h.ancestors)!==JSON.stringify(g.ancestors)||_.some((e,t)=>!f.db.normalizeId(d[t].target,e)))throw new t;try{let t=await D(e,n);for(let e=0;t&&e<_.length;e++){let n=d[e],r=null;if(n.cardinality===`one`){let i=await A(n,t,e+1);i?._id===_[e]&&(r=i)}else for await(let i of k(n,t,e+1))if(i._id===_[e]){r=i;break}t=r}return await P(p.source,t,i.at(-1),a,o,s,l,i,i.length,[n,..._],m,{cursor:h?.cursor??null,endCursor:g?.cursor??o.endCursor})}catch(e){r(e)}}return{matches:j,output:M,continuation:F,edge:y}}function d(e){return e.kind===`relation`?!1:e.kind===`and`||e.kind===`or`?e.children.every(d):e.kind===`not`||e.kind===`variant`?d(e.child):!0}export{c as RelationshipError,l as assertRelationshipDepth,u as relationshipExecutor};
1
+ import{scalarMatches as e}from"./planner.mjs";import{CursorError as t}from"./cursors.mjs";import{executeStream as n,rethrowQueryError as r}from"./execution.mjs";import{z as i}from"zod";import{EmptyStream as a,getIndexFields as o,stream as s}from"convex-helpers/server/stream";const c=i.object({cursor:i.string(),ancestors:i.array(i.string()).max(3)}).strict();var l=class extends Error{code;constructor(e){super(e),this.code=e,this.name=`RelationshipError`}};function u(e,t){for(let n of Object.values(e)){if(t>=4)throw new l(`INVALID_RELATION`);n!==!0&&u(n,t+1)}}function d(d,p,m,h,g){let _=m.metadata,v=e=>`base`in e?e.base:e;function y(e,t){let n=_.declarations[e]?.[t];if(!n)throw new l(`INVALID_RELATION`);return n}let b=(e,t)=>!t||e[t.discriminator]===t.tag,x=i.string();function S(e,t){if(!t)return!0;let n=x.safeParse(e);return n.success&&p.db.normalizeId(t.table,n.data)!==null}function C(e,t){if(!t||!b(t,e.sourceGuard))return;let n=t[v(e.from).field];return S(n,e.sourceMember)&&S(n,e.targetMember)?n:void 0}function w(e,t,n){let r=t===`_id`?{name:`by_id`,fields:[`_id`]}:_.tables[e].indexes.find(e=>{let r=e.fields.indexOf(t);return r>=0&&e.fields.slice(0,r).every(e=>e===n?.discriminator)});if(!r)throw new l(`INVALID_RELATION`);return r}function T(e,t,n,r,i){let a=t===`_id`?[{name:`by_id`,fields:[`_id`]}]:_.tables[e].indexes,o=e=>e===t||e===i?.discriminator||n.bindings.has(e),s=e=>e.fields.includes(t)&&e.fields.slice(0,e.fields.indexOf(t)).every(o),c=e=>{let t=0;for(let n of e.fields){if(!o(n))break;t++}return t},u=r.find(e=>e.value!==null&&e.value!==void 0);if(u){let e=a.find(e=>e.name===u.index&&s(e));if(!e)throw Error(`Explicit index "${u.index}" is incompatible with declared relationship lookup`);return e}let d=a.filter(s).sort((e,t)=>c(t)-c(e)||e.name.localeCompare(t.name)||e.fields.join(`\0`).localeCompare(t.fields.join(`\0`)));if(!d.length)throw new l(`INVALID_RELATION`);return d[0]}function E(e,t,n,r,i){let a=[];for(let o of e.fields)if(o===t)a.push({field:o,value:n});else if(o===i?.discriminator)a.push({field:o,value:i.tag});else if(r?.bindings.has(o))a.push({field:o,value:r.bindings.get(o)});else break;return a}async function D(e,t){if(m.beforeLeaf(e),t==null||!p.db.normalizeId(e,t))return null;let n=await p.db.get(e,t);return n&&m.validateDocument(e,n),n}async function*O(e,t,n,r,i,a){if(p.expand(r,0),n==null||!S(n,a))return;if(t===`_id`){let o=await D(e,n);o&&b(o,i)&&S(o[t],a)&&(p.expand(r),yield o);return}m.beforeLeaf(e);let o=w(e,t,i),s=p.leafQuery(e).withIndex(o.name,e=>{let r=e;for(let e of E(o,t,n,void 0,i))r=r.eq(e.field,e.value);return r})[Symbol.asyncIterator]();try{for(;;){m.beforeLeaf(e);let n=await s.next();if(n.done)return;await p.authorize(e,n.value)&&(m.validateDocument(e,n.value),b(n.value,i)&&S(n.value[t],a)&&(p.expand(r),yield n.value))}}finally{await s.return?.()}}async function*k(e,t,n){p.expand(n,0);let r=C(e,t);if(r!=null){if(`base`in e.from&&`base`in e.to)for await(let t of O(e.from.junction.table,e.from.junction.field,r,n,e.junctionGuard))yield*O(e.target,e.to.base.field,t[e.to.junction.field],n,e.targetGuard);else yield*O(e.target,v(e.to).field,r,n,e.targetGuard,e.targetMember)}}async function A(e,t,n){let r=null;for await(let i of k(e,t,n)){if(r)throw new l(`AMBIGUOUS_RELATION`);r=i}return r}async function j(t,n,r,i=0){if(p.expand(i,0),_.tables[t].variant&&m.validateDocument(t,n),f(r))return e(r,n);if(r.kind===`variant`)return n[r.discriminator]===r.tag&&j(t,n,r.child,i);if(r.kind===`scalar`)return e(r,n);if(r.kind===`not`)return!await j(t,n,r.child,i);if(r.kind===`and`||r.kind===`or`){for(let e of r.children){let a=await j(t,n,e,i);if(r.kind===`and`&&!a)return!1;if(r.kind===`or`&&a)return!0}return r.kind===`and`}if(r.kind!==`relation`)throw new l(`INVALID_RELATION`);let a=y(t,r.name);if(r.mode===`one`){let e=await A(a,n,i+1);return r.predicate===null?e===null:e!==null&&await j(a.target,e,r.predicate,i+1)}for await(let e of k(a,n,i+1))if(await j(a.target,e,r.predicate,i+1))return r.mode===`some`;return r.mode===`none`}async function M(e,t,n,r,i=[],a=0,o=[]){p.expand(a,0);let s=m.complete(e,t,!0,{kind:`and`,children:[]});for(let[c,l]of Object.entries(n)){let n=y(e,c),u=l===!0?{}:l;if(n.cardinality===`one`){let e=await A(n,t,a+1);s[c]=e?await M(n.target,e,u,r,[...i,c],a+1,[...o,t._id]):null}else s[c]=await P(e,t,c,u,{numItems:r.numItems,cursor:null,order:r.order},[],[],[...i,c],a+1,[...o,t._id])}return s}function N(e,n,r,i,a,o,s,d){m.select(y(e,n).target,r),u(r,s.length);let f=y(e,n);if(f.cardinality!==`many`)throw new l(`INVALID_RELATION`);let _=f.targetGuard?{fields:{[f.targetGuard.discriminator]:f.targetGuard.tag}}:void 0,b=m.plan(f.target,i,[],_?[...o,_]:o),x=f.from,S=f.to,C=`base`in x&&`base`in S?{table:x.junction.table,field:x.junction.field,targetField:S.base.field,targetReference:S.junction.field}:null,E=C?C.table:f.target,D=C?C.field:v(S).field,O=T(f.target,C?C.targetField:D,b,a,f.targetGuard),k=C?w(E,D,f.junctionGuard):O,A={...g,table:E,index:k.name,order:b.args.order??`asc`,clientFilters:b.clientIdentity,serverFilters:{predicates:b.serverIdentity,selection:r,scope:{...p.scope},rootTable:g.table,lookupIndex:O.name,guards:{source:f.sourceGuard?{...f.sourceGuard}:null,target:f.targetGuard?{...f.targetGuard}:null,junction:f.junctionGuard?{...f.junctionGuard}:null},...(f.sourceMember||f.targetMember)&&{members:{source:f.sourceMember?{...f.sourceMember}:null,target:f.targetMember?{...f.targetMember}:null}}},relationPath:s,parent:d};function j(e){try{return c.parse(JSON.parse(h.open(e,A)))}catch{throw new t}}return{declared:f,plan:b,through:C,sourceTable:E,field:D,index:k,targetIndex:O,binding:A,open:j}}async function P(e,t,r,i,c,l=[],u=[],f=[r],g=1,_=[],y=N(e,r,i,c,l,u,f,_[0]??t._id),x){p.expand(g,0);let{declared:w,plan:T,through:O,sourceTable:k,field:A,index:P,targetIndex:F,binding:I}=y,L=C(w,t),R={...T.args,...x??{cursor:null}},z={...T,index:P,prefix:L==null?[]:O?E(P,A,L,void 0,w.junctionGuard):E(P,A,L,T,w.targetGuard),unsatisfiable:L==null||T.unsatisfiable},B=O&&O.targetField!==`_id`;return await n(d,p,k,z,m,h,I,R,async(e,t)=>{if(t&&m.validateDocument(B?w.target:k,e),!t||O&&!B&&!b(e,w.junctionGuard))return null;p.expand(g);let n;return n=O&&!B?await D(w.target,e[O.targetReference]):e,!n||!b(n,w.targetGuard)||!S(n[v(w.to).field],w.targetMember)||!await j(w.target,n,T.residual,g)?null:M(w.target,n,i,T.args,f,g,_)},e=>h.seal(JSON.stringify({cursor:e,ancestors:_.slice(1)}),I),B?(e,t)=>{let n=d,r=o(w.target,F.name,n);return e.flatMap(async e=>{p.expand(g);let i=await p.authorize(k,e);i&&m.validateDocument(k,e);let o=e[O.targetReference];return!i||!b(e,w.junctionGuard)||o==null?new a(T.args.order??`asc`,r):s(t,n).query(w.target).withIndex(F.name,e=>{let t=e,n=E(F,O.targetField,o,T,w.targetGuard);for(let e of n)t=t.eq(e.field,e.value);return t}).order(T.args.order??`asc`)},r)}:void 0,B?w.target:k)}async function F(e,n,i,a,o,s,c){if(!i.length||i.length>4||!p.db.normalizeId(e,n))throw new l(`INVALID_RELATION`);let u=e,d=i.map(e=>{let t=y(u,e);return u=t.target,t}),f=d.at(-1),m=N(f.source,i.at(-1),a,o,s,c,i,n),h=o.cursor===null?null:m.open(o.cursor),g=o.endCursor==null?null:m.open(o.endCursor),_=h?.ancestors??g?.ancestors??[];if(_.length!==i.length-1||h&&g&&JSON.stringify(h.ancestors)!==JSON.stringify(g.ancestors)||_.some((e,t)=>!p.db.normalizeId(d[t].target,e)))throw new t;try{let t=await D(e,n);for(let e=0;t&&e<_.length;e++){let n=d[e],r=null;if(n.cardinality===`one`){let i=await A(n,t,e+1);i?._id===_[e]&&(r=i)}else for await(let i of k(n,t,e+1))if(i._id===_[e]){r=i;break}t=r}return await P(f.source,t,i.at(-1),a,o,s,c,i,i.length,[n,..._],m,{cursor:h?.cursor??null,endCursor:g?.cursor??o.endCursor})}catch(e){r(e)}}return{matches:j,output:M,continuation:F,edge:y}}function f(e){return e.kind===`relation`?!1:e.kind===`and`||e.kind===`or`?e.children.every(f):e.kind===`not`||e.kind===`variant`?f(e.child):!0}export{l as RelationshipError,u as assertRelationshipDepth,d as relationshipExecutor};
2
2
  //# sourceMappingURL=relationships.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"relationships.mjs","names":["RelationshipError","code","assertRelationshipDepth","nested","selection","depth","relationshipExecutor","metadata","planner","navigation","z","base","leg","edge","declared","table","name","guarded","guard","row","memberIdSchema","memberMatches","member","id","value","request","sourceValue","parent","lookup","index","field","position","i","key","relationIndex","indexes","bound","plan","usable","length","size","condition","conditions","c","chosen","candidates","b","a","relationPrefix","prefix","get","result","targets","target","iterator","range","q","binding","next","permitted","traverse","junction","one","match","matches","scalarOnly","ast","scalarMatches","child","output","dto","selected","args","path","parents","pageRelation","prepare","guardConstraint","input","constraints","from","to","through","sourceTable","targetIndex","rootBinding","rootId","open","codec","token","CursorError","prepared","opened","lookupPlan","indexedTarget","executeStream","schema","raw","nativeSchema","fields","getIndexFields","source","reference","EmptyStream","stream","db","continuation","rootTable","declarations","declaration","final","start","end","ancestors","found","error","rethrowQueryError"],"sources":["../../src/querying/relationships.ts"],"sourcesContent":["import type { GenericSchema, SchemaDefinition, IndexRangeBuilder } from 'convex/server'\nimport type { GenericId, Value } from 'convex/values'\nimport type { RelationEdge, RelationGuard } from '../relations'\nimport type { createPlanner, QueryInput, StoredConstraint } from './planner'\nimport { scalarMatches } from './planner'\nimport type {\n\tFilterAst,\n\tFilterScalar,\n\tIndexCondition,\n\tNativePagination,\n\tQueryIndex,\n} from './filters'\nimport { executeStream, rethrowQueryError, type ExecutionRequest } from './execution'\nimport type { createCursorCodec, CursorBinding } from './cursors'\nimport { CursorError } from './cursors'\nimport { z } from 'zod'\nimport { stream, EmptyStream, getIndexFields } from 'convex-helpers/server/stream'\n\nexport interface OutputSelection {\n\t[name: string]: true | OutputSelection\n}\ntype Edge = RelationEdge<string, string, 'one' | 'many', any, any>\nexport type RelationDocument = Record<string, Value> & {\n\t_id: GenericId<string>\n\t_creationTime: number\n}\ntype Document = RelationDocument\ntype Planner = ReturnType<typeof createPlanner>\n\nexport class RelationshipError extends Error {\n\tconstructor(readonly code: 'AMBIGUOUS_RELATION' | 'INVALID_RELATION') {\n\t\tsuper(code)\n\t\tthis.name = 'RelationshipError'\n\t}\n}\n\n/** The selection has already passed the registry validator; count leaf edges too. */\nexport function assertRelationshipDepth(selection: OutputSelection, depth: number): void {\n\tfor (const nested of Object.values(selection)) {\n\t\tif (depth >= 4) throw new RelationshipError('INVALID_RELATION')\n\t\tif (nested !== true) assertRelationshipDepth(nested, depth + 1)\n\t}\n}\n\n/** One request owns all traversal and authorized ID memoization. No raw reader escapes. */\nexport function relationshipExecutor(\n\tschema: SchemaDefinition<GenericSchema, boolean>,\n\trequest: ExecutionRequest,\n\tplanner: Planner,\n\tcodec: ReturnType<typeof createCursorCodec>,\n\trootBinding: CursorBinding,\n) {\n\tconst metadata = planner.metadata\n\tconst navigation = z\n\t\t.object({ cursor: z.string(), ancestors: z.array(z.string()).max(3) })\n\t\t.strict()\n\tconst base = (leg: Edge['from']) => ('base' in leg ? leg.base : leg)\n\tfunction edge(table: string, name: string): Edge {\n\t\tplanner.assertUnchanged()\n\t\tconst declared = metadata.declarations[table]?.[name]\n\t\tif (!declared) throw new RelationshipError('INVALID_RELATION')\n\t\treturn declared\n\t}\n\tconst guarded = (row: Document | Record<string, Value>, guard?: RelationGuard) =>\n\t\t!guard || row[guard.discriminator] === guard.tag\n\tconst memberIdSchema = z.string()\n\tfunction memberMatches(value: Value | undefined, member: Edge['sourceMember']): boolean {\n\t\tif (!member) return true\n\t\tconst id = memberIdSchema.safeParse(value)\n\t\treturn id.success && request.db.normalizeId(member.table, id.data) !== null\n\t}\n\tfunction sourceValue(declared: Edge, parent: Document | null): Value | undefined {\n\t\tif (!parent || !guarded(parent, declared.sourceGuard)) return undefined\n\t\tconst value = parent[base(declared.from).field]\n\t\treturn memberMatches(value, declared.sourceMember) &&\n\t\t\tmemberMatches(value, declared.targetMember)\n\t\t\t? value\n\t\t\t: undefined\n\t}\n\tfunction lookup(table: string, field: string, guard?: RelationGuard) {\n\t\tconst index =\n\t\t\tfield === '_id'\n\t\t\t\t? { name: 'by_id', fields: ['_id'] }\n\t\t\t\t: metadata.tables[table].indexes.find((i) => {\n\t\t\t\t\t\tconst position = i.fields.indexOf(field)\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tposition >= 0 &&\n\t\t\t\t\t\t\ti.fields.slice(0, position).every((key) => key === guard?.discriminator)\n\t\t\t\t\t\t)\n\t\t\t\t\t})\n\t\tif (!index) throw new RelationshipError('INVALID_RELATION')\n\t\treturn index\n\t}\n\tfunction relationIndex(\n\t\ttable: string,\n\t\tfield: string,\n\t\tplan: ReturnType<Planner['plan']>,\n\t\tconditions: readonly IndexCondition[],\n\t\tguard?: RelationGuard,\n\t): QueryIndex {\n\t\tconst indexes =\n\t\t\tfield === '_id' ? [{ name: 'by_id', fields: ['_id'] }] : metadata.tables[table].indexes\n\t\tconst bound = (key: string) =>\n\t\t\tkey === field || key === guard?.discriminator || plan.bindings.has(key)\n\t\tconst usable = (index: QueryIndex) =>\n\t\t\tindex.fields.includes(field) &&\n\t\t\tindex.fields.slice(0, index.fields.indexOf(field)).every(bound)\n\t\tconst length = (index: QueryIndex) => {\n\t\t\tlet size = 0\n\t\t\tfor (const key of index.fields) {\n\t\t\t\tif (!bound(key)) break\n\t\t\t\tsize++\n\t\t\t}\n\t\t\treturn size\n\t\t}\n\t\tconst condition = conditions.find((c) => c.value !== null && c.value !== undefined)\n\t\tif (condition) {\n\t\t\tconst chosen = indexes.find((i) => i.name === condition.index && usable(i))\n\t\t\tif (!chosen)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Explicit index \"${condition.index}\" is incompatible with declared relationship lookup`,\n\t\t\t\t)\n\t\t\treturn chosen\n\t\t}\n\t\tconst candidates = indexes\n\t\t\t.filter(usable)\n\t\t\t.sort(\n\t\t\t\t(a, b) =>\n\t\t\t\t\tlength(b) - length(a) ||\n\t\t\t\t\ta.name.localeCompare(b.name) ||\n\t\t\t\t\ta.fields.join('\\0').localeCompare(b.fields.join('\\0')),\n\t\t\t)\n\t\tif (!candidates.length) throw new RelationshipError('INVALID_RELATION')\n\t\treturn candidates[0]\n\t}\n\tfunction relationPrefix(\n\t\tindex: QueryIndex,\n\t\tfield: string,\n\t\tvalue: FilterScalar,\n\t\tplan?: ReturnType<Planner['plan']>,\n\t\tguard?: RelationGuard,\n\t) {\n\t\tconst prefix: { field: string; value: FilterScalar }[] = []\n\t\tfor (const key of index.fields) {\n\t\t\tif (key === field) prefix.push({ field: key, value })\n\t\t\telse if (key === guard?.discriminator) prefix.push({ field: key, value: guard.tag })\n\t\t\telse if (plan?.bindings.has(key)) prefix.push({ field: key, value: plan.bindings.get(key)! })\n\t\t\telse break\n\t\t}\n\t\treturn prefix\n\t}\n\n\tasync function get(table: string, id: Value | undefined): Promise<Document | null> {\n\t\tplanner.beforeLeaf(table)\n\t\t// SAFETY: native normalization rejects non-string/non-table IDs before any read.\n\t\tif (id == null || !request.db.normalizeId(table, id as string)) return null\n\t\t// SAFETY: normalizeId verifies the declared native table before the authorized metered get.\n\t\tconst result = await request.db.get(table, id as GenericId<string>)\n\t\tplanner.assertUnchanged()\n\t\tif (result) planner.validateDocument(table, result)\n\t\t// SAFETY: normalizeId checked the table; the authorized native get retains system fields.\n\t\treturn result as Document | null\n\t}\n\tasync function* targets(\n\t\ttable: string,\n\t\tfield: string,\n\t\tvalue: Value | undefined,\n\t\tdepth: number,\n\t\tguard?: RelationGuard,\n\t\tmember?: Edge['targetMember'],\n\t): AsyncGenerator<Document> {\n\t\trequest.expand(depth, 0)\n\t\tif (value == null || !memberMatches(value, member)) return\n\t\tif (field === '_id') {\n\t\t\tconst target = await get(table, value)\n\t\t\tif (target && guarded(target, guard) && memberMatches(target[field], member)) {\n\t\t\t\trequest.expand(depth)\n\t\t\t\tyield target\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tplanner.beforeLeaf(table)\n\t\tconst index = lookup(table, field, guard)\n\t\t// SAFETY: registry validates the indexed native lookup prefix and compatible values.\n\t\tconst source = request.leafQuery(table).withIndex(index.name, (q) => {\n\t\t\t// SAFETY: registration checks the mandatory join and every preceding guard equality.\n\t\t\tlet range = q as IndexRangeBuilder<any, string[], number>\n\t\t\t// SAFETY: registered relation fields are native scalars; each equality advances the consecutive checked prefix.\n\t\t\tfor (const binding of relationPrefix(index, field, value as FilterScalar, undefined, guard)) {\n\t\t\t\t// SAFETY: the prefix comes from the declared index and registry-owned guard.\n\t\t\t\trange = range.eq(binding.field, binding.value) as IndexRangeBuilder<any, string[], number>\n\t\t\t}\n\t\t\treturn range\n\t\t})\n\t\tconst iterator = source[Symbol.asyncIterator]()\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tplanner.assertUnchanged()\n\t\t\t\tplanner.beforeLeaf(table)\n\t\t\t\tconst next = await iterator.next()\n\t\t\t\tplanner.assertUnchanged()\n\t\t\t\tif (next.done) return\n\t\t\t\tconst permitted = await request.authorize(table, next.value)\n\t\t\t\t// Denials are an await boundary too; never hide them inside an authorized iterator.\n\t\t\t\tplanner.assertUnchanged()\n\t\t\t\tif (!permitted) continue\n\t\t\t\tplanner.validateDocument(table, next.value)\n\t\t\t\tif (!guarded(next.value, guard) || !memberMatches(next.value[field], member)) continue\n\t\t\t\trequest.expand(depth)\n\t\t\t\t// SAFETY: native rows include system fields and explicit authorization just completed.\n\t\t\t\tyield next.value as Document\n\t\t\t}\n\t\t} finally {\n\t\t\tawait iterator.return?.()\n\t\t}\n\t}\n\tasync function* traverse(\n\t\tdeclared: Edge,\n\t\tparent: Document,\n\t\tdepth: number,\n\t): AsyncGenerator<Document> {\n\t\trequest.expand(depth, 0)\n\t\tconst value = sourceValue(declared, parent)\n\t\tif (value == null) return\n\t\tif ('base' in declared.from && 'base' in declared.to) {\n\t\t\tfor await (const junction of targets(\n\t\t\t\tdeclared.from.junction.table,\n\t\t\t\tdeclared.from.junction.field,\n\t\t\t\tvalue,\n\t\t\t\tdepth,\n\t\t\t\tdeclared.junctionGuard,\n\t\t\t))\n\t\t\t\tyield* targets(\n\t\t\t\t\tdeclared.target,\n\t\t\t\t\tdeclared.to.base.field,\n\t\t\t\t\tjunction[declared.to.junction.field],\n\t\t\t\t\tdepth,\n\t\t\t\t\tdeclared.targetGuard,\n\t\t\t\t)\n\t\t} else\n\t\t\tyield* targets(\n\t\t\t\tdeclared.target,\n\t\t\t\tbase(declared.to).field,\n\t\t\t\tvalue,\n\t\t\t\tdepth,\n\t\t\t\tdeclared.targetGuard,\n\t\t\t\tdeclared.targetMember,\n\t\t\t)\n\t}\n\tasync function one(declared: Edge, parent: Document, depth: number) {\n\t\tlet match: Document | null = null\n\t\tfor await (const target of traverse(declared, parent, depth)) {\n\t\t\tif (match) throw new RelationshipError('AMBIGUOUS_RELATION')\n\t\t\tmatch = target\n\t\t}\n\t\treturn match\n\t}\n\tasync function matches(\n\t\ttable: string,\n\t\tparent: Document,\n\t\tast: FilterAst,\n\t\tdepth = 0,\n\t): Promise<boolean> {\n\t\trequest.expand(depth, 0)\n\t\tplanner.assertUnchanged()\n\t\t// Ordinary tables have no variant document validation. The live schema\n\t\t// guard above still covers them; variant rows retain full stored validation.\n\t\tif (metadata.tables[table].variant) planner.validateDocument(table, parent)\n\t\t// Evaluate a scalar Boolean tree synchronously under that same guard,\n\t\t// rather than rechecking every registry schema at each predicate node.\n\t\tif (scalarOnly(ast)) return scalarMatches(ast, parent)\n\t\tif (ast.kind === 'variant')\n\t\t\treturn parent[ast.discriminator] === ast.tag && matches(table, parent, ast.child, depth)\n\t\tif (ast.kind === 'scalar') return scalarMatches(ast, parent)\n\t\tif (ast.kind === 'not') return !(await matches(table, parent, ast.child, depth))\n\t\tif (ast.kind === 'and' || ast.kind === 'or') {\n\t\t\tfor (const child of ast.children) {\n\t\t\t\tconst result = await matches(table, parent, child, depth)\n\t\t\t\tif (ast.kind === 'and' && !result) return false\n\t\t\t\tif (ast.kind === 'or' && result) return true\n\t\t\t}\n\t\t\treturn ast.kind === 'and'\n\t\t}\n\t\tif (ast.kind !== 'relation') throw new RelationshipError('INVALID_RELATION')\n\t\tconst declared = edge(table, ast.name)\n\t\tif (ast.mode === 'one') {\n\t\t\tconst target = await one(declared, parent, depth + 1)\n\t\t\treturn ast.predicate === null\n\t\t\t\t? target === null\n\t\t\t\t: target !== null && (await matches(declared.target, target, ast.predicate, depth + 1))\n\t\t}\n\t\tfor await (const target of traverse(declared, parent, depth + 1))\n\t\t\tif (await matches(declared.target, target, ast.predicate!, depth + 1))\n\t\t\t\treturn ast.mode === 'some'\n\t\t// Only actual authorized traversal exhaustion proves none.\n\t\treturn ast.mode === 'none'\n\t}\n\tasync function output(\n\t\ttable: string,\n\t\tparent: Document,\n\t\tselection: OutputSelection,\n\t\targs: NativePagination & { order?: 'asc' | 'desc' },\n\t\tpath: readonly string[] = [],\n\t\tdepth = 0,\n\t\tparents: readonly string[] = [],\n\t): Promise<Record<string, Value>> {\n\t\trequest.expand(depth, 0)\n\t\t// SAFETY: the registry strictly validates this public native DTO projection.\n\t\tconst dto = planner.complete(table, parent, true, { kind: 'and', children: [] }) as Record<\n\t\t\tstring,\n\t\t\tValue\n\t\t>\n\t\tfor (const [name, selected] of Object.entries(selection)) {\n\t\t\tconst declared = edge(table, name),\n\t\t\t\tnested = selected === true ? {} : selected\n\t\t\tif (declared.cardinality === 'one') {\n\t\t\t\tconst target = await one(declared, parent, depth + 1)\n\t\t\t\tdto[name] = target\n\t\t\t\t\t? await output(declared.target, target, nested, args, [...path, name], depth + 1, [\n\t\t\t\t\t\t\t...parents,\n\t\t\t\t\t\t\tparent._id,\n\t\t\t\t\t\t])\n\t\t\t\t\t: null\n\t\t\t} else {\n\t\t\t\tconst page = await pageRelation(\n\t\t\t\t\ttable,\n\t\t\t\t\tparent,\n\t\t\t\t\tname,\n\t\t\t\t\tnested,\n\t\t\t\t\t{ numItems: args.numItems, cursor: null, order: args.order },\n\t\t\t\t\t[],\n\t\t\t\t\t[],\n\t\t\t\t\t[...path, name],\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\t[...parents, parent._id],\n\t\t\t\t)\n\t\t\t\t// SAFETY: the declared page validator has parsed this nested DTO page.\n\t\t\t\tdto[name] = page as Value\n\t\t\t}\n\t\t}\n\t\treturn dto\n\t}\n\tfunction prepare(\n\t\ttable: string,\n\t\tname: string,\n\t\tselection: OutputSelection,\n\t\tinput: QueryInput,\n\t\tconditions: readonly IndexCondition[],\n\t\tconstraints: readonly StoredConstraint[],\n\t\tpath: readonly string[],\n\t\trootId: string,\n\t) {\n\t\tplanner.page(edge(table, name).target, selection)\n\t\tassertRelationshipDepth(selection, path.length)\n\t\tconst declared = edge(table, name)\n\t\tif (declared.cardinality !== 'many') throw new RelationshipError('INVALID_RELATION')\n\t\tconst guardConstraint = declared.targetGuard\n\t\t\t? { fields: { [declared.targetGuard.discriminator]: declared.targetGuard.tag } }\n\t\t\t: undefined\n\t\tconst plan = planner.plan(\n\t\t\tdeclared.target,\n\t\t\tinput,\n\t\t\t[],\n\t\t\tguardConstraint ? [...constraints, guardConstraint] : constraints,\n\t\t)\n\t\tconst from = declared.from,\n\t\t\tto = declared.to\n\t\tconst through =\n\t\t\t'base' in from && 'base' in to\n\t\t\t\t? {\n\t\t\t\t\t\ttable: from.junction.table,\n\t\t\t\t\t\tfield: from.junction.field,\n\t\t\t\t\t\ttargetField: to.base.field,\n\t\t\t\t\t\ttargetReference: to.junction.field,\n\t\t\t\t\t}\n\t\t\t\t: null\n\t\tconst sourceTable = through ? through.table : declared.target\n\t\tconst field = through ? through.field : base(to).field\n\t\tconst targetIndex = relationIndex(\n\t\t\tdeclared.target,\n\t\t\tthrough ? through.targetField : field,\n\t\t\tplan,\n\t\t\tconditions,\n\t\t\tdeclared.targetGuard,\n\t\t)\n\t\tconst index = through ? lookup(sourceTable, field, declared.junctionGuard) : targetIndex\n\t\t// SAFETY: planner.page validated the complete output mask before cursor binding.\n\t\tconst binding: CursorBinding = {\n\t\t\t...rootBinding,\n\t\t\ttable: sourceTable,\n\t\t\tindex: index.name,\n\t\t\torder: plan.args.order ?? 'asc',\n\t\t\tclientFilters: plan.clientIdentity,\n\t\t\tserverFilters: {\n\t\t\t\tpredicates: plan.serverIdentity,\n\t\t\t\tselection: selection as Value,\n\t\t\t\tscope: { ...request.scope },\n\t\t\t\trootTable: rootBinding.table,\n\t\t\t\tlookupIndex: targetIndex.name,\n\t\t\t\tguards: {\n\t\t\t\t\tsource: declared.sourceGuard ? { ...declared.sourceGuard } : null,\n\t\t\t\t\ttarget: declared.targetGuard ? { ...declared.targetGuard } : null,\n\t\t\t\t\tjunction: declared.junctionGuard ? { ...declared.junctionGuard } : null,\n\t\t\t\t},\n\t\t\t\t...((declared.sourceMember || declared.targetMember) && {\n\t\t\t\t\tmembers: {\n\t\t\t\t\t\tsource: declared.sourceMember ? { ...declared.sourceMember } : null,\n\t\t\t\t\t\ttarget: declared.targetMember ? { ...declared.targetMember } : null,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\trelationPath: path,\n\t\t\tparent: rootId,\n\t\t}\n\t\tfunction open(token: string) {\n\t\t\ttry {\n\t\t\t\treturn navigation.parse(JSON.parse(codec.open(token, binding)))\n\t\t\t} catch {\n\t\t\t\tthrow new CursorError()\n\t\t\t}\n\t\t}\n\t\treturn { declared, plan, through, sourceTable, field, index, targetIndex, binding, open }\n\t}\n\tasync function pageRelation(\n\t\ttable: string,\n\t\tparent: Document | null,\n\t\tname: string,\n\t\tselection: OutputSelection,\n\t\tinput: QueryInput,\n\t\tconditions: readonly IndexCondition[] = [],\n\t\tconstraints: readonly StoredConstraint[] = [],\n\t\tpath: readonly string[] = [name],\n\t\tdepth = 1,\n\t\tparents: readonly string[] = [],\n\t\tprepared = prepare(\n\t\t\ttable,\n\t\t\tname,\n\t\t\tselection,\n\t\t\tinput,\n\t\t\tconditions,\n\t\t\tconstraints,\n\t\t\tpath,\n\t\t\tparents[0] ?? parent!._id,\n\t\t),\n\t\topened?: { cursor: string | null; endCursor?: string | null },\n\t) {\n\t\trequest.expand(depth, 0)\n\t\tconst { declared, plan, through, sourceTable, field, index, targetIndex, binding } = prepared\n\t\tconst value = sourceValue(declared, parent)\n\t\tconst args = { ...plan.args, ...(opened ?? { cursor: null }) }\n\t\t// SAFETY: declarations accept only native scalar lookup values; nullish references are absence.\n\t\tconst lookupPlan = {\n\t\t\t...plan,\n\t\t\tindex,\n\t\t\tprefix:\n\t\t\t\tvalue == null\n\t\t\t\t\t? []\n\t\t\t\t\t: through\n\t\t\t\t\t\t? relationPrefix(index, field, value as FilterScalar, undefined, declared.junctionGuard)\n\t\t\t\t\t\t: relationPrefix(index, field, value as FilterScalar, plan, declared.targetGuard),\n\t\t\tunsatisfiable: value == null || plan.unsatisfiable,\n\t\t}\n\t\tconst indexedTarget = through && through.targetField !== '_id'\n\t\tconst result = await executeStream(\n\t\t\tschema,\n\t\t\trequest,\n\t\t\tsourceTable,\n\t\t\tlookupPlan,\n\t\t\tplanner,\n\t\t\tcodec,\n\t\t\tbinding,\n\t\t\targs,\n\t\t\tasync (row, permitted) => {\n\t\t\t\tif (permitted) planner.validateDocument(indexedTarget ? declared.target : sourceTable, row)\n\t\t\t\tif (!permitted || (through && !indexedTarget && !guarded(row, declared.junctionGuard)))\n\t\t\t\t\treturn null\n\t\t\t\trequest.expand(depth)\n\t\t\t\tlet target: Document | null\n\t\t\t\tif (through && !indexedTarget)\n\t\t\t\t\ttarget = await get(declared.target, row[through.targetReference])\n\t\t\t\telse {\n\t\t\t\t\t// SAFETY: native direct/flattened target streams retain validated system fields.\n\t\t\t\t\ttarget = row as Document\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\t!target ||\n\t\t\t\t\t!guarded(target, declared.targetGuard) ||\n\t\t\t\t\t!memberMatches(target[base(declared.to).field], declared.targetMember) ||\n\t\t\t\t\t!(await matches(declared.target, target, plan.residual, depth))\n\t\t\t\t)\n\t\t\t\t\treturn null\n\t\t\t\treturn output(declared.target, target, selection, plan.args, path, depth, parents)\n\t\t\t},\n\t\t\t(raw) => codec.seal(JSON.stringify({ cursor: raw, ancestors: parents.slice(1) }), binding),\n\t\t\tindexedTarget\n\t\t\t\t? (source, db) => {\n\t\t\t\t\t\t// SAFETY: the registry owns the native schema/index descriptors. Public\n\t\t\t\t\t\t// helper flatMap concatenates native outer/inner keys and paginates them.\n\t\t\t\t\t\tconst nativeSchema = schema as SchemaDefinition<\n\t\t\t\t\t\t\tRecord<\n\t\t\t\t\t\t\t\tstring,\n\t\t\t\t\t\t\t\timport('convex/server').TableDefinition<any, Record<string, string[]>>\n\t\t\t\t\t\t\t>,\n\t\t\t\t\t\t\tboolean\n\t\t\t\t\t\t>\n\t\t\t\t\t\tconst fields = getIndexFields(declared.target, targetIndex.name, nativeSchema)\n\t\t\t\t\t\treturn source.flatMap(async (junction) => {\n\t\t\t\t\t\t\trequest.expand(depth)\n\t\t\t\t\t\t\tconst permitted = await request.authorize(sourceTable, junction)\n\t\t\t\t\t\t\tplanner.assertUnchanged()\n\t\t\t\t\t\t\tif (permitted) planner.validateDocument(sourceTable, junction)\n\t\t\t\t\t\t\tconst reference = junction[through.targetReference]\n\t\t\t\t\t\t\tif (!permitted || !guarded(junction, declared.junctionGuard) || reference == null)\n\t\t\t\t\t\t\t\treturn new EmptyStream(plan.args.order ?? 'asc', fields)\n\t\t\t\t\t\t\treturn stream(db, nativeSchema)\n\t\t\t\t\t\t\t\t.query(declared.target)\n\t\t\t\t\t\t\t\t.withIndex(targetIndex.name, (q) => {\n\t\t\t\t\t\t\t\t\t// SAFETY: registry validates the native leading lookup; validated filters supply each consecutive trailing binding.\n\t\t\t\t\t\t\t\t\tlet range = q as IndexRangeBuilder<any, string[], number>\n\t\t\t\t\t\t\t\t\t// SAFETY: junction references are native scalar Values validated by the declared lookup.\n\t\t\t\t\t\t\t\t\tconst prefix = relationPrefix(\n\t\t\t\t\t\t\t\t\t\ttargetIndex,\n\t\t\t\t\t\t\t\t\t\tthrough.targetField,\n\t\t\t\t\t\t\t\t\t\treference as FilterScalar,\n\t\t\t\t\t\t\t\t\t\tplan,\n\t\t\t\t\t\t\t\t\t\tdeclared.targetGuard,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tfor (const binding of prefix) {\n\t\t\t\t\t\t\t\t\t\t// SAFETY: native eq advances the validated consecutive index prefix.\n\t\t\t\t\t\t\t\t\t\trange = range.eq(binding.field, binding.value) as IndexRangeBuilder<\n\t\t\t\t\t\t\t\t\t\t\tany,\n\t\t\t\t\t\t\t\t\t\t\tstring[],\n\t\t\t\t\t\t\t\t\t\t\tnumber\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn range\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.order(plan.args.order ?? 'asc')\n\t\t\t\t\t\t}, fields)\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\tindexedTarget ? declared.target : sourceTable,\n\t\t)\n\t\tplanner.assertUnchanged()\n\t\treturn planner.page(declared.target, selection).parse(result)\n\t}\n\tasync function continuation(\n\t\trootTable: string,\n\t\trootId: string,\n\t\tpath: readonly string[],\n\t\tselection: OutputSelection,\n\t\tinput: QueryInput,\n\t\tconditions: readonly IndexCondition[],\n\t\tconstraints: readonly StoredConstraint[],\n\t) {\n\t\tif (!path.length || path.length > 4 || !request.db.normalizeId(rootTable, rootId))\n\t\t\tthrow new RelationshipError('INVALID_RELATION')\n\t\tlet table = rootTable\n\t\tconst declarations = path.map((name) => {\n\t\t\tconst declaration = edge(table, name)\n\t\t\ttable = declaration.target\n\t\t\treturn declaration\n\t\t})\n\t\tconst final = declarations.at(-1)!\n\t\tconst prepared = prepare(\n\t\t\tfinal.source,\n\t\t\tpath.at(-1)!,\n\t\t\tselection,\n\t\t\tinput,\n\t\t\tconditions,\n\t\t\tconstraints,\n\t\t\tpath,\n\t\t\trootId,\n\t\t)\n\t\t// Authenticate both slots and native ancestor IDs before ANY parent/traversal read.\n\t\tconst start = input.cursor === null ? null : prepared.open(input.cursor)\n\t\tconst end = input.endCursor == null ? null : prepared.open(input.endCursor)\n\t\tconst ancestors = start?.ancestors ?? end?.ancestors ?? []\n\t\tif (\n\t\t\tancestors.length !== path.length - 1 ||\n\t\t\t(start && end && JSON.stringify(start.ancestors) !== JSON.stringify(end.ancestors)) ||\n\t\t\tancestors.some((id, i) => !request.db.normalizeId(declarations[i].target, id))\n\t\t)\n\t\t\tthrow new CursorError()\n\t\t// Declarative input/index/cursor validation above retains its pre-read errors,\n\t\t// just as on the root path. Every awaited read, ancestry proof and page is protected.\n\t\ttry {\n\t\t\tlet parent = await get(rootTable, rootId)\n\t\t\tfor (let i = 0; parent && i < ancestors.length; i++) {\n\t\t\t\tconst declared = declarations[i]\n\t\t\t\tlet found: Document | null = null\n\t\t\t\tif (declared.cardinality === 'one') {\n\t\t\t\t\tconst target = await one(declared, parent, i + 1)\n\t\t\t\t\tif (target?._id === ancestors[i]) found = target\n\t\t\t\t} else\n\t\t\t\t\tfor await (const target of traverse(declared, parent, i + 1)) {\n\t\t\t\t\t\tif (target._id === ancestors[i]) {\n\t\t\t\t\t\t\tfound = target\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tparent = found\n\t\t\t}\n\t\t\treturn await pageRelation(\n\t\t\t\tfinal.source,\n\t\t\t\tparent,\n\t\t\t\tpath.at(-1)!,\n\t\t\t\tselection,\n\t\t\t\tinput,\n\t\t\t\tconditions,\n\t\t\t\tconstraints,\n\t\t\t\tpath,\n\t\t\t\tpath.length,\n\t\t\t\t[rootId, ...ancestors],\n\t\t\t\tprepared,\n\t\t\t\t{ cursor: start?.cursor ?? null, endCursor: end?.cursor ?? input.endCursor },\n\t\t\t)\n\t\t} catch (error) {\n\t\t\trethrowQueryError(error)\n\t\t}\n\t}\n\treturn { matches, output, continuation, edge }\n}\n\n/** Scalar subtrees have no reads or await boundaries requiring another live guard. */\nfunction scalarOnly(ast: FilterAst): boolean {\n\tif (ast.kind === 'relation') return false\n\tif (ast.kind === 'and' || ast.kind === 'or') return ast.children.every(scalarOnly)\n\tif (ast.kind === 'not' || ast.kind === 'variant') return scalarOnly(ast.child)\n\treturn true\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"relationships.mjs","names":["navigation","z","RelationshipError","code","assertRelationshipDepth","nested","selection","depth","relationshipExecutor","metadata","planner","base","leg","edge","declared","table","name","guarded","guard","row","memberIdSchema","memberMatches","member","id","value","request","sourceValue","parent","lookup","index","field","position","i","key","relationIndex","indexes","bound","plan","usable","length","size","condition","conditions","c","chosen","candidates","b","a","relationPrefix","prefix","get","result","targets","target","iterator","range","q","binding","next","traverse","junction","one","match","matches","scalarOnly","ast","scalarMatches","child","output","dto","selected","args","path","parents","pageRelation","prepare","guardConstraint","input","constraints","from","to","through","sourceTable","targetIndex","rootBinding","rootId","open","codec","token","CursorError","prepared","opened","lookupPlan","indexedTarget","executeStream","schema","permitted","raw","nativeSchema","fields","getIndexFields","source","reference","EmptyStream","stream","db","continuation","rootTable","declarations","declaration","final","start","end","ancestors","found","error","rethrowQueryError"],"sources":["../../src/querying/relationships.ts"],"sourcesContent":["import type { GenericSchema, SchemaDefinition, IndexRangeBuilder } from 'convex/server'\nimport type { GenericId, Value } from 'convex/values'\nimport type { RelationEdge, RelationGuard } from '../relations'\nimport type { createPlanner, QueryInput, StoredConstraint } from './planner'\nimport { scalarMatches } from './planner'\nimport type {\n\tFilterAst,\n\tFilterScalar,\n\tIndexCondition,\n\tNativePagination,\n\tQueryIndex,\n} from './filters'\nimport { executeStream, rethrowQueryError, type ExecutionRequest } from './execution'\nimport type { createCursorCodec, CursorBinding } from './cursors'\nimport { CursorError } from './cursors'\nimport { z } from 'zod'\nimport { stream, EmptyStream, getIndexFields } from 'convex-helpers/server/stream'\n\nexport interface OutputSelection {\n\t[name: string]: true | OutputSelection\n}\ntype Edge = RelationEdge<string, string, 'one' | 'many', any, any>\nexport type RelationDocument = Record<string, Value> & {\n\t_id: GenericId<string>\n\t_creationTime: number\n}\ntype Document = RelationDocument\ntype Planner = ReturnType<typeof createPlanner>\nconst navigation = z.object({ cursor: z.string(), ancestors: z.array(z.string()).max(3) }).strict()\n\nexport class RelationshipError extends Error {\n\tconstructor(readonly code: 'AMBIGUOUS_RELATION' | 'INVALID_RELATION') {\n\t\tsuper(code)\n\t\tthis.name = 'RelationshipError'\n\t}\n}\n\n/** The selection has already passed the registry validator; count leaf edges too. */\nexport function assertRelationshipDepth(selection: OutputSelection, depth: number): void {\n\tfor (const nested of Object.values(selection)) {\n\t\tif (depth >= 4) throw new RelationshipError('INVALID_RELATION')\n\t\tif (nested !== true) assertRelationshipDepth(nested, depth + 1)\n\t}\n}\n\n/** One request owns all traversal and authorized ID memoization. No raw reader escapes. */\nexport function relationshipExecutor(\n\tschema: SchemaDefinition<GenericSchema, boolean>,\n\trequest: ExecutionRequest,\n\tplanner: Planner,\n\tcodec: ReturnType<typeof createCursorCodec>,\n\trootBinding: CursorBinding,\n) {\n\tconst metadata = planner.metadata\n\tconst base = (leg: Edge['from']) => ('base' in leg ? leg.base : leg)\n\tfunction edge(table: string, name: string): Edge {\n\t\tconst declared = metadata.declarations[table]?.[name]\n\t\tif (!declared) throw new RelationshipError('INVALID_RELATION')\n\t\treturn declared\n\t}\n\tconst guarded = (row: Document | Record<string, Value>, guard?: RelationGuard) =>\n\t\t!guard || row[guard.discriminator] === guard.tag\n\tconst memberIdSchema = z.string()\n\tfunction memberMatches(value: Value | undefined, member: Edge['sourceMember']): boolean {\n\t\tif (!member) return true\n\t\tconst id = memberIdSchema.safeParse(value)\n\t\treturn id.success && request.db.normalizeId(member.table, id.data) !== null\n\t}\n\tfunction sourceValue(declared: Edge, parent: Document | null): Value | undefined {\n\t\tif (!parent || !guarded(parent, declared.sourceGuard)) return undefined\n\t\tconst value = parent[base(declared.from).field]\n\t\treturn memberMatches(value, declared.sourceMember) &&\n\t\t\tmemberMatches(value, declared.targetMember)\n\t\t\t? value\n\t\t\t: undefined\n\t}\n\tfunction lookup(table: string, field: string, guard?: RelationGuard) {\n\t\tconst index =\n\t\t\tfield === '_id'\n\t\t\t\t? { name: 'by_id', fields: ['_id'] }\n\t\t\t\t: metadata.tables[table].indexes.find((i) => {\n\t\t\t\t\t\tconst position = i.fields.indexOf(field)\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tposition >= 0 &&\n\t\t\t\t\t\t\ti.fields.slice(0, position).every((key) => key === guard?.discriminator)\n\t\t\t\t\t\t)\n\t\t\t\t\t})\n\t\tif (!index) throw new RelationshipError('INVALID_RELATION')\n\t\treturn index\n\t}\n\tfunction relationIndex(\n\t\ttable: string,\n\t\tfield: string,\n\t\tplan: ReturnType<Planner['plan']>,\n\t\tconditions: readonly IndexCondition[],\n\t\tguard?: RelationGuard,\n\t): QueryIndex {\n\t\tconst indexes =\n\t\t\tfield === '_id' ? [{ name: 'by_id', fields: ['_id'] }] : metadata.tables[table].indexes\n\t\tconst bound = (key: string) =>\n\t\t\tkey === field || key === guard?.discriminator || plan.bindings.has(key)\n\t\tconst usable = (index: QueryIndex) =>\n\t\t\tindex.fields.includes(field) &&\n\t\t\tindex.fields.slice(0, index.fields.indexOf(field)).every(bound)\n\t\tconst length = (index: QueryIndex) => {\n\t\t\tlet size = 0\n\t\t\tfor (const key of index.fields) {\n\t\t\t\tif (!bound(key)) break\n\t\t\t\tsize++\n\t\t\t}\n\t\t\treturn size\n\t\t}\n\t\tconst condition = conditions.find((c) => c.value !== null && c.value !== undefined)\n\t\tif (condition) {\n\t\t\tconst chosen = indexes.find((i) => i.name === condition.index && usable(i))\n\t\t\tif (!chosen)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Explicit index \"${condition.index}\" is incompatible with declared relationship lookup`,\n\t\t\t\t)\n\t\t\treturn chosen\n\t\t}\n\t\tconst candidates = indexes\n\t\t\t.filter(usable)\n\t\t\t.sort(\n\t\t\t\t(a, b) =>\n\t\t\t\t\tlength(b) - length(a) ||\n\t\t\t\t\ta.name.localeCompare(b.name) ||\n\t\t\t\t\ta.fields.join('\\0').localeCompare(b.fields.join('\\0')),\n\t\t\t)\n\t\tif (!candidates.length) throw new RelationshipError('INVALID_RELATION')\n\t\treturn candidates[0]\n\t}\n\tfunction relationPrefix(\n\t\tindex: QueryIndex,\n\t\tfield: string,\n\t\tvalue: FilterScalar,\n\t\tplan?: ReturnType<Planner['plan']>,\n\t\tguard?: RelationGuard,\n\t) {\n\t\tconst prefix: { field: string; value: FilterScalar }[] = []\n\t\tfor (const key of index.fields) {\n\t\t\tif (key === field) prefix.push({ field: key, value })\n\t\t\telse if (key === guard?.discriminator) prefix.push({ field: key, value: guard.tag })\n\t\t\telse if (plan?.bindings.has(key)) prefix.push({ field: key, value: plan.bindings.get(key)! })\n\t\t\telse break\n\t\t}\n\t\treturn prefix\n\t}\n\n\tasync function get(table: string, id: Value | undefined): Promise<Document | null> {\n\t\tplanner.beforeLeaf(table)\n\t\t// SAFETY: native normalization rejects non-string/non-table IDs before any read.\n\t\tif (id == null || !request.db.normalizeId(table, id as string)) return null\n\t\t// SAFETY: normalizeId verifies the declared native table before the authorized metered get.\n\t\tconst result = await request.db.get(table, id as GenericId<string>)\n\t\tif (result) planner.validateDocument(table, result)\n\t\t// SAFETY: normalizeId checked the table; the authorized native get retains system fields.\n\t\treturn result as Document | null\n\t}\n\tasync function* targets(\n\t\ttable: string,\n\t\tfield: string,\n\t\tvalue: Value | undefined,\n\t\tdepth: number,\n\t\tguard?: RelationGuard,\n\t\tmember?: Edge['targetMember'],\n\t): AsyncGenerator<Document> {\n\t\trequest.expand(depth, 0)\n\t\tif (value == null || !memberMatches(value, member)) return\n\t\tif (field === '_id') {\n\t\t\tconst target = await get(table, value)\n\t\t\tif (target && guarded(target, guard) && memberMatches(target[field], member)) {\n\t\t\t\trequest.expand(depth)\n\t\t\t\tyield target\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tplanner.beforeLeaf(table)\n\t\tconst index = lookup(table, field, guard)\n\t\t// SAFETY: registry validates the indexed native lookup prefix and compatible values.\n\t\tconst source = request.leafQuery(table).withIndex(index.name, (q) => {\n\t\t\t// SAFETY: registration checks the mandatory join and every preceding guard equality.\n\t\t\tlet range = q as IndexRangeBuilder<any, string[], number>\n\t\t\t// SAFETY: registered relation fields are native scalars; each equality advances the consecutive checked prefix.\n\t\t\tfor (const binding of relationPrefix(index, field, value as FilterScalar, undefined, guard)) {\n\t\t\t\t// SAFETY: the prefix comes from the declared index and registry-owned guard.\n\t\t\t\trange = range.eq(binding.field, binding.value) as IndexRangeBuilder<any, string[], number>\n\t\t\t}\n\t\t\treturn range\n\t\t})\n\t\tconst iterator = source[Symbol.asyncIterator]()\n\t\ttry {\n\t\t\twhile (true) {\n\t\t\t\tplanner.beforeLeaf(table)\n\t\t\t\tconst next = await iterator.next()\n\t\t\t\tif (next.done) return\n\t\t\t\tconst permitted = await request.authorize(table, next.value)\n\t\t\t\t// Denials are an await boundary too; never hide them inside an authorized iterator.\n\t\t\t\tif (!permitted) continue\n\t\t\t\tplanner.validateDocument(table, next.value)\n\t\t\t\tif (!guarded(next.value, guard) || !memberMatches(next.value[field], member)) continue\n\t\t\t\trequest.expand(depth)\n\t\t\t\t// SAFETY: native rows include system fields and explicit authorization just completed.\n\t\t\t\tyield next.value as Document\n\t\t\t}\n\t\t} finally {\n\t\t\tawait iterator.return?.()\n\t\t}\n\t}\n\tasync function* traverse(\n\t\tdeclared: Edge,\n\t\tparent: Document,\n\t\tdepth: number,\n\t): AsyncGenerator<Document> {\n\t\trequest.expand(depth, 0)\n\t\tconst value = sourceValue(declared, parent)\n\t\tif (value == null) return\n\t\tif ('base' in declared.from && 'base' in declared.to) {\n\t\t\tfor await (const junction of targets(\n\t\t\t\tdeclared.from.junction.table,\n\t\t\t\tdeclared.from.junction.field,\n\t\t\t\tvalue,\n\t\t\t\tdepth,\n\t\t\t\tdeclared.junctionGuard,\n\t\t\t))\n\t\t\t\tyield* targets(\n\t\t\t\t\tdeclared.target,\n\t\t\t\t\tdeclared.to.base.field,\n\t\t\t\t\tjunction[declared.to.junction.field],\n\t\t\t\t\tdepth,\n\t\t\t\t\tdeclared.targetGuard,\n\t\t\t\t)\n\t\t} else\n\t\t\tyield* targets(\n\t\t\t\tdeclared.target,\n\t\t\t\tbase(declared.to).field,\n\t\t\t\tvalue,\n\t\t\t\tdepth,\n\t\t\t\tdeclared.targetGuard,\n\t\t\t\tdeclared.targetMember,\n\t\t\t)\n\t}\n\tasync function one(declared: Edge, parent: Document, depth: number) {\n\t\tlet match: Document | null = null\n\t\tfor await (const target of traverse(declared, parent, depth)) {\n\t\t\tif (match) throw new RelationshipError('AMBIGUOUS_RELATION')\n\t\t\tmatch = target\n\t\t}\n\t\treturn match\n\t}\n\tasync function matches(\n\t\ttable: string,\n\t\tparent: Document,\n\t\tast: FilterAst,\n\t\tdepth = 0,\n\t): Promise<boolean> {\n\t\trequest.expand(depth, 0)\n\t\t// Variant rows must satisfy the captured stored branch before predicates\n\t\t// inspect branch fields. Ordinary output rows are validated by projection.\n\t\tif (metadata.tables[table].variant) planner.validateDocument(table, parent)\n\t\tif (scalarOnly(ast)) return scalarMatches(ast, parent)\n\t\tif (ast.kind === 'variant')\n\t\t\treturn parent[ast.discriminator] === ast.tag && matches(table, parent, ast.child, depth)\n\t\tif (ast.kind === 'scalar') return scalarMatches(ast, parent)\n\t\tif (ast.kind === 'not') return !(await matches(table, parent, ast.child, depth))\n\t\tif (ast.kind === 'and' || ast.kind === 'or') {\n\t\t\tfor (const child of ast.children) {\n\t\t\t\tconst result = await matches(table, parent, child, depth)\n\t\t\t\tif (ast.kind === 'and' && !result) return false\n\t\t\t\tif (ast.kind === 'or' && result) return true\n\t\t\t}\n\t\t\treturn ast.kind === 'and'\n\t\t}\n\t\tif (ast.kind !== 'relation') throw new RelationshipError('INVALID_RELATION')\n\t\tconst declared = edge(table, ast.name)\n\t\tif (ast.mode === 'one') {\n\t\t\tconst target = await one(declared, parent, depth + 1)\n\t\t\treturn ast.predicate === null\n\t\t\t\t? target === null\n\t\t\t\t: target !== null && (await matches(declared.target, target, ast.predicate, depth + 1))\n\t\t}\n\t\tfor await (const target of traverse(declared, parent, depth + 1))\n\t\t\tif (await matches(declared.target, target, ast.predicate!, depth + 1))\n\t\t\t\treturn ast.mode === 'some'\n\t\t// Only actual authorized traversal exhaustion proves none.\n\t\treturn ast.mode === 'none'\n\t}\n\tasync function output(\n\t\ttable: string,\n\t\tparent: Document,\n\t\tselection: OutputSelection,\n\t\targs: NativePagination & { order?: 'asc' | 'desc' },\n\t\tpath: readonly string[] = [],\n\t\tdepth = 0,\n\t\tparents: readonly string[] = [],\n\t): Promise<Record<string, Value>> {\n\t\trequest.expand(depth, 0)\n\t\t// SAFETY: the registry strictly validates this public native DTO projection.\n\t\tconst dto = planner.complete(table, parent, true, { kind: 'and', children: [] }) as Record<\n\t\t\tstring,\n\t\t\tValue\n\t\t>\n\t\tfor (const [name, selected] of Object.entries(selection)) {\n\t\t\tconst declared = edge(table, name),\n\t\t\t\tnested = selected === true ? {} : selected\n\t\t\tif (declared.cardinality === 'one') {\n\t\t\t\tconst target = await one(declared, parent, depth + 1)\n\t\t\t\tdto[name] = target\n\t\t\t\t\t? await output(declared.target, target, nested, args, [...path, name], depth + 1, [\n\t\t\t\t\t\t\t...parents,\n\t\t\t\t\t\t\tparent._id,\n\t\t\t\t\t\t])\n\t\t\t\t\t: null\n\t\t\t} else {\n\t\t\t\tconst page = await pageRelation(\n\t\t\t\t\ttable,\n\t\t\t\t\tparent,\n\t\t\t\t\tname,\n\t\t\t\t\tnested,\n\t\t\t\t\t{ numItems: args.numItems, cursor: null, order: args.order },\n\t\t\t\t\t[],\n\t\t\t\t\t[],\n\t\t\t\t\t[...path, name],\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\t[...parents, parent._id],\n\t\t\t\t)\n\t\t\t\t// SAFETY: pageRelation projects and validates each nested DTO row.\n\t\t\t\tdto[name] = page as Value\n\t\t\t}\n\t\t}\n\t\treturn dto\n\t}\n\tfunction prepare(\n\t\ttable: string,\n\t\tname: string,\n\t\tselection: OutputSelection,\n\t\tinput: QueryInput,\n\t\tconditions: readonly IndexCondition[],\n\t\tconstraints: readonly StoredConstraint[],\n\t\tpath: readonly string[],\n\t\trootId: string,\n\t) {\n\t\tplanner.select(edge(table, name).target, selection)\n\t\tassertRelationshipDepth(selection, path.length)\n\t\tconst declared = edge(table, name)\n\t\tif (declared.cardinality !== 'many') throw new RelationshipError('INVALID_RELATION')\n\t\tconst guardConstraint = declared.targetGuard\n\t\t\t? { fields: { [declared.targetGuard.discriminator]: declared.targetGuard.tag } }\n\t\t\t: undefined\n\t\tconst plan = planner.plan(\n\t\t\tdeclared.target,\n\t\t\tinput,\n\t\t\t[],\n\t\t\tguardConstraint ? [...constraints, guardConstraint] : constraints,\n\t\t)\n\t\tconst from = declared.from,\n\t\t\tto = declared.to\n\t\tconst through =\n\t\t\t'base' in from && 'base' in to\n\t\t\t\t? {\n\t\t\t\t\t\ttable: from.junction.table,\n\t\t\t\t\t\tfield: from.junction.field,\n\t\t\t\t\t\ttargetField: to.base.field,\n\t\t\t\t\t\ttargetReference: to.junction.field,\n\t\t\t\t\t}\n\t\t\t\t: null\n\t\tconst sourceTable = through ? through.table : declared.target\n\t\tconst field = through ? through.field : base(to).field\n\t\tconst targetIndex = relationIndex(\n\t\t\tdeclared.target,\n\t\t\tthrough ? through.targetField : field,\n\t\t\tplan,\n\t\t\tconditions,\n\t\t\tdeclared.targetGuard,\n\t\t)\n\t\tconst index = through ? lookup(sourceTable, field, declared.junctionGuard) : targetIndex\n\t\t// SAFETY: planner.page validated the complete output mask before cursor binding.\n\t\tconst binding: CursorBinding = {\n\t\t\t...rootBinding,\n\t\t\ttable: sourceTable,\n\t\t\tindex: index.name,\n\t\t\torder: plan.args.order ?? 'asc',\n\t\t\tclientFilters: plan.clientIdentity,\n\t\t\tserverFilters: {\n\t\t\t\tpredicates: plan.serverIdentity,\n\t\t\t\tselection: selection as Value,\n\t\t\t\tscope: { ...request.scope },\n\t\t\t\trootTable: rootBinding.table,\n\t\t\t\tlookupIndex: targetIndex.name,\n\t\t\t\tguards: {\n\t\t\t\t\tsource: declared.sourceGuard ? { ...declared.sourceGuard } : null,\n\t\t\t\t\ttarget: declared.targetGuard ? { ...declared.targetGuard } : null,\n\t\t\t\t\tjunction: declared.junctionGuard ? { ...declared.junctionGuard } : null,\n\t\t\t\t},\n\t\t\t\t...((declared.sourceMember || declared.targetMember) && {\n\t\t\t\t\tmembers: {\n\t\t\t\t\t\tsource: declared.sourceMember ? { ...declared.sourceMember } : null,\n\t\t\t\t\t\ttarget: declared.targetMember ? { ...declared.targetMember } : null,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t},\n\t\t\trelationPath: path,\n\t\t\tparent: rootId,\n\t\t}\n\t\tfunction open(token: string) {\n\t\t\ttry {\n\t\t\t\treturn navigation.parse(JSON.parse(codec.open(token, binding)))\n\t\t\t} catch {\n\t\t\t\tthrow new CursorError()\n\t\t\t}\n\t\t}\n\t\treturn { declared, plan, through, sourceTable, field, index, targetIndex, binding, open }\n\t}\n\tasync function pageRelation(\n\t\ttable: string,\n\t\tparent: Document | null,\n\t\tname: string,\n\t\tselection: OutputSelection,\n\t\tinput: QueryInput,\n\t\tconditions: readonly IndexCondition[] = [],\n\t\tconstraints: readonly StoredConstraint[] = [],\n\t\tpath: readonly string[] = [name],\n\t\tdepth = 1,\n\t\tparents: readonly string[] = [],\n\t\tprepared = prepare(\n\t\t\ttable,\n\t\t\tname,\n\t\t\tselection,\n\t\t\tinput,\n\t\t\tconditions,\n\t\t\tconstraints,\n\t\t\tpath,\n\t\t\tparents[0] ?? parent!._id,\n\t\t),\n\t\topened?: { cursor: string | null; endCursor?: string | null },\n\t) {\n\t\trequest.expand(depth, 0)\n\t\tconst { declared, plan, through, sourceTable, field, index, targetIndex, binding } = prepared\n\t\tconst value = sourceValue(declared, parent)\n\t\tconst args = { ...plan.args, ...(opened ?? { cursor: null }) }\n\t\t// SAFETY: declarations accept only native scalar lookup values; nullish references are absence.\n\t\tconst lookupPlan = {\n\t\t\t...plan,\n\t\t\tindex,\n\t\t\tprefix:\n\t\t\t\tvalue == null\n\t\t\t\t\t? []\n\t\t\t\t\t: through\n\t\t\t\t\t\t? relationPrefix(index, field, value as FilterScalar, undefined, declared.junctionGuard)\n\t\t\t\t\t\t: relationPrefix(index, field, value as FilterScalar, plan, declared.targetGuard),\n\t\t\tunsatisfiable: value == null || plan.unsatisfiable,\n\t\t}\n\t\tconst indexedTarget = through && through.targetField !== '_id'\n\t\tconst result = await executeStream(\n\t\t\tschema,\n\t\t\trequest,\n\t\t\tsourceTable,\n\t\t\tlookupPlan,\n\t\t\tplanner,\n\t\t\tcodec,\n\t\t\tbinding,\n\t\t\targs,\n\t\t\tasync (row, permitted) => {\n\t\t\t\tif (permitted) planner.validateDocument(indexedTarget ? declared.target : sourceTable, row)\n\t\t\t\tif (!permitted || (through && !indexedTarget && !guarded(row, declared.junctionGuard)))\n\t\t\t\t\treturn null\n\t\t\t\trequest.expand(depth)\n\t\t\t\tlet target: Document | null\n\t\t\t\tif (through && !indexedTarget)\n\t\t\t\t\ttarget = await get(declared.target, row[through.targetReference])\n\t\t\t\telse {\n\t\t\t\t\t// SAFETY: native direct/flattened target streams retain validated system fields.\n\t\t\t\t\ttarget = row as Document\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\t!target ||\n\t\t\t\t\t!guarded(target, declared.targetGuard) ||\n\t\t\t\t\t!memberMatches(target[base(declared.to).field], declared.targetMember) ||\n\t\t\t\t\t!(await matches(declared.target, target, plan.residual, depth))\n\t\t\t\t)\n\t\t\t\t\treturn null\n\t\t\t\treturn output(declared.target, target, selection, plan.args, path, depth, parents)\n\t\t\t},\n\t\t\t(raw) => codec.seal(JSON.stringify({ cursor: raw, ancestors: parents.slice(1) }), binding),\n\t\t\tindexedTarget\n\t\t\t\t? (source, db) => {\n\t\t\t\t\t\t// SAFETY: the registry owns the native schema/index descriptors. Public\n\t\t\t\t\t\t// helper flatMap concatenates native outer/inner keys and paginates them.\n\t\t\t\t\t\tconst nativeSchema = schema as SchemaDefinition<\n\t\t\t\t\t\t\tRecord<\n\t\t\t\t\t\t\t\tstring,\n\t\t\t\t\t\t\t\timport('convex/server').TableDefinition<any, Record<string, string[]>>\n\t\t\t\t\t\t\t>,\n\t\t\t\t\t\t\tboolean\n\t\t\t\t\t\t>\n\t\t\t\t\t\tconst fields = getIndexFields(declared.target, targetIndex.name, nativeSchema)\n\t\t\t\t\t\treturn source.flatMap(async (junction) => {\n\t\t\t\t\t\t\trequest.expand(depth)\n\t\t\t\t\t\t\tconst permitted = await request.authorize(sourceTable, junction)\n\t\t\t\t\t\t\tif (permitted) planner.validateDocument(sourceTable, junction)\n\t\t\t\t\t\t\tconst reference = junction[through.targetReference]\n\t\t\t\t\t\t\tif (!permitted || !guarded(junction, declared.junctionGuard) || reference == null)\n\t\t\t\t\t\t\t\treturn new EmptyStream(plan.args.order ?? 'asc', fields)\n\t\t\t\t\t\t\treturn stream(db, nativeSchema)\n\t\t\t\t\t\t\t\t.query(declared.target)\n\t\t\t\t\t\t\t\t.withIndex(targetIndex.name, (q) => {\n\t\t\t\t\t\t\t\t\t// SAFETY: registry validates the native leading lookup; validated filters supply each consecutive trailing binding.\n\t\t\t\t\t\t\t\t\tlet range = q as IndexRangeBuilder<any, string[], number>\n\t\t\t\t\t\t\t\t\t// SAFETY: junction references are native scalar Values validated by the declared lookup.\n\t\t\t\t\t\t\t\t\tconst prefix = relationPrefix(\n\t\t\t\t\t\t\t\t\t\ttargetIndex,\n\t\t\t\t\t\t\t\t\t\tthrough.targetField,\n\t\t\t\t\t\t\t\t\t\treference as FilterScalar,\n\t\t\t\t\t\t\t\t\t\tplan,\n\t\t\t\t\t\t\t\t\t\tdeclared.targetGuard,\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tfor (const binding of prefix) {\n\t\t\t\t\t\t\t\t\t\t// SAFETY: native eq advances the validated consecutive index prefix.\n\t\t\t\t\t\t\t\t\t\trange = range.eq(binding.field, binding.value) as IndexRangeBuilder<\n\t\t\t\t\t\t\t\t\t\t\tany,\n\t\t\t\t\t\t\t\t\t\t\tstring[],\n\t\t\t\t\t\t\t\t\t\t\tnumber\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn range\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.order(plan.args.order ?? 'asc')\n\t\t\t\t\t\t}, fields)\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\tindexedTarget ? declared.target : sourceTable,\n\t\t)\n\t\treturn result\n\t}\n\tasync function continuation(\n\t\trootTable: string,\n\t\trootId: string,\n\t\tpath: readonly string[],\n\t\tselection: OutputSelection,\n\t\tinput: QueryInput,\n\t\tconditions: readonly IndexCondition[],\n\t\tconstraints: readonly StoredConstraint[],\n\t) {\n\t\tif (!path.length || path.length > 4 || !request.db.normalizeId(rootTable, rootId))\n\t\t\tthrow new RelationshipError('INVALID_RELATION')\n\t\tlet table = rootTable\n\t\tconst declarations = path.map((name) => {\n\t\t\tconst declaration = edge(table, name)\n\t\t\ttable = declaration.target\n\t\t\treturn declaration\n\t\t})\n\t\tconst final = declarations.at(-1)!\n\t\tconst prepared = prepare(\n\t\t\tfinal.source,\n\t\t\tpath.at(-1)!,\n\t\t\tselection,\n\t\t\tinput,\n\t\t\tconditions,\n\t\t\tconstraints,\n\t\t\tpath,\n\t\t\trootId,\n\t\t)\n\t\t// Authenticate both slots and native ancestor IDs before ANY parent/traversal read.\n\t\tconst start = input.cursor === null ? null : prepared.open(input.cursor)\n\t\tconst end = input.endCursor == null ? null : prepared.open(input.endCursor)\n\t\tconst ancestors = start?.ancestors ?? end?.ancestors ?? []\n\t\tif (\n\t\t\tancestors.length !== path.length - 1 ||\n\t\t\t(start && end && JSON.stringify(start.ancestors) !== JSON.stringify(end.ancestors)) ||\n\t\t\tancestors.some((id, i) => !request.db.normalizeId(declarations[i].target, id))\n\t\t)\n\t\t\tthrow new CursorError()\n\t\t// Declarative input/index/cursor validation above retains its pre-read errors,\n\t\t// just as on the root path. Every awaited read, ancestry proof and page is protected.\n\t\ttry {\n\t\t\tlet parent = await get(rootTable, rootId)\n\t\t\tfor (let i = 0; parent && i < ancestors.length; i++) {\n\t\t\t\tconst declared = declarations[i]\n\t\t\t\tlet found: Document | null = null\n\t\t\t\tif (declared.cardinality === 'one') {\n\t\t\t\t\tconst target = await one(declared, parent, i + 1)\n\t\t\t\t\tif (target?._id === ancestors[i]) found = target\n\t\t\t\t} else\n\t\t\t\t\tfor await (const target of traverse(declared, parent, i + 1)) {\n\t\t\t\t\t\tif (target._id === ancestors[i]) {\n\t\t\t\t\t\t\tfound = target\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tparent = found\n\t\t\t}\n\t\t\treturn await pageRelation(\n\t\t\t\tfinal.source,\n\t\t\t\tparent,\n\t\t\t\tpath.at(-1)!,\n\t\t\t\tselection,\n\t\t\t\tinput,\n\t\t\t\tconditions,\n\t\t\t\tconstraints,\n\t\t\t\tpath,\n\t\t\t\tpath.length,\n\t\t\t\t[rootId, ...ancestors],\n\t\t\t\tprepared,\n\t\t\t\t{ cursor: start?.cursor ?? null, endCursor: end?.cursor ?? input.endCursor },\n\t\t\t)\n\t\t} catch (error) {\n\t\t\trethrowQueryError(error)\n\t\t}\n\t}\n\treturn { matches, output, continuation, edge }\n}\n\nfunction scalarOnly(ast: FilterAst): boolean {\n\tif (ast.kind === 'relation') return false\n\tif (ast.kind === 'and' || ast.kind === 'or') return ast.children.every(scalarOnly)\n\tif (ast.kind === 'not' || ast.kind === 'variant') return scalarOnly(ast.child)\n\treturn true\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ //#region src/querying/schema-snapshot.d.ts
3
+ type Recipe = {
4
+ readonly kind: 'value';
5
+ readonly value: unknown;
6
+ } | {
7
+ readonly kind: 'array';
8
+ readonly items: readonly Recipe[];
9
+ } | {
10
+ readonly kind: 'record';
11
+ readonly entries: readonly (readonly [string, Recipe])[];
12
+ } | {
13
+ readonly kind: 'regexp';
14
+ readonly source: string;
15
+ readonly flags: string;
16
+ } | {
17
+ readonly kind: 'node';
18
+ readonly constructor: string;
19
+ readonly definition: Recipe;
20
+ readonly id?: string;
21
+ };
22
+ export interface DtoRecipe<Schema extends z.ZodType = z.ZodType> {
23
+ readonly schemaType?: Schema;
24
+ readonly root: Recipe;
25
+ }
26
+ export declare function captureDto<Schema extends z.ZodType>(schema: Schema): DtoRecipe<Schema>;
27
+ export declare function materializeDto<Schema extends z.ZodType>(recipe: DtoRecipe<Schema>): Schema;
28
+ //#endregion
29
+ //# sourceMappingURL=schema-snapshot.d.mts.map
@@ -0,0 +1,2 @@
1
+ import{zid as e,zodToConvex as t}from"convex-helpers/server/zod4";import{z as n}from"zod";const r=/* @__PURE__ */ new Map;u(`object`,n.ZodObject),u(`array`,n.ZodArray),u(`optional`,n.ZodOptional),u(`exactOptional`,n.ZodExactOptional),u(`nullable`,n.ZodNullable),u(`nonoptional`,n.ZodNonOptional),u(`union`,n.ZodUnion),u(`discriminatedUnion`,n.ZodDiscriminatedUnion),u(`tuple`,n.ZodTuple),u(`record`,n.ZodRecord),u(`string`,n.ZodString),u(`number`,n.ZodNumber),u(`boolean`,n.ZodBoolean),u(`bigint`,n.ZodBigInt),u(`null`,n.ZodNull),u(`never`,n.ZodNever),u(`literal`,n.ZodLiteral),u(`enum`,n.ZodEnum),u(`custom`,n.ZodCustom),u(`minLength`,n.core.$ZodCheckMinLength),u(`maxLength`,n.core.$ZodCheckMaxLength),u(`length`,n.core.$ZodCheckLengthEquals),u(`lessThan`,n.core.$ZodCheckLessThan),u(`greaterThan`,n.core.$ZodCheckGreaterThan),u(`multipleOf`,n.core.$ZodCheckMultipleOf),u(`checkNumberFormat`,n.core.$ZodCheckNumberFormat),u(`checkBigintFormat`,n.core.$ZodCheckBigIntFormat),u(`stringFormat`,n.core.$ZodCheckStringFormat),u(`regex`,n.core.$ZodCheckRegex),u(`lowercase`,n.core.$ZodCheckLowerCase),u(`uppercase`,n.core.$ZodCheckUpperCase),u(`includes`,n.core.$ZodCheckIncludes),u(`startsWith`,n.core.$ZodCheckStartsWith),u(`endsWith`,n.core.$ZodCheckEndsWith),u(`property`,n.core.$ZodCheckProperty),u(`properties`,n.core.$ZodCheckProperties),u(`numberFormat`,n.ZodNumberFormat),u(`bigintFormat`,n.ZodBigIntFormat),u(`coreEmail`,n.core.$ZodEmail),u(`coreGUID`,n.core.$ZodGUID),u(`coreUUID`,n.core.$ZodUUID),u(`coreURL`,n.core.$ZodURL),u(`coreEmoji`,n.core.$ZodEmoji),u(`coreNanoID`,n.core.$ZodNanoID),u(`coreCUID`,n.core.$ZodCUID),u(`coreCUID2`,n.core.$ZodCUID2),u(`coreULID`,n.core.$ZodULID),u(`coreXID`,n.core.$ZodXID),u(`coreKSUID`,n.core.$ZodKSUID),u(`coreIPv4`,n.core.$ZodIPv4),u(`coreIPv6`,n.core.$ZodIPv6),u(`coreMAC`,n.core.$ZodMAC),u(`coreCIDRv4`,n.core.$ZodCIDRv4),u(`coreCIDRv6`,n.core.$ZodCIDRv6),u(`coreBase64`,n.core.$ZodBase64),u(`coreBase64URL`,n.core.$ZodBase64URL),u(`coreE164`,n.core.$ZodE164),u(`coreJWT`,n.core.$ZodJWT),u(`coreISODateTime`,n.core.$ZodISODateTime),u(`coreISODate`,n.core.$ZodISODate),u(`coreISOTime`,n.core.$ZodISOTime),u(`coreISODuration`,n.core.$ZodISODuration),u(`coreCreditCard`,n.core.$ZodCreditCard),u(`coreIBAN`,n.core.$ZodIBAN),u(`coreCustomStringFormat`,n.core.$ZodCustomStringFormat),u(`email`,n.ZodEmail),u(`guid`,n.ZodGUID),u(`uuid`,n.ZodUUID),u(`url`,n.ZodURL),u(`emoji`,n.ZodEmoji),u(`nanoid`,n.ZodNanoID),u(`cuid`,n.ZodCUID),u(`cuid2`,n.ZodCUID2),u(`ulid`,n.ZodULID),u(`xid`,n.ZodXID),u(`ksuid`,n.ZodKSUID),u(`ipv4`,n.ZodIPv4),u(`ipv6`,n.ZodIPv6),u(`mac`,n.ZodMAC),u(`cidrv4`,n.ZodCIDRv4),u(`cidrv6`,n.ZodCIDRv6),u(`base64`,n.ZodBase64),u(`base64url`,n.ZodBase64URL),u(`e164`,n.ZodE164),u(`jwt`,n.ZodJWT),u(`isoDateTime`,n.ZodISODateTime),u(`isoDate`,n.ZodISODate),u(`isoTime`,n.ZodISOTime),u(`isoDuration`,n.ZodISODuration),u(`creditCard`,n.ZodCreditCard),u(`iban`,n.ZodIBAN),u(`customStringFormat`,n.ZodCustomStringFormat);const i=[...r.entries()].reverse();function a(e){let t=/* @__PURE__ */ new WeakMap,r=/* @__PURE__ */ new WeakSet,a=0;function o(e,s){if(e===null||Object(e)!==e||e instanceof Function)return Object.freeze({kind:`value`,value:e});let c=e;if(r.has(c))throw Error(`Unsupported cyclic DTO schema`);let u=t.get(c);if(u)return u;if(s>64||++a>8192)throw Error(`DTO schema graph budget exceeded`);r.add(c);let d;if(e instanceof RegExp)d={kind:`regexp`,source:e.source,flags:e.flags};else if(e instanceof n.core.$ZodType||e instanceof n.core.$ZodCheck){if(e instanceof n.core.$ZodCheck&&e._zod.def.check===`custom`&&!(e instanceof n.ZodCustom))throw Error(`Unsupported opaque DTO check/superRefine; use .refine() instead`);let t=i.find(([,t])=>t.matches(e));if(!t)throw Error(`Unsupported DTO schema or check`);let r;if(e instanceof n.ZodCustom){let t=l(e);t.kind===`id`&&(r=t.tableName)}let a=e instanceof n.ZodObject?{...e._zod.def,shape:e.shape}:e._zod.def;d={kind:`node`,constructor:t[0],definition:o(a,s+1),id:r}}else if(Array.isArray(e))d={kind:`array`,items:Object.freeze(e.map(e=>o(e,s+1)))};else{if(Object.hasOwn(c,`_zod`))throw Error(`Unsupported opaque DTO check/superRefine; use .refine() instead`);if(Object.getPrototypeOf(e)!==Object.prototype&&Object.getPrototypeOf(e)!==null)throw Error(`Unsupported DTO definition object`);let t=[];for(let e of Reflect.ownKeys(c)){if(String(e)!==e)throw Error(`Unsupported DTO definition symbol`);let n=Object.getOwnPropertyDescriptor(c,e);if(!(`value`in n))throw Error(`Unsupported DTO schema accessor`);t.push(Object.freeze([e,o(n.value,s+1)]))}d={kind:`record`,entries:Object.freeze(t)}}return r.delete(c),Object.freeze(d),t.set(c,d),d}return Object.freeze({root:o(e,0)})}const o=/* @__PURE__ */ new WeakMap;function s(t){let n=o.get(t);if(n)return n;let i;switch(t.kind){case`value`:i=()=>t.value;break;case`regexp`:i=()=>new RegExp(t.source,t.flags);break;case`array`:{let e=t.items.map(s);i=()=>e.map(e=>e());break}case`record`:{let e=t.entries.map(([e,t])=>[e,s(t)]);i=()=>Object.fromEntries(e.map(([e,t])=>[e,t()]));break}case`node`:{let n=s(t.definition);if(t.id!==void 0){let r=t.id;i=()=>{let t=n(),i=e(r);if(t instanceof Object&&`checks`in t){let e=t.checks;if(Array.isArray(e))return i.check(...e)}return i}}else{let e=r.get(t.constructor);i=()=>e.create(n())}break}}return o.set(t,i),i}function c(e){let t=s(e.root)();if(!(t instanceof n.ZodType))throw Error(`Expected classic DTO schema`);return t}function l(e){return t(e)}function u(e,t){t!==void 0&&r.set(e,{matches:e=>e instanceof t,create:e=>new t(e)})}export{a as captureDto,c as materializeDto};
2
+ //# sourceMappingURL=schema-snapshot.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-snapshot.mjs","names":["constructors","register","z","dispatch","captureDto","seen","active","nodes","capture","value","object","cached","depth","recipe","entry","constructor","id","native","nativeValidator","definition","child","entries","key","descriptor","schema","factories","compile","factory","items","item","restored","result","zid","checks","materializeDto","zodToConvex","Constructor","name","node"],"sources":["../../src/querying/schema-snapshot.ts"],"sourcesContent":["import { z } from 'zod'\nimport type { GenericValidator } from 'convex/values'\nimport { zid, zodToConvex } from 'convex-helpers/server/zod4'\n\n// Recipes contain semantic definitions only. No source parser, constructor,\n// parent, hooks or lazy caches survive registration.\ntype Recipe =\n\t| { readonly kind: 'value'; readonly value: unknown }\n\t| { readonly kind: 'array'; readonly items: readonly Recipe[] }\n\t| { readonly kind: 'record'; readonly entries: readonly (readonly [string, Recipe])[] }\n\t| { readonly kind: 'regexp'; readonly source: string; readonly flags: string }\n\t| {\n\t\t\treadonly kind: 'node'\n\t\t\treadonly constructor: string\n\t\t\treadonly definition: Recipe\n\t\t\treadonly id?: string\n\t }\n\nexport interface DtoRecipe<Schema extends z.ZodType = z.ZodType> {\n\treadonly schemaType?: Schema\n\treadonly root: Recipe\n}\n\ntype Node = z.core.$ZodType | z.core.$ZodCheck\nconst constructors = new Map<\n\tstring,\n\t{\n\t\tmatches(node: Node): boolean\n\t\t// oxlint-disable-next-line anti-slop/no-unknown-parameters -- Only recipe-restored semantic definitions enter the selected installed constructor.\n\t\tcreate(definition: unknown): Node\n\t}\n>()\n// Base classes precede specialized classes so the most specific installed\n// constructor wins. Never consult a caller's _zod.constr or constructor property.\nregister('object', z.ZodObject)\nregister('array', z.ZodArray)\nregister('optional', z.ZodOptional)\nregister('exactOptional', z.ZodExactOptional)\nregister('nullable', z.ZodNullable)\nregister('nonoptional', z.ZodNonOptional)\nregister('union', z.ZodUnion)\nregister('discriminatedUnion', z.ZodDiscriminatedUnion)\nregister('tuple', z.ZodTuple)\nregister('record', z.ZodRecord)\nregister('string', z.ZodString)\nregister('number', z.ZodNumber)\nregister('boolean', z.ZodBoolean)\nregister('bigint', z.ZodBigInt)\nregister('null', z.ZodNull)\nregister('never', z.ZodNever)\nregister('literal', z.ZodLiteral)\nregister('enum', z.ZodEnum)\nregister('custom', z.ZodCustom)\nregister('minLength', z.core.$ZodCheckMinLength)\nregister('maxLength', z.core.$ZodCheckMaxLength)\nregister('length', z.core.$ZodCheckLengthEquals)\nregister('lessThan', z.core.$ZodCheckLessThan)\nregister('greaterThan', z.core.$ZodCheckGreaterThan)\nregister('multipleOf', z.core.$ZodCheckMultipleOf)\nregister('checkNumberFormat', z.core.$ZodCheckNumberFormat)\nregister('checkBigintFormat', z.core.$ZodCheckBigIntFormat)\nregister('stringFormat', z.core.$ZodCheckStringFormat)\nregister('regex', z.core.$ZodCheckRegex)\nregister('lowercase', z.core.$ZodCheckLowerCase)\nregister('uppercase', z.core.$ZodCheckUpperCase)\nregister('includes', z.core.$ZodCheckIncludes)\nregister('startsWith', z.core.$ZodCheckStartsWith)\nregister('endsWith', z.core.$ZodCheckEndsWith)\nregister('property', z.core.$ZodCheckProperty)\nregister('properties', z.core.$ZodCheckProperties)\nregister('numberFormat', z.ZodNumberFormat)\nregister('bigintFormat', z.ZodBigIntFormat)\n// Format schemas are also checks; preserve their implicit checks, including\n// URL/JWT validation which cannot be represented by a regex alone.\nregister('coreEmail', z.core.$ZodEmail)\nregister('coreGUID', z.core.$ZodGUID)\nregister('coreUUID', z.core.$ZodUUID)\nregister('coreURL', z.core.$ZodURL)\nregister('coreEmoji', z.core.$ZodEmoji)\nregister('coreNanoID', z.core.$ZodNanoID)\nregister('coreCUID', z.core.$ZodCUID)\nregister('coreCUID2', z.core.$ZodCUID2)\nregister('coreULID', z.core.$ZodULID)\nregister('coreXID', z.core.$ZodXID)\nregister('coreKSUID', z.core.$ZodKSUID)\nregister('coreIPv4', z.core.$ZodIPv4)\nregister('coreIPv6', z.core.$ZodIPv6)\nregister('coreMAC', z.core.$ZodMAC)\nregister('coreCIDRv4', z.core.$ZodCIDRv4)\nregister('coreCIDRv6', z.core.$ZodCIDRv6)\nregister('coreBase64', z.core.$ZodBase64)\nregister('coreBase64URL', z.core.$ZodBase64URL)\nregister('coreE164', z.core.$ZodE164)\nregister('coreJWT', z.core.$ZodJWT)\nregister('coreISODateTime', z.core.$ZodISODateTime)\nregister('coreISODate', z.core.$ZodISODate)\nregister('coreISOTime', z.core.$ZodISOTime)\nregister('coreISODuration', z.core.$ZodISODuration)\nregister('coreCreditCard', z.core.$ZodCreditCard)\nregister('coreIBAN', z.core.$ZodIBAN)\nregister('coreCustomStringFormat', z.core.$ZodCustomStringFormat)\nregister('email', z.ZodEmail)\nregister('guid', z.ZodGUID)\nregister('uuid', z.ZodUUID)\nregister('url', z.ZodURL)\nregister('emoji', z.ZodEmoji)\nregister('nanoid', z.ZodNanoID)\nregister('cuid', z.ZodCUID)\nregister('cuid2', z.ZodCUID2)\nregister('ulid', z.ZodULID)\nregister('xid', z.ZodXID)\nregister('ksuid', z.ZodKSUID)\nregister('ipv4', z.ZodIPv4)\nregister('ipv6', z.ZodIPv6)\nregister('mac', z.ZodMAC)\nregister('cidrv4', z.ZodCIDRv4)\nregister('cidrv6', z.ZodCIDRv6)\nregister('base64', z.ZodBase64)\nregister('base64url', z.ZodBase64URL)\nregister('e164', z.ZodE164)\nregister('jwt', z.ZodJWT)\nregister('isoDateTime', z.ZodISODateTime)\nregister('isoDate', z.ZodISODate)\nregister('isoTime', z.ZodISOTime)\nregister('isoDuration', z.ZodISODuration)\nregister('creditCard', z.ZodCreditCard)\nregister('iban', z.ZodIBAN)\nregister('customStringFormat', z.ZodCustomStringFormat)\nconst dispatch = [...constructors.entries()].reverse()\n\nexport function captureDto<Schema extends z.ZodType>(schema: Schema): DtoRecipe<Schema> {\n\tconst seen = new WeakMap<object, Recipe>()\n\tconst active = new WeakSet<object>()\n\tlet nodes = 0\n\t// oxlint-disable-next-line anti-slop/no-unknown-parameters -- Recursively decode preflighted Zod definitions into owned recipes.\n\tfunction capture(value: unknown, depth: number): Recipe {\n\t\tif (value === null || Object(value) !== value || value instanceof Function)\n\t\t\treturn Object.freeze({ kind: 'value', value })\n\t\t// SAFETY: the boxing equality above excludes primitives.\n\t\tconst object = value as object\n\t\tif (active.has(object)) throw new Error('Unsupported cyclic DTO schema')\n\t\tconst cached = seen.get(object)\n\t\tif (cached) return cached\n\t\tif (depth > 64 || ++nodes > 8192) throw new Error('DTO schema graph budget exceeded')\n\t\tactive.add(object)\n\t\tlet recipe: Recipe\n\t\tif (value instanceof RegExp) {\n\t\t\trecipe = { kind: 'regexp', source: value.source, flags: value.flags }\n\t\t} else if (value instanceof z.core.$ZodType || value instanceof z.core.$ZodCheck) {\n\t\t\tif (\n\t\t\t\tvalue instanceof z.core.$ZodCheck &&\n\t\t\t\tvalue._zod.def.check === 'custom' &&\n\t\t\t\t!(value instanceof z.ZodCustom)\n\t\t\t)\n\t\t\t\tthrow new Error('Unsupported opaque DTO check/superRefine; use .refine() instead')\n\t\t\tconst entry = dispatch.find(([, constructor]) => constructor.matches(value))\n\t\t\tif (!entry) throw new Error('Unsupported DTO schema or check')\n\t\t\tlet id: string | undefined\n\t\t\tif (value instanceof z.ZodCustom) {\n\t\t\t\tconst native = nativeValidator(value)\n\t\t\t\tif (native.kind === 'id') id = native.tableName\n\t\t\t}\n\t\t\tconst definition =\n\t\t\t\tvalue instanceof z.ZodObject\n\t\t\t\t\t? // oxlint-disable-next-line anti-slop/no-shape-in-symbol-names -- The installed Zod object definition requires this exact property.\n\t\t\t\t\t\t{ ...value._zod.def, shape: value.shape }\n\t\t\t\t\t: value._zod.def\n\t\t\trecipe = {\n\t\t\t\tkind: 'node',\n\t\t\t\tconstructor: entry[0],\n\t\t\t\tdefinition: capture(definition, depth + 1),\n\t\t\t\tid,\n\t\t\t}\n\t\t} else if (Array.isArray(value)) {\n\t\t\trecipe = {\n\t\t\t\tkind: 'array',\n\t\t\t\titems: Object.freeze(value.map((child) => capture(child, depth + 1))),\n\t\t\t}\n\t\t} else {\n\t\t\tif (Object.hasOwn(object, '_zod'))\n\t\t\t\tthrow new Error('Unsupported opaque DTO check/superRefine; use .refine() instead')\n\t\t\tif (\n\t\t\t\tObject.getPrototypeOf(value) !== Object.prototype &&\n\t\t\t\tObject.getPrototypeOf(value) !== null\n\t\t\t)\n\t\t\t\tthrow new Error('Unsupported DTO definition object')\n\t\t\tconst entries: (readonly [string, Recipe])[] = []\n\t\t\tfor (const key of Reflect.ownKeys(object)) {\n\t\t\t\tif (String(key) !== key) throw new Error('Unsupported DTO definition symbol')\n\t\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(object, key)!\n\t\t\t\tif (!('value' in descriptor)) throw new Error('Unsupported DTO schema accessor')\n\t\t\t\tentries.push(Object.freeze([key, capture(descriptor.value, depth + 1)]))\n\t\t\t}\n\t\t\trecipe = { kind: 'record', entries: Object.freeze(entries) }\n\t\t}\n\t\tactive.delete(object)\n\t\tObject.freeze(recipe)\n\t\tseen.set(object, recipe)\n\t\treturn recipe\n\t}\n\treturn Object.freeze({ root: capture(schema, 0) })\n}\n\n// Factories share immutable instructions only. Every occurrence invokes its factory\n// again, so shared recipe nodes never share mutable materialized definitions.\ntype Factory = () => unknown\nconst factories = new WeakMap<Recipe, Factory>()\n\nfunction compile(recipe: Recipe): Factory {\n\tconst cached = factories.get(recipe)\n\tif (cached) return cached\n\tlet factory: Factory\n\tswitch (recipe.kind) {\n\t\tcase 'value':\n\t\t\tfactory = () => recipe.value\n\t\t\tbreak\n\t\tcase 'regexp':\n\t\t\tfactory = () => new RegExp(recipe.source, recipe.flags)\n\t\t\tbreak\n\t\tcase 'array': {\n\t\t\tconst items = recipe.items.map(compile)\n\t\t\tfactory = () => items.map((item) => item())\n\t\t\tbreak\n\t\t}\n\t\tcase 'record': {\n\t\t\tconst entries = recipe.entries.map(([key, child]) => [key, compile(child)] as const)\n\t\t\tfactory = () => Object.fromEntries(entries.map(([key, child]) => [key, child()]))\n\t\t\tbreak\n\t\t}\n\t\tcase 'node': {\n\t\t\tconst definition = compile(recipe.definition)\n\t\t\tif (recipe.id !== undefined) {\n\t\t\t\tconst id = recipe.id\n\t\t\t\tfactory = () => {\n\t\t\t\t\tconst restored = definition()\n\t\t\t\t\tconst result = zid(id)\n\t\t\t\t\t// The new zid is registered with convex-helpers. Added refinements are\n\t\t\t\t\t// reconstructed independently, never inherited via _zod.parent.\n\t\t\t\t\tif (restored instanceof Object && 'checks' in restored) {\n\t\t\t\t\t\tconst checks = restored.checks\n\t\t\t\t\t\tif (Array.isArray(checks)) return result.check(...checks)\n\t\t\t\t\t}\n\t\t\t\t\treturn result\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst constructor = constructors.get(recipe.constructor)!\n\t\t\t\tfactory = () => constructor.create(definition())\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\t}\n\tfactories.set(recipe, factory)\n\treturn factory\n}\n\nexport function materializeDto<Schema extends z.ZodType>(recipe: DtoRecipe<Schema>): Schema {\n\tconst result = compile(recipe.root)()\n\tif (!(result instanceof z.ZodType)) throw new Error('Expected classic DTO schema')\n\t// SAFETY: the recipe preserves the captured schema constructor and definition.\n\treturn result as Schema\n}\n\nfunction nativeValidator(schema: z.ZodType): GenericValidator {\n\treturn zodToConvex(schema)\n}\n\nfunction register<T extends Node>(\n\tname: string,\n\tConstructor: z.core.$constructor<T> | undefined,\n): void {\n\tif (Constructor === undefined) return\n\tconstructors.set(name, {\n\t\tmatches: (node) => node instanceof Constructor,\n\t\tcreate: (definition) => {\n\t\t\t// SAFETY: capture selected this installed constructor and recursively copied\n\t\t\t// its own semantic definition; materialization restores every child first.\n\t\t\treturn new Constructor(definition as T['_zod']['def'])\n\t\t},\n\t})\n}\n"],"mappings":"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"}
package/dist/querying.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{createManagedSecurity as e}from"./querying/security.mjs";import{createPlanner as t}from"./querying/planner.mjs";import{createCursorCodec as n,createEnvironmentCursorCodec as r}from"./querying/cursors.mjs";import{assertRelationshipDepth as i,relationshipExecutor as a}from"./querying/relationships.mjs";import{executeQuery as o}from"./querying/execution.mjs";function s(s,c){let{schema:l,relations:u}=s,d={...s,...c},f=t(l,u),p=d.cursor===void 0?void 0:n(d.cursor),m=d.maxPageSize??100;if(!Number.isSafeInteger(m)||m<=0||m>100)throw Error(`Invalid central page size`);let h=d.engineVersion??`scalar-1`,g=d.policyVersion??`1`,_,v=e({tables:Object.keys(u.tables),policyVersion:g,budgets:d.budgets,trustedAdapter:d.trustedAdapter});function y(e){f.assertUnchanged();let t=v(e);function n(e,s=[],c=[],d={},v){return Object.freeze({when:(t,r)=>n(e,[...s,{value:t,index:r}],c,d,v),where:t=>n(e,s,[...c,t],d,v),with:t=>n(e,s,c,t,v),relation:(t,r)=>{let i=r.split(`.`);if(!i.length||i.length>4)throw Error(`INVALID_RELATION`);let a=e;for(let e of i){let t=f.metadata.declarations[a]?.[e];if(!t)throw Error(`INVALID_RELATION`);a=t.target}return n(a,s,c,{},{table:e,parent:t,path:i})},async paginate(n){let y=p??=r();f.assertUnchanged();let b=f.page(e,d);i(d,v?.path.length??0);let x=f.plan(e,n,v?[]:s,c);if(x.args.numItems>m)throw Error(`Page size exceeds central ceiling`);x.args.maximumRowsRead=Math.min(x.args.maximumRowsRead??t.budgets.rawCandidates,t.budgets.rawCandidates),x.args.maximumBytesRead=Math.min(x.args.maximumBytesRead??t.budgets.documentBytes,t.budgets.documentBytes),_??=Array.from(new Uint8Array(await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(u.identity))),e=>e.toString(16).padStart(2,`0`)).join(``),f.assertUnchanged();let S={table:v?.table??e,index:x.index?.name??`by_creation_time`,order:x.args.order??`asc`,clientFilters:x.clientIdentity,serverFilters:{predicates:x.serverIdentity,selection:d,scope:{...t.scope}},relationPath:[],principal:JSON.stringify(t.scope),tenant:t.scope.tenant,policyVersion:g,engineVersion:h,registryVersion:_},C=a(l,t,f,y,S);if(v)return C.continuation(v.table,v.parent,v.path,d,x.args,s,c);let w=await o(l,t,e,x,f,y,S,async(t,n)=>!n||!await C.matches(e,t,x.residual)?null:C.output(e,t,d,x.args));return f.assertUnchanged(),b.parse(w)}})}return Object.freeze(Object.fromEntries(Object.keys(u.tables).map(e=>[e,n(e)])))}return Object.assign(y,{tables:u.tables})}export{s as createQueryEngine};
1
+ import{createManagedSecurity as e}from"./querying/security.mjs";import{createPlanner as t}from"./querying/planner.mjs";import{createCursorCodec as n,createEnvironmentCursorCodec as r}from"./querying/cursors.mjs";import{assertRelationshipDepth as i,relationshipExecutor as a}from"./querying/relationships.mjs";import{executeQuery as o}from"./querying/execution.mjs";function s(s,c){let{relations:l}=s,u={...s,...c},d=t(s.schema,l),f=d.streamSchema,p=u.cursor===void 0?void 0:n(u.cursor),m=u.maxPageSize??100;if(!Number.isSafeInteger(m)||m<=0||m>100)throw Error(`Invalid central page size`);let h=u.engineVersion??`scalar-1`,g=u.policyVersion??`1`,_,v=e({tables:Object.keys(l.tables),policyVersion:g,budgets:u.budgets,trustedAdapter:u.trustedAdapter});function y(e){let t=v(e);function n(e,s=[],c=[],u={},v){return Object.freeze({when:(t,r)=>n(e,[...s,{value:t,index:r}],c,u,v),where:t=>n(e,s,[...c,t],u,v),with:t=>n(e,s,c,t,v),relation:(t,r)=>{let i=r.split(`.`);if(!i.length||i.length>4)throw Error(`INVALID_RELATION`);let a=e;for(let e of i){let t=d.metadata.declarations[a]?.[e];if(!t)throw Error(`INVALID_RELATION`);a=t.target}return n(a,s,c,{},{table:e,parent:t,path:i})},async paginate(n){let y=p??=r();d.select(e,u),i(u,v?.path.length??0);let b=d.plan(e,n,v?[]:s,c);if(b.args.numItems>m)throw Error(`Page size exceeds central ceiling`);b.args.maximumRowsRead=Math.min(b.args.maximumRowsRead??t.budgets.rawCandidates,t.budgets.rawCandidates),b.args.maximumBytesRead=Math.min(b.args.maximumBytesRead??t.budgets.documentBytes,t.budgets.documentBytes),_??=Array.from(new Uint8Array(await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(l.identity))),e=>e.toString(16).padStart(2,`0`)).join(``);let x={table:v?.table??e,index:b.index?.name??`by_creation_time`,order:b.args.order??`asc`,clientFilters:b.clientIdentity,serverFilters:{predicates:b.serverIdentity,selection:u,scope:{...t.scope}},relationPath:[],principal:JSON.stringify(t.scope),tenant:t.scope.tenant,policyVersion:g,engineVersion:h,registryVersion:_},S=a(f,t,d,y,x);return v?await S.continuation(v.table,v.parent,v.path,u,b.args,s,c):await o(f,t,e,b,d,y,x,async(t,n)=>!n||!await S.matches(e,t,b.residual)?null:S.output(e,t,u,b.args))}})}return Object.freeze(Object.fromEntries(Object.keys(l.tables).map(e=>[e,n(e)])))}return Object.assign(y,{tables:l.tables})}export{s as createQueryEngine};
2
2
  //# sourceMappingURL=querying.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"querying.mjs","names":["executorRequest","createQueryEngine","config","settings","options","planner","createPlanner","schema","relations","cursorCodec","createCursorCodec","maxPageSize","engineVersion","policyVersion","registryDigest","security","createManagedSecurity","querying","request","ctx","tableQuery","table","conditions","constraints","selection","route","spec","selected","path","declaredPath","target","name","edge","codec","createEnvironmentCursorCodec","pageSchema","assertRelationshipDepth","plan","input","byte","binding","executor","relationshipExecutor","result","executeQuery","permitted","row"],"sources":["../src/querying.ts"],"sourcesContent":["import type {\n\tGenericSchema,\n\tSchemaDefinition,\n\tDataModelFromSchemaDefinition,\n\tPaginationResult,\n} from 'convex/server'\nimport type { GenericId } from 'convex/values'\nimport type {\n\tRelationTables,\n\tRelationDeclarations,\n\tRelationRegistry,\n\tRelationQueryRow,\n\tRelationSelection,\n\tRelationFilters,\n\tRelationFilterSelection,\n} from './relations'\nimport { createPlanner, type QueryInput, type StoredConstraint } from './querying/planner'\nimport { executeQuery, type ExecutionRequest } from './querying/execution'\nimport {\n\trelationshipExecutor,\n\tassertRelationshipDepth,\n\ttype OutputSelection,\n\ttype RelationDocument,\n} from './querying/relationships'\nimport {\n\tcreateCursorCodec,\n\tcreateEnvironmentCursorCodec,\n\ttype CursorCodecConfig,\n\ttype CursorBinding,\n} from './querying/cursors'\nimport {\n\tcreateManagedSecurity,\n\ttype ManagedSecurityConfig,\n\ttype ManagedQueryContext,\n\ttype ManagedBudgets,\n} from './querying/security'\nimport type { IndexCondition, NativePagination } from './querying/filters'\n\ntype FullMask<S> = {\n\t[K in keyof S]-?: NonNullable<S[K]> extends true\n\t\t? true\n\t\t: FullMask<Exclude<NonNullable<S[K]>, true>>\n}\ntype Paths<\n\tD extends RelationDeclarations,\n\tT extends string,\n\tL extends readonly 1[] = [1, 1, 1, 1],\n> = L extends readonly [1, ...infer Rest extends 1[]]\n\t? {\n\t\t\t[K in keyof D[T] & string]:\n\t\t\t\t| (D[T][K]['cardinality'] extends 'many' ? K : never)\n\t\t\t\t| `${K}.${Paths<D, D[T][K]['target'], Rest>}`\n\t\t}[keyof D[T] & string]\n\t: never\ntype PathTarget<\n\tD extends RelationDeclarations,\n\tT extends string,\n\tP extends string,\n> = P extends `${infer Head}.${infer Rest}`\n\t? PathTarget<D, D[T][Head]['target'], Rest>\n\t: D[T][P]['target']\ntype PathScope<\n\tD extends RelationDeclarations,\n\tT extends string,\n\tP extends string,\n> = P extends `${infer Head}.${infer Rest}`\n\t? PathScope<D, D[T][Head]['target'], Rest>\n\t: Extract<NonNullable<D[T][P]['targetGuard']>['tag'], string>\ntype RemainingDepth<P extends string, L extends readonly 1[]> = L extends readonly [\n\t1,\n\t...infer Rest extends 1[],\n]\n\t? P extends `${string}.${infer Tail}`\n\t\t? RemainingDepth<Tail, Rest>\n\t\t: Rest\n\t: []\ntype EngineArgs<\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n\tT extends keyof Tables,\n> = NativePagination & {\n\tfilters?: RelationFilters<Tables, D, T, FullMask<RelationFilterSelection<Tables, D, T>>>\n\torder?: 'asc' | 'desc'\n}\n/** Typed declarative chain returned by the engine; named for consumer declaration emission. */\nexport interface TableQuery<\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n\tT extends keyof Tables,\n\tS = {},\n\tL extends readonly 1[] = [1, 1, 1, 1],\n\tScope extends string = never,\n> {\n\twhen(value: IndexCondition['value'], index: string): TableQuery<Tables, D, T, S, L, Scope>\n\twhere(\n\t\tspec: NonNullable<EngineArgs<Tables, D, T>['filters']>,\n\t): TableQuery<Tables, D, T, S, L, Scope>\n\twith<const Selection extends RelationSelection<Tables, D, T, L>>(\n\t\tselection: Selection & {\n\t\t\t[K in keyof Selection]: K extends keyof RelationSelection<Tables, D, T, L>\n\t\t\t\t? Selection[K]\n\t\t\t\t: never\n\t\t},\n\t): TableQuery<Tables, D, T, Selection, L, Scope>\n\trelation<const P extends Paths<D, Extract<T, string>>>(\n\t\tparent: GenericId<Tables[T]['tableName']>,\n\t\tpath: P,\n\t): Omit<\n\t\tTableQuery<\n\t\t\tTables,\n\t\t\tD,\n\t\t\tExtract<PathTarget<D, Extract<T, string>, P>, keyof Tables>,\n\t\t\t{},\n\t\t\tRemainingDepth<P, L>,\n\t\t\tPathScope<D, Extract<T, string>, P>\n\t\t>,\n\t\t'relation'\n\t>\n\tpaginate(\n\t\targs: EngineArgs<Tables, D, T>,\n\t): Promise<PaginationResult<RelationQueryRow<Tables, D, T, S, Scope>>>\n}\nexport interface QueryEngineDeclaration<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n> {\n\tschema: Schema\n\trelations: RelationRegistry<Tables, D>\n}\n/** Advanced server configuration, separate from the normal schema/relations declaration. */\nexport interface QueryEngineOptions<Schema extends SchemaDefinition<GenericSchema, boolean>> {\n\t/** Explicit codecs validate at creation. Otherwise environment keys load at first paginate. */\n\tcursor?: CursorCodecConfig\n\tbudgets?: Partial<ManagedBudgets>\n\tmaxPageSize?: number\n\tpolicyVersion?: string\n\tengineVersion?: string\n\ttrustedAdapter?: ManagedSecurityConfig<DataModelFromSchemaDefinition<Schema>>['trustedAdapter']\n}\n\n/** @deprecated Use QueryEngineDeclaration and optional QueryEngineOptions separately. */\nexport interface QueryEngineConfig<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n>\n\textends QueryEngineDeclaration<Schema, Tables, D>, QueryEngineOptions<Schema> {\n\tcursor: CursorCodecConfig\n}\n\ntype QueryEngine<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n> = {\n\t(ctx: ManagedQueryContext<DataModelFromSchemaDefinition<Schema>>): {\n\t\t[T in keyof Tables]: TableQuery<Tables, D, T>\n\t}\n\ttables: RelationRegistry<Tables, D>['tables']\n}\n\n/** Central facade. Endpoint chains carry declarative constraints and explicit relationships. */\nexport function createQueryEngine<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tconst Tables extends RelationTables,\n\tconst D extends RelationDeclarations,\n>(\n\tconfig: QueryEngineDeclaration<Schema, Tables, D>,\n\toptions?: QueryEngineOptions<Schema>,\n): QueryEngine<Schema, Tables, D>\n/** @deprecated Pass advanced fields in the optional second argument. */\nexport function createQueryEngine<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tconst Tables extends RelationTables,\n\tconst D extends RelationDeclarations,\n>(\n\tconfig: QueryEngineDeclaration<Schema, Tables, D> &\n\t\tQueryEngineOptions<Schema> & { cursor: CursorCodecConfig },\n): QueryEngine<Schema, Tables, D>\nexport function createQueryEngine<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tconst Tables extends RelationTables,\n\tconst D extends RelationDeclarations,\n>(\n\tconfig: QueryEngineDeclaration<Schema, Tables, D> & QueryEngineOptions<Schema>,\n\toptions?: QueryEngineOptions<Schema>,\n) {\n\tconst { schema, relations } = config\n\t// Retain released one-argument calls; a second argument overrides legacy fields.\n\tconst settings = { ...config, ...options }\n\tconst planner = createPlanner(schema, relations)\n\tlet cursorCodec = settings.cursor === undefined ? undefined : createCursorCodec(settings.cursor)\n\tconst maxPageSize = settings.maxPageSize ?? 100\n\tif (!Number.isSafeInteger(maxPageSize) || maxPageSize <= 0 || maxPageSize > 100)\n\t\tthrow new Error('Invalid central page size')\n\tconst engineVersion = settings.engineVersion ?? 'scalar-1'\n\tconst policyVersion = settings.policyVersion ?? '1'\n\t// Bind the full immutable identity through a collision-resistant digest so\n\t// real application registries fit the codec's bounded AAD. Live guards still\n\t// inspect current schemas; this caches only the immutable version identity.\n\tlet registryDigest: string | undefined\n\tconst security = createManagedSecurity<DataModelFromSchemaDefinition<Schema>>({\n\t\ttables: Object.keys(relations.tables),\n\t\tpolicyVersion,\n\t\tbudgets: settings.budgets,\n\t\ttrustedAdapter: settings.trustedAdapter,\n\t})\n\tfunction querying(ctx: ManagedQueryContext<DataModelFromSchemaDefinition<Schema>>) {\n\t\tplanner.assertUnchanged()\n\t\tconst request = security(ctx)\n\t\tfunction tableQuery(\n\t\t\ttable: string,\n\t\t\tconditions: readonly IndexCondition[] = [],\n\t\t\tconstraints: readonly StoredConstraint[] = [],\n\t\t\tselection: OutputSelection = {},\n\t\t\troute?: { table: string; parent: string; path: string[] },\n\t\t) {\n\t\t\treturn Object.freeze({\n\t\t\t\twhen: (value: IndexCondition['value'], index: string) =>\n\t\t\t\t\ttableQuery(table, [...conditions, { value, index }], constraints, selection, route),\n\t\t\t\twhere: (spec: StoredConstraint) =>\n\t\t\t\t\ttableQuery(table, conditions, [...constraints, spec], selection, route),\n\t\t\t\twith: (selected: OutputSelection) =>\n\t\t\t\t\ttableQuery(table, conditions, constraints, selected, route),\n\t\t\t\trelation: (parent: string, declaredPath: string) => {\n\t\t\t\t\tconst path = declaredPath.split('.')\n\t\t\t\t\tif (!path.length || path.length > 4) throw new Error('INVALID_RELATION')\n\t\t\t\t\tlet target = table\n\t\t\t\t\tfor (const name of path) {\n\t\t\t\t\t\tconst edge = planner.metadata.declarations[target]?.[name]\n\t\t\t\t\t\tif (!edge) throw new Error('INVALID_RELATION')\n\t\t\t\t\t\ttarget = edge.target\n\t\t\t\t\t}\n\t\t\t\t\treturn tableQuery(target, conditions, constraints, {}, { table, parent, path })\n\t\t\t\t},\n\t\t\t\tasync paginate(input: QueryInput) {\n\t\t\t\t\t// Resolve once per global engine, before any native query or policy reads.\n\t\t\t\t\tconst codec = (cursorCodec ??= createEnvironmentCursorCodec())\n\t\t\t\t\tplanner.assertUnchanged()\n\t\t\t\t\tconst pageSchema = planner.page(table, selection)\n\t\t\t\t\tassertRelationshipDepth(selection, route?.path.length ?? 0)\n\t\t\t\t\tconst plan = planner.plan(table, input, route ? [] : conditions, constraints)\n\t\t\t\t\tif (plan.args.numItems > maxPageSize) throw new Error('Page size exceeds central ceiling')\n\t\t\t\t\t// Native root limits stay native; lowering those limits cannot raise\n\t\t\t\t\t// the independent shared request meter.\n\t\t\t\t\tplan.args.maximumRowsRead = Math.min(\n\t\t\t\t\t\tplan.args.maximumRowsRead ?? request.budgets.rawCandidates,\n\t\t\t\t\t\trequest.budgets.rawCandidates,\n\t\t\t\t\t)\n\t\t\t\t\tplan.args.maximumBytesRead = Math.min(\n\t\t\t\t\t\tplan.args.maximumBytesRead ?? request.budgets.documentBytes,\n\t\t\t\t\t\trequest.budgets.documentBytes,\n\t\t\t\t\t)\n\t\t\t\t\tregistryDigest ??= Array.from(\n\t\t\t\t\t\tnew Uint8Array(\n\t\t\t\t\t\t\tawait crypto.subtle.digest('SHA-256', new TextEncoder().encode(relations.identity)),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t(byte) => byte.toString(16).padStart(2, '0'),\n\t\t\t\t\t).join('')\n\t\t\t\t\t// The digest await is a boundary too: mutation must be detected\n\t\t\t\t\t// before authenticated cursor validation or native query construction.\n\t\t\t\t\tplanner.assertUnchanged()\n\t\t\t\t\t// SAFETY: selection has passed the registry page validator before binding.\n\t\t\t\t\tconst binding: CursorBinding = {\n\t\t\t\t\t\ttable: route?.table ?? table,\n\t\t\t\t\t\tindex: plan.index?.name ?? 'by_creation_time',\n\t\t\t\t\t\torder: plan.args.order ?? 'asc',\n\t\t\t\t\t\tclientFilters: plan.clientIdentity,\n\t\t\t\t\t\t// Include output selection and the complete immutable scope in trusted identity.\n\t\t\t\t\t\tserverFilters: {\n\t\t\t\t\t\t\tpredicates: plan.serverIdentity,\n\t\t\t\t\t\t\tselection: selection as import('convex/values').Value,\n\t\t\t\t\t\t\tscope: { ...request.scope },\n\t\t\t\t\t\t},\n\t\t\t\t\t\trelationPath: [],\n\t\t\t\t\t\tprincipal: JSON.stringify(request.scope),\n\t\t\t\t\t\ttenant: request.scope.tenant,\n\t\t\t\t\t\tpolicyVersion,\n\t\t\t\t\t\tengineVersion,\n\t\t\t\t\t\tregistryVersion: registryDigest,\n\t\t\t\t\t}\n\t\t\t\t\t// The executor accepts registry-selected native tables, rather than a static DM key.\n\t\t\t\t\tconst executorRequest: unknown = request\n\t\t\t\t\t// SAFETY: only native DM types are erased at this private executor boundary.\n\t\t\t\t\tconst executor = relationshipExecutor(\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\texecutorRequest as ExecutionRequest,\n\t\t\t\t\t\tplanner,\n\t\t\t\t\t\tcodec,\n\t\t\t\t\t\tbinding,\n\t\t\t\t\t)\n\t\t\t\t\tif (route)\n\t\t\t\t\t\treturn executor.continuation(\n\t\t\t\t\t\t\troute.table,\n\t\t\t\t\t\t\troute.parent,\n\t\t\t\t\t\t\troute.path,\n\t\t\t\t\t\t\tselection,\n\t\t\t\t\t\t\tplan.args,\n\t\t\t\t\t\t\tconditions,\n\t\t\t\t\t\t\tconstraints,\n\t\t\t\t\t\t)\n\t\t\t\t\tconst result = await executeQuery(\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\trequest,\n\t\t\t\t\t\ttable,\n\t\t\t\t\t\tplan,\n\t\t\t\t\t\tplanner,\n\t\t\t\t\t\tcodec,\n\t\t\t\t\t\tbinding,\n\t\t\t\t\t\tasync (row, permitted) => {\n\t\t\t\t\t\t\t// SAFETY: metered native stream rows contain the validated system fields.\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!permitted ||\n\t\t\t\t\t\t\t\t!(await executor.matches(table, row as RelationDocument, plan.residual))\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\treturn null\n\t\t\t\t\t\t\t// SAFETY: the same native row is authorized and matches the declared predicates.\n\t\t\t\t\t\t\treturn executor.output(table, row as RelationDocument, selection, plan.args)\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t\tplanner.assertUnchanged()\n\t\t\t\t\treturn pageSchema.parse(result)\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\t// SAFETY: each key comes from the exact validated registry; the planner\n\t\t// validates all input and projection while mapped types retain table brands.\n\t\treturn Object.freeze(\n\t\t\tObject.fromEntries(Object.keys(relations.tables).map((table) => [table, tableQuery(table)])),\n\t\t) as { [T in keyof Tables]: TableQuery<Tables, D, T> }\n\t}\n\treturn Object.assign(querying, { tables: relations.tables })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"querying.mjs","names":["executorRequest","createQueryEngine","config","settings","options","planner","createPlanner","relations","schema","cursorCodec","createCursorCodec","maxPageSize","engineVersion","policyVersion","registryDigest","security","createManagedSecurity","querying","request","ctx","tableQuery","table","conditions","constraints","selection","route","spec","selected","path","declaredPath","target","name","edge","codec","createEnvironmentCursorCodec","assertRelationshipDepth","plan","input","byte","binding","executor","relationshipExecutor","executeQuery","permitted","row"],"sources":["../src/querying.ts"],"sourcesContent":["import type {\n\tGenericSchema,\n\tSchemaDefinition,\n\tDataModelFromSchemaDefinition,\n\tPaginationResult,\n} from 'convex/server'\nimport type { GenericId } from 'convex/values'\nimport type {\n\tRelationTables,\n\tRelationDeclarations,\n\tRelationRegistry,\n\tRelationQueryRow,\n\tRelationSelection,\n\tRelationFilters,\n\tRelationFilterSelection,\n} from './relations'\nimport { createPlanner, type QueryInput, type StoredConstraint } from './querying/planner'\nimport { executeQuery, type ExecutionRequest } from './querying/execution'\nimport {\n\trelationshipExecutor,\n\tassertRelationshipDepth,\n\ttype OutputSelection,\n\ttype RelationDocument,\n} from './querying/relationships'\nimport {\n\tcreateCursorCodec,\n\tcreateEnvironmentCursorCodec,\n\ttype CursorCodecConfig,\n\ttype CursorBinding,\n} from './querying/cursors'\nimport {\n\tcreateManagedSecurity,\n\ttype ManagedSecurityConfig,\n\ttype ManagedQueryContext,\n\ttype ManagedBudgets,\n} from './querying/security'\nimport type { IndexCondition, NativePagination } from './querying/filters'\n\ntype FullMask<S> = {\n\t[K in keyof S]-?: NonNullable<S[K]> extends true\n\t\t? true\n\t\t: FullMask<Exclude<NonNullable<S[K]>, true>>\n}\ntype Paths<\n\tD extends RelationDeclarations,\n\tT extends string,\n\tL extends readonly 1[] = [1, 1, 1, 1],\n> = L extends readonly [1, ...infer Rest extends 1[]]\n\t? {\n\t\t\t[K in keyof D[T] & string]:\n\t\t\t\t| (D[T][K]['cardinality'] extends 'many' ? K : never)\n\t\t\t\t| `${K}.${Paths<D, D[T][K]['target'], Rest>}`\n\t\t}[keyof D[T] & string]\n\t: never\ntype PathTarget<\n\tD extends RelationDeclarations,\n\tT extends string,\n\tP extends string,\n> = P extends `${infer Head}.${infer Rest}`\n\t? PathTarget<D, D[T][Head]['target'], Rest>\n\t: D[T][P]['target']\ntype PathScope<\n\tD extends RelationDeclarations,\n\tT extends string,\n\tP extends string,\n> = P extends `${infer Head}.${infer Rest}`\n\t? PathScope<D, D[T][Head]['target'], Rest>\n\t: Extract<NonNullable<D[T][P]['targetGuard']>['tag'], string>\ntype RemainingDepth<P extends string, L extends readonly 1[]> = L extends readonly [\n\t1,\n\t...infer Rest extends 1[],\n]\n\t? P extends `${string}.${infer Tail}`\n\t\t? RemainingDepth<Tail, Rest>\n\t\t: Rest\n\t: []\ntype EngineArgs<\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n\tT extends keyof Tables,\n> = NativePagination & {\n\tfilters?: RelationFilters<Tables, D, T, FullMask<RelationFilterSelection<Tables, D, T>>>\n\torder?: 'asc' | 'desc'\n}\n/** Typed declarative chain returned by the engine; named for consumer declaration emission. */\nexport interface TableQuery<\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n\tT extends keyof Tables,\n\tS = {},\n\tL extends readonly 1[] = [1, 1, 1, 1],\n\tScope extends string = never,\n> {\n\twhen(value: IndexCondition['value'], index: string): TableQuery<Tables, D, T, S, L, Scope>\n\twhere(\n\t\tspec: NonNullable<EngineArgs<Tables, D, T>['filters']>,\n\t): TableQuery<Tables, D, T, S, L, Scope>\n\twith<const Selection extends RelationSelection<Tables, D, T, L>>(\n\t\tselection: Selection & {\n\t\t\t[K in keyof Selection]: K extends keyof RelationSelection<Tables, D, T, L>\n\t\t\t\t? Selection[K]\n\t\t\t\t: never\n\t\t},\n\t): TableQuery<Tables, D, T, Selection, L, Scope>\n\trelation<const P extends Paths<D, Extract<T, string>>>(\n\t\tparent: GenericId<Tables[T]['tableName']>,\n\t\tpath: P,\n\t): Omit<\n\t\tTableQuery<\n\t\t\tTables,\n\t\t\tD,\n\t\t\tExtract<PathTarget<D, Extract<T, string>, P>, keyof Tables>,\n\t\t\t{},\n\t\t\tRemainingDepth<P, L>,\n\t\t\tPathScope<D, Extract<T, string>, P>\n\t\t>,\n\t\t'relation'\n\t>\n\tpaginate(\n\t\targs: EngineArgs<Tables, D, T>,\n\t): Promise<PaginationResult<RelationQueryRow<Tables, D, T, S, Scope>>>\n}\nexport interface QueryEngineDeclaration<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n> {\n\tschema: Schema\n\trelations: RelationRegistry<Tables, D>\n}\n/** Advanced server configuration, separate from the normal schema/relations declaration. */\nexport interface QueryEngineOptions<Schema extends SchemaDefinition<GenericSchema, boolean>> {\n\t/** Explicit codecs validate at creation. Otherwise environment keys load at first paginate. */\n\tcursor?: CursorCodecConfig\n\tbudgets?: Partial<ManagedBudgets>\n\tmaxPageSize?: number\n\tpolicyVersion?: string\n\tengineVersion?: string\n\ttrustedAdapter?: ManagedSecurityConfig<DataModelFromSchemaDefinition<Schema>>['trustedAdapter']\n}\n\n/** @deprecated Use QueryEngineDeclaration and optional QueryEngineOptions separately. */\nexport interface QueryEngineConfig<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n>\n\textends QueryEngineDeclaration<Schema, Tables, D>, QueryEngineOptions<Schema> {\n\tcursor: CursorCodecConfig\n}\n\ntype QueryEngine<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tTables extends RelationTables,\n\tD extends RelationDeclarations,\n> = {\n\t(ctx: ManagedQueryContext<DataModelFromSchemaDefinition<Schema>>): {\n\t\t[T in keyof Tables]: TableQuery<Tables, D, T>\n\t}\n\ttables: RelationRegistry<Tables, D>['tables']\n}\n\n/** Central facade. Endpoint chains carry declarative constraints and explicit relationships. */\nexport function createQueryEngine<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tconst Tables extends RelationTables,\n\tconst D extends RelationDeclarations,\n>(\n\tconfig: QueryEngineDeclaration<Schema, Tables, D>,\n\toptions?: QueryEngineOptions<Schema>,\n): QueryEngine<Schema, Tables, D>\n/** @deprecated Pass advanced fields in the optional second argument. */\nexport function createQueryEngine<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tconst Tables extends RelationTables,\n\tconst D extends RelationDeclarations,\n>(\n\tconfig: QueryEngineDeclaration<Schema, Tables, D> &\n\t\tQueryEngineOptions<Schema> & { cursor: CursorCodecConfig },\n): QueryEngine<Schema, Tables, D>\nexport function createQueryEngine<\n\tSchema extends SchemaDefinition<GenericSchema, boolean>,\n\tconst Tables extends RelationTables,\n\tconst D extends RelationDeclarations,\n>(\n\tconfig: QueryEngineDeclaration<Schema, Tables, D> & QueryEngineOptions<Schema>,\n\toptions?: QueryEngineOptions<Schema>,\n) {\n\tconst { relations } = config\n\t// Retain released one-argument calls; a second argument overrides legacy fields.\n\tconst settings = { ...config, ...options }\n\tconst planner = createPlanner(config.schema, relations)\n\tconst schema = planner.streamSchema\n\tlet cursorCodec = settings.cursor === undefined ? undefined : createCursorCodec(settings.cursor)\n\tconst maxPageSize = settings.maxPageSize ?? 100\n\tif (!Number.isSafeInteger(maxPageSize) || maxPageSize <= 0 || maxPageSize > 100)\n\t\tthrow new Error('Invalid central page size')\n\tconst engineVersion = settings.engineVersion ?? 'scalar-1'\n\tconst policyVersion = settings.policyVersion ?? '1'\n\t// Bind the full immutable identity through a collision-resistant digest so\n\t// real application registries fit the codec's bounded AAD.\n\tlet registryDigest: string | undefined\n\tconst security = createManagedSecurity<DataModelFromSchemaDefinition<Schema>>({\n\t\ttables: Object.keys(relations.tables),\n\t\tpolicyVersion,\n\t\tbudgets: settings.budgets,\n\t\ttrustedAdapter: settings.trustedAdapter,\n\t})\n\tfunction querying(ctx: ManagedQueryContext<DataModelFromSchemaDefinition<Schema>>) {\n\t\tconst request = security(ctx)\n\t\tfunction tableQuery(\n\t\t\ttable: string,\n\t\t\tconditions: readonly IndexCondition[] = [],\n\t\t\tconstraints: readonly StoredConstraint[] = [],\n\t\t\tselection: OutputSelection = {},\n\t\t\troute?: { table: string; parent: string; path: string[] },\n\t\t) {\n\t\t\treturn Object.freeze({\n\t\t\t\twhen: (value: IndexCondition['value'], index: string) =>\n\t\t\t\t\ttableQuery(table, [...conditions, { value, index }], constraints, selection, route),\n\t\t\t\twhere: (spec: StoredConstraint) =>\n\t\t\t\t\ttableQuery(table, conditions, [...constraints, spec], selection, route),\n\t\t\t\twith: (selected: OutputSelection) =>\n\t\t\t\t\ttableQuery(table, conditions, constraints, selected, route),\n\t\t\t\trelation: (parent: string, declaredPath: string) => {\n\t\t\t\t\tconst path = declaredPath.split('.')\n\t\t\t\t\tif (!path.length || path.length > 4) throw new Error('INVALID_RELATION')\n\t\t\t\t\tlet target = table\n\t\t\t\t\tfor (const name of path) {\n\t\t\t\t\t\tconst edge = planner.metadata.declarations[target]?.[name]\n\t\t\t\t\t\tif (!edge) throw new Error('INVALID_RELATION')\n\t\t\t\t\t\ttarget = edge.target\n\t\t\t\t\t}\n\t\t\t\t\treturn tableQuery(target, conditions, constraints, {}, { table, parent, path })\n\t\t\t\t},\n\t\t\t\tasync paginate(input: QueryInput) {\n\t\t\t\t\t// Resolve once per global engine, before any native query or policy reads.\n\t\t\t\t\tconst codec = (cursorCodec ??= createEnvironmentCursorCodec())\n\t\t\t\t\tplanner.select(table, selection)\n\t\t\t\t\tassertRelationshipDepth(selection, route?.path.length ?? 0)\n\t\t\t\t\tconst plan = planner.plan(table, input, route ? [] : conditions, constraints)\n\t\t\t\t\tif (plan.args.numItems > maxPageSize) throw new Error('Page size exceeds central ceiling')\n\t\t\t\t\t// Native root limits stay native; lowering those limits cannot raise\n\t\t\t\t\t// the independent shared request meter.\n\t\t\t\t\tplan.args.maximumRowsRead = Math.min(\n\t\t\t\t\t\tplan.args.maximumRowsRead ?? request.budgets.rawCandidates,\n\t\t\t\t\t\trequest.budgets.rawCandidates,\n\t\t\t\t\t)\n\t\t\t\t\tplan.args.maximumBytesRead = Math.min(\n\t\t\t\t\t\tplan.args.maximumBytesRead ?? request.budgets.documentBytes,\n\t\t\t\t\t\trequest.budgets.documentBytes,\n\t\t\t\t\t)\n\t\t\t\t\tregistryDigest ??= Array.from(\n\t\t\t\t\t\tnew Uint8Array(\n\t\t\t\t\t\t\tawait crypto.subtle.digest('SHA-256', new TextEncoder().encode(relations.identity)),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t(byte) => byte.toString(16).padStart(2, '0'),\n\t\t\t\t\t).join('')\n\t\t\t\t\t// SAFETY: selection has passed registry admission before cursor binding.\n\t\t\t\t\tconst binding: CursorBinding = {\n\t\t\t\t\t\ttable: route?.table ?? table,\n\t\t\t\t\t\tindex: plan.index?.name ?? 'by_creation_time',\n\t\t\t\t\t\torder: plan.args.order ?? 'asc',\n\t\t\t\t\t\tclientFilters: plan.clientIdentity,\n\t\t\t\t\t\t// Include output selection and the complete immutable scope in trusted identity.\n\t\t\t\t\t\tserverFilters: {\n\t\t\t\t\t\t\tpredicates: plan.serverIdentity,\n\t\t\t\t\t\t\tselection: selection as import('convex/values').Value,\n\t\t\t\t\t\t\tscope: { ...request.scope },\n\t\t\t\t\t\t},\n\t\t\t\t\t\trelationPath: [],\n\t\t\t\t\t\tprincipal: JSON.stringify(request.scope),\n\t\t\t\t\t\ttenant: request.scope.tenant,\n\t\t\t\t\t\tpolicyVersion,\n\t\t\t\t\t\tengineVersion,\n\t\t\t\t\t\tregistryVersion: registryDigest,\n\t\t\t\t\t}\n\t\t\t\t\t// The executor accepts registry-selected native tables, rather than a static DM key.\n\t\t\t\t\tconst executorRequest: unknown = request\n\t\t\t\t\t// SAFETY: only native DM types are erased at this private executor boundary.\n\t\t\t\t\tconst executor = relationshipExecutor(\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\texecutorRequest as ExecutionRequest,\n\t\t\t\t\t\tplanner,\n\t\t\t\t\t\tcodec,\n\t\t\t\t\t\tbinding,\n\t\t\t\t\t)\n\t\t\t\t\tconst result = route\n\t\t\t\t\t\t? await executor.continuation(\n\t\t\t\t\t\t\t\troute.table,\n\t\t\t\t\t\t\t\troute.parent,\n\t\t\t\t\t\t\t\troute.path,\n\t\t\t\t\t\t\t\tselection,\n\t\t\t\t\t\t\t\tplan.args,\n\t\t\t\t\t\t\t\tconditions,\n\t\t\t\t\t\t\t\tconstraints,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: await executeQuery(\n\t\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t\t\trequest,\n\t\t\t\t\t\t\t\ttable,\n\t\t\t\t\t\t\t\tplan,\n\t\t\t\t\t\t\t\tplanner,\n\t\t\t\t\t\t\t\tcodec,\n\t\t\t\t\t\t\t\tbinding,\n\t\t\t\t\t\t\t\tasync (row, permitted) => {\n\t\t\t\t\t\t\t\t\t// SAFETY: metered native stream rows contain the validated system fields.\n\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t!permitted ||\n\t\t\t\t\t\t\t\t\t\t!(await executor.matches(table, row as RelationDocument, plan.residual))\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\treturn null\n\t\t\t\t\t\t\t\t\t// SAFETY: the same native row is authorized and matches the declared predicates.\n\t\t\t\t\t\t\t\t\treturn executor.output(table, row as RelationDocument, selection, plan.args)\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t)\n\t\t\t\t\t// SAFETY: the private executor validated and projected every row against\n\t\t\t\t\t// this registry's DTO and selected edges before assembling the page.\n\t\t\t\t\treturn result as PaginationResult<\n\t\t\t\t\t\tRelationQueryRow<Tables, D, keyof Tables, OutputSelection>\n\t\t\t\t\t>\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t\t// SAFETY: each key comes from the exact validated registry; the planner\n\t\t// validates all input and projection while mapped types retain table brands.\n\t\treturn Object.freeze(\n\t\t\tObject.fromEntries(Object.keys(relations.tables).map((table) => [table, tableQuery(table)])),\n\t\t) as { [T in keyof Tables]: TableQuery<Tables, D, T> }\n\t}\n\treturn Object.assign(querying, { tables: relations.tables })\n}\n"],"mappings":"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"}
@@ -173,13 +173,10 @@ export interface RelationMetadata {
173
173
  }
174
174
  /** No ID-field inference and no readers: this registry owns declarations/schema helpers only. */
175
175
  export declare function defineRelations<const Tables extends RelationTables, const D extends RelationDeclarations>(tables: Tables, declare: (r: RelationBuilder<Tables>, branch: BranchBuilder<Tables>) => D & ExactDeclarations<Tables, D>): RelationRegistry<Tables, D>;
176
- /** Internal owned executor bridge. Not an advertised root API. Every operation
177
- * rechecks the live registry, including cached plans and individual projections.
178
- */
176
+ /** Internal owned executor bridge. Source ownership is checked once by each engine. */
179
177
  export declare function getRelationExecutor(registry: RelationRegistryIdentity): Readonly<{
180
- assertUnchanged: () => void;
178
+ streamSchema: import("convex/server").SchemaDefinition<import("convex/server").GenericSchema, boolean>;
181
179
  validateDocument: (table: string, row: Record<string, import('convex/values').Value>) => void;
182
- assertNativeTable: (table: string, definition: TableDefinition) => void;
183
180
  assertSchema: (tables: Readonly<Record<string, TableDefinition>>) => void;
184
181
  pagination(table: string): z.ZodObject<{
185
182
  cursor: z.ZodUnion<readonly [z.ZodString, z.ZodNull]>;
@@ -194,17 +191,8 @@ export declare function getRelationExecutor(registry: RelationRegistryIdentity):
194
191
  desc: "desc";
195
192
  }>>;
196
193
  }, z.core.$strict>;
197
- page(table: string, selection: SelectionMask): z.ZodObject<{
198
- page: z.ZodArray<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
199
- isDone: z.ZodBoolean;
200
- continueCursor: z.ZodString;
201
- splitCursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
202
- pageStatus: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
203
- SplitRecommended: "SplitRecommended";
204
- SplitRequired: "SplitRequired";
205
- }>>>;
206
- }, z.core.$strip>;
207
- project(tables: Readonly<Record<string, TableDefinition>>, table: string, row: Record<string, import('convex/values').Value>, eligible: () => boolean): Record<string, unknown> | null;
194
+ select(table: string, selection: SelectionMask): void;
195
+ project(table: string, row: Record<string, import('convex/values').Value>, eligible: () => boolean): Record<string, unknown> | null;
208
196
  }>;
209
197
  /** Internal compiler/engine adapter. Registry identity alone cannot forge a registry. */
210
198
  export declare function getRelationMetadata(registry: RelationRegistryIdentity): RelationMetadata;
@@ -1,2 +1,2 @@
1
- import{nativePagination as e,relationFilterSchema as t,scalarPredicateSchema as n}from"./querying/filters.mjs";import{paginated as r}from"./zod-table.mjs";import{convexToZod as i,zodToConvex as a}from"convex-helpers/server/zod4";import{z as o}from"zod";import{v as s}from"convex/values";const c=Symbol(`relationField`),l=Symbol(`relationEdge`),u=/* @__PURE__ */ new WeakMap,d=/* @__PURE__ */ new WeakMap,f=/* @__PURE__ */ new WeakMap,p=/* @__PURE__ */ new WeakMap,m=/* @__PURE__ */ new WeakSet,h=/* @__PURE__ */ new WeakSet,g=o.object({indexes:o.array(o.object({indexDescriptor:o.string(),fields:o.array(o.string())}))});function _(n,i){let l={},_=/* @__PURE__ */ new Set,v=/* @__PURE__ */ new Map,y={},b={},w={};for(let[e,t]of Object.entries(n)){if(t.tableName!==e||[`one`,`many`,`__proto__`,`constructor`,`prototype`].includes(e))throw Error(`Invalid relation table "${e}"`);let n=t.dto(!0);if(!(n instanceof o.ZodObject)&&!(n instanceof o.ZodDiscriminatedUnion))throw Error(`Expected object or discriminated union DTO`);let r=H(n),i=F(t.table);R(i.documentType);let u=N(e,t.schema,n,i.documentType),d=g.parse(i).indexes.map(e=>({name:e.indexDescriptor,fields:[...e.fields]})).sort((e,t)=>e.name.localeCompare(t.name));R(I(a(n))),l[e]={...u,indexes:d,dto:n,assertUnchanged:r};let h=(t,n)=>{let r=Object.create(null);function i(t,r,a){let o={[c]:void 0,table:e,field:t,guard:n,forTable(e){if(n)throw Error(`forTable on branch-scoped fields is unsupported`);if(!T(r)?.includes(e))throw Error(`Invalid native ID member selection`);if(!Object.hasOwn(l,e))throw Error(`Native ID member table is not registered`);let a=Q(r)?s.union(s.id(e),s.null()):s.id(e);return i(t,r.isOptional===`optional`?s.optional(a):a,Object.freeze({table:e}))},through(e){if(a||p.has(e))throw Error(`forTable with through is unsupported`);let t=f.get(e);if(!_.has(e)||!t||!E(r,t))throw Error(`Invalid junction field or registry`);let n=Object.freeze({base:o,junction:e});return m.add(n),n}};return f.set(o,r),a&&p.set(o,a),_.add(o),Object.freeze(o)}for(let[e,n]of Object.entries(t))r[e]=i(e,n);return Object.freeze(r)};if(y[e]=h(u.fields),u.branches)for(let[t,n]of Object.entries(u.branches.options))v.set(JSON.stringify([e,t]),h(n.fields,Object.freeze({discriminator:u.branches.discriminator,tag:t})));b[e]=t=>C(e,`one`,t,_),w[e]=t=>C(e,`many`,t,_)}let D=i(Object.freeze({...y,one:Object.freeze(b),many:Object.freeze(w)}),((e,t)=>{let n=v.get(JSON.stringify([e,t]));if(!n)throw Error(`Unknown variant scope "${e}.${t}"`);return n})),k=Object.fromEntries(Object.entries(D).map(([e,t])=>[e,Object.freeze({...t})]));Object.freeze(k);for(let[e,t]of Object.entries(k)){if(!Object.hasOwn(n,e))throw Error(`Unknown source table "${e}"`);for(let[n,r]of Object.entries(t)){if(l[e].allFields.has(n)||l[e].branches&&[`variant`,`variants`].includes(n)||[`and`,`or`,`not`,`fields`,`then`,`__proto__`,`constructor`,`prototype`].includes(n))throw Error(`Relation name collision "${n}"`);if(!h.has(r)||!_.has(S(r.from))||!_.has(S(r.to))||r.source!==e)throw Error(`Relation source bucket mismatch`);O(r,l)}}let P={metadata:l,declarations:k},z={};for(let i of Object.keys(n))z[i]={paginationOpts(n){return K(P),x(n),J(e.extend({filters:t(j(P,i,n)).optional(),order:o.enum([`asc`,`desc`]).optional()}),()=>K(P))},pageDto(e){return K(P),x(e),J(r(M(P,i,e)).result,()=>K(P))}};let B=JSON.stringify([2,Object.entries(l).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t.fields).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.isOptional,I(t)]),t.branches?[t.branches.discriminator,Object.entries(t.branches.options).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t.fields).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.isOptional,I(t)])])]:null,t.indexes,L(I(a(t.dto)))]),Object.entries(k).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.cardinality,t.target,A(t.from),A(t.to)])])]),V=Object.freeze({identity:B,version:1,tables:Object.freeze(z)});u.set(V,Z(P));let U=Object.freeze({...n}),W=Object.fromEntries(Object.entries(U).map(([e,t])=>{let n=G(t.schema,`stored`),r=G(t.publicDto,`dto`),i=t.table.validator,a=i.isOptional,o=JSON.stringify(F(t.table));return[e,()=>{if(n(),r(),t.table.validator!==i||i.isOptional!==a||JSON.stringify(F(t.table))!==o)throw Error(`Native schema mutated after registry construction: ${e}`)}]}));for(let[e,t]of Object.entries(l)){if(!t.branches)continue;let n=t.assertUnchanged;t.assertUnchanged=()=>{n(),W[e]()}}return d.set(V,{internal:P,tables:U,assertStoredUnchanged:()=>{for(let e of Object.values(W))e()},assertNativeTable(e,t){if(!Object.hasOwn(U,e)||U[e].table!==t)throw Error(`Native schema/table ownership disagrees with relation registry`);W[e]()}}),V}function v(a){let c=d.get(a);if(!c)throw Error(`Unknown relation registry`);let l=()=>{K(c.internal),c.assertStoredUnchanged()},u=e=>{l();let t=Object.keys(c.tables);if(t.length!==Object.keys(e).length||t.some(t=>e[t]!==c.tables[t].table))throw Error(`Native schema/table ownership disagrees with relation registry`)};l();let f=/* @__PURE__ */ new WeakMap,p=/* @__PURE__ */ new Map,m=/* @__PURE__ */ new Map,h=/* @__PURE__ */ new WeakMap;function g(e,t){l();let n=c.internal.metadata[e];if(!n)throw Error(`Unknown query table`);if(!n.branches)return;let r=o.string().safeParse(t[n.branches.discriminator]),a=r.success&&Object.hasOwn(n.branches.options,r.data)?n.branches.options[r.data]:void 0;if(!a)throw Error(`Invalid variant document`);let u=Object.fromEntries(Object.keys(a.fields).filter(e=>Object.hasOwn(t,e)).map(e=>[e,t[e]])),d=f.get(a);d||(d=i(s.object(a.fields)),f.set(a,d)),d.parse(u)}return Object.freeze({assertUnchanged:l,validateDocument:g,assertNativeTable:c.assertNativeTable,assertSchema:u,pagination(r){l();let i=c.internal;function a(e,t,r){let o=JSON.stringify([e,t,r??null]),s=m.get(o);if(s)return s;let c=i.metadata[e];if(!c)throw Error(`Unknown query table`);let l=JSON.stringify([e,r??null]),u=p.get(l);if(!u){u={};for(let[e,t]of Object.entries(r===void 0?c.fields:c.branches.options[r].fields))b(t)&&(u[e]=n(t).optional());p.set(l,u)}let d={fields:u,variants:c.branches&&r===void 0&&t<4?{discriminator:c.branches.discriminator,options:Object.fromEntries(Object.keys(c.branches.options).map(n=>[n,a(e,t+1,n)]))}:void 0,relations:t>=4?{}:Object.fromEntries(Object.entries(i.declarations[e]??{}).map(([e,n])=>[e,{cardinality:n.cardinality,target:a(n.target,t+1)}]))};return m.set(o,d),d}return e.extend({filters:t(a(r,0),h).optional(),order:o.enum([`asc`,`desc`]).optional()})},page(e,t){return l(),x(t),r(M(c.internal,e,t)).result},project(e,t,n,r){if(u(e),!r())return null;let i=c.internal.metadata[t];if(!i)throw Error(`Unknown query table`);let a=i.branches?i.branches.options[String(n[i.branches.discriminator])]:void 0;if(i.branches&&!a)throw Error(`Invalid variant document`);let s=a?.dto??i.dto;if(!(s instanceof o.ZodObject))throw Error(`Invalid variant DTO`);return g(t,n),s.parse(Object.fromEntries(Object.keys(s.shape).filter(e=>Object.hasOwn(n,e)).map(e=>[e,n[e]])))}})}function y(e){let t=u.get(e);if(!t)throw Error(`Unknown relation registry`);return t}function b(e){return[`id`,`string`,`float64`,`int64`,`boolean`,`null`,`literal`].includes(e.kind)||e.kind===`union`&&e.members.every(b)}function x(e){let t=[{value:e,depth:0,ancestors:[]}],n=0;for(;t.length;){let{value:e,depth:r,ancestors:i}=t.pop();if(++n>256||r>4||i.includes(e))throw Error(`Selection cycle or depth/node budget exceeded`);let a=Object.getPrototypeOf(e);if(a!==Object.prototype&&a!==null)throw Error(`Invalid selection`);let o=Reflect.ownKeys(e);if(o.length+n+t.length>256)throw Error(`Selection node budget exceeded`);for(let a of o){let o=Object.getOwnPropertyDescriptor(e,a);if(!o.enumerable||!(`value`in o)||String(a)!==a)throw Error(`Invalid selection property`);if(o.value!==!0)t.push({value:o.value,depth:r+1,ancestors:[...i,e]});else if(++n>256)throw Error(`Selection node budget exceeded`)}}}function S(e){return`base`in e?e.base:e}function C(e,t,n,r){for(let e of[n.from,n.to])if(!r.has(S(e))||`base`in e&&(!m.has(e)||!r.has(e.junction)))throw Error(`Foreign registry or invalid field reference`);if(S(n.to).table!==e)throw Error(`Wrong relation target table`);let i=Object.freeze({[l]:!0,source:S(n.from).table,target:e,cardinality:t,from:n.from,to:n.to,sourceGuard:S(n.from).guard,targetGuard:S(n.to).guard,junctionGuard:w(n.from,n.to),sourceMember:p.get(S(n.from)),targetMember:p.get(S(n.to))});return h.add(i),i}function w(e,t){let n=`base`in e?e.junction.guard:void 0,r=`base`in t?t.junction.guard:void 0;if(n&&r&&(n.discriminator!==r.discriminator||n.tag!==r.tag))throw Error(`Contradictory junction scopes`);return n??r}function T(e){if(e.kind===`id`)return[e.tableName];if(e.kind===`null`)return[];if(e.kind!==`union`)return null;let t=e.members.map(T);return t.some(e=>e===null)?null:[...new Set(t.flatMap(e=>e))].sort()}function E(e,t){let n=D(e);return n.length>0&&JSON.stringify(n)===JSON.stringify(D(t))}function D(e){if(e.kind===`union`)return[...new Set(e.members.flatMap(D))].sort();if(e.kind===`null`)return[];if(![`id`,`string`,`float64`,`int64`,`boolean`,`literal`].includes(e.kind))throw Error(`Unsupported relation field kind`);return[JSON.stringify(I(e))]}function O(e,t){let n=e.from,r=e.to;if(`base`in n!=`base`in r)throw Error(`Both relation legs must use through`);if(`base`in n&&`base`in r){if(n.junction.table!==r.junction.table)throw Error(`Different junction tables`);k(t,n.junction.table,n.junction.field,e.junctionGuard),k(t,e.target,r.base.field,e.targetGuard);return}if(!E(f.get(S(n)),f.get(S(r))))throw Error(`Incompatible relation field types`);k(t,e.target,S(r).field,e.targetGuard)}function k(e,t,n,r){if(n!==`_id`&&!e[t].indexes.some(e=>{let t=e.fields.indexOf(n);return t>=0&&e.fields.slice(0,t).every(e=>e===r?.discriminator)}))throw Error(`No active index begins with or has a guarded prefix for "${t}.${n}"`)}function A(e){return`base`in e?[e.base.table,e.base.field,e.base.guard??null,e.junction.table,e.junction.field,e.junction.guard??null]:p.has(e)?[e.table,e.field,e.guard??null,p.get(e)]:[e.table,e.field,e.guard??null]}function j(e,t,r,i=0,a){let o={},s={},c=e.metadata[t],l={};for(let[u,d]of Object.entries(r)){if(u===`variants`&&d!==!0&&c.branches&&a===void 0){if(i>=4)throw Error(`Invalid variant selection`);for(let[n,a]of Object.entries(d)){if(!Object.hasOwn(c.branches.options,n)||a===!0)throw Error(`Unknown variant filter selection`);l[n]=j(e,t,{...Object.fromEntries(Object.entries(r).filter(([e])=>e!==`variants`)),...a},i+1,n)}continue}let f=(a===void 0?c.fields:c.branches.options[a].fields)[u],p=e.declarations[t]?.[u];if(d===!0&&f)o[u]=n(f).optional();else if(d!==!0&&p&&i<4)s[u]={cardinality:p.cardinality,target:j(e,p.target,d,i+1)};else throw Error(`Invalid relation filter selection "${t}.${u}"`)}return{fields:o,relations:s,variants:c.branches&&a===void 0?{discriminator:c.branches.discriminator,options:l}:void 0}}function M(e,t,n,i=0){let a={};for(let[s,c]of Object.entries(n)){let n=e.declarations[t]?.[s];if(!n||i>=4)throw Error(`Unknown or too deep relation "${t}.${s}"`);let l=c===!0?e.metadata[n.target].dto:M(e,n.target,c,i+1);if(n.targetGuard){if(!(l instanceof o.ZodDiscriminatedUnion))throw Error(`Invalid target scope`);l=l.options.find(e=>e.shape[n.targetGuard.discriminator]instanceof o.ZodLiteral&&e.shape[n.targetGuard.discriminator].value===n.targetGuard.tag)}a[s]=n.cardinality===`one`?l.nullable():r(l).result}let s=e.metadata[t];function c(n,r){let i={...a};for(let n of Object.keys(i)){let a=e.declarations[t][n];a.sourceGuard&&r!==a.sourceGuard.tag&&a.cardinality===`one`&&(i[n]=o.null())}return J(n.extend(i).strict(),()=>K(e))}if(s.branches){let t=Object.entries(s.branches.options).map(([e,t])=>c(t.dto,e));return X(o.discriminatedUnion(s.branches.discriminator,[t[0],...t.slice(1)]),()=>K(e))}if(!(s.dto instanceof o.ZodObject))throw Error(`Expected object DTO`);return c(s.dto)}function N(e,t,n,r){if(t instanceof o.ZodObject&&n instanceof o.ZodObject){let n=a(t).fields;return z(e,n,r),{fields:n,allFields:new Set(Object.keys(n))}}if(!(t instanceof o.ZodDiscriminatedUnion)||!(n instanceof o.ZodDiscriminatedUnion))throw Error(`Expected matching discriminated union boundaries "${e}"`);let i=t._zod.def.discriminator;if(n._zod.def.discriminator!==i)throw Error(`DTO discriminator mismatch`);function c(e){let t=Object.create(null);for(let n of e.options){if(!(n instanceof o.ZodObject))throw Error(`Variant branches must be objects`);let e=n.shape[i];if(!(e instanceof o.ZodLiteral)||e.values.size!==1)throw Error(`Variant tags must be unique required string literals`);let r=o.string().safeParse(e.value);if(!r.success||Object.hasOwn(t,r.data))throw Error(`Variant tags must be unique required string literals`);t[r.data]=n}if(Object.keys(t).length===0)throw Error(`Expected at least one variant branch`);return t}let l=c(t),u=c(n);if(Object.keys(l).sort().join(`\0`)!==Object.keys(u).sort().join(`\0`))throw Error(`DTO variant tags mismatch`);let d={discriminator:i,options:Object.create(null)},f=[];for(let[t,n]of Object.entries(l)){let r=a(n).fields,{_id:i,_creationTime:o,...c}=r;z(e,r,I(s.object(c))),f.push(s.object(c)),d.options[t]={fields:r,dto:u[t]}}if(L(r)!==L(I(s.union(...f))))throw Error(`Native stored document disagrees with boundary "${e}"`);let p=Object.values(d.options).map(e=>e.fields),m={};for(let e of Object.keys(p[0])){if(!p.every(t=>Object.hasOwn(t,e))||e!==i&&!p.every(t=>P(t[e],p[0][e])))continue;let t=p.map(t=>t[e]),n=s.union(...t);m[e]=t.some(e=>e.isOptional===`optional`)?s.optional(n):n}return{fields:m,branches:d,allFields:new Set(p.flatMap(e=>Object.keys(e)))}}function P(e,t){try{return E(e,t)}catch{return L(I(e))===L(I(t))}}function F(e){return e.export()}function I(e){return e.json}function L(e){if(Array.isArray(e))return`[${e.map(L).join(`,`)}]`;if(e!==null&&Object(e)===e){let t=e;return`{${Object.keys(t).sort().map(e=>`${JSON.stringify(e)}:${L(t[e])}`).join(`,`)}}`}return JSON.stringify(e)}function R(e){if(e===null||Object(e)!==e)return;let t=e;if(t.type===`any`)throw Error(`Unsupported native validation form`);for(let e of Object.values(t))R(e)}function z(e,t,n){let{_id:r,_creationTime:i,...a}=t;if(!r||!i||L(I(r))!==L(I(s.id(e)))||L(I(i))!==L(I(s.number()))||r.isOptional!==`required`||i.isOptional!==`required`||L(n)!==L(I(s.object(a))))throw Error(`Native stored document disagrees with boundary "${e}"`)}const B=o.object({field:o.string()}),V=new Set([B,B.pick({field:!0}),B.omit({field:!0}),B.extend({other:o.string()}),B.safeExtend({other:o.string()}),B.merge(o.object({other:o.string()})),B.partial(),B.required()].flatMap(e=>{let t=Object.getOwnPropertyDescriptor(e._zod.def,`shape`)?.get;return t?[Function.prototype.toString.call(t)]:[]}));function H(e){return G(e,`dto`)}const U=Function.prototype.toString.call(Object.getOwnPropertyDescriptor(o.string().default(``)._zod.def,`defaultValue`).get),W=Function.prototype.toString.call(Object.getOwnPropertyDescriptor(o.string().prefault(``)._zod.def,`defaultValue`).get);function G(e,t){let n=[],r=/* @__PURE__ */ new Set,i=[],a=/* @__PURE__ */ new Set,s=/* @__PURE__ */ new Set,c=[];function l(e,u){if(s.has(e))throw Error(`Unsupported cyclic DTO schema`);if(!a.has(e)){if(u>32||n.length>=4096)throw Error(`DTO schema graph budget exceeded`);a.add(e),s.add(e);try{if(e instanceof RegExp&&i.push({expression:e,source:e.source,flags:e.flags}),e instanceof o.core.$ZodCheck&&`check`in e._zod.def){if(t===`dto`&&e._zod.def.check===`overwrite`)throw Error(`Unsupported DTO overwrite check`);l(e._zod.def,u+1),n.push({object:e._zod,exactKeys:!1,keys:[`def`,`check`],values:[`def`,`check`].map(t=>Object.getOwnPropertyDescriptor(e._zod,t))});return}if(e instanceof o.core.$ZodType){let i=e._zod.def;if(t===`dto`&&(![`object`,`array`,`optional`,`nullable`,`nonoptional`,`union`,`intersection`,`tuple`,`record`,`string`,`number`,`boolean`,`bigint`,`null`,`never`,`literal`,`enum`].includes(i.type)||`coerce`in i&&i.coerce))throw Error(`Unsupported DTO schema "${i.type}"`);if(t===`stored`&&(i.type==="default"||i.type===`prefault`)){let e=Object.getOwnPropertyDescriptor(i,`defaultValue`);if(e?.get){if(e.set||Function.prototype.toString.call(e.get)!==(i.type==="default"?U:W))throw Error(`Unsupported stored schema accessor`);r.add(i)}}if(e instanceof o.ZodUnion&&(l(e.options,u+1),n.push({object:e,exactKeys:!1,keys:[`options`],values:[Object.getOwnPropertyDescriptor(e,`options`)]})),i.type===`object`){let t=Object.getOwnPropertyDescriptor(i,`shape`);if(t?.get){if(t.set||!V.has(Function.prototype.toString.call(t.get)))throw Error(`Unsupported DTO schema accessor`);let e=i.shape;l(e,u+1),Object.getOwnPropertyDescriptor(i,`shape`)?.get&&c.push({definition:i,fields:e})}if(e instanceof o.ZodObject){let t=Object.getOwnPropertyDescriptor(e,`shape`);if(t&&!(`value`in t))throw Error(`Unsupported DTO schema accessor`);l(e.shape,u+1)}}l(i,u+1),n.push({object:e._zod,exactKeys:!1,keys:[`def`],values:[Object.getOwnPropertyDescriptor(e._zod,`def`)]});return}let a=Reflect.ownKeys(e),s=a.map(t=>Object.getOwnPropertyDescriptor(e,t));if(s.some((t,n)=>!(`value`in t)&&!c.some(({definition:t})=>t===e&&a[n]===`shape`)&&!(r.has(e)&&a[n]===`defaultValue`)))throw Error(`Unsupported DTO schema accessor`);n.push({object:e,exactKeys:!0,keys:a,values:s});for(let e of s)e.value!==null&&Object(e.value)===e.value&&!(e.value instanceof Function)&&l(e.value,u+1)}finally{s.delete(e)}}}return l(e,0),()=>{for(let e of i)if(e.expression.source!==e.source||e.expression.flags!==e.flags)throw Error(`DTO schema mutated after registry construction`);for(let e of n){let t=e.keys;if(e.exactKeys&&Reflect.ownKeys(e.object).length!==t.length)throw Error(`DTO schema mutated after registry construction`);for(let n=0;n<t.length;n++){if(e.object instanceof RegExp&&t[n]===`lastIndex`)continue;let r=Object.getOwnPropertyDescriptor(e.object,t[n]),i=e.values[n];if(!r||r.value!==i.value||r.get!==i.get||r.set!==i.set||r.enumerable!==i.enumerable)throw Error(`DTO schema mutated after registry construction`)}}for(let{definition:e,fields:t}of c){let n=e.shape,r=Reflect.ownKeys(t);if(Reflect.ownKeys(n).length!==r.length||r.some(e=>Object.getOwnPropertyDescriptor(n,e)?.value!==Object.getOwnPropertyDescriptor(t,e)?.value))throw Error(`DTO schema mutated after registry construction`)}}}function K(e){for(let t of Object.values(e.metadata))t.assertUnchanged()}const q=o.core.$constructor(`GuardedDtoObject`,(e,t)=>{let n=t;o.ZodObject.init(e,t),e._zod.deferred??=[],e._zod.deferred.push(()=>{let t=e._zod.run;e._zod.run=(e,r)=>{try{n.assertUnchanged()}catch{return e.issues.push({code:`custom`,input:e.value,message:`DTO schema mutated after registry construction`}),e}return t(e,r)}})});function J(e,t){let n=e.shape,r={...e._zod.def,assertUnchanged:t};return Object.defineProperty(r,"shape",{enumerable:!0,configurable:!0,get:()=>(t(),n)}),new q(r)}const Y=o.core.$constructor(`GuardedDtoUnion`,(e,t)=>{let n=t;o.ZodDiscriminatedUnion.init(e,t),e._zod.deferred??=[],e._zod.deferred.push(()=>{let t=e._zod.run;e._zod.run=(e,r)=>{try{n.assertUnchanged()}catch{return e.issues.push({code:`custom`,input:e.value,message:`DTO schema mutated after registry construction`}),e}return t(e,r)}})});function X(e,t){let n=e.options,r={...e._zod.def,assertUnchanged:t};return Object.defineProperty(r,"options",{enumerable:!0,configurable:!0,get:()=>(t(),n)}),new Y(r)}function Z(e){let t={};for(let[n,r]of Object.entries(e.metadata)){let e={};for(let[t,n]of Object.entries(r.fields))e[t]=Object.freeze({kind:n.kind,optional:n.isOptional===`optional`,nullable:Q(n),idTables:Object.freeze($(n)),native:ee(I(n))});t[n]=Object.freeze({fields:Object.freeze(e),variant:r.branches?Object.freeze({discriminator:r.branches.discriminator,tags:Object.freeze(Object.keys(r.branches.options))}):void 0,indexes:Object.freeze(r.indexes.map(e=>Object.freeze({name:e.name,fields:Object.freeze([...e.fields])})))})}return Object.freeze({tables:Object.freeze(t),declarations:e.declarations})}function Q(e){return e.kind===`null`||e.kind===`union`&&e.members.some(Q)}function $(e){return e.kind===`id`?[e.tableName]:e.kind===`union`?[...new Set(e.members.flatMap($))].sort():[]}function ee(e){let t=structuredClone(e),n=[t];for(;n.length;){let e=n.pop();if(Object(e)!==e)continue;let t=e;Object.freeze(t),n.push(...Object.values(t))}return t}export{_ as defineRelations,v as getRelationExecutor,y as getRelationMetadata};
1
+ import{nativePagination as e,relationFilterSchema as t,scalarPredicateSchema as n}from"./querying/filters.mjs";import{paginated as r}from"./zod-table.mjs";import{captureDto as i,materializeDto as a}from"./querying/schema-snapshot.mjs";import{convexToZod as o,zodToConvex as s}from"convex-helpers/server/zod4";import{defineSchema as c,defineTable as l}from"convex/server";import{z as u}from"zod";import{v as d}from"convex/values";const f=i(e),p=Symbol(`relationField`),m=Symbol(`relationEdge`),h=/* @__PURE__ */ new WeakMap,g=/* @__PURE__ */ new WeakMap,_=/* @__PURE__ */ new WeakMap,v=/* @__PURE__ */ new WeakMap,y=/* @__PURE__ */ new WeakSet,b=/* @__PURE__ */ new WeakSet,x=u.object({indexes:u.array(u.object({indexDescriptor:u.string(),fields:u.array(u.string())}))});function S(e,n){let o={},m={},S=/* @__PURE__ */ new Set,C=/* @__PURE__ */ new Map,w={},T={},k={};for(let[t,n]of Object.entries(e)){if(n.tableName!==t||[`one`,`many`,`__proto__`,`constructor`,`prototype`].includes(t))throw Error(`Invalid relation table "${t}"`);let e=Object.getOwnPropertyDescriptor(n,`table`);if(!e||!(`value`in e))throw Error(`Unsupported native table accessor`);let r=e.value;ee(r),X(n.schema,`stored`),X(n.publicDto,`dto`);let c=n.dto(!0);if(!(c instanceof u.ZodObject)&&!(c instanceof u.ZodDiscriminatedUnion))throw Error(`Expected object or discriminated union DTO`);X(c,`dto`);let l=i(c),f=a(l);if(!(f instanceof u.ZodObject)&&!(f instanceof u.ZodDiscriminatedUnion))throw Error(`Expected object or discriminated union DTO`);let h=V(r);W(h.documentType);let g=R(t,n.schema,f,h.documentType),b=x.parse(h).indexes.map(e=>({name:e.indexDescriptor,fields:[...e.fields]})).sort((e,t)=>e.name.localeCompare(t.name));W(H(s(f))),m[t]=r,o[t]={...g,indexes:b,dto:f,dtoRecipe:l};let E=(e,n)=>{let r=Object.create(null);function i(e,r,a){let s={[p]:void 0,table:t,field:e,guard:n,forTable(t){if(n)throw Error(`forTable on branch-scoped fields is unsupported`);if(!A(r)?.includes(t))throw Error(`Invalid native ID member selection`);if(!Object.hasOwn(o,t))throw Error(`Native ID member table is not registered`);let a=Q(r)?d.union(d.id(t),d.null()):d.id(t);return i(e,r.isOptional===`optional`?d.optional(a):a,Object.freeze({table:t}))},through(e){if(a||v.has(e))throw Error(`forTable with through is unsupported`);let t=_.get(e);if(!S.has(e)||!t||!j(r,t))throw Error(`Invalid junction field or registry`);let n=Object.freeze({base:s,junction:e});return y.add(n),n}};return _.set(s,r),a&&v.set(s,a),S.add(s),Object.freeze(s)}for(let[t,n]of Object.entries(e))r[t]=i(t,n);return Object.freeze(r)};if(w[t]=E(g.fields),g.branches)for(let[e,n]of Object.entries(g.branches.options))C.set(JSON.stringify([t,e]),E(n.fields,Object.freeze({discriminator:g.branches.discriminator,tag:e})));T[t]=e=>O(t,`one`,e,S),k[t]=e=>O(t,`many`,e,S)}let M=n(Object.freeze({...w,one:Object.freeze(T),many:Object.freeze(k)}),((e,t)=>{let n=C.get(JSON.stringify([e,t]));if(!n)throw Error(`Unknown variant scope "${e}.${t}"`);return n})),P=Object.fromEntries(Object.entries(M).map(([e,t])=>[e,Object.freeze({...t})]));Object.freeze(P);for(let[e,t]of Object.entries(P)){if(!Object.hasOwn(o,e))throw Error(`Unknown source table "${e}"`);for(let[n,r]of Object.entries(t)){if(o[e].allFields.has(n)||o[e].branches&&[`variant`,`variants`].includes(n)||[`and`,`or`,`not`,`fields`,`then`,`__proto__`,`constructor`,`prototype`].includes(n))throw Error(`Relation name collision "${n}"`);if(!b.has(r)||!S.has(D(r.from))||!S.has(D(r.to))||r.source!==e)throw Error(`Relation source bucket mismatch`);N(r,o)}}let z={metadata:o,declarations:P},B={};for(let e of Object.keys(o))B[e]={paginationOpts(n){return E(n),a(f).extend({filters:t(I(z,e,n)).optional(),order:u.enum([`asc`,`desc`]).optional()})},pageDto(t){return E(t),r(L(z,e,t)).result}};let G=JSON.stringify([2,Object.entries(o).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t.fields).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.isOptional,H(t)]),t.branches?[t.branches.discriminator,Object.entries(t.branches.options).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t.fields).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.isOptional,H(t)])])]:null,t.indexes,U(H(s(t.dto)))]),Object.entries(P).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,Object.entries(t).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>[e,t.cardinality,t.target,F(t.from),F(t.to)])])]),K=Object.freeze({identity:G,version:1,tables:Object.freeze(B)});h.set(K,Z(z));let q={};for(let[e,t]of Object.entries(o)){let n=l({});for(let e of t.indexes){let[t,...r]=e.fields;if(t===void 0)throw Error(`Invalid empty active index`);n.index(e.name,[t,...r])}let r=Object.getOwnPropertyDescriptor(n,`indexes`).value;for(let e of r)Object.freeze(e.fields),Object.freeze(e);Object.freeze(r),Object.freeze(n),q[e]=n}return g.set(K,{internal:z,nativeTables:Object.freeze(m),streamSchema:c(Object.freeze(q))}),K}function C(e){let r=g.get(e);if(!r)throw Error(`Unknown relation registry`);let i=e=>{let t=Object.keys(r.nativeTables);if(t.length!==Reflect.ownKeys(e).length||t.some(t=>{let n=Object.getOwnPropertyDescriptor(e,t);return!n||!(`value`in n)||n.value!==r.nativeTables[t]}))throw Error(`Native schema/table ownership disagrees with relation registry`)},s=/* @__PURE__ */ new WeakMap,c=/* @__PURE__ */ new WeakMap,l=/* @__PURE__ */ new Map,p=/* @__PURE__ */ new Map,m=/* @__PURE__ */ new WeakMap;function h(e,t){let n=r.internal.metadata[e];if(!n)throw Error(`Unknown query table`);if(!n.branches)return;let i=t[n.branches.discriminator],a=typeof i==`string`&&Object.hasOwn(n.branches.options,i)?n.branches.options[i]:void 0;if(!a)throw Error(`Invalid variant document`);let c=s.get(a),l=c?.fieldKeys??Object.keys(a.fields),u=[];for(let e of l)Object.hasOwn(t,e)&&u.push([e,void 0]);for(let e of u)e[1]=t[e[0]];let f=Object.fromEntries(u);c||(c={validator:o(d.object(a.fields)),fieldKeys:l},s.set(a,c)),c.validator.parse(f)}return Object.freeze({streamSchema:r.streamSchema,validateDocument:h,assertSchema:i,pagination(e){let i=r.internal;function o(e,t,r){let a=JSON.stringify([e,t,r??null]),s=p.get(a);if(s)return s;let c=i.metadata[e];if(!c)throw Error(`Unknown query table`);let u=JSON.stringify([e,r??null]),d=l.get(u);if(!d){d={};for(let[e,t]of Object.entries(r===void 0?c.fields:c.branches.options[r].fields))T(t)&&(d[e]=n(t).optional());l.set(u,d)}let f={fields:d,variants:c.branches&&r===void 0&&t<4?{discriminator:c.branches.discriminator,options:Object.fromEntries(Object.keys(c.branches.options).map(n=>[n,o(e,t+1,n)]))}:void 0,relations:t>=4?{}:Object.fromEntries(Object.entries(i.declarations[e]??{}).map(([e,n])=>[e,{cardinality:n.cardinality,target:o(n.target,t+1)}]))};return p.set(a,f),f}return a(f).extend({filters:t(o(e,0),m).optional(),order:u.enum([`asc`,`desc`]).optional()})},select(e,t){E(t);function n(e,t,i){if(!Object.hasOwn(r.internal.metadata,e))throw Error(`Unknown query table`);for(let[a,o]of Object.entries(t)){let t=r.internal.declarations[e]?.[a];if(!t||i>=4)throw Error(`Unknown or too deep relation "${e}.${a}"`);o!==!0&&n(t.target,o,i+1)}}n(e,t,0)},project(e,t,n){if(!n())return null;let i=r.internal.metadata[e];if(!i)throw Error(`Unknown query table`);let a=i.branches?i.branches.options[String(t[i.branches.discriminator])]:void 0;if(i.branches&&!a)throw Error(`Invalid variant document`);let o=a?.dto??i.dto;if(!(o instanceof u.ZodObject))throw Error(`Invalid variant DTO`);h(e,t);let s=c.get(o);return s||(s=Object.keys(o.shape),c.set(o,s)),o.parse(Object.fromEntries(s.filter(e=>Object.hasOwn(t,e)).map(e=>[e,t[e]])))}})}function w(e){let t=h.get(e);if(!t)throw Error(`Unknown relation registry`);return t}function T(e){return[`id`,`string`,`float64`,`int64`,`boolean`,`null`,`literal`].includes(e.kind)||e.kind===`union`&&e.members.every(T)}function E(e){let t=[{value:e,depth:0,ancestors:[]}],n=0;for(;t.length;){let{value:e,depth:r,ancestors:i}=t.pop();if(++n>256||r>4||i.includes(e))throw Error(`Selection cycle or depth/node budget exceeded`);let a=Object.getPrototypeOf(e);if(a!==Object.prototype&&a!==null)throw Error(`Invalid selection`);let o=Reflect.ownKeys(e);if(o.length+n+t.length>256)throw Error(`Selection node budget exceeded`);for(let a of o){let o=Object.getOwnPropertyDescriptor(e,a);if(!o.enumerable||!(`value`in o)||String(a)!==a)throw Error(`Invalid selection property`);if(o.value!==!0)t.push({value:o.value,depth:r+1,ancestors:[...i,e]});else if(++n>256)throw Error(`Selection node budget exceeded`)}}}function D(e){return`base`in e?e.base:e}function O(e,t,n,r){for(let e of[n.from,n.to])if(!r.has(D(e))||`base`in e&&(!y.has(e)||!r.has(e.junction)))throw Error(`Foreign registry or invalid field reference`);if(D(n.to).table!==e)throw Error(`Wrong relation target table`);let i=Object.freeze({[m]:!0,source:D(n.from).table,target:e,cardinality:t,from:n.from,to:n.to,sourceGuard:D(n.from).guard,targetGuard:D(n.to).guard,junctionGuard:k(n.from,n.to),sourceMember:v.get(D(n.from)),targetMember:v.get(D(n.to))});return b.add(i),i}function k(e,t){let n=`base`in e?e.junction.guard:void 0,r=`base`in t?t.junction.guard:void 0;if(n&&r&&(n.discriminator!==r.discriminator||n.tag!==r.tag))throw Error(`Contradictory junction scopes`);return n??r}function A(e){if(e.kind===`id`)return[e.tableName];if(e.kind===`null`)return[];if(e.kind!==`union`)return null;let t=e.members.map(A);return t.some(e=>e===null)?null:[...new Set(t.flatMap(e=>e))].sort()}function j(e,t){let n=M(e);return n.length>0&&JSON.stringify(n)===JSON.stringify(M(t))}function M(e){if(e.kind===`union`)return[...new Set(e.members.flatMap(M))].sort();if(e.kind===`null`)return[];if(![`id`,`string`,`float64`,`int64`,`boolean`,`literal`].includes(e.kind))throw Error(`Unsupported relation field kind`);return[JSON.stringify(H(e))]}function N(e,t){let n=e.from,r=e.to;if(`base`in n!=`base`in r)throw Error(`Both relation legs must use through`);if(`base`in n&&`base`in r){if(n.junction.table!==r.junction.table)throw Error(`Different junction tables`);P(t,n.junction.table,n.junction.field,e.junctionGuard),P(t,e.target,r.base.field,e.targetGuard);return}if(!j(_.get(D(n)),_.get(D(r))))throw Error(`Incompatible relation field types`);P(t,e.target,D(r).field,e.targetGuard)}function P(e,t,n,r){if(n!==`_id`&&!e[t].indexes.some(e=>{let t=e.fields.indexOf(n);return t>=0&&e.fields.slice(0,t).every(e=>e===r?.discriminator)}))throw Error(`No active index begins with or has a guarded prefix for "${t}.${n}"`)}function F(e){return`base`in e?[e.base.table,e.base.field,e.base.guard??null,e.junction.table,e.junction.field,e.junction.guard??null]:v.has(e)?[e.table,e.field,e.guard??null,v.get(e)]:[e.table,e.field,e.guard??null]}function I(e,t,r,i=0,a){let o={},s={},c=e.metadata[t],l={};for(let[u,d]of Object.entries(r)){if(u===`variants`&&d!==!0&&c.branches&&a===void 0){if(i>=4)throw Error(`Invalid variant selection`);for(let[n,a]of Object.entries(d)){if(!Object.hasOwn(c.branches.options,n)||a===!0)throw Error(`Unknown variant filter selection`);l[n]=I(e,t,{...Object.fromEntries(Object.entries(r).filter(([e])=>e!==`variants`)),...a},i+1,n)}continue}let f=(a===void 0?c.fields:c.branches.options[a].fields)[u],p=e.declarations[t]?.[u];if(d===!0&&f)o[u]=n(f).optional();else if(d!==!0&&p&&i<4)s[u]={cardinality:p.cardinality,target:I(e,p.target,d,i+1)};else throw Error(`Invalid relation filter selection "${t}.${u}"`)}return{fields:o,relations:s,variants:c.branches&&a===void 0?{discriminator:c.branches.discriminator,options:l}:void 0}}function L(e,t,n,i=0){let o={};for(let[s,c]of Object.entries(n)){let n=e.declarations[t]?.[s];if(!n||i>=4)throw Error(`Unknown or too deep relation "${t}.${s}"`);let l=c===!0?a(e.metadata[n.target].dtoRecipe):L(e,n.target,c,i+1);if(n.targetGuard){if(!(l instanceof u.ZodDiscriminatedUnion))throw Error(`Invalid target scope`);l=l.options.filter(e=>e instanceof u.ZodObject).find(e=>e.shape[n.targetGuard.discriminator]instanceof u.ZodLiteral&&e.shape[n.targetGuard.discriminator].value===n.targetGuard.tag)}o[s]=n.cardinality===`one`?l.nullable():r(l).result}let s=e.metadata[t],c=a(s.dtoRecipe);function l(n,r){let i={...o};for(let n of Object.keys(i)){let a=e.declarations[t][n];a.sourceGuard&&r!==a.sourceGuard.tag&&a.cardinality===`one`&&(i[n]=u.null())}return n.extend(i).strict()}if(s.branches){if(!(c instanceof u.ZodDiscriminatedUnion))throw Error(`Invalid variant DTO`);let e=c.options.map(e=>{if(!(e instanceof u.ZodObject))throw Error(`Invalid variant DTO`);let t=e.shape[s.branches.discriminator];if(!(t instanceof u.ZodLiteral))throw Error(`Invalid variant tag`);return l(e,String(t.value))});return u.discriminatedUnion(s.branches.discriminator,[e[0],...e.slice(1)])}if(!(c instanceof u.ZodObject))throw Error(`Expected object DTO`);return l(c)}function R(e,t,n,r){if(t instanceof u.ZodObject&&n instanceof u.ZodObject){let n=s(t).fields;return G(e,n,r),{fields:n,allFields:new Set(Object.keys(n))}}if(!(t instanceof u.ZodDiscriminatedUnion)||!(n instanceof u.ZodDiscriminatedUnion))throw Error(`Expected matching discriminated union boundaries "${e}"`);let i=t._zod.def.discriminator;if(n._zod.def.discriminator!==i)throw Error(`DTO discriminator mismatch`);function a(e){let t=Object.create(null);for(let n of e.options){if(!(n instanceof u.ZodObject))throw Error(`Variant branches must be objects`);let e=n.shape[i];if(!(e instanceof u.ZodLiteral)||e.values.size!==1)throw Error(`Variant tags must be unique required string literals`);let r=u.string().safeParse(e.value);if(!r.success||Object.hasOwn(t,r.data))throw Error(`Variant tags must be unique required string literals`);t[r.data]=n}if(Object.keys(t).length===0)throw Error(`Expected at least one variant branch`);return t}let o=a(t),c=a(n);if(Object.keys(o).sort().join(`\0`)!==Object.keys(c).sort().join(`\0`))throw Error(`DTO variant tags mismatch`);let l={discriminator:i,options:Object.create(null)},f=[];for(let[t,n]of Object.entries(o)){let r=s(n).fields,{_id:i,_creationTime:a,...o}=r;G(e,r,H(d.object(o))),f.push(d.object(o)),l.options[t]={fields:r,dto:c[t]}}if(U(r)!==U(H(d.union(...f))))throw Error(`Native stored document disagrees with boundary "${e}"`);let p=Object.values(l.options).map(e=>e.fields),m={};for(let e of Object.keys(p[0])){if(!p.every(t=>Object.hasOwn(t,e))||e!==i&&!p.every(t=>z(t[e],p[0][e])))continue;let t=p.map(t=>t[e]),n=d.union(...t);m[e]=t.some(e=>e.isOptional===`optional`)?d.optional(n):n}return{fields:m,branches:l,allFields:new Set(p.flatMap(e=>Object.keys(e)))}}function z(e,t){try{return j(e,t)}catch{return U(H(e))===U(H(t))}}const B=/* @__PURE__ */ new Map;for(let e of[l(d.object({})),d.id(`sample`),d.null(),d.number(),d.int64(),d.commitTs(),d.boolean(),d.string(),d.bytes(),d.any(),d.object({}),d.literal(`sample`),d.array(d.string()),d.record(d.string(),d.string()),d.union(d.string(),d.null())]){let t=Object.getPrototypeOf(e);for(;t&&t!==Object.prototype;)B.has(t)||B.set(t,Object.getOwnPropertyDescriptors(t)),t=Object.getPrototypeOf(t)}function ee(e){let t=/* @__PURE__ */ new Set,n=/* @__PURE__ */ new Set;function r(e,i,a=!1){if(n.has(e))throw Error(`Unsupported cyclic native schema`);if(t.has(e))return;if(i>64||t.size>=8192)throw Error(`Native schema graph budget exceeded`);t.add(e),n.add(e);let o=Object.getPrototypeOf(e),s=o&&B.get(o);if(o!==null&&o!==Object.prototype&&o!==Array.prototype&&!s)throw Error(`Unsupported native schema prototype`);if(Object.getOwnPropertySymbols(e).length)throw Error(`Unsupported native schema symbol`);let c=Object.getOwnPropertyNames(e).map(t=>Object.getOwnPropertyDescriptor(e,t));if(!a&&c.some(e=>!(`value`in e)||e.value instanceof Function))throw Error(`Unsupported native schema accessor or method`);if(s){let e=Object.getOwnPropertyNames(o);if(e.length!==Object.getOwnPropertyNames(s).length||e.some(e=>{let t=Object.getOwnPropertyDescriptor(o,e),n=Object.getOwnPropertyDescriptor(s,e)?.value;return!n||!Object.is(t.value,n.value)||t.get!==n.get||t.set!==n.set}))throw Error(`Unsupported native schema prototype mutation`);r(o,i+1,!0)}if(!a)for(let e of c)e.value!==null&&Object(e.value)===e.value&&r(e.value,i+1);n.delete(e)}r(e,0)}function V(e){return e.export()}function H(e){return e.json}function U(e){if(Array.isArray(e))return`[${e.map(U).join(`,`)}]`;if(e!==null&&Object(e)===e){let t=e;return`{${Object.keys(t).sort().map(e=>`${JSON.stringify(e)}:${U(t[e])}`).join(`,`)}}`}return JSON.stringify(e)}function W(e){if(e===null||Object(e)!==e)return;let t=e;if(t.type===`any`)throw Error(`Unsupported native validation form`);for(let e of Object.values(t))W(e)}function G(e,t,n){let{_id:r,_creationTime:i,...a}=t;if(!r||!i||U(H(r))!==U(H(d.id(e)))||U(H(i))!==U(H(d.number()))||r.isOptional!==`required`||i.isOptional!==`required`||U(n)!==U(H(d.object(a))))throw Error(`Native stored document disagrees with boundary "${e}"`)}const K=u.object({field:u.string()}),q=new Set([K,K.pick({field:!0}),K.omit({field:!0}),K.extend({other:u.string()}),K.safeExtend({other:u.string()}),K.merge(u.object({other:u.string()})),K.partial(),K.required()].flatMap(e=>{let t=Object.getOwnPropertyDescriptor(e._zod.def,`shape`)?.get;return t?[Function.prototype.toString.call(t)]:[]})),J=Function.prototype.toString.call(Object.getOwnPropertyDescriptor(u.string().default(``)._zod.def,`defaultValue`).get),Y=Function.prototype.toString.call(Object.getOwnPropertyDescriptor(u.string().prefault(``)._zod.def,`defaultValue`).get);function X(e,t){let n=/* @__PURE__ */ new Set,r=/* @__PURE__ */ new Set,i=/* @__PURE__ */ new Set,a=/* @__PURE__ */ new Set;function o(e,s){if(i.has(e))throw Error(`Unsupported cyclic DTO schema`);if(!r.has(e)){if(s>32||r.size>=4096)throw Error(`DTO schema graph budget exceeded`);r.add(e),i.add(e);try{let r=Object.getOwnPropertyDescriptor(e,`_zod`);if(r){if(!(`value`in r))throw Error(`Unsupported DTO schema accessor`);let e=Object.getOwnPropertyDescriptor(r.value,`def`);if(!e||!(`value`in e))throw Error(`Unsupported DTO schema accessor`)}if(e instanceof u.core.$ZodCheck&&!(e instanceof u.core.$ZodType)){if(t===`dto`&&e._zod.def.check===`overwrite`)throw Error(`Unsupported DTO overwrite check`);o(e._zod.def,s+1);return}if(e instanceof u.core.$ZodType){let r=e._zod.def;if(t===`dto`&&(![`object`,`array`,`optional`,`nullable`,`nonoptional`,`union`,`intersection`,`tuple`,`record`,`string`,`number`,`boolean`,`bigint`,`null`,`never`,`custom`,`literal`,`enum`].includes(r.type)||`coerce`in r&&r.coerce))throw Error(`Unsupported DTO schema "${r.type}"`);if(t===`stored`&&(r.type==="default"||r.type===`prefault`)){let e=Object.getOwnPropertyDescriptor(r,`defaultValue`);if(e?.get){if(e.set||Function.prototype.toString.call(e.get)!==(r.type==="default"?J:Y))throw Error(`Unsupported stored schema accessor`);n.add(r)}}if(e instanceof u.ZodUnion&&o(e.options,s+1),r.type===`object`){let t=Object.getOwnPropertyDescriptor(r,`shape`);if(t?.get){if(t.set||!q.has(Function.prototype.toString.call(t.get)))throw Error(`Unsupported DTO schema accessor`);let e=r.shape;o(e,s+1),a.add(r)}if(e instanceof u.ZodObject){let t=Object.getOwnPropertyDescriptor(e,`shape`);if(t&&!(`value`in t))throw Error(`Unsupported DTO schema accessor`);o(e.shape,s+1)}}o(r,s+1);return}let i=Reflect.ownKeys(e),c=i.map(t=>Object.getOwnPropertyDescriptor(e,t));if(c.some((t,r)=>!(`value`in t)&&!(a.has(e)&&i[r]===`shape`)&&!(n.has(e)&&i[r]===`defaultValue`)))throw Error(`Unsupported DTO schema accessor`);for(let e of c)e.value!==null&&Object(e.value)===e.value&&!(e.value instanceof Function)&&o(e.value,s+1)}finally{i.delete(e)}}}o(e,0)}function Z(e){let t={};for(let[n,r]of Object.entries(e.metadata)){let e={};for(let[t,n]of Object.entries(r.fields))e[t]=Object.freeze({kind:n.kind,optional:n.isOptional===`optional`,nullable:Q(n),idTables:Object.freeze($(n)),native:te(H(n))});t[n]=Object.freeze({fields:Object.freeze(e),variant:r.branches?Object.freeze({discriminator:r.branches.discriminator,tags:Object.freeze(Object.keys(r.branches.options))}):void 0,indexes:Object.freeze(r.indexes.map(e=>Object.freeze({name:e.name,fields:Object.freeze([...e.fields])})))})}return Object.freeze({tables:Object.freeze(t),declarations:e.declarations})}function Q(e){return e.kind===`null`||e.kind===`union`&&e.members.some(Q)}function $(e){return e.kind===`id`?[e.tableName]:e.kind===`union`?[...new Set(e.members.flatMap($))].sort():[]}function te(e){let t=structuredClone(e),n=[t];for(;n.length;){let e=n.pop();if(Object(e)!==e)continue;let t=e;Object.freeze(t),n.push(...Object.values(t))}return t}export{S as defineRelations,C as getRelationExecutor,w as getRelationMetadata};
2
2
  //# sourceMappingURL=relations.mjs.map