@easbot/database 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
- 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var module$1=require('module'),m=require('fs'),h=require('path'),pg=require('pg');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var m__namespace=/*#__PURE__*/_interopNamespace(m);var h__namespace=/*#__PURE__*/_interopNamespace(h);var V=Object.defineProperty;var j=(n,e,t)=>e in n?V(n,e,{enumerable:true,configurable:true,writable:true,value:t}):n[e]=t;var i=(n,e,t)=>j(n,typeof e!="symbol"?e+"":e,t);var U=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,c=U();var S=class extends Error{constructor(t,r,a){super(r);i(this,"code");i(this,"cause");this.name="DatabaseError",this.code=t,this.cause=a;}},o=class extends S{constructor(e,t){super("CONNECTION",e,t),this.name="ConnectionError";}},d=class extends S{constructor(e,t){super("QUERY",e,t),this.name="QueryError";}},l=class extends S{constructor(e,t){super("TX",e,t),this.name="TransactionError";}},T=(n,e)=>{if(e==="qmark")return n;let t=0;return n.replace(/\?/g,()=>`$${++t}`)},x=n=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(n);var J=module$1.createRequire(c),B=(n,e)=>{try{let t=J(n);return e(t)}catch{return false}},f=()=>{if(B("better-sqlite3",n=>typeof n.default=="function"))return "better-sqlite3";if(B("node:sqlite",n=>typeof n.DatabaseSync=="function"))return "node:sqlite";if(B("@tursodatabase/database",n=>typeof(n.default??n)=="function"))return "@tursodatabase/database";throw new o(`No SQLite backend available. Please install one of:
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var module$1=require('module'),m=require('fs'),h=require('path'),pg=require('pg');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var m__namespace=/*#__PURE__*/_interopNamespace(m);var h__namespace=/*#__PURE__*/_interopNamespace(h);var V=Object.defineProperty;var j=(r,e,t)=>e in r?V(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t;var i=(r,e,t)=>j(r,typeof e!="symbol"?e+"":e,t);var U=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,c=U();var S=class extends Error{constructor(t,n,a){super(n);i(this,"code");i(this,"cause");this.name="DatabaseError",this.code=t,this.cause=a;}},o=class extends S{constructor(e,t){super("CONNECTION",e,t),this.name="ConnectionError";}},d=class extends S{constructor(e,t){super("QUERY",e,t),this.name="QueryError";}},l=class extends S{constructor(e,t){super("TX",e,t),this.name="TransactionError";}},T=(r,e)=>{if(e==="qmark")return r;let t=0;return r.replace(/\?/g,()=>`$${++t}`)},x=r=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(r);var J=module$1.createRequire(c),D=(r,e)=>{try{let t=J(r);return e(t)}catch{return false}},f=()=>{if(D("better-sqlite3",r=>typeof r.default=="function"))return "better-sqlite3";if(D("node:sqlite",r=>typeof r.DatabaseSync=="function"))return "node:sqlite";if(D("@tursodatabase/database",r=>typeof(r.default??r)=="function"))return "@tursodatabase/database";throw new o(`No SQLite backend available. Please install one of:
2
2
  - better-sqlite3 (recommended; highest perf)
3
3
  - node:sqlite (built-in since Node.js 22.5+)
4
- - @tursodatabase/database`)};var y=class{constructor(e){i(this,"stmt",e);}run(...e){return this.stmt.run(...e)}get(...e){return this.stmt.get(...e)}all(...e){return this.stmt.all(...e)}iterate(...e){return this.stmt.iterate(...e)}};var X=module$1.createRequire(c),F=n=>typeof n=="function"&&n.prototype!==void 0,w=class{constructor(e,t={}){i(this,"backend","better-sqlite3");i(this,"db");let r=X("better-sqlite3"),a=F(r)?r:r.default;if(!F(a))throw new TypeError(`better-sqlite3 import did not expose a constructor (got ${typeof r})`);this.db=new a(e,t);}exec(e){this.db.exec(e);}prepare(e){return new y(this.db.prepare(e))}pragma(e,t){return this.db.pragma(e,t)}transaction(e){return this.db.transaction(e)}close(){this.db.open&&this.db.close();}get open(){return this.db.open}};var te=module$1.createRequire(c),b=class{constructor(e){i(this,"backend","node:sqlite");i(this,"db");let t=te("node:sqlite");this.db=new t.DatabaseSync(e);}exec(e){this.db.exec(e);}prepare(e){return new y(this.db.prepare(e))}pragma(e,t){return this.db.exec(`PRAGMA ${e}`),t?.simple!==true?void 0:this.db.prepare("SELECT pragma_value AS v FROM pragma_value(?)").get(e)}transaction(e){return((...r)=>{this.db.exec("BEGIN");let a;try{a=e(...r);}catch(s){try{this.db.exec("ROLLBACK");}catch{}throw s}return this.db.exec("COMMIT"),a})}close(){this.db.isOpen&&this.db.close();}get open(){return this.db.isOpen}};var re=module$1.createRequire(c),M=n=>typeof n=="function"&&n.prototype!==void 0,k=class{constructor(e){i(this,"backend","@tursodatabase/database");i(this,"db",null);let t=re("@tursodatabase/database"),r=M(t)?t:t.default;if(!M(r))throw new TypeError(`@tursodatabase/database import did not expose a constructor (got ${typeof t})`);this.db=new r(e);}requireDb(){if(!this.db)throw new Error(`Turso backend not initialized (db=${String(this.db)})`);return this.db}exec(e){this.requireDb().exec(e);}prepare(e){return new y(this.requireDb().prepare(e))}pragma(e){this.requireDb().exec(`PRAGMA ${e}`);}transaction(e){return((...r)=>{let a=this.requireDb();a.exec("BEGIN");let s;try{s=e(...r);}catch(u){try{a.exec("ROLLBACK");}catch{}throw u}return a.exec("COMMIT"),s})}close(){if(this.db)try{this.db.close();}finally{this.db=null;}}get open(){return this.db!==null}};var ae=256,O=class{constructor(e){i(this,"backend",e);i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let r=this.backend.prepare(e);if(this.cache.size>=ae){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,r),r}clear(){this.cache.clear();}},Q=n=>n==null?{}:typeof n!="object"?{}:{...n},ie=n=>n.map(Q);function E(n){if(!x(n))throw new l(`Unsafe SQL identifier: ${JSON.stringify(n)}`);return `"${n}"`}function se(n){let e=n.trimStart();if(e.length===0)return false;let a=((e.split(`
5
- `,1)[0]??"").trimStart().split(/\s+/,1)[0]??"").toUpperCase();return a==="CREATE"||a==="DROP"||a==="ALTER"||a==="TRUNCATE"||a==="REPLACE"}var L=class{constructor(e,t){i(this,"db",e);i(this,"depth");i(this,"finished",false);this.depth=t;}isFinished(){return this.finished}async query(e,t){return this.assertOpen(),this.db.query(e,t)}async queryOne(e,t){return this.assertOpen(),this.db.queryOne(e,t)}async execute(e,t){return this.assertOpen(),this.db.execute(e,t)}async exec(e){this.assertOpen(),await this.db.exec(e);}async commit(){this.finished||(this.finished=true,this.depth===1&&this.db.commitRoot(),this.db.popTxDepth());}async rollback(){if(!this.finished){this.finished=true;try{this.depth===1?this.db.rollbackRoot():this.db.rollbackToSavepoint(`sp_${this.depth}`);}catch{}this.db.popTxDepth();}}async savepoint(e){this.assertOpen(),this.db.execSavepoint(E(e));}async release(e){this.assertOpen(),this.db.execRelease(E(e));}async rollbackTo(e){this.assertOpen(),this.db.execRollbackTo(E(e));}assertOpen(){if(this.finished)throw new l(`Transaction already finalized (depth=${this.depth})`)}},R=class{constructor(e){i(this,"config",e);i(this,"flavor","sqlite");i(this,"sqliteBackend");i(this,"backend",null);i(this,"stmtCache",null);i(this,"inTxDepth",0);i(this,"readOnlyFlag",false);i(this,"initialized",false);i(this,"walShmSymlink",null);i(this,"effectiveDbPath",null);let t=e.sqlite??{};this.sqliteBackend=t.backend===void 0||t.backend==="auto"?f():t.backend;}async initialize(){if(this.initialized)return;let e=this.config.sqlite??{},t=e.path??":memory:",r=e.walMode!==false,a=e.foreignKeys!==false,s=e.readonly===true,u=e.busyTimeoutMs??5e3,q=e.walShmPath,_=this.resolveOpenPath(t,q);try{this.backend=this.createBackend(_,{readonly:s});}catch(D){throw this.cleanupWalShmSymlink(),new o(`Failed to create SQLite backend (${this.sqliteBackend}) at "${_}"`,D)}this.readOnlyFlag=s,this.stmtCache=new O(this.backend);try{!s&&t!==":memory:"&&r&&this.backend.exec("PRAGMA journal_mode = WAL"),!s&&a&&this.backend.exec("PRAGMA foreign_keys = ON"),this.backend.exec(`PRAGMA busy_timeout = ${u}`);}catch(D){throw this.backend=null,this.stmtCache=null,this.cleanupWalShmSymlink(),new o("Failed to apply SQLite pragmas",D)}this.initialized=true;}resolveOpenPath(e,t){if(e===":memory:"||t===void 0||t===""||this.sqliteBackend!=="better-sqlite3")return e;let r=h__namespace.dirname(e);if(h__namespace.resolve(r)===h__namespace.resolve(t))return e;let a=h__namespace.basename(e),s=h__namespace.join(t,a);try{try{let u=m__namespace.lstatSync(s);(u.isSymbolicLink()||u.isFile())&&m__namespace.unlinkSync(s);}catch{}return m__namespace.symlinkSync(h__namespace.resolve(e),s),this.walShmSymlink=s,this.effectiveDbPath=s,s}catch(u){throw new o(`Failed to create symlink for WAL at "${t}" \u2192 "${e}". Check directory existence & write permission.`,u)}}cleanupWalShmSymlink(){if(this.walShmSymlink){try{m__namespace.unlinkSync(this.walShmSymlink);}catch{}this.walShmSymlink=null,this.effectiveDbPath=null;}}createBackend(e,t){switch(this.sqliteBackend){case "better-sqlite3":return new w(e,{readonly:t.readonly});case "node:sqlite":return new b(e);case "@tursodatabase/database":return new k(e);default:throw new o(`Unsupported SQLite backend: ${String(this.sqliteBackend)}`)}}async close(){if(!this.backend){this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();return}try{this.backend.close();}finally{this.backend=null,this.stmtCache?.clear(),this.stmtCache=null,this.inTxDepth=0,this.initialized=false,this.cleanupWalShmSymlink();}}isConnected(){return this.backend?.open===true}isReadOnly(){return this.readOnlyFlag}requireBackend(){if(!this.backend)throw new o("SQLite database not initialized. Call initialize() first.");return this.backend}requireCache(){if(!this.stmtCache)throw new o("SQLite database not initialized. Call initialize() first.");return this.stmtCache}async query(e,t){let r=this.prepareOrThrow(e);try{return ie(r.all(...t??[]))}catch(a){throw new d(`SQLite query failed: ${this.errorMessage(a)}`,a)}}async queryOne(e,t){let r=this.prepareOrThrow(e);try{let a=r.get(...t??[]);return a==null?null:Q(a)}catch(a){throw new d(`SQLite queryOne failed: ${this.errorMessage(a)}`,a)}}async execute(e,t){let r=this.prepareOrThrow(e);try{return r.run(...t??[])}catch(a){throw new d(`SQLite execute failed: ${this.errorMessage(a)}`,a)}}prepareOrThrow(e){try{return this.requireCache().get(e)}catch(t){throw t instanceof o?t:new d(`SQLite prepare failed: ${this.errorMessage(t)}`,t)}}async exec(e){let t=this.requireBackend();try{t.exec(e),se(e)&&this.stmtCache?.clear();}catch(r){throw new d(`SQLite exec failed: ${this.errorMessage(r)}`,r)}}async execBatch(e){for(let t of e)await this.exec(t);}async begin(){let e=this.requireBackend();if(this.readOnlyFlag)throw new l("Cannot begin transaction on read-only SQLite database");let t=this.pushTxDepth();try{t===1?e.exec("BEGIN"):e.exec(`SAVEPOINT sp_${t}`);}catch(r){this.popTxDepth();let a=t===1?"BEGIN":`SAVEPOINT sp_${t}`;throw new l(`${a} failed`,r)}return new L(this,t)}async withTransaction(e){let t=await this.begin();try{let r=await e(t);return await t.commit(),r}catch(r){try{await t.rollback();}catch{}throw r}}getTransactionDepth(){return this.inTxDepth}commitRoot(){this.requireBackend().exec("COMMIT");}rollbackRoot(){this.requireBackend().exec("ROLLBACK");}rollbackToSavepoint(e){this.requireBackend().exec(`ROLLBACK TO SAVEPOINT ${e}`);}execSavepoint(e){this.requireBackend().exec(`SAVEPOINT ${e}`);}execRelease(e){this.requireBackend().exec(`RELEASE SAVEPOINT ${e}`);}execRollbackTo(e){this.requireBackend().exec(`ROLLBACK TO SAVEPOINT ${e}`);}pushTxDepth(){return this.inTxDepth+=1}popTxDepth(){this.inTxDepth>0&&(this.inTxDepth-=1);}errorMessage(e){return e instanceof Error?e.message:String(e)}};var le=256,$=class{constructor(){i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let r=T(e,"numbered");if(this.cache.size>=le){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,r),r}clear(){this.cache.clear();}},ce=n=>n==null?{}:{...n},de=n=>n.map(e=>ce(e)),I=n=>{if(!x(n))throw new l(`Unsafe SQL identifier: ${JSON.stringify(n)}`);return `"${n}"`};function K(n,e){return n.includes("?")?{sql:T(n,"numbered"),params:e?[...e]:[]}:{sql:n,params:void 0}}var C=class{constructor(e,t){i(this,"db",e);i(this,"depth");i(this,"finished",false);this.depth=t;}get client(){return this.db.getClient(this.depth)}isFinished(){return this.finished}assertOpen(){if(this.finished)throw new l("Transaction already finalized")}async query(e,t){return this.assertOpen(),await W(this.client,e,t)}async queryOne(e,t){let r=await this.query(e,t);return r.length>0?r[0]??null:null}async execute(e,t){return this.assertOpen(),await G(this.client,e,t)}async exec(e){this.assertOpen(),await z(this.client,e);}async commit(){if(!this.finished)if(this.finished=true,this.depth===1)try{await this.client.query("COMMIT");}finally{this.db.releaseTxClient(false),this.db.clearTxCtx();}else await this.client.query(`RELEASE SAVEPOINT sp_${this.depth}`);}async rollback(){if(!this.finished)if(this.finished=true,this.depth===1)try{await this.client.query("ROLLBACK");}catch{}finally{this.db.releaseTxClient(false),this.db.clearTxCtx();}else try{await this.client.query(`ROLLBACK TO SAVEPOINT sp_${this.depth}`);}catch{}}async savepoint(e){this.assertOpen(),await this.client.query(`SAVEPOINT ${I(e)}`);}async release(e){this.assertOpen(),await this.client.query(`RELEASE SAVEPOINT ${I(e)}`);}async rollbackTo(e){this.assertOpen(),await this.client.query(`ROLLBACK TO SAVEPOINT ${I(e)}`);}};async function W(n,e,t){let{sql:r,params:a}=K(e,t);try{let s=await n.query(r,a);return de(s.rows)}catch(s){throw new d(`PostgreSQL query failed: ${s instanceof Error?s.message:String(s)}`,s)}}async function G(n,e,t){let{sql:r,params:a}=K(e,t);try{return {changes:(await n.query(r,a)).rowCount??0}}catch(s){throw new d(`PostgreSQL execute failed: ${s instanceof Error?s.message:String(s)}`,s)}}async function z(n,e){try{await n.query(e);}catch(t){throw new d(`PostgreSQL exec failed: ${t instanceof Error?t.message:String(t)}`,t)}}async function ue(n,e){if(e.length===0)return;let t=e.join(`;
6
- `)+";";await z(n,t);}var v=class{constructor(e){i(this,"config",e);i(this,"flavor","postgresql");i(this,"sqliteBackend");i(this,"pool",null);i(this,"translatedSqlCache",new $);i(this,"txCtx",null);i(this,"lastTxDepth",0);}async initialize(){if(!this.pool)try{this.pool=new pg.Pool({host:this.config.host??"localhost",port:this.config.port??5432,user:this.config.username??"postgres",password:this.config.password??"",database:this.config.database??"eas_database",ssl:this.config.ssl??!1,max:this.config.poolSize??10}),(await this.pool.connect()).release();}catch(e){throw this.pool=null,new o("Failed to connect to PostgreSQL",e)}}async close(){if(!this.pool)return;let e=this.pool;this.pool=null;try{await e.end();}catch(t){throw new o("Failed to close PostgreSQL pool",t)}finally{this.translatedSqlCache.clear(),this.txCtx=null,this.lastTxDepth=0;}}isConnected(){return this.pool===null?false:!this.pool.ended&&!this.pool.closing}requirePool(){if(!this.pool)throw new o("PostgreSQL database not initialized. Call initialize() first.");return this.pool}async query(e,t){let r=await this.requirePool().connect();try{return await W(r,e,t)}finally{r.release();}}async queryOne(e,t){let r=await this.query(e,t);return r.length>0?r[0]??null:null}async execute(e,t){let r=await this.requirePool().connect();try{return await G(r,e,t)}finally{r.release();}}async exec(e){let t=await this.requirePool().connect();try{await z(t,e);}finally{t.release();}}async execBatch(e){if(e.length===0)return;let t=await this.requirePool().connect();try{await ue(t,e);}finally{t.release();}}async begin(){let e=this.requirePool(),t=this.pushTxDepth();if(t>1){let a=this.requireCtx(t);try{await a.client.query(`SAVEPOINT sp_${t}`);}catch(s){throw this.popTxDepth(),new l(`SAVEPOINT sp_${t} failed`,s)}return new C(this,t)}let r;try{r=await e.connect();}catch(a){throw this.popTxDepth(),new l("BEGIN failed: cannot acquire client",a)}try{await r.query("BEGIN");}catch(a){throw r.release(true),this.popTxDepth(),new l("BEGIN failed",a)}return this.txCtx={client:r,depth:t},new C(this,t)}requireCtx(e){if(!this.txCtx)throw new l(`No active transaction (depth=${e})`);return this.txCtx}getClient(e){return this.requireCtx(e).client}clearTxCtx(){this.txCtx=null,this.lastTxDepth=0,this.translatedSqlCache.clear();}releaseTxClient(e){let t=this.txCtx;if(t)try{t.client.release(e);}catch{}}async withTransaction(e){let t=await this.begin();try{let r=await e(t);return await t.commit(),r}catch(r){try{await t.rollback();}catch{}throw r}}pushTxDepth(){return this.lastTxDepth+=1}popTxDepth(){this.lastTxDepth>0&&(this.lastTxDepth-=1);}getTransactionDepth(){return this.lastTxDepth}};var P=class{static create(e){switch(e.flavor){case "sqlite":return new R(e);case "postgresql":return new v(e);default:{let t=e.flavor;throw new o(`Unsupported database flavor: ${String(t)}`)}}}};var he=256,A=class{constructor(e){i(this,"flavor","sqlite");i(this,"sqliteBackend");i(this,"backend",null);i(this,"stmtCache",null);i(this,"readOnlyFlag",false);i(this,"initialized",false);i(this,"walShmSymlink",null);i(this,"effectiveDbPath",null);i(this,"dbPath");this.sqliteBackend=e.backend===void 0||e.backend==="auto"?f():e.backend,this.dbPath=e.path??":memory:";}resolveBackendPath(e){return e===":memory:"?"":e}initialize(){if(this.initialized)return;let e=this.walModeDefault(),t=this.foreignKeysDefault(),r=this.readonlyDefault(),a=this.busyTimeoutDefault(),s=this.resolveOpenPath(this.dbPath,e?this.walShmPathDefault():void 0),u=s===":memory:"?"":s;try{this.backend=this.createBackend(u,{readonly:r});}catch(q){throw this.cleanupWalShmSymlink(),new o(`Failed to create SQLite backend (${this.sqliteBackend}) at "${s}"`,q)}this.readOnlyFlag=r,this.stmtCache=new N(this.backend);try{!r&&this.dbPath!==":memory:"&&e&&this.backend.exec("PRAGMA journal_mode = WAL"),!r&&t&&this.backend.exec("PRAGMA foreign_keys = ON"),this.backend.exec(`PRAGMA busy_timeout = ${a}`);}catch(q){throw this.backend=null,this.stmtCache=null,this.cleanupWalShmSymlink(),new o("Failed to apply SQLite pragmas",q)}this.initialized=true;}close(){if(!this.backend){this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();return}try{this.backend.close();}finally{this.backend=null,this.stmtCache?.clear(),this.stmtCache=null,this.readOnlyFlag=false,this.initialized=false,this.cleanupWalShmSymlink();}}isOpen(){return this.backend?.open===true}isReadOnly(){return this.readOnlyFlag}getDbPath(){return this.dbPath}getBackend(){return this.sqliteBackend}getJournalMode(){this.assertInitialized();let e=this.requireBackend().pragma("journal_mode"),t=Array.isArray(e)?e[0]:e;if(t==null)return "";if(typeof t=="object"){let r=t.journal_mode;return typeof r=="string"?r.toLowerCase():String(r??"").toLowerCase()}return String(t).toLowerCase()}prepare(e){this.assertInitialized();try{return this.requireCache().get(e)}catch(t){throw t instanceof o?t:new d(`SQLite prepare failed: ${H(t)}`,t)}}exec(e){this.assertInitialized();let t=this.requireBackend();try{t.exec(e),pe(e)&&this.stmtCache?.clear();}catch(r){throw new d(`SQLite exec failed: ${H(r)}`,r)}}pragma(e,t){return this.assertInitialized(),this.requireBackend().pragma(e,t)}transaction(e){if(this.assertInitialized(),this.readOnlyFlag)throw new l("Cannot begin transaction on read-only SQLite database");return this.requireBackend().transaction(e)}execBatch(e){if(e.length!==0)for(let t of e)this.exec(t);}resolveOpenPath(e,t){if(e===":memory:"||t===void 0||t===""||this.sqliteBackend!=="better-sqlite3")return e;let r=h__namespace.dirname(e);if(h__namespace.resolve(r)===h__namespace.resolve(t))return e;let a=h__namespace.basename(e),s=h__namespace.join(t,a);try{try{let u=m__namespace.lstatSync(s);(u.isSymbolicLink()||u.isFile())&&m__namespace.unlinkSync(s);}catch{}return m__namespace.symlinkSync(h__namespace.resolve(e),s),this.walShmSymlink=s,this.effectiveDbPath=s,s}catch(u){throw new o(`Failed to create symlink for WAL at "${t}" \u2192 "${e}". Check directory existence & write permission.`,u)}}cleanupWalShmSymlink(){if(this.walShmSymlink){try{m__namespace.unlinkSync(this.walShmSymlink);}catch{}this.walShmSymlink=null,this.effectiveDbPath=null;}}createBackend(e,t){switch(this.sqliteBackend){case "better-sqlite3":return new w(e,{readonly:t.readonly});case "node:sqlite":return new b(e);case "@tursodatabase/database":return new k(e);default:throw new o(`Unsupported SQLite backend: ${String(this.sqliteBackend)}`)}}requireBackend(){if(!this.backend)throw new o("SQLite database not initialized. Call initialize() first.");return this.backend}requireCache(){if(!this.stmtCache)throw new o("SQLite database not initialized. Call initialize() first.");return this.stmtCache}assertInitialized(){if(!this.initialized)throw new o("SyncSqliteConnection not initialized. Call initialize() first.")}walModeDefault(){return true}foreignKeysDefault(){return true}readonlyDefault(){return false}busyTimeoutDefault(){return 5e3}walShmPathDefault(){}syncStmtCacheAccessor(){return this.requireCache()}},N=class{constructor(e){i(this,"backend",e);i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let r=this.backend.prepare(e);if(this.cache.size>=he){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,r),r}clear(){this.cache.clear();}};function pe(n){let e=n.trimStart();if(e.length===0)return false;let a=((e.split(`
7
- `,1)[0]??"").trimStart().split(/\s+/,1)[0]??"").toUpperCase();return a==="CREATE"||a==="DROP"||a==="ALTER"||a==="TRUNCATE"||a==="REPLACE"}function H(n){return n instanceof Error?n.message:String(n)}function me(n={}){let e=n.backend===void 0||n.backend==="auto"?f():n.backend,t=new A({...n,backend:e}),r=n.path??":memory:";if(r!==":memory:"){let a=h__namespace.dirname(r);try{m__namespace.mkdirSync(a,{recursive:!0});}catch(s){throw new o(`Failed to ensure directory for SQLite database at "${r}"`,s)}}return t}exports.ConnectionError=o;exports.DatabaseError=S;exports.DatabaseFactory=P;exports.PostgresDatabase=v;exports.QueryError=d;exports.SqliteDatabase=R;exports.SyncSqliteConnection=A;exports.TransactionError=l;exports.createSyncSqliteConnection=me;exports.default=P;exports.isSafeIdent=x;exports.resolveDefaultSqliteBackend=f;exports.translatePlaceholders=T;
4
+ - @tursodatabase/database`)};var y=class{constructor(e){i(this,"stmt",e);}run(...e){return this.stmt.run(...e)}get(...e){return this.stmt.get(...e)}all(...e){return this.stmt.all(...e)}iterate(...e){return this.stmt.iterate(...e)}};var X=module$1.createRequire(c),N=r=>typeof r=="function"&&r.prototype!==void 0,w=class{constructor(e,t={}){i(this,"backend","better-sqlite3");i(this,"db");let n=X("better-sqlite3"),a=N(n)?n:n.default;if(!N(a))throw new TypeError(`better-sqlite3 import did not expose a constructor (got ${typeof n})`);this.db=new a(e,t);}exec(e){this.db.exec(e);}prepare(e){return new y(this.db.prepare(e))}pragma(e,t){return this.db.pragma(e,t)}transaction(e){return this.db.transaction(e)}close(){this.db.open&&this.db.close();}get open(){return this.db.open}};var te=module$1.createRequire(c),b=class{constructor(e){i(this,"backend","node:sqlite");i(this,"db");let t=te("node:sqlite");this.db=new t.DatabaseSync(e);}exec(e){this.db.exec(e);}prepare(e){return new y(this.db.prepare(e))}pragma(e,t){let n=e.replace(/[^a-zA-Z0-9_]/g,"");if(n){try{this.db.exec(`PRAGMA ${n}`);}catch{return}if(t?.simple===true)try{return this.db.prepare(`SELECT ${n} AS v`).get()?.v}catch{return}}}transaction(e){return((...n)=>{this.db.exec("BEGIN");let a;try{a=e(...n);}catch(s){try{this.db.exec("ROLLBACK");}catch{}throw s}return this.db.exec("COMMIT"),a})}close(){this.db.isOpen&&this.db.close();}get open(){return this.db.isOpen}};var re=module$1.createRequire(c),_=r=>typeof r=="function"&&r.prototype!==void 0,k=class{constructor(e){i(this,"backend","@tursodatabase/database");i(this,"db",null);let t=re("@tursodatabase/database"),n=_(t)?t:t.default;if(!_(n))throw new TypeError(`@tursodatabase/database import did not expose a constructor (got ${typeof t})`);this.db=new n(e);}requireDb(){if(!this.db)throw new Error(`Turso backend not initialized (db=${String(this.db)})`);return this.db}exec(e){this.requireDb().exec(e);}prepare(e){return new y(this.requireDb().prepare(e))}pragma(e){this.requireDb().exec(`PRAGMA ${e}`);}transaction(e){return((...n)=>{let a=this.requireDb();a.exec("BEGIN");let s;try{s=e(...n);}catch(u){try{a.exec("ROLLBACK");}catch{}throw u}return a.exec("COMMIT"),s})}close(){if(this.db)try{this.db.close();}finally{this.db=null;}}get open(){return this.db!==null}};var ae=256,O=class{constructor(e){i(this,"backend",e);i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let n=this.backend.prepare(e);if(this.cache.size>=ae){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,n),n}clear(){this.cache.clear();}},Q=r=>r==null?{}:typeof r!="object"?{}:{...r},ie=r=>r.map(Q);function E(r){if(!x(r))throw new l(`Unsafe SQL identifier: ${JSON.stringify(r)}`);return `"${r}"`}function se(r){let e=r.trimStart();if(e.length===0)return false;let a=((e.split(`
5
+ `,1)[0]??"").trimStart().split(/\s+/,1)[0]??"").toUpperCase();return a==="CREATE"||a==="DROP"||a==="ALTER"||a==="TRUNCATE"||a==="REPLACE"}var L=class{constructor(e,t){i(this,"db",e);i(this,"depth");i(this,"finished",false);this.depth=t;}isFinished(){return this.finished}async query(e,t){return this.assertOpen(),this.db.query(e,t)}async queryOne(e,t){return this.assertOpen(),this.db.queryOne(e,t)}async execute(e,t){return this.assertOpen(),this.db.execute(e,t)}async exec(e){this.assertOpen(),await this.db.exec(e);}async commit(){this.finished||(this.finished=true,this.depth===1&&this.db.commitRoot(),this.db.popTxDepth());}async rollback(){if(!this.finished){this.finished=true;try{this.depth===1?this.db.rollbackRoot():this.db.rollbackToSavepoint(`sp_${this.depth}`);}catch{}this.db.popTxDepth();}}async savepoint(e){this.assertOpen(),this.db.execSavepoint(E(e));}async release(e){this.assertOpen(),this.db.execRelease(E(e));}async rollbackTo(e){this.assertOpen(),this.db.execRollbackTo(E(e));}assertOpen(){if(this.finished)throw new l(`Transaction already finalized (depth=${this.depth})`)}},R=class{constructor(e){i(this,"config",e);i(this,"flavor","sqlite");i(this,"sqliteBackend");i(this,"backend",null);i(this,"stmtCache",null);i(this,"inTxDepth",0);i(this,"readOnlyFlag",false);i(this,"initialized",false);i(this,"walShmSymlink",null);i(this,"effectiveDbPath",null);let t=e.sqlite??{};this.sqliteBackend=t.backend===void 0||t.backend==="auto"?f():t.backend;}async initialize(){if(this.initialized)return;let e=this.config.sqlite??{},t=e.path??":memory:",n=e.walMode!==false,a=e.foreignKeys!==false,s=e.readonly===true,u=e.busyTimeoutMs??5e3,q=e.walShmPath,M=this.resolveOpenPath(t,q);try{this.backend=this.createBackend(M,{readonly:s});}catch(B){throw this.cleanupWalShmSymlink(),new o(`Failed to create SQLite backend (${this.sqliteBackend}) at "${M}"`,B)}this.readOnlyFlag=s,this.stmtCache=new O(this.backend);try{!s&&t!==":memory:"&&n&&this.backend.exec("PRAGMA journal_mode = WAL"),!s&&a&&this.backend.exec("PRAGMA foreign_keys = ON"),this.backend.exec(`PRAGMA busy_timeout = ${u}`);}catch(B){throw this.backend=null,this.stmtCache=null,this.cleanupWalShmSymlink(),new o("Failed to apply SQLite pragmas",B)}this.initialized=true;}resolveOpenPath(e,t){if(e===":memory:"||t===void 0||t===""||this.sqliteBackend!=="better-sqlite3")return e;let n=h__namespace.dirname(e);if(h__namespace.resolve(n)===h__namespace.resolve(t))return e;let a=h__namespace.basename(e),s=h__namespace.join(t,a);try{try{let u=m__namespace.lstatSync(s);(u.isSymbolicLink()||u.isFile())&&m__namespace.unlinkSync(s);}catch{}return m__namespace.symlinkSync(h__namespace.resolve(e),s),this.walShmSymlink=s,this.effectiveDbPath=s,s}catch(u){throw new o(`Failed to create symlink for WAL at "${t}" \u2192 "${e}". Check directory existence & write permission.`,u)}}cleanupWalShmSymlink(){if(this.walShmSymlink){try{m__namespace.unlinkSync(this.walShmSymlink);}catch{}this.walShmSymlink=null,this.effectiveDbPath=null;}}createBackend(e,t){switch(this.sqliteBackend){case "better-sqlite3":return new w(e,{readonly:t.readonly});case "node:sqlite":return new b(e);case "@tursodatabase/database":return new k(e);default:throw new o(`Unsupported SQLite backend: ${String(this.sqliteBackend)}`)}}async close(){if(!this.backend){this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();return}try{this.backend.close();}finally{this.backend=null,this.stmtCache?.clear(),this.stmtCache=null,this.inTxDepth=0,this.initialized=false,this.cleanupWalShmSymlink();}}isConnected(){return this.backend?.open===true}isReadOnly(){return this.readOnlyFlag}requireBackend(){if(!this.backend)throw new o("SQLite database not initialized. Call initialize() first.");return this.backend}requireCache(){if(!this.stmtCache)throw new o("SQLite database not initialized. Call initialize() first.");return this.stmtCache}async query(e,t){let n=this.prepareOrThrow(e);try{return ie(n.all(...t??[]))}catch(a){throw new d(`SQLite query failed: ${this.errorMessage(a)}`,a)}}async queryOne(e,t){let n=this.prepareOrThrow(e);try{let a=n.get(...t??[]);return a==null?null:Q(a)}catch(a){throw new d(`SQLite queryOne failed: ${this.errorMessage(a)}`,a)}}async execute(e,t){let n=this.prepareOrThrow(e);try{return n.run(...t??[])}catch(a){throw new d(`SQLite execute failed: ${this.errorMessage(a)}`,a)}}prepareOrThrow(e){try{return this.requireCache().get(e)}catch(t){throw t instanceof o?t:new d(`SQLite prepare failed: ${this.errorMessage(t)}`,t)}}async exec(e){let t=this.requireBackend();try{t.exec(e),se(e)&&this.stmtCache?.clear();}catch(n){throw new d(`SQLite exec failed: ${this.errorMessage(n)}`,n)}}async execBatch(e){for(let t of e)await this.exec(t);}async begin(){let e=this.requireBackend();if(this.readOnlyFlag)throw new l("Cannot begin transaction on read-only SQLite database");let t=this.pushTxDepth();try{t===1?e.exec("BEGIN"):e.exec(`SAVEPOINT sp_${t}`);}catch(n){this.popTxDepth();let a=t===1?"BEGIN":`SAVEPOINT sp_${t}`;throw new l(`${a} failed`,n)}return new L(this,t)}async withTransaction(e){let t=await this.begin();try{let n=await e(t);return await t.commit(),n}catch(n){try{await t.rollback();}catch{}throw n}}getTransactionDepth(){return this.inTxDepth}commitRoot(){this.requireBackend().exec("COMMIT");}rollbackRoot(){this.requireBackend().exec("ROLLBACK");}rollbackToSavepoint(e){this.requireBackend().exec(`ROLLBACK TO SAVEPOINT ${e}`);}execSavepoint(e){this.requireBackend().exec(`SAVEPOINT ${e}`);}execRelease(e){this.requireBackend().exec(`RELEASE SAVEPOINT ${e}`);}execRollbackTo(e){this.requireBackend().exec(`ROLLBACK TO SAVEPOINT ${e}`);}pushTxDepth(){return this.inTxDepth+=1}popTxDepth(){this.inTxDepth>0&&(this.inTxDepth-=1);}errorMessage(e){return e instanceof Error?e.message:String(e)}};var le=256,$=class{constructor(){i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let n=T(e,"numbered");if(this.cache.size>=le){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,n),n}clear(){this.cache.clear();}},ce=r=>r==null?{}:{...r},de=r=>r.map(e=>ce(e)),I=r=>{if(!x(r))throw new l(`Unsafe SQL identifier: ${JSON.stringify(r)}`);return `"${r}"`};function K(r,e){return r.includes("?")?{sql:T(r,"numbered"),params:e?[...e]:[]}:{sql:r,params:void 0}}var C=class{constructor(e,t){i(this,"db",e);i(this,"depth");i(this,"finished",false);this.depth=t;}get client(){return this.db.getClient(this.depth)}isFinished(){return this.finished}assertOpen(){if(this.finished)throw new l("Transaction already finalized")}async query(e,t){return this.assertOpen(),await W(this.client,e,t)}async queryOne(e,t){let n=await this.query(e,t);return n.length>0?n[0]??null:null}async execute(e,t){return this.assertOpen(),await G(this.client,e,t)}async exec(e){this.assertOpen(),await F(this.client,e);}async commit(){if(!this.finished)if(this.finished=true,this.depth===1)try{await this.client.query("COMMIT");}finally{this.db.releaseTxClient(false),this.db.clearTxCtx();}else await this.client.query(`RELEASE SAVEPOINT sp_${this.depth}`);}async rollback(){if(!this.finished)if(this.finished=true,this.depth===1)try{await this.client.query("ROLLBACK");}catch{}finally{this.db.releaseTxClient(false),this.db.clearTxCtx();}else try{await this.client.query(`ROLLBACK TO SAVEPOINT sp_${this.depth}`);}catch{}}async savepoint(e){this.assertOpen(),await this.client.query(`SAVEPOINT ${I(e)}`);}async release(e){this.assertOpen(),await this.client.query(`RELEASE SAVEPOINT ${I(e)}`);}async rollbackTo(e){this.assertOpen(),await this.client.query(`ROLLBACK TO SAVEPOINT ${I(e)}`);}};async function W(r,e,t){let{sql:n,params:a}=K(e,t);try{let s=await r.query(n,a);return de(s.rows)}catch(s){throw new d(`PostgreSQL query failed: ${s instanceof Error?s.message:String(s)}`,s)}}async function G(r,e,t){let{sql:n,params:a}=K(e,t);try{return {changes:(await r.query(n,a)).rowCount??0}}catch(s){throw new d(`PostgreSQL execute failed: ${s instanceof Error?s.message:String(s)}`,s)}}async function F(r,e){try{await r.query(e);}catch(t){throw new d(`PostgreSQL exec failed: ${t instanceof Error?t.message:String(t)}`,t)}}async function ue(r,e){if(e.length===0)return;let t=e.join(`;
6
+ `)+";";await F(r,t);}var v=class{constructor(e){i(this,"config",e);i(this,"flavor","postgresql");i(this,"sqliteBackend");i(this,"pool",null);i(this,"translatedSqlCache",new $);i(this,"txCtx",null);i(this,"lastTxDepth",0);}async initialize(){if(!this.pool)try{this.pool=new pg.Pool({host:this.config.host??"localhost",port:this.config.port??5432,user:this.config.username??"postgres",password:this.config.password??"",database:this.config.database??"eas_database",ssl:this.config.ssl??!1,max:this.config.poolSize??10}),(await this.pool.connect()).release();}catch(e){throw this.pool=null,new o("Failed to connect to PostgreSQL",e)}}async close(){if(!this.pool)return;let e=this.pool;this.pool=null;try{await e.end();}catch(t){throw new o("Failed to close PostgreSQL pool",t)}finally{this.translatedSqlCache.clear(),this.txCtx=null,this.lastTxDepth=0;}}isConnected(){return this.pool===null?false:!this.pool.ended&&!this.pool.closing}requirePool(){if(!this.pool)throw new o("PostgreSQL database not initialized. Call initialize() first.");return this.pool}async query(e,t){let n=await this.requirePool().connect();try{return await W(n,e,t)}finally{n.release();}}async queryOne(e,t){let n=await this.query(e,t);return n.length>0?n[0]??null:null}async execute(e,t){let n=await this.requirePool().connect();try{return await G(n,e,t)}finally{n.release();}}async exec(e){let t=await this.requirePool().connect();try{await F(t,e);}finally{t.release();}}async execBatch(e){if(e.length===0)return;let t=await this.requirePool().connect();try{await ue(t,e);}finally{t.release();}}async begin(){let e=this.requirePool(),t=this.pushTxDepth();if(t>1){let a=this.requireCtx(t);try{await a.client.query(`SAVEPOINT sp_${t}`);}catch(s){throw this.popTxDepth(),new l(`SAVEPOINT sp_${t} failed`,s)}return new C(this,t)}let n;try{n=await e.connect();}catch(a){throw this.popTxDepth(),new l("BEGIN failed: cannot acquire client",a)}try{await n.query("BEGIN");}catch(a){throw n.release(true),this.popTxDepth(),new l("BEGIN failed",a)}return this.txCtx={client:n,depth:t},new C(this,t)}requireCtx(e){if(!this.txCtx)throw new l(`No active transaction (depth=${e})`);return this.txCtx}getClient(e){return this.requireCtx(e).client}clearTxCtx(){this.txCtx=null,this.lastTxDepth=0,this.translatedSqlCache.clear();}releaseTxClient(e){let t=this.txCtx;if(t)try{t.client.release(e);}catch{}}async withTransaction(e){let t=await this.begin();try{let n=await e(t);return await t.commit(),n}catch(n){try{await t.rollback();}catch{}throw n}}pushTxDepth(){return this.lastTxDepth+=1}popTxDepth(){this.lastTxDepth>0&&(this.lastTxDepth-=1);}getTransactionDepth(){return this.lastTxDepth}};var P=class{static create(e){switch(e.flavor){case "sqlite":return new R(e);case "postgresql":return new v(e);default:{let t=e.flavor;throw new o(`Unsupported database flavor: ${String(t)}`)}}}};var he=256,A=class{constructor(e){i(this,"flavor","sqlite");i(this,"sqliteBackend");i(this,"backend",null);i(this,"stmtCache",null);i(this,"initialized",false);i(this,"walShmSymlink",null);i(this,"effectiveDbPath",null);i(this,"dbPath");i(this,"readOnlyFlag");i(this,"walModeFlag");i(this,"foreignKeysFlag");i(this,"busyTimeoutMsFlag");i(this,"walShmPathFlag");this.sqliteBackend=e.backend===void 0||e.backend==="auto"?f():e.backend,this.dbPath=e.path??":memory:",this.readOnlyFlag=e.readonly??false,this.walModeFlag=e.walMode??true,this.foreignKeysFlag=e.foreignKeys??true,this.busyTimeoutMsFlag=e.busyTimeoutMs??5e3,this.walShmPathFlag=e.walShmPath;}resolveBackendPath(e){return e===":memory:"?"":e}initialize(){if(this.initialized)return;let e=this.walModeFlag,t=this.foreignKeysFlag,n=this.readOnlyFlag,a=this.busyTimeoutMsFlag,s=this.resolveOpenPath(this.dbPath,e?this.walShmPathFlag:void 0),u=s===":memory:"?"":s;try{this.backend=this.createBackend(u,{readonly:n});}catch(q){throw this.cleanupWalShmSymlink(),new o(`Failed to create SQLite backend (${this.sqliteBackend}) at "${s}"`,q)}this.stmtCache=new z(this.backend);try{!n&&this.dbPath!==":memory:"&&e&&this.backend.exec("PRAGMA journal_mode = WAL"),n||this.backend.exec(`PRAGMA foreign_keys = ${t?"ON":"OFF"}`),this.backend.exec(`PRAGMA busy_timeout = ${a}`);}catch(q){throw this.backend=null,this.stmtCache=null,this.cleanupWalShmSymlink(),new o("Failed to apply SQLite pragmas",q)}this.initialized=true;}close(){if(!this.backend){this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();return}try{this.backend.close();}finally{this.backend=null,this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();}}isOpen(){return this.backend?.open===true}isReadOnly(){return this.readOnlyFlag}getDbPath(){return this.dbPath}getBackend(){return this.sqliteBackend}getJournalMode(){this.assertInitialized();let e=this.requireBackend().pragma("journal_mode"),t=Array.isArray(e)?e[0]:e;if(t==null)return "";if(typeof t=="object"){let n=t.journal_mode;return typeof n=="string"?n.toLowerCase():String(n??"").toLowerCase()}return String(t).toLowerCase()}prepare(e){this.assertInitialized();try{return this.requireCache().get(e)}catch(t){throw t instanceof o?t:new d(`SQLite prepare failed: ${H(t)}`,t)}}exec(e){this.assertInitialized();let t=this.requireBackend();try{t.exec(e),pe(e)&&this.stmtCache?.clear();}catch(n){throw new d(`SQLite exec failed: ${H(n)}`,n)}}pragma(e,t){return this.assertInitialized(),this.requireBackend().pragma(e,t)}transaction(e){if(this.assertInitialized(),this.readOnlyFlag)throw new l("Cannot begin transaction on read-only SQLite database");return this.requireBackend().transaction(e)}execBatch(e){if(e.length!==0)for(let t of e)this.exec(t);}resolveOpenPath(e,t){if(e===":memory:"||t===void 0||t===""||this.sqliteBackend!=="better-sqlite3")return e;let n=h__namespace.dirname(e);if(h__namespace.resolve(n)===h__namespace.resolve(t))return e;let a=h__namespace.basename(e),s=h__namespace.join(t,a);try{try{let u=m__namespace.lstatSync(s);(u.isSymbolicLink()||u.isFile())&&m__namespace.unlinkSync(s);}catch{}return m__namespace.symlinkSync(h__namespace.resolve(e),s),this.walShmSymlink=s,this.effectiveDbPath=s,s}catch(u){throw new o(`Failed to create symlink for WAL at "${t}" \u2192 "${e}". Check directory existence & write permission.`,u)}}cleanupWalShmSymlink(){if(this.walShmSymlink){try{m__namespace.unlinkSync(this.walShmSymlink);}catch{}this.walShmSymlink=null,this.effectiveDbPath=null;}}createBackend(e,t){switch(this.sqliteBackend){case "better-sqlite3":return new w(e,{readonly:t.readonly});case "node:sqlite":return new b(e);case "@tursodatabase/database":return new k(e);default:throw new o(`Unsupported SQLite backend: ${String(this.sqliteBackend)}`)}}requireBackend(){if(!this.backend)throw new o("SQLite database not initialized. Call initialize() first.");return this.backend}requireCache(){if(!this.stmtCache)throw new o("SQLite database not initialized. Call initialize() first.");return this.stmtCache}assertInitialized(){if(!this.initialized)throw new o("SyncSqliteConnection not initialized. Call initialize() first.")}walModeDefault(){return true}foreignKeysDefault(){return true}readonlyDefault(){return false}busyTimeoutDefault(){return 5e3}walShmPathDefault(){}syncStmtCacheAccessor(){return this.requireCache()}},z=class{constructor(e){i(this,"backend",e);i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let n=this.backend.prepare(e);if(this.cache.size>=he){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,n),n}clear(){this.cache.clear();}};function pe(r){let e=r.trimStart();if(e.length===0)return false;let a=((e.split(`
7
+ `,1)[0]??"").trimStart().split(/\s+/,1)[0]??"").toUpperCase();return a==="CREATE"||a==="DROP"||a==="ALTER"||a==="TRUNCATE"||a==="REPLACE"}function H(r){return r instanceof Error?r.message:String(r)}function me(r={}){let e=r.backend===void 0||r.backend==="auto"?f():r.backend,t=new A({...r,backend:e}),n=r.path??":memory:";if(n!==":memory:"){let a=h__namespace.dirname(n);try{m__namespace.mkdirSync(a,{recursive:!0});}catch(s){throw new o(`Failed to ensure directory for SQLite database at "${n}"`,s)}}return t}exports.ConnectionError=o;exports.DatabaseError=S;exports.DatabaseFactory=P;exports.PostgresDatabase=v;exports.QueryError=d;exports.SqliteDatabase=R;exports.SyncSqliteConnection=A;exports.TransactionError=l;exports.createSyncSqliteConnection=me;exports.default=P;exports.isSafeIdent=x;exports.resolveDefaultSqliteBackend=f;exports.translatePlaceholders=T;
package/dist/index.d.cts CHANGED
@@ -183,11 +183,15 @@ declare class SyncSqliteConnection {
183
183
  readonly sqliteBackend: SqliteBackendKind;
184
184
  private backend;
185
185
  private stmtCache;
186
- private readOnlyFlag;
187
186
  private initialized;
188
187
  private walShmSymlink;
189
188
  private effectiveDbPath;
190
189
  private readonly dbPath;
190
+ private readonly readOnlyFlag;
191
+ private readonly walModeFlag;
192
+ private readonly foreignKeysFlag;
193
+ private readonly busyTimeoutMsFlag;
194
+ private readonly walShmPathFlag;
191
195
  constructor(config: SyncSqliteConnectionConfig);
192
196
  private resolveBackendPath;
193
197
  initialize(): void;
package/dist/index.d.ts CHANGED
@@ -183,11 +183,15 @@ declare class SyncSqliteConnection {
183
183
  readonly sqliteBackend: SqliteBackendKind;
184
184
  private backend;
185
185
  private stmtCache;
186
- private readOnlyFlag;
187
186
  private initialized;
188
187
  private walShmSymlink;
189
188
  private effectiveDbPath;
190
189
  private readonly dbPath;
190
+ private readonly readOnlyFlag;
191
+ private readonly walModeFlag;
192
+ private readonly foreignKeysFlag;
193
+ private readonly busyTimeoutMsFlag;
194
+ private readonly walShmPathFlag;
191
195
  constructor(config: SyncSqliteConnectionConfig);
192
196
  private resolveBackendPath;
193
197
  initialize(): void;
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import {createRequire}from'module';import*as y from'fs';import*as p from'path';import {Pool}from'pg';var j=Object.defineProperty;var U=(n,e,t)=>e in n?j(n,e,{enumerable:true,configurable:true,writable:true,value:t}):n[e]=t;var i=(n,e,t)=>U(n,typeof e!="symbol"?e+"":e,t);var x=class extends Error{constructor(t,r,a){super(r);i(this,"code");i(this,"cause");this.name="DatabaseError",this.code=t,this.cause=a;}},o=class extends x{constructor(e,t){super("CONNECTION",e,t),this.name="ConnectionError";}},c=class extends x{constructor(e,t){super("QUERY",e,t),this.name="QueryError";}},l=class extends x{constructor(e,t){super("TX",e,t),this.name="TransactionError";}},C=(n,e)=>{if(e==="qmark")return n;let t=0;return n.replace(/\?/g,()=>`$${++t}`)},q=n=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(n);var J=createRequire(import.meta.url),E=(n,e)=>{try{let t=J(n);return e(t)}catch{return false}},w=()=>{if(E("better-sqlite3",n=>typeof n.default=="function"))return "better-sqlite3";if(E("node:sqlite",n=>typeof n.DatabaseSync=="function"))return "node:sqlite";if(E("@tursodatabase/database",n=>typeof(n.default??n)=="function"))return "@tursodatabase/database";throw new o(`No SQLite backend available. Please install one of:
1
+ import {createRequire}from'module';import*as y from'fs';import*as p from'path';import {Pool}from'pg';var j=Object.defineProperty;var U=(r,e,t)=>e in r?j(r,e,{enumerable:true,configurable:true,writable:true,value:t}):r[e]=t;var i=(r,e,t)=>U(r,typeof e!="symbol"?e+"":e,t);var x=class extends Error{constructor(t,n,a){super(n);i(this,"code");i(this,"cause");this.name="DatabaseError",this.code=t,this.cause=a;}},o=class extends x{constructor(e,t){super("CONNECTION",e,t),this.name="ConnectionError";}},c=class extends x{constructor(e,t){super("QUERY",e,t),this.name="QueryError";}},l=class extends x{constructor(e,t){super("TX",e,t),this.name="TransactionError";}},C=(r,e)=>{if(e==="qmark")return r;let t=0;return r.replace(/\?/g,()=>`$${++t}`)},q=r=>/^[A-Za-z_][A-Za-z0-9_]*$/.test(r);var J=createRequire(import.meta.url),E=(r,e)=>{try{let t=J(r);return e(t)}catch{return false}},w=()=>{if(E("better-sqlite3",r=>typeof r.default=="function"))return "better-sqlite3";if(E("node:sqlite",r=>typeof r.DatabaseSync=="function"))return "node:sqlite";if(E("@tursodatabase/database",r=>typeof(r.default??r)=="function"))return "@tursodatabase/database";throw new o(`No SQLite backend available. Please install one of:
2
2
  - better-sqlite3 (recommended; highest perf)
3
3
  - node:sqlite (built-in since Node.js 22.5+)
4
- - @tursodatabase/database`)};var f=class{constructor(e){i(this,"stmt",e);}run(...e){return this.stmt.run(...e)}get(...e){return this.stmt.get(...e)}all(...e){return this.stmt.all(...e)}iterate(...e){return this.stmt.iterate(...e)}};var X=createRequire(import.meta.url),_=n=>typeof n=="function"&&n.prototype!==void 0,b=class{constructor(e,t={}){i(this,"backend","better-sqlite3");i(this,"db");let r=X("better-sqlite3"),a=_(r)?r:r.default;if(!_(a))throw new TypeError(`better-sqlite3 import did not expose a constructor (got ${typeof r})`);this.db=new a(e,t);}exec(e){this.db.exec(e);}prepare(e){return new f(this.db.prepare(e))}pragma(e,t){return this.db.pragma(e,t)}transaction(e){return this.db.transaction(e)}close(){this.db.open&&this.db.close();}get open(){return this.db.open}};var te=createRequire(import.meta.url),k=class{constructor(e){i(this,"backend","node:sqlite");i(this,"db");let t=te("node:sqlite");this.db=new t.DatabaseSync(e);}exec(e){this.db.exec(e);}prepare(e){return new f(this.db.prepare(e))}pragma(e,t){return this.db.exec(`PRAGMA ${e}`),t?.simple!==true?void 0:this.db.prepare("SELECT pragma_value AS v FROM pragma_value(?)").get(e)}transaction(e){return((...r)=>{this.db.exec("BEGIN");let a;try{a=e(...r);}catch(s){try{this.db.exec("ROLLBACK");}catch{}throw s}return this.db.exec("COMMIT"),a})}close(){this.db.isOpen&&this.db.close();}get open(){return this.db.isOpen}};var re=createRequire(import.meta.url),Q=n=>typeof n=="function"&&n.prototype!==void 0,g=class{constructor(e){i(this,"backend","@tursodatabase/database");i(this,"db",null);let t=re("@tursodatabase/database"),r=Q(t)?t:t.default;if(!Q(r))throw new TypeError(`@tursodatabase/database import did not expose a constructor (got ${typeof t})`);this.db=new r(e);}requireDb(){if(!this.db)throw new Error(`Turso backend not initialized (db=${String(this.db)})`);return this.db}exec(e){this.requireDb().exec(e);}prepare(e){return new f(this.requireDb().prepare(e))}pragma(e){this.requireDb().exec(`PRAGMA ${e}`);}transaction(e){return((...r)=>{let a=this.requireDb();a.exec("BEGIN");let s;try{s=e(...r);}catch(d){try{a.exec("ROLLBACK");}catch{}throw d}return a.exec("COMMIT"),s})}close(){if(this.db)try{this.db.close();}finally{this.db=null;}}get open(){return this.db!==null}};var ae=256,L=class{constructor(e){i(this,"backend",e);i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let r=this.backend.prepare(e);if(this.cache.size>=ae){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,r),r}clear(){this.cache.clear();}},K=n=>n==null?{}:typeof n!="object"?{}:{...n},ie=n=>n.map(K);function O(n){if(!q(n))throw new l(`Unsafe SQL identifier: ${JSON.stringify(n)}`);return `"${n}"`}function se(n){let e=n.trimStart();if(e.length===0)return false;let a=((e.split(`
5
- `,1)[0]??"").trimStart().split(/\s+/,1)[0]??"").toUpperCase();return a==="CREATE"||a==="DROP"||a==="ALTER"||a==="TRUNCATE"||a==="REPLACE"}var I=class{constructor(e,t){i(this,"db",e);i(this,"depth");i(this,"finished",false);this.depth=t;}isFinished(){return this.finished}async query(e,t){return this.assertOpen(),this.db.query(e,t)}async queryOne(e,t){return this.assertOpen(),this.db.queryOne(e,t)}async execute(e,t){return this.assertOpen(),this.db.execute(e,t)}async exec(e){this.assertOpen(),await this.db.exec(e);}async commit(){this.finished||(this.finished=true,this.depth===1&&this.db.commitRoot(),this.db.popTxDepth());}async rollback(){if(!this.finished){this.finished=true;try{this.depth===1?this.db.rollbackRoot():this.db.rollbackToSavepoint(`sp_${this.depth}`);}catch{}this.db.popTxDepth();}}async savepoint(e){this.assertOpen(),this.db.execSavepoint(O(e));}async release(e){this.assertOpen(),this.db.execRelease(O(e));}async rollbackTo(e){this.assertOpen(),this.db.execRollbackTo(O(e));}assertOpen(){if(this.finished)throw new l(`Transaction already finalized (depth=${this.depth})`)}},v=class{constructor(e){i(this,"config",e);i(this,"flavor","sqlite");i(this,"sqliteBackend");i(this,"backend",null);i(this,"stmtCache",null);i(this,"inTxDepth",0);i(this,"readOnlyFlag",false);i(this,"initialized",false);i(this,"walShmSymlink",null);i(this,"effectiveDbPath",null);let t=e.sqlite??{};this.sqliteBackend=t.backend===void 0||t.backend==="auto"?w():t.backend;}async initialize(){if(this.initialized)return;let e=this.config.sqlite??{},t=e.path??":memory:",r=e.walMode!==false,a=e.foreignKeys!==false,s=e.readonly===true,d=e.busyTimeoutMs??5e3,R=e.walShmPath,F=this.resolveOpenPath(t,R);try{this.backend=this.createBackend(F,{readonly:s});}catch(B){throw this.cleanupWalShmSymlink(),new o(`Failed to create SQLite backend (${this.sqliteBackend}) at "${F}"`,B)}this.readOnlyFlag=s,this.stmtCache=new L(this.backend);try{!s&&t!==":memory:"&&r&&this.backend.exec("PRAGMA journal_mode = WAL"),!s&&a&&this.backend.exec("PRAGMA foreign_keys = ON"),this.backend.exec(`PRAGMA busy_timeout = ${d}`);}catch(B){throw this.backend=null,this.stmtCache=null,this.cleanupWalShmSymlink(),new o("Failed to apply SQLite pragmas",B)}this.initialized=true;}resolveOpenPath(e,t){if(e===":memory:"||t===void 0||t===""||this.sqliteBackend!=="better-sqlite3")return e;let r=p.dirname(e);if(p.resolve(r)===p.resolve(t))return e;let a=p.basename(e),s=p.join(t,a);try{try{let d=y.lstatSync(s);(d.isSymbolicLink()||d.isFile())&&y.unlinkSync(s);}catch{}return y.symlinkSync(p.resolve(e),s),this.walShmSymlink=s,this.effectiveDbPath=s,s}catch(d){throw new o(`Failed to create symlink for WAL at "${t}" \u2192 "${e}". Check directory existence & write permission.`,d)}}cleanupWalShmSymlink(){if(this.walShmSymlink){try{y.unlinkSync(this.walShmSymlink);}catch{}this.walShmSymlink=null,this.effectiveDbPath=null;}}createBackend(e,t){switch(this.sqliteBackend){case "better-sqlite3":return new b(e,{readonly:t.readonly});case "node:sqlite":return new k(e);case "@tursodatabase/database":return new g(e);default:throw new o(`Unsupported SQLite backend: ${String(this.sqliteBackend)}`)}}async close(){if(!this.backend){this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();return}try{this.backend.close();}finally{this.backend=null,this.stmtCache?.clear(),this.stmtCache=null,this.inTxDepth=0,this.initialized=false,this.cleanupWalShmSymlink();}}isConnected(){return this.backend?.open===true}isReadOnly(){return this.readOnlyFlag}requireBackend(){if(!this.backend)throw new o("SQLite database not initialized. Call initialize() first.");return this.backend}requireCache(){if(!this.stmtCache)throw new o("SQLite database not initialized. Call initialize() first.");return this.stmtCache}async query(e,t){let r=this.prepareOrThrow(e);try{return ie(r.all(...t??[]))}catch(a){throw new c(`SQLite query failed: ${this.errorMessage(a)}`,a)}}async queryOne(e,t){let r=this.prepareOrThrow(e);try{let a=r.get(...t??[]);return a==null?null:K(a)}catch(a){throw new c(`SQLite queryOne failed: ${this.errorMessage(a)}`,a)}}async execute(e,t){let r=this.prepareOrThrow(e);try{return r.run(...t??[])}catch(a){throw new c(`SQLite execute failed: ${this.errorMessage(a)}`,a)}}prepareOrThrow(e){try{return this.requireCache().get(e)}catch(t){throw t instanceof o?t:new c(`SQLite prepare failed: ${this.errorMessage(t)}`,t)}}async exec(e){let t=this.requireBackend();try{t.exec(e),se(e)&&this.stmtCache?.clear();}catch(r){throw new c(`SQLite exec failed: ${this.errorMessage(r)}`,r)}}async execBatch(e){for(let t of e)await this.exec(t);}async begin(){let e=this.requireBackend();if(this.readOnlyFlag)throw new l("Cannot begin transaction on read-only SQLite database");let t=this.pushTxDepth();try{t===1?e.exec("BEGIN"):e.exec(`SAVEPOINT sp_${t}`);}catch(r){this.popTxDepth();let a=t===1?"BEGIN":`SAVEPOINT sp_${t}`;throw new l(`${a} failed`,r)}return new I(this,t)}async withTransaction(e){let t=await this.begin();try{let r=await e(t);return await t.commit(),r}catch(r){try{await t.rollback();}catch{}throw r}}getTransactionDepth(){return this.inTxDepth}commitRoot(){this.requireBackend().exec("COMMIT");}rollbackRoot(){this.requireBackend().exec("ROLLBACK");}rollbackToSavepoint(e){this.requireBackend().exec(`ROLLBACK TO SAVEPOINT ${e}`);}execSavepoint(e){this.requireBackend().exec(`SAVEPOINT ${e}`);}execRelease(e){this.requireBackend().exec(`RELEASE SAVEPOINT ${e}`);}execRollbackTo(e){this.requireBackend().exec(`ROLLBACK TO SAVEPOINT ${e}`);}pushTxDepth(){return this.inTxDepth+=1}popTxDepth(){this.inTxDepth>0&&(this.inTxDepth-=1);}errorMessage(e){return e instanceof Error?e.message:String(e)}};var le=256,z=class{constructor(){i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let r=C(e,"numbered");if(this.cache.size>=le){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,r),r}clear(){this.cache.clear();}},ce=n=>n==null?{}:{...n},de=n=>n.map(e=>ce(e)),$=n=>{if(!q(n))throw new l(`Unsafe SQL identifier: ${JSON.stringify(n)}`);return `"${n}"`};function W(n,e){return n.includes("?")?{sql:C(n,"numbered"),params:e?[...e]:[]}:{sql:n,params:void 0}}var P=class{constructor(e,t){i(this,"db",e);i(this,"depth");i(this,"finished",false);this.depth=t;}get client(){return this.db.getClient(this.depth)}isFinished(){return this.finished}assertOpen(){if(this.finished)throw new l("Transaction already finalized")}async query(e,t){return this.assertOpen(),await G(this.client,e,t)}async queryOne(e,t){let r=await this.query(e,t);return r.length>0?r[0]??null:null}async execute(e,t){return this.assertOpen(),await H(this.client,e,t)}async exec(e){this.assertOpen(),await M(this.client,e);}async commit(){if(!this.finished)if(this.finished=true,this.depth===1)try{await this.client.query("COMMIT");}finally{this.db.releaseTxClient(false),this.db.clearTxCtx();}else await this.client.query(`RELEASE SAVEPOINT sp_${this.depth}`);}async rollback(){if(!this.finished)if(this.finished=true,this.depth===1)try{await this.client.query("ROLLBACK");}catch{}finally{this.db.releaseTxClient(false),this.db.clearTxCtx();}else try{await this.client.query(`ROLLBACK TO SAVEPOINT sp_${this.depth}`);}catch{}}async savepoint(e){this.assertOpen(),await this.client.query(`SAVEPOINT ${$(e)}`);}async release(e){this.assertOpen(),await this.client.query(`RELEASE SAVEPOINT ${$(e)}`);}async rollbackTo(e){this.assertOpen(),await this.client.query(`ROLLBACK TO SAVEPOINT ${$(e)}`);}};async function G(n,e,t){let{sql:r,params:a}=W(e,t);try{let s=await n.query(r,a);return de(s.rows)}catch(s){throw new c(`PostgreSQL query failed: ${s instanceof Error?s.message:String(s)}`,s)}}async function H(n,e,t){let{sql:r,params:a}=W(e,t);try{return {changes:(await n.query(r,a)).rowCount??0}}catch(s){throw new c(`PostgreSQL execute failed: ${s instanceof Error?s.message:String(s)}`,s)}}async function M(n,e){try{await n.query(e);}catch(t){throw new c(`PostgreSQL exec failed: ${t instanceof Error?t.message:String(t)}`,t)}}async function ue(n,e){if(e.length===0)return;let t=e.join(`;
6
- `)+";";await M(n,t);}var T=class{constructor(e){i(this,"config",e);i(this,"flavor","postgresql");i(this,"sqliteBackend");i(this,"pool",null);i(this,"translatedSqlCache",new z);i(this,"txCtx",null);i(this,"lastTxDepth",0);}async initialize(){if(!this.pool)try{this.pool=new Pool({host:this.config.host??"localhost",port:this.config.port??5432,user:this.config.username??"postgres",password:this.config.password??"",database:this.config.database??"eas_database",ssl:this.config.ssl??!1,max:this.config.poolSize??10}),(await this.pool.connect()).release();}catch(e){throw this.pool=null,new o("Failed to connect to PostgreSQL",e)}}async close(){if(!this.pool)return;let e=this.pool;this.pool=null;try{await e.end();}catch(t){throw new o("Failed to close PostgreSQL pool",t)}finally{this.translatedSqlCache.clear(),this.txCtx=null,this.lastTxDepth=0;}}isConnected(){return this.pool===null?false:!this.pool.ended&&!this.pool.closing}requirePool(){if(!this.pool)throw new o("PostgreSQL database not initialized. Call initialize() first.");return this.pool}async query(e,t){let r=await this.requirePool().connect();try{return await G(r,e,t)}finally{r.release();}}async queryOne(e,t){let r=await this.query(e,t);return r.length>0?r[0]??null:null}async execute(e,t){let r=await this.requirePool().connect();try{return await H(r,e,t)}finally{r.release();}}async exec(e){let t=await this.requirePool().connect();try{await M(t,e);}finally{t.release();}}async execBatch(e){if(e.length===0)return;let t=await this.requirePool().connect();try{await ue(t,e);}finally{t.release();}}async begin(){let e=this.requirePool(),t=this.pushTxDepth();if(t>1){let a=this.requireCtx(t);try{await a.client.query(`SAVEPOINT sp_${t}`);}catch(s){throw this.popTxDepth(),new l(`SAVEPOINT sp_${t} failed`,s)}return new P(this,t)}let r;try{r=await e.connect();}catch(a){throw this.popTxDepth(),new l("BEGIN failed: cannot acquire client",a)}try{await r.query("BEGIN");}catch(a){throw r.release(true),this.popTxDepth(),new l("BEGIN failed",a)}return this.txCtx={client:r,depth:t},new P(this,t)}requireCtx(e){if(!this.txCtx)throw new l(`No active transaction (depth=${e})`);return this.txCtx}getClient(e){return this.requireCtx(e).client}clearTxCtx(){this.txCtx=null,this.lastTxDepth=0,this.translatedSqlCache.clear();}releaseTxClient(e){let t=this.txCtx;if(t)try{t.client.release(e);}catch{}}async withTransaction(e){let t=await this.begin();try{let r=await e(t);return await t.commit(),r}catch(r){try{await t.rollback();}catch{}throw r}}pushTxDepth(){return this.lastTxDepth+=1}popTxDepth(){this.lastTxDepth>0&&(this.lastTxDepth-=1);}getTransactionDepth(){return this.lastTxDepth}};var A=class{static create(e){switch(e.flavor){case "sqlite":return new v(e);case "postgresql":return new T(e);default:{let t=e.flavor;throw new o(`Unsupported database flavor: ${String(t)}`)}}}};var he=256,D=class{constructor(e){i(this,"flavor","sqlite");i(this,"sqliteBackend");i(this,"backend",null);i(this,"stmtCache",null);i(this,"readOnlyFlag",false);i(this,"initialized",false);i(this,"walShmSymlink",null);i(this,"effectiveDbPath",null);i(this,"dbPath");this.sqliteBackend=e.backend===void 0||e.backend==="auto"?w():e.backend,this.dbPath=e.path??":memory:";}resolveBackendPath(e){return e===":memory:"?"":e}initialize(){if(this.initialized)return;let e=this.walModeDefault(),t=this.foreignKeysDefault(),r=this.readonlyDefault(),a=this.busyTimeoutDefault(),s=this.resolveOpenPath(this.dbPath,e?this.walShmPathDefault():void 0),d=s===":memory:"?"":s;try{this.backend=this.createBackend(d,{readonly:r});}catch(R){throw this.cleanupWalShmSymlink(),new o(`Failed to create SQLite backend (${this.sqliteBackend}) at "${s}"`,R)}this.readOnlyFlag=r,this.stmtCache=new N(this.backend);try{!r&&this.dbPath!==":memory:"&&e&&this.backend.exec("PRAGMA journal_mode = WAL"),!r&&t&&this.backend.exec("PRAGMA foreign_keys = ON"),this.backend.exec(`PRAGMA busy_timeout = ${a}`);}catch(R){throw this.backend=null,this.stmtCache=null,this.cleanupWalShmSymlink(),new o("Failed to apply SQLite pragmas",R)}this.initialized=true;}close(){if(!this.backend){this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();return}try{this.backend.close();}finally{this.backend=null,this.stmtCache?.clear(),this.stmtCache=null,this.readOnlyFlag=false,this.initialized=false,this.cleanupWalShmSymlink();}}isOpen(){return this.backend?.open===true}isReadOnly(){return this.readOnlyFlag}getDbPath(){return this.dbPath}getBackend(){return this.sqliteBackend}getJournalMode(){this.assertInitialized();let e=this.requireBackend().pragma("journal_mode"),t=Array.isArray(e)?e[0]:e;if(t==null)return "";if(typeof t=="object"){let r=t.journal_mode;return typeof r=="string"?r.toLowerCase():String(r??"").toLowerCase()}return String(t).toLowerCase()}prepare(e){this.assertInitialized();try{return this.requireCache().get(e)}catch(t){throw t instanceof o?t:new c(`SQLite prepare failed: ${V(t)}`,t)}}exec(e){this.assertInitialized();let t=this.requireBackend();try{t.exec(e),pe(e)&&this.stmtCache?.clear();}catch(r){throw new c(`SQLite exec failed: ${V(r)}`,r)}}pragma(e,t){return this.assertInitialized(),this.requireBackend().pragma(e,t)}transaction(e){if(this.assertInitialized(),this.readOnlyFlag)throw new l("Cannot begin transaction on read-only SQLite database");return this.requireBackend().transaction(e)}execBatch(e){if(e.length!==0)for(let t of e)this.exec(t);}resolveOpenPath(e,t){if(e===":memory:"||t===void 0||t===""||this.sqliteBackend!=="better-sqlite3")return e;let r=p.dirname(e);if(p.resolve(r)===p.resolve(t))return e;let a=p.basename(e),s=p.join(t,a);try{try{let d=y.lstatSync(s);(d.isSymbolicLink()||d.isFile())&&y.unlinkSync(s);}catch{}return y.symlinkSync(p.resolve(e),s),this.walShmSymlink=s,this.effectiveDbPath=s,s}catch(d){throw new o(`Failed to create symlink for WAL at "${t}" \u2192 "${e}". Check directory existence & write permission.`,d)}}cleanupWalShmSymlink(){if(this.walShmSymlink){try{y.unlinkSync(this.walShmSymlink);}catch{}this.walShmSymlink=null,this.effectiveDbPath=null;}}createBackend(e,t){switch(this.sqliteBackend){case "better-sqlite3":return new b(e,{readonly:t.readonly});case "node:sqlite":return new k(e);case "@tursodatabase/database":return new g(e);default:throw new o(`Unsupported SQLite backend: ${String(this.sqliteBackend)}`)}}requireBackend(){if(!this.backend)throw new o("SQLite database not initialized. Call initialize() first.");return this.backend}requireCache(){if(!this.stmtCache)throw new o("SQLite database not initialized. Call initialize() first.");return this.stmtCache}assertInitialized(){if(!this.initialized)throw new o("SyncSqliteConnection not initialized. Call initialize() first.")}walModeDefault(){return true}foreignKeysDefault(){return true}readonlyDefault(){return false}busyTimeoutDefault(){return 5e3}walShmPathDefault(){}syncStmtCacheAccessor(){return this.requireCache()}},N=class{constructor(e){i(this,"backend",e);i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let r=this.backend.prepare(e);if(this.cache.size>=he){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,r),r}clear(){this.cache.clear();}};function pe(n){let e=n.trimStart();if(e.length===0)return false;let a=((e.split(`
7
- `,1)[0]??"").trimStart().split(/\s+/,1)[0]??"").toUpperCase();return a==="CREATE"||a==="DROP"||a==="ALTER"||a==="TRUNCATE"||a==="REPLACE"}function V(n){return n instanceof Error?n.message:String(n)}function me(n={}){let e=n.backend===void 0||n.backend==="auto"?w():n.backend,t=new D({...n,backend:e}),r=n.path??":memory:";if(r!==":memory:"){let a=p.dirname(r);try{y.mkdirSync(a,{recursive:!0});}catch(s){throw new o(`Failed to ensure directory for SQLite database at "${r}"`,s)}}return t}export{o as ConnectionError,x as DatabaseError,A as DatabaseFactory,T as PostgresDatabase,c as QueryError,v as SqliteDatabase,D as SyncSqliteConnection,l as TransactionError,me as createSyncSqliteConnection,A as default,q as isSafeIdent,w as resolveDefaultSqliteBackend,C as translatePlaceholders};
4
+ - @tursodatabase/database`)};var f=class{constructor(e){i(this,"stmt",e);}run(...e){return this.stmt.run(...e)}get(...e){return this.stmt.get(...e)}all(...e){return this.stmt.all(...e)}iterate(...e){return this.stmt.iterate(...e)}};var X=createRequire(import.meta.url),_=r=>typeof r=="function"&&r.prototype!==void 0,b=class{constructor(e,t={}){i(this,"backend","better-sqlite3");i(this,"db");let n=X("better-sqlite3"),a=_(n)?n:n.default;if(!_(a))throw new TypeError(`better-sqlite3 import did not expose a constructor (got ${typeof n})`);this.db=new a(e,t);}exec(e){this.db.exec(e);}prepare(e){return new f(this.db.prepare(e))}pragma(e,t){return this.db.pragma(e,t)}transaction(e){return this.db.transaction(e)}close(){this.db.open&&this.db.close();}get open(){return this.db.open}};var te=createRequire(import.meta.url),k=class{constructor(e){i(this,"backend","node:sqlite");i(this,"db");let t=te("node:sqlite");this.db=new t.DatabaseSync(e);}exec(e){this.db.exec(e);}prepare(e){return new f(this.db.prepare(e))}pragma(e,t){let n=e.replace(/[^a-zA-Z0-9_]/g,"");if(n){try{this.db.exec(`PRAGMA ${n}`);}catch{return}if(t?.simple===true)try{return this.db.prepare(`SELECT ${n} AS v`).get()?.v}catch{return}}}transaction(e){return((...n)=>{this.db.exec("BEGIN");let a;try{a=e(...n);}catch(s){try{this.db.exec("ROLLBACK");}catch{}throw s}return this.db.exec("COMMIT"),a})}close(){this.db.isOpen&&this.db.close();}get open(){return this.db.isOpen}};var re=createRequire(import.meta.url),Q=r=>typeof r=="function"&&r.prototype!==void 0,g=class{constructor(e){i(this,"backend","@tursodatabase/database");i(this,"db",null);let t=re("@tursodatabase/database"),n=Q(t)?t:t.default;if(!Q(n))throw new TypeError(`@tursodatabase/database import did not expose a constructor (got ${typeof t})`);this.db=new n(e);}requireDb(){if(!this.db)throw new Error(`Turso backend not initialized (db=${String(this.db)})`);return this.db}exec(e){this.requireDb().exec(e);}prepare(e){return new f(this.requireDb().prepare(e))}pragma(e){this.requireDb().exec(`PRAGMA ${e}`);}transaction(e){return((...n)=>{let a=this.requireDb();a.exec("BEGIN");let s;try{s=e(...n);}catch(d){try{a.exec("ROLLBACK");}catch{}throw d}return a.exec("COMMIT"),s})}close(){if(this.db)try{this.db.close();}finally{this.db=null;}}get open(){return this.db!==null}};var ae=256,L=class{constructor(e){i(this,"backend",e);i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let n=this.backend.prepare(e);if(this.cache.size>=ae){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,n),n}clear(){this.cache.clear();}},K=r=>r==null?{}:typeof r!="object"?{}:{...r},ie=r=>r.map(K);function O(r){if(!q(r))throw new l(`Unsafe SQL identifier: ${JSON.stringify(r)}`);return `"${r}"`}function se(r){let e=r.trimStart();if(e.length===0)return false;let a=((e.split(`
5
+ `,1)[0]??"").trimStart().split(/\s+/,1)[0]??"").toUpperCase();return a==="CREATE"||a==="DROP"||a==="ALTER"||a==="TRUNCATE"||a==="REPLACE"}var I=class{constructor(e,t){i(this,"db",e);i(this,"depth");i(this,"finished",false);this.depth=t;}isFinished(){return this.finished}async query(e,t){return this.assertOpen(),this.db.query(e,t)}async queryOne(e,t){return this.assertOpen(),this.db.queryOne(e,t)}async execute(e,t){return this.assertOpen(),this.db.execute(e,t)}async exec(e){this.assertOpen(),await this.db.exec(e);}async commit(){this.finished||(this.finished=true,this.depth===1&&this.db.commitRoot(),this.db.popTxDepth());}async rollback(){if(!this.finished){this.finished=true;try{this.depth===1?this.db.rollbackRoot():this.db.rollbackToSavepoint(`sp_${this.depth}`);}catch{}this.db.popTxDepth();}}async savepoint(e){this.assertOpen(),this.db.execSavepoint(O(e));}async release(e){this.assertOpen(),this.db.execRelease(O(e));}async rollbackTo(e){this.assertOpen(),this.db.execRollbackTo(O(e));}assertOpen(){if(this.finished)throw new l(`Transaction already finalized (depth=${this.depth})`)}},R=class{constructor(e){i(this,"config",e);i(this,"flavor","sqlite");i(this,"sqliteBackend");i(this,"backend",null);i(this,"stmtCache",null);i(this,"inTxDepth",0);i(this,"readOnlyFlag",false);i(this,"initialized",false);i(this,"walShmSymlink",null);i(this,"effectiveDbPath",null);let t=e.sqlite??{};this.sqliteBackend=t.backend===void 0||t.backend==="auto"?w():t.backend;}async initialize(){if(this.initialized)return;let e=this.config.sqlite??{},t=e.path??":memory:",n=e.walMode!==false,a=e.foreignKeys!==false,s=e.readonly===true,d=e.busyTimeoutMs??5e3,v=e.walShmPath,N=this.resolveOpenPath(t,v);try{this.backend=this.createBackend(N,{readonly:s});}catch(D){throw this.cleanupWalShmSymlink(),new o(`Failed to create SQLite backend (${this.sqliteBackend}) at "${N}"`,D)}this.readOnlyFlag=s,this.stmtCache=new L(this.backend);try{!s&&t!==":memory:"&&n&&this.backend.exec("PRAGMA journal_mode = WAL"),!s&&a&&this.backend.exec("PRAGMA foreign_keys = ON"),this.backend.exec(`PRAGMA busy_timeout = ${d}`);}catch(D){throw this.backend=null,this.stmtCache=null,this.cleanupWalShmSymlink(),new o("Failed to apply SQLite pragmas",D)}this.initialized=true;}resolveOpenPath(e,t){if(e===":memory:"||t===void 0||t===""||this.sqliteBackend!=="better-sqlite3")return e;let n=p.dirname(e);if(p.resolve(n)===p.resolve(t))return e;let a=p.basename(e),s=p.join(t,a);try{try{let d=y.lstatSync(s);(d.isSymbolicLink()||d.isFile())&&y.unlinkSync(s);}catch{}return y.symlinkSync(p.resolve(e),s),this.walShmSymlink=s,this.effectiveDbPath=s,s}catch(d){throw new o(`Failed to create symlink for WAL at "${t}" \u2192 "${e}". Check directory existence & write permission.`,d)}}cleanupWalShmSymlink(){if(this.walShmSymlink){try{y.unlinkSync(this.walShmSymlink);}catch{}this.walShmSymlink=null,this.effectiveDbPath=null;}}createBackend(e,t){switch(this.sqliteBackend){case "better-sqlite3":return new b(e,{readonly:t.readonly});case "node:sqlite":return new k(e);case "@tursodatabase/database":return new g(e);default:throw new o(`Unsupported SQLite backend: ${String(this.sqliteBackend)}`)}}async close(){if(!this.backend){this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();return}try{this.backend.close();}finally{this.backend=null,this.stmtCache?.clear(),this.stmtCache=null,this.inTxDepth=0,this.initialized=false,this.cleanupWalShmSymlink();}}isConnected(){return this.backend?.open===true}isReadOnly(){return this.readOnlyFlag}requireBackend(){if(!this.backend)throw new o("SQLite database not initialized. Call initialize() first.");return this.backend}requireCache(){if(!this.stmtCache)throw new o("SQLite database not initialized. Call initialize() first.");return this.stmtCache}async query(e,t){let n=this.prepareOrThrow(e);try{return ie(n.all(...t??[]))}catch(a){throw new c(`SQLite query failed: ${this.errorMessage(a)}`,a)}}async queryOne(e,t){let n=this.prepareOrThrow(e);try{let a=n.get(...t??[]);return a==null?null:K(a)}catch(a){throw new c(`SQLite queryOne failed: ${this.errorMessage(a)}`,a)}}async execute(e,t){let n=this.prepareOrThrow(e);try{return n.run(...t??[])}catch(a){throw new c(`SQLite execute failed: ${this.errorMessage(a)}`,a)}}prepareOrThrow(e){try{return this.requireCache().get(e)}catch(t){throw t instanceof o?t:new c(`SQLite prepare failed: ${this.errorMessage(t)}`,t)}}async exec(e){let t=this.requireBackend();try{t.exec(e),se(e)&&this.stmtCache?.clear();}catch(n){throw new c(`SQLite exec failed: ${this.errorMessage(n)}`,n)}}async execBatch(e){for(let t of e)await this.exec(t);}async begin(){let e=this.requireBackend();if(this.readOnlyFlag)throw new l("Cannot begin transaction on read-only SQLite database");let t=this.pushTxDepth();try{t===1?e.exec("BEGIN"):e.exec(`SAVEPOINT sp_${t}`);}catch(n){this.popTxDepth();let a=t===1?"BEGIN":`SAVEPOINT sp_${t}`;throw new l(`${a} failed`,n)}return new I(this,t)}async withTransaction(e){let t=await this.begin();try{let n=await e(t);return await t.commit(),n}catch(n){try{await t.rollback();}catch{}throw n}}getTransactionDepth(){return this.inTxDepth}commitRoot(){this.requireBackend().exec("COMMIT");}rollbackRoot(){this.requireBackend().exec("ROLLBACK");}rollbackToSavepoint(e){this.requireBackend().exec(`ROLLBACK TO SAVEPOINT ${e}`);}execSavepoint(e){this.requireBackend().exec(`SAVEPOINT ${e}`);}execRelease(e){this.requireBackend().exec(`RELEASE SAVEPOINT ${e}`);}execRollbackTo(e){this.requireBackend().exec(`ROLLBACK TO SAVEPOINT ${e}`);}pushTxDepth(){return this.inTxDepth+=1}popTxDepth(){this.inTxDepth>0&&(this.inTxDepth-=1);}errorMessage(e){return e instanceof Error?e.message:String(e)}};var le=256,F=class{constructor(){i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let n=C(e,"numbered");if(this.cache.size>=le){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,n),n}clear(){this.cache.clear();}},ce=r=>r==null?{}:{...r},de=r=>r.map(e=>ce(e)),$=r=>{if(!q(r))throw new l(`Unsafe SQL identifier: ${JSON.stringify(r)}`);return `"${r}"`};function W(r,e){return r.includes("?")?{sql:C(r,"numbered"),params:e?[...e]:[]}:{sql:r,params:void 0}}var P=class{constructor(e,t){i(this,"db",e);i(this,"depth");i(this,"finished",false);this.depth=t;}get client(){return this.db.getClient(this.depth)}isFinished(){return this.finished}assertOpen(){if(this.finished)throw new l("Transaction already finalized")}async query(e,t){return this.assertOpen(),await G(this.client,e,t)}async queryOne(e,t){let n=await this.query(e,t);return n.length>0?n[0]??null:null}async execute(e,t){return this.assertOpen(),await H(this.client,e,t)}async exec(e){this.assertOpen(),await z(this.client,e);}async commit(){if(!this.finished)if(this.finished=true,this.depth===1)try{await this.client.query("COMMIT");}finally{this.db.releaseTxClient(false),this.db.clearTxCtx();}else await this.client.query(`RELEASE SAVEPOINT sp_${this.depth}`);}async rollback(){if(!this.finished)if(this.finished=true,this.depth===1)try{await this.client.query("ROLLBACK");}catch{}finally{this.db.releaseTxClient(false),this.db.clearTxCtx();}else try{await this.client.query(`ROLLBACK TO SAVEPOINT sp_${this.depth}`);}catch{}}async savepoint(e){this.assertOpen(),await this.client.query(`SAVEPOINT ${$(e)}`);}async release(e){this.assertOpen(),await this.client.query(`RELEASE SAVEPOINT ${$(e)}`);}async rollbackTo(e){this.assertOpen(),await this.client.query(`ROLLBACK TO SAVEPOINT ${$(e)}`);}};async function G(r,e,t){let{sql:n,params:a}=W(e,t);try{let s=await r.query(n,a);return de(s.rows)}catch(s){throw new c(`PostgreSQL query failed: ${s instanceof Error?s.message:String(s)}`,s)}}async function H(r,e,t){let{sql:n,params:a}=W(e,t);try{return {changes:(await r.query(n,a)).rowCount??0}}catch(s){throw new c(`PostgreSQL execute failed: ${s instanceof Error?s.message:String(s)}`,s)}}async function z(r,e){try{await r.query(e);}catch(t){throw new c(`PostgreSQL exec failed: ${t instanceof Error?t.message:String(t)}`,t)}}async function ue(r,e){if(e.length===0)return;let t=e.join(`;
6
+ `)+";";await z(r,t);}var T=class{constructor(e){i(this,"config",e);i(this,"flavor","postgresql");i(this,"sqliteBackend");i(this,"pool",null);i(this,"translatedSqlCache",new F);i(this,"txCtx",null);i(this,"lastTxDepth",0);}async initialize(){if(!this.pool)try{this.pool=new Pool({host:this.config.host??"localhost",port:this.config.port??5432,user:this.config.username??"postgres",password:this.config.password??"",database:this.config.database??"eas_database",ssl:this.config.ssl??!1,max:this.config.poolSize??10}),(await this.pool.connect()).release();}catch(e){throw this.pool=null,new o("Failed to connect to PostgreSQL",e)}}async close(){if(!this.pool)return;let e=this.pool;this.pool=null;try{await e.end();}catch(t){throw new o("Failed to close PostgreSQL pool",t)}finally{this.translatedSqlCache.clear(),this.txCtx=null,this.lastTxDepth=0;}}isConnected(){return this.pool===null?false:!this.pool.ended&&!this.pool.closing}requirePool(){if(!this.pool)throw new o("PostgreSQL database not initialized. Call initialize() first.");return this.pool}async query(e,t){let n=await this.requirePool().connect();try{return await G(n,e,t)}finally{n.release();}}async queryOne(e,t){let n=await this.query(e,t);return n.length>0?n[0]??null:null}async execute(e,t){let n=await this.requirePool().connect();try{return await H(n,e,t)}finally{n.release();}}async exec(e){let t=await this.requirePool().connect();try{await z(t,e);}finally{t.release();}}async execBatch(e){if(e.length===0)return;let t=await this.requirePool().connect();try{await ue(t,e);}finally{t.release();}}async begin(){let e=this.requirePool(),t=this.pushTxDepth();if(t>1){let a=this.requireCtx(t);try{await a.client.query(`SAVEPOINT sp_${t}`);}catch(s){throw this.popTxDepth(),new l(`SAVEPOINT sp_${t} failed`,s)}return new P(this,t)}let n;try{n=await e.connect();}catch(a){throw this.popTxDepth(),new l("BEGIN failed: cannot acquire client",a)}try{await n.query("BEGIN");}catch(a){throw n.release(true),this.popTxDepth(),new l("BEGIN failed",a)}return this.txCtx={client:n,depth:t},new P(this,t)}requireCtx(e){if(!this.txCtx)throw new l(`No active transaction (depth=${e})`);return this.txCtx}getClient(e){return this.requireCtx(e).client}clearTxCtx(){this.txCtx=null,this.lastTxDepth=0,this.translatedSqlCache.clear();}releaseTxClient(e){let t=this.txCtx;if(t)try{t.client.release(e);}catch{}}async withTransaction(e){let t=await this.begin();try{let n=await e(t);return await t.commit(),n}catch(n){try{await t.rollback();}catch{}throw n}}pushTxDepth(){return this.lastTxDepth+=1}popTxDepth(){this.lastTxDepth>0&&(this.lastTxDepth-=1);}getTransactionDepth(){return this.lastTxDepth}};var A=class{static create(e){switch(e.flavor){case "sqlite":return new R(e);case "postgresql":return new T(e);default:{let t=e.flavor;throw new o(`Unsupported database flavor: ${String(t)}`)}}}};var he=256,B=class{constructor(e){i(this,"flavor","sqlite");i(this,"sqliteBackend");i(this,"backend",null);i(this,"stmtCache",null);i(this,"initialized",false);i(this,"walShmSymlink",null);i(this,"effectiveDbPath",null);i(this,"dbPath");i(this,"readOnlyFlag");i(this,"walModeFlag");i(this,"foreignKeysFlag");i(this,"busyTimeoutMsFlag");i(this,"walShmPathFlag");this.sqliteBackend=e.backend===void 0||e.backend==="auto"?w():e.backend,this.dbPath=e.path??":memory:",this.readOnlyFlag=e.readonly??false,this.walModeFlag=e.walMode??true,this.foreignKeysFlag=e.foreignKeys??true,this.busyTimeoutMsFlag=e.busyTimeoutMs??5e3,this.walShmPathFlag=e.walShmPath;}resolveBackendPath(e){return e===":memory:"?"":e}initialize(){if(this.initialized)return;let e=this.walModeFlag,t=this.foreignKeysFlag,n=this.readOnlyFlag,a=this.busyTimeoutMsFlag,s=this.resolveOpenPath(this.dbPath,e?this.walShmPathFlag:void 0),d=s===":memory:"?"":s;try{this.backend=this.createBackend(d,{readonly:n});}catch(v){throw this.cleanupWalShmSymlink(),new o(`Failed to create SQLite backend (${this.sqliteBackend}) at "${s}"`,v)}this.stmtCache=new M(this.backend);try{!n&&this.dbPath!==":memory:"&&e&&this.backend.exec("PRAGMA journal_mode = WAL"),n||this.backend.exec(`PRAGMA foreign_keys = ${t?"ON":"OFF"}`),this.backend.exec(`PRAGMA busy_timeout = ${a}`);}catch(v){throw this.backend=null,this.stmtCache=null,this.cleanupWalShmSymlink(),new o("Failed to apply SQLite pragmas",v)}this.initialized=true;}close(){if(!this.backend){this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();return}try{this.backend.close();}finally{this.backend=null,this.stmtCache?.clear(),this.stmtCache=null,this.initialized=false,this.cleanupWalShmSymlink();}}isOpen(){return this.backend?.open===true}isReadOnly(){return this.readOnlyFlag}getDbPath(){return this.dbPath}getBackend(){return this.sqliteBackend}getJournalMode(){this.assertInitialized();let e=this.requireBackend().pragma("journal_mode"),t=Array.isArray(e)?e[0]:e;if(t==null)return "";if(typeof t=="object"){let n=t.journal_mode;return typeof n=="string"?n.toLowerCase():String(n??"").toLowerCase()}return String(t).toLowerCase()}prepare(e){this.assertInitialized();try{return this.requireCache().get(e)}catch(t){throw t instanceof o?t:new c(`SQLite prepare failed: ${V(t)}`,t)}}exec(e){this.assertInitialized();let t=this.requireBackend();try{t.exec(e),pe(e)&&this.stmtCache?.clear();}catch(n){throw new c(`SQLite exec failed: ${V(n)}`,n)}}pragma(e,t){return this.assertInitialized(),this.requireBackend().pragma(e,t)}transaction(e){if(this.assertInitialized(),this.readOnlyFlag)throw new l("Cannot begin transaction on read-only SQLite database");return this.requireBackend().transaction(e)}execBatch(e){if(e.length!==0)for(let t of e)this.exec(t);}resolveOpenPath(e,t){if(e===":memory:"||t===void 0||t===""||this.sqliteBackend!=="better-sqlite3")return e;let n=p.dirname(e);if(p.resolve(n)===p.resolve(t))return e;let a=p.basename(e),s=p.join(t,a);try{try{let d=y.lstatSync(s);(d.isSymbolicLink()||d.isFile())&&y.unlinkSync(s);}catch{}return y.symlinkSync(p.resolve(e),s),this.walShmSymlink=s,this.effectiveDbPath=s,s}catch(d){throw new o(`Failed to create symlink for WAL at "${t}" \u2192 "${e}". Check directory existence & write permission.`,d)}}cleanupWalShmSymlink(){if(this.walShmSymlink){try{y.unlinkSync(this.walShmSymlink);}catch{}this.walShmSymlink=null,this.effectiveDbPath=null;}}createBackend(e,t){switch(this.sqliteBackend){case "better-sqlite3":return new b(e,{readonly:t.readonly});case "node:sqlite":return new k(e);case "@tursodatabase/database":return new g(e);default:throw new o(`Unsupported SQLite backend: ${String(this.sqliteBackend)}`)}}requireBackend(){if(!this.backend)throw new o("SQLite database not initialized. Call initialize() first.");return this.backend}requireCache(){if(!this.stmtCache)throw new o("SQLite database not initialized. Call initialize() first.");return this.stmtCache}assertInitialized(){if(!this.initialized)throw new o("SyncSqliteConnection not initialized. Call initialize() first.")}walModeDefault(){return true}foreignKeysDefault(){return true}readonlyDefault(){return false}busyTimeoutDefault(){return 5e3}walShmPathDefault(){}syncStmtCacheAccessor(){return this.requireCache()}},M=class{constructor(e){i(this,"backend",e);i(this,"cache",new Map);}get(e){let t=this.cache.get(e);if(t)return this.cache.delete(e),this.cache.set(e,t),t;let n=this.backend.prepare(e);if(this.cache.size>=he){let a=this.cache.keys().next().value;a!==void 0&&this.cache.delete(a);}return this.cache.set(e,n),n}clear(){this.cache.clear();}};function pe(r){let e=r.trimStart();if(e.length===0)return false;let a=((e.split(`
7
+ `,1)[0]??"").trimStart().split(/\s+/,1)[0]??"").toUpperCase();return a==="CREATE"||a==="DROP"||a==="ALTER"||a==="TRUNCATE"||a==="REPLACE"}function V(r){return r instanceof Error?r.message:String(r)}function me(r={}){let e=r.backend===void 0||r.backend==="auto"?w():r.backend,t=new B({...r,backend:e}),n=r.path??":memory:";if(n!==":memory:"){let a=p.dirname(n);try{y.mkdirSync(a,{recursive:!0});}catch(s){throw new o(`Failed to ensure directory for SQLite database at "${n}"`,s)}}return t}export{o as ConnectionError,x as DatabaseError,A as DatabaseFactory,T as PostgresDatabase,c as QueryError,R as SqliteDatabase,B as SyncSqliteConnection,l as TransactionError,me as createSyncSqliteConnection,A as default,q as isSafeIdent,w as resolveDefaultSqliteBackend,C as translatePlaceholders};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easbot/database",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Unified database abstraction for EASBot — SQLite (better-sqlite3 / node:sqlite / @tursodatabase/database) with first-class transactions (begin/commit/rollback + nested SAVEPOINT) and PostgreSQL behind a single DatabaseInterface.",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -66,6 +66,7 @@
66
66
  "@types/pg": "^8.20.0",
67
67
  "@vitest/coverage-v8": "^4.1.5",
68
68
  "better-sqlite3": "^12.9.0",
69
+ "fast-glob": "^3.3.3",
69
70
  "dotenv": "^17.4.2",
70
71
  "tsup": "^8.5.1",
71
72
  "typescript": "^6.0.3",
@@ -82,6 +83,7 @@
82
83
  "build": "tsup --env.NODE_ENV production",
83
84
  "test": "vitest",
84
85
  "test:run": "vitest run",
86
+ "test:clean": "npx tsx scripts/clean-test-fixtures.ts",
85
87
  "type-check": "tsc --noEmit",
86
88
  "lint": "biome check .",
87
89
  "lint:fix": "biome check --write .",