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,278 @@
1
+ "use strict";
2
+ /**
3
+ * Query Optimizer - Main entry point that combines all optimization features
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.QueryOptimizer = void 0;
7
+ exports.createQueryOptimizer = createQueryOptimizer;
8
+ const query_hints_1 = require("./query-hints");
9
+ const explain_plans_1 = require("./explain-plans");
10
+ const slow_query_logger_1 = require("./slow-query-logger");
11
+ const batch_optimizer_1 = require("./batch-optimizer");
12
+ const prepared_statement_cache_1 = require("./prepared-statement-cache");
13
+ /**
14
+ * Main query optimizer class that combines all optimization features
15
+ */
16
+ class QueryOptimizer {
17
+ constructor(dialect, options) {
18
+ this.dialect = dialect;
19
+ this.options = {
20
+ enableHints: options?.enableHints ?? true,
21
+ enableExplain: options?.enableExplain ?? process.env.NODE_ENV === 'development',
22
+ enableSlowQueryLog: options?.enableSlowQueryLog ?? true,
23
+ enablePreparedStatementCache: options?.enablePreparedStatementCache ?? true,
24
+ enableQueryResultCache: options?.enableQueryResultCache ?? true,
25
+ enableBatchOptimization: options?.enableBatchOptimization ?? true,
26
+ slowQueryOptions: {
27
+ threshold: 1000,
28
+ ...options?.slowQueryOptions,
29
+ },
30
+ preparedStatementCacheOptions: {
31
+ maxSize: 500,
32
+ ...options?.preparedStatementCacheOptions,
33
+ },
34
+ queryResultCacheOptions: {
35
+ maxSize: 100,
36
+ ttl: 60000,
37
+ ...options?.queryResultCacheOptions,
38
+ },
39
+ batchOptions: {
40
+ chunkSize: 1000,
41
+ useTransaction: true,
42
+ ...options?.batchOptions,
43
+ },
44
+ explainOptions: {
45
+ ...options?.explainOptions,
46
+ },
47
+ logging: options?.logging,
48
+ };
49
+ this.initializeComponents();
50
+ }
51
+ /**
52
+ * Initialize all optimization components
53
+ */
54
+ initializeComponents() {
55
+ if (this.options.enableHints) {
56
+ this.queryHintManager = new query_hints_1.QueryHintManager(this.dialect);
57
+ }
58
+ if (this.options.enableExplain) {
59
+ this.explainPlanGenerator = new explain_plans_1.ExplainPlanGenerator(this.dialect, this.options.explainOptions);
60
+ }
61
+ if (this.options.enableSlowQueryLog) {
62
+ this.slowQueryLogger = new slow_query_logger_1.SlowQueryLogger(this.options.slowQueryOptions);
63
+ }
64
+ if (this.options.enablePreparedStatementCache) {
65
+ this.preparedStatementCache = new prepared_statement_cache_1.PreparedStatementCache(this.dialect, this.options.preparedStatementCacheOptions);
66
+ }
67
+ if (this.options.enableQueryResultCache) {
68
+ this.queryResultCache = new prepared_statement_cache_1.QueryResultCache(this.options.queryResultCacheOptions);
69
+ }
70
+ if (this.options.enableBatchOptimization) {
71
+ this.batchOptimizer = new batch_optimizer_1.BatchQueryOptimizer(this.dialect, this.options.batchOptions);
72
+ }
73
+ }
74
+ /**
75
+ * Get the query hint manager
76
+ */
77
+ getHintManager() {
78
+ return this.queryHintManager;
79
+ }
80
+ /**
81
+ * Get the explain plan generator
82
+ */
83
+ getExplainGenerator() {
84
+ return this.explainPlanGenerator;
85
+ }
86
+ /**
87
+ * Get the slow query logger
88
+ */
89
+ getSlowQueryLogger() {
90
+ return this.slowQueryLogger;
91
+ }
92
+ /**
93
+ * Get the prepared statement cache
94
+ */
95
+ getPreparedStatementCache() {
96
+ return this.preparedStatementCache;
97
+ }
98
+ /**
99
+ * Get the query result cache
100
+ */
101
+ getQueryResultCache() {
102
+ return this.queryResultCache;
103
+ }
104
+ /**
105
+ * Get the batch optimizer
106
+ */
107
+ getBatchOptimizer() {
108
+ return this.batchOptimizer;
109
+ }
110
+ /**
111
+ * Apply query hints to a SQL statement
112
+ */
113
+ applyHints(sql, hints) {
114
+ if (!this.queryHintManager) {
115
+ return sql;
116
+ }
117
+ return this.queryHintManager.applyHints(sql, hints);
118
+ }
119
+ /**
120
+ * Execute an optimized query with caching support
121
+ */
122
+ async executeQuery(sql, options) {
123
+ const startTime = Date.now();
124
+ // Apply hints if provided
125
+ let finalSql = sql;
126
+ if (options?.hint && this.queryHintManager) {
127
+ finalSql = this.queryHintManager.applyHints(sql, options.hint);
128
+ }
129
+ // Check query result cache
130
+ if (options?.useCache && this.queryResultCache && !options.params) {
131
+ const cached = this.queryResultCache.get(finalSql);
132
+ if (cached !== undefined) {
133
+ return { result: cached, fromCache: true, duration: Date.now() - startTime };
134
+ }
135
+ }
136
+ // Check prepared statement cache
137
+ let cacheKey;
138
+ if (options?.usePreparedStatement && this.preparedStatementCache) {
139
+ const cached = this.preparedStatementCache.get(finalSql, options.params);
140
+ if (cached) {
141
+ // Use cached prepared statement
142
+ const execStart = Date.now();
143
+ const result = await this.dialect.query(finalSql, { raw: true });
144
+ this.preparedStatementCache.recordExecution(cached.key, Date.now() - execStart);
145
+ // Log slow query
146
+ if (!options?.skipSlowLog && this.slowQueryLogger) {
147
+ this.slowQueryLogger.logQuery({
148
+ sql: finalSql,
149
+ params: options.params,
150
+ duration: Date.now() - startTime,
151
+ dialect: this.dialect.name,
152
+ });
153
+ }
154
+ return { result, fromCache: false, duration: Date.now() - startTime };
155
+ }
156
+ }
157
+ // Execute query
158
+ const result = await this.dialect.query(finalSql, { raw: true });
159
+ const duration = Date.now() - startTime;
160
+ // Cache result if enabled
161
+ if (options?.useCache && this.queryResultCache) {
162
+ this.queryResultCache.set(finalSql, options.params ?? [], result);
163
+ }
164
+ // Track statement usage if enabled. Note: `PreparedStatementCache` does not
165
+ // hold a real driver-level prepared-statement handle (see its class doc) -
166
+ // `compiled` here is just a lightweight, genuinely reusable descriptor of
167
+ // the statement shape (SQL + bound parameter count).
168
+ if (options?.usePreparedStatement && this.preparedStatementCache) {
169
+ this.preparedStatementCache.set(finalSql, { sql: finalSql, paramCount: options.params?.length ?? 0 }, options.params);
170
+ }
171
+ // Log slow query
172
+ if (!options?.skipSlowLog && this.slowQueryLogger) {
173
+ this.slowQueryLogger.logQuery({
174
+ sql: finalSql,
175
+ params: options?.params,
176
+ duration,
177
+ dialect: this.dialect.name,
178
+ });
179
+ }
180
+ return { result, fromCache: false, duration };
181
+ }
182
+ /**
183
+ * Explain a query
184
+ */
185
+ async explainQuery(sql, options) {
186
+ if (!this.explainPlanGenerator) {
187
+ throw new Error('Explain plans are not enabled');
188
+ }
189
+ return this.explainPlanGenerator.explain(sql, options);
190
+ }
191
+ /**
192
+ * Analyze a query for optimization opportunities
193
+ */
194
+ async analyzeQuery(sql, options) {
195
+ if (!this.explainPlanGenerator) {
196
+ throw new Error('Explain plans are not enabled');
197
+ }
198
+ return this.explainPlanGenerator.analyzeQuery(sql, options);
199
+ }
200
+ /**
201
+ * Perform batch insert with optimization
202
+ */
203
+ async batchInsert(tableName, records, options) {
204
+ if (!this.batchOptimizer) {
205
+ throw new Error('Batch optimization is not enabled');
206
+ }
207
+ return this.batchOptimizer.optimizeBatchInsert(tableName, records, options);
208
+ }
209
+ /**
210
+ * Perform batch update with optimization
211
+ */
212
+ async batchUpdate(tableName, records, identifierColumn, options) {
213
+ if (!this.batchOptimizer) {
214
+ throw new Error('Batch optimization is not enabled');
215
+ }
216
+ return this.batchOptimizer.optimizeBatchUpdate(tableName, records, identifierColumn, options);
217
+ }
218
+ /**
219
+ * Perform batch delete with optimization
220
+ */
221
+ async batchDelete(tableName, identifiers, identifierColumn, options) {
222
+ if (!this.batchOptimizer) {
223
+ throw new Error('Batch optimization is not enabled');
224
+ }
225
+ return this.batchOptimizer.optimizeBatchDelete(tableName, identifiers, identifierColumn, options);
226
+ }
227
+ /**
228
+ * Get optimization statistics
229
+ */
230
+ getStats() {
231
+ return {
232
+ slowQuery: this.slowQueryLogger?.getStatistics(),
233
+ preparedStatementCache: this.preparedStatementCache?.getStats(),
234
+ queryResultCache: this.queryResultCache?.getStats(),
235
+ };
236
+ }
237
+ /**
238
+ * Clear all caches
239
+ */
240
+ clearCaches() {
241
+ this.preparedStatementCache?.clear();
242
+ this.queryResultCache?.clear();
243
+ this.slowQueryLogger?.clear();
244
+ }
245
+ /**
246
+ * Prune expired cache entries
247
+ */
248
+ pruneCaches() {
249
+ this.preparedStatementCache?.prune();
250
+ }
251
+ /**
252
+ * Invalidate query result cache for a specific table
253
+ */
254
+ invalidateTableCache(tableName) {
255
+ const resultCacheInvalidated = this.queryResultCache?.invalidateTable(tableName) ?? 0;
256
+ const preparedStatementCacheInvalidated = this.preparedStatementCache?.invalidateTable(tableName) ?? 0;
257
+ return resultCacheInvalidated + preparedStatementCacheInvalidated;
258
+ }
259
+ /**
260
+ * Log a message
261
+ */
262
+ log(message, level = 'info') {
263
+ if (this.options.logging) {
264
+ this.options.logging(message, level);
265
+ }
266
+ }
267
+ }
268
+ exports.QueryOptimizer = QueryOptimizer;
269
+ /**
270
+ * Create a query optimizer instance
271
+ */
272
+ function createQueryOptimizer(dialect, options) {
273
+ return new QueryOptimizer(dialect, options);
274
+ }
275
+ exports.default = {
276
+ QueryOptimizer,
277
+ createQueryOptimizer,
278
+ };
@@ -0,0 +1,271 @@
1
+ "use strict";
2
+ /**
3
+ * Slow Query Logging
4
+ * Provides functionality to log and analyze slow database queries
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SlowQueryLogger = void 0;
8
+ exports.createSlowQueryLogger = createSlowQueryLogger;
9
+ const events_1 = require("events");
10
+ /**
11
+ * Slow query logger
12
+ */
13
+ class SlowQueryLogger extends events_1.EventEmitter {
14
+ constructor(options) {
15
+ super();
16
+ this.logAllQueries = false;
17
+ this.logParams = false;
18
+ this.maxEntries = 1000;
19
+ this.includeStackTrace = false;
20
+ this.logs = [];
21
+ this.alertThreshold = 10;
22
+ this.alertWindow = 60000; // 1 minute
23
+ this.queryTimestamps = [];
24
+ this.threshold = options.threshold || SlowQueryLogger.DEFAULT_THRESHOLD;
25
+ this.logAllQueries = options.logAllQueries || false;
26
+ this.logParams = options.logParams || false;
27
+ this.maxEntries = options.maxEntries || 1000;
28
+ this.onSlowQuery = options.onSlowQuery;
29
+ this.onAlert = options.onAlert;
30
+ this.includeStackTrace = options.includeStackTrace || false;
31
+ this.logger = options.logger;
32
+ if (options.alertThreshold !== undefined) {
33
+ this.alertThreshold = options.alertThreshold;
34
+ }
35
+ if (options.alertWindow !== undefined) {
36
+ this.alertWindow = options.alertWindow;
37
+ }
38
+ }
39
+ /**
40
+ * Set the slow query threshold
41
+ */
42
+ setThreshold(threshold) {
43
+ this.threshold = threshold;
44
+ }
45
+ /**
46
+ * Get the current threshold
47
+ */
48
+ getThreshold() {
49
+ return this.threshold;
50
+ }
51
+ /**
52
+ * Enable logging of all queries (not just slow ones)
53
+ */
54
+ setLogAllQueries(logAll) {
55
+ this.logAllQueries = logAll;
56
+ }
57
+ /**
58
+ * Log a query execution
59
+ */
60
+ logQuery(options) {
61
+ const entry = {
62
+ id: this.generateId(),
63
+ sql: options.sql,
64
+ params: this.logParams ? options.params : undefined,
65
+ duration: options.duration,
66
+ timestamp: new Date(),
67
+ dialect: options.dialect,
68
+ inTransaction: options.inTransaction || false,
69
+ connection: options.connection,
70
+ error: options.error,
71
+ queryType: options.queryType,
72
+ rowCount: options.rowCount,
73
+ };
74
+ if (this.includeStackTrace) {
75
+ entry.stackTrace = new Error().stack;
76
+ }
77
+ // Determine if this should be logged
78
+ const shouldLog = this.logAllQueries || options.duration >= this.threshold;
79
+ if (shouldLog) {
80
+ this.addLogEntry(entry);
81
+ // Log the query
82
+ this.logEntry(entry);
83
+ // Emit events
84
+ this.emit('query', entry);
85
+ if (options.duration >= this.threshold) {
86
+ this.emit('slowQuery', entry);
87
+ if (this.onSlowQuery) {
88
+ this.onSlowQuery(entry);
89
+ }
90
+ // Check alert threshold
91
+ this.checkAlertThreshold();
92
+ }
93
+ }
94
+ return shouldLog ? entry : null;
95
+ }
96
+ /**
97
+ * Add a log entry to the internal log storage
98
+ */
99
+ addLogEntry(entry) {
100
+ this.logs.push(entry);
101
+ // Maintain max entries limit
102
+ if (this.logs.length > this.maxEntries) {
103
+ this.logs.shift();
104
+ }
105
+ // Track query timestamps for alerting
106
+ if (entry.duration >= this.threshold) {
107
+ this.queryTimestamps.push(Date.now());
108
+ }
109
+ }
110
+ /**
111
+ * Log the entry using the configured logger
112
+ */
113
+ logEntry(entry) {
114
+ const isSlow = entry.duration >= this.threshold;
115
+ const level = isSlow ? 'warn' : 'debug';
116
+ const meta = {
117
+ duration: `${entry.duration}ms`,
118
+ dialect: entry.dialect,
119
+ queryType: entry.queryType,
120
+ rowCount: entry.rowCount,
121
+ inTransaction: entry.inTransaction,
122
+ };
123
+ const message = isSlow
124
+ ? `[SLOW] Query exceeded threshold (${this.threshold}ms): ${entry.sql}`
125
+ : entry.sql;
126
+ if (this.logger) {
127
+ this.logger(message, meta);
128
+ }
129
+ else {
130
+ // Default console logging
131
+ if (isSlow) {
132
+ console.warn(`[SLOW QUERY] ${message}`, meta);
133
+ }
134
+ else {
135
+ console.log(`[QUERY] ${message}`, meta);
136
+ }
137
+ }
138
+ }
139
+ /**
140
+ * Check if alert threshold has been exceeded
141
+ */
142
+ checkAlertThreshold() {
143
+ const now = Date.now();
144
+ const windowStart = now - this.alertWindow;
145
+ // Remove timestamps outside the window
146
+ this.queryTimestamps = this.queryTimestamps.filter((ts) => ts >= windowStart);
147
+ if (this.queryTimestamps.length >= this.alertThreshold) {
148
+ // Get all slow queries in the window
149
+ const alertEntries = this.logs.filter((entry) => entry.timestamp.getTime() >= windowStart && entry.duration >= this.threshold);
150
+ this.emit('alert', alertEntries);
151
+ if (this.onAlert) {
152
+ this.onAlert(alertEntries);
153
+ }
154
+ }
155
+ }
156
+ /**
157
+ * Get all log entries
158
+ */
159
+ getLogs() {
160
+ return [...this.logs];
161
+ }
162
+ /**
163
+ * Get slow query entries only
164
+ */
165
+ getSlowQueries() {
166
+ return this.logs.filter((entry) => entry.duration >= this.threshold);
167
+ }
168
+ /**
169
+ * Get query statistics
170
+ */
171
+ getStatistics() {
172
+ const slowQueries = this.getSlowQueries();
173
+ const totalQueries = this.logs.length;
174
+ if (totalQueries === 0) {
175
+ return {
176
+ totalQueries: 0,
177
+ slowQueries: 0,
178
+ averageDuration: 0,
179
+ maxDuration: 0,
180
+ minDuration: 0,
181
+ p50Duration: 0,
182
+ p95Duration: 0,
183
+ p99Duration: 0,
184
+ };
185
+ }
186
+ const durations = this.logs.map((e) => e.duration).sort((a, b) => a - b);
187
+ return {
188
+ totalQueries,
189
+ slowQueries: slowQueries.length,
190
+ averageDuration: durations.reduce((a, b) => a + b, 0) / totalQueries,
191
+ maxDuration: durations[durations.length - 1],
192
+ minDuration: durations[0],
193
+ p50Duration: this.percentile(durations, 50),
194
+ p95Duration: this.percentile(durations, 95),
195
+ p99Duration: this.percentile(durations, 99),
196
+ };
197
+ }
198
+ /**
199
+ * Calculate percentile from sorted array
200
+ */
201
+ percentile(sortedArray, p) {
202
+ if (sortedArray.length === 0)
203
+ return 0;
204
+ const index = Math.ceil((p / 100) * sortedArray.length) - 1;
205
+ return sortedArray[Math.max(0, index)];
206
+ }
207
+ /**
208
+ * Clear all log entries
209
+ */
210
+ clear() {
211
+ this.logs = [];
212
+ this.queryTimestamps = [];
213
+ }
214
+ /**
215
+ * Generate a unique ID for log entries
216
+ */
217
+ generateId() {
218
+ return `sq_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
219
+ }
220
+ /**
221
+ * Export logs to a file-compatible format
222
+ */
223
+ exportLogs() {
224
+ return JSON.stringify(this.logs, null, 2);
225
+ }
226
+ /**
227
+ * Get queries by type
228
+ */
229
+ getQueriesByType(type) {
230
+ return this.logs.filter((entry) => entry.queryType?.toUpperCase() === type.toUpperCase());
231
+ }
232
+ /**
233
+ * Get queries on a specific table
234
+ */
235
+ getQueriesOnTable(tableName) {
236
+ const regex = new RegExp(`\\b${tableName}\\b`, 'i');
237
+ return this.logs.filter((entry) => regex.test(entry.sql));
238
+ }
239
+ /**
240
+ * Find similar queries (group by SQL pattern)
241
+ */
242
+ findSimilarQueries(sql) {
243
+ // Normalize SQL by replacing literal values with placeholders
244
+ const normalizedSql = this.normalizeSql(sql);
245
+ const normalized = this.normalizeSql(normalizedSql);
246
+ return this.logs.filter((entry) => this.normalizeSql(entry.sql) === normalized);
247
+ }
248
+ /**
249
+ * Normalize SQL for comparison
250
+ */
251
+ normalizeSql(sql) {
252
+ return sql
253
+ .replace(/'[^']*'/g, '?')
254
+ .replace(/"[^"]*"/g, '?')
255
+ .replace(/\d+/g, '?')
256
+ .replace(/\s+/g, ' ')
257
+ .trim();
258
+ }
259
+ }
260
+ exports.SlowQueryLogger = SlowQueryLogger;
261
+ SlowQueryLogger.DEFAULT_THRESHOLD = 1000; // 1 second
262
+ /**
263
+ * Create a slow query logger instance
264
+ */
265
+ function createSlowQueryLogger(options) {
266
+ return new SlowQueryLogger(options);
267
+ }
268
+ exports.default = {
269
+ SlowQueryLogger,
270
+ createSlowQueryLogger,
271
+ };