@orchestr-sh/orchestr 1.11.3 → 1.11.4
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/CHANGELOG.md +2 -0
- package/dist/Database/Adapters/DrizzleAdapter.cjs +3 -2
- package/dist/Database/Adapters/DrizzleAdapter.d.cts +128 -6
- package/dist/Database/Adapters/DrizzleAdapter.d.cts.map +1 -1
- package/dist/Database/Adapters/DrizzleAdapter.d.mts +128 -6
- package/dist/Database/Adapters/DrizzleAdapter.d.mts.map +1 -1
- package/dist/Database/Adapters/DrizzleAdapter.mjs +3 -2
- package/dist/Database/Adapters/DrizzleAdapter.mjs.map +1 -1
- package/dist/Database/Connection.cjs +1 -1
- package/dist/Database/Connection.d.cts +29 -2
- package/dist/Database/Connection.d.cts.map +1 -1
- package/dist/Database/Connection.d.mts +29 -2
- package/dist/Database/Connection.d.mts.map +1 -1
- package/dist/Database/Connection.mjs +1 -1
- package/dist/Database/Connection.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
## [1.11.4](https://github.com/orchestr-sh/orchestr/compare/v1.11.3...v1.11.4) (2026-11-07)
|
|
2
|
+
|
|
1
3
|
## [1.11.3](https://github.com/orchestr-sh/orchestr/compare/v1.11.2...v1.11.3) (2026-11-07)
|
|
2
4
|
|
|
3
5
|
## [1.11.2](https://github.com/orchestr-sh/orchestr/compare/v1.11.1...v1.11.2) (2026-05-08)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require(`../../_virtual/_rolldown/runtime.cjs`);var e=class{config;client;rawClient;connected=!1;inTransaction=!1;transactionClient;constructor(e){this.config=e}async connect(){if(!this.connected)try{switch(this.config.driver){case`postgres`:await this.connectPostgres();break;case`mysql`:case`mysql2`:await this.connectMySQL();break;case`better-sqlite3`:case`sqlite`:await this.connectSQLite();break;default:throw Error(`Unsupported database driver: ${this.config.driver}`)}this.connected=!0}catch(e){throw Error(`Failed to connect to database: ${e?.message||e}`,{cause:e})}}async connectPostgres(){let{drizzle:e}=await import(`drizzle-orm/postgres-js`),t=(await import(`postgres`)).default({host:this.config.host,port:this.config.port,database:this.config.database,username:this.config.username,password:this.config.password,max:this.config.poolMax||10});this.rawClient=t,this.client=e(t)}async connectMySQL(){let{drizzle:e}=await import(`drizzle-orm/mysql2`),t=await(await import(`mysql2/promise`)).createPool({host:this.config.host,port:this.config.port,database:this.config.database,user:this.config.username,password:this.config.password,connectionLimit:this.config.poolMax||10});this.rawClient=t,this.client=e(t)}async connectSQLite(){let{drizzle:e}=await import(`drizzle-orm/better-sqlite3`),t=new(await(import(`better-sqlite3`))).default(this.config.database);this.rawClient=t,this.client=e(t)}async disconnect(){if(this.connected){if(this.rawClient)switch(this.config.driver){case`postgres`:await this.rawClient.end?.();break;case`mysql`:case`mysql2`:await this.rawClient.end?.();break;case`better-sqlite3`:case`sqlite`:this.rawClient.close?.();break}this.connected=!1,this.client=null,this.rawClient=null
|
|
1
|
+
require(`../../_virtual/_rolldown/runtime.cjs`);var e=class{config;client;rawClient;connected=!1;inTransaction=!1;transactionClient;transactionDepth=0;constructor(e){this.config=e}async connect(){if(!this.connected)try{switch(this.config.driver){case`postgres`:await this.connectPostgres();break;case`mysql`:case`mysql2`:await this.connectMySQL();break;case`better-sqlite3`:case`sqlite`:await this.connectSQLite();break;default:throw Error(`Unsupported database driver: ${this.config.driver}`)}this.connected=!0}catch(e){throw Error(`Failed to connect to database: ${e?.message||e}`,{cause:e})}}async connectPostgres(){let{drizzle:e}=await import(`drizzle-orm/postgres-js`),t=(await import(`postgres`)).default({host:this.config.host,port:this.config.port,database:this.config.database,username:this.config.username,password:this.config.password,max:this.config.poolMax||10});this.rawClient=t,this.client=e(t)}async connectMySQL(){let{drizzle:e}=await import(`drizzle-orm/mysql2`),t=await(await import(`mysql2/promise`)).createPool({host:this.config.host,port:this.config.port,database:this.config.database,user:this.config.username,password:this.config.password,connectionLimit:this.config.poolMax||10});this.rawClient=t,this.client=e(t)}async connectSQLite(){let{drizzle:e}=await import(`drizzle-orm/better-sqlite3`),t=new(await(import(`better-sqlite3`))).default(this.config.database);this.rawClient=t,this.client=e(t)}async disconnect(){if(this.connected){if(this.rawClient)switch(this.config.driver){case`postgres`:await this.rawClient.end?.();break;case`mysql`:case`mysql2`:await this.rawClient.end?.();break;case`better-sqlite3`:case`sqlite`:this.rawClient.close?.();break}this.connected=!1,this.client=null,this.rawClient=null,this.transactionClient=null,this.inTransaction=!1,this.transactionDepth=0}}async query(e,t=[]){let n=await this.execute(e,t,`all`);return{rows:n.rows,rowCount:n.rowCount}}async select(e,t=[]){return(await this.execute(e,t,`all`)).rows}async insert(e,t=[]){return(await this.execute(e,t,`run`)).insertId}async update(e,t=[]){return(await this.execute(e,t,`run`)).rowCount}async delete(e,t=[]){return(await this.execute(e,t,`run`)).rowCount}async beginTransaction(){if(this.ensureConnected(),this.transactionDepth===0){await this.beginRootTransaction();return}await this.executeTransactionControl(`SAVEPOINT ${this.savepointName(this.transactionDepth)}`),this.transactionDepth+=1}async commit(){if(!this.inTransaction)throw Error(`No transaction in progress`);if(this.transactionDepth>1){await this.executeTransactionControl(`RELEASE SAVEPOINT ${this.savepointName(this.transactionDepth-1)}`),--this.transactionDepth;return}let e=this.transactionClient;this.isMysql()?await e.commit():await this.executeTransactionControl(`COMMIT`),this.transactionDepth=0,this.inTransaction=!1,this.transactionClient=null,await this.releaseTransactionClient(e)}async rollback(){if(!this.inTransaction)throw Error(`No transaction in progress`);if(this.transactionDepth>1){await this.executeTransactionControl(`ROLLBACK TO ${this.savepointName(this.transactionDepth-1)}`),--this.transactionDepth;return}let e=this.transactionClient;this.isMysql()?await e.rollback():await this.executeTransactionControl(`ROLLBACK`),this.transactionDepth=0,this.inTransaction=!1,this.transactionClient=null,await this.releaseTransactionClient(e)}async transaction(e){await this.beginTransaction();try{let t=await e(this);return await this.commit(),t}catch(e){throw await this.rollback(),e}}async beginRootTransaction(){let e=await this.acquireTransactionClient();this.transactionClient=e,this.inTransaction=!0,this.transactionDepth=1;try{this.isMysql()?await e.beginTransaction():await this.executeTransactionControl(`BEGIN`)}catch(t){throw this.transactionDepth=0,this.inTransaction=!1,this.transactionClient=null,await this.releaseTransactionClient(e),t}}async acquireTransactionClient(){switch(this.config.driver){case`postgres`:return this.rawClient.reserve();case`mysql`:case`mysql2`:return this.rawClient.getConnection();default:return this.rawClient}}async releaseTransactionClient(e){if(!(!e||e===this.rawClient))switch(this.config.driver){case`postgres`:await e.release?.();break;case`mysql`:case`mysql2`:e.release?.();break}}savepointName(e){return`trans_${e}`}async executeTransactionControl(e){if(!this.isMysql()){await this.execute(e,[],`all`);return}let t=this.transactionClient??this.rawClient;try{await t.query(e)}catch(t){throw Error(`Query failed: ${t?.message||t}\nSQL: ${e}`,{cause:t})}}isMysql(){return this.config.driver===`mysql`||this.config.driver===`mysql2`}isConnected(){return this.connected}getDriver(){return this.client}async getTableInfo(e){switch(this.ensureConnected(),this.config.driver){case`postgres`:return this.getPostgresTableInfo(e);case`mysql`:case`mysql2`:return this.getMySQLTableInfo(e);case`better-sqlite3`:case`sqlite`:return this.getSQLiteTableInfo(e);default:throw Error(`Table info not supported for this driver`)}}async getPostgresTableInfo(e){return this.select(`
|
|
2
2
|
SELECT column_name, data_type, is_nullable, column_default
|
|
3
3
|
FROM information_schema.columns
|
|
4
4
|
WHERE table_name = ?
|
|
@@ -13,4 +13,5 @@ require(`../../_virtual/_rolldown/runtime.cjs`);var e=class{config;client;rawCli
|
|
|
13
13
|
FROM sqlite_master
|
|
14
14
|
WHERE type = 'table'
|
|
15
15
|
AND name NOT LIKE 'sqlite_%'
|
|
16
|
-
`)).map(e=>e.name)}
|
|
16
|
+
`)).map(e=>e.name)}async execute(e,t,n){this.ensureConnected();let r=this.transactionClient??this.rawClient;try{let i=this.normalizeBindings(t);switch(this.config.driver){case`postgres`:return await this.executePostgres(r,e,i,n);case`mysql`:case`mysql2`:return await this.executeMysql(r,e,i,n);case`better-sqlite3`:case`sqlite`:return this.executeSqlite(r,e,i,n);default:throw Error(`Unsupported database driver: ${this.config.driver}`)}}catch(t){throw Error(`Query failed: ${t?.message||t}\nSQL: ${e}`,{cause:t})}}executeSqlite(e,t,n,r){let i=e.prepare(t);if(r===`run`||r===`all`&&i.reader===!1){let e=i.run(...n);return{rows:[],rowCount:Number(e?.changes??0),insertId:e?.lastInsertRowid}}if(r===`get`){let e=i.get(...n);return{rows:e===void 0?[]:[e],rowCount:e===void 0?0:1}}let a=i.all(...n);return{rows:a,rowCount:a.length}}async executePostgres(e,t,n,r){let i=n.length>0?this.toPostgresPlaceholders(t,n.length):t,a=await e.unsafe(i,n),o=Array.isArray(a)?a:a?.rows||[];return r===`run`?{rows:o,rowCount:Number.isFinite(a?.count)?Number(a.count):o.length,insertId:o[0]?.id}:r===`get`?{rows:o.slice(0,1),rowCount:Math.min(o.length,1)}:{rows:o,rowCount:o.length}}async executeMysql(e,t,n,r){let[i]=await e.execute(t,n);if(Array.isArray(i)){let e=i;return r===`run`?{rows:e,rowCount:e.length,insertId:e[0]?.id}:r===`get`?{rows:e.slice(0,1),rowCount:Math.min(e.length,1)}:{rows:e,rowCount:e.length}}return{rows:[],rowCount:Number(i?.affectedRows??0),insertId:i?.insertId}}normalizeBindings(e){return e.map(e=>this.normalizeBinding(e))}normalizeBinding(e){if(e==null)return null;if(e instanceof Date)return e.toISOString();switch(typeof e){case`string`:case`number`:case`bigint`:return e;case`boolean`:return this.bindsBooleansNatively()?e:Number(e);case`object`:if(this.isBinary(e))return e;throw this.unsupportedBinding(e);default:throw this.unsupportedBinding(e)}}bindsBooleansNatively(){return this.config.driver!==`better-sqlite3`&&this.config.driver!==`sqlite`}isBinary(e){return typeof Buffer<`u`&&Buffer.isBuffer(e)?!0:ArrayBuffer.isView(e)&&!(e instanceof DataView)}unsupportedBinding(e){return TypeError(`Cannot bind a value of type "${Array.isArray(e)?`array`:typeof e==`object`?`object`:typeof e}" as a query parameter for the "${this.config.driver}" driver. Serialize the value explicitly before passing it as a binding (for example: JSON.stringify()).`)}toPostgresPlaceholders(e,t){let n=``,r=0,i=0;for(;r<e.length;){let t=e[r];if(t===`'`||t===`"`||t==="`"){let i=this.endOfQuoted(e,r,t);n+=e.slice(r,i),r=i;continue}if(t===`-`&&e[r+1]===`-`){let t=e.indexOf(`
|
|
17
|
+
`,r),i=t===-1?e.length:t;n+=e.slice(r,i),r=i;continue}if(t===`/`&&e[r+1]===`*`){let t=e.indexOf(`*/`,r+2),i=t===-1?e.length:t+2;n+=e.slice(r,i),r=i;continue}if(t===`?`){i+=1,n+=`$${i}`,r+=1;continue}n+=t,r+=1}if(i!==t)throw Error(`Cannot bind ${t} parameter(s) against ${i} placeholder(s) in SQL: ${e}`);return n}endOfQuoted(e,t,n){let r=t+1;for(;r<e.length;){if(e[r]===n){if(e[r+1]===n){r+=2;continue}return r+1}r+=1}return e.length}ensureConnected(){if(!this.connected)throw Error(`Database not connected. Call connect() first.`)}};exports.DrizzleAdapter=e;
|
|
@@ -8,6 +8,12 @@ declare class DrizzleAdapter implements DatabaseAdapter {
|
|
|
8
8
|
protected connected: boolean;
|
|
9
9
|
protected inTransaction: boolean;
|
|
10
10
|
protected transactionClient: any;
|
|
11
|
+
/**
|
|
12
|
+
* Nesting level of the transaction stack: 0 means no transaction, 1 is the
|
|
13
|
+
* root transaction, and anything deeper is backed by a savepoint. Shared by
|
|
14
|
+
* every driver so nesting behaves identically regardless of the pool.
|
|
15
|
+
*/
|
|
16
|
+
protected transactionDepth: number;
|
|
11
17
|
constructor(config: DatabaseConfig);
|
|
12
18
|
/**
|
|
13
19
|
* Connect to the database
|
|
@@ -50,21 +56,76 @@ declare class DrizzleAdapter implements DatabaseAdapter {
|
|
|
50
56
|
*/
|
|
51
57
|
delete(sql: string, bindings?: any[]): Promise<number>;
|
|
52
58
|
/**
|
|
53
|
-
* Begin a transaction
|
|
59
|
+
* Begin a transaction.
|
|
60
|
+
*
|
|
61
|
+
* The outermost call pins a dedicated connection (for pooled Postgres/MySQL
|
|
62
|
+
* drivers) and issues `BEGIN` on it, then every later statement runs on that
|
|
63
|
+
* pinned client until the transaction ends. Nested calls open a savepoint
|
|
64
|
+
* (`SAVEPOINT trans_N`) instead of a second `BEGIN`, so an inner rollback
|
|
65
|
+
* only undoes the work done since that savepoint.
|
|
54
66
|
*/
|
|
55
67
|
beginTransaction(): Promise<void>;
|
|
56
68
|
/**
|
|
57
|
-
* Commit a transaction
|
|
69
|
+
* Commit a transaction.
|
|
70
|
+
*
|
|
71
|
+
* At nesting levels deeper than one this releases the innermost savepoint
|
|
72
|
+
* (`RELEASE SAVEPOINT trans_N`) and keeps the outer transaction open; only
|
|
73
|
+
* the root commit persists the work and gives the pinned connection back.
|
|
58
74
|
*/
|
|
59
75
|
commit(): Promise<void>;
|
|
60
76
|
/**
|
|
61
|
-
* Rollback a transaction
|
|
77
|
+
* Rollback a transaction.
|
|
78
|
+
*
|
|
79
|
+
* Inside a nested transaction this rolls back to the innermost savepoint
|
|
80
|
+
* (`ROLLBACK TO trans_N`) without touching the outer transaction; a root
|
|
81
|
+
* rollback discards everything and releases the pinned connection.
|
|
62
82
|
*/
|
|
63
83
|
rollback(): Promise<void>;
|
|
64
84
|
/**
|
|
65
|
-
* Execute a callback within a transaction
|
|
85
|
+
* Execute a callback within a transaction.
|
|
86
|
+
*
|
|
87
|
+
* Re-entrant: calling this inside another transaction opens a savepoint, so
|
|
88
|
+
* a failure in the inner callback rolls back only the inner work while the
|
|
89
|
+
* outer transaction stays usable.
|
|
66
90
|
*/
|
|
67
91
|
transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
|
|
92
|
+
/**
|
|
93
|
+
* Start the root transaction: pin a connection, store it as the transaction
|
|
94
|
+
* client, then issue `BEGIN` on exactly that client.
|
|
95
|
+
*/
|
|
96
|
+
protected beginRootTransaction(): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Reserve the connection that will carry the transaction.
|
|
99
|
+
*
|
|
100
|
+
* - better-sqlite3 owns a single connection: the raw client doubles as the
|
|
101
|
+
* transaction client and there is nothing to reserve.
|
|
102
|
+
* - postgres.js: `reserve()` hands back a dedicated connection from the pool.
|
|
103
|
+
* - mysql2: `getConnection()` checks a pooled connection out.
|
|
104
|
+
*/
|
|
105
|
+
protected acquireTransactionClient(): Promise<any>;
|
|
106
|
+
/**
|
|
107
|
+
* Give a pinned transaction connection back to its pool. The SQLite raw
|
|
108
|
+
* client is shared with normal execution, so it is never released here.
|
|
109
|
+
*/
|
|
110
|
+
protected releaseTransactionClient(client: any): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Name of the savepoint at the given transaction level. The first nested
|
|
113
|
+
* transaction is `trans_1`, the second `trans_2`, and so on.
|
|
114
|
+
*/
|
|
115
|
+
protected savepointName(level: number): string;
|
|
116
|
+
/**
|
|
117
|
+
* Run a transaction-control statement (`BEGIN`, `COMMIT`, `ROLLBACK`,
|
|
118
|
+
* `SAVEPOINT ...`) on the client that carries the transaction.
|
|
119
|
+
*
|
|
120
|
+
* Postgres and SQLite take the normal parameterized path with no bindings.
|
|
121
|
+
* MySQL does not accept every transaction-control command through its
|
|
122
|
+
* prepared-statement protocol, so savepoints go through the text protocol.
|
|
123
|
+
*/
|
|
124
|
+
protected executeTransactionControl(sql: string): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Whether the configured driver is one of the MySQL variants.
|
|
127
|
+
*/
|
|
128
|
+
protected isMysql(): boolean;
|
|
68
129
|
/**
|
|
69
130
|
* Check if adapter is connected
|
|
70
131
|
*/
|
|
@@ -106,9 +167,70 @@ declare class DrizzleAdapter implements DatabaseAdapter {
|
|
|
106
167
|
*/
|
|
107
168
|
protected getSQLiteTables(): Promise<string[]>;
|
|
108
169
|
/**
|
|
109
|
-
*
|
|
170
|
+
* Execute a statement with its bindings passed natively to the driver.
|
|
171
|
+
*
|
|
172
|
+
* This is the single execution path behind `query()`, `select()`, `insert()`,
|
|
173
|
+
* `update()` and `delete()`. Bindings are never written into the SQL text: the
|
|
174
|
+
* driver receives the statement and the values separately, so quotes,
|
|
175
|
+
* semicolons, comments and `?` characters inside a value stay data.
|
|
176
|
+
*/
|
|
177
|
+
private execute;
|
|
178
|
+
/**
|
|
179
|
+
* Execute through better-sqlite3: positional `?` parameters bound natively.
|
|
180
|
+
*/
|
|
181
|
+
private executeSqlite;
|
|
182
|
+
/**
|
|
183
|
+
* Execute through postgres.js: values are sent as real query parameters.
|
|
184
|
+
*/
|
|
185
|
+
private executePostgres;
|
|
186
|
+
/**
|
|
187
|
+
* Execute through mysql2: positional `?` parameters bound natively.
|
|
188
|
+
*/
|
|
189
|
+
private executeMysql;
|
|
190
|
+
/**
|
|
191
|
+
* Normalize bindings before handing them to the driver.
|
|
192
|
+
*
|
|
193
|
+
* `undefined` becomes `null`, dates become ISO strings, and booleans become
|
|
194
|
+
* 1/0 only for the drivers that cannot bind a boolean natively. Anything the
|
|
195
|
+
* driver cannot bind (objects, arrays, functions, symbols) fails loudly rather
|
|
196
|
+
* than being silently stringified into the SQL text.
|
|
197
|
+
*/
|
|
198
|
+
private normalizeBindings;
|
|
199
|
+
/**
|
|
200
|
+
* Normalize a single binding value.
|
|
201
|
+
*/
|
|
202
|
+
private normalizeBinding;
|
|
203
|
+
/**
|
|
204
|
+
* Whether the current driver can bind a JS boolean as a native parameter.
|
|
205
|
+
*
|
|
206
|
+
* better-sqlite3 only binds numbers, strings, bigints, buffers and null, so
|
|
207
|
+
* booleans are converted to 1/0 there. postgres.js and mysql2 both send
|
|
208
|
+
* booleans natively.
|
|
209
|
+
*/
|
|
210
|
+
private bindsBooleansNatively;
|
|
211
|
+
/**
|
|
212
|
+
* Binary values are bindable by every supported driver.
|
|
213
|
+
*/
|
|
214
|
+
private isBinary;
|
|
215
|
+
/**
|
|
216
|
+
* Error for values the driver cannot bind as a parameter.
|
|
217
|
+
*/
|
|
218
|
+
private unsupportedBinding;
|
|
219
|
+
/**
|
|
220
|
+
* Rewrite `?` placeholders into the `$n` form postgres.js expects.
|
|
221
|
+
*
|
|
222
|
+
* Only placeholder tokens are rewritten: quoted strings, quoted identifiers
|
|
223
|
+
* and comments are copied through verbatim, so a literal `?` inside the SQL
|
|
224
|
+
* text never shifts the binding order. Values are never touched here — they
|
|
225
|
+
* stay in the parameter array sent alongside the statement.
|
|
226
|
+
*/
|
|
227
|
+
private toPostgresPlaceholders;
|
|
228
|
+
/**
|
|
229
|
+
* End index (exclusive) of a quoted literal/identifier starting at `start`.
|
|
230
|
+
*
|
|
231
|
+
* Doubled quotes (`''`, `""`) are escapes and stay inside the quoted region.
|
|
110
232
|
*/
|
|
111
|
-
|
|
233
|
+
private endOfQuoted;
|
|
112
234
|
/**
|
|
113
235
|
* Ensure the adapter is connected
|
|
114
236
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DrizzleAdapter.d.cts","names":[],"sources":["../../../src/Database/Adapters/DrizzleAdapter.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"DrizzleAdapter.d.cts","names":[],"sources":["../../../src/Database/Adapters/DrizzleAdapter.ts"],"mappings":";;;cA8Ba,cAAA,YAA0B,eAAA;EAAA,UAaf,MAAA,EAAQ,cAAA;EAAA,UAZpB,MAAA;EAAA,UACA,SAAA;EAAA,UACA,SAAA;EAAA,UACA,aAAA;EAAA,UACA,iBAAA;EAkImE;;;;;EAAA,UA5HnE,gBAAA;cAEY,MAAA,EAAQ,cAAA;EA2JmB;;;EAtJ3C,OAAA,CAAA,GAAW,OAAA;EAuPwB;;;EAAA,UAvNzB,eAAA,CAAA,GAAmB,OAAA;EAuNuC;;;EAAA,UAnM1D,YAAA,CAAA,GAAgB,OAAA;EAkSwB;;;EAAA,UA9QxC,aAAA,CAAA,GAAiB,OAAA;EA+VsB;;;EAnVjD,UAAA,CAAA,GAAc,OAAA;EAsYe;;;EArW7B,KAAA,SAAA,CAAe,GAAA,UAAa,QAAA,WAAuB,OAAA,CAAQ,WAAA,CAAY,CAAA;EAvIxC;;;EAgJ/B,MAAA,SAAA,CAAgB,GAAA,UAAa,QAAA,WAAuB,OAAA,CAAQ,CAAA;EA9IxD;;;EAsJJ,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EA7IvC;;;EAqJJ,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EA9I3C;;;EAsJA,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAlGjC;;;;;;;;;EAgHV,gBAAA,CAAA,GAAoB,OAAA;EA/C+B;;;;;;;EAkEnD,MAAA,CAAA,GAAU,OAAA;EAzDkD;;;;;;;EAyF5D,QAAA,CAAA,GAAY,OAAA;EAzE+B;;;;;;;EAyG3C,WAAA,GAAA,CAAe,QAAA,GAAW,OAAA,EAAS,eAAA,KAAoB,OAAA,CAAQ,CAAA,IAAK,OAAA,CAAQ,CAAA;EAhElE;;;;EAAA,UAiFA,oBAAA,CAAA,GAAwB,OAAA;EAjBC;;;;;;;;EAAA,UA+CzB,wBAAA,CAAA,GAA4B,OAAA;EAA5B;;;;EAAA,UAgBA,wBAAA,CAAyB,MAAA,QAAc,OAAA;EAoB7C;;;;EAAA,UAAA,aAAA,CAAc,KAAA;EA8Bd;;;;;;;;EAAA,UAlBM,yBAAA,CAA0B,GAAA,WAAc,OAAA;EAyExC;;;EAAA,UAvDN,OAAA,CAAA;EA+DyB;;;EAxDnC,WAAA,CAAA;EAoFgB;;;EA7EhB,SAAA,CAAA;EAoGgB;;;EA7FV,YAAA,CAAa,SAAA,WAAoB,OAAA;EAoKzB;;;EAAA,UA/IE,oBAAA,CAAqB,SAAA,WAAoB,OAAA;EAwPjD;;;EAAA,UA3OQ,iBAAA,CAAkB,SAAA,WAAoB,OAAA;EAoU9C;;;EAAA,UA5TQ,kBAAA,CAAmB,SAAA,WAAoB,OAAA;;;;EAQjD,SAAA,CAAA,GAAa,OAAA;;;;YAoBH,iBAAA,CAAA,GAAqB,OAAA;;;;YAcrB,cAAA,CAAA,GAAkB,OAAA;;;;YASlB,eAAA,CAAA,GAAmB,OAAA;;;;;;;;;UAmBrB,OAAA;;;;UA8BN,aAAA;;;;UAsBM,eAAA;;;;UA2BA,YAAA;;;;;;;;;UAsCN,iBAAA;;;;UAOA,gBAAA;;;;;;;;UAiCA,qBAAA;;;;UAOA,QAAA;;;;UAWA,kBAAA;;;;;;;;;UAiBA,sBAAA;;;;;;UAsDA,WAAA;;;;YAoBE,eAAA,CAAA;AAAA"}
|
|
@@ -8,6 +8,12 @@ declare class DrizzleAdapter implements DatabaseAdapter {
|
|
|
8
8
|
protected connected: boolean;
|
|
9
9
|
protected inTransaction: boolean;
|
|
10
10
|
protected transactionClient: any;
|
|
11
|
+
/**
|
|
12
|
+
* Nesting level of the transaction stack: 0 means no transaction, 1 is the
|
|
13
|
+
* root transaction, and anything deeper is backed by a savepoint. Shared by
|
|
14
|
+
* every driver so nesting behaves identically regardless of the pool.
|
|
15
|
+
*/
|
|
16
|
+
protected transactionDepth: number;
|
|
11
17
|
constructor(config: DatabaseConfig);
|
|
12
18
|
/**
|
|
13
19
|
* Connect to the database
|
|
@@ -50,21 +56,76 @@ declare class DrizzleAdapter implements DatabaseAdapter {
|
|
|
50
56
|
*/
|
|
51
57
|
delete(sql: string, bindings?: any[]): Promise<number>;
|
|
52
58
|
/**
|
|
53
|
-
* Begin a transaction
|
|
59
|
+
* Begin a transaction.
|
|
60
|
+
*
|
|
61
|
+
* The outermost call pins a dedicated connection (for pooled Postgres/MySQL
|
|
62
|
+
* drivers) and issues `BEGIN` on it, then every later statement runs on that
|
|
63
|
+
* pinned client until the transaction ends. Nested calls open a savepoint
|
|
64
|
+
* (`SAVEPOINT trans_N`) instead of a second `BEGIN`, so an inner rollback
|
|
65
|
+
* only undoes the work done since that savepoint.
|
|
54
66
|
*/
|
|
55
67
|
beginTransaction(): Promise<void>;
|
|
56
68
|
/**
|
|
57
|
-
* Commit a transaction
|
|
69
|
+
* Commit a transaction.
|
|
70
|
+
*
|
|
71
|
+
* At nesting levels deeper than one this releases the innermost savepoint
|
|
72
|
+
* (`RELEASE SAVEPOINT trans_N`) and keeps the outer transaction open; only
|
|
73
|
+
* the root commit persists the work and gives the pinned connection back.
|
|
58
74
|
*/
|
|
59
75
|
commit(): Promise<void>;
|
|
60
76
|
/**
|
|
61
|
-
* Rollback a transaction
|
|
77
|
+
* Rollback a transaction.
|
|
78
|
+
*
|
|
79
|
+
* Inside a nested transaction this rolls back to the innermost savepoint
|
|
80
|
+
* (`ROLLBACK TO trans_N`) without touching the outer transaction; a root
|
|
81
|
+
* rollback discards everything and releases the pinned connection.
|
|
62
82
|
*/
|
|
63
83
|
rollback(): Promise<void>;
|
|
64
84
|
/**
|
|
65
|
-
* Execute a callback within a transaction
|
|
85
|
+
* Execute a callback within a transaction.
|
|
86
|
+
*
|
|
87
|
+
* Re-entrant: calling this inside another transaction opens a savepoint, so
|
|
88
|
+
* a failure in the inner callback rolls back only the inner work while the
|
|
89
|
+
* outer transaction stays usable.
|
|
66
90
|
*/
|
|
67
91
|
transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T>;
|
|
92
|
+
/**
|
|
93
|
+
* Start the root transaction: pin a connection, store it as the transaction
|
|
94
|
+
* client, then issue `BEGIN` on exactly that client.
|
|
95
|
+
*/
|
|
96
|
+
protected beginRootTransaction(): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Reserve the connection that will carry the transaction.
|
|
99
|
+
*
|
|
100
|
+
* - better-sqlite3 owns a single connection: the raw client doubles as the
|
|
101
|
+
* transaction client and there is nothing to reserve.
|
|
102
|
+
* - postgres.js: `reserve()` hands back a dedicated connection from the pool.
|
|
103
|
+
* - mysql2: `getConnection()` checks a pooled connection out.
|
|
104
|
+
*/
|
|
105
|
+
protected acquireTransactionClient(): Promise<any>;
|
|
106
|
+
/**
|
|
107
|
+
* Give a pinned transaction connection back to its pool. The SQLite raw
|
|
108
|
+
* client is shared with normal execution, so it is never released here.
|
|
109
|
+
*/
|
|
110
|
+
protected releaseTransactionClient(client: any): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Name of the savepoint at the given transaction level. The first nested
|
|
113
|
+
* transaction is `trans_1`, the second `trans_2`, and so on.
|
|
114
|
+
*/
|
|
115
|
+
protected savepointName(level: number): string;
|
|
116
|
+
/**
|
|
117
|
+
* Run a transaction-control statement (`BEGIN`, `COMMIT`, `ROLLBACK`,
|
|
118
|
+
* `SAVEPOINT ...`) on the client that carries the transaction.
|
|
119
|
+
*
|
|
120
|
+
* Postgres and SQLite take the normal parameterized path with no bindings.
|
|
121
|
+
* MySQL does not accept every transaction-control command through its
|
|
122
|
+
* prepared-statement protocol, so savepoints go through the text protocol.
|
|
123
|
+
*/
|
|
124
|
+
protected executeTransactionControl(sql: string): Promise<void>;
|
|
125
|
+
/**
|
|
126
|
+
* Whether the configured driver is one of the MySQL variants.
|
|
127
|
+
*/
|
|
128
|
+
protected isMysql(): boolean;
|
|
68
129
|
/**
|
|
69
130
|
* Check if adapter is connected
|
|
70
131
|
*/
|
|
@@ -106,9 +167,70 @@ declare class DrizzleAdapter implements DatabaseAdapter {
|
|
|
106
167
|
*/
|
|
107
168
|
protected getSQLiteTables(): Promise<string[]>;
|
|
108
169
|
/**
|
|
109
|
-
*
|
|
170
|
+
* Execute a statement with its bindings passed natively to the driver.
|
|
171
|
+
*
|
|
172
|
+
* This is the single execution path behind `query()`, `select()`, `insert()`,
|
|
173
|
+
* `update()` and `delete()`. Bindings are never written into the SQL text: the
|
|
174
|
+
* driver receives the statement and the values separately, so quotes,
|
|
175
|
+
* semicolons, comments and `?` characters inside a value stay data.
|
|
176
|
+
*/
|
|
177
|
+
private execute;
|
|
178
|
+
/**
|
|
179
|
+
* Execute through better-sqlite3: positional `?` parameters bound natively.
|
|
180
|
+
*/
|
|
181
|
+
private executeSqlite;
|
|
182
|
+
/**
|
|
183
|
+
* Execute through postgres.js: values are sent as real query parameters.
|
|
184
|
+
*/
|
|
185
|
+
private executePostgres;
|
|
186
|
+
/**
|
|
187
|
+
* Execute through mysql2: positional `?` parameters bound natively.
|
|
188
|
+
*/
|
|
189
|
+
private executeMysql;
|
|
190
|
+
/**
|
|
191
|
+
* Normalize bindings before handing them to the driver.
|
|
192
|
+
*
|
|
193
|
+
* `undefined` becomes `null`, dates become ISO strings, and booleans become
|
|
194
|
+
* 1/0 only for the drivers that cannot bind a boolean natively. Anything the
|
|
195
|
+
* driver cannot bind (objects, arrays, functions, symbols) fails loudly rather
|
|
196
|
+
* than being silently stringified into the SQL text.
|
|
197
|
+
*/
|
|
198
|
+
private normalizeBindings;
|
|
199
|
+
/**
|
|
200
|
+
* Normalize a single binding value.
|
|
201
|
+
*/
|
|
202
|
+
private normalizeBinding;
|
|
203
|
+
/**
|
|
204
|
+
* Whether the current driver can bind a JS boolean as a native parameter.
|
|
205
|
+
*
|
|
206
|
+
* better-sqlite3 only binds numbers, strings, bigints, buffers and null, so
|
|
207
|
+
* booleans are converted to 1/0 there. postgres.js and mysql2 both send
|
|
208
|
+
* booleans natively.
|
|
209
|
+
*/
|
|
210
|
+
private bindsBooleansNatively;
|
|
211
|
+
/**
|
|
212
|
+
* Binary values are bindable by every supported driver.
|
|
213
|
+
*/
|
|
214
|
+
private isBinary;
|
|
215
|
+
/**
|
|
216
|
+
* Error for values the driver cannot bind as a parameter.
|
|
217
|
+
*/
|
|
218
|
+
private unsupportedBinding;
|
|
219
|
+
/**
|
|
220
|
+
* Rewrite `?` placeholders into the `$n` form postgres.js expects.
|
|
221
|
+
*
|
|
222
|
+
* Only placeholder tokens are rewritten: quoted strings, quoted identifiers
|
|
223
|
+
* and comments are copied through verbatim, so a literal `?` inside the SQL
|
|
224
|
+
* text never shifts the binding order. Values are never touched here — they
|
|
225
|
+
* stay in the parameter array sent alongside the statement.
|
|
226
|
+
*/
|
|
227
|
+
private toPostgresPlaceholders;
|
|
228
|
+
/**
|
|
229
|
+
* End index (exclusive) of a quoted literal/identifier starting at `start`.
|
|
230
|
+
*
|
|
231
|
+
* Doubled quotes (`''`, `""`) are escapes and stay inside the quoted region.
|
|
110
232
|
*/
|
|
111
|
-
|
|
233
|
+
private endOfQuoted;
|
|
112
234
|
/**
|
|
113
235
|
* Ensure the adapter is connected
|
|
114
236
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DrizzleAdapter.d.mts","names":[],"sources":["../../../src/Database/Adapters/DrizzleAdapter.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"DrizzleAdapter.d.mts","names":[],"sources":["../../../src/Database/Adapters/DrizzleAdapter.ts"],"mappings":";;;cA8Ba,cAAA,YAA0B,eAAA;EAAA,UAaf,MAAA,EAAQ,cAAA;EAAA,UAZpB,MAAA;EAAA,UACA,SAAA;EAAA,UACA,SAAA;EAAA,UACA,aAAA;EAAA,UACA,iBAAA;EAkImE;;;;;EAAA,UA5HnE,gBAAA;cAEY,MAAA,EAAQ,cAAA;EA2JmB;;;EAtJ3C,OAAA,CAAA,GAAW,OAAA;EAuPwB;;;EAAA,UAvNzB,eAAA,CAAA,GAAmB,OAAA;EAuNuC;;;EAAA,UAnM1D,YAAA,CAAA,GAAgB,OAAA;EAkSwB;;;EAAA,UA9QxC,aAAA,CAAA,GAAiB,OAAA;EA+VsB;;;EAnVjD,UAAA,CAAA,GAAc,OAAA;EAsYe;;;EArW7B,KAAA,SAAA,CAAe,GAAA,UAAa,QAAA,WAAuB,OAAA,CAAQ,WAAA,CAAY,CAAA;EAvIxC;;;EAgJ/B,MAAA,SAAA,CAAgB,GAAA,UAAa,QAAA,WAAuB,OAAA,CAAQ,CAAA;EA9IxD;;;EAsJJ,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EA7IvC;;;EAqJJ,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EA9I3C;;;EAsJA,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAlGjC;;;;;;;;;EAgHV,gBAAA,CAAA,GAAoB,OAAA;EA/C+B;;;;;;;EAkEnD,MAAA,CAAA,GAAU,OAAA;EAzDkD;;;;;;;EAyF5D,QAAA,CAAA,GAAY,OAAA;EAzE+B;;;;;;;EAyG3C,WAAA,GAAA,CAAe,QAAA,GAAW,OAAA,EAAS,eAAA,KAAoB,OAAA,CAAQ,CAAA,IAAK,OAAA,CAAQ,CAAA;EAhElE;;;;EAAA,UAiFA,oBAAA,CAAA,GAAwB,OAAA;EAjBC;;;;;;;;EAAA,UA+CzB,wBAAA,CAAA,GAA4B,OAAA;EAA5B;;;;EAAA,UAgBA,wBAAA,CAAyB,MAAA,QAAc,OAAA;EAoB7C;;;;EAAA,UAAA,aAAA,CAAc,KAAA;EA8Bd;;;;;;;;EAAA,UAlBM,yBAAA,CAA0B,GAAA,WAAc,OAAA;EAyExC;;;EAAA,UAvDN,OAAA,CAAA;EA+DyB;;;EAxDnC,WAAA,CAAA;EAoFgB;;;EA7EhB,SAAA,CAAA;EAoGgB;;;EA7FV,YAAA,CAAa,SAAA,WAAoB,OAAA;EAoKzB;;;EAAA,UA/IE,oBAAA,CAAqB,SAAA,WAAoB,OAAA;EAwPjD;;;EAAA,UA3OQ,iBAAA,CAAkB,SAAA,WAAoB,OAAA;EAoU9C;;;EAAA,UA5TQ,kBAAA,CAAmB,SAAA,WAAoB,OAAA;;;;EAQjD,SAAA,CAAA,GAAa,OAAA;;;;YAoBH,iBAAA,CAAA,GAAqB,OAAA;;;;YAcrB,cAAA,CAAA,GAAkB,OAAA;;;;YASlB,eAAA,CAAA,GAAmB,OAAA;;;;;;;;;UAmBrB,OAAA;;;;UA8BN,aAAA;;;;UAsBM,eAAA;;;;UA2BA,YAAA;;;;;;;;;UAsCN,iBAAA;;;;UAOA,gBAAA;;;;;;;;UAiCA,qBAAA;;;;UAOA,QAAA;;;;UAWA,kBAAA;;;;;;;;;UAiBA,sBAAA;;;;;;UAsDA,WAAA;;;;YAoBE,eAAA,CAAA;AAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var e=class{config;client;rawClient;connected=!1;inTransaction=!1;transactionClient;constructor(e){this.config=e}async connect(){if(!this.connected)try{switch(this.config.driver){case`postgres`:await this.connectPostgres();break;case`mysql`:case`mysql2`:await this.connectMySQL();break;case`better-sqlite3`:case`sqlite`:await this.connectSQLite();break;default:throw Error(`Unsupported database driver: ${this.config.driver}`)}this.connected=!0}catch(e){throw Error(`Failed to connect to database: ${e?.message||e}`,{cause:e})}}async connectPostgres(){let{drizzle:e}=await import(`drizzle-orm/postgres-js`),t=(await import(`postgres`)).default({host:this.config.host,port:this.config.port,database:this.config.database,username:this.config.username,password:this.config.password,max:this.config.poolMax||10});this.rawClient=t,this.client=e(t)}async connectMySQL(){let{drizzle:e}=await import(`drizzle-orm/mysql2`),t=await(await import(`mysql2/promise`)).createPool({host:this.config.host,port:this.config.port,database:this.config.database,user:this.config.username,password:this.config.password,connectionLimit:this.config.poolMax||10});this.rawClient=t,this.client=e(t)}async connectSQLite(){let{drizzle:e}=await import(`drizzle-orm/better-sqlite3`),t=new(await(import(`better-sqlite3`))).default(this.config.database);this.rawClient=t,this.client=e(t)}async disconnect(){if(this.connected){if(this.rawClient)switch(this.config.driver){case`postgres`:await this.rawClient.end?.();break;case`mysql`:case`mysql2`:await this.rawClient.end?.();break;case`better-sqlite3`:case`sqlite`:this.rawClient.close?.();break}this.connected=!1,this.client=null,this.rawClient=null
|
|
1
|
+
var e=class{config;client;rawClient;connected=!1;inTransaction=!1;transactionClient;transactionDepth=0;constructor(e){this.config=e}async connect(){if(!this.connected)try{switch(this.config.driver){case`postgres`:await this.connectPostgres();break;case`mysql`:case`mysql2`:await this.connectMySQL();break;case`better-sqlite3`:case`sqlite`:await this.connectSQLite();break;default:throw Error(`Unsupported database driver: ${this.config.driver}`)}this.connected=!0}catch(e){throw Error(`Failed to connect to database: ${e?.message||e}`,{cause:e})}}async connectPostgres(){let{drizzle:e}=await import(`drizzle-orm/postgres-js`),t=(await import(`postgres`)).default({host:this.config.host,port:this.config.port,database:this.config.database,username:this.config.username,password:this.config.password,max:this.config.poolMax||10});this.rawClient=t,this.client=e(t)}async connectMySQL(){let{drizzle:e}=await import(`drizzle-orm/mysql2`),t=await(await import(`mysql2/promise`)).createPool({host:this.config.host,port:this.config.port,database:this.config.database,user:this.config.username,password:this.config.password,connectionLimit:this.config.poolMax||10});this.rawClient=t,this.client=e(t)}async connectSQLite(){let{drizzle:e}=await import(`drizzle-orm/better-sqlite3`),t=new(await(import(`better-sqlite3`))).default(this.config.database);this.rawClient=t,this.client=e(t)}async disconnect(){if(this.connected){if(this.rawClient)switch(this.config.driver){case`postgres`:await this.rawClient.end?.();break;case`mysql`:case`mysql2`:await this.rawClient.end?.();break;case`better-sqlite3`:case`sqlite`:this.rawClient.close?.();break}this.connected=!1,this.client=null,this.rawClient=null,this.transactionClient=null,this.inTransaction=!1,this.transactionDepth=0}}async query(e,t=[]){let n=await this.execute(e,t,`all`);return{rows:n.rows,rowCount:n.rowCount}}async select(e,t=[]){return(await this.execute(e,t,`all`)).rows}async insert(e,t=[]){return(await this.execute(e,t,`run`)).insertId}async update(e,t=[]){return(await this.execute(e,t,`run`)).rowCount}async delete(e,t=[]){return(await this.execute(e,t,`run`)).rowCount}async beginTransaction(){if(this.ensureConnected(),this.transactionDepth===0){await this.beginRootTransaction();return}await this.executeTransactionControl(`SAVEPOINT ${this.savepointName(this.transactionDepth)}`),this.transactionDepth+=1}async commit(){if(!this.inTransaction)throw Error(`No transaction in progress`);if(this.transactionDepth>1){await this.executeTransactionControl(`RELEASE SAVEPOINT ${this.savepointName(this.transactionDepth-1)}`),--this.transactionDepth;return}let e=this.transactionClient;this.isMysql()?await e.commit():await this.executeTransactionControl(`COMMIT`),this.transactionDepth=0,this.inTransaction=!1,this.transactionClient=null,await this.releaseTransactionClient(e)}async rollback(){if(!this.inTransaction)throw Error(`No transaction in progress`);if(this.transactionDepth>1){await this.executeTransactionControl(`ROLLBACK TO ${this.savepointName(this.transactionDepth-1)}`),--this.transactionDepth;return}let e=this.transactionClient;this.isMysql()?await e.rollback():await this.executeTransactionControl(`ROLLBACK`),this.transactionDepth=0,this.inTransaction=!1,this.transactionClient=null,await this.releaseTransactionClient(e)}async transaction(e){await this.beginTransaction();try{let t=await e(this);return await this.commit(),t}catch(e){throw await this.rollback(),e}}async beginRootTransaction(){let e=await this.acquireTransactionClient();this.transactionClient=e,this.inTransaction=!0,this.transactionDepth=1;try{this.isMysql()?await e.beginTransaction():await this.executeTransactionControl(`BEGIN`)}catch(t){throw this.transactionDepth=0,this.inTransaction=!1,this.transactionClient=null,await this.releaseTransactionClient(e),t}}async acquireTransactionClient(){switch(this.config.driver){case`postgres`:return this.rawClient.reserve();case`mysql`:case`mysql2`:return this.rawClient.getConnection();default:return this.rawClient}}async releaseTransactionClient(e){if(!(!e||e===this.rawClient))switch(this.config.driver){case`postgres`:await e.release?.();break;case`mysql`:case`mysql2`:e.release?.();break}}savepointName(e){return`trans_${e}`}async executeTransactionControl(e){if(!this.isMysql()){await this.execute(e,[],`all`);return}let t=this.transactionClient??this.rawClient;try{await t.query(e)}catch(t){throw Error(`Query failed: ${t?.message||t}\nSQL: ${e}`,{cause:t})}}isMysql(){return this.config.driver===`mysql`||this.config.driver===`mysql2`}isConnected(){return this.connected}getDriver(){return this.client}async getTableInfo(e){switch(this.ensureConnected(),this.config.driver){case`postgres`:return this.getPostgresTableInfo(e);case`mysql`:case`mysql2`:return this.getMySQLTableInfo(e);case`better-sqlite3`:case`sqlite`:return this.getSQLiteTableInfo(e);default:throw Error(`Table info not supported for this driver`)}}async getPostgresTableInfo(e){return this.select(`
|
|
2
2
|
SELECT column_name, data_type, is_nullable, column_default
|
|
3
3
|
FROM information_schema.columns
|
|
4
4
|
WHERE table_name = ?
|
|
@@ -13,5 +13,6 @@ var e=class{config;client;rawClient;connected=!1;inTransaction=!1;transactionCli
|
|
|
13
13
|
FROM sqlite_master
|
|
14
14
|
WHERE type = 'table'
|
|
15
15
|
AND name NOT LIKE 'sqlite_%'
|
|
16
|
-
`)).map(e=>e.name)}
|
|
16
|
+
`)).map(e=>e.name)}async execute(e,t,n){this.ensureConnected();let r=this.transactionClient??this.rawClient;try{let i=this.normalizeBindings(t);switch(this.config.driver){case`postgres`:return await this.executePostgres(r,e,i,n);case`mysql`:case`mysql2`:return await this.executeMysql(r,e,i,n);case`better-sqlite3`:case`sqlite`:return this.executeSqlite(r,e,i,n);default:throw Error(`Unsupported database driver: ${this.config.driver}`)}}catch(t){throw Error(`Query failed: ${t?.message||t}\nSQL: ${e}`,{cause:t})}}executeSqlite(e,t,n,r){let i=e.prepare(t);if(r===`run`||r===`all`&&i.reader===!1){let e=i.run(...n);return{rows:[],rowCount:Number(e?.changes??0),insertId:e?.lastInsertRowid}}if(r===`get`){let e=i.get(...n);return{rows:e===void 0?[]:[e],rowCount:e===void 0?0:1}}let a=i.all(...n);return{rows:a,rowCount:a.length}}async executePostgres(e,t,n,r){let i=n.length>0?this.toPostgresPlaceholders(t,n.length):t,a=await e.unsafe(i,n),o=Array.isArray(a)?a:a?.rows||[];return r===`run`?{rows:o,rowCount:Number.isFinite(a?.count)?Number(a.count):o.length,insertId:o[0]?.id}:r===`get`?{rows:o.slice(0,1),rowCount:Math.min(o.length,1)}:{rows:o,rowCount:o.length}}async executeMysql(e,t,n,r){let[i]=await e.execute(t,n);if(Array.isArray(i)){let e=i;return r===`run`?{rows:e,rowCount:e.length,insertId:e[0]?.id}:r===`get`?{rows:e.slice(0,1),rowCount:Math.min(e.length,1)}:{rows:e,rowCount:e.length}}return{rows:[],rowCount:Number(i?.affectedRows??0),insertId:i?.insertId}}normalizeBindings(e){return e.map(e=>this.normalizeBinding(e))}normalizeBinding(e){if(e==null)return null;if(e instanceof Date)return e.toISOString();switch(typeof e){case`string`:case`number`:case`bigint`:return e;case`boolean`:return this.bindsBooleansNatively()?e:Number(e);case`object`:if(this.isBinary(e))return e;throw this.unsupportedBinding(e);default:throw this.unsupportedBinding(e)}}bindsBooleansNatively(){return this.config.driver!==`better-sqlite3`&&this.config.driver!==`sqlite`}isBinary(e){return typeof Buffer<`u`&&Buffer.isBuffer(e)?!0:ArrayBuffer.isView(e)&&!(e instanceof DataView)}unsupportedBinding(e){return TypeError(`Cannot bind a value of type "${Array.isArray(e)?`array`:typeof e==`object`?`object`:typeof e}" as a query parameter for the "${this.config.driver}" driver. Serialize the value explicitly before passing it as a binding (for example: JSON.stringify()).`)}toPostgresPlaceholders(e,t){let n=``,r=0,i=0;for(;r<e.length;){let t=e[r];if(t===`'`||t===`"`||t==="`"){let i=this.endOfQuoted(e,r,t);n+=e.slice(r,i),r=i;continue}if(t===`-`&&e[r+1]===`-`){let t=e.indexOf(`
|
|
17
|
+
`,r),i=t===-1?e.length:t;n+=e.slice(r,i),r=i;continue}if(t===`/`&&e[r+1]===`*`){let t=e.indexOf(`*/`,r+2),i=t===-1?e.length:t+2;n+=e.slice(r,i),r=i;continue}if(t===`?`){i+=1,n+=`$${i}`,r+=1;continue}n+=t,r+=1}if(i!==t)throw Error(`Cannot bind ${t} parameter(s) against ${i} placeholder(s) in SQL: ${e}`);return n}endOfQuoted(e,t,n){let r=t+1;for(;r<e.length;){if(e[r]===n){if(e[r+1]===n){r+=2;continue}return r+1}r+=1}return e.length}ensureConnected(){if(!this.connected)throw Error(`Database not connected. Call connect() first.`)}};export{e as DrizzleAdapter};
|
|
17
18
|
//# sourceMappingURL=DrizzleAdapter.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DrizzleAdapter.mjs","names":[],"sources":["../../../src/Database/Adapters/DrizzleAdapter.ts"],"sourcesContent":["/**\n * DrizzleAdapter\n *\n * Database adapter implementation using Drizzle ORM\n */\n\nimport { DatabaseAdapter, DatabaseConfig, QueryResult } from '@/Database/Contracts/DatabaseAdapter';\n\nexport class DrizzleAdapter implements DatabaseAdapter {\n protected client: any;\n protected rawClient: any;\n protected connected: boolean = false;\n protected inTransaction: boolean = false;\n protected transactionClient: any;\n\n constructor(protected config: DatabaseConfig) {}\n\n /**\n * Connect to the database\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n try {\n // Dynamically import the appropriate Drizzle driver\n switch (this.config.driver) {\n case 'postgres':\n await this.connectPostgres();\n break;\n case 'mysql':\n case 'mysql2':\n await this.connectMySQL();\n break;\n case 'better-sqlite3':\n case 'sqlite':\n await this.connectSQLite();\n break;\n default:\n throw new Error(`Unsupported database driver: ${this.config.driver}`);\n }\n\n this.connected = true;\n } catch (error: any) {\n throw new Error(`Failed to connect to database: ${error?.message || error}`, { cause: error });\n }\n }\n\n /**\n * Connect to PostgreSQL\n */\n protected async connectPostgres(): Promise<void> {\n const { drizzle } = await import('drizzle-orm/postgres-js');\n const postgres = await import('postgres');\n\n const rawClient = postgres.default({\n host: this.config.host,\n port: this.config.port,\n database: this.config.database,\n username: this.config.username,\n password: this.config.password,\n max: this.config.poolMax || 10,\n });\n\n this.rawClient = rawClient;\n this.client = drizzle(rawClient);\n }\n\n /**\n * Connect to MySQL\n */\n protected async connectMySQL(): Promise<void> {\n const { drizzle } = await import('drizzle-orm/mysql2');\n const mysql = await import('mysql2/promise');\n\n const rawClient = await mysql.createPool({\n host: this.config.host,\n port: this.config.port,\n database: this.config.database,\n user: this.config.username,\n password: this.config.password,\n connectionLimit: this.config.poolMax || 10,\n });\n\n this.rawClient = rawClient;\n this.client = drizzle(rawClient);\n }\n\n /**\n * Connect to SQLite\n */\n protected async connectSQLite(): Promise<void> {\n const { drizzle } = await import('drizzle-orm/better-sqlite3');\n const Database = await import('better-sqlite3');\n\n const rawClient = new Database.default(this.config.database);\n this.rawClient = rawClient;\n this.client = drizzle(rawClient);\n }\n\n /**\n * Disconnect from the database\n */\n async disconnect(): Promise<void> {\n if (!this.connected) {\n return;\n }\n\n // Close the raw client connection if possible\n if (this.rawClient) {\n switch (this.config.driver) {\n case 'postgres':\n await this.rawClient.end?.();\n break;\n case 'mysql':\n case 'mysql2':\n await this.rawClient.end?.();\n break;\n case 'better-sqlite3':\n case 'sqlite':\n this.rawClient.close?.();\n break;\n }\n }\n\n this.connected = false;\n this.client = null;\n this.rawClient = null;\n }\n\n /**\n * Execute a raw SQL query\n */\n async query<T = any>(sql: string, bindings: any[] = []): Promise<QueryResult<T>> {\n this.ensureConnected();\n\n try {\n const client = this.inTransaction ? this.transactionClient : this.rawClient;\n const boundSql = this.bindParameters(sql, bindings);\n\n let result: any;\n\n // Execute based on driver type\n switch (this.config.driver) {\n case 'postgres':\n result = await client.unsafe(boundSql);\n break;\n case 'mysql':\n case 'mysql2': {\n const [rows] = await client.execute(boundSql);\n result = rows;\n break;\n }\n case 'better-sqlite3':\n case 'sqlite':\n result = client.prepare(boundSql).all();\n break;\n default:\n throw new Error(`Unsupported database driver: ${this.config.driver}`);\n }\n\n return {\n rows: Array.isArray(result) ? result : result.rows || [],\n rowCount: Array.isArray(result) ? result.length : result.rowCount || 0,\n };\n } catch (error: any) {\n throw new Error(`Query failed: ${error?.message || error}\\nSQL: ${sql}`, { cause: error });\n }\n }\n\n /**\n * Execute a SELECT query\n */\n async select<T = any>(sql: string, bindings: any[] = []): Promise<T[]> {\n const result = await this.query<T>(sql, bindings);\n return result.rows;\n }\n\n /**\n * Execute an INSERT query\n */\n async insert(sql: string, bindings: any[] = []): Promise<any> {\n this.ensureConnected();\n\n try {\n const client = this.inTransaction ? this.transactionClient : this.rawClient;\n const boundSql = this.bindParameters(sql, bindings);\n\n let result: any;\n\n // Execute based on driver type\n switch (this.config.driver) {\n case 'postgres':\n result = await client.unsafe(boundSql);\n break;\n case 'mysql':\n case 'mysql2':\n [result] = await client.execute(boundSql);\n break;\n case 'better-sqlite3':\n case 'sqlite':\n result = client.prepare(boundSql).run();\n break;\n default:\n throw new Error(`Unsupported database driver: ${this.config.driver}`);\n }\n\n // Return the inserted ID\n return result.insertId || result.lastInsertRowid || result.rows?.[0]?.id;\n } catch (error: any) {\n throw new Error(`Insert failed: ${error?.message || error}\\nSQL: ${sql}`, { cause: error });\n }\n }\n\n /**\n * Execute an UPDATE query\n */\n async update(sql: string, bindings: any[] = []): Promise<number> {\n const result = await this.query(sql, bindings);\n return result.rowCount;\n }\n\n /**\n * Execute a DELETE query\n */\n async delete(sql: string, bindings: any[] = []): Promise<number> {\n const result = await this.query(sql, bindings);\n return result.rowCount;\n }\n\n /**\n * Begin a transaction\n */\n async beginTransaction(): Promise<void> {\n this.ensureConnected();\n\n if (this.inTransaction) {\n throw new Error('Transaction already in progress');\n }\n\n this.inTransaction = true;\n\n // For now, we'll use simple BEGIN/COMMIT/ROLLBACK\n // In a more sophisticated implementation, we'd use Drizzle's transaction API\n await this.query('BEGIN');\n }\n\n /**\n * Commit a transaction\n */\n async commit(): Promise<void> {\n if (!this.inTransaction) {\n throw new Error('No transaction in progress');\n }\n\n await this.query('COMMIT');\n this.inTransaction = false;\n this.transactionClient = null;\n }\n\n /**\n * Rollback a transaction\n */\n async rollback(): Promise<void> {\n if (!this.inTransaction) {\n throw new Error('No transaction in progress');\n }\n\n await this.query('ROLLBACK');\n this.inTransaction = false;\n this.transactionClient = null;\n }\n\n /**\n * Execute a callback within a transaction\n */\n async transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T> {\n await this.beginTransaction();\n\n try {\n const result = await callback(this);\n await this.commit();\n return result;\n } catch (error) {\n await this.rollback();\n throw error;\n }\n }\n\n /**\n * Check if adapter is connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Get the underlying driver instance\n */\n getDriver(): any {\n return this.client;\n }\n\n /**\n * Get table information\n */\n async getTableInfo(tableName: string): Promise<any> {\n this.ensureConnected();\n\n // Implementation varies by driver\n switch (this.config.driver) {\n case 'postgres':\n return this.getPostgresTableInfo(tableName);\n case 'mysql':\n case 'mysql2':\n return this.getMySQLTableInfo(tableName);\n case 'better-sqlite3':\n case 'sqlite':\n return this.getSQLiteTableInfo(tableName);\n default:\n throw new Error('Table info not supported for this driver');\n }\n }\n\n /**\n * Get PostgreSQL table info\n */\n protected async getPostgresTableInfo(tableName: string): Promise<any> {\n const sql = `\n SELECT column_name, data_type, is_nullable, column_default\n FROM information_schema.columns\n WHERE table_name = ?\n ORDER BY ordinal_position\n `;\n return this.select(sql, [tableName]);\n }\n\n /**\n * Get MySQL table info\n */\n protected async getMySQLTableInfo(tableName: string): Promise<any> {\n const sql = `DESCRIBE ${tableName}`;\n return this.select(sql);\n }\n\n /**\n * Get SQLite table info\n */\n protected async getSQLiteTableInfo(tableName: string): Promise<any> {\n const sql = `PRAGMA table_info(${tableName})`;\n return this.select(sql);\n }\n\n /**\n * Get all table names\n */\n async getTables(): Promise<string[]> {\n this.ensureConnected();\n\n switch (this.config.driver) {\n case 'postgres':\n return this.getPostgresTables();\n case 'mysql':\n case 'mysql2':\n return this.getMySQLTables();\n case 'better-sqlite3':\n case 'sqlite':\n return this.getSQLiteTables();\n default:\n throw new Error('Get tables not supported for this driver');\n }\n }\n\n /**\n * Get PostgreSQL tables\n */\n protected async getPostgresTables(): Promise<string[]> {\n const sql = `\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = 'public'\n AND table_type = 'BASE TABLE'\n `;\n const result = await this.select<any>(sql);\n return result.map((row) => row.table_name);\n }\n\n /**\n * Get MySQL tables\n */\n protected async getMySQLTables(): Promise<string[]> {\n const sql = 'SHOW TABLES';\n const result = await this.select<any>(sql);\n return result.map((row) => Object.values(row)[0] as string);\n }\n\n /**\n * Get SQLite tables\n */\n protected async getSQLiteTables(): Promise<string[]> {\n const sql = `\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name NOT LIKE 'sqlite_%'\n `;\n const result = await this.select<any>(sql);\n return result.map((row) => row.name);\n }\n\n /**\n * Bind parameters to SQL query\n */\n protected bindParameters(sql: string, bindings: any[] = []): string {\n if (bindings.length === 0) {\n return sql;\n }\n\n // Replace ? placeholders with actual values\n // Note: This is a simple implementation. In production, use parameterized queries\n let index = 0;\n return sql.replace(/\\?/g, () => {\n const value = bindings[index++];\n\n if (value === null || value === undefined) {\n return 'NULL';\n }\n\n if (typeof value === 'string') {\n return `'${value.replace(/'/g, \"''\")}'`;\n }\n\n if (typeof value === 'boolean') {\n return value ? '1' : '0';\n }\n\n if (value instanceof Date) {\n return `'${value.toISOString()}'`;\n }\n\n return String(value);\n });\n }\n\n /**\n * Ensure the adapter is connected\n */\n protected ensureConnected(): void {\n if (!this.connected) {\n throw new Error('Database not connected. Call connect() first.');\n }\n }\n}\n"],"mappings":"AAQA,IAAa,EAAb,KAAuD,CAO/B,OANtB,OACA,UACA,UAA+B,GAC/B,cAAmC,GACnC,kBAEA,YAAY,EAAkC,CAAxB,KAAA,OAAA,EAKtB,MAAM,SAAyB,CACzB,SAAK,UAIT,GAAI,CAEF,OAAQ,KAAK,OAAO,OAApB,CACE,IAAK,WACH,MAAM,KAAK,iBAAiB,CAC5B,MACF,IAAK,QACL,IAAK,SACH,MAAM,KAAK,cAAc,CACzB,MACF,IAAK,iBACL,IAAK,SACH,MAAM,KAAK,eAAe,CAC1B,MACF,QACE,MAAU,MAAM,gCAAgC,KAAK,OAAO,SAAS,CAGzE,KAAK,UAAY,SACV,EAAY,CACnB,MAAU,MAAM,kCAAkC,GAAO,SAAW,IAAS,CAAE,MAAO,EAAO,CAAC,EAOlG,MAAgB,iBAAiC,CAC/C,GAAM,CAAE,WAAY,MAAM,OAAO,2BAG3B,GAAY,MAFK,OAAO,aAEH,QAAQ,CACjC,KAAM,KAAK,OAAO,KAClB,KAAM,KAAK,OAAO,KAClB,SAAU,KAAK,OAAO,SACtB,SAAU,KAAK,OAAO,SACtB,SAAU,KAAK,OAAO,SACtB,IAAK,KAAK,OAAO,SAAW,GAC7B,CAAC,CAEF,KAAK,UAAY,EACjB,KAAK,OAAS,EAAQ,EAAU,CAMlC,MAAgB,cAA8B,CAC5C,GAAM,CAAE,WAAY,MAAM,OAAO,sBAG3B,EAAY,MAAM,MAFJ,OAAO,mBAEG,WAAW,CACvC,KAAM,KAAK,OAAO,KAClB,KAAM,KAAK,OAAO,KAClB,SAAU,KAAK,OAAO,SACtB,KAAM,KAAK,OAAO,SAClB,SAAU,KAAK,OAAO,SACtB,gBAAiB,KAAK,OAAO,SAAW,GACzC,CAAC,CAEF,KAAK,UAAY,EACjB,KAAK,OAAS,EAAQ,EAAU,CAMlC,MAAgB,eAA+B,CAC7C,GAAM,CAAE,WAAY,MAAM,OAAO,8BAG3B,EAAY,IAAI,MAFC,OAAO,oBAEC,QAAQ,KAAK,OAAO,SAAS,CAC5D,KAAK,UAAY,EACjB,KAAK,OAAS,EAAQ,EAAU,CAMlC,MAAM,YAA4B,CAC3B,QAAK,UAKV,IAAI,KAAK,UACP,OAAQ,KAAK,OAAO,OAApB,CACE,IAAK,WACH,MAAM,KAAK,UAAU,OAAO,CAC5B,MACF,IAAK,QACL,IAAK,SACH,MAAM,KAAK,UAAU,OAAO,CAC5B,MACF,IAAK,iBACL,IAAK,SACH,KAAK,UAAU,SAAS,CACxB,MAIN,KAAK,UAAY,GACjB,KAAK,OAAS,KACd,KAAK,UAAY,MAMnB,MAAM,MAAe,EAAa,EAAkB,EAAE,CAA2B,CAC/E,KAAK,iBAAiB,CAEtB,GAAI,CACF,IAAM,EAAS,KAAK,cAAgB,KAAK,kBAAoB,KAAK,UAC5D,EAAW,KAAK,eAAe,EAAK,EAAS,CAE/C,EAGJ,OAAQ,KAAK,OAAO,OAApB,CACE,IAAK,WACH,EAAS,MAAM,EAAO,OAAO,EAAS,CACtC,MACF,IAAK,QACL,IAAK,SAAU,CACb,GAAM,CAAC,GAAQ,MAAM,EAAO,QAAQ,EAAS,CAC7C,EAAS,EACT,MAEF,IAAK,iBACL,IAAK,SACH,EAAS,EAAO,QAAQ,EAAS,CAAC,KAAK,CACvC,MACF,QACE,MAAU,MAAM,gCAAgC,KAAK,OAAO,SAAS,CAGzE,MAAO,CACL,KAAM,MAAM,QAAQ,EAAO,CAAG,EAAS,EAAO,MAAQ,EAAE,CACxD,SAAU,MAAM,QAAQ,EAAO,CAAG,EAAO,OAAS,EAAO,UAAY,EACtE,OACM,EAAY,CACnB,MAAU,MAAM,iBAAiB,GAAO,SAAW,EAAM,SAAS,IAAO,CAAE,MAAO,EAAO,CAAC,EAO9F,MAAM,OAAgB,EAAa,EAAkB,EAAE,CAAgB,CAErE,OAAO,MADc,KAAK,MAAS,EAAK,EAAS,EACnC,KAMhB,MAAM,OAAO,EAAa,EAAkB,EAAE,CAAgB,CAC5D,KAAK,iBAAiB,CAEtB,GAAI,CACF,IAAM,EAAS,KAAK,cAAgB,KAAK,kBAAoB,KAAK,UAC5D,EAAW,KAAK,eAAe,EAAK,EAAS,CAE/C,EAGJ,OAAQ,KAAK,OAAO,OAApB,CACE,IAAK,WACH,EAAS,MAAM,EAAO,OAAO,EAAS,CACtC,MACF,IAAK,QACL,IAAK,SACH,CAAC,GAAU,MAAM,EAAO,QAAQ,EAAS,CACzC,MACF,IAAK,iBACL,IAAK,SACH,EAAS,EAAO,QAAQ,EAAS,CAAC,KAAK,CACvC,MACF,QACE,MAAU,MAAM,gCAAgC,KAAK,OAAO,SAAS,CAIzE,OAAO,EAAO,UAAY,EAAO,iBAAmB,EAAO,OAAO,IAAI,SAC/D,EAAY,CACnB,MAAU,MAAM,kBAAkB,GAAO,SAAW,EAAM,SAAS,IAAO,CAAE,MAAO,EAAO,CAAC,EAO/F,MAAM,OAAO,EAAa,EAAkB,EAAE,CAAmB,CAE/D,OAAO,MADc,KAAK,MAAM,EAAK,EAAS,EAChC,SAMhB,MAAM,OAAO,EAAa,EAAkB,EAAE,CAAmB,CAE/D,OAAO,MADc,KAAK,MAAM,EAAK,EAAS,EAChC,SAMhB,MAAM,kBAAkC,CAGtC,GAFA,KAAK,iBAAiB,CAElB,KAAK,cACP,MAAU,MAAM,kCAAkC,CAGpD,KAAK,cAAgB,GAIrB,MAAM,KAAK,MAAM,QAAQ,CAM3B,MAAM,QAAwB,CAC5B,GAAI,CAAC,KAAK,cACR,MAAU,MAAM,6BAA6B,CAG/C,MAAM,KAAK,MAAM,SAAS,CAC1B,KAAK,cAAgB,GACrB,KAAK,kBAAoB,KAM3B,MAAM,UAA0B,CAC9B,GAAI,CAAC,KAAK,cACR,MAAU,MAAM,6BAA6B,CAG/C,MAAM,KAAK,MAAM,WAAW,CAC5B,KAAK,cAAgB,GACrB,KAAK,kBAAoB,KAM3B,MAAM,YAAe,EAAgE,CACnF,MAAM,KAAK,kBAAkB,CAE7B,GAAI,CACF,IAAM,EAAS,MAAM,EAAS,KAAK,CAEnC,OADA,MAAM,KAAK,QAAQ,CACZ,QACA,EAAO,CAEd,MADA,MAAM,KAAK,UAAU,CACf,GAOV,aAAuB,CACrB,OAAO,KAAK,UAMd,WAAiB,CACf,OAAO,KAAK,OAMd,MAAM,aAAa,EAAiC,CAIlD,OAHA,KAAK,iBAAiB,CAGd,KAAK,OAAO,OAApB,CACE,IAAK,WACH,OAAO,KAAK,qBAAqB,EAAU,CAC7C,IAAK,QACL,IAAK,SACH,OAAO,KAAK,kBAAkB,EAAU,CAC1C,IAAK,iBACL,IAAK,SACH,OAAO,KAAK,mBAAmB,EAAU,CAC3C,QACE,MAAU,MAAM,2CAA2C,EAOjE,MAAgB,qBAAqB,EAAiC,CAOpE,OAAO,KAAK,OAAO;;;;;MAAK,CAAC,EAAU,CAAC,CAMtC,MAAgB,kBAAkB,EAAiC,CACjE,IAAM,EAAM,YAAY,IACxB,OAAO,KAAK,OAAO,EAAI,CAMzB,MAAgB,mBAAmB,EAAiC,CAClE,IAAM,EAAM,qBAAqB,EAAU,GAC3C,OAAO,KAAK,OAAO,EAAI,CAMzB,MAAM,WAA+B,CAGnC,OAFA,KAAK,iBAAiB,CAEd,KAAK,OAAO,OAApB,CACE,IAAK,WACH,OAAO,KAAK,mBAAmB,CACjC,IAAK,QACL,IAAK,SACH,OAAO,KAAK,gBAAgB,CAC9B,IAAK,iBACL,IAAK,SACH,OAAO,KAAK,iBAAiB,CAC/B,QACE,MAAU,MAAM,2CAA2C,EAOjE,MAAgB,mBAAuC,CAQrD,OAAO,MADc,KAAK,OAAY;;;;;MAAI,EAC5B,IAAK,GAAQ,EAAI,WAAW,CAM5C,MAAgB,gBAAoC,CAGlD,OAAO,MADc,KAAK,OAAY,cAAI,EAC5B,IAAK,GAAQ,OAAO,OAAO,EAAI,CAAC,GAAa,CAM7D,MAAgB,iBAAqC,CAQnD,OAAO,MADc,KAAK,OAAY;;;;;MAAI,EAC5B,IAAK,GAAQ,EAAI,KAAK,CAMtC,eAAyB,EAAa,EAAkB,EAAE,CAAU,CAClE,GAAI,EAAS,SAAW,EACtB,OAAO,EAKT,IAAI,EAAQ,EACZ,OAAO,EAAI,QAAQ,UAAa,CAC9B,IAAM,EAAQ,EAAS,KAkBvB,OAhBI,GAAU,KACL,OAGL,OAAO,GAAU,SACZ,IAAI,EAAM,QAAQ,KAAM,KAAK,CAAC,GAGnC,OAAO,GAAU,UACZ,EAAQ,IAAM,IAGnB,aAAiB,KACZ,IAAI,EAAM,aAAa,CAAC,GAG1B,OAAO,EAAM,EACpB,CAMJ,iBAAkC,CAChC,GAAI,CAAC,KAAK,UACR,MAAU,MAAM,gDAAgD"}
|
|
1
|
+
{"version":3,"file":"DrizzleAdapter.mjs","names":[],"sources":["../../../src/Database/Adapters/DrizzleAdapter.ts"],"sourcesContent":["/**\n * DrizzleAdapter\n *\n * Database adapter implementation using Drizzle ORM\n */\n\nimport { DatabaseAdapter, DatabaseConfig, QueryResult } from '@/Database/Contracts/DatabaseAdapter';\n\n/**\n * How a statement should be executed and what should be reported back.\n *\n * - `all`: read every row produced by the statement\n * - `get`: read only the first row produced by the statement\n * - `run`: execute the statement and report affected rows / the inserted id\n */\ntype ExecutionMode = 'all' | 'run' | 'get';\n\n/**\n * Normalized result of a single execution.\n *\n * `rows`/`rowCount` are the `QueryResult` callers see; `insertId` is extra\n * information the adapter needs for `insert()` and is never exposed as a\n * `QueryResult` field.\n */\ninterface ExecutedResult<T = any> {\n rows: T[];\n rowCount: number;\n insertId?: any;\n}\n\nexport class DrizzleAdapter implements DatabaseAdapter {\n protected client: any;\n protected rawClient: any;\n protected connected: boolean = false;\n protected inTransaction: boolean = false;\n protected transactionClient: any;\n /**\n * Nesting level of the transaction stack: 0 means no transaction, 1 is the\n * root transaction, and anything deeper is backed by a savepoint. Shared by\n * every driver so nesting behaves identically regardless of the pool.\n */\n protected transactionDepth: number = 0;\n\n constructor(protected config: DatabaseConfig) {}\n\n /**\n * Connect to the database\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n\n try {\n // Dynamically import the appropriate Drizzle driver\n switch (this.config.driver) {\n case 'postgres':\n await this.connectPostgres();\n break;\n case 'mysql':\n case 'mysql2':\n await this.connectMySQL();\n break;\n case 'better-sqlite3':\n case 'sqlite':\n await this.connectSQLite();\n break;\n default:\n throw new Error(`Unsupported database driver: ${this.config.driver}`);\n }\n\n this.connected = true;\n } catch (error: any) {\n throw new Error(`Failed to connect to database: ${error?.message || error}`, { cause: error });\n }\n }\n\n /**\n * Connect to PostgreSQL\n */\n protected async connectPostgres(): Promise<void> {\n const { drizzle } = await import('drizzle-orm/postgres-js');\n const postgres = await import('postgres');\n\n const rawClient = postgres.default({\n host: this.config.host,\n port: this.config.port,\n database: this.config.database,\n username: this.config.username,\n password: this.config.password,\n max: this.config.poolMax || 10,\n });\n\n this.rawClient = rawClient;\n this.client = drizzle(rawClient);\n }\n\n /**\n * Connect to MySQL\n */\n protected async connectMySQL(): Promise<void> {\n const { drizzle } = await import('drizzle-orm/mysql2');\n const mysql = await import('mysql2/promise');\n\n const rawClient = await mysql.createPool({\n host: this.config.host,\n port: this.config.port,\n database: this.config.database,\n user: this.config.username,\n password: this.config.password,\n connectionLimit: this.config.poolMax || 10,\n });\n\n this.rawClient = rawClient;\n this.client = drizzle(rawClient);\n }\n\n /**\n * Connect to SQLite\n */\n protected async connectSQLite(): Promise<void> {\n const { drizzle } = await import('drizzle-orm/better-sqlite3');\n const Database = await import('better-sqlite3');\n\n const rawClient = new Database.default(this.config.database);\n this.rawClient = rawClient;\n this.client = drizzle(rawClient);\n }\n\n /**\n * Disconnect from the database\n */\n async disconnect(): Promise<void> {\n if (!this.connected) {\n return;\n }\n\n // Close the raw client connection if possible\n if (this.rawClient) {\n switch (this.config.driver) {\n case 'postgres':\n await this.rawClient.end?.();\n break;\n case 'mysql':\n case 'mysql2':\n await this.rawClient.end?.();\n break;\n case 'better-sqlite3':\n case 'sqlite':\n this.rawClient.close?.();\n break;\n }\n }\n\n this.connected = false;\n this.client = null;\n this.rawClient = null;\n this.transactionClient = null;\n this.inTransaction = false;\n this.transactionDepth = 0;\n }\n\n /**\n * Execute a raw SQL query\n */\n async query<T = any>(sql: string, bindings: any[] = []): Promise<QueryResult<T>> {\n const result = await this.execute<T>(sql, bindings, 'all');\n\n return { rows: result.rows, rowCount: result.rowCount };\n }\n\n /**\n * Execute a SELECT query\n */\n async select<T = any>(sql: string, bindings: any[] = []): Promise<T[]> {\n const result = await this.execute<T>(sql, bindings, 'all');\n return result.rows;\n }\n\n /**\n * Execute an INSERT query\n */\n async insert(sql: string, bindings: any[] = []): Promise<any> {\n const result = await this.execute(sql, bindings, 'run');\n return result.insertId;\n }\n\n /**\n * Execute an UPDATE query\n */\n async update(sql: string, bindings: any[] = []): Promise<number> {\n const result = await this.execute(sql, bindings, 'run');\n return result.rowCount;\n }\n\n /**\n * Execute a DELETE query\n */\n async delete(sql: string, bindings: any[] = []): Promise<number> {\n const result = await this.execute(sql, bindings, 'run');\n return result.rowCount;\n }\n\n /**\n * Begin a transaction.\n *\n * The outermost call pins a dedicated connection (for pooled Postgres/MySQL\n * drivers) and issues `BEGIN` on it, then every later statement runs on that\n * pinned client until the transaction ends. Nested calls open a savepoint\n * (`SAVEPOINT trans_N`) instead of a second `BEGIN`, so an inner rollback\n * only undoes the work done since that savepoint.\n */\n async beginTransaction(): Promise<void> {\n this.ensureConnected();\n\n if (this.transactionDepth === 0) {\n await this.beginRootTransaction();\n return;\n }\n\n await this.executeTransactionControl(`SAVEPOINT ${this.savepointName(this.transactionDepth)}`);\n this.transactionDepth += 1;\n }\n\n /**\n * Commit a transaction.\n *\n * At nesting levels deeper than one this releases the innermost savepoint\n * (`RELEASE SAVEPOINT trans_N`) and keeps the outer transaction open; only\n * the root commit persists the work and gives the pinned connection back.\n */\n async commit(): Promise<void> {\n if (!this.inTransaction) {\n throw new Error('No transaction in progress');\n }\n\n if (this.transactionDepth > 1) {\n await this.executeTransactionControl(`RELEASE SAVEPOINT ${this.savepointName(this.transactionDepth - 1)}`);\n this.transactionDepth -= 1;\n return;\n }\n\n const client = this.transactionClient;\n\n if (this.isMysql()) {\n await client.commit();\n } else {\n await this.executeTransactionControl('COMMIT');\n }\n\n this.transactionDepth = 0;\n this.inTransaction = false;\n this.transactionClient = null;\n await this.releaseTransactionClient(client);\n }\n\n /**\n * Rollback a transaction.\n *\n * Inside a nested transaction this rolls back to the innermost savepoint\n * (`ROLLBACK TO trans_N`) without touching the outer transaction; a root\n * rollback discards everything and releases the pinned connection.\n */\n async rollback(): Promise<void> {\n if (!this.inTransaction) {\n throw new Error('No transaction in progress');\n }\n\n if (this.transactionDepth > 1) {\n await this.executeTransactionControl(`ROLLBACK TO ${this.savepointName(this.transactionDepth - 1)}`);\n this.transactionDepth -= 1;\n return;\n }\n\n const client = this.transactionClient;\n\n if (this.isMysql()) {\n await client.rollback();\n } else {\n await this.executeTransactionControl('ROLLBACK');\n }\n\n this.transactionDepth = 0;\n this.inTransaction = false;\n this.transactionClient = null;\n await this.releaseTransactionClient(client);\n }\n\n /**\n * Execute a callback within a transaction.\n *\n * Re-entrant: calling this inside another transaction opens a savepoint, so\n * a failure in the inner callback rolls back only the inner work while the\n * outer transaction stays usable.\n */\n async transaction<T>(callback: (adapter: DatabaseAdapter) => Promise<T>): Promise<T> {\n await this.beginTransaction();\n\n try {\n const result = await callback(this);\n await this.commit();\n return result;\n } catch (error) {\n await this.rollback();\n throw error;\n }\n }\n\n /**\n * Start the root transaction: pin a connection, store it as the transaction\n * client, then issue `BEGIN` on exactly that client.\n */\n protected async beginRootTransaction(): Promise<void> {\n const client = await this.acquireTransactionClient();\n\n this.transactionClient = client;\n this.inTransaction = true;\n this.transactionDepth = 1;\n\n try {\n if (this.isMysql()) {\n await client.beginTransaction();\n } else {\n await this.executeTransactionControl('BEGIN');\n }\n } catch (error) {\n this.transactionDepth = 0;\n this.inTransaction = false;\n this.transactionClient = null;\n await this.releaseTransactionClient(client);\n throw error;\n }\n }\n\n /**\n * Reserve the connection that will carry the transaction.\n *\n * - better-sqlite3 owns a single connection: the raw client doubles as the\n * transaction client and there is nothing to reserve.\n * - postgres.js: `reserve()` hands back a dedicated connection from the pool.\n * - mysql2: `getConnection()` checks a pooled connection out.\n */\n protected async acquireTransactionClient(): Promise<any> {\n switch (this.config.driver) {\n case 'postgres':\n return this.rawClient.reserve();\n case 'mysql':\n case 'mysql2':\n return this.rawClient.getConnection();\n default:\n return this.rawClient;\n }\n }\n\n /**\n * Give a pinned transaction connection back to its pool. The SQLite raw\n * client is shared with normal execution, so it is never released here.\n */\n protected async releaseTransactionClient(client: any): Promise<void> {\n if (!client || client === this.rawClient) {\n return;\n }\n\n switch (this.config.driver) {\n case 'postgres':\n await client.release?.();\n break;\n case 'mysql':\n case 'mysql2':\n client.release?.();\n break;\n }\n }\n\n /**\n * Name of the savepoint at the given transaction level. The first nested\n * transaction is `trans_1`, the second `trans_2`, and so on.\n */\n protected savepointName(level: number): string {\n return `trans_${level}`;\n }\n\n /**\n * Run a transaction-control statement (`BEGIN`, `COMMIT`, `ROLLBACK`,\n * `SAVEPOINT ...`) on the client that carries the transaction.\n *\n * Postgres and SQLite take the normal parameterized path with no bindings.\n * MySQL does not accept every transaction-control command through its\n * prepared-statement protocol, so savepoints go through the text protocol.\n */\n protected async executeTransactionControl(sql: string): Promise<void> {\n if (!this.isMysql()) {\n await this.execute(sql, [], 'all');\n return;\n }\n\n const client = this.transactionClient ?? this.rawClient;\n\n try {\n await client.query(sql);\n } catch (error: any) {\n throw new Error(`Query failed: ${error?.message || error}\\nSQL: ${sql}`, { cause: error });\n }\n }\n\n /**\n * Whether the configured driver is one of the MySQL variants.\n */\n protected isMysql(): boolean {\n return this.config.driver === 'mysql' || this.config.driver === 'mysql2';\n }\n\n /**\n * Check if adapter is connected\n */\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Get the underlying driver instance\n */\n getDriver(): any {\n return this.client;\n }\n\n /**\n * Get table information\n */\n async getTableInfo(tableName: string): Promise<any> {\n this.ensureConnected();\n\n // Implementation varies by driver\n switch (this.config.driver) {\n case 'postgres':\n return this.getPostgresTableInfo(tableName);\n case 'mysql':\n case 'mysql2':\n return this.getMySQLTableInfo(tableName);\n case 'better-sqlite3':\n case 'sqlite':\n return this.getSQLiteTableInfo(tableName);\n default:\n throw new Error('Table info not supported for this driver');\n }\n }\n\n /**\n * Get PostgreSQL table info\n */\n protected async getPostgresTableInfo(tableName: string): Promise<any> {\n const sql = `\n SELECT column_name, data_type, is_nullable, column_default\n FROM information_schema.columns\n WHERE table_name = ?\n ORDER BY ordinal_position\n `;\n return this.select(sql, [tableName]);\n }\n\n /**\n * Get MySQL table info\n */\n protected async getMySQLTableInfo(tableName: string): Promise<any> {\n const sql = `DESCRIBE ${tableName}`;\n return this.select(sql);\n }\n\n /**\n * Get SQLite table info\n */\n protected async getSQLiteTableInfo(tableName: string): Promise<any> {\n const sql = `PRAGMA table_info(${tableName})`;\n return this.select(sql);\n }\n\n /**\n * Get all table names\n */\n async getTables(): Promise<string[]> {\n this.ensureConnected();\n\n switch (this.config.driver) {\n case 'postgres':\n return this.getPostgresTables();\n case 'mysql':\n case 'mysql2':\n return this.getMySQLTables();\n case 'better-sqlite3':\n case 'sqlite':\n return this.getSQLiteTables();\n default:\n throw new Error('Get tables not supported for this driver');\n }\n }\n\n /**\n * Get PostgreSQL tables\n */\n protected async getPostgresTables(): Promise<string[]> {\n const sql = `\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = 'public'\n AND table_type = 'BASE TABLE'\n `;\n const result = await this.select<any>(sql);\n return result.map((row) => row.table_name);\n }\n\n /**\n * Get MySQL tables\n */\n protected async getMySQLTables(): Promise<string[]> {\n const sql = 'SHOW TABLES';\n const result = await this.select<any>(sql);\n return result.map((row) => Object.values(row)[0] as string);\n }\n\n /**\n * Get SQLite tables\n */\n protected async getSQLiteTables(): Promise<string[]> {\n const sql = `\n SELECT name\n FROM sqlite_master\n WHERE type = 'table'\n AND name NOT LIKE 'sqlite_%'\n `;\n const result = await this.select<any>(sql);\n return result.map((row) => row.name);\n }\n\n /**\n * Execute a statement with its bindings passed natively to the driver.\n *\n * This is the single execution path behind `query()`, `select()`, `insert()`,\n * `update()` and `delete()`. Bindings are never written into the SQL text: the\n * driver receives the statement and the values separately, so quotes,\n * semicolons, comments and `?` characters inside a value stay data.\n */\n private async execute<T = any>(sql: string, bindings: any[], mode: ExecutionMode): Promise<ExecutedResult<T>> {\n this.ensureConnected();\n\n // The driver instance to talk to: the transaction client when one is active,\n // otherwise the pooled connection.\n const client = this.transactionClient ?? this.rawClient;\n\n try {\n const values = this.normalizeBindings(bindings);\n\n switch (this.config.driver) {\n case 'postgres':\n return await this.executePostgres<T>(client, sql, values, mode);\n case 'mysql':\n case 'mysql2':\n return await this.executeMysql<T>(client, sql, values, mode);\n case 'better-sqlite3':\n case 'sqlite':\n return this.executeSqlite<T>(client, sql, values, mode);\n default:\n throw new Error(`Unsupported database driver: ${this.config.driver}`);\n }\n } catch (error: any) {\n throw new Error(`Query failed: ${error?.message || error}\\nSQL: ${sql}`, { cause: error });\n }\n }\n\n /**\n * Execute through better-sqlite3: positional `?` parameters bound natively.\n */\n private executeSqlite<T = any>(client: any, sql: string, values: any[], mode: ExecutionMode): ExecutedResult<T> {\n const statement = client.prepare(sql);\n\n // Statements that produce no rows (DDL, DML, BEGIN/COMMIT) must be run(),\n // otherwise better-sqlite3 throws when asked for rows that do not exist.\n if (mode === 'run' || (mode === 'all' && statement.reader === false)) {\n const info = statement.run(...values);\n return { rows: [], rowCount: Number(info?.changes ?? 0), insertId: info?.lastInsertRowid };\n }\n\n if (mode === 'get') {\n const row = statement.get(...values);\n return { rows: row === undefined ? [] : [row], rowCount: row === undefined ? 0 : 1 };\n }\n\n const rows: T[] = statement.all(...values);\n return { rows, rowCount: rows.length };\n }\n\n /**\n * Execute through postgres.js: values are sent as real query parameters.\n */\n private async executePostgres<T = any>(\n client: any,\n sql: string,\n values: any[],\n mode: ExecutionMode\n ): Promise<ExecutedResult<T>> {\n const query = values.length > 0 ? this.toPostgresPlaceholders(sql, values.length) : sql;\n const result: any = await client.unsafe(query, values);\n\n const rows: T[] = Array.isArray(result) ? result : result?.rows || [];\n\n if (mode === 'run') {\n // postgres.js reports affected rows on the command tag, not in `rows`.\n const affected = Number.isFinite(result?.count) ? Number(result.count) : rows.length;\n return { rows, rowCount: affected, insertId: (rows[0] as any)?.id };\n }\n\n if (mode === 'get') {\n return { rows: rows.slice(0, 1), rowCount: Math.min(rows.length, 1) };\n }\n\n return { rows, rowCount: rows.length };\n }\n\n /**\n * Execute through mysql2: positional `?` parameters bound natively.\n */\n private async executeMysql<T = any>(\n client: any,\n sql: string,\n values: any[],\n mode: ExecutionMode\n ): Promise<ExecutedResult<T>> {\n const [result] = await client.execute(sql, values);\n\n if (Array.isArray(result)) {\n const rows: T[] = result;\n\n if (mode === 'run') {\n return { rows, rowCount: rows.length, insertId: (rows[0] as any)?.id };\n }\n\n if (mode === 'get') {\n return { rows: rows.slice(0, 1), rowCount: Math.min(rows.length, 1) };\n }\n\n return { rows, rowCount: rows.length };\n }\n\n // DML/DDL statements give a result header instead of rows.\n return {\n rows: [],\n rowCount: Number(result?.affectedRows ?? 0),\n insertId: result?.insertId,\n };\n }\n\n /**\n * Normalize bindings before handing them to the driver.\n *\n * `undefined` becomes `null`, dates become ISO strings, and booleans become\n * 1/0 only for the drivers that cannot bind a boolean natively. Anything the\n * driver cannot bind (objects, arrays, functions, symbols) fails loudly rather\n * than being silently stringified into the SQL text.\n */\n private normalizeBindings(bindings: any[]): any[] {\n return bindings.map((value) => this.normalizeBinding(value));\n }\n\n /**\n * Normalize a single binding value.\n */\n private normalizeBinding(value: any): any {\n if (value === undefined || value === null) {\n return null;\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n switch (typeof value) {\n case 'string':\n case 'number':\n case 'bigint':\n return value;\n case 'boolean':\n return this.bindsBooleansNatively() ? value : Number(value);\n case 'object':\n if (this.isBinary(value)) {\n return value;\n }\n throw this.unsupportedBinding(value);\n default:\n throw this.unsupportedBinding(value);\n }\n }\n\n /**\n * Whether the current driver can bind a JS boolean as a native parameter.\n *\n * better-sqlite3 only binds numbers, strings, bigints, buffers and null, so\n * booleans are converted to 1/0 there. postgres.js and mysql2 both send\n * booleans natively.\n */\n private bindsBooleansNatively(): boolean {\n return this.config.driver !== 'better-sqlite3' && this.config.driver !== 'sqlite';\n }\n\n /**\n * Binary values are bindable by every supported driver.\n */\n private isBinary(value: any): boolean {\n if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {\n return true;\n }\n\n return ArrayBuffer.isView(value) && !(value instanceof DataView);\n }\n\n /**\n * Error for values the driver cannot bind as a parameter.\n */\n private unsupportedBinding(value: any): Error {\n const kind = Array.isArray(value) ? 'array' : typeof value === 'object' ? 'object' : typeof value;\n\n return new TypeError(\n `Cannot bind a value of type \"${kind}\" as a query parameter for the \"${this.config.driver}\" driver. ` +\n 'Serialize the value explicitly before passing it as a binding (for example: JSON.stringify()).'\n );\n }\n\n /**\n * Rewrite `?` placeholders into the `$n` form postgres.js expects.\n *\n * Only placeholder tokens are rewritten: quoted strings, quoted identifiers\n * and comments are copied through verbatim, so a literal `?` inside the SQL\n * text never shifts the binding order. Values are never touched here — they\n * stay in the parameter array sent alongside the statement.\n */\n private toPostgresPlaceholders(sql: string, expected: number): string {\n let out = '';\n let index = 0;\n let placeholders = 0;\n\n while (index < sql.length) {\n const char = sql[index];\n\n if (char === \"'\" || char === '\"' || char === '`') {\n const end = this.endOfQuoted(sql, index, char);\n out += sql.slice(index, end);\n index = end;\n continue;\n }\n\n if (char === '-' && sql[index + 1] === '-') {\n const end = sql.indexOf('\\n', index);\n const stop = end === -1 ? sql.length : end;\n out += sql.slice(index, stop);\n index = stop;\n continue;\n }\n\n if (char === '/' && sql[index + 1] === '*') {\n const end = sql.indexOf('*/', index + 2);\n const stop = end === -1 ? sql.length : end + 2;\n out += sql.slice(index, stop);\n index = stop;\n continue;\n }\n\n if (char === '?') {\n placeholders += 1;\n out += `$${placeholders}`;\n index += 1;\n continue;\n }\n\n out += char;\n index += 1;\n }\n\n if (placeholders !== expected) {\n throw new Error(`Cannot bind ${expected} parameter(s) against ${placeholders} placeholder(s) in SQL: ${sql}`);\n }\n\n return out;\n }\n\n /**\n * End index (exclusive) of a quoted literal/identifier starting at `start`.\n *\n * Doubled quotes (`''`, `\"\"`) are escapes and stay inside the quoted region.\n */\n private endOfQuoted(sql: string, start: number, quote: string): number {\n let index = start + 1;\n\n while (index < sql.length) {\n if (sql[index] === quote) {\n if (sql[index + 1] === quote) {\n index += 2;\n continue;\n }\n return index + 1;\n }\n index += 1;\n }\n\n return sql.length;\n }\n\n /**\n * Ensure the adapter is connected\n */\n protected ensureConnected(): void {\n if (!this.connected) {\n throw new Error('Database not connected. Call connect() first.');\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`./Query/Builder.cjs`);var
|
|
1
|
+
require(`../_virtual/_rolldown/runtime.cjs`);const e=require(`./Query/Builder.cjs`),t=new Set([`40001`,`40P01`,`ER_LOCK_DEADLOCK`,`ER_LOCK_WAIT_TIMEOUT`,`SQLITE_BUSY`,`SQLITE_LOCKED`]),n=new Set([1205,1213]);var r=class r{adapter;config;queryLog=[];loggingEnabled=!1;deadlockRetryDelayMs=50;constructor(e,t){this.adapter=e,this.config=t}table(t){return new e.Builder(this.adapter).from(t)}async query(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.query(e,t))}async select(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.select(e,t))}async insert(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.insert(e,t))}async update(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.update(e,t))}async delete(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.delete(e,t))}async beginTransaction(){await this.adapter.beginTransaction()}async commit(){await this.adapter.commit()}async rollback(){await this.adapter.rollback()}async transaction(e,t=1){let n=Math.max(1,Math.floor(t));for(let t=1;;t+=1)try{return await this.runInTransaction(e)}catch(e){if(t>=n||!r.isDeadlockOrLockTimeout(e))throw e;await r.sleep(this.deadlockRetryDelayMs)}}async runInTransaction(e){await this.beginTransaction();try{let t=await e(this);return await this.commit(),t}catch(e){throw await this.rollback(),e}}static isDeadlockOrLockTimeout(e){let r=new Set,i=e;for(;i!=null&&!r.has(i);){if(r.add(i),typeof i.code==`string`&&t.has(i.code)||typeof i.code==`number`&&n.has(i.code)||typeof i.errno==`number`&&n.has(i.errno))return!0;i=i.cause}return!1}static sleep(e){return new Promise(t=>setTimeout(t,e))}async connect(){await this.adapter.connect()}async disconnect(){await this.adapter.disconnect()}isConnected(){return this.adapter.isConnected()}async getTables(){return this.adapter.getTables()}getAdapter(){return this.adapter}getConfig(){return this.config}enableQueryLog(){this.loggingEnabled=!0}disableQueryLog(){this.loggingEnabled=!1}getQueryLog(){return this.queryLog}flushQueryLog(){this.queryLog=[]}async runQueryWithLogging(e,t,n){if(!this.loggingEnabled)return n();let r=Date.now();try{let i=await n(),a=Date.now()-r;return this.queryLog.push({query:e,bindings:t,time:a}),i}catch(n){let i=Date.now()-r;throw this.queryLog.push({query:e,bindings:t,time:i}),n}}};exports.Connection=r;
|
|
@@ -11,6 +11,11 @@ declare class Connection {
|
|
|
11
11
|
time: number;
|
|
12
12
|
}>;
|
|
13
13
|
protected loggingEnabled: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Pause between deadlock retries of `transaction()`, mirroring Laravel's
|
|
16
|
+
* 50ms `deadlockRetryInterval`.
|
|
17
|
+
*/
|
|
18
|
+
protected deadlockRetryDelayMs: number;
|
|
14
19
|
constructor(adapter: DatabaseAdapter, config: DatabaseConfig);
|
|
15
20
|
/**
|
|
16
21
|
* Get a query builder instance
|
|
@@ -49,9 +54,31 @@ declare class Connection {
|
|
|
49
54
|
*/
|
|
50
55
|
rollback(): Promise<void>;
|
|
51
56
|
/**
|
|
52
|
-
* Execute a callback within a transaction
|
|
57
|
+
* Execute a callback within a transaction.
|
|
58
|
+
*
|
|
59
|
+
* The same connection is passed to the callback, so `db.table(...)` writes
|
|
60
|
+
* and Ensemble model queries all run through the adapter's transaction
|
|
61
|
+
* client. When `attempts` is greater than one the whole transaction is
|
|
62
|
+
* retried, but only for deadlock/lock-timeout failures; any other error is
|
|
63
|
+
* rolled back and rethrown immediately.
|
|
64
|
+
*/
|
|
65
|
+
transaction<T>(callback: (connection: Connection) => Promise<T>, attempts?: number): Promise<T>;
|
|
66
|
+
/**
|
|
67
|
+
* Run one attempt of `transaction()`: begin, hand this same connection to
|
|
68
|
+
* the callback, then commit or roll back.
|
|
69
|
+
*/
|
|
70
|
+
protected runInTransaction<T>(callback: (connection: Connection) => Promise<T>): Promise<T>;
|
|
71
|
+
/**
|
|
72
|
+
* Detect the deadlock/lock-timeout errors that `transaction()` retries on.
|
|
73
|
+
*
|
|
74
|
+
* The adapter wraps driver failures with the original error as `cause`, so
|
|
75
|
+
* the whole cause chain is inspected for the driver's error code.
|
|
76
|
+
*/
|
|
77
|
+
protected static isDeadlockOrLockTimeout(error: unknown): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Wait for the given number of milliseconds between deadlock retries.
|
|
53
80
|
*/
|
|
54
|
-
|
|
81
|
+
protected static sleep(ms: number): Promise<void>;
|
|
55
82
|
/**
|
|
56
83
|
* Connect to the database
|
|
57
84
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Connection.d.cts","names":[],"sources":["../../src/Database/Connection.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"Connection.d.cts","names":[],"sources":["../../src/Database/Connection.ts"],"mappings":";;;;cA+Ba,UAAA;EAAA,UAUC,OAAA,EAAS,eAAA;EAAA,UACT,MAAA,EAAQ,cAAA;EAAA,UAVV,QAAA,EAAU,KAAA;IAAQ,KAAA;IAAe,QAAA;IAAiB,IAAA;EAAA;EAAA,UAClD,cAAA;EA2CuC;;;;EAAA,UAtCvC,oBAAA;cAGE,OAAA,EAAS,eAAA,EACT,MAAA,EAAQ,cAAA;EA2E+C;;;EArEnE,KAAA,CAAM,SAAA,WAAoB,OAAA;EAyFiC;;;EAlFrD,KAAA,CAAM,GAAA,UAAa,QAAA,WAAuB,OAAA;EAkFuC;;;EA3EjF,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAsJ9B;;;EA/Ib,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAgM8C;;;EAzLzF,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAyL0D;;;EAlLrG,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAzCrC;;;EAgDN,gBAAA,CAAA,GAAoB,OAAA;EA1DE;;;EAiEtB,MAAA,CAAA,GAAU,OAAA;EA3DN;;;EAkEJ,QAAA,CAAA,GAAY,OAAA;EA9DE;;;;;;;;;EA2Ed,WAAA,GAAA,CAAe,QAAA,GAAW,UAAA,EAAY,UAAA,KAAe,OAAA,CAAQ,CAAA,GAAI,QAAA,YAAuB,OAAA,CAAQ,CAAA;EAvDzF;;;;EAAA,UA2EG,gBAAA,GAAA,CAAoB,QAAA,GAAW,UAAA,EAAY,UAAA,KAAe,OAAA,CAAQ,CAAA,IAAK,OAAA,CAAQ,CAAA;EApErE;;;;;;EAAA,iBAuFT,uBAAA,CAAwB,KAAA;EAzE5B;;;EAAA,iBAqGI,KAAA,CAAM,EAAA,WAAa,OAAA;EA9FV;;;EAqGpB,OAAA,CAAA,GAAW,OAAA;EAvFC;;;EA8FZ,UAAA,CAAA,GAAc,OAAA;EAjFY;;;EAwFhC,WAAA,CAAA;EAxFuE;;;EA+FjE,SAAA,CAAA,GAAa,OAAA;EA3Ec;;;EAkFjC,UAAA,CAAA,GAAc,eAAA;EAlFoE;;;EAyFlF,SAAA,CAAA,GAAa,cAAA;EAtEI;;;EA6EjB,cAAA,CAAA;EAjDoC;;;EAwDpC,eAAA,CAAA;EA1CoB;;;EAiDpB,WAAA,CAAA,GAAe,KAAA;IAAQ,KAAA;IAAe,QAAA;IAAiB,IAAA;EAAA;EAdvD;;;EAqBA,aAAA,CAAA;EAPuB;;;EAAA,UAcP,mBAAA,GAAA,CAAuB,KAAA,UAAe,QAAA,SAAiB,QAAA,QAAgB,OAAA,CAAQ,CAAA,IAAK,OAAA,CAAQ,CAAA;AAAA"}
|
|
@@ -11,6 +11,11 @@ declare class Connection {
|
|
|
11
11
|
time: number;
|
|
12
12
|
}>;
|
|
13
13
|
protected loggingEnabled: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Pause between deadlock retries of `transaction()`, mirroring Laravel's
|
|
16
|
+
* 50ms `deadlockRetryInterval`.
|
|
17
|
+
*/
|
|
18
|
+
protected deadlockRetryDelayMs: number;
|
|
14
19
|
constructor(adapter: DatabaseAdapter, config: DatabaseConfig);
|
|
15
20
|
/**
|
|
16
21
|
* Get a query builder instance
|
|
@@ -49,9 +54,31 @@ declare class Connection {
|
|
|
49
54
|
*/
|
|
50
55
|
rollback(): Promise<void>;
|
|
51
56
|
/**
|
|
52
|
-
* Execute a callback within a transaction
|
|
57
|
+
* Execute a callback within a transaction.
|
|
58
|
+
*
|
|
59
|
+
* The same connection is passed to the callback, so `db.table(...)` writes
|
|
60
|
+
* and Ensemble model queries all run through the adapter's transaction
|
|
61
|
+
* client. When `attempts` is greater than one the whole transaction is
|
|
62
|
+
* retried, but only for deadlock/lock-timeout failures; any other error is
|
|
63
|
+
* rolled back and rethrown immediately.
|
|
64
|
+
*/
|
|
65
|
+
transaction<T>(callback: (connection: Connection) => Promise<T>, attempts?: number): Promise<T>;
|
|
66
|
+
/**
|
|
67
|
+
* Run one attempt of `transaction()`: begin, hand this same connection to
|
|
68
|
+
* the callback, then commit or roll back.
|
|
69
|
+
*/
|
|
70
|
+
protected runInTransaction<T>(callback: (connection: Connection) => Promise<T>): Promise<T>;
|
|
71
|
+
/**
|
|
72
|
+
* Detect the deadlock/lock-timeout errors that `transaction()` retries on.
|
|
73
|
+
*
|
|
74
|
+
* The adapter wraps driver failures with the original error as `cause`, so
|
|
75
|
+
* the whole cause chain is inspected for the driver's error code.
|
|
76
|
+
*/
|
|
77
|
+
protected static isDeadlockOrLockTimeout(error: unknown): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Wait for the given number of milliseconds between deadlock retries.
|
|
53
80
|
*/
|
|
54
|
-
|
|
81
|
+
protected static sleep(ms: number): Promise<void>;
|
|
55
82
|
/**
|
|
56
83
|
* Connect to the database
|
|
57
84
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Connection.d.mts","names":[],"sources":["../../src/Database/Connection.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"Connection.d.mts","names":[],"sources":["../../src/Database/Connection.ts"],"mappings":";;;;cA+Ba,UAAA;EAAA,UAUC,OAAA,EAAS,eAAA;EAAA,UACT,MAAA,EAAQ,cAAA;EAAA,UAVV,QAAA,EAAU,KAAA;IAAQ,KAAA;IAAe,QAAA;IAAiB,IAAA;EAAA;EAAA,UAClD,cAAA;EA2CuC;;;;EAAA,UAtCvC,oBAAA;cAGE,OAAA,EAAS,eAAA,EACT,MAAA,EAAQ,cAAA;EA2E+C;;;EArEnE,KAAA,CAAM,SAAA,WAAoB,OAAA;EAyFiC;;;EAlFrD,KAAA,CAAM,GAAA,UAAa,QAAA,WAAuB,OAAA;EAkFuC;;;EA3EjF,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAsJ9B;;;EA/Ib,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAgM8C;;;EAzLzF,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAyL0D;;;EAlLrG,MAAA,CAAO,GAAA,UAAa,QAAA,WAAuB,OAAA;EAzCrC;;;EAgDN,gBAAA,CAAA,GAAoB,OAAA;EA1DE;;;EAiEtB,MAAA,CAAA,GAAU,OAAA;EA3DN;;;EAkEJ,QAAA,CAAA,GAAY,OAAA;EA9DE;;;;;;;;;EA2Ed,WAAA,GAAA,CAAe,QAAA,GAAW,UAAA,EAAY,UAAA,KAAe,OAAA,CAAQ,CAAA,GAAI,QAAA,YAAuB,OAAA,CAAQ,CAAA;EAvDzF;;;;EAAA,UA2EG,gBAAA,GAAA,CAAoB,QAAA,GAAW,UAAA,EAAY,UAAA,KAAe,OAAA,CAAQ,CAAA,IAAK,OAAA,CAAQ,CAAA;EApErE;;;;;;EAAA,iBAuFT,uBAAA,CAAwB,KAAA;EAzE5B;;;EAAA,iBAqGI,KAAA,CAAM,EAAA,WAAa,OAAA;EA9FV;;;EAqGpB,OAAA,CAAA,GAAW,OAAA;EAvFC;;;EA8FZ,UAAA,CAAA,GAAc,OAAA;EAjFY;;;EAwFhC,WAAA,CAAA;EAxFuE;;;EA+FjE,SAAA,CAAA,GAAa,OAAA;EA3Ec;;;EAkFjC,UAAA,CAAA,GAAc,eAAA;EAlFoE;;;EAyFlF,SAAA,CAAA,GAAa,cAAA;EAtEI;;;EA6EjB,cAAA,CAAA;EAjDoC;;;EAwDpC,eAAA,CAAA;EA1CoB;;;EAiDpB,WAAA,CAAA,GAAe,KAAA;IAAQ,KAAA;IAAe,QAAA;IAAiB,IAAA;EAAA;EAdvD;;;EAqBA,aAAA,CAAA;EAPuB;;;EAAA,UAcP,mBAAA,GAAA,CAAuB,KAAA,UAAe,QAAA,SAAiB,QAAA,QAAgB,OAAA,CAAQ,CAAA,IAAK,OAAA,CAAQ,CAAA;AAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Builder as e}from"./Query/Builder.mjs";
|
|
1
|
+
import{Builder as e}from"./Query/Builder.mjs";const t=new Set([`40001`,`40P01`,`ER_LOCK_DEADLOCK`,`ER_LOCK_WAIT_TIMEOUT`,`SQLITE_BUSY`,`SQLITE_LOCKED`]),n=new Set([1205,1213]);var r=class r{adapter;config;queryLog=[];loggingEnabled=!1;deadlockRetryDelayMs=50;constructor(e,t){this.adapter=e,this.config=t}table(t){return new e(this.adapter).from(t)}async query(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.query(e,t))}async select(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.select(e,t))}async insert(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.insert(e,t))}async update(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.update(e,t))}async delete(e,t=[]){return this.runQueryWithLogging(e,t,()=>this.adapter.delete(e,t))}async beginTransaction(){await this.adapter.beginTransaction()}async commit(){await this.adapter.commit()}async rollback(){await this.adapter.rollback()}async transaction(e,t=1){let n=Math.max(1,Math.floor(t));for(let t=1;;t+=1)try{return await this.runInTransaction(e)}catch(e){if(t>=n||!r.isDeadlockOrLockTimeout(e))throw e;await r.sleep(this.deadlockRetryDelayMs)}}async runInTransaction(e){await this.beginTransaction();try{let t=await e(this);return await this.commit(),t}catch(e){throw await this.rollback(),e}}static isDeadlockOrLockTimeout(e){let r=new Set,i=e;for(;i!=null&&!r.has(i);){if(r.add(i),typeof i.code==`string`&&t.has(i.code)||typeof i.code==`number`&&n.has(i.code)||typeof i.errno==`number`&&n.has(i.errno))return!0;i=i.cause}return!1}static sleep(e){return new Promise(t=>setTimeout(t,e))}async connect(){await this.adapter.connect()}async disconnect(){await this.adapter.disconnect()}isConnected(){return this.adapter.isConnected()}async getTables(){return this.adapter.getTables()}getAdapter(){return this.adapter}getConfig(){return this.config}enableQueryLog(){this.loggingEnabled=!0}disableQueryLog(){this.loggingEnabled=!1}getQueryLog(){return this.queryLog}flushQueryLog(){this.queryLog=[]}async runQueryWithLogging(e,t,n){if(!this.loggingEnabled)return n();let r=Date.now();try{let i=await n(),a=Date.now()-r;return this.queryLog.push({query:e,bindings:t,time:a}),i}catch(n){let i=Date.now()-r;throw this.queryLog.push({query:e,bindings:t,time:i}),n}}};export{r as Connection};
|
|
2
2
|
//# sourceMappingURL=Connection.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Connection.mjs","names":[],"sources":["../../src/Database/Connection.ts"],"sourcesContent":["/**\n * Connection Class\n *\n * Represents a database connection\n */\n\nimport { DatabaseAdapter, DatabaseConfig } from './Contracts/DatabaseAdapter';\nimport { Builder } from './Query/Builder';\n\nexport class Connection {\n protected queryLog: Array<{ query: string; bindings: any[]; time: number }> = [];\n protected loggingEnabled: boolean = false;\n\n constructor(\n protected adapter: DatabaseAdapter,\n protected config: DatabaseConfig\n ) {}\n\n /**\n * Get a query builder instance\n */\n table(tableName: string): Builder {\n return new Builder(this.adapter).from(tableName);\n }\n\n /**\n * Execute a raw SQL query\n */\n async query(sql: string, bindings: any[] = []): Promise<any> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.query(sql, bindings));\n }\n\n /**\n * Execute a SELECT query\n */\n async select(sql: string, bindings: any[] = []): Promise<any[]> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.select(sql, bindings));\n }\n\n /**\n * Execute an INSERT query\n */\n async insert(sql: string, bindings: any[] = []): Promise<any> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.insert(sql, bindings));\n }\n\n /**\n * Execute an UPDATE query\n */\n async update(sql: string, bindings: any[] = []): Promise<number> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.update(sql, bindings));\n }\n\n /**\n * Execute a DELETE query\n */\n async delete(sql: string, bindings: any[] = []): Promise<number> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.delete(sql, bindings));\n }\n\n /**\n * Begin a transaction\n */\n async beginTransaction(): Promise<void> {\n await this.adapter.beginTransaction();\n }\n\n /**\n * Commit a transaction\n */\n async commit(): Promise<void> {\n await this.adapter.commit();\n }\n\n /**\n * Rollback a transaction\n */\n async rollback(): Promise<void> {\n await this.adapter.rollback();\n }\n\n /**\n * Execute a callback within a transaction\n */\n async transaction<T>(callback: (connection: Connection) => Promise<T>): Promise<T> {\n await this.beginTransaction();\n\n try {\n const result = await callback(this);\n await this.commit();\n return result;\n } catch (error) {\n await this.rollback();\n throw error;\n }\n }\n\n /**\n * Connect to the database\n */\n async connect(): Promise<void> {\n await this.adapter.connect();\n }\n\n /**\n * Disconnect from the database\n */\n async disconnect(): Promise<void> {\n await this.adapter.disconnect();\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.adapter.isConnected();\n }\n\n /**\n * Get all table names in the connected database\n */\n async getTables(): Promise<string[]> {\n return this.adapter.getTables();\n }\n\n /**\n * Get the underlying adapter\n */\n getAdapter(): DatabaseAdapter {\n return this.adapter;\n }\n\n /**\n * Get the configuration\n */\n getConfig(): DatabaseConfig {\n return this.config;\n }\n\n /**\n * Enable query logging\n */\n enableQueryLog(): void {\n this.loggingEnabled = true;\n }\n\n /**\n * Disable query logging\n */\n disableQueryLog(): void {\n this.loggingEnabled = false;\n }\n\n /**\n * Get the query log\n */\n getQueryLog(): Array<{ query: string; bindings: any[]; time: number }> {\n return this.queryLog;\n }\n\n /**\n * Clear the query log\n */\n flushQueryLog(): void {\n this.queryLog = [];\n }\n\n /**\n * Run a query with logging\n */\n protected async runQueryWithLogging<T>(query: string, bindings: any[], callback: () => Promise<T>): Promise<T> {\n if (!this.loggingEnabled) {\n return callback();\n }\n\n const start = Date.now();\n\n try {\n const result = await callback();\n const time = Date.now() - start;\n\n this.queryLog.push({ query, bindings, time });\n\n return result;\n } catch (error) {\n const time = Date.now() - start;\n this.queryLog.push({ query, bindings, time });\n throw error;\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Connection.mjs","names":[],"sources":["../../src/Database/Connection.ts"],"sourcesContent":["/**\n * Connection Class\n *\n * Represents a database connection\n */\n\nimport { DatabaseAdapter, DatabaseConfig } from './Contracts/DatabaseAdapter';\nimport { Builder } from './Query/Builder';\n\n/**\n * Driver error codes that signal a deadlock or a lock-wait timeout and are\n * therefore safe to retry: the rolled-back transaction left no partial state,\n * so re-running the callback has a chance of succeeding.\n */\nconst DEADLOCK_ERROR_CODES = new Set([\n '40001', // postgres: serialization failure\n '40P01', // postgres: deadlock detected\n 'ER_LOCK_DEADLOCK', // mysql: deadlock on lock\n 'ER_LOCK_WAIT_TIMEOUT', // mysql: lock wait timeout\n 'SQLITE_BUSY', // sqlite: database file is locked\n 'SQLITE_LOCKED', // sqlite: table is locked\n]);\n\n/**\n * Numeric driver error codes (mysql2 `errno`) for the same retryable failures.\n */\nconst DEADLOCK_ERROR_ERRNOS = new Set([\n 1205, // mysql: lock wait timeout\n 1213, // mysql: deadlock on lock\n]);\n\nexport class Connection {\n protected queryLog: Array<{ query: string; bindings: any[]; time: number }> = [];\n protected loggingEnabled: boolean = false;\n /**\n * Pause between deadlock retries of `transaction()`, mirroring Laravel's\n * 50ms `deadlockRetryInterval`.\n */\n protected deadlockRetryDelayMs: number = 50;\n\n constructor(\n protected adapter: DatabaseAdapter,\n protected config: DatabaseConfig\n ) {}\n\n /**\n * Get a query builder instance\n */\n table(tableName: string): Builder {\n return new Builder(this.adapter).from(tableName);\n }\n\n /**\n * Execute a raw SQL query\n */\n async query(sql: string, bindings: any[] = []): Promise<any> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.query(sql, bindings));\n }\n\n /**\n * Execute a SELECT query\n */\n async select(sql: string, bindings: any[] = []): Promise<any[]> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.select(sql, bindings));\n }\n\n /**\n * Execute an INSERT query\n */\n async insert(sql: string, bindings: any[] = []): Promise<any> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.insert(sql, bindings));\n }\n\n /**\n * Execute an UPDATE query\n */\n async update(sql: string, bindings: any[] = []): Promise<number> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.update(sql, bindings));\n }\n\n /**\n * Execute a DELETE query\n */\n async delete(sql: string, bindings: any[] = []): Promise<number> {\n return this.runQueryWithLogging(sql, bindings, () => this.adapter.delete(sql, bindings));\n }\n\n /**\n * Begin a transaction\n */\n async beginTransaction(): Promise<void> {\n await this.adapter.beginTransaction();\n }\n\n /**\n * Commit a transaction\n */\n async commit(): Promise<void> {\n await this.adapter.commit();\n }\n\n /**\n * Rollback a transaction\n */\n async rollback(): Promise<void> {\n await this.adapter.rollback();\n }\n\n /**\n * Execute a callback within a transaction.\n *\n * The same connection is passed to the callback, so `db.table(...)` writes\n * and Ensemble model queries all run through the adapter's transaction\n * client. When `attempts` is greater than one the whole transaction is\n * retried, but only for deadlock/lock-timeout failures; any other error is\n * rolled back and rethrown immediately.\n */\n async transaction<T>(callback: (connection: Connection) => Promise<T>, attempts: number = 1): Promise<T> {\n const maxAttempts = Math.max(1, Math.floor(attempts));\n\n for (let attempt = 1; ; attempt += 1) {\n try {\n return await this.runInTransaction(callback);\n } catch (error) {\n if (attempt >= maxAttempts || !Connection.isDeadlockOrLockTimeout(error)) {\n throw error;\n }\n\n await Connection.sleep(this.deadlockRetryDelayMs);\n }\n }\n }\n\n /**\n * Run one attempt of `transaction()`: begin, hand this same connection to\n * the callback, then commit or roll back.\n */\n protected async runInTransaction<T>(callback: (connection: Connection) => Promise<T>): Promise<T> {\n await this.beginTransaction();\n\n try {\n const result = await callback(this);\n await this.commit();\n return result;\n } catch (error) {\n await this.rollback();\n throw error;\n }\n }\n\n /**\n * Detect the deadlock/lock-timeout errors that `transaction()` retries on.\n *\n * The adapter wraps driver failures with the original error as `cause`, so\n * the whole cause chain is inspected for the driver's error code.\n */\n protected static isDeadlockOrLockTimeout(error: unknown): boolean {\n const seen = new Set<unknown>();\n let current: any = error;\n\n while (current !== null && current !== undefined && !seen.has(current)) {\n seen.add(current);\n\n if (typeof current.code === 'string' && DEADLOCK_ERROR_CODES.has(current.code)) {\n return true;\n }\n\n if (typeof current.code === 'number' && DEADLOCK_ERROR_ERRNOS.has(current.code)) {\n return true;\n }\n\n if (typeof current.errno === 'number' && DEADLOCK_ERROR_ERRNOS.has(current.errno)) {\n return true;\n }\n\n current = current.cause;\n }\n\n return false;\n }\n\n /**\n * Wait for the given number of milliseconds between deadlock retries.\n */\n protected static sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Connect to the database\n */\n async connect(): Promise<void> {\n await this.adapter.connect();\n }\n\n /**\n * Disconnect from the database\n */\n async disconnect(): Promise<void> {\n await this.adapter.disconnect();\n }\n\n /**\n * Check if connected\n */\n isConnected(): boolean {\n return this.adapter.isConnected();\n }\n\n /**\n * Get all table names in the connected database\n */\n async getTables(): Promise<string[]> {\n return this.adapter.getTables();\n }\n\n /**\n * Get the underlying adapter\n */\n getAdapter(): DatabaseAdapter {\n return this.adapter;\n }\n\n /**\n * Get the configuration\n */\n getConfig(): DatabaseConfig {\n return this.config;\n }\n\n /**\n * Enable query logging\n */\n enableQueryLog(): void {\n this.loggingEnabled = true;\n }\n\n /**\n * Disable query logging\n */\n disableQueryLog(): void {\n this.loggingEnabled = false;\n }\n\n /**\n * Get the query log\n */\n getQueryLog(): Array<{ query: string; bindings: any[]; time: number }> {\n return this.queryLog;\n }\n\n /**\n * Clear the query log\n */\n flushQueryLog(): void {\n this.queryLog = [];\n }\n\n /**\n * Run a query with logging\n */\n protected async runQueryWithLogging<T>(query: string, bindings: any[], callback: () => Promise<T>): Promise<T> {\n if (!this.loggingEnabled) {\n return callback();\n }\n\n const start = Date.now();\n\n try {\n const result = await callback();\n const time = Date.now() - start;\n\n this.queryLog.push({ query, bindings, time });\n\n return result;\n } catch (error) {\n const time = Date.now() - start;\n this.queryLog.push({ query, bindings, time });\n throw error;\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orchestr-sh/orchestr",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.11.
|
|
4
|
+
"version": "1.11.4",
|
|
5
5
|
"description": "A 1:1 Laravel replica in TypeScript - Brings Laravel's elegant syntax and architecture to Node.js",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.mjs",
|