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,328 @@
1
+ "use strict";
2
+ /**
3
+ * Typed window-function builder API.
4
+ *
5
+ * Provides a fluent, chainable builder for SQL window functions
6
+ * (`OVER (PARTITION BY ... ORDER BY ... ROWS/RANGE BETWEEN ...)`) so callers
7
+ * never need to hand-write raw SQL strings for `ROW_NUMBER()`, `RANK()`,
8
+ * `LAG()`, `LEAD()`, and friends.
9
+ *
10
+ * This module is intentionally self-contained: it does not add any new
11
+ * dispatch branches to the shared SQL compiler. Every builder resolves
12
+ * directly to a final SQL fragment string, which is then wrapped with the
13
+ * existing `literalExpr()`/`literal()` helpers from `src/operators.ts` so it
14
+ * slots into `attributes: [...]` arrays exactly the way `fn()`/`col()`/
15
+ * `cast()` do today (see `attributeToSql()` / `processAttribute()` in
16
+ * `src/query-builders/sql-compiler.ts`, which both already know how to
17
+ * render `{ __type: 'literal', sql }` and `[expr, alias]` tuples).
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { rowNumber, rank, lag, sumOver } from './query-builders/functions/window';
22
+ * import { col } from '../../operators';
23
+ *
24
+ * User.findAll({
25
+ * attributes: [
26
+ * 'department',
27
+ * 'salary',
28
+ * rowNumber().partitionBy('department').orderBy('salary', 'DESC').as('rn'),
29
+ * rank().partitionBy(col('department')).orderBy(col('salary'), 'DESC').as('rnk'),
30
+ * lag(col('salary'), 1).partitionBy('department').orderBy('hireDate').as('prevSalary'),
31
+ * sumOver(col('salary'))
32
+ * .partitionBy('department')
33
+ * .orderBy('hireDate')
34
+ * .rows({ start: 'unboundedPreceding', end: 'currentRow' })
35
+ * .as('runningTotal'),
36
+ * ],
37
+ * });
38
+ * ```
39
+ */
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.WindowFunctionBuilder = exports.NullsOrder = void 0;
42
+ exports.rowNumber = rowNumber;
43
+ exports.rank = rank;
44
+ exports.denseRank = denseRank;
45
+ exports.percentRank = percentRank;
46
+ exports.cumeDist = cumeDist;
47
+ exports.ntile = ntile;
48
+ exports.lag = lag;
49
+ exports.lead = lead;
50
+ exports.firstValue = firstValue;
51
+ exports.lastValue = lastValue;
52
+ exports.nthValue = nthValue;
53
+ exports.sumOver = sumOver;
54
+ exports.avgOver = avgOver;
55
+ exports.countOver = countOver;
56
+ exports.minOver = minOver;
57
+ exports.maxOver = maxOver;
58
+ exports.windowFn = windowFn;
59
+ const operators_1 = require("../../operators");
60
+ /**
61
+ * `NULLS FIRST` / `NULLS LAST` modifier, supported by most (not all) dialects.
62
+ *
63
+ * Companion enum {@link NullsOrder} is available for the `'FIRST' | 'LAST'`
64
+ * string-literal union below; raw string literals continue to work unchanged.
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * // Using raw string literals (still supported)
69
+ * rowNumber().orderBy('salary', 'DESC', 'LAST')
70
+ *
71
+ * // Using the NullsOrder enum
72
+ * import { NullsOrder } from './query-builders/functions/window';
73
+ * rowNumber().orderBy('salary', 'DESC', NullsOrder.LAST)
74
+ * ```
75
+ */
76
+ var NullsOrder;
77
+ (function (NullsOrder) {
78
+ NullsOrder["FIRST"] = "FIRST";
79
+ NullsOrder["LAST"] = "LAST";
80
+ })(NullsOrder || (exports.NullsOrder = NullsOrder = {}));
81
+ function escapeIdentifier(name) {
82
+ // Support dotted "table.column" references, same convention as col().
83
+ if (name.includes('.')) {
84
+ return name
85
+ .split('.')
86
+ .map((part) => `"${part.replace(/"/g, '""')}"`)
87
+ .join('.');
88
+ }
89
+ return `"${name.replace(/"/g, '""')}"`;
90
+ }
91
+ /**
92
+ * Flatten a window-function argument (string, ColExpression, FnExpression,
93
+ * LiteralExpression, number, null) into a raw SQL fragment string.
94
+ */
95
+ function toSqlFragment(arg) {
96
+ if (arg === null)
97
+ return 'NULL';
98
+ if (arg === undefined)
99
+ return 'NULL';
100
+ if (typeof arg === 'number') {
101
+ return String(arg);
102
+ }
103
+ if (typeof arg === 'string') {
104
+ return escapeIdentifier(arg);
105
+ }
106
+ if ((0, operators_1.isFnExpression)(arg)) {
107
+ const args = arg.args.map((a) => toSqlFragment(a)).join(', ');
108
+ return `${arg.fn}(${args})`;
109
+ }
110
+ if ((0, operators_1.isColExpression)(arg)) {
111
+ return escapeIdentifier(arg.col);
112
+ }
113
+ if ((0, operators_1.isLiteralExpression)(arg)) {
114
+ // Handles both { __type: 'literal', sql } and { $literal: sql } shapes.
115
+ return arg.sql ?? arg.$literal;
116
+ }
117
+ // Fallback: stringify.
118
+ return String(arg);
119
+ }
120
+ function frameBoundaryToSql(boundary) {
121
+ if (boundary === 'unboundedPreceding')
122
+ return 'UNBOUNDED PRECEDING';
123
+ if (boundary === 'unboundedFollowing')
124
+ return 'UNBOUNDED FOLLOWING';
125
+ if (boundary === 'currentRow')
126
+ return 'CURRENT ROW';
127
+ if (typeof boundary === 'object' && boundary !== null) {
128
+ if ('preceding' in boundary)
129
+ return `${boundary.preceding} PRECEDING`;
130
+ if ('following' in boundary)
131
+ return `${boundary.following} FOLLOWING`;
132
+ }
133
+ throw new Error(`Invalid window frame boundary: ${JSON.stringify(boundary)}`);
134
+ }
135
+ /**
136
+ * A chainable builder that accumulates PARTITION BY / ORDER BY / frame
137
+ * clauses for a single window function call and renders the final
138
+ * `FN(args) OVER (...)` SQL fragment.
139
+ */
140
+ class WindowFunctionBuilder {
141
+ constructor(fnName, fnArgs = []) {
142
+ this.partitions = [];
143
+ this.orders = [];
144
+ this.fnName = fnName;
145
+ this.fnArgs = fnArgs;
146
+ }
147
+ /**
148
+ * Set (or narrow) the target dialect. Only matters for the rare cases
149
+ * where OVER-clause syntax genuinely diverges (all listed dialects use the
150
+ * same ANSI-standard OVER syntax today, so this is mostly a documented
151
+ * escape hatch for future dialect-specific tweaks).
152
+ */
153
+ forDialect(dialect) {
154
+ this.dialect = dialect;
155
+ return this;
156
+ }
157
+ /** Add one or more PARTITION BY columns/expressions. Repeatable/additive. */
158
+ partitionBy(...cols) {
159
+ this.partitions.push(...cols);
160
+ return this;
161
+ }
162
+ /**
163
+ * Add an ORDER BY entry to the window definition. Call multiple times to
164
+ * order by multiple columns; each call appends one entry.
165
+ */
166
+ orderBy(expr, direction, nulls) {
167
+ this.orders.push({ expr, direction, nulls });
168
+ return this;
169
+ }
170
+ /** Set a ROWS frame clause, e.g. `ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`. */
171
+ rows(frame) {
172
+ this.frameMode = 'ROWS';
173
+ this.frame = frame;
174
+ return this;
175
+ }
176
+ /** Set a RANGE frame clause, e.g. `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`. */
177
+ range(frame) {
178
+ this.frameMode = 'RANGE';
179
+ this.frame = frame;
180
+ return this;
181
+ }
182
+ /** Render the `FN(args) OVER (...)` SQL fragment (no alias). */
183
+ toSQL() {
184
+ const argsSql = this.fnArgs.map((a) => toSqlFragment(a)).join(', ');
185
+ const overParts = [];
186
+ if (this.partitions.length > 0) {
187
+ overParts.push(`PARTITION BY ${this.partitions.map((p) => toSqlFragment(p)).join(', ')}`);
188
+ }
189
+ if (this.orders.length > 0) {
190
+ const orderSql = this.orders
191
+ .map((o) => {
192
+ let part = toSqlFragment(o.expr);
193
+ if (o.direction)
194
+ part += ` ${o.direction}`;
195
+ if (o.nulls)
196
+ part += ` NULLS ${o.nulls}`;
197
+ return part;
198
+ })
199
+ .join(', ');
200
+ overParts.push(`ORDER BY ${orderSql}`);
201
+ }
202
+ if (this.frameMode && this.frame) {
203
+ const start = frameBoundaryToSql(this.frame.start);
204
+ if (this.frame.end) {
205
+ const end = frameBoundaryToSql(this.frame.end);
206
+ overParts.push(`${this.frameMode} BETWEEN ${start} AND ${end}`);
207
+ }
208
+ else {
209
+ overParts.push(`${this.frameMode} ${start}`);
210
+ }
211
+ }
212
+ const overClause = overParts.length > 0 ? `OVER (${overParts.join(' ')})` : 'OVER ()';
213
+ return `${this.fnName}(${argsSql}) ${overClause}`;
214
+ }
215
+ /**
216
+ * Terminal call: returns an `[expr, alias]` tuple compatible with the
217
+ * existing `attributes: [...]` pattern (see `attributeToSql()` /
218
+ * `attributeToSqlWithAlias()` in `sql-compiler.ts`, both of which already
219
+ * know how to render `[LiteralExpression, alias]` tuples without any core
220
+ * changes).
221
+ */
222
+ as(alias) {
223
+ return [(0, operators_1.literalExpr)(this.toSQL()), alias];
224
+ }
225
+ /**
226
+ * Allow the builder to be used directly wherever a raw SQL literal is
227
+ * expected (e.g. passed straight into `literal()`-consuming positions)
228
+ * without requiring `.as(...)`.
229
+ */
230
+ toLiteral() {
231
+ return (0, operators_1.literalExpr)(this.toSQL());
232
+ }
233
+ }
234
+ exports.WindowFunctionBuilder = WindowFunctionBuilder;
235
+ // ---------------------------------------------------------------------------
236
+ // Ranking functions
237
+ // ---------------------------------------------------------------------------
238
+ /** `ROW_NUMBER() OVER (...)` */
239
+ function rowNumber() {
240
+ return new WindowFunctionBuilder('ROW_NUMBER');
241
+ }
242
+ /** `RANK() OVER (...)` */
243
+ function rank() {
244
+ return new WindowFunctionBuilder('RANK');
245
+ }
246
+ /** `DENSE_RANK() OVER (...)` */
247
+ function denseRank() {
248
+ return new WindowFunctionBuilder('DENSE_RANK');
249
+ }
250
+ /** `PERCENT_RANK() OVER (...)` */
251
+ function percentRank() {
252
+ return new WindowFunctionBuilder('PERCENT_RANK');
253
+ }
254
+ /** `CUME_DIST() OVER (...)` */
255
+ function cumeDist() {
256
+ return new WindowFunctionBuilder('CUME_DIST');
257
+ }
258
+ /** `NTILE(buckets) OVER (...)` */
259
+ function ntile(buckets) {
260
+ return new WindowFunctionBuilder('NTILE', [buckets]);
261
+ }
262
+ // ---------------------------------------------------------------------------
263
+ // Value / offset functions
264
+ // ---------------------------------------------------------------------------
265
+ /** `LAG(expr[, offset[, default]]) OVER (...)` */
266
+ function lag(expr, offset, defaultValue) {
267
+ const args = [expr];
268
+ if (offset !== undefined)
269
+ args.push(offset);
270
+ if (defaultValue !== undefined)
271
+ args.push(defaultValue);
272
+ return new WindowFunctionBuilder('LAG', args);
273
+ }
274
+ /** `LEAD(expr[, offset[, default]]) OVER (...)` */
275
+ function lead(expr, offset, defaultValue) {
276
+ const args = [expr];
277
+ if (offset !== undefined)
278
+ args.push(offset);
279
+ if (defaultValue !== undefined)
280
+ args.push(defaultValue);
281
+ return new WindowFunctionBuilder('LEAD', args);
282
+ }
283
+ /** `FIRST_VALUE(expr) OVER (...)` */
284
+ function firstValue(expr) {
285
+ return new WindowFunctionBuilder('FIRST_VALUE', [expr]);
286
+ }
287
+ /** `LAST_VALUE(expr) OVER (...)` */
288
+ function lastValue(expr) {
289
+ return new WindowFunctionBuilder('LAST_VALUE', [expr]);
290
+ }
291
+ /** `NTH_VALUE(expr, n) OVER (...)` */
292
+ function nthValue(expr, n) {
293
+ return new WindowFunctionBuilder('NTH_VALUE', [expr, n]);
294
+ }
295
+ // ---------------------------------------------------------------------------
296
+ // Window-aggregate forms
297
+ // ---------------------------------------------------------------------------
298
+ /** `SUM(expr) OVER (...)` */
299
+ function sumOver(expr) {
300
+ return new WindowFunctionBuilder('SUM', [expr]);
301
+ }
302
+ /** `AVG(expr) OVER (...)` */
303
+ function avgOver(expr) {
304
+ return new WindowFunctionBuilder('AVG', [expr]);
305
+ }
306
+ /** `COUNT(expr | *) OVER (...)` */
307
+ function countOver(expr) {
308
+ if (expr === undefined) {
309
+ return new WindowFunctionBuilder('COUNT', [(0, operators_1.literalExpr)('*')]);
310
+ }
311
+ return new WindowFunctionBuilder('COUNT', [expr]);
312
+ }
313
+ /** `MIN(expr) OVER (...)` */
314
+ function minOver(expr) {
315
+ return new WindowFunctionBuilder('MIN', [expr]);
316
+ }
317
+ /** `MAX(expr) OVER (...)` */
318
+ function maxOver(expr) {
319
+ return new WindowFunctionBuilder('MAX', [expr]);
320
+ }
321
+ /**
322
+ * Generic escape hatch: build a window function call for any function name
323
+ * not covered by the named helpers above (e.g. dialect-specific analytic
324
+ * functions).
325
+ */
326
+ function windowFn(fnName, ...args) {
327
+ return new WindowFunctionBuilder(fnName.toUpperCase(), args);
328
+ }
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+ /**
3
+ * Include builder for the ORM
4
+ * Handles JOIN clauses for model associations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.IncludeBuilder = void 0;
8
+ exports.createIncludeBuilder = createIncludeBuilder;
9
+ exports.buildIncludes = buildIncludes;
10
+ const where_builder_1 = require("./where-builder");
11
+ /**
12
+ * IncludeBuilder class for building JOIN clauses
13
+ */
14
+ class IncludeBuilder {
15
+ /**
16
+ * Creates a nested WhereBuilder (sharing replacements/model/dialect) used to
17
+ * render `on`, `where`, and `lateralSubquery.where` clauses on included tables
18
+ */
19
+ constructor(options = {}) {
20
+ this.options = options;
21
+ this.whereBuilder = new where_builder_1.WhereBuilder({
22
+ replacements: options.replacements,
23
+ model: options.model,
24
+ dialect: options.dialect,
25
+ });
26
+ }
27
+ /**
28
+ * Build JOIN clauses from include options
29
+ */
30
+ build(includes) {
31
+ const sqlParts = [];
32
+ const values = [];
33
+ for (const include of includes) {
34
+ const result = this.buildInclude(include, values);
35
+ if (result) {
36
+ sqlParts.push(result);
37
+ }
38
+ }
39
+ return { sql: sqlParts.join(' '), values };
40
+ }
41
+ /**
42
+ * Build a single include (can handle nested includes)
43
+ */
44
+ buildInclude(include, values) {
45
+ // Determine model and alias
46
+ const model = include.model;
47
+ const tableName = model?.tableName || model?.name || String(model);
48
+ const alias = include.as || tableName;
49
+ // Get schema from include options (supports joining across schemas)
50
+ const schema = include.schema;
51
+ const schemaDelimiter = this.options.schemaDelimiter || '.';
52
+ // Build table name with schema if specified (e.g., "schema.tableName")
53
+ const fullTableName = schema ? `${schema}${schemaDelimiter}${tableName}` : tableName;
54
+ // Handle anti-join (antiJoin or exclude option)
55
+ const isAntiJoin = include.antiJoin === true || include.exclude === true;
56
+ // Get anti-join type (defaults to leftJoinIsNull)
57
+ const antiJoinType = include.antiJoinType || 'leftJoinIsNull';
58
+ // For notExists and notIn, we handle differently - return null from join and handle in where
59
+ if (isAntiJoin && (antiJoinType === 'notExists' || antiJoinType === 'notIn')) {
60
+ // Return empty string - these will be handled in the where clause with subqueries
61
+ return '';
62
+ }
63
+ // Determine join type
64
+ let joinType = this.getJoinType(include);
65
+ // For anti-joins with leftJoinIsNull, always use LEFT JOIN
66
+ if (isAntiJoin && antiJoinType === 'leftJoinIsNull') {
67
+ joinType = 'LEFT JOIN';
68
+ }
69
+ // Build ON clause
70
+ const onClause = this.buildOnClause(include, fullTableName, alias, values);
71
+ // Build the JOIN clause
72
+ let sql = `${joinType} ${this.escapeId(fullTableName)} ${this.escapeId(alias)}`;
73
+ // Handle CROSS APPLY / OUTER APPLY (SQL Server)
74
+ if (include.apply) {
75
+ const applyType = include.apply === 'CROSS' ? 'CROSS APPLY' : 'OUTER APPLY';
76
+ sql = `${applyType} ${this.escapeId(fullTableName)} ${this.escapeId(alias)}`;
77
+ }
78
+ // Handle LATERAL keyword (PostgreSQL only)
79
+ if (include.lateral) {
80
+ sql = `${joinType} LATERAL ${this.escapeId(fullTableName)} ${this.escapeId(alias)}`;
81
+ }
82
+ // Handle lateralSubquery (inline subquery)
83
+ if (include.lateralSubquery) {
84
+ const subqueryModel = include.lateralSubquery.model;
85
+ const subqueryTableName = subqueryModel?.tableName || subqueryModel?.name || 'subquery';
86
+ const subqueryAlias = alias;
87
+ // Build SELECT clause
88
+ let selectColumns = '*';
89
+ if (include.lateralSubquery.attributes) {
90
+ if (Array.isArray(include.lateralSubquery.attributes)) {
91
+ selectColumns = include.lateralSubquery.attributes
92
+ .map((c) => this.escapeId(c))
93
+ .join(', ');
94
+ }
95
+ else if (include.lateralSubquery.attributes.include) {
96
+ selectColumns = include.lateralSubquery.attributes.include
97
+ .map((c) => this.escapeId(c))
98
+ .join(', ');
99
+ }
100
+ }
101
+ // Build the lateral subquery
102
+ let subquery = `SELECT ${selectColumns} FROM ${this.escapeId(subqueryTableName)}`;
103
+ // Add ON clause if there's a foreign key relationship
104
+ if (onClause) {
105
+ subquery += ` ON ${onClause}`;
106
+ }
107
+ else {
108
+ const fk = include.foreignKey;
109
+ const foreignKey = typeof fk === 'string'
110
+ ? fk
111
+ : Array.isArray(fk)
112
+ ? fk[0]
113
+ : fk?.name || this.guessForeignKey(include, tableName);
114
+ const parentAlias = this.options.parentAlias || 'main';
115
+ subquery += ` ON ${this.escapeId(parentAlias)}.${this.escapeId(foreignKey)} = ${this.escapeId(subqueryAlias)}.${this.getPrimaryKey(include)}`;
116
+ }
117
+ // Add WHERE clause if specified
118
+ if (include.lateralSubquery.where) {
119
+ const whereResult = this.whereBuilder.build(include.lateralSubquery.where);
120
+ if (whereResult.sql) {
121
+ subquery += ` AND (${whereResult.sql})`;
122
+ values.push(...whereResult.values);
123
+ }
124
+ }
125
+ sql = `${joinType} LATERAL (${subquery}) ${this.escapeId(subqueryAlias)}`;
126
+ }
127
+ if (onClause) {
128
+ sql += ` ON ${onClause}`;
129
+ }
130
+ else {
131
+ // Fallback: use foreign key if not specified
132
+ const fk = include.foreignKey;
133
+ const foreignKey = typeof fk === 'string'
134
+ ? fk
135
+ : Array.isArray(fk)
136
+ ? fk[0]
137
+ : fk?.name || this.guessForeignKey(include, tableName);
138
+ const parentAlias = this.options.parentAlias || 'main';
139
+ sql += ` ON ${this.escapeId(parentAlias)}.${this.escapeId(foreignKey)} = ${this.escapeId(alias)}.${this.escapeId(this.getPrimaryKey(include))}`;
140
+ }
141
+ // Handle through table for many-to-many associations
142
+ if (include.through) {
143
+ sql = this.buildThroughJoin(include, sql, values);
144
+ }
145
+ // Handle where clause on the joined table
146
+ if (include.where) {
147
+ const whereResult = this.whereBuilder.build(include.where);
148
+ if (whereResult.sql) {
149
+ sql += ` AND (${whereResult.sql})`;
150
+ values.push(...whereResult.values);
151
+ }
152
+ }
153
+ // For anti-joins, add WHERE clause to check for NULL (LEFT JOIN WHERE NULL pattern)
154
+ if (isAntiJoin) {
155
+ const pk = this.getPrimaryKey(include);
156
+ sql += ` AND ${this.escapeId(alias)}.${this.escapeId(pk)} IS NULL`;
157
+ }
158
+ // Handle nested includes
159
+ if (include.include && include.include.length > 0) {
160
+ const nestedBuilder = new IncludeBuilder({
161
+ ...this.options,
162
+ parentAlias: alias,
163
+ });
164
+ for (const nestedInclude of include.include) {
165
+ const nestedResult = nestedBuilder.buildInclude(nestedInclude, values);
166
+ if (nestedResult) {
167
+ sql += ` ${nestedResult}`;
168
+ }
169
+ }
170
+ }
171
+ return sql;
172
+ }
173
+ /**
174
+ * Build a through-table join for many-to-many associations
175
+ */
176
+ buildThroughJoin(include, baseJoin, values) {
177
+ const through = include.through;
178
+ const throughModel = through?.model;
179
+ const throughTableName = throughModel?.tableName || throughModel?.name || String(through?.model || 'through');
180
+ const throughAlias = through?.as || `${throughTableName}_through`;
181
+ // Build the join through the through table
182
+ const parentAlias = this.options.parentAlias || 'main';
183
+ // Use the provided 'as' alias or fall back to table name
184
+ const targetAlias = include.as || targetTableName(include.model);
185
+ // We need to modify the base join to go through the through table
186
+ // This creates: INNER JOIN through_table ON parent.id = through_table.parent_id
187
+ // INNER JOIN target_table ON through_table.target_id = target_table.id
188
+ const parentKey = this.options.parentKey || 'id';
189
+ const childKey = this.options.childKey || this.getPrimaryKey(include);
190
+ const throughJoin = `${this.getJoinType(include)} ${this.escapeId(throughTableName)} ${this.escapeId(throughAlias)} ON ${this.escapeId(parentAlias)}.${this.escapeId(parentKey)} = ${this.escapeId(throughAlias)}.${this.escapeId(this.guessForeignKey(include, parentAlias))}`;
191
+ return `${this.getJoinType(include)} ${this.escapeId(throughTableName)} ${this.escapeId(throughAlias)} ON ${this.escapeId(parentAlias)}.${this.escapeId(parentKey)} = ${this.escapeId(throughAlias)}.${this.guessForeignKey(include, parentAlias)} ${this.getJoinType(include)} ${this.escapeId(targetTableName(include.model))} ${this.escapeId(targetAlias)} ON ${this.escapeId(throughAlias)}.${this.escapeId(childKey)} = ${this.escapeId(targetAlias)}.${this.escapeId(childKey)}`;
192
+ }
193
+ /**
194
+ * Get the join type based on include options
195
+ */
196
+ getJoinType(include) {
197
+ // Check for explicit joinType first
198
+ if (include.joinType) {
199
+ switch (include.joinType) {
200
+ case 'INNER':
201
+ return 'INNER JOIN';
202
+ case 'LEFT':
203
+ return 'LEFT JOIN';
204
+ case 'RIGHT':
205
+ return 'RIGHT JOIN';
206
+ case 'FULL':
207
+ return 'FULL OUTER JOIN';
208
+ case 'CROSS':
209
+ return 'CROSS JOIN';
210
+ }
211
+ }
212
+ // Fall back to required flag
213
+ if (include.required) {
214
+ return 'INNER JOIN';
215
+ }
216
+ // Default to LEFT JOIN for optional associations
217
+ return 'LEFT JOIN';
218
+ }
219
+ /**
220
+ * Build the ON clause for a join
221
+ */
222
+ buildOnClause(include, tableName, alias, values) {
223
+ // If explicit ON clause is provided
224
+ if (include.on) {
225
+ const whereResult = this.whereBuilder.build(include.on);
226
+ // Need to handle the ON clause differently - it uses the alias
227
+ return this.buildOnFromWhere(include.on, alias, values);
228
+ }
229
+ // Otherwise, try to build from association
230
+ return null;
231
+ }
232
+ /**
233
+ * Build ON clause from WhereOptions
234
+ */
235
+ buildOnFromWhere(on, alias, values) {
236
+ const onConditions = [];
237
+ if (typeof on !== 'object') {
238
+ return '';
239
+ }
240
+ for (const [key, value] of Object.entries(on)) {
241
+ if (key.startsWith('$'))
242
+ continue;
243
+ if (typeof value === 'object' && value !== null) {
244
+ const valueObj = value;
245
+ // Handle $eq
246
+ if (valueObj.$eq !== undefined) {
247
+ values.push(valueObj.$eq);
248
+ onConditions.push(`${alias}.${this.escapeId(key)} = ?`);
249
+ }
250
+ }
251
+ else {
252
+ values.push(value);
253
+ onConditions.push(`${alias}.${this.escapeId(key)} = ?`);
254
+ }
255
+ }
256
+ return onConditions.join(' AND ');
257
+ }
258
+ /**
259
+ * Guess the foreign key name for an association
260
+ */
261
+ guessForeignKey(include, tableName) {
262
+ // If foreignKey is explicitly provided
263
+ if (include.foreignKey) {
264
+ return typeof include.foreignKey === 'string'
265
+ ? include.foreignKey
266
+ : include.foreignKey.name || 'id';
267
+ }
268
+ // Default convention: tableName_id
269
+ const model = include.model;
270
+ const modelName = model?.name || tableName;
271
+ return `${modelName.charAt(0).toLowerCase() + modelName.slice(1)}Id`;
272
+ }
273
+ /**
274
+ * Get the primary key of a model
275
+ */
276
+ getPrimaryKey(include) {
277
+ const model = include.model;
278
+ // Try to get from rawAttributes
279
+ if (model?.rawAttributes) {
280
+ for (const [attrName, attr] of Object.entries(model.rawAttributes)) {
281
+ if (attr.primaryKey) {
282
+ return attrName;
283
+ }
284
+ }
285
+ }
286
+ // Default to 'id'
287
+ return 'id';
288
+ }
289
+ /**
290
+ * Escape an identifier
291
+ */
292
+ escapeId(identifier) {
293
+ const id = String(identifier ?? '');
294
+ if (this.options.dialect?.escapeId) {
295
+ return this.options.dialect.escapeId(id);
296
+ }
297
+ return `"${id.replace(/"/g, '""')}"`;
298
+ }
299
+ }
300
+ exports.IncludeBuilder = IncludeBuilder;
301
+ /**
302
+ * Helper to get table name from model
303
+ */
304
+ function targetTableName(model) {
305
+ if (typeof model === 'string') {
306
+ return model;
307
+ }
308
+ return model.tableName || model.name || String(model);
309
+ }
310
+ /**
311
+ * Create an IncludeBuilder instance
312
+ */
313
+ function createIncludeBuilder(options) {
314
+ return new IncludeBuilder(options);
315
+ }
316
+ /**
317
+ * Quick helper to build include JOINs
318
+ */
319
+ function buildIncludes(includes, options) {
320
+ const builder = new IncludeBuilder(options);
321
+ return builder.build(includes);
322
+ }
323
+ exports.default = IncludeBuilder;