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