用户报告"站点演示失败了",实测复现并定位根因: - 现象:直接双击 site/demo.html(file://)→ 点「🌲 Aria」→ "❌ 数据库初始化失败: Failed to open AriaEngine database "demo""(Memory 正常)。 - 根因:file:// 属不透明来源,Chromium 拒绝 navigator.storage.getDirectory() 并抛 SecurityError;此时 isSecureContext 仍为 true、API 也存在,无法提前探测。 引擎把它包成 ARIA_OPEN_ERROR 时丢掉了底层错误 → 消息对用户不可操作。 - 修复:OPFSBackend.open() 显式检查并抛 ARIA_OPFS_UNAVAILABLE,消息给出两条出路 (用 http(s) 打开 / 改用 mode:'memory'),原始 SecurityError 挂 cause; site/demo.html 额外用中文说明"为什么失败 + 怎么修"。 顺带修掉一个更普遍的问题:DatabaseError 的第三个参数只进 details,err.cause 恒为 undefined,而文档/注释多处写"底层错误作为 cause 保留"。现在两者都成立 (details 语义不变;cause 声明为公开字段并接入标准错误链)。 站点版本同步:demo.html(title / 状态栏 / SQL 预置脚本 / console 日志)与 benchmark.html(title)此前仍是 v0.7.4(日志甚至是 v0.4.2)→ 统一 v0.8.0; docs.html 的 AriaEngine 版本演进列表补上 v0.8.0 条目、错误码表补 ARIA_OPFS_UNAVAILABLE;README 补"OPFS 需要 http(s) 页面"的浏览器兼容说明。 回归与门禁:tests/engine/aria-opfs-unavailable.test.ts(5 项,含正常环境正控); 变异 R19 / R20 均被拦住(总计 42/42);93 套件 / 1985 用例;覆盖率 90.59 / 82.61 / 94.14 / 93.50(阈值 90/82/94/93);e2e 14/14;lint + 两份 tsc 干净; dist 重建(251,731 B / gzip 63,431 B)并已同步全部体积宣称。
2 lines
246 KiB
JavaScript
2 lines
246 KiB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).MetonaSqlark={})}(this,function(e){"use strict";const t=["string","number","boolean","date","json"],s=Object.freeze({name:"metona-sqlark",mode:"hybrid",diskEngine:"opfs",version:1,maxRowsPerQuery:0,debug:!1,multiTabSync:!1,aria:void 0});class n extends Error{constructor(e,t,s){super(e),this.code=t,this.details=s,this.name="DatabaseError",void 0!==s&&(this.cause=s)}}const i="0.8.0";class r{constructor(e,t=()=>{},s=()=>{}){this.listeners=new Set,this.inner=e,this.onListenerError=t,this.onBroadcast=s}getInner(){return this.inner}addListener(e){return this.listeners.add(e),()=>this.listeners.delete(e)}async dispatch(e){try{this.onBroadcast(e.table)}catch{}for(const t of[...this.listeners])try{await t(e)}catch(e){this.onListenerError(e)}}async insert(e,t){const s=await this.inner.insert(e,t);for(let n=0;n<s.length;n++)await this.dispatch({type:"insert",table:e,key:s[n],row:n<t.length?t[n]:void 0,count:1});return s}async update(e,t,s){const n=await this.snapshotAffected(e,t),i=await this.inner.update(e,t,s);if(i>0&&n.length>0)for(const t of n){const n={...t,...a(s)};await this.dispatch({type:"update",table:e,row:n,count:1})}else i>0&&await this.dispatch({type:"update",table:e,count:i});return i}async delete(e,t){const s=await this.snapshotAffected(e,t),n=await this.inner.delete(e,t);if(n>0&&s.length>0)for(const t of s)await this.dispatch({type:"delete",table:e,row:t,count:1});else n>0&&await this.dispatch({type:"delete",table:e,count:n});return n}async clear(e){await this.inner.clear(e),await this.dispatch({type:"clear",table:e})}async createTable(e){await this.inner.createTable(e),await this.dispatch({type:"ddl",table:e.name})}async dropTable(e){await this.inner.dropTable(e),await this.dispatch({type:"ddl",table:e})}async alterTable(e,t,s){await this.requireCapability("alterTable")(e,t,s),await this.dispatch({type:"ddl",table:e})}async createIndex(e,t,s){await this.requireCapability("createIndex")(e,t,s),await this.dispatch({type:"ddl",table:e})}async dropIndex(e,t,s){await this.requireCapability("dropIndex")(e,t,s),await this.dispatch({type:"ddl",table:e})}get name(){return this.inner.name}open(e,t){return this.inner.open(e,t)}close(){return this.inner.close()}isOpen(){return this.inner.isOpen()}hasTable(e){return this.inner.hasTable(e)}getTableNames(){return this.inner.getTableNames()}getTableSchema(e){return this.inner.getTableSchema(e)}find(e,t){return this.inner.find(e,t)}count(e,t){return this.inner.count(e,t)}async findStream(e,t,s){return this.requireCapability("findStream")(e,t,s)}beginTransaction(){return this.inner.beginTransaction()}commitTransaction(){return this.inner.commitTransaction()}rollbackTransaction(){return this.inner.rollbackTransaction()}savepoint(e){return this.requireCapability("savepoint")(e)}rollbackToSavepoint(e){return this.requireCapability("rollbackToSavepoint")(e)}releaseSavepoint(e){return this.requireCapability("releaseSavepoint")(e)}backup(){return this.requireCapability("backup")()}repair(){return this.requireCapability("repair")()}clearAll(){return this.requireCapability("clearAll")()}analyzeTable(e){return this.requireOptionalMethod("analyzeTable")(e)}reindexTable(e){return this.requireOptionalMethod("reindexTable")(e)}vacuum(){return this.requireOptionalMethod("vacuum")()}getMeta(e){const t=this.inner.getMeta;return"function"!=typeof t?Promise.resolve(null):t.call(this.inner,e)}setMeta(e,t){const s=this.inner.setMeta;return"function"!=typeof s?Promise.resolve():s.call(this.inner,e,t)}requireCapability(e){const t=this.inner[e];return"function"!=typeof t?()=>{throw new n(`Engine "${this.inner.name}" does not support ${String(e)}`,"NOT_SUPPORTED")}:t.bind(this.inner)}requireOptionalMethod(e){const t=this.inner[e];return"function"!=typeof t?()=>{throw new n(`Engine "${this.inner.name}" does not support ${e}`,"NOT_SUPPORTED")}:t.bind(this.inner)}async snapshotAffected(e,t){try{return await this.inner.find(e,{table:e,where:t.where})}catch{return[]}}}function a(e){const t={};for(const[s,n]of Object.entries(e))void 0!==n&&(t[s]=n);return t}function o(e){if(null===e||"object"!=typeof e)return e;if("function"==typeof structuredClone)try{return structuredClone(e)}catch{}return h(e)}function h(e){if(null===e||"object"!=typeof e)return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(e=>h(e));if(e instanceof Uint8Array)return new Uint8Array(e);if(e instanceof ArrayBuffer)return e.slice(0);const t={};for(const[s,n]of Object.entries(e))t[s]=h(n);return t}const c=Object.freeze({TRUE:"TRUE",FALSE:"FALSE",UNKNOWN:"UNKNOWN"});function l(e){return null==e}const u=Symbol("sqlark.unresolved");function f(e){return e===u}function d(e){if(null==e)return"z";switch(typeof e){case"string":{const t=e;return`s${t.length}:${t}`}case"number":{const t=e;return Number.isNaN(t)?"nNaN":`n${Object.is(t,-0)?0:t}`}case"boolean":return"b"+(e?1:0);case"bigint":return`i${String(e)}`;case"object":return e instanceof Date?`d${e.getTime()}`:Array.isArray(e)?`a${JSON.stringify(e)}`:`o${JSON.stringify(e)}`;default:return`x${String(e)}`}}function p(e,t){const s=y(e,t);return null===s?c.UNKNOWN:0===s?c.TRUE:c.FALSE}function m(e,t){return p(e,t)}function y(e,t){if(f(e)||f(t))return null;if(l(e)||l(t))return null;if("number"==typeof e&&"number"==typeof t)return Number.isNaN(e)||Number.isNaN(t)?null:e===t?0:e<t?-1:1;if("boolean"==typeof e&&"boolean"==typeof t)return e===t?0:!1===e?-1:1;if("string"==typeof e&&"string"==typeof t)return e===t?0:e<t?-1:1;if(e instanceof Date&&t instanceof Date){const s=e.getTime(),n=t.getTime();return Number.isNaN(s)||Number.isNaN(n)?null:s===n?0:s<n?-1:1}const s=T(e),n=T(t);return null!==s&&null!==n?s===n?0:s<n?-1:1:null}function g(e,t){return e===c.FALSE||t===c.FALSE?c.FALSE:e===c.UNKNOWN||t===c.UNKNOWN?c.UNKNOWN:c.TRUE}function w(e,t){return e===c.TRUE||t===c.TRUE?c.TRUE:e===c.UNKNOWN||t===c.UNKNOWN?c.UNKNOWN:c.FALSE}function b(e){return e===c.TRUE?c.FALSE:e===c.FALSE?c.TRUE:c.UNKNOWN}function T(e){if("number"==typeof e)return Number.isNaN(e)?null:e;if("boolean"==typeof e)return e?1:0;if("string"==typeof e){const t=e.trim();if(""===t)return null;const s=Number(t);return Number.isNaN(s)?null:s}return null}function E(e,t){if(f(e))return c.UNKNOWN;let s=!1;for(const n of t){const t=m(e,n);if(t===c.TRUE)return c.TRUE;t===c.UNKNOWN&&(s=!0)}return s?c.UNKNOWN:c.FALSE}const S=new Map;function k(e,t,s={}){return O({row:e,options:s},t)===c.TRUE}function A(e){if(!e)return!1;for(const[t,s]of Object.entries(e))if(I(t)){if((Array.isArray(s)?s:[s]).some(e=>A(e)))return!0}else{if("$exists"===t)return!0;if(R(s)&&x(s))return!0}return!1}function x(e){for(const[t,s]of Object.entries(e))if("$and"!==t&&"$or"!==t){if("$not"!==t){if("$subquery"===t||"$col"===t)return!0;if(R(s)&&("$subquery"in s||"$col"in s))return!0}else if(R(s)&&x(s))return!0}else if((Array.isArray(s)?s:[s]).some(e=>R(e)&&x(e)))return!0;return!1}function I(e){return"$and"===e||"$or"===e||"$not"===e}function R(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function O(e,t){let s=c.TRUE;for(const[n,i]of Object.entries(t)){let t;if(t="$and"===n?C(e,i,"and"):"$or"===n?C(e,i,"or"):"$not"===n?b(O(e,i)):"$exists"===n||"$caseResult"===n?!0===i?c.TRUE:c.FALSE:L(e,N(e,n),i),s=g(s,t),s===c.FALSE)return c.FALSE}return s}function C(e,t,s){const n=Array.isArray(t)?t:[t];let i="and"===s?c.TRUE:c.FALSE;for(const t of n){const n=O(e,t);if(i="and"===s?g(i,n):w(i,n),"and"===s&&i===c.FALSE)return c.FALSE;if("or"===s&&i===c.TRUE)return c.TRUE}return i}function N(e,t){if(t in e.row)return e.row[t];let s=u,n=0;for(const i of Object.keys(e.row))i.endsWith(`.${t}`)&&(s=e.row[i],n+=1);return 1===n?s:u}function L(e,t,s){return R(s)?$(e,t,s):Array.isArray(s)?E(t,s):_(t,s)}function $(e,t,s){const n=Object.keys(s);if(1===n.length&&"$col"===n[0]&&e.options.$col)return _(t,N(e,String(s.$col)));let i=c.TRUE;for(const[n,r]of Object.entries(s)){let s;if(s="$and"===n?v(e,t,r,"and"):"$or"===n?v(e,t,r,"or"):"$not"===n?b(D(e,t,r)):U(e,t,n,r),i=g(i,s),i===c.FALSE)return c.FALSE}return i}function v(e,t,s,n){const i=Array.isArray(s)?s:[s];let r="and"===n?c.TRUE:c.FALSE;for(const s of i){const i=D(e,t,s);if(r="and"===n?g(r,i):w(r,i),"and"===n&&r===c.FALSE)return c.FALSE;if("or"===n&&r===c.TRUE)return c.TRUE}return r}function D(e,t,s){return R(s)?Object.keys(s).some(e=>!e.startsWith("$")||I(e)||"$exists"===e||"$caseResult"===e)?O(e,s):$(e,t,s):L(e,t,s)}function U(e,t,s,i){const r=function(e,t){if(!R(t))return t;const s=Object.keys(t);return 1!==s.length?t:"$col"===s[0]?e.options.$col?N(e,String(t.$col)):u:"$subquery"===s[0]?u:t}(e,i);switch(s){case"$eq":return _(t,r);case"$ne":return b(_(t,r));case"$gt":return M(t,r,e=>e>0);case"$gte":return M(t,r,e=>e>=0);case"$lt":return M(t,r,e=>e<0);case"$lte":return M(t,r,e=>e<=0);case"$in":return Array.isArray(r)?E(t,r):c.FALSE;case"$nin":return Array.isArray(r)?b(E(t,r)):c.FALSE;case"$like":return l(t)||l(r)||f(t)||f(r)?c.UNKNOWN:function(e){const t=S.get(e);if(t)return t;const s=e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*").replace(/_/g,"."),n=new RegExp(`^${s}$`,"i");return S.set(e,n),n}(String(r)).test(String(t))?c.TRUE:c.FALSE;case"$isNull":return l(t)?c.TRUE:c.FALSE;case"$isNotNull":return l(t)?c.FALSE:c.TRUE;case"$col":return e.options.$col?_(t,N(e,String(i))):c.UNKNOWN;case"$subquery":return c.UNKNOWN;default:throw new n(`Unknown where operator "${s}"`,"QUERY_ERROR")}}function _(e,t){return p(e,t)===c.TRUE?c.TRUE:l(e)||l(t)||f(e)||f(t)?c.UNKNOWN:c.FALSE}function M(e,t,s){const n=y(e,t);return null===n?c.UNKNOWN:s(n)?c.TRUE:c.FALSE}function P(e,t){return[...e].sort((e,s)=>{for(const{column:n,direction:i,nulls:r}of t){const t=null===e[n]||void 0===e[n],a=null===s[n]||void 0===s[n];if(r&&(t||a)){if(t&&a)continue;return"first"===r?t?-1:1:t?1:-1}const o=B(e[n],s[n]);if(0!==o)return"desc"===i?-o:o}return 0})}function B(e,t){return e===t?0:null==e?1:null==t?-1:"string"==typeof e&&"string"==typeof t?e.localeCompare(t):"number"==typeof e&&"number"==typeof t?e-t:String(e).localeCompare(String(t))}function F(e,t){const s={};for(const n of t){const t=K(n);if(t in e){s[t]=e[t];continue}let i,r=0;for(const s of Object.keys(e))(s.endsWith(`.${t}`)||s===t)&&(i=e[s],r+=1);r>=1&&(s[t]=i)}return s}function K(e){const t=e.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1).replace(/""/g,'"'):t}function z(e){const t=e.name,s=Object.entries(e.columns),i=new Set(s.map(([e])=>e));return{table:t,columns:i,validateRow:function(e,r){!function(e,s){const r=s?new Set(s):i,a=[];for(const t of Object.keys(e))"__proto__"!==t&&(r.has(t)||a.push(t));if(a.length>0)throw new n(`Unknown column${a.length>1?"s":""} ${a.map(e=>`"${e}"`).join(", ")} in table "${t}". Known columns: ${[...r].join(", ")}`,"COLUMN_NOT_FOUND")}(e,r);const a={};for(const[n,i]of s){let s=e[n];void 0===s&&void 0!==i.default&&(s=i.default),j(t,n,i,s),null!=s&&(q(t,n,s),V(t,n,i.type,s,i)),a[n]=void 0===s?null:s}return a},validatePartial:function(s){const i={},r=[];for(const[a,o]of Object.entries(s)){if("__proto__"===a)throw new n('Column name "__proto__" is not allowed',"VALIDATION_ERROR");const s=e.columns[a];s?void 0!==o&&(j(t,a,s,o),null!==o&&(q(t,a,o),V(t,a,s.type,o,s)),i[a]=o):r.push(a)}return{values:i,unknown:r}}}}function q(e,t,s){if("number"==typeof s&&!Number.isFinite(s))throw new n(`Column "${t}" in table "${e}" cannot store ${Number.isNaN(s)?"NaN":String(s)}: it is not representable in JSON and would be silently read back as null`,"VALIDATION_ERROR")}function j(e,t,s,i){if(s.required&&null==i)throw new n(`Column "${t}" is required in table "${e}"`,"VALIDATION_ERROR");if(s.primaryKey&&null==i)throw new n(`Primary key column "${t}" in table "${e}" cannot be null or undefined`,"VALIDATION_ERROR")}function V(e,t,s,i,r){const a=typeof i;switch(s){case"string":if("string"!==a)throw new n(`Column "${t}" in table "${e}" expects string, got ${a}`,"TYPE_ERROR");if(void 0!==r?.maxLength&&i.length>r.maxLength)throw new n(`Column "${t}" in table "${e}" exceeds max length ${r.maxLength}`,"VALIDATION_ERROR");break;case"number":if("number"!==a)throw new n(`Column "${t}" in table "${e}" expects number, got ${a}`,"TYPE_ERROR");if(void 0!==r?.min&&i<r.min)throw new n(`Column "${t}" in table "${e}" value ${i} below minimum ${r.min}`,"VALIDATION_ERROR");if(void 0!==r?.max&&i>r.max)throw new n(`Column "${t}" in table "${e}" value ${i} above maximum ${r.max}`,"VALIDATION_ERROR");break;case"boolean":if("boolean"!==a)throw new n(`Column "${t}" in table "${e}" expects boolean, got ${a}`,"TYPE_ERROR");break;case"date":if("string"!==a||isNaN(Date.parse(i)))throw new n(`Column "${t}" in table "${e}" expects valid date string, got ${typeof i}`,"TYPE_ERROR");break;case"json":if("object"!==a)throw new n(`Column "${t}" in table "${e}" expects object/array, got ${a}`,"TYPE_ERROR")}}function W(e,s){return function(e){if(0===Object.keys(e).length)throw new n("Table must have at least one column","SCHEMA_ERROR");let s=0;for(const[i,r]of Object.entries(e)){if("__proto__"===i)throw new n('Column name "__proto__" is not allowed',"SCHEMA_ERROR");if(!t.includes(r.type))throw new n(`Invalid type "${r.type}" for column "${i}". Valid types: ${t.join(", ")}`,"SCHEMA_ERROR");r.primaryKey&&s++}if(0===s)throw new n("Table must have at least one primary key column","SCHEMA_ERROR");if(s>1)throw new n(`Composite primary keys are not supported yet: table has ${s} primary key columns. Use a single primary key column (or a unique column combination) instead.`,"SCHEMA_ERROR")}(s),{name:e,columns:s}}function G(e){const t={};for(const[s,n]of Object.entries(e))void 0!==n&&(t[s]=n);return t}function H(e){return{type:e.type,primaryKey:e.primaryKey,unique:e.unique,required:e.required,default:e.default,index:e.index,maxLength:e.maxLength,min:e.min,max:e.max,references:e.references,onDelete:e.onDelete,onUpdate:e.onUpdate}}class Q{constructor(){this.name="memory",this.tables=new Map,this.schemas=new Map,this.indexes=new Map,this.opened=!1,this.metaStore=new Map,this.uniqueIndexCols=new Set,this.snapshot=null}async open(e,t){this.opened||(this.opened=!0)}async close(){this.tables.clear(),this.schemas.clear(),this.indexes.clear(),this.metaStore.clear(),this.opened=!1}isOpen(){return this.opened}async repair(){}async clearAll(){const e=Array.from(this.schemas.keys());for(const t of e)await this.dropTable(t);this.metaStore.clear()}async getMeta(e){return this.metaStore.get(e)??null}async setMeta(e,t){this.metaStore.set(e,t)}async createTable(e){if(this.schemas.has(e.name))throw new n(`Table "${e.name}" already exists`,"TABLE_EXISTS");const t={name:e.name,columns:{}};for(const[s,n]of Object.entries(e.columns))t.columns[s]={...n};this.schemas.set(e.name,t),this.tables.set(e.name,new Map);const s=new Map;for(const[e,n]of Object.entries(t.columns))(n.index||n.unique)&&s.set(e,new Map);this.indexes.set(e.name,s)}async dropTable(e){this.ensureTable(e),this.schemas.delete(e),this.tables.delete(e),this.indexes.delete(e);const t=`${e}:`;for(const e of this.uniqueIndexCols)e.startsWith(t)&&this.uniqueIndexCols.delete(e)}async hasTable(e){return this.schemas.has(e)}async getTableNames(){return Array.from(this.schemas.keys())}async getTableSchema(e){return this.schemas.get(e)??null}async alterTable(e,t,s){if(this.snapshot)throw new n("ALTER TABLE is not supported inside a transaction (MemoryEngine DDL is not transactional)","NOT_SUPPORTED");this.ensureTable(e);const i=this.schemas.get(e);if("ADD"===t){if(i.columns[s.name])throw new n(`Column "${s.name}" already exists in table "${e}"`,"COLUMN_EXISTS");if(i.columns[s.name]=s,s.index||s.unique){this.indexes.has(e)||this.indexes.set(e,new Map);const t=this.indexes.get(e);t.has(s.name)||t.set(s.name,new Map);const r=t.get(s.name),a=this.tables.get(e),o=new Set;for(const[h,c]of a){const a=c[s.name];if(null==a)continue;if(s.unique&&o.has(a))throw t.delete(s.name),delete i.columns[s.name],new n(`Duplicate value "${String(a)}" for UNIQUE column "${s.name}" in table "${e}"`,"UNIQUE_VIOLATION");o.add(a);let l=r.get(a);l||(l=new Set,r.set(a,l)),l.add(h)}}const t=this.tables.get(e);for(const e of t.values())s.name in e||(e[s.name]=null);return}if(!i.columns[s.name])throw new n(`Column "${s.name}" does not exist in table "${e}"`,"COLUMN_NOT_FOUND");(i.columns[s.name].index||i.columns[s.name].unique)&&this.indexes.get(e)?.delete(s.name),delete i.columns[s.name];const r=this.tables.get(e);for(const e of r.values())s.name in e&&delete e[s.name]}async insert(e,t){this.ensureTable(e);const s=this.schemas.get(e),i=this.tables.get(e),r=this.getPrimaryKey(s),a=[],o=[],h=new Set,c=new Map;for(const a of t){const t=this.validateRow(s,a),l=String(t[r]);if(i.has(l)||h.has(l))throw new n(`Duplicate primary key "${l}" in table "${e}"`,"DUPLICATE_KEY");h.add(l),this.checkInsertUniqueness(s,e,t,c),o.push(t)}for(const t of o){const s=String(t[r]);i.set(s,t),this.updateIndexes(e,t,s),a.push(s)}return a}getRow(e,t){const s=this.tables.get(e);if(!s)return null;const n=s.get(t);return n?o(n):null}async find(e,t){this.ensureTable(e);const s=this.tables.get(e);let n=this.tryIndexLookup(e,s,t);t.where&&Object.keys(t.where).length>0&&(n=n.filter(e=>k(e,t.where))),t.orderBy&&t.orderBy.length>0&&(n=P(n,t.orderBy));const i=t.offset??0,r=t.limit??n.length;return n=n.slice(i,i+r),t.columns&&t.columns.length>0&&"*"!==t.columns[0]&&(n=n.map(e=>F(e,t.columns))),n.map(e=>o(e))}async findStream(e,t,s){this.ensureTable(e);const n=this.tables.get(e),i=!!(t.where&&Object.keys(t.where).length>0),r=t.limit??1/0,a=t.offset??0,h=t.columns&&t.columns.length>0&&"*"!==t.columns[0]?e=>F(e,t.columns):null;let c=0,l=0;for(const e of n.values())if(!i||k(e,t.where))if(l<a)l++;else if(s(h?h(e):o(e)),c++,c>=r)break;return c}async update(e,t,s){this.ensureTable(e);const i=this.schemas.get(e),r=this.tables.get(e),a=this.getPrimaryKey(i),o=G(s);for(const t of Object.keys(o))if(!i.columns[t])throw new n(`Column "${t}" does not exist in table "${e}"`,"COLUMN_NOT_FOUND");const h=[],c=new Map,l=new Set;for(const[s,u]of r){if(t.where&&Object.keys(t.where).length>0&&!k(u,t.where))continue;const f={...u,...o};this.validateRow(i,f),this.checkUpdateUniqueness(i,e,s,f,c);const d=String(f[a]);if(d!==s&&r.has(d))throw new n(`Duplicate primary key "${d}" in table "${e}" (cannot update key to existing value)`,"DUPLICATE_KEY");if(d!==s){if(l.has(d))throw new n(`Duplicate primary key "${d}" in table "${e}" (multiple rows in the same statement update to the same key)`,"DUPLICATE_KEY");l.add(d)}h.push({pk:s,row:u,updated:f,newPk:d})}for(const t of h)t.newPk!==t.pk&&this.checkUpdateRestrict(e,t.pk);let u=0;for(const{pk:t,row:s,updated:n,newPk:i}of h)this.removeIndexEntries(e,s,t),i!==t&&await this.applyUpdateCascade(e,t,i),r.delete(t),r.set(i,n),this.updateIndexes(e,n,i),u++;return u}checkInsertUniqueness(e,t,s,i){const r=this.indexes.get(t);for(const[t,a]of Object.entries(e.columns)){if(!a.unique)continue;const o=s[t];if(null==o)continue;let h=i.get(t);if(h||(h=new Set,i.set(t,h)),h.has(o))throw new n(`Unique constraint violation on column "${t}" in table "${e.name}"`,"UNIQUE_VIOLATION");if(h.add(o),!r)continue;const c=r.get(t);if(c&&c.has(o))throw new n(`Unique constraint violation on column "${t}" in table "${e.name}"`,"UNIQUE_VIOLATION")}}checkUpdateUniqueness(e,t,s,i,r){const a=this.indexes.get(t);for(const[t,o]of Object.entries(e.columns)){if(!o.unique)continue;const h=i[t];if(null==h)continue;let c=r.get(t);if(c||(c=new Set,r.set(t,c)),c.has(h))throw new n(`Unique constraint violation on column "${t}" in table "${e.name}"`,"UNIQUE_VIOLATION");if(c.add(h),!a)continue;const l=a.get(t);if(l&&l.has(h)){const i=l.get(h);if(1!==i.size||!i.has(s))throw new n(`Unique constraint violation on column "${t}" in table "${e.name}"`,"UNIQUE_VIOLATION")}}}checkUpdateRestrict(e,t){for(const[s,i]of this.schemas)for(const[r,a]of Object.entries(i.columns)){if(!a.references||!a.onUpdate)continue;const[i]=a.references.split(".");if(i!==e)continue;const o=this.tables.get(s);if(!o)continue;let h=!1;for(const[,i]of o)if(String(i[r])===t&&(h=!0,"RESTRICT"===a.onUpdate))throw new n(`Cannot update "${e}" key "${t}": foreign key "${r}" in "${s}" has dependent rows`,"FOREIGN_KEY_VIOLATION");if(h&&"SET NULL"===a.onUpdate&&a.required)throw new n(`Cannot update "${e}" key "${t}": foreign key "${r}" in "${s}" is required (SET NULL violates constraint)`,"FOREIGN_KEY_VIOLATION")}}async applyUpdateCascade(e,t,s){for(const[n,i]of this.schemas)for(const[r,a]of Object.entries(i.columns)){if(!a.references||!a.onUpdate)continue;const[o]=a.references.split(".");if(o!==e)continue;const h=this.tables.get(n);if(!h)continue;if("CASCADE"!==a.onUpdate&&"SET NULL"!==a.onUpdate)continue;const c=this.rowValidator(i);for(const[e,i]of h){if(String(i[r])!==t)continue;const o="CASCADE"===a.onUpdate?s:null,{values:h}=c.validatePartial({[r]:o});this.removeIndexEntries(n,i,e),i[r]=h[r],this.updateIndexes(n,i,e)}}}async delete(e,t){this.ensureTable(e);const s=this.tables.get(e),n=[];for(const[e,i]of s)t.where&&0!==Object.keys(t.where).length&&!k(i,t.where)||n.push({pk:e,row:i});const i=new Set;for(const{pk:t}of n)this.checkCascadeRestrict(e,t,i);let r=0;for(const{pk:t,row:s}of n)this.removeIndexEntries(e,s,t),r+=await this.cascadeDelete(e,t,s);for(const{pk:e}of n)s.delete(e);return n.length+r}checkCascadeRestrict(e,t,s){const i=`${e}:${t}`;if(!s.has(i)){s.add(i);for(const[i,r]of this.schemas)for(const[a,o]of Object.entries(r.columns)){if(!o.references||!o.onDelete)continue;const[r]=o.references.split(".");if(r!==e)continue;const h=this.tables.get(i);if(!h)continue;const c=[];for(const[e,s]of h)String(s[a])===t&&c.push(e);if("RESTRICT"===o.onDelete&&c.length>0)throw new n(`Cannot delete from "${e}": foreign key "${a}" in "${i}" has dependent rows`,"FOREIGN_KEY_VIOLATION");if("SET NULL"===o.onDelete&&o.required&&c.length>0)throw new n(`Cannot delete from "${e}": foreign key "${a}" in "${i}" is required (SET NULL violates constraint)`,"FOREIGN_KEY_VIOLATION");if("CASCADE"===o.onDelete)for(const e of c)this.checkCascadeRestrict(i,e,s)}}}async count(e,t){this.ensureTable(e);const s=this.tables.get(e);if(!t?.where||0===Object.keys(t.where).length)return s.size;let n=0;for(const e of s.values())k(e,t.where)&&n++;return n}async clear(e){this.ensureTable(e),this.tables.get(e).clear();const t=this.indexes.get(e);if(t)for(const e of t.values())e.clear()}async createIndex(e,t,s){if(this.snapshot)throw new n("CREATE INDEX is not supported inside a transaction (MemoryEngine DDL is not transactional)","NOT_SUPPORTED");this.ensureTable(e);const i=this.schemas.get(e).columns[t];if(!i)throw new n(`Column "${t}" does not exist in table "${e}"`,"COLUMN_NOT_FOUND");if(i.index||i.unique)return;const r=this.indexes.get(e);r.has(t)||r.set(t,new Map);const a=r.get(t),o=this.tables.get(e);try{for(const[i,r]of o){const o=r[t];if(null!=o){if(s&&a.has(o))throw new n(`Unique index on column "${t}" in table "${e}" cannot be created: duplicate value "${String(o)}"`,"UNIQUE_VIOLATION");a.has(o)||a.set(o,new Set),a.get(o).add(i)}}}catch(e){throw r.delete(t),e}i.index=!0,s&&(i.unique=!0,this.uniqueIndexCols.add(`${e}:${t}`))}async dropIndex(e,t,s){if(this.snapshot)throw new n("DROP INDEX is not supported inside a transaction (MemoryEngine DDL is not transactional)","NOT_SUPPORTED");this.ensureTable(e);const i=this.schemas.get(e).columns[t];if(!i)throw new n(`Column "${t}" does not exist in table "${e}"`,"COLUMN_NOT_FOUND");if(!i.index&&!i.unique)throw new n(`Index on column "${t}" does not exist in table "${e}"`,"INDEX_NOT_FOUND");const r=`${e}:${t}`;if(i.unique&&!this.uniqueIndexCols.has(r))throw new n(`Cannot drop index on column "${t}" in table "${e}": UNIQUE constraint defined at table creation must be removed by recreating the table`,"NOT_SUPPORTED");i.index=!1,i.unique=!1,this.uniqueIndexCols.delete(r);const a=this.indexes.get(e);a&&a.delete(t)}async beginTransaction(){if(this.snapshot)throw new n("Transaction already in progress","TX_ACTIVE");this.snapshot={tables:this.deepCloneMapMap(this.tables),schemas:new Map(this.schemas),indexes:this.deepCloneIndexes(this.indexes)}}async commitTransaction(){if(!this.snapshot)throw new n("No active transaction","TX_NONE");this.snapshot=null}async rollbackTransaction(){if(!this.snapshot)throw new n("No active transaction","TX_NONE");this.tables=this.snapshot.tables,this.schemas=this.snapshot.schemas,this.indexes=this.snapshot.indexes,this.snapshot=null}deepCloneMapMap(e){const t=new Map;for(const[s,n]of e){const e=new Map;for(const[t,s]of n)e.set(t,{...s});t.set(s,e)}return t}deepCloneIndexes(e){const t=new Map;for(const[s,n]of e){const e=new Map;for(const[t,s]of n){const n=new Map;for(const[e,t]of s)n.set(e,new Set(t));e.set(t,n)}t.set(s,e)}return t}ensureTable(e){if(!this.tables.has(e))throw new n(`Table "${e}" does not exist`,"TABLE_NOT_FOUND")}getPrimaryKey(e){for(const[t,s]of Object.entries(e.columns))if(s.primaryKey)return t;return Object.keys(e.columns)[0]}validateRow(e,t){return this.rowValidator(e).validateRow(t)}rowValidator(e){return z(e)}async validatePayload(e,t,s="insert"){this.ensureTable(e);const n=this.schemas.get(e),i=this.rowValidator(n);for(const e of t)"update"===s?i.validatePartial(G(e)):i.validateRow(e)}tryIndexLookup(e,t,s){const n=this.indexes.get(e);if(!n||!s.where)return Array.from(t.values());const i=[],r=e=>{for(const[t,s]of Object.entries(e))if("$and"!==t)"$or"!==t&&"$not"!==t&&i.push([t,s]);else for(const e of s)r(e)};r(s.where);for(const[e,s]of i){let i;if("object"!=typeof s||null===s)i=s;else{if(!("$eq"in s)||1!==Object.keys(s).length)continue;i=s.$eq}if(null==i)continue;if("object"==typeof i)continue;const r=n.get(e);if(r){const e=r.get(i);if(e){const s=[];for(const n of e){const e=t.get(n);e&&s.push(e)}return s}return[]}}return Array.from(t.values())}updateIndexes(e,t,s){const n=this.indexes.get(e);if(n)for(const[e,i]of n){const n=t[e];null!=n&&(i.has(n)||i.set(n,new Set),i.get(n).add(s))}}removeIndexEntries(e,t,s){const n=this.indexes.get(e);if(n)for(const[e,i]of n){const n=t[e];if(null!=n){const e=i.get(n);e&&(e.delete(s),0===e.size&&i.delete(n))}}}async cascadeDelete(e,t,s,i=new Set){const r=`${e}:${t}`;if(i.has(r))return 0;i.add(r);let a=0;for(const[s,r]of this.schemas)for(const[o,h]of Object.entries(r.columns)){if(!h.references||!h.onDelete)continue;const[r]=h.references.split(".");if(r!==e)continue;const c=this.tables.get(s);if(!c)continue;const l=[];for(const[e,s]of c)String(s[o])===t&&l.push(e);if("RESTRICT"===h.onDelete&&l.length>0)throw new n(`Cannot delete from "${e}": foreign key "${o}" in "${s}" has dependent rows`,"FOREIGN_KEY_VIOLATION");if("CASCADE"===h.onDelete)for(const e of l){const t=c.get(e);t&&(this.removeIndexEntries(s,t,e),a+=await this.cascadeDelete(s,e,t,i)),c.has(e)&&(c.delete(e),a++)}else if("SET NULL"===h.onDelete)for(const e of l){const t=c.get(e);t&&(this.removeIndexEntries(s,t,e),t[o]=null,this.updateIndexes(s,t,e))}}return a}}const X=[".crswap",".tmp"];class Y{constructor(){this.root=null,this.dbDir=null,this.dbName="",this.writeQueue=Promise.resolve()}async open(e){if(this.dbName=e,"undefined"==typeof navigator||!navigator.storage||"function"!=typeof navigator.storage.getDirectory)throw new n("OPFS is not available in this environment: navigator.storage.getDirectory is missing. Use the http(s) protocol (file:// is rejected by browsers) or switch to mode: 'memory' / a KVStore backend.","ARIA_OPFS_UNAVAILABLE");try{this.root=await navigator.storage.getDirectory()}catch(e){throw new n(`OPFS is not accessible here (${e.name}: ${e.message}). Chromium blocks OPFS for file:// pages — serve the page over http(s) (e.g. \`npx serve .\` / \`node tests/e2e/server.cjs\`) or use mode: 'memory'.`,"ARIA_OPFS_UNAVAILABLE",e)}this.dbDir=await this.root.getDirectoryHandle(e,{create:!0}),await this.cleanupStaleFiles()}async close(){try{await this.writeQueue}catch{}this.dbDir=null,this.root=null}isOpen(){return null!==this.dbDir}async cleanupStaleFiles(){if(this.dbDir)try{const e=this.dbDir,t=[];for await(const[s]of e.entries())X.some(e=>s.endsWith(e))&&t.push(s);for(const e of t)try{await this.dbDir.removeEntry(e)}catch{}}catch{}}async read(e){if(!this.dbDir)return null;try{const t=await this.dbDir.getFileHandle(e),s=await t.getFile();return await s.arrayBuffer()}catch{return null}}async write(e,t){if(!this.dbDir)return;const s=this.writeQueue.then(async()=>{const s=await this.dbDir.getFileHandle(e,{create:!0}),n=await s.createWritable();await n.write(t),await n.close()});return this.writeQueue=s.then(()=>{},()=>{}),s}async append(e,t){if(!this.dbDir)return;const s=this.writeQueue.then(async()=>{const s=await this.dbDir.getFileHandle(e,{create:!0}),n=await s.getFile(),i=await s.createWritable({keepExistingData:!0});await i.write({type:"write",position:n.size,data:t}),await i.close()});return this.writeQueue=s.then(()=>{},()=>{}),s}async writeMany(e){if(!this.dbDir)return;const t=this.writeQueue.then(async()=>{for(const[t,s]of Object.entries(e)){const e=await this.dbDir.getFileHandle(t,{create:!0}),n=await e.createWritable();await n.write(s),await n.close()}});return this.writeQueue=t.then(()=>{},()=>{}),t}async delete(e){if(!this.dbDir)return;const t=this.writeQueue.then(async()=>{try{await this.dbDir.removeEntry(e)}catch{}});return this.writeQueue=t.then(()=>{},()=>{}),t}async deleteMany(e){if(!this.dbDir)return;const t=this.writeQueue.then(async()=>{for(const t of e)try{await this.dbDir.removeEntry(t)}catch{}});return this.writeQueue=t.then(()=>{},()=>{}),t}async listKeys(){if(!this.dbDir)return[];const e=[],t=this.dbDir;for await(const[s]of t.entries())e.push(s);return e}async exists(e){if(!this.dbDir)return!1;try{return await this.dbDir.getFileHandle(e),!0}catch{return!1}}async clear(){if(!this.dbDir)return;const e=this.dbDir;for await(const[t]of e.entries())try{await this.dbDir.removeEntry(t)}catch{}}}const J=new Map;let Z=0,ee=new Map;class te{constructor(){this.dbName="",this.store=null}static clearRegistry(){J.clear(),Z+=1,ee=new Map}async open(e){this.dbName=e,this.store=function(e){const t=ee.get(e);if(t&&t.epoch===Z)return t.store;const s=J.get(e);if(s)return ee.set(e,{epoch:Z,store:s}),s;const n={chunks:new Map,materialized:new Map};return J.set(e,n),ee.set(e,{epoch:Z,store:n}),n}(e)}async close(){this.store=null}isOpen(){return""!==this.dbName&&null!==this.store}db(){return this.store||(this.store={chunks:new Map,materialized:new Map}),this.store}async read(e){const t=this.db();if(t.materialized.has(e))return t.materialized.get(e)??null;const s=t.chunks.get(e);if(!s||0===s.length)return t.materialized.set(e,null),null;if(1===s.length)return t.materialized.set(e,s[0]),s[0];const n=s.reduce((e,t)=>e+t.byteLength,0),i=new Uint8Array(n);let r=0;for(const e of s)i.set(new Uint8Array(e),r),r+=e.byteLength;const a=i.buffer;return t.materialized.set(e,a),a}async write(e,t){const s=this.db();s.chunks.set(e,[t]),s.materialized.set(e,t)}async append(e,t){const s=this.db(),n=s.chunks.get(e);n?n.push(t):s.chunks.set(e,[t]),s.materialized.delete(e)}async writeMany(e){const t=this.db();for(const[s,n]of Object.entries(e))t.chunks.set(s,[n]),t.materialized.set(s,n)}async delete(e){const t=this.db();t.chunks.delete(e),t.materialized.set(e,null)}async deleteMany(e){const t=this.db();for(const s of e)t.chunks.delete(s),t.materialized.set(s,null)}async listKeys(){return Array.from(this.db().chunks.keys())}async exists(e){return this.db().chunks.has(e)}async clear(){const e=this.db();e.chunks.clear(),e.materialized.clear()}}const se=(()=>{const e=new Uint32Array(256);for(let t=0;t<256;t++){let s=t;for(let e=0;e<8;e++)s=1&s?3988292384^s>>>1:s>>>1;e[t]=s>>>0}return e})(),ne=4294967295;function ie(e,t=0){const s=function(e,t){let s=e>>>0;for(let e=0;e<t.byteLength;e++)s=(se[255&(s^t[e])]^s>>>8)>>>0;return s>>>0}(t^ne,e);return function(e){return(e^ne)>>>0}(s)}var re;!function(e){e[e.PUT=1]="PUT",e[e.DELETE=2]="DELETE",e[e.APPEND=3]="APPEND"}(re||(re={}));const ae=1263948622;function oe(e,t){const s=new TextEncoder,n=Array.from(t.keys()),i=[];let r=12;for(const e of n){const n=s.encode(e),a=new Uint8Array(t.get(e));i.push({key:n,value:a}),r+=4+n.byteLength+4+a.byteLength}r+=4;const a=new Uint8Array(r),o=new DataView(a.buffer);let h=0;o.setUint32(h,ae,!1),h+=4,o.setUint32(h,e,!1),h+=4,o.setUint32(h,i.length,!1),h+=4;for(const e of i)o.setUint32(h,e.key.byteLength,!1),h+=4,a.set(e.key,h),h+=e.key.byteLength,o.setUint32(h,e.value.byteLength,!1),h+=4,a.set(e.value,h),h+=e.value.byteLength;const c=ie(a.subarray(0,r-4));return o.setUint32(r-4,c,!1),a}function he(e){if(e.byteLength<16)return null;const t=new DataView(e.buffer,e.byteOffset,e.byteLength);if(t.getUint32(0,!1)!==ae)return null;if(t.getUint32(e.byteLength-4,!1)!==ie(e.subarray(0,e.byteLength-4)))return null;const s=new TextDecoder,n=new Map;let i=4;const r=t.getUint32(i,!1);i+=4;const a=t.getUint32(i,!1);i+=4;for(let r=0;r<a;r++){if(i+4>e.byteLength-4)return null;const r=t.getUint32(i,!1);if(i+=4,i+r+4>e.byteLength-4)return null;const a=s.decode(e.subarray(i,i+r));i+=r;const o=t.getUint32(i,!1);if(i+=4,i+o>e.byteLength-4)return null;const h=e.slice(i,i+o).buffer;i+=o,n.set(a,h)}return{seq:r,entries:n}}const ce="__kv_log",le="__kv_snapshot",ue="__kv_meta";class fe{constructor(e,t=16777216){this.dbName="",this.opened=!1,this.index=new Map,this.seq=0,this.logBytes=0,this.opQueue=Promise.resolve(),this.lastBackgroundError=null,this.instanceId="",this.stale=!1,this.medium=e??function(){const e=globalThis.navigator;return void 0!==e&&e.storage&&"function"==typeof e.storage.getDirectory?new Y:new te}(),this.checkpointThreshold=t}isOpen(){return this.opened}async open(e){if(this.opened)return;this.dbName=e,this.lastBackgroundError=null,this.stale=!1,await this.medium.open(e),await this.claimOwnership(),this.index=new Map,this.seq=0,this.logBytes=0;let t=0;const s=await this.medium.read(le);if(s){const e=he(new Uint8Array(s));e?(this.index=new Map(e.entries),this.seq=e.seq,t=e.seq):(this.index=new Map,this.seq=0,t=0)}const n=await this.medium.read(ce);if(n&&n.byteLength>0){const e=new Uint8Array(n),s=t,i=[];(function(e,t,s){let n=0,i=0;const r=new DataView(e.buffer,e.byteOffset,e.byteLength),a=new TextDecoder;for(;n+4<=e.byteLength;){const o=r.getUint32(n,!1);if(o<12||n+4+o>e.byteLength){if(s&&!s(n))break;break}const h=n,c=n+4+o,l=e.subarray(h,c),u=new DataView(e.buffer,e.byteOffset+h,o+4);if(u.getUint32(o,!1)!==ie(l.subarray(0,o))){if(s&&!s(h))break;break}let f=4;const d=u.getUint32(f,!1);f+=4;const p=u.getUint32(f,!1);f+=4;const m=[];let y=!0;for(let e=0;e<p;e++){if(f+1+4>o+4){y=!1;break}const e=u.getUint8(f);f+=1;const t=u.getUint32(f,!1);if(f+=4,f+t+4>o+4){y=!1;break}const s=a.decode(l.subarray(f,f+t));f+=t;const n=u.getUint32(f,!1);if(f+=4,f+n>o+4){y=!1;break}const i=l.slice(f,f+n).buffer;f+=n,m.push({op:e,key:s,value:i})}if(!y){if(s&&!s(h))break;break}t({seq:d,entries:m,raw:l}),i++,n=c}return i}(e,e=>{e.seq<=s||(this.applyRecord(e.entries),this.seq=e.seq)},e=>(i.push(e),!0))>0||i.length>0)&&(this.logBytes=e.byteLength),i.length>0&&await this.truncateLogTo(this.findValidLogLength(e))}this.opened=!0}async reload(){if(this.opened){try{await this.opQueue}catch{}this.index=new Map,this.seq=0,this.logBytes=0,this.opened=!1,await this.open(this.dbName)}}async close(){if(this.opened){try{await this.opQueue}catch{}await this.medium.close(),this.index.clear(),this.seq=0,this.logBytes=0,this.lastBackgroundError=null,this.instanceId="",this.stale=!1,this.opened=!1}}async get(e){return this.index.get(e)??null}async getAll(){return Array.from(this.index.entries())}async listKeys(){return Array.from(this.index.keys())}async exists(e){return this.index.has(e)}size(){return this.index.size}async put(e,t){await this.enqueue(async()=>{await this.appendRecord({[e]:t},[])})}async putMany(e){0!==Object.keys(e).length&&await this.enqueue(async()=>{await this.appendRecord(e,[])})}async delete(e){await this.enqueue(async()=>{await this.appendRecord({},[e])})}async deleteMany(e){0!==e.length&&await this.enqueue(async()=>{await this.appendRecord({},e)})}async writeBatch(e,t){0===Object.keys(e).length&&0===t.length||await this.enqueue(async()=>{await this.appendRecord(e,t)})}async appendValue(e,t){0!==t.byteLength&&await this.enqueue(async()=>{await this.appendRecord({},[],{[e]:t})})}async checkpoint(){await this.enqueue(async()=>{if(await this.assertOwnership(),null!==this.lastBackgroundError){const e=this.lastBackgroundError;throw this.lastBackgroundError=null,new n("KVStore background write failed","KV_BACKGROUND_ERROR",e)}if(0===this.logBytes&&0===this.index.size)return;const e=oe(this.seq,this.index);await this.medium.write(le,e.buffer),await this.writeMeta(),await this.truncateLog()})}async clear(){await this.enqueue(async()=>{await this.medium.clear(),this.index.clear(),this.seq=0,this.logBytes=0,await this.medium.write(ue,(new TextEncoder).encode(JSON.stringify({seq:0})).buffer)})}async repair(){return this.enqueue(async()=>{let e=0;const t=await this.medium.read(le);t&&!he(new Uint8Array(t))&&(await this.medium.delete(le),e++);const s=await this.medium.read(ce);if(s&&s.byteLength>0){const t=new Uint8Array(s),n=this.findValidLogLength(t);if(n<t.byteLength){e+=t.byteLength-n;const s=t.subarray(0,n).slice().buffer;await this.medium.write(ce,s)}}return e})}enqueue(e){const t=this.opQueue.then(e,e);return this.opQueue=t.then(()=>{},()=>{}),t}async appendRecord(e,t,s={}){if(this.stale)throw new n("KVStore instance has been superseded by another instance on the same database; re-open the database to continue","STALE_INSTANCE");this.seq++;const i=function(e,t,s=[],n={}){const i=new TextEncoder,r=[];for(const[e,s]of Object.entries(t))r.push({op:re.PUT,key:e,value:s});for(const e of s)r.push({op:re.DELETE,key:e,value:new ArrayBuffer(0)});for(const[e,t]of Object.entries(n))r.push({op:re.APPEND,key:e,value:t});const a=[];let o=12;for(const e of r){const t=i.encode(e.key),s=new Uint8Array(e.value);a.push({op:e.op,key:t,value:s}),o+=5+t.byteLength+4+s.byteLength}o+=4;const h=new Uint8Array(o),c=new DataView(h.buffer);let l=0;c.setUint32(l,o-4,!1),l+=4,c.setUint32(l,e,!1),l+=4,c.setUint32(l,a.length,!1),l+=4;for(const e of a)c.setUint8(l,e.op),l+=1,c.setUint32(l,e.key.byteLength,!1),l+=4,h.set(e.key,l),l+=e.key.byteLength,c.setUint32(l,e.value.byteLength,!1),l+=4,h.set(e.value,l),l+=e.value.byteLength;const u=ie(h.subarray(0,o-4));return c.setUint32(o-4,u,!1),h}(this.seq,e,t,s);try{const e=i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength);if("function"==typeof this.medium.append)await this.medium.append(ce,e);else{const t=await this.medium.read(ce);if(t){const s=new Uint8Array(t.byteLength+e.byteLength);s.set(new Uint8Array(t),0),s.set(new Uint8Array(e),t.byteLength),await this.medium.write(ce,s.buffer)}else await this.medium.write(ce,e)}}catch(e){throw this.seq--,this.lastBackgroundError=e,new n("KVStore log append failed","KV_LOG_ERROR",e)}for(const[t,s]of Object.entries(e))this.index.set(t,s);for(const e of t)this.index.delete(e);for(const[e,t]of Object.entries(s)){const s=this.index.get(e);if(s){const n=new Uint8Array(s.byteLength+t.byteLength);n.set(new Uint8Array(s),0),n.set(new Uint8Array(t),s.byteLength),this.index.set(e,n.buffer)}else this.index.set(e,t)}this.logBytes+=i.byteLength,this.checkpointThreshold>0&&this.logBytes>=this.checkpointThreshold&&await this.autoCheckpoint()}async autoCheckpoint(){try{await this.assertOwnership(),await this.medium.write(le,oe(this.seq,this.index).buffer),await this.writeMeta(),await this.truncateLog()}catch(e){this.stale||(this.lastBackgroundError=e)}}async truncateLog(){try{await this.medium.write(ce,new ArrayBuffer(0))}catch{}this.logBytes=0}async truncateLogTo(e){try{const t=await this.medium.read(ce);if(!t)return;if(e>=t.byteLength)return;const s=new Uint8Array(t).subarray(0,e).slice();await this.medium.write(ce,s.buffer),this.logBytes=e}catch{}}applyRecord(e){for(const t of e)if(t.op===re.PUT)this.index.set(t.key,t.value);else if(t.op===re.APPEND){const e=this.index.get(t.key);if(e){const s=new Uint8Array(e.byteLength+t.value.byteLength);s.set(new Uint8Array(e),0),s.set(new Uint8Array(t.value),e.byteLength),this.index.set(t.key,s.buffer)}else this.index.set(t.key,t.value)}else this.index.delete(t.key)}newInstanceId(){const e=Math.random().toString(36).slice(2);return`kv-${Date.now().toString(36)}-${e}`}async readMeta(){try{const e=await this.medium.read(ue);return e&&0!==e.byteLength?JSON.parse((new TextDecoder).decode(e)):null}catch{return null}}async writeMeta(){const e={seq:this.seq,owner:this.instanceId};await this.medium.write(ue,(new TextEncoder).encode(JSON.stringify(e)).buffer)}async claimOwnership(){this.instanceId=this.newInstanceId(),await this.writeMeta()}async assertOwnership(){const e=await this.readMeta();if(e?.owner&&this.instanceId&&e.owner!==this.instanceId)throw this.stale=!0,new n("KVStore instance has been superseded by another instance on the same database (refusing to commit a stale snapshot, which would discard the newer instance's writes); re-open the database to continue","STALE_INSTANCE")}isStale(){return this.stale}findValidLogLength(e){let t=0;const s=new DataView(e.buffer,e.byteOffset,e.byteLength);for(;t+4<=e.byteLength;){const n=s.getUint32(t,!1);if(n<12||t+4+n>e.byteLength)break;const i=e.subarray(t,t+4+n),r=s.getUint32(t+n,!1);if(ie(i.subarray(0,n))!==r)break;t+=4+n}return t}}const de="__schema",pe="t:",me=e=>(new TextEncoder).encode(e).buffer,ye=e=>(new TextDecoder).decode(e);class ge{constructor(e,t){this.name="kv",this.memory=new Q,this.dbName="",this.version=1,this.opened=!1,this.txActive=!1,this.txDirtyTables=new Set,this.txSchemaChanged=!1,this.txChanges=new Map,this.txFullTables=new Set,this.txClearedTables=new Set,this.kv=new fe(e,t)}rowKey(e,t){return`${pe}${e}:${t}`}rowPrefix(e){return`${pe}${e}:`}async open(e,t){if(this.opened)return;this.dbName=e,this.version=t,await this.kv.open(e),await this.memory.open(e,t);const s=await this.kv.get(de);if(s)try{const e=JSON.parse(ye(s));for(const t of Object.values(e))await this.memory.createTable(t)}catch{throw new n("Corrupted schema in KVStore","KV_SCHEMA_ERROR")}const i=await this.kv.getAll();for(const[e,t]of i){if(!e.startsWith(pe))continue;const s=e.indexOf(":",2);if(s<0)continue;const n=e.slice(2,s);if(await this.memory.hasTable(n))try{const e=JSON.parse(ye(t));await this.memory.insert(n,[e])}catch{}}const r=await this.memory.getTableNames();for(const e of r){const t=await this.memory.getTableSchema(e);if(t)for(const[s,n]of Object.entries(t.columns))(n.index||n.unique)&&await this.memory.createIndex(e,s,n.unique)}this.opened=!0}async close(){if(this.opened){if(this.txActive)try{await this.rollbackTransaction()}catch{}try{await this.kv.checkpoint()}catch{}await this.kv.close(),await this.memory.close(),this.opened=!1}}isOpen(){return this.opened}async reload(){this.opened&&(await this.kv.reload(),await this.memory.close(),await this.memory.open(this.dbName,this.version),this.opened=!1,await this.open(this.dbName,this.version))}async repair(){this.ensureOpen(),await this.kv.repair(),await this.memory.close(),await this.memory.open(this.dbName,this.version),this.opened=!1,await this.open(this.dbName,this.version)}async clearAll(){this.ensureOpen(),await this.kv.clear(),await this.memory.clearAll()}async getMeta(e){const t=await this.kv.get(`__meta:${e}`);return t?ye(t):null}async setMeta(e,t){await this.kv.put(`__meta:${e}`,me(t))}async createTable(e){if(this.ensureOpen(),await this.memory.createTable(e),this.txActive)return this.txDirtyTables.add(e.name),void(this.txSchemaChanged=!0);await this.persistSchema()}async dropTable(e){if(this.ensureOpen(),await this.memory.dropTable(e),this.txActive)return this.txDirtyTables.add(e),void(this.txSchemaChanged=!0);await this.persistSchema();const t=await this.collectTableDiff(e);await this.kv.writeBatch(t.puts,t.deletes)}async hasTable(e){return this.ensureOpen(),this.memory.hasTable(e)}async getTableNames(){return this.ensureOpen(),this.memory.getTableNames()}async getTableSchema(e){return this.ensureOpen(),this.memory.getTableSchema(e)}async alterTable(e,t,s){if(this.ensureOpen(),this.txActive)throw new n("ALTER TABLE is not supported inside a transaction (KVStoreEngine DDL is not transactional)","NOT_SUPPORTED");if(await this.memory.alterTable(e,t,s),this.txActive)return this.txDirtyTables.add(e),void(this.txSchemaChanged=!0);if(await this.persistSchema(),"DROP"===t){const t=await this.collectTableDiff(e);await this.kv.writeBatch(t.puts,t.deletes)}}async validatePayload(e,t,s="insert"){return this.ensureOpen(),this.memory.validatePayload(e,t,s)}async insert(e,t){this.ensureOpen();const s=await this.memory.insert(e,t);if(this.txActive){if(this.txDirtyTables.add(e),this.txClearedTables.has(e))return this.txClearedTables.delete(e),this.txFullTables.add(e),s;let t=this.txChanges.get(e);t||(t=new Map,this.txChanges.set(e,t));for(const e of s)t.set(e,"put");return s}if(!await this.memory.getTableSchema(e))throw new n(`Table "${e}" does not exist`,"TABLE_NOT_FOUND");const i={};for(const t of s){const s=this.memory.getRow(e,t);s&&(i[this.rowKey(e,t)]=me(JSON.stringify(s)))}return await this.kv.putMany(i),s}async find(e,t){return this.ensureOpen(),this.memory.find(e,t)}async findStream(e,t,s){return this.ensureOpen(),this.memory.findStream(e,t,s)}async update(e,t,s){this.ensureOpen();const i=await this.memory.getTableSchema(e);if(!i)throw new n(`Table "${e}" does not exist`,"TABLE_NOT_FOUND");const r=this.getPK(i),a=G(s),o=r in a,h=o?[]:await this.collectMatchingPks(e,t),c=await this.memory.update(e,t,a);if(this.txActive){if(this.txDirtyTables.add(e),o)for(const t of await this.affectedTables(e))this.txFullTables.add(t),this.txDirtyTables.add(t);else{let t=this.txChanges.get(e);t||(t=new Map,this.txChanges.set(e,t));for(const e of h)t.set(e,"put");for(const t of await this.affectedTables(e))t!==e&&(this.txFullTables.add(t),this.txDirtyTables.add(t))}return c}const l={},u=[];if(o)for(const t of await this.affectedTables(e)){const e=await this.collectTableDiff(t);Object.assign(l,e.puts),u.push(...e.deletes)}else{const t=new Set(h),s=await this.memory.find(e,{table:e});for(const n of s){const s=String(n[r]);t.has(s)&&(l[this.rowKey(e,s)]=me(JSON.stringify(n)),t.delete(s))}for(const s of t)u.push(this.rowKey(e,s));for(const t of await this.affectedTables(e)){if(t===e)continue;const s=await this.collectTableDiff(t);Object.assign(l,s.puts),u.push(...s.deletes)}}return await this.kv.writeBatch(l,u),c}async delete(e,t){this.ensureOpen();const s=await this.collectMatchingPks(e,t),n=await this.memory.delete(e,t);if(this.txActive){this.txDirtyTables.add(e);let t=this.txChanges.get(e);t||(t=new Map,this.txChanges.set(e,t));for(const e of s)t.set(e,"delete");for(const t of await this.affectedTables(e))t!==e&&(this.txFullTables.add(t),this.txDirtyTables.add(t));return n}const i={},r=s.map(t=>this.rowKey(e,t));for(const t of await this.affectedTables(e)){if(t===e)continue;const s=await this.collectTableDiff(t);Object.assign(i,s.puts),r.push(...s.deletes)}return await this.kv.writeBatch(i,r),n}async count(e,t){return this.ensureOpen(),this.memory.count(e,t)}async clear(e){if(this.ensureOpen(),await this.memory.clear(e),this.txActive)return this.txDirtyTables.add(e),this.txClearedTables.add(e),void this.txChanges.delete(e);const t=await this.collectTableDiff(e);await this.kv.writeBatch(t.puts,t.deletes)}async createIndex(e,t,s){if(this.ensureOpen(),this.txActive)throw new n("CREATE INDEX is not supported inside a transaction (KVStoreEngine DDL is not transactional)","NOT_SUPPORTED");if(await this.memory.createIndex(e,t,s),this.txActive)return this.txDirtyTables.add(e),void(this.txSchemaChanged=!0);await this.persistSchema()}async dropIndex(e,t,s){if(this.ensureOpen(),this.txActive)throw new n("DROP INDEX is not supported inside a transaction (KVStoreEngine DDL is not transactional)","NOT_SUPPORTED");if(await this.memory.dropIndex(e,t,s),this.txActive)return this.txDirtyTables.add(e),void(this.txSchemaChanged=!0);await this.persistSchema()}async beginTransaction(){this.ensureOpen(),await this.memory.beginTransaction(),this.txActive=!0,this.txDirtyTables=new Set,this.txSchemaChanged=!1,this.txChanges=new Map,this.txFullTables=new Set,this.txClearedTables=new Set}async commitTransaction(){if(this.ensureOpen(),!this.txActive)throw new n("No active transaction","TX_NONE");const e={},t=[];for(const s of this.txDirtyTables){if(!await this.memory.hasTable(s)){const e=await this.kv.getAll(),n=this.rowPrefix(s);for(const[s]of e)s.startsWith(n)&&t.push(s);continue}if(this.txClearedTables.has(s)){const e=await this.kv.getAll(),n=this.rowPrefix(s);for(const[s]of e)s.startsWith(n)&&t.push(s);continue}if(this.txFullTables.has(s)){const n=await this.collectTableDiff(s);Object.assign(e,n.puts),t.push(...n.deletes);continue}const n=this.txChanges.get(s);if(n&&n.size>0){const i=await this.memory.getTableSchema(s);if(!i)continue;const r=this.getPK(i),a=new Map(n),o=await this.memory.find(s,{table:s});for(const n of o){const i=String(n[r]),o=a.get(i);void 0!==o&&("put"===o?e[this.rowKey(s,i)]=me(JSON.stringify(n)):t.push(this.rowKey(s,i)),a.delete(i))}for(const[e,n]of a)"delete"===n&&t.push(this.rowKey(s,e))}}await this.kv.writeBatch(e,t),this.txSchemaChanged&&await this.persistSchema(),await this.memory.commitTransaction(),this.txActive=!1,this.txDirtyTables=new Set,this.txChanges=new Map,this.txFullTables=new Set,this.txClearedTables=new Set}async rollbackTransaction(){if(this.ensureOpen(),!this.txActive)throw new n("No active transaction","TX_NONE");await this.memory.rollbackTransaction(),this.txActive=!1,this.txDirtyTables=new Set,this.txSchemaChanged=!1,this.txChanges=new Map,this.txFullTables=new Set,this.txClearedTables=new Set}ensureOpen(){if(!this.opened)throw new n("Database not opened","DB_NOT_OPEN")}getPK(e){for(const[t,s]of Object.entries(e.columns))if(s.primaryKey)return t;return Object.keys(e.columns)[0]}async collectMatchingPks(e,t){const s=await this.memory.getTableSchema(e);if(!s)throw new n(`Table "${e}" does not exist`,"TABLE_NOT_FOUND");const i=this.getPK(s);return(await this.memory.find(e,t)).map(e=>String(e[i]))}async affectedTables(e){const t=new Set([e]);let s=!0;for(;s;){s=!1;for(const e of await this.memory.getTableNames()){if(t.has(e))continue;const n=await this.memory.getTableSchema(e);if(n)for(const i of Object.values(n.columns))if(i.references){const n=i.references.split(".")[0];if(t.has(n)){t.add(e),s=!0;break}}}}return t}async persistSchema(){const e={};for(const t of await this.memory.getTableNames()){const s=await this.memory.getTableSchema(t);s&&(e[t]=s)}await this.kv.put(de,me(JSON.stringify(e)))}async collectTableDiff(e){const t=this.rowPrefix(e),s={},n=[],i=await this.memory.getTableSchema(e);if(i){const r=this.getPK(i),a=await this.memory.find(e,{table:e}),o=new Set;for(const t of a){const n=this.rowKey(e,String(t[r]));o.add(n),s[n]=me(JSON.stringify(t))}const h=await this.kv.getAll();for(const[e]of h)e.startsWith(t)&&!o.has(e)&&n.push(e)}else{const e=await this.kv.getAll();for(const[s]of e)s.startsWith(t)&&n.push(s)}return{puts:s,deletes:n}}}const we=4096;var be;!function(e){e[e.DATA=1]="DATA",e[e.INDEX=2]="INDEX",e[e.OVERFLOW=3]="OVERFLOW",e[e.META=4]="META"}(be||(be={}));const Te=4194304;var Ee,Se;!function(e){e[e.INSERT=1]="INSERT",e[e.UPDATE=2]="UPDATE",e[e.DELETE=3]="DELETE",e[e.BEGIN=4]="BEGIN",e[e.COMMIT=5]="COMMIT",e[e.ROLLBACK=6]="ROLLBACK",e[e.CREATE_TABLE=7]="CREATE_TABLE",e[e.DROP_TABLE=8]="DROP_TABLE",e[e.SAVEPOINT_ROLLBACK=9]="SAVEPOINT_ROLLBACK",e[e.ALTER_TABLE=10]="ALTER_TABLE"}(Ee||(Ee={})),function(e){e[e.ACTIVE=1]="ACTIVE",e[e.COMMITTED=2]="COMMITTED",e[e.ABORTED=3]="ABORTED"}(Se||(Se={}));const ke={pageSize:we,bufferPoolPages:256,memtableSizeThreshold:Te,levelSizeMultiplier:10,bloomFilterBitsPerKey:10,walEnabled:!0,walSyncMode:"full",checkpointInterval:1e3,compression:!1,storageBackend:"opfs",walSizeThreshold:16777216,maxMemoryMB:64,encryption:void 0,pageStorage:void 0,testBackend:void 0};var Ae;!function(e){e[e.RED=0]="RED",e[e.BLACK=1]="BLACK"}(Ae||(Ae={}));class xe{constructor(e,t){this.color=Ae.RED,this.left=null,this.right=null,this.parent=null,this.key=e,this.value=t}}class Ie{constructor(){this.root=null,this._size=0}get size(){return this._size}insert(e,t){const s=new xe(e,t);if(!this.root)return this.root=s,s.color=Ae.BLACK,void this._size++;let n=null,i=this.root;for(;i;)if(n=i,e<i.key)i=i.left;else{if(!(e>i.key))return void(i.value=t);i=i.right}s.parent=n,e<n.key?n.left=s:n.right=s,this._size++,this.fixInsert(s)}find(e){let t=this.root;for(;t;)if(e<t.key)t=t.left;else{if(!(e>t.key))return t.value;t=t.right}return null}delete(e){const t=this.findNode(e);return!!t&&(this.deleteNode(t),this._size--,!0)}inorder(e){this._inorder(this.root,e)}rangeScan(e,t,s){this._rangeScan(this.root,e,t,s)}*scanLazy(e,t){const s=[];let n=this.root;for(;n;)n.key>=e?(s.push(n),n=n.left):n=n.right;for(;s.length>0;){const i=s.pop();if(i.key>t)break;for(i.key>=e&&(yield[i.key,i.value]),n=i.right;n;)s.push(n),n=n.left}}getAllEntries(){const e=[];return this.inorder((t,s)=>e.push([t,s])),e}clear(){this.root=null,this._size=0}findNode(e){let t=this.root;for(;t;)if(e<t.key)t=t.left;else{if(!(e>t.key))return t;t=t.right}return null}deleteNode(e){if(e.left||e.right)if(e.left)if(e.right){const t=this.minimum(e.right),s=t.right,n=t.parent;n!==e&&(this.transplant(t,s),t.right=e.right,t.right.parent=t),this.transplant(e,t),t.left=e.left,t.left.parent=t;const i=t.color;if(t.color=e.color,i===Ae.BLACK){const i=s,r=i?i.parent:n===e?t:n;this.fixDelete(i,r)}}else this.transplant(e,e.left),e.color===Ae.BLACK&&this.fixDelete(e.left,e.left.parent);else this.transplant(e,e.right),e.color===Ae.BLACK&&this.fixDelete(e.right,e.right.parent);else this.transplant(e,null),e.color===Ae.BLACK&&this.fixDelete(null,e.parent)}transplant(e,t){e.parent?e===e.parent.left?e.parent.left=t:e.parent.right=t:this.root=t,t&&(t.parent=e.parent)}minimum(e){for(;e.left;)e=e.left;return e}fixInsert(e){for(;e.parent&&e.parent.color===Ae.RED;){const t=e.parent,s=t.parent;if(!s)break;if(t===s.left){const n=s.right;n&&n.color===Ae.RED?(t.color=Ae.BLACK,n.color=Ae.BLACK,s.color=Ae.RED,e=s):(e===t.right&&(e=t,this.rotateLeft(e)),e.parent&&(e.parent.color=Ae.BLACK),e.parent?.parent&&(e.parent.parent.color=Ae.RED),e.parent?.parent&&this.rotateRight(e.parent.parent))}else{const n=s.left;n&&n.color===Ae.RED?(t.color=Ae.BLACK,n.color=Ae.BLACK,s.color=Ae.RED,e=s):(e===t.left&&(e=t,this.rotateRight(e)),e.parent&&(e.parent.color=Ae.BLACK),e.parent?.parent&&(e.parent.parent.color=Ae.RED),e.parent?.parent&&this.rotateLeft(e.parent.parent))}}this.root&&(this.root.color=Ae.BLACK)}fixDelete(e,t){let s=e,n=t;for(;(!s||s.color===Ae.BLACK)&&s!==this.root&&n;)if(s===n.left){let e=n.right;if(!e)break;if(e.color===Ae.RED&&(e.color=Ae.BLACK,n.color=Ae.RED,this.rotateLeft(n),e=n.right,!e))break;const t=e.left,i=e.right;if(t&&t.color!==Ae.BLACK||i&&i.color!==Ae.BLACK){if(!(i&&i.color!==Ae.BLACK||(t&&(t.color=Ae.BLACK),e.color=Ae.RED,this.rotateRight(e),e=n.right,e)))break;e.color=n.color,n.color=Ae.BLACK,e.right&&(e.right.color=Ae.BLACK),this.rotateLeft(n),s=this.root}else e.color=Ae.RED,s=n,n=s.parent}else{let e=n.left;if(!e)break;if(e.color===Ae.RED&&(e.color=Ae.BLACK,n.color=Ae.RED,this.rotateRight(n),e=n.left,!e))break;const t=e.left,i=e.right;if(t&&t.color!==Ae.BLACK||i&&i.color!==Ae.BLACK){if(!(t&&t.color!==Ae.BLACK||(i&&(i.color=Ae.BLACK),e.color=Ae.RED,this.rotateLeft(e),e=n.left,e)))break;e.color=n.color,n.color=Ae.BLACK,e.left&&(e.left.color=Ae.BLACK),this.rotateRight(n),s=this.root}else e.color=Ae.RED,s=n,n=s.parent}s&&(s.color=Ae.BLACK)}rotateLeft(e){const t=e.right;t&&(e.right=t.left,t.left&&(t.left.parent=e),t.parent=e.parent,e.parent?e===e.parent.left?e.parent.left=t:e.parent.right=t:this.root=t,t.left=e,e.parent=t)}rotateRight(e){const t=e.left;t&&(e.left=t.right,t.right&&(t.right.parent=e),t.parent=e.parent,e.parent?e===e.parent.right?e.parent.right=t:e.parent.left=t:this.root=t,t.right=e,e.parent=t)}_inorder(e,t){e&&(this._inorder(e.left,t),t(e.key,e.value),this._inorder(e.right,t))}_rangeScan(e,t,s,n){e&&(e.key>t&&this._rangeScan(e.left,t,s,n),e.key>=t&&e.key<=s&&n(e.key,e.value),e.key<s&&this._rangeScan(e.right,t,s,n))}}class Re{constructor(e=4194304){this._estimatedSize=0,this.tree=new Ie,this.maxSize=e}put(e,t){const s=this.estimateEntrySize(e,this.tree.find(e)),n=this.estimateEntrySize(e,t);this.tree.insert(e,t),this._estimatedSize+=n-s}get(e){return this.tree.find(e)}delete(e){const t=this.tree.find(e);return t&&(this._estimatedSize-=this.estimateEntrySize(e,t)),this.tree.delete(e)}shouldFlush(){return this._estimatedSize>=this.maxSize}getAllEntries(){return this.tree.getAllEntries()}rangeScan(e,t){const s=[];return this.tree.rangeScan(e,t,(e,t)=>s.push([e,t])),s}scanLazy(e,t){return this.tree.scanLazy(e,t)}getEntryCount(){return this.tree.size}getEstimatedSize(){return this._estimatedSize}clear(){this.tree.clear(),this._estimatedSize=0}estimateEntrySize(e,t){if(!t)return 0;let s=2*e.length;for(const e of Object.entries(t)){s+=2*e[0].length;const t=e[1];s+="string"==typeof t?2*t.length:"number"==typeof t?8:"boolean"==typeof t||null==t?1:16}return s}}class Oe{constructor(e,t=10){this._inserted=0;const s=Math.max(64,e*t),n=Math.ceil(s/8);this.bits=new Uint8Array(n),this.numHashes=Math.max(1,Math.floor(.69*t))}static fromData(e,t){const s=new Oe(1);return s.bits=e,s.numHashes=t,s}insert(e){const t=this.getHashes(e);for(const e of t){const t=Math.floor(e/8),s=e%8;this.bits[t]|=1<<s}this._inserted++}mayContain(e){const t=this.getHashes(e);for(const e of t){const t=Math.floor(e/8),s=e%8;if(!(this.bits[t]&1<<s))return!1}return!0}serialize(){return this.bits}getHashCount(){return this.numHashes}getHashes(e){const t=8*this.bits.byteLength,s=this.fnv1a(e),n=this.murmurSimple(e),i=[];for(let e=0;e<this.numHashes;e++){const r=Math.abs((s+e*n)%t);i.push(r)}return i}fnv1a(e){let t=2166136261;for(let s=0;s<e.length;s++)t^=e.charCodeAt(s),t=16777619*t>>>0;return t}murmurSimple(e){let t=0;for(let s=0;s<e.length;s++)t=(t<<5)-t+e.charCodeAt(s)|0,t=(t^t>>>16)>>>0;return Math.abs(t)}}const Ce=1397969987;class Ne{constructor(e=4096,t=10){this.entries=[],this.blockSizeLimit=e,this.bloomBitsPerKey=Number.isFinite(t)&&t>0?Math.floor(t):10}add(e,t){this.entries.push([e,t])}build(){const e=new TextEncoder,t=this.entries.map(([t,s])=>({key:t,keyBytes:e.encode(t),valueBytes:e.encode(JSON.stringify(s))})),s=this.splitIntoBlocks(t),n=new Oe(this.entries.length,this.bloomBitsPerKey);let i=0;const r=[];for(const e of s)r.push(i),i+=this.computeBlockSize(e);const a=[];for(let e=0;e<s.length;e++){const t=s[e];a.push({key:t[t.length-1].key,blockOffset:r[e],blockSize:this.computeBlockSize(t)})}const o=this.estimateIndexBlockSize(a),h=n.serialize(),c=h.byteLength,l=new ArrayBuffer(i+o+c+32),u=new DataView(l);let f=0;for(const e of s)f=this.writeDataBlock(u,f,e,n);const d=f;f=this.writeIndexBlock(u,f,a);const p=f;new Uint8Array(u.buffer).set(h,f),f+=c;const m=f;u.setUint32(m,d,!1),u.setUint32(m+4,o,!1),u.setUint32(m+8,p,!1),u.setUint32(m+12,c,!1),u.setUint32(m+16,n.getHashCount(),!1),u.setUint32(m+20,this.entries.length,!1),u.setUint32(m+24,Ce,!1),u.setUint32(m+28,0,!1);const y=new Uint8Array(l);let g=ie(y.subarray(0,y.byteLength-4));return 0===g&&(g=1),u.setUint32(m+28,g,!1),{sstableData:new Uint8Array(l),indexEntries:a}}getEntryCount(){return this.entries.length}splitIntoBlocks(e){const t=[];let s=[];for(const n of e)s.push(n),this.computeBlockSize(s)>=this.blockSizeLimit&&s.length>1&&(t.push(s.slice(0,-1)),s=[n]);return s.length>0&&t.push(s),t}computeBlockSize(e){let t=4;for(const s of e)t+=4+s.keyBytes.length+4+s.valueBytes.length;return t}writeDataBlock(e,t,s,n){e.setUint32(t,s.length,!1),t+=4;for(const i of s){if(i.keyBytes.length>4294967295||i.valueBytes.length>4294967295)throw new Error("SSTable entry too large (exceeds u32 length field)");e.setUint32(t,i.keyBytes.length,!1),t+=4,new Uint8Array(e.buffer).set(i.keyBytes,t),t+=i.keyBytes.length,e.setUint32(t,i.valueBytes.length,!1),t+=4,new Uint8Array(e.buffer).set(i.valueBytes,t),t+=i.valueBytes.length,n.insert(i.key)}return t}estimateIndexBlockSize(e){let t=4;const s=new TextEncoder;for(const n of e)t+=4+s.encode(n.key).byteLength+8;return t}writeIndexBlock(e,t,s){e.setUint32(t,s.length,!1),t+=4;for(const n of s){const s=(new TextEncoder).encode(n.key);e.setUint32(t,s.length,!1),t+=4,new Uint8Array(e.buffer).set(s,t),t+=s.length,e.setUint32(t,n.blockOffset,!1),t+=4,e.setUint32(t,n.blockSize,!1),t+=4}return t}}class Le{constructor(e,t){this.indexEntries=[],this.entryCount=0,this.bloomFilter=null,this.format=2,this.storedChecksum=0,this.data=e,this.view=new DataView(e.buffer,e.byteOffset,e.byteLength),this.meta=t,this.parseFooter()}verifyChecksum(){return 0===this.storedChecksum||!(this.data.byteLength<4)&&ie(this.data.subarray(0,this.data.byteLength-4))===this.storedChecksum}lenFieldSize(){return 2===this.format?4:2}readLen(e){return 2===this.format?this.view.getUint32(e,!1):this.view.getUint16(e,!1)}get(e){if(this.bloomFilter&&!this.bloomFilter.mayContain(e))return null;const t=this.locateBlock(e);if(t<0)return null;for(const[s,n]of this.iterEntries(t,t))if(s===e)return n;return null}rangeScan(e,t,s){for(const[n,i]of this.scanLazy(e,t))s(n,i)}*scanLazy(e,t){if(0===this.indexEntries.length)return;const s=Math.max(0,this.locateBlockGE(e)),n=Math.min(this.indexEntries.length-1,this.locateBlockLE(t)+1);if(!(s<0||n<0||s>n))for(const[i,r]of this.iterEntries(s,n))i>=e&&i<=t&&(yield[i,r])}scanAll(e){for(const[t,s]of this.iterEntries(0,this.indexEntries.length-1))e(t,s)}*iterEntries(e,t){const s=this.lenFieldSize(),n=Math.max(0,e),i=Math.min(t,this.indexEntries.length-1),r=new TextDecoder;for(let e=n;e<=i;e++){const t=this.getBlockData(this.indexEntries[e]);if(!t)continue;const n=new DataView(t.buffer,t.byteOffset,t.byteLength),i=n.getUint32(0,!1);let a=4;for(let e=0;e<i&&!(a+s>t.byteLength);e++){const e=2===this.format?n.getUint32(a,!1):n.getUint16(a,!1);if(a+=s,a+e+s>t.byteLength)break;const i=r.decode(t.slice(a,a+e));a+=e;const o=2===this.format?n.getUint32(a,!1):n.getUint16(a,!1);if(a+=s,a+o>t.byteLength)break;const h=t.slice(a,a+o);a+=o;try{const e=JSON.parse(r.decode(h));yield[i,e]}catch{}}}}parseFooter(){if(this.data.byteLength<32)throw new Error("SSTable too small: missing footer");const e=this.data.byteLength-32,t=this.view.getUint32(e+24,!1);if(1397969986===t)this.format=1;else{if(t!==Ce)throw new Error(`Invalid SSTable magic: expected 1397969986 or 1397969987, got ${t}`);this.format=2}const s=this.view.getUint32(e,!1),n=this.view.getUint32(e+4,!1),i=this.view.getUint32(e+8,!1),r=this.view.getUint32(e+12,!1),a=this.view.getUint32(e+16,!1);if(this.entryCount=this.view.getUint32(e+20,!1),this.storedChecksum=this.view.getUint32(e+28,!1),!(s+4>this.data.byteLength||s+n>this.data.byteLength)&&(this.parseIndexBlock(s,n),i>0&&r>0&&i+r<=this.data.byteLength))try{const e=this.data.slice(i,i+r);this.bloomFilter=Oe.fromData(e,a||10)}catch{}}parseIndexBlock(e,t){const s=this.view.getUint32(e,!1);e+=4;const n=this.lenFieldSize();for(let t=0;t<s&&!(e+n>this.data.byteLength);t++){const t=this.readLen(e);if((e+=n)+t+8>this.data.byteLength)break;const s=(new TextDecoder).decode(this.data.slice(e,e+t));e+=t;const i=this.view.getUint32(e,!1);e+=4;const r=this.view.getUint32(e,!1);e+=4,0===r||i+r>this.data.byteLength||this.indexEntries.push({key:s,blockOffset:i,blockSize:r})}}getBlockData(e){return e.blockSize<=0||e.blockOffset<0||e.blockOffset+e.blockSize>this.data.byteLength?null:new Uint8Array(this.data.buffer,this.data.byteOffset+e.blockOffset,e.blockSize)}locateBlock(e){let t=0,s=this.indexEntries.length-1;for(;t<=s;){const n=Math.floor((t+s)/2);if(e<=this.indexEntries[n].key){if(e>(0===n?"":this.indexEntries[n-1].key))return n;s=n-1}else t=n+1}return-1}locateBlockGE(e){let t=0,s=this.indexEntries.length;for(;t<s;){const n=t+s>>1;this.indexEntries[n].key<e?t=n+1:s=n}return t<this.indexEntries.length?t:this.indexEntries.length-1}locateBlockLE(e){let t=0,s=this.indexEntries.length;for(;t<s;){const n=t+s>>1;this.indexEntries[n].key<=e?t=n+1:s=n}return t>0?t-1:0}}class $e{constructor(e){this.index=0,this.entries=e}next(){return this.index>=this.entries.length?null:this.entries[this.index++]}reset(){this.index=0}}class ve{constructor(e){this.iter=e}next(){const e=this.iter.next();return e.done?null:e.value}reset(){}}class De{constructor(){this.heap=[]}push(e){this.heap.push(e),this.bubbleUp(this.heap.length-1)}pop(){if(0===this.heap.length)return null;if(1===this.heap.length)return this.heap.pop();const e=this.heap[0];return this.heap[0]=this.heap.pop(),this.bubbleDown(0),e}peek(){return this.heap.length>0?this.heap[0]:null}get size(){return this.heap.length}bubbleUp(e){for(;e>0;){const t=Math.floor((e-1)/2);if(this.heap[e].key>=this.heap[t].key)break;[this.heap[e],this.heap[t]]=[this.heap[t],this.heap[e]],e=t}}bubbleDown(e){const t=this.heap.length;for(;;){let s=e;const n=2*e+1,i=2*e+2;if(n<t&&this.heap[n].key<this.heap[s].key&&(s=n),i<t&&this.heap[i].key<this.heap[s].key&&(s=i),s===e)break;[this.heap[e],this.heap[s]]=[this.heap[s],this.heap[e]],e=s}}}class Ue{constructor(){this.pendingRefill=null,this.sources=[],this.heap=new De}addSource(e){this.sources.push(e),this.seedFromSource(this.sources.length-1)}next(){if(null!==this.pendingRefill){const e=this.pendingRefill;this.pendingRefill=null,this.seedFromSource(e)}if(0===this.heap.size)return null;const e=this.heap.pop(),t=e.key;let s=e;for(;this.heap.peek()&&this.heap.peek().key===t;){const e=this.heap.pop();this.seedFromSource(e.sourceIndex),e.sourceIndex<s.sourceIndex&&(s=e)}return this.pendingRefill=e.sourceIndex,[s.key,s.value]}drain(){const e=[];let t=this.next();for(;t;)e.push(t),t=this.next();return e}seedFromSource(e){const t=this.sources[e].next();t&&this.heap.push({key:t[0],value:t[1],sourceIndex:e})}}class _e{constructor(e){this.immutableMemtable=null,this.frozenMemtables=[],this.frozenIdCounter=0,this.levels=[],this.sstableCache=new Map,this.cacheSize=0,this.oversizedSSTables=new Set,this.operationCount=0,this.initialized=!1,this.compacting=new Set,this.flushChain=Promise.resolve(),this.maintenanceChain=Promise.resolve(),this.lastBackgroundError=null,this.backgroundWarnings=[],this.readEpoch=0,this.readStructureRetries=0,this.activeReaders=new Map,this.retired=[],this.structureVersion=0,this.memtableSizeThreshold=e.memtableSizeThreshold??Te,this.memtable=new Re(this.memtableSizeThreshold),this.levelSizeMultiplier=e.levelSizeMultiplier??10,this.blockSize=e.blockSize??4096,this.sstableStore=e.sstableStore,this.cacheLimitBytes=e.cacheLimitBytes??67108864,this.namespace=e.namespace??"main",this.walLsnProvider=e.walLsnProvider??(()=>0),this.requireDurableCoverage=e.requireDurableCoverage??!1,this.bloomBitsPerKey=Number.isFinite(e.bloomBitsPerKey)&&e.bloomBitsPerKey>0?Math.floor(e.bloomBitsPerKey):10,this.recoveryReport={namespace:this.namespace,droppedSSTables:[],dataLossSuspected:!1};for(let e=0;e<7;e++)this.levels.push([])}async init(){if(this.initialized)return;const e=await this.sstableStore.listMeta(),t=[];for(const s of e)await this.validateSSTable(s)&&t.push(s);for(const e of t)e.level>=0&&e.level<7&&this.levels[e.level].push(e);for(let e=0;e<7;e++)this.levels[e].sort((e,t)=>t.id-e.id);this.initialized=!0,this.structureVersion++}put(e,t){this.levels[0].length>=8&&this.enqueueCompact(0),this.memtable.put(e,t),this.operationCount++,this.memtable.shouldFlush()&&this.freezeMemtable()}delete(e){this.levels[0].length>=8&&this.enqueueCompact(0),this.memtable.put(e,{__tombstone:!0}),this.operationCount++,this.memtable.shouldFlush()&&this.freezeMemtable()}getCacheSize(){return this.cacheSize}getCacheLimit(){return this.cacheLimitBytes}getOversizedCount(){return this.oversizedSSTables.size}setCacheLimit(e){this.cacheLimitBytes=Math.max(0,e),this.trimCache()}getEstimatedMemory(){let e=this.memtable.getEstimatedSize();for(const t of this.frozenMemtables)e+=t.memtable.getEstimatedSize();return e+=this.cacheSize,e}freezeMemtable(){this.immutableMemtable&&this.enqueueFlush(this.immutableMemtable);const e={id:++this.frozenIdCounter,memtable:this.memtable,lsnAtFreeze:this.walLsnProvider(),queued:!1,committing:!1,attempts:0,lastError:null};this.immutableMemtable=e,this.frozenMemtables.push(e),this.memtable=new Re(this.memtableSizeThreshold),this.structureVersion++}enqueueFlush(e){e.queued||(e.queued=!0,this.flushChain=this.enqueueOnChain(async()=>{e.attempts++;try{await this.flushImmutableAsync(e),e.lastError=null}catch(t){throw e.lastError=t,t}finally{e.queued=!1}}))}enqueueOnChain(e){return this.flushChain.then(e).catch(e=>{this.lastBackgroundError=e})}enqueueMaintenance(e){this.maintenanceChain=this.maintenanceChain.then(e).catch(e=>{this.lastBackgroundError=e})}async drainChain(){for(;;){const e=this.flushChain;if(await e,this.flushChain===e)break}}async drainMaintenance(){for(;;){const e=this.maintenanceChain;if(await e,this.maintenanceChain===e)break}}async flushImmutableAsync(e){const t=e.memtable.getAllEntries();if(0===t.length)return this.immutableMemtable===e&&(this.immutableMemtable=null),void this.removeFrozen(e);const s=await this.sstableStore.allocateId(),i=new Ne(this.blockSize,this.bloomBitsPerKey);for(const[e,s]of t)i.add(e,s);const{sstableData:r,indexEntries:a}=i.build(),o={id:s,level:0,minKey:t[0][0],maxKey:t[t.length-1][0],blockCount:a.length,totalSize:r.byteLength,bloomData:null},h=await this.sstableStore.save(s,r);if(!h||"number"!=typeof h.storedSize)throw new n(`SSTableStore.save() returned ${JSON.stringify(h)} for namespace "${this.namespace}" (id=${s}, bytes=${r.byteLength}) — 存储实现违反了 save() 契约`,"ARIA_SSTABLE_SAVE_CONTRACT");o.totalSize=h.storedSize,e.committing=!0;try{await this.sstableStore.saveMeta(o)}finally{e.committing=!1}this.levels[0].unshift(o),this.structureVersion++,this.tryCacheSSTable(s,r),this.trimCache(),this.immutableMemtable===e&&(this.immutableMemtable=null),this.removeFrozen(e),this.levels[0].length>=4&&this.scheduleCompact(0)}removeFrozen(e){this.frozenMemtables=this.frozenMemtables.filter(t=>t!==e)}async compactLevel(e,t=2){return this.compactLevelAsync(e,t)}scheduleCompact(e){e>6||this.compacting.has(e)||(this.compacting.add(e),this.enqueueMaintenance(async()=>{try{await this.compactLevelAsync(e)}finally{this.compacting.delete(e),this.levels[e].length>=4&&this.scheduleCompact(e),e+1<=6&&this.levels[e+1].length>=4&&this.scheduleCompact(e+1)}}))}async vacuumLevels(){let e=0;for(let t=0;t<7;t++){const s=6===t?1:2;this.compacting.has(t)&&await this.drainMaintenance(),this.levels[t].length<s||(this.compacting.add(t),await new Promise(n=>{this.enqueueMaintenance(async()=>{try{await this.compactLevelAsync(t,s)&&e++}finally{this.compacting.delete(t),n()}})}))}return e}enqueueCompact(e){e>6||this.compacting.has(e)||(this.compacting.add(e),this.enqueueMaintenance(async()=>{try{await this.compactLevelAsync(e)}finally{this.compacting.delete(e)}}))}enterRead(){const e=++this.readEpoch;return this.activeReaders.set(e,(this.activeReaders.get(e)??0)+1),e}exitRead(e){const t=this.activeReaders.get(e);void 0!==t&&(t<=1?this.activeReaders.delete(e):this.activeReaders.set(e,t-1),this.reclaimRetired())}snapshotMetas(e,t){const s=[];for(let n=0;n<7;n++)for(const i of this.levels[n])t<i.minKey||e>i.maxKey||s.push(i);return s}async collectReaders(e,t){for(let s=0;s<16;s++){const s=this.structureVersion,n=this.snapshotMetas(e,t),i=[];for(const e of n){const t=await this.loadSSTableReader(e);t&&i.push(t)}if(s===this.structureVersion)return i;this.readStructureRetries++}await this.drainChain(),await this.drainMaintenance();const s=[];for(const n of this.snapshotMetas(e,t)){const e=await this.loadSSTableReader(n);e&&s.push(e)}return s}reclaimRetired(){if(0===this.retired.length)return;let e=1/0;for(const t of this.activeReaders.keys())t<e&&(e=t);const t=[],s=[];for(const n of this.retired)n.epoch<e?s.push(...n.metas):t.push(n);this.retired=t,0!==s.length&&(async()=>{for(const e of s){this.sstableCache.delete(e.id),this.oversizedSSTables.delete(e.id);try{await this.sstableStore.delete(e.id)}catch(e){}}})()}hasActiveReaders(){return this.activeReaders.size>0}getRetiredPageIds(){const e=[];for(const t of this.retired)for(const s of t.metas)s.pageIds&&e.push(...s.pageIds);return e}getRetiredSstableIds(){const e=[];for(const t of this.retired)for(const s of t.metas)e.push(s.id);return e}async whenIdle(){await this.drainChain(),await this.drainMaintenance()}getRetiredCount(){return this.retired.reduce((e,t)=>e+t.metas.length,0)}reclaimRetiredNow(){if(0===this.retired.length)return;if(this.activeReaders.size>0)return void this.reclaimRetired();const e=this.retired.flatMap(e=>e.metas);this.retired=[],(async()=>{for(const t of e){this.sstableCache.delete(t.id),this.oversizedSSTables.delete(t.id);try{await this.sstableStore.delete(t.id)}catch{}}})()}async get(e){for(let t=0;t<16;t++){let t=this.memtable.get(e);if(null!==t)return this.unwrapTombstone(t);for(let s=this.frozenMemtables.length-1;s>=0;s--)if(t=this.frozenMemtables[s].memtable.get(e),null!==t)return this.unwrapTombstone(t);const s=this.structureVersion,n=this.enterRead();try{const t=this.snapshotMetas(e,e),n=[];for(const e of t){const t=await this.loadSSTableReader(e);t&&n.push(t)}if(s!==this.structureVersion){this.readStructureRetries++;continue}for(const t of n){const s=t.get(e);if(null!==s)return this.unwrapTombstone(s)}return null}finally{this.exitRead(n)}}await this.drainChain(),await this.drainMaintenance();let t=this.memtable.get(e);if(null!==t)return this.unwrapTombstone(t);for(let s=this.frozenMemtables.length-1;s>=0;s--)if(t=this.frozenMemtables[s].memtable.get(e),null!==t)return this.unwrapTombstone(t);for(const t of this.snapshotMetas(e,e)){const s=await this.loadSSTableReader(t);if(!s)continue;const n=s.get(e);if(null!==n)return this.unwrapTombstone(n)}return null}async rangeScan(e,t){const s=[];return await this.rangeScanLazy(e,t,(e,t)=>{s.push([e,t])}),s}async rangeScanLazy(e,t,s){const n=this.enterRead();try{const n=await this.collectReaders(e,t),i=new Ue;i.addSource(new ve(this.memtable.scanLazy(e,t)));for(let s=this.frozenMemtables.length-1;s>=0;s--)i.addSource(new ve(this.frozenMemtables[s].memtable.scanLazy(e,t)));for(const s of n)i.addSource(new ve(s.scanLazy(e,t)));let r=i.next();for(;r;){const[e,t]=r;if(!t.__tombstone&&!1===s(e,t))return;r=i.next()}}finally{this.exitRead(n)}}async compactLevelAsync(e,t=4){if(e>6)return!1;if(this.levels[e].length<t)return!1;const s=6===e,i=s?e:e+1,r=[...this.levels[e]],a=new Set(r.map(e=>e.id)),o=new Ue,h=[];for(const e of r){let t,s=this.sstableCache.get(e.id)??null;if(!s)try{s=await this.sstableStore.load(e.id)}catch(t){throw new n(`AriaEngine compaction failed to read SSTable id=${e.id}: ${t.message}`,"ARIA_SSTABLE_READ_FAILED",t)}if(!s||s.byteLength<32){await this.dropInvalidSSTable(e,"missing or truncated during compaction");continue}try{if(t=new Le(s,e),!t.verifyChecksum()){await this.dropInvalidSSTable(e,"checksum mismatch during compaction");continue}}catch(t){await this.dropInvalidSSTable(e,`unparseable during compaction: ${t.message}`);continue}const i=[];t.scanAll((e,t)=>i.push([e,t])),o.addSource(new $e(i)),h.push(e)}const c=o.drain(),l=s?c.filter(([,e])=>!e.__tombstone):c;if(0===l.length){if(0===c.length){for(const t of h)this.levels[e].some(e=>e.id===t.id)||this.levels[e].push(t);return this.levels[e].sort((e,t)=>t.id-e.id),this.structureVersion++,!1}return await this.retireMetas(e,this.removeFromLevel(e,a)),!0}const u=await this.sstableStore.allocateId(),f=new Ne(this.blockSize,this.bloomBitsPerKey);for(const[e,t]of l)f.add(e,t);const{sstableData:d,indexEntries:p}=f.build(),m={id:u,level:i,minKey:l[0][0],maxKey:l[l.length-1][0],blockCount:p.length,totalSize:d.byteLength,bloomData:null},y=await this.sstableStore.save(u,d);if(!y||"number"!=typeof y.storedSize)throw new n(`SSTableStore.save() returned ${JSON.stringify(y)} for namespace "${this.namespace}" (id=${u}, bytes=${d.byteLength}) — 存储实现违反了 save() 契约`,"ARIA_SSTABLE_SAVE_CONTRACT");return m.totalSize=y.storedSize,await this.sstableStore.saveMeta(m),this.tryCacheSSTable(u,d),this.trimCache(),this.levels[i].unshift(m),this.structureVersion++,await this.retireMetas(e,this.removeFromLevel(e,a)),!0}removeFromLevel(e,t){const s=[];return this.levels[e]=this.levels[e].filter(e=>!t.has(e.id)||(s.push(e),!1)),s}async retireMetas(e,t){if(0===t.length)return;this.structureVersion++,this.retired.push({epoch:this.readEpoch,metas:t}),this.sstableStore.retire?.(t.map(e=>e.id));const s=t.map(e=>e.id);if("function"==typeof this.sstableStore.deleteManyMetas)await this.sstableStore.deleteManyMetas(s);else for(const e of s)await this.sstableStore.deleteMeta(e);this.reclaimRetired()}async flush(){this.enqueuePendingMemtables();const e=this.consumeBackgroundError();await this.drainChain(),await this.retryPendingFlushes(),await this.drainMaintenance(),this.assertNoPendingFrozen(e)}async flushMemtablesOnly(){this.enqueuePendingMemtables();const e=this.consumeBackgroundError();await this.drainChain(),await this.retryPendingFlushes(),this.assertNoPendingFrozen(e)}enqueuePendingMemtables(){if(this.immutableMemtable){const e=this.immutableMemtable;this.immutableMemtable=null,this.enqueueFlush(e)}if(this.memtable.getEntryCount()>0&&(this.freezeMemtable(),this.immutableMemtable)){const e=this.immutableMemtable;this.immutableMemtable=null,this.enqueueFlush(e)}}async retryPendingFlushes(){let e=0;for(;this.frozenMemtables.some(e=>!e.queued&&e.memtable.getEntryCount()>0)&&!(e>=3);){e++;for(const e of this.frozenMemtables)e.memtable.getEntryCount()>0&&this.enqueueFlush(e);await this.drainChain()}}consumeBackgroundError(){if(null===this.lastBackgroundError)return null;const e=this.lastBackgroundError;return this.lastBackgroundError=null,e}assertNoPendingFrozen(e){const t=this.consumeBackgroundError(),s=e??t,i=this.frozenMemtables.filter(e=>e.memtable.getEntryCount()>0);if(i.length>0){const e=i[i.length-1].lastError;throw new n(`AriaEngine LSM flush could not persist ${i.length} frozen memtable(s) after 3 retry round(s) — data is still only in memory (WAL is the only other copy)`,"ARIA_BACKGROUND_ERROR",e??s)}null!=s&&(this.backgroundWarnings.push(s),this.backgroundWarnings.length>64&&this.backgroundWarnings.splice(0,this.backgroundWarnings.length-64))}getBackgroundWarnings(){return[...this.backgroundWarnings]}hasPendingFlushData(){return this.memtable.getEntryCount()>0||this.frozenMemtables.some(e=>e.memtable.getEntryCount()>0)}getFrozenIntents(){const e=[];for(const t of this.frozenMemtables){if(t.committing)continue;const s=t.memtable.getAllEntries();0!==s.length&&e.push({ns:this.namespace,id:t.id,entryCount:s.length,minKey:s[0][0],maxKey:s[s.length-1][0],lsnAtFreeze:t.lsnAtFreeze})}if(this.immutableMemtable&&!this.immutableMemtable.committing){const t=this.immutableMemtable.memtable.getAllEntries();t.length>0&&!e.some(e=>e.id===this.immutableMemtable.id)&&e.push({ns:this.namespace,id:this.immutableMemtable.id,entryCount:t.length,minKey:t[0][0],maxKey:t[t.length-1][0],lsnAtFreeze:this.immutableMemtable.lsnAtFreeze})}return e}getRecoveryReport(){return{namespace:this.recoveryReport.namespace,droppedSSTables:[...this.recoveryReport.droppedSSTables],dataLossSuspected:this.recoveryReport.dataLossSuspected}}async clear(){await this.drainChain(),await this.drainMaintenance(),this.memtable.clear(),this.immutableMemtable=null,this.frozenMemtables=[];for(const e of this.levels)for(const t of e)this.sstableCache.delete(t.id),this.sstableStore.delete(t.id).catch(()=>{}),this.sstableStore.deleteMeta(t.id).catch(()=>{});this.levels=[];for(let e=0;e<7;e++)this.levels.push([]);this.sstableCache.clear(),this.cacheSize=0,this.oversizedSSTables.clear(),this.retired=[],this.structureVersion++}getStats(){return{memtableSize:this.memtable.getEntryCount(),sstableCount:this.levels.reduce((e,t)=>e+t.length,0),levelCounts:this.levels.map(e=>e.length),frozenTables:this.frozenMemtables.filter(e=>e.memtable.getEntryCount()>0).length,retiredTables:this.getRetiredCount(),compactingLevels:[...this.compacting].sort((e,t)=>e-t),readStructureRetries:this.readStructureRetries}}async validateAll(){const e=this.enterRead();try{let e=0;for(let t=0;t<7;t++){const s=[];for(const n of this.levels[t])await this.validateSSTable(n)?s.push(n):(this.sstableCache.delete(n.id),e++);this.levels[t]=s}return this.structureVersion++,e}finally{this.exitRead(e)}}async validateSSTable(e){const t=await this.sstableStore.load(e.id);if(!t)return await this.dropInvalidSSTable(e,"file missing at open"),!1;if(t.byteLength<32)return await this.dropInvalidSSTable(e,`file too small (${t.byteLength} bytes)`),!1;try{if(!new Le(t,e).verifyChecksum())return await this.dropInvalidSSTable(e,"checksum mismatch at open"),!1}catch(t){return await this.dropInvalidSSTable(e,`unparseable at open: ${t.message}`),!1}return!0}async dropInvalidSSTable(e,t){this.recoveryReport.droppedSSTables.push({id:e.id,level:e.level,reason:t}),this.levels[e.level]?.some(t=>t.id===e.id)&&(this.levels[e.level]=this.levels[e.level].filter(t=>t.id!==e.id),this.structureVersion++),this.requireDurableCoverage&&(this.recoveryReport.dataLossSuspected=!0),this.sstableCache.delete(e.id),this.oversizedSSTables.delete(e.id);try{await this.sstableStore.delete(e.id)}catch{}try{await this.sstableStore.deleteMeta(e.id)}catch{}}unwrapTombstone(e){return e?e.__tombstone?null:e:null}async loadSSTableReader(e){let t=this.sstableCache.get(e.id);if(!t){let s;try{s=await this.sstableStore.load(e.id)}catch(t){throw new n(`AriaEngine failed to read SSTable id=${e.id} from storage: ${t.message}`,"ARIA_SSTABLE_READ_FAILED",t)}if(!s)return(await this.sstableStore.listMeta()).some(t=>t.id===e.id)&&await this.dropInvalidSSTable(e,"file missing during read"),null;try{if(!new Le(s,e).verifyChecksum())return await this.dropInvalidSSTable(e,"checksum mismatch during read"),null}catch(t){return await this.dropInvalidSSTable(e,`unparseable during read: ${t.message}`),null}this.tryCacheSSTable(e.id,s),t=s}if(this.sstableCache.has(e.id)){const t=this.sstableCache.get(e.id);this.sstableCache.delete(e.id),this.sstableCache.set(e.id,t)}try{return new Le(t,e)}catch{return null}}tryCacheSSTable(e,t){t.byteLength>this.cacheLimitBytes?this.oversizedSSTables.add(e):this.oversizedSSTables.delete(e),this.cacheSSTable(e,t)}cacheSSTable(e,t){this.sstableCache.has(e)&&(this.cacheSize-=this.sstableCache.get(e).byteLength,this.sstableCache.delete(e)),this.sstableCache.set(e,t),this.cacheSize+=t.byteLength}trimCache(){let e=0;const t=this.sstableCache.size;let s=this.sstableCache.keys().next().value;for(;this.cacheSize>this.cacheLimitBytes&&e<t&&void 0!==s;){const t=this.nextCacheKey(s);if(e++,!this.oversizedSSTables.has(s)){const e=this.sstableCache.get(s);e&&(this.cacheSize-=e.byteLength,this.sstableCache.delete(s))}s=t}}nextCacheKey(e){let t=!1;for(const s of this.sstableCache.keys()){if(t)return s;s===e&&(t=!0)}}}class Me{constructor(e,t=!0,s="batch"){this.lsn=0,this.buffer=[],this.bufferedBytes=0,this.lastRecoveryInfo=null,this.store=e,this.enabled=t,this.syncMode=s}async append(e){if(!this.enabled)return;this.lsn++;const t={...e,lsn:this.lsn,checksum:0},s=this.encodeRecord(t);"full"===this.syncMode?(await this.store.append(s),this.bufferedBytes+=s.byteLength):"batch"===this.syncMode&&(this.buffer.push(s),this.bufferedBytes+=s.byteLength)}async appendBatch(e){if(!this.enabled||0===e.length)return;const t=[];for(const s of e)this.lsn++,t.push(this.encodeRecord({...s,lsn:this.lsn,checksum:0}));const s=this.mergeChunks(t);"full"===this.syncMode?(await this.store.append(s),this.bufferedBytes+=s.byteLength):"batch"===this.syncMode&&(this.buffer.push(s),this.bufferedBytes+=s.byteLength)}async flush(){if(!this.enabled||0===this.buffer.length)return;const e=this.mergeChunks(this.buffer);await this.store.append(e),this.buffer=[]}mergeChunks(e){if(1===e.length)return e[0];const t=e.reduce((e,t)=>e+t.byteLength,0),s=new Uint8Array(t);let n=0;for(const t of e)s.set(t,n),n+=t.byteLength;return s}async recover(e,t={}){if(!this.enabled)return 0;const s=t.fromSegment??0,i=t.fromLsn??0;let r,a=[],o=[];if("function"==typeof this.store.readAllFrom){const e=await this.store.readAllFrom(s,i);r=e.data,a=e.gaps,o=e.missingPrefix??[]}else{if(!await this.store.exists())return 0;r=await this.store.readAll()}if(a.length>0&&!t.allowGaps)throw new n(`WAL segment gap detected in live range (missing segment(s): ${a.join(", ")}) — records after the gap cannot be verified; refusing to continue silently`,"ARIA_WAL_GAP");const h=0===r.byteLength?{records:[],corrupt:0}:this.decodeAllRecords(r),c=h.records;let l=0,u=0,f=0;for(const t of c)t.lsn>f&&(f=t.lsn),t.lsn<=i?u++:(e(t),l++);return this.lsn=Math.max(this.lsn,f),this.buffer=[],this.bufferedBytes=0,this.lastRecoveryInfo={applied:l,skipped:u,maxLsn:f,gaps:a,missingPrefix:o,corruptRecords:h.corrupt,fromSegment:s,fromLsn:i},l}getLastRecoveryInfo(){return this.lastRecoveryInfo?{...this.lastRecoveryInfo,gaps:[...this.lastRecoveryInfo.gaps]}:null}getLsn(){return this.lsn}setLsn(e){Number.isFinite(e)&&e>this.lsn&&(this.lsn=e)}async checkpoint(){this.enabled&&(await this.flush(),await this.store.truncate(),this.bufferedBytes=0)}reset(){"function"==typeof this.store.reset&&this.store.reset()}async planKeepFromSegment(e){return this.enabled&&"function"==typeof this.store.planKeepFrom?this.store.planKeepFrom(e,this.lsn):0}async checkpointBefore(e){return this.enabled?(await this.flush(),"function"==typeof this.store.truncateBefore?this.store.truncateBefore(e,this.lsn):(e>=this.lsn&&(await this.store.truncate(),this.bufferedBytes=0),0)):0}getBufferedCount(){return this.buffer.length}getBufferedBytes(){return this.bufferedBytes}legacyChecksum(e){let t=0;for(let s=0;s<e.length;s++)t=(t<<5)-t+e[s]|0;return t>>>0}encodeRecord(e){const t=new TextEncoder,s=t.encode(e.tableName),n=t.encode(e.key),i=e.data?JSON.stringify(e.data):"",r=t.encode(i),a=11+s.length+2+n.length+4+r.length+4,o=new ArrayBuffer(a),h=new DataView(o);let c=0;h.setUint32(c,e.lsn,!1),c+=4,h.setUint8(c,e.type),c+=1,h.setUint32(c,e.txnId,!1),c+=4,h.setUint16(c,s.length,!1),c+=2,new Uint8Array(o).set(s,c),c+=s.length,h.setUint16(c,n.length,!1),c+=2,new Uint8Array(o).set(n,c),c+=n.length,h.setUint32(c,r.length,!1),c+=4,new Uint8Array(o).set(r,c),c+=r.length;const l=ie(new Uint8Array(o,0,c));return h.setUint32(c,l,!1),new Uint8Array(o)}decodeAllRecords(e){const t=[];let s=0;const n=new DataView(e.buffer,e.byteOffset,e.byteLength);let i=0;for(;i+15<=e.byteLength;)try{const r=i,a=n.getUint32(i,!1);i+=4;const o=n.getUint8(i);i+=1;const h=n.getUint32(i,!1);i+=4;const c=n.getUint16(i,!1);if(i+=2,i+c>e.byteLength)break;const l=(new TextDecoder).decode(e.slice(i,i+c));i+=c;const u=n.getUint16(i,!1);if(i+=2,i+u>e.byteLength)break;const f=(new TextDecoder).decode(e.slice(i,i+u));i+=u;const d=n.getUint32(i,!1);if(i+=4,i+d>e.byteLength)break;let p;if(d>0){const t=(new TextDecoder).decode(e.slice(i,i+d));try{p=JSON.parse(t)}catch{}}i+=d;const m=n.getUint32(i,!1);i+=4;const y=e.slice(r,i-4),g=ie(y),w=this.legacyChecksum(y);if(g>>>0!==m&&w>>>0!==m){s++;continue}t.push({lsn:a,type:o,txnId:h,tableName:l,key:f,data:p,checksum:m})}catch{break}return{records:t,corrupt:s}}}const Pe="__wal_",Be=/^__wal_(\d{6,})\.bin$/,Fe=/^__wal_(\d+)$/,Ke="__wal_count";class ze{constructor(e,t=4194304){this.backend=e,this.currentSegment=0,this.currentSize=0,this.segmentFirstLsn=new Map,this.segmentSize=t}segmentKey(e){return`${Pe}${String(e).padStart(6,"0")}.bin`}async append(e){if(0===e.byteLength)return;this.currentSize+e.byteLength>this.segmentSize&&(this.currentSegment++,this.currentSize=0);const t=this.currentSegment,s=this.segmentKey(t),n=e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength);if(!this.segmentFirstLsn.has(t)&&e.byteLength>=4&&this.segmentFirstLsn.set(t,new DataView(e.buffer,e.byteOffset,4).getUint32(0,!1)),"function"==typeof this.backend.append)await this.backend.append(s,n);else{const e=await this.backend.read(s);if(e){const t=new ArrayBuffer(e.byteLength+n.byteLength);new Uint8Array(t).set(new Uint8Array(e),0),new Uint8Array(t).set(new Uint8Array(n),e.byteLength),await this.backend.write(s,t)}else await this.backend.write(s,n)}this.currentSize+=e.byteLength}async listSegments(){return(await this.backend.listKeys()).filter(e=>Be.test(e)).map(e=>({seq:Number(e.match(Be)[1]),key:e})).sort((e,t)=>e.seq-t.seq)}async readAllFrom(e=0,t=0){const s=await this.backend.listKeys(),n=(await this.listSegments()).filter(t=>t.seq>=e),i=[];if(n.length>0)for(let t=e;t<n[0].seq;t++)i.push(t);const r=[];for(let e=1;e<n.length;e++)for(let t=n[e-1].seq+1;t<n[e].seq;t++)r.push(t);0===t&&i.length>0&&(r.unshift(...i),i.length=0),r.sort((e,t)=>e-t);let a=n;if(r.length>0){const e=r[0];a=n.filter(t=>t.seq<e)}const o=s.filter(e=>Fe.test(e)).map(e=>({seq:Number(e.match(Fe)[1]),key:e})).sort((e,t)=>e.seq-t.seq),h=[];for(const{key:e}of o){const t=await this.backend.read(e);t&&h.push(new Uint8Array(t))}const c=[];for(const{seq:e,key:t}of a){const s=await this.backend.read(t);if(!s)continue;const n=new Uint8Array(s);!this.segmentFirstLsn.has(e)&&n.byteLength>=4&&this.segmentFirstLsn.set(e,new DataView(n.buffer,n.byteOffset,4).getUint32(0,!1)),c.push(e),h.push(n)}if(n.length>0){const e=n[n.length-1].seq;this.currentSegment=e;const t=await this.backend.read(this.segmentKey(e));this.currentSize=t?t.byteLength:0,o.length>0&&(this.currentSegment++,this.currentSize=0)}else o.length>0?(this.currentSegment=0,this.currentSize=0):e>0&&(this.currentSegment=e,this.currentSize=0);const l=h.reduce((e,t)=>e+t.byteLength,0),u=new Uint8Array(l);let f=0;for(const e of h)u.set(e,f),f+=e.byteLength;return{data:u,fromSegment:e,segments:c,gaps:r,missingPrefix:i,missingTail:0}}async readAll(){return(await this.readAllFrom(0)).data}async truncate(){const e=(await this.backend.listKeys()).filter(e=>e.startsWith(Pe)||e===Ke);e.length>0&&await this.backend.deleteMany(e);const t=(await this.listSegments()).reduce((e,t)=>Math.max(e,t.seq),-1);this.currentSegment=Math.max(this.currentSegment,t+1),this.currentSize=0,this.segmentFirstLsn.clear()}reset(){this.currentSegment=0,this.currentSize=0,this.segmentFirstLsn.clear()}async planKeepFrom(e,t){const s=await this.listSegments();if(0===s.length)return this.currentSegment;for(let n=0;n<s.length;n++){const i=s[n],r=n===s.length-1;if(void 0===this.segmentFirstLsn.get(i.seq))return i.seq;if(!(r?"number"==typeof t&&t>0&&t<=e:(()=>{const t=this.segmentFirstLsn.get(s[n+1].seq);return void 0!==t&&t<=e})()))return i.seq}return s[s.length-1].seq+1}async truncateBefore(e,t){const s=(await this.backend.listKeys()).filter(e=>Fe.test(e));if(s.length>0){const t=[];for(const n of s){const s=await this.backend.read(n);!s||s.byteLength<4?t.push(n):new DataView(s,0,4).getUint32(0,!1)<=e&&t.push(n)}if(t.length>0)try{await this.backend.deleteMany([...t,Ke])}catch{}}const n=await this.listSegments();if(0===n.length)return this.currentSize=0,this.currentSegment;const i=await this.planKeepFrom(e,t),r=n.filter(e=>e.seq<i);if(r.length>0){try{await this.backend.deleteMany(r.map(e=>e.key))}catch{}for(const e of r)this.segmentFirstLsn.delete(e.seq)}if(r.length===n.length){const e=n[n.length-1].seq,t=await this.listSegments();return 0===t.length?(this.currentSegment=Math.max(e+1,i),this.currentSize=0,this.segmentFirstLsn.clear(),i):(this.currentSegment=Math.max(t[t.length-1].seq+1,i),this.currentSize=0,i)}return i}async exists(){return(await this.backend.listKeys()).some(e=>e.startsWith(Pe)||e===Ke)}}class qe{constructor(){this.acquired=!1,this.supported=!1,this.releaseResolve=null,this.releasePromise=null}async acquire(e){const t=globalThis.navigator,s=t?.locks;return s&&"function"==typeof s.request?(this.supported=!0,await new Promise((t,i)=>{s.request.bind(s)(function(e){return`metona-sqlark:${e}`}(e),{ifAvailable:!0,mode:"exclusive"},async s=>{if(!s)return void i(new n(`Database "${e}" is already open in another tab (locked)`,"ARIA_LOCKED"));this.acquired=!0;const r=new Promise(e=>{this.releaseResolve=e});this.releasePromise=r,t(),await r})}),!0):(this.supported=!1,!1)}async release(){if(this.acquired){if(this.releaseResolve){const e=this.releaseResolve,t=this.releasePromise;this.releaseResolve=null,this.releasePromise=null,e();try{await t}catch{}}this.acquired=!1}}isAcquired(){return this.acquired}isSupported(){return this.supported}}class je{constructor(e,t,s=null,n=1e3,i=16777216){this.opCount=0,this.lsm=e,this.wal=t,this.flushable=s,this.interval=n,this.walSizeThreshold=i}async tick(){this.opCount++,(this.opCount>=this.interval||this.getWALEstimatedSize()>=this.walSizeThreshold)&&await this.checkpoint()}getWALEstimatedSize(){const e=this.wal;if("function"==typeof e.getBufferedBytes){const t=e.getBufferedBytes();if(t>0)return t}return 200*("function"==typeof e.getBufferedCount?e.getBufferedCount():0)}async checkpoint(){this.flushable&&"function"==typeof this.flushable.flushMemtables?await this.flushable.flushMemtables():(await this.lsm.flush(),this.flushable&&await this.flushable.flushAll()),await this.wal.checkpoint(),this.opCount=0}}class Ve{constructor(){this.store=new Map,this.opened=!1}async open(e){this.opened=!0}async close(){this.store.clear(),this.opened=!1}isOpen(){return this.opened}async read(e){return this.store.get(e)??null}async write(e,t){this.store.set(e,t)}async writeMany(e){for(const[t,s]of Object.entries(e))this.store.set(t,s)}async delete(e){this.store.delete(e)}async deleteMany(e){for(const t of e)this.store.delete(t)}async listKeys(){return Array.from(this.store.keys())}async exists(e){return this.store.has(e)}async clear(){this.store.clear()}}class We{constructor(e,t){this.kv=new fe(e,t)}getKV(){return this.kv}async open(e){await this.kv.open(e)}async close(){await this.kv.close()}isOpen(){return this.kv.isOpen()}async read(e){return this.kv.get(e)}async write(e,t){await this.kv.put(e,t)}async append(e,t){await this.kv.appendValue(e,t)}async writeMany(e){await this.kv.putMany(e)}async delete(e){await this.kv.delete(e)}async deleteMany(e){await this.kv.deleteMany(e)}async listKeys(){return this.kv.listKeys()}async exists(e){return this.kv.exists(e)}async clear(){await this.kv.clear()}}const Ge="AES-GCM";class He{constructor(){this.cryptoKey=null,this._enabled=!1}get enabled(){return this._enabled}async init(e,t){const s=new TextEncoder,n=await crypto.subtle.importKey("raw",s.encode(e),"PBKDF2",!1,["deriveKey"]),i=t||crypto.getRandomValues(new Uint8Array(16));return this.cryptoKey=await crypto.subtle.deriveKey({name:"PBKDF2",salt:i,iterations:1e5,hash:"SHA-256"},n,{name:Ge,length:256},!1,["encrypt","decrypt"]),this._enabled=!0,i}async encryptPage(e){if(!this.cryptoKey)throw new Error("Crypto not initialized");const t=crypto.getRandomValues(new Uint8Array(12)),s=e instanceof Uint8Array?e:new Uint8Array(e);return{iv:t,data:await crypto.subtle.encrypt({name:Ge,iv:t},this.cryptoKey,s)}}async decryptPage(e,t){if(!this.cryptoKey)throw new Error("Crypto not initialized");const s=t instanceof Uint8Array?t:new Uint8Array(t);return crypto.subtle.decrypt({name:Ge,iv:e},this.cryptoKey,s)}close(){this.cryptoKey=null,this._enabled=!1}}const Qe=12,Xe="__aria_keymeta";function Ye(e){if("undefined"!=typeof Buffer)return Buffer.from(e).toString("base64");let t="";for(let s=0;s<e.byteLength;s++)t+=String.fromCharCode(e[s]);return btoa(t)}function Je(e){if("undefined"!=typeof Buffer)return new Uint8Array(Buffer.from(e,"base64"));const t=atob(e),s=new Uint8Array(t.length);for(let e=0;e<t.length;e++)s[e]=t.charCodeAt(e);return s}class Ze{constructor(e,t){if(this.inner=e,this.password=t,this.crypto=new He,this.opened=!1,!t||0===t.length)throw new n("Encryption password must not be empty","ARIA_ENCRYPT_CONFIG_ERROR")}getInner(){return this.inner}isCryptoReady(){return this.crypto.enabled}async open(e){this.inner.isOpen()||await this.inner.open(e);const t=await this.inner.read(Xe);if(t){let e;try{e=JSON.parse((new TextDecoder).decode(t))}catch{throw new n("Corrupted encryption key metadata","ARIA_DECRYPT_ERROR")}if(!e.salt||!e.verifier)throw new n("Corrupted encryption key metadata","ARIA_DECRYPT_ERROR");const s=Je(e.salt);await this.crypto.init(this.password,s);const i=Je(e.verifier);if(i.byteLength<=Qe)throw new n("Corrupted encryption key metadata","ARIA_DECRYPT_ERROR");const r=i.subarray(0,Qe),a=i.subarray(Qe);try{await this.crypto.decryptPage(r,a)}catch{throw new n("Decryption failed: wrong password or corrupted key metadata","ARIA_DECRYPT_ERROR")}}else{if((await this.inner.listKeys()).some(e=>e!==Xe))throw new n("Cannot open with encryption: existing database has no key metadata (database was created without encryption, or key metadata was lost)","ARIA_ENCRYPT_CONFIG_ERROR");const e=await this.crypto.init(this.password),t=await this.crypto.encryptPage((new TextEncoder).encode("metona-sqlark-encryption-verifier").buffer),s=new Uint8Array(Qe+t.data.byteLength);s.set(t.iv,0),s.set(new Uint8Array(t.data),Qe);const i=JSON.stringify({salt:Ye(e),verifier:Ye(s)});await this.inner.write(Xe,(new TextEncoder).encode(i).buffer)}this.opened=!0}async close(){await this.inner.close(),this.crypto.close(),this.opened=!1}isOpen(){return this.opened}async read(e){this.ensureReady();const t=await this.inner.read(e);return null===t?null:this.decrypt(t)}async write(e,t){this.ensureReady(),await this.inner.write(e,await this.encrypt(t))}async writeMany(e){this.ensureReady();const t={};for(const[s,n]of Object.entries(e))t[s]=await this.encrypt(n);await this.inner.writeMany(t)}async delete(e){this.ensureReady(),await this.inner.delete(e)}async deleteMany(e){this.ensureReady(),await this.inner.deleteMany(e)}async listKeys(){return this.ensureReady(),this.inner.listKeys()}async exists(e){return this.ensureReady(),this.inner.exists(e)}async clear(){const e=(await this.inner.listKeys()).filter(e=>e!==Xe);e.length>0&&await this.inner.deleteMany(e)}ensureReady(){if(!this.opened)throw new n("EncryptedBackend not opened","ARIA_DB_NOT_OPEN");if(!this.crypto.enabled)throw new n("EncryptedBackend key not initialized","ARIA_DECRYPT_ERROR")}async encrypt(e){const t=await this.crypto.encryptPage(e),s=new ArrayBuffer(Qe+t.data.byteLength),n=new Uint8Array(s);return n.set(t.iv,0),n.set(new Uint8Array(t.data),Qe),s}async decrypt(e){const t=new Uint8Array(e);if(t.byteLength<=Qe)throw new n("Corrupted encrypted data block (too short)","ARIA_DECRYPT_ERROR");const s=t.subarray(0,Qe),i=t.subarray(Qe);try{return await this.crypto.decryptPage(s,i)}catch(e){if(e instanceof n)throw e;throw new n("Decryption failed (data corrupted or wrong key)","ARIA_DECRYPT_ERROR",e)}}}function et(e){try{return function(e){if(0===e.byteLength){const e=new Uint8Array(4);return new DataView(e.buffer).setUint32(0,0,!0),e}const t=e.byteLength,s=t+Math.ceil(t/15)+8,n=new Uint8Array(s);let i=0;const r=new Int32Array(65536).fill(-1),a=new Int32Array(t).fill(-1),o=t=>{const s=(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0;return Math.imul(s,2654435761)>>>16&65535},h=e=>{if(e+4>t)return;const s=o(e);a[e]=r[s],r[s]=e};let c=0,l=0;const u=()=>{let t=c-l;for(;t>0;){const s=Math.min(t,15);n[i++]=(15&s)<<4;for(let t=0;t<s;t++)n[i++]=e[l+t];t-=s,l+=s}};for(;c<t;){let s=0,f=0;if(c+4<=t){let n=r[o(c)],i=0;for(;n>=0&&i<32;){const r=c-n;if(r>0&&r<=65535&&e[n]===e[c]){let i=0;for(;i<19&&c+i<t&&e[n+i]===e[c+i];)i++;if(i>s&&(s=i,f=r,19===i))break}n=a[n],i++}}if(s>4&&c-l<=15){const t=c-l;n[i++]=(15&t)<<4|s-4&15;for(let s=0;s<t;s++)n[i++]=e[l+s];n[i++]=255&f,n[i++]=f>>8&255;for(let e=0;e<s;e++)h(c+e);c+=s,l=c}else h(c),c++,c-l>=15&&u()}u();const f=new Uint8Array(4+i);return new DataView(f.buffer).setUint32(0,t,!0),f.set(n.subarray(0,i),4),f}(e)}catch{return function(e){const t=Math.ceil(e.byteLength/15),s=Math.max(t,0)+e.byteLength,n=new Uint8Array(4+s);new DataView(n.buffer).setUint32(0,e.byteLength,!0);let i=4,r=0;for(;r<e.byteLength;){const t=Math.min(15,e.byteLength-r);n[i++]=(15&t)<<4;for(let s=0;s<t;s++)n[i++]=e[r+s];r+=t}return i===n.byteLength?n:n.slice(0,i)}(e)}}function tt(e,t){if(e.byteLength<4)throw new Error("LZ4 stream too short: missing header");const s=new DataView(e.buffer,e.byteOffset,e.byteLength).getUint32(0,!0);if(0===s&&4===e.byteLength)return new Uint8Array(0);if(s<=0||s>1073741823)throw new Error("Invalid LZ4 header: bad original size");const n=e.subarray(4),i=new Uint8Array(s);let r=0,a=0;for(;r<n.byteLength&&a<s;){const e=n[r++],t=e>>4&15,o=15&e;for(let e=0;e<t&&r<n.byteLength&&a<s;e++)i[a++]=n[r++];if(0===o)continue;if(r+1>=n.byteLength)break;const h=n[r++]|n[r++]<<8,c=o+4;for(let e=0;e<c&&a<s;e++)i[a]=i[a-h],a++}return i}class st{constructor(e,t,s=!1){this.fileManager=e,this.bufferPool=t,this.compression=s,this.pageIds=new Map,this.retiredPageIds=new Map,this.storedSizes=new Map}async save(e,t){const s=this.compression?et(t):t,n=Math.max(1,Math.ceil(s.byteLength/we)),i=await this.bufferPool.newPages(n,be.DATA),r=[];for(let e=0;e<n;e++){const t=i[e];r.push(t.pageId);const n=new Uint8Array(t.data);n.fill(0);const a=s.subarray(e*we,Math.min((e+1)*we,s.byteLength));n.set(a,0),t.dirty=!0,await this.bufferPool.flushPage(t.pageId),this.bufferPool.unpin(t)}return this.pageIds.set(e,r),this.retiredPageIds.delete(e),this.storedSizes.set(e,s.byteLength),{storedSize:s.byteLength}}getPageIds(e){return this.pageIds.get(e)??this.retiredPageIds.get(e)}registerPageIds(e,t,s){this.pageIds.has(e)||(this.pageIds.set(e,[...t]),"number"==typeof s&&this.storedSizes.set(e,s))}retirePageIds(e){const t=this.pageIds.get(e);t&&(this.pageIds.delete(e),this.retiredPageIds.set(e,t))}async load(e,t,s){const n=t??this.pageIds.get(e)??this.retiredPageIds.get(e);if(!n||0===n.length)return null;const i=s??this.storedSizes.get(e);if("number"!=typeof i)return null;const r=[];for(const e of n){const t=await this.bufferPool.getPage(e);if(!t)return null;r.push(new Uint8Array(t.data)),this.bufferPool.unpin(t)}const a=r.reduce((e,t)=>e+t.byteLength,0),o=new Uint8Array(Math.min(a,i));let h=0;for(const e of r){const t=Math.min(e.byteLength,o.byteLength-h);if(t<=0)break;o.set(e.subarray(0,t),h),h+=t}return this.compression?tt(o):o}async delete(e,t){const s=t??this.pageIds.get(e)??this.retiredPageIds.get(e)??[];for(const e of s){this.bufferPool.removePage(e);try{await this.fileManager.freePageId(e)}catch{}}this.pageIds.delete(e),this.retiredPageIds.delete(e),this.storedSizes.delete(e)}}class nt{constructor(e){this.nextPageId=0,this.metaLoaded=!1,this.dbName="",this.backend=e}async init(e,t=1){this.dbName=e;const s=await this.backend.read("__aria_meta");let n=1;s&&s instanceof ArrayBuffer&&s.byteLength>=4&&(n=new DataView(s).getUint32(0,!1));const i=await this.backend.listKeys();for(const e of i)if(e.startsWith("pg_")){const t=Number.parseInt(e.slice(3),10);!Number.isNaN(t)&&t+1>n&&(n=t+1)}if(Number.isFinite(t)&&t>n&&(n=Math.floor(t)),this.nextPageId=n,this.metaLoaded=!0,(s&&s instanceof ArrayBuffer&&s.byteLength>=4?new DataView(s).getUint32(0,!1):-1)!==n)try{await this.writeLegacyWatermark(n)}catch{}}getNextPageId(){return this.nextPageId}async readPage(e){const t=`pg_${e}`,s=await this.backend.read(t);if(!s)return null;if(s.byteLength<we){const e=new ArrayBuffer(we);return new Uint8Array(e).set(new Uint8Array(s)),e}return s}async writePage(e,t){const s=`pg_${e}`;await this.backend.write(s,t)}async allocatePageId(){const e=this.nextPageId++;return await this.persistWatermarkHint(),e}async allocatePageIds(e){if(e<=0)return[];const t=[],s=this.nextPageId;this.nextPageId+=e;for(let n=0;n<e;n++)t.push(s+n);return await this.persistWatermarkHint(),t}async freePageId(e){const t=`pg_${e}`;await this.backend.delete(t)}async persistWatermarkHint(){if(this.metaLoaded)try{await this.writeLegacyWatermark(this.nextPageId)}catch{}}async writeLegacyWatermark(e){const t=new ArrayBuffer(8);new DataView(t).setUint32(0,e,!1),await this.backend.write("__aria_meta",t)}async clearAll(){await this.backend.clear(),this.nextPageId=1;try{await this.writeLegacyWatermark(1)}catch{}}}const it=1297304902,rt=24,at=/^__aria_manifest_(\d{8})$/;function ot(e){return{formatVersion:1,generation:0,pageIdWatermark:1,namespaces:{},schemas:{},wal:{startSegment:0,startLsn:0,nextLsn:0},frozen:[],owner:{instanceId:e.instanceId,epoch:0,openedAt:e.now??Date.now()},committedAt:e.now??Date.now()}}function ht(e){return`__aria_manifest_${String(e).padStart(8,"0")}`}function ct(e){const t=at.exec(e);return t?Number(t[1]):null}function lt(e){try{if(e.byteLength<rt)return{ok:!1,reason:`too small (${e.byteLength} < 24)`};const t=new DataView(e.buffer,e.byteOffset,e.byteLength),s=t.getUint32(0,!1);if(s!==it)return{ok:!1,reason:`bad magic 0x${s.toString(16)}`};const n=t.getUint32(20,!1),i=ie(e.subarray(0,20));if(n!==i)return{ok:!1,reason:`header CRC mismatch (stored=${n} computed=${i})`};const r=t.getUint16(4,!1);if(1!==r)return{ok:!1,reason:`unsupported format version ${r}`};const a=t.getUint16(6,!1);if(a!==rt)return{ok:!1,reason:`unexpected header size ${a}`};const o=t.getUint32(8,!1),h=t.getUint32(12,!1);if(0===h||h>e.byteLength-rt)return{ok:!1,reason:`invalid payload length ${h}`};const c=e.subarray(rt,rt+h),l=t.getUint32(16,!1),u=ie(c);if(l!==u)return{ok:!1,reason:`payload CRC mismatch (stored=${l} computed=${u})`};let f;try{f=JSON.parse((new TextDecoder).decode(c))}catch(e){return{ok:!1,reason:`payload is not valid JSON: ${e.message}`}}const d=function(e,t){try{if(!ut(e))return{ok:!1,reason:"payload is not an object"};const s=ft(e.formatVersion,"formatVersion");if(1!==s)return{ok:!1,reason:`payload formatVersion ${s}`};const n=ft(e.generation,"generation");if(n!==t)return{ok:!1,reason:`generation mismatch (header=${t} payload=${n})`};const i=ft(e.pageIdWatermark,"pageIdWatermark");if(!ut(e.namespaces))return{ok:!1,reason:"namespaces is not an object"};const r={};for(const[t,s]of Object.entries(e.namespaces)){if(!ut(s))return{ok:!1,reason:`namespace "${t}" is not an object`};const e=ft(s.nextSstableId,`namespaces.${t}.nextSstableId`);if(!Array.isArray(s.sstables))return{ok:!1,reason:`namespaces.${t}.sstables is not an array`};const n=[];for(const e of s.sstables){if(!ut(e))return{ok:!1,reason:`namespace "${t}" has a non-object sstable`};const s=ft(e.id,`namespaces.${t}.sstables[].id`),i=ft(e.level,`namespaces.${t}.sstables[].level`),r=ft(e.blockCount,`namespaces.${t}.sstables[].blockCount`),a=ft(e.totalSize,`namespaces.${t}.sstables[].totalSize`),o=dt(e.minKey,`namespaces.${t}.sstables[].minKey`),h=dt(e.maxKey,`namespaces.${t}.sstables[].maxKey`);let c;if(void 0!==e.pageIds){if(!Array.isArray(e.pageIds))return{ok:!1,reason:`namespaces.${t}.sstables[].pageIds is not an array`};c=e.pageIds.map((e,s)=>ft(e,`namespaces.${t}.sstables[].pageIds[${s}]`))}n.push({id:s,level:i,minKey:o,maxKey:h,blockCount:r,totalSize:a,bloomData:null,...c?{pageIds:c}:{}})}r[t]={nextSstableId:e,sstables:n}}if(!ut(e.schemas))return{ok:!1,reason:"schemas is not an object"};const a={};for(const[t,s]of Object.entries(e.schemas)){if(!ut(s))return{ok:!1,reason:`schemas.${t} is not an object`};a[t]=s}if(!ut(e.wal))return{ok:!1,reason:"wal is not an object"};const o={startSegment:ft(e.wal.startSegment,"wal.startSegment"),startLsn:ft(e.wal.startLsn,"wal.startLsn"),nextLsn:ft(e.wal.nextLsn,"wal.nextLsn")};if(o.startLsn>o.nextLsn)return{ok:!1,reason:`wal.startLsn ${o.startLsn} > wal.nextLsn ${o.nextLsn}`};if(!Array.isArray(e.frozen))return{ok:!1,reason:"frozen is not an array"};const h=[];for(const t of e.frozen){if(!ut(t))return{ok:!1,reason:"frozen has a non-object entry"};h.push({ns:dt(t.ns,"frozen[].ns"),id:ft(t.id,"frozen[].id"),entryCount:ft(t.entryCount,"frozen[].entryCount"),minKey:dt(t.minKey,"frozen[].minKey"),maxKey:dt(t.maxKey,"frozen[].maxKey"),lsnAtFreeze:ft(t.lsnAtFreeze,"frozen[].lsnAtFreeze")})}if(!ut(e.owner))return{ok:!1,reason:"owner is not an object"};return{ok:!0,manifest:{formatVersion:s,generation:t,pageIdWatermark:i,namespaces:r,schemas:a,wal:o,frozen:h,owner:{instanceId:dt(e.owner.instanceId,"owner.instanceId"),epoch:ft(e.owner.epoch,"owner.epoch"),openedAt:ft(e.owner.openedAt,"owner.openedAt")},committedAt:ft(e.committedAt,"committedAt")}}}catch(e){return{ok:!1,reason:e.message}}}(f,o);return d.ok?{ok:!0,manifest:d.manifest}:d}catch(e){return{ok:!1,reason:`decode threw: ${e.message}`}}}function ut(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}function ft(e,t){if("number"!=typeof e||!Number.isFinite(e)||e<0||!Number.isInteger(e))throw new Error(`manifest field "${t}" must be a non-negative integer, got ${JSON.stringify(e)}`);return e}function dt(e,t){if("string"!=typeof e)throw new Error(`manifest field "${t}" must be a string, got ${JSON.stringify(e)}`);return e}let pt=0;class mt{constructor(e){this.loaded=!1,this.hadInvalidGenerations=!1,this.skipped=[],this.commitChain=Promise.resolve(),this.generation=0,this.backend=e.backend,this.now=e.now??(()=>Date.now()),this.state=ot({instanceId:e.instanceId??`aria-${++pt}-${Math.random().toString(36).slice(2,10)}`,now:this.now()})}get instanceId(){return this.state.owner.instanceId}get current(){return this.state}get currentGeneration(){return this.generation}async load(){const e=(await this.backend.listKeys()).map(e=>ct(e)).filter(e=>null!==e).sort((e,t)=>t-e),t=[];for(const s of e){const e=await this.backend.read(ht(s));if(!e){t.push({generation:s,reason:"manifest file disappeared during load"});continue}const n=lt(new Uint8Array(e));if(n.ok){if(n.manifest.generation===s)return this.state=n.manifest,this.generation=s,this.skipped=t,this.hadInvalidGenerations=t.length>0,this.loaded=!0,{manifest:n.manifest,generation:s,hadInvalidGenerations:this.hadInvalidGenerations,skipped:t};t.push({generation:s,reason:`file name generation ${s} != payload generation ${n.manifest.generation}`})}else t.push({generation:s,reason:n.reason})}if(e.length>0)throw new n(`AriaEngine manifest is corrupt: ${e.length} generation(s) present, none passed validation (${t.map(e=>`gen ${e.generation}: ${e.reason}`).join("; ")})`,"ARIA_MANIFEST_CORRUPT");return this.loaded=!0,{manifest:null,generation:0,hadInvalidGenerations:!1,skipped:[]}}adopt(e){this.state=e,this.generation=e.generation}async claimOwnership(){return this.commitInternal({allowTakeover:!0})}async commit(){return this.commitInternal({allowTakeover:!1})}async commitInternal(e){let t,s=null;const n=this.commitChain.then(async()=>{try{t=await this.doCommit(e)}catch(e){s=e}});if(this.commitChain=n,await n,s)throw s;return t}async doCommit(e){if(!this.loaded)throw new n("ManifestStore.commit() before load()","ARIA_MANIFEST_NOT_LOADED");const t=await this.newestGenerationOnDisk(),s=new Set(this.skipped.map(e=>e.generation));let i=0;for(const e of await this.listGenerationNumbers())e>this.generation&&!s.has(e)&&(i=Math.max(i,e));if(!e.allowTakeover&&i>this.generation)throw new n(`Refusing to commit: another instance committed generation ${i} (this instance last committed ${this.generation}) — stale instance`,"STALE_INSTANCE");const r=e.allowTakeover?t+1e3:t+1,a={...this.state,formatVersion:1,generation:r,namespaces:this.state.namespaces,schemas:this.state.schemas,wal:{...this.state.wal},frozen:this.state.frozen.map(e=>({...e})),owner:{instanceId:this.state.owner.instanceId,epoch:this.state.owner.epoch+1,openedAt:this.state.owner.openedAt},committedAt:this.now()},o=function(e){const t=(new TextEncoder).encode(JSON.stringify(function(e){const t={};for(const[s,n]of Object.entries(e.namespaces))t[s]={nextSstableId:n.nextSstableId,sstables:n.sstables.map(e=>({id:e.id,level:e.level,minKey:e.minKey,maxKey:e.maxKey,blockCount:e.blockCount,totalSize:e.totalSize,bloomData:null,...e.pageIds&&e.pageIds.length>0?{pageIds:[...e.pageIds]}:{}}))};return{formatVersion:e.formatVersion,generation:e.generation,pageIdWatermark:e.pageIdWatermark,namespaces:t,schemas:e.schemas,wal:{startSegment:e.wal.startSegment,startLsn:e.wal.startLsn,nextLsn:e.wal.nextLsn},frozen:e.frozen.map(e=>({...e})),owner:{...e.owner},committedAt:e.committedAt}}(e))),s=new ArrayBuffer(rt+t.byteLength),n=new DataView(s);return n.setUint32(0,it,!1),n.setUint16(4,e.formatVersion,!1),n.setUint16(6,rt,!1),n.setUint32(8,e.generation>>>0,!1),n.setUint32(12,t.byteLength,!1),n.setUint32(16,t.byteLength>0?ie(t):0,!1),n.setUint32(20,ie(new Uint8Array(s,0,20)),!1),new Uint8Array(s,rt).set(t),new Uint8Array(s)}(a);await this.backend.write(ht(r),o.buffer.slice(o.byteOffset,o.byteOffset+o.byteLength));const h=await this.backend.read(ht(r));if(!h)throw new n(`Manifest commit verification failed: generation ${r} not readable after write`,"ARIA_MANIFEST_WRITE_FAILED");const c=lt(new Uint8Array(h));if(!c.ok||c.manifest.generation!==r)throw new n(`Manifest commit verification failed: generation ${r} (${c.ok?"generation mismatch":c.reason})`,"ARIA_MANIFEST_WRITE_FAILED");return this.state=a,this.generation=r,this.hadInvalidGenerations||await this.pruneOldGenerations(r),a}async newestGenerationOnDisk(){return(await this.listGenerationNumbers()).reduce((e,t)=>Math.max(e,t),0)}async listGenerationNumbers(){const e=await this.backend.listKeys(),t=[];for(const s of e){const e=ct(s);null!==e&&t.push(e)}return t}async pruneOldGenerations(e){const t=(await this.backend.listKeys()).map(e=>ct(e)).filter(t=>null!==t&&t<e-1);if(0!==t.length)try{await this.backend.deleteMany(t.map(e=>ht(e)))}catch{}}}class yt{constructor(){this.versionStore=new Map,this.activeTxns=new Map,this.nextTxnId=1,this.globalCommitLsn=0,this.txnWriteKeys=new Map}beginTransaction(){const e=this.nextTxnId++;return this.activeTxns.set(e,{txnId:e,state:Se.ACTIVE,snapshotLsn:this.globalCommitLsn,startTime:Date.now()}),this.txnWriteKeys.set(e,new Set),e}commitTransaction(e){const t=this.activeTxns.get(e);if(!t)throw new Error(`Transaction ${e} not found`);t.state=Se.COMMITTED,this.globalCommitLsn++;const s=this.txnWriteKeys.get(e);if(s)for(const t of s){const s=this.versionStore.get(t);if(!s)continue;const n=s.filter(t=>t.txnId!==e);0===n.length?this.versionStore.delete(t):this.versionStore.set(t,n)}this.activeTxns.delete(e),this.txnWriteKeys.delete(e)}rollbackTransaction(e){const t=this.activeTxns.get(e);if(!t)throw new Error(`Transaction ${e} not found`);t.state=Se.ABORTED;const s=this.txnWriteKeys.get(e);if(s)for(const t of s){const s=this.versionStore.get(t);if(!s)continue;const n=s.filter(t=>t.txnId!==e);0===n.length?this.versionStore.delete(t):this.versionStore.set(t,n)}this.activeTxns.delete(e),this.txnWriteKeys.delete(e)}writeVersion(e,t,s,n){const i=`${e}.${t}`,r=this.versionStore.get(i)??[],a={txnId:n,data:s,prevVersion:r.length>0?r[r.length-1]:null,committed:!1};r.push(a),this.versionStore.set(i,r),this.txnWriteKeys.get(n)?.add(i)}deleteVersion(e,t,s){this.writeVersion(e,t,{__mvcc_tombstone:!0},s)}discardVersions(e){const t=this.txnWriteKeys.get(e);if(t)for(const s of t){const t=this.versionStore.get(s);if(!t)continue;const n=t.filter(t=>t.txnId!==e);0===n.length?this.versionStore.delete(s):this.versionStore.set(s,n)}}gc(e=100){for(const[t,s]of this.versionStore){if(s.length<=e)continue;const n=s.slice(s.length-e);this.versionStore.set(t,n)}}getGlobalLSN(){return this.globalCommitLsn}}function gt(e,t){const s=new ArrayBuffer(we);return function(e,t,s){const n=new DataView(e);n.setUint32(0,t,!1),n.setUint8(4,s),n.setUint16(5,16,!1),n.setUint16(7,e.byteLength,!1),n.setUint16(9,0,!1),n.setUint32(11,0,!1),n.setUint8(15,0)}(s,e,t),{pageId:e,type:t,data:s,dirty:!0,pins:0,prev:null,next:null,lastAccess:Date.now()}}class wt{constructor(){this.head=null,this.tail=null,this._size=0}get size(){return this._size}moveToHead(e){this.head!==e&&(null!==e.prev||null!==e.next||this.head===e||this.tail===e?this.detach(e):this._size++,e.prev=null,e.next=this.head,this.head&&(this.head.prev=e),this.head=e,this.tail||(this.tail=e))}remove(e){(null!==e.prev||null!==e.next||this.head===e||this.tail===e)&&(this.detach(e),this._size=Math.max(0,this._size-1))}detach(e){e.prev?e.prev.next=e.next:this.head===e&&(this.head=e.next),e.next?e.next.prev=e.prev:this.tail===e&&(this.tail=e.prev),e.prev=null,e.next=null}clear(){this.head=null,this.tail=null,this._size=0}getLRU(){return this.tail}}class bt{constructor(e,t,s){this.lru=new wt,this.capacity=e,this.onEvict=t,this.onRemove=s}access(e){e.lastAccess=Date.now(),this.lru.moveToHead(e)}add(e){this.access(e)}remove(e){this.lru.remove(e)}async evictIfNeeded(e){let t=0;for(;this.lru.size+e>this.capacity&&this.lru.size>0;){const e=this.findEvictionCandidate();if(!e)break;e.dirty&&(await this.onEvict(e),e.dirty=!1),this.lru.remove(e),this.onRemove?.(e),t++}return t}findEvictionCandidate(){let e=this.lru.getLRU();for(;e;){if(0===e.pins&&!e.dirty)return e;e=e.prev}for(e=this.lru.getLRU();e;){if(0===e.pins)return e;e=e.prev}return null}clear(){this.lru.clear()}}class Tt{constructor(e,t=256){this.pages=new Map,this.nextPageId=0,this.pageIO=e,this.eviction=new bt(t,async e=>{e.dirty&&(await this.pageIO.writePage(e.pageId,e.data),e.dirty=!1)},e=>{this.pages.delete(e.pageId)})}async getPage(e){let t=this.pages.get(e);if(t)return this.eviction.access(t),t.pins++,t;const s=await this.pageIO.readPage(e);return s?(await this.eviction.evictIfNeeded(1),t={pageId:e,type:new DataView(s).getUint8(4),data:s,dirty:!1,pins:1,prev:null,next:null,lastAccess:Date.now()},this.pages.set(e,t),this.eviction.add(t),t):null}async newPages(e,t=be.DATA){if(e<=0)return[];let s;if("function"==typeof this.pageIO.allocatePageIds)s=await this.pageIO.allocatePageIds(e);else{s=[];for(let t=0;t<e;t++)s.push(await this.pageIO.allocatePageId())}await this.eviction.evictIfNeeded(e);const n=[];for(const e of s){const s=gt(e,t);s.pins=1,this.pages.set(e,s),this.eviction.add(s),n.push(s)}return n}unpin(e){e.pins>0&&e.pins--}markDirty(e){e.dirty=!0}async flushPage(e){const t=this.pages.get(e);t&&t.dirty&&(await this.pageIO.writePage(e,t.data),t.dirty=!1)}async flushAll(){for(const[,e]of this.pages)e.dirty&&(await this.pageIO.writePage(e.pageId,e.data),e.dirty=!1)}removePage(e){const t=this.pages.get(e);t&&(this.eviction.remove(t),this.pages.delete(e))}async clear(){await this.flushAll(),this.pages.clear(),this.eviction.clear()}}class Et{constructor(e={}){this.name="aria",this.opened=!1,this.dbName="",this.dbLock=null,this.durableLsn=0,this.walStartSegment=0,this.recoveryReport={droppedSSTables:[],dataLossSuspected:!1,walGaps:[],droppedWALRecords:0,legacyImported:!1,manifestFallback:!1},this.schemas=new Map,this.tablePKs=new Map,this.opCounter=0,this.secondaryIndexes=new Map,this.uniqueIndexCols=new Set,this.mvcc=new yt,this.currentTxnId=null,this.txnSnapshot=null,this.gcCounter=0,this.savepoints=new Map,this.txnWalRecordCount=0,this.savepointWalBoundary=new Map,this.config={...ke,...e}}async open(e,t){if(!this.opened)try{await this.openInternal(e)}catch(t){if(this.dbLock){try{await this.dbLock.release()}catch{}this.dbLock=null}if(t instanceof n)throw t;throw new n(`Failed to open AriaEngine database "${e}"`,"ARIA_OPEN_ERROR",t)}}async openInternal(e){this.dbName=e;const t=new qe;let s;if(this.dbLock=t,await t.acquire(e),s=this.config.testBackend?this.config.testBackend:"opfs"===this.config.storageBackend?new Y:"kv"===this.config.storageBackend?new We:new Ve,await s.open(e),this.config.encryption?.password)this.backend=new Ze(s,this.config.encryption.password);else if(this.backend=s,await s.exists("__aria_keymeta"))throw await s.close(),new n("Database is encrypted: provide encryption.password to open it","ARIA_ENCRYPT_REQUIRED");await this.backend.open(e),this.manifestStore=new mt({backend:this.backend});const i=await this.manifestStore.load();i.hadInvalidGenerations&&(this.recoveryReport.manifestFallback=!0),null===i.manifest?(this.manifest=ot({instanceId:this.manifestStore.instanceId}),this.manifestStore.adopt(this.manifest),await this.importLegacyState()):this.manifest=i.manifest,this.manifest=await this.manifestStore.claimOwnership(),this.durableLsn=this.manifest.wal.startLsn,this.walStartSegment=this.manifest.wal.startSegment,this.wal=new Me(new ze(this.backend),this.config.walEnabled,this.config.walSyncMode),this.wal.setLsn(this.manifest.wal.nextLsn),this.fileManager=new nt(this.backend),await this.fileManager.init(e,this.manifest.pageIdWatermark),this.bufferPool=new Tt(this.fileManager,this.config.bufferPoolPages),this.lsm=this.createLSM("main"),await this.loadSchemas();for(const[e,t]of this.schemas){const s=this.tablePKs.get(e);for(const[n,i]of Object.entries(t.columns))if((i.index||i.unique)&&n!==s){const t=`${e}:idx:${n}`;if(!this.secondaryIndexes.has(t)){const s=this.createLSM(`idx_${e}_${n}`);await s.init(),this.secondaryIndexes.set(t,s)}}}await this.lsm.init();const r=new Set,a=[];await this.wal.recover(e=>a.push(e),{fromSegment:this.manifest.wal.startSegment,fromLsn:this.manifest.wal.startLsn,allowGaps:!0});const o=this.wal.getLastRecoveryInfo();o&&o.corruptRecords>0&&(this.recoveryReport.droppedWALRecords=o.corruptRecords,this.recoveryReport.dataLossSuspected=!0),o&&o.gaps.length>0&&(this.recoveryReport.walGaps=[...o.gaps],this.recoveryReport.dataLossSuspected=!0);for(const e of a)e.type===Ee.COMMIT&&r.add(e.txnId),e.type===Ee.ROLLBACK&&r.delete(e.txnId);const h=new Map,c=new Map;for(let e=0;e<a.length;e++){const t=a[e];if(0===t.txnId)continue;const s=c.get(t.txnId)??0;h.set(e,s),c.set(t.txnId,s+1)}const l=new Map;for(let e=0;e<a.length;e++){const t=a[e];if(t.type!==Ee.SAVEPOINT_ROLLBACK)continue;const s=t.data?.replayFromIndex,n="number"==typeof s?s:0,i=h.get(e)??0,r=l.get(t.txnId);l.set(t.txnId,{keepUpTo:r?Math.min(r.keepUpTo,n):n,dropFrom:i})}for(let e=0;e<a.length;e++){const t=a[e];if(0===t.txnId||r.has(t.txnId)){if(t.type===Ee.SAVEPOINT_ROLLBACK)continue;const s=l.get(t.txnId);if(void 0!==s){const t=h.get(e)??0;if(t>=s.keepUpTo&&t<s.dropFrom)continue}t.type===Ee.DROP_TABLE?await this.applyDropTableRecovery(t.tableName):this.applyWALRecord(t)}}if(a.length>0){await this.flushAllLsms();for(const e of this.schemas.keys())await this.reindexTableInternal(e);await this.flushAllLsms(),await this.advanceWalCheckpoint()}else this.hasPendingFlushData()&&(await this.flushAllLsms(),await this.advanceWalCheckpoint());this.verifyFrozenIntentsAfterRecovery(a.length),this.checkpointManager=new je(this.lsm,{checkpoint:async()=>{this.currentTxnId||await this.advanceWalCheckpoint()},flush:async()=>{this.currentTxnId||await this.wal.flush()},getBufferedBytes:()=>this.wal.getBufferedBytes(),getBufferedCount:()=>this.wal.getBufferedCount()},{flushAll:async()=>{await this.flushAllLsms()},flushMemtables:async()=>{await this.flushAllLsms(!0)}},this.config.checkpointInterval,this.config.walSizeThreshold),this.opened=!0}async close(){if(!this.opened)return;let e=null;try{await this.flushAllLsms(),await this.bufferPool.flushAll(),await this.advanceWalCheckpoint()}catch(t){e=t}finally{try{await this.backend.close()}catch(t){null===e&&(e=t)}if(this.dbLock){try{await this.dbLock.release()}catch{}this.dbLock=null}this.schemas.clear(),this.tablePKs.clear(),this.secondaryIndexes.clear(),this.uniqueIndexCols.clear(),this.mvcc=new yt,this.currentTxnId=null,this.txnSnapshot=null,this.savepoints.clear(),this.opCounter=0,this.opened=!1}if(null!==e)throw e}async repair(){this.ensureOpen(),await this.bufferPool.clear();let e=0;for(const t of this.allLsms())e+=await t.validateAll();await this.flushAllLsms(),await this.advanceWalCheckpoint();for(const e of this.schemas.keys())await this.reindexTable(e);await this.flushAllLsms(),await this.commitManifest();for(const e of this.allLsms())e.reclaimRetiredNow();const t=this.backend;if("function"==typeof t.cleanupStaleFiles)try{await t.cleanupStaleFiles()}catch{}await this.cleanupOrphanPages()}async cleanupOrphanPages(){if(this.describeRecoveryDamage().length>0)return;if(this.allLsms().some(e=>e.hasActiveReaders()))return;const e=await this.backend.listKeys(),t=new Set;for(const e of Object.values(this.manifest.namespaces))for(const s of e.sstables)if(s.pageIds)for(const e of s.pageIds)t.add(e);for(const e of this.allLsms()){for(const s of this.getLsmLevels(e))for(const e of s)if(e.pageIds)for(const s of e.pageIds)t.add(s);for(const s of e.getRetiredPageIds())t.add(s)}const s=e.filter(e=>/^pg_\d+$/.test(e)).map(e=>Number(e.slice(3))).filter(e=>!t.has(e));s.length>0&&await this.backend.deleteMany(s.map(e=>`pg_${e}`));const n=new Set;for(const e of Object.values(this.manifest.namespaces))for(const t of e.sstables)n.add(t.id);for(const e of this.allLsms()){for(const t of this.getLsmLevels(e))for(const e of t)n.add(e.id);for(const t of e.getRetiredSstableIds())n.add(t)}const i=[];for(const[t,s]of this.sstableKeyPrefixes()){const t=new RegExp(`^${s}(\\d+)$`);for(const s of e){const e=t.exec(s);e&&(n.has(Number(e[1]))||i.push(s))}}i.length>0&&await this.backend.deleteMany(i)}sstableKeyPrefixes(){const e=[["main","sst_"]];for(const t of Object.keys(this.manifest.namespaces))"main"!==t&&e.push([t,`sst_${t}_`]);return e}getLsmLevels(e){return e.levels??[]}async clearAll(){this.ensureOpen(),await this.backend.clear(),await this.bufferPool.clear(),await this.fileManager.clearAll(),this.schemas.clear(),this.tablePKs.clear(),this.secondaryIndexes.clear(),this.uniqueIndexCols.clear(),this.lsm.clear(),this.mvcc=new yt,this.currentTxnId=null,this.txnSnapshot=null,this.savepoints.clear(),this.opCounter=0,await this.persistSchemas(),this.manifest.namespaces={},this.manifest.frozen=[],this.manifest.pageIdWatermark=Math.max(this.manifest.pageIdWatermark,this.fileManager.getNextPageId()),this.durableLsn=this.wal.getLsn(),this.walStartSegment=0,this.wal.reset(),await this.commitManifest(),await this.wal.checkpoint()}isOpen(){return this.opened}async getMeta(e){const t=await this.backend.read(`__meta_${e}`);return t?(new TextDecoder).decode(t):null}async setMeta(e,t){await this.backend.write(`__meta_${e}`,(new TextEncoder).encode(t).buffer)}async createTable(e){if(this.ensureOpen(),this.ensureNoDDLInTransaction("CREATE TABLE"),this.schemas.has(e.name))throw new n(`Table "${e.name}" already exists`,"TABLE_EXISTS");await this.appendDDLRecord({type:Ee.CREATE_TABLE,txnId:0,tableName:e.name,key:"",data:{schema:JSON.stringify(e)}}),this.schemas.set(e.name,e),this.tablePKs.set(e.name,this.getPK(e));for(const[t,s]of Object.entries(e.columns))if(s.index||s.unique){const s=`${e.name}:idx:${t}`;if(!this.secondaryIndexes.has(s)){const n=new _e({memtableSizeThreshold:this.config.memtableSizeThreshold,levelSizeMultiplier:this.config.levelSizeMultiplier,blockSize:this.config.pageSize,bloomBitsPerKey:this.config.bloomFilterBitsPerKey,cacheLimitBytes:this.config.bufferPoolPages*this.config.pageSize,sstableStore:this.createSSTableStore(`idx_${e.name}_${t}`)});await n.init(),this.secondaryIndexes.set(s,n)}}await this.persistSchemas()}async appendDDLRecord(e){await this.wal.append(e),await this.wal.flush()}async dropTable(e){this.ensureOpen(),this.ensureNoDDLInTransaction("DROP TABLE"),this.ensureTable(e),await this.appendDDLRecord({type:Ee.DROP_TABLE,txnId:0,tableName:e,key:""});const t=await this.getAllRows(e);for(const s of t){const t=this.tablePKs.get(e);this.lsm.delete(`${e}:${s[t]}`)}await this.cleanupTableIndexes(e);const s=`${e}:`;for(const e of this.uniqueIndexCols)e.startsWith(s)&&this.uniqueIndexCols.delete(e);this.schemas.delete(e),this.tablePKs.delete(e),await this.persistSchemas()}async cleanupTableIndexes(e){const t=`${e}:idx:`,s=[];for(const[e,n]of this.secondaryIndexes)if(e.startsWith(t)){s.push(e);try{await n.clear()}catch{}}for(const e of s)this.secondaryIndexes.delete(e)}async hasTable(e){return this.ensureOpen(),this.schemas.has(e)}async getTableNames(){return this.ensureOpen(),Array.from(this.schemas.keys())}async getTableSchema(e){return this.ensureOpen(),this.schemas.get(e)??null}async insert(e,t){this.ensureOpen(),this.ensureTable(e);const s=this.schemas.get(e),i=this.tablePKs.get(e),r=[],a=[],o=this.uniqueColumns(e,s),h=[];for(const n of t){const t=this.validateRow(s,n),r=String(t[i]);h.push({row:t,pkValue:r,key:`${e}:${r}`})}const c=new Set;for(const{pkValue:t,key:s}of h){if(c.has(t))throw new n(`Duplicate primary key "${t}" in table "${e}"`,"DUPLICATE_KEY");c.add(t);const i=this.currentTxnId?this.txnSnapshot?.get(s)??await this.lsm.get(s):await this.lsm.get(s);if(i&&!i.__txn_deleted)throw new n(`Duplicate primary key "${t}" in table "${e}"`,"DUPLICATE_KEY")}const l=new Map;for(const{row:t,pkValue:s}of h)for(const i of o){const r=t[i];if(null==r)continue;const a=String(r);let o=l.get(i);if(o||(o=new Set,l.set(i,o)),o.has(a))throw new n(`Unique constraint violation on column "${i}" in table "${e}"`,"UNIQUE_VIOLATION");o.add(a),await this.checkUnique(e,[i],t,s)}for(const{row:t,pkValue:s,key:n}of h)this.currentTxnId&&this.txnSnapshot?(this.txnSnapshot.set(n,t),this.mvcc.writeVersion(e,s,t,this.currentTxnId)):this.lsm.put(n,t),this.updateSecondaryIndexes(e,s,t,null),r.push(s),a.push({type:Ee.INSERT,txnId:this.currentTxnId??0,tableName:e,key:s,data:t});return await this.wal.appendBatch(a),this.txnWalRecordCount+=a.length,this.opCounter+=t.length,this.checkMemoryBudget(),await this.checkpointManager.tick(),this.tryGC(),r}async find(e,t){let s;this.ensureOpen(),this.ensureTable(e);const n=await this.tryIndexLookup(e,t);s=null!==n?n:await this.getAllRows(e),s=this.mergeTxnSnapshot(e,s),t.where&&Object.keys(t.where).length>0&&(s=s.filter(e=>k(e,t.where))),t.orderBy&&t.orderBy.length>0&&(s=P(s,t.orderBy));const i=t.offset??0,r=t.limit??s.length;return s=s.slice(i,i+r),t.columns&&t.columns.length>0&&"*"!==t.columns[0]&&(s=s.map(e=>F(e,t.columns))),this.trimAllCaches(),s.map(e=>o(e))}async update(e,t,s){this.ensureOpen(),this.ensureTable(e);const i=this.schemas.get(e),r=await this.getAllRows(e);let a=0;const o=[],h=new Set,c=G(s);for(const t of Object.keys(c))if(!i.columns[t])throw new n(`Column "${t}" does not exist in table "${e}"`,"COLUMN_NOT_FOUND");const l=this.uniqueColumns(e,i),u=[],f=new Map,d=new Set;for(const s of r){const r=this.tablePKs.get(e),a=`${e}:${s[r]}`;if(t.where&&Object.keys(t.where).length>0&&!k(s,t.where))continue;const o={...s,...c};this.validateRow(i,o),this.checkBatchUnique(e,l,o,f),await this.checkUnique(e,l,o,String(s[r]));const h=String(o[r]),p=h!==String(s[r]);if(p){const t=`${e}:${h}`,s=this.currentTxnId?this.txnSnapshot?.get(t)??await this.lsm.get(t):await this.lsm.get(t);if(s&&!s.__txn_deleted)throw new n(`Duplicate primary key "${h}" in table "${e}" (cannot update key to existing value)`,"DUPLICATE_KEY");if(d.has(h))throw new n(`Duplicate primary key "${h}" in table "${e}" (multiple rows in the same statement update to the same key)`,"DUPLICATE_KEY");d.add(h)}u.push({row:s,pk:String(s[r]),key:a,updated:o,newPk:h,pkChanged:p})}for(const t of u)t.pkChanged&&await this.checkForeignKeyUpdateRestrict(e,t.pk,t.newPk);for(const{row:t,pk:s,key:n,updated:i,newPk:r,pkChanged:c}of u)c&&await this.applyForeignKeyUpdateRules(e,s,r,o,h),this.currentTxnId&&this.txnSnapshot?(c&&(this.txnSnapshot.set(n,{__txn_deleted:!0}),this.mvcc.deleteVersion(e,s,this.currentTxnId)),this.txnSnapshot.set(`${e}:${r}`,i),this.mvcc.writeVersion(e,r,i,this.currentTxnId)):(c&&this.lsm.delete(n),this.lsm.put(`${e}:${r}`,i)),a++,c&&o.push({type:Ee.DELETE,txnId:this.currentTxnId??0,tableName:e,key:s}),o.push({type:Ee.UPDATE,txnId:this.currentTxnId??0,tableName:e,key:r,data:i}),this.updateSecondaryIndexes(e,r,i,t);return await this.wal.appendBatch(o),this.txnWalRecordCount+=o.length,this.opCounter+=a,await this.checkpointManager.tick(),this.trimAllCaches(),a}checkBatchUnique(e,t,s,i){for(const r of t){const t=s[r];if(null==t)continue;let a=i.get(r);if(a||(a=new Set,i.set(r,a)),a.has(t))throw new n(`Unique constraint violation on column "${r}" in table "${e}"`,"UNIQUE_VIOLATION");a.add(t)}}async checkForeignKeyUpdateRestrict(e,t,s){for(const[s,i]of this.schemas)for(const[r,a]of Object.entries(i.columns)){if(!a.references||!a.onUpdate)continue;const[i]=a.references.split(".");if(i===e&&("RESTRICT"===a.onUpdate||"SET NULL"===a.onUpdate&&a.required)){const i=await this.getAllRows(s);for(const o of i)if(String(o[r])===t){const i="RESTRICT"===a.onUpdate?`foreign key "${r}" in "${s}" has dependent rows`:`foreign key "${r}" in "${s}" is required (SET NULL violates constraint)`;throw new n(`Cannot update "${e}" key "${t}": ${i}`,"FOREIGN_KEY_VIOLATION")}}}}async applyForeignKeyUpdateRules(e,t,s,n,i){const r=`${e}:${t}`;if(!i.has(r)){i.add(r);for(const[i,r]of this.schemas)for(const[a,o]of Object.entries(r.columns)){if(!o.references||!o.onUpdate)continue;const[r]=o.references.split(".");if(r!==e)continue;if("CASCADE"!==o.onUpdate&&"SET NULL"!==o.onUpdate)continue;const h=await this.getAllRows(i);for(const e of h){if(String(e[a])!==t)continue;const r=this.tablePKs.get(i),h=String(e[r]),c={...e,[a]:"CASCADE"===o.onUpdate?s:null},l=`${i}:${h}`;this.currentTxnId&&this.txnSnapshot?(this.txnSnapshot.set(l,c),this.mvcc.writeVersion(i,h,c,this.currentTxnId)):this.lsm.put(l,c),this.updateSecondaryIndexes(i,h,c,e),n.push({type:Ee.UPDATE,txnId:this.currentTxnId??0,tableName:i,key:h,data:c})}}}}async delete(e,t){this.ensureOpen(),this.ensureTable(e);const s=await this.getAllRows(e);let n=0;const i=[],r=new Set,a=[];for(const n of s)t.where&&0!==Object.keys(t.where).length&&!k(n,t.where)||a.push(String(n[this.tablePKs.get(e)]));const o=new Set;for(const t of a)await this.checkCascadeRestrict(e,t,o);for(const a of s){const s=this.tablePKs.get(e),o=`${e}:${a[s]}`;t.where&&0!==Object.keys(t.where).length&&!k(a,t.where)||(n+=await this.applyForeignKeyRules(e,String(a[s]),i,r),this.currentTxnId&&this.txnSnapshot?(this.txnSnapshot.set(o,{__txn_deleted:!0}),this.mvcc.deleteVersion(e,String(a[s]),this.currentTxnId)):this.lsm.delete(o),n++,i.push({type:Ee.DELETE,txnId:this.currentTxnId??0,tableName:e,key:String(a[s])}),this.updateSecondaryIndexes(e,String(a[s]),null,a))}return await this.wal.appendBatch(i),this.txnWalRecordCount+=i.length,this.opCounter+=n,await this.checkpointManager.tick(),this.trimAllCaches(),n}async checkCascadeRestrict(e,t,s){const i=`${e}:${t}`;if(!s.has(i)){s.add(i);for(const[i,r]of this.schemas)for(const[a,o]of Object.entries(r.columns)){if(!o.references||!o.onDelete)continue;const[r]=o.references.split(".");if(r!==e)continue;const h=(await this.getAllRows(i)).filter(e=>String(e[a])===t);if("RESTRICT"===o.onDelete&&h.length>0)throw new n(`Cannot delete from "${e}": foreign key "${a}" in "${i}" has dependent rows`,"FOREIGN_KEY_VIOLATION");if("SET NULL"===o.onDelete&&o.required&&h.length>0)throw new n(`Cannot delete from "${e}": foreign key "${a}" in "${i}" is required (SET NULL violates constraint)`,"FOREIGN_KEY_VIOLATION");if("CASCADE"===o.onDelete){const e=this.tablePKs.get(i);for(const t of h)await this.checkCascadeRestrict(i,String(t[e]),s)}}}}async applyForeignKeyRules(e,t,s,i){let r=0;const a=`${e}:${t}`;if(i.has(a))return 0;i.add(a);for(const[a,o]of this.schemas)for(const[h,c]of Object.entries(o.columns)){if(!c.references||!c.onDelete)continue;const[o]=c.references.split(".");if(o!==e)continue;const l=(await this.getAllRows(a)).filter(e=>String(e[h])===t);if("RESTRICT"===c.onDelete&&l.length>0)throw new n(`Cannot delete from "${e}": foreign key "${h}" in "${a}" has dependent rows`,"FOREIGN_KEY_VIOLATION");if("CASCADE"===c.onDelete){const e=this.tablePKs.get(a);for(const t of l){const n=String(t[e]);r+=await this.applyForeignKeyRules(a,n,s,i);const o=`${a}:${n}`;this.currentTxnId&&this.txnSnapshot?(this.txnSnapshot.set(o,{__txn_deleted:!0}),this.mvcc.deleteVersion(a,n,this.currentTxnId)):this.lsm.delete(o),this.updateSecondaryIndexes(a,n,null,t),s.push({type:Ee.DELETE,txnId:this.currentTxnId??0,tableName:a,key:n}),r++}}else if("SET NULL"===c.onDelete){const e=this.tablePKs.get(a);for(const t of l){const n=String(t[e]),i={...t,[h]:null},r=`${a}:${n}`;this.currentTxnId&&this.txnSnapshot?(this.txnSnapshot.set(r,i),this.mvcc.writeVersion(a,n,i,this.currentTxnId)):this.lsm.put(r,i),this.updateSecondaryIndexes(a,n,i,t),s.push({type:Ee.UPDATE,txnId:this.currentTxnId??0,tableName:a,key:n,data:i})}}}return r}async findStream(e,t,s){this.ensureOpen(),this.ensureTable(e);const n=!!(t.where&&Object.keys(t.where).length>0),i=t.columns&&t.columns.length>0&&"*"!==t.columns[0]?e=>F(e,t.columns):null,r=t.limit??1/0,a=t.offset??0,h=this.tablePKs.get(e),c=`${e}:`;let l=0,u=0;const f=e=>!(!n||k(e,t.where))||(u<a?(u++,!0):(s(i?i(e):o(e)),l++,l<r));if(this.currentTxnId&&this.txnSnapshot){const n=await this.find(e,{...t,orderBy:void 0,limit:void 0,offset:void 0});for(const e of n)s(i?i(e):o(e));return n.length}const d=await this.tryIndexLookup(e,t);if(null!==d){for(const e of d)if(!f(e))break;return l}return await this.lsm.rangeScanLazy(c,`${c}`,(e,t)=>{if(l>=r)return!1;const s={...t};return s[h]=e.slice(c.length),f(s)}),l}async count(e,t){this.ensureOpen(),this.ensureTable(e);const s=await this.getAllRows(e);return this.trimAllCaches(),t?.where&&0!==Object.keys(t.where).length?s.filter(e=>k(e,t.where)).length:s.length}async clear(e){this.ensureOpen(),this.ensureTable(e);const t=await this.getAllRows(e),s=[];for(const n of t){const t=this.tablePKs.get(e),i=`${e}:${n[t]}`;this.currentTxnId&&this.txnSnapshot?(this.txnSnapshot.set(i,{__txn_deleted:!0}),this.mvcc.deleteVersion(e,String(n[t]),this.currentTxnId)):this.lsm.delete(i),s.push({type:Ee.DELETE,txnId:this.currentTxnId??0,tableName:e,key:String(n[t])}),this.updateSecondaryIndexes(e,String(n[t]),null,n)}await this.wal.appendBatch(s),this.txnWalRecordCount+=s.length,this.opCounter+=t.length,await this.checkpointManager.tick(),this.tryGC()}async alterTable(e,t,s){this.ensureOpen(),this.ensureNoDDLInTransaction("ALTER TABLE"),this.ensureTable(e);const i=this.schemas.get(e);if("ADD"===t){if(i.columns[s.name])throw new n(`Column "${s.name}" already exists in table "${e}"`,"COLUMN_EXISTS");const t={name:i.name,columns:{...i.columns,[s.name]:s}};return await this.appendDDLRecord({type:Ee.ALTER_TABLE,txnId:0,tableName:e,key:s.name,data:{schema:JSON.stringify(t),action:"ADD"}}),i.columns[s.name]=s,(s.index||s.unique)&&await this.createIndex(e,s.name,!0===s.unique),void await this.persistSchemas()}if(!i.columns[s.name])throw new n(`Column "${s.name}" does not exist in table "${e}"`,"COLUMN_NOT_FOUND");if(i.columns[s.name].index||i.columns[s.name].unique){const t=`${e}:idx:${s.name}`,n=this.secondaryIndexes.get(t);if(n){try{await n.clear()}catch{}this.secondaryIndexes.delete(t)}}{const t={name:i.name,columns:Object.fromEntries(Object.entries(i.columns).filter(([e])=>e!==s.name))};await this.appendDDLRecord({type:Ee.ALTER_TABLE,txnId:0,tableName:e,key:s.name,data:{schema:JSON.stringify(t),action:"DROP"}})}delete i.columns[s.name],await this.persistSchemas();const r=`${e}:`,a=`${r}`,o=await this.lsm.rangeScan(r,a),h=[];for(const[t,n]of o){if(!(s.name in n))continue;const i={...n};delete i[s.name],this.lsm.put(t,i);const a=t.slice(r.length);this.updateSecondaryIndexes(e,a,i,n),h.push({type:Ee.UPDATE,txnId:this.currentTxnId??0,tableName:e,key:a,data:i})}await this.wal.appendBatch(h),this.txnWalRecordCount+=h.length,this.opCounter+=h.length,await this.checkpointManager.tick(),this.trimAllCaches()}async createIndex(e,t,s){this.ensureOpen(),this.ensureNoDDLInTransaction("CREATE INDEX"),this.ensureTable(e);const i=this.schemas.get(e).columns[t];if(!i)throw new n(`Column "${t}" does not exist in table "${e}"`,"COLUMN_NOT_FOUND");const r=`${e}:idx:${t}`;if(this.secondaryIndexes.has(r))return;const a=new _e({memtableSizeThreshold:this.config.memtableSizeThreshold,levelSizeMultiplier:this.config.levelSizeMultiplier,blockSize:this.config.pageSize,bloomBitsPerKey:this.config.bloomFilterBitsPerKey,cacheLimitBytes:this.config.bufferPoolPages*this.config.pageSize,sstableStore:this.createSSTableStore(`idx_${e}_${t}`)});await a.init(),this.secondaryIndexes.set(r,a);try{const i=this.tablePKs.get(e),r=await this.getAllRows(e),o=new Set;for(const h of r){const r=h[t];if(null!=r){const c=String(r);if(s&&o.has(c))throw new n(`Unique index on column "${t}" in table "${e}" cannot be created: duplicate value "${c}"`,"UNIQUE_VIOLATION");o.add(c),a.put(`${c}:${h[i]}`,{pk:h[i]})}}await a.flush()}catch(e){this.secondaryIndexes.delete(r);try{await a.clear()}catch{}throw e}i.index=!0,s&&(i.unique=!0,this.uniqueIndexCols.add(`${e}:${t}`)),await this.persistSchemas()}async dropIndex(e,t,s){this.ensureOpen(),this.ensureNoDDLInTransaction("DROP INDEX"),this.ensureTable(e);const i=this.schemas.get(e).columns[t];if(!i)throw new n(`Column "${t}" does not exist in table "${e}"`,"COLUMN_NOT_FOUND");if(i.primaryKey)throw new n(`Cannot drop primary key index on column "${t}"`,"NOT_SUPPORTED");if(!i.index&&!i.unique&&!this.secondaryIndexes.has(`${e}:idx:${t}`))throw new n(`Index on column "${t}" does not exist in table "${e}"`,"INDEX_NOT_FOUND");const r=`${e}:${t}`;if(i.unique&&!this.uniqueIndexCols.has(r))throw new n(`Cannot drop index on column "${t}" in table "${e}": UNIQUE constraint defined at table creation must be removed by recreating the table`,"NOT_SUPPORTED");i.index=!1,i.unique=!1,this.uniqueIndexCols.delete(r);const a=`${e}:idx:${t}`,o=this.secondaryIndexes.get(a);o&&(await o.clear(),this.secondaryIndexes.delete(a)),await this.persistSchemas()}async beginTransaction(){if(this.currentTxnId)throw new n("Transaction already in progress","TX_ACTIVE");this.currentTxnId=this.mvcc.beginTransaction(),this.txnSnapshot=new Map,this.txnWalRecordCount=0;try{await this.wal.append({type:Ee.BEGIN,txnId:this.currentTxnId,tableName:"",key:""}),this.txnWalRecordCount=1}catch(e){throw this.mvcc.rollbackTransaction(this.currentTxnId),this.currentTxnId=null,this.txnSnapshot=null,e}}async commitTransaction(){if(!this.currentTxnId)throw new n("No active transaction","TX_NONE");if(await this.wal.append({type:Ee.COMMIT,txnId:this.currentTxnId,tableName:"",key:""}),await this.wal.flush(),this.txnSnapshot)for(const[e,t]of this.txnSnapshot)t.__txn_deleted?this.lsm.delete(e):this.lsm.put(e,t);this.mvcc.commitTransaction(this.currentTxnId),this.savepoints.clear(),this.savepointWalBoundary.clear(),this.txnWalRecordCount=0,this.currentTxnId=null,this.txnSnapshot=null}async rollbackTransaction(){if(!this.currentTxnId)throw new n("No active transaction","TX_NONE");const e=this.currentTxnId;await this.wal.append({type:Ee.ROLLBACK,txnId:e,tableName:"",key:""});const t=new Set;if(this.txnSnapshot)for(const e of this.txnSnapshot.keys()){const s=e.indexOf(":");s>0&&t.add(e.slice(0,s))}this.mvcc.rollbackTransaction(e),this.txnSnapshot=null,this.savepoints.clear(),this.savepointWalBoundary.clear(),this.txnWalRecordCount=0,this.currentTxnId=null;for(const e of t)this.schemas.has(e)&&await this.reindexTable(e)}async savepoint(e){if(!this.currentTxnId)throw new n("No active transaction for savepoint","TX_NONE");if(this.savepoints.has(e))throw new n(`Savepoint "${e}" already exists`,"SAVEPOINT_EXISTS");this.savepoints.set(e,{txnId:this.currentTxnId,snapshot:this.txnSnapshot?new Map(this.txnSnapshot):null}),this.savepointWalBoundary.set(`${this.currentTxnId}:${e}`,this.txnWalRecordCount)}async rollbackToSavepoint(e){const t=this.savepoints.get(e);if(!t)throw new n(`Savepoint "${e}" not found`,"SAVEPOINT_NOT_FOUND");if(t.txnId!==this.currentTxnId)throw new n(`Savepoint "${e}" belongs to a different transaction (stale savepoint)`,"SAVEPOINT_NOT_FOUND");const s=this.savepointWalBoundary.get(`${this.currentTxnId}:${e}`)??0;await this.wal.append({type:Ee.SAVEPOINT_ROLLBACK,txnId:this.currentTxnId,tableName:"",key:"",data:{replayFromIndex:s}}),this.txnWalRecordCount++,this.savepointWalBoundary.set(`${this.currentTxnId}:${e}`,s);const i=new Set;if(this.txnSnapshot)for(const e of this.txnSnapshot.keys()){const t=e.indexOf(":");t>0&&i.add(e.slice(0,t))}this.txnSnapshot=t.snapshot?new Map(t.snapshot):null,this.mvcc.discardVersions(this.currentTxnId);let r=!1;for(const[t]of this.savepoints)t!==e?r&&this.savepoints.delete(t):r=!0;for(const e of i)this.schemas.has(e)&&await this.reindexTable(e)}async releaseSavepoint(e){if(!this.savepoints.has(e))throw new n(`Savepoint "${e}" not found`,"SAVEPOINT_NOT_FOUND");this.savepoints.delete(e)}async backup(){this.ensureOpen();const e={};for(const t of this.schemas.keys())e[t]=await this.getAllRows(t);return e}async getAllRows(e){const t=this.tablePKs.get(e),s=`${e}:`,n=(await this.lsm.rangeScan(s,`${s}`)).map(([e,n])=>{const i=o(n);return i[t]=e.slice(s.length),i});return this.mergeTxnSnapshot(e,n)}mergeTxnSnapshot(e,t){if(!this.currentTxnId||!this.txnSnapshot)return t;const s=this.tablePKs.get(e),n=`${e}:`;for(const[e,i]of this.txnSnapshot){if(!e.startsWith(n))continue;const r=e.slice(n.length),a=i.__txn_deleted,o=t.findIndex(e=>e[s]===r);if(a)o>=0&&t.splice(o,1);else{const e={...i,[s]:r};o>=0?t[o]=e:t.push(e)}}return t}getPK(e){for(const[t,s]of Object.entries(e.columns))if(s.primaryKey)return t;return Object.keys(e.columns)[0]}validateRow(e,t){return z(e).validateRow(t)}async validatePayload(e,t,s="insert"){this.ensureTable(e);const n=z(this.schemas.get(e));for(const e of t)"update"===s?n.validatePartial(G(e)):n.validateRow(e)}async persistSchemas(){await this.commitManifest()}parseSchemaRecord(e,t){let s;try{s=JSON.parse((new TextDecoder).decode(e))}catch(e){throw new n(`${t} is corrupt and cannot be loaded: ${e.message}`,"ARIA_LEGACY_META_CORRUPT",e)}return this.validateSchemaShape(s,t)}validateSchemaShape(e,t){if(!e||"object"!=typeof e||Array.isArray(e))throw new n(`${t} is not a table-name → columns object (got ${Array.isArray(e)?"array":typeof e})`,"ARIA_LEGACY_META_CORRUPT");const s={};for(const[i,r]of Object.entries(e)){if(!r||"object"!=typeof r||Array.isArray(r))throw new n(`${t} entry "${i}" is not a column map (got ${Array.isArray(r)?"array":typeof r})`,"ARIA_LEGACY_META_CORRUPT");for(const[e,s]of Object.entries(r))if(!s||"object"!=typeof s||Array.isArray(s))throw new n(`${t} entry "${i}.${e}" is not a column definition (got ${Array.isArray(s)?"array":typeof s})`,"ARIA_LEGACY_META_CORRUPT");s[i]=r}return s}async loadSchemas(){let e=this.manifest.schemas??{};if(0===Object.keys(e).length){const t=await this.backend.read("__aria_schemas");t&&(e=this.parseSchemaRecord(t,'Schema record "__aria_schemas"'),this.manifest.schemas=e)}for(const[t,s]of Object.entries(e)){const e={name:t,columns:s};this.schemas.set(t,e),this.tablePKs.set(t,this.getPK(e))}}describeRecoveryDamage(){const e=[];this.recoveryReport.manifestFallback&&e.push("manifest fallback to previous generation"),this.recoveryReport.dataLossSuspected&&e.push("engine-level data loss suspected"),this.recoveryReport.walGaps.length>0&&e.push(`WAL segment gap(s) ${this.recoveryReport.walGaps.join(",")}`),this.recoveryReport.droppedWALRecords>0&&e.push(`${this.recoveryReport.droppedWALRecords} corrupt WAL record(s)`);for(const t of this.allLsms()){const s=t.getRecoveryReport();s.droppedSSTables.length>0&&e.push(`${s.namespace}: ${s.droppedSSTables.length} dropped SSTable(s)`),s.dataLossSuspected&&e.push(`${s.namespace}: LSM data loss suspected`)}return e}getRecoveryReport(){const e=this.recoveryReport.droppedSSTables.map(e=>({...e}));let t=this.recoveryReport.dataLossSuspected;for(const s of this.allLsms()){const n=s.getRecoveryReport();for(const t of n.droppedSSTables)e.push({namespace:n.namespace,...t});n.dataLossSuspected&&(t=!0)}return{droppedSSTables:e,dataLossSuspected:t,walGaps:[...this.recoveryReport.walGaps],droppedWALRecords:this.recoveryReport.droppedWALRecords,legacyImported:this.recoveryReport.legacyImported,manifestFallback:this.recoveryReport.manifestFallback}}createLSM(e){return new _e({memtableSizeThreshold:this.config.memtableSizeThreshold,levelSizeMultiplier:this.config.levelSizeMultiplier,blockSize:this.config.pageSize,bloomBitsPerKey:this.config.bloomFilterBitsPerKey,cacheLimitBytes:this.config.bufferPoolPages*this.config.pageSize,sstableStore:this.createSSTableStore(e),namespace:e,walLsnProvider:()=>this.wal?.getLsn()??0,requireDurableCoverage:(this.manifest?.wal.startLsn??0)>0})}allLsms(){return[this.lsm,...this.secondaryIndexes.values()]}async flushAllLsms(e=!1){for(const t of this.allLsms())e?await t.flushMemtablesOnly():await t.flush()}hasPendingFlushData(){return this.allLsms().some(e=>e.hasPendingFlushData())}serializeSchemas(){const e={};for(const[t,s]of this.schemas)e[t]=s.columns;return e}collectFrozenIntents(){const e=[];for(const t of this.allLsms())e.push(...t.getFrozenIntents());return e}async commitManifest(e){if(!this.opened&&!this.manifestStore)return;const t=this.collectFrozenIntents();this.manifest.pageIdWatermark=Math.max(this.manifest.pageIdWatermark,this.fileManager.getNextPageId()),this.manifest.schemas=this.serializeSchemas(),this.manifest.frozen=t;const s=this.computeDurableLsn(t);this.durableLsn="number"==typeof e?Math.min(s,Math.max(this.durableLsn,e)):s,this.manifest.wal={startSegment:this.walStartSegment,startLsn:this.durableLsn,nextLsn:Math.max(this.manifest.wal.nextLsn,this.wal.getLsn())},this.manifest=await this.manifestStore.commit()}computeDurableLsn(e){return null!==this.currentTxnId?this.durableLsn:e.length>0?Math.min(this.durableLsn,Math.min(...e.map(e=>e.lsnAtFreeze))):this.hasPendingFlushData()?this.durableLsn:Math.max(this.durableLsn,this.wal.getLsn())}async advanceWalCheckpoint(){if(null!==this.currentTxnId)return;await this.wal.flush();const e=this.hasPendingFlushData()?this.durableLsn:Math.max(this.durableLsn,this.wal.getLsn());this.walStartSegment=await this.wal.planKeepFromSegment(e),await this.commitManifest(e),await this.wal.checkpointBefore(e)}async importLegacyState(){let e=!1;const t=(await this.backend.listKeys()).filter(e=>"__aria_lsm_meta"===e||e.startsWith("__aria_lsm_meta_"));for(const s of t){const t="__aria_lsm_meta"===s?"main":s.slice(16),i=await this.backend.read(s);if(!i)continue;let r;try{r=JSON.parse((new TextDecoder).decode(i))}catch(e){throw new n(`Legacy SSTable metadata "${s}" is corrupt and cannot be migrated: ${e.message}`,"ARIA_LEGACY_META_CORRUPT",e)}if(!Array.isArray(r))throw new n(`Legacy SSTable metadata "${s}" is not an array`,"ARIA_LEGACY_META_CORRUPT");const a=[];for(const e of r){const t=e;if("number"!=typeof t?.id||"number"!=typeof t?.level||"string"!=typeof t?.minKey||"string"!=typeof t?.maxKey)throw new n(`Legacy SSTable metadata "${s}" has an entry with unexpected shape: ${JSON.stringify(e)}`,"ARIA_LEGACY_META_CORRUPT");a.push({id:t.id,level:t.level,minKey:t.minKey,maxKey:t.maxKey,blockCount:"number"==typeof t.blockCount?t.blockCount:0,totalSize:"number"==typeof t.totalSize?t.totalSize:0,bloomData:null,...Array.isArray(t.pageIds)?{pageIds:[...t.pageIds]}:{}})}a.sort((e,t)=>t.id-e.id),this.manifest.namespaces[t]={nextSstableId:a.reduce((e,t)=>Math.max(e,t.id),0),sstables:a},e=!0}const s=await this.backend.read("__aria_schemas");s&&(this.manifest.schemas=this.parseSchemaRecord(s,'Legacy schema record "__aria_schemas"'),e=!0);const i=await this.backend.read("__aria_meta");if(i&&i instanceof ArrayBuffer&&i.byteLength>=4){const t=new DataView(i).getUint32(0,!1);t>this.manifest.pageIdWatermark&&(this.manifest.pageIdWatermark=t,e=!0)}e&&(this.recoveryReport.legacyImported=!0)}verifyFrozenIntentsAfterRecovery(e){const t=this.manifest.frozen;if(0===t.length)return;if(e>0)return;if(!this.config.walEnabled)return;const s=t.map(e=>`${e.ns}#${e.id}(${e.entryCount} 项)`).join(", ");throw new n(`AriaEngine manifest declares ${t.length} un-flushed frozen table(s) [${s}] but no WAL record was replayed — confirmed writes are missing (WAL truncated or lost, and the data is not in any committed SSTable)`,"ARIA_WRITE_LOST")}createSSTableStore(e){const t="main"===e?"sst_":`sst_${e}_`,s=this.isPageStorage()?new st(this.fileManager,this.bufferPool,this.config.compression):null;if(s){const t=this.manifest.namespaces[e]?.sstables??[];for(const e of t)e.pageIds&&e.pageIds.length>0&&s.registerPageIds(e.id,e.pageIds,e.totalSize)}const n=()=>{let t=this.manifest.namespaces[e];return t||(t={nextSstableId:0,sstables:[]},this.manifest.namespaces[e]=t),t};return{save:async(e,n)=>{if(s)return s.save(e,n);let i=n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength);if(this.config.compression){const e=et(new Uint8Array(i));i=e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}return await this.backend.write(`${t}${e}`,i),{storedSize:i.byteLength}},load:async e=>{if(s){const t=await s.load(e);if(null!==t)return t}const n=await this.backend.read(`${t}${e}`);if(!n)return null;let i=new Uint8Array(n);return this.config.compression&&!s&&(i=tt(i)),i},delete:async e=>{s&&await s.delete(e),await this.backend.delete(`${t}${e}`)},allocateId:async()=>{const e=n(),t=e.sstables.reduce((e,t)=>Math.max(e,t.id),0);return e.nextSstableId=Math.max(e.nextSstableId,t)+1,e.nextSstableId},listMeta:async()=>n().sstables.map(e=>({...e})),saveMeta:async e=>{const t=n(),i=s?.getPageIds(e.id),r=i&&i.length>0?{...e,pageIds:[...i]}:{...e,bloomData:null},a=t.sstables.findIndex(t=>t.id===e.id);a>=0?t.sstables[a]=r:t.sstables.push(r),t.nextSstableId=Math.max(t.nextSstableId,e.id),await this.commitManifest()},deleteMeta:async e=>{const t=n();t.sstables=t.sstables.filter(t=>t.id!==e),s?.retirePageIds(e),await this.commitManifest()},deleteManyMetas:async e=>{if(0===e.length)return;const t=n(),i=new Set(e);t.sstables=t.sstables.filter(e=>!i.has(e.id));for(const t of e)s?.retirePageIds(t);await this.commitManifest()},retire:e=>{for(const t of e)s?.retirePageIds(t)}}}isPageStorage(){return!0===this.config.pageStorage||!1!==this.config.pageStorage&&("opfs"===this.config.storageBackend||"kv"===this.config.storageBackend)}applyWALRecord(e){switch(e.type){case Ee.INSERT:case Ee.UPDATE:e.data&&this.lsm.put(`${e.tableName}:${e.key}`,e.data);break;case Ee.DELETE:this.lsm.delete(`${e.tableName}:${e.key}`);break;case Ee.CREATE_TABLE:if(e.data?.schema)try{const t=JSON.parse(e.data.schema);this.schemas.has(t.name)||(this.schemas.set(t.name,t),this.tablePKs.set(t.name,this.getPK(t)))}catch{}break;case Ee.ALTER_TABLE:if(e.data?.schema)try{const t=JSON.parse(e.data.schema);this.schemas.set(t.name,t),this.tablePKs.set(t.name,this.getPK(t))}catch{}case Ee.COMMIT:case Ee.ROLLBACK:case Ee.BEGIN:}}async applyDropTableRecovery(e){if(!e)return;await this.cleanupTableIndexes(e),this.schemas.delete(e),this.tablePKs.delete(e);const t=`${e}:`,s=`${t}`,n=await this.lsm.rangeScan(t,s);for(const[e]of n)this.lsm.delete(e)}uniqueColumns(e,t){const s=[];for(const[n,i]of Object.entries(t.columns))i.unique&&this.secondaryIndexes.has(`${e}:idx:${n}`)&&s.push(n);return s}async checkUnique(e,t,s,i){for(const r of t){const t=s[r];if(null==t)continue;const a=this.secondaryIndexes.get(`${e}:idx:${r}`);if(!a)continue;const o=`${String(t)}:`,h=await a.rangeScan(o,`${o}`);for(const[,t]of h){const s=t.pk;if(void 0!==s&&s!==i)throw new n(`Unique constraint violation on column "${r}" in table "${e}"`,"UNIQUE_VIOLATION")}}}updateSecondaryIndexes(e,t,s,n){const i=this.schemas.get(e);if(i)for(const[r,a]of Object.entries(i.columns)){if(!a.index&&!a.unique)continue;const i=`${e}:idx:${r}`,o=this.secondaryIndexes.get(i);if(o){if(n){const e=n[r];null!=e&&o.delete(`${String(e)}:${t}`)}if(s){const e=s[r];null!=e&&o.put(`${String(e)}:${t}`,{pk:t})}}}}async tryIndexLookup(e,t){if(!t.where)return null;const s=this.schemas.get(e);if(!s)return null;const n=this.tablePKs.get(e),i=[],r=e=>{for(const[t,s]of Object.entries(e))if("$and"!==t)"$or"!==t&&"$not"!==t&&"$exists"!==t&&i.push([t,s]);else for(const e of s)r(e)};r(t.where);for(const[t,r]of i){const i=s.columns[t];if(!(i&&(i.index||i.unique||i.primaryKey)||t===n))continue;if(t===n){if("object"!=typeof r||null===r){const t=`${e}:${r}`,s=await this.lsm.get(t);return s?[{...s,[n]:r}]:[]}const t=r;if("$eq"in t){const s=`${e}:${t.$eq}`,i=await this.lsm.get(s);return i?[{...i,[n]:t.$eq}]:[]}if("$in"in t&&Array.isArray(t.$in)){const s=[],i=new Set;for(const r of t.$in){const t=String(r);if(i.has(t))continue;const a=await this.lsm.get(`${e}:${t}`);a&&(i.add(t),s.push({...a,[n]:t}))}return s}if("$gt"in t||"$gte"in t||"$lt"in t||"$lte"in t){const t=`${e}:`,s=await this.lsm.rangeScan(t,`${t}`),i=[];for(const[e,a]of s){const s={...a,[n]:e.slice(t.length)};k(s,{[n]:r})&&i.push(s)}return i}}const a=`${e}:idx:${t}`,o=this.secondaryIndexes.get(a);if(!o)continue;if("object"!=typeof r||null===r){if(null===r)continue;return this.indexScanToRows(e,n,o,String(r),String(r))}const h=r;if("$eq"in h){if(null===h.$eq)continue;if("object"==typeof h.$eq)continue;const t=String(h.$eq);return this.indexScanToRows(e,n,o,t,t)}if("$in"in h&&Array.isArray(h.$in)){if(h.$in.some(e=>null===e))continue;if(h.$in.some(e=>"object"==typeof e&&null!==e))continue;const t=h.$in.map(e=>String(e)),s=[],i=new Set,r=[];for(const e of t){const t=await o.rangeScan(e,`${e}`);for(const[,e]of t){const t=e.pk;t&&!i.has(t)&&(i.add(t),r.push(t))}}for(const t of r){const i=await this.lsm.get(`${e}:${t}`);i&&s.push({...i,[n]:t})}return s}if("$gt"in h||"$gte"in h||"$lt"in h||"$lte"in h)return(await this.indexScanToRows(e,n,o,"","")).filter(e=>k(e,{[t]:r}))}return null}async indexScanToRows(e,t,s,n,i){const r=i.includes("")?i:`${i}`,a=await s.rangeScan(n,r),o=[];for(const[,e]of a){const t=e.pk;t&&o.push(t)}const h=[];for(const s of o){const n=await this.lsm.get(`${e}:${s}`);n&&h.push({...n,[t]:s})}return h}tryGC(){this.gcCounter++,this.gcCounter>=10&&(this.mvcc.gc(100),this.gcCounter=0)}trimAllCaches(){this.lsm.trimCache();for(const e of this.secondaryIndexes.values())e.trimCache()}checkMemoryBudget(){const e=1024*this.config.maxMemoryMB*1024;this.lsm.getEstimatedMemory()>e&&(this.lsm.flush().catch(()=>{}),this.mvcc.gc(50))}async analyzeTable(e){this.ensureOpen(),this.ensureTable(e);const t=await this.getAllRows(e);let s=this.lsm.getStats().sstableCount,n=this.lsm.getStats().memtableSize,i=this.lsm.getStats().levelCounts.filter(e=>e>0).length;for(const[t,r]of this.secondaryIndexes){if(!t.startsWith(`${e}:idx:`))continue;const a=r.getStats();s+=a.sstableCount,n+=a.memtableSize,i=Math.max(i,a.levelCounts.filter(e=>e>0).length)}const r={table:e,rowCount:t.length,avgRowSize:t.length>0?Math.round(t.reduce((e,t)=>e+JSON.stringify(t).length,0)/t.length):0,indexDepth:i,sstableCount:s,memtableSize:n,estimatedMemory:this.lsm.getEstimatedMemory()},a=this.schemas.get(e);if(a&&t.length>0){const e={};for(const s of Object.keys(a.columns)){const n=new Set(t.map(e=>String(e[s])));e[s]={distinctValues:n.size}}r.columnStats=e}return r}async reindexTable(e){return this.ensureOpen(),this.ensureTable(e),this.reindexTableInternal(e)}async reindexTableInternal(e){const t=this.schemas.get(e);if(!t)return 0;let s=0;const n=this.tablePKs.get(e),i=Object.entries(t.columns).filter(([,e])=>e.index||e.unique);if(0===i.length)return 0;const r=await this.getAllRows(e);for(const[t]of i){const i=`${e}:idx:${t}`,a=this.secondaryIndexes.get(i);if(a){await a.clear(),s++;for(const e of r){const s=e[t];null!=s&&a.put(`${String(s)}:${e[n]}`,{pk:e[n]})}}}return s}async vacuum(){this.ensureOpen(),await this.lsm.flush();const e=await this.lsm.vacuumLevels(),t=this.mvcc.getGlobalLSN();return this.mvcc.gc(10),{compactedLevels:e,gcVersions:t}}ensureOpen(){if(!this.opened)throw new n("AriaEngine not opened","DB_NOT_OPEN")}ensureNoDDLInTransaction(e){if(this.currentTxnId)throw new n(`${e} is not supported inside a transaction (AriaEngine DDL is not transactional)`,"NOT_SUPPORTED")}ensureTable(e){if(!this.schemas.has(e))throw new n(`Table "${e}" does not exist`,"TABLE_NOT_FOUND")}}class St{constructor(e="opfs"){this.name="hybrid",this.dbName="",this.version=1,this.memoryEngine=new Q,this.diskEngineType=e,this.diskEngine=new ge}async open(e,t){this.dbName=e,this.version=t,await this.diskEngine.open(e,t),await this.memoryEngine.open(e,t),await this.reloadMemoryFromDisk()}async reloadMemoryFromDisk(){await this.memoryEngine.close(),await this.memoryEngine.open(this.dbName,this.version);const e=this.diskEngine;"function"==typeof e.reload&&await e.reload();const t=await this.diskEngine.getTableNames();for(const e of t){const t=await this.diskEngine.getTableSchema(e);if(!t)continue;await this.memoryEngine.createTable(t);const s=await this.diskEngine.find(e,{table:e});if(s.length>0)try{await this.memoryEngine.insert(e,s)}catch(e){}}}async close(){await this.memoryEngine.close(),await this.diskEngine.close()}isOpen(){return this.memoryEngine.isOpen()&&this.diskEngine.isOpen()}async repair(){"function"==typeof this.diskEngine.repair&&await this.diskEngine.repair(),await this.reloadMemoryFromDisk()}async clearAll(){if("function"==typeof this.diskEngine.clearAll)await this.diskEngine.clearAll();else{const e=await this.diskEngine.getTableNames();for(const t of e)await this.diskEngine.dropTable(t)}if("function"==typeof this.memoryEngine.clearAll)await this.memoryEngine.clearAll();else{const e=await this.memoryEngine.getTableNames();for(const t of e)await this.memoryEngine.dropTable(t)}}async getMeta(e){return"function"==typeof this.diskEngine.getMeta?this.diskEngine.getMeta(e):null}async setMeta(e,t){"function"==typeof this.diskEngine.setMeta&&await this.diskEngine.setMeta(e,t)}async createTable(e){await this.memoryEngine.createTable(e);try{await this.diskEngine.createTable(e)}catch(e){await this.recoverMemoryAfterDiskError(e)}}async dropTable(e){await this.memoryEngine.dropTable(e);try{await this.diskEngine.dropTable(e)}catch(e){await this.recoverMemoryAfterDiskError(e)}}async hasTable(e){return this.memoryEngine.hasTable(e)}async getTableNames(){return this.memoryEngine.getTableNames()}async getTableSchema(e){return this.memoryEngine.getTableSchema(e)}async alterTable(e,t,s){await this.memoryEngine.alterTable(e,t,s);try{if("function"==typeof this.diskEngine.alterTable)await this.diskEngine.alterTable(e,t,s);else{const n=await this.diskEngine.getTableSchema(e);n&&"DROP"===t&&delete n.columns[s.name]}}catch(e){await this.recoverMemoryAfterDiskError(e)}}async recoverMemoryAfterDiskError(e){try{await this.reloadMemoryFromDisk()}catch{}throw e}async validatePayload(e,t,s="insert"){return this.memoryEngine.validatePayload(e,t,s)}async insert(e,t){const s=await this.memoryEngine.insert(e,t);try{await this.diskEngine.insert(e,t)}catch(e){await this.recoverMemoryAfterDiskError(e)}return s}async find(e,t){return this.memoryEngine.find(e,t)}async findStream(e,t,s){return this.memoryEngine.findStream(e,t,s)}async update(e,t,s){const n=await this.memoryEngine.update(e,t,s);try{await this.diskEngine.update(e,t,s)}catch(e){await this.recoverMemoryAfterDiskError(e)}return n}async delete(e,t){const s=await this.memoryEngine.delete(e,t);try{await this.diskEngine.delete(e,t)}catch(e){await this.recoverMemoryAfterDiskError(e)}return s}async count(e,t){return this.memoryEngine.count(e,t)}async clear(e){await this.memoryEngine.clear(e);try{await this.diskEngine.clear(e)}catch(e){await this.recoverMemoryAfterDiskError(e)}}async createIndex(e,t,s){await this.memoryEngine.createIndex(e,t,s);try{"function"==typeof this.diskEngine.createIndex&&await this.diskEngine.createIndex(e,t,s)}catch(e){await this.recoverMemoryAfterDiskError(e)}}async dropIndex(e,t,s){await this.memoryEngine.dropIndex(e,t,s);try{"function"==typeof this.diskEngine.dropIndex&&await this.diskEngine.dropIndex(e,t,s)}catch(e){await this.recoverMemoryAfterDiskError(e)}}async beginTransaction(){await this.memoryEngine.beginTransaction();try{await this.diskEngine.beginTransaction()}catch(e){throw await this.memoryEngine.rollbackTransaction(),e}}async commitTransaction(){await this.diskEngine.commitTransaction();try{await this.memoryEngine.commitTransaction()}catch(e){throw new n("Hybrid commit failed: memory engine error after disk commit (disk data is committed)","TX_COMMIT_ERROR",e)}}async rollbackTransaction(){await this.memoryEngine.rollbackTransaction(),await this.diskEngine.rollbackTransaction()}getDiskEngineType(){return this.diskEngineType}getMemoryEngine(){return this.memoryEngine}}class kt{constructor(e,t,s=["*"]){this.tableName=e,this._columns=s,this._where={},this._orderBy=[],this._joins=[],this._executor=t}as(e){return this._alias=e,this}innerJoin(e,t,s){return this._addJoin("INNER",e,t,s)}leftJoin(e,t,s){return this._addJoin("LEFT",e,t,s)}rightJoin(e,t,s){return this._addJoin("RIGHT",e,t,s)}crossJoin(e,t){return this._addJoin("CROSS",e,{},t)}join(e,t,s){return this._addJoin("INNER",e,t,s)}_addJoin(e,t,s,n){return this._joins.push({type:e,table:t,on:s,alias:n}),this}where(e){return this._where={...this._where,...e},this}orderBy(e,t="asc"){return this._orderBy.push({column:e,direction:t}),this}limit(e){return this._limit=e,this}offset(e){return this._offset=e,this}async execute(){return this._executor.execute(this.toAST())}toAST(){return{type:"SELECT",columns:this._columns,from:this.tableName,alias:this._alias,joins:this._joins.length>0?[...this._joins]:void 0,where:this._where,orderBy:this._orderBy.length>0?this._orderBy:void 0,limit:this._limit,offset:this._offset}}}class At{constructor(e,t,s,n){this.tableName=e,this._updates=t,this.executor=s,this.hooks=n,this._where={}}where(e){return this._where={...this._where,...e},this}async execute(){const e=this.toAST();await(this.hooks?.before?.(e));const t=await this.executor.execute(e);return await(this.hooks?.after?.(t,e)),t}toAST(){return{type:"UPDATE",table:this.tableName,sets:this._updates,where:this._where}}}class xt{constructor(e,t,s){this.tableName=e,this.executor=t,this.hooks=s,this._where={}}where(e){return this._where={...this._where,...e},this}async execute(){const e=this.toAST();await(this.hooks?.before?.(e));const t=await this.executor.execute(e);return await(this.hooks?.after?.(t,e)),t}toAST(){return{type:"DELETE",from:this.tableName,where:this._where}}}class It{constructor(e,t,s,n,i){this.schema=null,this.engine=e,this.name=t,this.executor=s,this.onWrite=n,this.onHooks=i}async getSchema(){if(!this.schema){const e=await this.engine.getTableSchema(this.name);if(!e)throw new n(`Table "${this.name}" does not exist`,"TABLE_NOT_FOUND");this.schema=e}return this.schema}async insert(e){await(this.onHooks?.("beforeInsert",[[e]]));const t=await this.engine.insert(this.name,[e]);return this.onWrite?.(this.name),await(this.onHooks?.("afterInsert",[[e],t])),t[0]}async insertMany(e){await(this.onHooks?.("beforeInsert",[e]));const t=await this.engine.insert(this.name,e);return this.onWrite?.(this.name),await(this.onHooks?.("afterInsert",[e,t])),t}select(e=["*"]){return new kt(this.name,this.requireExecutor("select"),e)}requireExecutor(e){if(!this.executor)throw new n(`Table.${e}() requires a query executor (obtain the table via db.table())`,"NOT_SUPPORTED");return this.executor}async stream(e,t={}){if("function"!=typeof this.engine.findStream){const s=await this.engine.find(this.name,{table:this.name,where:t.where,limit:t.limit,offset:t.offset,columns:t.columns});for(const t of s)e(t);return s.length}return this.engine.findStream(this.name,{table:this.name,where:t.where,limit:t.limit,offset:t.offset,columns:t.columns},e)}update(e){return new At(this.name,e,this.requireExecutor("update"),{before:async t=>{await(this.onHooks?.("beforeUpdate",[{table:t.table,where:t.where},e]))},after:async(t,s)=>{this.onWrite?.(this.name),await(this.onHooks?.("afterUpdate",[{table:s.table,where:s.where},e,t]))}})}delete(){return new xt(this.name,this.requireExecutor("delete"),{before:async e=>{await(this.onHooks?.("beforeDelete",[{table:e.from,where:e.where}]))},after:async(e,t)=>{this.onWrite?.(this.name),await(this.onHooks?.("afterDelete",[{table:t.from,where:t.where},e]))}})}async count(e){return this.engine.count(this.name,e?{table:this.name,where:e}:void 0)}async clear(){await this.engine.clear(this.name),this.onWrite?.(this.name)}async drop(){await this.engine.dropTable(this.name),this.onWrite?.(this.name)}}function Rt(e){switch(e.type){case"SELECT":return function(e){return{table:e.from,columns:e.columns,where:e.where,orderBy:e.orderBy?.length?e.orderBy:void 0,limit:e.limit,offset:e.offset}}(e);case"DELETE":return function(e){return{table:e.from,where:e.where}}(e);case"UPDATE":return function(e){return{table:e.table,where:e.where}}(e);default:throw new n(`Cannot compile statement type "${e.type}" to QueryPlan`,"COMPILE_ERROR")}}var Ot;!function(e){e.SELECT="SELECT",e.FROM="FROM",e.WHERE="WHERE",e.INSERT="INSERT",e.INTO="INTO",e.VALUES="VALUES",e.UPDATE="UPDATE",e.SET="SET",e.DELETE="DELETE",e.CREATE="CREATE",e.TABLE="TABLE",e.DROP="DROP",e.ORDER="ORDER",e.BY="BY",e.ASC="ASC",e.DESC="DESC",e.LIMIT="LIMIT",e.OFFSET="OFFSET",e.AND="AND",e.OR="OR",e.NOT="NOT",e.LIKE="LIKE",e.IN="IN",e.PRIMARY="PRIMARY",e.KEY="KEY",e.UNIQUE="UNIQUE",e.DEFAULT="DEFAULT",e.NULL="NULL",e.TRUE="TRUE",e.REFERENCES="REFERENCES",e.CASCADE="CASCADE",e.BETWEEN="BETWEEN",e.IF="IF",e.EXISTS="EXISTS",e.FALSE="FALSE",e.ALTER="ALTER",e.ADD="ADD",e.TRUNCATE="TRUNCATE",e.INNER="INNER",e.LEFT="LEFT",e.RIGHT="RIGHT",e.CROSS="CROSS",e.JOIN="JOIN",e.ON="ON",e.AS="AS",e.OUTER="OUTER",e.GROUP="GROUP",e.HAVING="HAVING",e.COUNT="COUNT",e.SUM="SUM",e.AVG="AVG",e.MIN="MIN",e.MAX="MAX",e.DISTINCT="DISTINCT",e.BEGIN="BEGIN",e.COMMIT="COMMIT",e.ROLLBACK="ROLLBACK",e.UNION="UNION",e.ALL="ALL",e.INDEX="INDEX",e.CASE="CASE",e.WHEN="WHEN",e.THEN="THEN",e.ELSE="ELSE",e.END="END",e.EXPLAIN="EXPLAIN",e.ANALYZE="ANALYZE",e.REINDEX="REINDEX",e.VACUUM="VACUUM",e.SAVEPOINT="SAVEPOINT",e.RELEASE="RELEASE",e.TO="TO",e.IDENTIFIER="IDENTIFIER",e.QUOTED_IDENTIFIER="QUOTED_IDENTIFIER",e.STRING="STRING",e.NUMBER="NUMBER",e.COMMA="COMMA",e.LPAREN="LPAREN",e.RPAREN="RPAREN",e.SEMICOLON="SEMICOLON",e.EQ="EQ",e.NEQ="NEQ",e.GT="GT",e.GTE="GTE",e.LT="LT",e.LTE="LTE",e.STAR="STAR",e.DOT="DOT",e.EOF="EOF",e.ILLEGAL="ILLEGAL"}(Ot||(Ot={}));const Ct={SELECT:Ot.SELECT,FROM:Ot.FROM,WHERE:Ot.WHERE,INSERT:Ot.INSERT,INTO:Ot.INTO,VALUES:Ot.VALUES,UPDATE:Ot.UPDATE,SET:Ot.SET,DELETE:Ot.DELETE,CREATE:Ot.CREATE,TABLE:Ot.TABLE,DROP:Ot.DROP,ORDER:Ot.ORDER,BY:Ot.BY,ASC:Ot.ASC,DESC:Ot.DESC,LIMIT:Ot.LIMIT,OFFSET:Ot.OFFSET,AND:Ot.AND,OR:Ot.OR,NOT:Ot.NOT,LIKE:Ot.LIKE,IN:Ot.IN,PRIMARY:Ot.PRIMARY,KEY:Ot.KEY,UNIQUE:Ot.UNIQUE,DEFAULT:Ot.DEFAULT,NULL:Ot.NULL,TRUE:Ot.TRUE,FALSE:Ot.FALSE,REFERENCES:Ot.REFERENCES,CASCADE:Ot.CASCADE,BETWEEN:Ot.BETWEEN,IF:Ot.IF,EXISTS:Ot.EXISTS,ALTER:Ot.ALTER,ADD:Ot.ADD,TRUNCATE:Ot.TRUNCATE,INNER:Ot.INNER,LEFT:Ot.LEFT,RIGHT:Ot.RIGHT,CROSS:Ot.CROSS,JOIN:Ot.JOIN,ON:Ot.ON,AS:Ot.AS,OUTER:Ot.OUTER,GROUP:Ot.GROUP,HAVING:Ot.HAVING,COUNT:Ot.COUNT,SUM:Ot.SUM,AVG:Ot.AVG,MIN:Ot.MIN,MAX:Ot.MAX,DISTINCT:Ot.DISTINCT,BEGIN:Ot.BEGIN,COMMIT:Ot.COMMIT,ROLLBACK:Ot.ROLLBACK,UNION:Ot.UNION,ALL:Ot.ALL,INDEX:Ot.INDEX,CASE:Ot.CASE,WHEN:Ot.WHEN,THEN:Ot.THEN,ELSE:Ot.ELSE,END:Ot.END,EXPLAIN:Ot.EXPLAIN,ANALYZE:Ot.ANALYZE,REINDEX:Ot.REINDEX,VACUUM:Ot.VACUUM,SAVEPOINT:Ot.SAVEPOINT,RELEASE:Ot.RELEASE,TO:Ot.TO};class Nt{constructor(e){this.position=0,this.readPosition=0,this.ch="",this.input=e,this.readChar()}nextToken(){this.skipWhitespaceAndComments();const e=this.position;let t;switch(this.ch){case",":t=this.makeToken(Ot.COMMA,",",e);break;case"(":t=this.makeToken(Ot.LPAREN,"(",e);break;case")":t=this.makeToken(Ot.RPAREN,")",e);break;case";":t=this.makeToken(Ot.SEMICOLON,";");break;case"*":t=this.makeToken(Ot.STAR,"*",e);break;case".":t=this.makeToken(Ot.DOT,".",e);break;case"=":t=this.makeToken(Ot.EQ,"=",e);break;case"!":"="===this.peekChar()?(this.readChar(),t=this.makeToken(Ot.NEQ,"!=",e)):t=this.makeToken(Ot.ILLEGAL,"!",e);break;case">":"="===this.peekChar()?(this.readChar(),t=this.makeToken(Ot.GTE,">=",e)):t=this.makeToken(Ot.GT,">",e);break;case"<":"="===this.peekChar()?(this.readChar(),t=this.makeToken(Ot.LTE,"<=",e)):">"===this.peekChar()?(this.readChar(),t=this.makeToken(Ot.NEQ,"<>",e)):t=this.makeToken(Ot.LT,"<",e);break;case"'":t=this.readString();break;case'"':t=this.readQuotedIdentifier();break;case"":t={type:Ot.EOF,value:"",position:this.position};break;default:if(this.isLetter(this.ch)){const s=this.readIdentifier();return t={type:Ct[s.toUpperCase()]??Ot.IDENTIFIER,value:s,position:e},t}if(this.isDigit(this.ch)||"-"===this.ch&&this.isDigit(this.peekChar())){const s=this.readNumber();return t={type:Ot.NUMBER,value:s,position:e},t}t=this.makeToken(Ot.ILLEGAL,this.ch,e)}return this.readChar(),t}readChar(){this.readPosition>=this.input.length?this.ch="":this.ch=this.input[this.readPosition],this.position=this.readPosition,this.readPosition++}peekChar(){return this.readPosition>=this.input.length?"":this.input[this.readPosition]}skipWhitespaceAndComments(){for(;;){for(;" "===this.ch||"\t"===this.ch||"\n"===this.ch||"\r"===this.ch;)this.readChar();if("-"!==this.ch||"-"!==this.peekChar()){if("/"!==this.ch||"*"!==this.peekChar())return;this.skipBlockComment()}else this.skipLineComment()}}skipLineComment(){for(;"\n"!==this.ch&&"\r"!==this.ch&&""!==this.ch;)this.readChar()}skipBlockComment(){const e=this.position;for(this.readChar(),this.readChar();""!==this.ch&&("*"!==this.ch||"/"!==this.peekChar());)this.readChar();if(""===this.ch)throw new n(`Unterminated block comment at position ${e}`,"PARSE_ERROR");this.readChar(),this.readChar()}readIdentifier(){const e=this.position;for(;this.isLetter(this.ch)||this.isDigit(this.ch)||"_"===this.ch;)this.readChar();return this.input.slice(e,this.position)}readNumber(){const e=this.position;for("-"===this.ch&&this.readChar();this.isDigit(this.ch);)this.readChar();if("."===this.ch&&this.isDigit(this.peekChar()))for(this.readChar();this.isDigit(this.ch);)this.readChar();return this.input.slice(e,this.position)}readString(){const e=this.position,t=this.position+1;this.readChar();let s="";for(;""!==this.ch;){if("'"===this.ch){if("'"===this.peekChar()){s+="'",this.readChar(),this.readChar();continue}break}s+=this.ch,this.readChar()}if(""===this.ch)throw new n(`Unterminated string literal at position ${t}`,"PARSE_ERROR");return{type:Ot.STRING,value:s,position:e}}readQuotedIdentifier(){const e=this.position;this.readChar();let t="";for(;""!==this.ch;){if('"'===this.ch){if('"'===this.peekChar()){t+='"',this.readChar(),this.readChar();continue}break}t+=this.ch,this.readChar()}if(""===this.ch)throw new n(`Unterminated quoted identifier at position ${e}`,"PARSE_ERROR");if(0===t.length)throw new n(`Empty quoted identifier at position ${e}`,"PARSE_ERROR");return{type:Ot.QUOTED_IDENTIFIER,value:t,position:e}}isLetter(e){return/[a-zA-Z_]/.test(e)}isDigit(e){return/[0-9]/.test(e)}makeToken(e,t,s=this.position){return{type:e,value:t,position:s}}}function Lt(e){const t=new Nt(e),s=[];let n=t.nextToken();for(;n.type!==Ot.EOF;)s.push(n),n=t.nextToken();return s.push(n),s}class $t{constructor(e){this.sql=e,this.lexer=new Nt(e),this.nextToken(),this.nextToken()}parseStatement(){switch(this.curToken.type){case Ot.SELECT:return this.parseSelect();case Ot.INSERT:return this.parseInsert();case Ot.UPDATE:return this.parseUpdate();case Ot.DELETE:return this.parseDelete();case Ot.CREATE:return this.parseCreateStatement();case Ot.DROP:return this.parseDropStatement();case Ot.ALTER:return this.parseAlterTable();case Ot.TRUNCATE:return this.parseTruncateTable();case Ot.BEGIN:return this.parseBegin();case Ot.COMMIT:return this.parseCommit();case Ot.ROLLBACK:return this.parseRollback();case Ot.EXPLAIN:return this.parseExplain();case Ot.ANALYZE:return this.parseAnalyze();case Ot.REINDEX:return this.parseReindex();case Ot.VACUUM:return this.parseVacuum();case Ot.SAVEPOINT:case Ot.RELEASE:return this.parseSavepoint();default:throw this.error(`Unexpected token "${this.curToken.value}"`)}}parseAllStatements(){const e=[];for(;!this.curTokenIs(Ot.EOF);){for(;this.curTokenIs(Ot.SEMICOLON);)this.nextToken();if(this.curTokenIs(Ot.EOF))break;if(e.push(this.parseStatement()),this.curTokenIs(Ot.SEMICOLON))this.nextToken();else if(!this.curTokenIs(Ot.EOF))throw this.error(`Expected ';' after statement, got "${this.curToken.value}"`)}return e}parseExplain(){if(this.expect(Ot.EXPLAIN),this.curTokenIs(Ot.EXPLAIN))throw this.error("Nested EXPLAIN is not allowed");return{type:"EXPLAIN",query:this.parseStatement()}}parseAnalyze(){return this.expect(Ot.ANALYZE),this._isKeywordAsIdent()&&"TABLE"===this.curToken.value.toUpperCase()&&this.nextToken(),{type:"ANALYZE",table:this.expectIdentifier("table name")}}parseReindex(){return this.expect(Ot.REINDEX),this._isKeywordAsIdent()&&"TABLE"===this.curToken.value.toUpperCase()&&this.nextToken(),{type:"REINDEX",table:this.expectIdentifier("table name")}}parseVacuum(){return this.expect(Ot.VACUUM),{type:"VACUUM"}}parseSavepoint(){let e;return this.curTokenIs(Ot.RELEASE)?(e="RELEASE",this.nextToken()):(e="SAVE",this.expect(Ot.SAVEPOINT)),this.curTokenIs(Ot.SAVEPOINT)&&this.nextToken(),{type:"SAVEPOINT",name:this.expectIdentifier("savepoint name"),action:e}}parseBegin(){return this.expect(Ot.BEGIN),this._isKeywordAsIdent()&&"TRANSACTION"===this.curToken.value.toUpperCase()&&this.nextToken(),{type:"BEGIN"}}parseCommit(){return this.expect(Ot.COMMIT),this._isKeywordAsIdent()&&"TRANSACTION"===this.curToken.value.toUpperCase()&&this.nextToken(),{type:"COMMIT"}}parseRollback(){return this.expect(Ot.ROLLBACK),this._isKeywordAsIdent()&&"TRANSACTION"===this.curToken.value.toUpperCase()?(this.nextToken(),{type:"ROLLBACK"}):this.curTokenIs(Ot.TO)||this._isKeywordAsIdent()&&"TO"===this.curToken.value.toUpperCase()?(this.nextToken(),(this.curTokenIs(Ot.SAVEPOINT)||this._isKeywordAsIdent()&&"SAVEPOINT"===this.curToken.value.toUpperCase())&&this.nextToken(),{type:"SAVEPOINT",name:this.expectIdentifier("savepoint name"),action:"ROLLBACK"}):{type:"ROLLBACK"}}parseCreateStatement(){if(this.expect(Ot.CREATE),this.curTokenIs(Ot.TABLE))return this.parseCreateTable();if(this.curTokenIs(Ot.INDEX)||this._isKeywordAsIdent()&&"INDEX"===this.curToken.value.toUpperCase())return this.parseCreateIndex();if(this.curTokenIs(Ot.UNIQUE)&&(this.nextToken(),this.curTokenIs(Ot.INDEX)||this._isKeywordAsIdent()&&"INDEX"===this.curToken.value.toUpperCase())){const e=this.parseCreateIndex();return e.unique=!0,e}throw this.error(`Expected TABLE or INDEX after CREATE, got "${this.curToken.value}"`)}parseCreateIndex(){this.expect(Ot.INDEX);const e=this.expectIdentifier("index name");this.expect(Ot.ON);const t=this.expectIdentifier("table name");this.expect(Ot.LPAREN);const s=this.expectIdentifier("column name");return this.expect(Ot.RPAREN),{type:"CREATE_INDEX",name:e,table:t,column:s}}parseDropStatement(){if(this.expect(Ot.DROP),this.curTokenIs(Ot.TABLE))return this.parseDropTable();if(this.curTokenIs(Ot.INDEX)||this._isKeywordAsIdent()&&"INDEX"===this.curToken.value.toUpperCase())return this.parseDropIndex();throw this.error(`Expected TABLE or INDEX after DROP, got "${this.curToken.value}"`)}parseDropIndex(){this.expect(Ot.INDEX);const e=this.expectIdentifier("index name");let t="",s="";return this.curTokenIs(Ot.ON)&&(this.nextToken(),t=this.expectIdentifier("table name"),this.curTokenIs(Ot.LPAREN)&&(this.nextToken(),s=this.expectIdentifier("column name"),this.expect(Ot.RPAREN))),{type:"DROP_INDEX",name:e,table:t,column:s}}parseSelect(){this.expect(Ot.SELECT);let e=!1;this.curTokenIs(Ot.DISTINCT)&&(e=!0,this.nextToken());const t=[];if(this.curTokenIs(Ot.STAR))for(t.push("*"),this.nextToken();this.curTokenIs(Ot.COMMA);)this.nextToken(),t.push(this.parseColumnWithAlias());else t.push(...this.parseColumnList());let s,n,i="";this.curTokenIs(Ot.FROM)&&(this.nextToken(),this.curTokenIs(Ot.LPAREN)?(this.nextToken(),s=this.parseSelect(),this.expect(Ot.RPAREN),this.curTokenIs(Ot.AS)?(this.nextToken(),n=this.expectIdentifier("alias")):this.curToken.type!==Ot.IDENTIFIER||this._isReservedAfterFrom()||(n=this.curToken.value,this.nextToken())):(i=this.expectIdentifier("table name"),this.curTokenIs(Ot.AS)?(this.nextToken(),n=this.expectIdentifier("alias")):this.curToken.type!==Ot.IDENTIFIER||this._isReservedAfterFrom()||(n=this.curToken.value,this.nextToken())));const r={type:"SELECT",columns:t,distinct:e||void 0,from:i,alias:n,where:{}};s&&(r.fromSubquery=s);const a=this.parseJoinClauses();return a.length>0&&(r.joins=a),this.curTokenIs(Ot.WHERE)&&(this.nextToken(),r.where=this.parseCondition()),this.curTokenIs(Ot.GROUP)&&(this.nextToken(),this.expect(Ot.BY),r.groupBy=this.parseGroupByList()),this.curTokenIs(Ot.HAVING)&&(this.nextToken(),r.having=this.parseCondition()),this.curTokenIs(Ot.ORDER)&&(this.nextToken(),this.expect(Ot.BY),r.orderBy=this.parseOrderByList()),this.curTokenIs(Ot.LIMIT)&&(this.nextToken(),r.limit=this.expectNumber("LIMIT value")),this.curTokenIs(Ot.OFFSET)&&(this.nextToken(),r.offset=this.expectNumber("OFFSET value")),this.curTokenIs(Ot.UNION)?this.parseUnion(r):r}parseUnion(e){this.expect(Ot.UNION);let t=!1;this.curTokenIs(Ot.ALL)&&(t=!0,this.nextToken());const s=this.parseSelect(),n={type:"SELECT_UNION",left:e,right:s,all:t||void 0};return this.adoptTrailingClauses(n,s),this.curTokenIs(Ot.UNION)?this.parseUnionChain(n):n}parseUnionChain(e){this.expect(Ot.UNION);let t=!1;this.curTokenIs(Ot.ALL)&&(t=!0,this.nextToken());const s=this.parseSelect(),n={type:"SELECT_UNION",left:e,right:s,all:t||void 0};return this.adoptTrailingClauses(n,s),this.curTokenIs(Ot.UNION)?this.parseUnionChain(n):n}adoptTrailingClauses(e,t){"SELECT"===t.type&&(t.orderBy&&(e.orderBy=t.orderBy,delete t.orderBy),void 0!==t.limit&&(e.limit=t.limit,delete t.limit),void 0!==t.offset&&(e.offset=t.offset,delete t.offset))}parseJoinClauses(){const e=[];for(;this._isJoinKeyword();)e.push(this.parseJoinClause());return e}_isJoinKeyword(){return this.curTokenIs(Ot.INNER)||this.curTokenIs(Ot.LEFT)||this.curTokenIs(Ot.RIGHT)||this.curTokenIs(Ot.CROSS)||this.curTokenIs(Ot.JOIN)}parseJoinClause(){let e="INNER";this.curTokenIs(Ot.INNER)?(e="INNER",this.nextToken()):this.curTokenIs(Ot.LEFT)?(e="LEFT",this.nextToken(),this.curTokenIs(Ot.OUTER)&&this.nextToken()):this.curTokenIs(Ot.RIGHT)?(e="RIGHT",this.nextToken(),this.curTokenIs(Ot.OUTER)&&this.nextToken()):this.curTokenIs(Ot.CROSS)&&(e="CROSS",this.nextToken()),this.expect(Ot.JOIN);const t=this.expectIdentifier("table name");let s;this.curTokenIs(Ot.AS)?(this.nextToken(),s=this.expectIdentifier("alias")):this.curToken.type!==Ot.IDENTIFIER||this._isJoinReserved()||(s=this.curToken.value,this.nextToken());let n={};return"CROSS"!==e&&this.curTokenIs(Ot.ON)&&(this.nextToken(),n=this.parseCondition()),{type:e,table:t,alias:s,on:n}}_isReservedAfterFrom(){return this.curTokenIs(Ot.WHERE)||this.curTokenIs(Ot.ORDER)||this.curTokenIs(Ot.LIMIT)||this.curTokenIs(Ot.OFFSET)||this.curTokenIs(Ot.GROUP)||this._isJoinKeyword()}_isJoinReserved(){return this.curTokenIs(Ot.ON)||this.curTokenIs(Ot.WHERE)||this.curTokenIs(Ot.ORDER)||this.curTokenIs(Ot.LIMIT)||this._isJoinKeyword()}parseInsert(){this.expect(Ot.INSERT),this.expect(Ot.INTO);const e=this.expectIdentifier("table name");let t;if(this.curTokenIs(Ot.LPAREN)&&(this.nextToken(),t=this.parseIdentifierList(),this.expect(Ot.RPAREN)),this.curTokenIs(Ot.SELECT))return{type:"INSERT",into:e,columns:t,select:this.parseSelect()};this.expect(Ot.VALUES);const s=[];do{this.curTokenIs(Ot.COMMA)&&this.nextToken(),this.expect(Ot.LPAREN);const e=this.parseValueList();this.expect(Ot.RPAREN),s.push(e)}while(this.curTokenIs(Ot.COMMA));if(t)for(let e=0;e<s.length;e++)if(s[e].length!==t.length)throw this.error(`INSERT column/value count mismatch: ${t.length} column(s) but row ${e+1} has ${s[e].length} value(s)`);return{type:"INSERT",into:e,columns:t,values:s}}newColumnMap(){return Object.create(null)}parseUpdate(){this.expect(Ot.UPDATE);const e=this.expectIdentifier("table name");this.expect(Ot.SET);const t=this.newColumnMap();do{this.curTokenIs(Ot.COMMA)&&this.nextToken();const e=this.expectIdentifier("column name");this.expect(Ot.EQ),t[e]=this.parseValue()}while(this.curTokenIs(Ot.COMMA));let s=this.newColumnMap();return this.curTokenIs(Ot.WHERE)&&(this.nextToken(),s=this.parseCondition()),{type:"UPDATE",table:e,sets:t,where:s}}parseDelete(){this.expect(Ot.DELETE),this.expect(Ot.FROM);const e=this.expectIdentifier("table name");let t=this.newColumnMap();return this.curTokenIs(Ot.WHERE)&&(this.nextToken(),t=this.parseCondition()),{type:"DELETE",from:e,where:t}}parseCreateTable(){this.expect(Ot.TABLE);let e=!1;this.curTokenIs(Ot.IF)&&(this.nextToken(),this.expect(Ot.NOT),this.expect(Ot.EXISTS),e=!0);const t=this.expectIdentifier("table name");this.expect(Ot.LPAREN);const s=[];do{this.curTokenIs(Ot.COMMA)&&this.nextToken(),s.push(this.parseColumnDef())}while(this.curTokenIs(Ot.COMMA));return this.expect(Ot.RPAREN),{type:"CREATE_TABLE",name:t,columns:s,ifNotExists:e||void 0}}parseColumnDef(){const e={name:this.expectIdentifier("column name"),type:this.expectIdentifier("column type").toLowerCase()};for(;this.curTokenIs(Ot.PRIMARY)||this.curTokenIs(Ot.UNIQUE)||this.curTokenIs(Ot.NOT)||this.curTokenIs(Ot.DEFAULT)||this.curTokenIs(Ot.REFERENCES);)if(this.curTokenIs(Ot.PRIMARY))this.nextToken(),this.expect(Ot.KEY),e.primaryKey=!0;else if(this.curTokenIs(Ot.UNIQUE))this.nextToken(),e.unique=!0;else if(this.curTokenIs(Ot.NOT))this.nextToken(),this.expect(Ot.NULL),e.required=!0;else if(this.curTokenIs(Ot.DEFAULT))this.nextToken(),e.default=this.parseValue();else{if(!this.curTokenIs(Ot.REFERENCES))break;{this.nextToken();const t=this.expectIdentifier("referenced table");this.expect(Ot.LPAREN);const s=this.expectIdentifier("referenced column");for(this.expect(Ot.RPAREN),e.references=`${t}.${s}`;this.curTokenIs(Ot.ON);)if(this.nextToken(),this.curTokenIs(Ot.DELETE))this.nextToken(),e.onDelete=this.parseCascadeAction();else{if(!this.curTokenIs(Ot.UPDATE))break;this.nextToken(),e.onUpdate=this.parseCascadeAction()}}}return e}parseCascadeAction(){return this.curTokenIs(Ot.CASCADE)?(this.nextToken(),"CASCADE"):this.curTokenIs(Ot.SET)?(this.nextToken(),this.expect(Ot.NULL),"SET NULL"):this.curToken.type===Ot.IDENTIFIER&&"RESTRICT"===this.curToken.value.toUpperCase()?(this.nextToken(),"RESTRICT"):"RESTRICT"}parseAlterTable(){this.expect(Ot.ALTER),this.expect(Ot.TABLE);const e=this.expectIdentifier("table name");let t;if(this.curTokenIs(Ot.ADD))return t="ADD",this.nextToken(),this.curToken.type===Ot.IDENTIFIER&&"COLUMN"===this.curToken.value.toUpperCase()&&this.nextToken(),{type:"ALTER_TABLE",name:e,action:t,column:this.parseColumnDef()};if(this.curTokenIs(Ot.DROP)||this._isKeywordAsIdent()&&"DROP"===this.curToken.value.toUpperCase())return t="DROP",this.nextToken(),this.curToken.type===Ot.IDENTIFIER&&"COLUMN"===this.curToken.value.toUpperCase()&&this.nextToken(),{type:"ALTER_TABLE",name:e,action:t,column:{name:this.expectIdentifier("column name"),type:"string"}};throw this.error("Expected ADD or DROP in ALTER TABLE")}parseTruncateTable(){return this.expect(Ot.TRUNCATE),this.expect(Ot.TABLE),{type:"TRUNCATE_TABLE",name:this.expectIdentifier("table name")}}parseDropTable(){this.expect(Ot.TABLE);let e=!1;return this.curTokenIs(Ot.IF)&&(this.nextToken(),this.expect(Ot.EXISTS),e=!0),{type:"DROP_TABLE",name:this.expectIdentifier("table name"),ifExists:e||void 0}}parseCondition(){return this.parseOrExpression()}parseOrExpression(){const e=[this.parseAndExpression()];for(;this.curTokenIs(Ot.OR);)this.nextToken(),e.push(this.parseAndExpression());return 1===e.length?e[0]:{$or:e}}parseAndExpression(){const e=[this.parseSimpleCondition()];for(;this.curTokenIs(Ot.AND);)this.nextToken(),e.push(this.parseSimpleCondition());return 1===e.length?e[0]:{$and:e}}parseWhere(){return this.parseCondition()}parseSimpleCondition(){if(this.curTokenIs(Ot.EXISTS)||this._isKeywordAsIdent()&&"EXISTS"===this.curToken.value.toUpperCase())return this.nextToken(),this.parseExistsCondition(!1);if(this.curTokenIs(Ot.NOT)&&this._peekIsExists())return this.nextToken(),this.nextToken(),this.parseExistsCondition(!0);if(this.curTokenIs(Ot.NOT)&&!this._isNotInOrLike())return this.nextToken(),{$not:this.parseSimpleCondition()};if(this.curTokenIs(Ot.LPAREN)){this.nextToken();const e=this.parseCondition();return this.expect(Ot.RPAREN),e}const e=this.parseColumnRef();if(this.curTokenIs(Ot.IDENTIFIER)&&"IS"===this.curToken.value.toUpperCase()){this.nextToken();const t=this.curTokenIs(Ot.NOT);t&&this.nextToken(),this.expect(Ot.NULL);const s=this.newColumnMap();return s[e]=t?{$isNotNull:!0}:{$isNull:!0},s}if(this.curTokenIs(Ot.BETWEEN)){this.nextToken();const t=this.parseValue();this.expect(Ot.AND);const s=this.parseValue(),n=this.newColumnMap();return n[e]={$gte:t,$lte:s},n}if(this.curTokenIs(Ot.NOT)&&this.peekTokenIs(Ot.BETWEEN)){this.nextToken(),this.nextToken();const t=this.parseValue();this.expect(Ot.AND);const s=this.parseValue(),n=this.newColumnMap();return n[e]={$or:[{$lt:t},{$gt:s}]},n}if(this.curTokenIs(Ot.NOT)){if(this.peekTokenIs(Ot.IN)){if(this.nextToken(),this.nextToken(),this.expect(Ot.LPAREN),this.curTokenIs(Ot.SELECT)){const t=this.parseSelect();this.expect(Ot.RPAREN);const s=this.newColumnMap();return s[e]={$nin:{$subquery:t}},s}const t=this.parseValueList();this.expect(Ot.RPAREN);const s=this.newColumnMap();return s[e]={$nin:t},s}if(this.peekTokenIs(Ot.LIKE)){this.nextToken(),this.nextToken();const t=this.parseValue(),s=this.newColumnMap();return s[e]={$not:{$like:t}},s}}if(this.curTokenIs(Ot.LIKE)){this.nextToken();const t=this.parseValue(),s=this.newColumnMap();return s[e]={$like:t},s}if(this.curTokenIs(Ot.IN)){if(this.nextToken(),this.expect(Ot.LPAREN),this.curTokenIs(Ot.SELECT)){const t=this.parseSelect();this.expect(Ot.RPAREN);const s=this.newColumnMap();return s[e]={$in:{$subquery:t}},s}const t=this.parseValueList();this.expect(Ot.RPAREN);const s=this.newColumnMap();return s[e]={$in:t},s}if(this.curTokenIs(Ot.AND)||this.curTokenIs(Ot.OR)||this.curTokenIs(Ot.RPAREN)||this.curTokenIs(Ot.EOF)||this.curToken.type===Ot.IDENTIFIER&&["THEN","END","ELSE","NULLS","LIMIT","OFFSET","ORDER","GROUP","HAVING","UNION","WHERE"].includes(this.curToken.value.toUpperCase())){const t=this.newColumnMap();return t[e]={$eq:!0},t}const t=this.parseComparisonOp();if(this.curTokenIs(Ot.LPAREN)&&this.peekTokenIs(Ot.SELECT)){this.nextToken();const s=this.parseSelect();this.expect(Ot.RPAREN);const n=this.newColumnMap();return n[e]={[t]:{$subquery:s}},n}let s;s=this.curToken.type===Ot.QUOTED_IDENTIFIER?{$col:this.expectColumnReference()}:this.curToken.type!==Ot.IDENTIFIER||this._isReservedKeywordToken()?this.parseValue():{$col:this.expectColumnReference()};const n=this.newColumnMap();return n[e]={[t]:s},n}_isReservedKeywordToken(){return this.curToken.type!==Ot.IDENTIFIER&&this._isKeywordAsIdent()}parseExistsCondition(e){this.expect(Ot.LPAREN);const t=this.parseSelect();return this.expect(Ot.RPAREN),{$exists:{$subquery:t,$negate:e||void 0}}}_peekIsExists(){return this.peekToken.type===Ot.EXISTS||this.peekToken.type===Ot.IDENTIFIER&&"EXISTS"===this.peekToken.value.toUpperCase()}_isNotInOrLike(){return this.peekTokenIs(Ot.IN)||this.peekTokenIs(Ot.LIKE)}peekTokenIs(e){return this.peekToken.type===e}expectColumnReference(){const e=this.expectIdentifier("column reference");return this.curTokenIs(Ot.DOT)?(this.nextToken(),`${e}.${this.expectIdentifier('column name after "."')}`):e}parseComparisonOp(){switch(this.curToken.type){case Ot.EQ:return this.nextToken(),"$eq";case Ot.NEQ:return this.nextToken(),"$ne";case Ot.GT:return this.nextToken(),"$gt";case Ot.GTE:return this.nextToken(),"$gte";case Ot.LT:return this.nextToken(),"$lt";case Ot.LTE:return this.nextToken(),"$lte";default:throw this.error(`Expected comparison operator, got "${this.curToken.value}"`)}}parseColumnList(){const e=[];for(e.push(this.parseColumnWithAlias());this.curTokenIs(Ot.COMMA);)this.nextToken(),e.push(this.parseColumnWithAlias());return e}parseColumnWithAlias(){let e=this.parseColumnRef();if(this.curTokenIs(Ot.AS))this.nextToken(),e=`${e} AS ${this.expectIdentifier("alias")}`;else if(this.curToken.type===Ot.IDENTIFIER&&!this._isReservedAfterFrom()&&!this._isJoinKeyword()){const t=this.curToken.value;this.nextToken(),e=`${e} AS ${t}`}return e}parseColumnRef(){if(this.curTokenIs(Ot.CASE))return this.parseCaseExpressionText();if(this.curTokenIs(Ot.NUMBER)){const e=this.curToken.value;return this.nextToken(),e}if(this.curTokenIs(Ot.STRING)){const e=this.curToken.value;return this.nextToken(),`'${e.replace(/'/g,"''")}'`}if(this.curTokenIs(Ot.COUNT)||this.curTokenIs(Ot.SUM)||this.curTokenIs(Ot.AVG)||this.curTokenIs(Ot.MIN)||this.curTokenIs(Ot.MAX))return this.parseAggregateCall();if(this.curTokenIs(Ot.QUOTED_IDENTIFIER)){const e=this.curToken.value;if(this.nextToken(),this.curTokenIs(Ot.DOT)){this.nextToken();const t=this.expectIdentifier('column name after "."');return`"${e.replace(/"/g,'""')}".${t}`}return`"${e.replace(/"/g,'""')}"`}const e=this.expectIdentifier("column name");return this.curTokenIs(Ot.DOT)?(this.nextToken(),`${e}.${this.expectIdentifier("column name")}`):e}parseCaseExpressionText(){const e=this.curToken.position;this.nextToken();let t=1,s=e+4;for(;!this.curTokenIs(Ot.EOF)&&t>0&&(this.curTokenIs(Ot.CASE)&&t++,!this.curTokenIs(Ot.END)||(t--,s=this.curToken.position+3,this.nextToken(),0!==t));)s=this.curToken.position+this.curToken.value.length,this.nextToken();let n=this.sql.slice(e,s);return this.curTokenIs(Ot.AS)?(this.nextToken(),n+=` AS ${this.expectIdentifier("alias")}`):this.curToken.type!==Ot.IDENTIFIER||this.curTokenIs(Ot.COMMA)||this._isReservedAfterFrom()||(n+=` AS ${this.curToken.value}`,this.nextToken()),n}parseAggregateCall(){const e=this.curToken.value.toUpperCase();this.nextToken(),this.expect(Ot.LPAREN);let t,s=!1;this.curTokenIs(Ot.DISTINCT)&&(s=!0,this.nextToken()),this.curTokenIs(Ot.STAR)?(t="*",this.nextToken()):t=this.parseColumnRef(),this.expect(Ot.RPAREN);let n="";this.curTokenIs(Ot.AS)?(this.nextToken(),n=this.expectIdentifier("alias")):this.curToken.type===Ot.IDENTIFIER&&this._isAggregateAlias()&&(n=this.curToken.value,this.nextToken());const i=s?`DISTINCT ${t}`:t;return n?`${e}(${i}) AS ${n}`:`${e}(${i})`}_isAggregateAlias(){return!this._isReservedAfterFrom()&&!this._isJoinKeyword()}parseIdentifierList(){const e=[];for(e.push(this.parseIdentifierWithDot());this.curTokenIs(Ot.COMMA);)this.nextToken(),e.push(this.parseIdentifierWithDot());return e}parseValueList(){const e=[];for(e.push(this.parseValue());this.curTokenIs(Ot.COMMA);)this.nextToken(),e.push(this.parseValue());return e}parseOrderOrGroupKey(){if(this.curTokenIs(Ot.NUMBER)){const e=this.curToken.value;if(!/^\d+$/.test(e)||Number(e)<1)throw this.error(`Invalid output column ordinal "${e}" (must be a positive integer)`);return this.nextToken(),e}return this.parseIdentifierWithDot()}parseGroupByList(){const e=[];for(e.push(this.parseOrderOrGroupKey());this.curTokenIs(Ot.COMMA);)this.nextToken(),e.push(this.parseOrderOrGroupKey());return e}parseOrderByList(){const e=[];for(e.push(this.parseOrderBy());this.curTokenIs(Ot.COMMA);)this.nextToken(),e.push(this.parseOrderBy());return e}parseOrderBy(){const e=this.parseOrderOrGroupKey();let t,s="asc";return this.curTokenIs(Ot.ASC)?this.nextToken():this.curTokenIs(Ot.DESC)&&(s="desc",this.nextToken()),this.curTokenIs(Ot.IDENTIFIER)&&"NULLS"===this.curToken.value.toUpperCase()&&(this.nextToken(),this.curTokenIs(Ot.IDENTIFIER)&&"FIRST"===this.curToken.value.toUpperCase()?(t="first",this.nextToken()):this.curTokenIs(Ot.IDENTIFIER)&&"LAST"===this.curToken.value.toUpperCase()&&(t="last",this.nextToken())),{column:e,direction:s,...t?{nulls:t}:{}}}parseIdentifierWithDot(){const e=this.expectIdentifier("identifier");return this.curTokenIs(Ot.DOT)?(this.nextToken(),`${e}.${this.expectIdentifier("identifier")}`):e}parseValue(){switch(this.curToken.type){case Ot.STRING:{const e=this.curToken.value;return this.nextToken(),e}case Ot.NUMBER:{const e=Number(this.curToken.value);return this.nextToken(),e}case Ot.TRUE:return this.nextToken(),!0;case Ot.FALSE:return this.nextToken(),!1;case Ot.NULL:return this.nextToken(),null;default:throw this.error(`Expected value, got "${this.curToken.value}"`)}}nextToken(){this.curToken=this.peekToken,this.peekToken=this.lexer.nextToken()}curTokenIs(e){return this.curToken.type===e}expect(e){if(!this.curTokenIs(e))throw this.error(`Expected ${e}, got "${this.curToken.value}"`);this.nextToken()}expectIdentifier(e){if(this.curToken.type===Ot.QUOTED_IDENTIFIER){const e=this.curToken.value;return this.nextToken(),e}if(this.curToken.type===Ot.IDENTIFIER||this._isKeywordAsIdent()){const e=this.curToken.value;return this.nextToken(),e}throw this.error(`Expected ${e}, got "${this.curToken.value}"`)}_isKeywordAsIdent(){return this.curToken.type!==Ot.EOF&&this.curToken.type!==Ot.ILLEGAL&&this.curToken.type!==Ot.STRING&&this.curToken.type!==Ot.QUOTED_IDENTIFIER&&this.curToken.type!==Ot.NUMBER&&this.curToken.type!==Ot.COMMA&&this.curToken.type!==Ot.LPAREN&&this.curToken.type!==Ot.RPAREN&&this.curToken.type!==Ot.SEMICOLON&&this.curToken.type!==Ot.EQ&&this.curToken.type!==Ot.NEQ&&this.curToken.type!==Ot.GT&&this.curToken.type!==Ot.GTE&&this.curToken.type!==Ot.LT&&this.curToken.type!==Ot.LTE&&this.curToken.type!==Ot.DOT&&this.curToken.type!==Ot.STAR}expectNumber(e){if(this.curToken.type===Ot.NUMBER){const e=Number(this.curToken.value);return this.nextToken(),e}throw this.error(`Expected ${e}, got "${this.curToken.value}"`)}error(e){return new n(`Parse error at position ${this.curToken.position}: ${e}`,"PARSE_ERROR")}}function vt(e){return new $t(e).parseAllStatements()}function Dt(e){return new $t(e).parseWhere()}function Ut(e,t,s){let i,r=t.trim();if(r.length>=2&&r.startsWith('"')&&r.endsWith('"')&&(r=r.slice(1,-1).replace(/""/g,'"')),r in e)return e[r];if(r.includes(".")){const t=r.split(".").pop();if(t in e)return e[t]}let a=0;for(const t of Object.keys(e))t.endsWith(`.${r}`)&&(i=e[t],a+=1);if(1===a)return i;if(s.strict)throw new n(a>1?`Ambiguous column "${r}" in ${s.context}: present in multiple tables`:`Unknown column "${r}" in ${s.context}`,"COLUMN_NOT_FOUND",{column:r});return u}const _t=new Map;function Mt(e){const t=e.trim();if(!/^\s*CASE\b/i.test(t))return null;const s=_t.get(t);if(s)return s;const i=function(e){const t=Lt(e);let s=0;const i=(t,s)=>{throw new n(`${t} (at offset ${s} in "${e}")`,"PARSE_ERROR")};t[s]?.type!==Ot.CASE&&i("Expected CASE",t[s]?.position??0),s++;const r=[];let a=null;const o=(s,n)=>{const i=t[s];if(!i)return"";const r=t[n],a=r?r.position:e.length;return e.slice(i.position,a).trim()};for(;s<t.length;){const e=t[s];if(e.type===Ot.WHEN){const a=s+1;let h=0,c=-1;for(let e=a;e<t.length;e++){const s=t[e];if(s.type===Ot.LPAREN)h++;else if(s.type===Ot.RPAREN)h--;else{if(0===h&&s.type===Ot.THEN){c=e;break}if(0===h&&(s.type===Ot.ELSE||s.type===Ot.END))break}}c<0&&i("CASE WHEN without matching THEN",e.position);const l=c+1;let u=0,f=t.length;for(let e=l;e<t.length;e++){const s=t[e];if(s.type===Ot.LPAREN)u++;else if(s.type===Ot.RPAREN)u--;else{if(0===u&&(s.type===Ot.WHEN||s.type===Ot.ELSE||s.type===Ot.END)){f=e;break}if(0===u&&s.type===Ot.CASE){let s=1;for(let n=e+1;n<t.length;n++)if(t[n].type===Ot.CASE)s++;else if(t[n].type===Ot.END&&(s--,0===s)){e=n;break}}}}const d=o(a,c),p=o(l,f);let m;d||i("CASE WHEN has an empty condition",e.position),p||i("CASE THEN has an empty result",t[l]?.position??e.position);try{m=Dt(d)}catch(e){throw new n(`Invalid CASE WHEN condition "${d}": ${e.message}`,"PARSE_ERROR",{condition:d})}r.push({conditionText:d,resultText:p,condition:m}),s=f;continue}if(e.type===Ot.ELSE){const n=s+1;let r=0,h=t.length;for(let e=n;e<t.length;e++){const s=t[e];if(s.type===Ot.LPAREN)r++;else if(s.type===Ot.RPAREN)r--;else{if(0===r&&s.type===Ot.END){h=e;break}if(0===r&&s.type===Ot.CASE){let s=1;for(let n=e+1;n<t.length;n++)if(t[n].type===Ot.CASE)s++;else if(t[n].type===Ot.END&&(s--,0===s)){e=n;break}}}}a=o(n,h),a||i("CASE ELSE has an empty result",e.position),s=h;continue}if(e.type===Ot.END){s++;break}i(`Unexpected token "${e.value}" in CASE`,e.position)}if(0===r.length)throw new n(`CASE expression has no WHEN branch: "${e}"`,"PARSE_ERROR");let h=null;const c=t.slice(s).filter(e=>e.type!==Ot.EOF&&e.type!==Ot.SEMICOLON);if(c.length>0){const e=c[0];if(e.type===Ot.AS){const e=c[1];!e||e.type!==Ot.IDENTIFIER&&e.type!==Ot.QUOTED_IDENTIFIER||(h=e.value)}else e.type!==Ot.IDENTIFIER&&e.type!==Ot.QUOTED_IDENTIFIER||(h=e.value)}return{branches:r,elseText:a,alias:h,source:e}}(t);return _t.size>=512&&_t.clear(),_t.set(t,i),i}function Pt(e,t){for(const s of e.branches)if(k(t,s.condition,{$col:!0}))return Bt(s.resultText,t);return null!==e.elseText?Bt(e.elseText,t):null}function Bt(e,t){const s=e.trim();if(""===s)throw new n("Empty expression value","PARSE_ERROR");const i=s.match(/^'(.*)'$/s);if(i)return i[1].replace(/''/g,"'");if(/^NULL$/i.test(s))return null;if(/^TRUE$/i.test(s))return!0;if(/^FALSE$/i.test(s))return!1;if(/^-?\d+(\.\d+)?$/.test(s))return Number(s);const r=Mt(s);if(r)return Pt(r,t);if(/^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)?$/.test(s)){const e=Ut(t,s,{strict:!1,context:"CASE result"});if(f(e))throw new n(`Unknown column "${s}" in expression`,"COLUMN_NOT_FOUND",{column:s});return e}throw new n(`Unsupported expression in CASE result: "${s}"`,"NOT_SUPPORTED",{expression:s})}function Ft(e){const t=e.trim().match(/^(COUNT|SUM|AVG|MIN|MAX)\s*\(\s*([\s\S]+?)\s*\)\s*(?:AS\s+([A-Za-z_][A-Za-z0-9_]*))?$/i);if(!t)return null;const s=t[1].toUpperCase();let n=t[2].trim();const i=t[3],r=/^DISTINCT\s+/i.test(n);r&&(n=n.replace(/^\s*DISTINCT\s+/i,"").trim());const a=`${s}(${r?"DISTINCT ":""}${n})`;return{func:s,arg:n,outputKey:i||e.trim(),distinct:r,exprKey:a}}function Kt(e){return null!==Ft(e)}function zt(e){const t=e.trim();return t.includes(".")?t.split(".").pop():t}function qt(e,t){const s=Mt(t);return s?Pt(s,e):Ut(e,jt(t),{strict:!0,context:"GROUP BY"})}function jt(e){const t=e.trim();return t.length>=2&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1).replace(/""/g,'"'):t.includes(".")?t.split(".").map(e=>jt(e)).join("."):t}function Vt(e,t){const s=e.trim(),n=s.match(/^'(.*)'$/s);return n?n[1].replace(/''/g,"'"):/^-?\d+(\.\d+)?$/.test(s)?Number(s):!!/^TRUE$/i.test(s)||!/^FALSE$/i.test(s)&&(/^NULL$/i.test(s)?null:Ut(t,s,{strict:!1,context:"SELECT list"}))}function Wt(e,t){if(0===e.length)return null;let s="SUM"===t||"AVG"===t?0:e[0];for(let n=0;n<e.length;n++){const i=e[n];switch(t){case"SUM":case"AVG":s+=i;break;case"MIN":n>0&&i<s&&(s=i);break;case"MAX":n>0&&i>s&&(s=i)}}return"AVG"===t?s/e.length:s}class Gt{constructor(e,t=0){this.engine=e,this.maxRowsPerQuery=t}async execute(e){try{return await this.dispatch(e)}catch(e){throw e instanceof Error?e:new n(String(e),"QUERY_ERROR")}}dispatch(e){switch(e.type){case"SELECT":return this.executeSelect(e);case"SELECT_UNION":return this.executeSelectUnion(e);case"EXPLAIN":return this.executeExplain(e);case"INSERT":return this.executeInsert(e);case"UPDATE":return this.executeUpdate(e);case"DELETE":return this.executeDelete(e);case"CREATE_TABLE":return this.executeCreateTable(e);case"DROP_TABLE":return this.executeDropTable(e);case"ALTER_TABLE":return this.executeAlterTable(e);case"TRUNCATE_TABLE":return this.executeTruncateTable(e);case"CREATE_INDEX":return this.executeCreateIndex(e);case"DROP_INDEX":return this.executeDropIndex(e);case"BEGIN":return this.executeBegin();case"COMMIT":return this.executeCommit();case"ROLLBACK":return this.executeRollback();case"SAVEPOINT":return this.executeSavepoint(e);case"ANALYZE":return this.executeAnalyze(e);case"REINDEX":return this.executeReindex(e);case"VACUUM":return this.executeVacuum();default:throw new n("Unknown statement type","UNKNOWN_STATEMENT")}}async executeSelectUnion(e,t="result"){const s=await this.executeSelectPart(e.left,t),n=await this.executeSelectPart(e.right,t),i=s.length>0?Object.keys(s[0]):[],r=s.map(e=>e);let a;if(e.all){for(const e of n)r.push(this.projectUnionRow(e,i));a=r}else{const e=new Set;a=[];for(const t of r){const s=Object.values(t).map(d).join("");e.has(s)||(e.add(s),a.push(t))}for(const t of n){const s=this.projectUnionRow(t,i),n=Object.values(s).map(d).join("");e.has(n)||(e.add(n),a.push(s))}}e.orderBy&&e.orderBy.length>0&&(a=this.orderCompoundResult(a,e.orderBy));const o=e.offset??0;if(o>0||void 0!==e.limit){const t=e.limit??a.length;a=a.slice(o,o+t)}return a}orderCompoundResult(e,t){const s=e[0],i=s?Object.keys(s):[];return P(e,t.map(e=>{const t=/^\d+$/.test(e.column.trim())?Number(e.column.trim()):null;if(null!==t){if(t<1||t>i.length)throw new n(`ORDER BY position ${t} is out of range: compound query has ${i.length} output column(s)`,"QUERY_ERROR");return{...e,column:i[t-1]}}const r=e.column.includes(".")?e.column.split(".").pop():e.column;if(i.length>0&&!(e.column in s)&&!(r in s))throw new n(`Unknown column "${e.column}" in ORDER BY of compound query. Output columns: ${i.join(", ")}`,"COLUMN_NOT_FOUND");return{...e,column:e.column in s?e.column:r}}))}async executeSelectPart(e,t="result"){return"SELECT_UNION"===e.type?this.executeSelectUnion(e,t):this.executeSelect(e,t)}projectUnionRow(e,t){if(0===t.length)return e;const s=Object.values(e),n={};for(let e=0;e<t.length;e++)n[t[e]]=e<s.length?s[e]:null;return n}async executeExplain(e){const t=Date.now();let s=null,n=0;if("SELECT"===e.query.type||"SELECT_UNION"===e.query.type){try{s=await this.execute(e.query)}catch{}n=Array.isArray(s)?s.length:0}else if("UPDATE"===e.query.type||"DELETE"===e.query.type)try{await this.resolveWriteWhere(e.query);const t=Rt(e.query);t.where=e.query.where,n=await this.engine.count(t.table,t)}catch{n=0}const i=Date.now()-t;let r=null;try{r=Rt(e.query)}catch{}let a="none";if(r&&r.table&&r.where&&Object.keys(r.where).length>0)try{const e=await this.engine.getTableSchema(r.table);if(e){const t=s=>{for(const[n,i]of Object.entries(s)){if("$and"===n){for(const e of i){const s=t(e);if(s)return s}continue}if("$or"===n||"$not"===n)continue;const s=e.columns[n];if(s){if(s.primaryKey)return"pk";if(s.index||s.unique)return`index:${n}`}}return null};a=t(r.where)??"none"}}catch{}return{type:e.query.type,table:r?.table,columns:r?.columns,where:r?.where||{},orderBy:r?.orderBy||[],limit:r?.limit,offset:r?.offset,usingIndex:a,estimatedRows:n,actualTimeMs:i}}analyzeSelect(e){const t=!!(e.groupBy&&e.groupBy.length>0),s=!t&&this._hasAggregateColumn(e.columns),n=!!(e.joins&&e.joins.length>0),i=this.hasCaseColumn(e.columns)||!!e.where&&this.whereHasCase(e.where),r=this.orderByUsesSelectAlias(e),a=e.columns.some(e=>/\s+AS\s+\w+$/i.test(e)),o=!(t||s||n||e.fromSubquery||e.distinct||e.having&&Object.keys(e.having).length>0||r||i||a);let h=e.columns.length>0;for(const t of e.columns)if("*"!==t&&!/^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)?$/.test(t)){h=!1;break}return{hasGroupBy:t,hasAggregate:s,isJoinQuery:n,needsRawRows:i,orderByAlias:r,hasSelectAlias:a,limitPushdownSafe:o,engineEquivalentProjection:h,streamable:h&&!t&&!s&&!n&&!e.fromSubquery&&!e.distinct&&!(e.having&&Object.keys(e.having).length>0)&&!(e.orderBy&&e.orderBy.length>0)&&!i&&!r&&!a&&!this.hasCorrelatedRefs(e.where)&&!A(e.where)}}async executeSelect(e,t="result"){const s=this.analyzeSelect(e),{hasGroupBy:n,hasAggregate:i,isJoinQuery:r,needsRawRows:a,orderByAlias:o,hasSelectAlias:h,limitPushdownSafe:c}=s;let l;if(await this.assertCaseColumnsExist(e,r),await this.assertWhereColumnsExist(e,r),e.orderBy&&e.orderBy.length>0&&!e.fromSubquery){const t=this.selectAliasNames(e),s={};for(const n of e.orderBy){const e=jt(n.column.trim());e&&!/^\d+$/.test(e)&&(Mt(n.column)||t.has(e)||(s[e]={$exists:!0}))}Object.keys(s).length>0&&await this.validateWhereColumns(e,s,{context:"ORDER BY",rejectAmbiguous:r})}if(e.fromSubquery){const t=await this.executeSelectPart(e.fromSubquery);l=r?await this.executeJoinSelect(e,t.map(t=>this.prefixRow(t,e.alias??""))):t,r||(await this.resolveOutputOrdinals(e),this.normalizeUnprefixedReferences(e,[e.alias??e.from]),e.where&&Object.keys(e.where).length>0&&(e.where=await this.resolveSubqueries(e.where),l=l.filter(t=>k(t,e.where))))}else if(e.from||r)if(r)l=await this.executeJoinSelect(e);else{await this.resolveOutputOrdinals(e);const t=[e.alias??e.from].filter(Boolean);if(this.normalizeUnprefixedReferences(e,t),e.where&&this.hasCorrelatedRefs(e.where)){const s=Rt(n||i?{...e,columns:["*"]}:e);s.columns=["*"],o&&(s.orderBy=void 0,s.limit=void 0,s.offset=void 0),l=await this.engine.find(s.table,{...s,where:this.enginePreFilter(e.where)}),l=await this.filterCorrelated(l,e.where,t)}else{e.where&&Object.keys(e.where).length>0&&(e.where=await this.resolveSubqueries(e.where));const t=Rt(n||i?{...e,columns:["*"]}:e);(a||h)&&(t.columns=["*"]),c||(t.limit=void 0,t.offset=void 0),o&&(t.orderBy=void 0,t.limit=void 0,t.offset=void 0),l=await this.engine.find(t.table,t)}}else l=[{}];i&&(l=[this.computeSingleAggregate(l,e)]),n&&(l=this.executeGroupBy(l,e));const u=!!e.distinct&&this.distinctNeedsPreProjectionSort(e);if(u&&(l=this.executeDistinct(l)),e.having&&Object.keys(e.having).length>0){e.having=await this.resolveSubqueries(e.having);const t=e._aggAliasMap;if(t&&t.size>0){const s={};for(const[n,i]of Object.entries(e.having))s[t.get(n)??n]=i;e.having=s}l=l.filter(t=>k(t,e.having))}n&&(l=this.projectGroupedRows(l,e));const f=!!e.orderBy&&e.orderBy.length>0&&(u||!this.orderByReferencesOutputColumns(e));if(e.orderBy&&e.orderBy.length>0&&!o&&f&&(l=P(l,e.orderBy)),i||this.assertProjectionColumnsExist(l,e.columns,e),n||i||!(e.columns.length>0)||1===e.columns.length&&"*"===e.columns[0]||(l=l.map(t=>this.projectRow(t,e.columns))),e.distinct&&!u&&(l=this.executeDistinct(l)),o&&e.orderBy&&e.orderBy.length>0&&(l=P(l,e.orderBy)),!c){const t=e.offset??0,s=e.limit??l.length;l=l.slice(t,t+s)}return"result"===t&&this.maxRowsPerQuery>0&&l.length>this.maxRowsPerQuery&&(l=l.slice(0,this.maxRowsPerQuery)),l}async executeJoinSelect(e,t){for(const t of e.joins??[])t.on&&Object.keys(t.on).length>0&&await this.validateJoinOnColumns(e,t);const s=e.alias??e.from;let n;if(t)n=t;else{const{pushable:t}=this.extractPushableWhere(e.where??{},s);n=(await this.engine.find(e.from,{table:e.from,where:Object.keys(t).length>0?t:void 0})).map(e=>this.prefixRow(e,s))}let i=n;for(const t of e.joins){const e=t.alias??t.table,n=await this.tryHashJoin(i,t,e,s);if(n){i=n;continue}const r=(await this.engine.find(t.table,{table:t.table})).map(t=>this.prefixRow(t,e));i=this.joinRows(i,r,t)}return e.where&&Object.keys(e.where).length>0&&(this.hasCorrelatedRefs(e.where)?i=await this.filterCorrelated(i,e.where):(e.where=await this.resolveSubqueries(e.where),i=i.filter(t=>k(t,e.where)))),i}prefixRow(e,t){const s={};for(const[n,i]of Object.entries(e))s[`${t}.${n}`]=i;return s}extractPushableWhere(e,t){const s={};if(!t)return{pushable:s};const n=`${t}.`;for(const[t,i]of Object.entries(e))t.startsWith(n)&&("object"==typeof i&&null!==i&&("$col"in i||"$subquery"in i||"$and"in i||"$or"in i||"$not"in i)||(s[t.slice(n.length)]=i));return{pushable:s}}async tryHashJoin(e,t,s,n){if("CROSS"===t.type||"RIGHT"===t.type)return null;const i=[],r=e=>{for(const[t,s]of Object.entries(e)){if("$and"===t){if(!s.every(r))return!1;continue}if("$or"===t||"$not"===t)return!1;let e=null;if("object"==typeof s&&null!==s){const t=s;"$eq"in t&&"object"==typeof t.$eq&&null!==t.$eq&&"$col"in t.$eq?e=String(t.$eq.$col):"$col"in t&&1===Object.keys(t).length&&(e=String(t.$col))}if(!e)return!1;const a=!!n&&t.startsWith(`${n}.`);i.push({leftCol:a?t:e,rightCol:a?e:t})}return!0};if(!r(t.on))return null;if(0===i.length)return null;const a=await this.engine.getTableSchema(t.table);if(!a)return null;const o=i.find(e=>{const t=e.rightCol.split(".").pop(),s=a.columns[t];return s&&(s.primaryKey||s.index||s.unique)});if(!o)return null;const h=o.rightCol.split(".").pop(),c=Array.from(new Set(e.map(e=>e[o.leftCol]).filter(e=>null!=e)));if(0===c.length)return null;const l=await this.engine.find(t.table,{table:t.table,where:{[h]:{$in:c}}}),u=new Map;for(const e of l){const t=i.map(t=>String(e[t.rightCol.split(".").pop()]??"\0")).join("");u.has(t)||u.set(t,[]),u.get(t).push(e)}const f={};for(const e of Object.keys(a.columns))f[e]=null;const d=[];for(const n of e){const e=i.map(e=>String(n[e.leftCol]??"\0")).join(""),r=u.get(e);if(r&&r.length>0)for(const e of r)d.push({...n,...this.prefixRow(e,s)});else"LEFT"===t.type&&d.push({...n,...this.prefixRow(f,s)})}return d}joinRows(e,t,s){if("CROSS"===s.type){const s=[];for(const n of e)for(const e of t)s.push({...n,...e});return s}const n=[];for(const i of e){let e=!1;for(const r of t){const t={...i,...r};k(t,s.on,{$col:!0})&&(n.push(t),e=!0)}if(!e&&"LEFT"===s.type){const e={};for(const s of Object.keys(t[0]??{}))e[s]=null;n.push({...i,...e})}}if("RIGHT"===s.type)for(const i of t)if(!e.some(e=>k({...e,...i},s.on,{$col:!0}))){const t={};for(const s of Object.keys(e[0]??{}))t[s]=null;n.push({...t,...i})}return n}executeGroupBy(e,t){const s=this.resolveGroupByColumns(t),n=new Map;for(const t of e){const e=s.map(e=>d(qt(t,e))).join("");n.has(e)||n.set(e,[]),n.get(e).push(t)}const i=this.collectAggregateExpressions(t),r=[],a=new Map;for(const e of n.values()){const n=e[0],o={};for(const e of s){const t=Mt(e);o[t?.alias??jt(e)]=qt(n,e)}for(const t of i){const s=t.distinct?this.computeDistinctAggregate(t.func,e,t.arg):this.computeAggregate(t.func,e,t.arg);t.outputKey!==t.exprKey&&a.set(t.exprKey,t.outputKey),o[t.exprKey]=s,t.outputKey!==t.exprKey&&(o[t.outputKey]=s)}for(const e of t.columns){if("*"===e)continue;if(Ft(e))continue;if(/^\s*CASE\b/i.test(e)){const t=Mt(e),s=t?.alias??e;s in o||(o[s]=t?Pt(t,n):null);continue}if(e.match(/^(.+?)\s+AS\s+(\w+)$/i))continue;const t=zt(e);t in o||e in o||(o[t]=Ut(n,e,{strict:!0,context:"SELECT list"}))}r.push(o)}return t._aggAliasMap=a,r}projectGroupedRows(e,t){const s=this.resolveGroupByColumns(t);return e.map(e=>this.projectGroupedRow(e,s,t.columns))}projectGroupedRow(e,t,s){if(s.some(e=>"*"===e))return e;const n={};for(const s of t)s in e&&(n[s]=e[s]);for(const t of s){if("*"===t)continue;const s=Ft(t);if(s){n[s.outputKey]=e[s.outputKey];continue}const i=Mt(t);if(i){const s=i.alias??t;n[s]=e[s];continue}const r=t.match(/^(.+?)\s+AS\s+(\w+)$/i);if(r){n[r[2]]=e[r[2]];continue}const a=jt(zt(t));n[a]=a in e?e[a]:e[t]}return n}resolveGroupByColumns(e){const t=new Map;for(const s of e.columns){const e=Mt(s);if(e?.alias){t.set(e.alias,s.trim());continue}const n=s.match(/^(.+?)\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)$/i);n&&t.set(n[2],n[1].trim())}return e.groupBy.map(e=>{const s=t.get(e.trim());return void 0===s||Ft(s)?e:s})}collectAggregateExpressions(e){const t=new Map,s=e=>{const s=Ft(e);s&&(t.get(s.exprKey)||t.set(s.exprKey,s))};for(const t of e.columns)s(t);for(const t of function(e){const t=[];if(!e)return t;const s=e=>{const s=/(?:COUNT|SUM|AVG|MIN|MAX)\s*\([^()]*(?:\([^()]*\)[^()]*)*\)/gi;let n;for(;null!==(n=s.exec(e));)t.push(n[0])},n=e=>{for(const[t,i]of Object.entries(e))if("$and"!==t&&"$or"!==t)if("$not"!==t){if(s(t),"string"==typeof i)s(i);else if(Array.isArray(i))for(const e of i)"string"==typeof e&&s(e);else if(null!==i&&"object"==typeof i)for(const e of Object.values(i))"string"==typeof e&&s(e)}else n(i);else for(const e of Array.isArray(i)?i:[i])n(e)};return n(e),t}(e.having))s(t);return[...t.values()]}computeAggregate(e,t,s){const n=Mt(s),i=s.trim(),r=t.map(t=>n?Pt(n,t):"*"===i?t:Ut(t,i,{strict:!0,context:`aggregate ${e}(${i})`})).filter(e=>null!=e);if("COUNT"===e)return"*"===i?t.length:r.length;const a=r.map(e=>Number(e));switch(e){case"SUM":return Wt(a,"SUM");case"AVG":return Wt(a,"AVG");case"MIN":return Wt(a,"MIN");case"MAX":return Wt(a,"MAX");default:return null}}computeDistinctAggregate(e,t,s){const n=t.map(t=>Ut(t,s,{strict:!0,context:`aggregate ${e}(DISTINCT ${s})`})).filter(e=>null!=e);if("COUNT"===e)return new Set(n.map(e=>d(e))).size;const i=n.map(e=>Number(e)),r=new Set,a=[];for(const e of i){const t=d(e);r.has(t)||(r.add(t),a.push(e))}switch(e){case"SUM":return Wt(a,"SUM");case"AVG":return Wt(a,"AVG");case"MIN":return Wt(a,"MIN");case"MAX":return Wt(a,"MAX");default:return null}}executeDistinct(e){const t=new Set;return e.filter(e=>{const s=Object.values(e).map(d).join("");return!t.has(s)&&(t.add(s),!0)})}async executeInsert(e){const t=await this.engine.getTableSchema(e.into);if(!t)throw new n(`Table "${e.into}" does not exist`,"TABLE_NOT_FOUND");const s=e.columns??Object.keys(t.columns),i=s.filter(e=>!(e in t.columns));if(i.length>0)throw new n(`Unknown column${i.length>1?"s":""} ${i.map(e=>`"${e}"`).join(", ")} in table "${e.into}". Known columns: ${Object.keys(t.columns).join(", ")}`,"COLUMN_NOT_FOUND");if(e.select){const t=await this.executeSelectPart(e.select,"source");let n=[];const i=e.select;if("SELECT"===i.type)if(i.columns&&i.columns.length>0&&"*"!==i.columns[0])n=i.columns.map(e=>e.split(".").pop());else if(i.from){const e=await this.engine.getTableSchema(i.from);n=e?Object.keys(e.columns):[]}0===n.length&&t.length>0&&(n=Object.keys(t[0]));const r=t.map(e=>{const t={};for(let i=0;i<s.length;i++){const r=i<n.length?n[i]:null;r&&r in e&&(t[s[i]]=e[r])}return t});return this.assertWithinRowLimit(r.length),await(this.engine.validatePayload?.(e.into,r,"insert")),this.engine.insert(e.into,r)}const r=(e.values??[]).map((t,i)=>{if(t.length>s.length)throw new n(`INSERT has ${t.length} value(s) for ${s.length} column(s) in table "${e.into}" (row ${i+1}); too many values`,"VALIDATION_ERROR",{table:e.into,values:t.length,columns:s.length});const r={};for(let e=0;e<s.length;e++)e<t.length&&(r[s[e]]=t[e]);return r});return this.assertWithinRowLimit(r.length),await(this.engine.validatePayload?.(e.into,r,"insert")),this.engine.insert(e.into,r)}assertWithinRowLimit(e){if(this.maxRowsPerQuery>0&&e>this.maxRowsPerQuery)throw new n(`Statement would write ${e} rows, exceeding maxRowsPerQuery (${this.maxRowsPerQuery}). Narrow the source query or raise the limit.`,"QUERY_ERROR",{rows:e,maxRowsPerQuery:this.maxRowsPerQuery})}async executeUpdate(e){await this.resolveWriteWhere(e);const t=Rt(e);return t.where=e.where,this.engine.update(t.table,t,e.sets)}async executeDelete(e){await this.resolveWriteWhere(e);const t=Rt(e);return t.where=e.where,this.engine.delete(t.table,t)}async resolveWriteWhere(e){const t=e.where;if(!t||0===Object.keys(t).length)return t??{};if(this.hasCorrelatedRefs(t))throw new n("Correlated subqueries and column references are not supported in UPDATE/DELETE WHERE clauses","NOT_SUPPORTED");return e.where=await this.resolveSubqueries(t),e.where}async executeCreateTable(e){if(e.ifNotExists&&await this.engine.hasTable(e.name))return;const t=Object.create(null);for(const s of e.columns)t[s.name]=H(s);return this.engine.createTable(W(e.name,t))}async executeDropTable(e){if(!e.ifExists||await this.engine.hasTable(e.name))return this.engine.dropTable(e.name)}async executeAlterTable(e){if(!await this.engine.hasTable(e.name))throw new n(`Table "${e.name}" does not exist`,"TABLE_NOT_FOUND");const t=await this.engine.getTableSchema(e.name);if(t){if("ADD"===e.action&&e.column.primaryKey&&Object.values(t.columns).some(e=>e.primaryKey))throw new n(`Composite primary keys are not supported yet: table "${e.name}" already has a primary key column`,"SCHEMA_ERROR");if("function"==typeof this.engine.alterTable)return this.engine.alterTable(e.name,e.action,{...H(e.column),name:e.column.name});if("ADD"===e.action){if(t.columns[e.column.name])throw new n(`Column "${e.column.name}" already exists in table "${e.name}"`,"COLUMN_EXISTS");t.columns[e.column.name]=H(e.column)}else if("DROP"===e.action){if(!t.columns[e.column.name])throw new n(`Column "${e.column.name}" does not exist in table "${e.name}"`,"COLUMN_NOT_FOUND");delete t.columns[e.column.name];const s=await this.engine.find(e.name,{table:e.name}),i=e.column.name;for(const e of s)i in e&&delete e[i]}}}async executeTruncateTable(e){if(!await this.engine.hasTable(e.name))throw new n(`Table "${e.name}" does not exist`,"TABLE_NOT_FOUND");return this.engine.clear(e.name)}async executeCreateIndex(e){if(!await this.engine.hasTable(e.table))throw new n(`Table "${e.table}" does not exist`,"TABLE_NOT_FOUND");const t=await this.engine.getTableSchema(e.table);if(t&&!t.columns[e.column])throw new n(`Column "${e.column}" does not exist in table "${e.table}"`,"COLUMN_NOT_FOUND");if("function"!=typeof this.engine.createIndex)throw new n(`Engine "${this.engine.name}" does not support CREATE INDEX`,"NOT_SUPPORTED");return this.engine.createIndex(e.table,e.column,e.unique)}async executeDropIndex(e){if("function"!=typeof this.engine.dropIndex)throw new n(`Engine "${this.engine.name}" does not support DROP INDEX`,"NOT_SUPPORTED");return this.engine.dropIndex(e.table,e.column,e.name)}async executeBegin(){return this.engine.beginTransaction()}async executeCommit(){return this.engine.commitTransaction()}async executeRollback(){return this.engine.rollbackTransaction()}async executeSavepoint(e){const t=this.engine;if("SAVE"===e.action){if("function"!=typeof t.savepoint)throw new n(`Engine "${this.engine.name}" does not support SAVEPOINT`,"NOT_SUPPORTED");return t.savepoint(e.name)}if("ROLLBACK"===e.action){if("function"!=typeof t.rollbackToSavepoint)throw new n(`Engine "${this.engine.name}" does not support ROLLBACK TO SAVEPOINT`,"NOT_SUPPORTED");return t.rollbackToSavepoint(e.name)}if("function"!=typeof t.releaseSavepoint)throw new n(`Engine "${this.engine.name}" does not support RELEASE SAVEPOINT`,"NOT_SUPPORTED");return t.releaseSavepoint(e.name)}async executeAnalyze(e){const t=this.engine;if("function"!=typeof t.analyzeTable)throw new n(`Engine "${this.engine.name}" does not support ANALYZE`,"NOT_SUPPORTED");if(!await this.engine.hasTable(e.table))throw new n(`Table "${e.table}" does not exist`,"TABLE_NOT_FOUND");return t.analyzeTable(e.table)}async executeReindex(e){const t=this.engine;if("function"!=typeof t.reindexTable)throw new n(`Engine "${this.engine.name}" does not support REINDEX`,"NOT_SUPPORTED");if(!await this.engine.hasTable(e.table))throw new n(`Table "${e.table}" does not exist`,"TABLE_NOT_FOUND");return t.reindexTable(e.table)}async executeVacuum(){const e=this.engine;if("function"!=typeof e.vacuum)throw new n(`Engine "${this.engine.name}" does not support VACUUM`,"NOT_SUPPORTED");return e.vacuum()}outputColumnNames(e){const t=new Set;for(const s of e.columns){if("*"===s)return null;const e=Ft(s);if(e){t.add(e.outputKey);continue}const n=Mt(s);if(n){t.add(n.alias??s);continue}const i=s.match(/^(.+?)\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)$/i);i?t.add(i[2]):t.add(zt(s))}return t}orderByReferencesOutputColumns(e){if(!e.orderBy||0===e.orderBy.length)return!0;const t=this.outputColumnNames(e);return null===t||e.orderBy.every(e=>t.has(zt(e.column)))}distinctNeedsPreProjectionSort(e){return!(!e.orderBy||0===e.orderBy.length||this.orderByReferencesOutputColumns(e))}async validateJoinOnColumns(e,t){const s=new Set,i=async(e,t)=>{const n=await this.engine.getTableSchema(e);if(n)for(const e of Object.keys(n.columns))s.add(e),s.add(`${t}.${e}`)};await i(e.from,e.alias??e.from);for(const s of e.joins??[])if(await i(s.table,s.alias??s.table),s===t)break;await i(t.table,t.alias??t.table);const r=[],a=e=>{const t=e.trim();if(!t)return;if(s.has(t))return;const n=t.includes(".")?t.split(".").pop():t;s.has(n)||r.push(t)},o=e=>{if("object"==typeof e&&null!==e)for(const[t,s]of Object.entries(e))"$col"!==t?"object"!=typeof s||null===s||Array.isArray(s)||o(s):a(String(s))};for(const[e,s]of Object.entries(t.on))"$and"!==e&&"$or"!==e&&"$not"!==e&&(a(e),o(s));if(r.length>0)throw new n(`Unknown column${r.length>1?"s":""} ${r.map(e=>`"${e}"`).join(", ")} in JOIN ON of table "${e.from}"`,"COLUMN_NOT_FOUND",{columns:r,from:e.from})}async assertCaseColumnsExist(e,t){if(e.fromSubquery)return;if(!e.from)return;const s=new Set,i=async(e,t)=>{const n=await this.engine.getTableSchema(e);if(n)for(const e of Object.keys(n.columns))s.add(e),s.add(`${t}.${e}`)};if(await i(e.from,e.alias??e.from),t)for(const t of e.joins??[])await i(t.table,t.alias??t.table);const r=(e,t)=>{const i=Mt(e);i&&function(e,t,s){const i=[],r=e=>{const s=e.trim();if(!s)return;if(t.has(s))return;const n=s.includes(".")?s.split(".").pop():s;t.has(n)||i.push(s)},a=e=>{for(const[t,s]of Object.entries(e))if("$and"!==t&&"$or"!==t)if("$not"!==t){if("$exists"!==t&&!/^\s*CASE\b/i.test(t)&&(r(t),null!==s&&"object"==typeof s))for(const e of Object.values(s))null!==e&&"object"==typeof e&&!Array.isArray(e)&&"$col"in e&&r(String(e.$col))}else a(s);else for(const e of Array.isArray(s)?s:[s])a(e)};for(const t of e.branches)a(t.condition);const o=e=>{const t=e.trim();if(/^'/.test(t)||/^-?\d/.test(t)||/^(NULL|TRUE|FALSE)$/i.test(t))return;const s=Mt(t);if(s){for(const e of s.branches)a(e.condition);for(const e of s.branches)o(e.resultText);s.elseText&&o(s.elseText)}else/^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)?$/.test(t)&&r(t)};for(const t of e.branches)o(t.resultText);if(e.elseText&&o(e.elseText),i.length>0)throw new n(`Unknown column${i.length>1?"s":""} ${i.map(e=>`"${e}"`).join(", ")} in ${s}`,"COLUMN_NOT_FOUND",{columns:i})}(i,s,t)};for(const t of e.columns)r(t,`CASE expression "${t.trim()}"`);for(const t of e.groupBy??[])r(t,`GROUP BY "${t}"`);for(const t of e.orderBy??[])r(t.column,`ORDER BY "${t.column}"`);for(const t of Object.keys(e.having??{}))r(t,`HAVING "${t}"`)}async assertWhereColumnsExist(e,t){e.where&&0!==Object.keys(e.where).length&&(e.fromSubquery||e.from&&await this.validateWhereColumns(e,e.where,{context:"WHERE",rejectAmbiguous:t}))}async validateWhereColumns(e,t,s){const i=s.rejectAmbiguous,r=new Set,a=new Map,o=async(e,t)=>{const s=await this.engine.getTableSchema(e);if(s)for(const e of Object.keys(s.columns)){r.add(e),r.add(`${t}.${e}`);const s=a.get(e);void 0===s?a.set(e,t):s!==t&&a.set(e,"*")}};if(await o(e.from,e.alias??e.from),i)for(const t of e.joins??[])await o(t.table,t.alias??t.table);const h=[],c=[],l=e=>{const t=jt(e);if(!t)return;if(r.has(t))return void(!t.includes(".")&&i&&"*"===a.get(t)&&c.push(t));const s=t.includes(".")?t.split(".").pop():t;r.has(s)||h.push(t)},u=e=>{if("object"!=typeof e||null===e)return;const t=e;for(const[e,s]of Object.entries(t))if("$col"!==e)if("object"!=typeof s||null===s||Array.isArray(s)){if(Array.isArray(s))for(const e of s)u(e)}else u(s);else l(String(s))},f=e=>{for(const[t,s]of Object.entries(e))if("$and"!==t&&"$or"!==t)"$not"!==t?"$exists"!==t&&(/^\s*CASE\b/i.test(t)||(l(t),u(s))):f(s);else for(const e of Array.isArray(s)?s:[s])f(e)};if(f(t),c.length>0)throw new n(`Ambiguous column${c.length>1?"s":""} ${c.map(e=>`"${e}"`).join(", ")} in ${s.context}: present in multiple joined tables. Qualify with a table alias.`,"COLUMN_NOT_FOUND",{columns:c});if(h.length>0)throw new n(`Unknown column${h.length>1?"s":""} ${h.map(e=>`"${e}"`).join(", ")} in ${s.context} of table "${e.from}"`,"COLUMN_NOT_FOUND",{columns:h,from:e.from})}hasCaseColumn(e){return e.some(e=>/^\s*CASE\b/i.test(e))}selectAliasNames(e){const t=new Set;for(const s of e.columns){const e=Mt(s);if(e?.alias){t.add(e.alias);continue}const n=s.match(/\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)\s*$/i);n&&t.add(n[1])}return t}orderByUsesSelectAlias(e){if(!e.orderBy||0===e.orderBy.length)return!1;const t=this.selectAliasNames(e);return 0!==t.size&&e.orderBy.some(e=>t.has(jt(e.column)))}whereHasCase(e){for(const[t,s]of Object.entries(e))if("$and"!==t&&"$or"!==t){if("$not"!==t){if(/^\s*CASE\b/i.test(t))return!0}else if(this.whereHasCase(s))return!0}else if(s.some(e=>this.whereHasCase(e)))return!0;return!1}getEngine(){return this.engine}assertProjectionColumnsExist(e,t,s){if(0===e.length||0===t.length)return;const i=new Set;for(const t of e)for(const e of Object.keys(t))i.add(e);for(const e of t){const t=e.trim();if("*"===t)continue;if(Mt(t))continue;let r=t;const a=t.match(/^(.+?)\s+AS\s+\w+$/i);if(a&&(r=a[1].trim()),r=jt(r),/^'.*'$/s.test(r))continue;if(/^-?\d+(\.\d+)?$/.test(r))continue;if(/^(TRUE|FALSE|NULL)$/i.test(r))continue;if(/^(COUNT|SUM|AVG|MIN|MAX)\s*\(/i.test(r))continue;if(i.has(r))continue;const o=[];for(const e of i)e.endsWith(`.${r}`)&&o.push(e);if(1!==o.length){if(o.length>1){const e=o.map(e=>e.slice(0,e.length-r.length-1)).sort();throw new n(`Ambiguous column "${r}" in SELECT list: present in ${e.join(", ")}`,"COLUMN_NOT_FOUND",{column:r,tables:e,from:s.from})}throw new n(`Unknown column "${r}" in SELECT list`,"COLUMN_NOT_FOUND",{column:r,from:s.from,available:[...i].slice(0,32)})}}}projectRow(e,t){const s=[],n=[],i=[],r=[];let a=!1;for(const o of t){if("*"===o){a=!0;continue}const t=Mt(o);if(t){i.push({alias:t.alias??o,expr:t});continue}const h=o.match(/^(.+?)\s+AS\s+(\w+)$/i);if(h){n.push({alias:h[2],source:h[1].trim()});continue}const c=o.match(/^'(.*)'$/s);if(c){const e=c[1].replace(/''/g,"'");r.push({key:o,value:e});continue}if(/^-?\d+(\.\d+)?$/.test(o)||/^(TRUE|FALSE|NULL)$/i.test(o)){r.push({key:o,value:Vt(o,e)});continue}const l=jt(o);l===o?s.push(o):s.push(l)}const o=a?{...e}:s.length>0?F(e,s):{};for(const{alias:t,source:s}of n)"*"===s?Object.assign(o,e):o[t]=Vt(s,e);for(const{key:e,value:t}of r)o[e]=t;for(const{alias:t,expr:s}of i)o[t]=Pt(s,e);return o}_hasAggregateColumn(e){return e.some(e=>Kt(e))}computeSingleAggregate(e,t){const s={};for(const n of t.columns){if("*"===n)continue;const t=Ft(n);t?s[t.outputKey]=t.distinct?this.computeDistinctAggregate(t.func,e,t.arg):this.computeAggregate(t.func,e,t.arg):s[n]=e.length>0?Ut(e[0],n,{strict:!1,context:"SELECT list"}):null}return s}async resolveOutputOrdinals(e){const t=e.columns;let s=null;const i=async()=>{if(s)return s;const t=new Set,n=async e=>{const s=await this.engine.getTableSchema(e);if(s)for(const e of Object.keys(s.columns))t.add(e)};e.from&&await n(e.from);for(const t of e.joins??[])await n(t.table);return s=t,t},r=async e=>{const s=e.trim();return!!t.some(e=>zt(e)===s||new RegExp(`\\bAS\\s+${s}$`,"i").test(e))||!!(await i()).has(s)&&t.some(e=>e===s)},a=(e,s)=>{if(e<1||e>t.length)throw new n(`${s} position ${e} is out of range: query has ${t.length} output column(s)`,"QUERY_ERROR",{position:e,outputs:t.length});const i=t[e-1],r=Mt(i);if(r)return r.alias??i;const a=Ft(i);if(a)return a.outputKey;const o=i.match(/^(.+?)\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)$/i);return o?o[2]:zt(i)};if(e.orderBy){const t=[];for(const s of e.orderBy)/^\d+$/.test(s.column.trim())&&!await r(s.column)?t.push({...s,column:a(Number(s.column.trim()),"ORDER BY")}):t.push(s);e.orderBy=t}if(e.groupBy){const s=[];for(const i of e.groupBy){if(!/^\d+$/.test(i.trim())||await r(i)){s.push(i);continue}const e=Number(i.trim()),o=t[e-1];if(void 0!==o&&Ft(o))throw new n(`GROUP BY position ${e} refers to an aggregate expression ("${o.trim()}")`,"QUERY_ERROR",{position:e});s.push(a(e,"GROUP BY"))}e.groupBy=s}}normalizeUnprefixedReferences(e,t){const s=t.filter(e=>!!e);e.where&&Object.keys(e.where).length>0&&(e.where=this.normalizeWhereColumns(e.where,s)),e.orderBy&&e.orderBy.length>0&&(e.orderBy=e.orderBy.map(e=>({...e,column:jt(this.stripAlias(e.column,s))}))),e.groupBy&&e.groupBy.length>0&&(e.groupBy=e.groupBy.map(e=>jt(this.stripAlias(e,s)))),e.columns=e.columns.map(e=>{if("*"===e||Kt(e)||/^\s*CASE\b/i.test(e)||/^'/.test(e))return e;const t=e.match(/^(.+?)\s+AS\s+(\w+)$/i);if(t){const n=this.stripAlias(t[1].trim(),s);return n===t[1].trim()?e:`${n} AS ${t[2]}`}return this.stripAlias(e,s)})}normalizeWhereColumns(e,t){const s={};for(const[n,i]of Object.entries(e))"$and"!==n&&"$or"!==n?"$not"!==n?"$exists"!==n?s[jt(this.stripAlias(n,t))]=this.normalizeFieldValue(i,t):s[n]=this.normalizeExistsValue(i,t):s.$not=this.normalizeWhereColumns(i,t):s[n]=i.map(e=>this.normalizeWhereColumns(e,t));return s}normalizeExistsValue(e,t){if("object"!=typeof e||null===e)return e;const s=e;if(s.$subquery){const e=s.$subquery,n=[e.alias??e.from,...t].filter(Boolean);return{...s,$subquery:{...e,where:this.normalizeWhereColumns(e.where,n)}}}return e}normalizeFieldValue(e,t){if("object"!=typeof e||null===e||Array.isArray(e))return e;const s={};for(const[n,i]of Object.entries(e))"$and"===n||"$or"===n?s[n]=i.map(e=>this.normalizeWhereColumns(e,t)):"$not"===n&&"object"==typeof i&&null!==i?s[n]=this.normalizeFieldValue(i,t):"$col"===n?s[n]=jt(this.stripAlias(String(i),t)):"object"==typeof i&&null!==i&&!Array.isArray(i)&&"$col"in i?s[n]={$col:jt(this.stripAlias(String(i.$col),t))}:s[n]=i;return s}stripAlias(e,t){for(const s of t){if(!s)continue;const t=`${s}.`;if(e.startsWith(t))return e.slice(t.length)}return e}hasCorrelatedRefs(e){for(const[t,s]of Object.entries(e))if("$and"!==t&&"$or"!==t){if("$not"!==t){if("$exists"!==t){if(/^\s*CASE\b/i.test(t))return!0;if(this.fieldHasColRef(s))return!0}else if("object"==typeof s&&null!==s&&"$subquery"in s)return!0}else if(this.hasCorrelatedRefs(s))return!0}else if(s.some(e=>this.hasCorrelatedRefs(e)))return!0;return!1}fieldHasColRef(e){if("object"!=typeof e||null===e||Array.isArray(e))return!1;const t=e;if("$col"in t)return!0;if("$and"in t||"$or"in t)return(t.$and??t.$or).some(e=>this.hasCorrelatedRefs(e));if("$not"in t&&"object"==typeof t.$not&&null!==t.$not)return this.fieldHasColRef(t.$not);for(const[,e]of Object.entries(t))if("object"==typeof e&&null!==e&&!Array.isArray(e)){if("$col"in e)return!0;if(this.fieldHasColRef(e))return!0}return!1}enginePreFilter(e){const t={};for(const[s,n]of Object.entries(e)){if("$and"===s){const e=n.map(e=>this.enginePreFilter(e)).filter(e=>Object.keys(e).length>0);e.length>0&&(t.$and=e);continue}if("$or"===s){const e=n;if(e.some(e=>!this.isEngineEvaluable(e)))continue;t.$or=e.map(e=>this.enginePreFilter(e));continue}if("$not"===s){const e=n;if(!this.isEngineEvaluable(e))continue;t.$not=this.enginePreFilter(e);continue}"$exists"!==s&&(/^\s*CASE\b/i.test(s)||this.fieldHasColRef(n)||this.fieldHasSubquery(n)||(t[s]=n))}return t}isEngineEvaluable(e){for(const[t,s]of Object.entries(e))if("$and"!==t&&"$or"!==t){if("$not"!==t){if("$exists"===t)return!1;if(/^\s*CASE\b/i.test(t))return!1;if(this.fieldHasColRef(s)||this.fieldHasSubquery(s))return!1}else if(!this.isEngineEvaluable(s))return!1}else if(s.some(e=>!this.isEngineEvaluable(e)))return!1;return!0}fieldHasSubquery(e){if("object"!=typeof e||null===e||Array.isArray(e))return!1;const t=e;if("$subquery"in t)return!0;for(const[,e]of Object.entries(t)){if("object"==typeof e&&null!==e&&!Array.isArray(e)&&"$subquery"in e)return!0;if(Array.isArray(e))for(const t of e)if("object"==typeof t&&null!==t&&"$subquery"in t)return!0}return!1}async filterCorrelated(e,t,s=[]){const n=[];for(const i of e){let e=this.resolveCaseKeys(t,i);e=await this.resolveSubqueries(e,i,s),k(i,e,{$col:!0})&&n.push(i)}return n}resolveCaseKeys(e,t){const s={};for(const[n,i]of Object.entries(e))if("$and"!==n&&"$or"!==n)if("$not"!==n){if(/^\s*CASE\b/i.test(n)){const e=Mt(n);if(!e)continue;const r=Pt(e,t);if(!this.caseConditionMatches(r,i))return{$caseResult:!1};s.$caseResult=!0;continue}s[n]=i}else s.$not=this.resolveCaseKeys(i,t);else s[n]=i.map(e=>this.resolveCaseKeys(e,t));return s}caseConditionMatches(e,t){if("object"!=typeof t||null===t||Array.isArray(t))return e===t;const s=t;for(const[t,n]of Object.entries(s))switch(t){case"$eq":if(e!==n)return!1;break;case"$ne":if(e===n)return!1;break;case"$gt":if(!(e>n))return!1;break;case"$gte":if(!(e>=n))return!1;break;case"$lt":if(!(e<n))return!1;break;case"$lte":if(!(e<=n))return!1;break;case"$in":if(!Array.isArray(n)||!n.includes(e))return!1;break;case"$nin":if(Array.isArray(n)&&n.includes(e))return!1}return!0}bindColumnRefs(e,t,s=[]){if("object"!=typeof e||null===e||Array.isArray(e))return e;const n={};for(const[i,r]of Object.entries(e))if("$col"===i)n[i]=this.lookupOuterValue(t,String(r),s);else if("$and"===i||"$or"===i)n[i]=r.map(e=>this.bindWhereRefs(e,t,s));else if("$not"===i&&"object"==typeof r&&null!==r)n[i]=this.bindColumnRefs(r,t,s);else if("object"==typeof r&&null!==r&&!Array.isArray(r)&&"$col"in r)n[i]=this.lookupOuterValue(t,String(r.$col),s);else if("object"==typeof r&&null!==r&&!Array.isArray(r)&&"$subquery"in r){const e=r.$subquery,a=e.where&&this.hasCorrelatedRefs(e.where)?this.bindWhereRefs(e.where,t,s):e.where;n[i]={$subquery:{...e,where:a}}}else n[i]=r;return n}lookupOuterValue(e,t,s){const n=this.stripAlias(t,s);return n in e?e[n]:t in e?e[t]:null}bindWhereRefs(e,t,s=[]){const n={};for(const[i,r]of Object.entries(e))"$and"===i||"$or"===i?n[i]=r.map(e=>this.bindWhereRefs(e,t,s)):"$not"===i?n.$not=this.bindWhereRefs(r,t,s):n[i]="$exists"===i?r:this.bindColumnRefs(r,t,s);return n}async resolveSubqueries(e,t,s=[]){t&&(e=this.bindWhereRefs(e,t,s));const n={};for(const[i,r]of Object.entries(e)){if("$exists"===i&&"object"==typeof r&&null!==r){const e=r,s=e.$subquery,i=!!e.$negate;let a=s.where;this.hasCorrelatedRefs(a)&&(a=this.bindWhereRefs(a,t??{}));const o=await this.executeSelectPart({...s,where:a});n.$exists=o.length>0!==i;continue}"$and"===i&&Array.isArray(r)?n.$and=await Promise.all(r.map(e=>this.resolveSubqueries(e,t,s))):"$or"===i&&Array.isArray(r)?n.$or=await Promise.all(r.map(e=>this.resolveSubqueries(e,t,s))):"$not"!==i||"object"!=typeof r||null===r?n[i]="object"==typeof r&&null!==r?await this.resolveOperatorSubqueries(r,t,s):r:n.$not=await this.resolveSubqueries(r,t,s)}return n}async resolveOperatorSubqueries(e,t,s=[]){const n={};for(const[i,r]of Object.entries(e))if("$and"===i&&Array.isArray(r))n.$and=await Promise.all(r.map(e=>this.resolveSubqueries(e,t,s)));else if("$or"===i&&Array.isArray(r))n.$or=await Promise.all(r.map(e=>this.resolveSubqueries(e,t,s)));else if("$not"!==i)if("object"==typeof r&&null!==r&&"$subquery"in r){let e=r.$subquery;t&&this.hasCorrelatedRefs(e.where)&&(e={...e,where:this.bindWhereRefs(e.where,t,s)});const a=await this.executeSelect(e);if("$in"===i||"$nin"===i){const e=Object.keys(a[0]||{})[0],t=a.map(t=>t[e]);n[i]=t}else if(0===a.length)n[i]=null;else{const e=Object.keys(a[0])[0];n[i]=a[0][e]}}else n[i]=r;else n.$not="object"==typeof r&&null!==r?await this.resolveOperatorSubqueries(r,t,s):r;return n}}function Ht(e){if(null==e)return"NULL";if("number"==typeof e)return Number.isFinite(e)?String(e):"NULL";if("boolean"==typeof e)return e?"TRUE":"FALSE";if("string"==typeof e)return`'${e.replace(/'/g,"''")}'`;throw new n("Object/array query parameters are not supported by SQL binding (pass JSON strings explicitly)","PARAM_ERROR")}function Qt(e,t){if(!t)return e;let s="",i=0,r=0,a=null;for(;i<e.length;){const o=e[i];if(null===a)if("'"!==o&&'"'!==o)if("-"!==o||"-"!==e[i+1])if("/"!==o||"*"!==e[i+1])if("?"!==o)s+=o,i++;else{if(r>=t.length)throw new n(`Too few query parameters: placeholder #${r+1} has no value (got ${t.length} total)`,"PARAM_ERROR");s+=Ht(t[r]),r++,i++}else{for(s+=e[i]+e[i+1],i+=2;i<e.length&&("*"!==e[i]||"/"!==e[i+1]);)s+=e[i],i++;i<e.length&&(s+=e[i]+e[i+1],i+=2)}else for(;i<e.length&&"\n"!==e[i]&&"\r"!==e[i];)s+=e[i],i++;else a=o,s+=o,i++;else{if(s+=o,o===a){if(e[i+1]===a){s+=e[i+1],i+=2;continue}a=null}i++}}if(null!==a)throw new n("Unterminated string literal in SQL","PARSE_ERROR");if(r<t.length)throw new n(`Too many query parameters: ${t.length} provided but only ${r} placeholders`,"PARAM_ERROR");return s}class Xt{constructor(e){this.tables=new Map,this.completed=!1,this.engine=e,this.executor=new Gt(e)}table(e){let t=this.tables.get(e);return t||(t=new It(this.engine,e,this.executor),this.tables.set(e,t)),t}_markCompleted(){this.completed=!0}isCompleted(){return this.completed}}class Yt{constructor(e){this.engine=e}async execute(e){const t=new Xt(this.engine);await this.engine.beginTransaction();try{const s=await e(t);return await this.engine.commitTransaction(),t._markCompleted(),s}catch(e){try{await this.engine.rollbackTransaction()}catch{}if(e instanceof n)throw e;throw new n(`Transaction failed: ${e.message}`,"TRANSACTION_ERROR",e)}}}class Jt{constructor(){this.plugins=[],this.hooks=new Map}register(e,t){const s=e.priority??0,n=this.plugins.findIndex(e=>(e.priority??0)<s);-1===n?this.plugins.push(e):this.plugins.splice(n,0,e),e.install(t)}unregister(e){const t=this.plugins.findIndex(t=>t.name===e);-1!==t&&(this.plugins[t].destroy(),this.plugins.splice(t,1))}getPlugins(){return[...this.plugins]}on(e,t){const s=this.hooks.get(e)??[];s.push(t),this.hooks.set(e,s)}off(e,t){const s=this.hooks.get(e);if(s){const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}async trigger(e,...t){const s=this.hooks.get(e);if(s)for(const e of s)await e(...t)}destroy(){for(const e of this.plugins)try{e.destroy()}catch(e){}this.plugins=[],this.hooks.clear()}}class Zt{static async create(e){const t=new Zt(e);return await t.init(),t}get version(){return this._version}get maxRowsPerQuery(){return this.config.maxRowsPerQuery??0}get debug(){return this.config.debug??!1}constructor(e){this.ready=!1,this.tableCache=new Map,this.channel=null,this.notifier=null,this.listeners=new Map,this.migrations=new Map,this.config=e,this.name=e.name??s.name,this.mode=e.mode??s.mode,this._version=e.version??s.version,this.pluginManager=new Jt,e.multiTabSync&&"undefined"!=typeof BroadcastChannel&&(this.channel=new BroadcastChannel(`metona-sqlark:${this.name}`),this.channel.onmessage=e=>{const t=e.data;if(!t||"change"!==t.type)return;this.emitExternal(t.table??"");const s=this.unwrapEngine();s instanceof St&&s.reloadMemoryFromDisk().catch(()=>{})})}async init(){if(this.engine=this.createEngine(),await this.engine.open(this.name,this.version),this.engine=new r(this.engine,e=>this._onError(e),e=>this.broadcastChange(e)),this.notifier=this.engine,this.notifier.addListener(async e=>{const t=this.listeners.get(`change:${e.table}`);if(t&&0!==t.size)for(const s of[...t])try{await s(e)}catch(e){this._onError(e)}}),"function"==typeof this.engine.getMeta)try{const e=await this.engine.getMeta("__metona_version");null!=e&&Number(e)>=1&&(this._version=Math.max(this._version,Math.floor(Number(e))))}catch{}if(this.executor=new Gt(this.engine,this.maxRowsPerQuery),this.transactionManager=new Yt(this.engine),this.config.plugins){const e=this.config.plugins.map((e,t)=>({plugin:e,index:t})).sort((e,t)=>(t.plugin.priority??0)-(e.plugin.priority??0)||e.index-t.index).map(e=>e.plugin);for(const t of e)this.pluginManager.register(t,this)}this.ready=!0,this.config.onReady&&this.config.onReady(this)}isReady(){return this.ready}async defineTable(e,t){this.ensureReady();const s=W(e,t);try{await this.pluginManager.trigger("beforeCreateTable",s),await this.engine.createTable(s),await this.pluginManager.trigger("afterCreateTable",s)}catch(e){throw this._onError(e),e}this.tableCache.delete(e)}table(e){this.ensureReady();let t=this.tableCache.get(e);return t||(t=new It(this.engine,e,this.executor,()=>{},(e,t)=>this.pluginManager.trigger(e,...t)),this.tableCache.set(e,t)),t}async dropTable(e){this.ensureReady();try{await this.pluginManager.trigger("beforeDropTable",e),await this.engine.dropTable(e),await this.pluginManager.trigger("afterDropTable",e)}catch(e){throw this._onError(e),e}this.tableCache.delete(e)}async getTableNames(){return this.ensureReady(),this.engine.getTableNames()}async query(e,t){this.ensureReady();const s=this.debug?Date.now():0;let n;await this.pluginManager.trigger("beforeQuery",e);try{const s=vt(Qt(e,t));for(const e of s)await this.triggerStatementHooks(e,"before"),n=await this.executor.execute(e),await this.triggerStatementHooks(e,"after",n)}catch(e){throw this._onError(e),e}if(await this.pluginManager.trigger("afterQuery",e,n),this.debug){const t=Date.now()-s,i=Array.isArray(n)?n.length:0;this._debug(`query [${t}ms] ${i} rows: ${e.slice(0,100)}`)}return n}async queryStream(e,t){this.ensureReady();const s=vt(e);if(1!==s.length)throw new n("queryStream requires exactly one SELECT statement","PARSE_ERROR");const i=s[0];if(!i||"SELECT"!==i.type)throw new n("queryStream only supports SELECT statements","NOT_SUPPORTED");const r=i,a=this.executor.analyzeSelect(r);if(0===r.limit)return 0;if(this.isAsyncCallback(t)){const s=await this.query(e);if(!Array.isArray(s))return 0;for(const e of s)await t(e);return s.length}if(a.streamable&&"function"==typeof this.engine.findStream){const e=this.normalizeWhereForStream(r),s=[r.alias??r.from].filter(Boolean),n=r.columns.length>0?r.columns.map(e=>this.stripAliasPrefix(e,s)):["*"],i=this.maxRowsPerQuery;let a=0;const o=await this.engine.findStream(r.from,{table:r.from,columns:n,where:e&&Object.keys(e).length>0?e:void 0,limit:r.limit,offset:r.offset},e=>{i>0&&a>=i||(a++,t(e))});return i>0?Math.min(o,i):o}const o=await this.query(e);if(Array.isArray(o)){for(const e of o)await t(e);return o.length}return 0}isAsyncCallback(e){const t=e.constructor?.name;if("AsyncFunction"===t)return!0;try{return/^\s*async\b/.test(Function.prototype.toString.call(e))}catch{return!1}}stripAliasPrefix(e,t){for(const s of t)if(s&&e.startsWith(`${s}.`))return e.slice(s.length+1);return e}normalizeWhereForStream(e){const t=[e.alias??e.from].filter(Boolean),s=e=>{for(const s of t)if(e.startsWith(`${s}.`))return e.slice(s.length+1);return e},n=e=>{const t={};for(const[i,r]of Object.entries(e))"$and"===i||"$or"===i?t[i]=r.map(n):"$not"===i&&"object"==typeof r&&null!==r?t.$not=n(r):t[s(i)]=r;return t};return n(e.where??{})}async transaction(e){this.ensureReady(),await this.pluginManager.trigger("beforeTransaction");try{const t=await this.transactionManager.execute(e);return await this.pluginManager.trigger("afterTransaction"),t}catch(e){throw this._onError(e),e}}async exportTable(e){return this.ensureReady(),this.engine.find(e,{table:e})}async importTable(e,t){this.ensureReady();try{return await this.engine.insert(e,t)}catch(e){throw this._onError(e),e}}async exportAll(){this.ensureReady();const e={},t=await this.engine.getTableNames();for(const s of t)e[s]=await this.engine.find(s,{table:s});return e}async backup(){return this.ensureReady(),"function"==typeof this.engine.backup?this.engine.backup():this.exportAll()}subscribe(e,t){const s=`change:${e}`;return this.listeners.has(s)||this.listeners.set(s,new Set),this.listeners.get(s).add(t),()=>{this.listeners.get(s)?.delete(t)}}async emit(e,t){await this.dispatchChange({table:e,...t})}async emitExternal(e){const t={type:"external",table:e},s=this.listeners.get(`change:${e}`);if(s)for(const e of[...s])try{await e(t)}catch(e){this._onError(e)}}async dispatchChange(e){this.notifier?await this.notifier.dispatch(e):this.broadcastChange(e.table)}broadcastChange(e){if(this.channel)try{this.channel.postMessage({type:"change",table:e})}catch{}}writeStatementTable(e){switch(e.type){case"INSERT":return e.into;case"UPDATE":case"CREATE_INDEX":case"DROP_INDEX":return e.table;case"DELETE":return e.from;case"CREATE_TABLE":case"DROP_TABLE":case"TRUNCATE_TABLE":case"ALTER_TABLE":return e.name;default:return null}}async triggerStatementHooks(e,t,s){switch(e.type){case"INSERT":{let n=e.columns??[];if(0===n.length)try{const t=await this.engine.getTableSchema(e.into);n=t?Object.keys(t.columns):[]}catch{n=[]}const i=(e.values??[]).map(e=>{const t={};for(let s=0;s<e.length;s++)t[n[s]??String(s)]=e[s];return t});"before"===t?await this.pluginManager.trigger("beforeInsert",i):await this.pluginManager.trigger("afterInsert",i,s);break}case"UPDATE":{const n={table:e.table,where:e.where};"before"===t?await this.pluginManager.trigger("beforeUpdate",n,e.sets):await this.pluginManager.trigger("afterUpdate",n,e.sets,s);break}case"DELETE":{const n={table:e.from,where:e.where};"before"===t?await this.pluginManager.trigger("beforeDelete",n):await this.pluginManager.trigger("afterDelete",n,s);break}}}addMigration(e,t){this.migrations.set(e,t)}async migrateTo(e){this.ensureReady();for(const[t,s]of[...this.migrations.entries()].sort((e,t)=>e[0]-t[0]))t<=e&&t>this._version&&(await s(this),this._version=t);if("function"==typeof this.engine.setMeta)try{await this.engine.setMeta("__metona_version",String(this._version))}catch{}}async repair(){if(this.ensureReady(),"function"==typeof this.engine.repair)return await this.engine.repair(),void this.tableCache.clear();this.tableCache.clear()}async clearAll(){if(this.ensureReady(),"function"==typeof this.engine.clearAll)await this.engine.clearAll();else{const e=await this.engine.getTableNames();for(const t of e)await this.engine.dropTable(t)}this.tableCache.clear()}getPluginManager(){return this.pluginManager}on(e,t){this.pluginManager.on(e,t)}async close(){this.channel&&(this.channel.close(),this.channel=null),this.pluginManager.destroy(),this.engine&&await this.engine.close(),this.tableCache.clear(),this.ready=!1}getEngine(){return this.unwrapEngine()}unwrapEngine(){return this.notifier?this.notifier.getInner():this.engine}createEngine(){const e=this.mode,t=this.config.diskEngine??"opfs";switch(e){case"memory":return new Q;case"disk":return new ge;case"aria":return new Et({storageBackend:"memory"===t?"memory":"kv"===t?"kv":"opfs",...this.config.aria??{}});case"hybrid":return new St(t);default:throw new n(`Unknown storage mode: ${e}`,"CONFIG_ERROR")}}ensureReady(){if(!this.ready)throw new n("Database not initialized. Call await db.init() first.","DB_NOT_READY")}_onError(e){if(this.config.onError)try{this.config.onError(e)}catch{}}_debug(e,...t){this.debug}}const es=new class{constructor(){this.connections=new Map,this.refCount=new Map}async connect(e){const t=e.name,s=this.connections.get(t);if(s&&s.isReady()){const e=(this.refCount.get(t)??0)+1;return this.refCount.set(t,e),s}const n=new Zt(e);return await n.init(),this.connections.set(t,n),this.refCount.set(t,1),n.disconnect=async()=>{await this.release(t)},n}async release(e){const t=(this.refCount.get(e)??1)-1;if(t<=0){const t=this.connections.get(e);t&&(await t.close(),this.connections.delete(e)),this.refCount.delete(e)}else this.refCount.set(e,t)}async forceClose(e){const t=this.connections.get(e);t&&(await t.close(),this.connections.delete(e)),this.refCount.delete(e)}async closeAll(){for(const[,e]of this.connections)try{await e.close()}catch{}this.connections.clear(),this.refCount.clear()}getActiveConnections(){return Array.from(this.connections.keys())}};Zt.connect=e=>es.connect(e),Zt.disconnect=e=>es.release(e),Zt.disconnectAll=()=>es.closeAll(),Zt.getActiveConnections=()=>es.getActiveConnections();const ts="__metona_schema";function ss(e){return"number"==typeof e?"number":"boolean"==typeof e?"boolean":"object"==typeof e&&null!==e?"json":"string"}function ns(e,t){const s={};if(0===t.length)return{name:e,columns:s};const n=t[0],i=Object.keys(n),r=i.includes("id")?"id":i.find(e=>"json"!==ss(n[e]));if(!r)return null;for(const e of i)s[e]={type:ss(n[e]),primaryKey:e===r};return{name:e,columns:s}}function is(e){return new Promise((t,s)=>{const n=e.getAll();n.onsuccess=()=>t(n.result??[]),n.onerror=()=>s(n.error)})}async function rs(e){return Zt.create(e)}const as={VERSION:i,version:i,create:rs,MetonaSqlark:Zt,MeSqlark:Zt};"undefined"!=typeof window&&(window.MetonaSqlark=as,window.MeSqlark=as);const os=Zt;e.AriaEngine=Et,e.DatabaseError=n,e.HybridEngine=St,e.KVStoreEngine=ge,e.MeSqlark=os,e.MemoryEngine=Q,e.MetonaSqlark=Zt,e.OPFSBackend=Y,e.PluginManager=Jt,e.Table=It,e.Transaction=Xt,e.TransactionManager=Yt,e.VERSION=i,e.api=as,e.bindParameters=Qt,e.create=rs,e.default=as,e.migrateFromIndexedDB=async function(e){if("aria"===e.engine)throw new Error("Migration from AriaEngine IndexedDB backend is not supported (data is stored in engine-private SSTable/WAL format). Only disk-mode IndexedDBEngine databases can be migrated.");const t=e.dbName;let s=null;try{s=await function(e){return new Promise((t,s)=>{const n=indexedDB.open(e);n.onsuccess=()=>t(n.result),n.onerror=()=>s(n.error??new Error(`Failed to open legacy IndexedDB "${e}"`))})}(t)}catch(e){throw new Error(`Legacy IndexedDB database "${t}" not found or unreadable: ${e.message}`)}const n={migratedTables:[],rowCount:0,skippedTables:[]},i=await function(e){return e.objectStoreNames.contains(ts)?new Promise((t,s)=>{const n=e.transaction(ts,"readonly").objectStore(ts).getAll();n.onsuccess=()=>{const e={};for(const t of n.result??[])if(t.schema)try{const s=JSON.parse(t.schema);e[s.name]=s}catch{}t(e)},n.onerror=()=>s(n.error)}):Promise.resolve({})}(s);try{const t=Array.from(s.objectStoreNames).filter(e=>e!==ts);for(let r=0;r<t.length;r++){const a=t[r];e.onProgress?.(r,t.length,a);const o=await is(s.transaction(a,"readonly").objectStore(a));if((await e.target.getTableNames()).includes(a)){n.skippedTables.push(a);continue}let h=i[a];if(!h){if(0===o.length){n.skippedTables.push(a);continue}const e=ns(a,o);if(!e){n.skippedTables.push(a);continue}h=e}await e.target.defineTable(a,h.columns),o.length>0&&await e.target.table(a).insertMany(o),n.migratedTables.push(a),n.rowCount+=o.length}}finally{s.close()}return n},e.parse=function(e){return new $t(e).parseStatement()},e.parseAll=vt,e.parseWhereCondition=Dt,e.tokenize=Lt,Object.defineProperty(e,"__esModule",{value:!0})});
|