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,423 @@
1
+ "use strict";
2
+ /**
3
+ * Prepared Statement Caching
4
+ * Provides functionality to cache and reuse prepared statements for better performance
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.QueryResultCache = exports.PreparedStatementCache = void 0;
8
+ exports.createPreparedStatementCache = createPreparedStatementCache;
9
+ /**
10
+ * Tracks SQL statement usage (hit/miss counts, execution timings, last-used
11
+ * time) keyed by normalized SQL + params, with TTL-based expiry.
12
+ *
13
+ * IMPORTANT — naming caveat: despite the name, this does **not** cache a real
14
+ * driver-level prepared-statement handle. None of the `Dialect` implementations
15
+ * in `src/dialects/**` expose a separate prepare/execute split - `query(sql,
16
+ * options)` always receives the full SQL text and applies `options.replacements`
17
+ * / `options.bind` per call (see e.g. `sqlite/index.ts` `query()`, which calls
18
+ * `connection.prepare(sql)` fresh on every invocation). So there is no reusable
19
+ * driver object for this class to hold onto; the `compiled` field on each entry
20
+ * is whatever metadata the caller passes to `set()` (by default just `{}`, or -
21
+ * see `QueryOptimizer.executeQuery()` - a lightweight `{ sql, paramCount }`
22
+ * descriptor). In practice this class behaves as a query-usage/hit-count
23
+ * tracker with an optional metadata slot, not a real statement cache. It is
24
+ * kept under this name for backwards compatibility with existing callers/tests;
25
+ * treat `getStats()` / `hitCount` / `topStatements` as the reliable surface,
26
+ * and don't rely on `compiled` holding an executable handle.
27
+ *
28
+ * Invalidation: entries expire via TTL (`options.ttl`, default 1 hour). Since
29
+ * that alone can serve stale-shaped results after schema changes made via raw
30
+ * DDL, `invalidateTable()` is provided to drop entries referencing a given
31
+ * table name on write (e.g. from a caller's insert/update/delete path); it is
32
+ * not auto-wired to every write in this codebase, but `QueryOptimizer.
33
+ * invalidateTableCache()` calls it alongside the query-result cache.
34
+ */
35
+ class PreparedStatementCache {
36
+ constructor(dialect, options) {
37
+ this.stats = {
38
+ hits: 0,
39
+ misses: 0,
40
+ evictions: 0,
41
+ totalExecutionTime: 0,
42
+ };
43
+ this.dialect = dialect;
44
+ this.cache = new Map();
45
+ this.maxSize = options.maxSize || 500;
46
+ this.ttl = options.ttl || 3600000; // 1 hour default
47
+ this.normalizeSql = options.normalizeSql !== false;
48
+ this.onCache = options.onCache;
49
+ this.onEvict = options.onEvict;
50
+ this.logging = options.logging || false;
51
+ }
52
+ /**
53
+ * Get a cached prepared statement
54
+ */
55
+ get(sql, params) {
56
+ const key = this.generateKey(sql, params);
57
+ const entry = this.cache.get(key);
58
+ if (entry) {
59
+ // Check if entry has expired
60
+ if (Date.now() - entry.createdAt > this.ttl) {
61
+ this.evict(key, entry);
62
+ this.stats.misses++;
63
+ return undefined;
64
+ }
65
+ // Update statistics
66
+ entry.hitCount++;
67
+ entry.lastUsedAt = Date.now();
68
+ this.stats.hits++;
69
+ this.log(`Cache hit for: ${key} (hits: ${entry.hitCount})`);
70
+ return entry;
71
+ }
72
+ this.stats.misses++;
73
+ this.log(`Cache miss for: ${key}`);
74
+ return undefined;
75
+ }
76
+ /**
77
+ * Store a prepared statement in the cache
78
+ */
79
+ set(sql, compiled, params) {
80
+ const key = this.generateKey(sql, params);
81
+ // Check if we need to evict entries
82
+ if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
83
+ this.evictOldest();
84
+ }
85
+ const entry = {
86
+ key,
87
+ sql,
88
+ compiled,
89
+ createdAt: Date.now(),
90
+ hitCount: 0,
91
+ lastUsedAt: Date.now(),
92
+ executions: 0,
93
+ totalExecutionTime: 0,
94
+ };
95
+ this.cache.set(key, entry);
96
+ if (this.onCache) {
97
+ this.onCache(key, entry);
98
+ }
99
+ this.log(`Cached statement: ${key}`);
100
+ return entry;
101
+ }
102
+ /**
103
+ * Record execution of a prepared statement
104
+ */
105
+ recordExecution(key, executionTime) {
106
+ const entry = this.cache.get(key);
107
+ if (entry) {
108
+ entry.executions++;
109
+ entry.totalExecutionTime += executionTime;
110
+ this.stats.totalExecutionTime += executionTime;
111
+ }
112
+ }
113
+ /**
114
+ * Check if a statement is cached
115
+ */
116
+ has(sql, params) {
117
+ const key = this.generateKey(sql, params);
118
+ const entry = this.cache.get(key);
119
+ if (!entry)
120
+ return false;
121
+ // Check if entry has expired
122
+ if (Date.now() - entry.createdAt > this.ttl) {
123
+ this.evict(key, entry);
124
+ return false;
125
+ }
126
+ return true;
127
+ }
128
+ /**
129
+ * Clear all cached statements
130
+ */
131
+ clear() {
132
+ this.cache.clear();
133
+ this.stats = {
134
+ hits: 0,
135
+ misses: 0,
136
+ evictions: 0,
137
+ totalExecutionTime: 0,
138
+ };
139
+ this.log('Cache cleared');
140
+ }
141
+ /**
142
+ * Get cache statistics
143
+ */
144
+ getStats() {
145
+ const total = this.stats.hits + this.stats.misses;
146
+ const hitRate = total > 0 ? (this.stats.hits / total) * 100 : 0;
147
+ // Get most used statements
148
+ const topStatements = Array.from(this.cache.values())
149
+ .sort((a, b) => b.hitCount - a.hitCount)
150
+ .slice(0, 10)
151
+ .map((s) => ({
152
+ sql: s.sql,
153
+ hits: s.hitCount,
154
+ executions: s.executions,
155
+ avgExecutionTime: s.executions > 0 ? s.totalExecutionTime / s.executions : 0,
156
+ }));
157
+ return {
158
+ size: this.cache.size,
159
+ maxSize: this.maxSize,
160
+ hits: this.stats.hits,
161
+ misses: this.stats.misses,
162
+ hitRate: Math.round(hitRate * 100) / 100,
163
+ totalExecutions: this.stats.totalExecutionTime,
164
+ evictions: this.stats.evictions,
165
+ topStatements,
166
+ };
167
+ }
168
+ /**
169
+ * Get all cached statements
170
+ */
171
+ getAll() {
172
+ return Array.from(this.cache.values());
173
+ }
174
+ /**
175
+ * Generate a cache key from SQL and optional parameters
176
+ */
177
+ generateKey(sql, params) {
178
+ let normalizedSql = sql;
179
+ if (this.normalizeSql) {
180
+ // Normalize SQL by replacing values with placeholders
181
+ normalizedSql = this.normalizeSQL(sql);
182
+ }
183
+ if (params && params.length > 0) {
184
+ // Include params in key if not normalizing SQL
185
+ return `${normalizedSql}::${JSON.stringify(params)}`;
186
+ }
187
+ return normalizedSql;
188
+ }
189
+ /**
190
+ * Normalize SQL for consistent caching
191
+ */
192
+ normalizeSQL(sql) {
193
+ return (sql
194
+ // Remove extra whitespace
195
+ .replace(/\s+/g, ' ')
196
+ // Remove comments
197
+ .replace(/--.*$/gm, '')
198
+ .replace(/\/\*[\s\S]*?\*\//g, '')
199
+ // Uppercase keywords
200
+ .replace(/\b(SELECT|FROM|WHERE|JOIN|LEFT|RIGHT|INNER|OUTER|ON|AND|OR|ORDER|BY|GROUP|HAVING|LIMIT|OFFSET|INSERT|INTO|VALUES|UPDATE|SET|DELETE)\b/gi, (match) => match.toUpperCase())
201
+ .trim());
202
+ }
203
+ /**
204
+ * Evict the oldest entry from cache
205
+ */
206
+ evictOldest() {
207
+ let oldestKey = null;
208
+ let oldestTime = Date.now();
209
+ for (const [key, entry] of this.cache.entries()) {
210
+ if (entry.lastUsedAt < oldestTime) {
211
+ oldestTime = entry.lastUsedAt;
212
+ oldestKey = key;
213
+ }
214
+ }
215
+ if (oldestKey) {
216
+ const entry = this.cache.get(oldestKey);
217
+ if (entry) {
218
+ this.evict(oldestKey, entry);
219
+ }
220
+ }
221
+ }
222
+ /**
223
+ * Evict a specific entry from cache
224
+ */
225
+ evict(key, entry) {
226
+ this.cache.delete(key);
227
+ this.stats.evictions++;
228
+ if (this.onEvict) {
229
+ this.onEvict(key, entry);
230
+ }
231
+ this.log(`Evicted: ${key}`);
232
+ }
233
+ /**
234
+ * Log a message if logging is enabled
235
+ */
236
+ log(message) {
237
+ if (this.logging) {
238
+ console.log(`[PreparedStatementCache] ${message}`);
239
+ }
240
+ }
241
+ /**
242
+ * Invalidate (remove) cache entries whose SQL references the given table.
243
+ * Intended to be called by write paths (INSERT/UPDATE/DELETE/DDL) so cached
244
+ * entries can't outlive schema/data changes for that table between TTL
245
+ * expirations. Not automatically wired into every write in this codebase -
246
+ * callers that write outside of `QueryOptimizer` should call this explicitly.
247
+ */
248
+ invalidateTable(tableName) {
249
+ let invalidated = 0;
250
+ for (const [key, entry] of this.cache.entries()) {
251
+ if (entry.sql.toLowerCase().includes(tableName.toLowerCase())) {
252
+ this.evict(key, entry);
253
+ invalidated++;
254
+ }
255
+ }
256
+ return invalidated;
257
+ }
258
+ /**
259
+ * Remove expired entries
260
+ */
261
+ prune() {
262
+ const now = Date.now();
263
+ let pruned = 0;
264
+ for (const [key, entry] of this.cache.entries()) {
265
+ if (now - entry.createdAt > this.ttl) {
266
+ this.evict(key, entry);
267
+ pruned++;
268
+ }
269
+ }
270
+ return pruned;
271
+ }
272
+ /**
273
+ * Get cache size
274
+ */
275
+ get size() {
276
+ return this.cache.size;
277
+ }
278
+ }
279
+ exports.PreparedStatementCache = PreparedStatementCache;
280
+ /**
281
+ * Query result cache for caching query results
282
+ */
283
+ class QueryResultCache {
284
+ constructor(options = {}) {
285
+ this.cache = new Map();
286
+ this.maxSize = options.maxSize || 100;
287
+ this.ttl = options.ttl || 60000; // 1 minute default
288
+ this.logging = options.logging || false;
289
+ }
290
+ /**
291
+ * Get cached query result
292
+ */
293
+ get(sql, params) {
294
+ const key = this.generateKey(sql, params);
295
+ const entry = this.cache.get(key);
296
+ if (!entry)
297
+ return undefined;
298
+ // Check if entry has expired
299
+ if (Date.now() - entry.createdAt > this.ttl) {
300
+ this.cache.delete(key);
301
+ return undefined;
302
+ }
303
+ entry.hitCount++;
304
+ entry.lastUsedAt = Date.now();
305
+ return entry.result;
306
+ }
307
+ /**
308
+ * Store a query result in cache
309
+ */
310
+ set(sql, params, result) {
311
+ const key = this.generateKey(sql, params);
312
+ // Check if we need to evict entries
313
+ if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
314
+ this.evictOldest();
315
+ }
316
+ this.cache.set(key, {
317
+ key,
318
+ sql,
319
+ params,
320
+ result,
321
+ createdAt: Date.now(),
322
+ lastUsedAt: Date.now(),
323
+ hitCount: 0,
324
+ });
325
+ this.log(`Cached result for: ${key}`);
326
+ }
327
+ /**
328
+ * Check if a query result is cached
329
+ */
330
+ has(sql, params) {
331
+ const key = this.generateKey(sql, params);
332
+ const entry = this.cache.get(key);
333
+ if (!entry)
334
+ return false;
335
+ if (Date.now() - entry.createdAt > this.ttl) {
336
+ this.cache.delete(key);
337
+ return false;
338
+ }
339
+ return true;
340
+ }
341
+ /**
342
+ * Invalidate cache for a specific table
343
+ */
344
+ invalidateTable(tableName) {
345
+ let invalidated = 0;
346
+ for (const [key, entry] of this.cache.entries()) {
347
+ if (entry.sql.toLowerCase().includes(tableName.toLowerCase())) {
348
+ this.cache.delete(key);
349
+ invalidated++;
350
+ }
351
+ }
352
+ return invalidated;
353
+ }
354
+ /**
355
+ * Clear all cached results
356
+ */
357
+ clear() {
358
+ this.cache.clear();
359
+ }
360
+ /**
361
+ * Get cache statistics
362
+ */
363
+ getStats() {
364
+ let hitCount = 0;
365
+ for (const entry of this.cache.values()) {
366
+ hitCount += entry.hitCount;
367
+ }
368
+ return {
369
+ size: this.cache.size,
370
+ maxSize: this.maxSize,
371
+ hitCount,
372
+ };
373
+ }
374
+ /**
375
+ * Generate a cache key
376
+ */
377
+ generateKey(sql, params) {
378
+ const normalizedSql = sql.replace(/\s+/g, ' ').trim();
379
+ if (params && params.length > 0) {
380
+ return `${normalizedSql}::${JSON.stringify(params)}`;
381
+ }
382
+ return normalizedSql;
383
+ }
384
+ /**
385
+ * Evict the oldest entry
386
+ */
387
+ evictOldest() {
388
+ let oldestKey = null;
389
+ let oldestTime = Date.now();
390
+ for (const [key, entry] of this.cache.entries()) {
391
+ if (entry.lastUsedAt < oldestTime) {
392
+ oldestTime = entry.lastUsedAt;
393
+ oldestKey = key;
394
+ }
395
+ }
396
+ if (oldestKey) {
397
+ this.cache.delete(oldestKey);
398
+ }
399
+ }
400
+ /**
401
+ * Log a message
402
+ */
403
+ log(message) {
404
+ if (this.logging) {
405
+ console.log(`[QueryResultCache] ${message}`);
406
+ }
407
+ }
408
+ }
409
+ exports.QueryResultCache = QueryResultCache;
410
+ /**
411
+ * Create a prepared statement cache
412
+ */
413
+ function createPreparedStatementCache(dialect, options) {
414
+ return new PreparedStatementCache(dialect, {
415
+ maxSize: 500,
416
+ ...options,
417
+ });
418
+ }
419
+ exports.default = {
420
+ PreparedStatementCache,
421
+ QueryResultCache,
422
+ createPreparedStatementCache,
423
+ };