@warlock.js/cascade 4.0.92 → 4.0.93

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 (269) hide show
  1. package/cjs/contracts/database-driver.contract.d.ts +118 -0
  2. package/cjs/contracts/database-driver.contract.d.ts.map +1 -1
  3. package/cjs/contracts/migration-driver.contract.d.ts +14 -0
  4. package/cjs/contracts/migration-driver.contract.d.ts.map +1 -1
  5. package/cjs/contracts/query-builder.contract.d.ts +410 -1
  6. package/cjs/contracts/query-builder.contract.d.ts.map +1 -1
  7. package/cjs/data-source/data-source-registry.d.ts +4 -0
  8. package/cjs/data-source/data-source-registry.d.ts.map +1 -1
  9. package/cjs/data-source/data-source-registry.js +7 -0
  10. package/cjs/data-source/data-source-registry.js.map +1 -1
  11. package/cjs/drivers/mongodb/mongodb-blueprint.d.ts.map +1 -0
  12. package/cjs/drivers/mongodb/mongodb-blueprint.js.map +1 -0
  13. package/{esm/drivers/mongo → cjs/drivers/mongodb}/mongodb-driver.d.ts +49 -0
  14. package/cjs/drivers/mongodb/mongodb-driver.d.ts.map +1 -0
  15. package/cjs/drivers/{mongo → mongodb}/mongodb-driver.js +125 -8
  16. package/cjs/drivers/mongodb/mongodb-driver.js.map +1 -0
  17. package/cjs/drivers/{mongo/mongo-id-generator.d.ts → mongodb/mongodb-id-generator.d.ts} +1 -1
  18. package/cjs/drivers/mongodb/mongodb-id-generator.d.ts.map +1 -0
  19. package/cjs/drivers/{mongo/mongo-id-generator.js → mongodb/mongodb-id-generator.js} +1 -1
  20. package/cjs/drivers/mongodb/mongodb-id-generator.js.map +1 -0
  21. package/cjs/drivers/{mongo/mongo-migration-driver.d.ts → mongodb/mongodb-migration-driver.d.ts} +10 -1
  22. package/cjs/drivers/mongodb/mongodb-migration-driver.d.ts.map +1 -0
  23. package/cjs/drivers/{mongo/mongo-migration-driver.js → mongodb/mongodb-migration-driver.js} +18 -1
  24. package/cjs/drivers/mongodb/mongodb-migration-driver.js.map +1 -0
  25. package/cjs/drivers/{mongo/mongo-query-builder.d.ts → mongodb/mongodb-query-builder.d.ts} +172 -4
  26. package/cjs/drivers/mongodb/mongodb-query-builder.d.ts.map +1 -0
  27. package/cjs/drivers/{mongo/mongo-query-builder.js → mongodb/mongodb-query-builder.js} +220 -14
  28. package/cjs/drivers/mongodb/mongodb-query-builder.js.map +1 -0
  29. package/{esm/drivers/mongo/mongo-query-operations.d.ts → cjs/drivers/mongodb/mongodb-query-operations.d.ts} +16 -16
  30. package/cjs/drivers/mongodb/mongodb-query-operations.d.ts.map +1 -0
  31. package/cjs/drivers/{mongo/mongo-query-operations.js → mongodb/mongodb-query-operations.js} +22 -22
  32. package/cjs/drivers/mongodb/mongodb-query-operations.js.map +1 -0
  33. package/cjs/drivers/{mongo/mongo-query-parser.d.ts → mongodb/mongodb-query-parser.d.ts} +2 -2
  34. package/cjs/drivers/mongodb/mongodb-query-parser.d.ts.map +1 -0
  35. package/cjs/drivers/{mongo/mongo-query-parser.js → mongodb/mongodb-query-parser.js} +87 -87
  36. package/cjs/drivers/mongodb/mongodb-query-parser.js.map +1 -0
  37. package/cjs/drivers/{mongo/mongo-sync-adapter.d.ts → mongodb/mongodb-sync-adapter.d.ts} +2 -2
  38. package/cjs/drivers/mongodb/mongodb-sync-adapter.d.ts.map +1 -0
  39. package/cjs/drivers/{mongo/mongo-sync-adapter.js → mongodb/mongodb-sync-adapter.js} +2 -2
  40. package/cjs/drivers/mongodb/mongodb-sync-adapter.js.map +1 -0
  41. package/{esm/drivers/mongo → cjs/drivers/mongodb}/types.d.ts +2 -2
  42. package/cjs/drivers/mongodb/types.d.ts.map +1 -0
  43. package/cjs/drivers/postgres/index.d.ts +16 -0
  44. package/cjs/drivers/postgres/index.d.ts.map +1 -0
  45. package/cjs/drivers/postgres/postgres-blueprint.d.ts +64 -0
  46. package/cjs/drivers/postgres/postgres-blueprint.d.ts.map +1 -0
  47. package/cjs/drivers/postgres/postgres-blueprint.js +121 -0
  48. package/cjs/drivers/postgres/postgres-blueprint.js.map +1 -0
  49. package/cjs/drivers/postgres/postgres-dialect.d.ts +135 -0
  50. package/cjs/drivers/postgres/postgres-dialect.d.ts.map +1 -0
  51. package/cjs/drivers/postgres/postgres-dialect.js +245 -0
  52. package/cjs/drivers/postgres/postgres-dialect.js.map +1 -0
  53. package/cjs/drivers/postgres/postgres-driver.d.ts +360 -0
  54. package/cjs/drivers/postgres/postgres-driver.d.ts.map +1 -0
  55. package/cjs/drivers/postgres/postgres-driver.js +763 -0
  56. package/cjs/drivers/postgres/postgres-driver.js.map +1 -0
  57. package/cjs/drivers/postgres/postgres-migration-driver.d.ts +297 -0
  58. package/cjs/drivers/postgres/postgres-migration-driver.d.ts.map +1 -0
  59. package/cjs/drivers/postgres/postgres-migration-driver.js +578 -0
  60. package/cjs/drivers/postgres/postgres-migration-driver.js.map +1 -0
  61. package/cjs/drivers/postgres/postgres-query-builder.d.ts +824 -0
  62. package/cjs/drivers/postgres/postgres-query-builder.d.ts.map +1 -0
  63. package/cjs/drivers/postgres/postgres-query-builder.js +1800 -0
  64. package/cjs/drivers/postgres/postgres-query-builder.js.map +1 -0
  65. package/cjs/drivers/postgres/postgres-query-parser.d.ts +308 -0
  66. package/cjs/drivers/postgres/postgres-query-parser.d.ts.map +1 -0
  67. package/cjs/drivers/postgres/postgres-query-parser.js +706 -0
  68. package/cjs/drivers/postgres/postgres-query-parser.js.map +1 -0
  69. package/cjs/drivers/postgres/postgres-sync-adapter.d.ts +83 -0
  70. package/cjs/drivers/postgres/postgres-sync-adapter.d.ts.map +1 -0
  71. package/cjs/drivers/postgres/postgres-sync-adapter.js +197 -0
  72. package/cjs/drivers/postgres/postgres-sync-adapter.js.map +1 -0
  73. package/cjs/drivers/postgres/types.d.ts +142 -0
  74. package/cjs/drivers/postgres/types.d.ts.map +1 -0
  75. package/cjs/drivers/sql/index.d.ts +10 -0
  76. package/cjs/drivers/sql/index.d.ts.map +1 -0
  77. package/cjs/drivers/sql/sql-dialect.contract.d.ts +203 -0
  78. package/cjs/drivers/sql/sql-dialect.contract.d.ts.map +1 -0
  79. package/cjs/drivers/sql/sql-types.d.ts +202 -0
  80. package/cjs/drivers/sql/sql-types.d.ts.map +1 -0
  81. package/cjs/index.d.ts +9 -6
  82. package/cjs/index.d.ts.map +1 -1
  83. package/cjs/index.js +1 -1
  84. package/cjs/migration/migration-runner.d.ts.map +1 -1
  85. package/cjs/migration/migration-runner.js +3 -0
  86. package/cjs/migration/migration-runner.js.map +1 -1
  87. package/cjs/model/model.d.ts +236 -1
  88. package/cjs/model/model.d.ts.map +1 -1
  89. package/cjs/model/model.js +203 -4
  90. package/cjs/model/model.js.map +1 -1
  91. package/cjs/relations/helpers.d.ts +156 -0
  92. package/cjs/relations/helpers.d.ts.map +1 -0
  93. package/cjs/relations/helpers.js +197 -0
  94. package/cjs/relations/helpers.js.map +1 -0
  95. package/cjs/relations/index.d.ts +33 -0
  96. package/cjs/relations/index.d.ts.map +1 -0
  97. package/cjs/relations/pivot-operations.d.ts +160 -0
  98. package/cjs/relations/pivot-operations.d.ts.map +1 -0
  99. package/cjs/relations/pivot-operations.js +293 -0
  100. package/cjs/relations/pivot-operations.js.map +1 -0
  101. package/cjs/relations/relation-loader.d.ts +194 -0
  102. package/cjs/relations/relation-loader.d.ts.map +1 -0
  103. package/cjs/relations/relation-loader.js +466 -0
  104. package/cjs/relations/relation-loader.js.map +1 -0
  105. package/cjs/relations/types.d.ts +280 -0
  106. package/cjs/relations/types.d.ts.map +1 -0
  107. package/cjs/sync/model-sync-operation.js +1 -1
  108. package/cjs/sync/model-sync-operation.js.map +1 -1
  109. package/cjs/utils/connect-to-database.d.ts.map +1 -1
  110. package/cjs/utils/connect-to-database.js +15 -3
  111. package/cjs/utils/connect-to-database.js.map +1 -1
  112. package/cjs/utils/define-model.d.ts +51 -29
  113. package/cjs/utils/define-model.d.ts.map +1 -1
  114. package/cjs/validation/rules/database-model-rule.js +1 -1
  115. package/cjs/validation/rules/database-model-rule.js.map +1 -1
  116. package/esm/contracts/database-driver.contract.d.ts +118 -0
  117. package/esm/contracts/database-driver.contract.d.ts.map +1 -1
  118. package/esm/contracts/migration-driver.contract.d.ts +14 -0
  119. package/esm/contracts/migration-driver.contract.d.ts.map +1 -1
  120. package/esm/contracts/query-builder.contract.d.ts +410 -1
  121. package/esm/contracts/query-builder.contract.d.ts.map +1 -1
  122. package/esm/data-source/data-source-registry.d.ts +4 -0
  123. package/esm/data-source/data-source-registry.d.ts.map +1 -1
  124. package/esm/data-source/data-source-registry.js +7 -0
  125. package/esm/data-source/data-source-registry.js.map +1 -1
  126. package/esm/drivers/mongodb/mongodb-blueprint.d.ts.map +1 -0
  127. package/esm/drivers/mongodb/mongodb-blueprint.js.map +1 -0
  128. package/{cjs/drivers/mongo → esm/drivers/mongodb}/mongodb-driver.d.ts +49 -0
  129. package/esm/drivers/mongodb/mongodb-driver.d.ts.map +1 -0
  130. package/esm/drivers/{mongo → mongodb}/mongodb-driver.js +121 -4
  131. package/esm/drivers/mongodb/mongodb-driver.js.map +1 -0
  132. package/esm/drivers/{mongo/mongo-id-generator.d.ts → mongodb/mongodb-id-generator.d.ts} +1 -1
  133. package/esm/drivers/mongodb/mongodb-id-generator.d.ts.map +1 -0
  134. package/esm/drivers/{mongo/mongo-id-generator.js → mongodb/mongodb-id-generator.js} +1 -1
  135. package/esm/drivers/mongodb/mongodb-id-generator.js.map +1 -0
  136. package/esm/drivers/{mongo/mongo-migration-driver.d.ts → mongodb/mongodb-migration-driver.d.ts} +10 -1
  137. package/esm/drivers/mongodb/mongodb-migration-driver.d.ts.map +1 -0
  138. package/esm/drivers/{mongo/mongo-migration-driver.js → mongodb/mongodb-migration-driver.js} +18 -1
  139. package/esm/drivers/mongodb/mongodb-migration-driver.js.map +1 -0
  140. package/esm/drivers/{mongo/mongo-query-builder.d.ts → mongodb/mongodb-query-builder.d.ts} +172 -4
  141. package/esm/drivers/mongodb/mongodb-query-builder.d.ts.map +1 -0
  142. package/esm/drivers/{mongo/mongo-query-builder.js → mongodb/mongodb-query-builder.js} +218 -12
  143. package/esm/drivers/mongodb/mongodb-query-builder.js.map +1 -0
  144. package/{cjs/drivers/mongo/mongo-query-operations.d.ts → esm/drivers/mongodb/mongodb-query-operations.d.ts} +16 -16
  145. package/esm/drivers/mongodb/mongodb-query-operations.d.ts.map +1 -0
  146. package/esm/drivers/{mongo/mongo-query-operations.js → mongodb/mongodb-query-operations.js} +22 -22
  147. package/esm/drivers/mongodb/mongodb-query-operations.js.map +1 -0
  148. package/esm/drivers/{mongo/mongo-query-parser.d.ts → mongodb/mongodb-query-parser.d.ts} +2 -2
  149. package/esm/drivers/mongodb/mongodb-query-parser.d.ts.map +1 -0
  150. package/esm/drivers/{mongo/mongo-query-parser.js → mongodb/mongodb-query-parser.js} +87 -87
  151. package/esm/drivers/mongodb/mongodb-query-parser.js.map +1 -0
  152. package/esm/drivers/{mongo/mongo-sync-adapter.d.ts → mongodb/mongodb-sync-adapter.d.ts} +2 -2
  153. package/esm/drivers/mongodb/mongodb-sync-adapter.d.ts.map +1 -0
  154. package/esm/drivers/{mongo/mongo-sync-adapter.js → mongodb/mongodb-sync-adapter.js} +2 -2
  155. package/esm/drivers/mongodb/mongodb-sync-adapter.js.map +1 -0
  156. package/{cjs/drivers/mongo → esm/drivers/mongodb}/types.d.ts +2 -2
  157. package/esm/drivers/mongodb/types.d.ts.map +1 -0
  158. package/esm/drivers/postgres/index.d.ts +16 -0
  159. package/esm/drivers/postgres/index.d.ts.map +1 -0
  160. package/esm/drivers/postgres/postgres-blueprint.d.ts +64 -0
  161. package/esm/drivers/postgres/postgres-blueprint.d.ts.map +1 -0
  162. package/esm/drivers/postgres/postgres-blueprint.js +121 -0
  163. package/esm/drivers/postgres/postgres-blueprint.js.map +1 -0
  164. package/esm/drivers/postgres/postgres-dialect.d.ts +135 -0
  165. package/esm/drivers/postgres/postgres-dialect.d.ts.map +1 -0
  166. package/esm/drivers/postgres/postgres-dialect.js +245 -0
  167. package/esm/drivers/postgres/postgres-dialect.js.map +1 -0
  168. package/esm/drivers/postgres/postgres-driver.d.ts +360 -0
  169. package/esm/drivers/postgres/postgres-driver.d.ts.map +1 -0
  170. package/esm/drivers/postgres/postgres-driver.js +763 -0
  171. package/esm/drivers/postgres/postgres-driver.js.map +1 -0
  172. package/esm/drivers/postgres/postgres-migration-driver.d.ts +297 -0
  173. package/esm/drivers/postgres/postgres-migration-driver.d.ts.map +1 -0
  174. package/esm/drivers/postgres/postgres-migration-driver.js +578 -0
  175. package/esm/drivers/postgres/postgres-migration-driver.js.map +1 -0
  176. package/esm/drivers/postgres/postgres-query-builder.d.ts +824 -0
  177. package/esm/drivers/postgres/postgres-query-builder.d.ts.map +1 -0
  178. package/esm/drivers/postgres/postgres-query-builder.js +1800 -0
  179. package/esm/drivers/postgres/postgres-query-builder.js.map +1 -0
  180. package/esm/drivers/postgres/postgres-query-parser.d.ts +308 -0
  181. package/esm/drivers/postgres/postgres-query-parser.d.ts.map +1 -0
  182. package/esm/drivers/postgres/postgres-query-parser.js +706 -0
  183. package/esm/drivers/postgres/postgres-query-parser.js.map +1 -0
  184. package/esm/drivers/postgres/postgres-sync-adapter.d.ts +83 -0
  185. package/esm/drivers/postgres/postgres-sync-adapter.d.ts.map +1 -0
  186. package/esm/drivers/postgres/postgres-sync-adapter.js +197 -0
  187. package/esm/drivers/postgres/postgres-sync-adapter.js.map +1 -0
  188. package/esm/drivers/postgres/types.d.ts +142 -0
  189. package/esm/drivers/postgres/types.d.ts.map +1 -0
  190. package/esm/drivers/sql/index.d.ts +10 -0
  191. package/esm/drivers/sql/index.d.ts.map +1 -0
  192. package/esm/drivers/sql/sql-dialect.contract.d.ts +203 -0
  193. package/esm/drivers/sql/sql-dialect.contract.d.ts.map +1 -0
  194. package/esm/drivers/sql/sql-types.d.ts +202 -0
  195. package/esm/drivers/sql/sql-types.d.ts.map +1 -0
  196. package/esm/index.d.ts +9 -6
  197. package/esm/index.d.ts.map +1 -1
  198. package/esm/index.js +1 -1
  199. package/esm/migration/migration-runner.d.ts.map +1 -1
  200. package/esm/migration/migration-runner.js +3 -0
  201. package/esm/migration/migration-runner.js.map +1 -1
  202. package/esm/model/model.d.ts +236 -1
  203. package/esm/model/model.d.ts.map +1 -1
  204. package/esm/model/model.js +203 -4
  205. package/esm/model/model.js.map +1 -1
  206. package/esm/relations/helpers.d.ts +156 -0
  207. package/esm/relations/helpers.d.ts.map +1 -0
  208. package/esm/relations/helpers.js +197 -0
  209. package/esm/relations/helpers.js.map +1 -0
  210. package/esm/relations/index.d.ts +33 -0
  211. package/esm/relations/index.d.ts.map +1 -0
  212. package/esm/relations/pivot-operations.d.ts +160 -0
  213. package/esm/relations/pivot-operations.d.ts.map +1 -0
  214. package/esm/relations/pivot-operations.js +293 -0
  215. package/esm/relations/pivot-operations.js.map +1 -0
  216. package/esm/relations/relation-loader.d.ts +194 -0
  217. package/esm/relations/relation-loader.d.ts.map +1 -0
  218. package/esm/relations/relation-loader.js +466 -0
  219. package/esm/relations/relation-loader.js.map +1 -0
  220. package/esm/relations/types.d.ts +280 -0
  221. package/esm/relations/types.d.ts.map +1 -0
  222. package/esm/sync/model-sync-operation.js +1 -1
  223. package/esm/sync/model-sync-operation.js.map +1 -1
  224. package/esm/utils/connect-to-database.d.ts.map +1 -1
  225. package/esm/utils/connect-to-database.js +15 -3
  226. package/esm/utils/connect-to-database.js.map +1 -1
  227. package/esm/utils/define-model.d.ts +51 -29
  228. package/esm/utils/define-model.d.ts.map +1 -1
  229. package/esm/validation/rules/database-model-rule.js +1 -1
  230. package/esm/validation/rules/database-model-rule.js.map +1 -1
  231. package/package.json +4 -4
  232. package/cjs/drivers/mongo/mongo-id-generator.d.ts.map +0 -1
  233. package/cjs/drivers/mongo/mongo-id-generator.js.map +0 -1
  234. package/cjs/drivers/mongo/mongo-migration-driver.d.ts.map +0 -1
  235. package/cjs/drivers/mongo/mongo-migration-driver.js.map +0 -1
  236. package/cjs/drivers/mongo/mongo-query-builder.d.ts.map +0 -1
  237. package/cjs/drivers/mongo/mongo-query-builder.js.map +0 -1
  238. package/cjs/drivers/mongo/mongo-query-operations.d.ts.map +0 -1
  239. package/cjs/drivers/mongo/mongo-query-operations.js.map +0 -1
  240. package/cjs/drivers/mongo/mongo-query-parser.d.ts.map +0 -1
  241. package/cjs/drivers/mongo/mongo-query-parser.js.map +0 -1
  242. package/cjs/drivers/mongo/mongo-sync-adapter.d.ts.map +0 -1
  243. package/cjs/drivers/mongo/mongo-sync-adapter.js.map +0 -1
  244. package/cjs/drivers/mongo/mongodb-blueprint.d.ts.map +0 -1
  245. package/cjs/drivers/mongo/mongodb-blueprint.js.map +0 -1
  246. package/cjs/drivers/mongo/mongodb-driver.d.ts.map +0 -1
  247. package/cjs/drivers/mongo/mongodb-driver.js.map +0 -1
  248. package/cjs/drivers/mongo/types.d.ts.map +0 -1
  249. package/esm/drivers/mongo/mongo-id-generator.d.ts.map +0 -1
  250. package/esm/drivers/mongo/mongo-id-generator.js.map +0 -1
  251. package/esm/drivers/mongo/mongo-migration-driver.d.ts.map +0 -1
  252. package/esm/drivers/mongo/mongo-migration-driver.js.map +0 -1
  253. package/esm/drivers/mongo/mongo-query-builder.d.ts.map +0 -1
  254. package/esm/drivers/mongo/mongo-query-builder.js.map +0 -1
  255. package/esm/drivers/mongo/mongo-query-operations.d.ts.map +0 -1
  256. package/esm/drivers/mongo/mongo-query-operations.js.map +0 -1
  257. package/esm/drivers/mongo/mongo-query-parser.d.ts.map +0 -1
  258. package/esm/drivers/mongo/mongo-query-parser.js.map +0 -1
  259. package/esm/drivers/mongo/mongo-sync-adapter.d.ts.map +0 -1
  260. package/esm/drivers/mongo/mongo-sync-adapter.js.map +0 -1
  261. package/esm/drivers/mongo/mongodb-blueprint.d.ts.map +0 -1
  262. package/esm/drivers/mongo/mongodb-blueprint.js.map +0 -1
  263. package/esm/drivers/mongo/mongodb-driver.d.ts.map +0 -1
  264. package/esm/drivers/mongo/mongodb-driver.js.map +0 -1
  265. package/esm/drivers/mongo/types.d.ts.map +0 -1
  266. /package/cjs/drivers/{mongo → mongodb}/mongodb-blueprint.d.ts +0 -0
  267. /package/cjs/drivers/{mongo → mongodb}/mongodb-blueprint.js +0 -0
  268. /package/esm/drivers/{mongo → mongodb}/mongodb-blueprint.d.ts +0 -0
  269. /package/esm/drivers/{mongo → mongodb}/mongodb-blueprint.js +0 -0
@@ -0,0 +1,706 @@
1
+ import {PostgresDialect}from'./postgres-dialect.js';/**
2
+ * PostgreSQL Query Parser
3
+ *
4
+ * Translates Cascade query operations into PostgreSQL SQL queries.
5
+ * Mirrors the MongoQueryParser pattern but generates SQL instead
6
+ * of MongoDB aggregation pipelines.
7
+ *
8
+ * @module cascade/drivers/postgres
9
+ */
10
+ /**
11
+ * PostgreSQL Query Parser.
12
+ *
13
+ * Converts a list of query operations into a SQL query string with parameters.
14
+ * Handles SELECT, WHERE, JOIN, ORDER BY, GROUP BY, LIMIT/OFFSET clauses.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const parser = new PostgresQueryParser({
19
+ * table: 'users',
20
+ * operations: [
21
+ * { type: 'where', data: { field: 'name', operator: '=', value: 'Alice' } },
22
+ * { type: 'orderBy', data: { field: 'createdAt', direction: 'desc' } },
23
+ * { type: 'limit', data: { value: 10 } }
24
+ * ]
25
+ * });
26
+ *
27
+ * const { sql, params } = parser.parse();
28
+ * // sql: 'SELECT * FROM "users" WHERE "name" = $1 ORDER BY "createdAt" DESC LIMIT 10'
29
+ * // params: ['Alice']
30
+ * ```
31
+ */
32
+ class PostgresQueryParser {
33
+ /**
34
+ * Target table name.
35
+ */
36
+ table;
37
+ /**
38
+ * Table alias.
39
+ */
40
+ alias;
41
+ /**
42
+ * Operations to process.
43
+ */
44
+ operations;
45
+ /**
46
+ * SQL dialect for syntax.
47
+ */
48
+ dialect;
49
+ /**
50
+ * Current parameter index (1-based for PostgreSQL).
51
+ */
52
+ paramIndex = 1;
53
+ /**
54
+ * Collected parameters.
55
+ */
56
+ params = [];
57
+ /**
58
+ * SELECT columns.
59
+ */
60
+ selectColumns = [];
61
+ /**
62
+ * Deselected (excluded) columns.
63
+ */
64
+ deselectColumns = [];
65
+ /**
66
+ * Raw SELECT expressions.
67
+ */
68
+ selectRaw = [];
69
+ /**
70
+ * WHERE clauses.
71
+ */
72
+ whereClauses = [];
73
+ /**
74
+ * JOIN clauses.
75
+ */
76
+ joinClauses = [];
77
+ /**
78
+ * ORDER BY clauses.
79
+ */
80
+ orderClauses = [];
81
+ /**
82
+ * GROUP BY columns.
83
+ */
84
+ groupColumns = [];
85
+ /**
86
+ * HAVING clauses.
87
+ */
88
+ havingClauses = [];
89
+ /**
90
+ * LIMIT value.
91
+ */
92
+ limitValue;
93
+ /**
94
+ * OFFSET value.
95
+ */
96
+ offsetValue;
97
+ /**
98
+ * DISTINCT flag.
99
+ */
100
+ isDistinct = false;
101
+ /**
102
+ * Tracked joined tables (for table reference detection).
103
+ */
104
+ joinedTables = new Set();
105
+ /**
106
+ * Create a new query parser.
107
+ *
108
+ * @param options - Parser configuration
109
+ */
110
+ constructor(options) {
111
+ this.table = options.table;
112
+ this.alias = options.alias;
113
+ this.operations = options.operations;
114
+ this.dialect = options.dialect ?? new PostgresDialect();
115
+ }
116
+ /**
117
+ * Parse all operations and build the SQL query.
118
+ *
119
+ * @returns Object with SQL string and parameter values
120
+ */
121
+ parse() {
122
+ // Process each operation
123
+ for (const operation of this.operations) {
124
+ this.processOperation(operation);
125
+ }
126
+ // Build the final SQL query
127
+ const sql = this.buildSql();
128
+ return { sql, params: this.params };
129
+ }
130
+ /**
131
+ * Get a formatted string representation of the query.
132
+ *
133
+ * @returns Formatted SQL with parameters
134
+ */
135
+ toPrettyString() {
136
+ const { sql, params } = this.parse();
137
+ return `${sql}\n-- Parameters: ${JSON.stringify(params)}`;
138
+ }
139
+ /**
140
+ * Process a single operation.
141
+ *
142
+ * @param operation - The operation to process
143
+ */
144
+ processOperation(operation) {
145
+ const { type, data } = operation;
146
+ switch (type) {
147
+ // WHERE operations
148
+ case "where":
149
+ this.processWhere(data, "AND");
150
+ break;
151
+ case "orWhere":
152
+ this.processWhere(data, "OR");
153
+ break;
154
+ case "whereRaw":
155
+ this.processWhereRaw(data, "AND");
156
+ break;
157
+ case "orWhereRaw":
158
+ this.processWhereRaw(data, "OR");
159
+ break;
160
+ case "whereIn":
161
+ this.processWhereIn(data, false);
162
+ break;
163
+ case "whereNotIn":
164
+ this.processWhereIn(data, true);
165
+ break;
166
+ case "whereNull":
167
+ this.processWhereNull(data, false);
168
+ break;
169
+ case "whereNotNull":
170
+ this.processWhereNull(data, true);
171
+ break;
172
+ case "whereBetween":
173
+ this.processWhereBetween(data, false);
174
+ break;
175
+ case "whereNotBetween":
176
+ this.processWhereBetween(data, true);
177
+ break;
178
+ case "whereLike":
179
+ this.processWhereLike(data, false);
180
+ break;
181
+ case "whereNotLike":
182
+ this.processWhereLike(data, true);
183
+ break;
184
+ case "whereColumn":
185
+ this.processWhereColumn(data, "AND");
186
+ break;
187
+ case "orWhereColumn":
188
+ this.processWhereColumn(data, "OR");
189
+ break;
190
+ case "whereJsonContains":
191
+ this.processWhereJsonContains(data, false);
192
+ break;
193
+ case "whereJsonDoesntContain":
194
+ this.processWhereJsonContains(data, true);
195
+ break;
196
+ case "whereFullText":
197
+ this.processWhereFullText(data);
198
+ break;
199
+ // SELECT operations
200
+ case "select":
201
+ this.processSelect(data);
202
+ break;
203
+ case "selectRaw":
204
+ this.processSelectRaw(data);
205
+ break;
206
+ case "deselect":
207
+ this.processDeselect(data);
208
+ break;
209
+ // JOIN operations
210
+ case "join":
211
+ case "innerJoin":
212
+ this.processJoin(data, "INNER");
213
+ break;
214
+ case "leftJoin":
215
+ this.processJoin(data, "LEFT");
216
+ break;
217
+ case "rightJoin":
218
+ this.processJoin(data, "RIGHT");
219
+ break;
220
+ case "fullJoin":
221
+ this.processJoin(data, "FULL OUTER");
222
+ break;
223
+ case "crossJoin":
224
+ this.processCrossJoin(data);
225
+ break;
226
+ case "joinRaw":
227
+ this.processJoinRaw(data);
228
+ break;
229
+ // ORDER operations
230
+ case "orderBy":
231
+ this.processOrderBy(data);
232
+ break;
233
+ case "orderByRaw":
234
+ this.processOrderByRaw(data);
235
+ break;
236
+ // GROUP operations
237
+ case "groupBy":
238
+ this.processGroupBy(data);
239
+ break;
240
+ case "having":
241
+ this.processHaving(data);
242
+ break;
243
+ case "havingRaw":
244
+ this.processHavingRaw(data);
245
+ break;
246
+ // LIMIT operations
247
+ case "limit":
248
+ this.limitValue = data.value;
249
+ break;
250
+ case "offset":
251
+ this.offsetValue = data.value;
252
+ break;
253
+ // Other
254
+ case "distinct":
255
+ this.isDistinct = true;
256
+ break;
257
+ // joinWith select related columns
258
+ case "selectRelatedColumns":
259
+ this.processSelectRelatedColumns(data);
260
+ break;
261
+ }
262
+ }
263
+ /**
264
+ * Build the final SQL query from collected clauses.
265
+ *
266
+ * @returns Complete SQL query string
267
+ */
268
+ buildSql() {
269
+ const parts = [];
270
+ // SELECT clause
271
+ parts.push(this.buildSelectClause());
272
+ // FROM clause
273
+ const quotedTable = this.dialect.quoteIdentifier(this.table);
274
+ const fromClause = this.alias
275
+ ? `FROM ${quotedTable} AS ${this.dialect.quoteIdentifier(this.alias)}`
276
+ : `FROM ${quotedTable}`;
277
+ parts.push(fromClause);
278
+ // JOIN clauses
279
+ if (this.joinClauses.length > 0) {
280
+ parts.push(this.joinClauses.join(" "));
281
+ }
282
+ // WHERE clause
283
+ if (this.whereClauses.length > 0) {
284
+ parts.push(`WHERE ${this.whereClauses.join(" ")}`);
285
+ }
286
+ // GROUP BY clause
287
+ if (this.groupColumns.length > 0) {
288
+ const quotedCols = this.groupColumns.map((c) => this.dialect.quoteIdentifier(c));
289
+ parts.push(`GROUP BY ${quotedCols.join(", ")}`);
290
+ }
291
+ // HAVING clause
292
+ if (this.havingClauses.length > 0) {
293
+ parts.push(`HAVING ${this.havingClauses.join(" AND ")}`);
294
+ }
295
+ // ORDER BY clause
296
+ if (this.orderClauses.length > 0) {
297
+ parts.push(`ORDER BY ${this.orderClauses.join(", ")}`);
298
+ }
299
+ // LIMIT/OFFSET
300
+ const limitOffset = this.dialect.limitOffset(this.limitValue, this.offsetValue);
301
+ if (limitOffset) {
302
+ parts.push(limitOffset);
303
+ }
304
+ return parts.join(" ");
305
+ }
306
+ /**
307
+ * Build the SELECT clause.
308
+ *
309
+ * @returns SELECT clause string
310
+ */
311
+ buildSelectClause() {
312
+ const distinct = this.isDistinct ? "DISTINCT " : "";
313
+ // If no specific columns, select all
314
+ if (this.selectColumns.length === 0 && this.selectRaw.length === 0) {
315
+ // Handle deselect by explicitly listing columns (would need schema info)
316
+ // For now, just use *
317
+ return `SELECT ${distinct}*`;
318
+ }
319
+ const columns = [];
320
+ // Add selected columns
321
+ for (const col of this.selectColumns) {
322
+ if (!this.deselectColumns.includes(col)) {
323
+ columns.push(this.dialect.quoteIdentifier(col));
324
+ }
325
+ }
326
+ // Add raw expressions
327
+ columns.push(...this.selectRaw);
328
+ return `SELECT ${distinct}${columns.join(", ")}`;
329
+ }
330
+ /**
331
+ * Add a placeholder and parameter.
332
+ *
333
+ * @param value - Parameter value
334
+ * @returns Placeholder string ($1, $2, etc.)
335
+ */
336
+ addParam(value) {
337
+ this.params.push(value);
338
+ return this.dialect.placeholder(this.paramIndex++);
339
+ }
340
+ /**
341
+ * Process a basic WHERE operation.
342
+ */
343
+ processWhere(data, boolean) {
344
+ const field = data.field;
345
+ const operator = data.operator ?? "=";
346
+ const value = data.value;
347
+ const quotedField = this.dialect.quoteIdentifier(field);
348
+ const placeholder = this.addParam(value);
349
+ const clause = `${quotedField} ${this.mapOperator(operator)} ${placeholder}`;
350
+ this.addWhereClause(clause, boolean);
351
+ }
352
+ /**
353
+ * Process a raw WHERE operation.
354
+ */
355
+ processWhereRaw(data, boolean) {
356
+ const expression = data.expression;
357
+ const bindings = data.bindings ?? [];
358
+ // Replace ? placeholders with $n
359
+ let processed = expression;
360
+ for (const binding of bindings) {
361
+ processed = processed.replace("?", this.addParam(binding));
362
+ }
363
+ this.addWhereClause(processed, boolean);
364
+ }
365
+ /**
366
+ * Process WHERE IN / NOT IN.
367
+ */
368
+ processWhereIn(data, negate) {
369
+ const field = data.field;
370
+ const values = data.values;
371
+ const quotedField = this.dialect.quoteIdentifier(field);
372
+ const operator = negate ? "!= ALL" : "= ANY";
373
+ const placeholder = this.addParam(values);
374
+ this.addWhereClause(`${quotedField} ${operator}(${placeholder})`, "AND");
375
+ }
376
+ /**
377
+ * Process WHERE NULL / NOT NULL.
378
+ */
379
+ processWhereNull(data, negate) {
380
+ const field = data.field;
381
+ const quotedField = this.dialect.quoteIdentifier(field);
382
+ const clause = negate ? `${quotedField} IS NOT NULL` : `${quotedField} IS NULL`;
383
+ this.addWhereClause(clause, "AND");
384
+ }
385
+ /**
386
+ * Process WHERE BETWEEN / NOT BETWEEN.
387
+ */
388
+ processWhereBetween(data, negate) {
389
+ const field = data.field;
390
+ const range = data.range;
391
+ const quotedField = this.dialect.quoteIdentifier(field);
392
+ const placeholder1 = this.addParam(range[0]);
393
+ const placeholder2 = this.addParam(range[1]);
394
+ const keyword = negate ? "NOT BETWEEN" : "BETWEEN";
395
+ this.addWhereClause(`${quotedField} ${keyword} ${placeholder1} AND ${placeholder2}`, "AND");
396
+ }
397
+ /**
398
+ * Process WHERE LIKE / NOT LIKE.
399
+ */
400
+ processWhereLike(data, negate) {
401
+ const field = data.field;
402
+ const pattern = data.pattern;
403
+ const quotedField = this.dialect.quoteIdentifier(field);
404
+ const { operator } = this.dialect.likePattern(pattern, true);
405
+ const placeholder = this.addParam(pattern);
406
+ const keyword = negate ? `NOT ${operator}` : operator;
407
+ this.addWhereClause(`${quotedField} ${keyword} ${placeholder}`, "AND");
408
+ }
409
+ /**
410
+ * Process WHERE column comparison.
411
+ */
412
+ processWhereColumn(data, boolean) {
413
+ const first = data.first;
414
+ const operator = data.operator ?? "=";
415
+ const second = data.second;
416
+ const quotedFirst = this.dialect.quoteIdentifier(first);
417
+ const quotedSecond = this.dialect.quoteIdentifier(second);
418
+ this.addWhereClause(`${quotedFirst} ${operator} ${quotedSecond}`, boolean);
419
+ }
420
+ /**
421
+ * Process WHERE JSON contains.
422
+ */
423
+ processWhereJsonContains(data, negate) {
424
+ const path = data.path;
425
+ const value = data.value;
426
+ const quotedPath = this.dialect.quoteIdentifier(path);
427
+ const jsonValue = JSON.stringify(value);
428
+ const operator = negate ? "NOT @>" : "@>";
429
+ this.addWhereClause(`${quotedPath} ${operator} '${jsonValue}'::jsonb`, "AND");
430
+ }
431
+ /**
432
+ * Process full-text search WHERE.
433
+ */
434
+ processWhereFullText(data) {
435
+ const fields = data.fields;
436
+ const query = data.query;
437
+ // Build tsvector from fields
438
+ const tsVectors = fields
439
+ .map((f) => `to_tsvector('english', ${this.dialect.quoteIdentifier(f)})`)
440
+ .join(" || ");
441
+ const placeholder = this.addParam(query);
442
+ this.addWhereClause(`(${tsVectors}) @@ plainto_tsquery('english', ${placeholder})`, "AND");
443
+ }
444
+ /**
445
+ * Process SELECT operation.
446
+ */
447
+ processSelect(data) {
448
+ const fields = data.fields;
449
+ if (Array.isArray(fields)) {
450
+ this.selectColumns.push(...fields);
451
+ }
452
+ else {
453
+ // Handle aliases: { field: 'alias' }
454
+ for (const [field, alias] of Object.entries(fields)) {
455
+ const quotedField = this.dialect.quoteIdentifier(field);
456
+ const quotedAlias = this.dialect.quoteIdentifier(alias);
457
+ this.selectRaw.push(`${quotedField} AS ${quotedAlias}`);
458
+ }
459
+ }
460
+ }
461
+ /**
462
+ * Process raw SELECT expression.
463
+ */
464
+ processSelectRaw(data) {
465
+ const expression = data.expression;
466
+ if (typeof expression === "string") {
467
+ this.selectRaw.push(expression);
468
+ }
469
+ else {
470
+ // Handle object expressions (for compatibility)
471
+ for (const [alias, expr] of Object.entries(expression)) {
472
+ this.selectRaw.push(`${expr} AS ${this.dialect.quoteIdentifier(alias)}`);
473
+ }
474
+ }
475
+ }
476
+ /**
477
+ * Process DESELECT operation.
478
+ */
479
+ processDeselect(data) {
480
+ const fields = data.fields;
481
+ this.deselectColumns.push(...fields);
482
+ }
483
+ /**
484
+ * Process SELECT for related columns (joinWith).
485
+ * Uses row_to_json to package all related columns into a single JSON column.
486
+ * Also ensures main table columns are selected.
487
+ */
488
+ processSelectRelatedColumns(data) {
489
+ const alias = data.alias;
490
+ const quotedAlias = this.dialect.quoteIdentifier(alias);
491
+ const quotedTable = this.dialect.quoteIdentifier(this.table);
492
+ // Ensure main table columns are selected (only add once)
493
+ if (!this.selectRaw.includes(`${quotedTable}.*`)) {
494
+ this.selectRaw.unshift(`${quotedTable}.*`);
495
+ }
496
+ // Use row_to_json to get all columns from the joined table as a single JSON object
497
+ // The column will be named like "_rel_author" and contain { id, name, email, ... }
498
+ this.selectRaw.push(`row_to_json(${quotedAlias}.*) AS ${quotedAlias}`);
499
+ }
500
+ /**
501
+ * Process JOIN operation with smart field detection.
502
+ *
503
+ * Handles both regular columns and JSONB nested paths:
504
+ * - "id" → "table"."id" (auto-prefixed)
505
+ * - "users.id" → "users"."id" (explicit table)
506
+ * - "createdBy.id" → "table"."createdBy"->>'id' (JSONB path)
507
+ * - "posts.createdBy.id" → "posts"."createdBy"->>'id' (JSONB with table)
508
+ */
509
+ processJoin(data, type) {
510
+ const options = data;
511
+ const joinTable = "table" in options ? options.table : "";
512
+ const localField = "localField" in options ? options.localField : "";
513
+ const foreignField = "foreignField" in options ? options.foreignField : "";
514
+ const alias = "alias" in options ? options.alias : undefined;
515
+ const quotedTable = this.dialect.quoteIdentifier(joinTable);
516
+ const tableRef = alias
517
+ ? `${quotedTable} AS ${this.dialect.quoteIdentifier(alias)}`
518
+ : quotedTable;
519
+ const tableAlias = alias ?? joinTable;
520
+ // Track the joined table for reference detection
521
+ this.joinedTables.add(joinTable);
522
+ if (alias) {
523
+ this.joinedTables.add(alias);
524
+ }
525
+ // Parse local field (belongs to main table)
526
+ const quotedLocal = this.parseJoinField(localField, this.table, this.alias);
527
+ // Parse foreign field (belongs to join table)
528
+ const quotedForeign = this.parseJoinField(foreignField, joinTable, tableAlias);
529
+ this.joinClauses.push(`${type} JOIN ${tableRef} ON ${quotedLocal} = ${quotedForeign}`);
530
+ }
531
+ /**
532
+ * Parse a join field with smart detection for table prefixes and JSONB paths.
533
+ *
534
+ * @param field - The field string (e.g., "id", "users.id", "createdBy.id")
535
+ * @param defaultTable - Default table to use if no prefix
536
+ * @param tableAlias - Table alias to use if provided
537
+ * @returns Properly quoted SQL expression
538
+ */
539
+ parseJoinField(field, defaultTable, tableAlias) {
540
+ if (!field)
541
+ return "";
542
+ const effectiveTable = tableAlias ?? defaultTable;
543
+ const parts = field.split(".");
544
+ // Single part: just a column name, prefix with default table
545
+ if (parts.length === 1) {
546
+ return `${this.dialect.quoteIdentifier(effectiveTable)}.${this.dialect.quoteIdentifier(field)}`;
547
+ }
548
+ // Two parts: could be "table.column" or "jsonbColumn.key"
549
+ if (parts.length === 2) {
550
+ const [first, second] = parts;
551
+ // Check if first part is a known table (main table, join table, or alias)
552
+ if (this.isTableReference(first)) {
553
+ // It's table.column - regular column reference
554
+ return `${this.dialect.quoteIdentifier(first)}.${this.dialect.quoteIdentifier(second)}`;
555
+ }
556
+ // It's jsonbColumn.key - JSONB path
557
+ return this.buildJsonbPath(effectiveTable, first, [second]);
558
+ }
559
+ // Three or more parts: "table.jsonbColumn.key..." or "jsonbColumn.key1.key2..."
560
+ const [first, second, ...rest] = parts;
561
+ if (this.isTableReference(first)) {
562
+ // First part is table: "posts.createdBy.id" → table is "posts", JSONB is "createdBy.id"
563
+ return this.buildJsonbPath(first, second, rest);
564
+ }
565
+ // No table prefix: "createdBy.address.city" → use default table
566
+ return this.buildJsonbPath(effectiveTable, first, [second, ...rest]);
567
+ }
568
+ /**
569
+ * Check if a string is a table reference (main table or join table).
570
+ */
571
+ isTableReference(name) {
572
+ if (name === this.table || name === this.alias) {
573
+ return true;
574
+ }
575
+ if (this.joinedTables.has(name)) {
576
+ return true;
577
+ }
578
+ return false;
579
+ }
580
+ /**
581
+ * Build a JSONB path expression.
582
+ *
583
+ * @param table - Table name
584
+ * @param column - JSONB column name
585
+ * @param path - Array of nested keys
586
+ * @returns PostgreSQL JSONB path expression
587
+ *
588
+ * @example
589
+ * buildJsonbPath("posts", "createdBy", ["id"])
590
+ * // Returns: ("posts"."createdBy"->>'id')::integer
591
+ *
592
+ * buildJsonbPath("posts", "createdBy", ["address", "city"])
593
+ * // Returns: "posts"."createdBy"->'address'->>'city'
594
+ */
595
+ buildJsonbPath(table, column, path) {
596
+ const quotedTable = this.dialect.quoteIdentifier(table);
597
+ const quotedColumn = this.dialect.quoteIdentifier(column);
598
+ if (path.length === 0) {
599
+ return `${quotedTable}.${quotedColumn}`;
600
+ }
601
+ // Build JSONB path: use -> for intermediate keys, ->> for final key (returns text)
602
+ let expression = `${quotedTable}.${quotedColumn}`;
603
+ for (let i = 0; i < path.length; i++) {
604
+ const isLast = i === path.length - 1;
605
+ const operator = isLast ? "->>" : "->";
606
+ expression += `${operator}'${path[i]}'`;
607
+ }
608
+ // Cast to integer if the path ends with 'id' (common pattern for foreign keys)
609
+ const lastKey = path[path.length - 1].toLowerCase();
610
+ if (lastKey === "id" || lastKey.endsWith("id")) {
611
+ expression = `(${expression})::integer`;
612
+ }
613
+ return expression;
614
+ }
615
+ /**
616
+ * Process CROSS JOIN operation.
617
+ */
618
+ processCrossJoin(data) {
619
+ const table = data.table;
620
+ const quotedTable = this.dialect.quoteIdentifier(table);
621
+ this.joinClauses.push(`CROSS JOIN ${quotedTable}`);
622
+ }
623
+ /**
624
+ * Process raw JOIN expression.
625
+ */
626
+ processJoinRaw(data) {
627
+ const expression = data.expression;
628
+ const bindings = data.bindings ?? [];
629
+ let processed = expression;
630
+ for (const binding of bindings) {
631
+ processed = processed.replace("?", this.addParam(binding));
632
+ }
633
+ this.joinClauses.push(processed);
634
+ }
635
+ /**
636
+ * Process ORDER BY operation.
637
+ */
638
+ processOrderBy(data) {
639
+ const field = data.field;
640
+ const direction = (data.direction ?? "asc").toUpperCase();
641
+ const quotedField = this.dialect.quoteIdentifier(field);
642
+ this.orderClauses.push(`${quotedField} ${direction}`);
643
+ }
644
+ /**
645
+ * Process raw ORDER BY expression.
646
+ */
647
+ processOrderByRaw(data) {
648
+ const expression = data.expression;
649
+ this.orderClauses.push(expression);
650
+ }
651
+ /**
652
+ * Process GROUP BY operation.
653
+ */
654
+ processGroupBy(data) {
655
+ const fields = data.fields;
656
+ const columns = Array.isArray(fields) ? fields : [fields];
657
+ this.groupColumns.push(...columns);
658
+ }
659
+ /**
660
+ * Process HAVING operation.
661
+ */
662
+ processHaving(data) {
663
+ const field = data.field;
664
+ const operator = data.operator ?? "=";
665
+ const value = data.value;
666
+ const quotedField = this.dialect.quoteIdentifier(field);
667
+ const placeholder = this.addParam(value);
668
+ this.havingClauses.push(`${quotedField} ${operator} ${placeholder}`);
669
+ }
670
+ /**
671
+ * Process raw HAVING expression.
672
+ */
673
+ processHavingRaw(data) {
674
+ const expression = data.expression;
675
+ this.havingClauses.push(expression);
676
+ }
677
+ /**
678
+ * Add a WHERE clause with boolean operator.
679
+ */
680
+ addWhereClause(clause, boolean) {
681
+ if (this.whereClauses.length === 0) {
682
+ this.whereClauses.push(clause);
683
+ }
684
+ else {
685
+ this.whereClauses.push(`${boolean} ${clause}`);
686
+ }
687
+ }
688
+ /**
689
+ * Map Cascade operators to SQL operators.
690
+ */
691
+ mapOperator(operator) {
692
+ const mapping = {
693
+ "=": "=",
694
+ "!=": "!=",
695
+ "<>": "<>",
696
+ ">": ">",
697
+ ">=": ">=",
698
+ "<": "<",
699
+ "<=": "<=",
700
+ like: "LIKE",
701
+ notLike: "NOT LIKE",
702
+ ilike: "ILIKE",
703
+ };
704
+ return mapping[operator.toLowerCase()] ?? operator;
705
+ }
706
+ }export{PostgresQueryParser};//# sourceMappingURL=postgres-query-parser.js.map