@lunora/sql-store 1.0.0-alpha.68 → 1.0.0-alpha.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TableDefinitionLike, SchemaLike, ServerDefaultContextLike, DatabaseWriterLike, SchedulerLike, ValidatorLike } from '@lunora/shard-engine';
|
|
1
|
+
import { TableDefinitionLike, SchemaLike, ServerDefaultContextLike, DatabaseWriterLike, CrossShardReadArgs, QueryPage, SchedulerLike, ValidatorLike } from '@lunora/shard-engine';
|
|
2
2
|
import { SqlRunResult, SqlDialect } from "./dialect.mjs";
|
|
3
3
|
export type { SqlExec } from "./dialect.mjs";
|
|
4
4
|
import 'drizzle-orm';
|
|
@@ -81,8 +81,11 @@ interface SqlCtxDbOptions {
|
|
|
81
81
|
* RLS). Absent it, loading such a relation throws a clear "not supported"
|
|
82
82
|
* error (legacy behaviour). The forward direction (shard-local parent →
|
|
83
83
|
* global child) and same-backend relations never touch this.
|
|
84
|
+
*
|
|
85
|
+
* Takes {@link CrossShardReadArgs}, not `QueryArgs`: the hop is JSON, so the
|
|
86
|
+
* RLS filters are handed over as data (see that type's docblock).
|
|
84
87
|
*/
|
|
85
|
-
crossShardReader?:
|
|
88
|
+
crossShardReader?: (table: string, args: CrossShardReadArgs) => Promise<QueryPage>;
|
|
86
89
|
/**
|
|
87
90
|
* The SQL dialect that shapes every statement (identifier quoting, value
|
|
88
91
|
* encode/decode, column types, upserts, RETURNING vs affected-rows).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TableDefinitionLike, SchemaLike, ServerDefaultContextLike, DatabaseWriterLike, SchedulerLike, ValidatorLike } from '@lunora/shard-engine';
|
|
1
|
+
import { TableDefinitionLike, SchemaLike, ServerDefaultContextLike, DatabaseWriterLike, CrossShardReadArgs, QueryPage, SchedulerLike, ValidatorLike } from '@lunora/shard-engine';
|
|
2
2
|
import { SqlRunResult, SqlDialect } from "./dialect.js";
|
|
3
3
|
export type { SqlExec } from "./dialect.js";
|
|
4
4
|
import 'drizzle-orm';
|
|
@@ -81,8 +81,11 @@ interface SqlCtxDbOptions {
|
|
|
81
81
|
* RLS). Absent it, loading such a relation throws a clear "not supported"
|
|
82
82
|
* error (legacy behaviour). The forward direction (shard-local parent →
|
|
83
83
|
* global child) and same-backend relations never touch this.
|
|
84
|
+
*
|
|
85
|
+
* Takes {@link CrossShardReadArgs}, not `QueryArgs`: the hop is JSON, so the
|
|
86
|
+
* RLS filters are handed over as data (see that type's docblock).
|
|
84
87
|
*/
|
|
85
|
-
crossShardReader?:
|
|
88
|
+
crossShardReader?: (table: string, args: CrossShardReadArgs) => Promise<QueryPage>;
|
|
86
89
|
/**
|
|
87
90
|
* The SQL dialect that shapes every statement (identifier quoting, value
|
|
88
91
|
* encode/decode, column types, upserts, RETURNING vs affected-rows).
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createSqlCtxDb as o,readSqlCdcChanges as a,runSqlAggregateMigrations as t,runSqlCdcMigration as i,runSqlGlobalTableMigrations as l,runSqlRankMigrations as n,trimSqlCdcChanges as S}from"./packem_shared/createSqlCtxDb-
|
|
1
|
+
import{createSqlCtxDb as o,readSqlCdcChanges as a,runSqlAggregateMigrations as t,runSqlCdcMigration as i,runSqlGlobalTableMigrations as l,runSqlRankMigrations as n,trimSqlCdcChanges as S}from"./packem_shared/createSqlCtxDb-DGQ1bJSP.mjs";import{A as s,B as d}from"./packem_shared/ctx-db-search-IjbCKWI8.mjs";import{SEARCH_STATE_TABLE as q,migrateSearchState as f}from"./packem_shared/SEARCH_STATE_TABLE-DT7nfOye.mjs";import{decodeBigint as C,effectiveColumnKind as x,sqliteDecode as u,sqliteEncode as b,tryJsonParse as h}from"./packem_shared/decodeBigint-DWHvvLGA.mjs";import{decodeGlobalRow as A}from"./packem_shared/decodeGlobalRow-DOhQ8Anj.mjs";export{q as SEARCH_STATE_TABLE,s as backfillSqlSearchIndexes,o as createSqlCtxDb,C as decodeBigint,A as decodeGlobalRow,x as effectiveColumnKind,f as migrateSearchState,a as readSqlCdcChanges,t as runSqlAggregateMigrations,i as runSqlCdcMigration,l as runSqlGlobalTableMigrations,n as runSqlRankMigrations,d as runSqlSearchMigrations,u as sqliteDecode,b as sqliteEncode,S as trimSqlCdcChanges,h as tryJsonParse};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as N}from"@lunora/errors";import{F as bt,B as gt,T as Nt,x as Tt,_ as vt,C as Rt,v as St,D as It,b as At,N as Lt}from"./ctx-db-search-IjbCKWI8.mjs";import{A as Ci}from"./ctx-db-search-IjbCKWI8.mjs";import{aggregateTableName as G,rankTableName as Q,hasTrigger as kt,runRowValidators as ke,assertFlatPredicate as Je,mergeWhere as M,sortColumnName as z,resolveRankPartition as Xe,encodePartitionKey as Te,decodeCursor as Qe,RANK_TIEBREAK as $e,CountRlsUnsupportedError as Ze,normalizeIdStructurally as Ot,assertValidClientId as Ct,aggregateSqlFunction as ue,softDeleteScope as fe,compileWhereSql as _e,normalizeOrderKeys as Mt,buildSeekWhere as xt,resolveRelationPredicates as et,resolveWith as tt,relationHooks as it,applySelect as nt,encodeCursor as Dt,NotFoundError as Wt,applyOnDelete as qt,ConflictError as we,normalizeCountArgument as Bt,selectIndexForCount as Ft,encodeAggregateKey as Y,selectIndexForAggregate as Ut,readAggregateValue as Oe,runTriggers as jt,matchesRankStaticWhere as at,selectIndexForGroupBy as Pt,fanOutScalarCounts as Ht,matchesStaticWhere as Ce,foldAggregateTally as Kt,coerceAggregateNumber as Me,NotUniqueError as Vt,throwingScheduler as Yt}from"@lunora/shard-engine";import{sql as e}from"drizzle-orm";import{migrateSearchState as Gt}from"./SEARCH_STATE_TABLE-DT7nfOye.mjs";import{queryAll as I,queryRun as A,createIndexIfNotExists as De,decodeRow as Z,serializeColumnValue as H,columnRefSql as x,decodeRows as zt,forEachRowPaged as ot,queryBatch as rt}from"./decodeGlobalRow-DOhQ8Anj.mjs";import{decodeGlobalRow as xi}from"./decodeGlobalRow-DOhQ8Anj.mjs";import{effectiveColumnKind as ve}from"./decodeBigint-DWHvvLGA.mjs";const Jt=(l,w)=>{if(l.size<w)return;const _=l.keys().next().value;_!==void 0&&l.delete(_)},Xt=(l,w={})=>{const _=w.maxBatch??50,o=Number.isInteger(_)&&_>0?_:50,E=new Map;let c=!1;const s=async(y,v)=>{const R=[...v.keys()];for(let L=0;L<R.length;L+=o){const D=R.slice(L,L+o);try{const B=await l(y,D);for(const K of D){const F=B.get(K);for(const Se of v.get(K)??[])Se.resolve(F)}}catch(B){for(const K of D)for(const F of v.get(K)??[])F.reject(B)}}},T=()=>{c=!1;const y=[...E.entries()];E.clear();for(const[v,R]of y)s(v,R).catch(()=>{})};return{async load(y,v){return new Promise((R,L)=>{let D=E.get(y);D||(D=new Map,E.set(y,D));const B=D.get(v);B?B.push({reject:L,resolve:R}):D.set(v,[{reject:L,resolve:R}]),c||(c=!0,queueMicrotask(T))})}}},Qt=new Set(["_id","id"]),We=(l,w,_)=>l==="postgres"?e`${w} IS NOT DISTINCT FROM ${_}`:l==="mysql"?e`${w} <=> ${_}`:e`${w} IS ${_}`,Zt=l=>{const w=l.map(_=>e`${x(_.field)} ${e.raw(_.direction==="desc"?"DESC":"ASC")}`);return l.some(_=>Qt.has(_.field))||w.push(e`${x("id")} ASC`),e.join(w,e`, `)},st=50,qe=l=>{const w=[];for(const[_,o]of Object.entries(l.shape)){const E=o._meta?.column;E&&w.push([_,E])}return w},ei=(l,w,_)=>{const o={...w};for(const[E,c]of qe(l)){if(c.serverDefault){o[E]=c.serverDefault({auth:_});continue}o[E]===void 0&&(c.defaultFn?o[E]=c.defaultFn():"defaultValue"in c&&(o[E]=c.defaultValue))}return o},ct=(l,w,_,o)=>{for(const[E,c]of qe(l)){if(c.serverDefault){E in w&&(_[E]=c.serverDefault({auth:o}));continue}c.onUpdateFn&&!(E in w)&&(_[E]=c.onUpdateFn())}},ti=128,ii=()=>{const l=new Map;return{delete:w=>{l.delete(w)},get:w=>{const _=l.get(w);if(_!==void 0)return l.delete(w),l.set(w,_),_},set:(w,_)=>{l.has(w)?l.delete(w):Jt(l,ti),l.set(w,_)}}},ni=async(l,w,_,o,E)=>{const c=E.get(o);if(c!==void 0)return c;const s=Object.entries(_.tables).filter(([,y])=>y.shardMode===void 0||y.shardMode.kind==="global").map(([y])=>y),T=await Promise.all(s.map(async y=>({found:(await I(l,w,e`SELECT 1 FROM ${e.identifier(y)} WHERE ${e.identifier("id")} = ${o} LIMIT 1`)).length>0,tableName:y})));for(const y of T)if(y.found)return E.set(o,y.tableName),y.tableName},ee=l=>l==null?null:Number(l),ai=(l,w)=>w.map(_=>{const o={};for(const E of l)o[E]=_[E]??null;return{key:o,value:ee(_.value)}}),oi=(l,w,_)=>[...l.partitionBy??[],...l.sortBy.map(o=>o.field),...l.where?Object.keys(l.where):[]].every(o=>w[o]===_[o]),dt=l=>l.length===1?l[0]:e`(${e.join(l,e` AND `)})`,X=l=>e.join(l.map(w=>e`${e.identifier(w)}`),e`, `),te=l=>e.join(l.map(w=>e`${w}`),e`, `),ri=(l,w,_,o,E)=>{const c=[];for(let s=0;s<_.length+1;s+=1){const T=_.slice(0,s).map(R=>We(l,e`${e.identifier(R)}`,o[R])),y=_[s],v=w.sortBy[s];s<_.length&&y!==void 0&&v!==void 0?T.push(e`${e.identifier(y)} ${e.raw(v.direction==="desc"?">":"<")} ${o[y]}`):T.push(e`${e.identifier($e)} < ${E}`),c.push(dt(T))}return c.length>0?e.join(c,e` OR `):void 0},si=(l,w,_)=>{if(_.length!==w.length)return;const o=[];for(const[E,c]of w.entries()){const s=[];for(let T=0;T<E;T+=1){const y=w[T];y!==void 0&&s.push(We(l,e`${e.identifier(y.column)}`,_[T]))}s.push(e`${e.identifier(c.column)} ${e.raw(c.direction==="desc"?"<":">")} ${_[E]}`),o.push(dt(s))}return e`(${e.join(o,e` OR `)})`},ci=(l,w)=>{if(l.sortBy.length===0)throw new N("INTERNAL",`rankIndex "${l.name}" requires at least one "sortBy" column for stable pagination`);const _=[{column:"__partition__",direction:"asc"}];for(const[o,E]of l.sortBy.entries())_.push({column:w[o]??z(o),direction:E.direction});return _.push({column:$e,direction:"asc"}),_},di=async(l,w,_,o,E)=>{const c=[];for(let v=0;v<E.length;v+=50)c.push(E.slice(v,v+50));const s=await Promise.all(c.map(async v=>I(l,w,e`SELECT * FROM ${e.identifier(o)} WHERE ${e.identifier("id")} IN (${te(v)})`))),T=new Map;for(const v of s)for(const R of v)T.set(R.id,R);const y=[];for(const v of E){const R=Z(_,T.get(v));R&&y.push(R)}return y},li=l=>{const w=JSON.stringify(l),_=new TextEncoder().encode(w);let o="";for(const E of _)o+=String.fromCodePoint(E);return btoa(o)},ui=(l,w)=>w.columnType(ve(l)),fi=(l,w)=>{const _=[];for(const[E,c]of Object.entries(l.shape)){if(!c._meta?.column)continue;const s=c._meta.column.notNull&&c.kind!=="optional"?" NOT NULL":"";_.push(e`${e.identifier(E)} ${e.raw(`${ui(c,w)}${s}`)}`)}const o=w.frameworkColumns().map(E=>e`${e.identifier(E.name)} ${e.raw(E.type)}`);return e.join([...o,..._],e`, `)},_i=async(l,w,_,o)=>{const E=c=>{const s=x(c),T=_.shape[c],y=T&&o.indexKeyPrefix?o.indexKeyPrefix(ve(T)):void 0;return y===void 0?s:e`${s}(${e.raw(String(y))})`};for(const c of _.indexes){const s=e.join(c.fields.map(T=>E(T)),e`, `);await De(l,o,{columns:s,name:`${w}_${c.name}`,table:w,unique:c.unique??!1})}for(const[c,s]of qe(_))s.unique&&await De(l,o,{columns:E(c),name:`${w}_unique_${c}`,table:w,unique:!0})},wi=async(l,w,_)=>{for(const[o,E]of Object.entries(w.tables)){if(E.shardMode?.kind!=="global")continue;const c=fi(E,_);await A(l,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(o)} (${c})`),await _i(l,o,E,_)}},$i=async(l,w,_)=>{const{integer:o,key:E,real:c}=_.companionTypes;for(const[s,T]of Object.entries(w.tables)){const y=T.aggregateIndexes;if(!(!y||y.length===0))for(const v of y){const R=G(s,v.name);await A(l,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(R)} (${e.identifier("__key__")} ${e.raw(E)} PRIMARY KEY, ${e.identifier("__value__")} ${e.raw(c)}, ${e.identifier("__count__")} ${e.raw(o)} NOT NULL DEFAULT 0)`),_.name==="sqlite"&&((await I(l,_,e`PRAGMA table_info(${e.identifier(R)})`)).some(L=>L.name==="__count__")||await A(l,_,e`ALTER TABLE ${e.identifier(R)} ADD COLUMN ${e.identifier("__count__")} ${e.raw(o)} NOT NULL DEFAULT 0`))}}},xe=(l,w,_,o)=>{const E=l.name==="mysql"&&o?e`${e.identifier(w)}(191)`:e`${e.identifier(w)}`;return e`${E} ${e.raw(_)}`},hi=(l,w,_)=>{const o=[xe(l,"__partition__","ASC",!0)];for(const[E,c]of w.sortBy.entries()){const s=_.shape[c.field],T=s!==void 0&&l.indexKeyPrefix?.(ve(s))!==void 0;o.push(xe(l,z(E),c.direction==="desc"?"DESC":"ASC",T))}return o.push(xe(l,"__id__","ASC",!0)),o},pi=(l,w,_)=>w.sortBy.map((o,E)=>{const c=_.shape[o.field],s=l.columnType(c?ve(c):void 0);return e`${e.identifier(z(E))} ${e.raw(s)}`}),Ei=async(l,w,_)=>{const{key:o}=_.companionTypes;for(const[E,c]of Object.entries(w.tables)){const s=c.rankIndexes;if(!(!s||s.length===0))for(const T of s){const y=Q(E,T.name),v=pi(_,T,c),R=v.length>0?e`, ${e.join(v,e`, `)}`:e``;await A(l,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(y)} (${e.identifier("__id__")} ${e.raw(o)} PRIMARY KEY, ${e.identifier("__partition__")} ${e.raw(o)} NOT NULL${R})`);const L=hi(_,T,c),D=`${E}__rank_${T.name}__btree`;await De(l,_,{columns:e.join(L,e`, `),name:D,table:y,unique:!1})}}},Re="__cdc_log",mi=async(l,w)=>{const{autoincrementPrimaryKey:_,key:o,real:E,text:c}=w.companionTypes;await A(l,w,e`CREATE TABLE IF NOT EXISTS ${e.identifier(Re)} (${e.identifier("seq")} ${e.raw(_)}, ${e.identifier("ts")} ${e.raw(E)} NOT NULL, ${e.identifier("table")} ${e.raw(o)} NOT NULL, ${e.identifier("id")} ${e.raw(o)} NOT NULL, ${e.identifier("op")} ${e.raw(o)} NOT NULL, ${e.identifier("doc")} ${e.raw(c)})`)},yi=async(l,w,_,o,E,c,s)=>{await A(l,s,e`INSERT INTO ${e.identifier(Re)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${w}, ${_}, ${o}, ${E}, ${c===void 0?null:JSON.stringify(c)})`)},Ii=async(l,w,_)=>{const o=w.sinceSeq??0,E=Math.max(1,Math.min(w.limit??1e3,1e4)),c=(await I(l,_,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(Re)} WHERE seq > ${o} ORDER BY seq ASC LIMIT ${e.raw(String(E))}`)).map(s=>{const{doc:T}=s,y={id:String(s.id),op:String(s.op),seq:Number(s.seq),table:String(s.table),ts:Number(s.ts)};return typeof T=="string"?{...y,doc:JSON.parse(T)}:y});return{changes:c,cursor:c.at(-1)?.seq??o}},Ai=async(l,w,_)=>{await A(l,_,e`DELETE FROM ${e.identifier(Re)} WHERE ${e.identifier("seq")} <= ${w}`)},Li=l=>{const{crossShardCounter:w,crossShardReader:_,exec:o,maxRelationKeys:E,schema:c}=l,{dialect:s}=l,{isUniqueViolation:T}=s,y={fieldRef:x,serialize:H,...s.name==="mysql"?{likeContains:(t,i)=>e`${t} LIKE CONCAT('%', ${i}, '%') ESCAPE '\\\\'`}:{}},v=(t,i)=>We(s.name,t,i),R=t=>{const i=X(t.columns),n=te(t.values),a=u=>s.name==="mysql"?e`VALUES(${e.identifier(u)})`:e`excluded.${e.identifier(u)}`,r=u=>s.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(u)}`:e`${e.identifier(u)}`,f=e.join(Object.entries(t.set(a,r)).map(([u,p])=>e`${e.identifier(u)} = ${p}`),e`, `),$=s.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${f}`:e`ON CONFLICT(${e.identifier(t.conflictKey)}) DO UPDATE SET ${f}`;return e`INSERT INTO ${e.identifier(t.table)} (${i}) VALUES (${n}) ${$}`},L=l.clock??(()=>Date.now()),D=l.idGenerator??(()=>crypto.randomUUID()),B=l.cdc??!1,K=l.auth??{identity:null,userId:null},F=async(t,i,n,a)=>{B&&await yi(o,L(),t,i,n,a,s)},Se=l.scheduler??Yt,Ie=ii();let he=0,Ae;const U=async()=>(Ae??=(async()=>{await wi(o,c,s),await $i(o,c,s),await Ei(o,c,s),await Gt(o,s),await gt(o,c,s),B&&await mi(o,s)})().catch(t=>{throw Ae=void 0,t}),Ae),ie=async(t,i)=>{await U();const n=await ni(o,s,c,t,Ie);if(!(i!==void 0&&n!==i))return n},ne=new Map,Be=async(t,i)=>{const n=G(t,i);return(await I(o,s,s.tableExists(n))).length>0},pe=async(t,i)=>{const n=`${t}::${i.name}`,a=ne.get(n);if(a!==void 0)return a;if(!await Be(t,i.name))return ne.set(n,!1),!1;const r=c.tables[t];if(!r)return ne.set(n,!1),!1;const f=i.by??[],$=new Map;await ot(o,s,r,t,d=>{if(i.where&&!Ce(d,i.where))return;const h=Y(f,d);Kt($,h,i,d)});const u=G(t,i.name);await A(o,s,e`DELETE FROM ${e.identifier(u)}`);const p=[];for(const[d,h]of $)p.push(e`INSERT INTO ${e.identifier(u)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${d}, ${h.value}, ${h.count})`);return await rt(o,s,p),ne.set(n,!0),!0},lt=async(t,i,n)=>{const a=ue(i.op),r=i.field??"",f=[];for(const p of i.by??[]){const d=H(n[p]??null);f.push(d===null?e`${x(p)} IS NULL`:e`${x(p)} = ${d}`)}for(const[p,d]of Object.entries(i.where??{})){const h=d!==null&&typeof d=="object"&&!Array.isArray(d)?d.eq:d,m=H(h);f.push(m===null?e`${x(p)} IS NULL`:e`${x(p)} = ${m}`)}const $=e`SELECT ${e.raw(a)}(${x(r)}) AS value FROM ${e.identifier(t)}`,u=await I(o,s,f.length>0?e`${$} WHERE ${e.join(f,e` AND `)}`:$);return ee(u[0]?.value)},ut=async(t,i)=>{await A(o,s,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${i} AND ${e.identifier("__count__")} <= 0`)},ft=async(t,i,n,a)=>{const r=G(t,i.name),{op:f}=i,$=i.field??"",u=n&&(!i.where||Ce(n,i.where))?n:void 0,p=a&&(!i.where||Ce(a,i.where))?a:void 0;if(!(!u&&!p)){if(f==="count"||f==="sum"||f==="avg"){const d=new Set;for(const[h,m]of[[u,-1],[p,1]]){if(!h)continue;const b=f==="count"?1:Me(h[$]);if(b===void 0)continue;const g=Y(i.by??[],h);d.add(g),await A(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(S,k)=>({__count__:e`${k("__count__")} + ${S("__count__")}`,__value__:f==="count"?e`${k("__value__")} + ${S("__value__")}`:e`COALESCE(${k("__value__")}, 0) + ${S("__value__")}`}),table:r,values:[g,m*b,m]}))}for(const h of d)await ut(r,h);return}if(u){const d=Y(i.by??[],u),h=Me(u[$]),m=(await I(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${d}`))[0],b=ee(m?.value),g=(m?.count??0)-1;if(g<=0)await A(o,s,e`DELETE FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${d}`);else if(m&&h!==void 0&&b!==null&&h===b){const S=await lt(t,i,u);await A(o,s,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__value__")} = ${S}, ${e.identifier("__count__")} = ${g} WHERE ${e.identifier("__key__")} = ${d}`)}else await A(o,s,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${d}`)}if(p){const d=Y(i.by??[],p),h=Me(p[$]);if(h===void 0)await A(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(m,b)=>({__count__:e`${b("__count__")} + 1`}),table:r,values:[d,null,1]}));else{const m=f==="min"?"MIN":"MAX";await A(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(b,g)=>({__count__:e`${g("__count__")} + 1`,__value__:e`${e.raw(m)}(COALESCE(${g("__value__")}, ${b("__value__")}), ${b("__value__")})`}),table:r,values:[d,h,1]}))}}}},Ee=async t=>{const i=c.tables[t]?.aggregateIndexes;if(!(!i||i.length===0))for(const n of i)await pe(t,n)},ae=async(t,i,n)=>{const a=c.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const r of a){const f=`${t}::${r.name}`;(ne.get(f)??await Be(t,r.name))&&await ft(t,r,i,n)}},oe=new Map,Fe=async(t,i)=>{const n=Q(t,i);return(await I(o,s,s.tableExists(n))).length>0},Le=async(t,i)=>{const n=`${t}::rank::${i.name}`,a=oe.get(n);if(a!==void 0)return a;if(!await Fe(t,i.name))return oe.set(n,!1),!1;const r=c.tables[t];if(!r)return oe.set(n,!1),!1;const f=Q(t,i.name);await A(o,s,e`DELETE FROM ${e.identifier(f)}`);const $=i.sortBy.map((h,m)=>z(m)),u=X(["__id__","__partition__",...$]),p=[];await ot(o,s,r,t,h=>{if(i.where&&!at(h,i.where))return;const m=Te(i.partitionBy??[],h),b=i.sortBy.map(g=>H(h[g.field]??null));p.push([h._id,m,...b])});const d=p.map(h=>e`INSERT INTO ${e.identifier(f)} (${u}) VALUES (${te(h)})`);return await rt(o,s,d),oe.set(n,!0),!0},me=async t=>{const i=c.tables[t]?.rankIndexes;if(!(!i||i.length===0))for(const n of i)await Le(t,n)},J=async(t,i,n,a)=>{const r=c.tables[t],f=r?.rankIndexes;if(!f||f.length===0)return;const $=r?.softDeleteMode?.field,u=$===void 0||a===void 0?void 0:a[$],p=u!=null;for(const d of f){if(n!==void 0&&a!==void 0&&oi(d,n,a))continue;const h=`${t}::rank::${d.name}`;if(!(oe.get(h)??await Fe(t,d.name)))continue;const m=Q(t,d.name);if(n&&await A(o,s,e`DELETE FROM ${e.identifier(m)} WHERE ${e.identifier("__id__")} = ${i}`),a&&!p){if(d.where&&!at(a,d.where))continue;const b=d.sortBy.map((W,O)=>z(O)),g=X(["__id__","__partition__",...b]),S=Te(d.partitionBy??[],a),k=d.sortBy.map(W=>H(a[W.field]??null));await A(o,s,e`INSERT INTO ${e.identifier(m)} (${g}) VALUES (${te([i,S,...k])})`)}}},re=bt({dialect:s,exec:o,schema:c}),Ue=new Set;for(const[t,i]of Object.entries(c.tables))for(const n of Object.values(i.triggerMap??{}))Ue.add(`${t} ${n.timing} ${n.op}`);const j=(t,i,n)=>Ue.has(`${t} ${i} ${n}`);let je;const P=async(t,i,n)=>{if(he+=1,he>st)throw he-=1,new we(`trigger recursion exceeded ${String(st)} levels on "${n.table}" — check for a self-triggering write`,"trigger");try{await jt({ctx:je,event:n,op:i,schema:c,tableName:n.table,timing:t})}finally{he-=1}},_t=async(t,i)=>{try{await A(o,s,i)}catch(n){throw T(n)?new we(`unique constraint violation on "${t}"`,"unique"):n}},ye=async(t,i)=>(await I(o,s,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${i}`))[0],be=async(t,i,n,a)=>{if(a===void 0)return;const r=e.join(Object.keys(a).map(u=>v(e`${e.identifier(u)}`,a[u])),e` AND `),f=i==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${n} WHERE ${r}`:e`DELETE FROM ${e.identifier(t)} WHERE ${r}`,$=()=>{throw new we(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")};try{if(s.supportsReturning)(await I(o,s,e`${f} RETURNING ${e.identifier("id")}`)).length===0&&$();else{const u=await A(o,s,f);(s.affectedRows?s.affectedRows(u??{rowsAffected:0}):0)===0&&$()}}catch(u){throw T(u)?new we(`unique constraint violation on "${t}"`,"unique"):u}},wt=(t,i,n,a)=>{const r=Object.keys(t.shape);return{columns:["id","_creationTime",...r],values:[i,n,...r.map(f=>H(a[f]??null))]}},$t=async(t,i,n,a)=>{const r=Pt(i,n.op,n.field,a.by,a.where);if(!r||!await pe(t,r.index))return;const f=G(t,r.index.name),$=Object.keys(r.partial);if($.length===(r.index.by??[]).length&&$.length>0){const u=Y(r.index.by??[],r.partial),p=await I(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(f)} WHERE ${e.identifier("__key__")} = ${u}`);if(p.length===0)return[];const d=p[0];return[{key:{...r.partial},value:Oe(n.op,{count:d.count,value:ee(d.value)})}]}return $.length>0?void 0:(await I(o,s,e`SELECT ${e.identifier("__key__")} AS key, ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(f)}`)).map(u=>{const p=u;return{key:JSON.parse(p.key),value:Oe(n.op,{count:p.count,value:ee(p.value)})}})},Pe=t=>{const i=c.tables[t]?.shardMode?.kind;return i==="shardBy"||i==="root"},He=t=>{throw new N("INTERNAL",`cross-backend relation: a global table cannot load the shard-local relation '${t}' (it spans every shard) — wire a cross-shard reader to support it`)},ht=(t,i)=>{if(i?.relationMask!==void 0&&i.with!==void 0&&Object.keys(i.with).length>0)throw new N("MASK_UNSUPPORTED",`masking cannot follow a nested \`with\` across the cross-shard relation hop to "${t}" — the nested rows are hydrated on the serving shard, where the mask policy does not exist. Read the nested relation at its own (masked) call site instead.`);const n={};if(i?.relationBaseWhere)for(const a of Object.keys(c.tables)){const r=i.relationBaseWhere(a);r!==void 0&&(n[a]=r)}return{orderBy:i?.orderBy,relationPolicies:n,where:M(i?.baseWhere,i?.where),with:i?.with}},Ke=(t,i)=>Pe(t)?_?_(t,ht(t,i)):He(t):q.findMany(t,i),ge=(t,i,n)=>et(t,{fetcher:Ke,maxRelationKeys:E,relationBaseWhere:n,schema:c,tableName:i}),pt=Xt(async(t,i)=>{const n=await I(o,s,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} IN (${te(i)})`),a=new Map;for(const r of n){const{id:f}=r;typeof f=="string"&&a.set(f,r)}return a}),q={async aggregate(t,i){const n=c.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);if(await U(),ue(i.op),i.op==="count")return q.count(t,{baseWhere:i.baseWhere,relationBaseWhere:i.relationBaseWhere,restrictsCounts:i.restrictsCounts,where:i.where});if(!i.field)throw new N("INTERNAL",`aggregate(${t}, { op: "${i.op}" }): "field" is required for non-count reducers`);const a=fe(n.softDeleteMode,void 0),r=M(M(i.baseWhere,i.where),a),f=await ge(r,t,i.relationBaseWhere),$=f!==r;if(n.aggregateIndexes&&!i.baseWhere&&!$&&!a){const m=Ut(n.aggregateIndexes,i.op,i.field,i.where);if(m&&await pe(t,m.index)){const b=Y(m.index.by??[],m.key),g=G(t,m.index.name),S=(await I(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(g)} WHERE ${e.identifier("__key__")} = ${b}`))[0];return Oe(i.op,S===void 0?void 0:{count:S.count,value:ee(S.value)})}}const u=_e(f,y),p=e.raw(ue(i.op)),d=e`SELECT ${p}(${x(i.field)}) AS value FROM ${e.identifier(t)}`,h=(await I(o,s,u?e`${d} WHERE ${u}`:d))[0]?.value;return h==null?null:Number(h)},async count(t,i){const n=c.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await U();const a=Bt(i);if(a.restrictsCounts)throw new Ze(t);const r=fe(n.softDeleteMode,void 0),f=M(M(a.baseWhere,a.where),r),$=await ge(f,t,a.relationBaseWhere),u=$!==f;if(n.aggregateIndexes&&!a.baseWhere&&!u&&!r){const m=Ft(n.aggregateIndexes,a.where);if(m&&await pe(t,m.index)){const b=Y(m.index.by??[],m.key),g=G(t,m.index.name),S=await I(o,s,e`SELECT ${e.identifier("__value__")} AS value FROM ${e.identifier(g)} WHERE ${e.identifier("__key__")} = ${b}`);return Number(S[0]?.value??0)}}const p=_e($,y),d=e`SELECT COUNT(*) AS count FROM ${e.identifier(t)}`,h=await I(o,s,p?e`${d} WHERE ${p}`:d);return Number(h[0]?.count??0)},async delete(t,i,n){const a=await ie(t,i);if(!a)return;const r=c.tables[a];if(!r)return;const f=await ye(a,t),$=Z(r,f),u=n?.hard===!0,p=!u&&r.softDeleteMode?r.softDeleteMode.field:void 0;if(!(p&&(!$||$[p]!==null&&$[p]!==void 0))){if(j(a,"before","delete")&&await P("before","delete",{id:t,op:"delete",previous:$??void 0,table:a}),await qt({deletedId:t,deletedReference:d=>$?.[d],findHolders:async(d,h,m)=>{if(c.tables[d]?.shardMode?.kind==="shardBy")throw new N("INTERNAL",`cross-backend cascade from global '${a}' into shardBy '${d}' is not supported — would require Query Coordinator fan-out across shards`);return(await q.findMany(d,{includeDeleted:u,where:{[h]:m}})).page},onCascade:(d,h)=>q.delete(h,void 0,n),onRestrict:d=>{throw new we(d,"restrict")},onSetNull:(d,h,m)=>q.patch(h,{[m]:null}),schema:c,tableName:a}),await Ee(a),await me(a),p&&$){const d={...$,[p]:L()},h=e.join(Object.keys(r.shape).map(m=>e`${e.identifier(m)} = ${H(d[m]??null)}`),e`, `);await be(a,"UPDATE",h,f),await ae(a,$,d),await J(a,t,$,void 0),await re(a,t,d,$),await F(a,t,"update",d),j(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:$,table:a});return}await be(a,"DELETE",void 0,f),Ie.delete(t),await ae(a,$??void 0,void 0),await J(a,t,$??void 0,void 0),await re(a,t,void 0),await F(a,t,"delete"),j(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:$??void 0,table:a})}},async findFirst(t,i={}){return(await q.findMany(t,{...i,limit:1})).page[0]??null},async findFirstOrThrow(t,i={}){const n=await q.findFirst(t,i);if(n===null)throw new Wt(`findFirstOrThrow: no "${t}" document matched`);return n},async findMany(t,i={}){const n=c.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await U();const a=Mt(i.orderBy),r=i.cursor?xt(a,Qe(i.cursor)):void 0,f=Ke,$=async(O,se,Ne,ce)=>{if(Pe(O))return w?Ht(w,O,se,Ne,ce):He(O);const V=c.tables[O];if(!V)throw new N("INTERNAL",`unknown table: ${O}`);const C=fe(V.softDeleteMode,void 0),de={[se]:{in:Ne}},Et=M(M(de,ce),C),mt=await ge(Et,O,void 0),Ve=_e(mt,y),Ye=x(se);let le=e`SELECT ${Ye} AS __fk__, COUNT(*) AS count FROM ${e.identifier(O)}`;Ve&&(le=e`${le} WHERE ${Ve}`),le=e`${le} GROUP BY ${Ye}`;const yt=await I(o,s,le),Ge=new Map;for(const ze of yt)Ge.set(ze.__fk__,Number(ze.count??0));return Ge};let u=M(i.baseWhere,i.where);u=M(u,fe(n.softDeleteMode,i.includeDeleted)),u=await et(u,{fetcher:f,maxRelationKeys:E,relationBaseWhere:i.relationBaseWhere,schema:c,tableName:t}),r&&(u=u?{AND:[u,r]}:r);const p=_e(u,y),d=Zt(a);let h=e`SELECT * FROM ${e.identifier(t)}`;p&&(h=e`${h} WHERE ${p}`),h=e`${h} ORDER BY ${d}`;const m=typeof i.limit=="number"?Math.max(0,Math.floor(i.limit)):void 0;m!==void 0&&(h=e`${h} LIMIT ${e.raw(String(m+1))}`);const b=await I(o,s,h),g=zt(n,b);if(m===void 0)return i.with&&await tt({fetcher:f,groupedCounter:$,parents:g,...it(i),schema:c,tableName:t,with:i.with}),{continueCursor:null,isDone:!0,page:nt(g,i.select,i.with)};const S=g.length>m,k=S?g.slice(0,m):g,W=k.at(-1);return i.with&&await tt({fetcher:f,groupedCounter:$,parents:k,...it(i),schema:c,tableName:t,with:i.with}),{continueCursor:S&&W?Dt(W,a):null,isDone:!S,page:nt(k,i.select,i.with)}},async get(t,i){const n=await ie(t,i);if(!n)return null;const a=c.tables[n];return a?Z(a,await pt.load(n,t)):null},async groupBy(t,i){const n=c.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await U();const a=i.agg??{op:"count"};if(ue(a.op),a.op!=="count"&&!a.field)throw new N("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);const r=fe(n.softDeleteMode,void 0),f=M(M(i.baseWhere,i.where),r),$=await ge(f,t,i.relationBaseWhere),u=$!==f;if(n.aggregateIndexes&&!i.baseWhere&&!u&&!r){const g=await $t(t,n.aggregateIndexes,a,i);if(g!==void 0)return g}const p=_e($,y),d=i.by.map(g=>e`${x(g)} AS ${e.identifier(g)}`);if(a.op==="count")d.push(e`COUNT(*) AS value`);else{if(!a.field)throw new N("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);d.push(e`${e.raw(ue(a.op))}(${x(a.field)}) AS value`)}const h=e.join(i.by.map(g=>x(g)),e`, `);let m=e`SELECT ${e.join(d,e`, `)} FROM ${e.identifier(t)}`;p&&(m=e`${m} WHERE ${p}`),m=e`${m} GROUP BY ${h}`;const b=await I(o,s,m);return ai(i.by,b)},async insert(t,i,n){const a=c.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);await U();const r=ei(a,i,K);ke(a,r);let f,$=!0;n?.clientId!==void 0?(Ct(n.clientId),f=n.clientId):n?.allowExplicitId&&typeof r._id=="string"?f=r._id:(f=D(),$=!1);const u=n?.allowExplicitId&&typeof r._creationTime=="number"?r._creationTime:L(),p={...r,_creationTime:u,_id:f};j(t,"before","insert")&&await P("before","insert",{doc:{...p},id:f,op:"insert",table:t}),await Ee(t),await me(t);const{columns:d,values:h}=wt(a,f,u,r);return await _t(t,e`INSERT INTO ${e.identifier(t)} (${X(d)}) VALUES (${te(h)})`),$&&Ie.set(f,t),await ae(t,void 0,p),await J(t,f,void 0,p),await re(t,f,p),await F(t,f,"insert",p),j(t,"after","insert")&&await P("after","insert",{doc:p,id:f,op:"insert",table:t}),f},normalizeId(t,i){return Ot(c,t,i)},async patch(t,i,n){const a=await ie(t,n);if(!a)throw new N("INTERNAL",`document not found: ${t}`);const r=c.tables[a];if(!r)throw new N("INTERNAL",`document not found: ${t}`);const f=await ye(a,t),$=Z(r,f);if(!$)throw new N("INTERNAL",`document not found: ${t}`);const u={...$,...i,_id:t};ct(r,i,u,K),ke(r,u,!0),j(a,"before","update")&&await P("before","update",{doc:{...u},id:t,op:"update",previous:$,table:a}),await Ee(a),await me(a);const p=Object.keys(r.shape),d=e.join(p.map(h=>e`${e.identifier(h)} = ${H(u[h]??null)}`),e`, `);await be(a,"UPDATE",d,f),await ae(a,$,u),await J(a,t,$,u),await re(a,t,u,$),await F(a,t,"update",u),j(a,"after","update")&&await P("after","update",{doc:u,id:t,op:"update",previous:$,table:a})},async restore(t,i){const n=await ie(t,i);if(!n)throw new N("INTERNAL",`document not found: ${t}`);const a=c.tables[n],r=a?.softDeleteMode?.field;if(!a||!r)throw new N("INTERNAL",`ctx.db.restore: table "${n}" is not a .softDelete() table`);const f=await ye(n,t),$=f?.[r]!==null&&f?.[r]!==void 0;if(await q.patch(t,{[r]:null},i),$){const u=Z(a,f);u!==null&&await J(n,t,void 0,{...u,[r]:null})}},query(t){const i=c.tables[t];if(!i)throw new N("INTERNAL",`unknown table: ${t}`);const n="the legacy query()/withIndex() reader is not available on the D1 (global) backend; use findMany",a=[],r=u=>a.every(p=>p(u)),f=async(u,p)=>{await U();const d=a.length>0,h=await St(o,s,i,t,u,It(d?void 0:p));if(!d)return p===void 0&&At(h),h;const m=h.filter(b=>r(b));return p===void 0?m:m.slice(0,p)},$=u=>{const p={async*[Symbol.asyncIterator](){if(!u)throw new N("INTERNAL",n);yield*await f(u,void 0)},async collect(){if(!u)throw new N("INTERNAL",n);return f(u,void 0)},async collectWithScores(){throw new N("INTERNAL",`collectWithScores() is not supported on \`.global()\` tables (table "${t}") — relevance scores are not yet surfaced on this backend; use .collect() instead`)},filter(d){return a.push(d),p},async first(){if(!u)throw new N("INTERNAL",n);return(await f(u,1))[0]??null},order(){return p},async paginate(d){if(!u)throw new N("INTERNAL",n);const h=vt(d);return Rt(await f(u,Lt(h)),h)},async take(d){if(!u)throw new N("INTERNAL",n);return f(u,d)},async unique(){if(!u)throw new N("INTERNAL",n);const d=await f(u,2);if(d.length>1)throw new Vt(`unique() on table "${t}" matched ${String(d.length)} documents; expected at most one`);return d[0]??null},withGeoIndex(){throw new N("INTERNAL",`geo indexes are not supported on \`.global()\` tables (table "${t}") — geospatial queries run only on sharded tables`)},withIndex(){throw new N("INTERNAL",n)},withSearchIndex(d,h){const m=(i.searchIndexes??[]).find(g=>g.name===d);if(!m)throw new N("INTERNAL",`unknown search index "${d}" on table "${t}"`);const b={definition:m,field:m.field,filters:[],hasQuery:!1,indexName:d,query:""};if(h(Nt(b,t,Tt(m.language))),!b.hasQuery)throw new N("INTERNAL",`search index "${d}" on table "${t}" requires a .search(field, query) call`);return $(b)}};return p};return $(void 0)},async rank(t,i,n){const a=c.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(W=>W.name===i);if(!r)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(n.restrictsCounts)throw new Ze(t);if(await U(),!await Le(t,r))return null;const f=typeof n.row=="string"?n.row:n.row._id;if(!f)return null;const $=Q(t,r.name),u=r.sortBy.map((W,O)=>z(O)),p=X(["__partition__",...u]),d=(await I(o,s,e`SELECT ${p} FROM ${e.identifier($)} WHERE ${e.identifier("__id__")} = ${f}`))[0];if(!d)return null;const h=d.__partition__,m=M(n.baseWhere,n.where);Je(m,c,t,"rank");const b=Xe(r,m);if(b&&Te(r.partitionBy??[],b)!==h)return null;const g=ri(s.name,r,u,d,f),S=await I(o,s,e`SELECT COUNT(*) AS c FROM ${e.identifier($)} WHERE ${e.identifier("__partition__")} = ${h}${g?e` AND (${g})`:e``}`),k=await I(o,s,e`SELECT COUNT(*) AS c FROM ${e.identifier($)} WHERE ${e.identifier("__partition__")} = ${h}`);return{position:Number(S[0]?.c??0)+1,total:Number(k[0]?.c??0)}},async rankPage(t,i,n={}){Je(M(n.baseWhere,n.where),c,t,"rankPage");const a=c.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(C=>C.name===i);if(!r)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(await U(),!await Le(t,r))return{continueCursor:null,isDone:!0,page:[]};const f=Q(t,r.name),$=r.sortBy.map((C,de)=>z(de)),u=Math.max(1,Math.min(1e3,Math.floor(n.take??100))),p=M(n.baseWhere,n.where),d=Xe(r,p),h=ci(r,$),m=e.join(h.map(C=>e`${e.identifier(C.column)} ${e.raw(C.direction==="desc"?"DESC":"ASC")}`),e`, `),b=[];if(d&&b.push(e`${e.identifier("__partition__")} = ${Te(r.partitionBy??[],d)}`),n.cursor){const C=si(s.name,h,Qe(n.cursor));C!==void 0&&b.push(C)}const g=X([$e,"__partition__",...$]);let S=e`SELECT ${g} FROM ${e.identifier(f)}`;b.length>0&&(S=e`${S} WHERE ${e.join(b,e` AND `)}`),S=e`${S} ORDER BY ${m} LIMIT ${e.raw(String(u+1))}`;const k=await I(o,s,S),W=k.length>u,O=W?k.slice(0,u):k,se=O.map(C=>C[$e]),Ne=await di(o,s,a,t,se);let ce=null;const V=O.at(-1);if(W&&V!==void 0){const C=[V.__partition__,...$.map(de=>V[de]),V[$e]];ce=li(C)}return{continueCursor:ce,isDone:!W,page:Ne}},async replace(t,i,n,a){const r=await ie(t,n);if(!r)throw new N("INTERNAL",`document not found: ${t}`);const f=c.tables[r];if(!f)throw new N("INTERNAL",`document not found: ${t}`);const $=await ye(r,t);if($===void 0)throw new N("INTERNAL",`document not found: ${t}`);const u=kt(c,r,"update")||(f.aggregateIndexes??[]).length>0||(f.rankIndexes??[]).length>0?Z(f,$)??void 0:void 0,p=a?.allowExplicitId&&typeof i._creationTime=="number"?i._creationTime:L(),d={...i,_creationTime:p,_id:t};ct(f,i,d,K),ke(f,d),j(r,"before","update")&&await P("before","update",{doc:{...d},id:t,op:"update",previous:u,table:r}),await Ee(r),await me(r);const h=Object.keys(f.shape),m=e.join([e`${e.identifier("_creationTime")} = ${p}`,...h.map(b=>e`${e.identifier(b)} = ${H(d[b]??null)}`)],e`, `);await be(r,"UPDATE",m,$),await ae(r,u,d),await J(r,t,u,d),await re(r,t,d,u),await F(r,t,"update",d),j(r,"after","update")&&await P("after","update",{doc:d,id:t,op:"update",previous:u,table:r})}};return je={db:q,scheduler:Se},q};export{Ci as backfillSqlSearchIndexes,Li as createSqlCtxDb,xi as decodeGlobalRow,Ii as readSqlCdcChanges,$i as runSqlAggregateMigrations,mi as runSqlCdcMigration,wi as runSqlGlobalTableMigrations,Ei as runSqlRankMigrations,gt as runSqlSearchMigrations,Ai as trimSqlCdcChanges};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/sql-store",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.69",
|
|
4
4
|
"description": "Internal dialect-parameterized SQL store core for Lunora .global() backends (D1, PlanetScale)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@lunora/errors": "1.0.0-alpha.16",
|
|
54
|
-
"@lunora/shard-engine": "1.0.0-alpha.
|
|
54
|
+
"@lunora/shard-engine": "1.0.0-alpha.15",
|
|
55
55
|
"drizzle-orm": "^0.45.2"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as N}from"@lunora/errors";import{F as mt,B as yt,T as gt,x as bt,_ as Nt,C as Tt,v as vt,D as Rt,b as St,N as It}from"./ctx-db-search-IjbCKWI8.mjs";import{A as Oi}from"./ctx-db-search-IjbCKWI8.mjs";import{aggregateTableName as G,rankTableName as Q,hasTrigger as At,runRowValidators as Oe,assertFlatPredicate as Je,mergeWhere as D,sortColumnName as z,resolveRankPartition as Xe,encodePartitionKey as Te,decodeCursor as Qe,RANK_TIEBREAK as $e,CountRlsUnsupportedError as Ze,normalizeIdStructurally as Lt,assertValidClientId as Ot,aggregateSqlFunction as ue,softDeleteScope as fe,compileWhereSql as _e,normalizeOrderKeys as Ct,buildSeekWhere as kt,resolveRelationPredicates as et,resolveWith as tt,applySelect as it,encodeCursor as Mt,NotFoundError as xt,applyOnDelete as Dt,ConflictError as we,normalizeCountArgument as qt,selectIndexForCount as Wt,encodeAggregateKey as Y,selectIndexForAggregate as Ft,readAggregateValue as Ce,runTriggers as Bt,matchesRankStaticWhere as nt,selectIndexForGroupBy as Ut,fanOutScalarCounts as jt,matchesStaticWhere as ke,foldAggregateTally as Pt,coerceAggregateNumber as Me,NotUniqueError as Ht,throwingScheduler as Kt}from"@lunora/shard-engine";import{sql as e}from"drizzle-orm";import{migrateSearchState as Vt}from"./SEARCH_STATE_TABLE-DT7nfOye.mjs";import{queryAll as I,queryRun as A,createIndexIfNotExists as De,decodeRow as Z,serializeColumnValue as H,columnRefSql as M,decodeRows as Yt,forEachRowPaged as at,queryBatch as rt}from"./decodeGlobalRow-DOhQ8Anj.mjs";import{decodeGlobalRow as ki}from"./decodeGlobalRow-DOhQ8Anj.mjs";import{effectiveColumnKind as ve}from"./decodeBigint-DWHvvLGA.mjs";const Gt=(l,w)=>{if(l.size<w)return;const _=l.keys().next().value;_!==void 0&&l.delete(_)},zt=(l,w={})=>{const _=w.maxBatch??50,r=Number.isInteger(_)&&_>0?_:50,E=new Map;let d=!1;const s=async(y,v)=>{const R=[...v.keys()];for(let L=0;L<R.length;L+=r){const x=R.slice(L,L+r);try{const F=await l(y,x);for(const K of x){const B=F.get(K);for(const Se of v.get(K)??[])Se.resolve(B)}}catch(F){for(const K of x)for(const B of v.get(K)??[])B.reject(F)}}},T=()=>{d=!1;const y=[...E.entries()];E.clear();for(const[v,R]of y)s(v,R).catch(()=>{})};return{async load(y,v){return new Promise((R,L)=>{let x=E.get(y);x||(x=new Map,E.set(y,x));const F=x.get(v);F?F.push({reject:L,resolve:R}):x.set(v,[{reject:L,resolve:R}]),d||(d=!0,queueMicrotask(T))})}}},Jt=new Set(["_id","id"]),qe=(l,w,_)=>l==="postgres"?e`${w} IS NOT DISTINCT FROM ${_}`:l==="mysql"?e`${w} <=> ${_}`:e`${w} IS ${_}`,Xt=l=>{const w=l.map(_=>e`${M(_.field)} ${e.raw(_.direction==="desc"?"DESC":"ASC")}`);return l.some(_=>Jt.has(_.field))||w.push(e`${M("id")} ASC`),e.join(w,e`, `)},ot=50,We=l=>{const w=[];for(const[_,r]of Object.entries(l.shape)){const E=r._meta?.column;E&&w.push([_,E])}return w},Qt=(l,w,_)=>{const r={...w};for(const[E,d]of We(l)){if(d.serverDefault){r[E]=d.serverDefault({auth:_});continue}r[E]===void 0&&(d.defaultFn?r[E]=d.defaultFn():"defaultValue"in d&&(r[E]=d.defaultValue))}return r},st=(l,w,_,r)=>{for(const[E,d]of We(l)){if(d.serverDefault){E in w&&(_[E]=d.serverDefault({auth:r}));continue}d.onUpdateFn&&!(E in w)&&(_[E]=d.onUpdateFn())}},Zt=128,ei=()=>{const l=new Map;return{delete:w=>{l.delete(w)},get:w=>{const _=l.get(w);if(_!==void 0)return l.delete(w),l.set(w,_),_},set:(w,_)=>{l.has(w)?l.delete(w):Gt(l,Zt),l.set(w,_)}}},ti=async(l,w,_,r,E)=>{const d=E.get(r);if(d!==void 0)return d;const s=Object.entries(_.tables).filter(([,y])=>y.shardMode===void 0||y.shardMode.kind==="global").map(([y])=>y),T=await Promise.all(s.map(async y=>({found:(await I(l,w,e`SELECT 1 FROM ${e.identifier(y)} WHERE ${e.identifier("id")} = ${r} LIMIT 1`)).length>0,tableName:y})));for(const y of T)if(y.found)return E.set(r,y.tableName),y.tableName},ee=l=>l==null?null:Number(l),ii=(l,w)=>w.map(_=>{const r={};for(const E of l)r[E]=_[E]??null;return{key:r,value:ee(_.value)}}),ni=(l,w,_)=>[...l.partitionBy??[],...l.sortBy.map(r=>r.field),...l.where?Object.keys(l.where):[]].every(r=>w[r]===_[r]),ct=l=>l.length===1?l[0]:e`(${e.join(l,e` AND `)})`,X=l=>e.join(l.map(w=>e`${e.identifier(w)}`),e`, `),te=l=>e.join(l.map(w=>e`${w}`),e`, `),ai=(l,w,_,r,E)=>{const d=[];for(let s=0;s<_.length+1;s+=1){const T=_.slice(0,s).map(R=>qe(l,e`${e.identifier(R)}`,r[R])),y=_[s],v=w.sortBy[s];s<_.length&&y!==void 0&&v!==void 0?T.push(e`${e.identifier(y)} ${e.raw(v.direction==="desc"?">":"<")} ${r[y]}`):T.push(e`${e.identifier($e)} < ${E}`),d.push(ct(T))}return d.length>0?e.join(d,e` OR `):void 0},ri=(l,w,_)=>{if(_.length!==w.length)return;const r=[];for(const[E,d]of w.entries()){const s=[];for(let T=0;T<E;T+=1){const y=w[T];y!==void 0&&s.push(qe(l,e`${e.identifier(y.column)}`,_[T]))}s.push(e`${e.identifier(d.column)} ${e.raw(d.direction==="desc"?"<":">")} ${_[E]}`),r.push(ct(s))}return e`(${e.join(r,e` OR `)})`},oi=(l,w)=>{if(l.sortBy.length===0)throw new N("INTERNAL",`rankIndex "${l.name}" requires at least one "sortBy" column for stable pagination`);const _=[{column:"__partition__",direction:"asc"}];for(const[r,E]of l.sortBy.entries())_.push({column:w[r]??z(r),direction:E.direction});return _.push({column:$e,direction:"asc"}),_},si=async(l,w,_,r,E)=>{const d=[];for(let v=0;v<E.length;v+=50)d.push(E.slice(v,v+50));const s=await Promise.all(d.map(async v=>I(l,w,e`SELECT * FROM ${e.identifier(r)} WHERE ${e.identifier("id")} IN (${te(v)})`))),T=new Map;for(const v of s)for(const R of v)T.set(R.id,R);const y=[];for(const v of E){const R=Z(_,T.get(v));R&&y.push(R)}return y},ci=l=>{const w=JSON.stringify(l),_=new TextEncoder().encode(w);let r="";for(const E of _)r+=String.fromCodePoint(E);return btoa(r)},di=(l,w)=>w.columnType(ve(l)),li=(l,w)=>{const _=[];for(const[E,d]of Object.entries(l.shape)){if(!d._meta?.column)continue;const s=d._meta.column.notNull&&d.kind!=="optional"?" NOT NULL":"";_.push(e`${e.identifier(E)} ${e.raw(`${di(d,w)}${s}`)}`)}const r=w.frameworkColumns().map(E=>e`${e.identifier(E.name)} ${e.raw(E.type)}`);return e.join([...r,..._],e`, `)},ui=async(l,w,_,r)=>{const E=d=>{const s=M(d),T=_.shape[d],y=T&&r.indexKeyPrefix?r.indexKeyPrefix(ve(T)):void 0;return y===void 0?s:e`${s}(${e.raw(String(y))})`};for(const d of _.indexes){const s=e.join(d.fields.map(T=>E(T)),e`, `);await De(l,r,{columns:s,name:`${w}_${d.name}`,table:w,unique:d.unique??!1})}for(const[d,s]of We(_))s.unique&&await De(l,r,{columns:E(d),name:`${w}_unique_${d}`,table:w,unique:!0})},fi=async(l,w,_)=>{for(const[r,E]of Object.entries(w.tables)){if(E.shardMode?.kind!=="global")continue;const d=li(E,_);await A(l,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(r)} (${d})`),await ui(l,r,E,_)}},_i=async(l,w,_)=>{const{integer:r,key:E,real:d}=_.companionTypes;for(const[s,T]of Object.entries(w.tables)){const y=T.aggregateIndexes;if(!(!y||y.length===0))for(const v of y){const R=G(s,v.name);await A(l,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(R)} (${e.identifier("__key__")} ${e.raw(E)} PRIMARY KEY, ${e.identifier("__value__")} ${e.raw(d)}, ${e.identifier("__count__")} ${e.raw(r)} NOT NULL DEFAULT 0)`),_.name==="sqlite"&&((await I(l,_,e`PRAGMA table_info(${e.identifier(R)})`)).some(L=>L.name==="__count__")||await A(l,_,e`ALTER TABLE ${e.identifier(R)} ADD COLUMN ${e.identifier("__count__")} ${e.raw(r)} NOT NULL DEFAULT 0`))}}},xe=(l,w,_,r)=>{const E=l.name==="mysql"&&r?e`${e.identifier(w)}(191)`:e`${e.identifier(w)}`;return e`${E} ${e.raw(_)}`},wi=(l,w,_)=>{const r=[xe(l,"__partition__","ASC",!0)];for(const[E,d]of w.sortBy.entries()){const s=_.shape[d.field],T=s!==void 0&&l.indexKeyPrefix?.(ve(s))!==void 0;r.push(xe(l,z(E),d.direction==="desc"?"DESC":"ASC",T))}return r.push(xe(l,"__id__","ASC",!0)),r},$i=(l,w,_)=>w.sortBy.map((r,E)=>{const d=_.shape[r.field],s=l.columnType(d?ve(d):void 0);return e`${e.identifier(z(E))} ${e.raw(s)}`}),hi=async(l,w,_)=>{const{key:r}=_.companionTypes;for(const[E,d]of Object.entries(w.tables)){const s=d.rankIndexes;if(!(!s||s.length===0))for(const T of s){const y=Q(E,T.name),v=$i(_,T,d),R=v.length>0?e`, ${e.join(v,e`, `)}`:e``;await A(l,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(y)} (${e.identifier("__id__")} ${e.raw(r)} PRIMARY KEY, ${e.identifier("__partition__")} ${e.raw(r)} NOT NULL${R})`);const L=wi(_,T,d),x=`${E}__rank_${T.name}__btree`;await De(l,_,{columns:e.join(L,e`, `),name:x,table:y,unique:!1})}}},Re="__cdc_log",pi=async(l,w)=>{const{autoincrementPrimaryKey:_,key:r,real:E,text:d}=w.companionTypes;await A(l,w,e`CREATE TABLE IF NOT EXISTS ${e.identifier(Re)} (${e.identifier("seq")} ${e.raw(_)}, ${e.identifier("ts")} ${e.raw(E)} NOT NULL, ${e.identifier("table")} ${e.raw(r)} NOT NULL, ${e.identifier("id")} ${e.raw(r)} NOT NULL, ${e.identifier("op")} ${e.raw(r)} NOT NULL, ${e.identifier("doc")} ${e.raw(d)})`)},Ei=async(l,w,_,r,E,d,s)=>{await A(l,s,e`INSERT INTO ${e.identifier(Re)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${w}, ${_}, ${r}, ${E}, ${d===void 0?null:JSON.stringify(d)})`)},Ri=async(l,w,_)=>{const r=w.sinceSeq??0,E=Math.max(1,Math.min(w.limit??1e3,1e4)),d=(await I(l,_,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(Re)} WHERE seq > ${r} ORDER BY seq ASC LIMIT ${e.raw(String(E))}`)).map(s=>{const{doc:T}=s,y={id:String(s.id),op:String(s.op),seq:Number(s.seq),table:String(s.table),ts:Number(s.ts)};return typeof T=="string"?{...y,doc:JSON.parse(T)}:y});return{changes:d,cursor:d.at(-1)?.seq??r}},Si=async(l,w,_)=>{await A(l,_,e`DELETE FROM ${e.identifier(Re)} WHERE ${e.identifier("seq")} <= ${w}`)},Ii=l=>{const{crossShardCounter:w,crossShardReader:_,exec:r,maxRelationKeys:E,schema:d}=l,{dialect:s}=l,{isUniqueViolation:T}=s,y={fieldRef:M,serialize:H,...s.name==="mysql"?{likeContains:(t,i)=>e`${t} LIKE CONCAT('%', ${i}, '%') ESCAPE '\\\\'`}:{}},v=(t,i)=>qe(s.name,t,i),R=t=>{const i=X(t.columns),n=te(t.values),a=u=>s.name==="mysql"?e`VALUES(${e.identifier(u)})`:e`excluded.${e.identifier(u)}`,o=u=>s.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(u)}`:e`${e.identifier(u)}`,f=e.join(Object.entries(t.set(a,o)).map(([u,p])=>e`${e.identifier(u)} = ${p}`),e`, `),$=s.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${f}`:e`ON CONFLICT(${e.identifier(t.conflictKey)}) DO UPDATE SET ${f}`;return e`INSERT INTO ${e.identifier(t.table)} (${i}) VALUES (${n}) ${$}`},L=l.clock??(()=>Date.now()),x=l.idGenerator??(()=>crypto.randomUUID()),F=l.cdc??!1,K=l.auth??{identity:null,userId:null},B=async(t,i,n,a)=>{F&&await Ei(r,L(),t,i,n,a,s)},Se=l.scheduler??Kt,Ie=ei();let he=0,Ae;const U=async()=>(Ae??=(async()=>{await fi(r,d,s),await _i(r,d,s),await hi(r,d,s),await Vt(r,s),await yt(r,d,s),F&&await pi(r,s)})().catch(t=>{throw Ae=void 0,t}),Ae),ie=async(t,i)=>{await U();const n=await ti(r,s,d,t,Ie);if(!(i!==void 0&&n!==i))return n},ne=new Map,Fe=async(t,i)=>{const n=G(t,i);return(await I(r,s,s.tableExists(n))).length>0},pe=async(t,i)=>{const n=`${t}::${i.name}`,a=ne.get(n);if(a!==void 0)return a;if(!await Fe(t,i.name))return ne.set(n,!1),!1;const o=d.tables[t];if(!o)return ne.set(n,!1),!1;const f=i.by??[],$=new Map;await at(r,s,o,t,c=>{if(i.where&&!ke(c,i.where))return;const h=Y(f,c);Pt($,h,i,c)});const u=G(t,i.name);await A(r,s,e`DELETE FROM ${e.identifier(u)}`);const p=[];for(const[c,h]of $)p.push(e`INSERT INTO ${e.identifier(u)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${c}, ${h.value}, ${h.count})`);return await rt(r,s,p),ne.set(n,!0),!0},dt=async(t,i,n)=>{const a=ue(i.op),o=i.field??"",f=[];for(const p of i.by??[]){const c=H(n[p]??null);f.push(c===null?e`${M(p)} IS NULL`:e`${M(p)} = ${c}`)}for(const[p,c]of Object.entries(i.where??{})){const h=c!==null&&typeof c=="object"&&!Array.isArray(c)?c.eq:c,m=H(h);f.push(m===null?e`${M(p)} IS NULL`:e`${M(p)} = ${m}`)}const $=e`SELECT ${e.raw(a)}(${M(o)}) AS value FROM ${e.identifier(t)}`,u=await I(r,s,f.length>0?e`${$} WHERE ${e.join(f,e` AND `)}`:$);return ee(u[0]?.value)},lt=async(t,i)=>{await A(r,s,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${i} AND ${e.identifier("__count__")} <= 0`)},ut=async(t,i,n,a)=>{const o=G(t,i.name),{op:f}=i,$=i.field??"",u=n&&(!i.where||ke(n,i.where))?n:void 0,p=a&&(!i.where||ke(a,i.where))?a:void 0;if(!(!u&&!p)){if(f==="count"||f==="sum"||f==="avg"){const c=new Set;for(const[h,m]of[[u,-1],[p,1]]){if(!h)continue;const g=f==="count"?1:Me(h[$]);if(g===void 0)continue;const b=Y(i.by??[],h);c.add(b),await A(r,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(S,O)=>({__count__:e`${O("__count__")} + ${S("__count__")}`,__value__:f==="count"?e`${O("__value__")} + ${S("__value__")}`:e`COALESCE(${O("__value__")}, 0) + ${S("__value__")}`}),table:o,values:[b,m*g,m]}))}for(const h of c)await lt(o,h);return}if(u){const c=Y(i.by??[],u),h=Me(u[$]),m=(await I(r,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(o)} WHERE ${e.identifier("__key__")} = ${c}`))[0],g=ee(m?.value),b=(m?.count??0)-1;if(b<=0)await A(r,s,e`DELETE FROM ${e.identifier(o)} WHERE ${e.identifier("__key__")} = ${c}`);else if(m&&h!==void 0&&g!==null&&h===g){const S=await dt(t,i,u);await A(r,s,e`UPDATE ${e.identifier(o)} SET ${e.identifier("__value__")} = ${S}, ${e.identifier("__count__")} = ${b} WHERE ${e.identifier("__key__")} = ${c}`)}else await A(r,s,e`UPDATE ${e.identifier(o)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${c}`)}if(p){const c=Y(i.by??[],p),h=Me(p[$]);if(h===void 0)await A(r,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(m,g)=>({__count__:e`${g("__count__")} + 1`}),table:o,values:[c,null,1]}));else{const m=f==="min"?"MIN":"MAX";await A(r,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(g,b)=>({__count__:e`${b("__count__")} + 1`,__value__:e`${e.raw(m)}(COALESCE(${b("__value__")}, ${g("__value__")}), ${g("__value__")})`}),table:o,values:[c,h,1]}))}}}},Ee=async t=>{const i=d.tables[t]?.aggregateIndexes;if(!(!i||i.length===0))for(const n of i)await pe(t,n)},ae=async(t,i,n)=>{const a=d.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const o of a){const f=`${t}::${o.name}`;(ne.get(f)??await Fe(t,o.name))&&await ut(t,o,i,n)}},re=new Map,Be=async(t,i)=>{const n=Q(t,i);return(await I(r,s,s.tableExists(n))).length>0},Le=async(t,i)=>{const n=`${t}::rank::${i.name}`,a=re.get(n);if(a!==void 0)return a;if(!await Be(t,i.name))return re.set(n,!1),!1;const o=d.tables[t];if(!o)return re.set(n,!1),!1;const f=Q(t,i.name);await A(r,s,e`DELETE FROM ${e.identifier(f)}`);const $=i.sortBy.map((h,m)=>z(m)),u=X(["__id__","__partition__",...$]),p=[];await at(r,s,o,t,h=>{if(i.where&&!nt(h,i.where))return;const m=Te(i.partitionBy??[],h),g=i.sortBy.map(b=>H(h[b.field]??null));p.push([h._id,m,...g])});const c=p.map(h=>e`INSERT INTO ${e.identifier(f)} (${u}) VALUES (${te(h)})`);return await rt(r,s,c),re.set(n,!0),!0},me=async t=>{const i=d.tables[t]?.rankIndexes;if(!(!i||i.length===0))for(const n of i)await Le(t,n)},J=async(t,i,n,a)=>{const o=d.tables[t],f=o?.rankIndexes;if(!f||f.length===0)return;const $=o?.softDeleteMode?.field,u=$===void 0||a===void 0?void 0:a[$],p=u!=null;for(const c of f){if(n!==void 0&&a!==void 0&&ni(c,n,a))continue;const h=`${t}::rank::${c.name}`;if(!(re.get(h)??await Be(t,c.name)))continue;const m=Q(t,c.name);if(n&&await A(r,s,e`DELETE FROM ${e.identifier(m)} WHERE ${e.identifier("__id__")} = ${i}`),a&&!p){if(c.where&&!nt(a,c.where))continue;const g=c.sortBy.map((q,C)=>z(C)),b=X(["__id__","__partition__",...g]),S=Te(c.partitionBy??[],a),O=c.sortBy.map(q=>H(a[q.field]??null));await A(r,s,e`INSERT INTO ${e.identifier(m)} (${b}) VALUES (${te([i,S,...O])})`)}}},oe=mt({dialect:s,exec:r,schema:d}),Ue=new Set;for(const[t,i]of Object.entries(d.tables))for(const n of Object.values(i.triggerMap??{}))Ue.add(`${t} ${n.timing} ${n.op}`);const j=(t,i,n)=>Ue.has(`${t} ${i} ${n}`);let je;const P=async(t,i,n)=>{if(he+=1,he>ot)throw he-=1,new we(`trigger recursion exceeded ${String(ot)} levels on "${n.table}" — check for a self-triggering write`,"trigger");try{await Bt({ctx:je,event:n,op:i,schema:d,tableName:n.table,timing:t})}finally{he-=1}},ft=async(t,i)=>{try{await A(r,s,i)}catch(n){throw T(n)?new we(`unique constraint violation on "${t}"`,"unique"):n}},ye=async(t,i)=>(await I(r,s,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${i}`))[0],ge=async(t,i,n,a)=>{if(a===void 0)return;const o=e.join(Object.keys(a).map(u=>v(e`${e.identifier(u)}`,a[u])),e` AND `),f=i==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${n} WHERE ${o}`:e`DELETE FROM ${e.identifier(t)} WHERE ${o}`,$=()=>{throw new we(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")};try{if(s.supportsReturning)(await I(r,s,e`${f} RETURNING ${e.identifier("id")}`)).length===0&&$();else{const u=await A(r,s,f);(s.affectedRows?s.affectedRows(u??{rowsAffected:0}):0)===0&&$()}}catch(u){throw T(u)?new we(`unique constraint violation on "${t}"`,"unique"):u}},_t=(t,i,n,a)=>{const o=Object.keys(t.shape);return{columns:["id","_creationTime",...o],values:[i,n,...o.map(f=>H(a[f]??null))]}},wt=async(t,i,n,a)=>{const o=Ut(i,n.op,n.field,a.by,a.where);if(!o||!await pe(t,o.index))return;const f=G(t,o.index.name),$=Object.keys(o.partial);if($.length===(o.index.by??[]).length&&$.length>0){const u=Y(o.index.by??[],o.partial),p=await I(r,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(f)} WHERE ${e.identifier("__key__")} = ${u}`);if(p.length===0)return[];const c=p[0];return[{key:{...o.partial},value:Ce(n.op,{count:c.count,value:ee(c.value)})}]}return $.length>0?void 0:(await I(r,s,e`SELECT ${e.identifier("__key__")} AS key, ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(f)}`)).map(u=>{const p=u;return{key:JSON.parse(p.key),value:Ce(n.op,{count:p.count,value:ee(p.value)})}})},Pe=t=>{const i=d.tables[t]?.shardMode?.kind;return i==="shardBy"||i==="root"},He=t=>{throw new N("INTERNAL",`cross-backend relation: a global table cannot load the shard-local relation '${t}' (it spans every shard) — wire a cross-shard reader to support it`)},Ke=(t,i)=>Pe(t)?_?_(t,i):He(t):W.findMany(t,i),be=(t,i,n)=>et(t,{fetcher:Ke,maxRelationKeys:E,relationBaseWhere:n,schema:d,tableName:i}),$t=zt(async(t,i)=>{const n=await I(r,s,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} IN (${te(i)})`),a=new Map;for(const o of n){const{id:f}=o;typeof f=="string"&&a.set(f,o)}return a}),W={async aggregate(t,i){const n=d.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);if(await U(),ue(i.op),i.op==="count")return W.count(t,{baseWhere:i.baseWhere,relationBaseWhere:i.relationBaseWhere,restrictsCounts:i.restrictsCounts,where:i.where});if(!i.field)throw new N("INTERNAL",`aggregate(${t}, { op: "${i.op}" }): "field" is required for non-count reducers`);const a=fe(n.softDeleteMode,void 0),o=D(D(i.baseWhere,i.where),a),f=await be(o,t,i.relationBaseWhere),$=f!==o;if(n.aggregateIndexes&&!i.baseWhere&&!$&&!a){const m=Ft(n.aggregateIndexes,i.op,i.field,i.where);if(m&&await pe(t,m.index)){const g=Y(m.index.by??[],m.key),b=G(t,m.index.name),S=(await I(r,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(b)} WHERE ${e.identifier("__key__")} = ${g}`))[0];return Ce(i.op,S===void 0?void 0:{count:S.count,value:ee(S.value)})}}const u=_e(f,y),p=e.raw(ue(i.op)),c=e`SELECT ${p}(${M(i.field)}) AS value FROM ${e.identifier(t)}`,h=(await I(r,s,u?e`${c} WHERE ${u}`:c))[0]?.value;return h==null?null:Number(h)},async count(t,i){const n=d.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await U();const a=qt(i);if(a.restrictsCounts)throw new Ze(t);const o=fe(n.softDeleteMode,void 0),f=D(D(a.baseWhere,a.where),o),$=await be(f,t,a.relationBaseWhere),u=$!==f;if(n.aggregateIndexes&&!a.baseWhere&&!u&&!o){const m=Wt(n.aggregateIndexes,a.where);if(m&&await pe(t,m.index)){const g=Y(m.index.by??[],m.key),b=G(t,m.index.name),S=await I(r,s,e`SELECT ${e.identifier("__value__")} AS value FROM ${e.identifier(b)} WHERE ${e.identifier("__key__")} = ${g}`);return Number(S[0]?.value??0)}}const p=_e($,y),c=e`SELECT COUNT(*) AS count FROM ${e.identifier(t)}`,h=await I(r,s,p?e`${c} WHERE ${p}`:c);return Number(h[0]?.count??0)},async delete(t,i,n){const a=await ie(t,i);if(!a)return;const o=d.tables[a];if(!o)return;const f=await ye(a,t),$=Z(o,f),u=n?.hard===!0,p=!u&&o.softDeleteMode?o.softDeleteMode.field:void 0;if(!(p&&(!$||$[p]!==null&&$[p]!==void 0))){if(j(a,"before","delete")&&await P("before","delete",{id:t,op:"delete",previous:$??void 0,table:a}),await Dt({deletedId:t,deletedReference:c=>$?.[c],findHolders:async(c,h,m)=>{if(d.tables[c]?.shardMode?.kind==="shardBy")throw new N("INTERNAL",`cross-backend cascade from global '${a}' into shardBy '${c}' is not supported — would require Query Coordinator fan-out across shards`);return(await W.findMany(c,{includeDeleted:u,where:{[h]:m}})).page},onCascade:(c,h)=>W.delete(h,void 0,n),onRestrict:c=>{throw new we(c,"restrict")},onSetNull:(c,h,m)=>W.patch(h,{[m]:null}),schema:d,tableName:a}),await Ee(a),await me(a),p&&$){const c={...$,[p]:L()},h=e.join(Object.keys(o.shape).map(m=>e`${e.identifier(m)} = ${H(c[m]??null)}`),e`, `);await ge(a,"UPDATE",h,f),await ae(a,$,c),await J(a,t,$,void 0),await oe(a,t,c,$),await B(a,t,"update",c),j(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:$,table:a});return}await ge(a,"DELETE",void 0,f),Ie.delete(t),await ae(a,$??void 0,void 0),await J(a,t,$??void 0,void 0),await oe(a,t,void 0),await B(a,t,"delete"),j(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:$??void 0,table:a})}},async findFirst(t,i={}){return(await W.findMany(t,{...i,limit:1})).page[0]??null},async findFirstOrThrow(t,i={}){const n=await W.findFirst(t,i);if(n===null)throw new xt(`findFirstOrThrow: no "${t}" document matched`);return n},async findMany(t,i={}){const n=d.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await U();const a=Ct(i.orderBy),o=i.cursor?kt(a,Qe(i.cursor)):void 0,f=Ke,$=async(C,se,Ne,ce)=>{if(Pe(C))return w?jt(w,C,se,Ne,ce):He(C);const V=d.tables[C];if(!V)throw new N("INTERNAL",`unknown table: ${C}`);const k=fe(V.softDeleteMode,void 0),de={[se]:{in:Ne}},ht=D(D(de,ce),k),pt=await be(ht,C,void 0),Ve=_e(pt,y),Ye=M(se);let le=e`SELECT ${Ye} AS __fk__, COUNT(*) AS count FROM ${e.identifier(C)}`;Ve&&(le=e`${le} WHERE ${Ve}`),le=e`${le} GROUP BY ${Ye}`;const Et=await I(r,s,le),Ge=new Map;for(const ze of Et)Ge.set(ze.__fk__,Number(ze.count??0));return Ge};let u=D(i.baseWhere,i.where);u=D(u,fe(n.softDeleteMode,i.includeDeleted)),u=await et(u,{fetcher:f,maxRelationKeys:E,relationBaseWhere:i.relationBaseWhere,schema:d,tableName:t}),o&&(u=u?{AND:[u,o]}:o);const p=_e(u,y),c=Xt(a);let h=e`SELECT * FROM ${e.identifier(t)}`;p&&(h=e`${h} WHERE ${p}`),h=e`${h} ORDER BY ${c}`;const m=typeof i.limit=="number"?Math.max(0,Math.floor(i.limit)):void 0;m!==void 0&&(h=e`${h} LIMIT ${e.raw(String(m+1))}`);const g=await I(r,s,h),b=Yt(n,g);if(m===void 0)return i.with&&await tt({fetcher:f,groupedCounter:$,parents:b,schema:d,tableName:t,with:i.with}),{continueCursor:null,isDone:!0,page:it(b,i.select,i.with)};const S=b.length>m,O=S?b.slice(0,m):b,q=O.at(-1);return i.with&&await tt({fetcher:f,groupedCounter:$,parents:O,schema:d,tableName:t,with:i.with}),{continueCursor:S&&q?Mt(q,a):null,isDone:!S,page:it(O,i.select,i.with)}},async get(t,i){const n=await ie(t,i);if(!n)return null;const a=d.tables[n];return a?Z(a,await $t.load(n,t)):null},async groupBy(t,i){const n=d.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await U();const a=i.agg??{op:"count"};if(ue(a.op),a.op!=="count"&&!a.field)throw new N("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);const o=fe(n.softDeleteMode,void 0),f=D(D(i.baseWhere,i.where),o),$=await be(f,t,i.relationBaseWhere),u=$!==f;if(n.aggregateIndexes&&!i.baseWhere&&!u&&!o){const b=await wt(t,n.aggregateIndexes,a,i);if(b!==void 0)return b}const p=_e($,y),c=i.by.map(b=>e`${M(b)} AS ${e.identifier(b)}`);if(a.op==="count")c.push(e`COUNT(*) AS value`);else{if(!a.field)throw new N("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);c.push(e`${e.raw(ue(a.op))}(${M(a.field)}) AS value`)}const h=e.join(i.by.map(b=>M(b)),e`, `);let m=e`SELECT ${e.join(c,e`, `)} FROM ${e.identifier(t)}`;p&&(m=e`${m} WHERE ${p}`),m=e`${m} GROUP BY ${h}`;const g=await I(r,s,m);return ii(i.by,g)},async insert(t,i,n){const a=d.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);await U();const o=Qt(a,i,K);Oe(a,o);let f,$=!0;n?.clientId!==void 0?(Ot(n.clientId),f=n.clientId):n?.allowExplicitId&&typeof o._id=="string"?f=o._id:(f=x(),$=!1);const u=n?.allowExplicitId&&typeof o._creationTime=="number"?o._creationTime:L(),p={...o,_creationTime:u,_id:f};j(t,"before","insert")&&await P("before","insert",{doc:{...p},id:f,op:"insert",table:t}),await Ee(t),await me(t);const{columns:c,values:h}=_t(a,f,u,o);return await ft(t,e`INSERT INTO ${e.identifier(t)} (${X(c)}) VALUES (${te(h)})`),$&&Ie.set(f,t),await ae(t,void 0,p),await J(t,f,void 0,p),await oe(t,f,p),await B(t,f,"insert",p),j(t,"after","insert")&&await P("after","insert",{doc:p,id:f,op:"insert",table:t}),f},normalizeId(t,i){return Lt(d,t,i)},async patch(t,i,n){const a=await ie(t,n);if(!a)throw new N("INTERNAL",`document not found: ${t}`);const o=d.tables[a];if(!o)throw new N("INTERNAL",`document not found: ${t}`);const f=await ye(a,t),$=Z(o,f);if(!$)throw new N("INTERNAL",`document not found: ${t}`);const u={...$,...i,_id:t};st(o,i,u,K),Oe(o,u,!0),j(a,"before","update")&&await P("before","update",{doc:{...u},id:t,op:"update",previous:$,table:a}),await Ee(a),await me(a);const p=Object.keys(o.shape),c=e.join(p.map(h=>e`${e.identifier(h)} = ${H(u[h]??null)}`),e`, `);await ge(a,"UPDATE",c,f),await ae(a,$,u),await J(a,t,$,u),await oe(a,t,u,$),await B(a,t,"update",u),j(a,"after","update")&&await P("after","update",{doc:u,id:t,op:"update",previous:$,table:a})},async restore(t,i){const n=await ie(t,i);if(!n)throw new N("INTERNAL",`document not found: ${t}`);const a=d.tables[n],o=a?.softDeleteMode?.field;if(!a||!o)throw new N("INTERNAL",`ctx.db.restore: table "${n}" is not a .softDelete() table`);const f=await ye(n,t),$=f?.[o]!==null&&f?.[o]!==void 0;if(await W.patch(t,{[o]:null},i),$){const u=Z(a,f);u!==null&&await J(n,t,void 0,{...u,[o]:null})}},query(t){const i=d.tables[t];if(!i)throw new N("INTERNAL",`unknown table: ${t}`);const n="the legacy query()/withIndex() reader is not available on the D1 (global) backend; use findMany",a=[],o=u=>a.every(p=>p(u)),f=async(u,p)=>{await U();const c=a.length>0,h=await vt(r,s,i,t,u,Rt(c?void 0:p));if(!c)return p===void 0&&St(h),h;const m=h.filter(g=>o(g));return p===void 0?m:m.slice(0,p)},$=u=>{const p={async*[Symbol.asyncIterator](){if(!u)throw new N("INTERNAL",n);yield*await f(u,void 0)},async collect(){if(!u)throw new N("INTERNAL",n);return f(u,void 0)},async collectWithScores(){throw new N("INTERNAL",`collectWithScores() is not supported on \`.global()\` tables (table "${t}") — relevance scores are not yet surfaced on this backend; use .collect() instead`)},filter(c){return a.push(c),p},async first(){if(!u)throw new N("INTERNAL",n);return(await f(u,1))[0]??null},order(){return p},async paginate(c){if(!u)throw new N("INTERNAL",n);const h=Nt(c);return Tt(await f(u,It(h)),h)},async take(c){if(!u)throw new N("INTERNAL",n);return f(u,c)},async unique(){if(!u)throw new N("INTERNAL",n);const c=await f(u,2);if(c.length>1)throw new Ht(`unique() on table "${t}" matched ${String(c.length)} documents; expected at most one`);return c[0]??null},withGeoIndex(){throw new N("INTERNAL",`geo indexes are not supported on \`.global()\` tables (table "${t}") — geospatial queries run only on sharded tables`)},withIndex(){throw new N("INTERNAL",n)},withSearchIndex(c,h){const m=(i.searchIndexes??[]).find(b=>b.name===c);if(!m)throw new N("INTERNAL",`unknown search index "${c}" on table "${t}"`);const g={definition:m,field:m.field,filters:[],hasQuery:!1,indexName:c,query:""};if(h(gt(g,t,bt(m.language))),!g.hasQuery)throw new N("INTERNAL",`search index "${c}" on table "${t}" requires a .search(field, query) call`);return $(g)}};return p};return $(void 0)},async rank(t,i,n){const a=d.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const o=a.rankIndexes?.find(q=>q.name===i);if(!o)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(n.restrictsCounts)throw new Ze(t);if(await U(),!await Le(t,o))return null;const f=typeof n.row=="string"?n.row:n.row._id;if(!f)return null;const $=Q(t,o.name),u=o.sortBy.map((q,C)=>z(C)),p=X(["__partition__",...u]),c=(await I(r,s,e`SELECT ${p} FROM ${e.identifier($)} WHERE ${e.identifier("__id__")} = ${f}`))[0];if(!c)return null;const h=c.__partition__,m=D(n.baseWhere,n.where);Je(m,d,t,"rank");const g=Xe(o,m);if(g&&Te(o.partitionBy??[],g)!==h)return null;const b=ai(s.name,o,u,c,f),S=await I(r,s,e`SELECT COUNT(*) AS c FROM ${e.identifier($)} WHERE ${e.identifier("__partition__")} = ${h}${b?e` AND (${b})`:e``}`),O=await I(r,s,e`SELECT COUNT(*) AS c FROM ${e.identifier($)} WHERE ${e.identifier("__partition__")} = ${h}`);return{position:Number(S[0]?.c??0)+1,total:Number(O[0]?.c??0)}},async rankPage(t,i,n={}){Je(D(n.baseWhere,n.where),d,t,"rankPage");const a=d.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const o=a.rankIndexes?.find(k=>k.name===i);if(!o)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(await U(),!await Le(t,o))return{continueCursor:null,isDone:!0,page:[]};const f=Q(t,o.name),$=o.sortBy.map((k,de)=>z(de)),u=Math.max(1,Math.min(1e3,Math.floor(n.take??100))),p=D(n.baseWhere,n.where),c=Xe(o,p),h=oi(o,$),m=e.join(h.map(k=>e`${e.identifier(k.column)} ${e.raw(k.direction==="desc"?"DESC":"ASC")}`),e`, `),g=[];if(c&&g.push(e`${e.identifier("__partition__")} = ${Te(o.partitionBy??[],c)}`),n.cursor){const k=ri(s.name,h,Qe(n.cursor));k!==void 0&&g.push(k)}const b=X([$e,"__partition__",...$]);let S=e`SELECT ${b} FROM ${e.identifier(f)}`;g.length>0&&(S=e`${S} WHERE ${e.join(g,e` AND `)}`),S=e`${S} ORDER BY ${m} LIMIT ${e.raw(String(u+1))}`;const O=await I(r,s,S),q=O.length>u,C=q?O.slice(0,u):O,se=C.map(k=>k[$e]),Ne=await si(r,s,a,t,se);let ce=null;const V=C.at(-1);if(q&&V!==void 0){const k=[V.__partition__,...$.map(de=>V[de]),V[$e]];ce=ci(k)}return{continueCursor:ce,isDone:!q,page:Ne}},async replace(t,i,n,a){const o=await ie(t,n);if(!o)throw new N("INTERNAL",`document not found: ${t}`);const f=d.tables[o];if(!f)throw new N("INTERNAL",`document not found: ${t}`);const $=await ye(o,t);if($===void 0)throw new N("INTERNAL",`document not found: ${t}`);const u=At(d,o,"update")||(f.aggregateIndexes??[]).length>0||(f.rankIndexes??[]).length>0?Z(f,$)??void 0:void 0,p=a?.allowExplicitId&&typeof i._creationTime=="number"?i._creationTime:L(),c={...i,_creationTime:p,_id:t};st(f,i,c,K),Oe(f,c),j(o,"before","update")&&await P("before","update",{doc:{...c},id:t,op:"update",previous:u,table:o}),await Ee(o),await me(o);const h=Object.keys(f.shape),m=e.join([e`${e.identifier("_creationTime")} = ${p}`,...h.map(g=>e`${e.identifier(g)} = ${H(c[g]??null)}`)],e`, `);await ge(o,"UPDATE",m,$),await ae(o,u,c),await J(o,t,u,c),await oe(o,t,c,u),await B(o,t,"update",c),j(o,"after","update")&&await P("after","update",{doc:c,id:t,op:"update",previous:u,table:o})}};return je={db:W,scheduler:Se},W};export{Oi as backfillSqlSearchIndexes,Ii as createSqlCtxDb,ki as decodeGlobalRow,Ri as readSqlCdcChanges,_i as runSqlAggregateMigrations,pi as runSqlCdcMigration,fi as runSqlGlobalTableMigrations,hi as runSqlRankMigrations,yt as runSqlSearchMigrations,Si as trimSqlCdcChanges};
|