ts-prorm-orm 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1111 -0
- package/LICENSE +21 -0
- package/README.md +573 -0
- package/dist/audit/history-query.js +180 -0
- package/dist/audit/index.js +23 -0
- package/dist/audit/logger.js +236 -0
- package/dist/cache/cache-manager.js +84 -0
- package/dist/cache/index.js +16 -0
- package/dist/cache/redis-cluster-cache.js +557 -0
- package/dist/cli.js +2200 -0
- package/dist/compliance/audit-trail.js +68 -0
- package/dist/compliance/backup-verification.js +685 -0
- package/dist/compliance/breach-detector.js +505 -0
- package/dist/compliance/consent-record.js +227 -0
- package/dist/compliance/consent-versioning.js +331 -0
- package/dist/compliance/cross-border-log.js +530 -0
- package/dist/compliance/data-classifier.js +258 -0
- package/dist/compliance/data-lineage.js +565 -0
- package/dist/compliance/data-masker.js +303 -0
- package/dist/compliance/data-portability.js +265 -0
- package/dist/compliance/data-retention.js +195 -0
- package/dist/compliance/dsar-workflow.js +342 -0
- package/dist/compliance/field-encryption.js +223 -0
- package/dist/compliance/immutable-record.js +148 -0
- package/dist/compliance/index.js +260 -0
- package/dist/compliance/privacy-impact-assessment.js +364 -0
- package/dist/compliance/pseudonymization.js +269 -0
- package/dist/compliance/query-firewall.js +1182 -0
- package/dist/compliance/rate-limiter.js +580 -0
- package/dist/compliance/right-to-erasure.js +117 -0
- package/dist/compliance/row-level-security.js +246 -0
- package/dist/compliance/security-decorator.js +574 -0
- package/dist/compliance/security-monitor.js +525 -0
- package/dist/compliance/sensitive-data-discovery.js +476 -0
- package/dist/compliance/session-isolation.js +472 -0
- package/dist/compliance/tls-enforcer.js +108 -0
- package/dist/compliance/worm-storage.js +712 -0
- package/dist/connection-manager.js +198 -0
- package/dist/connection-pool.js +519 -0
- package/dist/decorators/audit.js +136 -0
- package/dist/decorators/belongs-to-many.js +115 -0
- package/dist/decorators/belongs-to.js +115 -0
- package/dist/decorators/check.js +435 -0
- package/dist/decorators/collate.js +329 -0
- package/dist/decorators/comment.js +205 -0
- package/dist/decorators/database-settings.js +236 -0
- package/dist/decorators/default.js +244 -0
- package/dist/decorators/encryption.js +235 -0
- package/dist/decorators/engine.js +97 -0
- package/dist/decorators/fk-constraints.js +594 -0
- package/dist/decorators/foreign-table.js +136 -0
- package/dist/decorators/generated.js +274 -0
- package/dist/decorators/has-many.js +127 -0
- package/dist/decorators/has-one.js +116 -0
- package/dist/decorators/hstore.js +129 -0
- package/dist/decorators/index.js +355 -0
- package/dist/decorators/json-column.js +83 -0
- package/dist/decorators/jsonb.js +101 -0
- package/dist/decorators/orm-decorators.js +425 -0
- package/dist/decorators/permissions.js +294 -0
- package/dist/decorators/procedure.js +210 -0
- package/dist/decorators/query-options.js +556 -0
- package/dist/decorators/range.js +167 -0
- package/dist/decorators/set-column.js +83 -0
- package/dist/decorators/spatial.js +114 -0
- package/dist/decorators/storage.js +580 -0
- package/dist/decorators/timezone.js +512 -0
- package/dist/decorators/trigger.js +90 -0
- package/dist/decorators/uuid.js +135 -0
- package/dist/decorators/view.js +258 -0
- package/dist/diagrams/chen-diagram.js +354 -0
- package/dist/diagrams/class-diagram.js +384 -0
- package/dist/diagrams/dependency-diagram.js +432 -0
- package/dist/diagrams/er-diagram.js +605 -0
- package/dist/diagrams/flow-diagram.js +394 -0
- package/dist/diagrams/gantt-diagram.js +411 -0
- package/dist/diagrams/index-diagram.js +353 -0
- package/dist/diagrams/index.js +184 -0
- package/dist/diagrams/migration-diagram.js +316 -0
- package/dist/diagrams/model-diagram.js +616 -0
- package/dist/diagrams/package-diagram.js +376 -0
- package/dist/diagrams/palette.js +85 -0
- package/dist/diagrams/relational-diagram.js +455 -0
- package/dist/diagrams/schemadoc-diagram.js +309 -0
- package/dist/diagrams/sequence-diagram.js +307 -0
- package/dist/diagrams/state-diagram.js +344 -0
- package/dist/diagrams/svg-dom.js +111 -0
- package/dist/diagrams/tree-diagram.js +250 -0
- package/dist/dialects/clickhouse/index.js +1742 -0
- package/dist/dialects/cockroachdb/index.js +4677 -0
- package/dist/dialects/cratedb/index.js +441 -0
- package/dist/dialects/databricks/index.js +517 -0
- package/dist/dialects/db2/index.js +2225 -0
- package/dist/dialects/dialect.js +720 -0
- package/dist/dialects/duckdb/index.js +2014 -0
- package/dist/dialects/exasol/index.js +357 -0
- package/dist/dialects/firebird/index.js +495 -0
- package/dist/dialects/greenplum/index.js +457 -0
- package/dist/dialects/hana/index.js +1741 -0
- package/dist/dialects/mariadb/index.js +3590 -0
- package/dist/dialects/mssql/index.js +2296 -0
- package/dist/dialects/mysql/index.js +4058 -0
- package/dist/dialects/oracle/index.js +2999 -0
- package/dist/dialects/postgres/index.js +5319 -0
- package/dist/dialects/query-stream-helper.js +152 -0
- package/dist/dialects/questdb/index.js +433 -0
- package/dist/dialects/redshift/index.js +2277 -0
- package/dist/dialects/singlestore/index.js +354 -0
- package/dist/dialects/snowflake/index.js +2082 -0
- package/dist/dialects/spanner/index.js +1768 -0
- package/dist/dialects/sqlite/index.js +3382 -0
- package/dist/dialects/tidb/index.js +377 -0
- package/dist/dialects/timescaledb/index.js +164 -0
- package/dist/dialects/trino/index.js +420 -0
- package/dist/dialects/turso/index.js +227 -0
- package/dist/dialects/vertica/index.js +317 -0
- package/dist/dialects/yugabytedb/index.js +424 -0
- package/dist/errors/index.js +472 -0
- package/dist/errors/utils.js +340 -0
- package/dist/errors.js +21 -0
- package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
- package/dist/extensions/catalog/mssql-features.js +147 -0
- package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
- package/dist/extensions/catalog/oracle-db2-features.js +196 -0
- package/dist/extensions/catalog/postgres-extensions.js +516 -0
- package/dist/extensions/index.js +71 -0
- package/dist/extensions/types.js +13 -0
- package/dist/foreign-data.js +173 -0
- package/dist/hooks/hooks-manager.js +350 -0
- package/dist/hooks/index.js +37 -0
- package/dist/index.js +463 -0
- package/dist/logging.js +335 -0
- package/dist/migrations/index.js +40 -0
- package/dist/migrations/migration.js +196 -0
- package/dist/migrations/migrator.js +411 -0
- package/dist/migrations/prormmigration.js +275 -0
- package/dist/migrations/query-interface.js +435 -0
- package/dist/migrations/seeder.js +353 -0
- package/dist/models/associations.js +852 -0
- package/dist/models/constraints.js +288 -0
- package/dist/models/data-types.js +2518 -0
- package/dist/models/decorators.js +445 -0
- package/dist/models/index.js +33 -0
- package/dist/models/indexes.js +531 -0
- package/dist/models/methods.js +382 -0
- package/dist/models/model-manager.js +103 -0
- package/dist/models/model.js +5349 -0
- package/dist/models/operators.js +67 -0
- package/dist/models/scopes.js +189 -0
- package/dist/models/typescript-types.js +26 -0
- package/dist/nosql/aerospike/index.js +205 -0
- package/dist/nosql/allegrograph/index.js +169 -0
- package/dist/nosql/arangodb/index.js +364 -0
- package/dist/nosql/azure-blob/index.js +206 -0
- package/dist/nosql/beanstalkd/index.js +231 -0
- package/dist/nosql/beequeue/index.js +210 -0
- package/dist/nosql/bigchaindb/index.js +195 -0
- package/dist/nosql/bigtable/index.js +224 -0
- package/dist/nosql/blazegraph/index.js +173 -0
- package/dist/nosql/bullmq/index.js +191 -0
- package/dist/nosql/cassandra/index.js +174 -0
- package/dist/nosql/chroma/index.js +190 -0
- package/dist/nosql/cloudflare-kv/index.js +220 -0
- package/dist/nosql/coherence/index.js +200 -0
- package/dist/nosql/cosmosdb/index.js +157 -0
- package/dist/nosql/couchbase/index.js +213 -0
- package/dist/nosql/dax/index.js +212 -0
- package/dist/nosql/deno-kv/index.js +206 -0
- package/dist/nosql/dgraph/index.js +171 -0
- package/dist/nosql/doris/index.js +169 -0
- package/dist/nosql/druid/index.js +162 -0
- package/dist/nosql/dynamodb/index.js +937 -0
- package/dist/nosql/elasticsearch/index.js +377 -0
- package/dist/nosql/etcd/index.js +502 -0
- package/dist/nosql/eventhubs/index.js +213 -0
- package/dist/nosql/eventstore/index.js +254 -0
- package/dist/nosql/faunadb/index.js +188 -0
- package/dist/nosql/firestore/index.js +177 -0
- package/dist/nosql/fluree/index.js +148 -0
- package/dist/nosql/fuseki/index.js +170 -0
- package/dist/nosql/gcs/index.js +172 -0
- package/dist/nosql/gearman/index.js +160 -0
- package/dist/nosql/geode/index.js +196 -0
- package/dist/nosql/graphdb/index.js +169 -0
- package/dist/nosql/graylog/index.js +188 -0
- package/dist/nosql/gridgain/index.js +171 -0
- package/dist/nosql/hazelcast/index.js +162 -0
- package/dist/nosql/hbase/index.js +230 -0
- package/dist/nosql/ignite/index.js +173 -0
- package/dist/nosql/immudb/index.js +184 -0
- package/dist/nosql/index.js +232 -0
- package/dist/nosql/infinispan/index.js +200 -0
- package/dist/nosql/influxdb/index.js +0 -0
- package/dist/nosql/kafka/index.js +234 -0
- package/dist/nosql/keyspaces/index.js +189 -0
- package/dist/nosql/kinesis/index.js +253 -0
- package/dist/nosql/leveldb/index.js +153 -0
- package/dist/nosql/lmdb/index.js +160 -0
- package/dist/nosql/loki/index.js +201 -0
- package/dist/nosql/marklogic/index.js +204 -0
- package/dist/nosql/materialize/index.js +145 -0
- package/dist/nosql/meilisearch/index.js +154 -0
- package/dist/nosql/memcached/index.js +223 -0
- package/dist/nosql/milvus/index.js +410 -0
- package/dist/nosql/minio/index.js +265 -0
- package/dist/nosql/momento/index.js +179 -0
- package/dist/nosql/mongodb/index.js +461 -0
- package/dist/nosql/nats/index.js +247 -0
- package/dist/nosql/nedb/index.js +164 -0
- package/dist/nosql/neo4j/index.js +450 -0
- package/dist/nosql/neptune/index.js +470 -0
- package/dist/nosql/nsq/index.js +200 -0
- package/dist/nosql/opensearch/index.js +186 -0
- package/dist/nosql/orientdb/index.js +175 -0
- package/dist/nosql/papertrail/index.js +200 -0
- package/dist/nosql/pinecone/index.js +0 -0
- package/dist/nosql/pinot/index.js +133 -0
- package/dist/nosql/pouchdb/index.js +172 -0
- package/dist/nosql/prometheus/index.js +174 -0
- package/dist/nosql/provendb/index.js +147 -0
- package/dist/nosql/pubsub/index.js +187 -0
- package/dist/nosql/pulsar/index.js +232 -0
- package/dist/nosql/qdrant/index.js +295 -0
- package/dist/nosql/qldb/index.js +192 -0
- package/dist/nosql/r2/index.js +281 -0
- package/dist/nosql/rabbitmq/index.js +237 -0
- package/dist/nosql/ravendb/index.js +175 -0
- package/dist/nosql/redis/index.js +607 -0
- package/dist/nosql/redpanda/index.js +237 -0
- package/dist/nosql/resque/index.js +203 -0
- package/dist/nosql/rethinkdb/index.js +232 -0
- package/dist/nosql/rocksdb/index.js +152 -0
- package/dist/nosql/rockset/index.js +126 -0
- package/dist/nosql/s3/index.js +298 -0
- package/dist/nosql/scylladb/index.js +178 -0
- package/dist/nosql/signoz/index.js +227 -0
- package/dist/nosql/sns/index.js +201 -0
- package/dist/nosql/solr/index.js +231 -0
- package/dist/nosql/splunk/index.js +227 -0
- package/dist/nosql/sqs/index.js +246 -0
- package/dist/nosql/stardog/index.js +169 -0
- package/dist/nosql/starrocks/index.js +170 -0
- package/dist/nosql/store.js +2 -0
- package/dist/nosql/sumologic/index.js +213 -0
- package/dist/nosql/surrealdb/index.js +179 -0
- package/dist/nosql/terminusdb/index.js +151 -0
- package/dist/nosql/tigergraph/index.js +469 -0
- package/dist/nosql/typesense/index.js +148 -0
- package/dist/nosql/unqlite/index.js +157 -0
- package/dist/nosql/upstash/index.js +167 -0
- package/dist/nosql/vercel-kv/index.js +166 -0
- package/dist/nosql/victoriametrics/index.js +213 -0
- package/dist/nosql/virtuoso/index.js +169 -0
- package/dist/nosql/weaviate/index.js +276 -0
- package/dist/operators/index.js +108 -0
- package/dist/operators.js +2690 -0
- package/dist/prisma-migrate/index.js +38 -0
- package/dist/prisma-migrate/migration-generator.js +125 -0
- package/dist/prisma-migrate/model-generator.js +172 -0
- package/dist/prisma-migrate/relations.js +100 -0
- package/dist/prisma-migrate/schema-parser.js +167 -0
- package/dist/prisma-migrate/type-mapper.js +40 -0
- package/dist/prorm.js +6832 -0
- package/dist/query-builders/cte-builder.js +80 -0
- package/dist/query-builders/functions/aggregate.js +390 -0
- package/dist/query-builders/functions/conditional.js +503 -0
- package/dist/query-builders/functions/datetime.js +695 -0
- package/dist/query-builders/functions/fulltext.js +439 -0
- package/dist/query-builders/functions/index.js +93 -0
- package/dist/query-builders/functions/json.js +427 -0
- package/dist/query-builders/functions/math.js +399 -0
- package/dist/query-builders/functions/string.js +518 -0
- package/dist/query-builders/functions/window.js +328 -0
- package/dist/query-builders/include-builder.js +323 -0
- package/dist/query-builders/index-expression-builder.js +242 -0
- package/dist/query-builders/index.js +161 -0
- package/dist/query-builders/insert-builder.js +164 -0
- package/dist/query-builders/model-helpers.js +38 -0
- package/dist/query-builders/order-limit-builder.js +239 -0
- package/dist/query-builders/sql-compiler.js +2040 -0
- package/dist/query-builders/subquery-builder.js +152 -0
- package/dist/query-builders/update-builder.js +182 -0
- package/dist/query-builders/view-builder.js +218 -0
- package/dist/query-builders/where-builder.js +1532 -0
- package/dist/query-interface.js +622 -0
- package/dist/query-optimizers/batch-optimizer.js +426 -0
- package/dist/query-optimizers/explain-plans.js +415 -0
- package/dist/query-optimizers/index.js +51 -0
- package/dist/query-optimizers/prepared-statement-cache.js +423 -0
- package/dist/query-optimizers/query-hints.js +438 -0
- package/dist/query-optimizers/query-optimizer.js +278 -0
- package/dist/query-optimizers/slow-query-logger.js +271 -0
- package/dist/replica-manager.js +507 -0
- package/dist/schema/index.js +15 -0
- package/dist/schema/migration-generator.js +374 -0
- package/dist/schema/schema-differ.js +549 -0
- package/dist/schema/types.js +6 -0
- package/dist/sql-constants.js +300 -0
- package/dist/sqlite-advanced.js +1047 -0
- package/dist/streams/index.js +12 -0
- package/dist/streams/transforms.js +178 -0
- package/dist/transaction.js +456 -0
- package/dist/types/index.js +180 -0
- package/dist/user-management.js +127 -0
- package/dist/utils/date.js +300 -0
- package/dist/utils/index.js +1079 -0
- package/dist/utils/string.js +161 -0
- package/dist/validators/index.js +19 -0
- package/dist/validators/validator.js +911 -0
- package/package.json +190 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Connection Manager for managing multiple named database connections
|
|
4
|
+
* Supports cross-database queries and SQLite ATTACH DATABASE
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.ConnectionManager = void 0;
|
|
8
|
+
exports.createConnectionManager = createConnectionManager;
|
|
9
|
+
const prorm_1 = require("./prorm");
|
|
10
|
+
/**
|
|
11
|
+
* Connection Manager class for managing multiple database connections
|
|
12
|
+
* Allows switching between different databases in the same application
|
|
13
|
+
*/
|
|
14
|
+
class ConnectionManager {
|
|
15
|
+
/**
|
|
16
|
+
* Create a new ConnectionManager instance
|
|
17
|
+
*/
|
|
18
|
+
constructor() {
|
|
19
|
+
this.connections = new Map();
|
|
20
|
+
this._defaultConnection = null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Add a new named database connection
|
|
24
|
+
* @param name - Unique name to identify this connection
|
|
25
|
+
* @param options - Prorm options for the connection
|
|
26
|
+
* @returns The Prorm instance for the new connection
|
|
27
|
+
* @example
|
|
28
|
+
* // Add a secondary SQLite database
|
|
29
|
+
* const manager = new ConnectionManager();
|
|
30
|
+
* await manager.addConnection('analytics', {
|
|
31
|
+
* dialect: 'sqlite',
|
|
32
|
+
* storage: './analytics.db'
|
|
33
|
+
* });
|
|
34
|
+
*/
|
|
35
|
+
async addConnection(name, options) {
|
|
36
|
+
if (this.connections.has(name)) {
|
|
37
|
+
throw new Error(`Connection with name '${name}' already exists`);
|
|
38
|
+
}
|
|
39
|
+
const prorm = new prorm_1.Prorm(options);
|
|
40
|
+
this.connections.set(name, prorm);
|
|
41
|
+
// Set as default if it's the first connection
|
|
42
|
+
if (this._defaultConnection === null) {
|
|
43
|
+
this._defaultConnection = name;
|
|
44
|
+
}
|
|
45
|
+
return prorm;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get a connection by name
|
|
49
|
+
* @param name - The connection name
|
|
50
|
+
* @returns The Prorm instance or undefined if not found
|
|
51
|
+
* @example
|
|
52
|
+
* const analyticsDb = manager.getConnection('analytics');
|
|
53
|
+
*/
|
|
54
|
+
getConnection(name) {
|
|
55
|
+
return this.connections.get(name);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Check if a connection exists
|
|
59
|
+
* @param name - The connection name to check
|
|
60
|
+
* @returns True if the connection exists
|
|
61
|
+
* @example
|
|
62
|
+
* if (manager.hasConnection('analytics')) {
|
|
63
|
+
* // Use analytics connection
|
|
64
|
+
* }
|
|
65
|
+
*/
|
|
66
|
+
hasConnection(name) {
|
|
67
|
+
return this.connections.has(name);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Remove a connection by name
|
|
71
|
+
* @param name - The connection name to remove
|
|
72
|
+
* @returns True if the connection was removed
|
|
73
|
+
* @example
|
|
74
|
+
* await manager.removeConnection('analytics');
|
|
75
|
+
*/
|
|
76
|
+
async removeConnection(name) {
|
|
77
|
+
const prorm = this.connections.get(name);
|
|
78
|
+
if (!prorm) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
// Close the connection
|
|
82
|
+
await prorm.close();
|
|
83
|
+
this.connections.delete(name);
|
|
84
|
+
// Update default if needed
|
|
85
|
+
if (this._defaultConnection === name) {
|
|
86
|
+
const remaining = Array.from(this.connections.keys());
|
|
87
|
+
this._defaultConnection = remaining.length > 0 ? remaining[0] : null;
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get all connection names
|
|
93
|
+
* @returns Array of connection names
|
|
94
|
+
* @example
|
|
95
|
+
* const names = manager.getConnectionNames();
|
|
96
|
+
* // ['main', 'analytics', 'logs']
|
|
97
|
+
*/
|
|
98
|
+
getConnectionNames() {
|
|
99
|
+
return Array.from(this.connections.keys());
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get or set the default connection name
|
|
103
|
+
*/
|
|
104
|
+
get defaultConnection() {
|
|
105
|
+
return this._defaultConnection;
|
|
106
|
+
}
|
|
107
|
+
set defaultConnection(name) {
|
|
108
|
+
if (name !== null && !this.connections.has(name)) {
|
|
109
|
+
throw new Error(`Connection with name '${name}' does not exist`);
|
|
110
|
+
}
|
|
111
|
+
this._defaultConnection = name;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get all connections
|
|
115
|
+
* @returns Map of connection names to Prorm instances
|
|
116
|
+
*/
|
|
117
|
+
get connectionsMap() {
|
|
118
|
+
return new Map(this.connections);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Attach a SQLite database using ATTACH DATABASE
|
|
122
|
+
* This allows querying across multiple SQLite files
|
|
123
|
+
* @param mainConnectionName - The name of the main connection to attach to
|
|
124
|
+
* @param alias - The alias to use for the attached database
|
|
125
|
+
* @param path - Path to the SQLite file to attach
|
|
126
|
+
* @example
|
|
127
|
+
* // Attach analytics database to main connection
|
|
128
|
+
* await manager.attachDatabase('main', 'analytics', './analytics.db');
|
|
129
|
+
* // Now you can query: SELECT * FROM analytics.users
|
|
130
|
+
*/
|
|
131
|
+
async attachDatabase(mainConnectionName, alias, path) {
|
|
132
|
+
const prorm = this.connections.get(mainConnectionName);
|
|
133
|
+
if (!prorm) {
|
|
134
|
+
throw new Error(`Connection with name '${mainConnectionName}' not found`);
|
|
135
|
+
}
|
|
136
|
+
if (!alias || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(alias)) {
|
|
137
|
+
throw new Error(`Invalid database alias: ${alias}`);
|
|
138
|
+
}
|
|
139
|
+
// Execute ATTACH DATABASE query. `path` is bound as a parameter (not
|
|
140
|
+
// string-interpolated) since a raw path containing a single quote would
|
|
141
|
+
// otherwise break out of the literal; `alias` is validated above since
|
|
142
|
+
// it appears in an identifier position that can't be parameterized.
|
|
143
|
+
await prorm.query(`ATTACH DATABASE ? AS ${alias}`, { replacements: [path] });
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Detach a SQLite database
|
|
147
|
+
* @param mainConnectionName - The name of the main connection
|
|
148
|
+
* @param alias - The alias of the database to detach
|
|
149
|
+
* @example
|
|
150
|
+
* await manager.detachDatabase('main', 'analytics');
|
|
151
|
+
*/
|
|
152
|
+
async detachDatabase(mainConnectionName, alias) {
|
|
153
|
+
const prorm = this.connections.get(mainConnectionName);
|
|
154
|
+
if (!prorm) {
|
|
155
|
+
throw new Error(`Connection with name '${mainConnectionName}' not found`);
|
|
156
|
+
}
|
|
157
|
+
if (!alias || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(alias)) {
|
|
158
|
+
throw new Error(`Invalid database alias: ${alias}`);
|
|
159
|
+
}
|
|
160
|
+
await prorm.query(`DETACH DATABASE ${alias}`);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Close all connections
|
|
164
|
+
* @example
|
|
165
|
+
* await manager.closeAll();
|
|
166
|
+
*/
|
|
167
|
+
async closeAll() {
|
|
168
|
+
const closePromises = Array.from(this.connections.values()).map((seq) => seq.close());
|
|
169
|
+
await Promise.all(closePromises);
|
|
170
|
+
this.connections.clear();
|
|
171
|
+
this._defaultConnection = null;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Execute a raw query on a specific connection
|
|
175
|
+
* @param connectionName - The name of the connection to use
|
|
176
|
+
* @param sql - The SQL query to execute
|
|
177
|
+
* @param options - Optional query options
|
|
178
|
+
* @returns Query results
|
|
179
|
+
* @example
|
|
180
|
+
* const results = await manager.query('main', 'SELECT * FROM users');
|
|
181
|
+
*/
|
|
182
|
+
async query(connectionName, sql, options) {
|
|
183
|
+
const prorm = this.connections.get(connectionName);
|
|
184
|
+
if (!prorm) {
|
|
185
|
+
throw new Error(`Connection with name '${connectionName}' not found`);
|
|
186
|
+
}
|
|
187
|
+
return prorm.query(sql, options);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
exports.ConnectionManager = ConnectionManager;
|
|
191
|
+
/**
|
|
192
|
+
* Create a new ConnectionManager instance
|
|
193
|
+
* @example
|
|
194
|
+
* const manager = createConnectionManager();
|
|
195
|
+
*/
|
|
196
|
+
function createConnectionManager() {
|
|
197
|
+
return new ConnectionManager();
|
|
198
|
+
}
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Connection Pool Management
|
|
4
|
+
* Manages a pool of database connections for efficient resource usage
|
|
5
|
+
* Includes health checks, connection validation, and comprehensive metrics
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.DatabaseConnectionPool = exports.ConnectionPool = exports.PooledConnection = void 0;
|
|
9
|
+
exports.createPool = createPool;
|
|
10
|
+
const events_1 = require("events");
|
|
11
|
+
/**
|
|
12
|
+
* Pooled connection wrapper with health tracking
|
|
13
|
+
*/
|
|
14
|
+
class PooledConnection {
|
|
15
|
+
constructor(connection, id) {
|
|
16
|
+
this.inUse = false;
|
|
17
|
+
this.metadata = {};
|
|
18
|
+
this.healthCheckFailures = 0;
|
|
19
|
+
this.lastHealthCheck = 0;
|
|
20
|
+
this.lastValidation = 0;
|
|
21
|
+
this.isHealthy = true;
|
|
22
|
+
this.id = id || `conn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
23
|
+
this.connection = connection;
|
|
24
|
+
this.timestamp = Date.now();
|
|
25
|
+
this.connectTimestamp = Date.now();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Mark the connection as in use
|
|
29
|
+
*/
|
|
30
|
+
markInUse() {
|
|
31
|
+
this.inUse = true;
|
|
32
|
+
this.timestamp = Date.now();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Release the connection back to the pool
|
|
36
|
+
*/
|
|
37
|
+
release() {
|
|
38
|
+
this.inUse = false;
|
|
39
|
+
this.timestamp = Date.now();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if the connection is idle for too long
|
|
43
|
+
*/
|
|
44
|
+
isIdle(timeout) {
|
|
45
|
+
return !this.inUse && Date.now() - this.timestamp > timeout;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if the connection has been idle longer than the given timeout
|
|
49
|
+
*/
|
|
50
|
+
isIdleExceeding(timeout) {
|
|
51
|
+
return !this.inUse && Date.now() - this.timestamp > timeout;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Increment health check failure counter
|
|
55
|
+
*/
|
|
56
|
+
recordHealthCheckFailure() {
|
|
57
|
+
this.healthCheckFailures++;
|
|
58
|
+
this.lastHealthCheck = Date.now();
|
|
59
|
+
if (this.healthCheckFailures > 3) {
|
|
60
|
+
this.isHealthy = false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Reset health check failures on successful check
|
|
65
|
+
*/
|
|
66
|
+
resetHealthCheckFailures() {
|
|
67
|
+
this.healthCheckFailures = 0;
|
|
68
|
+
this.isHealthy = true;
|
|
69
|
+
this.lastHealthCheck = Date.now();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get connection age in milliseconds
|
|
73
|
+
*/
|
|
74
|
+
getAge() {
|
|
75
|
+
return Date.now() - this.connectTimestamp;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.PooledConnection = PooledConnection;
|
|
79
|
+
/**
|
|
80
|
+
* Connection Pool class
|
|
81
|
+
* Manages a pool of database connections with configurable limits
|
|
82
|
+
*/
|
|
83
|
+
class ConnectionPool extends events_1.EventEmitter {
|
|
84
|
+
/**
|
|
85
|
+
* Maximum number of connections in the pool
|
|
86
|
+
*/
|
|
87
|
+
get max() {
|
|
88
|
+
return this.config.max ?? 10;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Minimum number of idle connections
|
|
92
|
+
*/
|
|
93
|
+
get min() {
|
|
94
|
+
return this.config.min ?? 0;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get the pending requests count
|
|
98
|
+
*/
|
|
99
|
+
get pending() {
|
|
100
|
+
return this._pending;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Constructor
|
|
104
|
+
*/
|
|
105
|
+
constructor(config) {
|
|
106
|
+
super();
|
|
107
|
+
this.connections = new Map();
|
|
108
|
+
this.waitingQueue = [];
|
|
109
|
+
this._isDestroyed = false;
|
|
110
|
+
// Statistics
|
|
111
|
+
this._size = 0;
|
|
112
|
+
this._available = 0;
|
|
113
|
+
this._inUse = 0;
|
|
114
|
+
this._acquired = 0;
|
|
115
|
+
this._released = 0;
|
|
116
|
+
this._destroyed = 0;
|
|
117
|
+
this._pending = 0;
|
|
118
|
+
this.config = {
|
|
119
|
+
max: 10,
|
|
120
|
+
min: 0,
|
|
121
|
+
acquire: 60000, // 60 seconds
|
|
122
|
+
idle: 30000, // 30 seconds
|
|
123
|
+
evict: 1000, // 1 second
|
|
124
|
+
...config,
|
|
125
|
+
};
|
|
126
|
+
// Start eviction timer
|
|
127
|
+
this.startEvictor();
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Initialize the pool with a factory function to create connections
|
|
131
|
+
*/
|
|
132
|
+
async initialize() {
|
|
133
|
+
// Create minimum number of connections if specified
|
|
134
|
+
const createPromises = [];
|
|
135
|
+
const minConnections = this.config.min ?? 0;
|
|
136
|
+
for (let i = 0; i < minConnections; i++) {
|
|
137
|
+
createPromises.push(this.createConnection());
|
|
138
|
+
}
|
|
139
|
+
await Promise.allSettled(createPromises);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get a connection from the pool
|
|
143
|
+
*/
|
|
144
|
+
async getConnection() {
|
|
145
|
+
if (this.isDestroyed) {
|
|
146
|
+
throw new Error('Pool is destroyed');
|
|
147
|
+
}
|
|
148
|
+
// Try to find an available connection
|
|
149
|
+
const available = this.getAvailableConnection();
|
|
150
|
+
if (available) {
|
|
151
|
+
available.markInUse();
|
|
152
|
+
this._acquired++;
|
|
153
|
+
this._inUse++;
|
|
154
|
+
this._available--;
|
|
155
|
+
// Emit acquire event
|
|
156
|
+
this.emit('acquire', available.connection);
|
|
157
|
+
// Call onConnect callback if provided (Prorm-style)
|
|
158
|
+
if (this.config.onConnect) {
|
|
159
|
+
try {
|
|
160
|
+
this.config.onConnect(available.connection);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
this.emit('error', error);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// Legacy callback support
|
|
167
|
+
if (this.config.onAcquire) {
|
|
168
|
+
try {
|
|
169
|
+
this.config.onAcquire(available.connection);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
// Log but don't fail the connection acquisition
|
|
173
|
+
console.error('onAcquire callback error:', error);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Log pool operation if enabled
|
|
177
|
+
if (this.config.logPoolOperations) {
|
|
178
|
+
console.log(`[Pool] Connection acquired. Pool size: ${this.size}, available: ${this._available}, in use: ${this._inUse}`);
|
|
179
|
+
}
|
|
180
|
+
return available;
|
|
181
|
+
}
|
|
182
|
+
// If we can create more connections, do so
|
|
183
|
+
const maxConnections = this.config.max ?? 10;
|
|
184
|
+
if (this.connections.size < maxConnections) {
|
|
185
|
+
const connection = await this.createConnection();
|
|
186
|
+
connection.markInUse();
|
|
187
|
+
this._acquired++;
|
|
188
|
+
this._inUse++;
|
|
189
|
+
if (this.config.onAcquire) {
|
|
190
|
+
try {
|
|
191
|
+
this.config.onAcquire(connection.connection);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
console.error('onAcquire callback error:', error);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return connection;
|
|
198
|
+
}
|
|
199
|
+
// Wait for a connection to become available
|
|
200
|
+
return new Promise((resolve, reject) => {
|
|
201
|
+
const timeoutId = setTimeout(() => {
|
|
202
|
+
// Remove from waiting queue
|
|
203
|
+
const index = this.waitingQueue.findIndex((w) => w.resolve === resolve);
|
|
204
|
+
if (index !== -1) {
|
|
205
|
+
this.waitingQueue.splice(index, 1);
|
|
206
|
+
}
|
|
207
|
+
// Emit timeout event
|
|
208
|
+
this.emit('timeout', null);
|
|
209
|
+
reject(new Error(`Acquisition timeout after ${this.config.acquire}ms. Pool size: ${this.connections.size}, max: ${this.config.max}`));
|
|
210
|
+
}, this.config.acquire);
|
|
211
|
+
this.waitingQueue.push({ resolve, reject, timeoutId });
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Release a connection back to the pool
|
|
216
|
+
*/
|
|
217
|
+
releaseConnection(pooledConnection) {
|
|
218
|
+
if (this.isDestroyed) {
|
|
219
|
+
this.destroyConnection(pooledConnection);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
pooledConnection.release();
|
|
223
|
+
this._released++;
|
|
224
|
+
this._inUse--;
|
|
225
|
+
this._available++;
|
|
226
|
+
// Emit release event
|
|
227
|
+
this.emit('release', pooledConnection.connection);
|
|
228
|
+
// Call onDisconnect callback if provided (Prorm-style)
|
|
229
|
+
if (this.config.onDisconnect) {
|
|
230
|
+
try {
|
|
231
|
+
this.config.onDisconnect(pooledConnection.connection);
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
this.emit('error', error);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Legacy callback support
|
|
238
|
+
if (this.config.onRelease) {
|
|
239
|
+
try {
|
|
240
|
+
this.config.onRelease(pooledConnection.connection);
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
console.error('onRelease callback error:', error);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Log pool operations if enabled
|
|
247
|
+
if (this.config.logPoolOperations) {
|
|
248
|
+
console.log(`[Pool] Connection released. Pool size: ${this.size}, available: ${this._available}, in use: ${this._inUse}`);
|
|
249
|
+
}
|
|
250
|
+
// Process waiting queue
|
|
251
|
+
this.processWaitingQueue();
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Destroy a connection
|
|
255
|
+
*/
|
|
256
|
+
async destroyConnection(pooledConnection) {
|
|
257
|
+
const { connection } = pooledConnection;
|
|
258
|
+
// Remove from pool
|
|
259
|
+
this.connections.delete(pooledConnection.id);
|
|
260
|
+
this._size--;
|
|
261
|
+
this._destroyed++;
|
|
262
|
+
if (pooledConnection.inUse) {
|
|
263
|
+
this._inUse--;
|
|
264
|
+
this._available--;
|
|
265
|
+
}
|
|
266
|
+
// Emit remove event
|
|
267
|
+
this.emit('remove', connection);
|
|
268
|
+
if (this.config.onDestroy) {
|
|
269
|
+
try {
|
|
270
|
+
this.config.onDestroy(connection);
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
this.emit('error', error);
|
|
274
|
+
console.error('onDestroy callback error:', error);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Log pool operations if enabled
|
|
278
|
+
if (this.config.logPoolOperations) {
|
|
279
|
+
console.log(`[Pool] Connection removed. Pool size: ${this._size}, available: ${this._available}, in use: ${this._inUse}`);
|
|
280
|
+
}
|
|
281
|
+
// Close the actual connection if it has a close method
|
|
282
|
+
try {
|
|
283
|
+
if (typeof connection.close === 'function') {
|
|
284
|
+
await connection.close();
|
|
285
|
+
}
|
|
286
|
+
else if (typeof connection.end === 'function') {
|
|
287
|
+
await connection.end();
|
|
288
|
+
}
|
|
289
|
+
else if (typeof connection.disconnect === 'function') {
|
|
290
|
+
await connection.disconnect();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
console.error('Error closing connection:', error);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Destroy a specific connection or the entire pool
|
|
299
|
+
* @param connection - Optional connection to destroy. If not provided, destroys the entire pool
|
|
300
|
+
*/
|
|
301
|
+
async destroy(connection) {
|
|
302
|
+
// If a connection is provided, destroy just that connection
|
|
303
|
+
if (connection) {
|
|
304
|
+
for (const [, pooledConnection] of this.connections) {
|
|
305
|
+
if (pooledConnection.connection === connection) {
|
|
306
|
+
await this.destroyConnection(pooledConnection);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
// Otherwise destroy the entire pool
|
|
313
|
+
if (this._isDestroyed) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
this._isDestroyed = true;
|
|
317
|
+
// Clear evict timer
|
|
318
|
+
if (this.evictTimer) {
|
|
319
|
+
clearInterval(this.evictTimer);
|
|
320
|
+
this.evictTimer = undefined;
|
|
321
|
+
}
|
|
322
|
+
// Reject waiting promises
|
|
323
|
+
for (const { reject, timeoutId } of this.waitingQueue) {
|
|
324
|
+
if (timeoutId) {
|
|
325
|
+
clearTimeout(timeoutId);
|
|
326
|
+
}
|
|
327
|
+
reject(new Error('Pool is being destroyed'));
|
|
328
|
+
}
|
|
329
|
+
this.waitingQueue = [];
|
|
330
|
+
// Destroy all connections
|
|
331
|
+
const destroyPromises = [];
|
|
332
|
+
for (const [, pooledConnection] of this.connections) {
|
|
333
|
+
destroyPromises.push(this.destroyConnection(pooledConnection));
|
|
334
|
+
}
|
|
335
|
+
await Promise.all(destroyPromises);
|
|
336
|
+
this.connections.clear();
|
|
337
|
+
this._size = 0;
|
|
338
|
+
this._available = 0;
|
|
339
|
+
this._inUse = 0;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Get pool statistics
|
|
343
|
+
*/
|
|
344
|
+
get stats() {
|
|
345
|
+
return {
|
|
346
|
+
size: this.connections.size,
|
|
347
|
+
available: this._available,
|
|
348
|
+
inUse: this._inUse,
|
|
349
|
+
acquired: this._acquired,
|
|
350
|
+
released: this._released,
|
|
351
|
+
destroyed: this._destroyed,
|
|
352
|
+
pending: this.waitingQueue.length,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Get the current pool size
|
|
357
|
+
*/
|
|
358
|
+
get size() {
|
|
359
|
+
return this._size;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Get the number of available connections
|
|
363
|
+
*/
|
|
364
|
+
get available() {
|
|
365
|
+
return this._available;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Get the number of connections in use
|
|
369
|
+
*/
|
|
370
|
+
get inUse() {
|
|
371
|
+
return this._inUse;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Check if the pool is destroyed
|
|
375
|
+
*/
|
|
376
|
+
get isDestroyed() {
|
|
377
|
+
return this._isDestroyed;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Get the number of connections in use (alias for inUse)
|
|
381
|
+
*/
|
|
382
|
+
get used() {
|
|
383
|
+
return this._inUse;
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Get an available connection from the pool
|
|
387
|
+
*/
|
|
388
|
+
getAvailableConnection() {
|
|
389
|
+
for (const [, pooledConnection] of this.connections) {
|
|
390
|
+
if (!pooledConnection.inUse) {
|
|
391
|
+
return pooledConnection;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Create a new connection
|
|
398
|
+
*/
|
|
399
|
+
async createConnection() {
|
|
400
|
+
if (this.isDestroyed) {
|
|
401
|
+
throw new Error('Pool is destroyed');
|
|
402
|
+
}
|
|
403
|
+
const maxConnections = this.config.max ?? 10;
|
|
404
|
+
if (this.connections.size >= maxConnections) {
|
|
405
|
+
throw new Error('Pool is at maximum capacity');
|
|
406
|
+
}
|
|
407
|
+
// This should be overridden by subclasses or set up via the factory
|
|
408
|
+
// For now, we'll throw an error if no factory is provided
|
|
409
|
+
throw new Error('Connection factory not set. Use setConnectionFactory()');
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Process the waiting queue
|
|
413
|
+
*/
|
|
414
|
+
processWaitingQueue() {
|
|
415
|
+
while (this.waitingQueue.length > 0 && this.getAvailableConnection()) {
|
|
416
|
+
const { resolve, timeoutId } = this.waitingQueue.shift();
|
|
417
|
+
if (timeoutId) {
|
|
418
|
+
clearTimeout(timeoutId);
|
|
419
|
+
}
|
|
420
|
+
const connection = this.getAvailableConnection();
|
|
421
|
+
if (connection) {
|
|
422
|
+
connection.markInUse();
|
|
423
|
+
this._acquired++;
|
|
424
|
+
this._inUse++;
|
|
425
|
+
this._available--;
|
|
426
|
+
if (this.config.onAcquire) {
|
|
427
|
+
try {
|
|
428
|
+
this.config.onAcquire(connection.connection);
|
|
429
|
+
}
|
|
430
|
+
catch (error) {
|
|
431
|
+
console.error('onAcquire callback error:', error);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
resolve(connection);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Start the evictor to clean up idle connections
|
|
440
|
+
*/
|
|
441
|
+
startEvictor() {
|
|
442
|
+
this.evictTimer = setInterval(async () => {
|
|
443
|
+
if (this.isDestroyed) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
// Check for idle connections to evict
|
|
447
|
+
const toEvict = [];
|
|
448
|
+
for (const [, pooledConnection] of this.connections) {
|
|
449
|
+
// Don't evict if we're below minimum
|
|
450
|
+
const minConnections = this.config.min ?? 0;
|
|
451
|
+
if (this.connections.size - toEvict.length <= minConnections) {
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
const idleTimeout = this.config.idle ?? 30000;
|
|
455
|
+
if (pooledConnection.isIdle(idleTimeout)) {
|
|
456
|
+
toEvict.push(pooledConnection);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
// Destroy idle connections
|
|
460
|
+
for (const pooledConnection of toEvict) {
|
|
461
|
+
await this.destroyConnection(pooledConnection);
|
|
462
|
+
}
|
|
463
|
+
}, this.config.evict || 1000);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
exports.ConnectionPool = ConnectionPool;
|
|
467
|
+
/**
|
|
468
|
+
* Database-specific connection pool implementation
|
|
469
|
+
*/
|
|
470
|
+
class DatabaseConnectionPool extends ConnectionPool {
|
|
471
|
+
constructor(config) {
|
|
472
|
+
super(config);
|
|
473
|
+
this.connectionFactory = config.factory;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Create a new database connection
|
|
477
|
+
*/
|
|
478
|
+
async createConnection() {
|
|
479
|
+
try {
|
|
480
|
+
const connection = await this.connectionFactory();
|
|
481
|
+
const pooledConnection = new PooledConnection(connection);
|
|
482
|
+
this.connections.set(pooledConnection.id, pooledConnection);
|
|
483
|
+
this._size++;
|
|
484
|
+
this._available++;
|
|
485
|
+
return pooledConnection;
|
|
486
|
+
}
|
|
487
|
+
catch (error) {
|
|
488
|
+
throw new Error(`Failed to create connection: ${error.message}`);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Get a connection using async/await
|
|
493
|
+
*/
|
|
494
|
+
async acquire() {
|
|
495
|
+
const pooledConnection = await this.getConnection();
|
|
496
|
+
return pooledConnection.connection;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Release a connection
|
|
500
|
+
*/
|
|
501
|
+
release(connection) {
|
|
502
|
+
for (const [, pooledConnection] of this.connections) {
|
|
503
|
+
if (pooledConnection.connection === connection) {
|
|
504
|
+
this.releaseConnection(pooledConnection);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
exports.DatabaseConnectionPool = DatabaseConnectionPool;
|
|
511
|
+
/**
|
|
512
|
+
* Create a new connection pool
|
|
513
|
+
*/
|
|
514
|
+
function createPool(config) {
|
|
515
|
+
const pool = new DatabaseConnectionPool(config);
|
|
516
|
+
pool.initialize();
|
|
517
|
+
return pool;
|
|
518
|
+
}
|
|
519
|
+
exports.default = ConnectionPool;
|