@lunora/sql-store 1.0.0-alpha.79 → 1.0.0-alpha.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +29 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/SEARCH_STATE_TABLE-DA3LgCT0.mjs +1 -0
- package/dist/packem_shared/backfillSqlSearchIndexes-BRlUTReN.mjs +1 -0
- package/dist/packem_shared/createSqlCtxDb-CRX3OS05.mjs +1 -0
- package/dist/packem_shared/ctx-db-search-Cl6zlJ11.mjs +1 -0
- package/dist/packem_shared/decodeBigint-B4wY6fcF.mjs +1 -0
- package/dist/packem_shared/decodeGlobalRow-BKIjk_Zk.mjs +1 -0
- package/package.json +3 -3
- package/dist/packem_shared/SEARCH_STATE_TABLE-Bw9dhHy2.mjs +0 -1
- package/dist/packem_shared/backfillSqlSearchIndexes-cNjcY2yu.mjs +0 -1
- package/dist/packem_shared/createSqlCtxDb-BCC5tX8G.mjs +0 -1
- package/dist/packem_shared/ctx-db-search-Cbt6DjpO.mjs +0 -1
- package/dist/packem_shared/decodeBigint-DrEQib7C.mjs +0 -1
- package/dist/packem_shared/decodeGlobalRow-BwzH1RLd.mjs +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -221,4 +221,32 @@ declare const effectiveColumnKind: (validator: ValidatorLike) => string | undefi
|
|
|
221
221
|
* - everything else (string/number/date/timestamp/id/literal): verbatim.
|
|
222
222
|
*/
|
|
223
223
|
declare const sqliteDecode: (raw: unknown, kind: string | undefined) => unknown;
|
|
224
|
-
export { SEARCH_STATE_TABLE,
|
|
224
|
+
export { SEARCH_STATE_TABLE,
|
|
225
|
+
/**
|
|
226
|
+
* `@lunora/sql-store` — the internal, dialect-parameterized SQL store core
|
|
227
|
+
* shared by Lunora's `.global()` table backends.
|
|
228
|
+
*
|
|
229
|
+
* One ORM implementation (`createSqlCtxDb`) drives any SQL engine through a
|
|
230
|
+
* `SqlDialect`: SQLite via `@lunora/d1`, and Postgres/MySQL (PlanetScale, Neon,
|
|
231
|
+
* any Hyperdrive-reachable database) via `@lunora/hyperdrive`. Reactivity is
|
|
232
|
+
* unaffected — the writer is injected as `globalDb` into `createShardCtxDb`,
|
|
233
|
+
* whose `broadcast` hook drives live queries regardless of engine.
|
|
234
|
+
*
|
|
235
|
+
* This package is internal: consumers depend on `@lunora/d1` or
|
|
236
|
+
* `@lunora/hyperdrive`, which assemble the concrete dialect and wrap the core.
|
|
237
|
+
*/
|
|
238
|
+
type SqlCtxDbOptions,
|
|
239
|
+
/**
|
|
240
|
+
* `@lunora/sql-store` — the internal, dialect-parameterized SQL store core
|
|
241
|
+
* shared by Lunora's `.global()` table backends.
|
|
242
|
+
*
|
|
243
|
+
* One ORM implementation (`createSqlCtxDb`) drives any SQL engine through a
|
|
244
|
+
* `SqlDialect`: SQLite via `@lunora/d1`, and Postgres/MySQL (PlanetScale, Neon,
|
|
245
|
+
* any Hyperdrive-reachable database) via `@lunora/hyperdrive`. Reactivity is
|
|
246
|
+
* unaffected — the writer is injected as `globalDb` into `createShardCtxDb`,
|
|
247
|
+
* whose `broadcast` hook drives live queries regardless of engine.
|
|
248
|
+
*
|
|
249
|
+
* This package is internal: consumers depend on `@lunora/d1` or
|
|
250
|
+
* `@lunora/hyperdrive`, which assemble the concrete dialect and wrap the core.
|
|
251
|
+
*/
|
|
252
|
+
type SqlCtxExec, type SqlDialect, type SqlRunResult, backfillSqlSearchIndexes, createSqlCtxDb, decodeBigint, decodeGlobalRow, effectiveColumnKind, migrateSearchState, readSqlCdcChanges, runSqlAggregateMigrations, runSqlCdcMigration, runSqlGlobalTableMigrations, runSqlRankMigrations, runSqlSearchMigrations, sqliteDecode, sqliteEncode, trimSqlCdcChanges, tryJsonParse };
|
package/dist/index.d.ts
CHANGED
|
@@ -221,4 +221,32 @@ declare const effectiveColumnKind: (validator: ValidatorLike) => string | undefi
|
|
|
221
221
|
* - everything else (string/number/date/timestamp/id/literal): verbatim.
|
|
222
222
|
*/
|
|
223
223
|
declare const sqliteDecode: (raw: unknown, kind: string | undefined) => unknown;
|
|
224
|
-
export { SEARCH_STATE_TABLE,
|
|
224
|
+
export { SEARCH_STATE_TABLE,
|
|
225
|
+
/**
|
|
226
|
+
* `@lunora/sql-store` — the internal, dialect-parameterized SQL store core
|
|
227
|
+
* shared by Lunora's `.global()` table backends.
|
|
228
|
+
*
|
|
229
|
+
* One ORM implementation (`createSqlCtxDb`) drives any SQL engine through a
|
|
230
|
+
* `SqlDialect`: SQLite via `@lunora/d1`, and Postgres/MySQL (PlanetScale, Neon,
|
|
231
|
+
* any Hyperdrive-reachable database) via `@lunora/hyperdrive`. Reactivity is
|
|
232
|
+
* unaffected — the writer is injected as `globalDb` into `createShardCtxDb`,
|
|
233
|
+
* whose `broadcast` hook drives live queries regardless of engine.
|
|
234
|
+
*
|
|
235
|
+
* This package is internal: consumers depend on `@lunora/d1` or
|
|
236
|
+
* `@lunora/hyperdrive`, which assemble the concrete dialect and wrap the core.
|
|
237
|
+
*/
|
|
238
|
+
type SqlCtxDbOptions,
|
|
239
|
+
/**
|
|
240
|
+
* `@lunora/sql-store` — the internal, dialect-parameterized SQL store core
|
|
241
|
+
* shared by Lunora's `.global()` table backends.
|
|
242
|
+
*
|
|
243
|
+
* One ORM implementation (`createSqlCtxDb`) drives any SQL engine through a
|
|
244
|
+
* `SqlDialect`: SQLite via `@lunora/d1`, and Postgres/MySQL (PlanetScale, Neon,
|
|
245
|
+
* any Hyperdrive-reachable database) via `@lunora/hyperdrive`. Reactivity is
|
|
246
|
+
* unaffected — the writer is injected as `globalDb` into `createShardCtxDb`,
|
|
247
|
+
* whose `broadcast` hook drives live queries regardless of engine.
|
|
248
|
+
*
|
|
249
|
+
* This package is internal: consumers depend on `@lunora/d1` or
|
|
250
|
+
* `@lunora/hyperdrive`, which assemble the concrete dialect and wrap the core.
|
|
251
|
+
*/
|
|
252
|
+
type SqlCtxExec, type SqlDialect, type SqlRunResult, backfillSqlSearchIndexes, createSqlCtxDb, decodeBigint, decodeGlobalRow, effectiveColumnKind, migrateSearchState, readSqlCdcChanges, runSqlAggregateMigrations, runSqlCdcMigration, runSqlGlobalTableMigrations, runSqlRankMigrations, runSqlSearchMigrations, sqliteDecode, sqliteEncode, trimSqlCdcChanges, tryJsonParse };
|
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-CRX3OS05.mjs";import{b as s,r as d}from"./packem_shared/ctx-db-search-Cl6zlJ11.mjs";import{SEARCH_STATE_TABLE as q,migrateSearchState as f}from"./packem_shared/SEARCH_STATE_TABLE-DA3LgCT0.mjs";import{decodeBigint as C,effectiveColumnKind as x,sqliteDecode as b,sqliteEncode as u,tryJsonParse as h}from"./packem_shared/decodeBigint-B4wY6fcF.mjs";import{decodeGlobalRow as M}from"./packem_shared/decodeGlobalRow-BKIjk_Zk.mjs";export{q as SEARCH_STATE_TABLE,s as backfillSqlSearchIndexes,o as createSqlCtxDb,C as decodeBigint,M 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,b as sqliteDecode,u as sqliteEncode,S as trimSqlCdcChanges,h as tryJsonParse};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{sql as i}from"drizzle-orm";import{queryRun as s,queryAll as E}from"./decodeGlobalRow-BKIjk_Zk.mjs";const f="__lunora_search_state",l=async(r,e)=>{const{integer:t,key:o}=e.companionTypes,n=async()=>{try{await s(r,e,i`ALTER TABLE ${i.identifier(f)} ADD COLUMN ${i.identifier("profile")} ${i.raw(o)}`)}catch{}};await s(r,e,i`CREATE TABLE IF NOT EXISTS ${i.identifier(f)} (${i.identifier("companion")} ${i.raw(o)} PRIMARY KEY, ${i.identifier("cursor")} ${i.raw(o)}, ${i.identifier("done")} ${i.raw(t)} NOT NULL DEFAULT 0, ${i.identifier("profile")} ${i.raw(o)})`),await n()},p=r=>r===1||r===!0||r==="1",S=async(r,e,t)=>{const n=(await E(r,e,i`SELECT ${i.identifier("cursor")}, ${i.identifier("done")}, ${i.identifier("profile")} FROM ${i.identifier(f)} WHERE ${i.identifier("companion")} = ${t}`))[0];if(!n)return{cursor:void 0,done:!1,profile:void 0};const{cursor:a,profile:$}=n;return{cursor:typeof a=="string"?a:void 0,done:p(n.done),profile:typeof $=="string"?$:void 0}},A=async(r,e,t,o,n,a)=>{const $=o??null,d=i`UPDATE ${i.identifier(f)} SET ${i.identifier("cursor")} = ${$}, ${i.identifier("done")} = ${n?1:0}, ${i.identifier("profile")} = ${a} WHERE ${i.identifier("companion")} = ${t}`;if((await E(r,e,i`SELECT ${i.identifier("companion")} FROM ${i.identifier(f)} WHERE ${i.identifier("companion")} = ${t}`)).length>0){await s(r,e,d);return}try{await s(r,e,i`INSERT INTO ${i.identifier(f)} (${i.identifier("companion")}, ${i.identifier("cursor")}, ${i.identifier("done")}, ${i.identifier("profile")}) VALUES (${t}, ${$}, ${n?1:0}, ${a})`)}catch(c){if(!e.isUniqueViolation(c))throw c;await s(r,e,d)}};export{f as SEARCH_STATE_TABLE,l as migrateSearchState,S as readSearchBackfillState,A as writeSearchBackfillState};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{b as S,c as s,a as i,r as l}from"./ctx-db-search-Cl6zlJ11.mjs";import"./SEARCH_STATE_TABLE-DA3LgCT0.mjs";import"./decodeGlobalRow-BKIjk_Zk.mjs";export{S as backfillSqlSearchIndexes,s as createSearchSync,i as runSqlSearch,l as runSqlSearchMigrations};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as v}from"@lunora/errors";import{c as Tt,r as gt,R as vt,j as St,D as bt,M as It,a as At,B as Ct,y as Lt,_ as kt}from"./ctx-db-search-Cl6zlJ11.mjs";import{b as xn}from"./ctx-db-search-Cl6zlJ11.mjs";import{literalInList as Nt,throwingScheduler as Mt,aggregateTableName as z,rankTableName as ee,hasTrigger as Dt,runRowValidators as Ne,assertFlatPredicate as Je,mergeWhere as q,sortColumnName as X,resolveRankPartition as Qe,encodePartitionKey as Se,decodeCursor as Ze,RANK_TIEBREAK as he,CountRlsUnsupportedError as et,normalizeIdStructurally as qt,assertValidClientId as xt,aggregateSqlFunction as fe,softDeleteScope as we,compileWhereSql as _e,normalizeOrderKeys as Bt,buildSeekWhere as Ft,resolveRelationPredicates as tt,resolveWith as nt,relationHooks as ot,applySelect as it,encodeCursor as Ot,NotFoundError as Wt,applyOnDelete as Ut,ConflictError as $e,normalizeCountArgument as jt,selectIndexForCount as Pt,encodeAggregateKey as Y,selectIndexForAggregate as Kt,readAggregateValue as Me,runTriggers as Ht,matchesRankStaticWhere as rt,selectIndexForGroupBy as Vt,fanOutScalarCounts as Gt,matchesStaticWhere as De,foldAggregateTally as Yt,coerceAggregateNumber as qe,NotUniqueError as zt}from"@lunora/shard-engine";import{sql as e}from"drizzle-orm";import{migrateSearchState as Xt}from"./SEARCH_STATE_TABLE-DA3LgCT0.mjs";import{queryAll as A,queryRun as k,createIndexIfNotExists as Be,decodeRow as te,serializeColumnValue as H,columnRefSql as x,decodeRows as Jt,forEachRowPaged as st,queryBatch as at}from"./decodeGlobalRow-BKIjk_Zk.mjs";import{decodeGlobalRow as Fn}from"./decodeGlobalRow-BKIjk_Zk.mjs";import{effectiveColumnKind as be}from"./decodeBigint-B4wY6fcF.mjs";const Qt=(c,_)=>{if(c.size<_)return;const f=c.keys().next().value;f!==void 0&&c.delete(f)},ct=50,Zt=(c,_={})=>{const f=_.maxBatch??ct,r=Number.isInteger(f)&&f>0?f:ct,p=new Map;let l=!1;const a=async(m,b)=>{const S=[...b.keys()];for(let L=0;L<S.length;L+=r){const M=S.slice(L,L+r);try{const W=await c(m,M);for(const V of M){const U=W.get(V);for(const Ae of b.get(V)??[])Ae.resolve(U)}}catch(W){for(const V of M)for(const U of b.get(V)??[])U.reject(W)}}},R=()=>{l=!1;const m=[...p.entries()];p.clear();for(const[b,S]of m)a(b,S).catch(()=>{})};return{async load(m,b){return new Promise((S,L)=>{let M=p.get(m);M||(M=new Map,p.set(m,M));const W=M.get(b);W?W.push({reject:L,resolve:S}):M.set(b,[{reject:L,resolve:S}]),l||(l=!0,queueMicrotask(R))})}}},en=new Set(["_id","id"]),Fe=(c,_,f)=>c==="postgres"?e`${_} IS NOT DISTINCT FROM ${f}`:c==="mysql"?e`${_} <=> ${f}`:e`${_} IS ${f}`,tn=c=>{const _=c.map(f=>e`${x(f.field)} ${e.raw(f.direction==="desc"?"DESC":"ASC")}`);return c.some(f=>en.has(f.field))||_.push(e`${x("id")} ASC`),e.join(_,e`, `)},lt=50,Oe=c=>{const _=[];for(const[f,r]of Object.entries(c.shape)){const p=r._meta?.column;p&&_.push([f,p])}return _},nn=(c,_,f)=>{const r={..._};for(const[p,l]of Oe(c)){if(l.serverDefault){r[p]=l.serverDefault({auth:f});continue}r[p]===void 0&&(l.defaultFn?r[p]=l.defaultFn():"defaultValue"in l&&(r[p]=l.defaultValue))}return r},ut=(c,_,f,r)=>{for(const[p,l]of Oe(c)){if(l.serverDefault){p in _&&(f[p]=l.serverDefault({auth:r}));continue}l.onUpdateFn&&!(p in _)&&(f[p]=l.onUpdateFn())}},on=128,rn=()=>{const c=new Map;return{delete:_=>{c.delete(_)},get:_=>{const f=c.get(_);if(f!==void 0)return c.delete(_),c.set(_,f),f},set:(_,f)=>{c.has(_)?c.delete(_):Qt(c,on),c.set(_,f)}}},sn=async(c,_,f,r,p)=>{const l=p.get(r);if(l!==void 0)return l;const a=Object.entries(f.tables).filter(([,m])=>m.shardMode===void 0||m.shardMode.kind==="global").map(([m])=>m),R=await Promise.all(a.map(async m=>({found:(await A(c,_,e`SELECT 1 FROM ${e.identifier(m)} WHERE ${e.identifier("id")} = ${r} LIMIT 1`)).length>0,tableName:m})));for(const m of R)if(m.found)return p.set(r,m.tableName),m.tableName},ne=c=>c==null?null:Number(c),an=(c,_)=>_.map(f=>{const r={};for(const p of c)r[p]=f[p]??null;return{key:r,value:ne(f.value)}}),cn=(c,_,f)=>[...c.partitionBy??[],...c.sortBy.map(p=>p.field),...c.where?Object.keys(c.where):[]].every(p=>_[p]===f[p]),dt=c=>c.length===1?c[0]:e`(${e.join(c,e` AND `)})`,Z=c=>e.join(c.map(_=>e`${e.identifier(_)}`),e`, `),oe=c=>e.join(c.map(_=>e`${_}`),e`, `),ln=(c,_,f,r,p)=>{const l=[];for(let a=0;a<f.length+1;a+=1){const R=f.slice(0,a).map(S=>Fe(c,e`${e.identifier(S)}`,r[S])),m=f[a],b=_.sortBy[a];a<f.length&&m!==void 0&&b!==void 0?R.push(e`${e.identifier(m)} ${e.raw(b.direction==="desc"?">":"<")} ${r[m]}`):R.push(e`${e.identifier(he)} < ${p}`),l.push(dt(R))}return l.length>0?e.join(l,e` OR `):void 0},un=(c,_,f)=>{if(f.length!==_.length)return;const r=[];for(const[p,l]of _.entries()){const a=[];for(let R=0;R<p;R+=1){const m=_[R];m!==void 0&&a.push(Fe(c,e`${e.identifier(m.column)}`,f[R]))}a.push(e`${e.identifier(l.column)} ${e.raw(l.direction==="desc"?"<":">")} ${f[p]}`),r.push(dt(a))}return e`(${e.join(r,e` OR `)})`},dn=(c,_)=>{if(c.sortBy.length===0)throw new v("INTERNAL",`rankIndex "${c.name}" requires at least one "sortBy" column for stable pagination`);const f=[{column:"__partition__",direction:"asc"}];for(const[r,p]of c.sortBy.entries())f.push({column:_[r]??X(r),direction:p.direction});return f.push({column:he,direction:"asc"}),f},fn=async(c,_,f,r,p)=>{const a=[];for(let S=0;S<p.length;S+=50)a.push(p.slice(S,S+50));const R=await Promise.all(a.map(async S=>A(c,_,e`SELECT * FROM ${e.identifier(r)} WHERE ${e.identifier("id")} IN (${oe(S)})`))),m=new Map;for(const S of R)for(const L of S)m.set(L.id,L);const b=[];for(const S of p){const L=te(f,m.get(S));L&&b.push(L)}return b},wn=c=>{const _=JSON.stringify(c),f=new TextEncoder().encode(_);let r="";for(const p of f)r+=String.fromCodePoint(p);return btoa(r)},_n=(c,_)=>_.columnType(be(c)),$n=(c,_,f)=>{const r=[];for(const[a,R]of Object.entries(_.shape)){if(!R._meta?.column)continue;const m=R._meta.column.notNull&&R.kind!=="optional"?" NOT NULL":"";r.push(e`${e.identifier(a)} ${e.raw(`${_n(R,f)}${m}`)}`)}const p=f.frameworkColumns().map(a=>e`${e.identifier(a.name)} ${e.raw(a.type)}`),l=p.length+r.length;if(f.maxTableColumns!==void 0&&l>f.maxTableColumns)throw new v("VALIDATION_ERROR",`@lunora/sql-store: global table "${c}" needs ${String(l)} columns, over this engine's ${String(f.maxTableColumns)}-column limit — split the table, or move the extra fields into one object field`);return e.join([...p,...r],e`, `)},hn=async(c,_,f,r)=>{const p=l=>{const a=x(l),R=f.shape[l],m=R&&r.indexKeyPrefix?r.indexKeyPrefix(be(R)):void 0;return m===void 0?a:e`${a}(${e.raw(String(m))})`};for(const l of f.indexes){const a=e.join(l.fields.map(R=>p(R)),e`, `);await Be(c,r,{columns:a,name:`${_}_${l.name}`,table:_,unique:l.unique??!1})}for(const[l,a]of Oe(f))a.unique&&await Be(c,r,{columns:p(l),name:`${_}_unique_${l}`,table:_,unique:!0})},yn=async(c,_,f)=>{for(const[r,p]of Object.entries(_.tables)){if(p.shardMode?.kind!=="global")continue;const l=$n(r,p,f);await k(c,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(r)} (${l})`),await hn(c,r,p,f)}},En=async(c,_,f)=>{const{integer:r,key:p,real:l}=f.companionTypes;for(const[a,R]of Object.entries(_.tables)){const m=R.aggregateIndexes;if(!(!m||m.length===0))for(const b of m){const S=z(a,b.name);await k(c,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(S)} (${e.identifier("__key__")} ${e.raw(p)} PRIMARY KEY, ${e.identifier("__value__")} ${e.raw(l)}, ${e.identifier("__count__")} ${e.raw(r)} NOT NULL DEFAULT 0)`),f.name==="sqlite"&&((await A(c,f,e`PRAGMA table_info(${e.identifier(S)})`)).some(M=>M.name==="__count__")||await k(c,f,e`ALTER TABLE ${e.identifier(S)} ADD COLUMN ${e.identifier("__count__")} ${e.raw(r)} NOT NULL DEFAULT 0`))}}},xe=(c,_,f,r)=>{const p=c.name==="mysql"&&r?e`${e.identifier(_)}(191)`:e`${e.identifier(_)}`;return e`${p} ${e.raw(f)}`},pn=(c,_,f)=>{const r=[xe(c,"__partition__","ASC",!0)];for(const[p,l]of _.sortBy.entries()){const a=f.shape[l.field],R=a!==void 0&&c.indexKeyPrefix?.(be(a))!==void 0;r.push(xe(c,X(p),l.direction==="desc"?"DESC":"ASC",R))}return r.push(xe(c,"__id__","ASC",!0)),r},mn=(c,_,f)=>_.sortBy.map((r,p)=>{const l=f.shape[r.field],a=c.columnType(l?be(l):void 0);return e`${e.identifier(X(p))} ${e.raw(a)}`}),Rn=async(c,_,f)=>{const{key:r}=f.companionTypes;for(const[p,l]of Object.entries(_.tables)){const a=l.rankIndexes;if(!(!a||a.length===0))for(const R of a){const m=ee(p,R.name),b=mn(f,R,l),S=b.length>0?e`, ${e.join(b,e`, `)}`:e``;await k(c,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(m)} (${e.identifier("__id__")} ${e.raw(r)} PRIMARY KEY, ${e.identifier("__partition__")} ${e.raw(r)} NOT NULL${S})`);const L=pn(f,R,l),M=`${p}__rank_${R.name}__btree`;await Be(c,f,{columns:e.join(L,e`, `),name:M,table:m,unique:!1})}}},Ie="__cdc_log",Tn=async(c,_)=>{const{autoincrementPrimaryKey:f,key:r,real:p,text:l}=_.companionTypes;await k(c,_,e`CREATE TABLE IF NOT EXISTS ${e.identifier(Ie)} (${e.identifier("seq")} ${e.raw(f)}, ${e.identifier("ts")} ${e.raw(p)} NOT NULL, ${e.identifier("table")} ${e.raw(r)} NOT NULL, ${e.identifier("id")} ${e.raw(r)} NOT NULL, ${e.identifier("op")} ${e.raw(r)} NOT NULL, ${e.identifier("doc")} ${e.raw(l)})`)},gn=async(c,_,f,r,p,l,a)=>{await k(c,a,e`INSERT INTO ${e.identifier(Ie)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${_}, ${f}, ${r}, ${p}, ${l===void 0?null:JSON.stringify(l)})`)},kn=async(c,_,f)=>{const r=_.sinceSeq??0,p=Math.max(1,Math.min(_.limit??1e3,1e4)),a=(await A(c,f,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(Ie)} WHERE seq > ${r} ORDER BY seq ASC LIMIT ${e.raw(String(p))}`)).map(R=>{const{doc:m}=R,b={id:String(R.id),op:String(R.op),seq:Number(R.seq),table:String(R.table),ts:Number(R.ts)};return typeof m=="string"?{...b,doc:JSON.parse(m)}:b});return{changes:a,cursor:a.at(-1)?.seq??r}},Nn=async(c,_,f)=>{await k(c,f,e`DELETE FROM ${e.identifier(Ie)} WHERE ${e.identifier("seq")} <= ${_}`)},Mn=c=>{const{crossShardCounter:_,crossShardReader:f,exec:r,maxRelationKeys:p,schema:l}=c,{dialect:a}=c,{isUniqueViolation:R}=a,m={fieldRef:x,serialize:H,...a.name==="mysql"?{containsExpr:(t,n)=>e`LOCATE(${n}, ${t}) > 0`}:{},...a.name==="postgres"?{containsExpr:(t,n)=>e`strpos(${t}, ${n}) > 0`}:{},...a.name==="sqlite"?{}:{inList:Nt}},b=(t,n)=>Fe(a.name,t,n),S=t=>{const n=Z(t.columns),o=oe(t.values),i=u=>a.name==="mysql"?e`VALUES(${e.identifier(u)})`:e`excluded.${e.identifier(u)}`,s=u=>a.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(u)}`:e`${e.identifier(u)}`,w=e.join(Object.entries(t.set(i,s)).map(([u,y])=>e`${e.identifier(u)} = ${y}`),e`, `),h=a.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${w}`:e`ON CONFLICT(${e.identifier(t.conflictKey)}) DO UPDATE SET ${w}`;return e`INSERT INTO ${e.identifier(t.table)} (${n}) VALUES (${o}) ${h}`},L=c.clock??(()=>Date.now()),M=c.idGenerator??(()=>crypto.randomUUID()),W=c.cdc??!1,V=c.auth??{identity:null,userId:null},U=async(t,n,o,i)=>{W&&await gn(r,L(),t,n,o,i,a)},Ae=c.scheduler??Mt,Ce=rn();let ye=0,Le;const j=async()=>(Le??=(async()=>{await yn(r,l,a),await En(r,l,a),await Rn(r,l,a),await Xt(r,a),await gt(r,l,a),W&&await Tn(r,a)})().catch(t=>{throw Le=void 0,t}),Le),ie=async(t,n)=>{await j();const o=await sn(r,a,l,t,Ce);if(!(n!==void 0&&o!==n))return o},re=new Map,We=async(t,n)=>{const o=z(t,n);return(await A(r,a,a.tableExists(o))).length>0},Ee=async(t,n)=>{const o=`${t}::${n.name}`,i=re.get(o);if(i!==void 0)return i;if(!await We(t,n.name))return re.set(o,!1),!1;const w=l.tables[t];if(!w)return re.set(o,!1),!1;const h=n.by??[],u=new Map;await st(r,a,w,t,$=>{if(n.where&&!De($,n.where))return;const E=Y(h,$);Yt(u,E,n,$)});const y=z(t,n.name);await k(r,a,e`DELETE FROM ${e.identifier(y)}`);const d=[];for(const[$,E]of u)d.push(e`INSERT INTO ${e.identifier(y)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${$}, ${E.value}, ${E.count})`);return await at(r,a,d),re.set(o,!0),!0},ft=async(t,n,o)=>{const i=fe(n.op),s=n.field??"",w=[];for(const y of n.by??[]){const d=H(o[y]??null);w.push(d===null?e`${x(y)} IS NULL`:e`${x(y)} = ${d}`)}for(const[y,d]of Object.entries(n.where??{})){const $=d!==null&&typeof d=="object"&&!Array.isArray(d)?d.eq:d,E=H($);w.push(E===null?e`${x(y)} IS NULL`:e`${x(y)} = ${E}`)}const h=e`SELECT ${e.raw(i)}(${x(s)}) AS value FROM ${e.identifier(t)}`,u=await A(r,a,w.length>0?e`${h} WHERE ${e.join(w,e` AND `)}`:h);return ne(u[0]?.value)},wt=async(t,n)=>{await k(r,a,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${n} AND ${e.identifier("__count__")} <= 0`)},_t=async(t,n,o,i)=>{const s=z(t,n.name),{op:w}=n,h=n.field??"",u=o&&(!n.where||De(o,n.where))?o:void 0,y=i&&(!n.where||De(i,n.where))?i:void 0;if(!(!u&&!y)){if(w==="count"||w==="sum"||w==="avg"){const d=new Set;for(const[$,E]of[[u,-1],[y,1]]){if(!$)continue;const g=w==="count"?1:qe($[h]);if(g===void 0)continue;const T=Y(n.by??[],$);d.add(T),await k(r,a,S({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(C,I)=>({__count__:e`${I("__count__")} + ${C("__count__")}`,__value__:w==="count"?e`${I("__value__")} + ${C("__value__")}`:e`COALESCE(${I("__value__")}, 0) + ${C("__value__")}`}),table:s,values:[T,E*g,E]}))}for(const $ of d)await wt(s,$);return}if(u){const d=Y(n.by??[],u),$=qe(u[h]),g=(await A(r,a,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(s)} WHERE ${e.identifier("__key__")} = ${d}`))[0],T=ne(g?.value),C=(g?.count??0)-1;if(C<=0)await k(r,a,e`DELETE FROM ${e.identifier(s)} WHERE ${e.identifier("__key__")} = ${d}`);else if(g&&$!==void 0&&T!==null&&$===T){const I=await ft(t,n,u);await k(r,a,e`UPDATE ${e.identifier(s)} SET ${e.identifier("__value__")} = ${I}, ${e.identifier("__count__")} = ${C} WHERE ${e.identifier("__key__")} = ${d}`)}else await k(r,a,e`UPDATE ${e.identifier(s)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${d}`)}if(y){const d=Y(n.by??[],y),$=qe(y[h]);if($===void 0)await k(r,a,S({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(E,g)=>({__count__:e`${g("__count__")} + 1`}),table:s,values:[d,null,1]}));else{const E=w==="min"?"MIN":"MAX";await k(r,a,S({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(g,T)=>({__count__:e`${T("__count__")} + 1`,__value__:e`${e.raw(E)}(COALESCE(${T("__value__")}, ${g("__value__")}), ${g("__value__")})`}),table:s,values:[d,$,1]}))}}}},pe=async t=>{const n=l.tables[t]?.aggregateIndexes;if(!(!n||n.length===0))for(const o of n)await Ee(t,o)},se=async(t,n,o)=>{const i=l.tables[t]?.aggregateIndexes;if(!(!i||i.length===0))for(const s of i){const w=`${t}::${s.name}`;(re.get(w)??await We(t,s.name))&&await _t(t,s,n,o)}},ae=new Map,Ue=async(t,n)=>{const o=ee(t,n);return(await A(r,a,a.tableExists(o))).length>0},ke=async(t,n)=>{const o=`${t}::rank::${n.name}`,i=ae.get(o);if(i!==void 0)return i;if(!await Ue(t,n.name))return ae.set(o,!1),!1;const w=l.tables[t];if(!w)return ae.set(o,!1),!1;const h=ee(t,n.name);await k(r,a,e`DELETE FROM ${e.identifier(h)}`);const u=n.sortBy.map((E,g)=>X(g)),y=Z(["__id__","__partition__",...u]),d=[];await st(r,a,w,t,E=>{if(n.where&&!rt(E,n.where))return;const g=Se(n.partitionBy??[],E),T=n.sortBy.map(C=>H(E[C.field]??null));d.push([E._id,g,...T])});const $=d.map(E=>e`INSERT INTO ${e.identifier(h)} (${y}) VALUES (${oe(E)})`);return await at(r,a,$),ae.set(o,!0),!0},me=async t=>{const n=l.tables[t]?.rankIndexes;if(!(!n||n.length===0))for(const o of n)await ke(t,o)},J=async(t,n,o,i)=>{const s=l.tables[t],w=s?.rankIndexes;if(!w||w.length===0)return;const h=s?.softDeleteMode?.field,u=h===void 0||i===void 0?void 0:i[h],y=u!=null;for(const d of w){if(o!==void 0&&i!==void 0&&cn(d,o,i))continue;const $=`${t}::rank::${d.name}`;if(!(ae.get($)??await Ue(t,d.name)))continue;const T=ee(t,d.name);if(o&&await k(r,a,e`DELETE FROM ${e.identifier(T)} WHERE ${e.identifier("__id__")} = ${n}`),i&&!y){if(d.where&&!rt(i,d.where))continue;const C=d.sortBy.map((B,G)=>X(G)),I=Z(["__id__","__partition__",...C]),F=Se(d.partitionBy??[],i),N=d.sortBy.map(B=>H(i[B.field]??null));await k(r,a,e`INSERT INTO ${e.identifier(T)} (${I}) VALUES (${oe([n,F,...N])})`)}}},ce=Tt({dialect:a,exec:r,schema:l}),je=new Set;for(const[t,n]of Object.entries(l.tables))for(const o of Object.values(n.triggerMap??{}))je.add(`${t} ${o.timing} ${o.op}`);const P=(t,n,o)=>je.has(`${t} ${n} ${o}`);let Pe;const K=async(t,n,o)=>{if(ye+=1,ye>lt)throw ye-=1,new $e(`trigger recursion exceeded ${String(lt)} levels on "${o.table}" — check for a self-triggering write`,"trigger");try{await Ht({ctx:Pe,event:o,op:n,schema:l,tableName:o.table,timing:t})}finally{ye-=1}},$t=async(t,n)=>{try{await k(r,a,n)}catch(o){throw R(o)?new $e(`unique constraint violation on "${t}"`,"unique"):o}},Re=async(t,n)=>(await A(r,a,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${n}`))[0],Te=async(t,n,o,i)=>{if(i===void 0)return;const s=e.join(Object.keys(i).map(u=>b(e`${e.identifier(u)}`,i[u])),e` AND `),w=n==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${o} WHERE ${s}`:e`DELETE FROM ${e.identifier(t)} WHERE ${s}`,h=()=>{throw new $e(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")};try{if(a.supportsReturning)(await A(r,a,e`${w} RETURNING ${e.identifier("id")}`)).length===0&&h();else{const u=await k(r,a,w);(a.affectedRows?a.affectedRows(u??{rowsAffected:0}):0)===0&&h()}}catch(u){throw R(u)?new $e(`unique constraint violation on "${t}"`,"unique"):u}},ht=(t,n,o,i)=>{const s=Object.keys(t.shape);return{columns:["id","_creationTime",...s],values:[n,o,...s.map(w=>H(i[w]??null))]}},yt=async(t,n,o,i)=>{const s=Vt(n,o.op,o.field,i.by,i.where);if(!s||!await Ee(t,s.index))return;const h=z(t,s.index.name),u=Object.keys(s.partial);if(u.length===(s.index.by??[]).length&&u.length>0){const d=Y(s.index.by??[],s.partial),$=await A(r,a,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(h)} WHERE ${e.identifier("__key__")} = ${d}`);if($.length===0)return[];const E=$[0];return[{key:{...s.partial},value:Me(o.op,{count:E.count,value:ne(E.value)})}]}return u.length>0?void 0:(await A(r,a,e`SELECT ${e.identifier("__key__")} AS key, ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(h)}`)).map(d=>{const $=d;return{key:JSON.parse($.key),value:Me(o.op,{count:$.count,value:ne($.value)})}})},Ke=t=>{const n=l.tables[t]?.shardMode?.kind;return n==="shardBy"||n==="root"},He=t=>{throw new v("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`)},Et=(t,n)=>{if(n?.relationMask!==void 0&&n.with!==void 0&&Object.keys(n.with).length>0)throw new v("MASK_UNSUPPORTED",`masking cannot follow a nested \`with\` across the cross-shard relation hop to "${t}" — the nested rows are hydrated on the serving shard, where the mask policy does not exist. Read the nested relation at its own (masked) call site instead.`);const o={};if(n?.relationBaseWhere)for(const i of Object.keys(l.tables)){const s=n.relationBaseWhere(i);s!==void 0&&(o[i]=s)}return{orderBy:n?.orderBy,relationPolicies:o,where:q(n?.baseWhere,n?.where),with:n?.with}},Ve=(t,n)=>Ke(t)?f?f(t,Et(t,n)):He(t):O.findMany(t,n),ge=(t,n,o)=>tt(t,{fetcher:Ve,maxRelationKeys:p,relationBaseWhere:o,schema:l,tableName:n}),pt=Zt(async(t,n)=>{const o=await A(r,a,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} IN (${oe(n)})`),i=new Map;for(const s of o){const{id:w}=s;typeof w=="string"&&i.set(w,s)}return i}),O={async aggregate(t,n){const o=l.tables[t];if(!o)throw new v("INTERNAL",`unknown table: ${t}`);if(await j(),fe(n.op),n.op==="count")return O.count(t,{baseWhere:n.baseWhere,relationBaseWhere:n.relationBaseWhere,restrictsCounts:n.restrictsCounts,where:n.where});if(!n.field)throw new v("INTERNAL",`aggregate(${t}, { op: "${n.op}" }): "field" is required for non-count reducers`);const i=we(o.softDeleteMode,void 0),s=q(q(n.baseWhere,n.where),i),w=await ge(s,t,n.relationBaseWhere),h=w!==s;if(o.aggregateIndexes&&!n.baseWhere&&!h&&!i){const g=Kt(o.aggregateIndexes,n.op,n.field,n.where);if(g&&await Ee(t,g.index)){const C=Y(g.index.by??[],g.key),I=z(t,g.index.name),N=(await A(r,a,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(I)} WHERE ${e.identifier("__key__")} = ${C}`))[0];return Me(n.op,N===void 0?void 0:{count:N.count,value:ne(N.value)})}}const u=_e(w,m),y=e.raw(fe(n.op)),d=e`SELECT ${y}(${x(n.field)}) AS value FROM ${e.identifier(t)}`,E=(await A(r,a,u?e`${d} WHERE ${u}`:d))[0]?.value;return E==null?null:Number(E)},async count(t,n){const o=l.tables[t];if(!o)throw new v("INTERNAL",`unknown table: ${t}`);await j();const i=jt(n);if(i.restrictsCounts)throw new et(t);const s=we(o.softDeleteMode,void 0),w=q(q(i.baseWhere,i.where),s),h=await ge(w,t,i.relationBaseWhere),u=h!==w;if(o.aggregateIndexes&&!i.baseWhere&&!u&&!s){const E=Pt(o.aggregateIndexes,i.where);if(E&&await Ee(t,E.index)){const T=Y(E.index.by??[],E.key),C=z(t,E.index.name),I=await A(r,a,e`SELECT ${e.identifier("__value__")} AS value FROM ${e.identifier(C)} WHERE ${e.identifier("__key__")} = ${T}`);return Number(I[0]?.value??0)}}const y=_e(h,m),d=e`SELECT COUNT(*) AS count FROM ${e.identifier(t)}`,$=await A(r,a,y?e`${d} WHERE ${y}`:d);return Number($[0]?.count??0)},async delete(t,n,o){const i=await ie(t,n);if(!i)return;const s=l.tables[i];if(!s)return;const w=await Re(i,t),h=te(s,w),u=o?.hard===!0,y=!u&&s.softDeleteMode?s.softDeleteMode.field:void 0;if(!(y&&(!h||h[y]!==null&&h[y]!==void 0))){if(P(i,"before","delete")&&await K("before","delete",{id:t,op:"delete",previous:h??void 0,table:i}),await Ut({deletedId:t,deletedReference:d=>h?.[d],findHolders:async(d,$,E)=>{if(l.tables[d]?.shardMode?.kind==="shardBy")throw new v("INTERNAL",`cross-backend cascade from global '${i}' into shardBy '${d}' is not supported — would require Query Coordinator fan-out across shards`);return(await O.findMany(d,{includeDeleted:u,where:{[$]:E}})).page},onCascade:(d,$)=>O.delete($,void 0,o),onRestrict:d=>{throw new $e(d,"restrict")},onSetNull:(d,$,E)=>O.patch($,{[E]:null}),schema:l,tableName:i}),await pe(i),await me(i),y&&h){const d={...h,[y]:L()},$=e.join(Object.keys(s.shape).map(E=>e`${e.identifier(E)} = ${H(d[E]??null)}`),e`, `);await Te(i,"UPDATE",$,w),await se(i,h,d),await J(i,t,h,void 0),await ce(i,t,d,h),await U(i,t,"update",d),P(i,"after","delete")&&await K("after","delete",{id:t,op:"delete",previous:h,table:i});return}await Te(i,"DELETE",void 0,w),Ce.delete(t),await se(i,h??void 0,void 0),await J(i,t,h??void 0,void 0),await ce(i,t,void 0),await U(i,t,"delete"),P(i,"after","delete")&&await K("after","delete",{id:t,op:"delete",previous:h??void 0,table:i})}},async findFirst(t,n={}){return(await O.findMany(t,{...n,limit:1})).page[0]??null},async findFirstOrThrow(t,n={}){const o=await O.findFirst(t,n);if(o===null)throw new Wt(`findFirstOrThrow: no "${t}" document matched`);return o},async findMany(t,n={}){const o=l.tables[t];if(!o)throw new v("INTERNAL",`unknown table: ${t}`);await j();const i=Bt(n.orderBy),s=n.cursor?Ft(i,Ze(n.cursor)):void 0,w=Ve,h=async(N,B,G,ve)=>{if(Ke(N))return _?Gt(_,N,B,G,ve):He(N);const le=l.tables[N];if(!le)throw new v("INTERNAL",`unknown table: ${N}`);const Q=we(le.softDeleteMode,void 0),D={[B]:{in:G}},ue=q(q(D,ve),Q),mt=await ge(ue,N,void 0),Ge=_e(mt,m),Ye=x(B);let de=e`SELECT ${Ye} AS __fk__, COUNT(*) AS count FROM ${e.identifier(N)}`;Ge&&(de=e`${de} WHERE ${Ge}`),de=e`${de} GROUP BY ${Ye}`;const Rt=await A(r,a,de),ze=new Map;for(const Xe of Rt)ze.set(Xe.__fk__,Number(Xe.count??0));return ze};let u=q(n.baseWhere,n.where);u=q(u,we(o.softDeleteMode,n.includeDeleted)),u=await tt(u,{fetcher:w,maxRelationKeys:p,relationBaseWhere:n.relationBaseWhere,schema:l,tableName:t}),s&&(u=u?{AND:[u,s]}:s);const y=_e(u,m),d=tn(i);let $=e`SELECT * FROM ${e.identifier(t)}`;y&&($=e`${$} WHERE ${y}`),$=e`${$} ORDER BY ${d}`;const E=typeof n.limit=="number"?Math.max(0,Math.floor(n.limit)):void 0;E!==void 0&&($=e`${$} LIMIT ${e.raw(String(E+1))}`);const g=await A(r,a,$),T=Jt(o,g);if(E===void 0)return n.with&&await nt({fetcher:w,groupedCounter:h,parents:T,...ot(n),schema:l,tableName:t,with:n.with}),{continueCursor:null,isDone:!0,page:it(T,n.select,n.with)};const C=T.length>E,I=C?T.slice(0,E):T,F=I.at(-1);return n.with&&await nt({fetcher:w,groupedCounter:h,parents:I,...ot(n),schema:l,tableName:t,with:n.with}),{continueCursor:C&&F?Ot(F,i):null,isDone:!C,page:it(I,n.select,n.with)}},async get(t,n){const o=await ie(t,n);if(!o)return null;const i=l.tables[o];return i?te(i,await pt.load(o,t)):null},async groupBy(t,n){const o=l.tables[t];if(!o)throw new v("INTERNAL",`unknown table: ${t}`);await j();const i=n.agg??{op:"count"};if(fe(i.op),i.op!=="count"&&!i.field)throw new v("INTERNAL",`groupBy(${t}, { agg: { op: "${i.op}" } }): "field" is required for non-count reducers`);const s=we(o.softDeleteMode,void 0),w=q(q(n.baseWhere,n.where),s),h=await ge(w,t,n.relationBaseWhere),u=h!==w;if(o.aggregateIndexes&&!n.baseWhere&&!u&&!s){const T=await yt(t,o.aggregateIndexes,i,n);if(T!==void 0)return T}const y=_e(h,m),d=n.by.map(T=>e`${x(T)} AS ${e.identifier(T)}`);if(i.op==="count")d.push(e`COUNT(*) AS value`);else{if(!i.field)throw new v("INTERNAL",`groupBy(${t}, { agg: { op: "${i.op}" } }): "field" is required for non-count reducers`);d.push(e`${e.raw(fe(i.op))}(${x(i.field)}) AS value`)}const $=e.join(n.by.map(T=>x(T)),e`, `);let E=e`SELECT ${e.join(d,e`, `)} FROM ${e.identifier(t)}`;y&&(E=e`${E} WHERE ${y}`),E=e`${E} GROUP BY ${$}`;const g=await A(r,a,E);return an(n.by,g)},async insert(t,n,o){const i=l.tables[t];if(!i)throw new v("INTERNAL",`unknown table: ${t}`);await j();const s=nn(i,n,V);Ne(i,s);let w,h=!0;o?.clientId!==void 0?(xt(o.clientId),w=o.clientId):o?.allowExplicitId&&typeof s._id=="string"?w=s._id:(w=M(),h=!1);const u=o?.allowExplicitId&&typeof s._creationTime=="number"?s._creationTime:L(),y={...s,_creationTime:u,_id:w};P(t,"before","insert")&&await K("before","insert",{doc:{...y},id:w,op:"insert",table:t}),await pe(t),await me(t);const{columns:d,values:$}=ht(i,w,u,s);return await $t(t,e`INSERT INTO ${e.identifier(t)} (${Z(d)}) VALUES (${oe($)})`),h&&Ce.set(w,t),await se(t,void 0,y),await J(t,w,void 0,y),await ce(t,w,y),await U(t,w,"insert",y),P(t,"after","insert")&&await K("after","insert",{doc:y,id:w,op:"insert",table:t}),w},normalizeId(t,n){return qt(l,t,n)},async patch(t,n,o){const i=await ie(t,o);if(!i)throw new v("INTERNAL",`document not found: ${t}`);const s=l.tables[i];if(!s)throw new v("INTERNAL",`document not found: ${t}`);const w=await Re(i,t),h=te(s,w);if(!h)throw new v("INTERNAL",`document not found: ${t}`);const u={...h,...n,_id:t};ut(s,n,u,V),Ne(s,u,!0),P(i,"before","update")&&await K("before","update",{doc:{...u},id:t,op:"update",previous:h,table:i}),await pe(i),await me(i);const y=Object.keys(s.shape),d=e.join(y.map($=>e`${e.identifier($)} = ${H(u[$]??null)}`),e`, `);await Te(i,"UPDATE",d,w),await se(i,h,u),await J(i,t,h,u),await ce(i,t,u,h),await U(i,t,"update",u),P(i,"after","update")&&await K("after","update",{doc:u,id:t,op:"update",previous:h,table:i})},async restore(t,n){const o=await ie(t,n);if(!o)throw new v("INTERNAL",`document not found: ${t}`);const i=l.tables[o],s=i?.softDeleteMode?.field;if(!i||!s)throw new v("INTERNAL",`ctx.db.restore: table "${o}" is not a .softDelete() table`);const w=await Re(o,t),h=w?.[s]!==null&&w?.[s]!==void 0;if(await O.patch(t,{[s]:null},n),h){const u=te(i,w);u!==null&&await J(o,t,void 0,{...u,[s]:null})}},query(t){const n=l.tables[t];if(!n)throw new v("INTERNAL",`unknown table: ${t}`);const o="the legacy query()/withIndex() reader is not available on the D1 (global) backend; use findMany",i=[],s=u=>i.every(y=>y(u)),w=async(u,y)=>{await j();const d=i.length>0,$=await At(r,a,n,t,u,Ct(d?void 0:y));if(!d)return y===void 0&&Lt($),$;const E=$.filter(g=>s(g));return y===void 0?E:E.slice(0,y)},h=u=>{const y={async*[Symbol.asyncIterator](){if(!u)throw new v("INTERNAL",o);yield*await w(u,void 0)},async collect(){if(!u)throw new v("INTERNAL",o);return w(u,void 0)},async collectWithScores(){throw new v("INTERNAL",`collectWithScores() is not supported on \`.global()\` tables (table "${t}") — relevance scores are not yet surfaced on this backend; use .collect() instead`)},filter(d){return i.push(d),y},async first(){if(!u)throw new v("INTERNAL",o);return(await w(u,1))[0]??null},order(){return y},async paginate(d){if(!u)throw new v("INTERNAL",o);const $=bt(d);return It(await w(u,kt($)),$)},async take(d){if(!u)throw new v("INTERNAL",o);return w(u,d)},async unique(){if(!u)throw new v("INTERNAL",o);const d=await w(u,2);if(d.length>1)throw new zt(`unique() on table "${t}" matched ${String(d.length)} documents; expected at most one`);return d[0]??null},withGeoIndex(){throw new v("INTERNAL",`geo indexes are not supported on \`.global()\` tables (table "${t}") — geospatial queries run only on sharded tables`)},withIndex(){throw new v("INTERNAL",o)},withSearchIndex(d,$){const E=(n.searchIndexes??[]).find(T=>T.name===d);if(!E)throw new v("INTERNAL",`unknown search index "${d}" on table "${t}"`);const g={definition:E,field:E.field,filters:[],hasQuery:!1,indexName:d,query:""};if($(vt(g,t,St(E.language))),!g.hasQuery)throw new v("INTERNAL",`search index "${d}" on table "${t}" requires a .search(field, query) call`);return h(g)}};return y};return h(void 0)},async rank(t,n,o){const i=l.tables[t];if(!i)throw new v("INTERNAL",`unknown table: ${t}`);const s=i.rankIndexes?.find(B=>B.name===n);if(!s)throw new v("INTERNAL",`unknown rankIndex "${n}" on table "${t}"`);if(o.restrictsCounts)throw new et(t);if(await j(),!await ke(t,s))return null;const h=typeof o.row=="string"?o.row:o.row._id;if(!h)return null;const u=ee(t,s.name),y=s.sortBy.map((B,G)=>X(G)),d=Z(["__partition__",...y]),E=(await A(r,a,e`SELECT ${d} FROM ${e.identifier(u)} WHERE ${e.identifier("__id__")} = ${h}`))[0];if(!E)return null;const g=E.__partition__,T=q(o.baseWhere,o.where);Je(T,l,t,"rank");const C=Qe(s,T);if(C&&Se(s.partitionBy??[],C)!==g)return null;const I=ln(a.name,s,y,E,h),F=await A(r,a,e`SELECT COUNT(*) AS c FROM ${e.identifier(u)} WHERE ${e.identifier("__partition__")} = ${g}${I?e` AND (${I})`:e``}`),N=await A(r,a,e`SELECT COUNT(*) AS c FROM ${e.identifier(u)} WHERE ${e.identifier("__partition__")} = ${g}`);return{position:Number(F[0]?.c??0)+1,total:Number(N[0]?.c??0)}},async rankPage(t,n,o={}){Je(q(o.baseWhere,o.where),l,t,"rankPage");const i=l.tables[t];if(!i)throw new v("INTERNAL",`unknown table: ${t}`);const s=i.rankIndexes?.find(D=>D.name===n);if(!s)throw new v("INTERNAL",`unknown rankIndex "${n}" on table "${t}"`);if(await j(),!await ke(t,s))return{continueCursor:null,isDone:!0,page:[]};const h=ee(t,s.name),u=s.sortBy.map((D,ue)=>X(ue)),y=Math.max(1,Math.min(1e3,Math.floor(o.take??100))),d=q(o.baseWhere,o.where),$=Qe(s,d),E=dn(s,u),g=e.join(E.map(D=>e`${e.identifier(D.column)} ${e.raw(D.direction==="desc"?"DESC":"ASC")}`),e`, `),T=[];if($&&T.push(e`${e.identifier("__partition__")} = ${Se(s.partitionBy??[],$)}`),o.cursor){const D=un(a.name,E,Ze(o.cursor));D!==void 0&&T.push(D)}const C=Z([he,"__partition__",...u]);let I=e`SELECT ${C} FROM ${e.identifier(h)}`;T.length>0&&(I=e`${I} WHERE ${e.join(T,e` AND `)}`),I=e`${I} ORDER BY ${g} LIMIT ${e.raw(String(y+1))}`;const F=await A(r,a,I),N=F.length>y,B=N?F.slice(0,y):F,G=B.map(D=>D[he]),ve=await fn(r,a,i,t,G);let le=null;const Q=B.at(-1);if(N&&Q!==void 0){const D=[Q.__partition__,...u.map(ue=>Q[ue]),Q[he]];le=wn(D)}return{continueCursor:le,isDone:!N,page:ve}},async replace(t,n,o,i){const s=await ie(t,o);if(!s)throw new v("INTERNAL",`document not found: ${t}`);const w=l.tables[s];if(!w)throw new v("INTERNAL",`document not found: ${t}`);const h=await Re(s,t);if(h===void 0)throw new v("INTERNAL",`document not found: ${t}`);const y=Dt(l,s,"update")||(w.aggregateIndexes??[]).length>0||(w.rankIndexes??[]).length>0?te(w,h)??void 0:void 0,d=i?.allowExplicitId&&typeof n._creationTime=="number"?n._creationTime:L(),$={...n,_creationTime:d,_id:t};ut(w,n,$,V),Ne(w,$),P(s,"before","update")&&await K("before","update",{doc:{...$},id:t,op:"update",previous:y,table:s}),await pe(s),await me(s);const E=Object.keys(w.shape),g=e.join([e`${e.identifier("_creationTime")} = ${d}`,...E.map(T=>e`${e.identifier(T)} = ${H($[T]??null)}`)],e`, `);await Te(s,"UPDATE",g,h),await se(s,y,$),await J(s,t,y,$),await ce(s,t,$,y),await U(s,t,"update",$),P(s,"after","update")&&await K("after","update",{doc:$,id:t,op:"update",previous:y,table:s})}};return Pe={db:O,scheduler:Ae},O};export{xn as backfillSqlSearchIndexes,Mn as createSqlCtxDb,Fn as decodeGlobalRow,kn as readSqlCdcChanges,En as runSqlAggregateMigrations,Tn as runSqlCdcMigration,yn as runSqlGlobalTableMigrations,Rn as runSqlRankMigrations,gt as runSqlSearchMigrations,Nn as trimSqlCdcChanges};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{sql as t}from"drizzle-orm";import{migrateSearchState as Z,readSearchBackfillState as P,writeSearchBackfillState as v}from"./SEARCH_STATE_TABLE-DA3LgCT0.mjs";import{LunoraError as S}from"@lunora/errors";import{unionAll as ee}from"@lunora/shard-engine";import{queryRun as h,decodeRows as z,queryAll as C,queryBatch as ne,createIndexIfNotExists as U,columnRefSql as M,serializeColumnValue as te,forEachRowPaged as ie}from"./decodeGlobalRow-BKIjk_Zk.mjs";const oe=["de","en","es","fr","it","nl","none","pt"],re=e=>oe.includes(e),se="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",ce="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",ue="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",de="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",le="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ê",me=/[\u0300-\u036F]/gu,W=e=>e.normalize("NFD").replaceAll(me,"").normalize("NFC").toLowerCase(),g=e=>new Set(W(e).split(" ")),$e={de:g(ae),en:g(se),es:g(ce),fr:g(ue),it:g(fe),nl:g(de),none:new Set,pt:g(le)},he=2,we=256,j=new Map,y=e=>{const n=e!==void 0&&re(e)?e:"none",i=j.get(n);if(i)return i;const o=$e[n],r=a=>{const c=(W(a).match(/[\p{L}\p{N}]+/gu)??[]).filter(u=>u.length<=we);return o.size===0?c:c.filter(u=>!o.has(u))},s={document:r,profile:`${n}-v${String(he)}`,query:a=>{const c=r(a);return c.filter((u,f)=>c.lastIndexOf(u)===f)}};return j.set(n,s),s},Se=(e,n)=>e.profile!==n?{cursor:void 0,finished:!1,wipe:e.cursor!==void 0||e.done}:{cursor:e.cursor,finished:e.done,wipe:!1},pe=(e,n)=>{if(!n.includes("."))return e[n];let i=e;for(const o of n.split(".")){if(i===null||typeof i!="object"||Array.isArray(i))return;i=i[o]}return i},I=(e,n)=>`${e}__fts_${n}`,Ee="__text__",l="__id__",T="__token__",D="__n__",ge=1e3,Q=(e,n)=>n.document(e),L=(e,n)=>pe(e,n),_e=e=>typeof e=="string"?e:e==null?"":typeof e=="number"||typeof e=="bigint"||typeof e=="boolean"?String(e):JSON.stringify(e)??"",ye=(e,n,i)=>e!==void 0&&n!==void 0&&L(e,i.field)===L(n,i.field),O=(e,n)=>Q(_e(L(e,n.field)),y(n.language)).slice(0,ge).join(" "),Te=(e,n)=>{const i=new Map;for(const o of Q(e,n))i.set(o,(i.get(o)??0)+1);return i},Ne=e=>{const n=new TextEncoder().encode(e);let i="";for(const o of n)i+=String.fromCodePoint(o);return btoa(i)},ve=e=>{const n=atob(e),i=Uint8Array.from(n,o=>o.codePointAt(0)??0);return new TextDecoder().decode(i)},Ie=()=>new S("BAD_REQUEST","invalid cursor"),B=16,F=8,p=1024,R=(e,n)=>n.query(e),Re=(e,n)=>{if(!n)return{exact:!0,lower:e,upper:e};const i=[...e].at(-1)??"",o=(i.codePointAt(0)??0)+1;if(o>=55296&&o<=57343||o>1114111)return{exact:!0,lower:e,upper:e};const r=e.slice(0,e.length-i.length);return{exact:!1,lower:e,upper:r+String.fromCodePoint(o)}},He=(e,n,i)=>{const o={eq:(r,s)=>{if(!e.definition.filterFields?.includes(r))throw new S("INTERNAL",`field "${r}" is not a filter field of search index "${e.indexName}" on table "${n}"`);if(e.filters.length>=F)throw new S("BAD_REQUEST",`search index "${e.indexName}" on table "${n}": at most ${String(F)} .eq() filters are supported per search query`);return e.filters.push({field:r,value:s}),o},search:(r,s)=>{const a=e;if(r!==a.definition.field)throw new S("INTERNAL",`search index "${a.indexName}" on table "${n}" indexes "${a.definition.field}", not "${r}"`);const c=R(s,i).length;if(c>B)throw new S("BAD_REQUEST",`search index "${a.indexName}" on table "${n}": at most ${String(B)} search terms are supported (got ${String(c)})`);return a.field=r,a.query=s,a.hasQuery=!0,o}};return o},Pe=e=>{if(e.length>p)throw new S("BAD_REQUEST",`more than ${String(p)} 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,p),Ae=e=>Ne(`search:${String(e)}`),be=e=>{let n;try{n=ve(e)}catch{return}if(!n.startsWith("search:"))return;const i=Number(n.slice(7));return Number.isInteger(i)&&i>=0?i:void 0},We=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 n=Math.max(0,Math.floor(e.numItems)),i=e.cursor?be(e.cursor):0;if(i===void 0)throw Ie();if(i+n>p)throw new S("BAD_REQUEST",`search pagination reaches past the ${String(p)}-document limit (offset ${String(i)} + ${String(n)} requested) — narrow the query or the filters instead`);return{numItems:n,offset:i}},Qe=(e,n)=>{const i=n.offset+n.numItems,o=n.numItems>0&&e.length>i;return{continueCursor:o?Ae(i):null,isDone:!o,page:e.slice(n.offset,i)}},Ge=e=>{if(e===void 0)return p+1;if(!Number.isFinite(e))return p;const n=Math.max(0,Math.floor(e));if(n>p)throw new S("BAD_REQUEST",`search returns at most ${String(p)} documents (asked for ${String(n)}) — narrow the query or paginate instead`);return n},A=async(e,n,i,o)=>{await h(e,n,t`DELETE FROM ${t.identifier(i)} WHERE ${t.identifier(l)} = ${o}`)},b=(e,n)=>e.name==="mysql"?t`${t.identifier(n)}(191)`:e.textPatternOperatorClass===void 0?t`${t.identifier(n)}`:t`${t.identifier(n)} ${t.raw(e.textPatternOperatorClass)}`,k=50,De=(e,n)=>n?t`${t.identifier(T)} LIKE ${`${e}%`}`:t`${t.identifier(T)} = ${e}`,G=(e,n)=>{const i=n.filters.map(o=>t`m.${M(o.field)} = ${te(o.value)}`);return e.softDeleteMode&&i.push(t`m.${M(e.softDeleteMode.field)} IS NULL`),i},V=async(e,n,i,o,r,s,a)=>{const c=G(i,r);let u=t`SELECT m.* FROM (${a}) s JOIN ${t.identifier(o)} m ON m.${t.identifier("id")} = s.${t.identifier(l)}`;return c.length>0&&(u=t`${u} WHERE ${t.join(c,t` AND `)}`),u=t`${u} ORDER BY s.${t.identifier("__score__")} DESC, m.${t.identifier("_creationTime")} DESC, m.${t.identifier("id")} ASC LIMIT ${t.raw(String(s))}`,z(i,await C(e,n,u))},Le=async(e,n,i,o,r,s)=>{const a=R(r.query,y(r.definition.language));if(a.length===0)return[];const c=I(o,r.indexName),u=a.length-1,f=a.map((d,_)=>De(d,_===u)),m=t.join(f,t` OR `),$=f.map(d=>t`SUM(CASE WHEN ${d} THEN ${t.identifier(D)} ELSE 0 END)`),E=t.join($.map(d=>t`${d} > 0`),t` AND `),w=t`SELECT ${t.identifier(l)}, ${t.join($,t` + `)} AS ${t.identifier("__score__")} FROM ${t.identifier(c)} WHERE ${m} GROUP BY ${t.identifier(l)} HAVING ${E}`;return V(e,n,i,o,r,s,w)},Ce=async(e,n,i,o,r,s)=>{const a=R(r.query,y(r.definition.language));if(a.length===0)return[];const c=I(o,r.indexName),u=`${c}__vocab`,f=a.length-1,m=a.map((w,d)=>{const _=Re(w,d===f),K=_.exact?t`${t.identifier("term")} = ${_.lower}`:t`${t.identifier("term")} >= ${_.lower} AND ${t.identifier("term")} < ${_.upper}`;return t`SELECT ${t.identifier("doc")}, ${t.raw(String(d))} AS ${t.identifier("__term__")}, COUNT(*) AS ${t.identifier("__n__")} FROM ${t.identifier(u)} WHERE ${K} GROUP BY ${t.identifier("doc")}`}),$=a.map((w,d)=>t`SUM(CASE WHEN u.${t.identifier("__term__")} = ${t.raw(String(d))} THEN u.${t.identifier("__n__")} ELSE 0 END)`),E=t`SELECT f.${t.identifier(l)} AS ${t.identifier(l)}, ${t.join($,t` + `)} AS ${t.identifier("__score__")} FROM (${ee(m)}) u JOIN ${t.identifier(c)} f ON f.rowid = u.${t.identifier("doc")} GROUP BY f.${t.identifier(l)} HAVING ${t.join($.map(w=>t`${w} > 0`),t` AND `)}`;return V(e,n,i,o,r,s,E)},Oe=async(e,n,i,o,r,s)=>{const a=n.nativeTextSearch,c=R(r.query,y(r.definition.language));if(!a||c.length===0)return[];const u=I(o,r.indexName),f=[a.matches(u,c),...G(i,r)],m=t`SELECT m.* FROM ${t.identifier(u)} JOIN ${t.identifier(o)} m ON m.${t.identifier("id")} = ${t.identifier(u)}.${t.identifier(l)} WHERE ${t.join(f,t` AND `)} ORDER BY ${a.rank(u,c)} DESC, m.${t.identifier("_creationTime")} DESC, m.${t.identifier("id")} ASC LIMIT ${t.raw(String(s))}`;return z(i,await C(e,n,m))},qe={ensureCompanion:async(e,n,i)=>{const{integer:o,key:r}=n.companionTypes;await h(e,n,t`CREATE TABLE IF NOT EXISTS ${t.identifier(i)} (${t.identifier(T)} ${t.raw(r)} NOT NULL, ${t.identifier(l)} ${t.raw(r)} NOT NULL, ${t.identifier(D)} ${t.raw(o)} NOT NULL)`),await U(e,n,{columns:t`${b(n,T)}, ${b(n,l)}`,name:`${i}__btree`,table:i,unique:!1}),await U(e,n,{columns:b(n,l),name:`${i}__by_id`,table:i,unique:!1})},indexDocument:async(e,n,i,o,r,s)=>{await A(e,n,i,o);const a=[...Te(O(r,s),y(s.language))],c=t.join([T,l,D].map(f=>t.identifier(f)),t`, `),u=[];for(let f=0;f<a.length;f+=k){const m=t.join(a.slice(f,f+k).map(([$,E])=>t`(${$}, ${o}, ${E})`),t`, `);u.push(t`INSERT INTO ${t.identifier(i)} (${c}) VALUES ${m}`)}await ne(e,n,u)},name:"inverted",runSearch:Le},xe={ensureCompanion:async(e,n,i)=>{await h(e,n,t`CREATE VIRTUAL TABLE IF NOT EXISTS ${t.identifier(i)} USING fts5(${t.identifier(Ee)}, ${t.identifier(l)} UNINDEXED)`),await h(e,n,t`CREATE VIRTUAL TABLE IF NOT EXISTS ${t.identifier(`${i}__vocab`)} USING fts5vocab(${t.identifier(i)}, ${t.raw("instance")})`)},indexDocument:async(e,n,i,o,r,s)=>{await A(e,n,i,o),await h(e,n,t`INSERT INTO ${t.identifier(i)} (${t.identifier("__text__")}, ${t.identifier(l)}) VALUES (${O(r,s)}, ${o})`)},name:"fts5",runSearch:Ce},Ue={ensureCompanion:async(e,n,i)=>{const o=n.nativeTextSearch;if(o){await h(e,n,o.createCompanion(i,n.companionTypes.key));for(const r of o.createIndexes(i))await h(e,n,r)}},indexDocument:async(e,n,i,o,r,s)=>{const a=n.nativeTextSearch;a&&(await A(e,n,i,o),await h(e,n,a.indexDocument(i,o,O(r,s))))},name:"native",runSearch:Oe},N=(e,n)=>e.strategy==="native"&&n.nativeTextSearch!==void 0?Ue:n.supportsFts5?xe:qe,J=(e,n)=>`${y(e.language).profile}/${N(e,n).name}`,q=function*(e){for(const[n,i]of Object.entries(e.tables)){const o=i.searchIndexes;if(!(i.shardMode!==void 0&&i.shardMode.kind!=="global"||!o))for(const r of o)yield[n,i,r]}},x=(e,n)=>I(e,n.name),Ve=async(e,n,i,o,r,s)=>N(r.definition,n).runSearch(e,n,i,o,r,s),H=200,X=async(e,n,i,o,r)=>{const s=x(o,r),a=N(r,n),c=J(r,n),u=Se(await P(e,n,s),c);if(u.finished)return!0;if(u.wipe&&(await h(e,n,t`DELETE FROM ${t.identifier(s)}`),await v(e,n,s,void 0,!1,c)),(await C(e,n,n.tableExists(o))).length===0)return await v(e,n,s,void 0,!0,c),!0;let m=0,$=u.cursor;await ie(e,n,i,o,async w=>{m+=1;const d=w._id;typeof d=="string"&&($=d,await a.indexDocument(e,n,s,d,w,r))},{after:u.cursor,limit:H});const E=m<H;return await v(e,n,s,$,E,c),E},Y=async(e,n,i)=>{await Z(e,i);for(const[o,,r]of q(n)){const s=x(o,r),a=J(r,i),c=await P(e,i,s);c.profile!==void 0&&c.profile!==a&&(await h(e,i,t`DROP TABLE IF EXISTS ${t.identifier(s)}`),await v(e,i,s,void 0,!1,a)),await N(r,i).ensureCompanion(e,i,s)}},Je=async(e,n,i)=>{await Y(e,n,i);for(const[o,r,s]of q(n))s.staged||await X(e,i,r,o,s)},Xe=async(e,n,i)=>{await Y(e,n,i);for(const[o,r,s]of q(n)){let a=!1;for(;!a;)a=await X(e,i,r,o,s)}},Ye=e=>{const{dialect:n,exec:i,schema:o}=e;return async(r,s,a,c)=>{const u=o.tables[r]?.searchIndexes;if(!(!u||u.length===0))for(const f of u){if(ye(c,a,f))continue;const m=x(r,f);if(a){await N(f,n).indexDocument(i,n,m,s,a,f);continue}await A(i,n,m,s)}}};export{Ge as B,We as D,Qe as M,He as R,ze as _,Ve as a,Xe as b,Ye as c,y as j,Je as r,Pe as y};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const r=t=>{if(t.kind!=="optional")return t.kind;const n=t._meta?.inner;return n?r(n):t.kind},f=t=>typeof t=="boolean"?t?1:0:t===null||typeof t=="string"||typeof t=="number"?t:typeof t=="bigint"?t.toString():t instanceof Uint8Array?t:t instanceof ArrayBuffer?new Uint8Array(t):JSON.stringify(t),e=t=>{try{return JSON.parse(t)}catch{return t}},i=t=>{if(typeof t!="string")return t;try{return BigInt(t)}catch{return t}},s=t=>r(t),c=(t,n)=>{if(t===null)return t;switch(n){case"any":case"from":case"union":return typeof t=="string"&&(t.startsWith("{")||t.startsWith("["))?e(t):t;case"array":case"object":case"record":return typeof t=="string"?e(t):t;case"bigint":return i(t);case"boolean":return t===0||t===1?t===1:t;case"bytes":return t instanceof ArrayBuffer?t:ArrayBuffer.isView(t)?new Uint8Array(t.buffer,t.byteOffset,t.byteLength).slice().buffer:t;default:return t}};export{i as decodeBigint,s as effectiveColumnKind,c as sqliteDecode,f as sqliteEncode,e as tryJsonParse};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{renderSql as u}from"@lunora/shard-engine";import{sql as i}from"drizzle-orm";import{sqliteEncode as I,sqliteDecode as y,effectiveColumnKind as C}from"./decodeBigint-B4wY6fcF.mjs";const g=t=>t==="_id"||t==="id"?"id":t,A=t=>i`${i.identifier(g(t))}`,S=(t,n,e)=>{const{params:o,sql:r}=u(n.name,e);return t.all(r,o)},l=(t,n,e)=>{const{params:o,sql:r}=u(n.name,e);return t.run(r,o)},b=async(t,n,e)=>{if(e.length!==0){if(!t.batch){for(const o of e)await l(t,n,o);return}await t.batch(e.map(o=>u(n.name,o)))}},M=async(t,n,e)=>{const o=e.unique?i`UNIQUE `:i``;if(n.name==="mysql"){try{await l(t,n,i`CREATE ${o}INDEX ${i.identifier(e.name)} ON ${i.identifier(e.table)} (${e.columns})`)}catch(r){const a=r;if(a.errno!==1061&&a.code!=="ER_DUP_KEYNAME"&&a.code!==1061)throw r}return}await l(t,n,i`CREATE ${o}INDEX IF NOT EXISTS ${i.identifier(e.name)} ON ${i.identifier(e.table)} (${e.columns})`)},O=I,h=new WeakMap,T=t=>{let n=h.get(t);return n===void 0&&(n=Object.entries(t.shape).map(([e,o])=>[e,C(o)]),h.set(t,n)),n},p=(t,n)=>{const e={};for(const[o,r]of T(t)){const a=n[o];a!==void 0&&(e[o]=y(a,r))}return e._id=n.id,e._creationTime=n._creationTime,e},$=(t,n)=>n?p(t,n):null,D=(t,n)=>{const e=[];for(const o of n){const r=$(t,o);r&&e.push(r)}return e},w=500,K=async(t,n,e,o,r,a={})=>{let d=a.after,c=a.limit,f=!0;for(;f&&(c===void 0||c>0);){const m=c===void 0?w:Math.min(w,c),R=d===void 0?i``:i` WHERE ${i.identifier("id")} > ${d}`,s=await S(t,n,i`SELECT * FROM ${i.identifier(o)}${R} ORDER BY ${i.identifier("id")} ASC LIMIT ${i.raw(String(m))}`);for(const q of s){const E=$(e,q);E&&await r(E)}d=s.at(-1)?.id,f=s.length===m,c=c===void 0?void 0:c-s.length}};export{w as BACKFILL_BATCH_SIZE,A as columnRefSql,M as createIndexIfNotExists,p as decodeGlobalRow,$ as decodeRow,D as decodeRows,K as forEachRowPaged,g as physicalColumn,S as queryAll,b as queryBatch,l as queryRun,O 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.80",
|
|
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.22",
|
|
54
|
+
"@lunora/shard-engine": "1.0.0-alpha.28",
|
|
55
55
|
"drizzle-orm": "^0.45.2"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{sql as i}from"drizzle-orm";import{queryRun as $,queryAll as E}from"./decodeGlobalRow-BwzH1RLd.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 +0,0 @@
|
|
|
1
|
-
import{A as o,F as t,v as s,B as l}from"./ctx-db-search-Cbt6DjpO.mjs";import"@lunora/errors";import"drizzle-orm";import"./SEARCH_STATE_TABLE-Bw9dhHy2.mjs";import"./decodeGlobalRow-BwzH1RLd.mjs";export{o as backfillSqlSearchIndexes,t as createSearchSync,s as runSqlSearch,l as runSqlSearchMigrations};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as N}from"@lunora/errors";import{F as gt,B as bt,T as Nt,x as Tt,_ as vt,C as Rt,v as St,D as It,b as At,N as Lt}from"./ctx-db-search-Cbt6DjpO.mjs";import{A as xi}from"./ctx-db-search-Cbt6DjpO.mjs";import{aggregateTableName as G,rankTableName as Q,hasTrigger as Ot,runRowValidators as Oe,assertFlatPredicate as Je,mergeWhere as x,sortColumnName as z,resolveRankPartition as Xe,encodePartitionKey as Te,decodeCursor as Qe,RANK_TIEBREAK as $e,CountRlsUnsupportedError as Ze,normalizeIdStructurally as kt,assertValidClientId as Ct,aggregateSqlFunction as ue,softDeleteScope as fe,compileWhereSql as _e,literalInList as xt,normalizeOrderKeys as Mt,buildSeekWhere as Dt,resolveRelationPredicates as et,resolveWith as tt,relationHooks as it,applySelect as nt,encodeCursor as qt,NotFoundError as Wt,applyOnDelete as Bt,ConflictError as we,normalizeCountArgument as Ft,selectIndexForCount as Ut,encodeAggregateKey as Y,selectIndexForAggregate as jt,readAggregateValue as ke,runTriggers as Pt,matchesRankStaticWhere as at,selectIndexForGroupBy as Ht,fanOutScalarCounts as Kt,matchesStaticWhere as Ce,foldAggregateTally as Vt,coerceAggregateNumber as xe,NotUniqueError as Yt,throwingScheduler as Gt}from"@lunora/shard-engine";import{sql as e}from"drizzle-orm";import{migrateSearchState as zt}from"./SEARCH_STATE_TABLE-Bw9dhHy2.mjs";import{queryAll as I,queryRun as A,createIndexIfNotExists as De,decodeRow as Z,serializeColumnValue as H,columnRefSql as M,decodeRows as Jt,forEachRowPaged as ot,queryBatch as rt}from"./decodeGlobalRow-BwzH1RLd.mjs";import{decodeGlobalRow as Di}from"./decodeGlobalRow-BwzH1RLd.mjs";import{effectiveColumnKind as ve}from"./decodeBigint-DrEQib7C.mjs";const Xt=(d,w)=>{if(d.size<w)return;const f=d.keys().next().value;f!==void 0&&d.delete(f)},Qt=(d,w={})=>{const f=w.maxBatch??50,o=Number.isInteger(f)&&f>0?f:50,m=new Map;let l=!1;const s=async(y,v)=>{const R=[...v.keys()];for(let L=0;L<R.length;L+=o){const D=R.slice(L,L+o);try{const B=await d(y,D);for(const K of D){const F=B.get(K);for(const Se of v.get(K)??[])Se.resolve(F)}}catch(B){for(const K of D)for(const F of v.get(K)??[])F.reject(B)}}},g=()=>{l=!1;const y=[...m.entries()];m.clear();for(const[v,R]of y)s(v,R).catch(()=>{})};return{async load(y,v){return new Promise((R,L)=>{let D=m.get(y);D||(D=new Map,m.set(y,D));const B=D.get(v);B?B.push({reject:L,resolve:R}):D.set(v,[{reject:L,resolve:R}]),l||(l=!0,queueMicrotask(g))})}}},Zt=new Set(["_id","id"]),qe=(d,w,f)=>d==="postgres"?e`${w} IS NOT DISTINCT FROM ${f}`:d==="mysql"?e`${w} <=> ${f}`:e`${w} IS ${f}`,ei=d=>{const w=d.map(f=>e`${M(f.field)} ${e.raw(f.direction==="desc"?"DESC":"ASC")}`);return d.some(f=>Zt.has(f.field))||w.push(e`${M("id")} ASC`),e.join(w,e`, `)},st=50,We=d=>{const w=[];for(const[f,o]of Object.entries(d.shape)){const m=o._meta?.column;m&&w.push([f,m])}return w},ti=(d,w,f)=>{const o={...w};for(const[m,l]of We(d)){if(l.serverDefault){o[m]=l.serverDefault({auth:f});continue}o[m]===void 0&&(l.defaultFn?o[m]=l.defaultFn():"defaultValue"in l&&(o[m]=l.defaultValue))}return o},ct=(d,w,f,o)=>{for(const[m,l]of We(d)){if(l.serverDefault){m in w&&(f[m]=l.serverDefault({auth:o}));continue}l.onUpdateFn&&!(m in w)&&(f[m]=l.onUpdateFn())}},ii=128,ni=()=>{const d=new Map;return{delete:w=>{d.delete(w)},get:w=>{const f=d.get(w);if(f!==void 0)return d.delete(w),d.set(w,f),f},set:(w,f)=>{d.has(w)?d.delete(w):Xt(d,ii),d.set(w,f)}}},ai=async(d,w,f,o,m)=>{const l=m.get(o);if(l!==void 0)return l;const s=Object.entries(f.tables).filter(([,y])=>y.shardMode===void 0||y.shardMode.kind==="global").map(([y])=>y),g=await Promise.all(s.map(async y=>({found:(await I(d,w,e`SELECT 1 FROM ${e.identifier(y)} WHERE ${e.identifier("id")} = ${o} LIMIT 1`)).length>0,tableName:y})));for(const y of g)if(y.found)return m.set(o,y.tableName),y.tableName},ee=d=>d==null?null:Number(d),oi=(d,w)=>w.map(f=>{const o={};for(const m of d)o[m]=f[m]??null;return{key:o,value:ee(f.value)}}),ri=(d,w,f)=>[...d.partitionBy??[],...d.sortBy.map(o=>o.field),...d.where?Object.keys(d.where):[]].every(o=>w[o]===f[o]),lt=d=>d.length===1?d[0]:e`(${e.join(d,e` AND `)})`,X=d=>e.join(d.map(w=>e`${e.identifier(w)}`),e`, `),te=d=>e.join(d.map(w=>e`${w}`),e`, `),si=(d,w,f,o,m)=>{const l=[];for(let s=0;s<f.length+1;s+=1){const g=f.slice(0,s).map(R=>qe(d,e`${e.identifier(R)}`,o[R])),y=f[s],v=w.sortBy[s];s<f.length&&y!==void 0&&v!==void 0?g.push(e`${e.identifier(y)} ${e.raw(v.direction==="desc"?">":"<")} ${o[y]}`):g.push(e`${e.identifier($e)} < ${m}`),l.push(lt(g))}return l.length>0?e.join(l,e` OR `):void 0},ci=(d,w,f)=>{if(f.length!==w.length)return;const o=[];for(const[m,l]of w.entries()){const s=[];for(let g=0;g<m;g+=1){const y=w[g];y!==void 0&&s.push(qe(d,e`${e.identifier(y.column)}`,f[g]))}s.push(e`${e.identifier(l.column)} ${e.raw(l.direction==="desc"?"<":">")} ${f[m]}`),o.push(lt(s))}return e`(${e.join(o,e` OR `)})`},li=(d,w)=>{if(d.sortBy.length===0)throw new N("INTERNAL",`rankIndex "${d.name}" requires at least one "sortBy" column for stable pagination`);const f=[{column:"__partition__",direction:"asc"}];for(const[o,m]of d.sortBy.entries())f.push({column:w[o]??z(o),direction:m.direction});return f.push({column:$e,direction:"asc"}),f},di=async(d,w,f,o,m)=>{const l=[];for(let v=0;v<m.length;v+=50)l.push(m.slice(v,v+50));const s=await Promise.all(l.map(async v=>I(d,w,e`SELECT * FROM ${e.identifier(o)} WHERE ${e.identifier("id")} IN (${te(v)})`))),g=new Map;for(const v of s)for(const R of v)g.set(R.id,R);const y=[];for(const v of m){const R=Z(f,g.get(v));R&&y.push(R)}return y},ui=d=>{const w=JSON.stringify(d),f=new TextEncoder().encode(w);let o="";for(const m of f)o+=String.fromCodePoint(m);return btoa(o)},fi=(d,w)=>w.columnType(ve(d)),_i=(d,w,f)=>{const o=[];for(const[s,g]of Object.entries(w.shape)){if(!g._meta?.column)continue;const y=g._meta.column.notNull&&g.kind!=="optional"?" NOT NULL":"";o.push(e`${e.identifier(s)} ${e.raw(`${fi(g,f)}${y}`)}`)}const m=f.frameworkColumns().map(s=>e`${e.identifier(s.name)} ${e.raw(s.type)}`),l=m.length+o.length;if(f.maxTableColumns!==void 0&&l>f.maxTableColumns)throw new N("VALIDATION_ERROR",`@lunora/sql-store: global table "${d}" needs ${String(l)} columns, over this engine's ${String(f.maxTableColumns)}-column limit — split the table, or move the extra fields into one object field`);return e.join([...m,...o],e`, `)},wi=async(d,w,f,o)=>{const m=l=>{const s=M(l),g=f.shape[l],y=g&&o.indexKeyPrefix?o.indexKeyPrefix(ve(g)):void 0;return y===void 0?s:e`${s}(${e.raw(String(y))})`};for(const l of f.indexes){const s=e.join(l.fields.map(g=>m(g)),e`, `);await De(d,o,{columns:s,name:`${w}_${l.name}`,table:w,unique:l.unique??!1})}for(const[l,s]of We(f))s.unique&&await De(d,o,{columns:m(l),name:`${w}_unique_${l}`,table:w,unique:!0})},$i=async(d,w,f)=>{for(const[o,m]of Object.entries(w.tables)){if(m.shardMode?.kind!=="global")continue;const l=_i(o,m,f);await A(d,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(o)} (${l})`),await wi(d,o,m,f)}},hi=async(d,w,f)=>{const{integer:o,key:m,real:l}=f.companionTypes;for(const[s,g]of Object.entries(w.tables)){const y=g.aggregateIndexes;if(!(!y||y.length===0))for(const v of y){const R=G(s,v.name);await A(d,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(R)} (${e.identifier("__key__")} ${e.raw(m)} PRIMARY KEY, ${e.identifier("__value__")} ${e.raw(l)}, ${e.identifier("__count__")} ${e.raw(o)} NOT NULL DEFAULT 0)`),f.name==="sqlite"&&((await I(d,f,e`PRAGMA table_info(${e.identifier(R)})`)).some(L=>L.name==="__count__")||await A(d,f,e`ALTER TABLE ${e.identifier(R)} ADD COLUMN ${e.identifier("__count__")} ${e.raw(o)} NOT NULL DEFAULT 0`))}}},Me=(d,w,f,o)=>{const m=d.name==="mysql"&&o?e`${e.identifier(w)}(191)`:e`${e.identifier(w)}`;return e`${m} ${e.raw(f)}`},pi=(d,w,f)=>{const o=[Me(d,"__partition__","ASC",!0)];for(const[m,l]of w.sortBy.entries()){const s=f.shape[l.field],g=s!==void 0&&d.indexKeyPrefix?.(ve(s))!==void 0;o.push(Me(d,z(m),l.direction==="desc"?"DESC":"ASC",g))}return o.push(Me(d,"__id__","ASC",!0)),o},mi=(d,w,f)=>w.sortBy.map((o,m)=>{const l=f.shape[o.field],s=d.columnType(l?ve(l):void 0);return e`${e.identifier(z(m))} ${e.raw(s)}`}),Ei=async(d,w,f)=>{const{key:o}=f.companionTypes;for(const[m,l]of Object.entries(w.tables)){const s=l.rankIndexes;if(!(!s||s.length===0))for(const g of s){const y=Q(m,g.name),v=mi(f,g,l),R=v.length>0?e`, ${e.join(v,e`, `)}`:e``;await A(d,f,e`CREATE TABLE IF NOT EXISTS ${e.identifier(y)} (${e.identifier("__id__")} ${e.raw(o)} PRIMARY KEY, ${e.identifier("__partition__")} ${e.raw(o)} NOT NULL${R})`);const L=pi(f,g,l),D=`${m}__rank_${g.name}__btree`;await De(d,f,{columns:e.join(L,e`, `),name:D,table:y,unique:!1})}}},Re="__cdc_log",yi=async(d,w)=>{const{autoincrementPrimaryKey:f,key:o,real:m,text:l}=w.companionTypes;await A(d,w,e`CREATE TABLE IF NOT EXISTS ${e.identifier(Re)} (${e.identifier("seq")} ${e.raw(f)}, ${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(l)})`)},gi=async(d,w,f,o,m,l,s)=>{await A(d,s,e`INSERT INTO ${e.identifier(Re)} (${e.identifier("ts")}, ${e.identifier("table")}, ${e.identifier("id")}, ${e.identifier("op")}, ${e.identifier("doc")}) VALUES (${w}, ${f}, ${o}, ${m}, ${l===void 0?null:JSON.stringify(l)})`)},Ai=async(d,w,f)=>{const o=w.sinceSeq??0,m=Math.max(1,Math.min(w.limit??1e3,1e4)),l=(await I(d,f,e`SELECT seq, ts, ${e.identifier("table")}, id, op, doc FROM ${e.identifier(Re)} WHERE seq > ${o} ORDER BY seq ASC LIMIT ${e.raw(String(m))}`)).map(s=>{const{doc:g}=s,y={id:String(s.id),op:String(s.op),seq:Number(s.seq),table:String(s.table),ts:Number(s.ts)};return typeof g=="string"?{...y,doc:JSON.parse(g)}:y});return{changes:l,cursor:l.at(-1)?.seq??o}},Li=async(d,w,f)=>{await A(d,f,e`DELETE FROM ${e.identifier(Re)} WHERE ${e.identifier("seq")} <= ${w}`)},Oi=d=>{const{crossShardCounter:w,crossShardReader:f,exec:o,maxRelationKeys:m,schema:l}=d,{dialect:s}=d,{isUniqueViolation:g}=s,y={fieldRef:M,serialize:H,...s.name==="mysql"?{containsExpr:(t,i)=>e`LOCATE(${i}, ${t}) > 0`}:{},...s.name==="postgres"?{containsExpr:(t,i)=>e`strpos(${t}, ${i}) > 0`}:{},...s.name==="sqlite"?{}:{inList:xt}},v=(t,i)=>qe(s.name,t,i),R=t=>{const i=X(t.columns),n=te(t.values),a=u=>s.name==="mysql"?e`VALUES(${e.identifier(u)})`:e`excluded.${e.identifier(u)}`,r=u=>s.name==="postgres"?e`${e.identifier(t.table)}.${e.identifier(u)}`:e`${e.identifier(u)}`,_=e.join(Object.entries(t.set(a,r)).map(([u,p])=>e`${e.identifier(u)} = ${p}`),e`, `),$=s.name==="mysql"?e`ON DUPLICATE KEY UPDATE ${_}`:e`ON CONFLICT(${e.identifier(t.conflictKey)}) DO UPDATE SET ${_}`;return e`INSERT INTO ${e.identifier(t.table)} (${i}) VALUES (${n}) ${$}`},L=d.clock??(()=>Date.now()),D=d.idGenerator??(()=>crypto.randomUUID()),B=d.cdc??!1,K=d.auth??{identity:null,userId:null},F=async(t,i,n,a)=>{B&&await gi(o,L(),t,i,n,a,s)},Se=d.scheduler??Gt,Ie=ni();let he=0,Ae;const U=async()=>(Ae??=(async()=>{await $i(o,l,s),await hi(o,l,s),await Ei(o,l,s),await zt(o,s),await bt(o,l,s),B&&await yi(o,s)})().catch(t=>{throw Ae=void 0,t}),Ae),ie=async(t,i)=>{await U();const n=await ai(o,s,l,t,Ie);if(!(i!==void 0&&n!==i))return n},ne=new Map,Be=async(t,i)=>{const n=G(t,i);return(await I(o,s,s.tableExists(n))).length>0},pe=async(t,i)=>{const n=`${t}::${i.name}`,a=ne.get(n);if(a!==void 0)return a;if(!await Be(t,i.name))return ne.set(n,!1),!1;const r=l.tables[t];if(!r)return ne.set(n,!1),!1;const _=i.by??[],$=new Map;await ot(o,s,r,t,c=>{if(i.where&&!Ce(c,i.where))return;const h=Y(_,c);Vt($,h,i,c)});const u=G(t,i.name);await A(o,s,e`DELETE FROM ${e.identifier(u)}`);const p=[];for(const[c,h]of $)p.push(e`INSERT INTO ${e.identifier(u)} (${e.identifier("__key__")}, ${e.identifier("__value__")}, ${e.identifier("__count__")}) VALUES (${c}, ${h.value}, ${h.count})`);return await rt(o,s,p),ne.set(n,!0),!0},dt=async(t,i,n)=>{const a=ue(i.op),r=i.field??"",_=[];for(const p of i.by??[]){const c=H(n[p]??null);_.push(c===null?e`${M(p)} IS NULL`:e`${M(p)} = ${c}`)}for(const[p,c]of Object.entries(i.where??{})){const h=c!==null&&typeof c=="object"&&!Array.isArray(c)?c.eq:c,E=H(h);_.push(E===null?e`${M(p)} IS NULL`:e`${M(p)} = ${E}`)}const $=e`SELECT ${e.raw(a)}(${M(r)}) AS value FROM ${e.identifier(t)}`,u=await I(o,s,_.length>0?e`${$} WHERE ${e.join(_,e` AND `)}`:$);return ee(u[0]?.value)},ut=async(t,i)=>{await A(o,s,e`DELETE FROM ${e.identifier(t)} WHERE ${e.identifier("__key__")} = ${i} AND ${e.identifier("__count__")} <= 0`)},ft=async(t,i,n,a)=>{const r=G(t,i.name),{op:_}=i,$=i.field??"",u=n&&(!i.where||Ce(n,i.where))?n:void 0,p=a&&(!i.where||Ce(a,i.where))?a:void 0;if(!(!u&&!p)){if(_==="count"||_==="sum"||_==="avg"){const c=new Set;for(const[h,E]of[[u,-1],[p,1]]){if(!h)continue;const b=_==="count"?1:xe(h[$]);if(b===void 0)continue;const T=Y(i.by??[],h);c.add(T),await A(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(S,O)=>({__count__:e`${O("__count__")} + ${S("__count__")}`,__value__:_==="count"?e`${O("__value__")} + ${S("__value__")}`:e`COALESCE(${O("__value__")}, 0) + ${S("__value__")}`}),table:r,values:[T,E*b,E]}))}for(const h of c)await ut(r,h);return}if(u){const c=Y(i.by??[],u),h=xe(u[$]),E=(await I(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${c}`))[0],b=ee(E?.value),T=(E?.count??0)-1;if(T<=0)await A(o,s,e`DELETE FROM ${e.identifier(r)} WHERE ${e.identifier("__key__")} = ${c}`);else if(E&&h!==void 0&&b!==null&&h===b){const S=await dt(t,i,u);await A(o,s,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__value__")} = ${S}, ${e.identifier("__count__")} = ${T} WHERE ${e.identifier("__key__")} = ${c}`)}else await A(o,s,e`UPDATE ${e.identifier(r)} SET ${e.identifier("__count__")} = ${e.identifier("__count__")} - 1 WHERE ${e.identifier("__key__")} = ${c}`)}if(p){const c=Y(i.by??[],p),h=xe(p[$]);if(h===void 0)await A(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(E,b)=>({__count__:e`${b("__count__")} + 1`}),table:r,values:[c,null,1]}));else{const E=_==="min"?"MIN":"MAX";await A(o,s,R({columns:["__key__","__value__","__count__"],conflictKey:"__key__",set:(b,T)=>({__count__:e`${T("__count__")} + 1`,__value__:e`${e.raw(E)}(COALESCE(${T("__value__")}, ${b("__value__")}), ${b("__value__")})`}),table:r,values:[c,h,1]}))}}}},me=async t=>{const i=l.tables[t]?.aggregateIndexes;if(!(!i||i.length===0))for(const n of i)await pe(t,n)},ae=async(t,i,n)=>{const a=l.tables[t]?.aggregateIndexes;if(!(!a||a.length===0))for(const r of a){const _=`${t}::${r.name}`;(ne.get(_)??await Be(t,r.name))&&await ft(t,r,i,n)}},oe=new Map,Fe=async(t,i)=>{const n=Q(t,i);return(await I(o,s,s.tableExists(n))).length>0},Le=async(t,i)=>{const n=`${t}::rank::${i.name}`,a=oe.get(n);if(a!==void 0)return a;if(!await Fe(t,i.name))return oe.set(n,!1),!1;const r=l.tables[t];if(!r)return oe.set(n,!1),!1;const _=Q(t,i.name);await A(o,s,e`DELETE FROM ${e.identifier(_)}`);const $=i.sortBy.map((h,E)=>z(E)),u=X(["__id__","__partition__",...$]),p=[];await ot(o,s,r,t,h=>{if(i.where&&!at(h,i.where))return;const E=Te(i.partitionBy??[],h),b=i.sortBy.map(T=>H(h[T.field]??null));p.push([h._id,E,...b])});const c=p.map(h=>e`INSERT INTO ${e.identifier(_)} (${u}) VALUES (${te(h)})`);return await rt(o,s,c),oe.set(n,!0),!0},Ee=async t=>{const i=l.tables[t]?.rankIndexes;if(!(!i||i.length===0))for(const n of i)await Le(t,n)},J=async(t,i,n,a)=>{const r=l.tables[t],_=r?.rankIndexes;if(!_||_.length===0)return;const $=r?.softDeleteMode?.field,u=$===void 0||a===void 0?void 0:a[$],p=u!=null;for(const c of _){if(n!==void 0&&a!==void 0&&ri(c,n,a))continue;const h=`${t}::rank::${c.name}`;if(!(oe.get(h)??await Fe(t,c.name)))continue;const E=Q(t,c.name);if(n&&await A(o,s,e`DELETE FROM ${e.identifier(E)} WHERE ${e.identifier("__id__")} = ${i}`),a&&!p){if(c.where&&!at(a,c.where))continue;const b=c.sortBy.map((q,k)=>z(k)),T=X(["__id__","__partition__",...b]),S=Te(c.partitionBy??[],a),O=c.sortBy.map(q=>H(a[q.field]??null));await A(o,s,e`INSERT INTO ${e.identifier(E)} (${T}) VALUES (${te([i,S,...O])})`)}}},re=gt({dialect:s,exec:o,schema:l}),Ue=new Set;for(const[t,i]of Object.entries(l.tables))for(const n of Object.values(i.triggerMap??{}))Ue.add(`${t} ${n.timing} ${n.op}`);const j=(t,i,n)=>Ue.has(`${t} ${i} ${n}`);let je;const P=async(t,i,n)=>{if(he+=1,he>st)throw he-=1,new we(`trigger recursion exceeded ${String(st)} levels on "${n.table}" — check for a self-triggering write`,"trigger");try{await Pt({ctx:je,event:n,op:i,schema:l,tableName:n.table,timing:t})}finally{he-=1}},_t=async(t,i)=>{try{await A(o,s,i)}catch(n){throw g(n)?new we(`unique constraint violation on "${t}"`,"unique"):n}},ye=async(t,i)=>(await I(o,s,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} = ${i}`))[0],ge=async(t,i,n,a)=>{if(a===void 0)return;const r=e.join(Object.keys(a).map(u=>v(e`${e.identifier(u)}`,a[u])),e` AND `),_=i==="UPDATE"?e`UPDATE ${e.identifier(t)} SET ${n} WHERE ${r}`:e`DELETE FROM ${e.identifier(t)} WHERE ${r}`,$=()=>{throw new we(`optimistic concurrency conflict on "${t}" — the row changed during this mutation; refetch and retry`,"occ")};try{if(s.supportsReturning)(await I(o,s,e`${_} RETURNING ${e.identifier("id")}`)).length===0&&$();else{const u=await A(o,s,_);(s.affectedRows?s.affectedRows(u??{rowsAffected:0}):0)===0&&$()}}catch(u){throw g(u)?new we(`unique constraint violation on "${t}"`,"unique"):u}},wt=(t,i,n,a)=>{const r=Object.keys(t.shape);return{columns:["id","_creationTime",...r],values:[i,n,...r.map(_=>H(a[_]??null))]}},$t=async(t,i,n,a)=>{const r=Ht(i,n.op,n.field,a.by,a.where);if(!r||!await pe(t,r.index))return;const _=G(t,r.index.name),$=Object.keys(r.partial);if($.length===(r.index.by??[]).length&&$.length>0){const u=Y(r.index.by??[],r.partial),p=await I(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(_)} WHERE ${e.identifier("__key__")} = ${u}`);if(p.length===0)return[];const c=p[0];return[{key:{...r.partial},value:ke(n.op,{count:c.count,value:ee(c.value)})}]}return $.length>0?void 0:(await I(o,s,e`SELECT ${e.identifier("__key__")} AS key, ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(_)}`)).map(u=>{const p=u;return{key:JSON.parse(p.key),value:ke(n.op,{count:p.count,value:ee(p.value)})}})},Pe=t=>{const i=l.tables[t]?.shardMode?.kind;return i==="shardBy"||i==="root"},He=t=>{throw new N("INTERNAL",`cross-backend relation: a global table cannot load the shard-local relation '${t}' (it spans every shard) — wire a cross-shard reader to support it`)},ht=(t,i)=>{if(i?.relationMask!==void 0&&i.with!==void 0&&Object.keys(i.with).length>0)throw new N("MASK_UNSUPPORTED",`masking cannot follow a nested \`with\` across the cross-shard relation hop to "${t}" — the nested rows are hydrated on the serving shard, where the mask policy does not exist. Read the nested relation at its own (masked) call site instead.`);const n={};if(i?.relationBaseWhere)for(const a of Object.keys(l.tables)){const r=i.relationBaseWhere(a);r!==void 0&&(n[a]=r)}return{orderBy:i?.orderBy,relationPolicies:n,where:x(i?.baseWhere,i?.where),with:i?.with}},Ke=(t,i)=>Pe(t)?f?f(t,ht(t,i)):He(t):W.findMany(t,i),be=(t,i,n)=>et(t,{fetcher:Ke,maxRelationKeys:m,relationBaseWhere:n,schema:l,tableName:i}),pt=Qt(async(t,i)=>{const n=await I(o,s,e`SELECT * FROM ${e.identifier(t)} WHERE ${e.identifier("id")} IN (${te(i)})`),a=new Map;for(const r of n){const{id:_}=r;typeof _=="string"&&a.set(_,r)}return a}),W={async aggregate(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);if(await U(),ue(i.op),i.op==="count")return W.count(t,{baseWhere:i.baseWhere,relationBaseWhere:i.relationBaseWhere,restrictsCounts:i.restrictsCounts,where:i.where});if(!i.field)throw new N("INTERNAL",`aggregate(${t}, { op: "${i.op}" }): "field" is required for non-count reducers`);const a=fe(n.softDeleteMode,void 0),r=x(x(i.baseWhere,i.where),a),_=await be(r,t,i.relationBaseWhere),$=_!==r;if(n.aggregateIndexes&&!i.baseWhere&&!$&&!a){const E=jt(n.aggregateIndexes,i.op,i.field,i.where);if(E&&await pe(t,E.index)){const b=Y(E.index.by??[],E.key),T=G(t,E.index.name),S=(await I(o,s,e`SELECT ${e.identifier("__value__")} AS value, ${e.identifier("__count__")} AS count FROM ${e.identifier(T)} WHERE ${e.identifier("__key__")} = ${b}`))[0];return ke(i.op,S===void 0?void 0:{count:S.count,value:ee(S.value)})}}const u=_e(_,y),p=e.raw(ue(i.op)),c=e`SELECT ${p}(${M(i.field)}) AS value FROM ${e.identifier(t)}`,h=(await I(o,s,u?e`${c} WHERE ${u}`:c))[0]?.value;return h==null?null:Number(h)},async count(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await U();const a=Ft(i);if(a.restrictsCounts)throw new Ze(t);const r=fe(n.softDeleteMode,void 0),_=x(x(a.baseWhere,a.where),r),$=await be(_,t,a.relationBaseWhere),u=$!==_;if(n.aggregateIndexes&&!a.baseWhere&&!u&&!r){const E=Ut(n.aggregateIndexes,a.where);if(E&&await pe(t,E.index)){const b=Y(E.index.by??[],E.key),T=G(t,E.index.name),S=await I(o,s,e`SELECT ${e.identifier("__value__")} AS value FROM ${e.identifier(T)} WHERE ${e.identifier("__key__")} = ${b}`);return Number(S[0]?.value??0)}}const p=_e($,y),c=e`SELECT COUNT(*) AS count FROM ${e.identifier(t)}`,h=await I(o,s,p?e`${c} WHERE ${p}`:c);return Number(h[0]?.count??0)},async delete(t,i,n){const a=await ie(t,i);if(!a)return;const r=l.tables[a];if(!r)return;const _=await ye(a,t),$=Z(r,_),u=n?.hard===!0,p=!u&&r.softDeleteMode?r.softDeleteMode.field:void 0;if(!(p&&(!$||$[p]!==null&&$[p]!==void 0))){if(j(a,"before","delete")&&await P("before","delete",{id:t,op:"delete",previous:$??void 0,table:a}),await Bt({deletedId:t,deletedReference:c=>$?.[c],findHolders:async(c,h,E)=>{if(l.tables[c]?.shardMode?.kind==="shardBy")throw new N("INTERNAL",`cross-backend cascade from global '${a}' into shardBy '${c}' is not supported — would require Query Coordinator fan-out across shards`);return(await W.findMany(c,{includeDeleted:u,where:{[h]:E}})).page},onCascade:(c,h)=>W.delete(h,void 0,n),onRestrict:c=>{throw new we(c,"restrict")},onSetNull:(c,h,E)=>W.patch(h,{[E]:null}),schema:l,tableName:a}),await me(a),await Ee(a),p&&$){const c={...$,[p]:L()},h=e.join(Object.keys(r.shape).map(E=>e`${e.identifier(E)} = ${H(c[E]??null)}`),e`, `);await ge(a,"UPDATE",h,_),await ae(a,$,c),await J(a,t,$,void 0),await re(a,t,c,$),await F(a,t,"update",c),j(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:$,table:a});return}await ge(a,"DELETE",void 0,_),Ie.delete(t),await ae(a,$??void 0,void 0),await J(a,t,$??void 0,void 0),await re(a,t,void 0),await F(a,t,"delete"),j(a,"after","delete")&&await P("after","delete",{id:t,op:"delete",previous:$??void 0,table:a})}},async findFirst(t,i={}){return(await 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 Wt(`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 U();const a=Mt(i.orderBy),r=i.cursor?Dt(a,Qe(i.cursor)):void 0,_=Ke,$=async(k,se,Ne,ce)=>{if(Pe(k))return w?Kt(w,k,se,Ne,ce):He(k);const V=l.tables[k];if(!V)throw new N("INTERNAL",`unknown table: ${k}`);const C=fe(V.softDeleteMode,void 0),le={[se]:{in:Ne}},mt=x(x(le,ce),C),Et=await be(mt,k,void 0),Ve=_e(Et,y),Ye=M(se);let de=e`SELECT ${Ye} AS __fk__, COUNT(*) AS count FROM ${e.identifier(k)}`;Ve&&(de=e`${de} WHERE ${Ve}`),de=e`${de} GROUP BY ${Ye}`;const yt=await I(o,s,de),Ge=new Map;for(const ze of yt)Ge.set(ze.__fk__,Number(ze.count??0));return Ge};let u=x(i.baseWhere,i.where);u=x(u,fe(n.softDeleteMode,i.includeDeleted)),u=await et(u,{fetcher:_,maxRelationKeys:m,relationBaseWhere:i.relationBaseWhere,schema:l,tableName:t}),r&&(u=u?{AND:[u,r]}:r);const p=_e(u,y),c=ei(a);let h=e`SELECT * FROM ${e.identifier(t)}`;p&&(h=e`${h} WHERE ${p}`),h=e`${h} ORDER BY ${c}`;const E=typeof i.limit=="number"?Math.max(0,Math.floor(i.limit)):void 0;E!==void 0&&(h=e`${h} LIMIT ${e.raw(String(E+1))}`);const b=await I(o,s,h),T=Jt(n,b);if(E===void 0)return i.with&&await tt({fetcher:_,groupedCounter:$,parents:T,...it(i),schema:l,tableName:t,with:i.with}),{continueCursor:null,isDone:!0,page:nt(T,i.select,i.with)};const S=T.length>E,O=S?T.slice(0,E):T,q=O.at(-1);return i.with&&await tt({fetcher:_,groupedCounter:$,parents:O,...it(i),schema:l,tableName:t,with:i.with}),{continueCursor:S&&q?qt(q,a):null,isDone:!S,page:nt(O,i.select,i.with)}},async get(t,i){const n=await ie(t,i);if(!n)return null;const a=l.tables[n];return a?Z(a,await pt.load(n,t)):null},async groupBy(t,i){const n=l.tables[t];if(!n)throw new N("INTERNAL",`unknown table: ${t}`);await U();const a=i.agg??{op:"count"};if(ue(a.op),a.op!=="count"&&!a.field)throw new N("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);const r=fe(n.softDeleteMode,void 0),_=x(x(i.baseWhere,i.where),r),$=await be(_,t,i.relationBaseWhere),u=$!==_;if(n.aggregateIndexes&&!i.baseWhere&&!u&&!r){const T=await $t(t,n.aggregateIndexes,a,i);if(T!==void 0)return T}const p=_e($,y),c=i.by.map(T=>e`${M(T)} AS ${e.identifier(T)}`);if(a.op==="count")c.push(e`COUNT(*) AS value`);else{if(!a.field)throw new N("INTERNAL",`groupBy(${t}, { agg: { op: "${a.op}" } }): "field" is required for non-count reducers`);c.push(e`${e.raw(ue(a.op))}(${M(a.field)}) AS value`)}const h=e.join(i.by.map(T=>M(T)),e`, `);let E=e`SELECT ${e.join(c,e`, `)} FROM ${e.identifier(t)}`;p&&(E=e`${E} WHERE ${p}`),E=e`${E} GROUP BY ${h}`;const b=await I(o,s,E);return oi(i.by,b)},async insert(t,i,n){const a=l.tables[t];if(!a)throw new N("INTERNAL",`unknown table: ${t}`);await U();const r=ti(a,i,K);Oe(a,r);let _,$=!0;n?.clientId!==void 0?(Ct(n.clientId),_=n.clientId):n?.allowExplicitId&&typeof r._id=="string"?_=r._id:(_=D(),$=!1);const u=n?.allowExplicitId&&typeof r._creationTime=="number"?r._creationTime:L(),p={...r,_creationTime:u,_id:_};j(t,"before","insert")&&await P("before","insert",{doc:{...p},id:_,op:"insert",table:t}),await me(t),await Ee(t);const{columns:c,values:h}=wt(a,_,u,r);return await _t(t,e`INSERT INTO ${e.identifier(t)} (${X(c)}) VALUES (${te(h)})`),$&&Ie.set(_,t),await ae(t,void 0,p),await J(t,_,void 0,p),await re(t,_,p),await F(t,_,"insert",p),j(t,"after","insert")&&await P("after","insert",{doc:p,id:_,op:"insert",table:t}),_},normalizeId(t,i){return kt(l,t,i)},async patch(t,i,n){const a=await ie(t,n);if(!a)throw new N("INTERNAL",`document not found: ${t}`);const r=l.tables[a];if(!r)throw new N("INTERNAL",`document not found: ${t}`);const _=await ye(a,t),$=Z(r,_);if(!$)throw new N("INTERNAL",`document not found: ${t}`);const u={...$,...i,_id:t};ct(r,i,u,K),Oe(r,u,!0),j(a,"before","update")&&await P("before","update",{doc:{...u},id:t,op:"update",previous:$,table:a}),await me(a),await Ee(a);const p=Object.keys(r.shape),c=e.join(p.map(h=>e`${e.identifier(h)} = ${H(u[h]??null)}`),e`, `);await ge(a,"UPDATE",c,_),await ae(a,$,u),await J(a,t,$,u),await re(a,t,u,$),await F(a,t,"update",u),j(a,"after","update")&&await P("after","update",{doc:u,id:t,op:"update",previous:$,table:a})},async restore(t,i){const n=await ie(t,i);if(!n)throw new N("INTERNAL",`document not found: ${t}`);const a=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 _=await ye(n,t),$=_?.[r]!==null&&_?.[r]!==void 0;if(await W.patch(t,{[r]:null},i),$){const u=Z(a,_);u!==null&&await J(n,t,void 0,{...u,[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=u=>a.every(p=>p(u)),_=async(u,p)=>{await U();const c=a.length>0,h=await St(o,s,i,t,u,It(c?void 0:p));if(!c)return p===void 0&&At(h),h;const E=h.filter(b=>r(b));return p===void 0?E:E.slice(0,p)},$=u=>{const p={async*[Symbol.asyncIterator](){if(!u)throw new N("INTERNAL",n);yield*await _(u,void 0)},async collect(){if(!u)throw new N("INTERNAL",n);return _(u,void 0)},async collectWithScores(){throw new N("INTERNAL",`collectWithScores() is not supported on \`.global()\` tables (table "${t}") — relevance scores are not yet surfaced on this backend; use .collect() instead`)},filter(c){return a.push(c),p},async first(){if(!u)throw new N("INTERNAL",n);return(await _(u,1))[0]??null},order(){return p},async paginate(c){if(!u)throw new N("INTERNAL",n);const h=vt(c);return Rt(await _(u,Lt(h)),h)},async take(c){if(!u)throw new N("INTERNAL",n);return _(u,c)},async unique(){if(!u)throw new N("INTERNAL",n);const c=await _(u,2);if(c.length>1)throw new Yt(`unique() on table "${t}" matched ${String(c.length)} documents; expected at most one`);return c[0]??null},withGeoIndex(){throw new N("INTERNAL",`geo indexes are not supported on \`.global()\` tables (table "${t}") — geospatial queries run only on sharded tables`)},withIndex(){throw new N("INTERNAL",n)},withSearchIndex(c,h){const E=(i.searchIndexes??[]).find(T=>T.name===c);if(!E)throw new N("INTERNAL",`unknown search index "${c}" on table "${t}"`);const b={definition:E,field:E.field,filters:[],hasQuery:!1,indexName:c,query:""};if(h(Nt(b,t,Tt(E.language))),!b.hasQuery)throw new N("INTERNAL",`search index "${c}" on table "${t}" requires a .search(field, query) call`);return $(b)}};return p};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(q=>q.name===i);if(!r)throw new N("INTERNAL",`unknown rankIndex "${i}" on table "${t}"`);if(n.restrictsCounts)throw new Ze(t);if(await U(),!await Le(t,r))return null;const _=typeof n.row=="string"?n.row:n.row._id;if(!_)return null;const $=Q(t,r.name),u=r.sortBy.map((q,k)=>z(k)),p=X(["__partition__",...u]),c=(await I(o,s,e`SELECT ${p} FROM ${e.identifier($)} WHERE ${e.identifier("__id__")} = ${_}`))[0];if(!c)return null;const h=c.__partition__,E=x(n.baseWhere,n.where);Je(E,l,t,"rank");const b=Xe(r,E);if(b&&Te(r.partitionBy??[],b)!==h)return null;const T=si(s.name,r,u,c,_),S=await I(o,s,e`SELECT COUNT(*) AS c FROM ${e.identifier($)} WHERE ${e.identifier("__partition__")} = ${h}${T?e` AND (${T})`:e``}`),O=await I(o,s,e`SELECT COUNT(*) AS c FROM ${e.identifier($)} WHERE ${e.identifier("__partition__")} = ${h}`);return{position:Number(S[0]?.c??0)+1,total:Number(O[0]?.c??0)}},async rankPage(t,i,n={}){Je(x(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 U(),!await Le(t,r))return{continueCursor:null,isDone:!0,page:[]};const _=Q(t,r.name),$=r.sortBy.map((C,le)=>z(le)),u=Math.max(1,Math.min(1e3,Math.floor(n.take??100))),p=x(n.baseWhere,n.where),c=Xe(r,p),h=li(r,$),E=e.join(h.map(C=>e`${e.identifier(C.column)} ${e.raw(C.direction==="desc"?"DESC":"ASC")}`),e`, `),b=[];if(c&&b.push(e`${e.identifier("__partition__")} = ${Te(r.partitionBy??[],c)}`),n.cursor){const C=ci(s.name,h,Qe(n.cursor));C!==void 0&&b.push(C)}const T=X([$e,"__partition__",...$]);let S=e`SELECT ${T} FROM ${e.identifier(_)}`;b.length>0&&(S=e`${S} WHERE ${e.join(b,e` AND `)}`),S=e`${S} ORDER BY ${E} LIMIT ${e.raw(String(u+1))}`;const O=await I(o,s,S),q=O.length>u,k=q?O.slice(0,u):O,se=k.map(C=>C[$e]),Ne=await di(o,s,a,t,se);let ce=null;const V=k.at(-1);if(q&&V!==void 0){const C=[V.__partition__,...$.map(le=>V[le]),V[$e]];ce=ui(C)}return{continueCursor:ce,isDone:!q,page:Ne}},async replace(t,i,n,a){const r=await ie(t,n);if(!r)throw new N("INTERNAL",`document not found: ${t}`);const _=l.tables[r];if(!_)throw new N("INTERNAL",`document not found: ${t}`);const $=await ye(r,t);if($===void 0)throw new N("INTERNAL",`document not found: ${t}`);const u=Ot(l,r,"update")||(_.aggregateIndexes??[]).length>0||(_.rankIndexes??[]).length>0?Z(_,$)??void 0:void 0,p=a?.allowExplicitId&&typeof i._creationTime=="number"?i._creationTime:L(),c={...i,_creationTime:p,_id:t};ct(_,i,c,K),Oe(_,c),j(r,"before","update")&&await P("before","update",{doc:{...c},id:t,op:"update",previous:u,table:r}),await me(r),await Ee(r);const h=Object.keys(_.shape),E=e.join([e`${e.identifier("_creationTime")} = ${p}`,...h.map(b=>e`${e.identifier(b)} = ${H(c[b]??null)}`)],e`, `);await ge(r,"UPDATE",E,$),await ae(r,u,c),await J(r,t,u,c),await re(r,t,c,u),await F(r,t,"update",c),j(r,"after","update")&&await P("after","update",{doc:c,id:t,op:"update",previous:u,table:r})}};return je={db:W,scheduler:Se},W};export{xi as backfillSqlSearchIndexes,Oi as createSqlCtxDb,Di as decodeGlobalRow,Ai as readSqlCdcChanges,hi as runSqlAggregateMigrations,yi as runSqlCdcMigration,$i as runSqlGlobalTableMigrations,Ei as runSqlRankMigrations,bt as runSqlSearchMigrations,Li as trimSqlCdcChanges};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as p}from"@lunora/errors";import{sql as t}from"drizzle-orm";import{migrateSearchState as Z,readSearchBackfillState as H,writeSearchBackfillState as x}from"./SEARCH_STATE_TABLE-Bw9dhHy2.mjs";import{unionAll as ee}from"@lunora/shard-engine";import{queryRun as w,decodeRows as P,queryAll as L,queryBatch as ie,createIndexIfNotExists as U,columnRefSql as j,serializeColumnValue as te,forEachRowPaged as ne}from"./decodeGlobalRow-BwzH1RLd.mjs";const re=["de","en","es","fr","it","nl","none","pt"],ae=e=>re.includes(e),oe="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",se="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",de="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",fe="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",ue="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",ce="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",le="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ê",$e=/[\u0300-\u036F]/gu,Q=e=>e.normalize("NFD").replaceAll($e,"").normalize("NFC").toLowerCase(),g=e=>new Set(Q(e).split(" ")),me={de:g(se),en:g(oe),es:g(de),fr:g(fe),it:g(ue),nl:g(ce),none:new Set,pt:g(le)},he=2,we=256,M=new Map,N=e=>{const i=e!==void 0&&ae(e)?e:"none",n=M.get(i);if(n)return n;const r=me[i],a=s=>{const d=(Q(s).match(/[\p{L}\p{N}]+/gu)??[]).filter(f=>f.length<=we);return r.size===0?d:d.filter(f=>!r.has(f))},o={document:a,profile:`${i}-v${String(he)}`,query:s=>{const d=a(s);return d.filter((f,u)=>d.lastIndexOf(f)===u)}};return M.set(i,o),o},pe=(e,i)=>e.profile!==i?{cursor:void 0,finished:!1,wipe:e.cursor!==void 0||e.done}:{cursor:e.cursor,finished:e.done,wipe:!1},Ee=(e,i)=>{if(!i.includes("."))return e[i];let n=e;for(const r of i.split(".")){if(n===null||typeof n!="object"||Array.isArray(n))return;n=n[r]}return n},A=(e,i)=>`${e}__fts_${i}`,Se="__text__",c="__id__",y="__token__",R="__n__",ge=1e3,W=(e,i)=>i.document(e),D=(e,i)=>Ee(e,i),_e=e=>typeof e=="string"?e:e==null?"":typeof e=="number"||typeof e=="bigint"||typeof e=="boolean"?String(e):JSON.stringify(e)??"",Ne=(e,i,n)=>e!==void 0&&i!==void 0&&D(e,n.field)===D(i,n.field),C=(e,i)=>W(_e(D(e,i.field)),N(i.language)).slice(0,ge).join(" "),ye=(e,i)=>{const n=new Map;for(const r of W(e,i))n.set(r,(n.get(r)??0)+1);return n},Te=e=>{const i=new TextEncoder().encode(e);let n="";for(const r of i)n+=String.fromCodePoint(r);return btoa(n)},xe=e=>{const i=atob(e),n=Uint8Array.from(i,r=>r.codePointAt(0)??0);return new TextDecoder().decode(n)},Ae=()=>new p("BAD_REQUEST","invalid cursor"),B=16,F=8,E=1024,v=(e,i)=>i.query(e),ve=(e,i)=>{if(!i)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)}},ke=(e,i,n)=>{const r={eq:(a,o)=>{if(!e.definition.filterFields?.includes(a))throw new p("INTERNAL",`field "${a}" is not a filter field of search index "${e.indexName}" on table "${i}"`);if(e.filters.length>=F)throw new p("BAD_REQUEST",`search index "${e.indexName}" on table "${i}": at most ${String(F)} .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 p("INTERNAL",`search index "${s.indexName}" on table "${i}" indexes "${s.definition.field}", not "${a}"`);const d=v(o,n).length;if(d>B)throw new p("BAD_REQUEST",`search index "${s.indexName}" on table "${i}": at most ${String(B)} search terms are supported (got ${String(d)})`);return s.field=a,s.query=o,s.hasQuery=!0,r}};return r},He=e=>{if(e.length>E)throw new p("BAD_REQUEST",`more than ${String(E)} documents match this search — narrow it with filters or read it a page at a time with .paginate()`)},Pe=e=>Math.min(e.offset+e.numItems+1,E),be=e=>Te(`search:${String(e)}`),Ie=e=>{let i;try{i=xe(e)}catch{return}if(!i.startsWith("search:"))return;const n=Number(i.slice(7));return Number.isInteger(n)&&n>=0?n:void 0},Qe=e=>{if(typeof e.endCursor=="string")throw new p("BAD_REQUEST","bounded (endCursor) pagination is not supported on search queries — relevance order has no stable range boundary");const i=Math.max(0,Math.floor(e.numItems)),n=e.cursor?Ie(e.cursor):0;if(n===void 0)throw Ae();if(n+i>E)throw new p("BAD_REQUEST",`search pagination reaches past the ${String(E)}-document limit (offset ${String(n)} + ${String(i)} requested) — narrow the query or the filters instead`);return{numItems:i,offset:n}},We=(e,i)=>{const n=i.offset+i.numItems,r=i.numItems>0&&e.length>n;return{continueCursor:r?be(n):null,isDone:!r,page:e.slice(i.offset,n)}},Ve=e=>{if(e===void 0)return E+1;if(!Number.isFinite(e))return E;const i=Math.max(0,Math.floor(e));if(i>E)throw new p("BAD_REQUEST",`search returns at most ${String(E)} documents (asked for ${String(i)}) — narrow the query or paginate instead`);return i},b=async(e,i,n,r)=>{await w(e,i,t`DELETE FROM ${t.identifier(n)} WHERE ${t.identifier(c)} = ${r}`)},I=(e,i)=>e.name==="mysql"?t`${t.identifier(i)}(191)`:e.textPatternOperatorClass===void 0?t`${t.identifier(i)}`:t`${t.identifier(i)} ${t.raw(e.textPatternOperatorClass)}`,z=50,Re=(e,i)=>i?t`${t.identifier(y)} LIKE ${`${e}%`}`:t`${t.identifier(y)} = ${e}`,V=(e,i)=>{const n=i.filters.map(r=>t`m.${j(r.field)} = ${te(r.value)}`);return e.softDeleteMode&&n.push(t`m.${j(e.softDeleteMode.field)} IS NULL`),n},G=async(e,i,n,r,a,o,s)=>{const d=V(n,a);let f=t`SELECT m.* FROM (${s}) s JOIN ${t.identifier(r)} m ON m.${t.identifier("id")} = s.${t.identifier(c)}`;return d.length>0&&(f=t`${f} WHERE ${t.join(d,t` AND `)}`),f=t`${f} ORDER BY s.${t.identifier("__score__")} DESC, m.${t.identifier("_creationTime")} DESC, m.${t.identifier("id")} ASC LIMIT ${t.raw(String(o))}`,P(n,await L(e,i,f))},De=async(e,i,n,r,a,o)=>{const s=v(a.query,N(a.definition.language));if(s.length===0)return[];const d=A(r,a.indexName),f=s.length-1,u=s.map((h,_)=>Re(h,_===f)),l=t.join(u,t` OR `),$=u.map(h=>t`SUM(CASE WHEN ${h} THEN ${t.identifier(R)} ELSE 0 END)`),S=t.join($.map(h=>t`${h} > 0`),t` AND `),m=t`SELECT ${t.identifier(c)}, ${t.join($,t` + `)} AS ${t.identifier("__score__")} FROM ${t.identifier(d)} WHERE ${l} GROUP BY ${t.identifier(c)} HAVING ${S}`;return G(e,i,n,r,a,o,m)},Le=async(e,i,n,r,a,o)=>{const s=v(a.query,N(a.definition.language));if(s.length===0)return[];const d=A(r,a.indexName),f=`${d}__vocab`,u=s.length-1,l=s.map((m,h)=>{const _=ve(m,h===u),K=_.exact?t`${t.identifier("term")} = ${_.lower}`:t`${t.identifier("term")} >= ${_.lower} AND ${t.identifier("term")} < ${_.upper}`;return t`SELECT ${t.identifier("doc")}, ${t.raw(String(h))} AS ${t.identifier("__term__")}, COUNT(*) AS ${t.identifier("__n__")} FROM ${t.identifier(f)} WHERE ${K} GROUP BY ${t.identifier("doc")}`}),$=s.map((m,h)=>t`SUM(CASE WHEN u.${t.identifier("__term__")} = ${t.raw(String(h))} THEN u.${t.identifier("__n__")} ELSE 0 END)`),S=t`SELECT f.${t.identifier(c)} AS ${t.identifier(c)}, ${t.join($,t` + `)} AS ${t.identifier("__score__")} FROM (${ee(l)}) u JOIN ${t.identifier(d)} f ON f.rowid = u.${t.identifier("doc")} GROUP BY f.${t.identifier(c)} HAVING ${t.join($.map(m=>t`${m} > 0`),t` AND `)}`;return G(e,i,n,r,a,o,S)},Ce=async(e,i,n,r,a,o)=>{const s=i.nativeTextSearch,d=v(a.query,N(a.definition.language));if(!s||d.length===0)return[];const f=A(r,a.indexName),u=[s.matches(f,d),...V(n,a)],l=t`SELECT m.* FROM ${t.identifier(f)} JOIN ${t.identifier(r)} m ON m.${t.identifier("id")} = ${t.identifier(f)}.${t.identifier(c)} WHERE ${t.join(u,t` AND `)} ORDER BY ${s.rank(f,d)} DESC, m.${t.identifier("_creationTime")} DESC, m.${t.identifier("id")} ASC LIMIT ${t.raw(String(o))}`;return P(n,await L(e,i,l))},Oe={ensureCompanion:async(e,i,n)=>{const{integer:r,key:a}=i.companionTypes;await w(e,i,t`CREATE TABLE IF NOT EXISTS ${t.identifier(n)} (${t.identifier(y)} ${t.raw(a)} NOT NULL, ${t.identifier(c)} ${t.raw(a)} NOT NULL, ${t.identifier(R)} ${t.raw(r)} NOT NULL)`),await U(e,i,{columns:t`${I(i,y)}, ${I(i,c)}`,name:`${n}__btree`,table:n,unique:!1}),await U(e,i,{columns:I(i,c),name:`${n}__by_id`,table:n,unique:!1})},indexDocument:async(e,i,n,r,a,o)=>{await b(e,i,n,r);const s=[...ye(C(a,o),N(o.language))],d=t.join([y,c,R].map(u=>t.identifier(u)),t`, `),f=[];for(let u=0;u<s.length;u+=z){const l=t.join(s.slice(u,u+z).map(([$,S])=>t`(${$}, ${r}, ${S})`),t`, `);f.push(t`INSERT INTO ${t.identifier(n)} (${d}) VALUES ${l}`)}await ie(e,i,f)},name:"inverted",runSearch:De},qe={ensureCompanion:async(e,i,n)=>{await w(e,i,t`CREATE VIRTUAL TABLE IF NOT EXISTS ${t.identifier(n)} USING fts5(${t.identifier(Se)}, ${t.identifier(c)} UNINDEXED)`),await w(e,i,t`CREATE VIRTUAL TABLE IF NOT EXISTS ${t.identifier(`${n}__vocab`)} USING fts5vocab(${t.identifier(n)}, ${t.raw("instance")})`)},indexDocument:async(e,i,n,r,a,o)=>{await b(e,i,n,r),await w(e,i,t`INSERT INTO ${t.identifier(n)} (${t.identifier("__text__")}, ${t.identifier(c)}) VALUES (${C(a,o)}, ${r})`)},name:"fts5",runSearch:Le},Ue={ensureCompanion:async(e,i,n)=>{const r=i.nativeTextSearch;if(r){await w(e,i,r.createCompanion(n,i.companionTypes.key));for(const a of r.createIndexes(n))await w(e,i,a)}},indexDocument:async(e,i,n,r,a,o)=>{const s=i.nativeTextSearch;s&&(await b(e,i,n,r),await w(e,i,s.indexDocument(n,r,C(a,o))))},name:"native",runSearch:Ce},T=(e,i)=>e.strategy==="native"&&i.nativeTextSearch!==void 0?Ue:i.supportsFts5?qe:Oe,X=(e,i)=>`${N(e.language).profile}/${T(e,i).name}`,O=function*(e){for(const[i,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[i,n,a]}},q=(e,i)=>A(e,i.name),Ge=async(e,i,n,r,a,o)=>T(a.definition,i).runSearch(e,i,n,r,a,o),k=200,Y=async(e,i,n,r,a)=>{const o=q(r,a),s=T(a,i),d=X(a,i),f=pe(await H(e,i,o),d);if(f.finished)return!0;if(f.wipe&&(await w(e,i,t`DELETE FROM ${t.identifier(o)}`),await x(e,i,o,void 0,!1,d)),(await L(e,i,i.tableExists(r))).length===0)return await x(e,i,o,void 0,!0,d),!0;let u=0,l=f.cursor;await ne(e,i,n,r,async S=>{u+=1;const m=S._id;typeof m=="string"&&(l=m,await s.indexDocument(e,i,o,m,S,a))},{after:f.cursor,limit:k});const $=u<k;return await x(e,i,o,l,$,d),$},J=async(e,i,n)=>{await Z(e,n);for(const[r,,a]of O(i)){const o=q(r,a),s=X(a,n),d=await H(e,n,o);d.profile!==void 0&&d.profile!==s&&(await w(e,n,t`DROP TABLE IF EXISTS ${t.identifier(o)}`),await x(e,n,o,void 0,!1,s)),await T(a,n).ensureCompanion(e,n,o)}},Xe=async(e,i,n)=>{await J(e,i,n);for(const[r,a,o]of O(i))o.staged||await Y(e,n,a,r,o)},Ye=async(e,i,n)=>{await J(e,i,n);for(const[r,a,o]of O(i)){let s=!1;for(;!s;)s=await Y(e,n,a,r,o)}},Je=e=>{const{dialect:i,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(Ne(d,s,u))continue;const l=q(a,u);if(s){await T(u,i).indexDocument(n,i,l,o,s,u);continue}await b(n,i,l,o)}}};export{Ye as A,Xe as B,We as C,Ve as D,Je as F,Pe as N,ke as T,Qe as _,He as b,Ge as v,N as x};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const i=e=>{if(e.kind!=="optional")return e.kind;const r=e._meta?.inner;return r?i(r):e.kind},a=e=>typeof e=="boolean"?e?1:0:e===null||typeof e=="string"||typeof e=="number"?e:typeof e=="bigint"?e.toString():e instanceof Uint8Array?e:e instanceof ArrayBuffer?new Uint8Array(e):JSON.stringify(e),t=e=>{try{return JSON.parse(e)}catch{return e}},s=e=>{if(typeof e!="string")return e;try{return BigInt(e)}catch{return e}},f=e=>i(e),o=(e,r)=>{if(e===null)return e;switch(r){case"any":case"from":case"union":return typeof e=="string"&&(e.startsWith("{")||e.startsWith("["))?t(e):e;case"array":case"object":case"record":return typeof e=="string"?t(e):e;case"bigint":return s(e);case"boolean":return e===0||e===1?e===1:e;case"bytes":return e instanceof ArrayBuffer?e:ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength).slice().buffer:e;default:return e}};export{s as decodeBigint,f as effectiveColumnKind,o as sqliteDecode,a as sqliteEncode,t as tryJsonParse};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{renderSql as f}from"@lunora/shard-engine";import{sql as a}from"drizzle-orm";import{sqliteEncode as q,sqliteDecode as I,effectiveColumnKind as y}from"./decodeBigint-DrEQib7C.mjs";const C=t=>t==="_id"||t==="id"?"id":t,g=t=>a`${a.identifier(C(t))}`,T=(t,o,e)=>{const{params:i,sql:n}=f(o.name,e);return t.all(n,i)},l=(t,o,e)=>{const{params:i,sql:n}=f(o.name,e);return t.run(n,i)},b=async(t,o,e)=>{if(e.length!==0){if(!t.batch){for(const i of e)await l(t,o,i);return}await t.batch(e.map(i=>f(o.name,i)))}},O=async(t,o,e)=>{const i=e.unique?a`UNIQUE `:a``;if(o.name==="mysql"){try{await l(t,o,a`CREATE ${i}INDEX ${a.identifier(e.name)} ON ${a.identifier(e.table)} (${e.columns})`)}catch(n){const r=n;if(r.errno!==1061&&r.code!=="ER_DUP_KEYNAME"&&r.code!==1061)throw n}return}await l(t,o,a`CREATE ${i}INDEX IF NOT EXISTS ${a.identifier(e.name)} ON ${a.identifier(e.table)} (${e.columns})`)},D=q,$=new WeakMap,S=t=>{let o=$.get(t);return o===void 0&&(o=Object.entries(t.shape).map(([e,i])=>[e,y(i)]),$.set(t,o)),o},v=(t,o)=>{const e={};for(const[i,n]of S(t)){const r=o[i];r!==void 0&&(e[i]=I(r,n))}return e._id=o.id,e._creationTime=o._creationTime,e},R=(t,o)=>o?v(t,o):null,L=(t,o)=>{const e=[];for(const i of o){const n=R(t,i);n&&e.push(n)}return e},w=500,M=async(t,o,e,i,n,r={})=>{let d=r.after,s=r.limit,m=!0;for(;m&&(s===void 0||s>0);){const u=s===void 0?w:Math.min(w,s),h=d===void 0?a``:a` WHERE ${a.identifier("id")} > ${d}`,c=await T(t,o,a`SELECT * FROM ${a.identifier(i)}${h} ORDER BY ${a.identifier("id")} ASC LIMIT ${a.raw(String(u))}`);for(const p of c){const E=R(e,p);E&&await n(E)}d=c.at(-1)?.id,m=c.length===u,s=s===void 0?void 0:s-c.length}};export{w as BACKFILL_BATCH_SIZE,g as columnRefSql,O as createIndexIfNotExists,v as decodeGlobalRow,R as decodeRow,L as decodeRows,M as forEachRowPaged,C as physicalColumn,T as queryAll,b as queryBatch,l as queryRun,D as serializeColumnValue};
|