@warlock.js/cascade 4.0.92 → 4.0.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/contracts/database-driver.contract.d.ts +118 -0
- package/cjs/contracts/database-driver.contract.d.ts.map +1 -1
- package/cjs/contracts/migration-driver.contract.d.ts +14 -0
- package/cjs/contracts/migration-driver.contract.d.ts.map +1 -1
- package/cjs/contracts/query-builder.contract.d.ts +410 -1
- package/cjs/contracts/query-builder.contract.d.ts.map +1 -1
- package/cjs/data-source/data-source-registry.d.ts +4 -0
- package/cjs/data-source/data-source-registry.d.ts.map +1 -1
- package/cjs/data-source/data-source-registry.js +7 -0
- package/cjs/data-source/data-source-registry.js.map +1 -1
- package/cjs/drivers/mongodb/mongodb-blueprint.d.ts.map +1 -0
- package/cjs/drivers/mongodb/mongodb-blueprint.js.map +1 -0
- package/{esm/drivers/mongo → cjs/drivers/mongodb}/mongodb-driver.d.ts +49 -0
- package/cjs/drivers/mongodb/mongodb-driver.d.ts.map +1 -0
- package/cjs/drivers/{mongo → mongodb}/mongodb-driver.js +125 -8
- package/cjs/drivers/mongodb/mongodb-driver.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-id-generator.d.ts → mongodb/mongodb-id-generator.d.ts} +1 -1
- package/cjs/drivers/mongodb/mongodb-id-generator.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-id-generator.js → mongodb/mongodb-id-generator.js} +1 -1
- package/cjs/drivers/mongodb/mongodb-id-generator.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-migration-driver.d.ts → mongodb/mongodb-migration-driver.d.ts} +10 -1
- package/cjs/drivers/mongodb/mongodb-migration-driver.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-migration-driver.js → mongodb/mongodb-migration-driver.js} +18 -1
- package/cjs/drivers/mongodb/mongodb-migration-driver.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-builder.d.ts → mongodb/mongodb-query-builder.d.ts} +172 -4
- package/cjs/drivers/mongodb/mongodb-query-builder.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-builder.js → mongodb/mongodb-query-builder.js} +220 -14
- package/cjs/drivers/mongodb/mongodb-query-builder.js.map +1 -0
- package/{esm/drivers/mongo/mongo-query-operations.d.ts → cjs/drivers/mongodb/mongodb-query-operations.d.ts} +16 -16
- package/cjs/drivers/mongodb/mongodb-query-operations.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-operations.js → mongodb/mongodb-query-operations.js} +22 -22
- package/cjs/drivers/mongodb/mongodb-query-operations.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-parser.d.ts → mongodb/mongodb-query-parser.d.ts} +2 -2
- package/cjs/drivers/mongodb/mongodb-query-parser.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-query-parser.js → mongodb/mongodb-query-parser.js} +87 -87
- package/cjs/drivers/mongodb/mongodb-query-parser.js.map +1 -0
- package/cjs/drivers/{mongo/mongo-sync-adapter.d.ts → mongodb/mongodb-sync-adapter.d.ts} +2 -2
- package/cjs/drivers/mongodb/mongodb-sync-adapter.d.ts.map +1 -0
- package/cjs/drivers/{mongo/mongo-sync-adapter.js → mongodb/mongodb-sync-adapter.js} +2 -2
- package/cjs/drivers/mongodb/mongodb-sync-adapter.js.map +1 -0
- package/{esm/drivers/mongo → cjs/drivers/mongodb}/types.d.ts +2 -2
- package/cjs/drivers/mongodb/types.d.ts.map +1 -0
- package/cjs/drivers/postgres/index.d.ts +16 -0
- package/cjs/drivers/postgres/index.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-blueprint.d.ts +64 -0
- package/cjs/drivers/postgres/postgres-blueprint.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-blueprint.js +121 -0
- package/cjs/drivers/postgres/postgres-blueprint.js.map +1 -0
- package/cjs/drivers/postgres/postgres-dialect.d.ts +135 -0
- package/cjs/drivers/postgres/postgres-dialect.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-dialect.js +245 -0
- package/cjs/drivers/postgres/postgres-dialect.js.map +1 -0
- package/cjs/drivers/postgres/postgres-driver.d.ts +360 -0
- package/cjs/drivers/postgres/postgres-driver.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-driver.js +763 -0
- package/cjs/drivers/postgres/postgres-driver.js.map +1 -0
- package/cjs/drivers/postgres/postgres-migration-driver.d.ts +297 -0
- package/cjs/drivers/postgres/postgres-migration-driver.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-migration-driver.js +578 -0
- package/cjs/drivers/postgres/postgres-migration-driver.js.map +1 -0
- package/cjs/drivers/postgres/postgres-query-builder.d.ts +824 -0
- package/cjs/drivers/postgres/postgres-query-builder.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-query-builder.js +1800 -0
- package/cjs/drivers/postgres/postgres-query-builder.js.map +1 -0
- package/cjs/drivers/postgres/postgres-query-parser.d.ts +308 -0
- package/cjs/drivers/postgres/postgres-query-parser.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-query-parser.js +706 -0
- package/cjs/drivers/postgres/postgres-query-parser.js.map +1 -0
- package/cjs/drivers/postgres/postgres-sync-adapter.d.ts +83 -0
- package/cjs/drivers/postgres/postgres-sync-adapter.d.ts.map +1 -0
- package/cjs/drivers/postgres/postgres-sync-adapter.js +197 -0
- package/cjs/drivers/postgres/postgres-sync-adapter.js.map +1 -0
- package/cjs/drivers/postgres/types.d.ts +142 -0
- package/cjs/drivers/postgres/types.d.ts.map +1 -0
- package/cjs/drivers/sql/index.d.ts +10 -0
- package/cjs/drivers/sql/index.d.ts.map +1 -0
- package/cjs/drivers/sql/sql-dialect.contract.d.ts +203 -0
- package/cjs/drivers/sql/sql-dialect.contract.d.ts.map +1 -0
- package/cjs/drivers/sql/sql-types.d.ts +202 -0
- package/cjs/drivers/sql/sql-types.d.ts.map +1 -0
- package/cjs/index.d.ts +9 -6
- package/cjs/index.d.ts.map +1 -1
- package/cjs/index.js +1 -1
- package/cjs/migration/migration-runner.d.ts.map +1 -1
- package/cjs/migration/migration-runner.js +3 -0
- package/cjs/migration/migration-runner.js.map +1 -1
- package/cjs/model/model.d.ts +236 -1
- package/cjs/model/model.d.ts.map +1 -1
- package/cjs/model/model.js +203 -4
- package/cjs/model/model.js.map +1 -1
- package/cjs/relations/helpers.d.ts +156 -0
- package/cjs/relations/helpers.d.ts.map +1 -0
- package/cjs/relations/helpers.js +197 -0
- package/cjs/relations/helpers.js.map +1 -0
- package/cjs/relations/index.d.ts +33 -0
- package/cjs/relations/index.d.ts.map +1 -0
- package/cjs/relations/pivot-operations.d.ts +160 -0
- package/cjs/relations/pivot-operations.d.ts.map +1 -0
- package/cjs/relations/pivot-operations.js +293 -0
- package/cjs/relations/pivot-operations.js.map +1 -0
- package/cjs/relations/relation-loader.d.ts +194 -0
- package/cjs/relations/relation-loader.d.ts.map +1 -0
- package/cjs/relations/relation-loader.js +466 -0
- package/cjs/relations/relation-loader.js.map +1 -0
- package/cjs/relations/types.d.ts +280 -0
- package/cjs/relations/types.d.ts.map +1 -0
- package/cjs/sync/model-sync-operation.js +1 -1
- package/cjs/sync/model-sync-operation.js.map +1 -1
- package/cjs/utils/connect-to-database.d.ts.map +1 -1
- package/cjs/utils/connect-to-database.js +15 -3
- package/cjs/utils/connect-to-database.js.map +1 -1
- package/cjs/utils/define-model.d.ts +51 -29
- package/cjs/utils/define-model.d.ts.map +1 -1
- package/cjs/validation/rules/database-model-rule.js +1 -1
- package/cjs/validation/rules/database-model-rule.js.map +1 -1
- package/esm/contracts/database-driver.contract.d.ts +118 -0
- package/esm/contracts/database-driver.contract.d.ts.map +1 -1
- package/esm/contracts/migration-driver.contract.d.ts +14 -0
- package/esm/contracts/migration-driver.contract.d.ts.map +1 -1
- package/esm/contracts/query-builder.contract.d.ts +410 -1
- package/esm/contracts/query-builder.contract.d.ts.map +1 -1
- package/esm/data-source/data-source-registry.d.ts +4 -0
- package/esm/data-source/data-source-registry.d.ts.map +1 -1
- package/esm/data-source/data-source-registry.js +7 -0
- package/esm/data-source/data-source-registry.js.map +1 -1
- package/esm/drivers/mongodb/mongodb-blueprint.d.ts.map +1 -0
- package/esm/drivers/mongodb/mongodb-blueprint.js.map +1 -0
- package/{cjs/drivers/mongo → esm/drivers/mongodb}/mongodb-driver.d.ts +49 -0
- package/esm/drivers/mongodb/mongodb-driver.d.ts.map +1 -0
- package/esm/drivers/{mongo → mongodb}/mongodb-driver.js +121 -4
- package/esm/drivers/mongodb/mongodb-driver.js.map +1 -0
- package/esm/drivers/{mongo/mongo-id-generator.d.ts → mongodb/mongodb-id-generator.d.ts} +1 -1
- package/esm/drivers/mongodb/mongodb-id-generator.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-id-generator.js → mongodb/mongodb-id-generator.js} +1 -1
- package/esm/drivers/mongodb/mongodb-id-generator.js.map +1 -0
- package/esm/drivers/{mongo/mongo-migration-driver.d.ts → mongodb/mongodb-migration-driver.d.ts} +10 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-migration-driver.js → mongodb/mongodb-migration-driver.js} +18 -1
- package/esm/drivers/mongodb/mongodb-migration-driver.js.map +1 -0
- package/esm/drivers/{mongo/mongo-query-builder.d.ts → mongodb/mongodb-query-builder.d.ts} +172 -4
- package/esm/drivers/mongodb/mongodb-query-builder.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-query-builder.js → mongodb/mongodb-query-builder.js} +218 -12
- package/esm/drivers/mongodb/mongodb-query-builder.js.map +1 -0
- package/{cjs/drivers/mongo/mongo-query-operations.d.ts → esm/drivers/mongodb/mongodb-query-operations.d.ts} +16 -16
- package/esm/drivers/mongodb/mongodb-query-operations.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-query-operations.js → mongodb/mongodb-query-operations.js} +22 -22
- package/esm/drivers/mongodb/mongodb-query-operations.js.map +1 -0
- package/esm/drivers/{mongo/mongo-query-parser.d.ts → mongodb/mongodb-query-parser.d.ts} +2 -2
- package/esm/drivers/mongodb/mongodb-query-parser.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-query-parser.js → mongodb/mongodb-query-parser.js} +87 -87
- package/esm/drivers/mongodb/mongodb-query-parser.js.map +1 -0
- package/esm/drivers/{mongo/mongo-sync-adapter.d.ts → mongodb/mongodb-sync-adapter.d.ts} +2 -2
- package/esm/drivers/mongodb/mongodb-sync-adapter.d.ts.map +1 -0
- package/esm/drivers/{mongo/mongo-sync-adapter.js → mongodb/mongodb-sync-adapter.js} +2 -2
- package/esm/drivers/mongodb/mongodb-sync-adapter.js.map +1 -0
- package/{cjs/drivers/mongo → esm/drivers/mongodb}/types.d.ts +2 -2
- package/esm/drivers/mongodb/types.d.ts.map +1 -0
- package/esm/drivers/postgres/index.d.ts +16 -0
- package/esm/drivers/postgres/index.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-blueprint.d.ts +64 -0
- package/esm/drivers/postgres/postgres-blueprint.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-blueprint.js +121 -0
- package/esm/drivers/postgres/postgres-blueprint.js.map +1 -0
- package/esm/drivers/postgres/postgres-dialect.d.ts +135 -0
- package/esm/drivers/postgres/postgres-dialect.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-dialect.js +245 -0
- package/esm/drivers/postgres/postgres-dialect.js.map +1 -0
- package/esm/drivers/postgres/postgres-driver.d.ts +360 -0
- package/esm/drivers/postgres/postgres-driver.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-driver.js +763 -0
- package/esm/drivers/postgres/postgres-driver.js.map +1 -0
- package/esm/drivers/postgres/postgres-migration-driver.d.ts +297 -0
- package/esm/drivers/postgres/postgres-migration-driver.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-migration-driver.js +578 -0
- package/esm/drivers/postgres/postgres-migration-driver.js.map +1 -0
- package/esm/drivers/postgres/postgres-query-builder.d.ts +824 -0
- package/esm/drivers/postgres/postgres-query-builder.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-query-builder.js +1800 -0
- package/esm/drivers/postgres/postgres-query-builder.js.map +1 -0
- package/esm/drivers/postgres/postgres-query-parser.d.ts +308 -0
- package/esm/drivers/postgres/postgres-query-parser.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-query-parser.js +706 -0
- package/esm/drivers/postgres/postgres-query-parser.js.map +1 -0
- package/esm/drivers/postgres/postgres-sync-adapter.d.ts +83 -0
- package/esm/drivers/postgres/postgres-sync-adapter.d.ts.map +1 -0
- package/esm/drivers/postgres/postgres-sync-adapter.js +197 -0
- package/esm/drivers/postgres/postgres-sync-adapter.js.map +1 -0
- package/esm/drivers/postgres/types.d.ts +142 -0
- package/esm/drivers/postgres/types.d.ts.map +1 -0
- package/esm/drivers/sql/index.d.ts +10 -0
- package/esm/drivers/sql/index.d.ts.map +1 -0
- package/esm/drivers/sql/sql-dialect.contract.d.ts +203 -0
- package/esm/drivers/sql/sql-dialect.contract.d.ts.map +1 -0
- package/esm/drivers/sql/sql-types.d.ts +202 -0
- package/esm/drivers/sql/sql-types.d.ts.map +1 -0
- package/esm/index.d.ts +9 -6
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/migration/migration-runner.d.ts.map +1 -1
- package/esm/migration/migration-runner.js +3 -0
- package/esm/migration/migration-runner.js.map +1 -1
- package/esm/model/model.d.ts +236 -1
- package/esm/model/model.d.ts.map +1 -1
- package/esm/model/model.js +203 -4
- package/esm/model/model.js.map +1 -1
- package/esm/relations/helpers.d.ts +156 -0
- package/esm/relations/helpers.d.ts.map +1 -0
- package/esm/relations/helpers.js +197 -0
- package/esm/relations/helpers.js.map +1 -0
- package/esm/relations/index.d.ts +33 -0
- package/esm/relations/index.d.ts.map +1 -0
- package/esm/relations/pivot-operations.d.ts +160 -0
- package/esm/relations/pivot-operations.d.ts.map +1 -0
- package/esm/relations/pivot-operations.js +293 -0
- package/esm/relations/pivot-operations.js.map +1 -0
- package/esm/relations/relation-loader.d.ts +194 -0
- package/esm/relations/relation-loader.d.ts.map +1 -0
- package/esm/relations/relation-loader.js +466 -0
- package/esm/relations/relation-loader.js.map +1 -0
- package/esm/relations/types.d.ts +280 -0
- package/esm/relations/types.d.ts.map +1 -0
- package/esm/sync/model-sync-operation.js +1 -1
- package/esm/sync/model-sync-operation.js.map +1 -1
- package/esm/utils/connect-to-database.d.ts.map +1 -1
- package/esm/utils/connect-to-database.js +15 -3
- package/esm/utils/connect-to-database.js.map +1 -1
- package/esm/utils/define-model.d.ts +51 -29
- package/esm/utils/define-model.d.ts.map +1 -1
- package/esm/validation/rules/database-model-rule.js +1 -1
- package/esm/validation/rules/database-model-rule.js.map +1 -1
- package/package.json +4 -4
- package/cjs/drivers/mongo/mongo-id-generator.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-id-generator.js.map +0 -1
- package/cjs/drivers/mongo/mongo-migration-driver.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-migration-driver.js.map +0 -1
- package/cjs/drivers/mongo/mongo-query-builder.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-query-builder.js.map +0 -1
- package/cjs/drivers/mongo/mongo-query-operations.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-query-operations.js.map +0 -1
- package/cjs/drivers/mongo/mongo-query-parser.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-query-parser.js.map +0 -1
- package/cjs/drivers/mongo/mongo-sync-adapter.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongo-sync-adapter.js.map +0 -1
- package/cjs/drivers/mongo/mongodb-blueprint.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongodb-blueprint.js.map +0 -1
- package/cjs/drivers/mongo/mongodb-driver.d.ts.map +0 -1
- package/cjs/drivers/mongo/mongodb-driver.js.map +0 -1
- package/cjs/drivers/mongo/types.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-id-generator.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-id-generator.js.map +0 -1
- package/esm/drivers/mongo/mongo-migration-driver.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-migration-driver.js.map +0 -1
- package/esm/drivers/mongo/mongo-query-builder.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-query-builder.js.map +0 -1
- package/esm/drivers/mongo/mongo-query-operations.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-query-operations.js.map +0 -1
- package/esm/drivers/mongo/mongo-query-parser.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-query-parser.js.map +0 -1
- package/esm/drivers/mongo/mongo-sync-adapter.d.ts.map +0 -1
- package/esm/drivers/mongo/mongo-sync-adapter.js.map +0 -1
- package/esm/drivers/mongo/mongodb-blueprint.d.ts.map +0 -1
- package/esm/drivers/mongo/mongodb-blueprint.js.map +0 -1
- package/esm/drivers/mongo/mongodb-driver.d.ts.map +0 -1
- package/esm/drivers/mongo/mongodb-driver.js.map +0 -1
- package/esm/drivers/mongo/types.d.ts.map +0 -1
- /package/cjs/drivers/{mongo → mongodb}/mongodb-blueprint.d.ts +0 -0
- /package/cjs/drivers/{mongo → mongodb}/mongodb-blueprint.js +0 -0
- /package/esm/drivers/{mongo → mongodb}/mongodb-blueprint.d.ts +0 -0
- /package/esm/drivers/{mongo → mongodb}/mongodb-blueprint.js +0 -0
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
'use strict';var copper=require('@mongez/copper'),logger=require('@warlock.js/logger'),databaseTransactionContext=require('../../context/database-transaction-context.js'),postgresBlueprint=require('./postgres-blueprint.js'),postgresDialect=require('./postgres-dialect.js'),postgresMigrationDriver=require('./postgres-migration-driver.js'),postgresQueryBuilder=require('./postgres-query-builder.js'),postgresSyncAdapter=require('./postgres-sync-adapter.js');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}/**
|
|
2
|
+
* PostgreSQL Driver
|
|
3
|
+
*
|
|
4
|
+
* Main driver implementation for PostgreSQL database operations.
|
|
5
|
+
* Implements the DriverContract interface to provide a unified API
|
|
6
|
+
* for CRUD operations, transactions, and query building.
|
|
7
|
+
*
|
|
8
|
+
* Uses the `pg` package for database connectivity with connection pooling.
|
|
9
|
+
*
|
|
10
|
+
* @module cascade/drivers/postgres
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Cached pg module reference.
|
|
14
|
+
*/
|
|
15
|
+
let pgModule;
|
|
16
|
+
/**
|
|
17
|
+
* Lazily load the pg package.
|
|
18
|
+
*
|
|
19
|
+
* @returns The pg module
|
|
20
|
+
* @throws Error if pg is not installed
|
|
21
|
+
*/
|
|
22
|
+
async function loadPg() {
|
|
23
|
+
if (pgModule) {
|
|
24
|
+
return pgModule;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
pgModule = await Promise.resolve().then(function(){return /*#__PURE__*/_interopNamespace(require('pg'))});
|
|
28
|
+
return pgModule;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error('The "pg" package is required for PostgreSQL support. ' + "Please install it: npm install pg");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* PostgreSQL database driver implementing the Cascade DriverContract.
|
|
36
|
+
*
|
|
37
|
+
* Provides connection pooling, CRUD operations, transactions, and
|
|
38
|
+
* integration with Cascade's query builder and migration systems.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const driver = new PostgresDriver({
|
|
43
|
+
* host: 'localhost',
|
|
44
|
+
* port: 5432,
|
|
45
|
+
* database: 'myapp',
|
|
46
|
+
* user: 'postgres',
|
|
47
|
+
* password: 'secret'
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* await driver.connect();
|
|
51
|
+
*
|
|
52
|
+
* // Insert a document
|
|
53
|
+
* const result = await driver.insert('users', { name: 'Alice', email: 'alice@example.com' });
|
|
54
|
+
*
|
|
55
|
+
* // Query using the query builder
|
|
56
|
+
* const users = await driver.queryBuilder('users')
|
|
57
|
+
* .where('name', 'Alice')
|
|
58
|
+
* .get();
|
|
59
|
+
*
|
|
60
|
+
* await driver.disconnect();
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
class PostgresDriver {
|
|
64
|
+
config;
|
|
65
|
+
/**
|
|
66
|
+
* Driver name identifier.
|
|
67
|
+
*/
|
|
68
|
+
name = "postgres";
|
|
69
|
+
/**
|
|
70
|
+
* SQL dialect for PostgreSQL-specific syntax.
|
|
71
|
+
*/
|
|
72
|
+
dialect = new postgresDialect.PostgresDialect();
|
|
73
|
+
/**
|
|
74
|
+
* Connection pool instance.
|
|
75
|
+
*/
|
|
76
|
+
_pool;
|
|
77
|
+
/**
|
|
78
|
+
* Event listeners for driver lifecycle events.
|
|
79
|
+
*/
|
|
80
|
+
_eventListeners = new Map();
|
|
81
|
+
/**
|
|
82
|
+
* Whether the driver is currently connected.
|
|
83
|
+
*/
|
|
84
|
+
_isConnected = false;
|
|
85
|
+
/**
|
|
86
|
+
* Blueprint instance (lazy-loaded).
|
|
87
|
+
*/
|
|
88
|
+
_blueprint;
|
|
89
|
+
/**
|
|
90
|
+
* Migration driver instance (lazy-loaded).
|
|
91
|
+
*/
|
|
92
|
+
_migrationDriver;
|
|
93
|
+
/**
|
|
94
|
+
* Sync adapter instance (lazy-loaded).
|
|
95
|
+
*/
|
|
96
|
+
_syncAdapter;
|
|
97
|
+
/**
|
|
98
|
+
* Create a new PostgreSQL driver instance.
|
|
99
|
+
*
|
|
100
|
+
* @param config - PostgreSQL connection configuration
|
|
101
|
+
*/
|
|
102
|
+
constructor(config) {
|
|
103
|
+
this.config = config;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get the connection pool instance.
|
|
107
|
+
*
|
|
108
|
+
* @throws Error if not connected
|
|
109
|
+
*/
|
|
110
|
+
get pool() {
|
|
111
|
+
if (!this._pool) {
|
|
112
|
+
throw new Error("PostgreSQL driver is not connected. Call connect() first.");
|
|
113
|
+
}
|
|
114
|
+
return this._pool;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if the driver is currently connected.
|
|
118
|
+
*/
|
|
119
|
+
get isConnected() {
|
|
120
|
+
return this._isConnected;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get the driver blueprint (information schema).
|
|
124
|
+
*/
|
|
125
|
+
get blueprint() {
|
|
126
|
+
if (!this._blueprint) {
|
|
127
|
+
this._blueprint = new postgresBlueprint.PostgresBlueprint(this);
|
|
128
|
+
}
|
|
129
|
+
return this._blueprint;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Establish connection to the PostgreSQL database.
|
|
133
|
+
*
|
|
134
|
+
* Creates a connection pool with the configured options.
|
|
135
|
+
* Emits 'connected' event on successful connection.
|
|
136
|
+
*/
|
|
137
|
+
async connect() {
|
|
138
|
+
if (this._isConnected) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const pg = await loadPg();
|
|
142
|
+
try {
|
|
143
|
+
const poolConfig = {
|
|
144
|
+
host: this.config.host ?? "localhost",
|
|
145
|
+
port: this.config.port ?? 5432,
|
|
146
|
+
database: this.config.database,
|
|
147
|
+
user: this.config.user,
|
|
148
|
+
password: this.config.password,
|
|
149
|
+
connectionString: this.config.connectionString,
|
|
150
|
+
max: this.config.max ?? 10,
|
|
151
|
+
min: this.config.min ?? 0,
|
|
152
|
+
idleTimeoutMillis: this.config.idleTimeoutMillis ?? 30000,
|
|
153
|
+
connectionTimeoutMillis: this.config.connectionTimeoutMillis ?? 2000,
|
|
154
|
+
application_name: this.config.application_name ?? "cascade",
|
|
155
|
+
ssl: this.config.ssl,
|
|
156
|
+
};
|
|
157
|
+
logger.log.info("database", "connection[Postgress]", `Connecting to database ${copper.colors.bold(copper.colors.yellowBright(this.config.database))}`);
|
|
158
|
+
this._pool = new pg.Pool(poolConfig);
|
|
159
|
+
// Test the connection
|
|
160
|
+
const client = await this._pool.connect();
|
|
161
|
+
client.release();
|
|
162
|
+
logger.log.success("database", "connection[Postgress]", `Connected to database ${copper.colors.bold(copper.colors.yellowBright(this.config.database))}`);
|
|
163
|
+
this._isConnected = true;
|
|
164
|
+
this.emit("connected");
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
logger.log.error("database", "connection[Postgress]", "Failed to connect to database");
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Close the database connection pool.
|
|
173
|
+
*
|
|
174
|
+
* Waits for all active queries to complete before closing.
|
|
175
|
+
* Emits 'disconnected' event on successful disconnection.
|
|
176
|
+
*/
|
|
177
|
+
async disconnect() {
|
|
178
|
+
if (!this._isConnected || !this._pool) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
await this._pool.end();
|
|
182
|
+
this._pool = undefined;
|
|
183
|
+
this._isConnected = false;
|
|
184
|
+
this.emit("disconnected");
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Register an event listener for driver lifecycle events.
|
|
188
|
+
*
|
|
189
|
+
* @param event - Event name ('connected', 'disconnected', etc.)
|
|
190
|
+
* @param listener - Callback function to invoke
|
|
191
|
+
*/
|
|
192
|
+
on(event, listener) {
|
|
193
|
+
if (!this._eventListeners.has(event)) {
|
|
194
|
+
this._eventListeners.set(event, new Set());
|
|
195
|
+
}
|
|
196
|
+
this._eventListeners.get(event).add(listener);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Serialize data for storage in PostgreSQL.
|
|
200
|
+
*
|
|
201
|
+
* Handles Date objects, BigInt, and other JavaScript types
|
|
202
|
+
* that need special handling for PostgreSQL storage.
|
|
203
|
+
*
|
|
204
|
+
* @param data - The data object to serialize
|
|
205
|
+
* @returns Serialized data ready for PostgreSQL
|
|
206
|
+
*/
|
|
207
|
+
serialize(data) {
|
|
208
|
+
const serialized = {};
|
|
209
|
+
for (const [key, value] of Object.entries(data)) {
|
|
210
|
+
if (value === undefined) {
|
|
211
|
+
continue; // Skip undefined values
|
|
212
|
+
}
|
|
213
|
+
if (value instanceof Date) {
|
|
214
|
+
serialized[key] = value.toISOString();
|
|
215
|
+
}
|
|
216
|
+
else if (typeof value === "bigint") {
|
|
217
|
+
serialized[key] = value.toString();
|
|
218
|
+
}
|
|
219
|
+
else if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
220
|
+
// Nested objects will be stored as JSONB
|
|
221
|
+
serialized[key] = value;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
serialized[key] = value;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return serialized;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Deserialize data retrieved from PostgreSQL.
|
|
231
|
+
*
|
|
232
|
+
* Converts PostgreSQL types back to JavaScript equivalents.
|
|
233
|
+
*
|
|
234
|
+
* @param data - The data object from PostgreSQL
|
|
235
|
+
* @returns Deserialized JavaScript object
|
|
236
|
+
*/
|
|
237
|
+
deserialize(data) {
|
|
238
|
+
// PostgreSQL pg driver handles most type conversions automatically
|
|
239
|
+
// Special handling can be added here if needed
|
|
240
|
+
return data;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Insert a single row into a table.
|
|
244
|
+
*
|
|
245
|
+
* Uses INSERT ... RETURNING to get the inserted row with generated values.
|
|
246
|
+
*
|
|
247
|
+
* @param table - Target table name
|
|
248
|
+
* @param document - Data to insert
|
|
249
|
+
* @param options - Optional insertion options
|
|
250
|
+
* @returns The inserted document
|
|
251
|
+
*/
|
|
252
|
+
async insert(table, document, _options) {
|
|
253
|
+
const serialized = this.serialize(document);
|
|
254
|
+
// Filter out id if null/undefined to let PostgreSQL SERIAL auto-generate
|
|
255
|
+
const filteredData = Object.fromEntries(Object.entries(serialized).filter(([key, value]) => {
|
|
256
|
+
// Exclude id if null/undefined (let SERIAL handle it)
|
|
257
|
+
if (key === "id" && (value === null || value === undefined)) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
}));
|
|
262
|
+
const columns = Object.keys(filteredData);
|
|
263
|
+
const values = Object.values(filteredData);
|
|
264
|
+
if (columns.length === 0) {
|
|
265
|
+
throw new Error("Cannot insert empty document");
|
|
266
|
+
}
|
|
267
|
+
const quotedColumns = columns.map((c) => this.dialect.quoteIdentifier(c)).join(", ");
|
|
268
|
+
const placeholders = columns.map((_, i) => this.dialect.placeholder(i + 1)).join(", ");
|
|
269
|
+
const quotedTable = this.dialect.quoteIdentifier(table);
|
|
270
|
+
const sql = `INSERT INTO ${quotedTable} (${quotedColumns}) VALUES (${placeholders}) RETURNING *`;
|
|
271
|
+
const result = await this.query(sql, values);
|
|
272
|
+
return {
|
|
273
|
+
document: this.deserialize(result.rows[0]),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Insert multiple rows into a table.
|
|
278
|
+
*
|
|
279
|
+
* Uses a single INSERT statement with multiple value sets for efficiency.
|
|
280
|
+
*
|
|
281
|
+
* @param table - Target table name
|
|
282
|
+
* @param documents - Array of documents to insert
|
|
283
|
+
* @param options - Optional insertion options
|
|
284
|
+
* @returns Array of inserted documents
|
|
285
|
+
*/
|
|
286
|
+
async insertMany(table, documents, _options) {
|
|
287
|
+
if (documents.length === 0) {
|
|
288
|
+
return [];
|
|
289
|
+
}
|
|
290
|
+
// Get all unique columns across all documents
|
|
291
|
+
const allColumns = new Set();
|
|
292
|
+
for (const doc of documents) {
|
|
293
|
+
const serialized = this.serialize(doc);
|
|
294
|
+
Object.keys(serialized).forEach((key) => allColumns.add(key));
|
|
295
|
+
}
|
|
296
|
+
const columns = Array.from(allColumns);
|
|
297
|
+
const quotedColumns = columns.map((c) => this.dialect.quoteIdentifier(c)).join(", ");
|
|
298
|
+
const quotedTable = this.dialect.quoteIdentifier(table);
|
|
299
|
+
// Build value sets and params
|
|
300
|
+
const valueSets = [];
|
|
301
|
+
const params = [];
|
|
302
|
+
let paramIndex = 1;
|
|
303
|
+
for (const doc of documents) {
|
|
304
|
+
const serialized = this.serialize(doc);
|
|
305
|
+
const rowPlaceholders = [];
|
|
306
|
+
for (const col of columns) {
|
|
307
|
+
if (col in serialized) {
|
|
308
|
+
rowPlaceholders.push(this.dialect.placeholder(paramIndex++));
|
|
309
|
+
params.push(serialized[col]);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
rowPlaceholders.push("DEFAULT");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
valueSets.push(`(${rowPlaceholders.join(", ")})`);
|
|
316
|
+
}
|
|
317
|
+
const sql = `INSERT INTO ${quotedTable} (${quotedColumns}) VALUES ${valueSets.join(", ")} RETURNING *`;
|
|
318
|
+
const result = await this.query(sql, params);
|
|
319
|
+
return result.rows.map((row) => ({
|
|
320
|
+
document: this.deserialize(row),
|
|
321
|
+
}));
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Update a single row matching the filter.
|
|
325
|
+
*
|
|
326
|
+
* @param table - Target table name
|
|
327
|
+
* @param filter - Filter conditions
|
|
328
|
+
* @param update - Update operations ($set, $unset, $inc)
|
|
329
|
+
* @param options - Optional update options
|
|
330
|
+
* @returns Update result with modified count
|
|
331
|
+
*/
|
|
332
|
+
async update(table, filter, update, _options) {
|
|
333
|
+
const { sql, params } = this.buildUpdateQuery(table, filter, update, 1);
|
|
334
|
+
const result = await this.query(sql, params);
|
|
335
|
+
return {
|
|
336
|
+
modifiedCount: result.rowCount ?? 0,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Update multiple rows matching the filter.
|
|
341
|
+
*
|
|
342
|
+
* @param table - Target table name
|
|
343
|
+
* @param filter - Filter conditions
|
|
344
|
+
* @param update - Update operations
|
|
345
|
+
* @param options - Optional update options
|
|
346
|
+
* @returns Update result with modified count
|
|
347
|
+
*/
|
|
348
|
+
async updateMany(table, filter, update, _options) {
|
|
349
|
+
const { sql, params } = this.buildUpdateQuery(table, filter, update);
|
|
350
|
+
const result = await this.query(sql, params);
|
|
351
|
+
return {
|
|
352
|
+
modifiedCount: result.rowCount ?? 0,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Replace a document matching the filter.
|
|
357
|
+
*
|
|
358
|
+
* Completely replaces the document (not a partial update).
|
|
359
|
+
*
|
|
360
|
+
* @param table - Target table name
|
|
361
|
+
* @param filter - Filter conditions
|
|
362
|
+
* @param document - New document data
|
|
363
|
+
* @param options - Optional options
|
|
364
|
+
* @returns The replaced document or null
|
|
365
|
+
*/
|
|
366
|
+
async replace(table, filter, document, _options) {
|
|
367
|
+
const serialized = this.serialize(document);
|
|
368
|
+
const columns = Object.keys(serialized);
|
|
369
|
+
const values = Object.values(serialized);
|
|
370
|
+
const quotedTable = this.dialect.quoteIdentifier(table);
|
|
371
|
+
const setClauses = columns
|
|
372
|
+
.map((col, i) => `${this.dialect.quoteIdentifier(col)} = ${this.dialect.placeholder(i + 1)}`)
|
|
373
|
+
.join(", ");
|
|
374
|
+
const { whereClause, whereParams } = this.buildWhereClause(filter, columns.length + 1);
|
|
375
|
+
const sql = `UPDATE ${quotedTable} SET ${setClauses} ${whereClause} RETURNING *`;
|
|
376
|
+
const params = [...values, ...whereParams];
|
|
377
|
+
const result = await this.query(sql, params);
|
|
378
|
+
return result.rows[0] ?? null;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Delete a single row matching the filter.
|
|
382
|
+
*
|
|
383
|
+
* @param table - Target table name
|
|
384
|
+
* @param filter - Filter conditions
|
|
385
|
+
* @param options - Optional options
|
|
386
|
+
* @returns Number of deleted rows (0 or 1)
|
|
387
|
+
*/
|
|
388
|
+
async delete(table, filter, _options) {
|
|
389
|
+
const quotedTable = this.dialect.quoteIdentifier(table);
|
|
390
|
+
const { whereClause, whereParams } = this.buildWhereClause(filter ?? {}, 1);
|
|
391
|
+
// Use ctid for single row deletion
|
|
392
|
+
const sql = `DELETE FROM ${quotedTable} WHERE ctid IN (SELECT ctid FROM ${quotedTable} ${whereClause} LIMIT 1)`;
|
|
393
|
+
const result = await this.query(sql, whereParams);
|
|
394
|
+
return result.rowCount ?? 0;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Delete multiple rows matching the filter.
|
|
398
|
+
*
|
|
399
|
+
* @param table - Target table name
|
|
400
|
+
* @param filter - Filter conditions
|
|
401
|
+
* @param options - Optional options
|
|
402
|
+
* @returns Number of deleted rows
|
|
403
|
+
*/
|
|
404
|
+
async deleteMany(table, filter, _options) {
|
|
405
|
+
const quotedTable = this.dialect.quoteIdentifier(table);
|
|
406
|
+
const { whereClause, whereParams } = this.buildWhereClause(filter ?? {}, 1);
|
|
407
|
+
const sql = `DELETE FROM ${quotedTable} ${whereClause}`;
|
|
408
|
+
const result = await this.query(sql, whereParams);
|
|
409
|
+
return result.rowCount ?? 0;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Truncate a table (remove all rows).
|
|
413
|
+
*
|
|
414
|
+
* Uses TRUNCATE TABLE for fast deletion with RESTART IDENTITY.
|
|
415
|
+
*
|
|
416
|
+
* @param table - Target table name
|
|
417
|
+
* @param options - Optional options
|
|
418
|
+
* @returns Number of deleted rows (always 0 for TRUNCATE)
|
|
419
|
+
*/
|
|
420
|
+
async truncateTable(table, _options) {
|
|
421
|
+
const quotedTable = this.dialect.quoteIdentifier(table);
|
|
422
|
+
await this.query(`TRUNCATE TABLE ${quotedTable} RESTART IDENTITY`);
|
|
423
|
+
return 0; // TRUNCATE doesn't return row count
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Get a query builder for the specified table.
|
|
427
|
+
*
|
|
428
|
+
* @param table - Target table name
|
|
429
|
+
* @returns Query builder instance
|
|
430
|
+
*/
|
|
431
|
+
queryBuilder(table) {
|
|
432
|
+
return new postgresQueryBuilder.PostgresQueryBuilder(table);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Begin a new database transaction.
|
|
436
|
+
*
|
|
437
|
+
* Acquires a client from the pool and starts a transaction.
|
|
438
|
+
* The client is stored in AsyncLocalStorage for automatic
|
|
439
|
+
* participation by subsequent queries.
|
|
440
|
+
*
|
|
441
|
+
* @param options - Optional transaction options
|
|
442
|
+
* @returns Transaction contract with commit/rollback methods
|
|
443
|
+
*/
|
|
444
|
+
async beginTransaction(options) {
|
|
445
|
+
const client = await this.pool.connect();
|
|
446
|
+
let beginSql = "BEGIN";
|
|
447
|
+
if (options?.isolationLevel) {
|
|
448
|
+
beginSql += ` ISOLATION LEVEL ${options.isolationLevel.toUpperCase()}`;
|
|
449
|
+
}
|
|
450
|
+
if (options?.readOnly) {
|
|
451
|
+
beginSql += " READ ONLY";
|
|
452
|
+
}
|
|
453
|
+
if (options?.deferrable) {
|
|
454
|
+
beginSql += " DEFERRABLE";
|
|
455
|
+
}
|
|
456
|
+
await client.query(beginSql);
|
|
457
|
+
return {
|
|
458
|
+
context: client,
|
|
459
|
+
commit: async () => {
|
|
460
|
+
await client.query("COMMIT");
|
|
461
|
+
client.release();
|
|
462
|
+
},
|
|
463
|
+
rollback: async () => {
|
|
464
|
+
await client.query("ROLLBACK");
|
|
465
|
+
client.release();
|
|
466
|
+
},
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Perform an atomic update operation.
|
|
471
|
+
*
|
|
472
|
+
* Uses PostgreSQL's row-level locking for atomicity.
|
|
473
|
+
*
|
|
474
|
+
* @param table - Target table name
|
|
475
|
+
* @param filter - Filter conditions
|
|
476
|
+
* @param operations - Update operations
|
|
477
|
+
* @param options - Optional options
|
|
478
|
+
* @returns Update result
|
|
479
|
+
*/
|
|
480
|
+
async atomic(table, filter, operations, _options) {
|
|
481
|
+
// For PostgreSQL, we use SELECT FOR UPDATE to lock the row
|
|
482
|
+
// then perform the update
|
|
483
|
+
const { sql, params } = this.buildUpdateQuery(table, filter, operations, 1);
|
|
484
|
+
const result = await this.query(sql, params);
|
|
485
|
+
return {
|
|
486
|
+
modifiedCount: result.rowCount ?? 0,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Get the sync adapter for bulk denormalized updates.
|
|
491
|
+
*
|
|
492
|
+
* @returns Sync adapter instance
|
|
493
|
+
*/
|
|
494
|
+
syncAdapter() {
|
|
495
|
+
if (!this._syncAdapter) {
|
|
496
|
+
this._syncAdapter = new postgresSyncAdapter.PostgresSyncAdapter(this);
|
|
497
|
+
}
|
|
498
|
+
return this._syncAdapter;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Get the migration driver for schema operations.
|
|
502
|
+
*
|
|
503
|
+
* @returns Migration driver instance
|
|
504
|
+
*/
|
|
505
|
+
migrationDriver() {
|
|
506
|
+
if (!this._migrationDriver) {
|
|
507
|
+
this._migrationDriver = new postgresMigrationDriver.PostgresMigrationDriver(this);
|
|
508
|
+
}
|
|
509
|
+
return this._migrationDriver;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Execute a raw SQL query.
|
|
513
|
+
*
|
|
514
|
+
* Automatically uses the transaction client if one is active.
|
|
515
|
+
*
|
|
516
|
+
* @param sql - SQL query string
|
|
517
|
+
* @param params - Query parameters
|
|
518
|
+
* @returns Query result
|
|
519
|
+
*/
|
|
520
|
+
async query(sql, params = []) {
|
|
521
|
+
// Check for active transaction client
|
|
522
|
+
const txClient = databaseTransactionContext.databaseTransactionContext.getSession();
|
|
523
|
+
if (txClient) {
|
|
524
|
+
const result = await txClient.query(sql, params);
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
527
|
+
return this.pool.query(sql, params);
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Emit an event to all registered listeners.
|
|
531
|
+
*
|
|
532
|
+
* @param event - Event name
|
|
533
|
+
* @param args - Event arguments
|
|
534
|
+
*/
|
|
535
|
+
emit(event, ...args) {
|
|
536
|
+
const listeners = this._eventListeners.get(event);
|
|
537
|
+
if (listeners) {
|
|
538
|
+
for (const listener of listeners) {
|
|
539
|
+
listener(...args);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Build a simple WHERE clause from a filter object.
|
|
545
|
+
*
|
|
546
|
+
* @param filter - Filter conditions
|
|
547
|
+
* @param startParamIndex - Starting parameter index
|
|
548
|
+
* @returns Object with WHERE clause string and parameters
|
|
549
|
+
*/
|
|
550
|
+
buildWhereClause(filter, startParamIndex) {
|
|
551
|
+
const conditions = [];
|
|
552
|
+
const params = [];
|
|
553
|
+
let paramIndex = startParamIndex;
|
|
554
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
555
|
+
const quotedKey = this.dialect.quoteIdentifier(key);
|
|
556
|
+
if (value === null) {
|
|
557
|
+
conditions.push(`${quotedKey} IS NULL`);
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
conditions.push(`${quotedKey} = ${this.dialect.placeholder(paramIndex++)}`);
|
|
561
|
+
params.push(value);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
565
|
+
return { whereClause, whereParams: params };
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Build an UPDATE query from update operations.
|
|
569
|
+
*
|
|
570
|
+
* @param table - Target table name
|
|
571
|
+
* @param filter - Filter conditions
|
|
572
|
+
* @param update - Update operations
|
|
573
|
+
* @param limit - Optional limit (for single row update)
|
|
574
|
+
* @returns Object with SQL and parameters
|
|
575
|
+
*/
|
|
576
|
+
buildUpdateQuery(table, filter, update, limit) {
|
|
577
|
+
const setClauses = [];
|
|
578
|
+
const params = [];
|
|
579
|
+
let paramIndex = 1;
|
|
580
|
+
// Handle $set
|
|
581
|
+
if (update.$set) {
|
|
582
|
+
for (const [key, value] of Object.entries(update.$set)) {
|
|
583
|
+
setClauses.push(`${this.dialect.quoteIdentifier(key)} = ${this.dialect.placeholder(paramIndex++)}`);
|
|
584
|
+
params.push(value);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
// Handle $unset (set to NULL)
|
|
588
|
+
if (update.$unset) {
|
|
589
|
+
for (const key of Object.keys(update.$unset)) {
|
|
590
|
+
setClauses.push(`${this.dialect.quoteIdentifier(key)} = NULL`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
// Handle $inc
|
|
594
|
+
if (update.$inc) {
|
|
595
|
+
for (const [key, amount] of Object.entries(update.$inc)) {
|
|
596
|
+
const quotedKey = this.dialect.quoteIdentifier(key);
|
|
597
|
+
setClauses.push(`${quotedKey} = COALESCE(${quotedKey}, 0) + ${this.dialect.placeholder(paramIndex++)}`);
|
|
598
|
+
params.push(amount);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
// Handle $dec
|
|
602
|
+
if (update.$dec) {
|
|
603
|
+
for (const [key, amount] of Object.entries(update.$dec)) {
|
|
604
|
+
const quotedKey = this.dialect.quoteIdentifier(key);
|
|
605
|
+
setClauses.push(`${quotedKey} = COALESCE(${quotedKey}, 0) - ${this.dialect.placeholder(paramIndex++)}`);
|
|
606
|
+
params.push(amount);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
if (setClauses.length === 0) {
|
|
610
|
+
throw new Error("No update operations specified");
|
|
611
|
+
}
|
|
612
|
+
const quotedTable = this.dialect.quoteIdentifier(table);
|
|
613
|
+
const { whereClause, whereParams } = this.buildWhereClause(filter, paramIndex);
|
|
614
|
+
params.push(...whereParams);
|
|
615
|
+
let sql = `UPDATE ${quotedTable} SET ${setClauses.join(", ")} ${whereClause}`;
|
|
616
|
+
// For single row update, use ctid subquery
|
|
617
|
+
if (limit === 1 && whereClause) {
|
|
618
|
+
sql = `UPDATE ${quotedTable} SET ${setClauses.join(", ")} WHERE ctid IN (SELECT ctid FROM ${quotedTable} ${whereClause} LIMIT 1)`;
|
|
619
|
+
}
|
|
620
|
+
return { sql, params };
|
|
621
|
+
}
|
|
622
|
+
// ============================================================
|
|
623
|
+
// Database Lifecycle Operations
|
|
624
|
+
// ============================================================
|
|
625
|
+
/**
|
|
626
|
+
* Create a new database.
|
|
627
|
+
*
|
|
628
|
+
* Note: This requires connecting to a system database (like 'postgres')
|
|
629
|
+
* since you cannot create a database while connected to it.
|
|
630
|
+
*
|
|
631
|
+
* @param name - Database name to create
|
|
632
|
+
* @param options - Creation options (encoding, template, etc.)
|
|
633
|
+
* @returns true if created, false if already exists
|
|
634
|
+
*/
|
|
635
|
+
async createDatabase(name, options) {
|
|
636
|
+
// Check if database already exists
|
|
637
|
+
if (await this.databaseExists(name)) {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
// Build CREATE DATABASE statement
|
|
641
|
+
const quotedName = this.dialect.quoteIdentifier(name);
|
|
642
|
+
let sql = `CREATE DATABASE ${quotedName}`;
|
|
643
|
+
const withClauses = [];
|
|
644
|
+
if (options?.encoding) {
|
|
645
|
+
withClauses.push(`ENCODING = '${options.encoding}'`);
|
|
646
|
+
}
|
|
647
|
+
if (options?.template) {
|
|
648
|
+
withClauses.push(`TEMPLATE = ${this.dialect.quoteIdentifier(options.template)}`);
|
|
649
|
+
}
|
|
650
|
+
if (options?.locale) {
|
|
651
|
+
withClauses.push(`LC_COLLATE = '${options.locale}'`);
|
|
652
|
+
withClauses.push(`LC_CTYPE = '${options.locale}'`);
|
|
653
|
+
}
|
|
654
|
+
if (options?.owner) {
|
|
655
|
+
withClauses.push(`OWNER = ${this.dialect.quoteIdentifier(options.owner)}`);
|
|
656
|
+
}
|
|
657
|
+
if (withClauses.length > 0) {
|
|
658
|
+
sql += ` WITH ${withClauses.join(" ")}`;
|
|
659
|
+
}
|
|
660
|
+
try {
|
|
661
|
+
await this.query(sql);
|
|
662
|
+
logger.log.success("database", "lifecycle", `Created database ${name}`);
|
|
663
|
+
return true;
|
|
664
|
+
}
|
|
665
|
+
catch (error) {
|
|
666
|
+
logger.log.error("database", "lifecycle", `Failed to create database ${name}: ${error}`);
|
|
667
|
+
throw error;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Drop a database.
|
|
672
|
+
*
|
|
673
|
+
* @param name - Database name to drop
|
|
674
|
+
* @param options - Drop options
|
|
675
|
+
* @returns true if dropped, false if didn't exist
|
|
676
|
+
*/
|
|
677
|
+
async dropDatabase(name, options) {
|
|
678
|
+
// Check if database exists first (if ifExists option not set)
|
|
679
|
+
if (!options?.ifExists && !(await this.databaseExists(name))) {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
const quotedName = this.dialect.quoteIdentifier(name);
|
|
683
|
+
let sql = "DROP DATABASE";
|
|
684
|
+
if (options?.ifExists) {
|
|
685
|
+
sql += " IF EXISTS";
|
|
686
|
+
}
|
|
687
|
+
sql += ` ${quotedName}`;
|
|
688
|
+
// PostgreSQL 13+ supports WITH (FORCE) to terminate active connections
|
|
689
|
+
if (options?.force) {
|
|
690
|
+
sql += " WITH (FORCE)";
|
|
691
|
+
}
|
|
692
|
+
try {
|
|
693
|
+
await this.query(sql);
|
|
694
|
+
logger.log.success("database", "lifecycle", `Dropped database ${name}`);
|
|
695
|
+
return true;
|
|
696
|
+
}
|
|
697
|
+
catch (error) {
|
|
698
|
+
logger.log.error("database", "lifecycle", `Failed to drop database ${name}: ${error}`);
|
|
699
|
+
throw error;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Check if a database exists.
|
|
704
|
+
*
|
|
705
|
+
* @param name - Database name to check
|
|
706
|
+
* @returns true if database exists
|
|
707
|
+
*/
|
|
708
|
+
async databaseExists(name) {
|
|
709
|
+
const result = await this.query(`SELECT EXISTS(SELECT 1 FROM pg_database WHERE datname = $1) as exists`, [name]);
|
|
710
|
+
return result.rows[0]?.exists ?? false;
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* List all databases.
|
|
714
|
+
*
|
|
715
|
+
* @returns Array of database names
|
|
716
|
+
*/
|
|
717
|
+
async listDatabases() {
|
|
718
|
+
const result = await this.query(`SELECT datname FROM pg_database WHERE datistemplate = false ORDER BY datname`);
|
|
719
|
+
return result.rows.map((row) => row.datname);
|
|
720
|
+
}
|
|
721
|
+
// ============================================================
|
|
722
|
+
// Table Management Operations
|
|
723
|
+
// ============================================================
|
|
724
|
+
/**
|
|
725
|
+
* Drop a table.
|
|
726
|
+
*
|
|
727
|
+
* @param name - Table name to drop
|
|
728
|
+
* @throws Error if table doesn't exist
|
|
729
|
+
*/
|
|
730
|
+
async dropTable(name) {
|
|
731
|
+
const quotedName = this.dialect.quoteIdentifier(name);
|
|
732
|
+
await this.query(`DROP TABLE ${quotedName}`);
|
|
733
|
+
logger.log.success("database", "table", `Dropped table ${name}`);
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Drop a table if it exists.
|
|
737
|
+
*
|
|
738
|
+
* @param name - Table name to drop
|
|
739
|
+
*/
|
|
740
|
+
async dropTableIfExists(name) {
|
|
741
|
+
const quotedName = this.dialect.quoteIdentifier(name);
|
|
742
|
+
await this.query(`DROP TABLE IF EXISTS ${quotedName}`);
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Drop all tables in the current database.
|
|
746
|
+
*
|
|
747
|
+
* Uses CASCADE to handle foreign key dependencies.
|
|
748
|
+
* Useful for `migrate:fresh` command.
|
|
749
|
+
*/
|
|
750
|
+
async dropAllTables() {
|
|
751
|
+
// Get all tables from blueprint
|
|
752
|
+
const tables = await this.blueprint.listTables();
|
|
753
|
+
if (tables.length === 0) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
// Drop all tables with CASCADE to handle foreign keys
|
|
757
|
+
for (const table of tables) {
|
|
758
|
+
const quotedName = this.dialect.quoteIdentifier(table);
|
|
759
|
+
await this.query(`DROP TABLE IF EXISTS ${quotedName} CASCADE`);
|
|
760
|
+
}
|
|
761
|
+
logger.log.success("database", "table", `Dropped ${tables.length} tables`);
|
|
762
|
+
}
|
|
763
|
+
}exports.PostgresDriver=PostgresDriver;//# sourceMappingURL=postgres-driver.js.map
|