@lunora/sql-store 1.0.0-alpha.52 → 1.0.0-alpha.54

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
@@ -2,7 +2,6 @@ import { TableDefinitionLike, SchemaLike, ServerDefaultContextLike, DatabaseWrit
2
2
  import { SqlRunResult, SqlDialect } from "./dialect.mjs";
3
3
  export type { SqlExec } from "./dialect.mjs";
4
4
  import 'drizzle-orm';
5
- import '@lunora/search-core';
6
5
  /**
7
6
  * Async SQL surface the D1 ORM needs: `all` for reads, `run` for writes.
8
7
  * Satisfied by a `D1Session`/`D1Client` in production and a `node:sqlite`
package/dist/index.d.ts CHANGED
@@ -2,7 +2,6 @@ import { TableDefinitionLike, SchemaLike, ServerDefaultContextLike, DatabaseWrit
2
2
  import { SqlRunResult, SqlDialect } from "./dialect.js";
3
3
  export type { SqlExec } from "./dialect.js";
4
4
  import 'drizzle-orm';
5
- import '@lunora/search-core';
6
5
  /**
7
6
  * Async SQL surface the D1 ORM needs: `all` for reads, `run` for writes.
8
7
  * Satisfied by a `D1Session`/`D1Client` in production and a `node:sqlite`
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{createSqlCtxDb as o,readSqlCdcChanges as t,runSqlAggregateMigrations as a,runSqlCdcMigration as i,runSqlGlobalTableMigrations as l,runSqlRankMigrations as n,trimSqlCdcChanges as S}from"./packem_shared/createSqlCtxDb-GMqRy9kV.mjs";import{backfillSqlSearchIndexes as d,runSqlSearchMigrations as g}from"./packem_shared/backfillSqlSearchIndexes-DBD_C3SK.mjs";import{SEARCH_STATE_TABLE as s,migrateSearchState as f}from"./packem_shared/SEARCH_STATE_TABLE-DWm7Rza8.mjs";import{decodeBigint as C,effectiveColumnKind as x,sqliteDecode as u,sqliteEncode as b,tryJsonParse as h}from"./packem_shared/decodeBigint-DfiI8pkL.mjs";import{decodeGlobalRow as M}from"./packem_shared/decodeGlobalRow-k4q7Ma1g.mjs";export{s as SEARCH_STATE_TABLE,d as backfillSqlSearchIndexes,o as createSqlCtxDb,C as decodeBigint,M as decodeGlobalRow,x as effectiveColumnKind,f as migrateSearchState,t as readSqlCdcChanges,a as runSqlAggregateMigrations,i as runSqlCdcMigration,l as runSqlGlobalTableMigrations,n as runSqlRankMigrations,g as runSqlSearchMigrations,u as sqliteDecode,b as sqliteEncode,S as trimSqlCdcChanges,h as tryJsonParse};
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-CTOIJx5h.mjs";import{A as s,B as d}from"./packem_shared/ctx-db-search-B_0pAmT_.mjs";import{SEARCH_STATE_TABLE as q,migrateSearchState as f}from"./packem_shared/SEARCH_STATE_TABLE-DWm7Rza8.mjs";import{decodeBigint as C,effectiveColumnKind as x,sqliteDecode as u,sqliteEncode as b,tryJsonParse as h}from"./packem_shared/decodeBigint-DfiI8pkL.mjs";import{decodeGlobalRow as A}from"./packem_shared/decodeGlobalRow-k4q7Ma1g.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{A as o,F as t,v as s,B as l}from"./ctx-db-search-B_0pAmT_.mjs";import"@lunora/errors";import"drizzle-orm";import"./SEARCH_STATE_TABLE-DWm7Rza8.mjs";import"./decodeGlobalRow-k4q7Ma1g.mjs";export{o as backfillSqlSearchIndexes,t as createSearchSync,s as runSqlSearch,l as runSqlSearchMigrations};
@@ -0,0 +1 @@
1
+ import{aggregateTableName as K,rankTableName as G,hasTrigger as wt,runRowValidators as Se,assertFlatPredicate as Ge,mergeWhere as M,sortColumnName as V,resolveRankPartition as Ye,encodePartitionKey as me,decodeCursor as Qe,RANK_TIEBREAK as le,CountRlsUnsupportedError as Xe,normalizeIdStructurally as ht,assertValidClientId as Et,aggregateSqlFunction as oe,softDeleteScope as se,compileWhereSql as ce,normalizeOrderKeys as pt,buildSeekWhere as mt,resolveRelationPredicates as Je,resolveWith as Ze,applySelect as et,encodeCursor as yt,NotFoundError as bt,applyOnDelete as gt,ConflictError as de,normalizeCountArgument as Nt,selectIndexForCount as Tt,encodeAggregateKey as U,selectIndexForAggregate as vt,readAggregateValue as Ae,runTriggers as Rt,matchesRankStaticWhere as tt,selectIndexForGroupBy as St,fanOutScalarCounts as At,matchesStaticWhere as Ie,foldAggregateTally as It,coerceAggregateNumber as Le,NotUniqueError as Lt,throwingScheduler as Ot}from"@lunora/do";import{LunoraError as N}from"@lunora/errors";import{F as Ct,B as kt,T as xt,a as Mt,N as Dt,_ as qt,v as Wt,D as Ft,b as jt,C as Bt}from"./ctx-db-search-B_0pAmT_.mjs";import{A as Ri}from"./ctx-db-search-B_0pAmT_.mjs";import{sql as e}from"drizzle-orm";import{migrateSearchState as Ut}from"./SEARCH_STATE_TABLE-DWm7Rza8.mjs";import{queryAll as R,queryRun as A,createIndexIfNotExists as Ce,decodeRow as Y,serializeColumnValue as B,columnRefSql as k,decodeRows as Pt,forEachRowPaged as it}from"./decodeGlobalRow-k4q7Ma1g.mjs";import{decodeGlobalRow as Ai}from"./decodeGlobalRow-k4q7Ma1g.mjs";import{effectiveColumnKind as ye}from"./decodeBigint-DfiI8pkL.mjs";const Ht=(u,$)=>{if(u.size<$)return;const f=u.keys().next().value;f!==void 0&&u.delete(f)},Kt=new Set(["_id","id"]),ke=(u,$,f)=>u==="postgres"?e`${$} IS NOT DISTINCT FROM ${f}`:u==="mysql"?e`${$} <=> ${f}`:e`${$} IS ${f}`,Vt=u=>{const $=u.map(f=>e`${k(f.field)} ${e.raw(f.direction==="desc"?"DESC":"ASC")}`);return u.some(f=>Kt.has(f.field))||$.push(e`${k("id")} ASC`),e.join($,e`, `)},nt=50,xe=u=>{const $=[];for(const[f,r]of Object.entries(u.shape)){const m=r._meta?.column;m&&$.push([f,m])}return $},zt=(u,$,f)=>{const r={...$};for(const[m,l]of xe(u)){if(l.serverDefault){r[m]=l.serverDefault({auth:f});continue}r[m]===void 0&&(l.defaultFn?r[m]=l.defaultFn():"defaultValue"in l&&(r[m]=l.defaultValue))}return r},at=(u,$,f,r)=>{for(const[m,l]of xe(u)){if(l.serverDefault){m in $&&(f[m]=l.serverDefault({auth:r}));continue}l.onUpdateFn&&!(m in $)&&(f[m]=l.onUpdateFn())}},Gt=128,Yt=()=>{const u=new Map;return{delete:$=>{u.delete($)},get:$=>{const f=u.get($);if(f!==void 0)return u.delete($),u.set($,f),f},set:($,f)=>{u.has($)?u.delete($):Ht(u,Gt),u.set($,f)}}},Qt=async(u,$,f,r,m)=>{const l=m.get(r);if(l!==void 0)return l;const c=[];for(const[g,S]of Object.entries(f.tables))S.shardMode!==void 0&&S.shardMode.kind!=="global"||c.push(g);const T=await Promise.all(c.map(async g=>({found:(await R(u,$,e`SELECT 1 FROM ${e.identifier(g)} WHERE ${e.identifier("id")} = ${r} LIMIT 1`)).length>0,tableName:g})));for(const g of T)if(g.found)return m.set(r,g.tableName),g.tableName},Q=u=>u==null?null:Number(u),Xt=(u,$)=>$.map(f=>{const r={};for(const m of u)r[m]=f[m]??null;return{key:r,value:Q(f.value)}}),Jt=(u,$,f)=>[...u.partitionBy??[],...u.sortBy.map(r=>r.field),...u.where?Object.keys(u.where):[]].every(r=>$[r]===f[r]),rt=u=>u.length===1?u[0]:e`(${e.join(u,e` AND `)})`,Zt=(u,$,f,r,m)=>{const l=[];for(let c=0;c<f.length+1;c+=1){const T=f.slice(0,c).map(I=>ke(u,e`${e.identifier(I)}`,r[I])),g=f[c],S=$.sortBy[c];c<f.length&&g!==void 0&&S!==void 0?T.push(e`${e.identifier(g)} ${e.raw(S.direction==="desc"?">":"<")} ${r[g]}`):T.push(e`${e.identifier(le)} < ${m}`),l.push(rt(T))}return l.length>0?e.join(l,e` OR `):void 0},ei=(u,$,f)=>{if(f.length!==$.length)return;const r=[];for(const[m,l]of $.entries()){const c=[];for(let T=0;T<m;T+=1){const g=$[T];g!==void 0&&c.push(ke(u,e`${e.identifier(g.column)}`,f[T]))}c.push(e`${e.identifier(l.column)} ${e.raw(l.direction==="desc"?"<":">")} ${f[m]}`),r.push(rt(c))}return e`(${e.join(r,e` OR `)})`},ti=(u,$)=>{if(u.sortBy.length===0)throw new N("INTERNAL",`rankIndex "${u.name}" requires at least one "sortBy" column for stable pagination`);const f=[{column:"__partition__",direction:"asc"}];for(const[r,m]of u.sortBy.entries())f.push({column:$[r]??V(r),direction:m.direction});return f.push({column:le,direction:"asc"}),f},ii=async(u,$,f,r,m)=>{const l=[];for(let S=0;S<m.length;S+=50)l.push(m.slice(S,S+50));const c=await Promise.all(l.map(async S=>{const I=e.join(S.map(D=>e`${D}`),e`, `);return R(u,$,e`SELECT * FROM ${e.identifier(r)} WHERE ${e.identifier("id")} IN (${I})`)})),T=new Map;for(const S of c)for(const I of S)T.set(I.id,I);const g=[];for(const S of m){const I=Y(f,T.get(S));I&&g.push(I)}return g},ni=u=>{const $=JSON.stringify(u),f=new TextEncoder().encode($);let r="";for(const m of f)r+=String.fromCodePoint(m);return btoa(r)},ai=(u,$)=>$.columnType(ye(u)),ri=(u,$)=>{const f=[];for(const[m,l]of Object.entries(u.shape)){if(!l._meta?.column)continue;const c=l._meta.column.notNull&&l.kind!=="optional"?" NOT NULL":"";f.push(e`${e.identifier(m)} ${e.raw(`${ai(l,$)}${c}`)}`)}const r=$.frameworkColumns().map(m=>e`${e.identifier(m.name)} ${e.raw(m.type)}`);return e.join([...r,...f],e`, `)},oi=async(u,$,f,r)=>{const m=l=>{const c=k(l),T=f.shape[l],g=T&&r.indexKeyPrefix?r.indexKeyPrefix(ye(T)):void 0;return g===void 0?c:e`${c}(${e.raw(String(g))})`};for(const l of f.indexes){const c=e.join(l.fields.map(T=>m(T)),e`, `);await Ce(u,r,{columns:c,name:`${$}_${l.name}`,table:$,unique:l.unique??!1})}for(const[l,c]of xe(f))c.unique&&await Ce(u,r,{columns:m(l),name:`${$}_unique_${l}`,table:$,unique:!0})},si=async(u,$,f)=>{for(const[r,m]of Object.entries($.tables)){if(m.shardMode?.kind!=="global")continue;const l=ri(m,f);await A(u,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(r)} (${l})`),await oi(u,r,m,f)}},ci=async(u,$,f)=>{const{integer:r,key:m,real:l}=f.companionTypes;for(const[c,T]of Object.entries($.tables)){const g=T.aggregateIndexes;if(!(!g||g.length===0))for(const S of g){const I=K(c,S.name);await A(u,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(I)} (${e.identifier("__key__")} ${e.raw(m)} PRIMARY KEY, ${e.identifier("__value__")} ${e.raw(l)}, ${e.identifier("__count__")} ${e.raw(r)} NOT NULL DEFAULT 0)`),f.name==="sqlite"&&((await R(u,f,e`PRAGMA table_info(${e.identifier(I)})`)).some(D=>D.name==="__count__")||await A(u,f,e`ALTER TABLE ${e.identifier(I)} ADD COLUMN ${e.identifier("__count__")} ${e.raw(r)} NOT NULL DEFAULT 0`))}}},Oe=(u,$,f,r)=>{const m=u.name==="mysql"&&r?e`${e.identifier($)}(191)`:e`${e.identifier($)}`;return e`${m} ${e.raw(f)}`},di=(u,$,f)=>{const r=[Oe(u,"__partition__","ASC",!0)];for(const[m,l]of $.sortBy.entries()){const c=f.shape[l.field],T=c!==void 0&&u.indexKeyPrefix?.(ye(c))!==void 0;r.push(Oe(u,V(m),l.direction==="desc"?"DESC":"ASC",T))}return r.push(Oe(u,"__id__","ASC",!0)),r},li=(u,$,f)=>$.sortBy.map((r,m)=>{const l=f.shape[r.field],c=u.columnType(l?ye(l):void 0);return e`${e.identifier(V(m))} ${e.raw(c)}`}),ui=async(u,$,f)=>{const{key:r}=f.companionTypes;for(const[m,l]of Object.entries($.tables)){const c=l.rankIndexes;if(!(!c||c.length===0))for(const T of c){const g=G(m,T.name),S=li(f,T,l),I=S.length>0?e`, ${e.join(S,e`, `)}`:e``;await A(u,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(g)} (${e.identifier("__id__")} ${e.raw(r)} PRIMARY KEY, ${e.identifier("__partition__")} ${e.raw(r)} NOT NULL${I})`);const D=di(f,T,l),ge=`${m}__rank_${T.name}__btree`;await Ce(u,f,{columns:e.join(D,e`, `),name:ge,table:g,unique:!1})}}},be="__cdc_log",fi=async(u,$)=>{const{autoincrementPrimaryKey:f,key:r,real:m,text:l}=$.companionTypes;await A(u,$,e`CREATE TABLE IF NOT EXISTS ${e.identifier(be)} (${e.identifier("seq")} ${e.raw(f)}, ${e.identifier("ts")} ${e.raw(m)} 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(l)})`)},_i=async(u,$,f,r,m,l,c)=>{await A(u,c,e`INSERT INTO ${e.identifier(be)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${$}, ${f}, ${r}, ${m}, ${l===void 0?null:JSON.stringify(l)})`)},bi=async(u,$,f)=>{const r=$.sinceSeq??0,m=Math.max(1,Math.min($.limit??1e3,1e4)),l=(await R(u,f,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(be)} WHERE seq > ${r} ORDER BY seq ASC LIMIT ${e.raw(String(m))}`)).map(c=>{const{doc:T}=c,g={id:String(c.id),op:String(c.op),seq:Number(c.seq),table:String(c.table),ts:Number(c.ts)};return typeof T=="string"?{...g,doc:JSON.parse(T)}:g});return{changes:l,cursor:l.at(-1)?.seq??r}},gi=async(u,$,f)=>{await A(u,f,e`DELETE FROM ${e.identifier(be)} WHERE ${e.identifier("seq")} <= ${$}`)},Ni=u=>{const{crossShardCounter:$,crossShardReader:f,exec:r,maxRelationKeys:m,schema:l}=u,{dialect:c}=u,{isUniqueViolation:T}=c,g={fieldRef:k,serialize:B,...c.name==="mysql"?{likeContains:(t,i)=>e`${t} LIKE CONCAT('%', ${i}, '%') ESCAPE '\\\\'`}:{}},S=(t,i)=>ke(c.name,t,i),I=t=>{const i=e.join(t.columns.map(d=>e`${e.identifier(d)}`),e`, `),n=e.join(t.values.map(d=>e`${d}`),e`, `),a=d=>c.name==="mysql"?e`VALUES(${e.identifier(d)})`:e`excluded.${e.identifier(d)}`,o=d=>c.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(d)}`:e`${e.identifier(d)}`,_=e.join(Object.entries(t.set(a,o)).map(([d,h])=>e`${e.identifier(d)} = ${h}`),e`, `),w=c.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${_}`:e`ON CONFLICT(${e.identifier(t.conflictKey)}) DO UPDATE SET ${_}`;return e`INSERT INTO ${e.identifier(t.table)} (${i}) VALUES (${n}) ${w}`},D=u.clock??(()=>Date.now()),ge=u.idGenerator??(()=>crypto.randomUUID()),Me=u.cdc??!1,Ne=u.auth??{identity:null,userId:null},X=async(t,i,n,a)=>{Me&&await _i(r,D(),t,i,n,a,c)},ot=u.scheduler??Ot,Te=Yt();let ue=0,ve;const W=async()=>(ve??=(async()=>{await si(r,l,c),await ci(r,l,c),await ui(r,l,c),await Ut(r,c),await kt(r,l,c),Me&&await fi(r,c)})().catch(t=>{throw ve=void 0,t}),ve),J=async(t,i)=>{await W();const n=await Qt(r,c,l,t,Te);if(!(i!==void 0&&n!==i))return n},Z=new Map,De=async(t,i)=>{const n=K(t,i);return(await R(r,c,c.tableExists(n))).length>0},fe=async(t,i)=>{const n=`${t}::${i.name}`,a=Z.get(n);if(a!==void 0)return a;if(!await De(t,i.name))return Z.set(n,!1),!1;const o=l.tables[t];if(!o)return Z.set(n,!1),!1;const _=i.by??[],w=new Map;await it(r,c,o,t,h=>{if(i.where&&!Ie(h,i.where))return;const s=U(_,h);It(w,s,i,h)});const d=K(t,i.name);await A(r,c,e`DELETE FROM ${e.identifier(d)}`);for(const[h,s]of w)await A(r,c,e`INSERT INTO ${e.identifier(d)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${h}, ${s.value}, ${s.count})`);return Z.set(n,!0),!0},st=async(t,i,n)=>{const a=oe(i.op),o=i.field??"",_=[];for(const h of i.by??[]){const s=B(n[h]??null);_.push(s===null?e`${k(h)} IS NULL`:e`${k(h)} = ${s}`)}for(const[h,s]of Object.entries(i.where??{})){const E=s!==null&&typeof s=="object"&&!Array.isArray(s)?s.eq:s,p=B(E);_.push(p===null?e`${k(h)} IS NULL`:e`${k(h)} = ${p}`)}const w=e`SELECT ${e.raw(a)}(${k(o)}) AS value FROM ${e.identifier(t)}`,d=await R(r,c,_.length>0?e`${w} WHERE ${e.join(_,e` AND `)}`:w);return Q(d[0]?.value)},qe=async(t,i)=>{await A(r,c,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${i} AND ${e.identifier("__count__")} <= 0`)},ct=async(t,i,n,a)=>{const o=K(t,i.name),{op:_}=i,w=i.field??"",d=n&&(!i.where||Ie(n,i.where))?n:void 0,h=a&&(!i.where||Ie(a,i.where))?a:void 0;if(!(!d&&!h)){if(_==="count"){const s=new Set;for(const[E,p]of[[d,-1],[h,1]]){if(!E)continue;const y=U(i.by??[],E);s.add(y),await A(r,c,I({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(b,v)=>({__count__:e`${v("__count__")} + ${b("__count__")}`,__value__:e`${v("__value__")} + ${b("__value__")}`}),table:o,values:[y,p,p]}))}for(const E of s)await qe(o,E);return}if(_==="sum"||_==="avg"){const s=new Set;for(const[E,p]of[[d,-1],[h,1]]){if(!E)continue;const y=Le(E[w]);if(y===void 0)continue;const b=U(i.by??[],E);s.add(b),await A(r,c,I({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(v,C)=>({__count__:e`${C("__count__")} + ${v("__count__")}`,__value__:e`COALESCE(${C("__value__")}, 0) + ${v("__value__")}`}),table:o,values:[b,p*y,p]}))}for(const E of s)await qe(o,E);return}if(d){const s=U(i.by??[],d),E=Le(d[w]),p=(await R(r,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(o)} WHERE ${e.identifier("__key__")} = ${s}`))[0],y=Q(p?.value),b=(p?.count??0)-1;if(b<=0)await A(r,c,e`DELETE FROM ${e.identifier(o)} WHERE ${e.identifier("__key__")} = ${s}`);else if(p&&E!==void 0&&y!==null&&E===y){const v=await st(t,i,d);await A(r,c,e`UPDATE ${e.identifier(o)} SET ${e.identifier("__value__")} = ${v}, ${e.identifier("__count__")} = ${b} WHERE ${e.identifier("__key__")} = ${s}`)}else await A(r,c,e`UPDATE ${e.identifier(o)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${s}`)}if(h){const s=U(i.by??[],h),E=Le(h[w]);if(E===void 0)await A(r,c,I({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(p,y)=>({__count__:e`${y("__count__")} + 1`}),table:o,values:[s,null,1]}));else{const p=_==="min"?"MIN":"MAX";await A(r,c,I({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(y,b)=>({__count__:e`${b("__count__")} + 1`,__value__:e`${e.raw(p)}(COALESCE(${b("__value__")}, ${y("__value__")}), ${y("__value__")})`}),table:o,values:[s,E,1]}))}}}},_e=async t=>{const i=l.tables[t]?.aggregateIndexes;if(!(!i||i.length===0))for(const n of i)await fe(t,n)},ee=async(t,i,n)=>{const a=l.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const o of a){const _=`${t}::${o.name}`;(Z.get(_)??await De(t,o.name))&&await ct(t,o,i,n)}},te=new Map,We=async(t,i)=>{const n=G(t,i);return(await R(r,c,c.tableExists(n))).length>0},Re=async(t,i)=>{const n=`${t}::rank::${i.name}`,a=te.get(n);if(a!==void 0)return a;if(!await We(t,i.name))return te.set(n,!1),!1;const o=l.tables[t];if(!o)return te.set(n,!1),!1;const _=G(t,i.name);await A(r,c,e`DELETE FROM ${e.identifier(_)}`);const w=i.sortBy.map((s,E)=>V(E)),d=e.join(["__id__","__partition__",...w].map(s=>e`${e.identifier(s)}`),e`, `),h=[];await it(r,c,o,t,s=>{if(i.where&&!tt(s,i.where))return;const E=me(i.partitionBy??[],s),p=i.sortBy.map(y=>B(s[y.field]??null));h.push([s._id,E,...p])});for(const s of h){const E=e.join(s.map(p=>e`${p}`),e`, `);await A(r,c,e`INSERT INTO ${e.identifier(_)} (${d}) VALUES (${E})`)}return te.set(n,!0),!0},$e=async t=>{const i=l.tables[t]?.rankIndexes;if(!(!i||i.length===0))for(const n of i)await Re(t,n)},z=async(t,i,n,a)=>{const o=l.tables[t],_=o?.rankIndexes;if(!_||_.length===0)return;const w=o?.softDeleteMode?.field,d=w===void 0||a===void 0?void 0:a[w],h=d!=null;for(const s of _){if(n!==void 0&&a!==void 0&&Jt(s,n,a))continue;const E=`${t}::rank::${s.name}`;if(!(te.get(E)??await We(t,s.name)))continue;const p=G(t,s.name);if(n&&await A(r,c,e`DELETE FROM ${e.identifier(p)} WHERE ${e.identifier("__id__")} = ${i}`),a&&!h){if(s.where&&!tt(a,s.where))continue;const y=s.sortBy.map((L,P)=>V(P)),b=e.join(["__id__","__partition__",...y].map(L=>e`${e.identifier(L)}`),e`, `),v=me(s.partitionBy??[],a),C=s.sortBy.map(L=>B(a[L.field]??null)),x=e.join([i,v,...C].map(L=>e`${L}`),e`, `);await A(r,c,e`INSERT INTO ${e.identifier(p)} (${b}) VALUES (${x})`)}}},ie=Ct({dialect:c,exec:r,schema:l}),Fe=new Set;for(const[t,i]of Object.entries(l.tables))for(const n of Object.values(i.triggerMap??{}))Fe.add(`${t} ${n.timing} ${n.op}`);const F=(t,i,n)=>Fe.has(`${t} ${i} ${n}`);let je;const j=async(t,i,n)=>{if(ue+=1,ue>nt)throw ue-=1,new de(`trigger recursion exceeded ${String(nt)} levels on "${n.table}" — check for a self-triggering write`,"trigger");try{await Rt({ctx:je,event:n,op:i,schema:l,tableName:n.table,timing:t})}finally{ue-=1}},dt=async(t,i)=>{try{await A(r,c,i)}catch(n){throw T(n)?new de(`unique constraint violation on "${t}"`,"unique"):n}},we=async(t,i)=>(await R(r,c,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${i}`))[0],he=async(t,i,n,a)=>{if(a===void 0)return;const o=e.join(Object.keys(a).map(d=>S(e`${e.identifier(d)}`,a[d])),e` AND `),_=i==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${n} WHERE ${o}`:e`DELETE FROM ${e.identifier(t)} WHERE ${o}`,w=()=>{throw new de(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")};try{if(c.supportsReturning)(await R(r,c,e`${_} RETURNING ${e.identifier("id")}`)).length===0&&w();else{const d=await A(r,c,_);(c.affectedRows?c.affectedRows(d??{rowsAffected:0}):0)===0&&w()}}catch(d){throw T(d)?new de(`unique constraint violation on "${t}"`,"unique"):d}},lt=(t,i,n,a)=>{const o=Object.keys(t.shape);return{columns:["id","_creationTime",...o],values:[i,n,...o.map(_=>B(a[_]??null))]}},ut=async(t,i,n,a)=>{const o=St(i,n.op,n.field,a.by,a.where);if(!o||!await fe(t,o.index))return;const _=K(t,o.index.name),w=Object.keys(o.partial);if(w.length===(o.index.by??[]).length&&w.length>0){const d=U(o.index.by??[],o.partial),h=await R(r,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(_)} WHERE ${e.identifier("__key__")} = ${d}`);if(h.length===0)return[];const s=h[0];return[{key:{...o.partial},value:Ae(n.op,{count:s.count,value:Q(s.value)})}]}return w.length>0?void 0:(await R(r,c,e`SELECT ${e.identifier("__key__")} AS key, ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(_)}`)).map(d=>{const h=d;return{key:JSON.parse(h.key),value:Ae(n.op,{count:h.count,value:Q(h.value)})}})},Be=t=>{const i=l.tables[t]?.shardMode?.kind;return i==="shardBy"||i==="root"},Ue=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`)},Pe=(t,i)=>Be(t)?f?f(t,i):Ue(t):q.findMany(t,i),Ee=(t,i,n)=>Je(t,{fetcher:Pe,maxRelationKeys:m,relationBaseWhere:n,schema:l,tableName:i}),q={async aggregate(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);if(await W(),oe(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=se(n.softDeleteMode,void 0),o=M(M(i.baseWhere,i.where),a),_=await Ee(o,t,i.relationBaseWhere),w=_!==o;if(n.aggregateIndexes&&!i.baseWhere&&!w&&!a){const p=vt(n.aggregateIndexes,i.op,i.field,i.where);if(p&&await fe(t,p.index)){const y=U(p.index.by??[],p.key),b=K(t,p.index.name),v=(await R(r,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(b)} WHERE ${e.identifier("__key__")} = ${y}`))[0];return Ae(i.op,v===void 0?void 0:{count:v.count,value:Q(v.value)})}}const d=ce(_,g),h=e.raw(oe(i.op)),s=e`SELECT ${h}(${k(i.field)}) AS value FROM ${e.identifier(t)}`,E=(await R(r,c,d?e`${s} WHERE ${d}`:s))[0]?.value;return E==null?null:Number(E)},async count(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await W();const a=Nt(i);if(a.restrictsCounts)throw new Xe(t);const o=se(n.softDeleteMode,void 0),_=M(M(a.baseWhere,a.where),o),w=await Ee(_,t,a.relationBaseWhere),d=w!==_;if(n.aggregateIndexes&&!a.baseWhere&&!d&&!o){const p=Tt(n.aggregateIndexes,a.where);if(p&&await fe(t,p.index)){const y=U(p.index.by??[],p.key),b=K(t,p.index.name),v=await R(r,c,e`SELECT ${e.identifier("__value__")} AS value FROM ${e.identifier(b)} WHERE ${e.identifier("__key__")} = ${y}`);return Number(v[0]?.value??0)}}const h=ce(w,g),s=e`SELECT COUNT(*) AS count FROM ${e.identifier(t)}`,E=await R(r,c,h?e`${s} WHERE ${h}`:s);return Number(E[0]?.count??0)},async delete(t,i,n){const a=await J(t,i);if(!a)return;const o=l.tables[a];if(!o)return;const _=await we(a,t),w=Y(o,_),d=n?.hard===!0,h=!d&&o.softDeleteMode?o.softDeleteMode.field:void 0;if(!(h&&(!w||w[h]!==null&&w[h]!==void 0))){if(F(a,"before","delete")&&await j("before","delete",{id:t,op:"delete",previous:w??void 0,table:a}),await gt({deletedId:t,deletedReference:s=>w?.[s],findHolders:async(s,E,p)=>{if(l.tables[s]?.shardMode?.kind==="shardBy")throw new N("INTERNAL",`cross-backend cascade from global '${a}' into shardBy '${s}' is not supported — would require Query Coordinator fan-out across shards`);return(await q.findMany(s,{includeDeleted:d,where:{[E]:p}})).page},onCascade:(s,E)=>q.delete(E,void 0,n),onRestrict:s=>{throw new de(s,"restrict")},onSetNull:(s,E,p)=>q.patch(E,{[p]:null}),schema:l,tableName:a}),await _e(a),await $e(a),h&&w){const s={...w,[h]:D()},E=e.join(Object.keys(o.shape).map(p=>e`${e.identifier(p)} = ${B(s[p]??null)}`),e`, `);await he(a,"UPDATE",E,_),await ee(a,w,s),await z(a,t,w,void 0),await ie(a,t,s,w),await X(a,t,"update",s),F(a,"after","delete")&&await j("after","delete",{id:t,op:"delete",previous:w,table:a});return}await he(a,"DELETE",void 0,_),Te.delete(t),await ee(a,w??void 0,void 0),await z(a,t,w??void 0,void 0),await ie(a,t,void 0),await X(a,t,"delete"),F(a,"after","delete")&&await j("after","delete",{id:t,op:"delete",previous:w??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 bt(`findFirstOrThrow: no "${t}" document matched`);return n},async findMany(t,i={}){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await W();const a=pt(i.orderBy),o=i.cursor?mt(a,Qe(i.cursor)):void 0,_=Pe,w=async(L,P,pe,ne)=>{if(Be(L))return $?At($,L,P,pe,ne):Ue(L);const H=l.tables[L];if(!H)throw new N("INTERNAL",`unknown table: ${L}`);const O=se(H.softDeleteMode,void 0),ae={[P]:{in:pe}},ft=M(M(ae,ne),O),_t=await Ee(ft,L,void 0),He=ce(_t,g),Ke=k(P);let re=e`SELECT ${Ke} AS __fk__, COUNT(*) AS count FROM ${e.identifier(L)}`;He&&(re=e`${re} WHERE ${He}`),re=e`${re} GROUP BY ${Ke}`;const $t=await R(r,c,re),Ve=new Map;for(const ze of $t)Ve.set(ze.__fk__,Number(ze.count??0));return Ve};let d=M(i.baseWhere,i.where);d=M(d,se(n.softDeleteMode,i.includeDeleted)),d=await Je(d,{fetcher:_,maxRelationKeys:m,relationBaseWhere:i.relationBaseWhere,schema:l,tableName:t}),o&&(d=d?{AND:[d,o]}:o);const h=ce(d,g),s=Vt(a);let E=e`SELECT * FROM ${e.identifier(t)}`;h&&(E=e`${E} WHERE ${h}`),E=e`${E} ORDER BY ${s}`;const p=typeof i.limit=="number"?Math.max(0,Math.floor(i.limit)):void 0;p!==void 0&&(E=e`${E} LIMIT ${e.raw(String(p+1))}`);const y=await R(r,c,E),b=Pt(n,y);if(p===void 0)return i.with&&await Ze({fetcher:_,groupedCounter:w,parents:b,schema:l,tableName:t,with:i.with}),{continueCursor:null,isDone:!0,page:et(b,i.select,i.with)};const v=b.length>p,C=v?b.slice(0,p):b,x=C.at(-1);return i.with&&await Ze({fetcher:_,groupedCounter:w,parents:C,schema:l,tableName:t,with:i.with}),{continueCursor:v&&x?yt(x,a):null,isDone:!v,page:et(C,i.select,i.with)}},async get(t,i){const n=await J(t,i);if(!n)return null;const a=l.tables[n];if(!a)return null;const o=await R(r,c,e`SELECT * FROM ${e.identifier(n)} WHERE ${e.identifier("id")} = ${t}`);return Y(a,o[0])},async groupBy(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await W();const a=i.agg??{op:"count"};if(oe(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=se(n.softDeleteMode,void 0),_=M(M(i.baseWhere,i.where),o),w=await Ee(_,t,i.relationBaseWhere),d=w!==_;if(n.aggregateIndexes&&!i.baseWhere&&!d&&!o){const b=await ut(t,n.aggregateIndexes,a,i);if(b!==void 0)return b}const h=ce(w,g),s=i.by.map(b=>e`${k(b)} AS ${e.identifier(b)}`);if(a.op==="count")s.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`);s.push(e`${e.raw(oe(a.op))}(${k(a.field)}) AS value`)}const E=e.join(i.by.map(b=>k(b)),e`, `);let p=e`SELECT ${e.join(s,e`, `)} FROM ${e.identifier(t)}`;h&&(p=e`${p} WHERE ${h}`),p=e`${p} GROUP BY ${E}`;const y=await R(r,c,p);return Xt(i.by,y)},async insert(t,i,n){const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);await W();const o=zt(a,i,Ne);Se(a,o);let _,w=!0;n?.clientId!==void 0?(Et(n.clientId),_=n.clientId):n?.allowExplicitId&&typeof o._id=="string"?_=o._id:(_=ge(),w=!1);const d=n?.allowExplicitId&&typeof o._creationTime=="number"?o._creationTime:D(),h={...o,_creationTime:d,_id:_};F(t,"before","insert")&&await j("before","insert",{doc:{...h},id:_,op:"insert",table:t}),await _e(t),await $e(t);const{columns:s,values:E}=lt(a,_,d,o),p=e.join(s.map(b=>e`${e.identifier(b)}`),e`, `),y=e.join(E.map(b=>e`${b}`),e`, `);return await dt(t,e`INSERT INTO ${e.identifier(t)} (${p}) VALUES (${y})`),w&&Te.set(_,t),await ee(t,void 0,h),await z(t,_,void 0,h),await ie(t,_,h),await X(t,_,"insert",h),F(t,"after","insert")&&await j("after","insert",{doc:h,id:_,op:"insert",table:t}),_},normalizeId(t,i){return ht(l,t,i)},async patch(t,i,n){const a=await J(t,n);if(!a)throw new N("INTERNAL",`document not found: ${t}`);const o=l.tables[a];if(!o)throw new N("INTERNAL",`document not found: ${t}`);const _=await we(a,t),w=Y(o,_);if(!w)throw new N("INTERNAL",`document not found: ${t}`);const d={...w,...i,_id:t};at(o,i,d,Ne),Se(o,d,!0),F(a,"before","update")&&await j("before","update",{doc:{...d},id:t,op:"update",previous:w,table:a}),await _e(a),await $e(a);const h=Object.keys(o.shape),s=e.join(h.map(E=>e`${e.identifier(E)} = ${B(d[E]??null)}`),e`, `);await he(a,"UPDATE",s,_),await ee(a,w,d),await z(a,t,w,d),await ie(a,t,d,w),await X(a,t,"update",d),F(a,"after","update")&&await j("after","update",{doc:d,id:t,op:"update",previous:w,table:a})},async restore(t,i){const n=await J(t,i);if(!n)throw new N("INTERNAL",`document not found: ${t}`);const a=l.tables[n],o=a?.softDeleteMode?.field;if(!a||!o)throw new N("INTERNAL",`ctx.db.restore: table "${n}" is not a .softDelete() table`);const _=await we(n,t),w=_?.[o]!==null&&_?.[o]!==void 0;if(await q.patch(t,{[o]:null},i),w){const d=Y(a,_);d!==null&&await z(n,t,void 0,{...d,[o]:null})}},query(t){const i=l.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=d=>a.every(h=>h(d)),_=async(d,h)=>{await W();const s=a.length>0,E=await Wt(r,c,i,t,d,Ft(s?void 0:h));if(!s)return h===void 0&&jt(E),E;const p=E.filter(y=>o(y));return h===void 0?p:p.slice(0,h)},w=d=>{const h={async collect(){if(!d)throw new N("INTERNAL",n);return _(d,void 0)},filter(s){if(!d)throw new N("INTERNAL",n);return a.push(s),h},async first(){if(!d)throw new N("INTERNAL",n);return(await _(d,1))[0]??null},order(){return h},async paginate(s){if(!d)throw new N("INTERNAL",n);const E=Dt(s);return qt(await _(d,Bt(E)),E)},async take(s){if(!d)throw new N("INTERNAL",n);return _(d,s)},async unique(){if(!d)throw new N("INTERNAL",n);const s=await _(d,2);if(s.length>1)throw new Lt(`unique() on table "${t}" matched ${String(s.length)} documents; expected at most one`);return s[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(s,E){const p=(i.searchIndexes??[]).find(b=>b.name===s);if(!p)throw new N("INTERNAL",`unknown search index "${s}" on table "${t}"`);const y={definition:p,field:p.field,filters:[],hasQuery:!1,indexName:s,query:""};if(E(xt(y,t,Mt(p.language))),!y.hasQuery)throw new N("INTERNAL",`search index "${s}" on table "${t}" requires a .search(field, query) call`);return w(y)}};return h};return w(void 0)},async rank(t,i,n){const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const o=a.rankIndexes?.find(x=>x.name===i);if(!o)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(n.restrictsCounts)throw new Xe(t);if(await W(),!await Re(t,o))return null;const _=typeof n.row=="string"?n.row:n.row._id;if(!_)return null;const w=G(t,o.name),d=o.sortBy.map((x,L)=>V(L)),h=e.join([e`${e.identifier("__partition__")}`,...d.map(x=>e`${e.identifier(x)}`)],e`, `),s=(await R(r,c,e`SELECT ${h} FROM ${e.identifier(w)} WHERE ${e.identifier("__id__")} = ${_}`))[0];if(!s)return null;const E=s.__partition__,p=M(n.baseWhere,n.where);Ge(p,l,t,"rank");const y=Ye(o,p);if(y&&me(o.partitionBy??[],y)!==E)return null;const b=Zt(c.name,o,d,s,_),v=await R(r,c,e`SELECT COUNT(*) AS c FROM ${e.identifier(w)} WHERE ${e.identifier("__partition__")} = ${E}${b?e` AND (${b})`:e``}`),C=await R(r,c,e`SELECT COUNT(*) AS c FROM ${e.identifier(w)} WHERE ${e.identifier("__partition__")} = ${E}`);return{position:Number(v[0]?.c??0)+1,total:Number(C[0]?.c??0)}},async rankPage(t,i,n={}){Ge(M(n.baseWhere,n.where),l,t,"rankPage");const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const o=a.rankIndexes?.find(O=>O.name===i);if(!o)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(await W(),!await Re(t,o))return{continueCursor:null,isDone:!0,page:[]};const _=G(t,o.name),w=o.sortBy.map((O,ae)=>V(ae)),d=Math.max(1,Math.min(1e3,Math.floor(n.take??100))),h=M(n.baseWhere,n.where),s=Ye(o,h),E=ti(o,w),p=e.join(E.map(O=>e`${e.identifier(O.column)} ${e.raw(O.direction==="desc"?"DESC":"ASC")}`),e`, `),y=[];if(s&&y.push(e`${e.identifier("__partition__")} = ${me(o.partitionBy??[],s)}`),n.cursor){const O=ei(c.name,E,Qe(n.cursor));O!==void 0&&y.push(O)}const b=e.join([e`${e.identifier(le)}`,e`${e.identifier("__partition__")}`,...w.map(O=>e`${e.identifier(O)}`)],e`, `);let v=e`SELECT ${b} FROM ${e.identifier(_)}`;y.length>0&&(v=e`${v} WHERE ${e.join(y,e` AND `)}`),v=e`${v} ORDER BY ${p} LIMIT ${e.raw(String(d+1))}`;const C=await R(r,c,v),x=C.length>d,L=x?C.slice(0,d):C,P=L.map(O=>O[le]),pe=await ii(r,c,a,t,P);let ne=null;const H=L.at(-1);if(x&&H!==void 0){const O=[H.__partition__,...w.map(ae=>H[ae]),H[le]];ne=ni(O)}return{continueCursor:ne,isDone:!x,page:pe}},async replace(t,i,n,a){const o=await J(t,n);if(!o)throw new N("INTERNAL",`document not found: ${t}`);const _=l.tables[o];if(!_)throw new N("INTERNAL",`document not found: ${t}`);const w=await we(o,t);if(w===void 0)throw new N("INTERNAL",`document not found: ${t}`);const d=wt(l,o,"update")||(_.aggregateIndexes??[]).length>0||(_.rankIndexes??[]).length>0?Y(_,w)??void 0:void 0,h=a?.allowExplicitId&&typeof i._creationTime=="number"?i._creationTime:D(),s={...i,_creationTime:h,_id:t};at(_,i,s,Ne),Se(_,s),F(o,"before","update")&&await j("before","update",{doc:{...s},id:t,op:"update",previous:d,table:o}),await _e(o),await $e(o);const E=Object.keys(_.shape),p=e.join([e`${e.identifier("_creationTime")} = ${h}`,...E.map(y=>e`${e.identifier(y)} = ${B(s[y]??null)}`)],e`, `);await he(o,"UPDATE",p,w),await ee(o,d,s),await z(o,t,d,s),await ie(o,t,s,d),await X(o,t,"update",s),F(o,"after","update")&&await j("after","update",{doc:s,id:t,op:"update",previous:d,table:o})}};return je={db:q,scheduler:ot},q};export{Ri as backfillSqlSearchIndexes,Ni as createSqlCtxDb,Ai as decodeGlobalRow,bi as readSqlCdcChanges,ci as runSqlAggregateMigrations,fi as runSqlCdcMigration,si as runSqlGlobalTableMigrations,ui as runSqlRankMigrations,kt as runSqlSearchMigrations,gi as trimSqlCdcChanges};
@@ -0,0 +1 @@
1
+ import{LunoraError as S}from"@lunora/errors";import{sql as i}from"drizzle-orm";import{migrateSearchState as ee,readSearchBackfillState as G,writeSearchBackfillState as R}from"./SEARCH_STATE_TABLE-DWm7Rza8.mjs";import{queryRun as w,columnRefSql as y,serializeColumnValue as M,decodeRows as U,queryAll as v,createIndexIfNotExists as z,forEachRowPaged as ie}from"./decodeGlobalRow-k4q7Ma1g.mjs";const te=["de","en","es","fr","it","nl","none","pt"],ne=e=>te.includes(e),re="a an and are as at be but by for if in into is it no not of on or such that the their then there these they this to was will with",ae="aber als am an auch auf aus bei bin bis bist da dass der den des dem die das denn dir du ein eine für hat ich im in ist mit nicht noch nur oder sich sie sind über und von vor war wie wir zu zum zur",oe="a al como con de del el en es la las lo los mas no o para pero por que se su sus un una uno y ya",se="au aux avec ce ces dans de des du elle en et eux il je la le les leur lui ma mais me même mes moi mon ne nos notre nous on ou par pas pour qu que qui sa se ses son sur ta te tes toi ton tu un une vos votre vous y",de="a ai al alla anche che chi ci coi col come con da dal degli dei del della di do e ed gli ha hai hanno i il in la le lo ma mi ne nei nel non o per più quale quanto se si sono su sul tra un una uno vi",fe="aan al als bij dan dat de der deze die dit door een en er het hij ij in is je kan me men met mij na naar niet nog nu of om ons ook op over te tot uit van voor was wat we wij zij zijn zo",ue="a ao aos as até com como da das de do dos e em entre era essa esse esta este eu foi há isso já mais mas me mesmo meu na nas no nos num numa o os ou para pela pelo por qual que quem se sem seu só sua também te tem um uma você",ce=/[\u0300-\u036F]/gu,V=e=>e.normalize("NFD").replaceAll(ce,"").normalize("NFC").toLowerCase(),_=e=>new Set(V(e).split(" ")),le={de:_(ae),en:_(re),es:_(oe),fr:_(se),it:_(de),nl:_(fe),none:new Set,pt:_(ue)},$e=2,me=256,H=new Map,A=e=>{const t=e!==void 0&&ne(e)?e:"none",n=H.get(t);if(n)return n;const r=le[t],a=s=>{const f=(V(s).match(/[\p{L}\p{N}]+/gu)??[]).filter(d=>d.length<=me);return r.size===0?f:f.filter(d=>!r.has(d))},o={document:a,profile:`${t}-v${String($e)}`,query:s=>{const f=a(s),d=new Set,u=[];for(let c=f.length-1;c>=0;c-=1){const l=f[c];d.has(l)||(d.add(l),u.unshift(l))}return u}};return H.set(t,o),o},he=(e,t)=>e.profile!==t?{cursor:void 0,finished:!1,wipe:e.cursor!==void 0||e.done}:{cursor:e.cursor,finished:e.done,wipe:!1},we=(e,t)=>{if(!t.includes("."))return e[t];let n=e;for(const r of t.split(".")){if(n===null||typeof n!="object"||Array.isArray(n))return;n=n[r]}return n},D=(e,t)=>`${e}__fts_${t}`,Ee="__text__",$="__id__",I="__token__",O="__n__",pe=1e3,Y=(e,t)=>t.document(e),q=(e,t)=>we(e,t),Se=e=>typeof e=="string"?e:e==null?"":typeof e=="number"||typeof e=="bigint"||typeof e=="boolean"?String(e):JSON.stringify(e)??"",ge=(e,t,n)=>e!==void 0&&t!==void 0&&q(e,n.field)===q(t,n.field),j=(e,t)=>Y(Se(q(e,t.field)),A(t.language)).slice(0,pe).join(" "),_e=(e,t)=>{const n=new Map;for(const r of Y(e,t))n.set(r,(n.get(r)??0)+1);return n},Ne=e=>{const t=new TextEncoder().encode(e);let n="";for(const r of t)n+=String.fromCodePoint(r);return btoa(n)},Te=e=>{const t=atob(e),n=Uint8Array.from(t,r=>r.codePointAt(0)??0);return new TextDecoder().decode(n)},ye=()=>new S("BAD_REQUEST","invalid cursor"),P=16,k=8,g=1024,L=(e,t)=>t.query(e),Ae=(e,t)=>{if(!t)return{exact:!0,lower:e,upper:e};const n=e.codePointAt(e.length-1)??0,r=e.slice(0,Math.max(0,e.length-String.fromCodePoint(n).length));return{exact:!1,lower:e,upper:r+String.fromCodePoint(n+1)}},Be=(e,t,n)=>{const r={eq:(a,o)=>{if(!e.definition.filterFields?.includes(a))throw new S("INTERNAL",`field "${a}" is not a filter field of search index "${e.indexName}" on table "${t}"`);if(e.filters.length>=k)throw new S("BAD_REQUEST",`search index "${e.indexName}" on table "${t}": at most ${String(k)} .eq() filters are supported per search query`);return e.filters.push({field:a,value:o}),r},search:(a,o)=>{const s=e;if(a!==s.definition.field)throw new S("INTERNAL",`search index "${s.indexName}" on table "${t}" indexes "${s.definition.field}", not "${a}"`);const f=L(o,n).length;if(f>P)throw new S("BAD_REQUEST",`search index "${s.indexName}" on table "${t}": at most ${String(P)} search terms are supported (got ${String(f)})`);return s.field=a,s.query=o,s.hasQuery=!0,r}};return r},Fe=e=>{if(e.length>g)throw new S("BAD_REQUEST",`more than ${String(g)} documents match this search — narrow it with filters or read it a page at a time with .paginate()`)},ze=e=>Math.min(e.offset+e.numItems+1,g),Ie=e=>Ne(`search:${String(e)}`),xe=e=>{let t;try{t=Te(e)}catch{return}if(!t.startsWith("search:"))return;const n=Number(t.slice(7));return Number.isInteger(n)&&n>=0?n:void 0},He=e=>{if(typeof e.endCursor=="string")throw new S("BAD_REQUEST","bounded (endCursor) pagination is not supported on search queries — relevance order has no stable range boundary");const t=Math.max(0,Math.floor(e.numItems)),n=e.cursor?xe(e.cursor):0;if(n===void 0)throw ye();if(n+t>g)throw new S("BAD_REQUEST",`search pagination reaches past the ${String(g)}-document limit (offset ${String(n)} + ${String(t)} requested) — narrow the query or the filters instead`);return{numItems:t,offset:n}},Pe=(e,t)=>{const n=t.offset+t.numItems,r=t.numItems>0&&e.length>n;return{continueCursor:r?Ie(n):null,isDone:!r,page:e.slice(t.offset,n)}},ke=e=>{if(e===void 0)return g+1;if(!Number.isFinite(e))return g;const t=Math.max(0,Math.floor(e));if(t>g)throw new S("BAD_REQUEST",`search returns at most ${String(g)} documents (asked for ${String(t)}) — narrow the query or paginate instead`);return t},b=async(e,t,n,r)=>{await w(e,t,i`DELETE FROM ${i.identifier(n)} WHERE ${i.identifier($)} = ${r}`)},C=(e,t)=>e.name==="mysql"?i`${i.identifier(t)}(191)`:e.textPatternOperatorClass===void 0?i`${i.identifier(t)}`:i`${i.identifier(t)} ${i.raw(e.textPatternOperatorClass)}`,W=50,Re=(e,t)=>t?i`${i.identifier(I)} LIKE ${`${e}%`}`:i`${i.identifier(I)} = ${e}`,ve=async(e,t,n,r,a,o)=>{const s=L(a.query,A(a.definition.language));if(s.length===0)return[];const f=D(r,a.indexName),d=s.length-1,u=s.map((h,T)=>Re(h,T===d)),c=i.join(u,i` OR `),l=u.map(h=>i`SUM(CASE WHEN ${h} THEN ${i.identifier(O)} ELSE 0 END)`),N=i.join(l.map(h=>i`${h} > 0`),i` AND `),E=i`SELECT ${i.identifier($)}, ${i.join(l,i` + `)} AS ${i.identifier("__score__")} FROM ${i.identifier(f)} WHERE ${c} GROUP BY ${i.identifier($)} HAVING ${N}`,p=[];for(const h of a.filters)p.push(i`m.${y(h.field)} = ${M(h.value)}`);n.softDeleteMode&&p.push(i`m.${y(n.softDeleteMode.field)} IS NULL`);let m=i`SELECT m.* FROM (${E}) s JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = s.${i.identifier($)}`;return p.length>0&&(m=i`${m} WHERE ${i.join(p,i` AND `)}`),m=i`${m} ORDER BY s.${i.identifier("__score__")} DESC, m.${i.identifier("_creationTime")} DESC, m.${i.identifier("id")} ASC LIMIT ${i.raw(String(o))}`,U(n,await v(e,t,m))},De=async(e,t,n,r,a,o)=>{const s=L(a.query,A(a.definition.language));if(s.length===0)return[];const f=D(r,a.indexName),d=`${f}__vocab`,u=s.length-1,c=s.map((m,h)=>{const T=Ae(m,h===u),Z=T.exact?i`${i.identifier("term")} = ${T.lower}`:i`${i.identifier("term")} >= ${T.lower} AND ${i.identifier("term")} < ${T.upper}`;return i`SELECT ${i.identifier("doc")}, ${i.raw(String(h))} AS ${i.identifier("__term__")}, COUNT(*) AS ${i.identifier("__n__")} FROM ${i.identifier(d)} WHERE ${Z} GROUP BY ${i.identifier("doc")}`}),l=s.map((m,h)=>i`SUM(CASE WHEN u.${i.identifier("__term__")} = ${i.raw(String(h))} THEN u.${i.identifier("__n__")} ELSE 0 END)`),N=i`SELECT f.${i.identifier($)} AS ${i.identifier($)}, ${i.join(l,i` + `)} AS ${i.identifier("__score__")} FROM (${i.join(c,i` UNION ALL `)}) u JOIN ${i.identifier(f)} f ON f.rowid = u.${i.identifier("doc")} GROUP BY f.${i.identifier($)} HAVING ${i.join(l.map(m=>i`${m} > 0`),i` AND `)}`,E=[];for(const m of a.filters)E.push(i`m.${y(m.field)} = ${M(m.value)}`);n.softDeleteMode&&E.push(i`m.${y(n.softDeleteMode.field)} IS NULL`);let p=i`SELECT m.* FROM (${N}) s JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = s.${i.identifier($)}`;return E.length>0&&(p=i`${p} WHERE ${i.join(E,i` AND `)}`),p=i`${p} ORDER BY s.${i.identifier("__score__")} DESC, m.${i.identifier("_creationTime")} DESC, m.${i.identifier("id")} ASC LIMIT ${i.raw(String(o))}`,U(n,await v(e,t,p))},Le=async(e,t,n,r,a,o)=>{const s=t.nativeTextSearch,f=L(a.query,A(a.definition.language));if(!s||f.length===0)return[];const d=D(r,a.indexName),u=[s.matches(d,f)];for(const l of a.filters)u.push(i`m.${y(l.field)} = ${M(l.value)}`);n.softDeleteMode&&u.push(i`m.${y(n.softDeleteMode.field)} IS NULL`);const c=i`SELECT m.* FROM ${i.identifier(d)} JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = ${i.identifier(d)}.${i.identifier($)} WHERE ${i.join(u,i` AND `)} ORDER BY ${s.rank(d,f)} DESC, m.${i.identifier("_creationTime")} DESC, m.${i.identifier("id")} ASC LIMIT ${i.raw(String(o))}`;return U(n,await v(e,t,c))},be={ensureCompanion:async(e,t,n)=>{const{integer:r,key:a}=t.companionTypes;await w(e,t,i`CREATE TABLE IF NOT EXISTS ${i.identifier(n)} (${i.identifier(I)} ${i.raw(a)} NOT NULL, ${i.identifier($)} ${i.raw(a)} NOT NULL, ${i.identifier(O)} ${i.raw(r)} NOT NULL)`),await z(e,t,{columns:i`${C(t,I)}, ${C(t,$)}`,name:`${n}__btree`,table:n,unique:!1}),await z(e,t,{columns:C(t,$),name:`${n}__by_id`,table:n,unique:!1})},indexDocument:async(e,t,n,r,a,o)=>{await b(e,t,n,r);const s=[..._e(j(a,o),A(o.language))],f=i.join([I,$,O].map(d=>i.identifier(d)),i`, `);for(let d=0;d<s.length;d+=W){const u=i.join(s.slice(d,d+W).map(([c,l])=>i`(${c}, ${r}, ${l})`),i`, `);await w(e,t,i`INSERT INTO ${i.identifier(n)} (${f}) VALUES ${u}`)}},name:"inverted",runSearch:ve},Ce={ensureCompanion:async(e,t,n)=>{await w(e,t,i`CREATE VIRTUAL TABLE IF NOT EXISTS ${i.identifier(n)} USING fts5(${i.identifier(Ee)}, ${i.identifier($)} UNINDEXED)`),await w(e,t,i`CREATE VIRTUAL TABLE IF NOT EXISTS ${i.identifier(`${n}__vocab`)} USING fts5vocab(${i.identifier(n)}, ${i.raw("instance")})`)},indexDocument:async(e,t,n,r,a,o)=>{await b(e,t,n,r),await w(e,t,i`INSERT INTO ${i.identifier(n)} (${i.identifier("__text__")}, ${i.identifier($)}) VALUES (${j(a,o)}, ${r})`)},name:"fts5",runSearch:De},Oe={ensureCompanion:async(e,t,n)=>{const r=t.nativeTextSearch;if(r){await w(e,t,r.createCompanion(n,t.companionTypes.key));for(const a of r.createIndexes(n))await w(e,t,a)}},indexDocument:async(e,t,n,r,a,o)=>{const s=t.nativeTextSearch;s&&(await b(e,t,n,r),await w(e,t,s.indexDocument(n,r,j(a,o))))},name:"native",runSearch:Le},x=(e,t)=>e.strategy==="native"&&t.nativeTextSearch!==void 0?Oe:t.supportsFts5?Ce:be,J=(e,t)=>`${A(e.language).profile}/${x(e,t).name}`,B=function*(e){for(const[t,n]of Object.entries(e.tables)){const r=n.searchIndexes;if(!(n.shardMode!==void 0&&n.shardMode.kind!=="global"||!r))for(const a of r)yield[t,n,a]}},F=(e,t)=>D(e,t.name),We=async(e,t,n,r,a,o)=>x(a.definition,t).runSearch(e,t,n,r,a,o),Q=200,X=async(e,t,n,r,a)=>{const o=F(r,a),s=x(a,t),f=J(a,t),d=he(await G(e,t,o),f);if(d.finished)return!0;if(d.wipe&&(await w(e,t,i`DELETE FROM ${i.identifier(o)}`),await R(e,t,o,void 0,!1,f)),(await v(e,t,t.tableExists(r))).length===0)return await R(e,t,o,void 0,!0,f),!0;let u=0,c=d.cursor;await ie(e,t,n,r,async N=>{u+=1;const E=N._id;typeof E=="string"&&(c=E,await s.indexDocument(e,t,o,E,N,a))},{after:d.cursor,limit:Q});const l=u<Q;return await R(e,t,o,c,l,f),l},K=async(e,t,n)=>{await ee(e,n);for(const[r,,a]of B(t)){const o=F(r,a),s=J(a,n),f=await G(e,n,o);f.profile!==void 0&&f.profile!==s&&(await w(e,n,i`DROP TABLE IF EXISTS ${i.identifier(o)}`),await R(e,n,o,void 0,!1,s)),await x(a,n).ensureCompanion(e,n,o)}},Qe=async(e,t,n)=>{await K(e,t,n);for(const[r,a,o]of B(t))o.staged||await X(e,n,a,r,o)},Ge=async(e,t,n)=>{await K(e,t,n);for(const[r,a,o]of B(t)){let s=!1;for(;!s;)s=await X(e,n,a,r,o)}},Ve=e=>{const{dialect:t,exec:n,schema:r}=e;return async(a,o,s,f)=>{const d=r.tables[a]?.searchIndexes;if(!(!d||d.length===0))for(const u of d){if(ge(f,s,u))continue;const c=F(a,u);if(s){await x(u,t).indexDocument(n,t,c,o,s,u);continue}await b(n,t,c,o)}}};export{Ge as A,Qe as B,ze as C,ke as D,Ve as F,He as N,Be as T,Pe as _,A as a,Fe as b,We as v};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/sql-store",
3
- "version": "1.0.0-alpha.52",
3
+ "version": "1.0.0-alpha.54",
4
4
  "description": "Internal dialect-parameterized SQL store core for Lunora .global() backends (D1, PlanetScale)",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -50,10 +50,9 @@
50
50
  "access": "public"
51
51
  },
52
52
  "dependencies": {
53
- "@lunora/do": "1.0.0-alpha.55",
53
+ "@lunora/do": "1.0.0-alpha.57",
54
54
  "@lunora/errors": "1.0.0-alpha.9",
55
- "drizzle-orm": "^0.45.2",
56
- "@lunora/search-core": "1.0.0-alpha.0"
55
+ "drizzle-orm": "^0.45.2"
57
56
  },
58
57
  "engines": {
59
58
  "node": "^22.15.0 || >=24.11.0"
@@ -1 +0,0 @@
1
- import{ftsTableName as y,FTS_ID_COLUMN as d,createSearchAnalyzer as I,analyzedSearchText as C,tokenizeSearch as x,FTS_TEXT_COLUMN as P,searchTermRange as V,countSearchTokens as Y,FTS_TOKEN_COLUMN as L,FTS_COUNT_COLUMN as A,searchTextUnchanged as X,planSearchBackfillPass as z}from"@lunora/search-core";import{sql as e}from"drizzle-orm";import{migrateSearchState as J,readSearchBackfillState as j,writeSearchBackfillState as p}from"./SEARCH_STATE_TABLE-DWm7Rza8.mjs";import{queryRun as u,columnRefSql as h,serializeColumnValue as M,decodeRows as U,queryAll as R,createIndexIfNotExists as b,forEachRowPaged as K}from"./decodeGlobalRow-k4q7Ma1g.mjs";const g=async(t,i,a,r)=>{await u(t,i,e`DELETE FROM ${e.identifier(a)} WHERE ${e.identifier(d)} = ${r}`)},D=(t,i)=>t.name==="mysql"?e`${e.identifier(i)}(191)`:t.textPatternOperatorClass===void 0?e`${e.identifier(i)}`:e`${e.identifier(i)} ${e.raw(t.textPatternOperatorClass)}`,B=50,Q=(t,i)=>i?e`${e.identifier(L)} LIKE ${`${t}%`}`:e`${e.identifier(L)} = ${t}`,Z=async(t,i,a,r,n,s)=>{const o=x(n.query,I(n.definition.language));if(o.length===0)return[];const $=y(r,n.indexName),f=o.length-1,c=o.map((S,w)=>Q(S,w===f)),l=e.join(c,e` OR `),m=c.map(S=>e`SUM(CASE WHEN ${S} THEN ${e.identifier(A)} ELSE 0 END)`),N=e.join(m.map(S=>e`${S} > 0`),e` AND `),T=e`SELECT ${e.identifier(d)}, ${e.join(m,e` + `)} AS ${e.identifier("__score__")} FROM ${e.identifier($)} WHERE ${l} GROUP BY ${e.identifier(d)} HAVING ${N}`,_=[];for(const S of n.filters)_.push(e`m.${h(S.field)} = ${M(S.value)}`);a.softDeleteMode&&_.push(e`m.${h(a.softDeleteMode.field)} IS NULL`);let E=e`SELECT m.* FROM (${T}) s JOIN ${e.identifier(r)} m ON m.${e.identifier("id")} = s.${e.identifier(d)}`;return _.length>0&&(E=e`${E} WHERE ${e.join(_,e` AND `)}`),E=e`${E} ORDER BY s.${e.identifier("__score__")} DESC, m.${e.identifier("_creationTime")} DESC, m.${e.identifier("id")} ASC LIMIT ${e.raw(String(s))}`,U(a,await R(t,i,E))},ee=async(t,i,a,r,n,s)=>{const o=x(n.query,I(n.definition.language));if(o.length===0)return[];const $=y(r,n.indexName),f=`${$}__vocab`,c=o.length-1,l=o.map((E,S)=>{const w=V(E,S===c),G=w.exact?e`${e.identifier("term")} = ${w.lower}`:e`${e.identifier("term")} >= ${w.lower} AND ${e.identifier("term")} < ${w.upper}`;return e`SELECT ${e.identifier("doc")}, ${e.raw(String(S))} AS ${e.identifier("__term__")}, COUNT(*) AS ${e.identifier("__n__")} FROM ${e.identifier(f)} WHERE ${G} GROUP BY ${e.identifier("doc")}`}),m=o.map((E,S)=>e`SUM(CASE WHEN u.${e.identifier("__term__")} = ${e.raw(String(S))} THEN u.${e.identifier("__n__")} ELSE 0 END)`),N=e`SELECT f.${e.identifier(d)} AS ${e.identifier(d)}, ${e.join(m,e` + `)} AS ${e.identifier("__score__")} FROM (${e.join(l,e` UNION ALL `)}) u JOIN ${e.identifier($)} f ON f.rowid = u.${e.identifier("doc")} GROUP BY f.${e.identifier(d)} HAVING ${e.join(m.map(E=>e`${E} > 0`),e` AND `)}`,T=[];for(const E of n.filters)T.push(e`m.${h(E.field)} = ${M(E.value)}`);a.softDeleteMode&&T.push(e`m.${h(a.softDeleteMode.field)} IS NULL`);let _=e`SELECT m.* FROM (${N}) s JOIN ${e.identifier(r)} m ON m.${e.identifier("id")} = s.${e.identifier(d)}`;return T.length>0&&(_=e`${_} WHERE ${e.join(T,e` AND `)}`),_=e`${_} ORDER BY s.${e.identifier("__score__")} DESC, m.${e.identifier("_creationTime")} DESC, m.${e.identifier("id")} ASC LIMIT ${e.raw(String(s))}`,U(a,await R(t,i,_))},ie=async(t,i,a,r,n,s)=>{const o=i.nativeTextSearch,$=x(n.query,I(n.definition.language));if(!o||$.length===0)return[];const f=y(r,n.indexName),c=[o.matches(f,$)];for(const m of n.filters)c.push(e`m.${h(m.field)} = ${M(m.value)}`);a.softDeleteMode&&c.push(e`m.${h(a.softDeleteMode.field)} IS NULL`);const l=e`SELECT m.* FROM ${e.identifier(f)} JOIN ${e.identifier(r)} m ON m.${e.identifier("id")} = ${e.identifier(f)}.${e.identifier(d)} WHERE ${e.join(c,e` AND `)} ORDER BY ${o.rank(f,$)} DESC, m.${e.identifier("_creationTime")} DESC, m.${e.identifier("id")} ASC LIMIT ${e.raw(String(s))}`;return U(a,await R(t,i,l))},te={ensureCompanion:async(t,i,a)=>{const{integer:r,key:n}=i.companionTypes;await u(t,i,e`CREATE TABLE IF NOT EXISTS ${e.identifier(a)} (${e.identifier(L)} ${e.raw(n)} NOT NULL, ${e.identifier(d)} ${e.raw(n)} NOT NULL, ${e.identifier(A)} ${e.raw(r)} NOT NULL)`),await b(t,i,{columns:e`${D(i,L)}, ${D(i,d)}`,name:`${a}__btree`,table:a,unique:!1}),await b(t,i,{columns:D(i,d),name:`${a}__by_id`,table:a,unique:!1})},indexDocument:async(t,i,a,r,n,s)=>{await g(t,i,a,r);const o=[...Y(C(n,s),I(s.language))],$=e.join([L,d,A].map(f=>e.identifier(f)),e`, `);for(let f=0;f<o.length;f+=B){const c=e.join(o.slice(f,f+B).map(([l,m])=>e`(${l}, ${r}, ${m})`),e`, `);await u(t,i,e`INSERT INTO ${e.identifier(a)} (${$}) VALUES ${c}`)}},name:"inverted",runSearch:Z},ae={ensureCompanion:async(t,i,a)=>{await u(t,i,e`CREATE VIRTUAL TABLE IF NOT EXISTS ${e.identifier(a)} USING fts5(${e.identifier(P)}, ${e.identifier(d)} UNINDEXED)`),await u(t,i,e`CREATE VIRTUAL TABLE IF NOT EXISTS ${e.identifier(`${a}__vocab`)} USING fts5vocab(${e.identifier(a)}, ${e.raw("instance")})`)},indexDocument:async(t,i,a,r,n,s)=>{await g(t,i,a,r),await u(t,i,e`INSERT INTO ${e.identifier(a)} (${e.identifier("__text__")}, ${e.identifier(d)}) VALUES (${C(n,s)}, ${r})`)},name:"fts5",runSearch:ee},ne={ensureCompanion:async(t,i,a)=>{const r=i.nativeTextSearch;if(r){await u(t,i,r.createCompanion(a,i.companionTypes.key));for(const n of r.createIndexes(a))await u(t,i,n)}},indexDocument:async(t,i,a,r,n,s)=>{const o=i.nativeTextSearch;o&&(await g(t,i,a,r),await u(t,i,o.indexDocument(a,r,C(n,s))))},name:"native",runSearch:ie},O=(t,i)=>t.strategy==="native"&&i.nativeTextSearch!==void 0?ne:i.supportsFts5?ae:te,H=(t,i)=>`${I(t.language).profile}/${O(t,i).name}`,v=function*(t){for(const[i,a]of Object.entries(t.tables)){const r=a.searchIndexes;if(!(a.shardMode!==void 0&&a.shardMode.kind!=="global"||!r))for(const n of r)yield[i,a,n]}},F=(t,i)=>y(t,i.name),$e=async(t,i,a,r,n,s)=>O(n.definition,i).runSearch(t,i,a,r,n,s),q=200,k=async(t,i,a,r,n)=>{const s=F(r,n),o=O(n,i),$=H(n,i),f=z(await j(t,i,s),$);if(f.finished)return!0;if(f.wipe&&(await u(t,i,e`DELETE FROM ${e.identifier(s)}`),await p(t,i,s,void 0,!1,$)),(await R(t,i,i.tableExists(r))).length===0)return await p(t,i,s,void 0,!0,$),!0;let c=0,l=f.cursor;await K(t,i,a,r,async N=>{c+=1;const T=N._id;typeof T=="string"&&(l=T,await o.indexDocument(t,i,s,T,N,n))},{after:f.cursor,limit:q});const m=c<q;return await p(t,i,s,l,m,$),m},W=async(t,i,a)=>{await J(t,a);for(const[r,,n]of v(i)){const s=F(r,n),o=H(n,a),$=await j(t,a,s);$.profile!==void 0&&$.profile!==o&&(await u(t,a,e`DROP TABLE IF EXISTS ${e.identifier(s)}`),await p(t,a,s,void 0,!1,o)),await O(n,a).ensureCompanion(t,a,s)}},ce=async(t,i,a)=>{await W(t,i,a);for(const[r,n,s]of v(i))s.staged||await k(t,a,n,r,s)},de=async(t,i,a)=>{await W(t,i,a);for(const[r,n,s]of v(i)){let o=!1;for(;!o;)o=await k(t,a,n,r,s)}},le=t=>{const{dialect:i,exec:a,schema:r}=t;return async(n,s,o,$)=>{const f=r.tables[n]?.searchIndexes;if(!(!f||f.length===0))for(const c of f){if(X($,o,c))continue;const l=F(n,c);if(o){await O(c,i).indexDocument(a,i,l,s,o,c);continue}await g(a,i,l,s)}}};export{de as backfillSqlSearchIndexes,le as createSearchSync,$e as runSqlSearch,ce as runSqlSearchMigrations};
@@ -1 +0,0 @@
1
- import{aggregateTableName as K,rankTableName as G,hasTrigger as wt,runRowValidators as Re,assertFlatPredicate as Ge,mergeWhere as M,sortColumnName as V,resolveRankPartition as Ye,encodePartitionKey as me,decodeCursor as Qe,RANK_TIEBREAK as le,CountRlsUnsupportedError as Xe,normalizeIdStructurally as ht,assertValidClientId as pt,aggregateSqlFunction as oe,softDeleteScope as se,compileWhereSql as ce,normalizeOrderKeys as Et,buildSeekWhere as mt,resolveRelationPredicates as Je,resolveWith as Ze,applySelect as et,encodeCursor as yt,NotFoundError as gt,applyOnDelete as bt,ConflictError as de,normalizeCountArgument as Nt,selectIndexForCount as Tt,encodeAggregateKey as U,selectIndexForAggregate as vt,readAggregateValue as Ae,runTriggers as St,matchesRankStaticWhere as tt,selectIndexForGroupBy as Rt,fanOutScalarCounts as At,matchesStaticWhere as Ie,foldAggregateTally as It,coerceAggregateNumber as Le,NotUniqueError as Lt,throwingScheduler as Ot}from"@lunora/do";import{LunoraError as N}from"@lunora/errors";import{createSearchBuilder as Ct,createSearchAnalyzer as kt,planSearchPage as xt,finishSearchPage as Mt,searchPageScan as Dt,resolveSearchScan as qt,assertSearchWithinCap as Wt}from"@lunora/search-core";import{sql as e}from"drizzle-orm";import{createSearchSync as Ft,runSqlSearchMigrations as Bt,runSqlSearch as jt}from"./backfillSqlSearchIndexes-DBD_C3SK.mjs";import{backfillSqlSearchIndexes as Ri}from"./backfillSqlSearchIndexes-DBD_C3SK.mjs";import{migrateSearchState as Ut}from"./SEARCH_STATE_TABLE-DWm7Rza8.mjs";import{queryAll as S,queryRun as A,createIndexIfNotExists as Ce,decodeRow as Y,serializeColumnValue as j,columnRefSql as k,decodeRows as Pt,forEachRowPaged as it}from"./decodeGlobalRow-k4q7Ma1g.mjs";import{decodeGlobalRow as Ii}from"./decodeGlobalRow-k4q7Ma1g.mjs";import{effectiveColumnKind as ye}from"./decodeBigint-DfiI8pkL.mjs";const Ht=(u,$)=>{if(u.size<$)return;const f=u.keys().next().value;f!==void 0&&u.delete(f)},Kt=new Set(["_id","id"]),ke=(u,$,f)=>u==="postgres"?e`${$} IS NOT DISTINCT FROM ${f}`:u==="mysql"?e`${$} <=> ${f}`:e`${$} IS ${f}`,Vt=u=>{const $=u.map(f=>e`${k(f.field)} ${e.raw(f.direction==="desc"?"DESC":"ASC")}`);return u.some(f=>Kt.has(f.field))||$.push(e`${k("id")} ASC`),e.join($,e`, `)},nt=50,xe=u=>{const $=[];for(const[f,r]of Object.entries(u.shape)){const m=r._meta?.column;m&&$.push([f,m])}return $},zt=(u,$,f)=>{const r={...$};for(const[m,l]of xe(u)){if(l.serverDefault){r[m]=l.serverDefault({auth:f});continue}r[m]===void 0&&(l.defaultFn?r[m]=l.defaultFn():"defaultValue"in l&&(r[m]=l.defaultValue))}return r},at=(u,$,f,r)=>{for(const[m,l]of xe(u)){if(l.serverDefault){m in $&&(f[m]=l.serverDefault({auth:r}));continue}l.onUpdateFn&&!(m in $)&&(f[m]=l.onUpdateFn())}},Gt=128,Yt=()=>{const u=new Map;return{delete:$=>{u.delete($)},get:$=>{const f=u.get($);if(f!==void 0)return u.delete($),u.set($,f),f},set:($,f)=>{u.has($)?u.delete($):Ht(u,Gt),u.set($,f)}}},Qt=async(u,$,f,r,m)=>{const l=m.get(r);if(l!==void 0)return l;const c=[];for(const[b,R]of Object.entries(f.tables))R.shardMode!==void 0&&R.shardMode.kind!=="global"||c.push(b);const T=await Promise.all(c.map(async b=>({found:(await S(u,$,e`SELECT 1 FROM ${e.identifier(b)} WHERE ${e.identifier("id")} = ${r} LIMIT 1`)).length>0,tableName:b})));for(const b of T)if(b.found)return m.set(r,b.tableName),b.tableName},Q=u=>u==null?null:Number(u),Xt=(u,$)=>$.map(f=>{const r={};for(const m of u)r[m]=f[m]??null;return{key:r,value:Q(f.value)}}),Jt=(u,$,f)=>[...u.partitionBy??[],...u.sortBy.map(r=>r.field),...u.where?Object.keys(u.where):[]].every(r=>$[r]===f[r]),rt=u=>u.length===1?u[0]:e`(${e.join(u,e` AND `)})`,Zt=(u,$,f,r,m)=>{const l=[];for(let c=0;c<f.length+1;c+=1){const T=f.slice(0,c).map(I=>ke(u,e`${e.identifier(I)}`,r[I])),b=f[c],R=$.sortBy[c];c<f.length&&b!==void 0&&R!==void 0?T.push(e`${e.identifier(b)} ${e.raw(R.direction==="desc"?">":"<")} ${r[b]}`):T.push(e`${e.identifier(le)} < ${m}`),l.push(rt(T))}return l.length>0?e.join(l,e` OR `):void 0},ei=(u,$,f)=>{if(f.length!==$.length)return;const r=[];for(const[m,l]of $.entries()){const c=[];for(let T=0;T<m;T+=1){const b=$[T];b!==void 0&&c.push(ke(u,e`${e.identifier(b.column)}`,f[T]))}c.push(e`${e.identifier(l.column)} ${e.raw(l.direction==="desc"?"<":">")} ${f[m]}`),r.push(rt(c))}return e`(${e.join(r,e` OR `)})`},ti=(u,$)=>{if(u.sortBy.length===0)throw new N("INTERNAL",`rankIndex "${u.name}" requires at least one "sortBy" column for stable pagination`);const f=[{column:"__partition__",direction:"asc"}];for(const[r,m]of u.sortBy.entries())f.push({column:$[r]??V(r),direction:m.direction});return f.push({column:le,direction:"asc"}),f},ii=async(u,$,f,r,m)=>{const l=[];for(let R=0;R<m.length;R+=50)l.push(m.slice(R,R+50));const c=await Promise.all(l.map(async R=>{const I=e.join(R.map(D=>e`${D}`),e`, `);return S(u,$,e`SELECT * FROM ${e.identifier(r)} WHERE ${e.identifier("id")} IN (${I})`)})),T=new Map;for(const R of c)for(const I of R)T.set(I.id,I);const b=[];for(const R of m){const I=Y(f,T.get(R));I&&b.push(I)}return b},ni=u=>{const $=JSON.stringify(u),f=new TextEncoder().encode($);let r="";for(const m of f)r+=String.fromCodePoint(m);return btoa(r)},ai=(u,$)=>$.columnType(ye(u)),ri=(u,$)=>{const f=[];for(const[m,l]of Object.entries(u.shape)){if(!l._meta?.column)continue;const c=l._meta.column.notNull&&l.kind!=="optional"?" NOT NULL":"";f.push(e`${e.identifier(m)} ${e.raw(`${ai(l,$)}${c}`)}`)}const r=$.frameworkColumns().map(m=>e`${e.identifier(m.name)} ${e.raw(m.type)}`);return e.join([...r,...f],e`, `)},oi=async(u,$,f,r)=>{const m=l=>{const c=k(l),T=f.shape[l],b=T&&r.indexKeyPrefix?r.indexKeyPrefix(ye(T)):void 0;return b===void 0?c:e`${c}(${e.raw(String(b))})`};for(const l of f.indexes){const c=e.join(l.fields.map(T=>m(T)),e`, `);await Ce(u,r,{columns:c,name:`${$}_${l.name}`,table:$,unique:l.unique??!1})}for(const[l,c]of xe(f))c.unique&&await Ce(u,r,{columns:m(l),name:`${$}_unique_${l}`,table:$,unique:!0})},si=async(u,$,f)=>{for(const[r,m]of Object.entries($.tables)){if(m.shardMode?.kind!=="global")continue;const l=ri(m,f);await A(u,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(r)} (${l})`),await oi(u,r,m,f)}},ci=async(u,$,f)=>{const{integer:r,key:m,real:l}=f.companionTypes;for(const[c,T]of Object.entries($.tables)){const b=T.aggregateIndexes;if(!(!b||b.length===0))for(const R of b){const I=K(c,R.name);await A(u,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(I)} (${e.identifier("__key__")} ${e.raw(m)} PRIMARY KEY, ${e.identifier("__value__")} ${e.raw(l)}, ${e.identifier("__count__")} ${e.raw(r)} NOT NULL DEFAULT 0)`),f.name==="sqlite"&&((await S(u,f,e`PRAGMA table_info(${e.identifier(I)})`)).some(D=>D.name==="__count__")||await A(u,f,e`ALTER TABLE ${e.identifier(I)} ADD COLUMN ${e.identifier("__count__")} ${e.raw(r)} NOT NULL DEFAULT 0`))}}},Oe=(u,$,f,r)=>{const m=u.name==="mysql"&&r?e`${e.identifier($)}(191)`:e`${e.identifier($)}`;return e`${m} ${e.raw(f)}`},di=(u,$,f)=>{const r=[Oe(u,"__partition__","ASC",!0)];for(const[m,l]of $.sortBy.entries()){const c=f.shape[l.field],T=c!==void 0&&u.indexKeyPrefix?.(ye(c))!==void 0;r.push(Oe(u,V(m),l.direction==="desc"?"DESC":"ASC",T))}return r.push(Oe(u,"__id__","ASC",!0)),r},li=(u,$,f)=>$.sortBy.map((r,m)=>{const l=f.shape[r.field],c=u.columnType(l?ye(l):void 0);return e`${e.identifier(V(m))} ${e.raw(c)}`}),ui=async(u,$,f)=>{const{key:r}=f.companionTypes;for(const[m,l]of Object.entries($.tables)){const c=l.rankIndexes;if(!(!c||c.length===0))for(const T of c){const b=G(m,T.name),R=li(f,T,l),I=R.length>0?e`, ${e.join(R,e`, `)}`:e``;await A(u,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(b)} (${e.identifier("__id__")} ${e.raw(r)} PRIMARY KEY, ${e.identifier("__partition__")} ${e.raw(r)} NOT NULL${I})`);const D=di(f,T,l),be=`${m}__rank_${T.name}__btree`;await Ce(u,f,{columns:e.join(D,e`, `),name:be,table:b,unique:!1})}}},ge="__cdc_log",fi=async(u,$)=>{const{autoincrementPrimaryKey:f,key:r,real:m,text:l}=$.companionTypes;await A(u,$,e`CREATE TABLE IF NOT EXISTS ${e.identifier(ge)} (${e.identifier("seq")} ${e.raw(f)}, ${e.identifier("ts")} ${e.raw(m)} 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(l)})`)},_i=async(u,$,f,r,m,l,c)=>{await A(u,c,e`INSERT INTO ${e.identifier(ge)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${$}, ${f}, ${r}, ${m}, ${l===void 0?null:JSON.stringify(l)})`)},bi=async(u,$,f)=>{const r=$.sinceSeq??0,m=Math.max(1,Math.min($.limit??1e3,1e4)),l=(await S(u,f,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(ge)} WHERE seq > ${r} ORDER BY seq ASC LIMIT ${e.raw(String(m))}`)).map(c=>{const{doc:T}=c,b={id:String(c.id),op:String(c.op),seq:Number(c.seq),table:String(c.table),ts:Number(c.ts)};return typeof T=="string"?{...b,doc:JSON.parse(T)}:b});return{changes:l,cursor:l.at(-1)?.seq??r}},Ni=async(u,$,f)=>{await A(u,f,e`DELETE FROM ${e.identifier(ge)} WHERE ${e.identifier("seq")} <= ${$}`)},Ti=u=>{const{crossShardCounter:$,crossShardReader:f,exec:r,maxRelationKeys:m,schema:l}=u,{dialect:c}=u,{isUniqueViolation:T}=c,b={fieldRef:k,serialize:j,...c.name==="mysql"?{likeContains:(t,i)=>e`${t} LIKE CONCAT('%', ${i}, '%') ESCAPE '\\\\'`}:{}},R=(t,i)=>ke(c.name,t,i),I=t=>{const i=e.join(t.columns.map(d=>e`${e.identifier(d)}`),e`, `),n=e.join(t.values.map(d=>e`${d}`),e`, `),a=d=>c.name==="mysql"?e`VALUES(${e.identifier(d)})`:e`excluded.${e.identifier(d)}`,o=d=>c.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(d)}`:e`${e.identifier(d)}`,_=e.join(Object.entries(t.set(a,o)).map(([d,h])=>e`${e.identifier(d)} = ${h}`),e`, `),w=c.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${_}`:e`ON CONFLICT(${e.identifier(t.conflictKey)}) DO UPDATE SET ${_}`;return e`INSERT INTO ${e.identifier(t.table)} (${i}) VALUES (${n}) ${w}`},D=u.clock??(()=>Date.now()),be=u.idGenerator??(()=>crypto.randomUUID()),Me=u.cdc??!1,Ne=u.auth??{identity:null,userId:null},X=async(t,i,n,a)=>{Me&&await _i(r,D(),t,i,n,a,c)},ot=u.scheduler??Ot,Te=Yt();let ue=0,ve;const W=async()=>(ve??=(async()=>{await si(r,l,c),await ci(r,l,c),await ui(r,l,c),await Ut(r,c),await Bt(r,l,c),Me&&await fi(r,c)})().catch(t=>{throw ve=void 0,t}),ve),J=async(t,i)=>{await W();const n=await Qt(r,c,l,t,Te);if(!(i!==void 0&&n!==i))return n},Z=new Map,De=async(t,i)=>{const n=K(t,i);return(await S(r,c,c.tableExists(n))).length>0},fe=async(t,i)=>{const n=`${t}::${i.name}`,a=Z.get(n);if(a!==void 0)return a;if(!await De(t,i.name))return Z.set(n,!1),!1;const o=l.tables[t];if(!o)return Z.set(n,!1),!1;const _=i.by??[],w=new Map;await it(r,c,o,t,h=>{if(i.where&&!Ie(h,i.where))return;const s=U(_,h);It(w,s,i,h)});const d=K(t,i.name);await A(r,c,e`DELETE FROM ${e.identifier(d)}`);for(const[h,s]of w)await A(r,c,e`INSERT INTO ${e.identifier(d)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${h}, ${s.value}, ${s.count})`);return Z.set(n,!0),!0},st=async(t,i,n)=>{const a=oe(i.op),o=i.field??"",_=[];for(const h of i.by??[]){const s=j(n[h]??null);_.push(s===null?e`${k(h)} IS NULL`:e`${k(h)} = ${s}`)}for(const[h,s]of Object.entries(i.where??{})){const p=s!==null&&typeof s=="object"&&!Array.isArray(s)?s.eq:s,E=j(p);_.push(E===null?e`${k(h)} IS NULL`:e`${k(h)} = ${E}`)}const w=e`SELECT ${e.raw(a)}(${k(o)}) AS value FROM ${e.identifier(t)}`,d=await S(r,c,_.length>0?e`${w} WHERE ${e.join(_,e` AND `)}`:w);return Q(d[0]?.value)},qe=async(t,i)=>{await A(r,c,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${i} AND ${e.identifier("__count__")} <= 0`)},ct=async(t,i,n,a)=>{const o=K(t,i.name),{op:_}=i,w=i.field??"",d=n&&(!i.where||Ie(n,i.where))?n:void 0,h=a&&(!i.where||Ie(a,i.where))?a:void 0;if(!(!d&&!h)){if(_==="count"){const s=new Set;for(const[p,E]of[[d,-1],[h,1]]){if(!p)continue;const y=U(i.by??[],p);s.add(y),await A(r,c,I({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(g,v)=>({__count__:e`${v("__count__")} + ${g("__count__")}`,__value__:e`${v("__value__")} + ${g("__value__")}`}),table:o,values:[y,E,E]}))}for(const p of s)await qe(o,p);return}if(_==="sum"||_==="avg"){const s=new Set;for(const[p,E]of[[d,-1],[h,1]]){if(!p)continue;const y=Le(p[w]);if(y===void 0)continue;const g=U(i.by??[],p);s.add(g),await A(r,c,I({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(v,C)=>({__count__:e`${C("__count__")} + ${v("__count__")}`,__value__:e`COALESCE(${C("__value__")}, 0) + ${v("__value__")}`}),table:o,values:[g,E*y,E]}))}for(const p of s)await qe(o,p);return}if(d){const s=U(i.by??[],d),p=Le(d[w]),E=(await S(r,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(o)} WHERE ${e.identifier("__key__")} = ${s}`))[0],y=Q(E?.value),g=(E?.count??0)-1;if(g<=0)await A(r,c,e`DELETE FROM ${e.identifier(o)} WHERE ${e.identifier("__key__")} = ${s}`);else if(E&&p!==void 0&&y!==null&&p===y){const v=await st(t,i,d);await A(r,c,e`UPDATE ${e.identifier(o)} SET ${e.identifier("__value__")} = ${v}, ${e.identifier("__count__")} = ${g} WHERE ${e.identifier("__key__")} = ${s}`)}else await A(r,c,e`UPDATE ${e.identifier(o)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${s}`)}if(h){const s=U(i.by??[],h),p=Le(h[w]);if(p===void 0)await A(r,c,I({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(E,y)=>({__count__:e`${y("__count__")} + 1`}),table:o,values:[s,null,1]}));else{const E=_==="min"?"MIN":"MAX";await A(r,c,I({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(y,g)=>({__count__:e`${g("__count__")} + 1`,__value__:e`${e.raw(E)}(COALESCE(${g("__value__")}, ${y("__value__")}), ${y("__value__")})`}),table:o,values:[s,p,1]}))}}}},_e=async t=>{const i=l.tables[t]?.aggregateIndexes;if(!(!i||i.length===0))for(const n of i)await fe(t,n)},ee=async(t,i,n)=>{const a=l.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const o of a){const _=`${t}::${o.name}`;(Z.get(_)??await De(t,o.name))&&await ct(t,o,i,n)}},te=new Map,We=async(t,i)=>{const n=G(t,i);return(await S(r,c,c.tableExists(n))).length>0},Se=async(t,i)=>{const n=`${t}::rank::${i.name}`,a=te.get(n);if(a!==void 0)return a;if(!await We(t,i.name))return te.set(n,!1),!1;const o=l.tables[t];if(!o)return te.set(n,!1),!1;const _=G(t,i.name);await A(r,c,e`DELETE FROM ${e.identifier(_)}`);const w=i.sortBy.map((s,p)=>V(p)),d=e.join(["__id__","__partition__",...w].map(s=>e`${e.identifier(s)}`),e`, `),h=[];await it(r,c,o,t,s=>{if(i.where&&!tt(s,i.where))return;const p=me(i.partitionBy??[],s),E=i.sortBy.map(y=>j(s[y.field]??null));h.push([s._id,p,...E])});for(const s of h){const p=e.join(s.map(E=>e`${E}`),e`, `);await A(r,c,e`INSERT INTO ${e.identifier(_)} (${d}) VALUES (${p})`)}return te.set(n,!0),!0},$e=async t=>{const i=l.tables[t]?.rankIndexes;if(!(!i||i.length===0))for(const n of i)await Se(t,n)},z=async(t,i,n,a)=>{const o=l.tables[t],_=o?.rankIndexes;if(!_||_.length===0)return;const w=o?.softDeleteMode?.field,d=w===void 0||a===void 0?void 0:a[w],h=d!=null;for(const s of _){if(n!==void 0&&a!==void 0&&Jt(s,n,a))continue;const p=`${t}::rank::${s.name}`;if(!(te.get(p)??await We(t,s.name)))continue;const E=G(t,s.name);if(n&&await A(r,c,e`DELETE FROM ${e.identifier(E)} WHERE ${e.identifier("__id__")} = ${i}`),a&&!h){if(s.where&&!tt(a,s.where))continue;const y=s.sortBy.map((L,P)=>V(P)),g=e.join(["__id__","__partition__",...y].map(L=>e`${e.identifier(L)}`),e`, `),v=me(s.partitionBy??[],a),C=s.sortBy.map(L=>j(a[L.field]??null)),x=e.join([i,v,...C].map(L=>e`${L}`),e`, `);await A(r,c,e`INSERT INTO ${e.identifier(E)} (${g}) VALUES (${x})`)}}},ie=Ft({dialect:c,exec:r,schema:l}),Fe=new Set;for(const[t,i]of Object.entries(l.tables))for(const n of Object.values(i.triggerMap??{}))Fe.add(`${t} ${n.timing} ${n.op}`);const F=(t,i,n)=>Fe.has(`${t} ${i} ${n}`);let Be;const B=async(t,i,n)=>{if(ue+=1,ue>nt)throw ue-=1,new de(`trigger recursion exceeded ${String(nt)} levels on "${n.table}" — check for a self-triggering write`,"trigger");try{await St({ctx:Be,event:n,op:i,schema:l,tableName:n.table,timing:t})}finally{ue-=1}},dt=async(t,i)=>{try{await A(r,c,i)}catch(n){throw T(n)?new de(`unique constraint violation on "${t}"`,"unique"):n}},we=async(t,i)=>(await S(r,c,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${i}`))[0],he=async(t,i,n,a)=>{if(a===void 0)return;const o=e.join(Object.keys(a).map(d=>R(e`${e.identifier(d)}`,a[d])),e` AND `),_=i==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${n} WHERE ${o}`:e`DELETE FROM ${e.identifier(t)} WHERE ${o}`,w=()=>{throw new de(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")};try{if(c.supportsReturning)(await S(r,c,e`${_} RETURNING ${e.identifier("id")}`)).length===0&&w();else{const d=await A(r,c,_);(c.affectedRows?c.affectedRows(d??{rowsAffected:0}):0)===0&&w()}}catch(d){throw T(d)?new de(`unique constraint violation on "${t}"`,"unique"):d}},lt=(t,i,n,a)=>{const o=Object.keys(t.shape);return{columns:["id","_creationTime",...o],values:[i,n,...o.map(_=>j(a[_]??null))]}},ut=async(t,i,n,a)=>{const o=Rt(i,n.op,n.field,a.by,a.where);if(!o||!await fe(t,o.index))return;const _=K(t,o.index.name),w=Object.keys(o.partial);if(w.length===(o.index.by??[]).length&&w.length>0){const d=U(o.index.by??[],o.partial),h=await S(r,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(_)} WHERE ${e.identifier("__key__")} = ${d}`);if(h.length===0)return[];const s=h[0];return[{key:{...o.partial},value:Ae(n.op,{count:s.count,value:Q(s.value)})}]}return w.length>0?void 0:(await S(r,c,e`SELECT ${e.identifier("__key__")} AS key, ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(_)}`)).map(d=>{const h=d;return{key:JSON.parse(h.key),value:Ae(n.op,{count:h.count,value:Q(h.value)})}})},je=t=>{const i=l.tables[t]?.shardMode?.kind;return i==="shardBy"||i==="root"},Ue=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`)},Pe=(t,i)=>je(t)?f?f(t,i):Ue(t):q.findMany(t,i),pe=(t,i,n)=>Je(t,{fetcher:Pe,maxRelationKeys:m,relationBaseWhere:n,schema:l,tableName:i}),q={async aggregate(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);if(await W(),oe(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=se(n.softDeleteMode,void 0),o=M(M(i.baseWhere,i.where),a),_=await pe(o,t,i.relationBaseWhere),w=_!==o;if(n.aggregateIndexes&&!i.baseWhere&&!w&&!a){const E=vt(n.aggregateIndexes,i.op,i.field,i.where);if(E&&await fe(t,E.index)){const y=U(E.index.by??[],E.key),g=K(t,E.index.name),v=(await S(r,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(g)} WHERE ${e.identifier("__key__")} = ${y}`))[0];return Ae(i.op,v===void 0?void 0:{count:v.count,value:Q(v.value)})}}const d=ce(_,b),h=e.raw(oe(i.op)),s=e`SELECT ${h}(${k(i.field)}) AS value FROM ${e.identifier(t)}`,p=(await S(r,c,d?e`${s} WHERE ${d}`:s))[0]?.value;return p==null?null:Number(p)},async count(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await W();const a=Nt(i);if(a.restrictsCounts)throw new Xe(t);const o=se(n.softDeleteMode,void 0),_=M(M(a.baseWhere,a.where),o),w=await pe(_,t,a.relationBaseWhere),d=w!==_;if(n.aggregateIndexes&&!a.baseWhere&&!d&&!o){const E=Tt(n.aggregateIndexes,a.where);if(E&&await fe(t,E.index)){const y=U(E.index.by??[],E.key),g=K(t,E.index.name),v=await S(r,c,e`SELECT ${e.identifier("__value__")} AS value FROM ${e.identifier(g)} WHERE ${e.identifier("__key__")} = ${y}`);return Number(v[0]?.value??0)}}const h=ce(w,b),s=e`SELECT COUNT(*) AS count FROM ${e.identifier(t)}`,p=await S(r,c,h?e`${s} WHERE ${h}`:s);return Number(p[0]?.count??0)},async delete(t,i,n){const a=await J(t,i);if(!a)return;const o=l.tables[a];if(!o)return;const _=await we(a,t),w=Y(o,_),d=n?.hard===!0,h=!d&&o.softDeleteMode?o.softDeleteMode.field:void 0;if(!(h&&(!w||w[h]!==null&&w[h]!==void 0))){if(F(a,"before","delete")&&await B("before","delete",{id:t,op:"delete",previous:w??void 0,table:a}),await bt({deletedId:t,deletedReference:s=>w?.[s],findHolders:async(s,p,E)=>{if(l.tables[s]?.shardMode?.kind==="shardBy")throw new N("INTERNAL",`cross-backend cascade from global '${a}' into shardBy '${s}' is not supported — would require Query Coordinator fan-out across shards`);return(await q.findMany(s,{includeDeleted:d,where:{[p]:E}})).page},onCascade:(s,p)=>q.delete(p,void 0,n),onRestrict:s=>{throw new de(s,"restrict")},onSetNull:(s,p,E)=>q.patch(p,{[E]:null}),schema:l,tableName:a}),await _e(a),await $e(a),h&&w){const s={...w,[h]:D()},p=e.join(Object.keys(o.shape).map(E=>e`${e.identifier(E)} = ${j(s[E]??null)}`),e`, `);await he(a,"UPDATE",p,_),await ee(a,w,s),await z(a,t,w,void 0),await ie(a,t,s,w),await X(a,t,"update",s),F(a,"after","delete")&&await B("after","delete",{id:t,op:"delete",previous:w,table:a});return}await he(a,"DELETE",void 0,_),Te.delete(t),await ee(a,w??void 0,void 0),await z(a,t,w??void 0,void 0),await ie(a,t,void 0),await X(a,t,"delete"),F(a,"after","delete")&&await B("after","delete",{id:t,op:"delete",previous:w??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 gt(`findFirstOrThrow: no "${t}" document matched`);return n},async findMany(t,i={}){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await W();const a=Et(i.orderBy),o=i.cursor?mt(a,Qe(i.cursor)):void 0,_=Pe,w=async(L,P,Ee,ne)=>{if(je(L))return $?At($,L,P,Ee,ne):Ue(L);const H=l.tables[L];if(!H)throw new N("INTERNAL",`unknown table: ${L}`);const O=se(H.softDeleteMode,void 0),ae={[P]:{in:Ee}},ft=M(M(ae,ne),O),_t=await pe(ft,L,void 0),He=ce(_t,b),Ke=k(P);let re=e`SELECT ${Ke} AS __fk__, COUNT(*) AS count FROM ${e.identifier(L)}`;He&&(re=e`${re} WHERE ${He}`),re=e`${re} GROUP BY ${Ke}`;const $t=await S(r,c,re),Ve=new Map;for(const ze of $t)Ve.set(ze.__fk__,Number(ze.count??0));return Ve};let d=M(i.baseWhere,i.where);d=M(d,se(n.softDeleteMode,i.includeDeleted)),d=await Je(d,{fetcher:_,maxRelationKeys:m,relationBaseWhere:i.relationBaseWhere,schema:l,tableName:t}),o&&(d=d?{AND:[d,o]}:o);const h=ce(d,b),s=Vt(a);let p=e`SELECT * FROM ${e.identifier(t)}`;h&&(p=e`${p} WHERE ${h}`),p=e`${p} ORDER BY ${s}`;const E=typeof i.limit=="number"?Math.max(0,Math.floor(i.limit)):void 0;E!==void 0&&(p=e`${p} LIMIT ${e.raw(String(E+1))}`);const y=await S(r,c,p),g=Pt(n,y);if(E===void 0)return i.with&&await Ze({fetcher:_,groupedCounter:w,parents:g,schema:l,tableName:t,with:i.with}),{continueCursor:null,isDone:!0,page:et(g,i.select,i.with)};const v=g.length>E,C=v?g.slice(0,E):g,x=C.at(-1);return i.with&&await Ze({fetcher:_,groupedCounter:w,parents:C,schema:l,tableName:t,with:i.with}),{continueCursor:v&&x?yt(x,a):null,isDone:!v,page:et(C,i.select,i.with)}},async get(t,i){const n=await J(t,i);if(!n)return null;const a=l.tables[n];if(!a)return null;const o=await S(r,c,e`SELECT * FROM ${e.identifier(n)} WHERE ${e.identifier("id")} = ${t}`);return Y(a,o[0])},async groupBy(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await W();const a=i.agg??{op:"count"};if(oe(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=se(n.softDeleteMode,void 0),_=M(M(i.baseWhere,i.where),o),w=await pe(_,t,i.relationBaseWhere),d=w!==_;if(n.aggregateIndexes&&!i.baseWhere&&!d&&!o){const g=await ut(t,n.aggregateIndexes,a,i);if(g!==void 0)return g}const h=ce(w,b),s=i.by.map(g=>e`${k(g)} AS ${e.identifier(g)}`);if(a.op==="count")s.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`);s.push(e`${e.raw(oe(a.op))}(${k(a.field)}) AS value`)}const p=e.join(i.by.map(g=>k(g)),e`, `);let E=e`SELECT ${e.join(s,e`, `)} FROM ${e.identifier(t)}`;h&&(E=e`${E} WHERE ${h}`),E=e`${E} GROUP BY ${p}`;const y=await S(r,c,E);return Xt(i.by,y)},async insert(t,i,n){const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);await W();const o=zt(a,i,Ne);Re(a,o);let _,w=!0;n?.clientId!==void 0?(pt(n.clientId),_=n.clientId):n?.allowExplicitId&&typeof o._id=="string"?_=o._id:(_=be(),w=!1);const d=n?.allowExplicitId&&typeof o._creationTime=="number"?o._creationTime:D(),h={...o,_creationTime:d,_id:_};F(t,"before","insert")&&await B("before","insert",{doc:{...h},id:_,op:"insert",table:t}),await _e(t),await $e(t);const{columns:s,values:p}=lt(a,_,d,o),E=e.join(s.map(g=>e`${e.identifier(g)}`),e`, `),y=e.join(p.map(g=>e`${g}`),e`, `);return await dt(t,e`INSERT INTO ${e.identifier(t)} (${E}) VALUES (${y})`),w&&Te.set(_,t),await ee(t,void 0,h),await z(t,_,void 0,h),await ie(t,_,h),await X(t,_,"insert",h),F(t,"after","insert")&&await B("after","insert",{doc:h,id:_,op:"insert",table:t}),_},normalizeId(t,i){return ht(l,t,i)},async patch(t,i,n){const a=await J(t,n);if(!a)throw new N("INTERNAL",`document not found: ${t}`);const o=l.tables[a];if(!o)throw new N("INTERNAL",`document not found: ${t}`);const _=await we(a,t),w=Y(o,_);if(!w)throw new N("INTERNAL",`document not found: ${t}`);const d={...w,...i,_id:t};at(o,i,d,Ne),Re(o,d,!0),F(a,"before","update")&&await B("before","update",{doc:{...d},id:t,op:"update",previous:w,table:a}),await _e(a),await $e(a);const h=Object.keys(o.shape),s=e.join(h.map(p=>e`${e.identifier(p)} = ${j(d[p]??null)}`),e`, `);await he(a,"UPDATE",s,_),await ee(a,w,d),await z(a,t,w,d),await ie(a,t,d,w),await X(a,t,"update",d),F(a,"after","update")&&await B("after","update",{doc:d,id:t,op:"update",previous:w,table:a})},async restore(t,i){const n=await J(t,i);if(!n)throw new N("INTERNAL",`document not found: ${t}`);const a=l.tables[n],o=a?.softDeleteMode?.field;if(!a||!o)throw new N("INTERNAL",`ctx.db.restore: table "${n}" is not a .softDelete() table`);const _=await we(n,t),w=_?.[o]!==null&&_?.[o]!==void 0;if(await q.patch(t,{[o]:null},i),w){const d=Y(a,_);d!==null&&await z(n,t,void 0,{...d,[o]:null})}},query(t){const i=l.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=d=>a.every(h=>h(d)),_=async(d,h)=>{await W();const s=a.length>0,p=await jt(r,c,i,t,d,qt(s?void 0:h));if(!s)return h===void 0&&Wt(p),p;const E=p.filter(y=>o(y));return h===void 0?E:E.slice(0,h)},w=d=>{const h={async collect(){if(!d)throw new N("INTERNAL",n);return _(d,void 0)},filter(s){if(!d)throw new N("INTERNAL",n);return a.push(s),h},async first(){if(!d)throw new N("INTERNAL",n);return(await _(d,1))[0]??null},order(){return h},async paginate(s){if(!d)throw new N("INTERNAL",n);const p=xt(s);return Mt(await _(d,Dt(p)),p)},async take(s){if(!d)throw new N("INTERNAL",n);return _(d,s)},async unique(){if(!d)throw new N("INTERNAL",n);const s=await _(d,2);if(s.length>1)throw new Lt(`unique() on table "${t}" matched ${String(s.length)} documents; expected at most one`);return s[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(s,p){const E=(i.searchIndexes??[]).find(g=>g.name===s);if(!E)throw new N("INTERNAL",`unknown search index "${s}" on table "${t}"`);const y={definition:E,field:E.field,filters:[],hasQuery:!1,indexName:s,query:""};if(p(Ct(y,t,kt(E.language))),!y.hasQuery)throw new N("INTERNAL",`search index "${s}" on table "${t}" requires a .search(field, query) call`);return w(y)}};return h};return w(void 0)},async rank(t,i,n){const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const o=a.rankIndexes?.find(x=>x.name===i);if(!o)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(n.restrictsCounts)throw new Xe(t);if(await W(),!await Se(t,o))return null;const _=typeof n.row=="string"?n.row:n.row._id;if(!_)return null;const w=G(t,o.name),d=o.sortBy.map((x,L)=>V(L)),h=e.join([e`${e.identifier("__partition__")}`,...d.map(x=>e`${e.identifier(x)}`)],e`, `),s=(await S(r,c,e`SELECT ${h} FROM ${e.identifier(w)} WHERE ${e.identifier("__id__")} = ${_}`))[0];if(!s)return null;const p=s.__partition__,E=M(n.baseWhere,n.where);Ge(E,l,t,"rank");const y=Ye(o,E);if(y&&me(o.partitionBy??[],y)!==p)return null;const g=Zt(c.name,o,d,s,_),v=await S(r,c,e`SELECT COUNT(*) AS c FROM ${e.identifier(w)} WHERE ${e.identifier("__partition__")} = ${p}${g?e` AND (${g})`:e``}`),C=await S(r,c,e`SELECT COUNT(*) AS c FROM ${e.identifier(w)} WHERE ${e.identifier("__partition__")} = ${p}`);return{position:Number(v[0]?.c??0)+1,total:Number(C[0]?.c??0)}},async rankPage(t,i,n={}){Ge(M(n.baseWhere,n.where),l,t,"rankPage");const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const o=a.rankIndexes?.find(O=>O.name===i);if(!o)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(await W(),!await Se(t,o))return{continueCursor:null,isDone:!0,page:[]};const _=G(t,o.name),w=o.sortBy.map((O,ae)=>V(ae)),d=Math.max(1,Math.min(1e3,Math.floor(n.take??100))),h=M(n.baseWhere,n.where),s=Ye(o,h),p=ti(o,w),E=e.join(p.map(O=>e`${e.identifier(O.column)} ${e.raw(O.direction==="desc"?"DESC":"ASC")}`),e`, `),y=[];if(s&&y.push(e`${e.identifier("__partition__")} = ${me(o.partitionBy??[],s)}`),n.cursor){const O=ei(c.name,p,Qe(n.cursor));O!==void 0&&y.push(O)}const g=e.join([e`${e.identifier(le)}`,e`${e.identifier("__partition__")}`,...w.map(O=>e`${e.identifier(O)}`)],e`, `);let v=e`SELECT ${g} FROM ${e.identifier(_)}`;y.length>0&&(v=e`${v} WHERE ${e.join(y,e` AND `)}`),v=e`${v} ORDER BY ${E} LIMIT ${e.raw(String(d+1))}`;const C=await S(r,c,v),x=C.length>d,L=x?C.slice(0,d):C,P=L.map(O=>O[le]),Ee=await ii(r,c,a,t,P);let ne=null;const H=L.at(-1);if(x&&H!==void 0){const O=[H.__partition__,...w.map(ae=>H[ae]),H[le]];ne=ni(O)}return{continueCursor:ne,isDone:!x,page:Ee}},async replace(t,i,n,a){const o=await J(t,n);if(!o)throw new N("INTERNAL",`document not found: ${t}`);const _=l.tables[o];if(!_)throw new N("INTERNAL",`document not found: ${t}`);const w=await we(o,t);if(w===void 0)throw new N("INTERNAL",`document not found: ${t}`);const d=wt(l,o,"update")||(_.aggregateIndexes??[]).length>0||(_.rankIndexes??[]).length>0?Y(_,w)??void 0:void 0,h=a?.allowExplicitId&&typeof i._creationTime=="number"?i._creationTime:D(),s={...i,_creationTime:h,_id:t};at(_,i,s,Ne),Re(_,s),F(o,"before","update")&&await B("before","update",{doc:{...s},id:t,op:"update",previous:d,table:o}),await _e(o),await $e(o);const p=Object.keys(_.shape),E=e.join([e`${e.identifier("_creationTime")} = ${h}`,...p.map(y=>e`${e.identifier(y)} = ${j(s[y]??null)}`)],e`, `);await he(o,"UPDATE",E,w),await ee(o,d,s),await z(o,t,d,s),await ie(o,t,s,d),await X(o,t,"update",s),F(o,"after","update")&&await B("after","update",{doc:s,id:t,op:"update",previous:d,table:o})}};return Be={db:q,scheduler:ot},q};export{Ri as backfillSqlSearchIndexes,Ti as createSqlCtxDb,Ii as decodeGlobalRow,bi as readSqlCdcChanges,ci as runSqlAggregateMigrations,fi as runSqlCdcMigration,si as runSqlGlobalTableMigrations,ui as runSqlRankMigrations,Bt as runSqlSearchMigrations,Ni as trimSqlCdcChanges};