@groundbrick/db-postgres 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.
@@ -0,0 +1,8 @@
1
+ import { BaseSqlAdapter } from '@groundbrick/db-core';
2
+ export declare class PostgresSqlAdapter extends BaseSqlAdapter {
3
+ getDatabaseType(): 'postgresql';
4
+ supportsReturning(): boolean;
5
+ adaptSql(sql: string): string;
6
+ protected createPlaceholder(index: number): string;
7
+ }
8
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,qBAAa,kBAAmB,SAAQ,cAAc;IAClD,eAAe,IAAI,YAAY;IAI/B,iBAAiB,IAAI,OAAO;IAI5B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAM7B,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAGrD"}
@@ -0,0 +1,18 @@
1
+ import { BaseSqlAdapter } from '@groundbrick/db-core';
2
+ export class PostgresSqlAdapter extends BaseSqlAdapter {
3
+ getDatabaseType() {
4
+ return 'postgresql';
5
+ }
6
+ supportsReturning() {
7
+ return true;
8
+ }
9
+ adaptSql(sql) {
10
+ // Convert ? placeholders to $1, $2, etc.
11
+ let index = 1;
12
+ return sql.replace(/\?/g, () => `$${index++}`);
13
+ }
14
+ createPlaceholder(index) {
15
+ return `$${index}`;
16
+ }
17
+ }
18
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,OAAO,kBAAmB,SAAQ,cAAc;IAClD,eAAe;QACX,OAAO,YAAY,CAAC;IACxB,CAAC;IAED,iBAAiB;QACb,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,QAAQ,CAAC,GAAW;QAChB,yCAAyC;QACzC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC,CAAC;IACnD,CAAC;IAES,iBAAiB,CAAC,KAAa;QACrC,OAAO,IAAI,KAAK,EAAE,CAAC;IACvB,CAAC;CACJ"}
@@ -0,0 +1,31 @@
1
+ import { Logger } from '@groundbrick/logger';
2
+ import { DatabaseClient, QueryResult, HealthCheckResult, SqlAdapter } from '@groundbrick/db-core';
3
+ import { PostgresConfig } from './types.js';
4
+ import { PostgresTransaction } from './transaction.js';
5
+ /**
6
+ * Unified PostgreSQL Database Client implementation
7
+ * Follows the exact same interface as MySQL for easy switching
8
+ */
9
+ export declare class PostgresClient implements DatabaseClient {
10
+ private pool;
11
+ private logger;
12
+ private sqlAdapter;
13
+ private isInitialized;
14
+ constructor(config: PostgresConfig, logger: Logger);
15
+ initialize(): Promise<void>;
16
+ close(): Promise<void>;
17
+ getDatabaseType(): 'postgresql';
18
+ getSqlAdapter(): SqlAdapter;
19
+ supportsReturning(): boolean;
20
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
21
+ transaction<T>(callback: (tx: PostgresTransaction) => Promise<T>): Promise<T>;
22
+ healthCheck(): Promise<HealthCheckResult>;
23
+ isReady(): boolean;
24
+ getConnectionInfo(): {
25
+ total: number;
26
+ idle: number;
27
+ waiting: number;
28
+ };
29
+ }
30
+ export { type PostgresConfig, PostgresTransaction };
31
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EACH,cAAc,EACd,WAAW,EACX,iBAAiB,EAIjB,UAAU,EACb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGvD;;;GAGG;AACH,qBAAa,cAAe,YAAW,cAAc;IACjD,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,aAAa,CAAS;gBAElB,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM;IAqB5C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B,eAAe,IAAI,YAAY;IAI/B,aAAa,IAAI,UAAU;IAI3B,iBAAiB,IAAI,OAAO;IAItB,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,GAAG,EAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IA4CxE,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,mBAAmB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsC7E,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IA+B/C,OAAO,IAAI,OAAO;IAIlB,iBAAiB,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;CAWxE;AAED,OAAO,EAAE,KAAK,cAAc,EAAE,mBAAmB,EAAE,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,177 @@
1
+ import { Pool } from 'pg';
2
+ import { ConnectionError, QueryError, TransactionError } from '@groundbrick/db-core';
3
+ import { PostgresTransaction } from './transaction.js';
4
+ import { PostgresSqlAdapter } from './adapter.js';
5
+ /**
6
+ * Unified PostgreSQL Database Client implementation
7
+ * Follows the exact same interface as MySQL for easy switching
8
+ */
9
+ export class PostgresClient {
10
+ pool;
11
+ logger;
12
+ sqlAdapter;
13
+ isInitialized = false;
14
+ constructor(config, logger) {
15
+ this.logger = logger.child('postgres-client');
16
+ this.sqlAdapter = new PostgresSqlAdapter();
17
+ this.pool = new Pool({
18
+ host: config.host,
19
+ port: config.port,
20
+ database: config.database,
21
+ user: config.user,
22
+ password: config.password,
23
+ max: config.max || 10,
24
+ idleTimeoutMillis: config.idleTimeoutMillis || 30000,
25
+ connectionTimeoutMillis: config.connectionTimeoutMillis || 2000,
26
+ ssl: config.ssl
27
+ });
28
+ this.pool.on('error', (err) => {
29
+ this.logger.error('PostgreSQL pool error', err);
30
+ });
31
+ }
32
+ async initialize() {
33
+ if (this.isInitialized) {
34
+ this.logger.warn('Database already initialized');
35
+ return;
36
+ }
37
+ try {
38
+ // Test connection
39
+ const client = await this.pool.connect();
40
+ await client.query('SELECT 1');
41
+ client.release();
42
+ this.isInitialized = true;
43
+ this.logger.info('PostgreSQL client initialized');
44
+ }
45
+ catch (error) {
46
+ this.logger.error('Failed to initialize PostgreSQL client', error);
47
+ throw error;
48
+ }
49
+ }
50
+ async close() {
51
+ if (!this.isInitialized || !this.pool)
52
+ return;
53
+ try {
54
+ await this.pool.end();
55
+ this.isInitialized = false;
56
+ this.logger.info('PostgreSQL client closed');
57
+ }
58
+ catch (error) {
59
+ this.logger.error('Failed to close PostgreSQL client', error);
60
+ throw error;
61
+ }
62
+ }
63
+ getDatabaseType() {
64
+ return 'postgresql';
65
+ }
66
+ getSqlAdapter() {
67
+ return this.sqlAdapter;
68
+ }
69
+ supportsReturning() {
70
+ return true;
71
+ }
72
+ async query(sql, params = []) {
73
+ if (!this.isInitialized || !this.pool) {
74
+ throw new ConnectionError('PostgreSQL client not initialized');
75
+ }
76
+ const timer = this.logger.startTimer('query');
77
+ try {
78
+ this.logger.debug('Executing query', {
79
+ sql: sql.substring(0, 100) + (sql.length > 100 ? '...' : ''),
80
+ paramCount: params.length
81
+ });
82
+ const startTime = Date.now();
83
+ const result = await this.pool.query(sql, params);
84
+ const duration = Date.now() - startTime;
85
+ this.logger.debug('Query executed successfully', {
86
+ duration,
87
+ rowCount: result.rowCount
88
+ });
89
+ return {
90
+ rows: result.rows,
91
+ rowCount: result.rowCount || 0,
92
+ fields: result.fields?.map(field => ({
93
+ name: field.name,
94
+ dataTypeID: field.dataTypeID
95
+ })) || []
96
+ };
97
+ }
98
+ catch (error) {
99
+ this.logger.error('Query execution failed', error instanceof Error ? error : new Error(String(error)), { error, sql, params });
100
+ throw new QueryError(`Query execution failed: ${error.message}`, sql, params, error);
101
+ }
102
+ finally {
103
+ timer();
104
+ }
105
+ }
106
+ async transaction(callback) {
107
+ if (!this.isInitialized || !this.pool) {
108
+ throw new ConnectionError('PostgreSQL client not initialized');
109
+ }
110
+ const client = await this.pool.connect();
111
+ const transactionLogger = this.logger.child('transaction');
112
+ const timer = transactionLogger.startTimer('transaction');
113
+ try {
114
+ await client.query('BEGIN');
115
+ transactionLogger.debug('Transaction started');
116
+ // Create PostgreSQL transaction using existing BaseTransaction
117
+ const transaction = new PostgresTransaction(client, this.logger);
118
+ const result = await callback(transaction); // Pass DatabaseTransaction
119
+ await transaction.commit(); // Use transaction's commit method
120
+ transactionLogger.debug('PostgreSQL transaction committed');
121
+ return result;
122
+ }
123
+ catch (error) {
124
+ await client.query('ROLLBACK');
125
+ transactionLogger.error('Transaction rolled back', error);
126
+ throw new TransactionError(`Transaction failed: ${error.message}`, error);
127
+ }
128
+ finally {
129
+ // don't release the client on a transaction, since the pool will handle it
130
+ // client.release();
131
+ timer();
132
+ }
133
+ }
134
+ async healthCheck() {
135
+ const startTime = Date.now();
136
+ try {
137
+ if (!this.pool) {
138
+ return {
139
+ status: 'unhealthy',
140
+ message: 'Connection pool not initialized',
141
+ timestamp: new Date(),
142
+ responseTime: Date.now() - startTime
143
+ };
144
+ }
145
+ await this.pool.query('SELECT 1');
146
+ return {
147
+ status: 'healthy',
148
+ message: 'Connection successful',
149
+ timestamp: new Date(),
150
+ responseTime: Date.now() - startTime
151
+ };
152
+ }
153
+ catch (error) {
154
+ return {
155
+ status: 'unhealthy',
156
+ message: error.message,
157
+ timestamp: new Date(),
158
+ responseTime: Date.now() - startTime
159
+ };
160
+ }
161
+ }
162
+ isReady() {
163
+ return this.isInitialized && this.pool !== null;
164
+ }
165
+ getConnectionInfo() {
166
+ if (!this.pool) {
167
+ return { total: 0, idle: 0, waiting: 0 };
168
+ }
169
+ return {
170
+ total: this.pool.totalCount,
171
+ idle: this.pool.idleCount,
172
+ waiting: this.pool.waitingCount
173
+ };
174
+ }
175
+ }
176
+ export { PostgresTransaction };
177
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { Logger } from '@groundbrick/logger';
2
+ import { DatabaseFactory, DatabaseConfig } from '@groundbrick/db-core';
3
+ import { PostgresClient } from './client.js';
4
+ /**
5
+ * PostgreSQL Database Factory implementation
6
+ * Singleton pattern to manage database instances across the application
7
+ */
8
+ export declare class PostgresDatabaseFactory implements DatabaseFactory {
9
+ private static instance;
10
+ private clients;
11
+ private defaultLogger;
12
+ private constructor();
13
+ static getInstance(): PostgresDatabaseFactory;
14
+ getInstance(config: DatabaseConfig, logger?: Logger): PostgresClient;
15
+ closeInstance(): Promise<void>;
16
+ private generateClientKey;
17
+ }
18
+ export declare const PostgresFactory: PostgresDatabaseFactory;
19
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAC;AAE7D;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,eAAe;IAC3D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAwC;IAC/D,OAAO,CAAC,OAAO,CAA0C;IACzD,OAAO,CAAC,aAAa,CAAS;IAE9B,OAAO;IAIP,MAAM,CAAC,WAAW,IAAI,uBAAuB;IAO7C,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,cAAc;IAiB9D,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAcpC,OAAO,CAAC,iBAAiB;CAG5B;AAGD,eAAO,MAAM,eAAe,yBAAwC,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { createLogger } from '@groundbrick/logger';
2
+ import { PostgresClient } from './client.js';
3
+ /**
4
+ * PostgreSQL Database Factory implementation
5
+ * Singleton pattern to manage database instances across the application
6
+ */
7
+ export class PostgresDatabaseFactory {
8
+ static instance = null;
9
+ clients = new Map();
10
+ defaultLogger;
11
+ constructor() {
12
+ this.defaultLogger = createLogger({ context: 'postgres-factory' });
13
+ }
14
+ static getInstance() {
15
+ if (!PostgresDatabaseFactory.instance) {
16
+ PostgresDatabaseFactory.instance = new PostgresDatabaseFactory();
17
+ }
18
+ return PostgresDatabaseFactory.instance;
19
+ }
20
+ getInstance(config, logger) {
21
+ const clientKey = this.generateClientKey(config);
22
+ if (this.clients.has(clientKey)) {
23
+ this.defaultLogger.debug('Reusing existing PostgreSQL client', { key: clientKey });
24
+ return this.clients.get(clientKey);
25
+ }
26
+ const clientLogger = logger || this.defaultLogger;
27
+ const client = new PostgresClient(config, clientLogger.child('postgres-client'));
28
+ this.clients.set(clientKey, client);
29
+ this.defaultLogger.info('Created new PostgreSQL client', { key: clientKey });
30
+ return client;
31
+ }
32
+ async closeInstance() {
33
+ this.defaultLogger.info('Closing all PostgreSQL connections');
34
+ const closePromises = Array.from(this.clients.values()).map(client => client.close().catch(error => this.defaultLogger.error('Error closing client', error instanceof Error ? error : new Error(String(error)), { error })));
35
+ await Promise.all(closePromises);
36
+ this.clients.clear();
37
+ PostgresDatabaseFactory.instance = null;
38
+ }
39
+ generateClientKey(config) {
40
+ return `${config.host}:${config.port}:${config.database}:${config.user}`;
41
+ }
42
+ }
43
+ // Default factory instance for convenience
44
+ export const PostgresFactory = PostgresDatabaseFactory.getInstance();
45
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAkB,MAAM,aAAa,CAAC;AAE7D;;;GAGG;AACH,MAAM,OAAO,uBAAuB;IACxB,MAAM,CAAC,QAAQ,GAAmC,IAAI,CAAC;IACvD,OAAO,GAAgC,IAAI,GAAG,EAAE,CAAC;IACjD,aAAa,CAAS;IAE9B;QACI,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,CAAC,WAAW;QACd,IAAI,CAAC,uBAAuB,CAAC,QAAQ,EAAE,CAAC;YACpC,uBAAuB,CAAC,QAAQ,GAAG,IAAI,uBAAuB,EAAE,CAAC;QACrE,CAAC;QACD,OAAO,uBAAuB,CAAC,QAAQ,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,MAAsB,EAAE,MAAe;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAEjD,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,oCAAoC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;YACnF,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC;QACxC,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC;QAClD,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC,MAAwB,EAAE,YAAY,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAEnG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAE7E,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,aAAa;QACf,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAE9D,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CACjE,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CACzB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CACzH,CACJ,CAAC;QAEF,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,uBAAuB,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC5C,CAAC;IAEO,iBAAiB,CAAC,MAAsB;QAC5C,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;IAC7E,CAAC;;AAGL,2CAA2C;AAC3C,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAC,WAAW,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { PostgresClient, PostgresTransaction } from './client.js';
2
+ export { PostgresDatabaseFactory, PostgresFactory } from './factory.js';
3
+ export { PostgresMigrator } from './migrator.js';
4
+ export type { PostgresConfig } from './types.js';
5
+ export type { DatabaseClient, QueryResult, Transaction, Migration, MigrationRecord, HealthCheckResult, ConnectionError, QueryError, MigrationError } from '@groundbrick/db-core';
6
+ export { createLogger } from '@groundbrick/logger';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,YAAY,EACR,cAAc,EACd,WAAW,EACX,WAAW,EACX,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,cAAc,EACjB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { PostgresClient, PostgresTransaction } from './client.js';
2
+ export { PostgresDatabaseFactory, PostgresFactory } from './factory.js';
3
+ export { PostgresMigrator } from './migrator.js';
4
+ // Convenience export for quick setup
5
+ export { createLogger } from '@groundbrick/logger';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAgBjD,qCAAqC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { Logger } from '@groundbrick/logger';
2
+ import { DatabaseClient, Migration, MigrationRecord } from '@groundbrick/db-core';
3
+ export declare class PostgresMigrator {
4
+ private client;
5
+ private migrationsPath;
6
+ private logger;
7
+ constructor(client: DatabaseClient, migrationsPath: string, logger: Logger);
8
+ initialize(): Promise<void>;
9
+ migrate(): Promise<void>;
10
+ rollback(steps?: number): Promise<void>;
11
+ getPending(): Promise<Migration[]>;
12
+ getApplied(): Promise<MigrationRecord[]>;
13
+ getStatus(): Promise<{
14
+ total: number;
15
+ applied: number;
16
+ pending: string[];
17
+ }>;
18
+ private loadMigrations;
19
+ private parseMigration;
20
+ private applyMigration;
21
+ private rollbackMigration;
22
+ }
23
+ //# sourceMappingURL=migrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrator.d.ts","sourceRoot":"","sources":["../src/migrator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,eAAe,EAAkB,MAAM,sBAAsB,CAAC;AAElG,qBAAa,gBAAgB;IAErB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,MAAM;gBAFN,MAAM,EAAE,cAAc,EACtB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM;IAGpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBxB,QAAQ,CAAC,KAAK,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBlC,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAUlC,UAAU,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAOxC,SAAS,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;YAanE,cAAc;IAsB5B,OAAO,CAAC,cAAc;YAyBR,cAAc;YAsBd,iBAAiB;CA0BlC"}
@@ -0,0 +1,162 @@
1
+ import { readdir, readFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { createHash } from 'crypto';
4
+ import { MigrationError } from '@groundbrick/db-core';
5
+ export class PostgresMigrator {
6
+ client;
7
+ migrationsPath;
8
+ logger;
9
+ constructor(client, migrationsPath, logger) {
10
+ this.client = client;
11
+ this.migrationsPath = migrationsPath;
12
+ this.logger = logger;
13
+ }
14
+ async initialize() {
15
+ try {
16
+ await this.client.query(`
17
+ CREATE TABLE IF NOT EXISTS schema_migrations (
18
+ id VARCHAR(255) PRIMARY KEY,
19
+ description TEXT NOT NULL,
20
+ checksum VARCHAR(64) NOT NULL,
21
+ applied_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
22
+ )
23
+ `);
24
+ this.logger.info('Migration table initialized');
25
+ }
26
+ catch (error) {
27
+ this.logger.error('Failed to initialize migration table', error instanceof Error ? error : new Error(String(error)), { error });
28
+ throw new MigrationError(`Failed to initialize migration table: ${error instanceof Error ? error.message : 'Unknown error'}`);
29
+ }
30
+ }
31
+ async migrate() {
32
+ await this.initialize();
33
+ const pending = await this.getPending();
34
+ if (pending.length === 0) {
35
+ this.logger.info('No pending migrations');
36
+ return;
37
+ }
38
+ this.logger.info(`Applying ${pending.length} migrations`, {
39
+ migrations: pending.map(m => m.id)
40
+ });
41
+ for (const migration of pending) {
42
+ await this.applyMigration(migration);
43
+ }
44
+ this.logger.info('All migrations applied successfully');
45
+ }
46
+ async rollback(steps = 1) {
47
+ await this.initialize();
48
+ const applied = await this.getApplied();
49
+ const toRollback = applied.slice(-steps);
50
+ if (toRollback.length === 0) {
51
+ this.logger.info('No migrations to rollback');
52
+ return;
53
+ }
54
+ this.logger.info(`Rolling back ${toRollback.length} migrations`, {
55
+ migrations: toRollback.map(m => m.id)
56
+ });
57
+ // Rollback in reverse order
58
+ for (const migration of toRollback.reverse()) {
59
+ await this.rollbackMigration(migration);
60
+ }
61
+ this.logger.info('Rollback completed successfully');
62
+ }
63
+ async getPending() {
64
+ const [allMigrations, appliedRecords] = await Promise.all([
65
+ this.loadMigrations(),
66
+ this.getApplied()
67
+ ]);
68
+ const appliedIds = new Set(appliedRecords.map(r => r.id));
69
+ return allMigrations.filter(m => !appliedIds.has(m.id));
70
+ }
71
+ async getApplied() {
72
+ const result = await this.client.query('SELECT * FROM schema_migrations ORDER BY applied_at');
73
+ return result.rows;
74
+ }
75
+ async getStatus() {
76
+ const [allMigrations, pending] = await Promise.all([
77
+ this.loadMigrations(),
78
+ this.getPending()
79
+ ]);
80
+ return {
81
+ total: allMigrations.length,
82
+ applied: allMigrations.length - pending.length,
83
+ pending: pending.map(m => m.id)
84
+ };
85
+ }
86
+ async loadMigrations() {
87
+ try {
88
+ const files = await readdir(this.migrationsPath);
89
+ const migrationFiles = files
90
+ .filter(file => file.endsWith('.sql'))
91
+ .sort();
92
+ const migrations = [];
93
+ for (const file of migrationFiles) {
94
+ const content = await readFile(join(this.migrationsPath, file), 'utf8');
95
+ const migration = this.parseMigration(file, content);
96
+ migrations.push(migration);
97
+ }
98
+ return migrations;
99
+ }
100
+ catch (error) {
101
+ this.logger.error('Failed to load migrations', error instanceof Error ? error : new Error(String(error)), { error, path: this.migrationsPath });
102
+ throw new MigrationError(`Failed to load migrations: ${error instanceof Error ? error.message : 'Unknown error'}`);
103
+ }
104
+ }
105
+ parseMigration(filename, content) {
106
+ const id = filename.replace('.sql', '');
107
+ // Extract description from first comment line
108
+ const firstLine = content.split('\n')[0];
109
+ const description = firstLine.startsWith('--') ? firstLine.slice(2).trim() : id;
110
+ // Split by DOWN marker
111
+ const downIndex = content.toLowerCase().indexOf('-- down');
112
+ if (downIndex === -1) {
113
+ throw new MigrationError(`Migration ${id} missing DOWN section`);
114
+ }
115
+ const up = content.substring(0, downIndex).trim();
116
+ const down = content.substring(downIndex + 7).trim(); // Skip "-- DOWN"
117
+ if (!up || !down) {
118
+ throw new MigrationError(`Migration ${id} has empty UP or DOWN section`);
119
+ }
120
+ const checksum = createHash('sha256').update(content).digest('hex');
121
+ return { id, description, up, down, checksum };
122
+ }
123
+ async applyMigration(migration) {
124
+ try {
125
+ this.logger.info(`Applying migration: ${migration.id} - ${migration.description}`);
126
+ await this.client.transaction(async (trx) => {
127
+ // Execute the UP migration
128
+ await trx.query(migration.up);
129
+ // Record in migrations table
130
+ await trx.query('INSERT INTO schema_migrations (id, description, checksum) VALUES ($1, $2, $3)', [migration.id, migration.description, migration.checksum]);
131
+ });
132
+ this.logger.info(`Migration applied successfully: ${migration.id}`);
133
+ }
134
+ catch (error) {
135
+ this.logger.error(`Failed to apply migration: ${migration.id}`, error instanceof Error ? error : new Error(String(error)), { error });
136
+ throw new MigrationError(`Failed to apply migration ${migration.id}: ${error instanceof Error ? error.message : 'Unknown error'}`);
137
+ }
138
+ }
139
+ async rollbackMigration(record) {
140
+ try {
141
+ this.logger.info(`Rolling back migration: ${record.id} - ${record.description}`);
142
+ // Load the migration file to get the DOWN script
143
+ const migrations = await this.loadMigrations();
144
+ const migration = migrations.find(m => m.id === record.id);
145
+ if (!migration) {
146
+ throw new MigrationError(`Migration file not found for ${record.id}`);
147
+ }
148
+ await this.client.transaction(async (trx) => {
149
+ // Execute the DOWN migration
150
+ await trx.query(migration.down);
151
+ // Remove from migrations table
152
+ await trx.query('DELETE FROM schema_migrations WHERE id = $1', [record.id]);
153
+ });
154
+ this.logger.info(`Migration rolled back successfully: ${record.id}`);
155
+ }
156
+ catch (error) {
157
+ this.logger.error(`Failed to rollback migration: ${record.id}`, error instanceof Error ? error : new Error(String(error)), { error });
158
+ throw new MigrationError(`Failed to rollback migration ${record.id}: ${error instanceof Error ? error.message : 'Unknown error'}`);
159
+ }
160
+ }
161
+ }
162
+ //# sourceMappingURL=migrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrator.js","sourceRoot":"","sources":["../src/migrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { PoolClient } from 'pg';
2
+ import { Logger } from '@groundbrick/logger';
3
+ import { BaseTransaction, QueryResult } from '@groundbrick/db-core';
4
+ /**
5
+ * PostgreSQL Transaction implementation using the unified BaseTransaction
6
+ */
7
+ export declare class PostgresTransaction extends BaseTransaction {
8
+ private readonly client;
9
+ constructor(client: PoolClient, logger: Logger);
10
+ query<T = any>(sql: string, params?: any[]): Promise<QueryResult<T>>;
11
+ protected doCommit(): Promise<void>;
12
+ protected doRollback(): Promise<void>;
13
+ protected doCleanup(): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=transaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAc,eAAe,EAAE,WAAW,EAAoB,MAAM,sBAAsB,CAAC;AAElG;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,eAAe;IAEhD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU,EACnC,MAAM,EAAE,MAAM;IAKZ,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,GAAG,EAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;cA8C9D,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;cAKzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;cAK3B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7C"}
@@ -0,0 +1,60 @@
1
+ import { QueryError, BaseTransaction, TransactionError } from '@groundbrick/db-core';
2
+ /**
3
+ * PostgreSQL Transaction implementation using the unified BaseTransaction
4
+ */
5
+ export class PostgresTransaction extends BaseTransaction {
6
+ client;
7
+ constructor(client, logger) {
8
+ super(logger, 'postgresql'); // Pass database type to base class
9
+ this.client = client;
10
+ }
11
+ async query(sql, params = []) {
12
+ if (this.completed) {
13
+ throw new TransactionError('Transaction has already been completed');
14
+ }
15
+ try {
16
+ this.logger.debug('Executing PostgreSQL transaction query', {
17
+ sql: sql.substring(0, 100) + (sql.length > 100 ? '...' : ''),
18
+ paramCount: params.length,
19
+ dbType: this.dbType
20
+ });
21
+ const startTime = Date.now();
22
+ const result = await this.client.query(sql, params);
23
+ const duration = Date.now() - startTime;
24
+ this.logger.debug('PostgreSQL transaction query executed', {
25
+ duration,
26
+ rowCount: result.rowCount,
27
+ dbType: this.dbType
28
+ });
29
+ return {
30
+ rows: result.rows,
31
+ rowCount: result.rowCount || 0,
32
+ fields: result.fields?.map(field => ({
33
+ name: field.name,
34
+ dataTypeID: field.dataTypeID
35
+ })) || []
36
+ };
37
+ }
38
+ catch (error) {
39
+ this.logger.error('PostgreSQL transaction query failed', error instanceof Error ? error : new Error(String(error)), {
40
+ error,
41
+ sql,
42
+ params,
43
+ dbType: this.dbType
44
+ });
45
+ throw new QueryError(`PostgreSQL transaction query failed: ${error.message}`, sql, params, error);
46
+ }
47
+ }
48
+ async doCommit() {
49
+ await this.client.query('COMMIT');
50
+ await this.ensureCleanup();
51
+ }
52
+ async doRollback() {
53
+ await this.client.query('ROLLBACK');
54
+ await this.ensureCleanup();
55
+ }
56
+ async doCleanup() {
57
+ this.client.release();
58
+ }
59
+ }
60
+ //# sourceMappingURL=transaction.js.map