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.
Files changed (310) hide show
  1. package/CHANGELOG.md +1111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +573 -0
  4. package/dist/audit/history-query.js +180 -0
  5. package/dist/audit/index.js +23 -0
  6. package/dist/audit/logger.js +236 -0
  7. package/dist/cache/cache-manager.js +84 -0
  8. package/dist/cache/index.js +16 -0
  9. package/dist/cache/redis-cluster-cache.js +557 -0
  10. package/dist/cli.js +2200 -0
  11. package/dist/compliance/audit-trail.js +68 -0
  12. package/dist/compliance/backup-verification.js +685 -0
  13. package/dist/compliance/breach-detector.js +505 -0
  14. package/dist/compliance/consent-record.js +227 -0
  15. package/dist/compliance/consent-versioning.js +331 -0
  16. package/dist/compliance/cross-border-log.js +530 -0
  17. package/dist/compliance/data-classifier.js +258 -0
  18. package/dist/compliance/data-lineage.js +565 -0
  19. package/dist/compliance/data-masker.js +303 -0
  20. package/dist/compliance/data-portability.js +265 -0
  21. package/dist/compliance/data-retention.js +195 -0
  22. package/dist/compliance/dsar-workflow.js +342 -0
  23. package/dist/compliance/field-encryption.js +223 -0
  24. package/dist/compliance/immutable-record.js +148 -0
  25. package/dist/compliance/index.js +260 -0
  26. package/dist/compliance/privacy-impact-assessment.js +364 -0
  27. package/dist/compliance/pseudonymization.js +269 -0
  28. package/dist/compliance/query-firewall.js +1182 -0
  29. package/dist/compliance/rate-limiter.js +580 -0
  30. package/dist/compliance/right-to-erasure.js +117 -0
  31. package/dist/compliance/row-level-security.js +246 -0
  32. package/dist/compliance/security-decorator.js +574 -0
  33. package/dist/compliance/security-monitor.js +525 -0
  34. package/dist/compliance/sensitive-data-discovery.js +476 -0
  35. package/dist/compliance/session-isolation.js +472 -0
  36. package/dist/compliance/tls-enforcer.js +108 -0
  37. package/dist/compliance/worm-storage.js +712 -0
  38. package/dist/connection-manager.js +198 -0
  39. package/dist/connection-pool.js +519 -0
  40. package/dist/decorators/audit.js +136 -0
  41. package/dist/decorators/belongs-to-many.js +115 -0
  42. package/dist/decorators/belongs-to.js +115 -0
  43. package/dist/decorators/check.js +435 -0
  44. package/dist/decorators/collate.js +329 -0
  45. package/dist/decorators/comment.js +205 -0
  46. package/dist/decorators/database-settings.js +236 -0
  47. package/dist/decorators/default.js +244 -0
  48. package/dist/decorators/encryption.js +235 -0
  49. package/dist/decorators/engine.js +97 -0
  50. package/dist/decorators/fk-constraints.js +594 -0
  51. package/dist/decorators/foreign-table.js +136 -0
  52. package/dist/decorators/generated.js +274 -0
  53. package/dist/decorators/has-many.js +127 -0
  54. package/dist/decorators/has-one.js +116 -0
  55. package/dist/decorators/hstore.js +129 -0
  56. package/dist/decorators/index.js +355 -0
  57. package/dist/decorators/json-column.js +83 -0
  58. package/dist/decorators/jsonb.js +101 -0
  59. package/dist/decorators/orm-decorators.js +425 -0
  60. package/dist/decorators/permissions.js +294 -0
  61. package/dist/decorators/procedure.js +210 -0
  62. package/dist/decorators/query-options.js +556 -0
  63. package/dist/decorators/range.js +167 -0
  64. package/dist/decorators/set-column.js +83 -0
  65. package/dist/decorators/spatial.js +114 -0
  66. package/dist/decorators/storage.js +580 -0
  67. package/dist/decorators/timezone.js +512 -0
  68. package/dist/decorators/trigger.js +90 -0
  69. package/dist/decorators/uuid.js +135 -0
  70. package/dist/decorators/view.js +258 -0
  71. package/dist/diagrams/chen-diagram.js +354 -0
  72. package/dist/diagrams/class-diagram.js +384 -0
  73. package/dist/diagrams/dependency-diagram.js +432 -0
  74. package/dist/diagrams/er-diagram.js +605 -0
  75. package/dist/diagrams/flow-diagram.js +394 -0
  76. package/dist/diagrams/gantt-diagram.js +411 -0
  77. package/dist/diagrams/index-diagram.js +353 -0
  78. package/dist/diagrams/index.js +184 -0
  79. package/dist/diagrams/migration-diagram.js +316 -0
  80. package/dist/diagrams/model-diagram.js +616 -0
  81. package/dist/diagrams/package-diagram.js +376 -0
  82. package/dist/diagrams/palette.js +85 -0
  83. package/dist/diagrams/relational-diagram.js +455 -0
  84. package/dist/diagrams/schemadoc-diagram.js +309 -0
  85. package/dist/diagrams/sequence-diagram.js +307 -0
  86. package/dist/diagrams/state-diagram.js +344 -0
  87. package/dist/diagrams/svg-dom.js +111 -0
  88. package/dist/diagrams/tree-diagram.js +250 -0
  89. package/dist/dialects/clickhouse/index.js +1742 -0
  90. package/dist/dialects/cockroachdb/index.js +4677 -0
  91. package/dist/dialects/cratedb/index.js +441 -0
  92. package/dist/dialects/databricks/index.js +517 -0
  93. package/dist/dialects/db2/index.js +2225 -0
  94. package/dist/dialects/dialect.js +720 -0
  95. package/dist/dialects/duckdb/index.js +2014 -0
  96. package/dist/dialects/exasol/index.js +357 -0
  97. package/dist/dialects/firebird/index.js +495 -0
  98. package/dist/dialects/greenplum/index.js +457 -0
  99. package/dist/dialects/hana/index.js +1741 -0
  100. package/dist/dialects/mariadb/index.js +3590 -0
  101. package/dist/dialects/mssql/index.js +2296 -0
  102. package/dist/dialects/mysql/index.js +4058 -0
  103. package/dist/dialects/oracle/index.js +2999 -0
  104. package/dist/dialects/postgres/index.js +5319 -0
  105. package/dist/dialects/query-stream-helper.js +152 -0
  106. package/dist/dialects/questdb/index.js +433 -0
  107. package/dist/dialects/redshift/index.js +2277 -0
  108. package/dist/dialects/singlestore/index.js +354 -0
  109. package/dist/dialects/snowflake/index.js +2082 -0
  110. package/dist/dialects/spanner/index.js +1768 -0
  111. package/dist/dialects/sqlite/index.js +3382 -0
  112. package/dist/dialects/tidb/index.js +377 -0
  113. package/dist/dialects/timescaledb/index.js +164 -0
  114. package/dist/dialects/trino/index.js +420 -0
  115. package/dist/dialects/turso/index.js +227 -0
  116. package/dist/dialects/vertica/index.js +317 -0
  117. package/dist/dialects/yugabytedb/index.js +424 -0
  118. package/dist/errors/index.js +472 -0
  119. package/dist/errors/utils.js +340 -0
  120. package/dist/errors.js +21 -0
  121. package/dist/extensions/catalog/cloud-warehouse-features.js +207 -0
  122. package/dist/extensions/catalog/mssql-features.js +147 -0
  123. package/dist/extensions/catalog/mysql-mariadb-plugins.js +229 -0
  124. package/dist/extensions/catalog/oracle-db2-features.js +196 -0
  125. package/dist/extensions/catalog/postgres-extensions.js +516 -0
  126. package/dist/extensions/index.js +71 -0
  127. package/dist/extensions/types.js +13 -0
  128. package/dist/foreign-data.js +173 -0
  129. package/dist/hooks/hooks-manager.js +350 -0
  130. package/dist/hooks/index.js +37 -0
  131. package/dist/index.js +463 -0
  132. package/dist/logging.js +335 -0
  133. package/dist/migrations/index.js +40 -0
  134. package/dist/migrations/migration.js +196 -0
  135. package/dist/migrations/migrator.js +411 -0
  136. package/dist/migrations/prormmigration.js +275 -0
  137. package/dist/migrations/query-interface.js +435 -0
  138. package/dist/migrations/seeder.js +353 -0
  139. package/dist/models/associations.js +852 -0
  140. package/dist/models/constraints.js +288 -0
  141. package/dist/models/data-types.js +2518 -0
  142. package/dist/models/decorators.js +445 -0
  143. package/dist/models/index.js +33 -0
  144. package/dist/models/indexes.js +531 -0
  145. package/dist/models/methods.js +382 -0
  146. package/dist/models/model-manager.js +103 -0
  147. package/dist/models/model.js +5349 -0
  148. package/dist/models/operators.js +67 -0
  149. package/dist/models/scopes.js +189 -0
  150. package/dist/models/typescript-types.js +26 -0
  151. package/dist/nosql/aerospike/index.js +205 -0
  152. package/dist/nosql/allegrograph/index.js +169 -0
  153. package/dist/nosql/arangodb/index.js +364 -0
  154. package/dist/nosql/azure-blob/index.js +206 -0
  155. package/dist/nosql/beanstalkd/index.js +231 -0
  156. package/dist/nosql/beequeue/index.js +210 -0
  157. package/dist/nosql/bigchaindb/index.js +195 -0
  158. package/dist/nosql/bigtable/index.js +224 -0
  159. package/dist/nosql/blazegraph/index.js +173 -0
  160. package/dist/nosql/bullmq/index.js +191 -0
  161. package/dist/nosql/cassandra/index.js +174 -0
  162. package/dist/nosql/chroma/index.js +190 -0
  163. package/dist/nosql/cloudflare-kv/index.js +220 -0
  164. package/dist/nosql/coherence/index.js +200 -0
  165. package/dist/nosql/cosmosdb/index.js +157 -0
  166. package/dist/nosql/couchbase/index.js +213 -0
  167. package/dist/nosql/dax/index.js +212 -0
  168. package/dist/nosql/deno-kv/index.js +206 -0
  169. package/dist/nosql/dgraph/index.js +171 -0
  170. package/dist/nosql/doris/index.js +169 -0
  171. package/dist/nosql/druid/index.js +162 -0
  172. package/dist/nosql/dynamodb/index.js +937 -0
  173. package/dist/nosql/elasticsearch/index.js +377 -0
  174. package/dist/nosql/etcd/index.js +502 -0
  175. package/dist/nosql/eventhubs/index.js +213 -0
  176. package/dist/nosql/eventstore/index.js +254 -0
  177. package/dist/nosql/faunadb/index.js +188 -0
  178. package/dist/nosql/firestore/index.js +177 -0
  179. package/dist/nosql/fluree/index.js +148 -0
  180. package/dist/nosql/fuseki/index.js +170 -0
  181. package/dist/nosql/gcs/index.js +172 -0
  182. package/dist/nosql/gearman/index.js +160 -0
  183. package/dist/nosql/geode/index.js +196 -0
  184. package/dist/nosql/graphdb/index.js +169 -0
  185. package/dist/nosql/graylog/index.js +188 -0
  186. package/dist/nosql/gridgain/index.js +171 -0
  187. package/dist/nosql/hazelcast/index.js +162 -0
  188. package/dist/nosql/hbase/index.js +230 -0
  189. package/dist/nosql/ignite/index.js +173 -0
  190. package/dist/nosql/immudb/index.js +184 -0
  191. package/dist/nosql/index.js +232 -0
  192. package/dist/nosql/infinispan/index.js +200 -0
  193. package/dist/nosql/influxdb/index.js +0 -0
  194. package/dist/nosql/kafka/index.js +234 -0
  195. package/dist/nosql/keyspaces/index.js +189 -0
  196. package/dist/nosql/kinesis/index.js +253 -0
  197. package/dist/nosql/leveldb/index.js +153 -0
  198. package/dist/nosql/lmdb/index.js +160 -0
  199. package/dist/nosql/loki/index.js +201 -0
  200. package/dist/nosql/marklogic/index.js +204 -0
  201. package/dist/nosql/materialize/index.js +145 -0
  202. package/dist/nosql/meilisearch/index.js +154 -0
  203. package/dist/nosql/memcached/index.js +223 -0
  204. package/dist/nosql/milvus/index.js +410 -0
  205. package/dist/nosql/minio/index.js +265 -0
  206. package/dist/nosql/momento/index.js +179 -0
  207. package/dist/nosql/mongodb/index.js +461 -0
  208. package/dist/nosql/nats/index.js +247 -0
  209. package/dist/nosql/nedb/index.js +164 -0
  210. package/dist/nosql/neo4j/index.js +450 -0
  211. package/dist/nosql/neptune/index.js +470 -0
  212. package/dist/nosql/nsq/index.js +200 -0
  213. package/dist/nosql/opensearch/index.js +186 -0
  214. package/dist/nosql/orientdb/index.js +175 -0
  215. package/dist/nosql/papertrail/index.js +200 -0
  216. package/dist/nosql/pinecone/index.js +0 -0
  217. package/dist/nosql/pinot/index.js +133 -0
  218. package/dist/nosql/pouchdb/index.js +172 -0
  219. package/dist/nosql/prometheus/index.js +174 -0
  220. package/dist/nosql/provendb/index.js +147 -0
  221. package/dist/nosql/pubsub/index.js +187 -0
  222. package/dist/nosql/pulsar/index.js +232 -0
  223. package/dist/nosql/qdrant/index.js +295 -0
  224. package/dist/nosql/qldb/index.js +192 -0
  225. package/dist/nosql/r2/index.js +281 -0
  226. package/dist/nosql/rabbitmq/index.js +237 -0
  227. package/dist/nosql/ravendb/index.js +175 -0
  228. package/dist/nosql/redis/index.js +607 -0
  229. package/dist/nosql/redpanda/index.js +237 -0
  230. package/dist/nosql/resque/index.js +203 -0
  231. package/dist/nosql/rethinkdb/index.js +232 -0
  232. package/dist/nosql/rocksdb/index.js +152 -0
  233. package/dist/nosql/rockset/index.js +126 -0
  234. package/dist/nosql/s3/index.js +298 -0
  235. package/dist/nosql/scylladb/index.js +178 -0
  236. package/dist/nosql/signoz/index.js +227 -0
  237. package/dist/nosql/sns/index.js +201 -0
  238. package/dist/nosql/solr/index.js +231 -0
  239. package/dist/nosql/splunk/index.js +227 -0
  240. package/dist/nosql/sqs/index.js +246 -0
  241. package/dist/nosql/stardog/index.js +169 -0
  242. package/dist/nosql/starrocks/index.js +170 -0
  243. package/dist/nosql/store.js +2 -0
  244. package/dist/nosql/sumologic/index.js +213 -0
  245. package/dist/nosql/surrealdb/index.js +179 -0
  246. package/dist/nosql/terminusdb/index.js +151 -0
  247. package/dist/nosql/tigergraph/index.js +469 -0
  248. package/dist/nosql/typesense/index.js +148 -0
  249. package/dist/nosql/unqlite/index.js +157 -0
  250. package/dist/nosql/upstash/index.js +167 -0
  251. package/dist/nosql/vercel-kv/index.js +166 -0
  252. package/dist/nosql/victoriametrics/index.js +213 -0
  253. package/dist/nosql/virtuoso/index.js +169 -0
  254. package/dist/nosql/weaviate/index.js +276 -0
  255. package/dist/operators/index.js +108 -0
  256. package/dist/operators.js +2690 -0
  257. package/dist/prisma-migrate/index.js +38 -0
  258. package/dist/prisma-migrate/migration-generator.js +125 -0
  259. package/dist/prisma-migrate/model-generator.js +172 -0
  260. package/dist/prisma-migrate/relations.js +100 -0
  261. package/dist/prisma-migrate/schema-parser.js +167 -0
  262. package/dist/prisma-migrate/type-mapper.js +40 -0
  263. package/dist/prorm.js +6832 -0
  264. package/dist/query-builders/cte-builder.js +80 -0
  265. package/dist/query-builders/functions/aggregate.js +390 -0
  266. package/dist/query-builders/functions/conditional.js +503 -0
  267. package/dist/query-builders/functions/datetime.js +695 -0
  268. package/dist/query-builders/functions/fulltext.js +439 -0
  269. package/dist/query-builders/functions/index.js +93 -0
  270. package/dist/query-builders/functions/json.js +427 -0
  271. package/dist/query-builders/functions/math.js +399 -0
  272. package/dist/query-builders/functions/string.js +518 -0
  273. package/dist/query-builders/functions/window.js +328 -0
  274. package/dist/query-builders/include-builder.js +323 -0
  275. package/dist/query-builders/index-expression-builder.js +242 -0
  276. package/dist/query-builders/index.js +161 -0
  277. package/dist/query-builders/insert-builder.js +164 -0
  278. package/dist/query-builders/model-helpers.js +38 -0
  279. package/dist/query-builders/order-limit-builder.js +239 -0
  280. package/dist/query-builders/sql-compiler.js +2040 -0
  281. package/dist/query-builders/subquery-builder.js +152 -0
  282. package/dist/query-builders/update-builder.js +182 -0
  283. package/dist/query-builders/view-builder.js +218 -0
  284. package/dist/query-builders/where-builder.js +1532 -0
  285. package/dist/query-interface.js +622 -0
  286. package/dist/query-optimizers/batch-optimizer.js +426 -0
  287. package/dist/query-optimizers/explain-plans.js +415 -0
  288. package/dist/query-optimizers/index.js +51 -0
  289. package/dist/query-optimizers/prepared-statement-cache.js +423 -0
  290. package/dist/query-optimizers/query-hints.js +438 -0
  291. package/dist/query-optimizers/query-optimizer.js +278 -0
  292. package/dist/query-optimizers/slow-query-logger.js +271 -0
  293. package/dist/replica-manager.js +507 -0
  294. package/dist/schema/index.js +15 -0
  295. package/dist/schema/migration-generator.js +374 -0
  296. package/dist/schema/schema-differ.js +549 -0
  297. package/dist/schema/types.js +6 -0
  298. package/dist/sql-constants.js +300 -0
  299. package/dist/sqlite-advanced.js +1047 -0
  300. package/dist/streams/index.js +12 -0
  301. package/dist/streams/transforms.js +178 -0
  302. package/dist/transaction.js +456 -0
  303. package/dist/types/index.js +180 -0
  304. package/dist/user-management.js +127 -0
  305. package/dist/utils/date.js +300 -0
  306. package/dist/utils/index.js +1079 -0
  307. package/dist/utils/string.js +161 -0
  308. package/dist/validators/index.js +19 -0
  309. package/dist/validators/validator.js +911 -0
  310. 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;