@lunora/sql-store 1.0.0-alpha.58 → 1.0.0-alpha.59
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/dialect.d.mts +25 -0
- package/dist/dialect.d.ts +25 -0
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{SEARCH_STATE_TABLE-CtJTyVzp.mjs → SEARCH_STATE_TABLE-Bo7-Ng-F.mjs} +1 -1
- package/dist/packem_shared/{backfillSqlSearchIndexes-Dd3SzEYh.mjs → backfillSqlSearchIndexes-D3PpMetT.mjs} +1 -1
- package/dist/packem_shared/createSqlCtxDb-BsUNKVXY.mjs +1 -0
- package/dist/packem_shared/ctx-db-search-DPAoW2oD.mjs +1 -0
- package/dist/packem_shared/decodeGlobalRow-CyB_gkZ1.mjs +1 -0
- package/package.json +3 -3
- package/dist/packem_shared/createSqlCtxDb-DQTpO_JA.mjs +0 -1
- package/dist/packem_shared/ctx-db-search-CSETWaAQ.mjs +0 -1
- package/dist/packem_shared/decodeGlobalRow-DhFrSrmu.mjs +0 -1
package/dist/dialect.d.mts
CHANGED
|
@@ -19,6 +19,31 @@ interface SqlRunResult {
|
|
|
19
19
|
*/
|
|
20
20
|
interface SqlExec {
|
|
21
21
|
all: (sql: string, params: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Optional: run several write statements as one round trip instead of
|
|
24
|
+
* `run()` called once per statement in sequence. Statements MUST be
|
|
25
|
+
* mutually independent — an implementation MAY reorder or parallelize
|
|
26
|
+
* across elements, so callers must never rely on array order between
|
|
27
|
+
* elements (e.g. a purge-then-insert pair belongs in separate sequential
|
|
28
|
+
* `queryRun`/`run` calls, not one `batch`).
|
|
29
|
+
*
|
|
30
|
+
* Absent, the store core falls back to its historical sequential `run()`
|
|
31
|
+
* loop, so an exec that doesn't implement this keeps working unchanged.
|
|
32
|
+
*
|
|
33
|
+
* D1's `client.batch` executes the whole array atomically (all-or-nothing)
|
|
34
|
+
* in one request, preserving array order — an actual atomicity improvement
|
|
35
|
+
* over the sequential fallback, not just a round-trip one. The Hyperdrive
|
|
36
|
+
* `postgres`/`pg` adapters instead dispatch every statement concurrently
|
|
37
|
+
* (`Promise.all`) over the same connection/pool rather than awaiting each
|
|
38
|
+
* in turn — still "at-least-once, non-atomic" like the fallback, but no
|
|
39
|
+
* longer serialized one full RTT at a time, and with no ordering between
|
|
40
|
+
* elements. Safe only for statements whose effects don't depend on each
|
|
41
|
+
* other (distinct-keyed rows), which is what every current caller batches.
|
|
42
|
+
*/
|
|
43
|
+
batch?: (statements: ReadonlyArray<{
|
|
44
|
+
params: ReadonlyArray<unknown>;
|
|
45
|
+
sql: string;
|
|
46
|
+
}>) => Promise<void>;
|
|
22
47
|
run: (sql: string, params: ReadonlyArray<unknown>) => Promise<SqlRunResult>;
|
|
23
48
|
}
|
|
24
49
|
/** Everything engine-specific the store core needs. One value per engine; `sqliteDialect` (in `@lunora/d1`) is the reference, Postgres/MySQL live in `@lunora/hyperdrive/global`. */
|
package/dist/dialect.d.ts
CHANGED
|
@@ -19,6 +19,31 @@ interface SqlRunResult {
|
|
|
19
19
|
*/
|
|
20
20
|
interface SqlExec {
|
|
21
21
|
all: (sql: string, params: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Optional: run several write statements as one round trip instead of
|
|
24
|
+
* `run()` called once per statement in sequence. Statements MUST be
|
|
25
|
+
* mutually independent — an implementation MAY reorder or parallelize
|
|
26
|
+
* across elements, so callers must never rely on array order between
|
|
27
|
+
* elements (e.g. a purge-then-insert pair belongs in separate sequential
|
|
28
|
+
* `queryRun`/`run` calls, not one `batch`).
|
|
29
|
+
*
|
|
30
|
+
* Absent, the store core falls back to its historical sequential `run()`
|
|
31
|
+
* loop, so an exec that doesn't implement this keeps working unchanged.
|
|
32
|
+
*
|
|
33
|
+
* D1's `client.batch` executes the whole array atomically (all-or-nothing)
|
|
34
|
+
* in one request, preserving array order — an actual atomicity improvement
|
|
35
|
+
* over the sequential fallback, not just a round-trip one. The Hyperdrive
|
|
36
|
+
* `postgres`/`pg` adapters instead dispatch every statement concurrently
|
|
37
|
+
* (`Promise.all`) over the same connection/pool rather than awaiting each
|
|
38
|
+
* in turn — still "at-least-once, non-atomic" like the fallback, but no
|
|
39
|
+
* longer serialized one full RTT at a time, and with no ordering between
|
|
40
|
+
* elements. Safe only for statements whose effects don't depend on each
|
|
41
|
+
* other (distinct-keyed rows), which is what every current caller batches.
|
|
42
|
+
*/
|
|
43
|
+
batch?: (statements: ReadonlyArray<{
|
|
44
|
+
params: ReadonlyArray<unknown>;
|
|
45
|
+
sql: string;
|
|
46
|
+
}>) => Promise<void>;
|
|
22
47
|
run: (sql: string, params: ReadonlyArray<unknown>) => Promise<SqlRunResult>;
|
|
23
48
|
}
|
|
24
49
|
/** Everything engine-specific the store core needs. One value per engine; `sqliteDialect` (in `@lunora/d1`) is the reference, Postgres/MySQL live in `@lunora/hyperdrive/global`. */
|
package/dist/index.d.mts
CHANGED
|
@@ -9,6 +9,10 @@ import 'drizzle-orm';
|
|
|
9
9
|
*/
|
|
10
10
|
interface SqlCtxExec {
|
|
11
11
|
all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
12
|
+
batch?: (statements: ReadonlyArray<{
|
|
13
|
+
params: ReadonlyArray<unknown>;
|
|
14
|
+
sql: string;
|
|
15
|
+
}>) => Promise<void>;
|
|
12
16
|
run: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<SqlRunResult | void>;
|
|
13
17
|
}
|
|
14
18
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ import 'drizzle-orm';
|
|
|
9
9
|
*/
|
|
10
10
|
interface SqlCtxExec {
|
|
11
11
|
all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
12
|
+
batch?: (statements: ReadonlyArray<{
|
|
13
|
+
params: ReadonlyArray<unknown>;
|
|
14
|
+
sql: string;
|
|
15
|
+
}>) => Promise<void>;
|
|
12
16
|
run: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<SqlRunResult | void>;
|
|
13
17
|
}
|
|
14
18
|
/**
|
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-BsUNKVXY.mjs";import{A as s,B as d}from"./packem_shared/ctx-db-search-DPAoW2oD.mjs";import{SEARCH_STATE_TABLE as q,migrateSearchState as f}from"./packem_shared/SEARCH_STATE_TABLE-Bo7-Ng-F.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-CyB_gkZ1.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};
|
package/dist/packem_shared/{SEARCH_STATE_TABLE-CtJTyVzp.mjs → SEARCH_STATE_TABLE-Bo7-Ng-F.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sql as i}from"drizzle-orm";import{queryRun as $,queryAll as E}from"./decodeGlobalRow-
|
|
1
|
+
import{sql as i}from"drizzle-orm";import{queryRun as $,queryAll as E}from"./decodeGlobalRow-CyB_gkZ1.mjs";const a="__lunora_search_state",T=async(e,r)=>{const{integer:n,key:t}=r.companionTypes,o=async()=>{try{await $(e,r,i`ALTER TABLE ${i.identifier(a)} ADD COLUMN ${i.identifier("profile")} ${i.raw(t)}`)}catch{}};await $(e,r,i`CREATE TABLE IF NOT EXISTS ${i.identifier(a)} (${i.identifier("companion")} ${i.raw(t)} PRIMARY KEY, ${i.identifier("cursor")} ${i.raw(t)}, ${i.identifier("done")} ${i.raw(n)} NOT NULL DEFAULT 0, ${i.identifier("profile")} ${i.raw(t)})`),await o()},l=e=>e===1||e===!0||e==="1",S=async(e,r,n)=>{const t=(await E(e,r,i`SELECT ${i.identifier("cursor")}, ${i.identifier("done")}, ${i.identifier("profile")} FROM ${i.identifier(a)} WHERE ${i.identifier("companion")} = ${n}`))[0];if(!t)return{cursor:void 0,done:!1,profile:void 0};const{cursor:o,profile:f}=t;return{cursor:typeof o=="string"?o:void 0,done:l(t.done),profile:typeof f=="string"?f:void 0}},w=async(e,r,n,t,o,f)=>{const d=t??null,c=i`UPDATE ${i.identifier(a)} SET ${i.identifier("cursor")} = ${d}, ${i.identifier("done")} = ${o?1:0}, ${i.identifier("profile")} = ${f} WHERE ${i.identifier("companion")} = ${n}`;if((await E(e,r,i`SELECT ${i.identifier("companion")} FROM ${i.identifier(a)} WHERE ${i.identifier("companion")} = ${n}`)).length>0){await $(e,r,c);return}try{await $(e,r,i`INSERT INTO ${i.identifier(a)} (${i.identifier("companion")}, ${i.identifier("cursor")}, ${i.identifier("done")}, ${i.identifier("profile")}) VALUES (${n}, ${d}, ${o?1:0}, ${f})`)}catch(s){if(!r.isUniqueViolation(s))throw s;await $(e,r,c)}};export{a as SEARCH_STATE_TABLE,T as migrateSearchState,S as readSearchBackfillState,w as writeSearchBackfillState};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as o,F as t,v as s,B as l}from"./ctx-db-search-
|
|
1
|
+
import{A as o,F as t,v as s,B as l}from"./ctx-db-search-DPAoW2oD.mjs";import"@lunora/errors";import"drizzle-orm";import"./SEARCH_STATE_TABLE-Bo7-Ng-F.mjs";import"./decodeGlobalRow-CyB_gkZ1.mjs";export{o as backfillSqlSearchIndexes,t as createSearchSync,s as runSqlSearch,l as runSqlSearchMigrations};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as N}from"@lunora/errors";import{F as pt,B as Et,T as mt,a as yt,_ as gt,C as bt,v as Nt,D as Tt,b as vt,N as Rt}from"./ctx-db-search-DPAoW2oD.mjs";import{A as Ii}from"./ctx-db-search-DPAoW2oD.mjs";import{aggregateTableName as z,rankTableName as J,hasTrigger as St,runRowValidators as Ie,assertFlatPredicate as ze,mergeWhere as q,sortColumnName as Q,resolveRankPartition as Qe,encodePartitionKey as be,decodeCursor as Xe,RANK_TIEBREAK as _e,CountRlsUnsupportedError as Je,normalizeIdStructurally as At,assertValidClientId as It,aggregateSqlFunction as de,softDeleteScope as le,compileWhereSql as ue,normalizeOrderKeys as Lt,buildSeekWhere as Ot,resolveRelationPredicates as Ze,resolveWith as et,applySelect as tt,encodeCursor as kt,NotFoundError as Ct,applyOnDelete as xt,ConflictError as fe,normalizeCountArgument as Mt,selectIndexForCount as Dt,encodeAggregateKey as V,selectIndexForAggregate as qt,readAggregateValue as Le,runTriggers as Wt,matchesRankStaticWhere as it,selectIndexForGroupBy as jt,fanOutScalarCounts as Ft,matchesStaticWhere as Oe,foldAggregateTally as Bt,coerceAggregateNumber as ke,NotUniqueError as Ut,throwingScheduler as Pt}from"@lunora/shard-engine";import{sql as e}from"drizzle-orm";import{migrateSearchState as Ht}from"./SEARCH_STATE_TABLE-Bo7-Ng-F.mjs";import{queryAll as A,queryRun as I,createIndexIfNotExists as xe,decodeRow as Z,serializeColumnValue as H,columnRefSql as x,decodeRows as Kt,forEachRowPaged as nt,queryBatch as at}from"./decodeGlobalRow-CyB_gkZ1.mjs";import{decodeGlobalRow as Oi}from"./decodeGlobalRow-CyB_gkZ1.mjs";import{effectiveColumnKind as Ne}from"./decodeBigint-DfiI8pkL.mjs";const Vt=(u,$)=>{if(u.size<$)return;const _=u.keys().next().value;_!==void 0&&u.delete(_)},Gt=(u,$={})=>{const _=$.maxBatch??50,o=Number.isInteger(_)&&_>0?_:50,m=new Map;let d=!1;const s=async(g,v)=>{const R=[...v.keys()];for(let O=0;O<R.length;O+=o){const M=R.slice(O,O+o);try{const j=await u(g,M);for(const K of M){const F=j.get(K);for(const ve of v.get(K)??[])ve.resolve(F)}}catch(j){for(const K of M)for(const F of v.get(K)??[])F.reject(j)}}},T=()=>{d=!1;const g=[...m.entries()];m.clear();for(const[v,R]of g)s(v,R).catch(()=>{})};return{async load(g,v){return new Promise((R,O)=>{let M=m.get(g);M||(M=new Map,m.set(g,M));const j=M.get(v);j?j.push({reject:O,resolve:R}):M.set(v,[{reject:O,resolve:R}]),d||(d=!0,queueMicrotask(T))})}}},Yt=new Set(["_id","id"]),Me=(u,$,_)=>u==="postgres"?e`${$} IS NOT DISTINCT FROM ${_}`:u==="mysql"?e`${$} <=> ${_}`:e`${$} IS ${_}`,zt=u=>{const $=u.map(_=>e`${x(_.field)} ${e.raw(_.direction==="desc"?"DESC":"ASC")}`);return u.some(_=>Yt.has(_.field))||$.push(e`${x("id")} ASC`),e.join($,e`, `)},ot=50,De=u=>{const $=[];for(const[_,o]of Object.entries(u.shape)){const m=o._meta?.column;m&&$.push([_,m])}return $},Qt=(u,$,_)=>{const o={...$};for(const[m,d]of De(u)){if(d.serverDefault){o[m]=d.serverDefault({auth:_});continue}o[m]===void 0&&(d.defaultFn?o[m]=d.defaultFn():"defaultValue"in d&&(o[m]=d.defaultValue))}return o},rt=(u,$,_,o)=>{for(const[m,d]of De(u)){if(d.serverDefault){m in $&&(_[m]=d.serverDefault({auth:o}));continue}d.onUpdateFn&&!(m in $)&&(_[m]=d.onUpdateFn())}},Xt=128,Jt=()=>{const u=new Map;return{delete:$=>{u.delete($)},get:$=>{const _=u.get($);if(_!==void 0)return u.delete($),u.set($,_),_},set:($,_)=>{u.has($)?u.delete($):Vt(u,Xt),u.set($,_)}}},Zt=async(u,$,_,o,m)=>{const d=m.get(o);if(d!==void 0)return d;const s=[];for(const[g,v]of Object.entries(_.tables))v.shardMode!==void 0&&v.shardMode.kind!=="global"||s.push(g);const T=await Promise.all(s.map(async g=>({found:(await A(u,$,e`SELECT 1 FROM ${e.identifier(g)} WHERE ${e.identifier("id")} = ${o} LIMIT 1`)).length>0,tableName:g})));for(const g of T)if(g.found)return m.set(o,g.tableName),g.tableName},ee=u=>u==null?null:Number(u),ei=(u,$)=>$.map(_=>{const o={};for(const m of u)o[m]=_[m]??null;return{key:o,value:ee(_.value)}}),ti=(u,$,_)=>[...u.partitionBy??[],...u.sortBy.map(o=>o.field),...u.where?Object.keys(u.where):[]].every(o=>$[o]===_[o]),st=u=>u.length===1?u[0]:e`(${e.join(u,e` AND `)})`,ii=(u,$,_,o,m)=>{const d=[];for(let s=0;s<_.length+1;s+=1){const T=_.slice(0,s).map(R=>Me(u,e`${e.identifier(R)}`,o[R])),g=_[s],v=$.sortBy[s];s<_.length&&g!==void 0&&v!==void 0?T.push(e`${e.identifier(g)} ${e.raw(v.direction==="desc"?">":"<")} ${o[g]}`):T.push(e`${e.identifier(_e)} < ${m}`),d.push(st(T))}return d.length>0?e.join(d,e` OR `):void 0},ni=(u,$,_)=>{if(_.length!==$.length)return;const o=[];for(const[m,d]of $.entries()){const s=[];for(let T=0;T<m;T+=1){const g=$[T];g!==void 0&&s.push(Me(u,e`${e.identifier(g.column)}`,_[T]))}s.push(e`${e.identifier(d.column)} ${e.raw(d.direction==="desc"?"<":">")} ${_[m]}`),o.push(st(s))}return e`(${e.join(o,e` OR `)})`},ai=(u,$)=>{if(u.sortBy.length===0)throw new N("INTERNAL",`rankIndex "${u.name}" requires at least one "sortBy" column for stable pagination`);const _=[{column:"__partition__",direction:"asc"}];for(const[o,m]of u.sortBy.entries())_.push({column:$[o]??Q(o),direction:m.direction});return _.push({column:_e,direction:"asc"}),_},oi=async(u,$,_,o,m)=>{const d=[];for(let v=0;v<m.length;v+=50)d.push(m.slice(v,v+50));const s=await Promise.all(d.map(async v=>{const R=e.join(v.map(O=>e`${O}`),e`, `);return A(u,$,e`SELECT * FROM ${e.identifier(o)} WHERE ${e.identifier("id")} IN (${R})`)})),T=new Map;for(const v of s)for(const R of v)T.set(R.id,R);const g=[];for(const v of m){const R=Z(_,T.get(v));R&&g.push(R)}return g},ri=u=>{const $=JSON.stringify(u),_=new TextEncoder().encode($);let o="";for(const m of _)o+=String.fromCodePoint(m);return btoa(o)},si=(u,$)=>$.columnType(Ne(u)),ci=(u,$)=>{const _=[];for(const[m,d]of Object.entries(u.shape)){if(!d._meta?.column)continue;const s=d._meta.column.notNull&&d.kind!=="optional"?" NOT NULL":"";_.push(e`${e.identifier(m)} ${e.raw(`${si(d,$)}${s}`)}`)}const o=$.frameworkColumns().map(m=>e`${e.identifier(m.name)} ${e.raw(m.type)}`);return e.join([...o,..._],e`, `)},di=async(u,$,_,o)=>{const m=d=>{const s=x(d),T=_.shape[d],g=T&&o.indexKeyPrefix?o.indexKeyPrefix(Ne(T)):void 0;return g===void 0?s:e`${s}(${e.raw(String(g))})`};for(const d of _.indexes){const s=e.join(d.fields.map(T=>m(T)),e`, `);await xe(u,o,{columns:s,name:`${$}_${d.name}`,table:$,unique:d.unique??!1})}for(const[d,s]of De(_))s.unique&&await xe(u,o,{columns:m(d),name:`${$}_unique_${d}`,table:$,unique:!0})},li=async(u,$,_)=>{for(const[o,m]of Object.entries($.tables)){if(m.shardMode?.kind!=="global")continue;const d=ci(m,_);await I(u,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(o)} (${d})`),await di(u,o,m,_)}},ui=async(u,$,_)=>{const{integer:o,key:m,real:d}=_.companionTypes;for(const[s,T]of Object.entries($.tables)){const g=T.aggregateIndexes;if(!(!g||g.length===0))for(const v of g){const R=z(s,v.name);await I(u,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(R)} (${e.identifier("__key__")} ${e.raw(m)} PRIMARY KEY, ${e.identifier("__value__")} ${e.raw(d)}, ${e.identifier("__count__")} ${e.raw(o)} NOT NULL DEFAULT 0)`),_.name==="sqlite"&&((await A(u,_,e`PRAGMA table_info(${e.identifier(R)})`)).some(O=>O.name==="__count__")||await I(u,_,e`ALTER TABLE ${e.identifier(R)} ADD COLUMN ${e.identifier("__count__")} ${e.raw(o)} NOT NULL DEFAULT 0`))}}},Ce=(u,$,_,o)=>{const m=u.name==="mysql"&&o?e`${e.identifier($)}(191)`:e`${e.identifier($)}`;return e`${m} ${e.raw(_)}`},fi=(u,$,_)=>{const o=[Ce(u,"__partition__","ASC",!0)];for(const[m,d]of $.sortBy.entries()){const s=_.shape[d.field],T=s!==void 0&&u.indexKeyPrefix?.(Ne(s))!==void 0;o.push(Ce(u,Q(m),d.direction==="desc"?"DESC":"ASC",T))}return o.push(Ce(u,"__id__","ASC",!0)),o},_i=(u,$,_)=>$.sortBy.map((o,m)=>{const d=_.shape[o.field],s=u.columnType(d?Ne(d):void 0);return e`${e.identifier(Q(m))} ${e.raw(s)}`}),$i=async(u,$,_)=>{const{key:o}=_.companionTypes;for(const[m,d]of Object.entries($.tables)){const s=d.rankIndexes;if(!(!s||s.length===0))for(const T of s){const g=J(m,T.name),v=_i(_,T,d),R=v.length>0?e`, ${e.join(v,e`, `)}`:e``;await I(u,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(g)} (${e.identifier("__id__")} ${e.raw(o)} PRIMARY KEY, ${e.identifier("__partition__")} ${e.raw(o)} NOT NULL${R})`);const O=fi(_,T,d),M=`${m}__rank_${T.name}__btree`;await xe(u,_,{columns:e.join(O,e`, `),name:M,table:g,unique:!1})}}},Te="__cdc_log",wi=async(u,$)=>{const{autoincrementPrimaryKey:_,key:o,real:m,text:d}=$.companionTypes;await I(u,$,e`CREATE TABLE IF NOT EXISTS ${e.identifier(Te)} (${e.identifier("seq")} ${e.raw(_)}, ${e.identifier("ts")} ${e.raw(m)} 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(d)})`)},hi=async(u,$,_,o,m,d,s)=>{await I(u,s,e`INSERT INTO ${e.identifier(Te)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${$}, ${_}, ${o}, ${m}, ${d===void 0?null:JSON.stringify(d)})`)},Ti=async(u,$,_)=>{const o=$.sinceSeq??0,m=Math.max(1,Math.min($.limit??1e3,1e4)),d=(await A(u,_,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(Te)} WHERE seq > ${o} ORDER BY seq ASC LIMIT ${e.raw(String(m))}`)).map(s=>{const{doc:T}=s,g={id:String(s.id),op:String(s.op),seq:Number(s.seq),table:String(s.table),ts:Number(s.ts)};return typeof T=="string"?{...g,doc:JSON.parse(T)}:g});return{changes:d,cursor:d.at(-1)?.seq??o}},vi=async(u,$,_)=>{await I(u,_,e`DELETE FROM ${e.identifier(Te)} WHERE ${e.identifier("seq")} <= ${$}`)},Ri=u=>{const{crossShardCounter:$,crossShardReader:_,exec:o,maxRelationKeys:m,schema:d}=u,{dialect:s}=u,{isUniqueViolation:T}=s,g={fieldRef:x,serialize:H,...s.name==="mysql"?{likeContains:(t,i)=>e`${t} LIKE CONCAT('%', ${i}, '%') ESCAPE '\\\\'`}:{}},v=(t,i)=>Me(s.name,t,i),R=t=>{const i=e.join(t.columns.map(l=>e`${e.identifier(l)}`),e`, `),n=e.join(t.values.map(l=>e`${l}`),e`, `),a=l=>s.name==="mysql"?e`VALUES(${e.identifier(l)})`:e`excluded.${e.identifier(l)}`,r=l=>s.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(l)}`:e`${e.identifier(l)}`,f=e.join(Object.entries(t.set(a,r)).map(([l,p])=>e`${e.identifier(l)} = ${p}`),e`, `),h=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}) ${h}`},O=u.clock??(()=>Date.now()),M=u.idGenerator??(()=>crypto.randomUUID()),j=u.cdc??!1,K=u.auth??{identity:null,userId:null},F=async(t,i,n,a)=>{j&&await hi(o,O(),t,i,n,a,s)},ve=u.scheduler??Pt,Re=Jt();let $e=0,Se;const B=async()=>(Se??=(async()=>{await li(o,d,s),await ui(o,d,s),await $i(o,d,s),await Ht(o,s),await Et(o,d,s),j&&await wi(o,s)})().catch(t=>{throw Se=void 0,t}),Se),te=async(t,i)=>{await B();const n=await Zt(o,s,d,t,Re);if(!(i!==void 0&&n!==i))return n},ie=new Map,qe=async(t,i)=>{const n=z(t,i);return(await A(o,s,s.tableExists(n))).length>0},we=async(t,i)=>{const n=`${t}::${i.name}`,a=ie.get(n);if(a!==void 0)return a;if(!await qe(t,i.name))return ie.set(n,!1),!1;const r=d.tables[t];if(!r)return ie.set(n,!1),!1;const f=i.by??[],h=new Map;await nt(o,s,r,t,c=>{if(i.where&&!Oe(c,i.where))return;const w=V(f,c);Bt(h,w,i,c)});const l=z(t,i.name);await I(o,s,e`DELETE FROM ${e.identifier(l)}`);const p=[];for(const[c,w]of h)p.push(e`INSERT INTO ${e.identifier(l)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${c}, ${w.value}, ${w.count})`);return await at(o,s,p),ie.set(n,!0),!0},ct=async(t,i,n)=>{const a=de(i.op),r=i.field??"",f=[];for(const p of i.by??[]){const c=H(n[p]??null);f.push(c===null?e`${x(p)} IS NULL`:e`${x(p)} = ${c}`)}for(const[p,c]of Object.entries(i.where??{})){const w=c!==null&&typeof c=="object"&&!Array.isArray(c)?c.eq:c,E=H(w);f.push(E===null?e`${x(p)} IS NULL`:e`${x(p)} = ${E}`)}const h=e`SELECT ${e.raw(a)}(${x(r)}) AS value FROM ${e.identifier(t)}`,l=await A(o,s,f.length>0?e`${h} WHERE ${e.join(f,e` AND `)}`:h);return ee(l[0]?.value)},We=async(t,i)=>{await I(o,s,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${i} AND ${e.identifier("__count__")} <= 0`)},dt=async(t,i,n,a)=>{const r=z(t,i.name),{op:f}=i,h=i.field??"",l=n&&(!i.where||Oe(n,i.where))?n:void 0,p=a&&(!i.where||Oe(a,i.where))?a:void 0;if(!(!l&&!p)){if(f==="count"){const c=new Set;for(const[w,E]of[[l,-1],[p,1]]){if(!w)continue;const y=V(i.by??[],w);c.add(y),await I(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(b,S)=>({__count__:e`${S("__count__")} + ${b("__count__")}`,__value__:e`${S("__value__")} + ${b("__value__")}`}),table:r,values:[y,E,E]}))}for(const w of c)await We(r,w);return}if(f==="sum"||f==="avg"){const c=new Set;for(const[w,E]of[[l,-1],[p,1]]){if(!w)continue;const y=ke(w[h]);if(y===void 0)continue;const b=V(i.by??[],w);c.add(b),await I(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(S,C)=>({__count__:e`${C("__count__")} + ${S("__count__")}`,__value__:e`COALESCE(${C("__value__")}, 0) + ${S("__value__")}`}),table:r,values:[b,E*y,E]}))}for(const w of c)await We(r,w);return}if(l){const c=V(i.by??[],l),w=ke(l[h]),E=(await A(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${c}`))[0],y=ee(E?.value),b=(E?.count??0)-1;if(b<=0)await I(o,s,e`DELETE FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${c}`);else if(E&&w!==void 0&&y!==null&&w===y){const S=await ct(t,i,l);await I(o,s,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__value__")} = ${S}, ${e.identifier("__count__")} = ${b} WHERE ${e.identifier("__key__")} = ${c}`)}else await I(o,s,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${c}`)}if(p){const c=V(i.by??[],p),w=ke(p[h]);if(w===void 0)await I(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(E,y)=>({__count__:e`${y("__count__")} + 1`}),table:r,values:[c,null,1]}));else{const E=f==="min"?"MIN":"MAX";await I(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(y,b)=>({__count__:e`${b("__count__")} + 1`,__value__:e`${e.raw(E)}(COALESCE(${b("__value__")}, ${y("__value__")}), ${y("__value__")})`}),table:r,values:[c,w,1]}))}}}},he=async t=>{const i=d.tables[t]?.aggregateIndexes;if(!(!i||i.length===0))for(const n of i)await we(t,n)},ne=async(t,i,n)=>{const a=d.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const r of a){const f=`${t}::${r.name}`;(ie.get(f)??await qe(t,r.name))&&await dt(t,r,i,n)}},ae=new Map,je=async(t,i)=>{const n=J(t,i);return(await A(o,s,s.tableExists(n))).length>0},Ae=async(t,i)=>{const n=`${t}::rank::${i.name}`,a=ae.get(n);if(a!==void 0)return a;if(!await je(t,i.name))return ae.set(n,!1),!1;const r=d.tables[t];if(!r)return ae.set(n,!1),!1;const f=J(t,i.name);await I(o,s,e`DELETE FROM ${e.identifier(f)}`);const h=i.sortBy.map((w,E)=>Q(E)),l=e.join(["__id__","__partition__",...h].map(w=>e`${e.identifier(w)}`),e`, `),p=[];await nt(o,s,r,t,w=>{if(i.where&&!it(w,i.where))return;const E=be(i.partitionBy??[],w),y=i.sortBy.map(b=>H(w[b.field]??null));p.push([w._id,E,...y])});const c=p.map(w=>{const E=e.join(w.map(y=>e`${y}`),e`, `);return e`INSERT INTO ${e.identifier(f)} (${l}) VALUES (${E})`});return await at(o,s,c),ae.set(n,!0),!0},pe=async t=>{const i=d.tables[t]?.rankIndexes;if(!(!i||i.length===0))for(const n of i)await Ae(t,n)},X=async(t,i,n,a)=>{const r=d.tables[t],f=r?.rankIndexes;if(!f||f.length===0)return;const h=r?.softDeleteMode?.field,l=h===void 0||a===void 0?void 0:a[h],p=l!=null;for(const c of f){if(n!==void 0&&a!==void 0&&ti(c,n,a))continue;const w=`${t}::rank::${c.name}`;if(!(ae.get(w)??await je(t,c.name)))continue;const E=J(t,c.name);if(n&&await I(o,s,e`DELETE FROM ${e.identifier(E)} WHERE ${e.identifier("__id__")} = ${i}`),a&&!p){if(c.where&&!it(a,c.where))continue;const y=c.sortBy.map((L,G)=>Q(G)),b=e.join(["__id__","__partition__",...y].map(L=>e`${e.identifier(L)}`),e`, `),S=be(c.partitionBy??[],a),C=c.sortBy.map(L=>H(a[L.field]??null)),D=e.join([i,S,...C].map(L=>e`${L}`),e`, `);await I(o,s,e`INSERT INTO ${e.identifier(E)} (${b}) VALUES (${D})`)}}},oe=pt({dialect:s,exec:o,schema:d}),Fe=new Set;for(const[t,i]of Object.entries(d.tables))for(const n of Object.values(i.triggerMap??{}))Fe.add(`${t} ${n.timing} ${n.op}`);const U=(t,i,n)=>Fe.has(`${t} ${i} ${n}`);let Be;const P=async(t,i,n)=>{if($e+=1,$e>ot)throw $e-=1,new fe(`trigger recursion exceeded ${String(ot)} levels on "${n.table}" — check for a self-triggering write`,"trigger");try{await Wt({ctx:Be,event:n,op:i,schema:d,tableName:n.table,timing:t})}finally{$e-=1}},lt=async(t,i)=>{try{await I(o,s,i)}catch(n){throw T(n)?new fe(`unique constraint violation on "${t}"`,"unique"):n}},Ee=async(t,i)=>(await A(o,s,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${i}`))[0],me=async(t,i,n,a)=>{if(a===void 0)return;const r=e.join(Object.keys(a).map(l=>v(e`${e.identifier(l)}`,a[l])),e` AND `),f=i==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${n} WHERE ${r}`:e`DELETE FROM ${e.identifier(t)} WHERE ${r}`,h=()=>{throw new fe(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")};try{if(s.supportsReturning)(await A(o,s,e`${f} RETURNING ${e.identifier("id")}`)).length===0&&h();else{const l=await I(o,s,f);(s.affectedRows?s.affectedRows(l??{rowsAffected:0}):0)===0&&h()}}catch(l){throw T(l)?new fe(`unique constraint violation on "${t}"`,"unique"):l}},ut=(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))]}},ft=async(t,i,n,a)=>{const r=jt(i,n.op,n.field,a.by,a.where);if(!r||!await we(t,r.index))return;const f=z(t,r.index.name),h=Object.keys(r.partial);if(h.length===(r.index.by??[]).length&&h.length>0){const l=V(r.index.by??[],r.partial),p=await A(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(f)} WHERE ${e.identifier("__key__")} = ${l}`);if(p.length===0)return[];const c=p[0];return[{key:{...r.partial},value:Le(n.op,{count:c.count,value:ee(c.value)})}]}return h.length>0?void 0:(await A(o,s,e`SELECT ${e.identifier("__key__")} AS key, ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(f)}`)).map(l=>{const p=l;return{key:JSON.parse(p.key),value:Le(n.op,{count:p.count,value:ee(p.value)})}})},Ue=t=>{const i=d.tables[t]?.shardMode?.kind;return i==="shardBy"||i==="root"},Pe=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`)},He=(t,i)=>Ue(t)?_?_(t,i):Pe(t):W.findMany(t,i),ye=(t,i,n)=>Ze(t,{fetcher:He,maxRelationKeys:m,relationBaseWhere:n,schema:d,tableName:i}),_t=Gt(async(t,i)=>{const n=e.join(i.map(f=>e`${f}`),e`, `),a=await A(o,s,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} IN (${n})`),r=new Map;for(const f of a){const{id:h}=f;typeof h=="string"&&r.set(h,f)}return r}),W={async aggregate(t,i){const n=d.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);if(await B(),de(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=le(n.softDeleteMode,void 0),r=q(q(i.baseWhere,i.where),a),f=await ye(r,t,i.relationBaseWhere),h=f!==r;if(n.aggregateIndexes&&!i.baseWhere&&!h&&!a){const E=qt(n.aggregateIndexes,i.op,i.field,i.where);if(E&&await we(t,E.index)){const y=V(E.index.by??[],E.key),b=z(t,E.index.name),S=(await A(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(b)} WHERE ${e.identifier("__key__")} = ${y}`))[0];return Le(i.op,S===void 0?void 0:{count:S.count,value:ee(S.value)})}}const l=ue(f,g),p=e.raw(de(i.op)),c=e`SELECT ${p}(${x(i.field)}) AS value FROM ${e.identifier(t)}`,w=(await A(o,s,l?e`${c} WHERE ${l}`:c))[0]?.value;return w==null?null:Number(w)},async count(t,i){const n=d.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await B();const a=Mt(i);if(a.restrictsCounts)throw new Je(t);const r=le(n.softDeleteMode,void 0),f=q(q(a.baseWhere,a.where),r),h=await ye(f,t,a.relationBaseWhere),l=h!==f;if(n.aggregateIndexes&&!a.baseWhere&&!l&&!r){const E=Dt(n.aggregateIndexes,a.where);if(E&&await we(t,E.index)){const y=V(E.index.by??[],E.key),b=z(t,E.index.name),S=await A(o,s,e`SELECT ${e.identifier("__value__")} AS value FROM ${e.identifier(b)} WHERE ${e.identifier("__key__")} = ${y}`);return Number(S[0]?.value??0)}}const p=ue(h,g),c=e`SELECT COUNT(*) AS count FROM ${e.identifier(t)}`,w=await A(o,s,p?e`${c} WHERE ${p}`:c);return Number(w[0]?.count??0)},async delete(t,i,n){const a=await te(t,i);if(!a)return;const r=d.tables[a];if(!r)return;const f=await Ee(a,t),h=Z(r,f),l=n?.hard===!0,p=!l&&r.softDeleteMode?r.softDeleteMode.field:void 0;if(!(p&&(!h||h[p]!==null&&h[p]!==void 0))){if(U(a,"before","delete")&&await P("before","delete",{id:t,op:"delete",previous:h??void 0,table:a}),await xt({deletedId:t,deletedReference:c=>h?.[c],findHolders:async(c,w,E)=>{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:l,where:{[w]:E}})).page},onCascade:(c,w)=>W.delete(w,void 0,n),onRestrict:c=>{throw new fe(c,"restrict")},onSetNull:(c,w,E)=>W.patch(w,{[E]:null}),schema:d,tableName:a}),await he(a),await pe(a),p&&h){const c={...h,[p]:O()},w=e.join(Object.keys(r.shape).map(E=>e`${e.identifier(E)} = ${H(c[E]??null)}`),e`, `);await me(a,"UPDATE",w,f),await ne(a,h,c),await X(a,t,h,void 0),await oe(a,t,c,h),await F(a,t,"update",c),U(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:h,table:a});return}await me(a,"DELETE",void 0,f),Re.delete(t),await ne(a,h??void 0,void 0),await X(a,t,h??void 0,void 0),await oe(a,t,void 0),await F(a,t,"delete"),U(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:h??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 Ct(`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 B();const a=Lt(i.orderBy),r=i.cursor?Ot(a,Xe(i.cursor)):void 0,f=He,h=async(L,G,ge,re)=>{if(Ue(L))return $?Ft($,L,G,ge,re):Pe(L);const Y=d.tables[L];if(!Y)throw new N("INTERNAL",`unknown table: ${L}`);const k=le(Y.softDeleteMode,void 0),se={[G]:{in:ge}},$t=q(q(se,re),k),wt=await ye($t,L,void 0),Ke=ue(wt,g),Ve=x(G);let ce=e`SELECT ${Ve} AS __fk__, COUNT(*) AS count FROM ${e.identifier(L)}`;Ke&&(ce=e`${ce} WHERE ${Ke}`),ce=e`${ce} GROUP BY ${Ve}`;const ht=await A(o,s,ce),Ge=new Map;for(const Ye of ht)Ge.set(Ye.__fk__,Number(Ye.count??0));return Ge};let l=q(i.baseWhere,i.where);l=q(l,le(n.softDeleteMode,i.includeDeleted)),l=await Ze(l,{fetcher:f,maxRelationKeys:m,relationBaseWhere:i.relationBaseWhere,schema:d,tableName:t}),r&&(l=l?{AND:[l,r]}:r);const p=ue(l,g),c=zt(a);let w=e`SELECT * FROM ${e.identifier(t)}`;p&&(w=e`${w} WHERE ${p}`),w=e`${w} ORDER BY ${c}`;const E=typeof i.limit=="number"?Math.max(0,Math.floor(i.limit)):void 0;E!==void 0&&(w=e`${w} LIMIT ${e.raw(String(E+1))}`);const y=await A(o,s,w),b=Kt(n,y);if(E===void 0)return i.with&&await et({fetcher:f,groupedCounter:h,parents:b,schema:d,tableName:t,with:i.with}),{continueCursor:null,isDone:!0,page:tt(b,i.select,i.with)};const S=b.length>E,C=S?b.slice(0,E):b,D=C.at(-1);return i.with&&await et({fetcher:f,groupedCounter:h,parents:C,schema:d,tableName:t,with:i.with}),{continueCursor:S&&D?kt(D,a):null,isDone:!S,page:tt(C,i.select,i.with)}},async get(t,i){const n=await te(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 B();const a=i.agg??{op:"count"};if(de(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=le(n.softDeleteMode,void 0),f=q(q(i.baseWhere,i.where),r),h=await ye(f,t,i.relationBaseWhere),l=h!==f;if(n.aggregateIndexes&&!i.baseWhere&&!l&&!r){const b=await ft(t,n.aggregateIndexes,a,i);if(b!==void 0)return b}const p=ue(h,g),c=i.by.map(b=>e`${x(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(de(a.op))}(${x(a.field)}) AS value`)}const w=e.join(i.by.map(b=>x(b)),e`, `);let E=e`SELECT ${e.join(c,e`, `)} FROM ${e.identifier(t)}`;p&&(E=e`${E} WHERE ${p}`),E=e`${E} GROUP BY ${w}`;const y=await A(o,s,E);return ei(i.by,y)},async insert(t,i,n){const a=d.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);await B();const r=Qt(a,i,K);Ie(a,r);let f,h=!0;n?.clientId!==void 0?(It(n.clientId),f=n.clientId):n?.allowExplicitId&&typeof r._id=="string"?f=r._id:(f=M(),h=!1);const l=n?.allowExplicitId&&typeof r._creationTime=="number"?r._creationTime:O(),p={...r,_creationTime:l,_id:f};U(t,"before","insert")&&await P("before","insert",{doc:{...p},id:f,op:"insert",table:t}),await he(t),await pe(t);const{columns:c,values:w}=ut(a,f,l,r),E=e.join(c.map(b=>e`${e.identifier(b)}`),e`, `),y=e.join(w.map(b=>e`${b}`),e`, `);return await lt(t,e`INSERT INTO ${e.identifier(t)} (${E}) VALUES (${y})`),h&&Re.set(f,t),await ne(t,void 0,p),await X(t,f,void 0,p),await oe(t,f,p),await F(t,f,"insert",p),U(t,"after","insert")&&await P("after","insert",{doc:p,id:f,op:"insert",table:t}),f},normalizeId(t,i){return At(d,t,i)},async patch(t,i,n){const a=await te(t,n);if(!a)throw new N("INTERNAL",`document not found: ${t}`);const r=d.tables[a];if(!r)throw new N("INTERNAL",`document not found: ${t}`);const f=await Ee(a,t),h=Z(r,f);if(!h)throw new N("INTERNAL",`document not found: ${t}`);const l={...h,...i,_id:t};rt(r,i,l,K),Ie(r,l,!0),U(a,"before","update")&&await P("before","update",{doc:{...l},id:t,op:"update",previous:h,table:a}),await he(a),await pe(a);const p=Object.keys(r.shape),c=e.join(p.map(w=>e`${e.identifier(w)} = ${H(l[w]??null)}`),e`, `);await me(a,"UPDATE",c,f),await ne(a,h,l),await X(a,t,h,l),await oe(a,t,l,h),await F(a,t,"update",l),U(a,"after","update")&&await P("after","update",{doc:l,id:t,op:"update",previous:h,table:a})},async restore(t,i){const n=await te(t,i);if(!n)throw new N("INTERNAL",`document not found: ${t}`);const a=d.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 Ee(n,t),h=f?.[r]!==null&&f?.[r]!==void 0;if(await W.patch(t,{[r]:null},i),h){const l=Z(a,f);l!==null&&await X(n,t,void 0,{...l,[r]: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=[],r=l=>a.every(p=>p(l)),f=async(l,p)=>{await B();const c=a.length>0,w=await Nt(o,s,i,t,l,Tt(c?void 0:p));if(!c)return p===void 0&&vt(w),w;const E=w.filter(y=>r(y));return p===void 0?E:E.slice(0,p)},h=l=>{const p={async*[Symbol.asyncIterator](){if(!l)throw new N("INTERNAL",n);yield*await f(l,void 0)},async collect(){if(!l)throw new N("INTERNAL",n);return f(l,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(!l)throw new N("INTERNAL",n);return(await f(l,1))[0]??null},order(){return p},async paginate(c){if(!l)throw new N("INTERNAL",n);const w=gt(c);return bt(await f(l,Rt(w)),w)},async take(c){if(!l)throw new N("INTERNAL",n);return f(l,c)},async unique(){if(!l)throw new N("INTERNAL",n);const c=await f(l,2);if(c.length>1)throw new Ut(`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,w){const E=(i.searchIndexes??[]).find(b=>b.name===c);if(!E)throw new N("INTERNAL",`unknown search index "${c}" on table "${t}"`);const y={definition:E,field:E.field,filters:[],hasQuery:!1,indexName:c,query:""};if(w(mt(y,t,yt(E.language))),!y.hasQuery)throw new N("INTERNAL",`search index "${c}" on table "${t}" requires a .search(field, query) call`);return h(y)}};return p};return h(void 0)},async rank(t,i,n){const a=d.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(D=>D.name===i);if(!r)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(n.restrictsCounts)throw new Je(t);if(await B(),!await Ae(t,r))return null;const f=typeof n.row=="string"?n.row:n.row._id;if(!f)return null;const h=J(t,r.name),l=r.sortBy.map((D,L)=>Q(L)),p=e.join([e`${e.identifier("__partition__")}`,...l.map(D=>e`${e.identifier(D)}`)],e`, `),c=(await A(o,s,e`SELECT ${p} FROM ${e.identifier(h)} WHERE ${e.identifier("__id__")} = ${f}`))[0];if(!c)return null;const w=c.__partition__,E=q(n.baseWhere,n.where);ze(E,d,t,"rank");const y=Qe(r,E);if(y&&be(r.partitionBy??[],y)!==w)return null;const b=ii(s.name,r,l,c,f),S=await A(o,s,e`SELECT COUNT(*) AS c FROM ${e.identifier(h)} WHERE ${e.identifier("__partition__")} = ${w}${b?e` AND (${b})`:e``}`),C=await A(o,s,e`SELECT COUNT(*) AS c FROM ${e.identifier(h)} WHERE ${e.identifier("__partition__")} = ${w}`);return{position:Number(S[0]?.c??0)+1,total:Number(C[0]?.c??0)}},async rankPage(t,i,n={}){ze(q(n.baseWhere,n.where),d,t,"rankPage");const a=d.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(k=>k.name===i);if(!r)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(await B(),!await Ae(t,r))return{continueCursor:null,isDone:!0,page:[]};const f=J(t,r.name),h=r.sortBy.map((k,se)=>Q(se)),l=Math.max(1,Math.min(1e3,Math.floor(n.take??100))),p=q(n.baseWhere,n.where),c=Qe(r,p),w=ai(r,h),E=e.join(w.map(k=>e`${e.identifier(k.column)} ${e.raw(k.direction==="desc"?"DESC":"ASC")}`),e`, `),y=[];if(c&&y.push(e`${e.identifier("__partition__")} = ${be(r.partitionBy??[],c)}`),n.cursor){const k=ni(s.name,w,Xe(n.cursor));k!==void 0&&y.push(k)}const b=e.join([e`${e.identifier(_e)}`,e`${e.identifier("__partition__")}`,...h.map(k=>e`${e.identifier(k)}`)],e`, `);let S=e`SELECT ${b} FROM ${e.identifier(f)}`;y.length>0&&(S=e`${S} WHERE ${e.join(y,e` AND `)}`),S=e`${S} ORDER BY ${E} LIMIT ${e.raw(String(l+1))}`;const C=await A(o,s,S),D=C.length>l,L=D?C.slice(0,l):C,G=L.map(k=>k[_e]),ge=await oi(o,s,a,t,G);let re=null;const Y=L.at(-1);if(D&&Y!==void 0){const k=[Y.__partition__,...h.map(se=>Y[se]),Y[_e]];re=ri(k)}return{continueCursor:re,isDone:!D,page:ge}},async replace(t,i,n,a){const r=await te(t,n);if(!r)throw new N("INTERNAL",`document not found: ${t}`);const f=d.tables[r];if(!f)throw new N("INTERNAL",`document not found: ${t}`);const h=await Ee(r,t);if(h===void 0)throw new N("INTERNAL",`document not found: ${t}`);const l=St(d,r,"update")||(f.aggregateIndexes??[]).length>0||(f.rankIndexes??[]).length>0?Z(f,h)??void 0:void 0,p=a?.allowExplicitId&&typeof i._creationTime=="number"?i._creationTime:O(),c={...i,_creationTime:p,_id:t};rt(f,i,c,K),Ie(f,c),U(r,"before","update")&&await P("before","update",{doc:{...c},id:t,op:"update",previous:l,table:r}),await he(r),await pe(r);const w=Object.keys(f.shape),E=e.join([e`${e.identifier("_creationTime")} = ${p}`,...w.map(y=>e`${e.identifier(y)} = ${H(c[y]??null)}`)],e`, `);await me(r,"UPDATE",E,h),await ne(r,l,c),await X(r,t,l,c),await oe(r,t,c,l),await F(r,t,"update",c),U(r,"after","update")&&await P("after","update",{doc:c,id:t,op:"update",previous:l,table:r})}};return Be={db:W,scheduler:ve},W};export{Ii as backfillSqlSearchIndexes,Ri as createSqlCtxDb,Oi as decodeGlobalRow,Ti as readSqlCdcChanges,ui as runSqlAggregateMigrations,wi as runSqlCdcMigration,li as runSqlGlobalTableMigrations,$i as runSqlRankMigrations,Et as runSqlSearchMigrations,vi 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 L}from"./SEARCH_STATE_TABLE-Bo7-Ng-F.mjs";import{queryRun as E,columnRefSql as y,serializeColumnValue as M,decodeRows as U,queryAll as R,queryBatch as ie,createIndexIfNotExists as z,forEachRowPaged as te}from"./decodeGlobalRow-CyB_gkZ1.mjs";const ne=["de","en","es","fr","it","nl","none","pt"],re=e=>ne.includes(e),ae="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",oe="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",se="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",de="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",fe="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",ue="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",ce="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ê",le=/[\u0300-\u036F]/gu,V=e=>e.normalize("NFD").replaceAll(le,"").normalize("NFC").toLowerCase(),N=e=>new Set(V(e).split(" ")),$e={de:N(oe),en:N(ae),es:N(se),fr:N(de),it:N(fe),nl:N(ue),none:new Set,pt:N(ce)},me=2,he=256,H=new Map,A=e=>{const t=e!==void 0&&re(e)?e:"none",n=H.get(t);if(n)return n;const r=$e[t],a=s=>{const d=(V(s).match(/[\p{L}\p{N}]+/gu)??[]).filter(f=>f.length<=he);return r.size===0?d:d.filter(f=>!r.has(f))},o={document:a,profile:`${t}-v${String(me)}`,query:s=>{const d=a(s),f=new Set,u=[];for(let c=d.length-1;c>=0;c-=1){const l=d[c];f.has(l)||(f.add(l),u.unshift(l))}return u}};return H.set(t,o),o},we=(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},pe=(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},v=(e,t)=>`${e}__fts_${t}`,Ee="__text__",$="__id__",x="__token__",C="__n__",Se=1e3,Y=(e,t)=>t.document(e),q=(e,t)=>pe(e,t),ge=e=>typeof e=="string"?e:e==null?"":typeof e=="number"||typeof e=="bigint"||typeof e=="boolean"?String(e):JSON.stringify(e)??"",_e=(e,t,n)=>e!==void 0&&t!==void 0&&q(e,n.field)===q(t,n.field),j=(e,t)=>Y(ge(q(e,t.field)),A(t.language)).slice(0,Se).join(" "),Ne=(e,t)=>{const n=new Map;for(const r of Y(e,t))n.set(r,(n.get(r)??0)+1);return n},Te=e=>{const t=new TextEncoder().encode(e);let n="";for(const r of t)n+=String.fromCodePoint(r);return btoa(n)},ye=e=>{const t=atob(e),n=Uint8Array.from(t,r=>r.codePointAt(0)??0);return new TextDecoder().decode(n)},Ae=()=>new S("BAD_REQUEST","invalid cursor"),k=16,P=8,g=1024,D=(e,t)=>t.query(e),xe=(e,t)=>{if(!t)return{exact:!0,lower:e,upper:e};const n=[...e].at(-1)??"",r=(n.codePointAt(0)??0)+1;if(r>=55296&&r<=57343||r>1114111)return{exact:!0,lower:e,upper:e};const a=e.slice(0,e.length-n.length);return{exact:!1,lower:e,upper:a+String.fromCodePoint(r)}},Fe=(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>=P)throw new S("BAD_REQUEST",`search index "${e.indexName}" on table "${t}": at most ${String(P)} .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 d=D(o,n).length;if(d>k)throw new S("BAD_REQUEST",`search index "${s.indexName}" on table "${t}": at most ${String(k)} search terms are supported (got ${String(d)})`);return s.field=a,s.query=o,s.hasQuery=!0,r}};return r},ze=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()`)},He=e=>Math.min(e.offset+e.numItems+1,g),Ie=e=>Te(`search:${String(e)}`),Le=e=>{let t;try{t=ye(e)}catch{return}if(!t.startsWith("search:"))return;const n=Number(t.slice(7));return Number.isInteger(n)&&n>=0?n:void 0},ke=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?Le(e.cursor):0;if(n===void 0)throw Ae();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)}},We=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 E(e,t,i`DELETE FROM ${i.identifier(n)} WHERE ${i.identifier($)} = ${r}`)},O=(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(x)} LIKE ${`${e}%`}`:i`${i.identifier(x)} = ${e}`,ve=async(e,t,n,r,a,o)=>{const s=D(a.query,A(a.definition.language));if(s.length===0)return[];const d=v(r,a.indexName),f=s.length-1,u=s.map((h,T)=>Re(h,T===f)),c=i.join(u,i` OR `),l=u.map(h=>i`SUM(CASE WHEN ${h} THEN ${i.identifier(C)} ELSE 0 END)`),_=i.join(l.map(h=>i`${h} > 0`),i` AND `),w=i`SELECT ${i.identifier($)}, ${i.join(l,i` + `)} AS ${i.identifier("__score__")} FROM ${i.identifier(d)} WHERE ${c} GROUP BY ${i.identifier($)} HAVING ${_}`,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 (${w}) 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 R(e,t,m))},De=async(e,t,n,r,a,o)=>{const s=D(a.query,A(a.definition.language));if(s.length===0)return[];const d=v(r,a.indexName),f=`${d}__vocab`,u=s.length-1,c=s.map((m,h)=>{const T=xe(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(f)} 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)`),_=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(d)} f ON f.rowid = u.${i.identifier("doc")} GROUP BY f.${i.identifier($)} HAVING ${i.join(l.map(m=>i`${m} > 0`),i` AND `)}`,w=[];for(const m of a.filters)w.push(i`m.${y(m.field)} = ${M(m.value)}`);n.softDeleteMode&&w.push(i`m.${y(n.softDeleteMode.field)} IS NULL`);let p=i`SELECT m.* FROM (${_}) s JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = s.${i.identifier($)}`;return w.length>0&&(p=i`${p} WHERE ${i.join(w,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 R(e,t,p))},be=async(e,t,n,r,a,o)=>{const s=t.nativeTextSearch,d=D(a.query,A(a.definition.language));if(!s||d.length===0)return[];const f=v(r,a.indexName),u=[s.matches(f,d)];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(f)} JOIN ${i.identifier(r)} m ON m.${i.identifier("id")} = ${i.identifier(f)}.${i.identifier($)} WHERE ${i.join(u,i` AND `)} ORDER BY ${s.rank(f,d)} DESC, m.${i.identifier("_creationTime")} DESC, m.${i.identifier("id")} ASC LIMIT ${i.raw(String(o))}`;return U(n,await R(e,t,c))},Oe={ensureCompanion:async(e,t,n)=>{const{integer:r,key:a}=t.companionTypes;await E(e,t,i`CREATE TABLE IF NOT EXISTS ${i.identifier(n)} (${i.identifier(x)} ${i.raw(a)} NOT NULL, ${i.identifier($)} ${i.raw(a)} NOT NULL, ${i.identifier(C)} ${i.raw(r)} NOT NULL)`),await z(e,t,{columns:i`${O(t,x)}, ${O(t,$)}`,name:`${n}__btree`,table:n,unique:!1}),await z(e,t,{columns:O(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=[...Ne(j(a,o),A(o.language))],d=i.join([x,$,C].map(u=>i.identifier(u)),i`, `),f=[];for(let u=0;u<s.length;u+=W){const c=i.join(s.slice(u,u+W).map(([l,_])=>i`(${l}, ${r}, ${_})`),i`, `);f.push(i`INSERT INTO ${i.identifier(n)} (${d}) VALUES ${c}`)}await ie(e,t,f)},name:"inverted",runSearch:ve},Ce={ensureCompanion:async(e,t,n)=>{await E(e,t,i`CREATE VIRTUAL TABLE IF NOT EXISTS ${i.identifier(n)} USING fts5(${i.identifier(Ee)}, ${i.identifier($)} UNINDEXED)`),await E(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 E(e,t,i`INSERT INTO ${i.identifier(n)} (${i.identifier("__text__")}, ${i.identifier($)}) VALUES (${j(a,o)}, ${r})`)},name:"fts5",runSearch:De},qe={ensureCompanion:async(e,t,n)=>{const r=t.nativeTextSearch;if(r){await E(e,t,r.createCompanion(n,t.companionTypes.key));for(const a of r.createIndexes(n))await E(e,t,a)}},indexDocument:async(e,t,n,r,a,o)=>{const s=t.nativeTextSearch;s&&(await b(e,t,n,r),await E(e,t,s.indexDocument(n,r,j(a,o))))},name:"native",runSearch:be},I=(e,t)=>e.strategy==="native"&&t.nativeTextSearch!==void 0?qe:t.supportsFts5?Ce:Oe,X=(e,t)=>`${A(e.language).profile}/${I(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)=>v(e,t.name),Qe=async(e,t,n,r,a,o)=>I(a.definition,t).runSearch(e,t,n,r,a,o),Q=200,J=async(e,t,n,r,a)=>{const o=F(r,a),s=I(a,t),d=X(a,t),f=we(await G(e,t,o),d);if(f.finished)return!0;if(f.wipe&&(await E(e,t,i`DELETE FROM ${i.identifier(o)}`),await L(e,t,o,void 0,!1,d)),(await R(e,t,t.tableExists(r))).length===0)return await L(e,t,o,void 0,!0,d),!0;let u=0,c=f.cursor;await te(e,t,n,r,async _=>{u+=1;const w=_._id;typeof w=="string"&&(c=w,await s.indexDocument(e,t,o,w,_,a))},{after:f.cursor,limit:Q});const l=u<Q;return await L(e,t,o,c,l,d),l},K=async(e,t,n)=>{await ee(e,n);for(const[r,,a]of B(t)){const o=F(r,a),s=X(a,n),d=await G(e,n,o);d.profile!==void 0&&d.profile!==s&&(await E(e,n,i`DROP TABLE IF EXISTS ${i.identifier(o)}`),await L(e,n,o,void 0,!1,s)),await I(a,n).ensureCompanion(e,n,o)}},Ge=async(e,t,n)=>{await K(e,t,n);for(const[r,a,o]of B(t))o.staged||await J(e,n,a,r,o)},Ve=async(e,t,n)=>{await K(e,t,n);for(const[r,a,o]of B(t)){let s=!1;for(;!s;)s=await J(e,n,a,r,o)}},Ye=e=>{const{dialect:t,exec:n,schema:r}=e;return async(a,o,s,d)=>{const f=r.tables[a]?.searchIndexes;if(!(!f||f.length===0))for(const u of f){if(_e(d,s,u))continue;const c=F(a,u);if(s){await I(u,t).indexDocument(n,t,c,o,s,u);continue}await b(n,t,c,o)}}};export{Ve as A,Ge as B,Pe as C,We as D,Ye as F,He as N,Fe as T,ke as _,A as a,ze as b,Qe as v};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{renderSql as m}from"@lunora/shard-engine";import{sql as a}from"drizzle-orm";import{sqliteEncode as I,sqliteDecode as p,effectiveColumnKind as S}from"./decodeBigint-DfiI8pkL.mjs";const T=e=>e==="_id"||e==="id"?"id":e,O=e=>a`${a.identifier(T(e))}`,$=(e,t,i)=>{const{params:o,sql:r}=m(t.name,i);return e.all(r,o)},f=(e,t,i)=>{const{params:o,sql:r}=m(t.name,i);return e.run(r,o)},_=async(e,t,i)=>{if(i.length!==0){if(!e.batch){for(const o of i)await f(e,t,o);return}await e.batch(i.map(o=>m(t.name,o)))}},b=async(e,t,i)=>{const o=i.unique?a`UNIQUE `:a``;if(t.name==="mysql"){try{await f(e,t,a`CREATE ${o}INDEX ${a.identifier(i.name)} ON ${a.identifier(i.table)} (${i.columns})`)}catch(r){const n=r;if(n.errno!==1061&&n.code!=="ER_DUP_KEYNAME"&&n.code!==1061)throw r}return}await f(e,t,a`CREATE ${o}INDEX IF NOT EXISTS ${a.identifier(i.name)} ON ${a.identifier(i.table)} (${i.columns})`)},g=I,R=new WeakMap,C=e=>{let t=R.get(e);return t===void 0&&(t=Object.entries(e.shape).map(([i,o])=>[i,S(o)]),R.set(e,t)),t},y=(e,t)=>{const i={};for(const[o,r]of C(e)){const n=t[o];n!==void 0&&(i[o]=p(n,r))}return i._id=t.id,i._creationTime=t._creationTime,i},h=(e,t)=>t?y(e,t):null,L=(e,t)=>{const i=[];for(const o of t){const r=h(e,o);r&&i.push(r)}return i},w=500,M=async(e,t,i,o,r,n={})=>{let d=n.after,s=n.limit,u=!0;for(;u&&(s===void 0||s>0);){const l=s===void 0?w:Math.min(w,s),c=d===void 0?await $(e,t,a`SELECT * FROM ${a.identifier(o)} ORDER BY ${a.identifier("id")} ASC LIMIT ${a.raw(String(l))}`):await $(e,t,a`SELECT * FROM ${a.identifier(o)} WHERE ${a.identifier("id")} > ${d} ORDER BY ${a.identifier("id")} ASC LIMIT ${a.raw(String(l))}`);for(const q of c){const E=h(i,q);E&&await r(E)}d=c.at(-1)?.id,u=c.length===l,s=s===void 0?void 0:s-c.length}};export{w as BACKFILL_BATCH_SIZE,O as columnRefSql,b as createIndexIfNotExists,y as decodeGlobalRow,h as decodeRow,L as decodeRows,M as forEachRowPaged,T as physicalColumn,$ as queryAll,_ as queryBatch,f as queryRun,g as serializeColumnValue};
|
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.59",
|
|
4
4
|
"description": "Internal dialect-parameterized SQL store core for Lunora .global() backends (D1, PlanetScale)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
54
|
-
"@lunora/shard-engine": "1.0.0-alpha.
|
|
53
|
+
"@lunora/errors": "1.0.0-alpha.12",
|
|
54
|
+
"@lunora/shard-engine": "1.0.0-alpha.6",
|
|
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 ht,B as pt,T as mt,a as Et,N as yt,_ as gt,v as bt,D as Nt,b as vt,C as Tt}from"./ctx-db-search-CSETWaAQ.mjs";import{A as Ai}from"./ctx-db-search-CSETWaAQ.mjs";import{aggregateTableName as z,rankTableName as X,hasTrigger as Rt,runRowValidators as Ie,assertFlatPredicate as ze,mergeWhere as q,sortColumnName as Q,resolveRankPartition as Qe,encodePartitionKey as be,decodeCursor as Je,RANK_TIEBREAK as $e,CountRlsUnsupportedError as Xe,normalizeIdStructurally as St,assertValidClientId as At,aggregateSqlFunction as de,softDeleteScope as le,compileWhereSql as ue,normalizeOrderKeys as It,buildSeekWhere as Lt,resolveRelationPredicates as Ze,resolveWith as et,applySelect as tt,encodeCursor as Ot,NotFoundError as Ct,applyOnDelete as kt,ConflictError as fe,normalizeCountArgument as xt,selectIndexForCount as Mt,encodeAggregateKey as V,selectIndexForAggregate as Dt,readAggregateValue as Le,runTriggers as qt,matchesRankStaticWhere as it,selectIndexForGroupBy as Wt,fanOutScalarCounts as jt,matchesStaticWhere as Oe,foldAggregateTally as Bt,coerceAggregateNumber as Ce,NotUniqueError as Ft,throwingScheduler as Ut}from"@lunora/shard-engine";import{sql as e}from"drizzle-orm";import{migrateSearchState as Pt}from"./SEARCH_STATE_TABLE-CtJTyVzp.mjs";import{queryAll as A,queryRun as I,createIndexIfNotExists as xe,decodeRow as Z,serializeColumnValue as H,columnRefSql as x,decodeRows as Ht,forEachRowPaged as nt}from"./decodeGlobalRow-DhFrSrmu.mjs";import{decodeGlobalRow as Li}from"./decodeGlobalRow-DhFrSrmu.mjs";import{effectiveColumnKind as Ne}from"./decodeBigint-DfiI8pkL.mjs";const Kt=(u,w)=>{if(u.size<w)return;const $=u.keys().next().value;$!==void 0&&u.delete($)},Vt=(u,w={})=>{const $=w.maxBatch??50,o=Number.isInteger($)&&$>0?$:50,E=new Map;let l=!1;const c=async(y,T)=>{const R=[...T.keys()];for(let O=0;O<R.length;O+=o){const M=R.slice(O,O+o);try{const j=await u(y,M);for(const K of M){const B=j.get(K);for(const Te of T.get(K)??[])Te.resolve(B)}}catch(j){for(const K of M)for(const B of T.get(K)??[])B.reject(j)}}},v=()=>{l=!1;const y=[...E.entries()];E.clear();for(const[T,R]of y)c(T,R).catch(()=>{})};return{async load(y,T){return new Promise((R,O)=>{let M=E.get(y);M||(M=new Map,E.set(y,M));const j=M.get(T);j?j.push({reject:O,resolve:R}):M.set(T,[{reject:O,resolve:R}]),l||(l=!0,queueMicrotask(v))})}}},Gt=new Set(["_id","id"]),Me=(u,w,$)=>u==="postgres"?e`${w} IS NOT DISTINCT FROM ${$}`:u==="mysql"?e`${w} <=> ${$}`:e`${w} IS ${$}`,Yt=u=>{const w=u.map($=>e`${x($.field)} ${e.raw($.direction==="desc"?"DESC":"ASC")}`);return u.some($=>Gt.has($.field))||w.push(e`${x("id")} ASC`),e.join(w,e`, `)},at=50,De=u=>{const w=[];for(const[$,o]of Object.entries(u.shape)){const E=o._meta?.column;E&&w.push([$,E])}return w},zt=(u,w,$)=>{const o={...w};for(const[E,l]of De(u)){if(l.serverDefault){o[E]=l.serverDefault({auth:$});continue}o[E]===void 0&&(l.defaultFn?o[E]=l.defaultFn():"defaultValue"in l&&(o[E]=l.defaultValue))}return o},ot=(u,w,$,o)=>{for(const[E,l]of De(u)){if(l.serverDefault){E in w&&($[E]=l.serverDefault({auth:o}));continue}l.onUpdateFn&&!(E in w)&&($[E]=l.onUpdateFn())}},Qt=128,Jt=()=>{const u=new Map;return{delete:w=>{u.delete(w)},get:w=>{const $=u.get(w);if($!==void 0)return u.delete(w),u.set(w,$),$},set:(w,$)=>{u.has(w)?u.delete(w):Kt(u,Qt),u.set(w,$)}}},Xt=async(u,w,$,o,E)=>{const l=E.get(o);if(l!==void 0)return l;const c=[];for(const[y,T]of Object.entries($.tables))T.shardMode!==void 0&&T.shardMode.kind!=="global"||c.push(y);const v=await Promise.all(c.map(async y=>({found:(await A(u,w,e`SELECT 1 FROM ${e.identifier(y)} WHERE ${e.identifier("id")} = ${o} LIMIT 1`)).length>0,tableName:y})));for(const y of v)if(y.found)return E.set(o,y.tableName),y.tableName},ee=u=>u==null?null:Number(u),Zt=(u,w)=>w.map($=>{const o={};for(const E of u)o[E]=$[E]??null;return{key:o,value:ee($.value)}}),ei=(u,w,$)=>[...u.partitionBy??[],...u.sortBy.map(o=>o.field),...u.where?Object.keys(u.where):[]].every(o=>w[o]===$[o]),rt=u=>u.length===1?u[0]:e`(${e.join(u,e` AND `)})`,ti=(u,w,$,o,E)=>{const l=[];for(let c=0;c<$.length+1;c+=1){const v=$.slice(0,c).map(R=>Me(u,e`${e.identifier(R)}`,o[R])),y=$[c],T=w.sortBy[c];c<$.length&&y!==void 0&&T!==void 0?v.push(e`${e.identifier(y)} ${e.raw(T.direction==="desc"?">":"<")} ${o[y]}`):v.push(e`${e.identifier($e)} < ${E}`),l.push(rt(v))}return l.length>0?e.join(l,e` OR `):void 0},ii=(u,w,$)=>{if($.length!==w.length)return;const o=[];for(const[E,l]of w.entries()){const c=[];for(let v=0;v<E;v+=1){const y=w[v];y!==void 0&&c.push(Me(u,e`${e.identifier(y.column)}`,$[v]))}c.push(e`${e.identifier(l.column)} ${e.raw(l.direction==="desc"?"<":">")} ${$[E]}`),o.push(rt(c))}return e`(${e.join(o,e` OR `)})`},ni=(u,w)=>{if(u.sortBy.length===0)throw new N("INTERNAL",`rankIndex "${u.name}" requires at least one "sortBy" column for stable pagination`);const $=[{column:"__partition__",direction:"asc"}];for(const[o,E]of u.sortBy.entries())$.push({column:w[o]??Q(o),direction:E.direction});return $.push({column:$e,direction:"asc"}),$},ai=async(u,w,$,o,E)=>{const l=[];for(let T=0;T<E.length;T+=50)l.push(E.slice(T,T+50));const c=await Promise.all(l.map(async T=>{const R=e.join(T.map(O=>e`${O}`),e`, `);return A(u,w,e`SELECT * FROM ${e.identifier(o)} WHERE ${e.identifier("id")} IN (${R})`)})),v=new Map;for(const T of c)for(const R of T)v.set(R.id,R);const y=[];for(const T of E){const R=Z($,v.get(T));R&&y.push(R)}return y},oi=u=>{const w=JSON.stringify(u),$=new TextEncoder().encode(w);let o="";for(const E of $)o+=String.fromCodePoint(E);return btoa(o)},ri=(u,w)=>w.columnType(Ne(u)),si=(u,w)=>{const $=[];for(const[E,l]of Object.entries(u.shape)){if(!l._meta?.column)continue;const c=l._meta.column.notNull&&l.kind!=="optional"?" NOT NULL":"";$.push(e`${e.identifier(E)} ${e.raw(`${ri(l,w)}${c}`)}`)}const o=w.frameworkColumns().map(E=>e`${e.identifier(E.name)} ${e.raw(E.type)}`);return e.join([...o,...$],e`, `)},ci=async(u,w,$,o)=>{const E=l=>{const c=x(l),v=$.shape[l],y=v&&o.indexKeyPrefix?o.indexKeyPrefix(Ne(v)):void 0;return y===void 0?c:e`${c}(${e.raw(String(y))})`};for(const l of $.indexes){const c=e.join(l.fields.map(v=>E(v)),e`, `);await xe(u,o,{columns:c,name:`${w}_${l.name}`,table:w,unique:l.unique??!1})}for(const[l,c]of De($))c.unique&&await xe(u,o,{columns:E(l),name:`${w}_unique_${l}`,table:w,unique:!0})},di=async(u,w,$)=>{for(const[o,E]of Object.entries(w.tables)){if(E.shardMode?.kind!=="global")continue;const l=si(E,$);await I(u,$,e`CREATE TABLE IF NOT EXISTS ${e.identifier(o)} (${l})`),await ci(u,o,E,$)}},li=async(u,w,$)=>{const{integer:o,key:E,real:l}=$.companionTypes;for(const[c,v]of Object.entries(w.tables)){const y=v.aggregateIndexes;if(!(!y||y.length===0))for(const T of y){const R=z(c,T.name);await I(u,$,e`CREATE TABLE IF NOT EXISTS ${e.identifier(R)} (${e.identifier("__key__")} ${e.raw(E)} PRIMARY KEY, ${e.identifier("__value__")} ${e.raw(l)}, ${e.identifier("__count__")} ${e.raw(o)} NOT NULL DEFAULT 0)`),$.name==="sqlite"&&((await A(u,$,e`PRAGMA table_info(${e.identifier(R)})`)).some(O=>O.name==="__count__")||await I(u,$,e`ALTER TABLE ${e.identifier(R)} ADD COLUMN ${e.identifier("__count__")} ${e.raw(o)} NOT NULL DEFAULT 0`))}}},ke=(u,w,$,o)=>{const E=u.name==="mysql"&&o?e`${e.identifier(w)}(191)`:e`${e.identifier(w)}`;return e`${E} ${e.raw($)}`},ui=(u,w,$)=>{const o=[ke(u,"__partition__","ASC",!0)];for(const[E,l]of w.sortBy.entries()){const c=$.shape[l.field],v=c!==void 0&&u.indexKeyPrefix?.(Ne(c))!==void 0;o.push(ke(u,Q(E),l.direction==="desc"?"DESC":"ASC",v))}return o.push(ke(u,"__id__","ASC",!0)),o},fi=(u,w,$)=>w.sortBy.map((o,E)=>{const l=$.shape[o.field],c=u.columnType(l?Ne(l):void 0);return e`${e.identifier(Q(E))} ${e.raw(c)}`}),$i=async(u,w,$)=>{const{key:o}=$.companionTypes;for(const[E,l]of Object.entries(w.tables)){const c=l.rankIndexes;if(!(!c||c.length===0))for(const v of c){const y=X(E,v.name),T=fi($,v,l),R=T.length>0?e`, ${e.join(T,e`, `)}`:e``;await I(u,$,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 O=ui($,v,l),M=`${E}__rank_${v.name}__btree`;await xe(u,$,{columns:e.join(O,e`, `),name:M,table:y,unique:!1})}}},ve="__cdc_log",wi=async(u,w)=>{const{autoincrementPrimaryKey:$,key:o,real:E,text:l}=w.companionTypes;await I(u,w,e`CREATE TABLE IF NOT EXISTS ${e.identifier(ve)} (${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(l)})`)},_i=async(u,w,$,o,E,l,c)=>{await I(u,c,e`INSERT INTO ${e.identifier(ve)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${w}, ${$}, ${o}, ${E}, ${l===void 0?null:JSON.stringify(l)})`)},Ni=async(u,w,$)=>{const o=w.sinceSeq??0,E=Math.max(1,Math.min(w.limit??1e3,1e4)),l=(await A(u,$,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(ve)} WHERE seq > ${o} ORDER BY seq ASC LIMIT ${e.raw(String(E))}`)).map(c=>{const{doc:v}=c,y={id:String(c.id),op:String(c.op),seq:Number(c.seq),table:String(c.table),ts:Number(c.ts)};return typeof v=="string"?{...y,doc:JSON.parse(v)}:y});return{changes:l,cursor:l.at(-1)?.seq??o}},vi=async(u,w,$)=>{await I(u,$,e`DELETE FROM ${e.identifier(ve)} WHERE ${e.identifier("seq")} <= ${w}`)},Ti=u=>{const{crossShardCounter:w,crossShardReader:$,exec:o,maxRelationKeys:E,schema:l}=u,{dialect:c}=u,{isUniqueViolation:v}=c,y={fieldRef:x,serialize:H,...c.name==="mysql"?{likeContains:(t,i)=>e`${t} LIKE CONCAT('%', ${i}, '%') ESCAPE '\\\\'`}:{}},T=(t,i)=>Me(c.name,t,i),R=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)}`,r=d=>c.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(d)}`:e`${e.identifier(d)}`,f=e.join(Object.entries(t.set(a,r)).map(([d,h])=>e`${e.identifier(d)} = ${h}`),e`, `),_=c.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}) ${_}`},O=u.clock??(()=>Date.now()),M=u.idGenerator??(()=>crypto.randomUUID()),j=u.cdc??!1,K=u.auth??{identity:null,userId:null},B=async(t,i,n,a)=>{j&&await _i(o,O(),t,i,n,a,c)},Te=u.scheduler??Ut,Re=Jt();let we=0,Se;const F=async()=>(Se??=(async()=>{await di(o,l,c),await li(o,l,c),await $i(o,l,c),await Pt(o,c),await pt(o,l,c),j&&await wi(o,c)})().catch(t=>{throw Se=void 0,t}),Se),te=async(t,i)=>{await F();const n=await Xt(o,c,l,t,Re);if(!(i!==void 0&&n!==i))return n},ie=new Map,qe=async(t,i)=>{const n=z(t,i);return(await A(o,c,c.tableExists(n))).length>0},_e=async(t,i)=>{const n=`${t}::${i.name}`,a=ie.get(n);if(a!==void 0)return a;if(!await qe(t,i.name))return ie.set(n,!1),!1;const r=l.tables[t];if(!r)return ie.set(n,!1),!1;const f=i.by??[],_=new Map;await nt(o,c,r,t,h=>{if(i.where&&!Oe(h,i.where))return;const s=V(f,h);Bt(_,s,i,h)});const d=z(t,i.name);await I(o,c,e`DELETE FROM ${e.identifier(d)}`);for(const[h,s]of _)await I(o,c,e`INSERT INTO ${e.identifier(d)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${h}, ${s.value}, ${s.count})`);return ie.set(n,!0),!0},st=async(t,i,n)=>{const a=de(i.op),r=i.field??"",f=[];for(const h of i.by??[]){const s=H(n[h]??null);f.push(s===null?e`${x(h)} IS NULL`:e`${x(h)} = ${s}`)}for(const[h,s]of Object.entries(i.where??{})){const p=s!==null&&typeof s=="object"&&!Array.isArray(s)?s.eq:s,m=H(p);f.push(m===null?e`${x(h)} IS NULL`:e`${x(h)} = ${m}`)}const _=e`SELECT ${e.raw(a)}(${x(r)}) AS value FROM ${e.identifier(t)}`,d=await A(o,c,f.length>0?e`${_} WHERE ${e.join(f,e` AND `)}`:_);return ee(d[0]?.value)},We=async(t,i)=>{await I(o,c,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${i} AND ${e.identifier("__count__")} <= 0`)},ct=async(t,i,n,a)=>{const r=z(t,i.name),{op:f}=i,_=i.field??"",d=n&&(!i.where||Oe(n,i.where))?n:void 0,h=a&&(!i.where||Oe(a,i.where))?a:void 0;if(!(!d&&!h)){if(f==="count"){const s=new Set;for(const[p,m]of[[d,-1],[h,1]]){if(!p)continue;const g=V(i.by??[],p);s.add(g),await I(o,c,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(b,S)=>({__count__:e`${S("__count__")} + ${b("__count__")}`,__value__:e`${S("__value__")} + ${b("__value__")}`}),table:r,values:[g,m,m]}))}for(const p of s)await We(r,p);return}if(f==="sum"||f==="avg"){const s=new Set;for(const[p,m]of[[d,-1],[h,1]]){if(!p)continue;const g=Ce(p[_]);if(g===void 0)continue;const b=V(i.by??[],p);s.add(b),await I(o,c,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(S,k)=>({__count__:e`${k("__count__")} + ${S("__count__")}`,__value__:e`COALESCE(${k("__value__")}, 0) + ${S("__value__")}`}),table:r,values:[b,m*g,m]}))}for(const p of s)await We(r,p);return}if(d){const s=V(i.by??[],d),p=Ce(d[_]),m=(await A(o,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${s}`))[0],g=ee(m?.value),b=(m?.count??0)-1;if(b<=0)await I(o,c,e`DELETE FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${s}`);else if(m&&p!==void 0&&g!==null&&p===g){const S=await st(t,i,d);await I(o,c,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__value__")} = ${S}, ${e.identifier("__count__")} = ${b} WHERE ${e.identifier("__key__")} = ${s}`)}else await I(o,c,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${s}`)}if(h){const s=V(i.by??[],h),p=Ce(h[_]);if(p===void 0)await I(o,c,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(m,g)=>({__count__:e`${g("__count__")} + 1`}),table:r,values:[s,null,1]}));else{const m=f==="min"?"MIN":"MAX";await I(o,c,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:r,values:[s,p,1]}))}}}},he=async t=>{const i=l.tables[t]?.aggregateIndexes;if(!(!i||i.length===0))for(const n of i)await _e(t,n)},ne=async(t,i,n)=>{const a=l.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const r of a){const f=`${t}::${r.name}`;(ie.get(f)??await qe(t,r.name))&&await ct(t,r,i,n)}},ae=new Map,je=async(t,i)=>{const n=X(t,i);return(await A(o,c,c.tableExists(n))).length>0},Ae=async(t,i)=>{const n=`${t}::rank::${i.name}`,a=ae.get(n);if(a!==void 0)return a;if(!await je(t,i.name))return ae.set(n,!1),!1;const r=l.tables[t];if(!r)return ae.set(n,!1),!1;const f=X(t,i.name);await I(o,c,e`DELETE FROM ${e.identifier(f)}`);const _=i.sortBy.map((s,p)=>Q(p)),d=e.join(["__id__","__partition__",..._].map(s=>e`${e.identifier(s)}`),e`, `),h=[];await nt(o,c,r,t,s=>{if(i.where&&!it(s,i.where))return;const p=be(i.partitionBy??[],s),m=i.sortBy.map(g=>H(s[g.field]??null));h.push([s._id,p,...m])});for(const s of h){const p=e.join(s.map(m=>e`${m}`),e`, `);await I(o,c,e`INSERT INTO ${e.identifier(f)} (${d}) VALUES (${p})`)}return ae.set(n,!0),!0},pe=async t=>{const i=l.tables[t]?.rankIndexes;if(!(!i||i.length===0))for(const n of i)await Ae(t,n)},J=async(t,i,n,a)=>{const r=l.tables[t],f=r?.rankIndexes;if(!f||f.length===0)return;const _=r?.softDeleteMode?.field,d=_===void 0||a===void 0?void 0:a[_],h=d!=null;for(const s of f){if(n!==void 0&&a!==void 0&&ei(s,n,a))continue;const p=`${t}::rank::${s.name}`;if(!(ae.get(p)??await je(t,s.name)))continue;const m=X(t,s.name);if(n&&await I(o,c,e`DELETE FROM ${e.identifier(m)} WHERE ${e.identifier("__id__")} = ${i}`),a&&!h){if(s.where&&!it(a,s.where))continue;const g=s.sortBy.map((L,G)=>Q(G)),b=e.join(["__id__","__partition__",...g].map(L=>e`${e.identifier(L)}`),e`, `),S=be(s.partitionBy??[],a),k=s.sortBy.map(L=>H(a[L.field]??null)),D=e.join([i,S,...k].map(L=>e`${L}`),e`, `);await I(o,c,e`INSERT INTO ${e.identifier(m)} (${b}) VALUES (${D})`)}}},oe=ht({dialect:c,exec:o,schema:l}),Be=new Set;for(const[t,i]of Object.entries(l.tables))for(const n of Object.values(i.triggerMap??{}))Be.add(`${t} ${n.timing} ${n.op}`);const U=(t,i,n)=>Be.has(`${t} ${i} ${n}`);let Fe;const P=async(t,i,n)=>{if(we+=1,we>at)throw we-=1,new fe(`trigger recursion exceeded ${String(at)} levels on "${n.table}" — check for a self-triggering write`,"trigger");try{await qt({ctx:Fe,event:n,op:i,schema:l,tableName:n.table,timing:t})}finally{we-=1}},dt=async(t,i)=>{try{await I(o,c,i)}catch(n){throw v(n)?new fe(`unique constraint violation on "${t}"`,"unique"):n}},me=async(t,i)=>(await A(o,c,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${i}`))[0],Ee=async(t,i,n,a)=>{if(a===void 0)return;const r=e.join(Object.keys(a).map(d=>T(e`${e.identifier(d)}`,a[d])),e` AND `),f=i==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${n} WHERE ${r}`:e`DELETE FROM ${e.identifier(t)} WHERE ${r}`,_=()=>{throw new fe(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")};try{if(c.supportsReturning)(await A(o,c,e`${f} RETURNING ${e.identifier("id")}`)).length===0&&_();else{const d=await I(o,c,f);(c.affectedRows?c.affectedRows(d??{rowsAffected:0}):0)===0&&_()}}catch(d){throw v(d)?new fe(`unique constraint violation on "${t}"`,"unique"):d}},lt=(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))]}},ut=async(t,i,n,a)=>{const r=Wt(i,n.op,n.field,a.by,a.where);if(!r||!await _e(t,r.index))return;const f=z(t,r.index.name),_=Object.keys(r.partial);if(_.length===(r.index.by??[]).length&&_.length>0){const d=V(r.index.by??[],r.partial),h=await A(o,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(f)} WHERE ${e.identifier("__key__")} = ${d}`);if(h.length===0)return[];const s=h[0];return[{key:{...r.partial},value:Le(n.op,{count:s.count,value:ee(s.value)})}]}return _.length>0?void 0:(await A(o,c,e`SELECT ${e.identifier("__key__")} AS key, ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(f)}`)).map(d=>{const h=d;return{key:JSON.parse(h.key),value:Le(n.op,{count:h.count,value:ee(h.value)})}})},Ue=t=>{const i=l.tables[t]?.shardMode?.kind;return i==="shardBy"||i==="root"},Pe=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`)},He=(t,i)=>Ue(t)?$?$(t,i):Pe(t):W.findMany(t,i),ye=(t,i,n)=>Ze(t,{fetcher:He,maxRelationKeys:E,relationBaseWhere:n,schema:l,tableName:i}),ft=Vt(async(t,i)=>{const n=e.join(i.map(f=>e`${f}`),e`, `),a=await A(o,c,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} IN (${n})`),r=new Map;for(const f of a){const{id:_}=f;typeof _=="string"&&r.set(_,f)}return r}),W={async aggregate(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);if(await F(),de(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=le(n.softDeleteMode,void 0),r=q(q(i.baseWhere,i.where),a),f=await ye(r,t,i.relationBaseWhere),_=f!==r;if(n.aggregateIndexes&&!i.baseWhere&&!_&&!a){const m=Dt(n.aggregateIndexes,i.op,i.field,i.where);if(m&&await _e(t,m.index)){const g=V(m.index.by??[],m.key),b=z(t,m.index.name),S=(await A(o,c,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(b)} WHERE ${e.identifier("__key__")} = ${g}`))[0];return Le(i.op,S===void 0?void 0:{count:S.count,value:ee(S.value)})}}const d=ue(f,y),h=e.raw(de(i.op)),s=e`SELECT ${h}(${x(i.field)}) AS value FROM ${e.identifier(t)}`,p=(await A(o,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 F();const a=xt(i);if(a.restrictsCounts)throw new Xe(t);const r=le(n.softDeleteMode,void 0),f=q(q(a.baseWhere,a.where),r),_=await ye(f,t,a.relationBaseWhere),d=_!==f;if(n.aggregateIndexes&&!a.baseWhere&&!d&&!r){const m=Mt(n.aggregateIndexes,a.where);if(m&&await _e(t,m.index)){const g=V(m.index.by??[],m.key),b=z(t,m.index.name),S=await A(o,c,e`SELECT ${e.identifier("__value__")} AS value FROM ${e.identifier(b)} WHERE ${e.identifier("__key__")} = ${g}`);return Number(S[0]?.value??0)}}const h=ue(_,y),s=e`SELECT COUNT(*) AS count FROM ${e.identifier(t)}`,p=await A(o,c,h?e`${s} WHERE ${h}`:s);return Number(p[0]?.count??0)},async delete(t,i,n){const a=await te(t,i);if(!a)return;const r=l.tables[a];if(!r)return;const f=await me(a,t),_=Z(r,f),d=n?.hard===!0,h=!d&&r.softDeleteMode?r.softDeleteMode.field:void 0;if(!(h&&(!_||_[h]!==null&&_[h]!==void 0))){if(U(a,"before","delete")&&await P("before","delete",{id:t,op:"delete",previous:_??void 0,table:a}),await kt({deletedId:t,deletedReference:s=>_?.[s],findHolders:async(s,p,m)=>{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 W.findMany(s,{includeDeleted:d,where:{[p]:m}})).page},onCascade:(s,p)=>W.delete(p,void 0,n),onRestrict:s=>{throw new fe(s,"restrict")},onSetNull:(s,p,m)=>W.patch(p,{[m]:null}),schema:l,tableName:a}),await he(a),await pe(a),h&&_){const s={..._,[h]:O()},p=e.join(Object.keys(r.shape).map(m=>e`${e.identifier(m)} = ${H(s[m]??null)}`),e`, `);await Ee(a,"UPDATE",p,f),await ne(a,_,s),await J(a,t,_,void 0),await oe(a,t,s,_),await B(a,t,"update",s),U(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:_,table:a});return}await Ee(a,"DELETE",void 0,f),Re.delete(t),await ne(a,_??void 0,void 0),await J(a,t,_??void 0,void 0),await oe(a,t,void 0),await B(a,t,"delete"),U(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 Ct(`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 F();const a=It(i.orderBy),r=i.cursor?Lt(a,Je(i.cursor)):void 0,f=He,_=async(L,G,ge,re)=>{if(Ue(L))return w?jt(w,L,G,ge,re):Pe(L);const Y=l.tables[L];if(!Y)throw new N("INTERNAL",`unknown table: ${L}`);const C=le(Y.softDeleteMode,void 0),se={[G]:{in:ge}},$t=q(q(se,re),C),wt=await ye($t,L,void 0),Ke=ue(wt,y),Ve=x(G);let ce=e`SELECT ${Ve} AS __fk__, COUNT(*) AS count FROM ${e.identifier(L)}`;Ke&&(ce=e`${ce} WHERE ${Ke}`),ce=e`${ce} GROUP BY ${Ve}`;const _t=await A(o,c,ce),Ge=new Map;for(const Ye of _t)Ge.set(Ye.__fk__,Number(Ye.count??0));return Ge};let d=q(i.baseWhere,i.where);d=q(d,le(n.softDeleteMode,i.includeDeleted)),d=await Ze(d,{fetcher:f,maxRelationKeys:E,relationBaseWhere:i.relationBaseWhere,schema:l,tableName:t}),r&&(d=d?{AND:[d,r]}:r);const h=ue(d,y),s=Yt(a);let p=e`SELECT * FROM ${e.identifier(t)}`;h&&(p=e`${p} WHERE ${h}`),p=e`${p} ORDER BY ${s}`;const m=typeof i.limit=="number"?Math.max(0,Math.floor(i.limit)):void 0;m!==void 0&&(p=e`${p} LIMIT ${e.raw(String(m+1))}`);const g=await A(o,c,p),b=Ht(n,g);if(m===void 0)return i.with&&await et({fetcher:f,groupedCounter:_,parents:b,schema:l,tableName:t,with:i.with}),{continueCursor:null,isDone:!0,page:tt(b,i.select,i.with)};const S=b.length>m,k=S?b.slice(0,m):b,D=k.at(-1);return i.with&&await et({fetcher:f,groupedCounter:_,parents:k,schema:l,tableName:t,with:i.with}),{continueCursor:S&&D?Ot(D,a):null,isDone:!S,page:tt(k,i.select,i.with)}},async get(t,i){const n=await te(t,i);if(!n)return null;const a=l.tables[n];return a?Z(a,await ft.load(n,t)):null},async groupBy(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await F();const a=i.agg??{op:"count"};if(de(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=le(n.softDeleteMode,void 0),f=q(q(i.baseWhere,i.where),r),_=await ye(f,t,i.relationBaseWhere),d=_!==f;if(n.aggregateIndexes&&!i.baseWhere&&!d&&!r){const b=await ut(t,n.aggregateIndexes,a,i);if(b!==void 0)return b}const h=ue(_,y),s=i.by.map(b=>e`${x(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(de(a.op))}(${x(a.field)}) AS value`)}const p=e.join(i.by.map(b=>x(b)),e`, `);let m=e`SELECT ${e.join(s,e`, `)} FROM ${e.identifier(t)}`;h&&(m=e`${m} WHERE ${h}`),m=e`${m} GROUP BY ${p}`;const g=await A(o,c,m);return Zt(i.by,g)},async insert(t,i,n){const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);await F();const r=zt(a,i,K);Ie(a,r);let f,_=!0;n?.clientId!==void 0?(At(n.clientId),f=n.clientId):n?.allowExplicitId&&typeof r._id=="string"?f=r._id:(f=M(),_=!1);const d=n?.allowExplicitId&&typeof r._creationTime=="number"?r._creationTime:O(),h={...r,_creationTime:d,_id:f};U(t,"before","insert")&&await P("before","insert",{doc:{...h},id:f,op:"insert",table:t}),await he(t),await pe(t);const{columns:s,values:p}=lt(a,f,d,r),m=e.join(s.map(b=>e`${e.identifier(b)}`),e`, `),g=e.join(p.map(b=>e`${b}`),e`, `);return await dt(t,e`INSERT INTO ${e.identifier(t)} (${m}) VALUES (${g})`),_&&Re.set(f,t),await ne(t,void 0,h),await J(t,f,void 0,h),await oe(t,f,h),await B(t,f,"insert",h),U(t,"after","insert")&&await P("after","insert",{doc:h,id:f,op:"insert",table:t}),f},normalizeId(t,i){return St(l,t,i)},async patch(t,i,n){const a=await te(t,n);if(!a)throw new N("INTERNAL",`document not found: ${t}`);const r=l.tables[a];if(!r)throw new N("INTERNAL",`document not found: ${t}`);const f=await me(a,t),_=Z(r,f);if(!_)throw new N("INTERNAL",`document not found: ${t}`);const d={..._,...i,_id:t};ot(r,i,d,K),Ie(r,d,!0),U(a,"before","update")&&await P("before","update",{doc:{...d},id:t,op:"update",previous:_,table:a}),await he(a),await pe(a);const h=Object.keys(r.shape),s=e.join(h.map(p=>e`${e.identifier(p)} = ${H(d[p]??null)}`),e`, `);await Ee(a,"UPDATE",s,f),await ne(a,_,d),await J(a,t,_,d),await oe(a,t,d,_),await B(a,t,"update",d),U(a,"after","update")&&await P("after","update",{doc:d,id:t,op:"update",previous:_,table:a})},async restore(t,i){const n=await te(t,i);if(!n)throw new N("INTERNAL",`document not found: ${t}`);const a=l.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 me(n,t),_=f?.[r]!==null&&f?.[r]!==void 0;if(await W.patch(t,{[r]:null},i),_){const d=Z(a,f);d!==null&&await J(n,t,void 0,{...d,[r]: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=[],r=d=>a.every(h=>h(d)),f=async(d,h)=>{await F();const s=a.length>0,p=await bt(o,c,i,t,d,Nt(s?void 0:h));if(!s)return h===void 0&&vt(p),p;const m=p.filter(g=>r(g));return h===void 0?m:m.slice(0,h)},_=d=>{const h={async*[Symbol.asyncIterator](){if(!d)throw new N("INTERNAL",n);yield*await f(d,void 0)},async collect(){if(!d)throw new N("INTERNAL",n);return f(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 f(d,1))[0]??null},order(){return h},async paginate(s){if(!d)throw new N("INTERNAL",n);const p=yt(s);return gt(await f(d,Tt(p)),p)},async take(s){if(!d)throw new N("INTERNAL",n);return f(d,s)},async unique(){if(!d)throw new N("INTERNAL",n);const s=await f(d,2);if(s.length>1)throw new Ft(`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 m=(i.searchIndexes??[]).find(b=>b.name===s);if(!m)throw new N("INTERNAL",`unknown search index "${s}" on table "${t}"`);const g={definition:m,field:m.field,filters:[],hasQuery:!1,indexName:s,query:""};if(p(mt(g,t,Et(m.language))),!g.hasQuery)throw new N("INTERNAL",`search index "${s}" on table "${t}" requires a .search(field, query) call`);return _(g)}};return h};return _(void 0)},async rank(t,i,n){const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);const r=a.rankIndexes?.find(D=>D.name===i);if(!r)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(n.restrictsCounts)throw new Xe(t);if(await F(),!await Ae(t,r))return null;const f=typeof n.row=="string"?n.row:n.row._id;if(!f)return null;const _=X(t,r.name),d=r.sortBy.map((D,L)=>Q(L)),h=e.join([e`${e.identifier("__partition__")}`,...d.map(D=>e`${e.identifier(D)}`)],e`, `),s=(await A(o,c,e`SELECT ${h} FROM ${e.identifier(_)} WHERE ${e.identifier("__id__")} = ${f}`))[0];if(!s)return null;const p=s.__partition__,m=q(n.baseWhere,n.where);ze(m,l,t,"rank");const g=Qe(r,m);if(g&&be(r.partitionBy??[],g)!==p)return null;const b=ti(c.name,r,d,s,f),S=await A(o,c,e`SELECT COUNT(*) AS c FROM ${e.identifier(_)} WHERE ${e.identifier("__partition__")} = ${p}${b?e` AND (${b})`:e``}`),k=await A(o,c,e`SELECT COUNT(*) AS c FROM ${e.identifier(_)} WHERE ${e.identifier("__partition__")} = ${p}`);return{position:Number(S[0]?.c??0)+1,total:Number(k[0]?.c??0)}},async rankPage(t,i,n={}){ze(q(n.baseWhere,n.where),l,t,"rankPage");const a=l.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 F(),!await Ae(t,r))return{continueCursor:null,isDone:!0,page:[]};const f=X(t,r.name),_=r.sortBy.map((C,se)=>Q(se)),d=Math.max(1,Math.min(1e3,Math.floor(n.take??100))),h=q(n.baseWhere,n.where),s=Qe(r,h),p=ni(r,_),m=e.join(p.map(C=>e`${e.identifier(C.column)} ${e.raw(C.direction==="desc"?"DESC":"ASC")}`),e`, `),g=[];if(s&&g.push(e`${e.identifier("__partition__")} = ${be(r.partitionBy??[],s)}`),n.cursor){const C=ii(c.name,p,Je(n.cursor));C!==void 0&&g.push(C)}const b=e.join([e`${e.identifier($e)}`,e`${e.identifier("__partition__")}`,..._.map(C=>e`${e.identifier(C)}`)],e`, `);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(d+1))}`;const k=await A(o,c,S),D=k.length>d,L=D?k.slice(0,d):k,G=L.map(C=>C[$e]),ge=await ai(o,c,a,t,G);let re=null;const Y=L.at(-1);if(D&&Y!==void 0){const C=[Y.__partition__,..._.map(se=>Y[se]),Y[$e]];re=oi(C)}return{continueCursor:re,isDone:!D,page:ge}},async replace(t,i,n,a){const r=await te(t,n);if(!r)throw new N("INTERNAL",`document not found: ${t}`);const f=l.tables[r];if(!f)throw new N("INTERNAL",`document not found: ${t}`);const _=await me(r,t);if(_===void 0)throw new N("INTERNAL",`document not found: ${t}`);const d=Rt(l,r,"update")||(f.aggregateIndexes??[]).length>0||(f.rankIndexes??[]).length>0?Z(f,_)??void 0:void 0,h=a?.allowExplicitId&&typeof i._creationTime=="number"?i._creationTime:O(),s={...i,_creationTime:h,_id:t};ot(f,i,s,K),Ie(f,s),U(r,"before","update")&&await P("before","update",{doc:{...s},id:t,op:"update",previous:d,table:r}),await he(r),await pe(r);const p=Object.keys(f.shape),m=e.join([e`${e.identifier("_creationTime")} = ${h}`,...p.map(g=>e`${e.identifier(g)} = ${H(s[g]??null)}`)],e`, `);await Ee(r,"UPDATE",m,_),await ne(r,d,s),await J(r,t,d,s),await oe(r,t,s,d),await B(r,t,"update",s),U(r,"after","update")&&await P("after","update",{doc:s,id:t,op:"update",previous:d,table:r})}};return Fe={db:W,scheduler:Te},W};export{Ai as backfillSqlSearchIndexes,Ti as createSqlCtxDb,Li as decodeGlobalRow,Ni as readSqlCdcChanges,li as runSqlAggregateMigrations,wi as runSqlCdcMigration,di as runSqlGlobalTableMigrations,$i as runSqlRankMigrations,pt as runSqlSearchMigrations,vi as trimSqlCdcChanges};
|
|
@@ -1 +0,0 @@
|
|
|
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-CtJTyVzp.mjs";import{queryRun as w,columnRefSql as y,serializeColumnValue as q,decodeRows as U,queryAll as v,createIndexIfNotExists as z,forEachRowPaged as ie}from"./decodeGlobalRow-DhFrSrmu.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),M=(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&&M(e,n.field)===M(t,n.field),j=(e,t)=>Y(Se(M(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)} = ${q(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)} = ${q(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)} = ${q(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};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{renderSql as w}from"@lunora/shard-engine";import{sql as o}from"drizzle-orm";import{sqliteEncode as C,sqliteDecode as S,effectiveColumnKind as q}from"./decodeBigint-DfiI8pkL.mjs";const T=e=>e==="_id"||e==="id"?"id":e,O=e=>o`${o.identifier(T(e))}`,E=(e,i,t)=>{const{params:r,sql:a}=w(i.name,t);return e.all(a,r)},u=(e,i,t)=>{const{params:r,sql:a}=w(i.name,t);return e.run(a,r)},_=async(e,i,t)=>{const r=t.unique?o`UNIQUE `:o``;if(i.name==="mysql"){try{await u(e,i,o`CREATE ${r}INDEX ${o.identifier(t.name)} ON ${o.identifier(t.table)} (${t.columns})`)}catch(a){const n=a;if(n.errno!==1061&&n.code!=="ER_DUP_KEYNAME"&&n.code!==1061)throw a}return}await u(e,i,o`CREATE ${r}INDEX IF NOT EXISTS ${o.identifier(t.name)} ON ${o.identifier(t.table)} (${t.columns})`)},g=C,$=new WeakMap,h=e=>{let i=$.get(e);return i===void 0&&(i=Object.entries(e.shape).map(([t,r])=>[t,q(r)]),$.set(e,i)),i},v=(e,i)=>{const t={};for(const[r,a]of h(e)){const n=i[r];n!==void 0&&(t[r]=S(n,a))}return t._id=i.id,t._creationTime=i._creationTime,t},I=(e,i)=>i?v(e,i):null,M=(e,i)=>{const t=[];for(const r of i){const a=I(e,r);a&&t.push(a)}return t},R=500,D=async(e,i,t,r,a,n={})=>{let c=n.after,s=n.limit,f=!0;for(;f&&(s===void 0||s>0);){const l=s===void 0?R:Math.min(R,s),d=c===void 0?await E(e,i,o`SELECT * FROM ${o.identifier(r)} ORDER BY ${o.identifier("id")} ASC LIMIT ${o.raw(String(l))}`):await E(e,i,o`SELECT * FROM ${o.identifier(r)} WHERE ${o.identifier("id")} > ${c} ORDER BY ${o.identifier("id")} ASC LIMIT ${o.raw(String(l))}`);for(const p of d){const m=I(t,p);m&&await a(m)}c=d.at(-1)?.id,f=d.length===l,s=s===void 0?void 0:s-d.length}};export{R as BACKFILL_BATCH_SIZE,O as columnRefSql,_ as createIndexIfNotExists,v as decodeGlobalRow,I as decodeRow,M as decodeRows,D as forEachRowPaged,T as physicalColumn,E as queryAll,u as queryRun,g as serializeColumnValue};
|