@supalive/core 0.1.4 → 0.1.6

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 (222) hide show
  1. package/README.md +17 -2
  2. package/dist/bytes-AuEkyxeU.js +19 -0
  3. package/dist/bytes-AuEkyxeU.js.map +1 -0
  4. package/dist/codec-BHAmGEIQ.js +62 -0
  5. package/dist/codec-BHAmGEIQ.js.map +1 -0
  6. package/dist/helper-CiacMqje.d.ts +14 -0
  7. package/dist/helper-CiacMqje.d.ts.map +1 -0
  8. package/dist/helper-wGbzz6zo.js +42 -0
  9. package/dist/helper-wGbzz6zo.js.map +1 -0
  10. package/dist/index-CaWMDqq0.d.ts +1754 -0
  11. package/dist/index-CaWMDqq0.d.ts.map +1 -0
  12. package/dist/mysql-Cxd4Uq5p.d.ts +104 -0
  13. package/dist/mysql-Cxd4Uq5p.d.ts.map +1 -0
  14. package/dist/mysql-bvnjYWvZ.js +570 -0
  15. package/dist/mysql-bvnjYWvZ.js.map +1 -0
  16. package/dist/overlap-checker-Ct_HP_iB.js +187 -0
  17. package/dist/overlap-checker-Ct_HP_iB.js.map +1 -0
  18. package/dist/postgres-B8u1YN8X.js +824 -0
  19. package/dist/postgres-B8u1YN8X.js.map +1 -0
  20. package/dist/postgres-Ck-xt72U.d.ts +108 -0
  21. package/dist/postgres-Ck-xt72U.d.ts.map +1 -0
  22. package/dist/procedure-DX87tyef.js +124 -0
  23. package/dist/procedure-DX87tyef.js.map +1 -0
  24. package/dist/query-Bh0RNxDz.js +673 -0
  25. package/dist/query-Bh0RNxDz.js.map +1 -0
  26. package/dist/realtime_db-DOCgqbwi.js +247 -0
  27. package/dist/realtime_db-DOCgqbwi.js.map +1 -0
  28. package/dist/router-DlTYWpop.js +81 -0
  29. package/dist/router-DlTYWpop.js.map +1 -0
  30. package/dist/schema-Dd7u0A1L.js +109 -0
  31. package/dist/schema-Dd7u0A1L.js.map +1 -0
  32. package/dist/src/client/index.d.ts +2 -17
  33. package/dist/src/client/index.js +1152 -18
  34. package/dist/src/client/index.js.map +1 -1
  35. package/dist/src/exports/mysql.d.ts +2 -2
  36. package/dist/src/exports/mysql.js +2 -2
  37. package/dist/src/exports/postgres.d.ts +2 -2
  38. package/dist/src/exports/postgres.js +2 -2
  39. package/dist/src/exports/procedure.d.ts +3 -5
  40. package/dist/src/exports/procedure.js +6 -5
  41. package/dist/src/exports/schema-sql.d.ts +18 -0
  42. package/dist/src/exports/schema-sql.d.ts.map +1 -0
  43. package/dist/src/exports/schema-sql.js +161 -0
  44. package/dist/src/exports/schema-sql.js.map +1 -0
  45. package/dist/src/exports/server.d.ts +368 -2
  46. package/dist/src/exports/server.d.ts.map +1 -1
  47. package/dist/src/exports/server.js +1346 -2
  48. package/dist/src/exports/server.js.map +1 -1
  49. package/dist/src/exports/subscription-manager-worker-entry.d.ts +1 -0
  50. package/dist/src/exports/subscription-manager-worker-entry.js +115 -0
  51. package/dist/src/exports/subscription-manager-worker-entry.js.map +1 -0
  52. package/dist/src/exports/types.d.ts +4 -6
  53. package/dist/src/exports/types.js +5 -6
  54. package/dist/subscription-worker-pahX0zxg.js +511 -0
  55. package/dist/subscription-worker-pahX0zxg.js.map +1 -0
  56. package/dist/types_client_rpc-CIsjQQGG.js +105 -0
  57. package/dist/types_client_rpc-CIsjQQGG.js.map +1 -0
  58. package/dist/types_db-DXj_l9n-.js +168 -0
  59. package/dist/types_db-DXj_l9n-.js.map +1 -0
  60. package/dist/types_server-Dk6o_B7N.js +24 -0
  61. package/dist/types_server-Dk6o_B7N.js.map +1 -0
  62. package/dist/types_server-TFo6SWDH.d.ts +216 -0
  63. package/dist/types_server-TFo6SWDH.d.ts.map +1 -0
  64. package/package.json +7 -3
  65. package/dist/src/client/caller_client.d.ts +0 -42
  66. package/dist/src/client/caller_client.d.ts.map +0 -1
  67. package/dist/src/client/caller_client.js +0 -77
  68. package/dist/src/client/caller_client.js.map +0 -1
  69. package/dist/src/client/client.d.ts +0 -149
  70. package/dist/src/client/client.d.ts.map +0 -1
  71. package/dist/src/client/client.js +0 -308
  72. package/dist/src/client/client.js.map +0 -1
  73. package/dist/src/client/index.d.ts.map +0 -1
  74. package/dist/src/client/sub_key.d.ts +0 -20
  75. package/dist/src/client/sub_key.d.ts.map +0 -1
  76. package/dist/src/client/sub_key.js +0 -37
  77. package/dist/src/client/sub_key.js.map +0 -1
  78. package/dist/src/client/ws_client_manager.d.ts +0 -268
  79. package/dist/src/client/ws_client_manager.d.ts.map +0 -1
  80. package/dist/src/client/ws_client_manager.js +0 -1013
  81. package/dist/src/client/ws_client_manager.js.map +0 -1
  82. package/dist/src/config.d.ts +0 -117
  83. package/dist/src/config.d.ts.map +0 -1
  84. package/dist/src/config.js +0 -2
  85. package/dist/src/config.js.map +0 -1
  86. package/dist/src/db/bytes.d.ts +0 -4
  87. package/dist/src/db/bytes.d.ts.map +0 -1
  88. package/dist/src/db/bytes.js +0 -24
  89. package/dist/src/db/bytes.js.map +0 -1
  90. package/dist/src/db/cache.d.ts +0 -30
  91. package/dist/src/db/cache.d.ts.map +0 -1
  92. package/dist/src/db/cache.js +0 -153
  93. package/dist/src/db/cache.js.map +0 -1
  94. package/dist/src/db/codec.d.ts +0 -10
  95. package/dist/src/db/codec.d.ts.map +0 -1
  96. package/dist/src/db/codec.js +0 -73
  97. package/dist/src/db/codec.js.map +0 -1
  98. package/dist/src/db/context.d.ts +0 -28
  99. package/dist/src/db/context.d.ts.map +0 -1
  100. package/dist/src/db/context.js +0 -147
  101. package/dist/src/db/context.js.map +0 -1
  102. package/dist/src/db/db.d.ts +0 -154
  103. package/dist/src/db/db.d.ts.map +0 -1
  104. package/dist/src/db/db.js +0 -23
  105. package/dist/src/db/db.js.map +0 -1
  106. package/dist/src/db/mysql.d.ts +0 -120
  107. package/dist/src/db/mysql.d.ts.map +0 -1
  108. package/dist/src/db/mysql.js +0 -708
  109. package/dist/src/db/mysql.js.map +0 -1
  110. package/dist/src/db/postgres.d.ts +0 -116
  111. package/dist/src/db/postgres.d.ts.map +0 -1
  112. package/dist/src/db/postgres.js +0 -998
  113. package/dist/src/db/postgres.js.map +0 -1
  114. package/dist/src/db/query.d.ts +0 -174
  115. package/dist/src/db/query.d.ts.map +0 -1
  116. package/dist/src/db/query.js +0 -790
  117. package/dist/src/db/query.js.map +0 -1
  118. package/dist/src/db/query_definition.d.ts +0 -54
  119. package/dist/src/db/query_definition.d.ts.map +0 -1
  120. package/dist/src/db/query_definition.js +0 -47
  121. package/dist/src/db/query_definition.js.map +0 -1
  122. package/dist/src/db/realtime_db.d.ts +0 -19
  123. package/dist/src/db/realtime_db.d.ts.map +0 -1
  124. package/dist/src/db/realtime_db.js +0 -98
  125. package/dist/src/db/realtime_db.js.map +0 -1
  126. package/dist/src/db/schema.d.ts +0 -110
  127. package/dist/src/db/schema.d.ts.map +0 -1
  128. package/dist/src/db/schema.js +0 -47
  129. package/dist/src/db/schema.js.map +0 -1
  130. package/dist/src/db/types_client_rpc.d.ts +0 -157
  131. package/dist/src/db/types_client_rpc.d.ts.map +0 -1
  132. package/dist/src/db/types_client_rpc.js +0 -106
  133. package/dist/src/db/types_client_rpc.js.map +0 -1
  134. package/dist/src/db/types_db.d.ts +0 -236
  135. package/dist/src/db/types_db.d.ts.map +0 -1
  136. package/dist/src/db/types_db.js +0 -188
  137. package/dist/src/db/types_db.js.map +0 -1
  138. package/dist/src/exports/mysql.d.ts.map +0 -1
  139. package/dist/src/exports/mysql.js.map +0 -1
  140. package/dist/src/exports/postgres.d.ts.map +0 -1
  141. package/dist/src/exports/postgres.js.map +0 -1
  142. package/dist/src/exports/procedure.d.ts.map +0 -1
  143. package/dist/src/exports/procedure.js.map +0 -1
  144. package/dist/src/exports/types.d.ts.map +0 -1
  145. package/dist/src/exports/types.js.map +0 -1
  146. package/dist/src/helper.d.ts +0 -11
  147. package/dist/src/helper.d.ts.map +0 -1
  148. package/dist/src/helper.js +0 -45
  149. package/dist/src/helper.js.map +0 -1
  150. package/dist/src/logger.d.ts +0 -7
  151. package/dist/src/logger.d.ts.map +0 -1
  152. package/dist/src/logger.js +0 -47
  153. package/dist/src/logger.js.map +0 -1
  154. package/dist/src/router/index.d.ts +0 -4
  155. package/dist/src/router/index.d.ts.map +0 -1
  156. package/dist/src/router/index.js +0 -4
  157. package/dist/src/router/index.js.map +0 -1
  158. package/dist/src/router/procedure.d.ts +0 -204
  159. package/dist/src/router/procedure.d.ts.map +0 -1
  160. package/dist/src/router/procedure.js +0 -122
  161. package/dist/src/router/procedure.js.map +0 -1
  162. package/dist/src/router/router.d.ts +0 -88
  163. package/dist/src/router/router.d.ts.map +0 -1
  164. package/dist/src/router/router.js +0 -88
  165. package/dist/src/router/router.js.map +0 -1
  166. package/dist/src/server/hash.d.ts +0 -12
  167. package/dist/src/server/hash.d.ts.map +0 -1
  168. package/dist/src/server/hash.js +0 -20
  169. package/dist/src/server/hash.js.map +0 -1
  170. package/dist/src/server/hash.test.d.ts +0 -2
  171. package/dist/src/server/hash.test.d.ts.map +0 -1
  172. package/dist/src/server/hash.test.js +0 -43
  173. package/dist/src/server/hash.test.js.map +0 -1
  174. package/dist/src/server/index.d.ts +0 -9
  175. package/dist/src/server/index.d.ts.map +0 -1
  176. package/dist/src/server/index.js +0 -8
  177. package/dist/src/server/index.js.map +0 -1
  178. package/dist/src/server/overlap-checker.d.ts +0 -18
  179. package/dist/src/server/overlap-checker.d.ts.map +0 -1
  180. package/dist/src/server/overlap-checker.js +0 -247
  181. package/dist/src/server/overlap-checker.js.map +0 -1
  182. package/dist/src/server/sub_hash.d.ts +0 -23
  183. package/dist/src/server/sub_hash.d.ts.map +0 -1
  184. package/dist/src/server/sub_hash.js +0 -38
  185. package/dist/src/server/sub_hash.js.map +0 -1
  186. package/dist/src/server/subscription-manager-client.d.ts +0 -120
  187. package/dist/src/server/subscription-manager-client.d.ts.map +0 -1
  188. package/dist/src/server/subscription-manager-client.js +0 -207
  189. package/dist/src/server/subscription-manager-client.js.map +0 -1
  190. package/dist/src/server/subscription-manager-types.d.ts +0 -168
  191. package/dist/src/server/subscription-manager-types.d.ts.map +0 -1
  192. package/dist/src/server/subscription-manager-types.js +0 -94
  193. package/dist/src/server/subscription-manager-types.js.map +0 -1
  194. package/dist/src/server/subscription-manager-worker-entry.d.ts +0 -2
  195. package/dist/src/server/subscription-manager-worker-entry.d.ts.map +0 -1
  196. package/dist/src/server/subscription-manager-worker-entry.js +0 -127
  197. package/dist/src/server/subscription-manager-worker-entry.js.map +0 -1
  198. package/dist/src/server/subscription-manager-worker-protocol.d.ts +0 -40
  199. package/dist/src/server/subscription-manager-worker-protocol.d.ts.map +0 -1
  200. package/dist/src/server/subscription-manager-worker-protocol.js +0 -20
  201. package/dist/src/server/subscription-manager-worker-protocol.js.map +0 -1
  202. package/dist/src/server/subscription-manager.d.ts +0 -32
  203. package/dist/src/server/subscription-manager.d.ts.map +0 -1
  204. package/dist/src/server/subscription-manager.js +0 -249
  205. package/dist/src/server/subscription-manager.js.map +0 -1
  206. package/dist/src/server/subscription-manager.test.d.ts +0 -2
  207. package/dist/src/server/subscription-manager.test.d.ts.map +0 -1
  208. package/dist/src/server/subscription-manager.test.js +0 -610
  209. package/dist/src/server/subscription-manager.test.js.map +0 -1
  210. package/dist/src/server/subscription-worker.d.ts +0 -32
  211. package/dist/src/server/subscription-worker.d.ts.map +0 -1
  212. package/dist/src/server/subscription-worker.js +0 -190
  213. package/dist/src/server/subscription-worker.js.map +0 -1
  214. package/dist/src/server/supalive-server.d.ts +0 -158
  215. package/dist/src/server/supalive-server.d.ts.map +0 -1
  216. package/dist/src/server/supalive-server.js +0 -1048
  217. package/dist/src/server/supalive-server.js.map +0 -1
  218. package/dist/src/server/types_server.d.ts +0 -96
  219. package/dist/src/server/types_server.d.ts.map +0 -1
  220. package/dist/src/server/types_server.js +0 -36
  221. package/dist/src/server/types_server.js.map +0 -1
  222. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,673 @@
1
+ import { n as normalizeCodec } from "./codec-BHAmGEIQ.js";
2
+ import { t as bytesEqual } from "./bytes-AuEkyxeU.js";
3
+ import { z as z$1 } from "zod";
4
+ //#region src/db/sqlcommenter.ts
5
+ function comment(input) {
6
+ if (!input) return "";
7
+ if (typeof input === "string") return `/*${input}*/`;
8
+ const entries = Object.entries(input).filter(([_, v]) => v != null);
9
+ if (entries.length === 0) return "";
10
+ return `/*${entries.map(([k, v]) => `${encodeURIComponent(k)}='${encodeURIComponent(v)}'`).sort().join(",")}*/`;
11
+ }
12
+ //#endregion
13
+ //#region src/db/query.ts
14
+ function jsonKeysToPath(keys) {
15
+ let out = "$";
16
+ for (const k of keys) out += `."${k.replace(/"/g, "\\\"")}"`;
17
+ return out;
18
+ }
19
+ function resolveJsonPath(opts) {
20
+ if (opts?.path !== void 0 && opts?.pathRaw !== void 0) throw new Error("jsonContains: pass either `path` or `pathRaw`, not both");
21
+ if (opts?.pathRaw !== void 0) return opts.pathRaw;
22
+ if (opts?.path !== void 0) return jsonKeysToPath(Array.isArray(opts.path) ? opts.path : [opts.path]);
23
+ }
24
+ var QueryBuilder = class {
25
+ ctx;
26
+ model;
27
+ constructor(ctx, model) {
28
+ this.ctx = ctx;
29
+ this.model = model;
30
+ }
31
+ getColumnName(key) {
32
+ return this.model.columns[key] ?? key;
33
+ }
34
+ select(...columns) {
35
+ const selectedProps = columns.length > 0 ? columns : Object.keys(this.model.columns);
36
+ return new SelectQueryBuilder(this.ctx, this.model, [], null, null, null, selectedProps);
37
+ }
38
+ };
39
+ var SelectQueryBuilder = class SelectQueryBuilder {
40
+ ctx;
41
+ model;
42
+ filters = [];
43
+ orderByClause = null;
44
+ limitVal = null;
45
+ offsetVal = null;
46
+ selectedProps = [];
47
+ computedFields = [];
48
+ commentStr = "";
49
+ constructor(ctx, model, filters = [], orderByClause = null, limitVal = null, offsetVal = null, selectedProps = [], computedFields = [], commentStr = "") {
50
+ this.ctx = ctx;
51
+ this.model = model;
52
+ this.filters = filters;
53
+ this.orderByClause = orderByClause;
54
+ this.limitVal = limitVal;
55
+ this.offsetVal = offsetVal;
56
+ this.selectedProps = selectedProps;
57
+ this.computedFields = computedFields;
58
+ this.commentStr = commentStr;
59
+ }
60
+ getColumnName(key) {
61
+ return this.model.columns[key] ?? key;
62
+ }
63
+ getPropertyName(column) {
64
+ return this.model.reverseColumns[column] ?? this.computedFields.find((f) => f.alias === column)?.field ?? column;
65
+ }
66
+ mapRowToSchema(row) {
67
+ const result = {};
68
+ for (const [col, value] of Object.entries(row)) {
69
+ const prop = this.getPropertyName(col);
70
+ const codec = this.model.codecs[prop] ?? this.computedFields.find((f) => f.alias === col)?.codec;
71
+ result[prop] = codec?.decode && value !== void 0 && value !== null ? codec.decode(value) : value;
72
+ }
73
+ return result;
74
+ }
75
+ where(filterFn) {
76
+ this.filters.push(filterFn);
77
+ return this;
78
+ }
79
+ orderBy(column, direction = "asc") {
80
+ this.orderByClause = `${this.getColumnName(column)} ${direction}`;
81
+ return this;
82
+ }
83
+ limit(n) {
84
+ this.limitVal = n;
85
+ return this;
86
+ }
87
+ offset(n) {
88
+ this.offsetVal = n;
89
+ return this;
90
+ }
91
+ computed(config) {
92
+ const computed = {
93
+ field: config.field,
94
+ sql: config.sql,
95
+ alias: config.alias ?? config.field,
96
+ codec: normalizeCodec(config.codec, config.type)
97
+ };
98
+ this.computedFields.push(computed);
99
+ return new SelectQueryBuilder(this.ctx, this.model, this.filters, this.orderByClause, this.limitVal, this.offsetVal, [...this.selectedProps, config.field], this.computedFields, this.commentStr);
100
+ }
101
+ comment(input) {
102
+ this.commentStr = comment(input);
103
+ return this;
104
+ }
105
+ async first() {
106
+ return (await this.limit(1).get())[0] ?? null;
107
+ }
108
+ async exists() {
109
+ return await this.count() > 0;
110
+ }
111
+ static defaultCountType = z$1.coerce.number();
112
+ async count(parser) {
113
+ const predicate = this.buildPredicate() ?? {
114
+ kind: "leaf",
115
+ column: "1",
116
+ operator: "=",
117
+ value: "1"
118
+ };
119
+ const table = this.model.table;
120
+ const querySpec = {
121
+ kind: "range",
122
+ table,
123
+ tableId: this.model.tableId,
124
+ predicate,
125
+ columns: ["count"],
126
+ orderBy: null,
127
+ limit: null,
128
+ offset: null
129
+ };
130
+ const params = [];
131
+ const sql = `SELECT COUNT(*) as count FROM ${table} WHERE (${buildPredicateSql(predicate, params, this.ctx.db.sqlBuilder)})${this.commentStr ? " " + this.commentStr : ""}`;
132
+ const raw = (await this.ctx.db.query(sql, params)).rows[0]?.count ?? "0";
133
+ this.ctx.internalGetReadSet().push({
134
+ ...querySpec,
135
+ tableId: this.model.tableId
136
+ });
137
+ if (parser) return parser.parse(raw);
138
+ else return SelectQueryBuilder.defaultCountType.parse(raw);
139
+ }
140
+ async find(id) {
141
+ if (this.filters.length > 0) throw new Error(`Cannot use find() after where() - find() is meant for primary key lookups without additional filters`);
142
+ const table = this.model.table;
143
+ const tableId = this.model.tableId;
144
+ const pendingWrite = this.ctx.internalGetWriteSet().find((w) => w.id === id && bytesEqual(w.tableId, tableId));
145
+ if (pendingWrite) {
146
+ if (pendingWrite.op === "delete") return null;
147
+ return this.mapRowToSchema({
148
+ ...pendingWrite.data,
149
+ id,
150
+ commit_ts: this.ctx.beginTs
151
+ });
152
+ }
153
+ const computedCols = this.computedFields.map((f) => `${f.sql} as ${f.alias}`);
154
+ const selectPropsWithComputed = this.selectedProps.slice(0, this.selectedProps.length - this.computedFields.length);
155
+ let sql = `SELECT ${selectPropsWithComputed.length > 0 ? [
156
+ "id",
157
+ ...selectPropsWithComputed.map((p) => this.getColumnName(p)),
158
+ ...computedCols,
159
+ "commit_ts"
160
+ ].join(", ") : "*"} FROM ${table} WHERE id = ${this.ctx.db.sqlBuilder.placeholder(1)}`;
161
+ if (this.commentStr) sql += ` ${this.commentStr}`;
162
+ const row = (await this.ctx.db.query(sql, [id])).rows[0] ?? null;
163
+ const expectedCommitTs = row ? BigInt(row.commit_ts) : null;
164
+ this.ctx.internalGetReadSet().push({
165
+ kind: "point",
166
+ table,
167
+ tableId,
168
+ id,
169
+ expectedCommitTs
170
+ });
171
+ return row ? this.mapRowToSchema(row) : null;
172
+ }
173
+ async get() {
174
+ const predicate = this.buildPredicate() ?? {
175
+ kind: "leaf",
176
+ column: "1",
177
+ operator: "=",
178
+ value: "1"
179
+ };
180
+ const table = this.model.table;
181
+ const tableId = this.model.tableId;
182
+ const querySpec = {
183
+ kind: "range",
184
+ table,
185
+ tableId,
186
+ predicate,
187
+ columns: this.selectedProps,
188
+ orderBy: this.orderByClause,
189
+ limit: this.limitVal,
190
+ offset: this.offsetVal
191
+ };
192
+ const params = [];
193
+ const whereSql = buildPredicateSql(predicate, params, this.ctx.db.sqlBuilder);
194
+ const computedCols = this.computedFields.map((f) => `${f.sql} as ${f.alias}`);
195
+ const selectPropsWithComputed = this.selectedProps.slice(0, this.selectedProps.length - this.computedFields.length);
196
+ const selectColsNames = selectPropsWithComputed.length > 0 ? [
197
+ "id",
198
+ ...selectPropsWithComputed.map((p) => this.getColumnName(p)),
199
+ ...computedCols,
200
+ "commit_ts"
201
+ ] : "*";
202
+ let sql = `SELECT ${Array.from(new Set(selectColsNames).values()).join(", ")} FROM ${table} WHERE (${whereSql})`;
203
+ if (this.orderByClause) sql += ` ORDER BY ${this.orderByClause}`;
204
+ if (this.limitVal !== null) sql += ` LIMIT ${this.limitVal}`;
205
+ if (this.offsetVal !== null) sql += ` OFFSET ${this.offsetVal}`;
206
+ if (this.commentStr) sql += ` ${this.commentStr}`;
207
+ const result = await this.ctx.db.query(sql, params);
208
+ this.ctx.internalGetReadSet().push({
209
+ ...querySpec,
210
+ tableId
211
+ });
212
+ return result.rows.map((row) => this.mapRowToSchema(row));
213
+ }
214
+ buildPredicate() {
215
+ if (this.filters.length === 0) return null;
216
+ const predicates = [];
217
+ const fb = new FilterBuilder(this.model.columns, this.model.codecs);
218
+ for (const filterFn of this.filters) {
219
+ filterFn(fb);
220
+ if (fb.predicates.length > 0) {
221
+ if (fb.predicates.some((p) => p.kind === "or")) predicates.push(...fb.predicates);
222
+ else predicates.push({
223
+ kind: "and",
224
+ children: fb.predicates
225
+ });
226
+ fb.predicates = [];
227
+ }
228
+ }
229
+ if (predicates.length === 0) return null;
230
+ if (predicates.length === 1) return predicates[0] ?? null;
231
+ return {
232
+ kind: "and",
233
+ children: predicates
234
+ };
235
+ }
236
+ };
237
+ var FilterBuilder = class FilterBuilder {
238
+ columns;
239
+ codecs;
240
+ predicates = [];
241
+ constructor(columns, codecs) {
242
+ this.columns = columns;
243
+ this.codecs = codecs;
244
+ }
245
+ add(column, operator, value, value2, raw) {
246
+ const leaf = {
247
+ kind: "leaf",
248
+ column,
249
+ operator,
250
+ value,
251
+ value2
252
+ };
253
+ if (raw) leaf.raw = true;
254
+ this.predicates.push(leaf);
255
+ }
256
+ addJsonContains(operator, key, value, opts) {
257
+ const leaf = {
258
+ kind: "leaf",
259
+ column: this.getColumnName(key),
260
+ operator,
261
+ value: this.encodeJson(value, opts?.raw)
262
+ };
263
+ if (opts?.raw) leaf.raw = true;
264
+ const path = resolveJsonPath(opts);
265
+ if (path !== void 0) leaf.path = path;
266
+ this.predicates.push(leaf);
267
+ }
268
+ getColumnName(key) {
269
+ return this.columns[key] ?? key;
270
+ }
271
+ encode(key, value) {
272
+ const codec = this.codecs[key];
273
+ if (!codec?.encode || value === void 0 || value === null) return value;
274
+ return codec.encode(value);
275
+ }
276
+ encodeJson(value, raw) {
277
+ if (value === null || value === void 0) return value;
278
+ if (raw) return value;
279
+ return JSON.stringify(value);
280
+ }
281
+ eq(key, value) {
282
+ this.add(this.getColumnName(key), "=", this.encode(key, value));
283
+ return this;
284
+ }
285
+ neq(key, value) {
286
+ this.add(this.getColumnName(key), "!=", this.encode(key, value));
287
+ return this;
288
+ }
289
+ gt(key, value) {
290
+ this.add(this.getColumnName(key), ">", this.encode(key, value));
291
+ return this;
292
+ }
293
+ gte(key, value) {
294
+ this.add(this.getColumnName(key), ">=", this.encode(key, value));
295
+ return this;
296
+ }
297
+ lt(key, value) {
298
+ this.add(this.getColumnName(key), "<", this.encode(key, value));
299
+ return this;
300
+ }
301
+ lte(key, value) {
302
+ this.add(this.getColumnName(key), "<=", this.encode(key, value));
303
+ return this;
304
+ }
305
+ like(key, pattern) {
306
+ this.add(this.getColumnName(key), "like", this.encode(key, pattern));
307
+ return this;
308
+ }
309
+ ilike(key, pattern) {
310
+ this.add(this.getColumnName(key), "ilike", this.encode(key, pattern));
311
+ return this;
312
+ }
313
+ contains(key, value) {
314
+ this.add(this.getColumnName(key), "contains", this.encode(key, value));
315
+ return this;
316
+ }
317
+ icontains(key, value) {
318
+ this.add(this.getColumnName(key), "icontains", this.encode(key, value));
319
+ return this;
320
+ }
321
+ /**
322
+ * JSON containment. Targets a JSON/JSONB column and asserts the document
323
+ * contains the given candidate (object-key subset for objects,
324
+ * element-subset for arrays — see dialect-specific docs for edge cases).
325
+ * Pass `{ raw: true }` if `value` is already a JSON-encoded string.
326
+ * Pass `{ path: ... }` to scope the check to a sub-document of the
327
+ * target (jsonb_path_query_first on PG, JSON_CONTAINS path arg on MySQL).
328
+ */
329
+ jsonContains(key, value, opts) {
330
+ this.addJsonContains("jsonContains", key, value, opts);
331
+ return this;
332
+ }
333
+ /** Inverse of {@link jsonContains}: column is contained in the given value. */
334
+ jsonContainedBy(key, value, opts) {
335
+ this.addJsonContains("jsonContainedBy", key, value, opts);
336
+ return this;
337
+ }
338
+ jsonHasKey(key, value, opts) {
339
+ const col = this.getColumnName(key);
340
+ if (opts?.mode && Array.isArray(value)) {
341
+ const leaf = {
342
+ kind: "leaf",
343
+ column: col,
344
+ operator: "jsonHasKey",
345
+ value: value.map((p) => opts.raw && typeof p === "string" ? p : jsonKeysToPath(Array.isArray(p) ? p : [p])),
346
+ mode: opts.mode
347
+ };
348
+ this.predicates.push(leaf);
349
+ return this;
350
+ }
351
+ if (Array.isArray(value)) this.add(col, "jsonHasKey", jsonKeysToPath(value), void 0, true);
352
+ else if (opts?.raw) this.add(col, "jsonHasKey", value, void 0, true);
353
+ else this.add(col, "jsonHasKey", value, void 0, false);
354
+ return this;
355
+ }
356
+ /**
357
+ * Array element containment: target column is a JSON array; the given
358
+ * `value` (any JSON-encodable type) must appear as one of its elements.
359
+ * Pass `{ raw: true }` if `value` is already a JSON-encoded string.
360
+ * Pass `{ path: ... }` to scope the check to a sub-array of the column.
361
+ */
362
+ jsonArrayContains(key, value, opts) {
363
+ this.addJsonContains("jsonArrayContains", key, value, opts);
364
+ return this;
365
+ }
366
+ between(key, lo, hi) {
367
+ this.add(this.getColumnName(key), "between", this.encode(key, lo), this.encode(key, hi));
368
+ return this;
369
+ }
370
+ isNull(key) {
371
+ this.add(this.getColumnName(key), "isNull", null);
372
+ return this;
373
+ }
374
+ notNull(key) {
375
+ this.add(this.getColumnName(key), "isNotNull", null);
376
+ return this;
377
+ }
378
+ /**
379
+ * Compose an OR clause. Each callback fills a fresh sub-FilterBuilder
380
+ * with predicates that are AND-ed together within that branch; the
381
+ * branches themselves are OR-ed. Example:
382
+ * f.or([
383
+ * b => b.eq("tag", "a"),
384
+ * b => b.eq("tag", "b").gt("qty", 3), // (tag=b AND qty>3)
385
+ * ])
386
+ * produces (tag=a) OR (tag=b AND qty>3).
387
+ */
388
+ or(branches) {
389
+ const children = [];
390
+ for (const fn of branches) {
391
+ const sub = new FilterBuilder(this.columns, this.codecs);
392
+ fn(sub);
393
+ if (sub.predicates.length === 1) children.push(sub.predicates[0]);
394
+ else if (sub.predicates.length > 1) children.push({
395
+ kind: "and",
396
+ children: sub.predicates
397
+ });
398
+ }
399
+ if (children.length > 0) this.predicates.push({
400
+ kind: "or",
401
+ children
402
+ });
403
+ return this;
404
+ }
405
+ };
406
+ function buildPredicateSql(predicate, params, sql) {
407
+ switch (predicate.kind) {
408
+ case "and": return `(${predicate.children.map((c) => buildPredicateSql(c, params, sql)).join(" AND ")})`;
409
+ case "or": return `(${predicate.children.map((c) => buildPredicateSql(c, params, sql)).join(" OR ")})`;
410
+ case "leaf": return buildLeafSql(predicate, params, sql);
411
+ }
412
+ }
413
+ function buildLeafSql(leaf, params, sql) {
414
+ const col = leaf.column;
415
+ switch (leaf.operator) {
416
+ case "=":
417
+ case "!=":
418
+ case ">":
419
+ case ">=":
420
+ case "<":
421
+ case "<=":
422
+ params.push(leaf.value);
423
+ return `${col} ${leaf.operator} ${sql.placeholder(params.length)}`;
424
+ case "between": {
425
+ params.push(leaf.value);
426
+ const p1 = sql.placeholder(params.length);
427
+ params.push(leaf.value2);
428
+ return `${col} BETWEEN ${p1} AND ${sql.placeholder(params.length)}`;
429
+ }
430
+ case "like":
431
+ params.push(leaf.value);
432
+ return `${col} LIKE ${sql.placeholder(params.length)}`;
433
+ case "ilike":
434
+ params.push(leaf.value);
435
+ return sql.ilike(col, params.length);
436
+ case "contains":
437
+ params.push(`%${leaf.value}%`);
438
+ return `${col} LIKE ${sql.placeholder(params.length)}`;
439
+ case "icontains":
440
+ params.push(`%${leaf.value}%`);
441
+ return sql.icontains(col, params.length);
442
+ case "jsonContains": {
443
+ params.push(leaf.value);
444
+ const valIdx = params.length;
445
+ let pathIndex;
446
+ if (leaf.path !== void 0) {
447
+ params.push(leaf.path);
448
+ pathIndex = params.length;
449
+ }
450
+ return sql.jsonContains(col, valIdx, {
451
+ raw: leaf.raw,
452
+ pathIndex
453
+ });
454
+ }
455
+ case "jsonContainedBy": {
456
+ params.push(leaf.value);
457
+ const valIdx = params.length;
458
+ let pathIndex;
459
+ if (leaf.path !== void 0) {
460
+ params.push(leaf.path);
461
+ pathIndex = params.length;
462
+ }
463
+ return sql.jsonContainedBy(col, valIdx, {
464
+ raw: leaf.raw,
465
+ pathIndex
466
+ });
467
+ }
468
+ case "jsonHasKey":
469
+ if (leaf.mode && Array.isArray(leaf.value)) {
470
+ const paths = leaf.value;
471
+ const startIdx = params.length + 1;
472
+ for (const p of paths) params.push(p);
473
+ return sql.jsonHasKey(col, startIdx, {
474
+ raw: true,
475
+ mode: leaf.mode,
476
+ pathCount: paths.length
477
+ });
478
+ }
479
+ params.push(leaf.value);
480
+ return sql.jsonHasKey(col, params.length, { raw: leaf.raw });
481
+ case "jsonArrayContains": {
482
+ params.push(leaf.value);
483
+ const valIdx = params.length;
484
+ let pathIndex;
485
+ if (leaf.path !== void 0) {
486
+ params.push(leaf.path);
487
+ pathIndex = params.length;
488
+ }
489
+ return sql.jsonArrayContains(col, valIdx, {
490
+ raw: leaf.raw,
491
+ pathIndex
492
+ });
493
+ }
494
+ case "isNull": return `${col} IS NULL`;
495
+ case "isNotNull": return `${col} IS NOT NULL`;
496
+ }
497
+ }
498
+ function matchesPredicate(row, predicate) {
499
+ switch (predicate.kind) {
500
+ case "and": return predicate.children.every((c) => matchesPredicate(row, c));
501
+ case "or": return predicate.children.some((c) => matchesPredicate(row, c));
502
+ case "leaf": return matchesLeaf(row, predicate);
503
+ }
504
+ }
505
+ function matchesLeaf(row, leaf) {
506
+ const val = row[leaf.column];
507
+ switch (leaf.operator) {
508
+ case "=": return val === leaf.value;
509
+ case "!=": return val !== leaf.value;
510
+ case ">": return val > leaf.value;
511
+ case ">=": return val >= leaf.value;
512
+ case "<": return val < leaf.value;
513
+ case "<=": return val <= leaf.value;
514
+ case "between": return val >= leaf.value && val <= leaf.value2;
515
+ case "like":
516
+ case "contains":
517
+ case "ilike":
518
+ case "icontains": {
519
+ if (typeof val !== "string" || typeof leaf.value !== "string") return false;
520
+ const haystack = leaf.operator === "ilike" || leaf.operator === "icontains" ? val.toLowerCase() : val;
521
+ const raw = leaf.value;
522
+ const needle = leaf.operator === "ilike" || leaf.operator === "icontains" ? raw.toLowerCase() : raw;
523
+ const pattern = leaf.operator === "contains" || leaf.operator === "icontains" ? `%${needle}%` : needle;
524
+ return new RegExp("^" + pattern.replace(/%/g, ".*").replace(/_/g, ".") + "$").test(haystack);
525
+ }
526
+ case "jsonContains": {
527
+ const candidate = decodeJsonLeafValue(leaf);
528
+ const target = leaf.path !== void 0 ? jsonPathExtract(val, leaf.path) : val;
529
+ if (target === void 0) return false;
530
+ return jsonContains(target, candidate);
531
+ }
532
+ case "jsonContainedBy": {
533
+ const candidate = decodeJsonLeafValue(leaf);
534
+ const target = leaf.path !== void 0 ? jsonPathExtract(val, leaf.path) : val;
535
+ if (target === void 0) return false;
536
+ return jsonContains(candidate, target);
537
+ }
538
+ case "jsonHasKey": {
539
+ if (leaf.mode && Array.isArray(leaf.value)) {
540
+ const paths = leaf.value;
541
+ if (paths.length === 0) return false;
542
+ return leaf.mode === "all" ? paths.every((p) => jsonPathExists(val, p)) : paths.some((p) => jsonPathExists(val, p));
543
+ }
544
+ if (leaf.raw) return jsonPathExists(val, leaf.value);
545
+ const key = leaf.value;
546
+ if (val === null || typeof val !== "object") return false;
547
+ if (Array.isArray(val)) return val.includes(key);
548
+ return key in val;
549
+ }
550
+ case "jsonArrayContains": {
551
+ const candidate = decodeJsonLeafValue(leaf);
552
+ const target = leaf.path !== void 0 ? jsonPathExtract(val, leaf.path) : val;
553
+ if (!Array.isArray(target)) return false;
554
+ return target.some((el) => jsonContains(el, candidate));
555
+ }
556
+ case "isNull": return val === null;
557
+ case "isNotNull": return val !== null;
558
+ default: return false;
559
+ }
560
+ }
561
+ function decodeJsonLeafValue(leaf) {
562
+ if (!leaf.raw) return leaf.value;
563
+ if (typeof leaf.value !== "string") return leaf.value;
564
+ try {
565
+ return JSON.parse(leaf.value);
566
+ } catch {
567
+ return leaf.value;
568
+ }
569
+ }
570
+ function jsonContains(target, candidate) {
571
+ if (candidate === target) return true;
572
+ if (target === null || candidate === null) return target === candidate;
573
+ if (target === void 0 || candidate === void 0) return false;
574
+ const tArr = Array.isArray(target);
575
+ const cArr = Array.isArray(candidate);
576
+ const tObj = !tArr && typeof target === "object";
577
+ const cObj = !cArr && typeof candidate === "object";
578
+ if (!cArr && !cObj && tArr) return target.some((el) => jsonContains(el, candidate));
579
+ if (cArr && tArr) {
580
+ const t = target;
581
+ return candidate.every((c) => t.some((el) => jsonContains(el, c)));
582
+ }
583
+ if (cObj && tObj) {
584
+ const t = target;
585
+ const c = candidate;
586
+ for (const k of Object.keys(c)) {
587
+ if (!(k in t)) return false;
588
+ if (!jsonContains(t[k], c[k])) return false;
589
+ }
590
+ return true;
591
+ }
592
+ return false;
593
+ }
594
+ function jsonPathExtract(val, path) {
595
+ let p = path;
596
+ if (p.startsWith("$")) p = p.slice(1);
597
+ let cur = val;
598
+ while (p.length > 0) if (p.startsWith(".\"")) {
599
+ let end = 2;
600
+ while (end < p.length) {
601
+ if (p[end] === "\\" && end + 1 < p.length) {
602
+ end += 2;
603
+ continue;
604
+ }
605
+ if (p[end] === "\"") break;
606
+ end++;
607
+ }
608
+ if (end >= p.length) return void 0;
609
+ const key = p.slice(2, end).replace(/\\"/g, "\"").replace(/\\\\/g, "\\");
610
+ if (cur === null || typeof cur !== "object" || Array.isArray(cur)) return void 0;
611
+ if (!(key in cur)) return void 0;
612
+ cur = cur[key];
613
+ p = p.slice(end + 1);
614
+ } else if (p.startsWith(".")) {
615
+ const m = p.slice(1).match(/^([^.[]+)/);
616
+ if (!m) return void 0;
617
+ const key = m[1];
618
+ if (cur === null || typeof cur !== "object" || Array.isArray(cur)) return void 0;
619
+ if (!(key in cur)) return void 0;
620
+ cur = cur[key];
621
+ p = p.slice(1 + key.length);
622
+ } else if (p.startsWith("[")) {
623
+ const end = p.indexOf("]");
624
+ if (end === -1) return void 0;
625
+ const idx = parseInt(p.slice(1, end), 10);
626
+ if (!Array.isArray(cur) || idx < 0 || idx >= cur.length) return void 0;
627
+ cur = cur[idx];
628
+ p = p.slice(end + 1);
629
+ } else return;
630
+ return cur;
631
+ }
632
+ function jsonPathExists(val, path) {
633
+ let p = path;
634
+ if (p.startsWith("$")) p = p.slice(1);
635
+ let cur = val;
636
+ while (p.length > 0) if (p.startsWith(".\"")) {
637
+ let end = 2;
638
+ while (end < p.length) {
639
+ if (p[end] === "\\" && end + 1 < p.length) {
640
+ end += 2;
641
+ continue;
642
+ }
643
+ if (p[end] === "\"") break;
644
+ end++;
645
+ }
646
+ if (end >= p.length) return false;
647
+ const key = p.slice(2, end).replace(/\\"/g, "\"").replace(/\\\\/g, "\\");
648
+ if (cur === null || typeof cur !== "object" || Array.isArray(cur)) return false;
649
+ if (!(key in cur)) return false;
650
+ cur = cur[key];
651
+ p = p.slice(end + 1);
652
+ } else if (p.startsWith(".")) {
653
+ const m = p.slice(1).match(/^([^.[]+)/);
654
+ if (!m) return false;
655
+ const key = m[1];
656
+ if (cur === null || typeof cur !== "object" || Array.isArray(cur)) return false;
657
+ if (!(key in cur)) return false;
658
+ cur = cur[key];
659
+ p = p.slice(1 + key.length);
660
+ } else if (p.startsWith("[")) {
661
+ const end = p.indexOf("]");
662
+ if (end === -1) return false;
663
+ const idx = parseInt(p.slice(1, end), 10);
664
+ if (!Array.isArray(cur) || idx < 0 || idx >= cur.length) return false;
665
+ cur = cur[idx];
666
+ p = p.slice(end + 1);
667
+ } else return false;
668
+ return cur !== void 0;
669
+ }
670
+ //#endregion
671
+ export { jsonPathExtract as a, jsonPathExists as i, buildPredicateSql as n, matchesPredicate as o, jsonContains as r, QueryBuilder as t };
672
+
673
+ //# sourceMappingURL=query-Bh0RNxDz.js.map