@groundbrick/db-core 0.0.1

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 (102) hide show
  1. package/README.md +214 -0
  2. package/dist/adapters/BaseSqlAdapter.d.ts +14 -0
  3. package/dist/adapters/BaseSqlAdapter.d.ts.map +1 -0
  4. package/dist/adapters/BaseSqlAdapter.js +37 -0
  5. package/dist/adapters/BaseSqlAdapter.js.map +1 -0
  6. package/dist/adapters/DatabaseAdapter.d.ts +59 -0
  7. package/dist/adapters/DatabaseAdapter.d.ts.map +1 -0
  8. package/dist/adapters/DatabaseAdapter.js +120 -0
  9. package/dist/adapters/DatabaseAdapter.js.map +1 -0
  10. package/dist/base/BaseTransaction.d.ts +65 -0
  11. package/dist/base/BaseTransaction.d.ts.map +1 -0
  12. package/dist/base/BaseTransaction.js +134 -0
  13. package/dist/base/BaseTransaction.js.map +1 -0
  14. package/dist/custom-types/MigrationRecord.d.ts +6 -0
  15. package/dist/custom-types/MigrationRecord.d.ts.map +1 -0
  16. package/dist/custom-types/MigrationRecord.js +2 -0
  17. package/dist/custom-types/MigrationRecord.js.map +1 -0
  18. package/dist/custom-types/QueryParams.d.ts +5 -0
  19. package/dist/custom-types/QueryParams.d.ts.map +1 -0
  20. package/dist/custom-types/QueryParams.js +2 -0
  21. package/dist/custom-types/QueryParams.js.map +1 -0
  22. package/dist/custom-types/Transaction.d.ts +6 -0
  23. package/dist/custom-types/Transaction.d.ts.map +1 -0
  24. package/dist/custom-types/Transaction.js +2 -0
  25. package/dist/custom-types/Transaction.js.map +1 -0
  26. package/dist/custom-types/TransactionCallback.d.ts +3 -0
  27. package/dist/custom-types/TransactionCallback.d.ts.map +1 -0
  28. package/dist/custom-types/TransactionCallback.js +2 -0
  29. package/dist/custom-types/TransactionCallback.js.map +1 -0
  30. package/dist/error-handling/ConnectionError.d.ts +8 -0
  31. package/dist/error-handling/ConnectionError.d.ts.map +1 -0
  32. package/dist/error-handling/ConnectionError.js +11 -0
  33. package/dist/error-handling/ConnectionError.js.map +1 -0
  34. package/dist/error-handling/DatabaseError.d.ts +18 -0
  35. package/dist/error-handling/DatabaseError.d.ts.map +1 -0
  36. package/dist/error-handling/DatabaseError.js +22 -0
  37. package/dist/error-handling/DatabaseError.js.map +1 -0
  38. package/dist/error-handling/MigrationError.d.ts +8 -0
  39. package/dist/error-handling/MigrationError.d.ts.map +1 -0
  40. package/dist/error-handling/MigrationError.js +11 -0
  41. package/dist/error-handling/MigrationError.js.map +1 -0
  42. package/dist/error-handling/QueryError.d.ts +8 -0
  43. package/dist/error-handling/QueryError.d.ts.map +1 -0
  44. package/dist/error-handling/QueryError.js +11 -0
  45. package/dist/error-handling/QueryError.js.map +1 -0
  46. package/dist/error-handling/TransactionError.d.ts +8 -0
  47. package/dist/error-handling/TransactionError.d.ts.map +1 -0
  48. package/dist/error-handling/TransactionError.js +11 -0
  49. package/dist/error-handling/TransactionError.js.map +1 -0
  50. package/dist/index.d.ts +138 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +105 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/interfaces/ConfigValidator.d.ts +10 -0
  55. package/dist/interfaces/ConfigValidator.d.ts.map +1 -0
  56. package/dist/interfaces/ConfigValidator.js +2 -0
  57. package/dist/interfaces/ConfigValidator.js.map +1 -0
  58. package/dist/interfaces/DatabaseClient.d.ts +18 -0
  59. package/dist/interfaces/DatabaseClient.d.ts.map +1 -0
  60. package/dist/interfaces/DatabaseClient.js +2 -0
  61. package/dist/interfaces/DatabaseClient.js.map +1 -0
  62. package/dist/interfaces/DatabaseConfig.d.ts +22 -0
  63. package/dist/interfaces/DatabaseConfig.d.ts.map +1 -0
  64. package/dist/interfaces/DatabaseConfig.js +2 -0
  65. package/dist/interfaces/DatabaseConfig.js.map +1 -0
  66. package/dist/interfaces/DatabaseFactory.d.ts +11 -0
  67. package/dist/interfaces/DatabaseFactory.d.ts.map +1 -0
  68. package/dist/interfaces/DatabaseFactory.js +2 -0
  69. package/dist/interfaces/DatabaseFactory.js.map +1 -0
  70. package/dist/interfaces/DatabaseTransaction.d.ts +31 -0
  71. package/dist/interfaces/DatabaseTransaction.d.ts.map +1 -0
  72. package/dist/interfaces/DatabaseTransaction.js +2 -0
  73. package/dist/interfaces/DatabaseTransaction.js.map +1 -0
  74. package/dist/interfaces/HealthCheckResult.d.ts +14 -0
  75. package/dist/interfaces/HealthCheckResult.d.ts.map +1 -0
  76. package/dist/interfaces/HealthCheckResult.js +2 -0
  77. package/dist/interfaces/HealthCheckResult.js.map +1 -0
  78. package/dist/interfaces/Migration.d.ts +11 -0
  79. package/dist/interfaces/Migration.d.ts.map +1 -0
  80. package/dist/interfaces/Migration.js +2 -0
  81. package/dist/interfaces/Migration.js.map +1 -0
  82. package/dist/interfaces/MigrationManager.d.ts +31 -0
  83. package/dist/interfaces/MigrationManager.d.ts.map +1 -0
  84. package/dist/interfaces/MigrationManager.js +2 -0
  85. package/dist/interfaces/MigrationManager.js.map +1 -0
  86. package/dist/interfaces/MigrationStatus.d.ts +10 -0
  87. package/dist/interfaces/MigrationStatus.d.ts.map +1 -0
  88. package/dist/interfaces/MigrationStatus.js +2 -0
  89. package/dist/interfaces/MigrationStatus.js.map +1 -0
  90. package/dist/interfaces/QueryResult.d.ts +14 -0
  91. package/dist/interfaces/QueryResult.d.ts.map +1 -0
  92. package/dist/interfaces/QueryResult.js +2 -0
  93. package/dist/interfaces/QueryResult.js.map +1 -0
  94. package/dist/interfaces/SqlAdapter.d.ts +11 -0
  95. package/dist/interfaces/SqlAdapter.d.ts.map +1 -0
  96. package/dist/interfaces/SqlAdapter.js +2 -0
  97. package/dist/interfaces/SqlAdapter.js.map +1 -0
  98. package/dist/interfaces/index.d.ts +14 -0
  99. package/dist/interfaces/index.d.ts.map +1 -0
  100. package/dist/interfaces/index.js +3 -0
  101. package/dist/interfaces/index.js.map +1 -0
  102. package/package.json +56 -0
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+
2
+ # @groundbrick/db-core
3
+
4
+ **Database abstraction core for the BitBrick microframework**
5
+
6
+ This package provides the backbone for integrating with relational databases (PostgreSQL or MySQL), offering a unified layer for connection handling, querying, transactions, and migrations.
7
+
8
+ ---
9
+
10
+ ## 🔧 Key Features
11
+
12
+ - Unified interface for database clients
13
+ - Adapter support for PostgreSQL and MySQL (via external factories)
14
+ - Full support for transactions
15
+ - Strongly-typed migration system
16
+ - Configuration validation and health checks
17
+ - Granular error handling by operation type
18
+
19
+ ---
20
+
21
+ ## 📦 Installation
22
+
23
+ ```bash
24
+ npm install @groundbrick/db-core
25
+ ```
26
+
27
+ > You will also need to install a specific adapter package such as `@groundbrick/db-postgres` or `@groundbrick/db-mysql`.
28
+
29
+ ---
30
+
31
+ ## 🚀 Quick Start
32
+
33
+ ```ts
34
+ import { DatabaseAdapter } from '@groundbrick/db-core';
35
+
36
+ const adapter = new DatabaseAdapter({
37
+ type: 'postgresql',
38
+ host: 'localhost',
39
+ user: 'admin',
40
+ password: 'secret',
41
+ database: 'mydb',
42
+ port: 5432
43
+ });
44
+
45
+ await adapter.initialize();
46
+
47
+ const users = await adapter.query('SELECT * FROM users WHERE active = $1', [true]);
48
+
49
+ await adapter.close();
50
+ ```
51
+
52
+ ---
53
+
54
+ ## 🔄 Transactions
55
+
56
+ ```ts
57
+ await adapter.transaction(async (trx) => {
58
+ await trx.query('INSERT INTO logs (event, ts) VALUES ($1, now())', ['create_user']);
59
+
60
+ const result = await trx.query<{ id: number }>(
61
+ 'INSERT INTO users (email, active) VALUES ($1, $2) RETURNING id',
62
+ ['user@example.com', true]
63
+ );
64
+
65
+ const userId = result.rows[0].id;
66
+
67
+ await trx.query('INSERT INTO profiles (user_id) VALUES ($1)', [userId]);
68
+ });
69
+ ```
70
+
71
+ - The transaction will automatically **commit** if successful
72
+ - Any thrown error will **rollback** the transaction
73
+ - Nested transactions are not natively supported
74
+
75
+ ---
76
+
77
+ ## 🧪 Health Check
78
+
79
+ ```ts
80
+ const status = await adapter.healthCheck();
81
+
82
+ if (status.status !== 'ok') {
83
+ throw new Error(`Database unavailable: ${status.reason}`);
84
+ }
85
+ ```
86
+
87
+ ---
88
+
89
+ ## 🔍 Pool Info (if supported by the adapter)
90
+
91
+ ```ts
92
+ const pool = adapter.getClient().getConnectionInfo?.();
93
+ if (pool) {
94
+ console.log(`Pool: total=${pool.total}, idle=${pool.idle}, waiting=${pool.waiting}`);
95
+ }
96
+ ```
97
+
98
+ ---
99
+
100
+ ## ⏱ Readiness Check
101
+
102
+ ```ts
103
+ if (!adapter.isReady()) {
104
+ console.warn('Adapter is not ready yet.');
105
+ }
106
+ ```
107
+
108
+ ---
109
+
110
+ ## 📦 Architecture Overview
111
+
112
+ ### 🔌 DatabaseAdapter
113
+
114
+ This class encapsulates adapter selection (PostgreSQL or MySQL), dynamically initializes the correct client, and exposes high-level methods:
115
+
116
+ - `.initialize()` / `.close()`
117
+ - `.query(sql, params)`
118
+ - `.transaction(cb)`
119
+ - `.healthCheck()`
120
+ - `.getClient()` (direct access to `DatabaseClient`)
121
+
122
+ > The dynamic loading logic (e.g., `PostgresFactory.getInstance`) must be implemented in the actual adapter packages.
123
+
124
+ ### 🧠 `DatabaseClient` Interface
125
+
126
+ Contract that all database adapters must implement:
127
+
128
+ ```ts
129
+ interface DatabaseClient {
130
+ initialize(): Promise<void>;
131
+ close(): Promise<void>;
132
+ query<T>(sql: string, params?: any[]): Promise<QueryResult<T>>;
133
+ transaction<T>(cb: (trx: DatabaseTransaction) => Promise<T>): Promise<T>;
134
+ healthCheck(): Promise<HealthCheckResult>;
135
+ isReady(): boolean;
136
+ }
137
+ ```
138
+
139
+ ### 🔄 `DatabaseTransaction`
140
+
141
+ Within a transaction, the callback receives a `DatabaseTransaction` instance, allowing you to perform isolated queries.
142
+
143
+ ---
144
+
145
+ ## 📁 Project Structure
146
+
147
+ ```
148
+ db-core/
149
+ ├── src/
150
+ │ ├── adapters/ # Generic adapter layer
151
+ │ ├── base/ # Reusable base logic (e.g., transactions)
152
+ │ ├── custom-types/ # Utility and internal types
153
+ │ ├── error-handling/ # Operation-specific error classes
154
+ │ ├── interfaces/ # Public contract definitions
155
+ │ └── index.ts # Entry point
156
+ ```
157
+
158
+ ---
159
+
160
+ ## 🧬 Migrations
161
+
162
+ The core defines types for managing and recording schema migrations. You can implement your own `MigrationManager`:
163
+
164
+ ```ts
165
+ const manager: MigrationManager = getCustomMigrationManager();
166
+
167
+ const pending = await manager.getPendingMigrations();
168
+
169
+ for (const migration of pending) {
170
+ try {
171
+ await manager.applyMigration(migration);
172
+ console.log(`Migration ${migration.version} applied`);
173
+ } catch (err) {
174
+ console.error(`Failed to apply migration ${migration.version}:`, err);
175
+ break;
176
+ }
177
+ }
178
+ ```
179
+
180
+ Each migration should follow the `Migration` type contract with `up`, `down`, and `version` fields.
181
+
182
+ ---
183
+
184
+ ## 💣 Error Handling
185
+
186
+ All operations raise specific error classes for easier diagnosis:
187
+
188
+ - `ConnectionError`
189
+ - `QueryError`
190
+ - `MigrationError`
191
+ - `TransactionError`
192
+ - `DatabaseError` (generic base class)
193
+
194
+ ---
195
+
196
+ ## 🧩 Creating a Custom Adapter
197
+
198
+ Example: PostgreSQL Adapter Factory
199
+
200
+ ```ts
201
+ export class PostgresFactory {
202
+ static getInstance(config: DatabaseConfig, logger: Logger): DatabaseClient {
203
+ return new PostgresClient(config, logger);
204
+ }
205
+ }
206
+ ```
207
+
208
+ Inside `DatabaseAdapter`, you would dynamically import and use this factory depending on the type.
209
+
210
+ ---
211
+
212
+ ## 📝 License
213
+
214
+ MIT — © 200Systems
@@ -0,0 +1,14 @@
1
+ import { SqlAdapter } from "../interfaces/SqlAdapter.js";
2
+ export declare abstract class BaseSqlAdapter implements SqlAdapter {
3
+ abstract adaptSql(sql: string): string;
4
+ abstract getDatabaseType(): 'postgresql' | 'mysql';
5
+ abstract supportsReturning(): boolean;
6
+ createInsertSql(tableName: string, columns: string[]): string;
7
+ createUpdateSql(tableName: string, columns: string[]): string;
8
+ createDeleteSql(tableName: string): string;
9
+ getNowFunction(): string;
10
+ getLimitClause(limit: number, offset?: number): string;
11
+ protected abstract createPlaceholder(index: number): string;
12
+ protected createPlaceholders(count: number): string;
13
+ }
14
+ //# sourceMappingURL=BaseSqlAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseSqlAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/BaseSqlAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,8BAAsB,cAAe,YAAW,UAAU;IACtD,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IACtC,QAAQ,CAAC,eAAe,IAAI,YAAY,GAAG,OAAO;IAClD,QAAQ,CAAC,iBAAiB,IAAI,OAAO;IAErC,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM;IAW7D,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM;IAe7D,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAI1C,cAAc,IAAI,MAAM;IAIxB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM;IAOzD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAE3D,SAAS,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAGtD"}
@@ -0,0 +1,37 @@
1
+ export class BaseSqlAdapter {
2
+ createInsertSql(tableName, columns) {
3
+ const placeholders = this.createPlaceholders(columns.length);
4
+ let sql = `INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`;
5
+ if (this.supportsReturning()) {
6
+ sql += ' RETURNING *';
7
+ }
8
+ return sql;
9
+ }
10
+ createUpdateSql(tableName, columns) {
11
+ const setParts = columns.map((col, index) => {
12
+ return `${col} = ${this.createPlaceholder(index + 1)}`;
13
+ });
14
+ const idPlaceholder = this.createPlaceholder(columns.length + 1);
15
+ let sql = `UPDATE ${tableName} SET ${setParts.join(', ')} WHERE id = ${idPlaceholder}`;
16
+ if (this.supportsReturning()) {
17
+ sql += ' RETURNING *';
18
+ }
19
+ return sql;
20
+ }
21
+ createDeleteSql(tableName) {
22
+ return this.adaptSql(`DELETE FROM ${tableName} WHERE id = ?`);
23
+ }
24
+ getNowFunction() {
25
+ return 'NOW()';
26
+ }
27
+ getLimitClause(limit, offset = 0) {
28
+ if (offset > 0) {
29
+ return `LIMIT ${limit} OFFSET ${offset}`;
30
+ }
31
+ return `LIMIT ${limit}`;
32
+ }
33
+ createPlaceholders(count) {
34
+ return Array.from({ length: count }, (_, i) => this.createPlaceholder(i + 1)).join(', ');
35
+ }
36
+ }
37
+ //# sourceMappingURL=BaseSqlAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseSqlAdapter.js","sourceRoot":"","sources":["../../src/adapters/BaseSqlAdapter.ts"],"names":[],"mappings":"AAEA,MAAM,OAAgB,cAAc;IAKhC,eAAe,CAAC,SAAiB,EAAE,OAAiB;QAChD,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,GAAG,GAAG,eAAe,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,YAAY,GAAG,CAAC;QAEtF,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YAC3B,GAAG,IAAI,cAAc,CAAC;QAC1B,CAAC;QAED,OAAO,GAAG,CAAC;IACf,CAAC;IAED,eAAe,CAAC,SAAiB,EAAE,OAAiB;QAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACxC,OAAO,GAAG,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACjE,IAAI,GAAG,GAAG,UAAU,SAAS,QAAQ,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,aAAa,EAAE,CAAC;QAEvF,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YAC3B,GAAG,IAAI,cAAc,CAAC;QAC1B,CAAC;QAED,OAAO,GAAG,CAAC;IACf,CAAC;IAED,eAAe,CAAC,SAAiB;QAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,SAAS,eAAe,CAAC,CAAC;IAClE,CAAC;IAED,cAAc;QACV,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,cAAc,CAAC,KAAa,EAAE,SAAiB,CAAC;QAC5C,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACb,OAAO,SAAS,KAAK,WAAW,MAAM,EAAE,CAAC;QAC7C,CAAC;QACD,OAAO,SAAS,KAAK,EAAE,CAAC;IAC5B,CAAC;IAIS,kBAAkB,CAAC,KAAa;QACtC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7F,CAAC;CACJ"}
@@ -0,0 +1,59 @@
1
+ import { Logger } from '@groundbrick/logger';
2
+ import { DatabaseClient, DatabaseConfig } from '../interfaces/index.js';
3
+ export type DatabaseType = 'postgresql' | 'mysql';
4
+ export interface AdapterConfig extends DatabaseConfig {
5
+ type: DatabaseType;
6
+ }
7
+ /**
8
+ * Database Adapter that provides a unified interface for both PostgreSQL and MySQL
9
+ * This allows easy switching between database types without changing application code
10
+ */
11
+ export declare class DatabaseAdapter {
12
+ private client;
13
+ private logger;
14
+ private dbType;
15
+ constructor(config: AdapterConfig, logger?: Logger);
16
+ private createPostgresClient;
17
+ private createMySQLClient;
18
+ /**
19
+ * Get the database type
20
+ */
21
+ getDatabaseType(): DatabaseType;
22
+ /**
23
+ * Initialize the database connection
24
+ */
25
+ initialize(): Promise<void>;
26
+ /**
27
+ * Close the database connection
28
+ */
29
+ close(): Promise<void>;
30
+ /**
31
+ * Get the underlying database client
32
+ * This allows access to all database-specific methods
33
+ */
34
+ getClient(): DatabaseClient;
35
+ /**
36
+ * Execute a database-agnostic query
37
+ */
38
+ query<T = any>(sql: string, params?: any[]): Promise<{
39
+ rows: T[];
40
+ rowCount: number;
41
+ }>;
42
+ /**
43
+ * Execute a transaction with unified interface
44
+ */
45
+ transaction<T>(callback: (client: DatabaseClient) => Promise<T>): Promise<T>;
46
+ /**
47
+ * Health check
48
+ */
49
+ healthCheck(): Promise<{
50
+ status: 'ok' | 'error';
51
+ timestamp: Date;
52
+ reason?: string;
53
+ }>;
54
+ /**
55
+ * Check if adapter is ready
56
+ */
57
+ isReady(): boolean;
58
+ }
59
+ //# sourceMappingURL=DatabaseAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatabaseAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/DatabaseAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExE,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,OAAO,CAAC;AAElD,MAAM,WAAW,aAAc,SAAQ,cAAc;IACjD,IAAI,EAAE,YAAY,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,eAAe;IACxB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,MAAM;IAmBlD,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,iBAAiB;IAUzB;;OAEG;IACH,eAAe,IAAI,YAAY;IAI/B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;;OAGG;IACH,SAAS,IAAI,cAAc;IAI3B;;OAEG;IACG,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAQ3F;;OAEG;IACG,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAalF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;QAAC,SAAS,EAAE,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAa1F;;OAEG;IACH,OAAO,IAAI,OAAO;CAGrB"}
@@ -0,0 +1,120 @@
1
+ import { createLogger } from '@groundbrick/logger';
2
+ /**
3
+ * Database Adapter that provides a unified interface for both PostgreSQL and MySQL
4
+ * This allows easy switching between database types without changing application code
5
+ */
6
+ export class DatabaseAdapter {
7
+ client;
8
+ logger;
9
+ dbType;
10
+ constructor(config, logger) {
11
+ this.logger = logger || createLogger({ context: 'database-adapter' });
12
+ this.dbType = config.type;
13
+ // Create the appropriate database client based on the type
14
+ switch (config.type) {
15
+ case 'postgresql':
16
+ this.client = this.createPostgresClient(config);
17
+ break;
18
+ case 'mysql':
19
+ this.client = this.createMySQLClient(config);
20
+ break;
21
+ default:
22
+ throw new Error(`Unsupported database type: ${config.type}`);
23
+ }
24
+ this.logger.info('Database adapter created', { type: config.type });
25
+ }
26
+ createPostgresClient(config) {
27
+ try {
28
+ // Use dynamic import to avoid bundling unused drivers
29
+ const { PostgresFactory } = require('@groundbrick/db-postgres');
30
+ return PostgresFactory.getInstance(config, this.logger);
31
+ }
32
+ catch (error) {
33
+ throw new Error(`Failed to load PostgreSQL driver: ${error instanceof Error ? error.message : 'Unknown error'}. Make sure @groundbrick/db-postgres is installed.`);
34
+ }
35
+ }
36
+ createMySQLClient(config) {
37
+ try {
38
+ // Use dynamic import to avoid bundling unused drivers
39
+ const { MySQLFactory } = require('@groundbrick/db-mysql');
40
+ return MySQLFactory.getInstance(config, this.logger);
41
+ }
42
+ catch (error) {
43
+ throw new Error(`Failed to load MySQL driver: ${error instanceof Error ? error.message : 'Unknown error'}. Make sure @groundbrick/db-mysql is installed.`);
44
+ }
45
+ }
46
+ /**
47
+ * Get the database type
48
+ */
49
+ getDatabaseType() {
50
+ return this.dbType;
51
+ }
52
+ /**
53
+ * Initialize the database connection
54
+ */
55
+ async initialize() {
56
+ await this.client.initialize();
57
+ this.logger.info('Database adapter initialized');
58
+ }
59
+ /**
60
+ * Close the database connection
61
+ */
62
+ async close() {
63
+ await this.client.close();
64
+ this.logger.info('Database adapter closed');
65
+ }
66
+ /**
67
+ * Get the underlying database client
68
+ * This allows access to all database-specific methods
69
+ */
70
+ getClient() {
71
+ return this.client;
72
+ }
73
+ /**
74
+ * Execute a database-agnostic query
75
+ */
76
+ async query(sql, params) {
77
+ const result = await this.client.query(sql, params);
78
+ return {
79
+ rows: result.rows,
80
+ rowCount: result.rowCount ?? 0
81
+ };
82
+ }
83
+ /**
84
+ * Execute a transaction with unified interface
85
+ */
86
+ async transaction(callback) {
87
+ return await this.client.transaction(async (trx) => {
88
+ // Create a wrapper that looks like a DatabaseClient but uses the transaction
89
+ const transactionClient = {
90
+ ...this.client,
91
+ query: trx.query.bind(trx),
92
+ transaction: () => Promise.reject(new Error('Nested transactions not supported'))
93
+ };
94
+ return await callback(transactionClient);
95
+ });
96
+ }
97
+ /**
98
+ * Health check
99
+ */
100
+ async healthCheck() {
101
+ try {
102
+ await this.client.query('SELECT 1');
103
+ return { status: 'ok', timestamp: new Date() };
104
+ }
105
+ catch (error) {
106
+ return {
107
+ status: 'error',
108
+ timestamp: new Date(),
109
+ reason: error instanceof Error ? error.message : 'Unknown error'
110
+ };
111
+ }
112
+ }
113
+ /**
114
+ * Check if adapter is ready
115
+ */
116
+ isReady() {
117
+ return !!this.client;
118
+ }
119
+ }
120
+ //# sourceMappingURL=DatabaseAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatabaseAdapter.js","sourceRoot":"","sources":["../../src/adapters/DatabaseAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { DatabaseTransaction } from '../interfaces/DatabaseTransaction.js';
2
+ import { QueryResult } from '../interfaces/QueryResult.js';
3
+ import { Logger } from '@groundbrick/logger';
4
+ /**
5
+ * Base transaction class that provides common transaction logic with database type awareness
6
+ * This ensures consistent behavior across different database implementations
7
+ */
8
+ export declare abstract class BaseTransaction implements DatabaseTransaction {
9
+ protected readonly logger: Logger;
10
+ protected readonly dbType: 'postgresql' | 'mysql';
11
+ protected completed: boolean;
12
+ constructor(logger: Logger, dbType: 'postgresql' | 'mysql');
13
+ abstract query<T = any>(text: string, params?: any[]): Promise<QueryResult<T>>;
14
+ /**
15
+ * NEW: Get the database type for this transaction
16
+ */
17
+ getDatabaseType(): 'postgresql' | 'mysql';
18
+ /**
19
+ * NEW: Check if this database supports RETURNING clause
20
+ */
21
+ supportsReturning(): boolean;
22
+ /**
23
+ * NEW: Adapt SQL query for database-specific syntax
24
+ */
25
+ adaptSql(sql: string): string;
26
+ /**
27
+ * NEW: Create database-specific INSERT SQL
28
+ */
29
+ createInsertSql(tableName: string, columns: string[]): string;
30
+ /**
31
+ * NEW: Create database-specific UPDATE SQL
32
+ */
33
+ createUpdateSql(tableName: string, columns: string[]): string;
34
+ /**
35
+ * Template method for committing transaction
36
+ * Subclasses implement doCommit() for database-specific logic
37
+ */
38
+ commit(): Promise<void>;
39
+ /**
40
+ * Template method for rolling back transaction
41
+ * Subclasses implement doRollback() for database-specific logic
42
+ */
43
+ rollback(): Promise<void>;
44
+ /**
45
+ * Check if transaction is completed
46
+ */
47
+ isCompleted(): boolean;
48
+ /**
49
+ * Database-specific commit implementation
50
+ */
51
+ protected abstract doCommit(): Promise<void>;
52
+ /**
53
+ * Database-specific rollback implementation
54
+ */
55
+ protected abstract doRollback(): Promise<void>;
56
+ /**
57
+ * Database-specific cleanup (connection release, etc.)
58
+ */
59
+ protected abstract doCleanup(): Promise<void>;
60
+ /**
61
+ * Ensure cleanup happens in both success and error cases
62
+ */
63
+ protected ensureCleanup(): Promise<void>;
64
+ }
65
+ //# sourceMappingURL=BaseTransaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseTransaction.d.ts","sourceRoot":"","sources":["../../src/base/BaseTransaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAE3D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C;;;GAGG;AACH,8BAAsB,eAAgB,YAAW,mBAAmB;IAI5D,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACjC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAJrD,SAAS,CAAC,SAAS,UAAS;gBAGL,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,YAAY,GAAG,OAAO;IAGrD,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAE9E;;OAEG;IACH,eAAe,IAAI,YAAY,GAAG,OAAO;IAIzC;;OAEG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAU7B;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM;IAc7D;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM;IAgB7D;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB7B;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB/B;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAE5C;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9C;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAE7C;;OAEG;cACa,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAWjD"}
@@ -0,0 +1,134 @@
1
+ import { TransactionError } from '../error-handling/TransactionError.js';
2
+ /**
3
+ * Base transaction class that provides common transaction logic with database type awareness
4
+ * This ensures consistent behavior across different database implementations
5
+ */
6
+ export class BaseTransaction {
7
+ logger;
8
+ dbType;
9
+ completed = false;
10
+ constructor(logger, dbType // NEW: Database type awareness
11
+ ) {
12
+ this.logger = logger;
13
+ this.dbType = dbType;
14
+ }
15
+ /**
16
+ * NEW: Get the database type for this transaction
17
+ */
18
+ getDatabaseType() {
19
+ return this.dbType;
20
+ }
21
+ /**
22
+ * NEW: Check if this database supports RETURNING clause
23
+ */
24
+ supportsReturning() {
25
+ return this.dbType === 'postgresql';
26
+ }
27
+ /**
28
+ * NEW: Adapt SQL query for database-specific syntax
29
+ */
30
+ adaptSql(sql) {
31
+ if (this.dbType === 'postgresql') {
32
+ // Convert ? placeholders to $1, $2, etc.
33
+ let index = 1;
34
+ return sql.replace(/\?/g, () => `$${index++}`);
35
+ }
36
+ // MySQL uses ? placeholders as-is
37
+ return sql;
38
+ }
39
+ /**
40
+ * NEW: Create database-specific INSERT SQL
41
+ */
42
+ createInsertSql(tableName, columns) {
43
+ const placeholders = columns.map((_, index) => {
44
+ return this.dbType === 'postgresql' ? `$${index + 1}` : '?';
45
+ }).join(', ');
46
+ let sql = `INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`;
47
+ if (this.supportsReturning()) {
48
+ sql += ' RETURNING *';
49
+ }
50
+ return sql;
51
+ }
52
+ /**
53
+ * NEW: Create database-specific UPDATE SQL
54
+ */
55
+ createUpdateSql(tableName, columns) {
56
+ const setParts = columns.map((col, index) => {
57
+ const placeholder = this.dbType === 'postgresql' ? `$${index + 1}` : '?';
58
+ return `${col} = ${placeholder}`;
59
+ });
60
+ const idPlaceholder = this.dbType === 'postgresql' ? `$${columns.length + 1}` : '?';
61
+ let sql = `UPDATE ${tableName} SET ${setParts.join(', ')} WHERE id = ${idPlaceholder}`;
62
+ if (this.supportsReturning()) {
63
+ sql += ' RETURNING *';
64
+ }
65
+ return sql;
66
+ }
67
+ /**
68
+ * Template method for committing transaction
69
+ * Subclasses implement doCommit() for database-specific logic
70
+ */
71
+ async commit() {
72
+ if (this.completed) {
73
+ throw new TransactionError('Transaction has already been completed');
74
+ }
75
+ try {
76
+ this.logger.debug('Committing transaction', { dbType: this.dbType });
77
+ await this.doCommit();
78
+ this.completed = true;
79
+ this.logger.debug('Transaction committed successfully', { dbType: this.dbType });
80
+ }
81
+ catch (error) {
82
+ this.logger.error('Failed to commit transaction', error instanceof Error ? error : new Error(String(error)), {
83
+ error,
84
+ dbType: this.dbType
85
+ });
86
+ throw new TransactionError(`Failed to commit transaction: ${error.message}`, error);
87
+ }
88
+ }
89
+ /**
90
+ * Template method for rolling back transaction
91
+ * Subclasses implement doRollback() for database-specific logic
92
+ */
93
+ async rollback() {
94
+ if (this.completed) {
95
+ this.logger.debug('Transaction already completed, nothing to rollback', { dbType: this.dbType });
96
+ return;
97
+ }
98
+ try {
99
+ this.logger.debug('Rolling back transaction', { dbType: this.dbType });
100
+ await this.doRollback();
101
+ this.completed = true;
102
+ this.logger.debug('Transaction rolled back successfully', { dbType: this.dbType });
103
+ }
104
+ catch (error) {
105
+ this.logger.error('Failed to rollback transaction', error instanceof Error ? error : new Error(String(error)), {
106
+ error,
107
+ dbType: this.dbType
108
+ });
109
+ throw new TransactionError(`Failed to rollback transaction: ${error.message}`, error);
110
+ }
111
+ }
112
+ /**
113
+ * Check if transaction is completed
114
+ */
115
+ isCompleted() {
116
+ return this.completed;
117
+ }
118
+ /**
119
+ * Ensure cleanup happens in both success and error cases
120
+ */
121
+ async ensureCleanup() {
122
+ try {
123
+ await this.doCleanup();
124
+ }
125
+ catch (error) {
126
+ // Don't throw here as we don't want cleanup errors to mask the original error
127
+ this.logger.error('Failed to cleanup transaction resources', error instanceof Error ? error : new Error(String(error)), {
128
+ error,
129
+ dbType: this.dbType
130
+ });
131
+ }
132
+ }
133
+ }
134
+ //# sourceMappingURL=BaseTransaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseTransaction.js","sourceRoot":"","sources":["../../src/base/BaseTransaction.ts"],"names":[],"mappings":"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"}