@pineliner/odb-client 1.0.5 → 1.0.7

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.
Files changed (36) hide show
  1. package/dist/core/http-client.d.ts.map +1 -1
  2. package/dist/database/adapters/bun-sqlite.d.ts.map +1 -1
  3. package/dist/database/adapters/libsql.d.ts.map +1 -1
  4. package/dist/database/adapters/odblite.d.ts +2 -1
  5. package/dist/database/adapters/odblite.d.ts.map +1 -1
  6. package/dist/database/index.d.ts +2 -0
  7. package/dist/database/index.d.ts.map +1 -1
  8. package/dist/database/manager.d.ts +2 -1
  9. package/dist/database/manager.d.ts.map +1 -1
  10. package/dist/database/sql-template.d.ts +432 -0
  11. package/dist/database/sql-template.d.ts.map +1 -0
  12. package/dist/database/sql-template.examples.d.ts +28 -0
  13. package/dist/database/sql-template.examples.d.ts.map +1 -0
  14. package/dist/database/types.d.ts +10 -1
  15. package/dist/database/types.d.ts.map +1 -1
  16. package/dist/index.cjs +1861 -1663
  17. package/dist/index.d.ts +3 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +785 -653
  20. package/dist/orm/index.d.ts +228 -0
  21. package/dist/orm/index.d.ts.map +1 -0
  22. package/dist/types.d.ts +2 -0
  23. package/dist/types.d.ts.map +1 -1
  24. package/package.json +1 -1
  25. package/src/core/http-client.ts +1 -0
  26. package/src/database/adapters/bun-sqlite.ts +73 -15
  27. package/src/database/adapters/libsql.ts +73 -15
  28. package/src/database/adapters/odblite.ts +95 -26
  29. package/src/database/index.ts +4 -0
  30. package/src/database/manager.ts +5 -1
  31. package/src/database/sql-template.examples.ts +363 -0
  32. package/src/database/sql-template.ts +660 -0
  33. package/src/database/types.ts +19 -3
  34. package/src/index.ts +31 -0
  35. package/src/orm/index.ts +538 -0
  36. package/src/types.ts +2 -0
package/dist/index.cjs CHANGED
@@ -1,40 +1,366 @@
1
1
  "use strict";
2
- // The require scope
3
- var __webpack_require__ = {};
4
- /************************************************************************/ // webpack/runtime/compat_get_default_export
2
+ var __webpack_modules__ = {
3
+ "./src/orm/index.ts": function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
4
+ __webpack_require__.r(__webpack_exports__);
5
+ __webpack_require__.d(__webpack_exports__, {
6
+ ORM: ()=>ORM,
7
+ and: ()=>and,
8
+ createORM: ()=>createORM,
9
+ eq: ()=>eq,
10
+ gt: ()=>gt,
11
+ gte: ()=>gte,
12
+ inArray: ()=>inArray,
13
+ isNotNull: ()=>isNotNull,
14
+ isNull: ()=>isNull,
15
+ like: ()=>like,
16
+ lt: ()=>lt,
17
+ lte: ()=>lte,
18
+ ne: ()=>ne,
19
+ or: ()=>or
20
+ });
21
+ function eq(field, value) {
22
+ return {
23
+ sql: `${field} = ?`,
24
+ params: [
25
+ value
26
+ ]
27
+ };
28
+ }
29
+ function ne(field, value) {
30
+ return {
31
+ sql: `${field} != ?`,
32
+ params: [
33
+ value
34
+ ]
35
+ };
36
+ }
37
+ function gt(field, value) {
38
+ return {
39
+ sql: `${field} > ?`,
40
+ params: [
41
+ value
42
+ ]
43
+ };
44
+ }
45
+ function gte(field, value) {
46
+ return {
47
+ sql: `${field} >= ?`,
48
+ params: [
49
+ value
50
+ ]
51
+ };
52
+ }
53
+ function lt(field, value) {
54
+ return {
55
+ sql: `${field} < ?`,
56
+ params: [
57
+ value
58
+ ]
59
+ };
60
+ }
61
+ function lte(field, value) {
62
+ return {
63
+ sql: `${field} <= ?`,
64
+ params: [
65
+ value
66
+ ]
67
+ };
68
+ }
69
+ function like(field, pattern) {
70
+ return {
71
+ sql: `${field} LIKE ?`,
72
+ params: [
73
+ pattern
74
+ ]
75
+ };
76
+ }
77
+ function inArray(field, values) {
78
+ const placeholders = values.map(()=>'?').join(', ');
79
+ return {
80
+ sql: `${field} IN (${placeholders})`,
81
+ params: values
82
+ };
83
+ }
84
+ function isNull(field) {
85
+ return {
86
+ sql: `${field} IS NULL`,
87
+ params: []
88
+ };
89
+ }
90
+ function isNotNull(field) {
91
+ return {
92
+ sql: `${field} IS NOT NULL`,
93
+ params: []
94
+ };
95
+ }
96
+ function and(...conditions) {
97
+ const sql = conditions.map((c)=>`(${c.sql})`).join(' AND ');
98
+ const params = conditions.flatMap((c)=>c.params);
99
+ return {
100
+ sql,
101
+ params
102
+ };
103
+ }
104
+ function or(...conditions) {
105
+ const sql = conditions.map((c)=>`(${c.sql})`).join(' OR ');
106
+ const params = conditions.flatMap((c)=>c.params);
107
+ return {
108
+ sql,
109
+ params
110
+ };
111
+ }
112
+ class SelectBuilder {
113
+ db;
114
+ tableName;
115
+ selectFields = [
116
+ '*'
117
+ ];
118
+ whereConditions = [];
119
+ orderByField;
120
+ orderByDir = 'ASC';
121
+ limitValue;
122
+ offsetValue;
123
+ constructor(db, tableName){
124
+ this.db = db;
125
+ this.tableName = tableName;
126
+ }
127
+ select(fields = {}) {
128
+ if (0 === Object.keys(fields).length) this.selectFields = [
129
+ '*'
130
+ ];
131
+ else this.selectFields = Object.keys(fields);
132
+ return this;
133
+ }
134
+ where(condition) {
135
+ this.whereConditions.push(condition);
136
+ return this;
137
+ }
138
+ orderBy(field, direction = 'ASC') {
139
+ this.orderByField = field;
140
+ this.orderByDir = direction;
141
+ return this;
142
+ }
143
+ limit(value) {
144
+ this.limitValue = value;
145
+ return this;
146
+ }
147
+ offset(value) {
148
+ this.offsetValue = value;
149
+ return this;
150
+ }
151
+ async execute() {
152
+ const fields = this.selectFields.join(', ');
153
+ const params = [];
154
+ let sql = `SELECT ${fields} FROM ${this.tableName}`;
155
+ if (this.whereConditions.length > 0) {
156
+ const combinedCondition = 1 === this.whereConditions.length ? this.whereConditions[0] : and(...this.whereConditions);
157
+ sql += ` WHERE ${combinedCondition.sql}`;
158
+ params.push(...combinedCondition.params);
159
+ }
160
+ if (this.orderByField) sql += ` ORDER BY ${this.orderByField} ${this.orderByDir}`;
161
+ if (void 0 !== this.limitValue) {
162
+ sql += " LIMIT ?";
163
+ params.push(this.limitValue);
164
+ }
165
+ if (void 0 !== this.offsetValue) {
166
+ sql += " OFFSET ?";
167
+ params.push(this.offsetValue);
168
+ }
169
+ const result = await this.db.execute(sql, params);
170
+ return result.rows;
171
+ }
172
+ }
173
+ class InsertBuilder {
174
+ db;
175
+ tableName;
176
+ insertValues = {};
177
+ shouldReturn = false;
178
+ constructor(db, tableName){
179
+ this.db = db;
180
+ this.tableName = tableName;
181
+ }
182
+ values(data) {
183
+ this.insertValues = data;
184
+ return this;
185
+ }
186
+ returning() {
187
+ this.shouldReturn = true;
188
+ return this;
189
+ }
190
+ async execute() {
191
+ const fields = Object.keys(this.insertValues);
192
+ const placeholders = fields.map(()=>'?').join(', ');
193
+ const values = fields.map((f)=>this.insertValues[f]);
194
+ let sql = `
195
+ INSERT INTO ${this.tableName} (${fields.join(', ')})
196
+ VALUES (${placeholders})
197
+ `;
198
+ await this.db.execute(sql, values);
199
+ if (this.shouldReturn) {
200
+ const selectSql = `SELECT * FROM ${this.tableName} ORDER BY id DESC LIMIT 1`;
201
+ const result = await this.db.execute(selectSql, []);
202
+ return result.rows;
203
+ }
204
+ return [];
205
+ }
206
+ }
207
+ class UpdateBuilder {
208
+ db;
209
+ tableName;
210
+ updateValues = {};
211
+ whereConditions = [];
212
+ shouldReturn = false;
213
+ constructor(db, tableName){
214
+ this.db = db;
215
+ this.tableName = tableName;
216
+ }
217
+ set(data) {
218
+ this.updateValues = data;
219
+ return this;
220
+ }
221
+ where(condition) {
222
+ this.whereConditions.push(condition);
223
+ return this;
224
+ }
225
+ returning() {
226
+ this.shouldReturn = true;
227
+ return this;
228
+ }
229
+ async execute() {
230
+ const fields = Object.keys(this.updateValues);
231
+ const setClause = fields.map((f)=>`${f} = ?`).join(', ');
232
+ const values = fields.map((f)=>this.updateValues[f]);
233
+ let sql = `UPDATE ${this.tableName} SET ${setClause}`;
234
+ const params = [
235
+ ...values
236
+ ];
237
+ if (this.whereConditions.length > 0) {
238
+ const combinedCondition = 1 === this.whereConditions.length ? this.whereConditions[0] : and(...this.whereConditions);
239
+ sql += ` WHERE ${combinedCondition.sql}`;
240
+ params.push(...combinedCondition.params);
241
+ }
242
+ await this.db.execute(sql, params);
243
+ if (this.shouldReturn && this.whereConditions.length > 0) {
244
+ const combinedCondition = 1 === this.whereConditions.length ? this.whereConditions[0] : and(...this.whereConditions);
245
+ const selectSql = `SELECT * FROM ${this.tableName} WHERE ${combinedCondition.sql}`;
246
+ const result = await this.db.execute(selectSql, combinedCondition.params);
247
+ return result.rows;
248
+ }
249
+ return [];
250
+ }
251
+ }
252
+ class DeleteBuilder {
253
+ db;
254
+ tableName;
255
+ whereConditions = [];
256
+ constructor(db, tableName){
257
+ this.db = db;
258
+ this.tableName = tableName;
259
+ }
260
+ where(condition) {
261
+ this.whereConditions.push(condition);
262
+ return this;
263
+ }
264
+ async execute() {
265
+ let sql = `DELETE FROM ${this.tableName}`;
266
+ const params = [];
267
+ if (this.whereConditions.length > 0) {
268
+ const combinedCondition = 1 === this.whereConditions.length ? this.whereConditions[0] : and(...this.whereConditions);
269
+ sql += ` WHERE ${combinedCondition.sql}`;
270
+ params.push(...combinedCondition.params);
271
+ }
272
+ await this.db.execute(sql, params);
273
+ }
274
+ }
275
+ class TableQueryBuilder {
276
+ db;
277
+ tableName;
278
+ constructor(db, tableName){
279
+ this.db = db;
280
+ this.tableName = tableName;
281
+ }
282
+ select(fields) {
283
+ const builder = new SelectBuilder(this.db, this.tableName);
284
+ if (fields) builder.select(fields);
285
+ return builder;
286
+ }
287
+ insert() {
288
+ return new InsertBuilder(this.db, this.tableName);
289
+ }
290
+ update() {
291
+ return new UpdateBuilder(this.db, this.tableName);
292
+ }
293
+ delete() {
294
+ return new DeleteBuilder(this.db, this.tableName);
295
+ }
296
+ }
297
+ class ORM {
298
+ db;
299
+ constructor(db){
300
+ this.db = db;
301
+ }
302
+ table(tableName) {
303
+ return new TableQueryBuilder(this.db, tableName);
304
+ }
305
+ select(fields) {
306
+ return {
307
+ from: (tableName)=>{
308
+ const builder = new SelectBuilder(this.db, tableName);
309
+ if (fields) builder.select(fields);
310
+ return builder;
311
+ }
312
+ };
313
+ }
314
+ insert(tableName) {
315
+ return new InsertBuilder(this.db, tableName);
316
+ }
317
+ update(tableName) {
318
+ return new UpdateBuilder(this.db, tableName);
319
+ }
320
+ delete(tableName) {
321
+ return new DeleteBuilder(this.db, tableName);
322
+ }
323
+ execute(sql, params) {
324
+ return this.db.execute(sql, params);
325
+ }
326
+ }
327
+ function createORM(db) {
328
+ return new ORM(db);
329
+ }
330
+ }
331
+ };
332
+ var __webpack_module_cache__ = {};
333
+ function __webpack_require__(moduleId) {
334
+ var cachedModule = __webpack_module_cache__[moduleId];
335
+ if (void 0 !== cachedModule) return cachedModule.exports;
336
+ var module = __webpack_module_cache__[moduleId] = {
337
+ exports: {}
338
+ };
339
+ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
340
+ return module.exports;
341
+ }
5
342
  (()=>{
6
- // getDefaultExport function for compatibility with non-ESM modules
7
- __webpack_require__.n = function(module) {
8
- var getter = module && module.__esModule ? function() {
9
- return module['default'];
10
- } : function() {
11
- return module;
12
- };
343
+ __webpack_require__.n = (module)=>{
344
+ var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
13
345
  __webpack_require__.d(getter, {
14
346
  a: getter
15
347
  });
16
348
  return getter;
17
349
  };
18
350
  })();
19
- // webpack/runtime/define_property_getters
20
351
  (()=>{
21
- __webpack_require__.d = function(exports1, definition) {
352
+ __webpack_require__.d = (exports1, definition)=>{
22
353
  for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
23
354
  enumerable: true,
24
355
  get: definition[key]
25
356
  });
26
357
  };
27
358
  })();
28
- // webpack/runtime/has_own_property
29
359
  (()=>{
30
- __webpack_require__.o = function(obj, prop) {
31
- return Object.prototype.hasOwnProperty.call(obj, prop);
32
- };
360
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
33
361
  })();
34
- // webpack/runtime/make_namespace_object
35
362
  (()=>{
36
- // define __esModule on exports
37
- __webpack_require__.r = function(exports1) {
363
+ __webpack_require__.r = (exports1)=>{
38
364
  if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
39
365
  value: 'Module'
40
366
  });
@@ -43,117 +369,144 @@ var __webpack_require__ = {};
43
369
  });
44
370
  };
45
371
  })();
46
- /************************************************************************/ var __webpack_exports__ = {};
47
- // ESM COMPAT FLAG
48
- __webpack_require__.r(__webpack_exports__);
49
- // EXPORTS
50
- __webpack_require__.d(__webpack_exports__, {
51
- fragment: ()=>/* reexport */ fragment,
52
- HTTPClient: ()=>/* reexport */ HTTPClient,
53
- default: ()=>/* reexport */ odblite,
54
- identifier: ()=>/* binding */ src_identifier,
55
- ODBLiteAdapter: ()=>/* reexport */ ODBLiteAdapter,
56
- BunSQLiteAdapter: ()=>/* reexport */ BunSQLiteAdapter,
57
- raw: ()=>/* binding */ src_raw,
58
- insertValues: ()=>/* binding */ src_insertValues,
59
- sql: ()=>/* reexport */ sql_parser_sql,
60
- where: ()=>/* binding */ src_where,
61
- DatabaseManager: ()=>/* reexport */ DatabaseManager,
62
- LibSQLAdapter: ()=>/* reexport */ LibSQLAdapter,
63
- updateSet: ()=>/* binding */ src_updateSet,
64
- ODBLiteClient: ()=>/* reexport */ ODBLiteClient,
65
- ODBLiteTransaction: ()=>/* reexport */ ODBLiteTransaction,
66
- join: ()=>/* binding */ src_join,
67
- ODBLiteError: ()=>/* reexport */ ODBLiteError,
68
- parseSQL: ()=>/* reexport */ parseSQL,
69
- ConnectionError: ()=>/* reexport */ ConnectionError,
70
- SQLParser: ()=>/* reexport */ sql_parser_SQLParser,
71
- SimpleTransaction: ()=>/* reexport */ SimpleTransaction,
72
- odblite: ()=>/* reexport */ odblite,
73
- splitSQLStatements: ()=>/* reexport */ splitSQLStatements,
74
- QueryError: ()=>/* reexport */ types_QueryError,
75
- ServiceClient: ()=>/* reexport */ ServiceClient
76
- });
77
- // Core types for the ODBLite client
78
- // Error types
79
- class ODBLiteError extends Error {
80
- code;
81
- query;
82
- params;
83
- constructor(message, code, query, params){
84
- super(message), this.code = code, this.query = query, this.params = params;
85
- this.name = 'ODBLiteError';
86
- }
87
- }
88
- class ConnectionError extends ODBLiteError {
89
- originalError;
90
- constructor(message, originalError){
91
- super(message, 'CONNECTION_ERROR'), this.originalError = originalError;
92
- this.name = 'ConnectionError';
372
+ var __webpack_exports__ = {};
373
+ (()=>{
374
+ __webpack_require__.r(__webpack_exports__);
375
+ __webpack_require__.d(__webpack_exports__, {
376
+ insertValues: ()=>src_insertValues,
377
+ updateSet: ()=>src_updateSet,
378
+ gte: ()=>orm.gte,
379
+ ODBLiteClient: ()=>ODBLiteClient,
380
+ QueryError: ()=>types_QueryError,
381
+ sql: ()=>sql_parser_sql,
382
+ sqlFragment: ()=>sql_template_fragment,
383
+ ODBLiteError: ()=>ODBLiteError,
384
+ ORM: ()=>orm.ORM,
385
+ ConnectionError: ()=>ConnectionError,
386
+ join: ()=>src_join,
387
+ convertTemplateToQuery: ()=>convertTemplateToQuery,
388
+ HTTPClient: ()=>HTTPClient,
389
+ BunSQLiteAdapter: ()=>BunSQLiteAdapter,
390
+ SQLParser: ()=>sql_parser_SQLParser,
391
+ default: ()=>odblite,
392
+ gt: ()=>orm.gt,
393
+ eq: ()=>orm.eq,
394
+ identifier: ()=>src_identifier,
395
+ lte: ()=>orm.lte,
396
+ ne: ()=>orm.ne,
397
+ parseSQL: ()=>parseSQL,
398
+ splitSQLStatements: ()=>splitSQLStatements,
399
+ where: ()=>src_where,
400
+ LibSQLAdapter: ()=>LibSQLAdapter,
401
+ lt: ()=>orm.lt,
402
+ fragment: ()=>fragment,
403
+ isNull: ()=>orm.isNull,
404
+ DatabaseManager: ()=>DatabaseManager,
405
+ or: ()=>orm.or,
406
+ ODBLiteTransaction: ()=>ODBLiteTransaction,
407
+ ServiceClient: ()=>ServiceClient,
408
+ and: ()=>orm.and,
409
+ odblite: ()=>odblite,
410
+ rawSQL: ()=>sql_template_raw,
411
+ set: ()=>set,
412
+ sqlJoin: ()=>sql_template_join,
413
+ createORM: ()=>orm.createORM,
414
+ empty: ()=>empty,
415
+ sqlTemplate: ()=>sql_template_sql,
416
+ SimpleTransaction: ()=>SimpleTransaction,
417
+ inArray: ()=>orm.inArray,
418
+ sqlWhere: ()=>sql_template_where,
419
+ ODBLiteAdapter: ()=>ODBLiteAdapter,
420
+ isNotNull: ()=>orm.isNotNull,
421
+ like: ()=>orm.like,
422
+ raw: ()=>src_raw
423
+ });
424
+ class ODBLiteError extends Error {
425
+ code;
426
+ query;
427
+ params;
428
+ constructor(message, code, query, params){
429
+ super(message), this.code = code, this.query = query, this.params = params;
430
+ this.name = 'ODBLiteError';
431
+ }
93
432
  }
94
- }
95
- class types_QueryError extends ODBLiteError {
96
- originalError;
97
- constructor(message, query, params, originalError){
98
- super(message, 'QUERY_ERROR', query, params), this.originalError = originalError;
99
- this.name = 'QueryError';
433
+ class ConnectionError extends ODBLiteError {
434
+ originalError;
435
+ constructor(message, originalError){
436
+ super(message, 'CONNECTION_ERROR'), this.originalError = originalError;
437
+ this.name = 'ConnectionError';
438
+ }
100
439
  }
101
- }
102
- /**
103
- * HTTP client for communicating with ODBLite service
104
- */ class HTTPClient {
105
- config;
106
- constructor(config){
107
- this.config = {
108
- timeout: 30000,
109
- retries: 3,
110
- ...config
111
- };
112
- // Ensure baseUrl doesn't end with slash
113
- if ('string' == typeof this.config.baseUrl) this.config.baseUrl = this.config.baseUrl.replace(/\/$/, '');
440
+ class types_QueryError extends ODBLiteError {
441
+ originalError;
442
+ constructor(message, query, params, originalError){
443
+ super(message, 'QUERY_ERROR', query, params), this.originalError = originalError;
444
+ this.name = 'QueryError';
445
+ }
114
446
  }
115
- /**
116
- * Execute a query against the ODBLite service
117
- */ async query(sql, params = []) {
118
- if (!this.config.databaseId) throw new ConnectionError('No database ID configured. Use setDatabase() first.');
119
- const url = `${this.config.baseUrl}/query/${this.config.databaseId}`;
120
- const body = {
121
- sql,
122
- params
123
- };
124
- try {
125
- const response = await this.makeRequest(url, {
126
- method: 'POST',
127
- headers: {
128
- 'Content-Type': 'application/json',
129
- Authorization: `Bearer ${this.config.apiKey}`
130
- },
131
- body: JSON.stringify(body)
132
- });
133
- const data = await response.json();
134
- if (!data.success) throw new types_QueryError(data.error || 'Query failed', sql, params);
135
- // Handle nested data structure: { success: true, data: { rows: [...] } }
136
- let rows = [];
137
- if (data.data && 'object' == typeof data.data && 'rows' in data.data) rows = data.data.rows;
138
- else if (Array.isArray(data.data)) rows = data.data;
139
- else if (Array.isArray(data.rows)) rows = data.rows;
140
- return {
141
- rows: rows,
142
- rowsAffected: data.rowsAffected || data.data?.rowsAffected || 0,
143
- executionTime: data.executionTime || data.data?.executionTime || 0,
144
- databaseName: data.databaseName || data.data?.databaseName
447
+ class HTTPClient {
448
+ config;
449
+ constructor(config){
450
+ this.config = {
451
+ timeout: 30000,
452
+ retries: 3,
453
+ ...config
145
454
  };
146
- } catch (error) {
147
- if (error instanceof types_QueryError || error instanceof ConnectionError) throw error;
148
- throw new types_QueryError(error instanceof Error ? error.message : 'Unknown error occurred', sql, params, error instanceof Error ? error : void 0);
455
+ if ('string' == typeof this.config.baseUrl) this.config.baseUrl = this.config.baseUrl.replace(/\/$/, '');
149
456
  }
150
- }
151
- /**
152
- * Check database health
153
- */ async ping() {
154
- if (!this.config.databaseId) return false;
155
- try {
156
- const url = `${this.config.baseUrl}/api/db/${this.config.databaseId}/health`;
457
+ async query(sql, params = []) {
458
+ if (!this.config.databaseId) throw new ConnectionError('No database ID configured. Use setDatabase() first.');
459
+ const url = `${this.config.baseUrl}/query/${this.config.databaseId}`;
460
+ const body = {
461
+ sql,
462
+ params
463
+ };
464
+ try {
465
+ const response = await this.makeRequest(url, {
466
+ method: 'POST',
467
+ headers: {
468
+ 'Content-Type': 'application/json',
469
+ Authorization: `Bearer ${this.config.apiKey}`
470
+ },
471
+ body: JSON.stringify(body)
472
+ });
473
+ const data = await response.json();
474
+ if (!data.success) throw new types_QueryError(data.error || 'Query failed', sql, params);
475
+ let rows = [];
476
+ if (data.data && 'object' == typeof data.data && 'rows' in data.data) rows = data.data.rows;
477
+ else if (Array.isArray(data.data)) rows = data.data;
478
+ else if (Array.isArray(data.rows)) rows = data.rows;
479
+ return {
480
+ rows: rows,
481
+ rowsAffected: data.rowsAffected || data.data?.rowsAffected || 0,
482
+ lastInsertRowid: data.lastInsertRowid || data.data?.lastInsertRowid,
483
+ executionTime: data.executionTime || data.data?.executionTime || 0,
484
+ databaseName: data.databaseName || data.data?.databaseName
485
+ };
486
+ } catch (error) {
487
+ if (error instanceof types_QueryError || error instanceof ConnectionError) throw error;
488
+ throw new types_QueryError(error instanceof Error ? error.message : 'Unknown error occurred', sql, params, error instanceof Error ? error : void 0);
489
+ }
490
+ }
491
+ async ping() {
492
+ if (!this.config.databaseId) return false;
493
+ try {
494
+ const url = `${this.config.baseUrl}/api/db/${this.config.databaseId}/health`;
495
+ const response = await this.makeRequest(url, {
496
+ method: 'GET',
497
+ headers: {
498
+ Authorization: `Bearer ${this.config.apiKey}`
499
+ }
500
+ });
501
+ const data = await response.json();
502
+ return 'healthy' === data.status;
503
+ } catch {
504
+ return false;
505
+ }
506
+ }
507
+ async getDatabaseInfo() {
508
+ if (!this.config.databaseId) throw new ConnectionError('No database ID configured');
509
+ const url = `${this.config.baseUrl}/query/${this.config.databaseId}`;
157
510
  const response = await this.makeRequest(url, {
158
511
  method: 'GET',
159
512
  headers: {
@@ -161,1390 +514,1233 @@ class types_QueryError extends ODBLiteError {
161
514
  }
162
515
  });
163
516
  const data = await response.json();
164
- return 'healthy' === data.status;
165
- } catch {
166
- return false;
517
+ if (!data.success) throw new ConnectionError(data.error || 'Failed to get database info');
518
+ return data;
167
519
  }
168
- }
169
- /**
170
- * Get database information
171
- */ async getDatabaseInfo() {
172
- if (!this.config.databaseId) throw new ConnectionError('No database ID configured');
173
- const url = `${this.config.baseUrl}/query/${this.config.databaseId}`;
174
- const response = await this.makeRequest(url, {
175
- method: 'GET',
176
- headers: {
177
- Authorization: `Bearer ${this.config.apiKey}`
520
+ setDatabase(databaseId) {
521
+ this.config.databaseId = databaseId;
522
+ }
523
+ async makeRequest(url, options) {
524
+ let lastError;
525
+ for(let attempt = 1; attempt <= (this.config.retries || 3); attempt++)try {
526
+ const controller = new AbortController();
527
+ const timeoutId = setTimeout(()=>controller.abort(), this.config.timeout);
528
+ const response = await fetch(url, {
529
+ ...options,
530
+ signal: controller.signal
531
+ });
532
+ clearTimeout(timeoutId);
533
+ if (!response.ok) {
534
+ const errorText = await response.text();
535
+ let errorData;
536
+ try {
537
+ errorData = JSON.parse(errorText);
538
+ } catch {
539
+ errorData = {
540
+ error: errorText
541
+ };
542
+ }
543
+ throw new ConnectionError(`HTTP ${response.status}: ${errorData.error || response.statusText}`);
544
+ }
545
+ return response;
546
+ } catch (error) {
547
+ lastError = error instanceof Error ? error : new Error('Unknown error');
548
+ if (error instanceof ConnectionError && error.message.includes('HTTP 4')) throw error;
549
+ if (attempt < (this.config.retries || 3)) {
550
+ const delay = Math.min(1000 * 2 ** (attempt - 1), 10000);
551
+ await new Promise((resolve)=>setTimeout(resolve, delay));
552
+ }
178
553
  }
179
- });
180
- const data = await response.json();
181
- if (!data.success) throw new ConnectionError(data.error || 'Failed to get database info');
182
- return data;
183
- }
184
- /**
185
- * Set the database ID for subsequent queries
186
- */ setDatabase(databaseId) {
187
- this.config.databaseId = databaseId;
188
- }
189
- /**
190
- * Make HTTP request with retry logic
191
- */ async makeRequest(url, options) {
192
- let lastError;
193
- for(let attempt = 1; attempt <= (this.config.retries || 3); attempt++)try {
194
- const controller = new AbortController();
195
- const timeoutId = setTimeout(()=>controller.abort(), this.config.timeout);
196
- const response = await fetch(url, {
197
- ...options,
198
- signal: controller.signal
554
+ throw new ConnectionError(`Failed after ${this.config.retries} attempts: ${lastError?.message}`, lastError);
555
+ }
556
+ configure(updates) {
557
+ return new HTTPClient({
558
+ ...this.config,
559
+ ...updates
199
560
  });
200
- clearTimeout(timeoutId);
201
- if (!response.ok) {
202
- const errorText = await response.text();
203
- let errorData;
204
- try {
205
- errorData = JSON.parse(errorText);
206
- } catch {
207
- errorData = {
208
- error: errorText
561
+ }
562
+ getConfig() {
563
+ return {
564
+ ...this.config
565
+ };
566
+ }
567
+ }
568
+ class sql_parser_SQLParser {
569
+ static parse(sql, values) {
570
+ if (Array.isArray(sql) && ('raw' in sql || 'string' == typeof sql[0] && void 0 !== values)) return this.parseTemplateString(sql, values || []);
571
+ return this.parseContextualInput(sql, values);
572
+ }
573
+ static parseContextualInput(input, values, context) {
574
+ if (Array.isArray(input)) {
575
+ if (input.length > 0 && input[0] && 'object' == typeof input[0] && input[0].constructor === Object) {
576
+ const insertResult = this.insertValues(input);
577
+ return {
578
+ sql: insertResult.text,
579
+ params: insertResult.values
209
580
  };
210
581
  }
211
- throw new ConnectionError(`HTTP ${response.status}: ${errorData.error || response.statusText}`);
212
- }
213
- return response;
214
- } catch (error) {
215
- lastError = error instanceof Error ? error : new Error('Unknown error');
216
- // Don't retry on client errors (4xx)
217
- if (error instanceof ConnectionError && error.message.includes('HTTP 4')) throw error;
218
- // Wait before retry (exponential backoff)
219
- if (attempt < (this.config.retries || 3)) {
220
- const delay = Math.min(1000 * 2 ** (attempt - 1), 10000);
221
- await new Promise((resolve)=>setTimeout(resolve, delay));
582
+ const placeholders = input.map(()=>'?').join(', ');
583
+ return {
584
+ sql: `(${placeholders})`,
585
+ params: input.map((v)=>this.convertValue(v))
586
+ };
222
587
  }
223
- }
224
- throw new ConnectionError(`Failed after ${this.config.retries} attempts: ${lastError?.message}`, lastError);
225
- }
226
- /**
227
- * Create a new HTTPClient with updated config
228
- */ configure(updates) {
229
- return new HTTPClient({
230
- ...this.config,
231
- ...updates
232
- });
233
- }
234
- /**
235
- * Get current configuration
236
- */ getConfig() {
237
- return {
238
- ...this.config
239
- };
240
- }
241
- }
242
- /**
243
- * SQL template string parser that converts postgres.js-style template strings
244
- * into LibSQL-compatible parameterized queries
245
- */ class sql_parser_SQLParser {
246
- /**
247
- * Parse input that can be template strings, objects, or arrays
248
- * Context-aware like postgres.js
249
- */ static parse(sql, values) {
250
- // Handle template string arrays (have the raw property or look like template strings)
251
- if (Array.isArray(sql) && ('raw' in sql || 'string' == typeof sql[0] && void 0 !== values)) return this.parseTemplateString(sql, values || []);
252
- // Handle direct object/array inputs (context detection)
253
- return this.parseContextualInput(sql, values);
254
- }
255
- /**
256
- * Parse contextual input (objects, arrays, etc.)
257
- * Uses heuristics to detect the intended context
258
- */ static parseContextualInput(input, values, context) {
259
- if (Array.isArray(input)) {
260
- // Check if this is an array of objects (for INSERT VALUES)
261
- if (input.length > 0 && input[0] && 'object' == typeof input[0] && input[0].constructor === Object) {
588
+ if (input && 'object' == typeof input && input.constructor === Object) {
589
+ const entries = Object.entries(input).filter(([, value])=>void 0 !== value);
590
+ if (0 === entries.length) return {
591
+ sql: '',
592
+ params: []
593
+ };
594
+ const hasNullValues = entries.some(([, value])=>null === value);
595
+ const hasArrayValues = entries.some(([, value])=>Array.isArray(value));
596
+ const hasComplexValues = entries.some(([, value])=>null !== value && 'object' == typeof value && !Array.isArray(value));
597
+ if (hasNullValues || hasArrayValues || hasComplexValues) {
598
+ const whereResult = this.where(input);
599
+ return {
600
+ sql: whereResult.text,
601
+ params: whereResult.values
602
+ };
603
+ }
604
+ if (entries.length <= 3 && !Array.isArray(input)) return this.buildSetClause(input);
262
605
  const insertResult = this.insertValues(input);
263
606
  return {
264
607
  sql: insertResult.text,
265
608
  params: insertResult.values
266
609
  };
267
610
  }
268
- // Array of primitives - assume it's for IN clause
269
- const placeholders = input.map(()=>'?').join(', ');
270
611
  return {
271
- sql: `(${placeholders})`,
272
- params: input.map((v)=>this.convertValue(v))
612
+ sql: '?',
613
+ params: [
614
+ this.convertValue(input)
615
+ ]
273
616
  };
274
617
  }
275
- if (input && 'object' == typeof input && input.constructor === Object) {
276
- // Plain object - try to detect context based on structure and usage patterns
277
- const entries = Object.entries(input).filter(([, value])=>void 0 !== value);
618
+ static buildSetClause(data) {
619
+ const entries = Object.entries(data).filter(([, value])=>void 0 !== value);
278
620
  if (0 === entries.length) return {
279
621
  sql: '',
280
622
  params: []
281
623
  };
282
- // Analyze the object structure to determine intent
283
- const hasNullValues = entries.some(([, value])=>null === value);
284
- const hasArrayValues = entries.some(([, value])=>Array.isArray(value));
285
- const hasComplexValues = entries.some(([, value])=>null !== value && 'object' == typeof value && !Array.isArray(value));
286
- // Strong indicators for WHERE clauses:
287
- // - null values (for IS NULL checks)
288
- // - array values (for IN clauses)
289
- // - complex nested objects
290
- if (hasNullValues || hasArrayValues || hasComplexValues) {
291
- const whereResult = this.where(input);
292
- return {
293
- sql: whereResult.text,
294
- params: whereResult.values
295
- };
624
+ const setClauses = entries.map(([key])=>`${this.escapeIdentifier(key)} = ?`).join(', ');
625
+ const values = entries.map(([, value])=>this.convertValue(value));
626
+ return {
627
+ sql: setClauses,
628
+ params: values
629
+ };
630
+ }
631
+ static parseTemplateString(sql, values) {
632
+ const fragments = [
633
+ ...sql
634
+ ];
635
+ const params = [];
636
+ let query = '';
637
+ for(let i = 0; i < fragments.length; i++){
638
+ query += fragments[i];
639
+ if (i < values.length) {
640
+ const value = values[i];
641
+ if (Array.isArray(value)) {
642
+ const placeholders = value.map(()=>"?").join(', ');
643
+ query += `(${placeholders})`;
644
+ params.push(...value.map((v)=>this.convertValue(v)));
645
+ } else if (value && 'object' == typeof value && value.constructor === Object) {
646
+ const contextResult = this.parseContextualInput(value);
647
+ query += contextResult.sql;
648
+ params.push(...contextResult.params);
649
+ } else if ('string' == typeof value && value.startsWith('__RAW__')) query += value.slice(7);
650
+ else {
651
+ query += '?';
652
+ params.push(this.convertValue(value));
653
+ }
654
+ }
296
655
  }
297
- // For simple objects with primitive values, we need to guess context
298
- // This is inherently ambiguous - could be SET or VALUES
299
- // We'll default to a flexible format that works for both
300
- // If single object, more likely to be SET clause
301
- if (entries.length <= 3 && !Array.isArray(input)) // Return SET format by default
302
- return this.buildSetClause(input);
303
- // For larger objects or arrays of objects, likely INSERT VALUES
304
- const insertResult = this.insertValues(input);
305
656
  return {
306
- sql: insertResult.text,
307
- params: insertResult.values
657
+ sql: query.trim(),
658
+ params
308
659
  };
309
660
  }
310
- // Fallback for other types
311
- return {
312
- sql: '?',
313
- params: [
314
- this.convertValue(input)
315
- ]
316
- };
317
- }
318
- /**
319
- * Build a SET clause for UPDATE statements
320
- */ static buildSetClause(data) {
321
- const entries = Object.entries(data).filter(([, value])=>void 0 !== value);
322
- if (0 === entries.length) return {
323
- sql: '',
324
- params: []
325
- };
326
- const setClauses = entries.map(([key])=>`${this.escapeIdentifier(key)} = ?`).join(', ');
327
- const values = entries.map(([, value])=>this.convertValue(value));
328
- return {
329
- sql: setClauses,
330
- params: values
331
- };
332
- }
333
- /**
334
- * Parse template string SQL into LibSQL format
335
- */ static parseTemplateString(sql, values) {
336
- const fragments = [
337
- ...sql
338
- ];
339
- const params = [];
340
- let query = '';
341
- for(let i = 0; i < fragments.length; i++){
342
- query += fragments[i];
343
- if (i < values.length) {
344
- const value = values[i];
345
- // Handle different value types using context detection
661
+ static raw(text) {
662
+ return `__RAW__${text}`;
663
+ }
664
+ static identifier(name) {
665
+ return this.escapeIdentifier(name);
666
+ }
667
+ static escapeIdentifier(identifier) {
668
+ return `"${identifier.replace(/"/g, '""')}"`;
669
+ }
670
+ static convertValue(value) {
671
+ if (null == value) return null;
672
+ if (value instanceof Date) return value.toISOString();
673
+ if (value instanceof Buffer) return new Uint8Array(value);
674
+ if ('boolean' == typeof value) return value ? 1 : 0;
675
+ if ('bigint' == typeof value) return value.toString();
676
+ if ('object' == typeof value) return JSON.stringify(value);
677
+ return value;
678
+ }
679
+ static fragment(sql, ...values) {
680
+ const parsed = this.parse(sql, values);
681
+ return {
682
+ text: parsed.sql,
683
+ values: parsed.params
684
+ };
685
+ }
686
+ static join(fragments, separator = ' ') {
687
+ const text = fragments.map((f)=>f.text).join(separator);
688
+ const values = fragments.flatMap((f)=>f.values);
689
+ return {
690
+ text,
691
+ values
692
+ };
693
+ }
694
+ static where(conditions) {
695
+ const entries = Object.entries(conditions).filter(([, value])=>void 0 !== value);
696
+ if (0 === entries.length) return {
697
+ text: '',
698
+ values: []
699
+ };
700
+ const clauses = entries.map(([key, value])=>{
701
+ if (null === value) return `${this.escapeIdentifier(key)} IS NULL`;
346
702
  if (Array.isArray(value)) {
347
- // Handle IN clauses: sql`SELECT * FROM users WHERE id IN ${[1, 2, 3]}`
348
- const placeholders = value.map(()=>"?").join(', ');
349
- query += `(${placeholders})`;
350
- params.push(...value.map((v)=>this.convertValue(v)));
351
- } else if (value && 'object' == typeof value && value.constructor === Object) {
352
- // Use context detection for objects
353
- const contextResult = this.parseContextualInput(value);
354
- query += contextResult.sql;
355
- params.push(...contextResult.params);
356
- } else if ('string' == typeof value && value.startsWith('__RAW__')) // Handle raw SQL: sql`SELECT * FROM ${raw('users')}`
357
- query += value.slice(7); // Remove __RAW__ prefix
358
- else {
359
- // Regular parameter
360
- query += '?';
361
- params.push(this.convertValue(value));
703
+ const placeholders = value.map(()=>'?').join(', ');
704
+ return `${this.escapeIdentifier(key)} IN (${placeholders})`;
362
705
  }
363
- }
706
+ return `${this.escapeIdentifier(key)} = ?`;
707
+ });
708
+ const values = entries.flatMap(([, value])=>{
709
+ if (null === value) return [];
710
+ if (Array.isArray(value)) return value.map((v)=>this.convertValue(v));
711
+ return [
712
+ this.convertValue(value)
713
+ ];
714
+ });
715
+ return {
716
+ text: clauses.join(' AND '),
717
+ values
718
+ };
364
719
  }
365
- return {
366
- sql: query.trim(),
367
- params
368
- };
369
- }
370
- /**
371
- * Create a raw SQL fragment (not parameterized)
372
- */ static raw(text) {
373
- return `__RAW__${text}`;
374
- }
375
- /**
376
- * Create an identifier (table name, column name, etc.)
377
- */ static identifier(name) {
378
- return this.escapeIdentifier(name);
379
- }
380
- /**
381
- * Escape SQL identifiers (table names, column names)
382
- */ static escapeIdentifier(identifier) {
383
- // SQLite uses double quotes for identifiers
384
- return `"${identifier.replace(/"/g, '""')}"`;
385
- }
386
- /**
387
- * Convert JavaScript values to LibSQL-compatible values
388
- */ static convertValue(value) {
389
- if (null == value) return null;
390
- if (value instanceof Date) // Convert Date to ISO string for SQLite
391
- return value.toISOString();
392
- if (value instanceof Buffer) // Convert Buffer to Uint8Array for LibSQL
393
- return new Uint8Array(value);
394
- if ('boolean' == typeof value) // SQLite uses 0/1 for booleans
395
- return value ? 1 : 0;
396
- if ('bigint' == typeof value) // Convert BigInt to string to avoid precision loss
397
- return value.toString();
398
- if ('object' == typeof value) // Serialize objects as JSON
399
- return JSON.stringify(value);
400
- return value;
401
- }
402
- /**
403
- * Create a SQL fragment for building complex queries
404
- */ static fragment(sql, ...values) {
405
- const parsed = this.parse(sql, values);
406
- return {
407
- text: parsed.sql,
408
- values: parsed.params
409
- };
410
- }
411
- /**
412
- * Join multiple SQL fragments
413
- */ static join(fragments, separator = ' ') {
414
- const text = fragments.map((f)=>f.text).join(separator);
415
- const values = fragments.flatMap((f)=>f.values);
416
- return {
417
- text,
418
- values
419
- };
420
- }
421
- /**
422
- * Helper for building WHERE clauses from objects
423
- */ static where(conditions) {
424
- const entries = Object.entries(conditions).filter(([, value])=>void 0 !== value);
425
- if (0 === entries.length) return {
426
- text: '',
427
- values: []
428
- };
429
- const clauses = entries.map(([key, value])=>{
430
- if (null === value) return `${this.escapeIdentifier(key)} IS NULL`;
431
- if (Array.isArray(value)) {
432
- const placeholders = value.map(()=>'?').join(', ');
433
- return `${this.escapeIdentifier(key)} IN (${placeholders})`;
434
- }
435
- return `${this.escapeIdentifier(key)} = ?`;
436
- });
437
- const values = entries.flatMap(([, value])=>{
438
- if (null === value) return [];
439
- if (Array.isArray(value)) return value.map((v)=>this.convertValue(v));
440
- return [
441
- this.convertValue(value)
720
+ static insertValues(data) {
721
+ const records = Array.isArray(data) ? data : [
722
+ data
442
723
  ];
443
- });
444
- return {
445
- text: clauses.join(' AND '),
446
- values
447
- };
448
- }
449
- /**
450
- * Helper for building INSERT VALUES from objects
451
- */ static insertValues(data) {
452
- const records = Array.isArray(data) ? data : [
453
- data
454
- ];
455
- if (0 === records.length) throw new Error('No data provided for insert');
456
- const keys = Object.keys(records[0]);
457
- const columns = keys.map((key)=>this.escapeIdentifier(key)).join(', ');
458
- const valueClauses = records.map((record)=>{
459
- const placeholders = keys.map(()=>'?').join(', ');
460
- return `(${placeholders})`;
461
- }).join(', ');
462
- const values = records.flatMap((record)=>keys.map((key)=>this.convertValue(record[key])));
463
- return {
464
- text: `(${columns}) VALUES ${valueClauses}`,
465
- values
466
- };
467
- }
468
- /**
469
- * Helper for building UPDATE SET clauses from objects
470
- */ static updateSet(data) {
471
- const entries = Object.entries(data).filter(([, value])=>void 0 !== value);
472
- if (0 === entries.length) throw new Error('No data provided for update');
473
- const setClauses = entries.map(([key])=>`${this.escapeIdentifier(key)} = ?`).join(', ');
474
- const values = entries.map(([, value])=>this.convertValue(value));
475
- return {
476
- text: setClauses,
477
- values
478
- };
479
- }
480
- }
481
- // Export convenience functions
482
- const sql_parser_sql = sql_parser_SQLParser.parse.bind(sql_parser_SQLParser);
483
- sql_parser_SQLParser.raw.bind(sql_parser_SQLParser);
484
- sql_parser_SQLParser.identifier.bind(sql_parser_SQLParser);
485
- const fragment = sql_parser_SQLParser.fragment.bind(sql_parser_SQLParser);
486
- sql_parser_SQLParser.join.bind(sql_parser_SQLParser);
487
- sql_parser_SQLParser.where.bind(sql_parser_SQLParser);
488
- sql_parser_SQLParser.insertValues.bind(sql_parser_SQLParser);
489
- sql_parser_SQLParser.updateSet.bind(sql_parser_SQLParser);
490
- /**
491
- * Transaction implementation for ODBLite
492
- * Note: SQLite transactions are simulated at the client level since ODBLite
493
- * operates on individual queries. This provides a familiar API but doesn't
494
- * provide true ACID guarantees across multiple HTTP requests.
495
- */ class ODBLiteTransaction {
496
- httpClient;
497
- isCommitted = false;
498
- isRolledBack = false;
499
- queries = [];
500
- constructor(httpClient){
501
- this.httpClient = httpClient;
502
- }
503
- /**
504
- * Execute a query within the transaction
505
- * For SQLite, we'll queue queries and execute them in batch on commit
506
- */ async sql(sql, ...values) {
507
- this.checkTransactionState();
508
- const parsed = sql_parser_SQLParser.parse(sql, values);
509
- // For read queries, execute immediately
510
- if (this.isReadQuery(parsed.sql)) return await this.httpClient.query(parsed.sql, parsed.params);
511
- // For write queries, queue them for batch execution
512
- this.queries.push(parsed);
513
- // Return a placeholder result for queued queries
514
- return {
515
- rows: [],
516
- rowsAffected: 0,
517
- executionTime: 0
518
- };
724
+ if (0 === records.length) throw new Error('No data provided for insert');
725
+ const keys = Object.keys(records[0]);
726
+ const columns = keys.map((key)=>this.escapeIdentifier(key)).join(', ');
727
+ const valueClauses = records.map((record)=>{
728
+ const placeholders = keys.map(()=>'?').join(', ');
729
+ return `(${placeholders})`;
730
+ }).join(', ');
731
+ const values = records.flatMap((record)=>keys.map((key)=>this.convertValue(record[key])));
732
+ return {
733
+ text: `(${columns}) VALUES ${valueClauses}`,
734
+ values
735
+ };
736
+ }
737
+ static updateSet(data) {
738
+ const entries = Object.entries(data).filter(([, value])=>void 0 !== value);
739
+ if (0 === entries.length) throw new Error('No data provided for update');
740
+ const setClauses = entries.map(([key])=>`${this.escapeIdentifier(key)} = ?`).join(', ');
741
+ const values = entries.map(([, value])=>this.convertValue(value));
742
+ return {
743
+ text: setClauses,
744
+ values
745
+ };
746
+ }
519
747
  }
520
- /**
521
- * Commit the transaction by executing all queued queries
522
- */ async commit() {
523
- this.checkTransactionState();
524
- try {
525
- // Execute BEGIN
526
- await this.httpClient.query('BEGIN');
527
- // Execute all queued queries
528
- for (const query of this.queries)await this.httpClient.query(query.sql, query.params);
529
- // Commit the transaction
530
- await this.httpClient.query('COMMIT');
531
- this.isCommitted = true;
532
- } catch (error) {
533
- // Rollback on any error
748
+ const sql_parser_sql = sql_parser_SQLParser.parse.bind(sql_parser_SQLParser);
749
+ sql_parser_SQLParser.raw.bind(sql_parser_SQLParser);
750
+ sql_parser_SQLParser.identifier.bind(sql_parser_SQLParser);
751
+ const fragment = sql_parser_SQLParser.fragment.bind(sql_parser_SQLParser);
752
+ sql_parser_SQLParser.join.bind(sql_parser_SQLParser);
753
+ sql_parser_SQLParser.where.bind(sql_parser_SQLParser);
754
+ sql_parser_SQLParser.insertValues.bind(sql_parser_SQLParser);
755
+ sql_parser_SQLParser.updateSet.bind(sql_parser_SQLParser);
756
+ class ODBLiteTransaction {
757
+ httpClient;
758
+ isCommitted = false;
759
+ isRolledBack = false;
760
+ queries = [];
761
+ constructor(httpClient){
762
+ this.httpClient = httpClient;
763
+ }
764
+ async sql(sql, ...values) {
765
+ this.checkTransactionState();
766
+ const parsed = sql_parser_SQLParser.parse(sql, values);
767
+ if (this.isReadQuery(parsed.sql)) return await this.httpClient.query(parsed.sql, parsed.params);
768
+ this.queries.push(parsed);
769
+ return {
770
+ rows: [],
771
+ rowsAffected: 0,
772
+ executionTime: 0
773
+ };
774
+ }
775
+ async commit() {
776
+ this.checkTransactionState();
534
777
  try {
535
- await this.httpClient.query('ROLLBACK');
536
- } catch (rollbackError) {
537
- // Ignore rollback errors
778
+ await this.httpClient.query('BEGIN');
779
+ for (const query of this.queries)await this.httpClient.query(query.sql, query.params);
780
+ await this.httpClient.query('COMMIT');
781
+ this.isCommitted = true;
782
+ } catch (error) {
783
+ try {
784
+ await this.httpClient.query('ROLLBACK');
785
+ } catch (rollbackError) {}
786
+ this.isRolledBack = true;
787
+ throw new types_QueryError(`Transaction failed: ${error instanceof Error ? error.message : 'Unknown error'}`, void 0, void 0, error instanceof Error ? error : void 0);
538
788
  }
539
- this.isRolledBack = true;
540
- throw new types_QueryError(`Transaction failed: ${error instanceof Error ? error.message : 'Unknown error'}`, void 0, void 0, error instanceof Error ? error : void 0);
541
789
  }
542
- }
543
- /**
544
- * Rollback the transaction
545
- */ async rollback() {
546
- this.checkTransactionState();
547
- try {
548
- // If we have any queries, we need to actually rollback
549
- if (this.queries.length > 0) await this.httpClient.query('ROLLBACK');
550
- } finally{
551
- this.isRolledBack = true;
790
+ async rollback() {
791
+ this.checkTransactionState();
792
+ try {
793
+ if (this.queries.length > 0) await this.httpClient.query('ROLLBACK');
794
+ } finally{
795
+ this.isRolledBack = true;
796
+ }
552
797
  }
553
- }
554
- /**
555
- * Check if transaction is still active
556
- */ checkTransactionState() {
557
- if (this.isCommitted) throw new types_QueryError('Transaction has already been committed');
558
- if (this.isRolledBack) throw new types_QueryError('Transaction has been rolled back');
559
- }
560
- /**
561
- * Determine if a query is a read operation
562
- */ isReadQuery(sql) {
563
- const trimmed = sql.trim().toUpperCase();
564
- return trimmed.startsWith('SELECT') || trimmed.startsWith('WITH') || trimmed.startsWith('EXPLAIN') || trimmed.startsWith('PRAGMA');
565
- }
566
- }
567
- /**
568
- * Create a simple transaction function that executes immediately
569
- * This is more suitable for HTTP-based databases where true transactions
570
- * across multiple requests are not practical
571
- */ function createSimpleTransaction(httpClient) {
572
- let isActive = true;
573
- // Create the callable transaction function with context awareness
574
- const txFunction = (sql, ...values)=>{
575
- if (!isActive) throw new types_QueryError('Transaction is no longer active');
576
- // Handle template string queries (returns Promise)
577
- if (Array.isArray(sql) && ('raw' in sql || 'string' == typeof sql[0] && values.length >= 0)) {
578
- const parsed = sql_parser_SQLParser.parse(sql, values);
579
- return httpClient.query(parsed.sql, parsed.params);
798
+ checkTransactionState() {
799
+ if (this.isCommitted) throw new types_QueryError('Transaction has already been committed');
800
+ if (this.isRolledBack) throw new types_QueryError('Transaction has been rolled back');
580
801
  }
581
- // Handle direct object/array inputs (returns SQLFragment for composing)
582
- const parsed = sql_parser_SQLParser.parse(sql, values);
583
- return {
584
- text: parsed.sql,
585
- values: parsed.params
586
- };
587
- };
588
- // Attach utility methods to the transaction function
589
- txFunction.raw = (text)=>sql_parser_SQLParser.raw(text);
590
- txFunction.identifier = (name)=>sql_parser_SQLParser.identifier(name);
591
- // Add execute method for compatibility
592
- txFunction.execute = async (sql, args)=>{
593
- if (!isActive) throw new types_QueryError('Transaction is no longer active');
594
- if ('string' == typeof sql) return await httpClient.query(sql, args || []);
595
- return await httpClient.query(sql.sql, sql.args || []);
596
- };
597
- // Add query method for compatibility
598
- txFunction.query = async (sql, params = [])=>{
599
- if (!isActive) throw new types_QueryError('Transaction is no longer active');
600
- return await httpClient.query(sql, params);
601
- };
602
- txFunction.commit = async ()=>{
603
- isActive = false;
604
- // No-op for simple transactions
605
- };
606
- txFunction.rollback = async ()=>{
607
- isActive = false;
608
- // No-op for simple transactions - individual queries are atomic
609
- };
610
- txFunction.savepoint = async (callback)=>{
611
- if (!isActive) throw new types_QueryError('Transaction is no longer active');
612
- // Create a nested transaction for the savepoint
613
- const savepointTx = createSimpleTransaction(httpClient);
614
- try {
615
- // Execute the callback with the savepoint transaction
616
- const result = await callback(savepointTx);
617
- // Commit the savepoint (no-op for simple transactions)
618
- await savepointTx.commit();
619
- return result;
620
- } catch (error) {
621
- // Rollback the savepoint on error
622
- await savepointTx.rollback();
623
- throw error;
802
+ isReadQuery(sql) {
803
+ const trimmed = sql.trim().toUpperCase();
804
+ return trimmed.startsWith('SELECT') || trimmed.startsWith('WITH') || trimmed.startsWith('EXPLAIN') || trimmed.startsWith('PRAGMA');
624
805
  }
625
- };
626
- return txFunction;
627
- }
628
- /**
629
- * Simple transaction implementation that executes immediately
630
- * This is more suitable for HTTP-based databases where true transactions
631
- * across multiple requests are not practical
632
- */ class SimpleTransaction {
633
- httpClient;
634
- isActive = true;
635
- constructor(httpClient){
636
- this.httpClient = httpClient;
637
- }
638
- async sql(sql, ...values) {
639
- if (!this.isActive) throw new types_QueryError('Transaction is no longer active');
640
- const parsed = sql_parser_SQLParser.parse(sql, values);
641
- return await this.httpClient.query(parsed.sql, parsed.params);
642
806
  }
643
- async commit() {
644
- this.isActive = false;
645
- // No-op for simple transactions
646
- }
647
- async rollback() {
648
- this.isActive = false;
649
- // No-op for simple transactions - individual queries are atomic
650
- }
651
- }
652
- /**
653
- * Main ODBLite client that provides postgres.js-like interface
654
- */ class ODBLiteClient {
655
- httpClient;
656
- config;
657
- sql;
658
- constructor(config){
659
- this.config = config;
660
- this.httpClient = new HTTPClient(config);
661
- // Create the callable sql function with attached utility methods
662
- const sqlFunction = (sql, ...values)=>{
663
- // Handle template string queries (returns Promise)
807
+ function createSimpleTransaction(httpClient) {
808
+ let isActive = true;
809
+ const txFunction = (sql, ...values)=>{
810
+ if (!isActive) throw new types_QueryError('Transaction is no longer active');
664
811
  if (Array.isArray(sql) && ('raw' in sql || 'string' == typeof sql[0] && values.length >= 0)) {
665
812
  const parsed = sql_parser_SQLParser.parse(sql, values);
666
- return this.httpClient.query(parsed.sql, parsed.params);
813
+ return httpClient.query(parsed.sql, parsed.params);
667
814
  }
668
- // Handle direct object/array inputs (returns SQLFragment for composing)
669
815
  const parsed = sql_parser_SQLParser.parse(sql, values);
670
816
  return {
671
817
  text: parsed.sql,
672
818
  values: parsed.params
673
819
  };
674
820
  };
675
- // Attach minimal utility methods to the function
676
- sqlFunction.raw = (text)=>sql_parser_SQLParser.raw(text);
677
- sqlFunction.identifier = (name)=>sql_parser_SQLParser.identifier(name);
678
- // Attach client methods to the function
679
- sqlFunction.query = async (sql, params = [])=>await this.httpClient.query(sql, params);
680
- // libsql-compatible execute method (for backward compatibility)
681
- sqlFunction.execute = async (sql, args)=>{
682
- if ('string' == typeof sql) return await this.httpClient.query(sql, args || []);
683
- return await this.httpClient.query(sql.sql, sql.args || []);
821
+ txFunction.raw = (text)=>sql_parser_SQLParser.raw(text);
822
+ txFunction.identifier = (name)=>sql_parser_SQLParser.identifier(name);
823
+ txFunction.execute = async (sql, args)=>{
824
+ if (!isActive) throw new types_QueryError('Transaction is no longer active');
825
+ if ('string' == typeof sql) return await httpClient.query(sql, args || []);
826
+ return await httpClient.query(sql.sql, sql.args || []);
684
827
  };
685
- // Enhanced begin method with callback support
686
- sqlFunction.begin = async (modeOrCallback, callback)=>{
687
- // Determine if this is callback-style or traditional
688
- if ('function' == typeof modeOrCallback) // begin(callback)
689
- return this.executeTransactionWithCallback(modeOrCallback);
690
- if ('string' == typeof modeOrCallback && callback) // begin(mode, callback)
691
- return this.executeTransactionWithCallback(callback, modeOrCallback);
692
- // begin() - traditional style
693
- return createSimpleTransaction(this.httpClient);
828
+ txFunction.query = async (sql, params = [])=>{
829
+ if (!isActive) throw new types_QueryError('Transaction is no longer active');
830
+ return await httpClient.query(sql, params);
831
+ };
832
+ txFunction.commit = async ()=>{
833
+ isActive = false;
694
834
  };
695
- sqlFunction.ping = async ()=>await this.httpClient.ping();
696
- sqlFunction.end = async ()=>{
697
- // No-op for HTTP-based client
835
+ txFunction.rollback = async ()=>{
836
+ isActive = false;
698
837
  };
699
- sqlFunction.setDatabase = (databaseId)=>{
838
+ txFunction.savepoint = async (callback)=>{
839
+ if (!isActive) throw new types_QueryError('Transaction is no longer active');
840
+ const savepointTx = createSimpleTransaction(httpClient);
841
+ try {
842
+ const result = await callback(savepointTx);
843
+ await savepointTx.commit();
844
+ return result;
845
+ } catch (error) {
846
+ await savepointTx.rollback();
847
+ throw error;
848
+ }
849
+ };
850
+ return txFunction;
851
+ }
852
+ class SimpleTransaction {
853
+ httpClient;
854
+ isActive = true;
855
+ constructor(httpClient){
856
+ this.httpClient = httpClient;
857
+ }
858
+ async sql(sql, ...values) {
859
+ if (!this.isActive) throw new types_QueryError('Transaction is no longer active');
860
+ const parsed = sql_parser_SQLParser.parse(sql, values);
861
+ return await this.httpClient.query(parsed.sql, parsed.params);
862
+ }
863
+ async commit() {
864
+ this.isActive = false;
865
+ }
866
+ async rollback() {
867
+ this.isActive = false;
868
+ }
869
+ }
870
+ class ODBLiteClient {
871
+ httpClient;
872
+ config;
873
+ sql;
874
+ constructor(config){
875
+ this.config = config;
876
+ this.httpClient = new HTTPClient(config);
877
+ const sqlFunction = (sql, ...values)=>{
878
+ if (Array.isArray(sql) && ('raw' in sql || 'string' == typeof sql[0] && values.length >= 0)) {
879
+ const parsed = sql_parser_SQLParser.parse(sql, values);
880
+ return this.httpClient.query(parsed.sql, parsed.params);
881
+ }
882
+ const parsed = sql_parser_SQLParser.parse(sql, values);
883
+ return {
884
+ text: parsed.sql,
885
+ values: parsed.params
886
+ };
887
+ };
888
+ sqlFunction.raw = (text)=>sql_parser_SQLParser.raw(text);
889
+ sqlFunction.identifier = (name)=>sql_parser_SQLParser.identifier(name);
890
+ sqlFunction.query = async (sql, params = [])=>await this.httpClient.query(sql, params);
891
+ sqlFunction.execute = async (sql, args)=>{
892
+ if ('string' == typeof sql) return await this.httpClient.query(sql, args || []);
893
+ return await this.httpClient.query(sql.sql, sql.args || []);
894
+ };
895
+ sqlFunction.begin = async (modeOrCallback, callback)=>{
896
+ if ('function' == typeof modeOrCallback) return this.executeTransactionWithCallback(modeOrCallback);
897
+ if ('string' == typeof modeOrCallback && callback) return this.executeTransactionWithCallback(callback, modeOrCallback);
898
+ return createSimpleTransaction(this.httpClient);
899
+ };
900
+ sqlFunction.ping = async ()=>await this.httpClient.ping();
901
+ sqlFunction.end = async ()=>{};
902
+ sqlFunction.setDatabase = (databaseId)=>{
903
+ this.httpClient.setDatabase(databaseId);
904
+ this.config.databaseId = databaseId;
905
+ return sqlFunction;
906
+ };
907
+ sqlFunction.getDatabaseInfo = async ()=>await this.httpClient.getDatabaseInfo();
908
+ sqlFunction.configure = (updates)=>{
909
+ const newConfig = {
910
+ ...this.config,
911
+ ...updates
912
+ };
913
+ return new ODBLiteClient(newConfig).sql;
914
+ };
915
+ this.sql = sqlFunction;
916
+ }
917
+ async executeTransactionWithCallback(callback, mode) {
918
+ const tx = createSimpleTransaction(this.httpClient);
919
+ try {
920
+ const result = await callback(tx);
921
+ await tx.commit();
922
+ return result;
923
+ } catch (error) {
924
+ await tx.rollback();
925
+ throw error;
926
+ }
927
+ }
928
+ async query(sql, params = []) {
929
+ return await this.httpClient.query(sql, params);
930
+ }
931
+ async begin() {
932
+ return createSimpleTransaction(this.httpClient);
933
+ }
934
+ async ping() {
935
+ return await this.httpClient.ping();
936
+ }
937
+ async end() {}
938
+ setDatabase(databaseId) {
700
939
  this.httpClient.setDatabase(databaseId);
701
940
  this.config.databaseId = databaseId;
702
- return sqlFunction;
703
- };
704
- sqlFunction.getDatabaseInfo = async ()=>await this.httpClient.getDatabaseInfo();
705
- sqlFunction.configure = (updates)=>{
941
+ return this;
942
+ }
943
+ async getDatabaseInfo() {
944
+ return await this.httpClient.getDatabaseInfo();
945
+ }
946
+ configure(updates) {
706
947
  const newConfig = {
707
948
  ...this.config,
708
949
  ...updates
709
950
  };
710
- return new ODBLiteClient(newConfig).sql;
711
- };
712
- this.sql = sqlFunction;
713
- }
714
- /**
715
- * Execute a transaction with callback (postgres.js style)
716
- */ async executeTransactionWithCallback(callback, mode) {
717
- const tx = createSimpleTransaction(this.httpClient);
718
- try {
719
- // Execute the callback with the transaction
720
- const result = await callback(tx);
721
- // Commit the transaction
722
- await tx.commit();
723
- return result;
724
- } catch (error) {
725
- // Rollback on any error
726
- await tx.rollback();
727
- throw error;
951
+ return new ODBLiteClient(newConfig);
728
952
  }
729
- }
730
- /**
731
- * Raw query method
732
- * Usage: client.query('SELECT * FROM users WHERE id = ?', [123])
733
- */ async query(sql, params = []) {
734
- return await this.httpClient.query(sql, params);
735
- }
736
- /**
737
- * Begin a transaction
738
- * Note: Uses simple transaction model suitable for HTTP-based access
739
- */ async begin() {
740
- return createSimpleTransaction(this.httpClient);
741
- }
742
- /**
743
- * Health check
744
- */ async ping() {
745
- return await this.httpClient.ping();
746
- }
747
- /**
748
- * Close connection (no-op for HTTP client)
749
- */ async end() {
750
- // No-op for HTTP-based client
751
- }
752
- /**
753
- * Set the database ID for queries
754
- */ setDatabase(databaseId) {
755
- this.httpClient.setDatabase(databaseId);
756
- this.config.databaseId = databaseId;
757
- return this;
758
- }
759
- /**
760
- * Get database information
761
- */ async getDatabaseInfo() {
762
- return await this.httpClient.getDatabaseInfo();
763
- }
764
- /**
765
- * Create a new client instance with updated configuration
766
- */ configure(updates) {
767
- const newConfig = {
768
- ...this.config,
769
- ...updates
770
- };
771
- return new ODBLiteClient(newConfig);
772
- }
773
- /**
774
- * Create raw SQL that won't be parameterized
775
- * Usage: sql`SELECT * FROM ${raw('users')}`
776
- */ static raw(text) {
777
- return sql_parser_SQLParser.raw(text);
778
- }
779
- /**
780
- * Escape identifier (table/column names)
781
- * Usage: sql`SELECT * FROM ${identifier('user-table')}`
782
- */ static identifier(name) {
783
- return sql_parser_SQLParser.identifier(name);
784
- }
785
- /**
786
- * Build WHERE clause from object
787
- * Usage: const whereClause = ODBLiteClient.where({ id: 1, name: 'John' });
788
- */ static where(conditions) {
789
- return sql_parser_SQLParser.where(conditions);
790
- }
791
- /**
792
- * Build INSERT VALUES from object(s)
793
- * Usage: const insertClause = ODBLiteClient.insertValues({ name: 'John', age: 30 });
794
- */ static insertValues(data) {
795
- return sql_parser_SQLParser.insertValues(data);
796
- }
797
- /**
798
- * Build UPDATE SET clause from object
799
- * Usage: const setClause = ODBLiteClient.updateSet({ name: 'John', age: 30 });
800
- */ static updateSet(data) {
801
- return sql_parser_SQLParser.updateSet(data);
802
- }
803
- /**
804
- * Join SQL fragments
805
- * Usage: const query = ODBLiteClient.join([baseQuery, whereClause], ' WHERE ');
806
- */ static join(fragments, separator = ' ') {
807
- return sql_parser_SQLParser.join(fragments, separator);
808
- }
809
- }
810
- function odblite(configOrBaseUrl, apiKey, databaseId) {
811
- const client = 'string' == typeof configOrBaseUrl ? new ODBLiteClient({
812
- baseUrl: configOrBaseUrl,
813
- apiKey: apiKey,
814
- databaseId
815
- }) : new ODBLiteClient(configOrBaseUrl);
816
- return client.sql;
817
- }
818
- // Export static utility functions
819
- ODBLiteClient.raw;
820
- ODBLiteClient.identifier;
821
- ODBLiteClient.where;
822
- ODBLiteClient.insertValues;
823
- ODBLiteClient.updateSet;
824
- ODBLiteClient.join;
825
- /**
826
- * Service Client - High-level client for managing tenant databases via ODB-Lite Tenant API
827
- *
828
- * This client provides automatic database provisioning and management for multi-tenant applications.
829
- * It handles:
830
- * - Automatic database creation on first use
831
- * - Database hash caching for performance
832
- * - Tenant API integration with ODB-Lite
833
- * - Query execution via ODB-Lite's query API
834
- *
835
- * @example
836
- * ```typescript
837
- * const service = new ServiceClient({
838
- * baseUrl: 'http://localhost:8671',
839
- * apiKey: 'odblite_tenant_key'
840
- * });
841
- *
842
- * // Automatically creates database if it doesn't exist
843
- * const dbHash = await service.ensureDatabaseForTenant('wallet', 'tenant-123');
844
- *
845
- * // Execute queries
846
- * const result = await service.query(dbHash, 'SELECT * FROM wallets', []);
847
- * ```
848
- */ /**
849
- * Service Client for managing tenant databases in ODB-Lite
850
- *
851
- * This is a higher-level client that sits on top of the base ODB client.
852
- * It provides automatic database provisioning and management for services
853
- * that need per-tenant database isolation.
854
- */ class ServiceClient {
855
- apiUrl;
856
- apiKey;
857
- databaseCache;
858
- constructor(config){
859
- this.apiUrl = config.baseUrl;
860
- this.apiKey = config.apiKey;
861
- this.databaseCache = new Map();
862
- }
863
- /**
864
- * Get or create a database for a tenant
865
- *
866
- * This is the main method used by services. It will:
867
- * 1. Check the cache for an existing database hash
868
- * 2. Query ODB-Lite to see if the database exists
869
- * 3. Create the database if it doesn't exist
870
- * 4. Cache and return the database hash
871
- *
872
- * @param prefix - Database name prefix (e.g., 'wallet', 'tracking')
873
- * @param tenantId - Tenant identifier
874
- * @returns Database hash for querying
875
- *
876
- * @example
877
- * ```typescript
878
- * const hash = await service.ensureDatabaseForTenant('wallet', 'tenant-123');
879
- * // Returns hash for database named 'wallet_tenant-123'
880
- * ```
881
- */ async ensureDatabaseForTenant(prefix, tenantId) {
882
- const cacheKey = `${prefix}_${tenantId}`;
883
- console.log(`📊 Ensuring database for ${cacheKey}`);
884
- // Check cache first
885
- const cached = this.databaseCache.get(cacheKey);
886
- if (cached) {
887
- console.log(`✅ Found cached database hash: ${cached}`);
888
- return cached;
889
- }
890
- try {
891
- // Check if database already exists
892
- console.log(`🔍 Checking if database exists: ${cacheKey}`);
893
- const existing = await this.getDatabaseByName(cacheKey);
894
- if (existing) {
895
- console.log(`✅ Database already exists: ${cacheKey} (${existing.hash})`);
896
- this.databaseCache.set(cacheKey, existing.hash);
897
- return existing.hash;
898
- }
899
- // Create new database
900
- console.log(`🆕 Creating new database: ${cacheKey}`);
901
- const nodes = await this.listNodes();
902
- console.log(`📡 Available nodes: ${nodes.length}`);
903
- if (0 === nodes.length) throw new Error('No available nodes to create database');
904
- // Use first healthy node
905
- const node = nodes.find((n)=>'healthy' === n.status) || nodes[0];
906
- if (!node) throw new Error('No available nodes to create database');
907
- console.log(`🎯 Using node: ${node.nodeId}`);
908
- const database = await this.createDatabase(cacheKey, node.nodeId);
909
- console.log(`✅ Database created successfully: ${database.hash}`);
910
- this.databaseCache.set(cacheKey, database.hash);
911
- return database.hash;
912
- } catch (error) {
913
- console.error(`❌ Error ensuring database for ${cacheKey}:`, error.message);
914
- throw error;
953
+ static raw(text) {
954
+ return sql_parser_SQLParser.raw(text);
955
+ }
956
+ static identifier(name) {
957
+ return sql_parser_SQLParser.identifier(name);
958
+ }
959
+ static where(conditions) {
960
+ return sql_parser_SQLParser.where(conditions);
961
+ }
962
+ static insertValues(data) {
963
+ return sql_parser_SQLParser.insertValues(data);
964
+ }
965
+ static updateSet(data) {
966
+ return sql_parser_SQLParser.updateSet(data);
967
+ }
968
+ static join(fragments, separator = ' ') {
969
+ return sql_parser_SQLParser.join(fragments, separator);
915
970
  }
916
971
  }
917
- /**
918
- * List all databases owned by this tenant
919
- *
920
- * Queries ODB-Lite's tenant API to get all databases accessible with the current API key.
921
- *
922
- * @returns Array of database objects
923
- */ async listDatabases() {
924
- const response = await fetch(`${this.apiUrl}/api/tenant/databases`, {
925
- headers: {
926
- Authorization: `Bearer ${this.apiKey}`
972
+ function odblite(configOrBaseUrl, apiKey, databaseId) {
973
+ const client = 'string' == typeof configOrBaseUrl ? new ODBLiteClient({
974
+ baseUrl: configOrBaseUrl,
975
+ apiKey: apiKey,
976
+ databaseId
977
+ }) : new ODBLiteClient(configOrBaseUrl);
978
+ return client.sql;
979
+ }
980
+ ODBLiteClient.raw;
981
+ ODBLiteClient.identifier;
982
+ ODBLiteClient.where;
983
+ ODBLiteClient.insertValues;
984
+ ODBLiteClient.updateSet;
985
+ ODBLiteClient.join;
986
+ class ServiceClient {
987
+ apiUrl;
988
+ apiKey;
989
+ databaseCache;
990
+ constructor(config){
991
+ this.apiUrl = config.baseUrl;
992
+ this.apiKey = config.apiKey;
993
+ this.databaseCache = new Map();
994
+ }
995
+ async ensureDatabaseForTenant(prefix, tenantId) {
996
+ const cacheKey = `${prefix}_${tenantId}`;
997
+ console.log(`📊 Ensuring database for ${cacheKey}`);
998
+ const cached = this.databaseCache.get(cacheKey);
999
+ if (cached) {
1000
+ console.log(`✅ Found cached database hash: ${cached}`);
1001
+ return cached;
927
1002
  }
928
- });
929
- const result = await response.json();
930
- if (!result.success) throw new Error(result.error || 'Failed to list databases');
931
- return result.databases;
932
- }
933
- /**
934
- * Create a new database
935
- *
936
- * @param name - Database name (should be unique)
937
- * @param nodeId - ID of the node to host the database (optional - server will select if null)
938
- * @returns Created database object with hash
939
- */ async createDatabase(name, nodeId) {
940
- const body = {
941
- name
942
- };
943
- if (nodeId) body.nodeId = nodeId;
944
- const response = await fetch(`${this.apiUrl}/api/tenant/databases`, {
945
- method: 'POST',
946
- headers: {
947
- Authorization: `Bearer ${this.apiKey}`,
948
- 'Content-Type': 'application/json'
949
- },
950
- body: JSON.stringify(body)
951
- });
952
- const result = await response.json();
953
- if (!result.success) throw new Error(result.error || 'Failed to create database');
954
- return result.database;
955
- }
956
- /**
957
- * Get database details by hash
958
- *
959
- * @param hash - Database hash
960
- * @returns Database object
961
- */ async getDatabase(hash) {
962
- const response = await fetch(`${this.apiUrl}/api/tenant/databases/${hash}`, {
963
- headers: {
964
- Authorization: `Bearer ${this.apiKey}`
1003
+ try {
1004
+ console.log(`🔍 Checking if database exists: ${cacheKey}`);
1005
+ const existing = await this.getDatabaseByName(cacheKey);
1006
+ if (existing) {
1007
+ console.log(`✅ Database already exists: ${cacheKey} (${existing.hash})`);
1008
+ this.databaseCache.set(cacheKey, existing.hash);
1009
+ return existing.hash;
1010
+ }
1011
+ console.log(`🆕 Creating new database: ${cacheKey}`);
1012
+ const nodes = await this.listNodes();
1013
+ console.log(`📡 Available nodes: ${nodes.length}`);
1014
+ if (0 === nodes.length) throw new Error('No available nodes to create database');
1015
+ const node = nodes.find((n)=>'healthy' === n.status) || nodes[0];
1016
+ if (!node) throw new Error('No available nodes to create database');
1017
+ console.log(`🎯 Using node: ${node.nodeId}`);
1018
+ const database = await this.createDatabase(cacheKey, node.nodeId);
1019
+ console.log(`✅ Database created successfully: ${database.hash}`);
1020
+ this.databaseCache.set(cacheKey, database.hash);
1021
+ return database.hash;
1022
+ } catch (error) {
1023
+ console.error(`❌ Error ensuring database for ${cacheKey}:`, error.message);
1024
+ throw error;
965
1025
  }
966
- });
967
- const result = await response.json();
968
- if (!result.success) throw new Error(result.error || 'Failed to get database');
969
- return result.database;
1026
+ }
1027
+ async listDatabases() {
1028
+ const response = await fetch(`${this.apiUrl}/api/tenant/databases`, {
1029
+ headers: {
1030
+ Authorization: `Bearer ${this.apiKey}`
1031
+ }
1032
+ });
1033
+ const result = await response.json();
1034
+ if (!result.success) throw new Error(result.error || 'Failed to list databases');
1035
+ return result.databases;
1036
+ }
1037
+ async createDatabase(name, nodeId) {
1038
+ const body = {
1039
+ name
1040
+ };
1041
+ if (nodeId) body.nodeId = nodeId;
1042
+ const response = await fetch(`${this.apiUrl}/api/tenant/databases`, {
1043
+ method: 'POST',
1044
+ headers: {
1045
+ Authorization: `Bearer ${this.apiKey}`,
1046
+ 'Content-Type': 'application/json'
1047
+ },
1048
+ body: JSON.stringify(body)
1049
+ });
1050
+ const result = await response.json();
1051
+ if (!result.success) throw new Error(result.error || 'Failed to create database');
1052
+ return result.database;
1053
+ }
1054
+ async getDatabase(hash) {
1055
+ const response = await fetch(`${this.apiUrl}/api/tenant/databases/${hash}`, {
1056
+ headers: {
1057
+ Authorization: `Bearer ${this.apiKey}`
1058
+ }
1059
+ });
1060
+ const result = await response.json();
1061
+ if (!result.success) throw new Error(result.error || 'Failed to get database');
1062
+ return result.database;
1063
+ }
1064
+ async getDatabaseByName(name) {
1065
+ const response = await fetch(`${this.apiUrl}/api/tenant/databases/by-name/${name}`, {
1066
+ headers: {
1067
+ Authorization: `Bearer ${this.apiKey}`
1068
+ }
1069
+ });
1070
+ if (404 === response.status) return null;
1071
+ const result = await response.json();
1072
+ if (!result.success) throw new Error(result.error || 'Failed to get database');
1073
+ return result.database;
1074
+ }
1075
+ async deleteDatabase(hash) {
1076
+ const response = await fetch(`${this.apiUrl}/api/tenant/databases/${hash}`, {
1077
+ method: 'DELETE',
1078
+ headers: {
1079
+ Authorization: `Bearer ${this.apiKey}`
1080
+ }
1081
+ });
1082
+ const result = await response.json();
1083
+ if (!result.success) throw new Error(result.error || 'Failed to delete database');
1084
+ for (const [key, cachedHash] of this.databaseCache.entries())if (cachedHash === hash) {
1085
+ this.databaseCache.delete(key);
1086
+ break;
1087
+ }
1088
+ }
1089
+ async listNodes() {
1090
+ const response = await fetch(`${this.apiUrl}/api/tenant/nodes`, {
1091
+ headers: {
1092
+ Authorization: `Bearer ${this.apiKey}`
1093
+ }
1094
+ });
1095
+ const result = await response.json();
1096
+ if (!result.success) throw new Error(result.error || 'Failed to list nodes');
1097
+ return result.nodes;
1098
+ }
1099
+ async query(databaseHash, sql, params = []) {
1100
+ const response = await fetch(`${this.apiUrl}/query/${databaseHash}`, {
1101
+ method: 'POST',
1102
+ headers: {
1103
+ 'Content-Type': 'application/json',
1104
+ Authorization: `Bearer ${this.apiKey}`
1105
+ },
1106
+ body: JSON.stringify({
1107
+ sql,
1108
+ params
1109
+ })
1110
+ });
1111
+ const result = await response.json();
1112
+ if (!result.success) throw new Error(result.error || 'Query failed');
1113
+ return result.data;
1114
+ }
1115
+ clearCache() {
1116
+ this.databaseCache.clear();
1117
+ }
1118
+ getCachedHash(prefix, tenantId) {
1119
+ const cacheKey = `${prefix}_${tenantId}`;
1120
+ return this.databaseCache.get(cacheKey);
1121
+ }
1122
+ setCachedHash(prefix, tenantId, hash) {
1123
+ const cacheKey = `${prefix}_${tenantId}`;
1124
+ this.databaseCache.set(cacheKey, hash);
1125
+ }
970
1126
  }
971
- /**
972
- * Get database details by name
973
- *
974
- * @param name - Database name
975
- * @returns Database object or null if not found
976
- */ async getDatabaseByName(name) {
977
- const response = await fetch(`${this.apiUrl}/api/tenant/databases/by-name/${name}`, {
978
- headers: {
979
- Authorization: `Bearer ${this.apiKey}`
1127
+ const external_bun_sqlite_namespaceObject = require("bun:sqlite");
1128
+ function convertTemplateToQuery(strings, values) {
1129
+ let sql = '';
1130
+ const args = [];
1131
+ for(let i = 0; i < strings.length; i++){
1132
+ sql += strings[i];
1133
+ if (i < values.length) {
1134
+ const value = values[i];
1135
+ if (isSqlFragment(value)) {
1136
+ sql += value.sql;
1137
+ args.push(...value.args);
1138
+ } else if (Array.isArray(value)) if (value.length > 0 && Array.isArray(value[0])) {
1139
+ const rowPlaceholders = value.map((row)=>`(${row.map(()=>'?').join(', ')})`).join(', ');
1140
+ sql += rowPlaceholders;
1141
+ args.push(...value.flat());
1142
+ } else {
1143
+ const placeholders = value.map(()=>'?').join(', ');
1144
+ sql += `(${placeholders})`;
1145
+ args.push(...value);
1146
+ }
1147
+ else {
1148
+ sql += '?';
1149
+ args.push(value);
1150
+ }
980
1151
  }
981
- });
982
- if (404 === response.status) return null;
983
- const result = await response.json();
984
- if (!result.success) throw new Error(result.error || 'Failed to get database');
985
- return result.database;
1152
+ }
1153
+ return {
1154
+ sql,
1155
+ args
1156
+ };
1157
+ }
1158
+ function isSqlFragment(value) {
1159
+ return value && 'object' == typeof value && true === value._isSqlFragment;
986
1160
  }
987
- /**
988
- * Delete a database
989
- *
990
- * @param hash - Database hash to delete
991
- */ async deleteDatabase(hash) {
992
- const response = await fetch(`${this.apiUrl}/api/tenant/databases/${hash}`, {
993
- method: 'DELETE',
994
- headers: {
995
- Authorization: `Bearer ${this.apiKey}`
1161
+ function sql_template_sql(value, ...keys) {
1162
+ let columnKeys = [];
1163
+ if (keys.length > 0) columnKeys = Array.isArray(keys[0]) ? keys[0] : keys;
1164
+ if ('string' == typeof value && 0 === columnKeys.length) return {
1165
+ _isSqlFragment: true,
1166
+ sql: value,
1167
+ args: []
1168
+ };
1169
+ if (Array.isArray(value) && value.length > 0 && 'string' == typeof value[0]) return {
1170
+ _isSqlFragment: true,
1171
+ sql: value.join(', '),
1172
+ args: []
1173
+ };
1174
+ if (Array.isArray(value) && value.length > 0 && 'object' == typeof value[0] && !Array.isArray(value[0])) {
1175
+ if (0 === columnKeys.length) columnKeys = Object.keys(value[0]);
1176
+ const allValues = [];
1177
+ const rowPlaceholders = [];
1178
+ for (const obj of value){
1179
+ const rowValues = columnKeys.map((key)=>obj[key]);
1180
+ allValues.push(...rowValues);
1181
+ rowPlaceholders.push(`(${columnKeys.map(()=>'?').join(', ')})`);
996
1182
  }
997
- });
998
- const result = await response.json();
999
- if (!result.success) throw new Error(result.error || 'Failed to delete database');
1000
- // Remove from cache
1001
- for (const [key, cachedHash] of this.databaseCache.entries())if (cachedHash === hash) {
1002
- this.databaseCache.delete(key);
1003
- break;
1183
+ return {
1184
+ _isSqlFragment: true,
1185
+ sql: `(${columnKeys.join(', ')}) VALUES ${rowPlaceholders.join(', ')}`,
1186
+ args: allValues
1187
+ };
1188
+ }
1189
+ if (value && 'object' == typeof value && !Array.isArray(value)) {
1190
+ if (0 === columnKeys.length) columnKeys = Object.keys(value);
1191
+ const values = columnKeys.map((key)=>value[key]);
1192
+ const placeholders = columnKeys.map(()=>'?').join(', ');
1193
+ return {
1194
+ _isSqlFragment: true,
1195
+ sql: `(${columnKeys.join(', ')}) VALUES (${placeholders})`,
1196
+ args: values
1197
+ };
1198
+ }
1199
+ if (Array.isArray(value) && value.length > 0 && Array.isArray(value[0])) {
1200
+ const rowPlaceholders = value.map((row)=>`(${row.map(()=>'?').join(', ')})`).join(', ');
1201
+ return {
1202
+ _isSqlFragment: true,
1203
+ sql: rowPlaceholders,
1204
+ args: value.flat()
1205
+ };
1004
1206
  }
1207
+ return {
1208
+ _isSqlFragment: true,
1209
+ sql: '',
1210
+ args: []
1211
+ };
1005
1212
  }
1006
- /**
1007
- * List available nodes
1008
- *
1009
- * @returns Array of node objects
1010
- */ async listNodes() {
1011
- const response = await fetch(`${this.apiUrl}/api/tenant/nodes`, {
1012
- headers: {
1013
- Authorization: `Bearer ${this.apiKey}`
1014
- }
1015
- });
1016
- const result = await response.json();
1017
- if (!result.success) throw new Error(result.error || 'Failed to list nodes');
1018
- return result.nodes;
1019
- }
1020
- /**
1021
- * Execute a query on a specific database
1022
- *
1023
- * This is a low-level query method. For most use cases, you should use
1024
- * the full ODB client (`odblite()` function) instead, which provides
1025
- * template tag support and better ergonomics.
1026
- *
1027
- * @param databaseHash - Hash of the database to query
1028
- * @param sql - SQL query string
1029
- * @param params - Query parameters
1030
- * @returns Query result
1031
- */ async query(databaseHash, sql, params = []) {
1032
- const response = await fetch(`${this.apiUrl}/query/${databaseHash}`, {
1033
- method: 'POST',
1034
- headers: {
1035
- 'Content-Type': 'application/json',
1036
- Authorization: `Bearer ${this.apiKey}`
1037
- },
1038
- body: JSON.stringify({
1039
- sql,
1040
- params
1041
- })
1042
- });
1043
- const result = await response.json();
1044
- if (!result.success) throw new Error(result.error || 'Query failed');
1045
- return result.data;
1046
- }
1047
- /**
1048
- * Clear the database hash cache
1049
- *
1050
- * Useful when database mappings have changed or for testing.
1051
- */ clearCache() {
1052
- this.databaseCache.clear();
1213
+ function empty() {
1214
+ return {
1215
+ _isSqlFragment: true,
1216
+ sql: '',
1217
+ args: []
1218
+ };
1053
1219
  }
1054
- /**
1055
- * Get cached database hash for a specific tenant (if exists)
1056
- *
1057
- * @param prefix - Database name prefix
1058
- * @param tenantId - Tenant identifier
1059
- * @returns Cached hash or undefined
1060
- */ getCachedHash(prefix, tenantId) {
1061
- const cacheKey = `${prefix}_${tenantId}`;
1062
- return this.databaseCache.get(cacheKey);
1220
+ function sql_template_raw(value) {
1221
+ return {
1222
+ _isSqlFragment: true,
1223
+ sql: value,
1224
+ args: []
1225
+ };
1063
1226
  }
1064
- /**
1065
- * Pre-cache a database hash
1066
- *
1067
- * Useful when you know the mapping ahead of time and want to avoid
1068
- * the initial lookup.
1069
- *
1070
- * @param prefix - Database name prefix
1071
- * @param tenantId - Tenant identifier
1072
- * @param hash - Database hash
1073
- */ setCachedHash(prefix, tenantId, hash) {
1074
- const cacheKey = `${prefix}_${tenantId}`;
1075
- this.databaseCache.set(cacheKey, hash);
1227
+ function sql_template_fragment(strings, ...values) {
1228
+ const query = convertTemplateToQuery(strings, values);
1229
+ return {
1230
+ _isSqlFragment: true,
1231
+ ...query
1232
+ };
1076
1233
  }
1077
- }
1078
- const external_bun_sqlite_namespaceObject = require("bun:sqlite");
1079
- /**
1080
- * Bun SQLite adapter for DatabaseManager
1081
- * Wraps bun:sqlite with Connection interface
1082
- */ class BunSQLiteAdapter {
1083
- type = 'bun-sqlite';
1084
- config;
1085
- constructor(config){
1086
- this.config = config;
1234
+ function sql_template_join(fragments, separator = ', ') {
1235
+ if (0 === fragments.length) return empty();
1236
+ const sql = fragments.map((f)=>f.sql).join(separator);
1237
+ const args = fragments.flatMap((f)=>f.args);
1238
+ return {
1239
+ _isSqlFragment: true,
1240
+ sql,
1241
+ args
1242
+ };
1087
1243
  }
1088
- async connect(config) {
1089
- const db = new external_bun_sqlite_namespaceObject.Database(config.databasePath, {
1090
- readonly: config.readonly,
1091
- create: config.create ?? true
1092
- });
1093
- return new BunSQLiteConnection(db);
1244
+ function set(data, ...keys) {
1245
+ let columns;
1246
+ columns = keys.length > 0 ? keys : Object.keys(data);
1247
+ if (0 === columns.length) return empty();
1248
+ const setClauses = columns.map((key)=>`${key} = ?`);
1249
+ const values = columns.map((key)=>data[key]);
1250
+ return {
1251
+ _isSqlFragment: true,
1252
+ sql: setClauses.join(', '),
1253
+ args: values
1254
+ };
1094
1255
  }
1095
- async disconnect(tenantId) {
1096
- // bun:sqlite doesn't require explicit disconnection
1097
- // File handles are cleaned up by GC
1256
+ function sql_template_where(conditions) {
1257
+ const entries = Object.entries(conditions);
1258
+ if (0 === entries.length) return empty();
1259
+ const whereClauses = entries.map(([key])=>`${key} = ?`);
1260
+ const values = entries.map(([, value])=>value);
1261
+ return {
1262
+ _isSqlFragment: true,
1263
+ sql: whereClauses.join(' AND '),
1264
+ args: values
1265
+ };
1098
1266
  }
1099
- async isHealthy() {
1100
- try {
1101
- const db = new external_bun_sqlite_namespaceObject.Database(this.config.databasePath, {
1102
- readonly: true,
1103
- create: false
1267
+ class BunSQLiteAdapter {
1268
+ type = 'bun-sqlite';
1269
+ config;
1270
+ constructor(config){
1271
+ this.config = config;
1272
+ }
1273
+ async connect(config) {
1274
+ const db = new external_bun_sqlite_namespaceObject.Database(config.databasePath, {
1275
+ readonly: config.readonly,
1276
+ create: config.create ?? true
1104
1277
  });
1105
- db.query('SELECT 1').get();
1106
- db.close();
1107
- return true;
1108
- } catch {
1109
- return false;
1278
+ return new BunSQLiteConnection(db);
1110
1279
  }
1111
- }
1112
- }
1113
- /**
1114
- * Connection implementation for Bun SQLite
1115
- */ class BunSQLiteConnection {
1116
- db;
1117
- inTransaction = false;
1118
- constructor(db){
1119
- this.db = db;
1120
- }
1121
- /**
1122
- * Template tag query (postgres.js-like)
1123
- */ async sql(strings, ...values) {
1124
- // Build SQL from template
1125
- const sqlStr = strings.reduce((acc, str, i)=>acc + str + (i < values.length ? '?' : ''), '');
1126
- return this.execute(sqlStr, values);
1127
- }
1128
- /**
1129
- * Query with SQL string and parameters (alias for execute)
1130
- */ async query(sql, params = []) {
1131
- return this.execute(sql, params);
1132
- }
1133
- /**
1134
- * Execute SQL with parameters
1135
- */ async execute(sql, params = []) {
1136
- try {
1137
- // Handle object format { sql, args }
1138
- let sqlStr;
1139
- let sqlParams;
1140
- if ('object' == typeof sql) {
1141
- sqlStr = sql.sql;
1142
- sqlParams = sql.args || [];
1143
- } else {
1144
- sqlStr = sql;
1145
- sqlParams = params;
1146
- }
1147
- const stmt = this.db.query(sqlStr);
1148
- const isSelect = sqlStr.trim().toUpperCase().startsWith('SELECT') || sqlStr.trim().toUpperCase().includes('RETURNING');
1149
- if (isSelect) {
1150
- const rows = stmt.all(...sqlParams);
1151
- return {
1152
- rows: rows,
1153
- rowsAffected: 0
1154
- };
1155
- }
1156
- {
1157
- const result = stmt.run(...sqlParams);
1158
- return {
1159
- rows: [],
1160
- rowsAffected: result.changes || 0,
1161
- lastInsertRowid: result.lastInsertRowid
1162
- };
1280
+ async disconnect(tenantId) {}
1281
+ async isHealthy() {
1282
+ try {
1283
+ const db = new external_bun_sqlite_namespaceObject.Database(this.config.databasePath, {
1284
+ readonly: true,
1285
+ create: false
1286
+ });
1287
+ db.query('SELECT 1').get();
1288
+ db.close();
1289
+ return true;
1290
+ } catch {
1291
+ return false;
1163
1292
  }
1164
- } catch (error) {
1165
- throw new Error(`SQL execution failed: ${error.message}`);
1166
1293
  }
1167
1294
  }
1168
- /**
1169
- * Prepare statement for repeated execution
1170
- */ prepare(sql) {
1171
- const stmt = this.db.query(sql);
1172
- return {
1173
- execute: async (params = [])=>{
1174
- const isSelect = sql.trim().toUpperCase().startsWith('SELECT');
1295
+ class BunSQLiteConnection {
1296
+ db;
1297
+ inTransaction = false;
1298
+ sql;
1299
+ constructor(db){
1300
+ this.db = db;
1301
+ const self = this;
1302
+ this.sql = function(stringsOrValue, ...values) {
1303
+ if (!stringsOrValue || 'object' != typeof stringsOrValue || !('raw' in stringsOrValue)) return sql_template_sql(stringsOrValue, ...values);
1304
+ {
1305
+ const query = convertTemplateToQuery(stringsOrValue, values);
1306
+ const thenableFragment = {
1307
+ _isSqlFragment: true,
1308
+ sql: query.sql,
1309
+ args: query.args
1310
+ };
1311
+ thenableFragment['then'] = function(onFulfilled, onRejected) {
1312
+ return self.execute(query).then((result)=>result.rows).then(onFulfilled, onRejected);
1313
+ };
1314
+ return thenableFragment;
1315
+ }
1316
+ };
1317
+ this.sql.empty = empty;
1318
+ this.sql.raw = sql_template_raw;
1319
+ this.sql.fragment = sql_template_fragment;
1320
+ this.sql.join = sql_template_join;
1321
+ this.sql.set = set;
1322
+ this.sql.where = sql_template_where;
1323
+ }
1324
+ async query(sql, params = []) {
1325
+ return this.execute(sql, params);
1326
+ }
1327
+ async execute(sql, params = []) {
1328
+ try {
1329
+ let sqlStr;
1330
+ let sqlParams;
1331
+ if ('object' == typeof sql) {
1332
+ if (process.env.DEBUG_SQL) {
1333
+ console.log('[BunSQLite] Executing SQL:', sql.sql);
1334
+ console.log('[BunSQLite] With args:', sql.args);
1335
+ }
1336
+ sqlStr = sql.sql;
1337
+ sqlParams = sql.args || [];
1338
+ } else {
1339
+ if (process.env.DEBUG_SQL) {
1340
+ console.log('[BunSQLite] Executing SQL:', sql);
1341
+ console.log('[BunSQLite] With params:', params);
1342
+ }
1343
+ sqlStr = sql;
1344
+ sqlParams = params;
1345
+ }
1346
+ const stmt = this.db.query(sqlStr);
1347
+ const isSelect = sqlStr.trim().toUpperCase().startsWith('SELECT') || sqlStr.trim().toUpperCase().includes('RETURNING');
1175
1348
  if (isSelect) {
1176
- const rows = stmt.all(...params);
1349
+ const rows = stmt.all(...sqlParams);
1177
1350
  return {
1178
1351
  rows: rows,
1179
1352
  rowsAffected: 0
1180
1353
  };
1181
1354
  }
1182
1355
  {
1183
- const result = stmt.run(...params);
1356
+ const result = stmt.run(...sqlParams);
1184
1357
  return {
1185
1358
  rows: [],
1186
1359
  rowsAffected: result.changes || 0,
1187
1360
  lastInsertRowid: result.lastInsertRowid
1188
1361
  };
1189
1362
  }
1190
- },
1191
- all: async (params = [])=>stmt.all(...params),
1192
- get: async (params = [])=>stmt.get(...params)
1193
- };
1194
- }
1195
- /**
1196
- * Execute function in transaction
1197
- */ async transaction(fn) {
1198
- if (this.inTransaction) // Nested transaction - just execute the function
1199
- return fn(this);
1200
- this.inTransaction = true;
1201
- try {
1202
- await this.execute('BEGIN');
1203
- const result = await fn(this);
1204
- await this.execute('COMMIT');
1205
- return result;
1206
- } catch (error) {
1207
- await this.execute('ROLLBACK');
1208
- throw error;
1209
- } finally{
1210
- this.inTransaction = false;
1363
+ } catch (error) {
1364
+ throw error;
1365
+ }
1366
+ }
1367
+ prepare(sql) {
1368
+ const stmt = this.db.query(sql);
1369
+ return {
1370
+ execute: async (params = [])=>{
1371
+ const isSelect = sql.trim().toUpperCase().startsWith('SELECT');
1372
+ if (isSelect) {
1373
+ const rows = stmt.all(...params);
1374
+ return {
1375
+ rows: rows,
1376
+ rowsAffected: 0
1377
+ };
1378
+ }
1379
+ {
1380
+ const result = stmt.run(...params);
1381
+ return {
1382
+ rows: [],
1383
+ rowsAffected: result.changes || 0,
1384
+ lastInsertRowid: result.lastInsertRowid
1385
+ };
1386
+ }
1387
+ },
1388
+ all: async (params = [])=>stmt.all(...params),
1389
+ get: async (params = [])=>stmt.get(...params)
1390
+ };
1391
+ }
1392
+ async transaction(fn) {
1393
+ if (this.inTransaction) return fn(this);
1394
+ this.inTransaction = true;
1395
+ try {
1396
+ await this.execute('BEGIN');
1397
+ const result = await fn(this);
1398
+ await this.execute('COMMIT');
1399
+ return result;
1400
+ } catch (error) {
1401
+ await this.execute('ROLLBACK');
1402
+ throw error;
1403
+ } finally{
1404
+ this.inTransaction = false;
1405
+ }
1406
+ }
1407
+ async begin(fn) {
1408
+ return this.transaction(fn);
1409
+ }
1410
+ async close() {
1411
+ this.db.close();
1412
+ }
1413
+ createORM() {
1414
+ const { createORM } = __webpack_require__("./src/orm/index.ts");
1415
+ return createORM(this);
1211
1416
  }
1212
1417
  }
1213
- /**
1214
- * Execute function in transaction (alias for transaction)
1215
- */ async begin(fn) {
1216
- return this.transaction(fn);
1217
- }
1218
- /**
1219
- * Close connection
1220
- */ async close() {
1221
- this.db.close();
1222
- }
1223
- }
1224
- const external_libsql_client_namespaceObject = require("@libsql/client");
1225
- /**
1226
- * LibSQL adapter for DatabaseManager
1227
- * Wraps @libsql/client with Connection interface
1228
- */ class LibSQLAdapter {
1229
- type = 'libsql';
1230
- config;
1231
- constructor(config){
1232
- this.config = config;
1233
- }
1234
- async connect(config) {
1235
- const client = (0, external_libsql_client_namespaceObject.createClient)({
1236
- url: config.url,
1237
- authToken: config.authToken,
1238
- encryptionKey: config.encryptionKey
1239
- });
1240
- return new LibSQLConnection(client);
1241
- }
1242
- async disconnect(tenantId) {
1243
- // LibSQL clients don't require explicit disconnection
1244
- // Connections are pooled internally
1245
- }
1246
- async isHealthy() {
1247
- try {
1418
+ const external_libsql_client_namespaceObject = require("@libsql/client");
1419
+ class LibSQLAdapter {
1420
+ type = 'libsql';
1421
+ config;
1422
+ constructor(config){
1423
+ this.config = config;
1424
+ }
1425
+ async connect(config) {
1248
1426
  const client = (0, external_libsql_client_namespaceObject.createClient)({
1249
- url: this.config.url,
1250
- authToken: this.config.authToken
1427
+ url: config.url,
1428
+ authToken: config.authToken,
1429
+ encryptionKey: config.encryptionKey
1251
1430
  });
1252
- await client.execute('SELECT 1');
1253
- return true;
1254
- } catch {
1255
- return false;
1431
+ return new LibSQLConnection(client);
1432
+ }
1433
+ async disconnect(tenantId) {}
1434
+ async isHealthy() {
1435
+ try {
1436
+ const client = (0, external_libsql_client_namespaceObject.createClient)({
1437
+ url: this.config.url,
1438
+ authToken: this.config.authToken
1439
+ });
1440
+ await client.execute('SELECT 1');
1441
+ return true;
1442
+ } catch {
1443
+ return false;
1444
+ }
1256
1445
  }
1257
1446
  }
1258
- }
1259
- /**
1260
- * Connection implementation for LibSQL
1261
- */ class LibSQLConnection {
1262
- client;
1263
- txClient;
1264
- constructor(client){
1265
- this.client = client;
1266
- }
1267
- /**
1268
- * Template tag query (postgres.js-like)
1269
- */ async sql(strings, ...values) {
1270
- // Build SQL from template
1271
- const sqlStr = strings.reduce((acc, str, i)=>acc + str + (i < values.length ? '?' : ''), '');
1272
- return this.execute(sqlStr, values);
1273
- }
1274
- /**
1275
- * Query with SQL string and parameters (alias for execute)
1276
- */ async query(sql, params = []) {
1277
- return this.execute(sql, params);
1278
- }
1279
- /**
1280
- * Execute SQL with parameters
1281
- * Supports both formats: execute(sql, params) and execute({sql, args})
1282
- */ async execute(sql, params = []) {
1283
- try {
1284
- const target = this.txClient || this.client;
1285
- // Support both execute(sql, params) and execute({sql, args}) formats
1286
- let query;
1287
- query = 'string' == typeof sql ? {
1288
- sql,
1289
- args: params
1290
- } : {
1291
- sql: sql.sql,
1292
- args: sql.args || []
1447
+ class LibSQLConnection {
1448
+ client;
1449
+ txClient;
1450
+ sql;
1451
+ constructor(client){
1452
+ this.client = client;
1453
+ const self = this;
1454
+ this.sql = function(stringsOrValue, ...values) {
1455
+ if (!stringsOrValue || 'object' != typeof stringsOrValue || !('raw' in stringsOrValue)) return sql_template_sql(stringsOrValue, ...values);
1456
+ {
1457
+ const query = convertTemplateToQuery(stringsOrValue, values);
1458
+ const thenableFragment = {
1459
+ _isSqlFragment: true,
1460
+ sql: query.sql,
1461
+ args: query.args
1462
+ };
1463
+ thenableFragment['then'] = function(onFulfilled, onRejected) {
1464
+ return self.execute(query).then((result)=>result.rows).then(onFulfilled, onRejected);
1465
+ };
1466
+ return thenableFragment;
1467
+ }
1293
1468
  };
1294
- const result = await target.execute(query);
1469
+ this.sql.empty = empty;
1470
+ this.sql.raw = sql_template_raw;
1471
+ this.sql.fragment = sql_template_fragment;
1472
+ this.sql.join = sql_template_join;
1473
+ this.sql.set = set;
1474
+ this.sql.where = sql_template_where;
1475
+ }
1476
+ async query(sql, params = []) {
1477
+ return this.execute(sql, params);
1478
+ }
1479
+ async execute(sql, params = []) {
1480
+ try {
1481
+ const target = this.txClient || this.client;
1482
+ let query;
1483
+ if ('string' == typeof sql) {
1484
+ if (process.env.DEBUG_SQL) {
1485
+ console.log('[LibSQL] Executing SQL:', sql);
1486
+ console.log('[LibSQL] With params:', params);
1487
+ }
1488
+ query = {
1489
+ sql,
1490
+ args: params
1491
+ };
1492
+ } else {
1493
+ if (process.env.DEBUG_SQL) {
1494
+ console.log('[LibSQL] Executing SQL:', sql.sql);
1495
+ console.log('[LibSQL] With args:', sql.args);
1496
+ }
1497
+ query = {
1498
+ sql: sql.sql,
1499
+ args: sql.args || []
1500
+ };
1501
+ }
1502
+ const result = await target.execute(query);
1503
+ return {
1504
+ rows: result.rows,
1505
+ rowsAffected: Number(result.rowsAffected),
1506
+ lastInsertRowid: result.lastInsertRowid ? BigInt(result.lastInsertRowid.toString()) : void 0
1507
+ };
1508
+ } catch (error) {
1509
+ throw error;
1510
+ }
1511
+ }
1512
+ prepare(sql) {
1295
1513
  return {
1296
- rows: result.rows,
1297
- rowsAffected: Number(result.rowsAffected),
1298
- lastInsertRowid: result.lastInsertRowid ? BigInt(result.lastInsertRowid.toString()) : void 0
1514
+ execute: async (params = [])=>this.execute(sql, params),
1515
+ all: async (params = [])=>{
1516
+ const result = await this.execute(sql, params);
1517
+ return result.rows;
1518
+ },
1519
+ get: async (params = [])=>{
1520
+ const result = await this.execute(sql, params);
1521
+ return result.rows[0] || null;
1522
+ }
1299
1523
  };
1300
- } catch (error) {
1301
- throw new Error(`SQL execution failed: ${error.message}`);
1302
1524
  }
1303
- }
1304
- /**
1305
- * Prepare statement for repeated execution
1306
- */ prepare(sql) {
1307
- return {
1308
- execute: async (params = [])=>this.execute(sql, params),
1309
- all: async (params = [])=>{
1310
- const result = await this.execute(sql, params);
1311
- return result.rows;
1312
- },
1313
- get: async (params = [])=>{
1314
- const result = await this.execute(sql, params);
1315
- return result.rows[0] || null;
1525
+ async transaction(fn) {
1526
+ if (this.txClient) return fn(this);
1527
+ try {
1528
+ await this.execute('BEGIN');
1529
+ const result = await fn(this);
1530
+ await this.execute('COMMIT');
1531
+ return result;
1532
+ } catch (error) {
1533
+ await this.execute('ROLLBACK');
1534
+ throw error;
1316
1535
  }
1317
- };
1318
- }
1319
- /**
1320
- * Execute function in transaction
1321
- */ async transaction(fn) {
1322
- if (this.txClient) // Nested transaction - just execute the function
1323
- return fn(this);
1324
- // Use manual BEGIN/COMMIT/ROLLBACK for simplicity
1325
- try {
1326
- await this.execute('BEGIN');
1327
- const result = await fn(this);
1328
- await this.execute('COMMIT');
1329
- return result;
1330
- } catch (error) {
1331
- await this.execute('ROLLBACK');
1332
- throw error;
1536
+ }
1537
+ async begin(fn) {
1538
+ return this.transaction(fn);
1539
+ }
1540
+ async close() {}
1541
+ createORM() {
1542
+ const { createORM } = __webpack_require__("./src/orm/index.ts");
1543
+ return createORM(this);
1333
1544
  }
1334
1545
  }
1335
- /**
1336
- * Execute function in transaction (alias for transaction)
1337
- */ async begin(fn) {
1338
- return this.transaction(fn);
1339
- }
1340
- /**
1341
- * Close connection
1342
- */ async close() {
1343
- // LibSQL client.close() if available in future versions
1344
- // For now, connections are managed by the client pool
1345
- }
1346
- }
1347
- /**
1348
- * ODB-Lite adapter for DatabaseManager
1349
- * Wraps ServiceClient and ODBLiteClient with Connection interface
1350
- */ class ODBLiteAdapter {
1351
- type = 'odblite';
1352
- config;
1353
- serviceClient;
1354
- constructor(config){
1355
- this.config = config;
1356
- this.serviceClient = new ServiceClient({
1357
- baseUrl: config.serviceUrl,
1358
- apiKey: config.apiKey
1359
- });
1360
- }
1361
- async connect(config) {
1362
- const databaseName = config.databaseName || 'default';
1363
- // Ensure database exists
1364
- const dbInfo = await this.serviceClient.getDatabaseByName(databaseName);
1365
- if (!dbInfo) // Create database - pass nodeId from config if provided, otherwise server selects
1366
- await this.serviceClient.createDatabase(databaseName, this.config.nodeId);
1367
- // Get fresh database info
1368
- const db = await this.serviceClient.getDatabaseByName(databaseName);
1369
- if (!db) throw new Error(`Database ${databaseName} not found after creation`);
1370
- // Create ODBLiteClient for this database
1371
- const client = new ODBLiteClient({
1372
- baseUrl: this.config.serviceUrl,
1373
- apiKey: this.config.apiKey,
1374
- databaseId: db.hash
1375
- });
1376
- return new ODBLiteConnection(client, this.serviceClient, databaseName);
1377
- }
1378
- async disconnect(tenantId) {
1379
- if (tenantId) {
1380
- const prefix = 'pipeline_tenant_' // TODO: make configurable
1381
- ;
1382
- const databaseName = `${prefix}${tenantId}`;
1546
+ class ODBLiteAdapter {
1547
+ type = 'odblite';
1548
+ config;
1549
+ serviceClient;
1550
+ constructor(config){
1551
+ this.config = config;
1552
+ this.serviceClient = new ServiceClient({
1553
+ baseUrl: config.serviceUrl,
1554
+ apiKey: config.apiKey
1555
+ });
1556
+ }
1557
+ async connect(config) {
1558
+ const databaseName = config.databaseName || 'default';
1559
+ const databaseHash = config.databaseHash;
1560
+ if (databaseHash) {
1561
+ const client = new ODBLiteClient({
1562
+ baseUrl: this.config.serviceUrl,
1563
+ apiKey: this.config.apiKey,
1564
+ databaseId: databaseHash
1565
+ });
1566
+ return new ODBLiteConnection(client, this.serviceClient, databaseName, databaseHash);
1567
+ }
1568
+ const db = await this.serviceClient.getDatabaseByName(databaseName);
1569
+ if (!db) throw new Error(`Database ${databaseName} not found. Please create it first using the admin API.`);
1570
+ const client = new ODBLiteClient({
1571
+ baseUrl: this.config.serviceUrl,
1572
+ apiKey: this.config.apiKey,
1573
+ databaseId: db.hash
1574
+ });
1575
+ return new ODBLiteConnection(client, this.serviceClient, databaseName, db.hash);
1576
+ }
1577
+ async disconnect(tenantId) {
1578
+ if (tenantId) {
1579
+ const prefix = 'pipeline_tenant_';
1580
+ const databaseName = `${prefix}${tenantId}`;
1581
+ try {
1582
+ await this.serviceClient.deleteDatabase(databaseName);
1583
+ } catch (error) {
1584
+ console.warn(`Failed to delete database ${databaseName}:`, error.message);
1585
+ }
1586
+ }
1587
+ }
1588
+ async isHealthy() {
1383
1589
  try {
1384
- await this.serviceClient.deleteDatabase(databaseName);
1385
- } catch (error) {
1386
- console.warn(`Failed to delete database ${databaseName}:`, error.message);
1590
+ await this.serviceClient.listDatabases();
1591
+ return true;
1592
+ } catch {
1593
+ return false;
1387
1594
  }
1388
1595
  }
1389
1596
  }
1390
- async isHealthy() {
1391
- try {
1392
- await this.serviceClient.listDatabases();
1393
- return true;
1394
- } catch {
1395
- return false;
1597
+ class ODBLiteConnection {
1598
+ client;
1599
+ serviceClient;
1600
+ inTransaction = false;
1601
+ databaseName;
1602
+ databaseHash;
1603
+ sql;
1604
+ constructor(client, serviceClient, databaseName, databaseHash){
1605
+ this.client = client;
1606
+ this.serviceClient = serviceClient;
1607
+ this.databaseName = databaseName;
1608
+ this.databaseHash = databaseHash;
1609
+ const self = this;
1610
+ this.sql = function(stringsOrValue, ...values) {
1611
+ if (!stringsOrValue || 'object' != typeof stringsOrValue || !('raw' in stringsOrValue)) return sql_template_sql(stringsOrValue, ...values);
1612
+ {
1613
+ const query = convertTemplateToQuery(stringsOrValue, values);
1614
+ const thenableFragment = {
1615
+ _isSqlFragment: true,
1616
+ sql: query.sql,
1617
+ args: query.args
1618
+ };
1619
+ thenableFragment['then'] = function(onFulfilled, onRejected) {
1620
+ return self.execute(query).then((result)=>result.rows).then(onFulfilled, onRejected);
1621
+ };
1622
+ return thenableFragment;
1623
+ }
1624
+ };
1625
+ this.sql.empty = empty;
1626
+ this.sql.raw = sql_template_raw;
1627
+ this.sql.fragment = sql_template_fragment;
1628
+ this.sql.join = sql_template_join;
1629
+ this.sql.set = set;
1630
+ this.sql.where = sql_template_where;
1396
1631
  }
1397
- }
1398
- }
1399
- /**
1400
- * Connection implementation for ODB-Lite
1401
- */ class ODBLiteConnection {
1402
- client;
1403
- serviceClient;
1404
- databaseName;
1405
- inTransaction = false;
1406
- constructor(client, serviceClient, databaseName){
1407
- this.client = client;
1408
- this.serviceClient = serviceClient;
1409
- this.databaseName = databaseName;
1410
- }
1411
- /**
1412
- * Template tag query (postgres.js-like)
1413
- */ async sql(strings, ...values) {
1414
- // ODBLiteClient.sql is a function that returns a Promise
1415
- const result = await this.client.sql(strings, ...values);
1416
- return {
1417
- rows: result.rows,
1418
- rowsAffected: result.rowsAffected || 0
1419
- };
1420
- }
1421
- /**
1422
- * Query with SQL string and parameters (alias for execute)
1423
- */ async query(sql, params = []) {
1424
- return this.execute(sql, params);
1425
- }
1426
- /**
1427
- * Execute SQL with parameters
1428
- */ async execute(sql, params = []) {
1429
- try {
1430
- // Handle object format { sql, args }
1431
- if ('object' == typeof sql) {
1432
- const result = await this.client.sql.execute(sql.sql, sql.args || []);
1632
+ async query(sql, params = []) {
1633
+ return this.execute(sql, params);
1634
+ }
1635
+ async execute(sql, params = []) {
1636
+ try {
1637
+ if ('object' == typeof sql) {
1638
+ if (process.env.DEBUG_SQL) {
1639
+ console.log('[ODBLite] Executing SQL:', sql.sql);
1640
+ console.log('[ODBLite] With args:', sql.args);
1641
+ }
1642
+ const result = await this.client.sql.execute(sql.sql, sql.args || []);
1643
+ return {
1644
+ rows: result.rows,
1645
+ rowsAffected: result.rowsAffected || 0,
1646
+ lastInsertRowid: result.lastInsertRowid
1647
+ };
1648
+ }
1649
+ if (process.env.DEBUG_SQL) {
1650
+ console.log('[ODBLite] Executing SQL:', sql);
1651
+ console.log('[ODBLite] With params:', params);
1652
+ }
1653
+ const result = await this.client.sql.execute(sql, params);
1433
1654
  return {
1434
1655
  rows: result.rows,
1435
- rowsAffected: result.rowsAffected || 0
1656
+ rowsAffected: result.rowsAffected || 0,
1657
+ lastInsertRowid: result.lastInsertRowid
1436
1658
  };
1659
+ } catch (error) {
1660
+ throw error;
1437
1661
  }
1438
- // Handle string format
1439
- const result = await this.client.sql.execute(sql, params);
1662
+ }
1663
+ prepare(sql) {
1440
1664
  return {
1441
- rows: result.rows,
1442
- rowsAffected: result.rowsAffected || 0
1665
+ execute: async (params = [])=>this.execute(sql, params),
1666
+ all: async (params = [])=>{
1667
+ const result = await this.execute(sql, params);
1668
+ return result.rows;
1669
+ },
1670
+ get: async (params = [])=>{
1671
+ const result = await this.execute(sql, params);
1672
+ return result.rows[0] || null;
1673
+ }
1443
1674
  };
1444
- } catch (error) {
1445
- throw new Error(`SQL execution failed: ${error.message}`);
1446
1675
  }
1447
- }
1448
- /**
1449
- * Prepare statement for repeated execution
1450
- */ prepare(sql) {
1451
- return {
1452
- execute: async (params = [])=>this.execute(sql, params),
1453
- all: async (params = [])=>{
1454
- const result = await this.execute(sql, params);
1455
- return result.rows;
1456
- },
1457
- get: async (params = [])=>{
1458
- const result = await this.execute(sql, params);
1459
- return result.rows[0] || null;
1676
+ async transaction(fn) {
1677
+ if (this.inTransaction) return fn(this);
1678
+ this.inTransaction = true;
1679
+ try {
1680
+ await this.execute('BEGIN');
1681
+ const result = await fn(this);
1682
+ await this.execute('COMMIT');
1683
+ return result;
1684
+ } catch (error) {
1685
+ await this.execute('ROLLBACK');
1686
+ throw error;
1687
+ } finally{
1688
+ this.inTransaction = false;
1460
1689
  }
1461
- };
1462
- }
1463
- /**
1464
- * Execute function in transaction
1465
- */ async transaction(fn) {
1466
- if (this.inTransaction) // Nested transaction - just execute the function
1467
- return fn(this);
1468
- this.inTransaction = true;
1469
- try {
1470
- await this.execute('BEGIN');
1471
- const result = await fn(this);
1472
- await this.execute('COMMIT');
1473
- return result;
1474
- } catch (error) {
1475
- await this.execute('ROLLBACK');
1476
- throw error;
1477
- } finally{
1478
- this.inTransaction = false;
1690
+ }
1691
+ async begin(fn) {
1692
+ return this.transaction(fn);
1693
+ }
1694
+ async close() {}
1695
+ createORM() {
1696
+ const { createORM } = __webpack_require__("./src/orm/index.ts");
1697
+ return createORM(this);
1479
1698
  }
1480
1699
  }
1481
- /**
1482
- * Execute function in transaction (alias for transaction)
1483
- */ async begin(fn) {
1484
- return this.transaction(fn);
1485
- }
1486
- /**
1487
- * Close connection
1488
- */ async close() {
1489
- // ODBLiteClient connections are stateless HTTP requests
1490
- // No explicit close needed
1491
- }
1492
- }
1493
- /**
1494
- * Parse SQL file into statements, separating PRAGMA from regular SQL
1495
- * Uses custom parser that handles BEGIN...END blocks
1496
- */ function parseSQL(sqlContent, options = {}) {
1497
- const separatePragma = options.separatePragma ?? true;
1498
- // Split SQL statements manually
1499
- const statements = splitStatements(sqlContent);
1500
- if (!separatePragma) return {
1501
- pragmaStatements: [],
1502
- regularStatements: statements
1503
- };
1504
- const pragmaStatements = [];
1505
- const regularStatements = [];
1506
- for (const statement of statements){
1507
- const trimmed = statement.trim().toUpperCase();
1508
- if (trimmed.startsWith('PRAGMA')) pragmaStatements.push(statement);
1509
- else regularStatements.push(statement);
1700
+ function parseSQL(sqlContent, options = {}) {
1701
+ const separatePragma = options.separatePragma ?? true;
1702
+ const statements = splitStatements(sqlContent);
1703
+ if (!separatePragma) return {
1704
+ pragmaStatements: [],
1705
+ regularStatements: statements
1706
+ };
1707
+ const pragmaStatements = [];
1708
+ const regularStatements = [];
1709
+ for (const statement of statements){
1710
+ const trimmed = statement.trim().toUpperCase();
1711
+ if (trimmed.startsWith('PRAGMA')) pragmaStatements.push(statement);
1712
+ else regularStatements.push(statement);
1713
+ }
1714
+ return {
1715
+ pragmaStatements,
1716
+ regularStatements
1717
+ };
1510
1718
  }
1511
- return {
1512
- pragmaStatements,
1513
- regularStatements
1514
- };
1515
- }
1516
- /**
1517
- * Split SQL content into individual statements
1518
- * Handles comments, quotes, semicolons, and BEGIN...END blocks properly
1519
- */ function splitStatements(sqlContent) {
1520
- const statements = [];
1521
- let currentStatement = '';
1522
- let inQuote = false;
1523
- let quoteChar = '';
1524
- let beginEndDepth = 0;
1525
- const lines = sqlContent.split('\n');
1526
- for (const line of lines){
1527
- let processedLine = '';
1528
- const lineWithoutComments = line.replace(/--.*$/, '');
1529
- // Track BEGIN...END depth for this line BEFORE processing characters
1530
- if (!inQuote && lineWithoutComments.trim()) {
1531
- const beginMatches = lineWithoutComments.match(/\bBEGIN\b/gi);
1532
- const endMatches = lineWithoutComments.match(/\bEND\b/gi);
1533
- if (beginMatches) beginEndDepth += beginMatches.length;
1534
- if (endMatches) {
1535
- beginEndDepth -= endMatches.length;
1536
- if (beginEndDepth < 0) beginEndDepth = 0;
1537
- }
1538
- }
1539
- for(let i = 0; i < line.length; i++){
1540
- const char = line[i];
1541
- const prevChar = i > 0 ? line[i - 1] : '';
1542
- const nextChar = i < line.length - 1 ? line[i + 1] : '';
1543
- // Handle single-line comments
1544
- if (!inQuote && '-' === char && '-' === nextChar) break; // Skip rest of line
1545
- // Track quotes
1546
- if (("'" === char || '"' === char) && '\\' !== prevChar) {
1547
- if (inQuote) {
1719
+ function splitStatements(sqlContent) {
1720
+ const statements = [];
1721
+ let currentStatement = '';
1722
+ let inQuote = false;
1723
+ let quoteChar = '';
1724
+ let beginEndDepth = 0;
1725
+ const lines = sqlContent.split('\n');
1726
+ for (const line of lines){
1727
+ let processedLine = '';
1728
+ const lineWithoutComments = line.replace(/--.*$/, '');
1729
+ if (!inQuote && lineWithoutComments.trim()) {
1730
+ const beginMatches = lineWithoutComments.match(/\bBEGIN\b/gi);
1731
+ const endMatches = lineWithoutComments.match(/\bEND\b/gi);
1732
+ if (beginMatches) beginEndDepth += beginMatches.length;
1733
+ if (endMatches) {
1734
+ beginEndDepth -= endMatches.length;
1735
+ if (beginEndDepth < 0) beginEndDepth = 0;
1736
+ }
1737
+ }
1738
+ for(let i = 0; i < line.length; i++){
1739
+ const char = line[i];
1740
+ const prevChar = i > 0 ? line[i - 1] : '';
1741
+ const nextChar = i < line.length - 1 ? line[i + 1] : '';
1742
+ if (!inQuote && '-' === char && '-' === nextChar) break;
1743
+ if (("'" === char || '"' === char) && '\\' !== prevChar) if (inQuote) {
1548
1744
  if (char === quoteChar) {
1549
1745
  inQuote = false;
1550
1746
  quoteChar = '';
@@ -1553,289 +1749,291 @@ const external_libsql_client_namespaceObject = require("@libsql/client");
1553
1749
  inQuote = true;
1554
1750
  quoteChar = char;
1555
1751
  }
1556
- }
1557
- processedLine += char;
1558
- // Split on semicolon when not in quotes AND not inside BEGIN...END
1559
- if (';' === char && !inQuote && 0 === beginEndDepth) {
1560
- currentStatement += processedLine;
1561
- const stmt = currentStatement.trim();
1562
- if (stmt && !stmt.startsWith('--')) statements.push(stmt);
1563
- currentStatement = '';
1564
- processedLine = '';
1565
- }
1566
- }
1567
- if (processedLine.trim()) currentStatement += `${processedLine}\n`;
1568
- }
1569
- // Handle remaining statement
1570
- const finalStmt = currentStatement.trim();
1571
- if (finalStmt && !finalStmt.startsWith('--')) statements.push(finalStmt);
1572
- return statements;
1573
- }
1574
- /**
1575
- * Simple split for systems that don't need PRAGMA separation
1576
- */ function splitSQLStatements(sqlContent) {
1577
- const { pragmaStatements, regularStatements } = parseSQL(sqlContent);
1578
- return [
1579
- ...pragmaStatements,
1580
- ...regularStatements
1581
- ];
1582
- }
1583
- const external_node_fs_namespaceObject = require("node:fs");
1584
- var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
1585
- /**
1586
- * Database factory for creating and managing multiple databases
1587
- *
1588
- * Features:
1589
- * - Creates multiple databases from single manager instance
1590
- * - Supports libsql, bun:sqlite, and ODB-Lite backends
1591
- * - Connection pooling with LRU eviction
1592
- * - Automatic schema migrations
1593
- *
1594
- * @example
1595
- * ```ts
1596
- * const dbManager = new DatabaseManager({
1597
- * backend: 'libsql',
1598
- * databasePath: './data'
1599
- * })
1600
- *
1601
- * // Create databases
1602
- * await dbManager.createDatabase('identity', { schemaContent })
1603
- * await dbManager.createDatabase('analytics', { schemaContent })
1604
- *
1605
- * // Get connections
1606
- * const identityDB = await dbManager.getConnection('identity')
1607
- * const analyticsDB = await dbManager.getConnection('analytics')
1608
- * ```
1609
- */ class DatabaseManager {
1610
- config;
1611
- adapter;
1612
- connections = new Map();
1613
- // Connection pool management (LRU)
1614
- connectionTimestamps = new Map();
1615
- maxConnections;
1616
- constructor(config){
1617
- this.config = config;
1618
- this.maxConnections = config.connectionPoolSize || 10;
1619
- // Create appropriate adapter based on backend
1620
- switch(config.backend){
1621
- case 'bun-sqlite':
1622
- this.adapter = new BunSQLiteAdapter({
1623
- databasePath: config.databasePath,
1624
- create: true
1625
- });
1626
- break;
1627
- case 'libsql':
1628
- this.adapter = new LibSQLAdapter({
1629
- url: `file:${config.databasePath}`,
1630
- ...config.libsql
1631
- });
1632
- break;
1633
- case 'odblite':
1634
- if (!config.odblite) throw new Error('odblite config required for odblite backend');
1635
- this.adapter = new ODBLiteAdapter(config.odblite);
1636
- break;
1637
- default:
1638
- throw new Error(`Unknown backend type: ${config.backend}`);
1639
- }
1640
- }
1641
- /**
1642
- * Create a new database
1643
- * @param name - Database name (becomes filename or ODB-Lite database name)
1644
- * @param options - Optional creation options
1645
- */ async createDatabase(name, options) {
1646
- console.log(`📦 Creating database: ${name}`);
1647
- // Build database-specific config
1648
- const dbConfig = this.getDatabaseConfig(name);
1649
- // Create connection
1650
- const conn = await this.adapter.connect(dbConfig);
1651
- // Run migrations if schema provided
1652
- if (options?.schemaContent) await this.runMigrations(conn, {
1653
- schemaContent: options.schemaContent
1654
- });
1655
- // Store connection
1656
- this.connections.set(name, conn);
1657
- this.connectionTimestamps.set(name, Date.now());
1658
- // Evict LRU if pool is full
1659
- if (this.connections.size > this.maxConnections) await this.evictLRU();
1660
- console.log(`✅ Database created: ${name}`);
1661
- }
1662
- /**
1663
- * Check if a database exists
1664
- * @param name - Database name
1665
- * @returns true if database exists, false otherwise
1666
- *
1667
- * Note: For local backends (libsql, bun-sqlite), checks file existence.
1668
- * For ODB-Lite, checks if database is in connection cache.
1669
- */ async databaseExists(name) {
1670
- // Check if already in connection cache
1671
- if (this.connections.has(name)) return true;
1672
- // For local file-based backends, check if file exists
1673
- switch(this.config.backend){
1674
- case 'bun-sqlite':
1675
- {
1676
- const dbPath = `${this.config.databasePath}/${name}.db`;
1677
- return external_node_fs_default().existsSync(dbPath);
1678
- }
1679
- case 'libsql':
1680
- {
1681
- const dbPath = `${this.config.databasePath}/${name}.db`;
1682
- return external_node_fs_default().existsSync(dbPath);
1752
+ processedLine += char;
1753
+ if (';' === char && !inQuote && 0 === beginEndDepth) {
1754
+ currentStatement += processedLine;
1755
+ const stmt = currentStatement.trim();
1756
+ if (stmt && !stmt.startsWith('--')) statements.push(stmt);
1757
+ currentStatement = '';
1758
+ processedLine = '';
1683
1759
  }
1684
- case 'odblite':
1685
- // For ODB-Lite, only return true if in cache
1686
- // (no way to check remote database existence without connecting)
1687
- return false;
1688
- default:
1689
- return false;
1760
+ }
1761
+ if (processedLine.trim()) currentStatement += `${processedLine}\n`;
1690
1762
  }
1763
+ const finalStmt = currentStatement.trim();
1764
+ if (finalStmt && !finalStmt.startsWith('--')) statements.push(finalStmt);
1765
+ return statements;
1766
+ }
1767
+ function splitSQLStatements(sqlContent) {
1768
+ const { pragmaStatements, regularStatements } = parseSQL(sqlContent);
1769
+ return [
1770
+ ...pragmaStatements,
1771
+ ...regularStatements
1772
+ ];
1691
1773
  }
1692
- /**
1693
- * Get connection to a database
1694
- * @param name - Database name
1695
- *
1696
- * If database exists on disk but not in cache, it will be connected automatically.
1697
- * If database doesn't exist at all, an error will be thrown.
1698
- */ async getConnection(name) {
1699
- // Check if connection exists in cache
1700
- let conn = this.connections.get(name);
1701
- if (conn) {
1702
- this.connectionTimestamps.set(name, Date.now());
1703
- return conn;
1774
+ const external_node_fs_namespaceObject = require("node:fs");
1775
+ var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
1776
+ class DatabaseManager {
1777
+ config;
1778
+ adapter;
1779
+ connections = new Map();
1780
+ connectionTimestamps = new Map();
1781
+ maxConnections;
1782
+ constructor(config){
1783
+ this.config = config;
1784
+ this.maxConnections = config.connectionPoolSize || 10;
1785
+ switch(config.backend){
1786
+ case 'bun-sqlite':
1787
+ this.adapter = new BunSQLiteAdapter({
1788
+ databasePath: config.databasePath,
1789
+ create: true
1790
+ });
1791
+ break;
1792
+ case 'libsql':
1793
+ this.adapter = new LibSQLAdapter({
1794
+ url: `file:${config.databasePath}`,
1795
+ ...config.libsql
1796
+ });
1797
+ break;
1798
+ case 'odblite':
1799
+ if (!config.odblite) throw new Error('odblite config required for odblite backend');
1800
+ this.adapter = new ODBLiteAdapter(config.odblite);
1801
+ break;
1802
+ default:
1803
+ throw new Error(`Unknown backend type: ${config.backend}`);
1804
+ }
1704
1805
  }
1705
- // Check if database exists on disk
1706
- const exists = await this.databaseExists(name);
1707
- if (exists) {
1708
- // Connect to existing database
1806
+ async createDatabase(name, options) {
1807
+ console.log(`📦 Creating database: ${name}`);
1709
1808
  const dbConfig = this.getDatabaseConfig(name);
1710
- conn = await this.adapter.connect(dbConfig);
1711
- // Store connection
1809
+ const conn = await this.adapter.connect(dbConfig);
1810
+ if (options?.schemaContent) await this.runMigrations(conn, {
1811
+ schemaContent: options.schemaContent
1812
+ });
1712
1813
  this.connections.set(name, conn);
1713
1814
  this.connectionTimestamps.set(name, Date.now());
1714
- // Evict LRU if pool is full
1715
1815
  if (this.connections.size > this.maxConnections) await this.evictLRU();
1816
+ console.log(`✅ Database created: ${name}`);
1716
1817
  return conn;
1717
1818
  }
1718
- // If database doesn't exist, throw error
1719
- throw new Error(`Database "${name}" not found. Call createDatabase("${name}", { schemaContent }) first.`);
1720
- }
1721
- /**
1722
- * Delete a database
1723
- * @param name - Database name
1724
- */ async deleteDatabase(name) {
1725
- console.log(`🗑️ Deleting database: ${name}`);
1726
- // Close connection if exists
1727
- const conn = this.connections.get(name);
1728
- if (conn) {
1729
- await conn.close();
1730
- this.connections.delete(name);
1731
- this.connectionTimestamps.delete(name);
1732
- }
1733
- // Backend-specific deletion
1734
- await this.adapter.disconnect(name);
1735
- console.log(`✅ Database deleted: ${name}`);
1736
- }
1737
- /**
1738
- * Execute SQL content on a database connection
1739
- * Useful for running migrations or initial schema
1740
- * @param name - Database name
1741
- * @param sqlContent - SQL content to execute
1742
- */ async executeSQLFile(name, sqlContent) {
1743
- const conn = await this.getConnection(name);
1744
- await this.runMigrations(conn, {
1745
- schemaContent: sqlContent
1746
- });
1747
- }
1748
- /**
1749
- * List all managed databases
1750
- */ async listDatabases() {
1751
- return Array.from(this.connections.keys());
1752
- }
1753
- /**
1754
- * Close all connections
1755
- */ async close() {
1756
- console.log(`🔌 Closing all database connections...`);
1757
- for (const [name, conn] of this.connections)await conn.close();
1758
- this.connections.clear();
1759
- this.connectionTimestamps.clear();
1760
- console.log(`✅ All connections closed`);
1761
- }
1762
- /**
1763
- * Run migrations on a connection
1764
- */ async runMigrations(conn, config) {
1765
- // Parse SQL statements
1766
- const { pragmaStatements, regularStatements } = parseSQL(config.schemaContent);
1767
- // Execute PRAGMA statements first
1768
- for (const pragma of pragmaStatements)try {
1769
- await conn.execute(pragma);
1770
- } catch (error) {
1771
- // Ignore PRAGMA errors (they might not be supported on all backends)
1772
- console.log(`⚠️ PRAGMA note: ${error.message}`);
1773
- }
1774
- // Execute regular statements
1775
- for (const statement of regularStatements)try {
1776
- await conn.execute(statement);
1777
- } catch (error) {
1778
- // Ignore "already exists" errors for idempotency
1779
- if (error.message?.includes('already exists') || error.message?.includes('no such column') || error.message?.includes('no such table')) {
1780
- console.log(` ⚠️ Skipping: ${error.message}`);
1781
- continue;
1782
- }
1783
- console.error(`❌ Migration failed: ${statement.substring(0, 100)}...`);
1784
- throw error;
1785
- }
1786
- console.log(`✅ Migrations completed (${regularStatements.length} statements)`);
1787
- }
1788
- /**
1789
- * Get database-specific configuration
1790
- */ getDatabaseConfig(name) {
1791
- switch(this.config.backend){
1792
- case 'bun-sqlite':
1793
- return {
1794
- databasePath: `${this.config.databasePath}/${name}.db`,
1795
- create: true
1796
- };
1797
- case 'libsql':
1798
- return {
1799
- url: `file:${this.config.databasePath}/${name}.db`,
1800
- ...this.config.libsql
1801
- };
1802
- case 'odblite':
1803
- return {
1804
- databaseName: `${this.config.databasePath}_${name}`,
1805
- ...this.config.odblite
1806
- };
1807
- default:
1808
- throw new Error(`Unknown backend: ${this.config.backend}`);
1819
+ async databaseExists(name) {
1820
+ if (this.connections.has(name)) return true;
1821
+ switch(this.config.backend){
1822
+ case 'bun-sqlite':
1823
+ {
1824
+ const dbPath = `${this.config.databasePath}/${name}.db`;
1825
+ return external_node_fs_default().existsSync(dbPath);
1826
+ }
1827
+ case 'libsql':
1828
+ {
1829
+ const dbPath = `${this.config.databasePath}/${name}.db`;
1830
+ return external_node_fs_default().existsSync(dbPath);
1831
+ }
1832
+ case 'odblite':
1833
+ return false;
1834
+ default:
1835
+ return false;
1836
+ }
1809
1837
  }
1810
- }
1811
- /**
1812
- * Evict least recently used connection
1813
- */ async evictLRU() {
1814
- let oldestKey = null;
1815
- let oldestTime = 1 / 0;
1816
- for (const [key, timestamp] of this.connectionTimestamps)if (timestamp < oldestTime) {
1817
- oldestTime = timestamp;
1818
- oldestKey = key;
1819
- }
1820
- if (oldestKey) {
1821
- const conn = this.connections.get(oldestKey);
1822
- if (conn) await conn.close();
1823
- this.connections.delete(oldestKey);
1824
- this.connectionTimestamps.delete(oldestKey);
1825
- console.log(`♻️ Evicted LRU connection: ${oldestKey}`);
1838
+ async getConnection(name) {
1839
+ let conn = this.connections.get(name);
1840
+ if (conn) {
1841
+ this.connectionTimestamps.set(name, Date.now());
1842
+ return conn;
1843
+ }
1844
+ const exists = await this.databaseExists(name);
1845
+ if (exists) {
1846
+ const dbConfig = this.getDatabaseConfig(name);
1847
+ conn = await this.adapter.connect(dbConfig);
1848
+ this.connections.set(name, conn);
1849
+ this.connectionTimestamps.set(name, Date.now());
1850
+ if (this.connections.size > this.maxConnections) await this.evictLRU();
1851
+ return conn;
1852
+ }
1853
+ throw new Error(`Database "${name}" not found. Call createDatabase("${name}", { schemaContent }) first.`);
1854
+ }
1855
+ async deleteDatabase(name) {
1856
+ console.log(`🗑️ Deleting database: ${name}`);
1857
+ const conn = this.connections.get(name);
1858
+ if (conn) {
1859
+ await conn.close();
1860
+ this.connections.delete(name);
1861
+ this.connectionTimestamps.delete(name);
1862
+ }
1863
+ await this.adapter.disconnect(name);
1864
+ console.log(`✅ Database deleted: ${name}`);
1865
+ }
1866
+ async executeSQLFile(name, sqlContent) {
1867
+ const conn = await this.getConnection(name);
1868
+ await this.runMigrations(conn, {
1869
+ schemaContent: sqlContent
1870
+ });
1871
+ }
1872
+ async listDatabases() {
1873
+ return Array.from(this.connections.keys());
1874
+ }
1875
+ async close() {
1876
+ console.log(`🔌 Closing all database connections...`);
1877
+ for (const [name, conn] of this.connections)await conn.close();
1878
+ this.connections.clear();
1879
+ this.connectionTimestamps.clear();
1880
+ console.log(`✅ All connections closed`);
1881
+ }
1882
+ async runMigrations(conn, config) {
1883
+ const { pragmaStatements, regularStatements } = parseSQL(config.schemaContent);
1884
+ for (const pragma of pragmaStatements)try {
1885
+ await conn.execute(pragma);
1886
+ } catch (error) {
1887
+ console.log(`⚠️ PRAGMA note: ${error.message}`);
1888
+ }
1889
+ for (const statement of regularStatements)try {
1890
+ await conn.execute(statement);
1891
+ } catch (error) {
1892
+ if (error.message?.includes('already exists') || error.message?.includes('no such column') || error.message?.includes('no such table')) {
1893
+ console.log(` ⚠️ Skipping: ${error.message}`);
1894
+ continue;
1895
+ }
1896
+ console.error(`❌ Migration failed: ${statement.substring(0, 100)}...`);
1897
+ throw error;
1898
+ }
1899
+ console.log(`✅ Migrations completed (${regularStatements.length} statements)`);
1900
+ }
1901
+ getDatabaseConfig(name) {
1902
+ switch(this.config.backend){
1903
+ case 'bun-sqlite':
1904
+ return {
1905
+ databasePath: `${this.config.databasePath}/${name}.db`,
1906
+ create: true
1907
+ };
1908
+ case 'libsql':
1909
+ return {
1910
+ url: `file:${this.config.databasePath}/${name}.db`,
1911
+ ...this.config.libsql
1912
+ };
1913
+ case 'odblite':
1914
+ return {
1915
+ databaseName: `${this.config.databasePath}_${name}`,
1916
+ ...this.config.odblite
1917
+ };
1918
+ default:
1919
+ throw new Error(`Unknown backend: ${this.config.backend}`);
1920
+ }
1921
+ }
1922
+ async evictLRU() {
1923
+ let oldestKey = null;
1924
+ let oldestTime = 1 / 0;
1925
+ for (const [key, timestamp] of this.connectionTimestamps)if (timestamp < oldestTime) {
1926
+ oldestTime = timestamp;
1927
+ oldestKey = key;
1928
+ }
1929
+ if (oldestKey) {
1930
+ const conn = this.connections.get(oldestKey);
1931
+ if (conn) await conn.close();
1932
+ this.connections.delete(oldestKey);
1933
+ this.connectionTimestamps.delete(oldestKey);
1934
+ console.log(`♻️ Evicted LRU connection: ${oldestKey}`);
1935
+ }
1826
1936
  }
1827
1937
  }
1828
- }
1829
- // Main entry point for ODB Client
1830
- // Core query client exports (postgres.js-like interface)
1831
- // Service management exports (high-level tenant database management)
1832
- // Database Manager exports (unified multi-backend database abstraction)
1833
- // Export error classes
1834
- // Export static utility functions for easy access
1835
- const { raw: src_raw, identifier: src_identifier, where: src_where, insertValues: src_insertValues, updateSet: src_updateSet, join: src_join } = ODBLiteClient;
1836
- // Default export for convenient usage
1837
- var __webpack_export_target__ = exports;
1838
- for(var i in __webpack_exports__)__webpack_export_target__[i] = __webpack_exports__[i];
1839
- if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, '__esModule', {
1938
+ var orm = __webpack_require__("./src/orm/index.ts");
1939
+ const { raw: src_raw, identifier: src_identifier, where: src_where, insertValues: src_insertValues, updateSet: src_updateSet, join: src_join } = ODBLiteClient;
1940
+ })();
1941
+ exports.BunSQLiteAdapter = __webpack_exports__.BunSQLiteAdapter;
1942
+ exports.ConnectionError = __webpack_exports__.ConnectionError;
1943
+ exports.DatabaseManager = __webpack_exports__.DatabaseManager;
1944
+ exports.HTTPClient = __webpack_exports__.HTTPClient;
1945
+ exports.LibSQLAdapter = __webpack_exports__.LibSQLAdapter;
1946
+ exports.ODBLiteAdapter = __webpack_exports__.ODBLiteAdapter;
1947
+ exports.ODBLiteClient = __webpack_exports__.ODBLiteClient;
1948
+ exports.ODBLiteError = __webpack_exports__.ODBLiteError;
1949
+ exports.ODBLiteTransaction = __webpack_exports__.ODBLiteTransaction;
1950
+ exports.ORM = __webpack_exports__.ORM;
1951
+ exports.QueryError = __webpack_exports__.QueryError;
1952
+ exports.SQLParser = __webpack_exports__.SQLParser;
1953
+ exports.ServiceClient = __webpack_exports__.ServiceClient;
1954
+ exports.SimpleTransaction = __webpack_exports__.SimpleTransaction;
1955
+ exports.and = __webpack_exports__.and;
1956
+ exports.convertTemplateToQuery = __webpack_exports__.convertTemplateToQuery;
1957
+ exports.createORM = __webpack_exports__.createORM;
1958
+ exports["default"] = __webpack_exports__["default"];
1959
+ exports.empty = __webpack_exports__.empty;
1960
+ exports.eq = __webpack_exports__.eq;
1961
+ exports.fragment = __webpack_exports__.fragment;
1962
+ exports.gt = __webpack_exports__.gt;
1963
+ exports.gte = __webpack_exports__.gte;
1964
+ exports.identifier = __webpack_exports__.identifier;
1965
+ exports.inArray = __webpack_exports__.inArray;
1966
+ exports.insertValues = __webpack_exports__.insertValues;
1967
+ exports.isNotNull = __webpack_exports__.isNotNull;
1968
+ exports.isNull = __webpack_exports__.isNull;
1969
+ exports.join = __webpack_exports__.join;
1970
+ exports.like = __webpack_exports__.like;
1971
+ exports.lt = __webpack_exports__.lt;
1972
+ exports.lte = __webpack_exports__.lte;
1973
+ exports.ne = __webpack_exports__.ne;
1974
+ exports.odblite = __webpack_exports__.odblite;
1975
+ exports.or = __webpack_exports__.or;
1976
+ exports.parseSQL = __webpack_exports__.parseSQL;
1977
+ exports.raw = __webpack_exports__.raw;
1978
+ exports.rawSQL = __webpack_exports__.rawSQL;
1979
+ exports.set = __webpack_exports__.set;
1980
+ exports.splitSQLStatements = __webpack_exports__.splitSQLStatements;
1981
+ exports.sql = __webpack_exports__.sql;
1982
+ exports.sqlFragment = __webpack_exports__.sqlFragment;
1983
+ exports.sqlJoin = __webpack_exports__.sqlJoin;
1984
+ exports.sqlTemplate = __webpack_exports__.sqlTemplate;
1985
+ exports.sqlWhere = __webpack_exports__.sqlWhere;
1986
+ exports.updateSet = __webpack_exports__.updateSet;
1987
+ exports.where = __webpack_exports__.where;
1988
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
1989
+ "BunSQLiteAdapter",
1990
+ "ConnectionError",
1991
+ "DatabaseManager",
1992
+ "HTTPClient",
1993
+ "LibSQLAdapter",
1994
+ "ODBLiteAdapter",
1995
+ "ODBLiteClient",
1996
+ "ODBLiteError",
1997
+ "ODBLiteTransaction",
1998
+ "ORM",
1999
+ "QueryError",
2000
+ "SQLParser",
2001
+ "ServiceClient",
2002
+ "SimpleTransaction",
2003
+ "and",
2004
+ "convertTemplateToQuery",
2005
+ "createORM",
2006
+ "default",
2007
+ "empty",
2008
+ "eq",
2009
+ "fragment",
2010
+ "gt",
2011
+ "gte",
2012
+ "identifier",
2013
+ "inArray",
2014
+ "insertValues",
2015
+ "isNotNull",
2016
+ "isNull",
2017
+ "join",
2018
+ "like",
2019
+ "lt",
2020
+ "lte",
2021
+ "ne",
2022
+ "odblite",
2023
+ "or",
2024
+ "parseSQL",
2025
+ "raw",
2026
+ "rawSQL",
2027
+ "set",
2028
+ "splitSQLStatements",
2029
+ "sql",
2030
+ "sqlFragment",
2031
+ "sqlJoin",
2032
+ "sqlTemplate",
2033
+ "sqlWhere",
2034
+ "updateSet",
2035
+ "where"
2036
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
2037
+ Object.defineProperty(exports, '__esModule', {
1840
2038
  value: true
1841
2039
  });