gemi 0.52.0 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-a0sy9f9x.js → chunk-07jtzbf0.js} +1 -1
- package/dist/{chunk-jdfe4dmh.js → chunk-1pqfmw5h.js} +2 -2
- package/dist/{chunk-jdfe4dmh.js.map → chunk-1pqfmw5h.js.map} +1 -1
- package/dist/chunk-3d3nmr5g.js +4 -0
- package/dist/{chunk-qj4mmner.js.map → chunk-3d3nmr5g.js.map} +2 -2
- package/dist/{chunk-et0j6jx8.js → chunk-7s1g3v1y.js} +3 -3
- package/dist/{chunk-et0j6jx8.js.map → chunk-7s1g3v1y.js.map} +1 -1
- package/dist/chunk-92793zh4.js +5 -0
- package/dist/{chunk-0tbwn6er.js.map → chunk-92793zh4.js.map} +3 -4
- package/dist/chunk-9279y4af.js +5 -0
- package/dist/{chunk-f29vd5mc.js.map → chunk-9279y4af.js.map} +2 -2
- package/dist/chunk-bq4w14a6.js +5 -0
- package/dist/chunk-bq4w14a6.js.map +10 -0
- package/dist/{chunk-4t6a82fh.js → chunk-cg53h5ht.js} +2 -2
- package/dist/{chunk-4t6a82fh.js.map → chunk-cg53h5ht.js.map} +1 -1
- package/dist/{chunk-km6x37ws.js → chunk-ear03axe.js} +24 -24
- package/dist/{chunk-km6x37ws.js.map → chunk-ear03axe.js.map} +3 -5
- package/dist/{chunk-38ma6gg3.js → chunk-fbp5vapa.js} +2 -2
- package/dist/{chunk-38ma6gg3.js.map → chunk-fbp5vapa.js.map} +2 -2
- package/dist/chunk-ffre1z8s.js +6 -0
- package/dist/{chunk-hbycemy5.js.map → chunk-ffre1z8s.js.map} +2 -2
- package/dist/{chunk-53e48ce8.js → chunk-qjnv2rkh.js} +2 -2
- package/dist/{chunk-53e48ce8.js.map → chunk-qjnv2rkh.js.map} +1 -1
- package/dist/{chunk-1ce7veh9.js → chunk-tkv6cw94.js} +3 -3
- package/dist/{chunk-1ce7veh9.js.map → chunk-tkv6cw94.js.map} +1 -1
- package/dist/chunk-y4djde42.js +5 -0
- package/dist/chunk-y4djde42.js.map +11 -0
- package/dist/chunks/ThemeProvider-CTX9LOFC.js +2718 -0
- package/dist/chunks/ThemeProvider-CTX9LOFC.js.map +1 -0
- package/dist/client/Mutation.d.ts +1 -1
- package/dist/client/Mutation.d.ts.map +1 -1
- package/dist/client/ThemeProvider.d.ts +7 -0
- package/dist/client/ThemeProvider.d.ts.map +1 -1
- package/dist/client/index.js +107 -2673
- package/dist/client/index.js.map +1 -1
- package/dist/client/useIsNavigationPending.d.ts.map +1 -1
- package/dist/client/useMutate.d.ts.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/i18n/Dictionary.d.ts.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +3 -3
- package/dist/kernel/index.js +2 -2
- package/dist/kernel/index.js.map +2 -2
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +2 -2
- package/dist/server/index.js +1 -1
- package/dist/services/index.js +2 -2
- package/dist/services/index.js.map +2 -2
- package/dist/testing/Page.d.ts +166 -0
- package/dist/testing/Page.d.ts.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +352 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/utils/Subject.d.ts.map +1 -1
- package/dist/utils/variantKey.d.ts +19 -0
- package/dist/utils/variantKey.d.ts.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-0tbwn6er.js +0 -5
- package/dist/chunk-f29vd5mc.js +0 -5
- package/dist/chunk-hbycemy5.js +0 -6
- package/dist/chunk-qj4mmner.js +0 -4
- /package/dist/{chunk-a0sy9f9x.js.map → chunk-07jtzbf0.js.map} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{
|
|
2
|
+
import{uc as i}from"./chunk-7s1g3v1y.js";import{ae as O,be as E,ce as k}from"./chunk-bq4w14a6.js";import{fe as I,oe as R,pe as l,qe as C,re as M,se as Wz}from"./chunk-cg53h5ht.js";import{Be as d}from"./chunk-92793zh4.js";var Zz=["every","none","some"],$z=["is","isNot"];function h(z){return z==="many"?Zz:$z}function g(z,J){let W=Object.keys(z);return W.length>0&&W.every((Z)=>J.includes(Z))}var m="_count";function N(z,J,W,Z){let X={model:z,operation:J,hasUser:W!=null};return Object.defineProperty(X,"user",{enumerable:!0,get(){if(W==null&&!Z)throw new R(z,J,"no-user");return W}}),X}class a{}class Vz extends a{}var Qz=new Set(["findMany","findFirst","findFirstOrThrow","findUnique","findUniqueOrThrow","count","aggregate","groupBy","update","updateMany","delete","deleteMany"]),qz=new Set(["create","createMany","upsert"]),Yz=new Set(["update","updateMany","upsert"]),jz=new Set(["update","updateMany"]),Lz=new Set(["create","createMany"]),y=new WeakMap;function Kz(z,J,W){if(typeof z!=="function")return z;let Z=y.get(z);if(Z!==void 0)return Z;let X;try{X=new z}catch($){throw new M(b(J),W,"constructor-threw",`${f(z)}, and constructing it threw:
|
|
3
3
|
|
|
4
4
|
${$?.message??String($)}`,H,void 0,{cause:$})}return s(X,J,W),y.set(z,X),X}function S(z,J){return z.map((W,Z)=>Kz(W,J,Z))}var H=["before","scope","onCreate","onUpdate","redact"];var p=new WeakSet;function n(z,J){if(p.has(J))return;for(let W=0;W<J.length;W++)Uz(J[W],z,W);p.add(J)}function Uz(z,J,W){let Z=b(J),X=typeof z;if(z===null||Array.isArray(z)||X!=="object"&&X!=="function")throw new M(Z,W,"not-a-policy",t(z),H);if(X==="function"){if(!Hz(z))throw new M(Z,W,"not-constructable",f(z),H);return}s(z,J,W)}function s(z,J,W){let Z=b(J),X=0,$=[];for(let Y of H){let q=z[Y];if(q===void 0||q===null){if(Y in z)$.push(Y);continue}if(typeof q!=="function")throw new M(Z,W,"hook-not-callable",`'${Y}' that is ${t(q)} rather than a function`,H);X++}if(X>0)return;if($.length>0)throw new M(Z,W,"no-hooks",`It writes ${$.map((Y)=>`'${Y}'`).join(", ")} down and leaves ${$.length===1?"it":"them"} unset, which reads as `+"absent \u2014 so nothing is left to run.",H);let V=Bz(z),Q=Fz(V);throw new M(Z,W,"no-hooks",V.length===0?"It is empty.":`It spells ${Gz(V)}.`+(V.length===1&&V[0]==="default"?" A lone 'default' is a module namespace rather than the policy "+"inside it \u2014 put `entry.default` in the array, or import the "+"policy by name.":""),H,Q)}function Gz(z){let J=z.slice(0,8).map((W)=>`'${W}'`);return z.length>J.length?`${J.join(", ")} and ${z.length-J.length} more`:J.join(", ")}function Hz(z){try{return Reflect.construct(Mz,[],z),!0}catch{return!1}}var Mz=function(){};function Bz(z){let J=new Set,W=z;while(W!==null&&W!==Object.prototype){for(let Z of Object.getOwnPropertyNames(W))if(Z!=="constructor")J.add(Z);W=Object.getPrototypeOf(W)}return[...J]}function Fz(z){let J,W=2;for(let Z of z)for(let X of H){let $=Tz(Z.toLowerCase(),X.toLowerCase());if($<W)W=$,J={key:Z,hook:X}}return J}function Tz(z,J){if(z===J)return 0;let W=Array.from({length:J.length+1},(Z,X)=>X);for(let Z=1;Z<=z.length;Z++){let X=W[0];W[0]=Z;for(let $=1;$<=J.length;$++){let V=W[$];W[$]=Math.min(W[$]+1,W[$-1]+1,X+(z[Z-1]===J[$-1]?0:1)),X=V}}return W[J.length]}function t(z){if(z===null)return"null";if(z===void 0)return"undefined";if(typeof z==="string")return`the string ${JSON.stringify(z)}`;if(typeof z==="function")return f(z);if(Array.isArray(z))return"an array";if(typeof z==="object")return"an object";return`the ${typeof z} ${String(z)}`}function f(z){return z.name?`the function \`${z.name}\``:"an anonymous function"}function _(z){let J,W,Z,X=z;while(X&&X!==Function.prototype){if(Object.hasOwn(X,"$policy"))throw Error(`${X.name??"This model"} declares \`$policy\`, which is now \`$policies\` and takes a list. The old `+"name is not read, so this model is currently unpolicied \u2014 every "+"scope, onCreate and redact on it is being skipped.");if(Object.hasOwn(X,"$policies")&&X.$policies){let $=X.$policies;if($.length>0){let V=X;if(n(V,$),W===void 0&&J===void 0)W=$,Z=V;else J??=S(W,Z),W=void 0,J.unshift(...S($,V))}}X=Object.getPrototypeOf(X)}if(J!==void 0)return J;if(W===void 0)return Iz;return W.some(($)=>typeof $==="function")?S(W,Z):W}function o(z){let J=z;while(J&&J!==Function.prototype){if(Object.hasOwn(J,"$policies")&&J.$policies){let W=J.$policies;if(W.length>0)n(J,W)}J=Object.getPrototypeOf(J)}}function b(z){return z?.name??"This model"}var Iz=Object.freeze([]);function D(z,J,W,Z=[]){if(z.length===0)return W;let X=W,$;for(let V of z)if(V.before){if(V.before(J)===!1)throw new R(J.model,J.operation)}for(let V of z){if(!V.scope)continue;if(Lz.has(J.operation)){Pz(V,J);continue}let Q=V.scope(J);if(Q===void 0||Q===null)continue;if(Sz(J),jz.has(J.operation)&&!V.onUpdate){let Y=Cz(Q);if(Y.length>0)($??=[]).push(...Y)}X=Nz(X,Q)}if(qz.has(J.operation)){for(let V of z)if(V.onCreate)X=_z(X,J,V)}if(Yz.has(J.operation)){for(let V of z)if(V.onUpdate)X=Dz(X,J,V)}if($!==void 0)Az($,J,X,Z);return X}function Nz(z,J){let W=z?.where;if(W===void 0||W===null)return{...z,where:J};if(typeof W!=="object"||Array.isArray(W))return{...z,where:{AND:[W,J]}};let Z=W.AND,X=Z===void 0||Z===null?[]:Array.isArray(Z)?Z:[Z];return{...z,where:{...W,AND:[...X,J]}}}function _z(z,J,W){let Z=(X)=>W.onCreate(J,{...X});if(J.operation==="createMany"){let X=z?.data;return{...z,data:Array.isArray(X)?X.map(Z):Z(X)}}if(J.operation==="upsert")return{...z,create:Z(z?.create)};return{...z,data:Z(z?.data)}}function Dz(z,J,W){let Z=J.operation==="upsert"?"update":"data",X=z?.[Z];if(X===void 0||X===null)return z;return{...z,[Z]:W.onUpdate(J,{...X})}}function Az(z,J,W,Z=[]){let X=W?.data;if(typeof X!=="object"||X===null)return;let $=z.filter((V)=>(V in X)&&!Z.includes(V));if($.length===0)return;throw new l(J.model,J.operation,[...new Set($)])}function Cz(z){if(typeof z!=="object"||z===null||Array.isArray(z))return[];let J=[];for(let W of Object.keys(z)){if(W==="AND"||W==="OR"||W==="NOT")continue;J.push(W)}return J}function Pz(z,J){if(z.onCreate)return;throw new I(J.operation,J.model,J.operation,`${J.model} has a policy that scopes reads but no 'onCreate', and ${J.operation} has no where clause for a scope to narrow. As written the policy would confine reads to the caller and let an insert name any value it likes. Add an onCreate that sets the scoped `+"column \u2014 or, if unscoped creates are intended, say so with an onCreate "+"that returns its data unchanged.")}function Sz(z){if(Qz.has(z.operation))return;throw new I(z.operation,z.model,z.operation,`${z.model} has a policy with a scope, and ${z.operation} cannot carry one: its where clause compiles to an 'on conflict' target, which is a key rather than a filter. Running it would write outside the scope.
|
|
5
5
|
|
|
6
6
|
Two ways out. Use update and create separately, which both scope `+"normally \u2014 or leave the conflict key out of 'create', which Model.upsert "+"runs as a scoped read and a scoped write inside one transaction. The refusal is about 'on conflict' specifically, not about upsert.")}function cz(z,J,W){if(z.length===0)return;let Z=z.filter((X)=>X.redact);if(Z.length===0)return;for(let X of Rz(W))for(let $ of Z)$.redact(J,X)}function Rz(z){if(Array.isArray(z))return z;if(z===null||z===void 0)return[];if(typeof z!=="object")return[];return[z]}function dz(z,J,W){for(let Z of W){let X=z.fields[Z];if(X&&!X.nullable)throw new I(`redact.${Z}`,z.name,"redact",`'${Z}' is not nullable, so setting it to null would contradict `+"the generated type \u2014 which still says the field is there. Make the "+"field optional in schema.prisma, omit it with 'select' instead, or delete the key yourself if a runtime-only guarantee is enough.");if(Z in J)J[Z]=null}}function lz(){let z=i();if(z)return z.user;return fz()?.user??null}function fz(){try{return d.getStore()}catch{return}}var r=Symbol("gemi.orm.policiesAppliedByCaller");function iz(z){return{...z,[r]:!0}}function az(z){return typeof z==="object"&&z!==null&&z[r]===!0}var e=Symbol("gemi.orm.columnsWrittenByTheOrm");function nz(z,J){return{...z,[e]:J}}function sz(z){if(typeof z!=="object"||z===null)return u;let J=z[e];return Array.isArray(J)?J:u}var u=[],zz=Symbol("gemi.orm.operationTheRowIsReturnedFor");function tz(z,J){return{...z,[zz]:J}}function oz(z){if(typeof z!=="object"||z===null)return;let J=z[zz];return typeof J==="string"?J:void 0}var A="findMany";function bz(z,J,W,Z,X){if(J===void 0||J===null)return J;if(typeof J!=="object")return J;let $=J;for(let Y of["include","select"]){let q=J[Y];if(typeof q!=="object"||q===null||Array.isArray(q))continue;let j;for(let L of Object.keys(q)){if(L===m){let w=Oz(z,q[L],W,Z,X);if(w!==q[L])j??={...q},j[L]=w;continue}let K=z.relations[L];if(!K)continue;let U=q[L];if(U===void 0||U===!1)continue;let G=X(K.model);if(!G)continue;let F=U===!0?{}:U;if(typeof F!=="object"||Array.isArray(F))continue;let v=bz(G.schema,F,W,Z,X),x=!Z&&G.policies.length>0?D(G.policies,N(G.schema.name,A,W,Z),v):v;if(x!==F)j??={...q},j[L]=x}if(j)$={...$,[Y]:j}}let V=Jz(z,$.orderBy,W,Z,X);if(V!==$.orderBy)$={...$,orderBy:V};let Q=T(z,$.where,W,Z,X);if(Q!==$.where)$={...$,where:Q};return $}function Jz(z,J,W,Z,X){if(Z)return J;if(typeof J!=="object"||J===null)return J;if(Array.isArray(J)){let Q=!1,Y=J.map((q)=>{let j=Jz(z,q,W,Z,X);if(j!==q)Q=!0;return j});return Q?Y:J}let $,V=J;for(let Q of Object.keys(V)){let Y=z.relations[Q];if(!Y)continue;let q=V[Q];if(typeof q!=="object"||q===null||Array.isArray(q))continue;let j=X(Y.model);if(!j||j.policies.length===0)continue;let L=D(j.policies,N(j.schema.name,A,W,Z),q);if(L!==q)$??={...V},$[Q]=L}return $??J}function Oz(z,J,W,Z,X){if(Z)return J;if(typeof J!=="object"||J===null||Array.isArray(J))return J;let $=J.select;if(typeof $!=="object"||$===null||Array.isArray($))return J;let V,Q=$;for(let Y of Object.keys(Q)){let q=Q[Y];if(q===void 0||q===!1)continue;let j=z.relations[Y];if(!j)continue;let L=X(j.model);if(!L||L.policies.length===0)continue;let K=q===!0?{}:q;if(typeof K!=="object"||Array.isArray(K))continue;let U=D(L.policies,N(L.schema.name,A,W,Z),K);if(U!==K)V??={...Q},V[Y]=U}return V?{...J,select:V}:J}function T(z,J,W,Z,X){if(typeof J!=="object"||J===null)return J;if(Array.isArray(J)){let Q=!1,Y=J.map((q)=>{let j=T(z,q,W,Z,X);if(j!==q)Q=!0;return j});return Q?Y:J}let $,V=J;for(let Q of Object.keys(V)){let Y=V[Q];if(Y===void 0)continue;if(Q==="AND"||Q==="OR"||Q==="NOT"){let L=T(z,Y,W,Z,X);if(L!==Y)$??={...V},$[Q]=L;continue}let q=z.relations[Q];if(!q)continue;let j=Ez(q,Y,W,Z,X);if(j!==Y)$??={...V},$[Q]=j}return $??J}function Ez(z,J,W,Z,X){if(typeof J!=="object"||J===null||Array.isArray(J))return J;let $=X(z.model);if(!$)return J;let V=h(z.kind),Q=!g(J,V),Y=Q?[["is",J]]:Object.entries(J),q;for(let[j,L]of Y){if(L===null||L===void 0)continue;let K=T($.schema,L,W,Z,X),U=!Z&&$.policies.length>0?D($.policies,N($.schema.name,A,W,Z),{where:K}).where:K,G=j==="every"?kz(K,U):U;if(G!==L)q??=Q?{}:{...J},q[j]=G}if(!q)return J;return q}function kz(z,J){if(J===z)return z;let W=c(z),X=c(J).slice(W.length);if(X.length===0)return z;return{OR:[{NOT:X.length===1?X[0]:{AND:X}},z]}}function c(z){if(typeof z!=="object"||z===null)return[];let J=z.AND;if(J===void 0)return[];return Array.isArray(J)?J:[J]}function vz(...z){let[J]=xz(...z);if(J!==void 0)throw J}function xz(...z){let J=[];for(let W of z)for(let Z of Object.values(W)){let X=Xz(Z);if(X===null)continue;o(X);let $=X.$schema.name,V=E($)?k($):void 0;if(V===void 0||V===X)continue;let Q=_(X),Y=_(V),q=Q.length!==Y.length||Q.some((j,L)=>j!==Y[L]);if(P(V,X)||P(X,V)){let j=P(X,V)?V:X,L=j===V?X:V;if(_(j).length===0){if(V===L)continue;if(!q)continue;J.push(new C($,B(V),B(X),Q.length>0?"queried":"registered"));continue}if(q)J.push(new C($,B(j),B(L),"narrowing"));continue}if(!q)continue;J.push(new C($,B(V),B(X),Q.length>0?"queried":"registered"))}return J}function WJ(...z){let J=new Map;for(let Z of z){let X=new Map;for(let $ of new Set(Object.values(Z))){let V=Xz($);if(V===null)continue;let Q=V.$schema.name,Y=X.get(Q);if(Y===void 0)X.set(Q,[V]);else Y.push(V)}for(let[$,V]of X)J.set($,wz($,V))}let W=[...J.keys()].filter((Z)=>E(Z)).map((Z)=>[Z,k(Z)]);for(let[Z,X]of J)O(Z,X);try{vz(...z)}catch(Z){for(let[X,$]of W)O(X,$);throw Z}}function wz(z,J){if(J.length===1)return J[0];let W=J.filter(($)=>!hz($)),Z=W.length>0?W:J;if(Z.length===1)return Z[0];let X=Z.filter(($)=>Z.every((V)=>V===$||P(V,$)));if(X.length===1)return X[0];throw new Wz(z,Z.map(($)=>B($)))}function hz(z){if("$generated"in z)return Object.hasOwn(z,"$generated")&&z.$generated===!0;return Object.hasOwn(z,"$schema")}function P(z,J){let W=Object.getPrototypeOf(z);while(W!==null&&W!==Function.prototype){if(W===J)return!0;W=Object.getPrototypeOf(W)}return!1}function B(z){return z?.name??String(z)}function Xz(z){if(typeof z!=="function")return null;let J=z.$schema;if(J===void 0||typeof J.name!=="string")return null;return z}
|
|
7
7
|
export{h as q,g as r,m as s,N as t,a as u,Vz as v,_ as w,D as x,cz as y,dz as z,lz as A,iz as B,az as C,nz as D,sz as E,tz as F,oz as G,A as H,bz as I,vz as J,xz as K,WJ as L};
|
|
8
8
|
|
|
9
|
-
//# debugId=
|
|
9
|
+
//# debugId=6DEDF8CD485C3EB164756E2164756E21
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"import { RequestContext } from \"../http/requestContext\";\nimport { currentActor } from \"./context\";\nimport {\n InvalidPolicyEntryError,\n PolicyDeniedError,\n ScopeEscapeError,\n UnsupportedQueryError,\n} from \"./errors\";\nimport type { Operation } from \"./plan\";\nimport {\n COUNT_KEY,\n isOperatorForm,\n relationFilterOperators,\n} from \"./relation-filters\";\nimport type { ModelSchema } from \"./schema\";\n\n/**\n * Per-model policies: deny an operation, scope its `where`, or redact fields —\n * applied to **every** query, including every nested relation read.\n *\n * The second of the two features that justify the project. Prisma's query\n * extensions do not fire on nested reads, so a scope written for `Account` is\n * bypassed by `User.findMany({ include: { accounts: true } })`. Ours is not,\n * and not because it takes care to cover that case: a relation read *is*\n * `$exec` on the related model's own class (invariant 1), so it goes through\n * the same hook as a root query and there is no second path to keep in step.\n *\n * Two rules the rest of this file exists to enforce:\n *\n * **Args in, args out.** A policy never sees SQL. It receives the plain\n * argument tree and returns a plain argument tree, before compilation. That is\n * what makes a scope a two-line `AND` instead of string surgery, what keeps the\n * relation strategies interchangeable — iteration 7's lateral joins put the\n * scoped `where` inside the subquery with no policy change — and what keeps the\n * plan cache sound.\n *\n * **Policies run before the plan key is computed.** They change the SQL, so a\n * plan keyed on the pre-policy args would let two differently-scoped users\n * share one plan. That is a cross-tenant data leak produced by a caching bug,\n * which is why the ordering is asserted by a test rather than left to the\n * pipeline's shape.\n */\n\nexport interface PolicyContext {\n /**\n * The authenticated user.\n *\n * Read synchronously off the request store — no `await` anywhere on this\n * path, because the hook runs per query *per relation node* and an awaited\n * user would be a round trip per node. A route without the `auth` middleware\n * therefore sees no user even when a cookie is present, which is the correct\n * reading: the route did not ask to authenticate.\n *\n * **Reading this when there is no user raises `PolicyDeniedError`.** That is\n * where deny-by-default actually lives, and it is deliberately here rather\n * than as an up-front check on the model: a policy that never consults the\n * user has nothing to deny. `softDeletes()` scopes on `deletedAt: null` and\n * is a data-integrity rule, not an authorization one — it must keep working\n * in a cron tick, a queue worker and a seed script. An up-front \"this model\n * has a policy, so it needs a user\" check made it unusable outside a request,\n * which was wrong.\n *\n * Raising on *access* rather than returning null is what keeps it safe: a\n * scope built from a null user would be `{ organizationId: undefined }`, and\n * Prisma treats an undefined value as an absent filter — so the scope would\n * silently vanish and the read would be unscoped. The leak, in other words,\n * is the quiet version of this error.\n *\n * Check {@link hasUser} first if a policy genuinely wants to handle both.\n */\n readonly user: unknown;\n /**\n * Whether there is a user to read, for a policy that wants to branch rather\n * than raise — a scope that differs for anonymous access, say.\n */\n readonly hasUser: boolean;\n /** The operation being performed, so a policy can vary by it. */\n readonly operation: Operation;\n /** The model the policy is attached to. */\n readonly model: string;\n}\n\n/**\n * Builds the context a policy sees, with `user` as an accessor that enforces\n * deny-by-default at the moment of use.\n *\n * `system` suppresses the raise, because `Model.asSystem` has already said this\n * code is not acting for anybody — a policy under it reading `user` gets\n * `null` rather than an error, which is what lets a policy written for requests\n * be reused by a script without rewriting it.\n */\nexport function policyContext(\n model: string,\n operation: Operation,\n user: unknown,\n system: boolean,\n): PolicyContext {\n // `!= null` and `== null` below, not `!==` / `===`. `user` is `unknown` and\n // arrives verbatim from `Model.asUser`, so `undefined` is reachable —\n // `asUser(usersById.get(job.userId), ...)` on a miss, which is exactly the\n // \"user failed to turn up\" case deny-by-default exists for. Strict equality\n // let it through: `hasUser` said true and the accessor did not raise, so a\n // scope reading `ctx.user?.organizationId` collapsed to `{}` — an *absent*\n // filter — and returned every tenant's rows. The request path normalises with\n // `?? null` and so never produced it, which is why only `asUser` could.\n const context = { model, operation, hasUser: user != null } as {\n model: string;\n operation: Operation;\n hasUser: boolean;\n user: unknown;\n };\n\n Object.defineProperty(context, \"user\", {\n enumerable: true,\n get() {\n if (user == null && !system) {\n throw new PolicyDeniedError(model, operation, \"no-user\");\n }\n return user;\n },\n });\n\n return context as PolicyContext;\n}\n\n/**\n * What a model contributes. Every member is optional; a model with none is\n * unpolicied and pays a single `undefined` check per query.\n */\nexport interface ModelPolicy<TWhere = any, TCreate = any, TRow = any> {\n /**\n * Runs first, and may throw to deny outright. Return `false` to deny with the\n * framework's own message.\n */\n before?(context: PolicyContext): boolean | void;\n\n /**\n * Rewrites the argument tree. The one thing an extension cannot do.\n *\n * Returns a `where` fragment that is `AND`ed into `args.where` — not a\n * replacement for it, so a caller's own filters always still apply and a\n * policy can only ever *narrow*. Returning `undefined` means no scope.\n */\n scope?(context: PolicyContext): TWhere | undefined;\n\n /**\n * Defaults or validates the payload of a `create`. Separate from `scope`\n * because the read semantics genuinely do not generalise: there is no `where`\n * on an insert, and \"restrict which rows are affected\" has no meaning for one\n * that does not exist yet. Receives and returns plain `data`.\n */\n onCreate?(context: PolicyContext, data: TCreate): TCreate;\n\n /**\n * The same job for an `update`, and the reason it is a separate hook rather\n * than something `scope` covers.\n *\n * A scope narrows *which rows* an update may touch. It says nothing about the\n * values being written — so a tenant-scoped model could only ever update its\n * own rows, and could set `organizationId` on one of them to any tenant it\n * liked. Read-scoped, write-open: the row leaves the caller's scope and cannot\n * be read back, which makes it a one-way door rather than a visible error.\n *\n * That is the same hole `onCreate` exists to close, arriving through `data`\n * instead of through a missing `where`, and `plans/orm/06-policies.md` §5 asked\n * for exactly this — \"define what `scope` means per operation rather than\n * assuming the read semantics generalise\" — for every write. It was answered\n * for `create` and `delete` and left open for `update`.\n *\n * Receives and returns plain `data`. A policy that does not define it is not\n * penalised on ordinary updates; it is only required when an update actually\n * names a column the policy's own scope constrains. See `assertNoScopeEscape`.\n */\n onUpdate?(context: PolicyContext, data: Partial<TCreate>): Partial<TCreate>;\n\n /**\n * Removes fields from a row after it is fetched. Runs in the shaping stage.\n *\n * The one policy capability that deliberately makes gemi's result differ from\n * Prisma's, so the differential harness must compare against the\n * *pre-redaction* payload.\n *\n * `Partial<TRow>` rather than `TRow`, because redaction's whole problem is that\n * it makes the generated type a lie — the type says the field is there and the\n * value is gone. A `redact` also runs over rows shaped by a `select`, where\n * most fields genuinely are absent. `redactNullable` is the guard rail that\n * keeps the lie out of the *caller's* type; this keeps it out of the policy's.\n */\n redact?(context: PolicyContext, row: Partial<TRow>): void;\n}\n\n/**\n * A policy as it may be written in a `$policies` array: the object itself, or a\n * class to be instantiated once.\n *\n * Both forms are accepted because neither dominates. A class gets contextual\n * *return* checking against {@link Policy} and — through {@link ScopedPolicy} —\n * lets `scope`/`onCreate`/`onUpdate` be abstract members, so the pairing this\n * file otherwise enforces at runtime becomes a compile error. An object comes\n * out of a factory, which is the only form that can carry configuration and be\n * reused across models: `softDeletes<User>({ field })` cannot be a bare\n * constructor, because a constructor in an array has nowhere to put arguments\n * or type parameters.\n */\nexport type PolicyEntry<TWhere = any, TCreate = any, TRow = any> =\n | ModelPolicy<TWhere, TCreate, TRow>\n | (new () => ModelPolicy<TWhere, TCreate, TRow>);\n\n/**\n * The optional base class for the class-authoring form.\n *\n * The members are declared through an interface merged with the class rather\n * than in the class body, and that is not a style choice. A class *field*\n * declaration — `scope?: (ctx) => T` — emits `Object.defineProperty(this,\n * \"scope\", { value: undefined })` under `useDefineForClassFields`, which is the\n * default at this target. That own property would shadow the derived class's\n * prototype method and every policy written this way would silently do nothing.\n * Declaration merging gives the instance type the same members and emits no\n * field at all.\n *\n * Extending this is optional in both directions: a plain object satisfies\n * `ModelPolicy` structurally, and an instance of a subclass satisfies it the\n * same way. Nothing in the runtime checks for it.\n *\n * Note what it does *not* buy: TypeScript never contextually types an\n * overriding method's parameters from its base, so `scope(ctx)` in a subclass is\n * an implicit `any`. Write `scope(ctx: PolicyContext)`. What it does buy is the\n * return type being checked against the model's `WhereInput`.\n */\n// Both suppressions are the merge described above, seen from the linter's side.\n//\n// `no-unsafe-declaration-merging` fires because merging a class with an\n// interface lets the interface claim members the constructor never initialises.\n// That is exactly what is wanted here and it is safe for the same reason the\n// generated model bases' merge is: every member is optional, so \"not\n// initialised\" is a value the type already permits. The unsafe version of this\n// pattern declares *required* members.\n//\n// `no-unused-vars` fires because the type parameters appear only on the\n// interface half. Dropping them from the class is not an option — `ScopedPolicy`\n// extends it with the same three — and renaming them to `_TWhere` would put the\n// underscores in every author's hover text.\n// oxlint-disable-next-line typescript-eslint/no-unsafe-declaration-merging, eslint/no-unused-vars\nexport abstract class Policy<TWhere = any, TCreate = any, TRow = any> {}\nexport interface Policy<TWhere = any, TCreate = any, TRow = any>\n extends ModelPolicy<TWhere, TCreate, TRow> {}\n\n/**\n * A policy that scopes, with the write halves made mandatory by the type system.\n *\n * `assertCreateCovered` and `assertNoScopeEscape` enforce this at runtime, and\n * have to: an object literal can always omit a key. Extending this class moves\n * the same rule to compile time for the authors who want it — a missing\n * `onCreate` becomes `TS2515` at the class declaration rather than an error on\n * the first `create` that reaches production.\n */\nexport abstract class ScopedPolicy<\n TWhere = any,\n TCreate = any,\n TRow = any,\n> extends Policy<TWhere, TCreate, TRow> {\n abstract scope(context: PolicyContext): TWhere | undefined;\n abstract onCreate(context: PolicyContext, data: TCreate): TCreate;\n abstract onUpdate(\n context: PolicyContext,\n data: Partial<TCreate>,\n ): Partial<TCreate>;\n}\n\n/** A model class carrying optional policies, as seen from here. */\nexport interface PolicedModel {\n $policies?: readonly PolicyEntry[];\n $schema?: ModelSchema;\n}\n\n/**\n * Which operations have a `where` for `scope` to narrow.\n *\n * `upsert` is deliberately absent: its `where` compiles to an `on conflict`\n * target, which is a key rather than a predicate, and iteration 4 already\n * refuses a `where` carrying anything beside that key. A scoped upsert is\n * therefore not expressible at all, and is refused by name rather than run\n * unscoped — see `assertScopable`.\n *\n * **Every other operation with a `where` has to be in here, and adding one is\n * the step that is easy to forget.** `assertScopable` is written for `upsert`,\n * so an operation missing from this set does not run unscoped — it fails, with\n * `upsert`'s reason about `on conflict` targets, which sends the reader\n * somewhere unrelated. That is the safe direction and a confusing one, and it\n * takes the operation away from exactly the models the ORM's headline\n * capability is for: anything carrying `softDeletes()` has a `scope`.\n */\nconst SCOPABLE = new Set<string>([\n \"findMany\",\n \"findFirst\",\n \"findFirstOrThrow\",\n \"findUnique\",\n \"findUniqueOrThrow\",\n \"count\",\n // Its `where` is an ordinary predicate over the rows being aggregated, so a\n // scope narrows it exactly as it narrows a `count` — which is the same\n // statement with one function in it.\n \"aggregate\",\n // Same reasoning one step further: its `where` filters the rows *before* they\n // are grouped, so a scope narrows which rows any group can contain. Leaving\n // it out would not merely refuse the operation — `assertScopable` raises — so\n // every policied model would lose `groupBy` entirely, which is how `aggregate`\n // was found missing on #74.\n \"groupBy\",\n \"update\",\n \"updateMany\",\n \"delete\",\n \"deleteMany\",\n]);\n\n/** Operations whose `data` an `onCreate` applies to. */\nconst CREATING = new Set<string>([\"create\", \"createMany\", \"upsert\"]);\n\n/**\n * Operations whose payload an `onUpdate` applies to. `upsert` is here and absent\n * from {@link UPDATING} below for the same reason it is in `CREATING`: it has an\n * update payload to default, but a scope can never reach it (see\n * `assertScopable`), so there is nothing for the scope-escape guard to check.\n */\nconst MUTATING = new Set<string>([\"update\", \"updateMany\", \"upsert\"]);\n\n/**\n * Operations that write to existing rows *and* carry a scope, so an update can\n * move a row out of the scope that selected it.\n */\nconst UPDATING = new Set<string>([\"update\", \"updateMany\"]);\n\n/**\n * Operations that write a new row and have no `where` at all, so a `scope`\n * cannot apply to them even in principle. `upsert` is not here: it *has* a\n * where, it just cannot carry a predicate — a different problem with a\n * different message.\n */\nconst INSERTING = new Set<string>([\"create\", \"createMany\"]);\n\n/**\n * Instances made from constructor entries, so identity is stable across calls.\n *\n * Not an optimisation. `$exec`'s divergence guard and `assertPoliciesRegistered`\n * both compare two policy chains element by element, and a fresh instance per\n * call would make every comparison fail — every query on a class-form policy\n * would raise `UnregisteredPolicyClassError` against itself. Keyed on the\n * constructor, which is as stable as the class object.\n *\n * Keyed on the constructor and nothing else, so a policy class listed in two\n * models' `$policies` is **one instance shared across both** — once per process,\n * not once per model. Correct for every policy that exists today, all of which\n * are stateless, and the reason the class form is documented as a place for\n * behaviour rather than for state: a policy that memoised anything per model\n * would silently serve one model's cache to the other. A policy that genuinely\n * needs per-model state should be a factory returning a fresh object, which is\n * what `PolicyEntry`'s other half is for.\n */\nconst instantiated = new WeakMap<object, ModelPolicy>();\n\n/**\n * Turns one `$policies` entry into the object the hooks are read off.\n *\n * Takes the declaring class's name and the entry's index so that **everything\n * construction can go wrong with is named**. `assertPolicyEntries` has already\n * proved a function entry constructable, which is a fact about `[[Construct]]`\n * and says nothing about the body: a class whose constructor takes a required\n * argument is perfectly constructable and dies inside `new` with\n * `TypeError: undefined is not an object (evaluating 'opts.field')`. That is\n * #321's case A3, it is the shape the issue's own `not-constructable` advice was\n * written for, and it reaches here rather than the check — so the `try` is not\n * defensive, it is the third of the three cases.\n *\n * The hook check for the class form is here too, and can only be here: a policy\n * class keeps its hooks on a prototype, or assigns them in the constructor, so\n * there is nothing to read until an instance exists.\n */\nfunction resolveEntry(\n entry: PolicyEntry,\n owner: unknown,\n index: number,\n): ModelPolicy {\n if (typeof entry !== \"function\") return entry;\n\n const existing = instantiated.get(entry);\n if (existing !== undefined) return existing;\n\n let made: ModelPolicy;\n try {\n made = new (entry as new () => ModelPolicy)();\n } catch (cause) {\n throw new InvalidPolicyEntryError(\n nameOfOwner(owner),\n index,\n \"constructor-threw\",\n `${describeFunction(entry)}, and constructing it threw:\\n\\n ` +\n `${(cause as Error)?.message ?? String(cause)}`,\n RECOGNISED_HOOKS,\n undefined,\n { cause },\n );\n }\n\n assertHasCallableHook(made as Record<string, unknown>, owner, index);\n\n instantiated.set(entry, made);\n return made;\n}\n\n/** One level's entries resolved, each knowing where it was written. */\nfunction resolveLevel(\n entries: readonly PolicyEntry[],\n owner: unknown,\n): ModelPolicy[] {\n return entries.map((entry, index) => resolveEntry(entry, owner, index));\n}\n\n/**\n * The hooks the runtime actually dispatches on, in the order it consults them.\n *\n * `applyPolicies` reads the first four and `applyRedaction` the fifth. An entry\n * that spells none of them contributes nothing to any query, which is the whole\n * of case B in #321 — so this list is the definition of \"a policy that would\n * run\", and it has to stay the same list.\n *\n * **Adding a hook to {@link ModelPolicy} without adding it here is a compile\n * error**, by the assertion below. That direction is the dangerous one: a new\n * hook missing from this list would make an entry carrying only that hook look\n * like a typo and be refused at boot — a working policy rejected — which is\n * exactly the over-strictness this guard must not produce. The other direction\n * is checked too, so a name removed from `ModelPolicy` cannot linger here and go\n * on being accepted.\n *\n * **The pin is over `ModelPolicy`'s *callable* members, not over `keyof`**, and\n * that distinction is load-bearing rather than fussy. Entries in this list are\n * required to be functions — `hook-not-callable` refuses anything else — so a\n * `keyof` pin would force a future non-function member (`priority?: number`,\n * `appliesTo?: string[]`) into the list to satisfy the compiler, and every entry\n * that then set it would be refused at boot. A data member simply is not a hook:\n * it is left out, it is not required to be callable, and it does not on its own\n * make an entry one that would run.\n */\nconst RECOGNISED_HOOKS = [\n \"before\",\n \"scope\",\n \"onCreate\",\n \"onUpdate\",\n \"redact\",\n] as const;\n\n/** The members of `T` whose value, when present, is callable. */\ntype CallableKeys<T> = {\n [K in keyof T]-?: NonNullable<T[K]> extends (...args: never[]) => unknown\n ? K\n : never;\n}[keyof T];\n\ntype _MissingHook = Exclude<\n CallableKeys<ModelPolicy>,\n (typeof RECOGNISED_HOOKS)[number]\n>;\ntype _ExtraHook = Exclude<\n (typeof RECOGNISED_HOOKS)[number],\n CallableKeys<ModelPolicy>\n>;\n\n// Assigning `true` is what fails: either branch resolves to a string literal\n// type when the two lists disagree, and the message is the diagnostic.\nconst _hooksExhaustive: [_MissingHook] extends [never]\n ? [_ExtraHook] extends [never]\n ? true\n : \"RECOGNISED_HOOKS names something ModelPolicy does not declare as a callable member\"\n : \"ModelPolicy declares a callable member RECOGNISED_HOOKS does not list — an entry carrying only that hook would be refused at boot\" =\n true;\nvoid _hooksExhaustive;\n\n/**\n * Entry arrays already checked, so the guard costs one lookup per contributing\n * level per call rather than a walk of every entry.\n *\n * Keyed on the **array** and not on the entries, because that is the granularity\n * the hot path already has: `policiesFor` runs per query per node of an include\n * tree, and `$policies` is an ordinary static that a test or a feature flag\n * reassigns — a reassignment produces a new array, which is unchecked and gets\n * checked. Mutating an array in place after it has been read once is the one\n * thing this does not re-examine, and it is not a shape anything writes.\n */\nconst checkedEntries = new WeakSet<readonly PolicyEntry[]>();\n\n/**\n * Refuses a `$policies` entry that could not do what it was written to do,\n * naming the class, the index, and what was found there.\n *\n * Called from `policiesFor` once per contributing level, with `owner` being the\n * class that **declares** the array rather than the model being queried — so the\n * name in the message is the one the author typed the entry under, which on a\n * shared base is not the model whose query happened to reach it.\n *\n * One placement, and it is `policiesFor` rather than the audit the issue\n * proposed, because `policiesFor` is what every path already goes through:\n * `registerModels` at boot and `gemi check models` reach it through\n * `auditModelRegistrations`, and `Model.$exec` reaches it directly on a class\n * neither of those ever saw. Putting the check in the audit alone would leave\n * the crash live on the query path and leave the naming problem unsolved, since\n * the audit knows the model but not which level of the chain declared the array.\n */\nfunction assertPolicyEntries(\n owner: unknown,\n entries: readonly PolicyEntry[],\n): void {\n if (checkedEntries.has(entries)) return;\n\n for (let index = 0; index < entries.length; index++) {\n assertPolicyEntry(entries[index] as PolicyEntry, owner, index);\n }\n\n checkedEntries.add(entries);\n}\n\n/**\n * What can be known about an entry **without constructing it**.\n *\n * The split matters, and it is the reviewer's question answered rather than a\n * layering preference: this half runs at boot over every model class an\n * application declares, and constructing a policy class there would move\n * whatever its constructor touches — a config slice, an environment variable, a\n * service container — from first-query time to `registerModels` time. A class\n * that was fine because it was built lazily would take the app's boot with it,\n * and the entry it was refusing might have been perfectly good.\n *\n * So: an object entry is fully checkable here (case B is an object entry in both\n * of the shapes #321 reports), a function entry is checked for `[[Construct]]`\n * and nothing more, and the class form's hooks are checked in `resolveEntry`\n * where an instance exists because one was needed anyway.\n */\nfunction assertPolicyEntry(\n entry: PolicyEntry,\n owner: unknown,\n index: number,\n): void {\n const model = nameOfOwner(owner);\n const kind = typeof entry;\n\n // Arrays are refused here rather than falling through as objects. A nested\n // array is a plausible slip — `$policies = [[a, b]]` — and reading one as a\n // policy produced a message listing `length`, `concat`, `pop` and the rest of\n // `Array.prototype` as the keys it \"spells\".\n if (\n entry === null ||\n Array.isArray(entry) ||\n (kind !== \"object\" && kind !== \"function\")\n ) {\n throw new InvalidPolicyEntryError(\n model,\n index,\n \"not-a-policy\",\n describeValue(entry),\n RECOGNISED_HOOKS,\n );\n }\n\n if (kind === \"function\") {\n if (!isConstructable(entry as Function)) {\n throw new InvalidPolicyEntryError(\n model,\n index,\n \"not-constructable\",\n describeFunction(entry as Function),\n RECOGNISED_HOOKS,\n );\n }\n\n // Everything else about a class is a property of its instance.\n return;\n }\n\n assertHasCallableHook(entry as Record<string, unknown>, owner, index);\n}\n\n/**\n * The hook check itself, over a policy that already exists — an object entry, or\n * an instance `resolveEntry` has just built.\n *\n * A property read rather than `Object.keys`, so it walks the prototype chain and\n * sees a class's methods, an inherited hook, a getter and a `defineProperty`\n * alike. That is the whole reason the class form works at all.\n */\nfunction assertHasCallableHook(\n policy: Record<string, unknown>,\n owner: unknown,\n index: number,\n): void {\n const model = nameOfOwner(owner);\n let callable = 0;\n /** Hooks written down and left nullish — reported, so \"it spells 'scope'\"\n * beside \"it has no scope\" is not a contradiction the reader has to resolve. */\n const unset: string[] = [];\n\n for (const hook of RECOGNISED_HOOKS) {\n const value = policy[hook];\n // `undefined` and `null` are absence, not error: `{ scope: undefined }` is\n // what a conditionally-built policy leaves behind and `applyPolicies` skips\n // it exactly as it skips a key that was never written.\n if (value === undefined || value === null) {\n if (hook in policy) unset.push(hook);\n continue;\n }\n\n if (typeof value !== \"function\") {\n throw new InvalidPolicyEntryError(\n model,\n index,\n \"hook-not-callable\",\n `'${hook}' that is ${describeValue(value)} rather than a function`,\n RECOGNISED_HOOKS,\n );\n }\n\n callable++;\n }\n\n if (callable > 0) return;\n\n if (unset.length > 0) {\n throw new InvalidPolicyEntryError(\n model,\n index,\n \"no-hooks\",\n `It writes ${unset.map((hook) => `'${hook}'`).join(\", \")} down and ` +\n `leaves ${unset.length === 1 ? \"it\" : \"them\"} unset, which reads as ` +\n `absent — so nothing is left to run.`,\n RECOGNISED_HOOKS,\n );\n }\n\n const spelled = spelledKeys(policy);\n const near = nearestHook(spelled);\n\n throw new InvalidPolicyEntryError(\n model,\n index,\n \"no-hooks\",\n spelled.length === 0\n ? \"It is empty.\"\n : `It spells ${listKeys(spelled)}.` +\n // The other half of #321's case B, and it is not a misspelling, so\n // \"did you mean\" has nothing to offer it: an entry whose only key is\n // `default` is a module namespace — `import * as p` or a CJS interop\n // — put in the array instead of the policy inside it.\n (spelled.length === 1 && spelled[0] === \"default\"\n ? ` A lone 'default' is a module namespace rather than the policy ` +\n `inside it — put \\`entry.default\\` in the array, or import the ` +\n `policy by name.`\n : \"\"),\n RECOGNISED_HOOKS,\n near,\n );\n}\n\n/**\n * The keys, listed, with a ceiling.\n *\n * A policy-shaped object that happens to carry no hook can hold a great many\n * keys, and an error whose useful sentence is buried under forty of them is a\n * worse error than one that says \"and 32 more\".\n */\nfunction listKeys(keys: readonly string[]): string {\n const shown = keys.slice(0, 8).map((key) => `'${key}'`);\n return keys.length > shown.length\n ? `${shown.join(\", \")} and ${keys.length - shown.length} more`\n : shown.join(\", \");\n}\n\n/**\n * Whether `new value()` is a thing that can be written.\n *\n * The language exposes `[[Construct]]` nowhere directly, and every syntactic\n * proxy for it is wrong somewhere. `value.prototype === undefined` is the usual\n * one — true of arrow functions, method shorthand and `async` functions, which\n * are three of the four shapes a forgotten factory call takes — and it is also\n * true of `SomeClass.bind(null)`, which *is* constructable. Refusing that would\n * be the over-strict direction, where a policy somebody legitimately wrote stops\n * an app from booting. A generator function fails the other way: it has a\n * `prototype` and is not constructable.\n *\n * So the engine is asked outright. `Reflect.construct` validates `newTarget` as\n * a constructor **before** it runs the target's body, so putting the entry there\n * and a do-nothing constructor in the target position answers the question\n * without executing the policy's own constructor — which matters, because that\n * is user code and this runs at boot on every class in a declared module.\n */\nfunction isConstructable(value: Function): boolean {\n try {\n Reflect.construct(NOOP, [], value as new () => unknown);\n return true;\n } catch {\n return false;\n }\n}\n\n/** The do-nothing target of the probe above. Its body is what does not run. */\nconst NOOP = function () {} as unknown as new () => unknown;\n\n/**\n * The keys an entry spells, own and inherited, so the message can say what was\n * found. Prototype methods are included because the class form is where the\n * hooks live there; `Object.prototype` and `constructor` are not, because they\n * are not something the author wrote.\n */\nfunction spelledKeys(policy: object): string[] {\n const keys = new Set<string>();\n\n let current: object | null = policy;\n while (current !== null && current !== Object.prototype) {\n for (const key of Object.getOwnPropertyNames(current)) {\n if (key !== \"constructor\") keys.add(key);\n }\n current = Object.getPrototypeOf(current) as object | null;\n }\n\n return [...keys];\n}\n\n/**\n * The recognised hook a spelled key most plausibly meant, **with the key it is\n * about** — or nothing.\n *\n * Two things were wrong with the obvious version, and both produced a confident\n * suggestion to an author who had not misspelled anything.\n *\n * **The threshold was two edits.** `store` and `code` and `copy` are each two\n * from `scope`, and `reduce` is two from `redact` — all ordinary names for\n * things that sit beside a policy. One edit is what an actual typo costs\n * (`scopes`, `onCreat`), and case is free because the comparison is lowered\n * first, so `Scope` still lands. Anything further away is a guess, and this\n * error's whole subject is an authorization rule that is not in effect: a wrong\n * suggestion there sends someone to rename a key that was never the problem.\n *\n * **And it was reported unattributed.** \"Did you mean `scope`?\" after a list of\n * five keys does not say which of them it read as a misspelling, so it cannot be\n * dismissed by a reader who can see that none of them are. The pair travels\n * together now, and the error prints both.\n */\nfunction nearestHook(\n spelled: readonly string[],\n): { key: string; hook: string } | undefined {\n let best: { key: string; hook: string } | undefined;\n let bestDistance = 2;\n\n for (const key of spelled) {\n for (const hook of RECOGNISED_HOOKS) {\n const distance = editDistance(key.toLowerCase(), hook.toLowerCase());\n if (distance < bestDistance) {\n bestDistance = distance;\n best = { key, hook };\n }\n }\n }\n\n return best;\n}\n\n/** Levenshtein, iterative over one row. Inputs here are hook names. */\nfunction editDistance(a: string, b: string): number {\n if (a === b) return 0;\n\n let row = Array.from({ length: b.length + 1 }, (_value, index) => index);\n\n for (let i = 1; i <= a.length; i++) {\n let previous = row[0]!;\n row[0] = i;\n\n for (let j = 1; j <= b.length; j++) {\n const held = row[j]!;\n row[j] = Math.min(\n row[j]! + 1,\n row[j - 1]! + 1,\n previous + (a[i - 1] === b[j - 1] ? 0 : 1),\n );\n previous = held;\n }\n }\n\n return row[b.length]!;\n}\n\n/**\n * A value as a message names it: what it is, not what it holds. Objects are not\n * stringified — `[object Object]` names nothing, and a policy's own data is not\n * something to print into a log line.\n */\nfunction describeValue(value: unknown): string {\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (typeof value === \"string\") return `the string ${JSON.stringify(value)}`;\n if (typeof value === \"function\") return describeFunction(value);\n if (Array.isArray(value)) return \"an array\";\n if (typeof value === \"object\") return \"an object\";\n return `the ${typeof value} ${String(value)}`;\n}\n\nfunction describeFunction(value: Function): string {\n return value.name ? `the function \\`${value.name}\\`` : \"an anonymous function\";\n}\n\n/**\n * Every policy that applies to a model class, base first.\n *\n * Walks the prototype chain so a `TenantModel` or `SoftDeletes` base\n * contributes to every subclass, and concatenates each level's `$policies`.\n * The order is **base to derived**, and it is chosen rather than incidental: a\n * subclass's `scope` is `AND`ed after its base's, so a base can only ever be\n * narrowed further, never widened. A derived policy that could drop its base's\n * scope would make a shared tenant guard unenforceable, which is the opposite of\n * why a base class would carry one. Within one level, array order is the\n * author's and is preserved.\n *\n * `Object.hasOwn` rather than a property read: an inherited `$policies` would\n * otherwise be collected once per level of the chain.\n *\n * **Deliberately uncached.** This runs per query per node of an include tree, so\n * a cache is tempting — but `$policies` is an ordinary static that tests and\n * feature flags reassign at runtime, and a cache keyed on the class would serve\n * the stale chain with no way to notice. The single-level fast path below is\n * what keeps the common case free: one `Object.hasOwn` per level and no\n * allocation at all when nothing needs instantiating.\n */\nexport function policiesFor(model: unknown): readonly ModelPolicy[] {\n let found: ModelPolicy[] | undefined;\n let only: readonly PolicyEntry[] | undefined;\n // Held beside `only`, because the class that *declared* the held array is not\n // the one the walk is standing on by the time it gets resolved.\n let onlyOwner: unknown;\n\n let current = model as PolicedModel | null;\n while (current && current !== Function.prototype) {\n // The rename tripwire, and it earns its keep because the failure it catches\n // is silent in both directions: `Model` no longer declares `$policy`, so a\n // class still carrying it neither fails to compile nor gets read — the model\n // is simply unpolicied, and a tenant scope stops applying with nothing to\n // notice it. Every call site in this repository is migrated; the window this\n // covers is a branch rebased across the rename, or a stack still on the old\n // name. Same argument `UnregisteredPolicyClassError` makes one function over:\n // a policy that is present but not in effect has to be loud.\n //\n // Delete once `feat/orm` merges and nothing can still be carrying it.\n if (Object.hasOwn(current, \"$policy\")) {\n throw new Error(\n `${(current as { name?: string }).name ?? \"This model\"} declares ` +\n `\\`$policy\\`, which is now \\`$policies\\` and takes a list. The old ` +\n `name is not read, so this model is currently unpolicied — every ` +\n `scope, onCreate and redact on it is being skipped.`,\n );\n }\n\n if (Object.hasOwn(current, \"$policies\") && current.$policies) {\n const level = current.$policies;\n if (level.length > 0) {\n // Before anything is resolved, and with the declaring class in hand —\n // which is what lets the refusal say `ScopedAccount.$policies[0]`\n // instead of dying inside `new entry` with nothing named. Memoised on\n // the array, so the per-query cost is one `WeakSet.has` per level; the\n // class is passed rather than its name so that even reading `.name` is\n // something only a refusal pays for.\n const owner = current;\n assertPolicyEntries(owner, level);\n\n if (only === undefined && found === undefined) {\n // First contributing level, walking derived to base. Held rather than\n // copied, in case it turns out to be the only one — and the class that\n // declared it is held beside it, because `current` will have moved on\n // by the time the array is resolved.\n only = level;\n onlyOwner = owner;\n } else {\n // A second level exists, so the held one has to be materialised.\n // Unshifted, so the walk's derived-to-base order comes back\n // base-first.\n found ??= resolveLevel(only as readonly PolicyEntry[], onlyOwner);\n only = undefined;\n found.unshift(...resolveLevel(level, owner));\n }\n }\n }\n current = Object.getPrototypeOf(current);\n }\n\n if (found !== undefined) return found;\n if (only === undefined) return EMPTY;\n\n // The overwhelmingly common shape: policies on exactly one class. Returned\n // without copying when every entry is already an object, which is every\n // factory-authored policy.\n return only.some((entry) => typeof entry === \"function\")\n ? resolveLevel(only, onlyOwner)\n : (only as readonly ModelPolicy[]);\n}\n\n/**\n * Every `$policies` entry a model class carries, checked as far as it can be\n * **without constructing anything** — the boot-time half of #321's guard.\n *\n * `auditModelRegistrations` calls this for every model class in every declared\n * module, and that is the whole point: it is the one walk that sees a class\n * regardless of whether anything registered it, whether it registered itself, or\n * whether its name is claimed at all. `policiesFor` is only reached there for\n * the classes whose registration diverges, so the two commonest arrangements —\n * a class that owns its name, and a name nothing else claims — would boot with\n * their entries unexamined, which is exactly the `{ scopes: … }` typo shipping.\n *\n * **Shape only, deliberately.** The alternative was to resolve, which is one\n * line and would also catch a class whose constructor throws. It would also\n * construct every policy class in the application at `registerModels` time,\n * moving whatever a constructor touches — config, environment, a service\n * container — ahead of where it is wired. A guard against a policy that does\n * nothing must not be a reason a working application stops booting, so the\n * cases that need an instance wait for one to be needed.\n */\nexport function assertPolicyShapes(model: unknown): void {\n let current = model as PolicedModel | null;\n\n while (current && current !== Function.prototype) {\n // Note what is *not* here: the `$policy` rename tripwire that `policiesFor`\n // carries. It belongs to resolution, and firing it from a walk that reaches\n // strictly more classes would turn a first-query error into a boot failure\n // for models this function has no business having an opinion about.\n if (Object.hasOwn(current, \"$policies\") && current.$policies) {\n const level = current.$policies;\n if (level.length > 0) assertPolicyEntries(current, level);\n }\n current = Object.getPrototypeOf(current);\n }\n}\n\nfunction nameOfOwner(owner: unknown): string {\n return (owner as { name?: string })?.name ?? \"This model\";\n}\n\nconst EMPTY: readonly ModelPolicy[] = Object.freeze([]);\n\n/**\n * Applies every policy to the argument tree, returning a new tree.\n *\n * The caller's `args` is never mutated: a policy that rewrote it in place would\n * leave the mutation visible to the caller's own object, and — worse — would\n * apply a second time if the same args object were reused for a second call.\n */\nexport function applyPolicies(\n policies: readonly ModelPolicy[],\n context: PolicyContext,\n args: any,\n /**\n * Columns of `args.data` the ORM wrote rather than the caller — see\n * {@link ormAuthoredFields}. Only the scope-escape guard reads it.\n */\n ormAuthored: readonly string[] = [],\n): any {\n if (policies.length === 0) return args;\n\n let out = args;\n\n /**\n * Scope-owned columns whose policy has no `onUpdate`, so nobody has said what\n * writing them should mean. Accumulated during the scope loop and checked once\n * at the end, against the payload as it will actually be written.\n */\n let unguarded: string[] | undefined;\n\n for (const policy of policies) {\n if (policy.before) {\n const verdict = policy.before(context);\n if (verdict === false) {\n throw new PolicyDeniedError(context.model, context.operation);\n }\n }\n }\n\n for (const policy of policies) {\n if (!policy.scope) continue;\n\n // An insert has no `where`, so there is nothing for a scope to narrow —\n // `onCreate` is the mechanism there. Skipping silently is only safe when the\n // policy has actually said how creates work; a `scope` with no `onCreate` is\n // an author who expressed an intent this operation cannot honour, and\n // running it would write a row into whatever tenant the caller named.\n if (INSERTING.has(context.operation)) {\n assertCreateCovered(policy, context);\n continue;\n }\n\n const scope = policy.scope(context);\n if (scope === undefined || scope === null) continue;\n\n assertScopable(context);\n\n // Collected from *this* policy's own fragment — only this iteration knows\n // what its scope constrains — but checked after the rewrites below rather\n // than here. See `unguarded` and `assertNoScopeEscape`.\n if (UPDATING.has(context.operation) && !policy.onUpdate) {\n const owned = scopeOwnedFields(scope);\n if (owned.length > 0) (unguarded ??= []).push(...owned);\n }\n\n out = withScope(out, scope);\n }\n\n if (CREATING.has(context.operation)) {\n for (const policy of policies) {\n if (policy.onCreate) out = withCreated(out, context, policy);\n }\n }\n\n if (MUTATING.has(context.operation)) {\n for (const policy of policies) {\n if (policy.onUpdate) out = withUpdated(out, context, policy);\n }\n }\n\n // **After the `onUpdate` pass, not before it**, and that ordering is the whole\n // point of hoisting the check out of the scope loop.\n //\n // Checking the caller's `data` where the fragment is computed is the obvious\n // placement and it leaves a gap the same shape as the `assertCreateCovered`\n // bug this guard was written alongside: one policy acting on another's behalf.\n // There it was a `some()` over the list; here it is the rewrite. A policy\n // carrying only an `onUpdate` can write a column that a *different* policy\n // scopes on, and if that policy has no `onUpdate` of its own then nobody has\n // taken responsibility for the column — yet the value lands anyway, because\n // the check already ran against a `data` that did not contain it.\n //\n // [{ onUpdate: (_c, d) => ({ ...d, orgId: 999 }) },\n // { scope: () => ({ orgId: 7 }) }]\n //\n // Running last means the question is asked of what will actually be written,\n // whoever put it there — which is the only version of the question worth\n // asking.\n if (unguarded !== undefined) {\n assertNoScopeEscape(unguarded, context, out, ormAuthored);\n }\n\n return out;\n}\n\n/**\n * Adds a policy's fragment to `args.where` as an extra `AND` member, **beside**\n * the caller's own keys rather than wrapping them.\n *\n * Two requirements pull in opposite directions here, and getting either wrong is\n * silent:\n *\n * 1. The scope must not *replace* a caller's filter on the same field, which\n * rules out merging keys. `{ organizationId: 9 }` scoped by\n * `{ organizationId: 7 }` has to mean \"both\", i.e. no rows.\n * 2. The caller's top-level keys must stay at the top level, because\n * `matchUniqueKey` reads them there. This is the one the obvious\n * implementation gets wrong: `{ AND: [caller, scope] }` is semantically\n * correct SQL and it hides `{ id: 1 }` one level down, so **every scoped\n * `update` and `delete` fails** with \"update needs a unique field\". Found by\n * the soft-delete tests, and one earlier test was passing for the wrong\n * reason because of it — it expected a throw and got the wrong throw.\n *\n * `{ ...caller, AND: [...callersOwnAND, scope] }` satisfies both: `AND` is a\n * sibling key in Prisma's `where` grammar and `compileWhere` treats it as one,\n * so the scope is conjoined without moving anything the caller wrote.\n */\nfunction withScope(args: any, scope: unknown): any {\n const where = args?.where;\n\n if (where === undefined || where === null) {\n return { ...args, where: scope };\n }\n\n if (typeof where !== \"object\" || Array.isArray(where)) {\n return { ...args, where: { AND: [where, scope] } };\n }\n\n // The caller may already have an `AND`, as an array or a bare object.\n const existing = where.AND;\n const members =\n existing === undefined || existing === null\n ? []\n : Array.isArray(existing)\n ? existing\n : [existing];\n\n return { ...args, where: { ...where, AND: [...members, scope] } };\n}\n\n/** Runs an `onCreate` over whichever shape the operation's payload takes. */\nfunction withCreated(args: any, context: PolicyContext, policy: ModelPolicy): any {\n // A shallow copy, so `applyPolicies`' promise that the caller's args are never\n // mutated is one the *mechanism* keeps rather than one every policy author has\n // to remember. The natural way to write an `onCreate` is\n // `data.organizationId = ...; return data`, and without the copy that mutates\n // the caller's object — which then applies a second time if the same args are\n // reused for another call, the exact hazard the promise cites. `redact` is\n // deliberately different: there the mutation *is* the interface.\n const run = (data: any) => policy.onCreate!(context, { ...data });\n\n if (context.operation === \"createMany\") {\n const rows = args?.data;\n return {\n ...args,\n data: Array.isArray(rows) ? rows.map(run) : run(rows),\n };\n }\n\n if (context.operation === \"upsert\") {\n // Only the insert branch. The update branch is an update, and giving it a\n // create's defaults would overwrite columns on an existing row.\n return { ...args, create: run(args?.create) };\n }\n\n return { ...args, data: run(args?.data) };\n}\n\n/**\n * Runs an `onUpdate` over whichever shape the operation's payload takes.\n *\n * The same shallow copy as `withCreated`, for the same reason, and the same\n * split for `upsert` — there the update branch is `args.update` rather than\n * `args.data`, and the create branch is `onCreate`'s.\n */\nfunction withUpdated(\n args: any,\n context: PolicyContext,\n policy: ModelPolicy,\n): any {\n const key = context.operation === \"upsert\" ? \"update\" : \"data\";\n const payload = args?.[key];\n\n // Nothing to default. An `update` with no `data` is the compiler's error to\n // report, and manufacturing `{}` here would turn it into a silent no-op write.\n if (payload === undefined || payload === null) return args;\n\n return { ...args, [key]: policy.onUpdate!(context, { ...payload }) };\n}\n\n/**\n * Refuses an update whose payload writes a scope-owned column that no policy has\n * taken responsibility for.\n *\n * See {@link ScopeEscapeError} for what the shape is and why it is dangerous.\n * The check is deliberately narrow — it fires only when the payload actually\n * names such a column — so an ordinary `update({ data: { name } })` on a\n * tenant-scoped model costs one `Object.keys` and passes, and nobody has to\n * write an `onUpdate` they do not need.\n *\n * `unguarded` is already filtered to policies without an `onUpdate`: a policy\n * that has one owns its columns, and whatever it does with them is its business.\n */\nfunction assertNoScopeEscape(\n unguarded: readonly string[],\n context: PolicyContext,\n args: any,\n /**\n * Columns the ORM itself wrote — a relation operand's own foreign key.\n *\n * The guard exists to stop a **caller** moving a row out of the scope that\n * selected it by naming a scoped column in `data`. A relation key is not\n * that: its value is the ORM's, the parent was reached through the parent\n * model's own scoping, and a child row this caller cannot see was already\n * refused before this runs. What is left is the operand doing what it means.\n *\n * Empty by default, and that direction matters: forgetting to pass it makes\n * the guard *stricter*, not looser, so an omission is a refused query rather\n * than a silent escape. That is the opposite of #79's defaulted `operation`,\n * where the default was the wrong answer — which is why this one is allowed\n * to have a default at all.\n */\n ormAuthored: readonly string[] = [],\n): void {\n const data = args?.data;\n if (typeof data !== \"object\" || data === null) return;\n\n const escaping = unguarded.filter(\n (field) => field in data && !ormAuthored.includes(field),\n );\n if (escaping.length === 0) return;\n\n throw new ScopeEscapeError(context.model, context.operation, [\n ...new Set(escaping),\n ]);\n}\n\n/**\n * The columns a scope fragment constrains, as far as they can be known.\n *\n * Top-level keys only, and combinators excluded: `{ organizationId: 7 }` names\n * a column, `{ OR: [...] }` names a structure whose columns cannot be attributed\n * to this policy without interpreting the whole `where` grammar. Returning\n * nothing for those is the permissive answer and is the documented limit of the\n * guard rather than an oversight.\n */\nfunction scopeOwnedFields(scope: unknown): string[] {\n if (typeof scope !== \"object\" || scope === null || Array.isArray(scope)) {\n return [];\n }\n\n const owned: string[] = [];\n for (const key of Object.keys(scope as Record<string, unknown>)) {\n if (key === \"AND\" || key === \"OR\" || key === \"NOT\") continue;\n owned.push(key);\n }\n return owned;\n}\n\n/**\n * Refuses a `create` whose policy scopes reads but says nothing about writes.\n *\n * The natural tenant policy carries both `scope` and `onCreate`, and for it this\n * is a no-op. The dangerous shape is `scope` alone: reads are confined to the\n * caller's tenant and an insert can name any tenant it likes, which is a policy\n * that looks complete and is half of one. Refused with the missing piece named.\n *\n * **Asks about one policy, not the chain.** It used to take the whole list and\n * pass if *any* member had an `onCreate`, which meant one policy could satisfy\n * the check on another's behalf — and `softDeletes()` ships a pass-through\n * `onCreate` precisely so that its own scope does not trip this. So adding soft\n * deletes to a model disarmed the guard for that model's tenant policy, and the\n * insert ran with the scoped column unset: the exact outcome the message below\n * describes, produced by the guard meant to prevent it. Composition is the\n * normal case now that `$policies` is a list, so the question has to be asked of\n * the policy that carries the scope.\n */\nfunction assertCreateCovered(\n policy: ModelPolicy,\n context: PolicyContext,\n): void {\n if (policy.onCreate) return;\n\n throw new UnsupportedQueryError(\n context.operation,\n context.model,\n context.operation,\n `${context.model} has a policy that scopes reads but no 'onCreate', and ` +\n `${context.operation} has no where clause for a scope to narrow. As ` +\n `written the policy would confine reads to the caller and let an insert ` +\n `name any value it likes. Add an onCreate that sets the scoped ` +\n `column — or, if unscoped creates are intended, say so with an onCreate ` +\n `that returns its data unchanged.`,\n );\n}\n\n/**\n * Refuses an operation a scope cannot be applied to, rather than running it\n * unscoped.\n *\n * Only `upsert` reaches this. Its `where` becomes an `on conflict` target,\n * which takes a key and not a predicate — so there is nowhere for\n * `organizationId: 7` to go, and silently dropping it would mean a policied\n * model writing across a tenant boundary. Use `update` and `create`, both of\n * which scope normally.\n */\nfunction assertScopable(context: PolicyContext): void {\n if (SCOPABLE.has(context.operation)) return;\n\n throw new UnsupportedQueryError(\n context.operation,\n context.model,\n context.operation,\n `${context.model} has a policy with a scope, and ${context.operation} ` +\n `cannot carry one: its where clause compiles to an 'on conflict' target, ` +\n `which is a key rather than a filter. Running it would write outside the ` +\n `scope.\\n\\n` +\n `Two ways out. Use update and create separately, which both scope ` +\n `normally — or leave the conflict key out of 'create', which Model.upsert ` +\n `runs as a scoped read and a scoped write inside one transaction. The ` +\n `refusal is about 'on conflict' specifically, not about upsert.`,\n );\n}\n\n/**\n * Applies every `redact` to every returned row, in place.\n *\n * In the shaping stage rather than the compiler, because it is the one policy\n * capability that is genuinely about the *result* — a redacted column is still\n * selected and still read, it just does not survive to the caller. Doing it by\n * dropping the column from the `select` instead would change the SQL, and so\n * the plan key, per user.\n */\nexport function applyRedaction(\n policies: readonly ModelPolicy[],\n context: PolicyContext,\n result: unknown,\n): void {\n if (policies.length === 0) return;\n\n const redactors = policies.filter((policy) => policy.redact);\n if (redactors.length === 0) return;\n\n for (const row of rowsOf(result)) {\n for (const policy of redactors) policy.redact!(context, row);\n }\n}\n\nfunction rowsOf(result: unknown): any[] {\n if (Array.isArray(result)) return result;\n if (result === null || result === undefined) return [];\n if (typeof result !== \"object\") return [];\n return [result];\n}\n\n/**\n * A `redact` helper that refuses to lie about the type.\n *\n * Redaction's problem is that the generated type says the field is there and\n * the value is gone, so `user.password.length` type-checks and throws. Limiting\n * it to *nullable* fields makes the runtime value one the type already allows,\n * which turns a lie into a narrowing. A non-nullable field is refused by name\n * rather than silently redacted, so the type-honesty decision is made once here\n * instead of per policy.\n *\n * A policy that genuinely needs to drop a non-nullable field can still `delete`\n * the key in its own `redact` — this is the guard rail, not a cage.\n */\nexport function redactNullable(\n schema: ModelSchema,\n row: any,\n fields: readonly string[],\n): void {\n for (const name of fields) {\n const field = schema.fields[name];\n\n if (field && !field.nullable) {\n throw new UnsupportedQueryError(\n `redact.${name}`,\n schema.name,\n \"redact\",\n `'${name}' is not nullable, so setting it to null would contradict ` +\n `the generated type — which still says the field is there. Make the ` +\n `field optional in schema.prisma, omit it with 'select' instead, or ` +\n `delete the key yourself if a runtime-only guarantee is enough.`,\n );\n }\n\n if (name in row) row[name] = null;\n }\n}\n\n/**\n * The authenticated user for the current async scope, or `null`.\n *\n * Read **synchronously** off the request store, which is the decision that\n * shapes this whole hook. `Auth.user()` is the fuller answer — it falls back to\n * the cookie and resolves a session from the database — but it is `async`, and\n * this runs once per query *per node of an include tree*. An awaited user there\n * is a round trip per node on every request, for a value that is already sitting\n * in the store on any route that authenticated.\n *\n * The consequence, stated rather than discovered: a route without the `auth`\n * middleware sees `null` even when the request carries a valid cookie. That is\n * the correct reading — the route did not ask to authenticate — but it makes\n * middleware configuration load-bearing for data access, so under\n * deny-by-default a policied model on an unauthenticated route raises rather\n * than reading unscoped.\n *\n * The import is deliberately narrow. `http/requestContext.ts` pulls in no\n * runtime the ORM does not already have, and taking the store rather than the\n * `Auth` facade keeps `AuthManager` — and its user provider, and its database\n * queries — off this path entirely.\n */\nexport function currentUser(): unknown {\n // An explicit actor wins over the ambient request. A job that has said who it\n // is acting as must not be quietly re-scoped by a request that happens to\n // enclose it — and in a test, that is the only user there is.\n const actor = currentActor();\n if (actor) return actor.user;\n\n // `RequestContext.getStore()` is non-null-asserted at its definition, so it\n // is `undefined` rather than a throw outside a request. Cron ticks, queue\n // workers and CLI never enter it; that case is the null.\n return requestStore()?.user ?? null;\n}\n\nfunction requestStore(): { user?: unknown } | undefined {\n try {\n return RequestContext.getStore() as { user?: unknown } | undefined;\n } catch {\n // Defensive: the accessor's non-null assertion is a type-level claim, not a\n // runtime guard, but a future change to it must not turn \"no request\" into\n // a crash on every ORM query.\n return undefined;\n }\n}\n\n\n// --- nested policy application ---------------------------------------------\n\n/**\n * Marks an `$exec` call as having had its policies applied by the caller.\n *\n * A module-private `Symbol`, deliberately, and **not exported from\n * `orm/index.ts`**. An application cannot forge it without importing something\n * that is not reachable, so it cannot become a way to skip policies — which is\n * the one thing iteration 6 spent three review rounds closing. `ExecOptions` is\n * public and a `policiesApplied?: boolean` there would have been exactly that\n * door.\n */\nconst PRE_SCOPED = Symbol(\"gemi.orm.policiesAppliedByCaller\");\n\nexport function markPreScoped(options: object | undefined): object {\n return { ...options, [PRE_SCOPED]: true };\n}\n\nexport function isPreScoped(options: unknown): boolean {\n return (\n typeof options === \"object\" &&\n options !== null &&\n (options as Record<symbol, unknown>)[PRE_SCOPED] === true\n );\n}\n\n/**\n * Columns in this call's `data` that the **ORM** put there, not the caller.\n *\n * A nested relation operand writes exactly one column: the relation's own\n * foreign key, with a value this statement chose — the parent it is about, or\n * `null` for a `disconnect`. `assertNoScopeEscape` reads `args.data` and cannot\n * tell that apart from a caller naming the same column, so a child whose policy\n * scopes on its foreign key lost every relation operand that writes it (#98):\n *\n * connect ScopeEscapeError: Note.update writes 'folderId', which\n * Note's policy also scopes on…\n * disconnect ScopeEscapeError: Note.updateMany writes 'folderId', …\n *\n * The caller wrote `connect: { id: 1 }`. The error described a write they had\n * not made and sent them to their own `data`, where there was nothing to find.\n *\n * **A module-private `Symbol`, for the same reason `PRE_SCOPED` is one**: it is\n * not exported from `orm/index.ts`, so an application cannot forge it and it\n * cannot become a way to write a scoped column past the guard. An\n * `ExecOptions` field would have been exactly that door.\n */\nconst ORM_AUTHORED = Symbol(\"gemi.orm.columnsWrittenByTheOrm\");\n\nexport function markOrmAuthored(\n options: object | undefined,\n fields: readonly string[],\n): object {\n return { ...options, [ORM_AUTHORED]: fields };\n}\n\nexport function ormAuthoredFields(options: unknown): readonly string[] {\n if (typeof options !== \"object\" || options === null) return EMPTY_FIELDS;\n const fields = (options as Record<symbol, unknown>)[ORM_AUTHORED];\n return Array.isArray(fields) ? (fields as string[]) : EMPTY_FIELDS;\n}\n\nconst EMPTY_FIELDS: readonly string[] = [];\n\n/**\n * The operation whose *return value* this `$exec` is producing, when that is not\n * the operation it runs.\n *\n * There is exactly one such call: the pre-read a read-first `delete` performs.\n * `delete({ where, include })` cannot be one statement — the children have to be\n * read before the row goes away — so `$exec` runs a `findFirst` inside a\n * transaction and hands **that** row to the caller, discarding what the `delete`\n * statement returned. Every other consequence of the split was already made\n * invisible: the read is scoped as the delete was, a miss raises\n * `RecordNotFoundError` naming `delete`, and #364 taught it to carry the `omit`.\n * `context.operation` was the last one left visible, and it was visible in the\n * worst direction — a `redact` keyed on `\"delete\"` stopped firing on the row the\n * caller got back, the moment an `include` was added (#366).\n *\n * **Redaction only, which is why it is named for redaction.** By the time this\n * is read the pre-read is already `markPreScoped`, so `applyPolicies` does not\n * run on it at all — no `before`, no `scope`, no `onCreate` / `onUpdate` sees\n * this value, and a scope written for reads cannot be turned off by it. The\n * remaining reader of the context is `applyRedaction`, over the one row that is\n * about to be returned.\n *\n * **Not the nested reads.** A relation read underneath is *scoped* as `findMany`\n * — see {@link NESTED_READ}, which is a constant for the reason this marker is\n * narrow: a nested read is a read of another model, whatever statement encloses\n * it. This marker travels no further than the row it names, and the relation\n * executor rebuilds its options from `{ strategy }` rather than forwarding\n * these, so it cannot travel even by accident.\n *\n * *Redaction* of a nested row is the same answer only when the child went\n * through its own `$exec`. Scoping and redaction are two mechanisms here and\n * they do not currently agree:\n *\n * - **batched** — the child runs its own `$exec` under `NESTED_READ`, so its\n * `redact` is handed `findMany`. True on both dialects.\n * - **folded** (lateral, the Postgres default) — the child's rows never enter\n * its own `$exec`, so the parent redacts them on its behalf via\n * `redactFolded`, which builds its context from the **enclosing** `$exec`'s\n * operation rather than from `NESTED_READ`. Under this marker's one call site\n * that enclosing operation is the pre-read, so a folded child of a\n * `delete({ where, include })` is redacted as `findFirst`. Measured on\n * postgres:16.\n *\n * That divergence predates this marker and is not widened by it — it is two\n * reads disagreeing by strategy, not a read reporting a write, and it is the\n * same on an ordinary `findFirst`. It is filed as #388. It is also the reason\n * `REDACTED_AS` must **not** be widened to nested rows: doing so would hand a\n * child's policy the enclosing *write*'s name on one strategy and not the other,\n * which is strictly worse than two read names disagreeing.\n *\n * A module-private `Symbol`, for the same reason `PRE_SCOPED` and `ORM_AUTHORED`\n * are: it is not exported from `orm/index.ts`, so an application cannot forge it\n * and cannot use it to make a query claim to be an operation it is not.\n */\nconst REDACTED_AS = Symbol(\"gemi.orm.operationTheRowIsReturnedFor\");\n\nexport function markRedactedAs(\n options: object | undefined,\n operation: Operation,\n): object {\n return { ...options, [REDACTED_AS]: operation };\n}\n\nexport function redactedAs(options: unknown): Operation | undefined {\n if (typeof options !== \"object\" || options === null) return undefined;\n const operation = (options as Record<symbol, unknown>)[REDACTED_AS];\n return typeof operation === \"string\" ? (operation as Operation) : undefined;\n}\n\n/** Resolves a model name to its policies, so this file need not import the registry. */\nexport type PolicyLookup = (model: string) => {\n policies: readonly ModelPolicy[];\n schema: {\n name: string;\n // `kind` because a relation filter reads differently per kind — `some` /\n // `every` / `none` on a to-many, `is` / `isNot` on a to-one — and the walk\n // has to know which nested `where` it is scoping.\n relations: Record<string, { model: string; kind: \"one\" | \"many\" }>;\n };\n} | undefined;\n\n/**\n * The operation every node this walk touches is scoped as.\n *\n * `findMany` because that is what each of them *is* — one query for rows of\n * another model, named from inside somebody else's arguments — and because a\n * policy reading `context.operation` should see the read it is being asked\n * about rather than the statement that happens to enclose it. It is also in\n * `SCOPABLE`, which an inserting operation is not, and that mismatch is what\n * produced the bug this constant exists to prevent.\n *\n * **It is a constant rather than a parameter, and that is the fix.** The walk\n * used to take the root operation and pass it down; every node type then had\n * its own opportunity to be scoped as the enclosing statement instead of as\n * the read it is, and two of the four took it. Threading the right value\n * through four call sites leaves the wrong value expressible at all four. Not\n * accepting one at all is what makes it unrepresentable — the same reason #79\n * made `resolveLink`'s `operation` required rather than defaulted.\n */\nexport const NESTED_READ: Operation = \"findMany\";\n\n/**\n * Applies every *nested* model's policies to its own node in the argument tree,\n * recursively, returning a new tree.\n *\n * **Why this has to happen here rather than in the strategy.** A nested read under\n * the batched strategy acquires its policies by recursing through the child's own\n * `$exec`. A lateral join has no such call — the child's SQL is compiled inside\n * the parent's compile step — so the child's policies would never be consulted and\n * the subquery would be unscoped. That is a cross-tenant read arriving through a\n * new door, and iteration 9's plan doc has the full reasoning.\n *\n * The alternative was to let the strategy resolve policies while building the\n * subquery, which would give `compile/` knowledge of the registry and the ambient\n * user. It would then no longer be a pure function of the argument shape and the\n * plan cache would stop being sound — which invariant 2 and iteration 6's \"do not\n * let policies see SQL\" both exist to prevent.\n *\n * Doing it on the arg tree, before the plan key, keeps the compiler pure: it\n * receives a tree whose nested `where`s are already scoped, and the scope lands\n * inside whatever SQL the strategy chooses to emit. It also makes the README's\n * claim — that scoping applies under every strategy because policies rewrite the\n * arg tree before planning — *true*, where before it was true only of the\n * strategy that happened to recurse.\n *\n * **Every node it touches is a read.** There are four kinds — an `include` /\n * `select` node, a `_count` entry, a relation filter in a `where`, a relation\n * ordering in an `orderBy` — and each names *another model's rows*, whatever\n * the statement around it is doing. So each is scoped as {@link NESTED_READ}\n * rather than as the enclosing operation.\n *\n * Passing the root operation down broke two of the four, and only the ones\n * reachable from an insert were visible:\n *\n * User.create({ data, include: { accounts: true } })\n * User.create({ data, include: { _count: { select: { accounts: true } } } })\n *\n * - A child with a `scope` and no `onCreate` **raised**, with\n * `Account has a policy that scopes reads but no 'onCreate'` — naming an\n * operation the caller never asked for, about rows being read back rather\n * than written. That is a legal policy: a model can scope reads and never\n * create rows.\n * - A child with both took `applyPolicies`' inserting branch, which skips\n * `withScope` and then runs `onCreate` over the node. It came out carrying\n * `data: {}` where its `where` should have been, so the child's read scope —\n * a tenant filter, or `softDeletes`' own `deletedAt: null` — silently\n * disappeared from the nested read.\n *\n * The other two are not reachable from an insert, and the reason is worth\n * recording so the asymmetry is not rediscovered: `create` accepts only\n * `data` / `select` / `include` and `createMany` only `data`, so neither has a\n * `where` or an `orderBy` for a relation to be named in. They were still\n * wrong, just more quietly — under a root `update` a policy whose `scope`\n * reads `context.operation` saw `\"update\"` for what is a read, and answered\n * the question it was not asked.\n *\n * Nested *write* nodes under `data` are a different path entirely\n * (`planNestedWrites`), and already scope themselves as writes. This walk only\n * ever sees the read tree, which is why it can take the operation as a\n * constant at all.\n */\n\nexport function applyNestedPolicies(\n schema: {\n relations: Record<string, { model: string; kind: \"one\" | \"many\" }>;\n },\n args: any,\n user: unknown,\n system: boolean,\n lookup: PolicyLookup,\n): any {\n if (args === undefined || args === null) return args;\n if (typeof args !== \"object\") return args;\n\n let out = args;\n\n for (const container of [\"include\", \"select\"] as const) {\n const tree = args[container];\n if (typeof tree !== \"object\" || tree === null || Array.isArray(tree)) {\n continue;\n }\n\n let rewritten: Record<string, unknown> | undefined;\n\n for (const key of Object.keys(tree)) {\n // `_count` counts another model's rows, so it is a read of that model and\n // carries its policies — the third shape of the same rule, after nested\n // includes and relation filters. An unscoped count is the quietest of the\n // three: it returns a *number*, so what leaks is how many rows exist in\n // tenants the caller cannot see.\n if (key === COUNT_KEY) {\n const scopedCounts = scopeCounts(\n schema,\n (tree as Record<string, unknown>)[key],\n user,\n system,\n lookup,\n );\n if (scopedCounts !== (tree as Record<string, unknown>)[key]) {\n rewritten ??= { ...(tree as Record<string, unknown>) };\n rewritten[key] = scopedCounts;\n }\n continue;\n }\n\n const relation = schema.relations[key];\n if (!relation) continue;\n\n const node = (tree as Record<string, unknown>)[key];\n if (node === undefined || node === false) continue;\n\n const target = lookup(relation.model);\n // An unregistered relation target is the relation planner's error to raise,\n // with the message it has for it — not this walk's.\n if (!target) continue;\n\n // `true` is shorthand for \"this relation, no arguments\", and it has to\n // *stay* `true` unless something actually applies. Turning it into `{}`\n // unconditionally changes the argument tree — and therefore the plan key —\n // for every include on an unpolicied model, which is a cache invalidation\n // and a canonical-shape change in exchange for nothing.\n const nodeArgs = node === true ? {} : node;\n if (typeof nodeArgs !== \"object\" || Array.isArray(nodeArgs)) continue;\n\n // Depth first, so a grandchild's scope is in place before its parent's\n // node is rewritten around it.\n const deeper = applyNestedPolicies(\n target.schema,\n nodeArgs,\n user,\n system,\n lookup,\n );\n\n // `system` short-circuits here as well as at the root: `asSystem` suspends\n // policies for the whole subtree, not just the model that was queried.\n const scoped =\n !system && target.policies.length > 0\n ? applyPolicies(\n target.policies,\n policyContext(target.schema.name, NESTED_READ, user, system),\n deeper,\n )\n : deeper;\n\n // Only when something changed. `deeper !== nodeArgs` covers a grandchild's\n // rewrite; `scoped !== deeper` covers this level's own scope.\n if (scoped !== nodeArgs) {\n rewritten ??= { ...(tree as Record<string, unknown>) };\n rewritten[key] = scoped;\n }\n }\n\n if (rewritten) out = { ...out, [container]: rewritten };\n }\n\n // Relation *orderings*. `orderBy: { organization: { name: \"asc\" } }` reads\n // another model's rows to sort by them, so the same rule applies — and this is\n // the one path where Prisma's grammar has no slot for the scope, so the walk\n // adds one. See `compile/order-relation.ts`.\n const ordered = scopeRelationOrderings(\n schema,\n out.orderBy,\n user,\n system,\n lookup,\n );\n if (ordered !== out.orderBy) out = { ...out, orderBy: ordered };\n\n // Relation *filters*, which reach another model's rows through `where` rather\n // than through `include`. Same rule, and it has to be the same walk: a filter\n // that reads a model is a read of that model.\n const filtered = scopeRelationFilters(\n schema,\n out.where,\n user,\n system,\n lookup,\n );\n if (filtered !== out.where) out = { ...out, where: filtered };\n\n return out;\n}\n\n/**\n * Adds a `where` to every relation ordering whose target carries policies.\n *\n * The other three paths all have somewhere for a scope to go: an `include` node\n * takes a `where`, a relation filter's operand *is* one, a `_count` entry takes\n * one. `orderBy: { rel: { field: \"asc\" } }` has none in Prisma's grammar, so this\n * writes the key the compiler reads.\n *\n * It has to happen. Ordering by a column of rows the caller cannot read leaks\n * their contents by comparison — sort ascending, sort descending, and the\n * invisible row's position tells you where its value falls. Ordering by\n * `_count` leaks the number outright.\n *\n * Unscoped rows then sort as `NULL`, because the correlated subquery finds\n * nothing. That is the same answer the caller would get if the row did not\n * exist, which is the whole point.\n */\nfunction scopeRelationOrderings(\n schema: { relations: Record<string, { model: string; kind: \"one\" | \"many\" }> },\n orderBy: unknown,\n user: unknown,\n system: boolean,\n lookup: PolicyLookup,\n): unknown {\n if (system) return orderBy;\n if (typeof orderBy !== \"object\" || orderBy === null) return orderBy;\n\n if (Array.isArray(orderBy)) {\n let changed = false;\n const out = orderBy.map((entry) => {\n const scoped = scopeRelationOrderings(\n schema,\n entry,\n user,\n system,\n lookup,\n );\n if (scoped !== entry) changed = true;\n return scoped;\n });\n return changed ? out : orderBy;\n }\n\n let rewritten: Record<string, unknown> | undefined;\n const source = orderBy as Record<string, unknown>;\n\n for (const key of Object.keys(source)) {\n const relation = schema.relations[key];\n if (!relation) continue;\n\n const node = source[key];\n if (typeof node !== \"object\" || node === null || Array.isArray(node)) {\n // Malformed, and the compiler reports it with the message it has.\n continue;\n }\n\n const target = lookup(relation.model);\n if (!target || target.policies.length === 0) continue;\n\n const scoped = applyPolicies(\n target.policies,\n policyContext(target.schema.name, NESTED_READ, user, system),\n node,\n );\n\n if (scoped !== node) {\n rewritten ??= { ...source };\n rewritten[key] = scoped;\n }\n }\n\n return rewritten ?? orderBy;\n}\n\n/**\n * Scopes each relation named inside `_count: { select: { … } }`.\n *\n * `true` becomes `{ where: <scope> }` for the same reason an `include: true`\n * does — a scope has to go somewhere — and stays `true` when nothing applies, so\n * an unpolicied count does not move the plan key.\n */\nfunction scopeCounts(\n schema: { relations: Record<string, { model: string; kind: \"one\" | \"many\" }> },\n node: unknown,\n user: unknown,\n system: boolean,\n lookup: PolicyLookup,\n): unknown {\n if (system) return node;\n if (typeof node !== \"object\" || node === null || Array.isArray(node)) {\n return node;\n }\n\n const selection = (node as Record<string, unknown>).select;\n if (\n typeof selection !== \"object\" ||\n selection === null ||\n Array.isArray(selection)\n ) {\n // Every other shape is the compiler's to report, with the message it has.\n return node;\n }\n\n let rewritten: Record<string, unknown> | undefined;\n const source = selection as Record<string, unknown>;\n\n for (const key of Object.keys(source)) {\n const value = source[key];\n if (value === undefined || value === false) continue;\n\n const relation = schema.relations[key];\n if (!relation) continue;\n\n const target = lookup(relation.model);\n if (!target || target.policies.length === 0) continue;\n\n const nodeArgs = value === true ? {} : value;\n if (typeof nodeArgs !== \"object\" || Array.isArray(nodeArgs)) continue;\n\n const scoped = applyPolicies(\n target.policies,\n policyContext(target.schema.name, NESTED_READ, user, system),\n nodeArgs,\n );\n\n if (scoped !== nodeArgs) {\n rewritten ??= { ...source };\n rewritten[key] = scoped;\n }\n }\n\n return rewritten\n ? { ...(node as Record<string, unknown>), select: rewritten }\n : node;\n}\n\n/**\n * Scopes every relation filter inside a `where`, recursively.\n *\n * `where: { memberships: { some: {} } }` compiles to a correlated subquery over\n * `Membership`. Unscoped, it answers \"does this user have a membership *in any\n * tenant*\" — which returns no membership rows, so the leak is existence rather\n * than data, and correspondingly harder to notice. It is still a cross-tenant\n * read, and iteration 6's rule is that every read of a model carries that\n * model's policies.\n *\n * Structural sharing throughout: an unpolicied tree comes back as the same\n * object, so the plan key does not move for the queries this does not touch.\n */\nfunction scopeRelationFilters(\n schema: { relations: Record<string, { model: string; kind: \"one\" | \"many\" }> },\n where: unknown,\n user: unknown,\n system: boolean,\n lookup: PolicyLookup,\n): unknown {\n if (typeof where !== \"object\" || where === null) return where;\n\n if (Array.isArray(where)) {\n let changed = false;\n const out = where.map((entry) => {\n const scoped = scopeRelationFilters(\n schema,\n entry,\n user,\n system,\n lookup,\n );\n if (scoped !== entry) changed = true;\n return scoped;\n });\n return changed ? out : where;\n }\n\n let rewritten: Record<string, unknown> | undefined;\n const source = where as Record<string, unknown>;\n\n for (const key of Object.keys(source)) {\n const value = source[key];\n if (value === undefined) continue;\n\n // Combinators hold more `where`s on the *same* model, so they recurse with\n // this schema rather than a child's.\n if (key === \"AND\" || key === \"OR\" || key === \"NOT\") {\n const scoped = scopeRelationFilters(\n schema,\n value,\n user,\n system,\n lookup,\n );\n if (scoped !== value) {\n rewritten ??= { ...source };\n rewritten[key] = scoped;\n }\n continue;\n }\n\n const relation = schema.relations[key];\n if (!relation) continue;\n\n const scoped = scopeRelationNode(\n relation,\n value,\n user,\n system,\n lookup,\n );\n if (scoped !== value) {\n rewritten ??= { ...source };\n rewritten[key] = scoped;\n }\n }\n\n return rewritten ?? where;\n}\n\n/** One relation filter: `{ some: … }`, `{ is: … }`, or a to-one shorthand. */\nfunction scopeRelationNode(\n relation: { model: string; kind: \"one\" | \"many\" },\n value: unknown,\n user: unknown,\n system: boolean,\n lookup: PolicyLookup,\n): unknown {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n // `null` is `is: null` — \"no related row at all\". There is no nested `where`\n // to scope, and narrowing what counts as \"related\" here would change the\n // meaning of the filter rather than restrict it. The compiler reports every\n // other non-object.\n return value;\n }\n\n const target = lookup(relation.model);\n if (!target) return value;\n\n const operators = relationFilterOperators(relation.kind);\n const shorthand = !isOperatorForm(value, operators);\n const entries: Array<[string, unknown]> = shorthand\n ? [[\"is\", value]]\n : Object.entries(value as Record<string, unknown>);\n\n let rewritten: Record<string, unknown> | undefined;\n\n for (const [operator, argument] of entries) {\n if (argument === null || argument === undefined) continue;\n\n // Depth first: a filter nested inside this one is scoped before this level\n // wraps anything around it.\n const deeper = scopeRelationFilters(\n target.schema,\n argument,\n user,\n system,\n lookup,\n );\n\n const scope =\n !system && target.policies.length > 0\n ? applyPolicies(\n target.policies,\n policyContext(target.schema.name, NESTED_READ, user, system),\n { where: deeper },\n ).where\n : deeper;\n\n const final = operator === \"every\" ? invertForEvery(deeper, scope) : scope;\n\n if (final !== argument) {\n rewritten ??= shorthand\n ? {}\n : { ...(value as Record<string, unknown>) };\n rewritten[operator] = final;\n }\n }\n\n if (!rewritten) return value;\n // A scoped shorthand becomes the explicit form, because there is nowhere else\n // to put the operator once the argument is no longer the whole object.\n return rewritten;\n}\n\n/**\n * `every` needs the scope **outside** the negation, and this is the one place\n * where ANDing a scope into a nested `where` would be wrong.\n *\n * `every: X` compiles to `not exists (child where correlated and not X)`. AND a\n * scope S into X and you get `not exists (… and not (X and S))`, which is\n * \"every child either matches X or is invisible\" — a parent with one hidden\n * non-matching child now *passes*, and worse, a parent whose only children are\n * invisible passes too. The scope has to restrict which children are considered,\n * not which ones count as matching:\n *\n * not exists (child where correlated and S and not X)\n *\n * In argument space that is `every: { OR: [{ NOT: S }, X] }` — because\n * `not (not S or X)` is `S and not X`. Expressed as arguments rather than as SQL\n * so the compiler stays a pure function of the shape and the plan cache stays\n * sound; it is the same move iteration 9 made when it put nested policies on the\n * arg tree instead of teaching the lateral strategy about the registry.\n *\n * **This logic is outside the differential harness's reach, deliberately, and\n * therefore rests on its own tests.** Those 147 cases compare gemi against\n * Prisma, and Prisma has no policies — so nothing in them exercises a scoped\n * path at all. Do not read the matrix being green as coverage of this rewrite.\n * What stands over it is the unit tests on `applyNestedPolicies` and the\n * database test in `templates/saas-starter/app/models/relation-filter-policies.test.ts`,\n * which is arranged so the two candidate rewrites give *different* answers.\n *\n * The failure this guards against is not a crash or an obviously wrong row\n * count. It is a filter that silently consults rows the caller cannot see, and\n * the tempting \"simplification\" to `AND` is exactly how it comes back.\n */\nfunction invertForEvery(inner: unknown, scoped: unknown): unknown {\n if (scoped === inner) return inner;\n\n // `applyPolicies` adds its fragments as `AND` members beside the caller's own\n // keys, so what it added is exactly the tail of `AND` that was not there\n // before.\n const before = andMembers(inner);\n const after = andMembers(scoped);\n const added = after.slice(before.length);\n if (added.length === 0) return inner;\n\n const restriction =\n added.length === 1 ? added[0] : { AND: added };\n\n return { OR: [{ NOT: restriction }, inner] };\n}\n\nfunction andMembers(where: unknown): unknown[] {\n if (typeof where !== \"object\" || where === null) return [];\n const value = (where as Record<string, unknown>).AND;\n if (value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n",
|
|
7
7
|
"import {\n AmbiguousModelRegistrationError,\n UnregisteredPolicyClassError,\n} from \"./errors\";\nimport { assertPolicyShapes, policiesFor } from \"./policy\";\nimport * as registry from \"./registry\";\nimport type { ModelSchema } from \"./schema\";\n\n/** A model class, as much of one as anything below `Model.ts` can name. */\ntype ModelClass = object & { $schema: ModelSchema };\n\n/**\n * Checks that every policied model class an application defines is the one the\n * registry resolves its name to — **ahead of any query**, rather than when one\n * happens to be run.\n *\n * ### Why this exists\n *\n * `Model.$exec` already refuses a query whose class carries policies the\n * registered class does not (`UnregisteredPolicyClassError`). That guard closed\n * the two shapes found in #51, and it is the right check, but it can only fire\n * on a class somebody actually queries **at the root**. Its condition begins\n * `registered !== this`, and there is a case where that is false and the leak is\n * real:\n *\n * export class Membership extends MembershipModel {\n * static $policies = [{ scope: (ctx) => ({ orgId: ctx.user.orgId }) }]\n * }\n * // ...and no `register(\"Membership\", Membership)`\n *\n * If nothing ever calls `Membership.findMany()` — because memberships are only\n * ever read through `include: { memberships: true }` — then the include resolves\n * the name to the *generated base*, `this` **is** that base, the comparison\n * never runs, and rows come back unscoped with no error. Not a policy chain that\n * fails to diverge: a check that is never reached.\n *\n * A model reached only through includes is usually a membership or a pivot,\n * which is exactly the kind that carries a tenant scope. So the residual runs\n * the wrong way: the guard is weakest where the data is most sensitive.\n *\n * ### What this does about it\n *\n * The same rule, triggered differently. Instead of waiting for a root query,\n * it takes the modules where an application's model classes live and applies the\n * divergence comparison to every one of them:\n *\n * import * as models from \"@/app/models\"\n * assertPoliciesRegistered(models)\n *\n * Reading a class out of a module namespace is what makes the unqueried case\n * visible — the class exists and is exported whether or not anything queries it.\n *\n * `registerModels` runs this after registering, and `Kernel.models` runs\n * `registerModels` at boot, so an application that declares its model modules\n * gets it without asking. This is the same check for modules the Kernel does\n * not own — a test over a package's models, a script that boots nothing.\n *\n * It can only see modules it is handed, which is the residual either way: a\n * policied class in a file no barrel re-exports is invisible to it.\n * `gemi check models` closes that by handing it the files instead of the\n * barrel — see `auditModelRegistrations`, which is the same rule without the\n * throw.\n */\nexport function assertPoliciesRegistered(\n ...modules: Array<Record<string, unknown>>\n): void {\n const [first] = auditModelRegistrations(...modules);\n if (first !== undefined) throw first;\n}\n\n/**\n * Every problem `assertPoliciesRegistered` would report, as values rather than\n * as a throw — in the order it would have reported them, so the first element is\n * exactly what that function throws.\n *\n * ### Why the rule needed a second caller\n *\n * A throw is the right shape at boot: the first policied class that does not own\n * its name is a reason not to start, and the rest of the list is noise nobody\n * reads before fixing the first one.\n *\n * It is the wrong shape for a checker. `gemi check models` walks\n * `app/models/**` and audits each file, so it wants *all* of them, and it wants\n * to sort them — a policied class the Kernel never sees is a leak to report,\n * while a policied view deliberately kept out of the declared modules is the\n * arrangement the error for that case actually recommends, and reporting it\n * would be telling an author to undo what the framework told them to do.\n * `UnregisteredPolicyClassError.carries` is what separates the two, and it can\n * only be read off an error somebody is holding.\n *\n * Errors rather than a plain finding type, because the message is the useful\n * part and it is already written once, in the error. Constructing them is not\n * free — a stack per finding — and it is a check somebody runs, not a request\n * path.\n */\nexport function auditModelRegistrations(\n ...modules: Array<Record<string, unknown>>\n): UnregisteredPolicyClassError[] {\n const problems: UnregisteredPolicyClassError[] = [];\n\n for (const module of modules) {\n for (const exported of Object.values(module)) {\n const model = asModelClass(exported);\n if (model === null) continue;\n\n // #321's boot-time half, run **before** the early return below and for\n // every class rather than only the diverging ones. Left below the return,\n // the two commonest arrangements were never checked at all — a class that\n // already owns its name, and one whose name nothing else claims — so a\n // `{ scopes: … }` typo registered, reported green, and read unscoped.\n //\n // `assertPolicyShapes` and not `policiesFor`, and the difference is the\n // point: this walk checks the entries and constructs nothing. Resolving\n // here instead is one line and would additionally catch a policy class\n // whose constructor throws — at the price of constructing every policy\n // class in the application at `registerModels` time, ahead of whatever\n // config or container the constructor reaches for. A guard against a\n // policy that does nothing must not become the reason a working\n // application stops booting, so the cases that need an instance are left\n // to `policiesFor`, which is reached below, on the first query, and by\n // `Model.$exec`.\n assertPolicyShapes(model);\n\n const name = model.$schema.name;\n const registered = registry.has(name)\n ? (registry.get<unknown>(name) as object)\n : undefined;\n\n // Nothing registered under the name at all. The generated `index.ts`\n // registers every model, so reaching this means it was never imported —\n // a different mistake, and one the first query reports clearly through\n // `ModelNotRegisteredError`. Not this function's business.\n if (registered === undefined || registered === model) continue;\n\n const ours = policiesFor(model);\n const theirs = policiesFor(registered);\n const diverges =\n ours.length !== theirs.length ||\n ours.some((policy, index) => policy !== theirs[index]);\n\n // The two classes are on one prototype chain — a base and something\n // extending it — which is the arrangement almost every application has,\n // and the one this audit used to get wrong in both directions.\n //\n // `policiesFor` accumulates upwards, so a descendant's chain always\n // contains its ancestor's. What separates the two shapes is therefore\n // whether the **ancestor** carries anything of its own.\n if (descendsFrom(registered, model) || descendsFrom(model, registered)) {\n const ancestor = descendsFrom(model, registered) ? registered : model;\n const descendant = ancestor === registered ? model : registered;\n\n if (policiesFor(ancestor).length === 0) {\n // The ancestor contributes nothing, so the descendant is the first\n // class to carry a policy: it is not a view over the model, it *is*\n // the model. A generated base is the usual ancestor here, and a\n // hand-written intermediate behaves the same way.\n //\n // Registered already? Then this is the correct arrangement, and it\n // has to be skipped rather than reported — it used not to be, and\n // that is why the documented\n //\n // assertPoliciesRegistered(generated, models)\n //\n // threw the moment an application wrote its first policy: it walked\n // the generated namespace, found `UserModel` diverging from the\n // registered `User`, and refused the thing it exists to protect.\n // Being reachable through a base is not the bug; querying through one\n // is, and that is a property of a call site rather than of a module's\n // export list, so `Model.$exec` keeps that direction.\n if (registered === descendant) continue;\n\n // Neither class carries anything, so which one owns the name changes\n // no query's scope. An unregistered plain subclass is not a mistake.\n if (!diverges) continue;\n\n // Not registered, and it has policies: #316 itself. The policied\n // class is not the one the name resolves to, so every nested read\n // runs the ancestor and skips it.\n problems.push(\n new UnregisteredPolicyClassError(\n name,\n nameOf(registered),\n nameOf(model),\n ours.length > 0 ? \"queried\" : \"registered\",\n ),\n );\n continue;\n }\n\n // The ancestor carries policies of its own, so it is a registered model\n // in good standing and the descendant is narrowing it. The registry\n // holds one class per name: registering the view applies its narrowing\n // to every nested read, and leaving the ancestor registered skips the\n // view's policies entirely. Both are silent, so neither is chosen.\n if (diverges) {\n problems.push(\n new UnregisteredPolicyClassError(\n name,\n nameOf(ancestor),\n nameOf(descendant),\n \"narrowing\",\n ),\n );\n }\n\n // Same chain, same policies — a plain typed view. Nothing to report.\n continue;\n }\n\n if (!diverges) continue;\n\n // Unrelated classes claiming one name. Whichever is registered, the\n // other's policies are simply not in effect.\n problems.push(\n new UnregisteredPolicyClassError(\n name,\n nameOf(registered),\n nameOf(model),\n ours.length > 0 ? \"queried\" : \"registered\",\n ),\n );\n }\n }\n\n return problems;\n}\n\n/**\n * Registers every model class the given modules export, under the name each\n * one's schema carries, and then audits the result.\n *\n * ### The line this exists to delete\n *\n * `register(\"User\", User)` next to every subclass is a correct instruction and\n * a bad mechanism, because forgetting it is invisible. A relation read resolves\n * its target by name, so an unregistered policied subclass leaves the generated\n * base owning the name and every nested `include` of that model comes back\n * unscoped — no error, no warning, and an authorization hole in the direction\n * nobody checks. `assertPoliciesRegistered` turns that into a loud failure, but\n * only for someone who remembered to run it.\n *\n * Deriving the registration from the module removes the mistake instead of\n * reporting it. The name is not a string an author repeats; it is\n * `$schema.name`, which the generator wrote and the subclass inherits:\n *\n * import * as generated from \"./generated\"\n * import * as models from \"./models\"\n *\n * registerModels(generated, models)\n *\n * Later modules win, so the application's classes replace the generated bases\n * they extend. `register` still exists and still works — this is what an\n * application calls once instead of writing it thirteen times.\n *\n * ### What it still cannot see\n *\n * Modules it is handed. A policied class in a file nothing imports is invisible\n * to this exactly as it is to `assertPoliciesRegistered`, and closing *that*\n * would take the framework enumerating the filesystem at boot. Handing it a\n * barrel is the whole discipline: one file to add a model to, and the audit\n * covers everything in it.\n *\n * `Kernel.models` is that call, wired at boot, so an application declares its\n * model modules the way it already declares config slices and providers.\n */\nexport function registerModels(\n ...modules: Array<Record<string, unknown>>\n): void {\n // Elected into a local map first, and only committed once the audit passes.\n //\n // The registry is process-wide and outlives the throw. Registering as we went\n // meant a refused call left the arrangement it had just refused installed —\n // `registerModels({Ours}, {Theirs})` threw, and `\"User\"` resolved to `Theirs`\n // afterwards, which is the leaking mapping the audit exists to reject. A\n // server whose boot dies never notices; a dev server that catches and keeps\n // serving, or a test harness that continues past the error, serves the rest\n // of the process from it.\n const staged = new Map<string, ModelClass>();\n\n for (const module of modules) {\n const candidates = new Map<string, ModelClass[]>();\n\n // Deduped by identity first: `export { User }` alongside a default export\n // is the same class under two keys, not two classes competing for a name.\n for (const exported of new Set(Object.values(module))) {\n const model = asModelClass(exported);\n if (model === null) continue;\n\n const name = model.$schema.name;\n const existing = candidates.get(name);\n if (existing === undefined) candidates.set(name, [model]);\n else existing.push(model);\n }\n\n // Later modules win, which is what lets an application's classes replace\n // the generated bases they extend.\n for (const [name, classes] of candidates) {\n staged.set(name, elect(name, classes));\n }\n }\n\n // What the registry said before, so a failed audit can put it back. `register`\n // has no inverse, so a name that was previously *absent* cannot be made\n // absent again — it is left pointing at what this call elected. That is the\n // one residue, and it is the harmless direction: the alternative to a wrong\n // registration under a name nothing claimed is `ModelNotRegisteredError`, and\n // the class elected here is the one this module set would have used anyway.\n const previous = [...staged.keys()]\n .filter((name) => registry.has(name))\n .map((name) => [name, registry.get<unknown>(name)] as const);\n\n for (const [name, model] of staged) registry.register(name, model);\n\n try {\n assertPoliciesRegistered(...modules);\n } catch (error) {\n for (const [name, model] of previous) registry.register(name, model);\n throw error;\n }\n}\n\n/**\n * Which of several classes claiming one name in one module gets it.\n *\n * Two shapes put more than one candidate in a namespace, and they want opposite\n * answers, so neither \"most derived\" nor \"least derived\" is the rule on its\n * own:\n *\n * export * from \"./generated\" // UserModel, and\n * export class User extends UserModel { static $policies = [...] }\n *\n * wants the subclass — electing the base here *is* the leak, in the one file an\n * author most plausibly writes it in. While\n *\n * export class User extends UserModel { static $policies = [...] }\n * export class AdminUser extends User {}\n *\n * wants `User`. `AdminUser` is a typed view over the same rows; it inherits the\n * policies either way, so registering it changes nothing when it adds none and\n * silently applies its own narrowing to every nested read when it does.\n *\n * What separates them is which class the *generator* wrote. It emits\n * `static $schema = schema.User` on the base, and a subclass inherits that\n * property rather than declaring one — so an own `$schema` is the mark of a\n * generated base, and it is a fact about the classes rather than about the\n * order somebody exported them in. Application classes are preferred over\n * bases; among application classes the least derived wins, for the reason\n * `AdminUser` gives.\n *\n * When that leaves no single answer the candidates are unrelated classes with a\n * genuine claim each, and there is nothing left to infer. That case is refused\n * rather than guessed at: `register` says which, in the application's own\n * words.\n */\nfunction elect(name: string, classes: ModelClass[]): ModelClass {\n if (classes.length === 1) return classes[0]!;\n\n const written = classes.filter((candidate) => !isGeneratedBase(candidate));\n const eligible = written.length > 0 ? written : classes;\n\n if (eligible.length === 1) return eligible[0]!;\n\n const roots = eligible.filter((candidate) =>\n eligible.every(\n (other) => other === candidate || descendsFrom(other, candidate),\n ),\n );\n\n if (roots.length === 1) return roots[0]!;\n\n throw new AmbiguousModelRegistrationError(\n name,\n eligible.map((candidate) => nameOf(candidate)),\n );\n}\n\n/**\n * Whether the generator wrote this class, rather than an application extending\n * one it wrote.\n *\n * The generator marks its own output — `static $generated = true` on each\n * emitted base, and on nothing else — so for artifacts that carry the mark this\n * is a fact the generator stated rather than a property of how it happens to be\n * written. A subclass *inherits* the mark and does not own it, which is what\n * makes own-vs-inherited the whole test.\n *\n * ### The fallback, and why it is second\n *\n * `$schema` is also declared on the emitted base and inherited below it, so\n * owning *that* used to answer the same question, and it answered it wrongly for\n * one shape (#318): a subclass that redeclares `static $schema` — pointing at a\n * modified schema object, or by copy-paste — read as a base, every candidate\n * looked generated, and the least derived won. That did not pass quietly, since\n * `assertPoliciesRegistered` runs immediately after `elect` and refuses a\n * policied class that lost its name. But loud-and-wrong is still wrong, and the\n * silent half — a subclass with statics and row methods but no policies, whose\n * methods then never run inside a nested read — had nothing to refuse.\n *\n * The inference survives as the fallback for artifacts generated *before* the\n * mark existed, where it is the only signal there is. `\"$generated\" in candidate`\n * is what separates the two worlds: it walks the prototype chain, so it is true\n * for a marked base and for everything under it, and false for every class in an\n * app whose `app/models/generated` predates 0.51. Asking `Object.hasOwn` first\n * and falling back on `false` would send a subclass of a *marked* base back into\n * the inference — which is exactly the case the mark was added to fix.\n *\n * `registration.test.ts` in the template asserts the contract against real\n * generator output, because this is the one place a generator change could\n * quietly invalidate an assumption made here.\n */\nfunction isGeneratedBase(candidate: ModelClass): boolean {\n // Owning the mark, not merely having it — and owning it set to `true`. The\n // declared type is `?: true`, so TypeScript already refuses `false`; reading\n // the value anyway is what makes `static $generated = false` mean the thing\n // it plainly says in an app with no typechecking between it and here.\n if (\"$generated\" in candidate) {\n return (\n Object.hasOwn(candidate, \"$generated\") &&\n (candidate as { $generated?: unknown }).$generated === true\n );\n }\n\n return Object.hasOwn(candidate, \"$schema\");\n}\n\n/**\n * Whether `derived` has `base` in its static prototype chain — the `extends`\n * relation between two classes, walked on the constructor side because that is\n * where `$schema` and `$policies` live.\n */\nfunction descendsFrom(derived: unknown, base: unknown): boolean {\n let current = Object.getPrototypeOf(derived);\n\n while (current !== null && current !== Function.prototype) {\n if (current === base) return true;\n current = Object.getPrototypeOf(current);\n }\n\n return false;\n}\n\nfunction nameOf(value: unknown): string {\n return (value as { name?: string })?.name ?? String(value);\n}\n\n/**\n * A model class, structurally.\n *\n * Structural rather than `instanceof Model` on purpose: this module sits below\n * `Model.ts` in the import graph, and importing it here to answer a question\n * about shape would put a cycle between the registry, the policy hook and the\n * model base for no gain. `$schema` carrying a `name` is what every operation\n * already relies on.\n *\n * A module namespace holds anything the author exported — types erase, but\n * constants, helpers and re-exported values do not — so everything that is not\n * a model class is skipped rather than treated as an error.\n */\nfunction asModelClass(value: unknown): ModelClass | null {\n if (typeof value !== \"function\") return null;\n\n const schema = (value as { $schema?: ModelSchema }).$schema;\n if (schema === undefined || typeof schema.name !== \"string\") return null;\n\n return value as unknown as ModelClass;\n}\n"
|
|
8
8
|
],
|
|
9
|
-
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "6DEDF8CD485C3EB164756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import{m as j}from"./chunk-ppt296ye.js";import{createElement as a}from"react";function y(i,n){let s=Object.keys(n).sort((b,u)=>u.length-b.length).map((b)=>b.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")),r=new RegExp(s.join("|"),"g");return i.replace(r,(b)=>n[b])}async function L(i,n,s=[]){let r=[...s.map((t)=>`${i}/views/${t}.tsx`),`${i}/views/RootLayout.tsx`],b=new Set;for(let t of r){let e=n.moduleGraph.getModulesByFile(t);if(e)for(let g of e)b.add(g)}let u=[],p=[],c={};for(let t of b)if(t)for(let e of t.importedModules){if(e.file.includes("module.css"))c[e.file]=e.ssrTransformResult.map.sourcesContent.join("");if(e.file.includes(".css"))p.push(e.file)}for(let t of p){let e=await n.transformRequest(t+"?direct"),g=t.includes("module.css"),o="";if(g)o=y(c[t],e.default);u.push({isDev:!0,id:t,content:g?o:e.code})}return u.map((t,e)=>{return a("style",{key:e,type:"text/css","data-vite-dev-id":t.id,dangerouslySetInnerHTML:{__html:t.content}})})}async function N(i=[]){return i.map((n,s)=>{return a("style",{key:s,id:n?.id,type:"text/css",dangerouslySetInnerHTML:{__html:n.content}})})}import{existsSync as f}from"fs";import{basename as m}from"path";import{networkInterfaces as z}from"os";var h={name:"gemi",version:"0.53.0",private:!1,license:"MIT",author:"Enes Tufekci <enes@gemijs.dev>",repository:{type:"git",url:"git+https://github.com/nstfkc/gemi.git",directory:"packages/gemi"},bin:{gemi:"./dist/bin/gemi.js","gemi-orm-generator":"./dist/bin/orm-generator.js"},files:["dist/**/*"],module:!0,exports:{"./http":"./http/index.ts","./client":"./client/index.ts","./testing":"./testing/index.ts","./app":"./app/index.ts","./facades":"./facades/index.ts","./email":"./email/index.ts","./vite":"./dist/vite/index.mjs","./kernel":"./kernel/index.ts","./services":"./services/index.ts","./broadcasting":"./broadcasting/index.ts","./i18n":"./i18n/index.ts","./server":"./server/index.ts","./config":"./config/index.ts","./container":"./container/index.ts","./foundation":"./foundation/index.ts","./database":"./database/index.ts","./orm":"./orm/index.ts","./support":"./support/index.ts","./console/run":"./console/run.ts","./bun/preload":"./bun/preload.ts","./bun/plugin":"./bun/plugin.ts"},scripts:{lint:"oxlint",typecheck:"tsc --noEmit -p tsconfig.json",build:"NODE_ENV=production bun run build:core && bun run build:bin && bun run build:types && bun run build:client && bun run build:plugin && bun run build:client-types","build:core":"bun ./scripts/build.ts","build:bin":"bun build --outdir=./dist/bin --target=bun --external=vite --external=react-dom --external=react/jsx-runtime --external=bun --external=sharp --external=@azure/storage-blob --sourcemap ./bin/gemi.ts ./bin/orm-generator.ts && bun ./scripts/prepare-bin.ts","build:client":"rm -rf dist/client dist/testing dist/chunks && vite build -c vite.client.config.mts","build:plugin":"vite build -c vite.plugin.config.mts","build:types":"tsc","build:client-types":"tsc -p tsconfig.browser.json",test:"bun --bun vitest","test:types":"vitest run --typecheck.only","build:publish":"bun scripts/build-publish.ts",prepublishOnly:"echo 'Do not publish from this directory \u2014 its exports point at TS source. Run: bun run build:publish, then publish from .publish/' && exit 1"},dependencies:{"@aws-sdk/client-s3":"^3.629.0","@aws-sdk/s3-request-presigner":"^3.629.0","ast-types":"^0.14.2",commander:"^12.1.0",history:"^5.3.0","jsx-email":"2.0.0-rc2.1",open:"^10.1.0","react-error-boundary":"^6.0.0",recast:"^0.23.9",resend:"^6.12.3",satori:"^0.12.2","temporal-polyfill":"^0.2.5","twitter-api-v2":"^1.20.2","urlpattern-polyfill":"^10.0.0",uuid:"^9.0.1"},devDependencies:{"@babel/parser":"^7.25.4","@prisma/generator-helper":"^6.5.0","@repo/typescript-config":"*","@testing-library/react":"^16.3.2","@types/bun":"^1.3.14","@types/eslint":"^8.56.5","@types/node":"^20.11.24","@types/react":"^19.0.2","@types/react-dom":"^19.0.2",eslint:"^8.57.0",jsdom:"^30.0.1",oxlint:"^1.39.0",react:"19.2.3","react-dom":"19.2.3",typescript:"^5.7.3",vitest:"^4.0.0"},peerDependencies:{"@azure/storage-blob":"^12.28.0",react:">=19","react-dom":">=19",sharp:"^0.34.2",vite:"^8.0.0"},peerDependenciesMeta:{"@azure/storage-blob":{optional:!0}}};var k=[" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551","\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551","\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551"," \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D"],O=Boolean(process.stdout.isTTY)&&!process.env.NO_COLOR,d=(i,n)=>O?`\x1B[${i}m${n}\x1B[0m`:n,T=(i)=>d("1",i),l=(i)=>d("2",i),x=(i)=>d("36",i),q=(i)=>d("32",i),_=(i)=>d("35",i);function E(){return h.version??"?"}function G(i){for(let n of Object.values(z()))for(let s of n??[])if((s.family==="IPv4"||s.family===4)&&!s.internal)return`http://${s.address}:${i}`;return null}function H(i){return j(i).filter((n)=>f(n)).map((n)=>m(n))}function A(i){let{port:n,rootDir:s}=i,r=`http://localhost:${n}`,b=G(n),u=H(s),p=(t,e)=>` ${q("\u279C")} ${T(t.padEnd(9))}${e}`,c=["",...k.map((t)=>_(t)),"",` ${l("gemi")} ${x(`v${E()}`)}`,"",p("Local:",x(r)),p("Network:",b?x(b):l("unavailable")),p("Env:",u.length?u.join(", "):l("none")),""];console.log(c.join(`
|
|
3
|
+
`))}
|
|
4
|
+
export{L as b,N as c,A as d};
|
|
5
|
+
|
|
6
|
+
//# debugId=C06770E4D796E3EE64756E2164756E21
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"import { createElement } from \"react\";\nimport { type ModuleNode, type ViteDevServer } from \"vite\";\n\nfunction replaceStrings(text: string, record: Record<string, string>): string {\n const escapedKeys = Object.keys(record)\n .sort((a, b) => b.length - a.length)\n .map((key) => key.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\n\n // Create a single regex with all keys\n const regex = new RegExp(escapedKeys.join(\"|\"), \"g\");\n\n return text.replace(regex, (match) => record[match]);\n}\n\nexport async function createDevStyles(\n appDir: string,\n vite: ViteDevServer,\n currentViews: string[] = [],\n) {\n const views = [\n ...currentViews.map((view) => `${appDir}/views/${view}.tsx`),\n `${appDir}/views/RootLayout.tsx`,\n ];\n\n const modules = new Set<ModuleNode>();\n for (const view of views) {\n const mod = vite.moduleGraph.getModulesByFile(view);\n if (mod) {\n for (const m of mod) modules.add(m);\n }\n }\n\n const styles = [];\n const cssModules = [];\n const cssModuleContent: Record<string, string> = {};\n for (const mod of modules as any) {\n if (mod) {\n for (const imported of mod.importedModules) {\n if (imported.file.includes(\"module.css\")) {\n cssModuleContent[imported.file] = imported.ssrTransformResult.map.sourcesContent.join(\"\");\n }\n if (imported.file.includes(\".css\")) {\n cssModules.push(imported.file);\n }\n }\n }\n }\n\n for (const cssModulePath of cssModules) {\n const transform = await vite.transformRequest(cssModulePath + \"?direct\");\n\n const isCssModule = cssModulePath.includes(\"module.css\");\n\n let transformedCssModule = \"\";\n\n if (isCssModule) {\n transformedCssModule = replaceStrings(\n cssModuleContent[cssModulePath],\n // Vite's `TransformResult` type has no `default`, but the CSS-module\n // transform attaches the class-name mapping there at runtime.\n (transform as unknown as { default: Record<string, string> }).default,\n );\n }\n\n styles.push({\n isDev: true,\n id: cssModulePath,\n content: isCssModule ? transformedCssModule : transform.code,\n });\n }\n\n return styles.map((style, i) => {\n return createElement(\"style\", {\n key: i,\n type: \"text/css\",\n \"data-vite-dev-id\": style.id,\n dangerouslySetInnerHTML: { __html: style.content },\n });\n });\n}\n\nexport async function createStyles(styles = []) {\n return styles.map((style, i) => {\n return createElement(\"style\", {\n key: i,\n id: style?.id,\n type: \"text/css\",\n dangerouslySetInnerHTML: { __html: style.content },\n });\n });\n}\n",
|
|
6
6
|
"import { existsSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { networkInterfaces } from \"node:os\";\nimport { envFiles } from \"./watchEnv\";\nimport pkg from \"../package.json\";\n\n// \"GEMI\" — ANSI Shadow figlet font.\nconst ART = [\n \" ██████╗ ███████╗███╗ ███╗██╗\",\n \"██╔════╝ ██╔════╝████╗ ████║██║\",\n \"██║ ███╗█████╗ ██╔████╔██║██║\",\n \"██║ ██║██╔══╝ ██║╚██╔╝██║██║\",\n \"╚██████╔╝███████╗██║ ╚═╝ ██║██║\",\n \" ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝\",\n];\n\nconst useColor = Boolean(process.stdout.isTTY) && !process.env.NO_COLOR;\nconst paint = (code: string, text: string) =>\n useColor ? `\\x1b[${code}m${text}\\x1b[0m` : text;\nconst bold = (t: string) => paint(\"1\", t);\nconst dim = (t: string) => paint(\"2\", t);\nconst cyan = (t: string) => paint(\"36\", t);\nconst green = (t: string) => paint(\"32\", t);\nconst magenta = (t: string) => paint(\"35\", t);\n\nfunction gemiVersion(): string {\n return (pkg as { version?: string }).version ?? \"?\";\n}\n\nfunction networkUrl(port: number | string): string | null {\n for (const ifaces of Object.values(networkInterfaces())) {\n for (const iface of ifaces ?? []) {\n // Node <18 reported `family` as the number 4; newer Bun/Node use \"IPv4\".\n const isV4 = iface.family === \"IPv4\" || (iface.family as unknown) === 4;\n if (isV4 && !iface.internal) return `http://${iface.address}:${port}`;\n }\n }\n return null;\n}\n\nfunction loadedEnvFiles(rootDir: string): string[] {\n return envFiles(rootDir)\n .filter((file) => existsSync(file))\n .map((file) => basename(file));\n}\n\nexport function printStartupBanner(params: {\n port: number | string;\n rootDir: string;\n}) {\n const { port, rootDir } = params;\n const local = `http://localhost:${port}`;\n const network = networkUrl(port);\n const env = loadedEnvFiles(rootDir);\n\n const row = (label: string, value: string) =>\n ` ${green(\"➜\")} ${bold(label.padEnd(9))}${value}`;\n\n const out = [\n \"\",\n ...ART.map((line) => magenta(line)),\n \"\",\n ` ${dim(\"gemi\")} ${cyan(`v${gemiVersion()}`)}`,\n \"\",\n row(\"Local:\", cyan(local)),\n row(\"Network:\", network ? cyan(network) : dim(\"unavailable\")),\n row(\"Env:\", env.length ? env.join(\", \") : dim(\"none\")),\n \"\",\n ];\n\n console.log(out.join(\"\\n\"));\n}\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";wCAAA,wBAAS,cAGT,SAAS,CAAc,CAAC,EAAc,EAAwC,CAC5E,IAAM,EAAc,OAAO,KAAK,CAAM,EACnC,KAAK,CAAC,EAAG,IAAM,EAAE,OAAS,EAAE,MAAM,EAClC,IAAI,CAAC,IAAQ,EAAI,QAAQ,sBAAuB,MAAM,CAAC,EAGpD,EAAQ,IAAI,OAAO,EAAY,KAAK,GAAG,EAAG,GAAG,EAEnD,OAAO,EAAK,QAAQ,EAAO,CAAC,IAAU,EAAO,EAAM,EAGrD,eAAsB,CAAe,CACnC,EACA,EACA,EAAyB,CAAC,EAC1B,CACA,IAAM,EAAQ,CACZ,GAAG,EAAa,IAAI,CAAC,IAAS,GAAG,WAAgB,OAAU,EAC3D,GAAG,wBACL,EAEM,EAAU,IAAI,IACpB,QAAW,KAAQ,EAAO,CACxB,IAAM,EAAM,EAAK,YAAY,iBAAiB,CAAI,EAClD,GAAI,EACF,QAAW,KAAK,EAAK,EAAQ,IAAI,CAAC,EAItC,IAAM,EAAS,CAAC,EACV,EAAa,CAAC,EACd,EAA2C,CAAC,EAClD,QAAW,KAAO,EAChB,GAAI,EACF,QAAW,KAAY,EAAI,gBAAiB,CAC1C,GAAI,EAAS,KAAK,SAAS,YAAY,EACrC,EAAiB,EAAS,MAAQ,EAAS,mBAAmB,IAAI,eAAe,KAAK,EAAE,EAE1F,GAAI,EAAS,KAAK,SAAS,MAAM,EAC/B,EAAW,KAAK,EAAS,IAAI,EAMrC,QAAW,KAAiB,EAAY,CACtC,IAAM,EAAY,MAAM,EAAK,iBAAiB,EAAgB,SAAS,EAEjE,EAAc,EAAc,SAAS,YAAY,EAEnD,EAAuB,GAE3B,GAAI,EACF,EAAuB,EACrB,EAAiB,GAGhB,EAA6D,OAChE,EAGF,EAAO,KAAK,CACV,MAAO,GACP,GAAI,EACJ,QAAS,EAAc,EAAuB,EAAU,IAC1D,CAAC,EAGH,OAAO,EAAO,IAAI,CAAC,EAAO,IAAM,CAC9B,OAAO,EAAc,QAAS,CAC5B,IAAK,EACL,KAAM,WACN,mBAAoB,EAAM,GAC1B,wBAAyB,CAAE,OAAQ,EAAM,OAAQ,CACnD,CAAC,EACF,EAGH,eAAsB,CAAY,CAAC,EAAS,CAAC,EAAG,CAC9C,OAAO,EAAO,IAAI,CAAC,EAAO,IAAM,CAC9B,OAAO,EAAc,QAAS,CAC5B,IAAK,EACL,GAAI,GAAO,GACX,KAAM,WACN,wBAAyB,CAAE,OAAQ,EAAM,OAAQ,CACnD,CAAC,EACF,ECzFH,qBAAS,WACT,mBAAS,aACT,4BAAS,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "C06770E4D796E3EE64756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Fb as G}from"./chunk-ttzkn1qd.js";import{
|
|
2
|
+
import{Fb as G}from"./chunk-ttzkn1qd.js";import{Mc as z,Oc as E,fd as F}from"./chunk-tkv6cw94.js";import{Ce as B}from"./chunk-3y9nf09k.js";class J extends G{register(){this.app.singleton(z,()=>{let j=new z(B(E(),this.app.config.get("database",{})));return K(j),j})}}function K(j){if(Bun.env.NODE_ENV!=="development")return;for(let x of j.connectionNames){let A=j.connection(x);if(F(A.dialect))continue;let H=x===j.name?"DATABASE_URL":`The "${x}" database connection`;console.warn(`[gemi] ${H} points at ${A.dialect}, which the gemi ORM `+"does not implement \u2014 only sqlite and postgres are. The connection "+`works, so raw SQL through DB.query / DB.sql and transactions are fine, but every model operation will raise UnsupportedDialectError.
|
|
3
3
|
(development only)`)}}
|
|
4
4
|
export{J as p};
|
|
5
5
|
|
|
6
|
-
//# debugId=
|
|
6
|
+
//# debugId=DA5840EA47FEDD4B64756E2164756E21
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
"import { ormSupports } from \"../orm/dialect\";\nimport { ServiceProvider } from \"../support/ServiceProvider\";\nimport { withDefaults } from \"../support/withDefaults\";\nimport { databaseConfigDefaults, type DatabaseConfig } from \"./config\";\nimport { DatabaseManager } from \"./DatabaseManager\";\n\nexport class DatabaseServiceProvider extends ServiceProvider {\n register() {\n this.app.singleton(\n DatabaseManager,\n () => {\n const database = new DatabaseManager(\n withDefaults(\n databaseConfigDefaults(),\n this.app.config.get<DatabaseConfig>(\"database\", {}),\n ),\n );\n\n warnIfOrmUnavailable(database);\n return database;\n },\n );\n }\n}\n\n/**\n * Say it at boot, not on the first model query.\n *\n * `DatabaseManager` connects to MySQL and MariaDB without complaint — Bun's\n * client speaks them — and the ORM's compiler has no dialect for either. So a\n * deploy pointed at one starts, passes a health check, serves whatever does not\n * touch a model, and raises `UnsupportedDialectError` on the first `findMany`.\n * That is the latest and most expensive moment to learn it.\n *\n * A **warning rather than a throw**, deliberately: raw SQL through `DB.query`\n * and `DB.sql` genuinely works on those dialects, and so do transactions.\n * Refusing to construct the manager would break code that is correct today to\n * pre-empt an error the ORM already raises clearly. The supported set is a\n * property of the query compiler, not of the connection.\n *\n * Development only, for the same reason the slow-transaction warning is: it is\n * a diagnostic aimed at whoever is choosing the database, and it should not\n * add noise to a production log every time the container starts.\n */\nfunction warnIfOrmUnavailable(database: DatabaseManager): void {\n if (process.env.NODE_ENV !== \"development\") return;\n\n // Every connection, not only the default one. A named connection is a whole\n // pool an application will run model queries on — `Model.on(\"analytics\")` —\n // so it can be pointed at MySQL exactly as the default can, and warning about\n // only one of them would make the check pass while the query that raises is\n // on the other.\n for (const name of database.connectionNames) {\n const connection = database.connection(name);\n if (ormSupports(connection.dialect)) continue;\n\n const source =\n name === database.name\n ? \"DATABASE_URL\"\n : `The \"${name}\" database connection`;\n\n console.warn(\n `[gemi] ${source} points at ${connection.dialect}, which the gemi ORM ` +\n `does not implement — only sqlite and postgres are. The connection ` +\n `works, so raw SQL through DB.query / DB.sql and transactions are ` +\n `fine, but every model operation will raise ` +\n `UnsupportedDialectError.\\n(development only)`,\n );\n }\n}\n"
|
|
6
6
|
],
|
|
7
7
|
"mappings": ";uJAMO,AAAM,IAAgC,CAAgB,CAC3D,QAAQ,EAAG,CACT,KAAK,IAAI,UACP,EACA,IAAM,CACJ,IAAM,EAAW,IAAI,EACnB,EACE,EAAuB,EACvB,KAAK,IAAI,OAAO,IAAoB,WAAY,CAAC,CAAC,CACpD,CACF,EAGA,OADA,EAAqB,CAAQ,EACtB,EAEX,EAEJ,CAqBA,SAAS,CAAoB,CAAC,EAAiC,CAC7D,GAAI,mBAAyB,cAAe,OAO5C,QAAW,KAAQ,EAAS,gBAAiB,CAC3C,IAAM,EAAa,EAAS,WAAW,CAAI,EAC3C,GAAI,EAAY,EAAW,OAAO,EAAG,SAErC,IAAM,EACJ,IAAS,EAAS,KACd,eACA,QAAQ,yBAEd,QAAQ,KACN,UAAU,eAAoB,EAAW,+BACvC,0EACA;AAAA,mBAGJ",
|
|
8
|
-
"debugId": "
|
|
8
|
+
"debugId": "DA5840EA47FEDD4B64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{ke as X,ue as k}from"./chunk-4t6a82fh.js";class S extends Error{constructor(z){super(`Could not infer a database dialect from "${z}". Expected a URL starting with postgres://, postgresql://, mysql://, mariadb://, `+"sqlite://, or file: \u2014 or a SQLite path such as ./dev.db or :memory:.");this.name="UnknownDatabaseUrlError"}}class U extends Error{constructor(z){super(z===void 0||z==="default"?"No database URL configured. Set the DATABASE_URL environment variable, or set `url` in app/config/database.ts.":`The "${z}" database connection has no \`url\`. Set one under \`connections.${z}\` in app/config/database.ts.`);this.name="MissingDatabaseUrlError"}}var D={"postgres:":"postgres","postgresql:":"postgres","mysql:":"mysql","mariadb:":"mariadb","sqlite:":"sqlite","file:":"sqlite"},h=[".db",".sqlite",".sqlite3"];function N(z){let G=z.trim();if(G==="")throw new S(z);if(G===":memory:")return"sqlite";let V=G.indexOf(":");if(V!==-1){let Y=G.slice(0,V+1).toLowerCase(),$=D[Y];if($)return $}if(y(G))return"sqlite";throw new S(z)}function y(z){if(z.startsWith("./")||z.startsWith("../")||z.startsWith("/"))return!0;let G=z.toLowerCase();return h.some((V)=>G.endsWith(V))}function o(z){return z==="sqlite"}function i(z){return z==="mysql"||z==="mariadb"}var{SQL:L}=globalThis.Bun;var Q="default";class R extends Error{constructor(z,G){super(`No database connection named "${z}". Configured: ${G.map((V)=>`"${V}"`).join(", ")}. Declare it under \`connections\` in app/config/database.ts.`);this.name="UnknownConnectionError"}}class b extends Error{constructor(z){super(`"${z}" is the name of the connection declared by the top-level \`url\` and \`options\`, so it cannot also appear under \`connections\`. Rename it, or move its settings up to the top level.`);this.name="ReservedConnectionNameError"}}class E extends Error{open;requested;constructor(z,G){super(`A transaction is open on the "${z}" connection, and this statement names "${G}". A transaction cannot span two connections: the statement would run outside it and stay committed when the transaction rolls back. Move this query outside the transaction, or run the whole unit on one connection.`);this.open=z;this.requested=G;this.name="CrossConnectionTransactionError"}}class P{name;config;sql;dialect;url;ready;constructor(z,G={}){this.name=z;this.config=G;let V=G.url;if(!V)throw new U(z);this.url=V,this.dialect=G.dialect??N(V),this.sql=G.options?new L(V,G.options):new L(V),this.ready=this.configure()}async configure(){if(this.dialect!=="sqlite")return;await this.sql.unsafe("pragma foreign_keys = ON")}get query(){return this.sql}async close(){this.ready.catch(()=>{}),await this.sql.close()}}class g{config;static token="database";name=Q;pools=new Map;ready;constructor(z={}){this.config=z;let{connections:G={},...V}=z;this.pools.set(Q,new P(Q,V));try{this.build(G,V.slowTransactionThreshold)}catch(Y){for(let $ of this.pools.values())$.ready.catch(()=>{}),$.close().catch(()=>{});throw Y}this.ready=Promise.all([...this.pools.values()].map((Y)=>Y.ready)).then(()=>{return})}build(z,G){for(let[V,Y]of Object.entries(z)){if(V===Q)throw new b(V);this.pools.set(V,new P(V,{slowTransactionThreshold:G,...Y}))}}connection(z=Q){if(z===Q)return this;let G=this.pools.get(z);if(!G)throw new R(z,this.connectionNames);return G}get connectionNames(){return[...this.pools.keys()]}get sql(){return this.default.sql}get dialect(){return this.default.dialect}get url(){return this.default.url}get query(){return this.sql}async close(){this.ready.catch(()=>{}),await Promise.all([...this.pools.values()].map((z)=>z.close()))}get default(){return this.pools.get(Q)}}function e(z){return z}function zz(){return{url:process.env.DATABASE_URL,dialect:void 0,options:void 0,slowTransactionThreshold:x,connections:void 0}}var x=2000;function Yz(){return{now:new Date,resolved:{}}}var f={now:new Date(0),resolved:{}};function Zz(z){return(G,V=f)=>{let Y=[];for(let $=0;$<z.length;$++)Y.push(z[$](G,V));return Y}}var I="\x00";function B(z){return{text:z,binders:[]}}function J(z,G=""){return{text:I+G,binders:[z]}}function $z(z){return z.text.split(I)}function Bz(z,G){return{text:z.join(I),binders:G}}function W(...z){return C(z,"")}function C(z,G){let V="",Y=[];for(let $=0;$<z.length;$++){if($>0)V+=G;V+=z[$].text;for(let Z of z[$].binders)Y.push(Z)}return{text:V,binders:Y}}function Wz(z,G,V){let Y=z.text.split(I),$=Y.length-1;if($!==z.binders.length)throw Error(`Compiled ${$} parameter placeholders but collected ${z.binders.length} binders.`);if($>G.maxBoundParameters)throw new k(V.model,V.operation,$,G.maxBoundParameters,G.name,G.bindsListAsOneParameter?"That is one parameter per value in the statement.":`That is one parameter per value, and on ${G.name} each element of an 'in' list counts separately.`);let Z=Y[0];for(let H=0;H<$;H++)Z+=G.placeholder(H)+Y[H+1];return{text:Z,binders:z.binders}}class F{name="postgres";supportsInsensitiveMode=!0;bindsListAsOneParameter=!0;supportsReturning=!0;maxBoundParameters=65535;typesParametersFromStatement=!0;quoteIdent(z){if(z.includes("\x00"))throw Error(`Refusing to quote the identifier ${JSON.stringify(z)}: it contains a NUL byte, which is reserved as the parameter marker.`);return`"${z.replace(/"/g,'""')}"`}placeholder(z){return`$${z+1}`}inList(z,G,V,Y){return W(B(`${z} ${G?"<> all":"= any"} (`),J((Z,H)=>K(Y(Z,H))),B(")"))}static COMPOSITE_IN_TYPES={Int:"int",BigInt:"bigint",String:"text",Boolean:"boolean"};canBindCompositeIn(z){return z.length>0&&z.every((G)=>F.COMPOSITE_IN_TYPES[G])}compositeIn(z,G,V){let Y=z.map(($,Z)=>W(J((H,j)=>K(V(H,j).map((_)=>_[Z]))),B(`::${F.COMPOSITE_IN_TYPES[G[Z]]}[]`)));return W(B(`(${z.join(", ")}) in (select * from unnest(`),...Y.flatMap(($,Z)=>Z===0?[$]:[B(", "),$]),B("))"))}listFilters=new Set(["equals","has","hasEvery","hasSome","isEmpty"]);listHas(z,G){return W(G,B(` = any(${z})`))}listHasEvery(z,G){return W(B(`${z} @> `),G)}listHasSome(z,G){return W(B(`${z} && `),G)}listIsEmpty(z,G){return W(B(`${z} ${G?"=":"<>"} `),J(()=>K([])))}listPush(z,G){return W(B(`array_cat(${z}, `),G,B(")"))}jsonPathSyntax="array";jsonFilters=new Set(["equals","not","string_contains","string_starts_with","string_ends_with","array_contains","lt","lte","gt","gte"]);jsonComparesAsText=!0;jsonExtract(z,G,V){return W(B(`${z} ${V?"#>>":"#>"} `),J((Y,$)=>K(G(Y,$))))}jsonArrayContains(z,G,V){return W(B("("),this.jsonExtract(z,G,!1),B(") @> "),J((Y,$)=>{let Z=V(Y,$);if(Z===null||Z===void 0)return null;return typeof Z==="string"||typeof Z==="object"?Z:JSON.stringify(Z)}),B("::jsonb"))}like(z,G,V){return W(B(`${z} ${G?"ilike":"like"} `),J(V))}ignoreConflicts(){return B(" on conflict do nothing")}paginate(z,G){let V=[];if(z)V.push(W(B(" limit "),J(z)));if(G)V.push(W(B(" offset "),J(G)));return W(...V)}constraintViolation(z){let G=z;if(!G)return null;if(String(G.errno??G.code??"")!=="23505")return null;let Y=typeof G.constraint==="string"&&G.constraint!==""?G.constraint:void 0,$=typeof G.detail==="string"?G.detail:"",Z=/\((.+?)\)=/.exec($);return{kind:"unique",columns:Z?Z[1].split(",").map((j)=>j.trim()).filter((j)=>j!==""):[],constraint:Y}}castParameter(z){if(z.isList)return"";return z.type==="Json"?"::text::jsonb":""}encode(z,G){if(z===null||z===void 0)return null;if(G.isList){if(!Array.isArray(z))throw Error(`gemi ORM bug: a non-array reached the parameter binder for the scalar list '${G.column}' (received ${typeof z}). Every path that binds a list is supposed to have checked its operand.`);return K(G.type==="Json"?z.map((V)=>V===null||V===void 0?null:JSON.stringify(V)):z)}return z}encodeUntyped(z){return z}needsDecode(z){return z.isList===!0||z.type==="BigInt"||z.type==="Bytes"}decode(z,G){if(z===null||z===void 0)return null;if(G.isList)return this.decodeList(z,G);return this.decodeScalar(z,G)}decodeList(z,G){let V=Array.isArray(z)?z:typeof z==="string"?m(z,G):ArrayBuffer.isView(z)?Array.from(z):null;if(V===null)throw new X(G,z);return V.map((Y)=>Y===null||Y===void 0?null:this.decodeScalar(Y,G))}decodeScalar(z,G){switch(G.type){case"BigInt":if(typeof z==="bigint")return z;try{return BigInt(z)}catch{throw new X(G,z)}case"Json":return z;case"Bytes":return Buffer.isBuffer(z)?new Uint8Array(z.buffer,z.byteOffset,z.byteLength):z;default:return z}}}function K(z){let G="{";for(let V=0;V<z.length;V++){if(V>0)G+=",";G+=p(z[V])}return G+"}"}function p(z){if(z===null||z===void 0)return"NULL";if(z instanceof Date)return`"${z.toISOString()}"`;if(ArrayBuffer.isView(z)){let V="";for(let Y of new Uint8Array(z.buffer,z.byteOffset,z.byteLength))V+=Y.toString(16).padStart(2,"0");return`"\\\\x${V}"`}return`"${(typeof z==="string"?z:String(z)).replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function m(z,G){if(!z.startsWith("{")||!z.endsWith("}"))throw new X(G,z);if(z==="{}")return[];let V=[],Y=1,$=z.length-1;while(Y<=$){let Z="",H=!1;if(z[Y]==='"'){H=!0,Y++;while(Y<$&&z[Y]!=='"')Z+=z[Y]==="\\"?z[++Y]:z[Y],Y++;Y++}else while(Y<$&&z[Y]!==","){if(z[Y]==="{")throw new X(G,z);Z+=z[Y],Y++}if(V.push(!H&&Z.toUpperCase()==="NULL"?null:Z),Y<$&&z[Y]!==",")throw new X(G,z);Y++}if(G.type!=="Json")return V;return V.map((Z)=>{if(Z===null)return null;try{return JSON.parse(Z)}catch{throw new X(G,Z)}})}var c={"Prisma.DbNull":"db","Prisma.JsonNull":"json","Prisma.AnyNull":"any"};function O(z){return new class{toString(){return z}}}var jz=O("Prisma.DbNull"),d=O("Prisma.JsonNull"),Kz=O("Prisma.AnyNull"),Fz=d;function T(z){if(typeof z!=="object"||z===null)return null;for(let V in z)return null;if(Object.getOwnPropertyNames(z).length>0)return null;let G;try{G=String(z)}catch{return null}return c[G]??null}var v=/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(\.\d+)?$/;function s(z,G){if(z instanceof Date)return z;let V;if(typeof z==="number")V=new Date(z);else if(typeof z==="bigint")V=new Date(Number(z));else if(typeof z==="string")V=new Date(v.test(z)?`${z.replace(" ","T")}Z`:z);else throw new X(G,z);if(Number.isNaN(V.getTime()))throw new X(G,z);return V}class w{name="sqlite";supportsInsensitiveMode=!1;bindsListAsOneParameter=!1;supportsReturning=!0;maxBoundParameters=32766;typesParametersFromStatement=!1;quoteIdent(z){if(z.includes("\x00"))throw Error(`Refusing to quote the identifier ${JSON.stringify(z)}: it contains a NUL byte, which is reserved as the parameter marker.`);return`"${z.replace(/"/g,'""')}"`}placeholder(z){return"?"}inList(z,G,V,Y){let $=G?"not in":"in",Z=[];for(let H=0;H<V;H++)Z.push(J((j,_)=>Y(j,_)[H]));return W(B(`${z} ${$} (`),C(Z,", "),B(")"))}canBindCompositeIn(){return!1}compositeIn(){throw Error("SQLite cannot bind a composite `in`; `canBindCompositeIn` is the guard.")}listFilters=new Set;listHas(){throw Error(M("has"))}listHasEvery(){throw Error(M("hasEvery"))}listHasSome(){throw Error(M("hasSome"))}listIsEmpty(){throw Error(M("isEmpty"))}listPush(){throw Error(M("push"))}jsonPathSyntax="jsonpath";jsonFilters=new Set(["equals","not","string_contains","string_starts_with","string_ends_with"]);jsonComparesAsText=!1;jsonExtract(z,G,V){return W(B(`json_extract(${z}, `),J(G),B(")"))}jsonArrayContains(){throw Error("SQLite cannot express array_contains; `jsonFilters` is the guard.")}like(z,G,V){return W(B(`${z} like `),J(V))}ignoreConflicts(){return null}paginate(z,G){if(!z&&!G)return B("");if(!G)return W(B(" limit "),J(z));return W(B(" limit "),J(z??(()=>-1)),B(" offset "),J(G))}constraintViolation(z){let G=z?.code;if(G!=="SQLITE_CONSTRAINT_UNIQUE"&&G!=="SQLITE_CONSTRAINT_PRIMARYKEY")return null;let V=String(z.message??""),Y=/constraint failed:\s*(.+)$/.exec(V);if(!Y)return{kind:"unique",columns:[]};return{kind:"unique",columns:Y[1].split(",").map((Z)=>Z.trim()).map((Z)=>{let H=Z.indexOf(".");return H===-1?Z:Z.slice(H+1)}).filter((Z)=>Z!=="")}}castParameter(z){return""}encode(z,G){if(z===null||z===void 0)return null;switch(G.type){case"DateTime":return z instanceof Date?z.getTime():z;case"Boolean":return typeof z==="boolean"?z?1:0:z;case"Json":{let V=T(z);if(V==="db")return null;if(V==="json")return"null";if(V==="any")throw Error("gemi ORM bug: Prisma.AnyNull reached the SQLite encoder. It is a filter operand only, and both the filter and write paths are supposed to have handled it before this point.")}return JSON.stringify(z);default:return z}}encodeUntyped(z){if(z instanceof Date)return z.getTime();if(typeof z==="boolean")return z?1:0;return z}needsDecode(z){switch(z.type){case"DateTime":case"Boolean":case"BigInt":case"Json":return!0;default:return!1}}decode(z,G){if(z===null||z===void 0)return null;switch(G.type){case"DateTime":return s(z,G);case"Boolean":if(typeof z==="boolean")return z;return Number(z)!==0;case"BigInt":if(typeof z==="bigint")return z;try{return BigInt(z)}catch{throw new X(G,z)}case"Json":try{return typeof z==="string"?JSON.parse(z):z}catch{throw new X(G,z)}default:return z}}}function M(z){return`SQLite has no array type, so it cannot express '${z}' on a scalar list; \`listFilters\` is the guard.`}class q extends Error{constructor(z){super(`The gemi ORM does not support the '${z}' dialect. Only sqlite `+"and postgres are implemented \u2014 see the supported matrix in "+`docs/orm.md.
|
|
2
|
+
import{je as X,te as k}from"./chunk-cg53h5ht.js";class S extends Error{constructor(z){super(`Could not infer a database dialect from "${z}". Expected a URL starting with postgres://, postgresql://, mysql://, mariadb://, `+"sqlite://, or file: \u2014 or a SQLite path such as ./dev.db or :memory:.");this.name="UnknownDatabaseUrlError"}}class U extends Error{constructor(z){super(z===void 0||z==="default"?"No database URL configured. Set the DATABASE_URL environment variable, or set `url` in app/config/database.ts.":`The "${z}" database connection has no \`url\`. Set one under \`connections.${z}\` in app/config/database.ts.`);this.name="MissingDatabaseUrlError"}}var D={"postgres:":"postgres","postgresql:":"postgres","mysql:":"mysql","mariadb:":"mariadb","sqlite:":"sqlite","file:":"sqlite"},h=[".db",".sqlite",".sqlite3"];function N(z){let G=z.trim();if(G==="")throw new S(z);if(G===":memory:")return"sqlite";let V=G.indexOf(":");if(V!==-1){let Y=G.slice(0,V+1).toLowerCase(),$=D[Y];if($)return $}if(y(G))return"sqlite";throw new S(z)}function y(z){if(z.startsWith("./")||z.startsWith("../")||z.startsWith("/"))return!0;let G=z.toLowerCase();return h.some((V)=>G.endsWith(V))}function o(z){return z==="sqlite"}function i(z){return z==="mysql"||z==="mariadb"}var{SQL:L}=globalThis.Bun;var Q="default";class R extends Error{constructor(z,G){super(`No database connection named "${z}". Configured: ${G.map((V)=>`"${V}"`).join(", ")}. Declare it under \`connections\` in app/config/database.ts.`);this.name="UnknownConnectionError"}}class b extends Error{constructor(z){super(`"${z}" is the name of the connection declared by the top-level \`url\` and \`options\`, so it cannot also appear under \`connections\`. Rename it, or move its settings up to the top level.`);this.name="ReservedConnectionNameError"}}class E extends Error{open;requested;constructor(z,G){super(`A transaction is open on the "${z}" connection, and this statement names "${G}". A transaction cannot span two connections: the statement would run outside it and stay committed when the transaction rolls back. Move this query outside the transaction, or run the whole unit on one connection.`);this.open=z;this.requested=G;this.name="CrossConnectionTransactionError"}}class P{name;config;sql;dialect;url;ready;constructor(z,G={}){this.name=z;this.config=G;let V=G.url;if(!V)throw new U(z);this.url=V,this.dialect=G.dialect??N(V),this.sql=G.options?new L(V,G.options):new L(V),this.ready=this.configure()}async configure(){if(this.dialect!=="sqlite")return;await this.sql.unsafe("pragma foreign_keys = ON")}get query(){return this.sql}async close(){this.ready.catch(()=>{}),await this.sql.close()}}class g{config;static token="database";name=Q;pools=new Map;ready;constructor(z={}){this.config=z;let{connections:G={},...V}=z;this.pools.set(Q,new P(Q,V));try{this.build(G,V.slowTransactionThreshold)}catch(Y){for(let $ of this.pools.values())$.ready.catch(()=>{}),$.close().catch(()=>{});throw Y}this.ready=Promise.all([...this.pools.values()].map((Y)=>Y.ready)).then(()=>{return})}build(z,G){for(let[V,Y]of Object.entries(z)){if(V===Q)throw new b(V);this.pools.set(V,new P(V,{slowTransactionThreshold:G,...Y}))}}connection(z=Q){if(z===Q)return this;let G=this.pools.get(z);if(!G)throw new R(z,this.connectionNames);return G}get connectionNames(){return[...this.pools.keys()]}get sql(){return this.default.sql}get dialect(){return this.default.dialect}get url(){return this.default.url}get query(){return this.sql}async close(){this.ready.catch(()=>{}),await Promise.all([...this.pools.values()].map((z)=>z.close()))}get default(){return this.pools.get(Q)}}function e(z){return z}function zz(){return{url:process.env.DATABASE_URL,dialect:void 0,options:void 0,slowTransactionThreshold:x,connections:void 0}}var x=2000;function Yz(){return{now:new Date,resolved:{}}}var f={now:new Date(0),resolved:{}};function Zz(z){return(G,V=f)=>{let Y=[];for(let $=0;$<z.length;$++)Y.push(z[$](G,V));return Y}}var I="\x00";function B(z){return{text:z,binders:[]}}function J(z,G=""){return{text:I+G,binders:[z]}}function $z(z){return z.text.split(I)}function Bz(z,G){return{text:z.join(I),binders:G}}function W(...z){return C(z,"")}function C(z,G){let V="",Y=[];for(let $=0;$<z.length;$++){if($>0)V+=G;V+=z[$].text;for(let Z of z[$].binders)Y.push(Z)}return{text:V,binders:Y}}function Wz(z,G,V){let Y=z.text.split(I),$=Y.length-1;if($!==z.binders.length)throw Error(`Compiled ${$} parameter placeholders but collected ${z.binders.length} binders.`);if($>G.maxBoundParameters)throw new k(V.model,V.operation,$,G.maxBoundParameters,G.name,G.bindsListAsOneParameter?"That is one parameter per value in the statement.":`That is one parameter per value, and on ${G.name} each element of an 'in' list counts separately.`);let Z=Y[0];for(let H=0;H<$;H++)Z+=G.placeholder(H)+Y[H+1];return{text:Z,binders:z.binders}}class F{name="postgres";supportsInsensitiveMode=!0;bindsListAsOneParameter=!0;supportsReturning=!0;maxBoundParameters=65535;typesParametersFromStatement=!0;quoteIdent(z){if(z.includes("\x00"))throw Error(`Refusing to quote the identifier ${JSON.stringify(z)}: it contains a NUL byte, which is reserved as the parameter marker.`);return`"${z.replace(/"/g,'""')}"`}placeholder(z){return`$${z+1}`}inList(z,G,V,Y){return W(B(`${z} ${G?"<> all":"= any"} (`),J((Z,H)=>K(Y(Z,H))),B(")"))}static COMPOSITE_IN_TYPES={Int:"int",BigInt:"bigint",String:"text",Boolean:"boolean"};canBindCompositeIn(z){return z.length>0&&z.every((G)=>F.COMPOSITE_IN_TYPES[G])}compositeIn(z,G,V){let Y=z.map(($,Z)=>W(J((H,j)=>K(V(H,j).map((_)=>_[Z]))),B(`::${F.COMPOSITE_IN_TYPES[G[Z]]}[]`)));return W(B(`(${z.join(", ")}) in (select * from unnest(`),...Y.flatMap(($,Z)=>Z===0?[$]:[B(", "),$]),B("))"))}listFilters=new Set(["equals","has","hasEvery","hasSome","isEmpty"]);listHas(z,G){return W(G,B(` = any(${z})`))}listHasEvery(z,G){return W(B(`${z} @> `),G)}listHasSome(z,G){return W(B(`${z} && `),G)}listIsEmpty(z,G){return W(B(`${z} ${G?"=":"<>"} `),J(()=>K([])))}listPush(z,G){return W(B(`array_cat(${z}, `),G,B(")"))}jsonPathSyntax="array";jsonFilters=new Set(["equals","not","string_contains","string_starts_with","string_ends_with","array_contains","lt","lte","gt","gte"]);jsonComparesAsText=!0;jsonExtract(z,G,V){return W(B(`${z} ${V?"#>>":"#>"} `),J((Y,$)=>K(G(Y,$))))}jsonArrayContains(z,G,V){return W(B("("),this.jsonExtract(z,G,!1),B(") @> "),J((Y,$)=>{let Z=V(Y,$);if(Z===null||Z===void 0)return null;return typeof Z==="string"||typeof Z==="object"?Z:JSON.stringify(Z)}),B("::jsonb"))}like(z,G,V){return W(B(`${z} ${G?"ilike":"like"} `),J(V))}ignoreConflicts(){return B(" on conflict do nothing")}paginate(z,G){let V=[];if(z)V.push(W(B(" limit "),J(z)));if(G)V.push(W(B(" offset "),J(G)));return W(...V)}constraintViolation(z){let G=z;if(!G)return null;if(String(G.errno??G.code??"")!=="23505")return null;let Y=typeof G.constraint==="string"&&G.constraint!==""?G.constraint:void 0,$=typeof G.detail==="string"?G.detail:"",Z=/\((.+?)\)=/.exec($);return{kind:"unique",columns:Z?Z[1].split(",").map((j)=>j.trim()).filter((j)=>j!==""):[],constraint:Y}}castParameter(z){if(z.isList)return"";return z.type==="Json"?"::text::jsonb":""}encode(z,G){if(z===null||z===void 0)return null;if(G.isList){if(!Array.isArray(z))throw Error(`gemi ORM bug: a non-array reached the parameter binder for the scalar list '${G.column}' (received ${typeof z}). Every path that binds a list is supposed to have checked its operand.`);return K(G.type==="Json"?z.map((V)=>V===null||V===void 0?null:JSON.stringify(V)):z)}return z}encodeUntyped(z){return z}needsDecode(z){return z.isList===!0||z.type==="BigInt"||z.type==="Bytes"}decode(z,G){if(z===null||z===void 0)return null;if(G.isList)return this.decodeList(z,G);return this.decodeScalar(z,G)}decodeList(z,G){let V=Array.isArray(z)?z:typeof z==="string"?m(z,G):ArrayBuffer.isView(z)?Array.from(z):null;if(V===null)throw new X(G,z);return V.map((Y)=>Y===null||Y===void 0?null:this.decodeScalar(Y,G))}decodeScalar(z,G){switch(G.type){case"BigInt":if(typeof z==="bigint")return z;try{return BigInt(z)}catch{throw new X(G,z)}case"Json":return z;case"Bytes":return Buffer.isBuffer(z)?new Uint8Array(z.buffer,z.byteOffset,z.byteLength):z;default:return z}}}function K(z){let G="{";for(let V=0;V<z.length;V++){if(V>0)G+=",";G+=p(z[V])}return G+"}"}function p(z){if(z===null||z===void 0)return"NULL";if(z instanceof Date)return`"${z.toISOString()}"`;if(ArrayBuffer.isView(z)){let V="";for(let Y of new Uint8Array(z.buffer,z.byteOffset,z.byteLength))V+=Y.toString(16).padStart(2,"0");return`"\\\\x${V}"`}return`"${(typeof z==="string"?z:String(z)).replace(/\\/g,"\\\\").replace(/"/g,"\\\"")}"`}function m(z,G){if(!z.startsWith("{")||!z.endsWith("}"))throw new X(G,z);if(z==="{}")return[];let V=[],Y=1,$=z.length-1;while(Y<=$){let Z="",H=!1;if(z[Y]==='"'){H=!0,Y++;while(Y<$&&z[Y]!=='"')Z+=z[Y]==="\\"?z[++Y]:z[Y],Y++;Y++}else while(Y<$&&z[Y]!==","){if(z[Y]==="{")throw new X(G,z);Z+=z[Y],Y++}if(V.push(!H&&Z.toUpperCase()==="NULL"?null:Z),Y<$&&z[Y]!==",")throw new X(G,z);Y++}if(G.type!=="Json")return V;return V.map((Z)=>{if(Z===null)return null;try{return JSON.parse(Z)}catch{throw new X(G,Z)}})}var c={"Prisma.DbNull":"db","Prisma.JsonNull":"json","Prisma.AnyNull":"any"};function O(z){return new class{toString(){return z}}}var jz=O("Prisma.DbNull"),d=O("Prisma.JsonNull"),Kz=O("Prisma.AnyNull"),Fz=d;function T(z){if(typeof z!=="object"||z===null)return null;for(let V in z)return null;if(Object.getOwnPropertyNames(z).length>0)return null;let G;try{G=String(z)}catch{return null}return c[G]??null}var v=/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(\.\d+)?$/;function s(z,G){if(z instanceof Date)return z;let V;if(typeof z==="number")V=new Date(z);else if(typeof z==="bigint")V=new Date(Number(z));else if(typeof z==="string")V=new Date(v.test(z)?`${z.replace(" ","T")}Z`:z);else throw new X(G,z);if(Number.isNaN(V.getTime()))throw new X(G,z);return V}class w{name="sqlite";supportsInsensitiveMode=!1;bindsListAsOneParameter=!1;supportsReturning=!0;maxBoundParameters=32766;typesParametersFromStatement=!1;quoteIdent(z){if(z.includes("\x00"))throw Error(`Refusing to quote the identifier ${JSON.stringify(z)}: it contains a NUL byte, which is reserved as the parameter marker.`);return`"${z.replace(/"/g,'""')}"`}placeholder(z){return"?"}inList(z,G,V,Y){let $=G?"not in":"in",Z=[];for(let H=0;H<V;H++)Z.push(J((j,_)=>Y(j,_)[H]));return W(B(`${z} ${$} (`),C(Z,", "),B(")"))}canBindCompositeIn(){return!1}compositeIn(){throw Error("SQLite cannot bind a composite `in`; `canBindCompositeIn` is the guard.")}listFilters=new Set;listHas(){throw Error(M("has"))}listHasEvery(){throw Error(M("hasEvery"))}listHasSome(){throw Error(M("hasSome"))}listIsEmpty(){throw Error(M("isEmpty"))}listPush(){throw Error(M("push"))}jsonPathSyntax="jsonpath";jsonFilters=new Set(["equals","not","string_contains","string_starts_with","string_ends_with"]);jsonComparesAsText=!1;jsonExtract(z,G,V){return W(B(`json_extract(${z}, `),J(G),B(")"))}jsonArrayContains(){throw Error("SQLite cannot express array_contains; `jsonFilters` is the guard.")}like(z,G,V){return W(B(`${z} like `),J(V))}ignoreConflicts(){return null}paginate(z,G){if(!z&&!G)return B("");if(!G)return W(B(" limit "),J(z));return W(B(" limit "),J(z??(()=>-1)),B(" offset "),J(G))}constraintViolation(z){let G=z?.code;if(G!=="SQLITE_CONSTRAINT_UNIQUE"&&G!=="SQLITE_CONSTRAINT_PRIMARYKEY")return null;let V=String(z.message??""),Y=/constraint failed:\s*(.+)$/.exec(V);if(!Y)return{kind:"unique",columns:[]};return{kind:"unique",columns:Y[1].split(",").map((Z)=>Z.trim()).map((Z)=>{let H=Z.indexOf(".");return H===-1?Z:Z.slice(H+1)}).filter((Z)=>Z!=="")}}castParameter(z){return""}encode(z,G){if(z===null||z===void 0)return null;switch(G.type){case"DateTime":return z instanceof Date?z.getTime():z;case"Boolean":return typeof z==="boolean"?z?1:0:z;case"Json":{let V=T(z);if(V==="db")return null;if(V==="json")return"null";if(V==="any")throw Error("gemi ORM bug: Prisma.AnyNull reached the SQLite encoder. It is a filter operand only, and both the filter and write paths are supposed to have handled it before this point.")}return JSON.stringify(z);default:return z}}encodeUntyped(z){if(z instanceof Date)return z.getTime();if(typeof z==="boolean")return z?1:0;return z}needsDecode(z){switch(z.type){case"DateTime":case"Boolean":case"BigInt":case"Json":return!0;default:return!1}}decode(z,G){if(z===null||z===void 0)return null;switch(G.type){case"DateTime":return s(z,G);case"Boolean":if(typeof z==="boolean")return z;return Number(z)!==0;case"BigInt":if(typeof z==="bigint")return z;try{return BigInt(z)}catch{throw new X(G,z)}case"Json":try{return typeof z==="string"?JSON.parse(z):z}catch{throw new X(G,z)}default:return z}}}function M(z){return`SQLite has no array type, so it cannot express '${z}' on a scalar list; \`listFilters\` is the guard.`}class q extends Error{constructor(z){super(`The gemi ORM does not support the '${z}' dialect. Only sqlite `+"and postgres are implemented \u2014 see the supported matrix in "+`docs/orm.md.
|
|
3
3
|
|
|
4
4
|
The *connection* is fine: Bun's client speaks ${z}, so raw SQL through DB.query / DB.sql and transactions all work. It is the query compiler that has no ${z} dialect, so every model operation raises this.
|
|
5
5
|
|
|
6
6
|
Point DATABASE_URL at Postgres or SQLite to use the ORM, or keep using Prisma's own client for this database.`);this.name="UnsupportedDialectError"}}function Cz(z){return A[z]!==null}function Oz(){return Object.keys(A)}var A={sqlite:new w,postgres:new F,mysql:null,mariadb:null};function wz(z){let G=A[z];if(G===null)throw new q(z);return G}
|
|
7
|
-
export{S as
|
|
7
|
+
export{S as Cc,U as Dc,N as Ec,o as Fc,i as Gc,Q as Hc,R as Ic,b as Jc,E as Kc,P as Lc,g as Mc,e as Nc,zz as Oc,x as Pc,Yz as Qc,Zz as Rc,B as Sc,J as Tc,$z as Uc,Bz as Vc,W as Wc,C as Xc,Wz as Yc,F as Zc,jz as _c,d as $c,Kz as ad,Fz as bd,T as cd,w as dd,q as ed,Cz as fd,Oz as gd,wz as hd};
|
|
8
8
|
|
|
9
|
-
//# debugId=
|
|
9
|
+
//# debugId=A91B85C09BFA044964756E2164756E21
|