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,427 @@
1
+ "use strict";
2
+ /**
3
+ * Cross-dialect, typed JSON-path function API.
4
+ *
5
+ * This module lets callers pull a JSON field/path out of a JSON/JSONB column
6
+ * (or any expression producing one) as a first-class, typed SQL expression
7
+ * usable in `attributes` / `SELECT`, without ever having to hand-write raw
8
+ * SQL strings for it.
9
+ *
10
+ * It is intentionally self-contained: it does not rely on (or modify) the
11
+ * dialect classes in `src/dialects/**` or the compiler in
12
+ * `src/query-builders/sql-compiler.ts`. Instead it re-derives, per dialect,
13
+ * the exact SQL fragments that this codebase's own dialect-internal
14
+ * WHERE-clause JSON helpers already produce (see the JSDoc on each function
15
+ * below for the specific dialect file/method that was used as the source of
16
+ * truth), so behavior stays consistent with the rest of the ORM.
17
+ *
18
+ * All functions return a `{ $literal: string }` value (the same shape
19
+ * produced by `literal()` in `src/operators.ts`), so the result can be
20
+ * dropped directly into `attributes`, e.g.:
21
+ *
22
+ * ```ts
23
+ * User.findAll({
24
+ * attributes: ['id', [jsonExtract('postgres', 'data', 'address.city'), 'city']],
25
+ * });
26
+ * ```
27
+ */
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.jsonExtract = jsonExtract;
30
+ exports.jsonContains = jsonContains;
31
+ exports.jsonHasKey = jsonHasKey;
32
+ exports.jsonKeys = jsonKeys;
33
+ exports.jsonTypeOf = jsonTypeOf;
34
+ const operators_1 = require("../../operators");
35
+ // ---------------------------------------------------------------------------
36
+ // Local, self-contained SQL-fragment rendering helpers
37
+ // (deliberately not imported from sql-compiler.ts, per architecture constraints)
38
+ // ---------------------------------------------------------------------------
39
+ function quoteChars(dialect) {
40
+ switch (dialect) {
41
+ case 'mysql':
42
+ case 'mariadb':
43
+ case 'clickhouse':
44
+ return { open: '`', close: '`', escape: (s) => s.replace(/`/g, '``') };
45
+ case 'mssql':
46
+ return { open: '[', close: ']', escape: (s) => s.replace(/\]/g, ']]') };
47
+ default:
48
+ // postgres, sqlite, cockroachdb, redshift, db2, snowflake, oracle
49
+ return { open: '"', close: '"', escape: (s) => s.replace(/"/g, '""') };
50
+ }
51
+ }
52
+ /** Escape/quote a single identifier segment (no dot-splitting). */
53
+ function quoteIdentifierPart(dialect, part) {
54
+ const { open, close, escape } = quoteChars(dialect);
55
+ return `${open}${escape(part)}${close}`;
56
+ }
57
+ /** Escape/quote a possibly dotted identifier path (e.g. `table.column`). */
58
+ function quoteIdentifierPath(dialect, name) {
59
+ return name
60
+ .split('.')
61
+ .map((part) => quoteIdentifierPart(dialect, part))
62
+ .join('.');
63
+ }
64
+ /**
65
+ * Escape a string literal for embedding directly into generated SQL text.
66
+ * MySQL/MariaDB also need backslash escaping (in addition to quote doubling);
67
+ * every other supported dialect here only needs `'` doubled.
68
+ */
69
+ function escapeStringLiteral(dialect, value) {
70
+ if (dialect === 'mysql' || dialect === 'mariadb') {
71
+ return value.replace(/\\/g, '\\\\').replace(/'/g, "''");
72
+ }
73
+ return value.replace(/'/g, "''");
74
+ }
75
+ /**
76
+ * Render any supported expression argument (plain column name string,
77
+ * `col()`, `fn()`, or `literal()`/`{ $literal }`) down to a raw SQL fragment
78
+ * string, using this module's own dialect-aware identifier quoting.
79
+ */
80
+ function toSqlFragment(dialect, arg) {
81
+ if (arg !== null && typeof arg === 'object') {
82
+ if ('$literal' in arg) {
83
+ return arg.$literal;
84
+ }
85
+ const typed = arg;
86
+ if (typed.__type === 'literal') {
87
+ return arg.sql;
88
+ }
89
+ if (typed.__type === 'col') {
90
+ return quoteIdentifierPath(dialect, arg.col);
91
+ }
92
+ if (typed.__type === 'fn') {
93
+ const fnExpr = arg;
94
+ const renderedArgs = fnExpr.args.map((a) => toSqlFragment(dialect, a)).join(', ');
95
+ return `${fnExpr.fn}(${renderedArgs})`;
96
+ }
97
+ throw new Error(`jsonExtract/jsonContains/jsonHasKey/jsonKeys/jsonTypeOf: unsupported expression argument: ${JSON.stringify(arg)}`);
98
+ }
99
+ if (typeof arg === 'string') {
100
+ // Plain strings are treated as column names (consistent with col()).
101
+ return quoteIdentifierPath(dialect, arg);
102
+ }
103
+ throw new Error(`jsonExtract: unsupported expression argument: ${String(arg)}`);
104
+ }
105
+ // ---------------------------------------------------------------------------
106
+ // Path normalization
107
+ // ---------------------------------------------------------------------------
108
+ /** Normalize `path` (dotted string or array of keys/indices) to plain string segments. */
109
+ function normalizePathSegments(path) {
110
+ if (Array.isArray(path)) {
111
+ return path.map((p) => String(p));
112
+ }
113
+ // Strip a leading '$.' / '$' so callers can pass either 'a.b' or '$.a.b'.
114
+ const stripped = path.startsWith('$.') ? path.slice(2) : path.startsWith('$') ? path.slice(1) : path;
115
+ return stripped.split('.').filter((s) => s.length > 0);
116
+ }
117
+ const isArrayIndexSegment = (seg) => /^\d+$/.test(seg);
118
+ /** Build a MySQL/MariaDB/MSSQL/SQLite/Oracle/Db2-style `$.a.b[0]` JSON path string. */
119
+ function buildDollarPath(segments) {
120
+ let out = '$';
121
+ for (const seg of segments) {
122
+ out += isArrayIndexSegment(seg) ? `[${seg}]` : `.${seg}`;
123
+ }
124
+ return out;
125
+ }
126
+ /** Build a Postgres/CockroachDB `#>`/`#>>` style `'{a,b}'` path-array literal body. */
127
+ function buildPgPathArray(segments) {
128
+ return segments.join(',');
129
+ }
130
+ /** Build a Redshift SUPER-navigation dot path: `a.b` or `a[0].b`. */
131
+ function buildDotPath(segments) {
132
+ return segments
133
+ .map((seg, i) => (isArrayIndexSegment(seg) ? `[${seg}]` : i === 0 ? seg : `.${seg}`))
134
+ .join('');
135
+ }
136
+ /** Build a Snowflake VARIANT `:`-path: `:a.b` or `:a[0].b`. */
137
+ function buildSnowflakePath(segments) {
138
+ return segments
139
+ .map((seg, i) => (isArrayIndexSegment(seg) ? `[${seg}]` : i === 0 ? `:${seg}` : `.${seg}`))
140
+ .join('');
141
+ }
142
+ // ---------------------------------------------------------------------------
143
+ // jsonExtract
144
+ // ---------------------------------------------------------------------------
145
+ /**
146
+ * Extract a value at a JSON path from `expr` as a typed, cross-dialect SQL
147
+ * expression usable in `attributes` / `SELECT`.
148
+ *
149
+ * Dialect syntax sources (matched against this codebase's existing internal
150
+ * dialect helpers where they exist):
151
+ * - mysql/mariadb: `src/dialects/{mysql,mariadb}/index.ts` `buildJsonExtract` ->
152
+ * `JSON_UNQUOTE(JSON_EXTRACT(col, '$.path'))` (asText) / `JSON_EXTRACT(col, '$.path')`.
153
+ * - mssql: `src/dialects/mssql/index.ts` `buildJsonExtract` ->
154
+ * `JSON_VALUE(col, '$.path')` (asText) / `JSON_QUERY(col, '$.path')`.
155
+ * - sqlite: `src/dialects/sqlite/index.ts` `buildJsonExtract` ->
156
+ * `CAST(json_extract(col, '$.path') AS TEXT)` (asText) / `json_extract(col, '$.path')`.
157
+ * - postgres/cockroachdb: `src/query-builders/where-builder.ts` `#>>`/`#>` handling ->
158
+ * `col #>> '{a,b}'` (asText) / `col #> '{a,b}'`.
159
+ * - oracle: Oracle SQL/JSON functions -> `JSON_VALUE(col, '$.path')` (asText) /
160
+ * `JSON_QUERY(col, '$.path')`.
161
+ * - snowflake: `src/dialects/snowflake/index.ts` `buildJsonQuery` -> `col:a.b::STRING`
162
+ * (asText) / `col:a.b` (VARIANT, non-text).
163
+ * - redshift: SUPER-type dot navigation (see `getDataTypeSql` mapping JSON/JSONB -> SUPER
164
+ * in `src/dialects/redshift/index.ts`) -> `CAST(col.a.b AS VARCHAR)` (asText) / `col.a.b`.
165
+ * - db2: Db2 JSON_VAL/JSON_QUERY path functions -> `JSON_VAL(col, 'a.b')` (asText) /
166
+ * `JSON_QUERY(col, '$.a.b')`.
167
+ * - clickhouse: `JSONExtractString(col, 'a', 'b')` (asText) / `JSONExtractRaw(col, 'a', 'b')`.
168
+ */
169
+ function jsonExtract(dialect, expr, path, options = {}) {
170
+ const asText = options.asText !== false;
171
+ const columnRef = toSqlFragment(dialect, expr);
172
+ const segments = normalizePathSegments(path);
173
+ switch (dialect) {
174
+ case 'mysql':
175
+ case 'mariadb': {
176
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
177
+ const extracted = `JSON_EXTRACT(${columnRef}, '${dollarPath}')`;
178
+ return (0, operators_1.literal)(asText ? `JSON_UNQUOTE(${extracted})` : extracted);
179
+ }
180
+ case 'mssql': {
181
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
182
+ return (0, operators_1.literal)(asText ? `JSON_VALUE(${columnRef}, '${dollarPath}')` : `JSON_QUERY(${columnRef}, '${dollarPath}')`);
183
+ }
184
+ case 'sqlite': {
185
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
186
+ const extracted = `json_extract(${columnRef}, '${dollarPath}')`;
187
+ return (0, operators_1.literal)(asText ? `CAST(${extracted} AS TEXT)` : extracted);
188
+ }
189
+ case 'postgres':
190
+ case 'cockroachdb': {
191
+ const pgPath = escapeStringLiteral(dialect, buildPgPathArray(segments));
192
+ return (0, operators_1.literal)(asText ? `${columnRef} #>> '{${pgPath}}'` : `${columnRef} #> '{${pgPath}}'`);
193
+ }
194
+ case 'oracle': {
195
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
196
+ return (0, operators_1.literal)(asText ? `JSON_VALUE(${columnRef}, '${dollarPath}')` : `JSON_QUERY(${columnRef}, '${dollarPath}')`);
197
+ }
198
+ case 'snowflake': {
199
+ const snowPath = buildSnowflakePath(segments);
200
+ const extracted = `${columnRef}${snowPath}`;
201
+ return (0, operators_1.literal)(asText ? `${extracted}::STRING` : extracted);
202
+ }
203
+ case 'redshift': {
204
+ const dotPath = buildDotPath(segments);
205
+ const extracted = `${columnRef}.${dotPath}`;
206
+ return (0, operators_1.literal)(asText ? `CAST(${extracted} AS VARCHAR)` : extracted);
207
+ }
208
+ case 'db2': {
209
+ // Db2 stores JSON as text (JSON DataType maps to CLOB, see
210
+ // src/dialects/db2/index.ts getDataTypeSql), so JSON_VAL/JSON_QUERY
211
+ // operate over the CLOB/VARCHAR content.
212
+ const dotPath = escapeStringLiteral(dialect, segments.join('.'));
213
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
214
+ return (0, operators_1.literal)(asText ? `JSON_VAL(${columnRef}, '${dotPath}')` : `JSON_QUERY(${columnRef}, '${dollarPath}')`);
215
+ }
216
+ case 'clickhouse': {
217
+ const args = [columnRef, ...segments.map((seg) => (isArrayIndexSegment(seg) ? seg : `'${escapeStringLiteral(dialect, seg)}'`))].join(', ');
218
+ return (0, operators_1.literal)(asText ? `JSONExtractString(${args})` : `JSONExtractRaw(${args})`);
219
+ }
220
+ default:
221
+ throw new Error(`jsonExtract: unsupported dialect '${dialect}'`);
222
+ }
223
+ }
224
+ // ---------------------------------------------------------------------------
225
+ // jsonContains
226
+ // ---------------------------------------------------------------------------
227
+ /**
228
+ * Does the JSON value in `expr` contain `value` (as a fragment/sub-document,
229
+ * or, where the dialect has no native containment predicate, as an exact
230
+ * equality check)?
231
+ *
232
+ * - mysql/mariadb: `JSON_CONTAINS(col, '<value-json>')` (matches
233
+ * `buildJsonContains` in `src/dialects/{mysql,mariadb}/index.ts`).
234
+ * - postgres/cockroachdb: native jsonb containment operator -> `col @> '<value-json>'::jsonb`.
235
+ * - sqlite: SQLite has no containment operator; mirrors the whole-document
236
+ * equality fallback used by `buildJsonContains` in
237
+ * `src/dialects/sqlite/index.ts` -> `col = '<value-json>'`.
238
+ * - mssql, oracle, snowflake, redshift, db2, clickhouse: none of these expose
239
+ * a native "does this JSON document contain this sub-fragment" predicate
240
+ * (as opposed to key existence or exact-path equality), so this throws a
241
+ * clear "not supported" error rather than emitting a plausible-looking but
242
+ * semantically wrong query.
243
+ */
244
+ function jsonContains(dialect, expr, value) {
245
+ const columnRef = toSqlFragment(dialect, expr);
246
+ const jsonText = escapeStringLiteral(dialect, JSON.stringify(value));
247
+ switch (dialect) {
248
+ case 'mysql':
249
+ case 'mariadb':
250
+ return (0, operators_1.literal)(`JSON_CONTAINS(${columnRef}, '${jsonText}')`);
251
+ case 'postgres':
252
+ case 'cockroachdb':
253
+ return (0, operators_1.literal)(`${columnRef} @> '${jsonText}'::jsonb`);
254
+ case 'sqlite':
255
+ // SQLite has no jsonb-style containment operator; the dialect's own
256
+ // buildJsonContains() falls back to whole-document equality.
257
+ return (0, operators_1.literal)(`${columnRef} = '${jsonText}'`);
258
+ case 'mssql':
259
+ case 'oracle':
260
+ case 'snowflake':
261
+ case 'redshift':
262
+ case 'db2':
263
+ case 'clickhouse':
264
+ throw new Error(`jsonContains: not supported for dialect '${dialect}' - this dialect has no native JSON containment predicate (only key existence / exact path equality), so a correct containment query cannot be generated here.`);
265
+ default:
266
+ throw new Error(`jsonContains: unsupported dialect '${dialect}'`);
267
+ }
268
+ }
269
+ // ---------------------------------------------------------------------------
270
+ // jsonHasKey
271
+ // ---------------------------------------------------------------------------
272
+ /**
273
+ * Does the JSON object in `expr` have the given top-level (or path-qualified,
274
+ * dotted) key?
275
+ *
276
+ * - mysql/mariadb: `JSON_CONTAINS_PATH(col, 'one', '$.key')` (matches
277
+ * `buildJsonHasKey` in `src/dialects/{mysql,mariadb}/index.ts`).
278
+ * - postgres/cockroachdb: native `?` key-existence operator -> `col ? 'key'`
279
+ * (top-level keys only, matching jsonb semantics).
280
+ * - sqlite: `json_extract(col, '$.key') IS NOT NULL` (matches
281
+ * `buildJsonHasKey` in `src/dialects/sqlite/index.ts`).
282
+ * - mssql: `JSON_VALUE(col, '$.key') IS NOT NULL` (standard SQL Server
283
+ * workaround pattern; note this cannot distinguish "key present with a
284
+ * JSON null value" from "key absent").
285
+ * - oracle: `JSON_EXISTS(col, '$.key')`.
286
+ * - snowflake: `ARRAY_CONTAINS('key'::VARIANT, OBJECT_KEYS(col))`.
287
+ * - redshift: SUPER dot-navigation returns SQL NULL for missing attributes,
288
+ * so `col.key IS NOT NULL` reliably detects key presence.
289
+ * - db2: `JSON_EXISTS(col, '$.key')` (Db2 11.5+ JSON path predicates).
290
+ * - clickhouse: `JSONHas(col, 'key')`.
291
+ */
292
+ function jsonHasKey(dialect, expr, key) {
293
+ const columnRef = toSqlFragment(dialect, expr);
294
+ const segments = normalizePathSegments(key);
295
+ switch (dialect) {
296
+ case 'mysql':
297
+ case 'mariadb': {
298
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
299
+ return (0, operators_1.literal)(`JSON_CONTAINS_PATH(${columnRef}, 'one', '${dollarPath}')`);
300
+ }
301
+ case 'postgres':
302
+ case 'cockroachdb': {
303
+ if (segments.length !== 1) {
304
+ throw new Error(`jsonHasKey: not supported for dialect '${dialect}' with a nested/dotted key ('${key}') - the '?' key-existence operator only tests top-level keys.`);
305
+ }
306
+ return (0, operators_1.literal)(`${columnRef} ? '${escapeStringLiteral(dialect, segments[0])}'`);
307
+ }
308
+ case 'sqlite': {
309
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
310
+ return (0, operators_1.literal)(`json_extract(${columnRef}, '${dollarPath}') IS NOT NULL`);
311
+ }
312
+ case 'mssql': {
313
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
314
+ return (0, operators_1.literal)(`JSON_VALUE(${columnRef}, '${dollarPath}') IS NOT NULL`);
315
+ }
316
+ case 'oracle':
317
+ case 'db2': {
318
+ const dollarPath = escapeStringLiteral(dialect, buildDollarPath(segments));
319
+ return (0, operators_1.literal)(`JSON_EXISTS(${columnRef}, '${dollarPath}')`);
320
+ }
321
+ case 'snowflake': {
322
+ if (segments.length !== 1) {
323
+ throw new Error(`jsonHasKey: not supported for dialect '${dialect}' with a nested/dotted key ('${key}') - OBJECT_KEYS() only enumerates the top-level keys of a VARIANT/OBJECT.`);
324
+ }
325
+ return (0, operators_1.literal)(`ARRAY_CONTAINS('${escapeStringLiteral(dialect, segments[0])}'::VARIANT, OBJECT_KEYS(${columnRef}))`);
326
+ }
327
+ case 'redshift': {
328
+ const dotPath = buildDotPath(segments);
329
+ return (0, operators_1.literal)(`${columnRef}.${dotPath} IS NOT NULL`);
330
+ }
331
+ case 'clickhouse': {
332
+ const args = [columnRef, ...segments.map((seg) => (isArrayIndexSegment(seg) ? seg : `'${escapeStringLiteral(dialect, seg)}'`))].join(', ');
333
+ return (0, operators_1.literal)(`JSONHas(${args})`);
334
+ }
335
+ default:
336
+ throw new Error(`jsonHasKey: unsupported dialect '${dialect}'`);
337
+ }
338
+ }
339
+ // ---------------------------------------------------------------------------
340
+ // jsonKeys
341
+ // ---------------------------------------------------------------------------
342
+ /**
343
+ * Get the list of top-level keys of a JSON object.
344
+ *
345
+ * - mysql/mariadb: `JSON_KEYS(col)` -> native, returns a JSON array of keys.
346
+ * - postgres/cockroachdb: `ARRAY(SELECT jsonb_object_keys(col))` -> a SQL
347
+ * text array of keys.
348
+ * - sqlite: `(SELECT json_group_array(key) FROM json_each(col))` -> a JSON
349
+ * array of keys, built from SQLite's own `json_each` table-valued function.
350
+ * - snowflake: `OBJECT_KEYS(col)` -> native, returns an ARRAY of keys.
351
+ * - clickhouse: `JSONExtractKeys(col)` -> native, returns an Array(String).
352
+ * - mssql: no native function returns a JSON/array value of keys inline;
353
+ * `OPENJSON` requires a derived table, so the closest inline expression is
354
+ * a scalar subquery producing a comma-separated string (NOT a JSON array):
355
+ * `(SELECT STRING_AGG([key], ',') FROM OPENJSON(col))`.
356
+ * - oracle, redshift, db2: throw "not supported" - none of these dialects
357
+ * expose a documented function/operator that enumerates JSON object keys
358
+ * as a value usable inline in a SELECT list, so faking one with a fragile
359
+ * workaround would be worse than a clear error.
360
+ */
361
+ function jsonKeys(dialect, expr) {
362
+ const columnRef = toSqlFragment(dialect, expr);
363
+ switch (dialect) {
364
+ case 'mysql':
365
+ case 'mariadb':
366
+ return (0, operators_1.literal)(`JSON_KEYS(${columnRef})`);
367
+ case 'postgres':
368
+ case 'cockroachdb':
369
+ return (0, operators_1.literal)(`ARRAY(SELECT jsonb_object_keys(${columnRef}))`);
370
+ case 'sqlite':
371
+ return (0, operators_1.literal)(`(SELECT json_group_array(key) FROM json_each(${columnRef}))`);
372
+ case 'snowflake':
373
+ return (0, operators_1.literal)(`OBJECT_KEYS(${columnRef})`);
374
+ case 'clickhouse':
375
+ return (0, operators_1.literal)(`JSONExtractKeys(${columnRef})`);
376
+ case 'mssql':
377
+ // Note: returns a comma-separated string of keys, not a JSON array,
378
+ // since T-SQL has no scalar function that produces one directly.
379
+ return (0, operators_1.literal)(`(SELECT STRING_AGG(CAST([key] AS NVARCHAR(MAX)), ',') FROM OPENJSON(${columnRef}))`);
380
+ case 'oracle':
381
+ case 'redshift':
382
+ case 'db2':
383
+ throw new Error(`jsonKeys: not supported for dialect '${dialect}' - no documented function/operator enumerates JSON object keys as an inline SELECT-list expression for this dialect.`);
384
+ default:
385
+ throw new Error(`jsonKeys: unsupported dialect '${dialect}'`);
386
+ }
387
+ }
388
+ // ---------------------------------------------------------------------------
389
+ // jsonTypeOf
390
+ // ---------------------------------------------------------------------------
391
+ /**
392
+ * Get the JSON value's type (object/array/string/number/boolean/null/...).
393
+ *
394
+ * - mysql/mariadb: `JSON_TYPE(col)` -> native.
395
+ * - postgres/cockroachdb: `jsonb_typeof(col)` -> native.
396
+ * - sqlite: `json_type(col)` -> native.
397
+ * - snowflake: `TYPEOF(col)` -> native (works on VARIANT).
398
+ * - clickhouse: `JSONType(col)` -> native.
399
+ * - mssql, oracle, redshift, db2: throw "not supported" - none of these
400
+ * expose a documented function that returns the JSON value's type as a
401
+ * string (SQL Server's `ISJSON(col, 'object'|'array')` only returns a
402
+ * boolean for two of the possible types, not a general type name).
403
+ */
404
+ function jsonTypeOf(dialect, expr) {
405
+ const columnRef = toSqlFragment(dialect, expr);
406
+ switch (dialect) {
407
+ case 'mysql':
408
+ case 'mariadb':
409
+ return (0, operators_1.literal)(`JSON_TYPE(${columnRef})`);
410
+ case 'postgres':
411
+ case 'cockroachdb':
412
+ return (0, operators_1.literal)(`jsonb_typeof(${columnRef})`);
413
+ case 'sqlite':
414
+ return (0, operators_1.literal)(`json_type(${columnRef})`);
415
+ case 'snowflake':
416
+ return (0, operators_1.literal)(`TYPEOF(${columnRef})`);
417
+ case 'clickhouse':
418
+ return (0, operators_1.literal)(`JSONType(${columnRef})`);
419
+ case 'mssql':
420
+ case 'oracle':
421
+ case 'redshift':
422
+ case 'db2':
423
+ throw new Error(`jsonTypeOf: not supported for dialect '${dialect}' - no documented function returns a general JSON value type name for this dialect.`);
424
+ default:
425
+ throw new Error(`jsonTypeOf: unsupported dialect '${dialect}'`);
426
+ }
427
+ }