@noy-db/hub 0.2.0-pre.14 → 0.2.0-pre.15

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 (122) hide show
  1. package/dist/aggregate/index.cjs +56 -56
  2. package/dist/aggregate/index.cjs.map +1 -1
  3. package/dist/aggregate/index.d.cts +2 -2
  4. package/dist/aggregate/index.d.ts +2 -2
  5. package/dist/aggregate/index.js +3 -3
  6. package/dist/attestation/index.d.cts +5 -5
  7. package/dist/attestation/index.d.ts +5 -5
  8. package/dist/blobs/index.d.cts +6 -6
  9. package/dist/blobs/index.d.ts +6 -6
  10. package/dist/bundle/index.cjs +426 -68
  11. package/dist/bundle/index.cjs.map +1 -1
  12. package/dist/bundle/index.d.cts +7 -7
  13. package/dist/bundle/index.d.ts +7 -7
  14. package/dist/bundle/index.js +1 -1
  15. package/dist/{chunk-3EWA37FV.js → chunk-3EWXMOK3.js} +7 -266
  16. package/dist/chunk-3EWXMOK3.js.map +1 -0
  17. package/dist/{chunk-ACKFRSAH.js → chunk-7EFFHEN5.js} +26 -19
  18. package/dist/chunk-7EFFHEN5.js.map +1 -0
  19. package/dist/{chunk-UWNYBOOO.js → chunk-C5T5AFWN.js} +2 -2
  20. package/dist/chunk-CJORTUJ2.js +524 -0
  21. package/dist/chunk-CJORTUJ2.js.map +1 -0
  22. package/dist/{chunk-YNTBADIY.js → chunk-CZI2A4MQ.js} +2 -2
  23. package/dist/{chunk-KGCORI4L.js → chunk-EYVQHAGH.js} +266 -66
  24. package/dist/chunk-EYVQHAGH.js.map +1 -0
  25. package/dist/{chunk-NP6EZT44.js → chunk-IQLVUT37.js} +2 -2
  26. package/dist/{chunk-4PEFEETV.js → chunk-KIP6JLTF.js} +2 -2
  27. package/dist/{chunk-ZWTNWAO4.js → chunk-NU6Q3FOR.js} +3 -3
  28. package/dist/chunk-NU6Q3FOR.js.map +1 -0
  29. package/dist/{chunk-WIBHRONM.js → chunk-XWH4MXIU.js} +2 -2
  30. package/dist/consent/index.d.cts +6 -6
  31. package/dist/consent/index.d.ts +6 -6
  32. package/dist/derivations/index.d.cts +7 -7
  33. package/dist/derivations/index.d.ts +7 -7
  34. package/dist/{dev-unlock-DV7ujTCI.d.ts → dev-unlock-iAS8z9jc.d.ts} +1 -1
  35. package/dist/{dev-unlock-BF4OSxRv.d.cts → dev-unlock-nVkuRLLe.d.cts} +1 -1
  36. package/dist/{executor-723ZP6TH.js → executor-HSSRXDOB.js} +4 -4
  37. package/dist/guards/index.d.cts +7 -7
  38. package/dist/guards/index.d.ts +7 -7
  39. package/dist/{hash-BcF5WQXl.d.cts → hash-Cv6byZs7.d.cts} +1 -1
  40. package/dist/{hash-DswxkLtW.d.ts → hash-DHOnRarj.d.ts} +1 -1
  41. package/dist/history/index.d.cts +7 -7
  42. package/dist/history/index.d.ts +7 -7
  43. package/dist/i18n/index.d.cts +6 -6
  44. package/dist/i18n/index.d.ts +6 -6
  45. package/dist/{immutable-guard-C8IYdzfu.d.ts → immutable-guard-BehB1YGB.d.ts} +1 -1
  46. package/dist/{immutable-guard-7KqslW2K.d.cts → immutable-guard-yBEOYmif.d.cts} +1 -1
  47. package/dist/{index-CUVOMtgg.d.cts → index-D95VK1Qy.d.cts} +11 -3
  48. package/dist/{index-Cqzp4tt9.d.ts → index-XNB2r6bX.d.ts} +11 -3
  49. package/dist/index.cjs +567 -70
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.d.cts +145 -15
  52. package/dist/index.d.ts +145 -15
  53. package/dist/index.js +132 -16
  54. package/dist/index.js.map +1 -1
  55. package/dist/indexing/index.cjs +92 -31
  56. package/dist/indexing/index.cjs.map +1 -1
  57. package/dist/indexing/index.d.cts +3 -3
  58. package/dist/indexing/index.d.ts +3 -3
  59. package/dist/indexing/index.js +3 -3
  60. package/dist/{lazy-builder-D5GU14TS.d.ts → lazy-builder-ChSqcF5t.d.ts} +1 -1
  61. package/dist/{lazy-builder-Ci5_YG73.d.cts → lazy-builder-eYZzLEL1.d.cts} +1 -1
  62. package/dist/materialized-views/index.cjs +2 -2
  63. package/dist/materialized-views/index.cjs.map +1 -1
  64. package/dist/materialized-views/index.d.cts +7 -7
  65. package/dist/materialized-views/index.d.ts +7 -7
  66. package/dist/materialized-views/index.js +5 -5
  67. package/dist/{noydb-VZ4JVW55.js → noydb-GZGFBA4E.js} +8 -8
  68. package/dist/overlay-views/index.d.cts +7 -7
  69. package/dist/overlay-views/index.d.ts +7 -7
  70. package/dist/periods/index.d.cts +6 -6
  71. package/dist/periods/index.d.ts +6 -6
  72. package/dist/{predicate-Bt5ft-9c.d.cts → predicate-BmhBSPCH.d.cts} +59 -2
  73. package/dist/{predicate-Bt5ft-9c.d.ts → predicate-BmhBSPCH.d.ts} +59 -2
  74. package/dist/query/index.cjs +580 -195
  75. package/dist/query/index.cjs.map +1 -1
  76. package/dist/query/index.d.cts +3 -3
  77. package/dist/query/index.d.ts +3 -3
  78. package/dist/query/index.js +5 -5
  79. package/dist/session/index.d.cts +7 -7
  80. package/dist/session/index.d.ts +7 -7
  81. package/dist/shadow/index.d.cts +6 -6
  82. package/dist/shadow/index.d.ts +6 -6
  83. package/dist/snapshots/index.d.cts +6 -6
  84. package/dist/snapshots/index.d.ts +6 -6
  85. package/dist/{stale-7FRJVHN6.js → stale-JH67FU57.js} +2 -2
  86. package/dist/store/index.d.cts +6 -6
  87. package/dist/store/index.d.ts +6 -6
  88. package/dist/{strategy-CrS7PnbE.d.ts → strategy-CbneC7bS.d.cts} +1 -1
  89. package/dist/{strategy-CrS7PnbE.d.cts → strategy-CbneC7bS.d.ts} +1 -1
  90. package/dist/sync/index.d.cts +5 -5
  91. package/dist/sync/index.d.ts +5 -5
  92. package/dist/team/index.d.cts +6 -6
  93. package/dist/team/index.d.ts +6 -6
  94. package/dist/tx/index.d.cts +6 -6
  95. package/dist/tx/index.d.ts +6 -6
  96. package/dist/{types-BFHQUjdy.d.ts → types-4t1-tWS4.d.ts} +22 -7
  97. package/dist/{types-V5R2-pd4.d.cts → types-BpPV5uyy.d.cts} +22 -7
  98. package/dist/{ulid-CwNf9e6-.d.cts → ulid-CiPrpGqm.d.cts} +1 -1
  99. package/dist/{ulid-p2nKiiKg.d.ts → ulid-DAfenvFd.d.ts} +1 -1
  100. package/dist/{vault-group-W7QC4UYW.js → vault-group-KOM7QRJG.js} +3 -3
  101. package/dist/{with-derivation-C9K43BOB.d.cts → with-derivation-DBqJB3dQ.d.cts} +1 -1
  102. package/dist/{with-derivation-Ds9yZgCj.d.ts → with-derivation-OK9M2sJE.d.ts} +1 -1
  103. package/dist/{with-materialized-view-DwR4jkV5.d.ts → with-materialized-view-Dt-ufPWQ.d.ts} +1 -1
  104. package/dist/{with-materialized-view-DgQcAjYv.d.cts → with-materialized-view-NzuxYPDF.d.cts} +1 -1
  105. package/dist/{with-overlayed-view-7-rUB3vD.d.cts → with-overlayed-view-CC0_ocy-.d.cts} +1 -1
  106. package/dist/{with-overlayed-view-ByyhHdVr.d.ts → with-overlayed-view-eDvMs6LO.d.ts} +1 -1
  107. package/package.json +3 -3
  108. package/dist/chunk-3EWA37FV.js.map +0 -1
  109. package/dist/chunk-ACKFRSAH.js.map +0 -1
  110. package/dist/chunk-KGCORI4L.js.map +0 -1
  111. package/dist/chunk-TV3YZ35S.js +0 -90
  112. package/dist/chunk-TV3YZ35S.js.map +0 -1
  113. package/dist/chunk-ZWTNWAO4.js.map +0 -1
  114. /package/dist/{chunk-UWNYBOOO.js.map → chunk-C5T5AFWN.js.map} +0 -0
  115. /package/dist/{chunk-YNTBADIY.js.map → chunk-CZI2A4MQ.js.map} +0 -0
  116. /package/dist/{chunk-NP6EZT44.js.map → chunk-IQLVUT37.js.map} +0 -0
  117. /package/dist/{chunk-4PEFEETV.js.map → chunk-KIP6JLTF.js.map} +0 -0
  118. /package/dist/{chunk-WIBHRONM.js.map → chunk-XWH4MXIU.js.map} +0 -0
  119. /package/dist/{executor-723ZP6TH.js.map → executor-HSSRXDOB.js.map} +0 -0
  120. /package/dist/{noydb-VZ4JVW55.js.map → noydb-GZGFBA4E.js.map} +0 -0
  121. /package/dist/{stale-7FRJVHN6.js.map → stale-JH67FU57.js.map} +0 -0
  122. /package/dist/{vault-group-W7QC4UYW.js.map → vault-group-KOM7QRJG.js.map} +0 -0
@@ -1,18 +1,21 @@
1
1
  import {
2
- MoneyPrecisionError,
3
- formatScaledInt,
4
- parseToScaledInt,
5
2
  wrapMoneyReducers
6
- } from "./chunk-3EWA37FV.js";
3
+ } from "./chunk-3EWXMOK3.js";
7
4
  import {
5
+ MoneyPrecisionError,
8
6
  evaluateClause,
7
+ formatScaledInt,
8
+ hasFnClause,
9
+ moneyFieldClause,
10
+ parseToScaledInt,
9
11
  readPath
10
- } from "./chunk-TV3YZ35S.js";
12
+ } from "./chunk-CJORTUJ2.js";
11
13
  import {
12
14
  CrossJoinSourceUnknownError,
13
15
  CrossJoinTooLargeError,
14
16
  DanglingReferenceError,
15
- JoinTooLargeError
17
+ JoinTooLargeError,
18
+ ValidationError
16
19
  } from "./chunk-535SSHBS.js";
17
20
 
18
21
  // src/query/join.ts
@@ -260,6 +263,108 @@ var NO_AGGREGATE = {
260
263
  }
261
264
  };
262
265
 
266
+ // src/money/paths.ts
267
+ var SEGMENT_RE = /^(\*|[^.[\]*]+)(\[\])?$/;
268
+ var parseCache = /* @__PURE__ */ new Map();
269
+ function parseMoneyPath(path) {
270
+ const cached = parseCache.get(path);
271
+ if (cached) return cached;
272
+ if (typeof path !== "string" || path.length === 0) {
273
+ throw new ValidationError("moneyFields: path must be a non-empty string");
274
+ }
275
+ const segments = [];
276
+ for (const part of path.split(".")) {
277
+ const m = SEGMENT_RE.exec(part);
278
+ if (!m) {
279
+ throw new ValidationError(
280
+ `moneyFields: invalid path "${path}" \u2014 segment "${part}" must be a key, "key[]", "*", or "*[]"`
281
+ );
282
+ }
283
+ const array = m[2] === "[]";
284
+ segments.push(
285
+ m[1] === "*" ? { kind: "wildcard", array } : { kind: "key", key: m[1], array }
286
+ );
287
+ }
288
+ parseCache.set(path, segments);
289
+ return segments;
290
+ }
291
+ function isSimpleMoneyPath(path) {
292
+ return !path.includes(".") && !path.includes("[") && !path.includes("*");
293
+ }
294
+ function validateMoneyFieldPaths(moneyFields) {
295
+ for (const path of Object.keys(moneyFields)) parseMoneyPath(path);
296
+ }
297
+ function transformAtMoneyPath(node, path, segments, index, visit, lenient) {
298
+ if (node === null || node === void 0) return node;
299
+ const seg = segments[index];
300
+ const last = index === segments.length - 1;
301
+ if (seg.kind === "key") {
302
+ if (typeof node !== "object" || Array.isArray(node)) {
303
+ if (lenient) return node;
304
+ throw new ValidationError(
305
+ `moneyFields: path "${path}" expected an object at segment "${seg.key}", got ${Array.isArray(node) ? "an array" : typeof node}`
306
+ );
307
+ }
308
+ const obj2 = node;
309
+ if (!(seg.key in obj2) || obj2[seg.key] === null || obj2[seg.key] === void 0) return node;
310
+ if (seg.array) {
311
+ const arr = obj2[seg.key];
312
+ if (!Array.isArray(arr)) {
313
+ if (lenient) return node;
314
+ throw new ValidationError(
315
+ `moneyFields: path "${path}" declares "${seg.key}[]" but the value is not an array`
316
+ );
317
+ }
318
+ const cloned = [...arr];
319
+ if (last) {
320
+ for (let i = 0; i < cloned.length; i++) visit(cloned, i);
321
+ } else {
322
+ for (let i = 0; i < cloned.length; i++) {
323
+ cloned[i] = transformAtMoneyPath(cloned[i], path, segments, index + 1, visit, lenient);
324
+ }
325
+ }
326
+ return { ...obj2, [seg.key]: cloned };
327
+ }
328
+ const clone2 = { ...obj2 };
329
+ if (last) {
330
+ visit(clone2, seg.key);
331
+ } else {
332
+ clone2[seg.key] = transformAtMoneyPath(clone2[seg.key], path, segments, index + 1, visit, lenient);
333
+ }
334
+ return clone2;
335
+ }
336
+ if (seg.array) {
337
+ if (!Array.isArray(node)) {
338
+ if (lenient) return node;
339
+ throw new ValidationError(`moneyFields: path "${path}" declares "*[]" but the value is not an array`);
340
+ }
341
+ const cloned = [...node];
342
+ if (last) {
343
+ for (let i = 0; i < cloned.length; i++) visit(cloned, i);
344
+ } else {
345
+ for (let i = 0; i < cloned.length; i++) {
346
+ cloned[i] = transformAtMoneyPath(cloned[i], path, segments, index + 1, visit, lenient);
347
+ }
348
+ }
349
+ return cloned;
350
+ }
351
+ if (typeof node !== "object" || Array.isArray(node)) {
352
+ if (lenient) return node;
353
+ throw new ValidationError(
354
+ `moneyFields: path "${path}" applies "*" to a non-object (${Array.isArray(node) ? 'array \u2014 use "*[]"' : typeof node})`
355
+ );
356
+ }
357
+ const obj = node;
358
+ const clone = { ...obj };
359
+ for (const key of Object.keys(obj)) {
360
+ const v = clone[key];
361
+ if (v === null || v === void 0) continue;
362
+ if (last) visit(clone, key);
363
+ else clone[key] = transformAtMoneyPath(v, path, segments, index + 1, visit, lenient);
364
+ }
365
+ return clone;
366
+ }
367
+
263
368
  // src/money/normalize.ts
264
369
  function isMoneyValueObject(v) {
265
370
  return typeof v === "object" && v !== null && "currency" in v;
@@ -272,33 +377,68 @@ function quantizeAmount(field, input, scale, rounding) {
272
377
  }
273
378
  return r.value.toString();
274
379
  }
380
+ function canonicalizeStoredMoney(record, moneyFields) {
381
+ if (record === null || record === void 0) return record;
382
+ if (!moneyFields || Object.keys(moneyFields).length === 0) return record;
383
+ return decodeMoneyFields(record, moneyFields, "raw");
384
+ }
385
+ function canonicalizeIncomingMoney(record, moneyFields) {
386
+ if (!moneyFields || Object.keys(moneyFields).length === 0) return record;
387
+ try {
388
+ return decodeMoneyFields(
389
+ quantizeMoneyFields(record, moneyFields),
390
+ moneyFields,
391
+ "raw"
392
+ );
393
+ } catch {
394
+ return record;
395
+ }
396
+ }
397
+ function quantizeValue(field, raw, desc) {
398
+ if (desc.mode === "fixed") {
399
+ const currency2 = desc.fixedCurrency;
400
+ return quantizeAmount(field, raw, desc.scaleFor(currency2), desc.rounding);
401
+ }
402
+ let amount;
403
+ let currency;
404
+ if (isMoneyValueObject(raw)) {
405
+ currency = String(raw.currency);
406
+ amount = raw.amount;
407
+ } else {
408
+ const sole = desc.soleCurrency();
409
+ if (sole === void 0) {
410
+ throw new TypeError(
411
+ `money: field "${field}" is multi-currency \u2014 write { amount, currency }, not a bare amount`
412
+ );
413
+ }
414
+ currency = sole;
415
+ amount = raw;
416
+ }
417
+ const scale = desc.scaleFor(currency);
418
+ return { amount: quantizeAmount(field, amount, scale, desc.rounding), currency };
419
+ }
275
420
  function quantizeMoneyFields(record, moneyFields) {
276
- const out = { ...record };
277
- for (const [field, desc] of Object.entries(moneyFields)) {
278
- const raw = out[field];
279
- if (raw === null || raw === void 0) continue;
280
- if (desc.mode === "fixed") {
281
- const currency2 = desc.fixedCurrency;
282
- out[field] = quantizeAmount(field, raw, desc.scaleFor(currency2), desc.rounding);
421
+ let out = { ...record };
422
+ for (const [path, desc] of Object.entries(moneyFields)) {
423
+ if (isSimpleMoneyPath(path)) {
424
+ const raw = out[path];
425
+ if (raw === null || raw === void 0) continue;
426
+ out[path] = quantizeValue(path, raw, desc);
283
427
  continue;
284
428
  }
285
- let amount;
286
- let currency;
287
- if (isMoneyValueObject(raw)) {
288
- currency = String(raw.currency);
289
- amount = raw.amount;
290
- } else {
291
- const sole = desc.soleCurrency();
292
- if (sole === void 0) {
293
- throw new TypeError(
294
- `money: field "${field}" is multi-currency \u2014 write { amount, currency }, not a bare amount`
295
- );
296
- }
297
- currency = sole;
298
- amount = raw;
299
- }
300
- const scale = desc.scaleFor(currency);
301
- out[field] = { amount: quantizeAmount(field, amount, scale, desc.rounding), currency };
429
+ out = transformAtMoneyPath(
430
+ out,
431
+ path,
432
+ parseMoneyPath(path),
433
+ 0,
434
+ (container, key) => {
435
+ const raw = container[key];
436
+ if (raw === null || raw === void 0) return;
437
+ container[key] = quantizeValue(path, raw, desc);
438
+ },
439
+ /* lenient */
440
+ false
441
+ );
302
442
  }
303
443
  return out;
304
444
  }
@@ -311,33 +451,70 @@ function formatCurrency(decimal, currency, scale, locale) {
311
451
  });
312
452
  return fmt.format(decimal);
313
453
  }
454
+ function decodeValue(stored, desc) {
455
+ let currency;
456
+ let scaledIntString;
457
+ if (desc.mode === "fixed") {
458
+ if (typeof stored !== "string" && typeof stored !== "number") return null;
459
+ currency = desc.fixedCurrency;
460
+ scaledIntString = String(stored);
461
+ } else {
462
+ if (!isMoneyValueObject(stored)) return null;
463
+ const amount = stored.amount;
464
+ if (typeof stored.currency !== "string" || typeof amount !== "string" && typeof amount !== "number") return null;
465
+ currency = stored.currency;
466
+ scaledIntString = String(amount);
467
+ }
468
+ const scale = desc.scaleFor(currency);
469
+ let decimal;
470
+ try {
471
+ decimal = formatScaledInt(BigInt(scaledIntString), scale);
472
+ } catch {
473
+ return null;
474
+ }
475
+ return {
476
+ decoded: desc.mode === "fixed" ? decimal : { amount: decimal, currency },
477
+ decimal,
478
+ currency,
479
+ scale
480
+ };
481
+ }
314
482
  function decodeMoneyFields(record, moneyFields, locale) {
315
- const out = { ...record };
483
+ let out = { ...record };
316
484
  const format = locale !== "raw";
317
485
  const fmtLocale = typeof locale === "string" && locale !== "raw" ? locale : "en-US";
318
- for (const [field, desc] of Object.entries(moneyFields)) {
319
- const stored = out[field];
320
- if (stored === null || stored === void 0) continue;
321
- let currency;
322
- let scaledIntString;
323
- if (desc.mode === "fixed") {
324
- if (typeof stored !== "string" && typeof stored !== "number") continue;
325
- currency = desc.fixedCurrency;
326
- scaledIntString = String(stored);
327
- } else {
328
- if (!isMoneyValueObject(stored)) continue;
329
- const amount = stored.amount;
330
- if (typeof stored.currency !== "string" || typeof amount !== "string" && typeof amount !== "number") continue;
331
- currency = stored.currency;
332
- scaledIntString = String(amount);
333
- }
334
- const scale = desc.scaleFor(currency);
335
- const decimal = formatScaledInt(BigInt(scaledIntString), scale);
336
- out[field] = desc.mode === "fixed" ? decimal : { amount: decimal, currency };
337
- if (format) {
338
- out[`${field}Formatted`] = formatCurrency(decimal, currency, scale, fmtLocale);
339
- out[`${field}Number`] = Number(decimal);
486
+ for (const [path, desc] of Object.entries(moneyFields)) {
487
+ if (isSimpleMoneyPath(path)) {
488
+ const stored = out[path];
489
+ if (stored === null || stored === void 0) continue;
490
+ const r = decodeValue(stored, desc);
491
+ if (r === null) continue;
492
+ out[path] = r.decoded;
493
+ if (format) {
494
+ out[`${path}Formatted`] = formatCurrency(r.decimal, r.currency, r.scale, fmtLocale);
495
+ out[`${path}Number`] = Number(r.decimal);
496
+ }
497
+ continue;
340
498
  }
499
+ out = transformAtMoneyPath(
500
+ out,
501
+ path,
502
+ parseMoneyPath(path),
503
+ 0,
504
+ (container, key) => {
505
+ const stored = container[key];
506
+ if (stored === null || stored === void 0) return;
507
+ const r = decodeValue(stored, desc);
508
+ if (r === null) return;
509
+ container[key] = r.decoded;
510
+ if (format && typeof key === "string" && !Array.isArray(container)) {
511
+ container[`${key}Formatted`] = formatCurrency(r.decimal, r.currency, r.scale, fmtLocale);
512
+ container[`${key}Number`] = Number(r.decimal);
513
+ }
514
+ },
515
+ /* lenient */
516
+ true
517
+ );
341
518
  }
342
519
  return out;
343
520
  }
@@ -434,9 +611,18 @@ var Query = class _Query {
434
611
  this.predicates
435
612
  );
436
613
  }
437
- /** Add a field comparison. Multiple where() calls are AND-combined. */
614
+ /**
615
+ * Add a field comparison. Multiple where() calls are AND-combined.
616
+ *
617
+ * A declared money field compares in MAJOR units (#336): the operand
618
+ * (`10000`, `'10000.00'`, or `{ amount, currency }` in multi mode) is
619
+ * quantized into stored scaled-int space at build time and evaluated
620
+ * BigInt-exact per record. A malformed operand or a string operator
621
+ * (`contains`/`startsWith`) throws here, at the call site.
622
+ */
438
623
  where(field, op, value) {
439
- const clause = { type: "field", field, op, value };
624
+ const desc = this.source.moneyFields?.[field];
625
+ const clause = desc ? moneyFieldClause(field, op, value, desc) : { type: "field", field, op, value };
440
626
  return new _Query(
441
627
  this.source,
442
628
  { ...this.plan, clauses: [...this.plan.clauses, clause] },
@@ -762,7 +948,7 @@ var Query = class _Query {
762
948
  }
763
949
  const { candidates, remainingClauses } = candidateRecords(this.source, this.plan.clauses);
764
950
  if (remainingClauses.length === 0) return candidates.length;
765
- return filterRecords(candidates, remainingClauses).length;
951
+ return filterRecords(candidates, remainingClauses, fnViewDecoder(this.source)).length;
766
952
  }
767
953
  /**
768
954
  * Reduce the matching records through a named set of reducers.
@@ -819,7 +1005,7 @@ var Query = class _Query {
819
1005
  return executeClausePipeline(source, clauses, joinCtx);
820
1006
  }
821
1007
  const { candidates, remainingClauses } = candidateRecords(source, clauses);
822
- return remainingClauses.length === 0 ? candidates : filterRecords(candidates, remainingClauses);
1008
+ return remainingClauses.length === 0 ? candidates : filterRecords(candidates, remainingClauses, fnViewDecoder(source));
823
1009
  };
824
1010
  const upstreams = [];
825
1011
  if (source.subscribe) {
@@ -842,7 +1028,7 @@ var Query = class _Query {
842
1028
  return executeClausePipeline(source, clauses, joinCtx);
843
1029
  }
844
1030
  const { candidates, remainingClauses } = candidateRecords(source, clauses);
845
- return remainingClauses.length === 0 ? candidates : filterRecords(candidates, remainingClauses);
1031
+ return remainingClauses.length === 0 ? candidates : filterRecords(candidates, remainingClauses, fnViewDecoder(source));
846
1032
  };
847
1033
  const upstreams = [];
848
1034
  if (source.subscribe) {
@@ -994,7 +1180,7 @@ function executePlanWithSource(source, plan, joinContext) {
994
1180
  result = executeClausePipeline(source, plan.clauses, joinContext);
995
1181
  } else {
996
1182
  const { candidates, remainingClauses } = candidateRecords(source, plan.clauses);
997
- result = remainingClauses.length === 0 ? [...candidates] : filterRecords(candidates, remainingClauses);
1183
+ result = remainingClauses.length === 0 ? [...candidates] : filterRecords(candidates, remainingClauses, fnViewDecoder(source));
998
1184
  }
999
1185
  if (plan.orderBy.length > 0) {
1000
1186
  result = sortRecords(result, plan.orderBy);
@@ -1017,6 +1203,7 @@ function candidateRecords(source, clauses) {
1017
1203
  const clause = clauses[i];
1018
1204
  if (clause.type !== "field") continue;
1019
1205
  if (!indexes.has(clause.field)) continue;
1206
+ if (clause.money?.mode === "multi") continue;
1020
1207
  let ids = null;
1021
1208
  if (clause.op === "==") {
1022
1209
  ids = indexes.lookupEqual(clause.field, clause.value);
@@ -1062,13 +1249,20 @@ function executePlan(records, plan) {
1062
1249
  }
1063
1250
  return result;
1064
1251
  }
1065
- function filterRecords(records, clauses) {
1252
+ function fnViewDecoder(source) {
1253
+ const mf = source.moneyFields;
1254
+ if (!mf || Object.keys(mf).length === 0) return void 0;
1255
+ return (r) => decodeMoneyFields(r, mf, "raw");
1256
+ }
1257
+ function filterRecords(records, clauses, decodeForFns) {
1066
1258
  if (clauses.length === 0) return [...records];
1259
+ const needsFnView = decodeForFns !== void 0 && hasFnClause(clauses);
1067
1260
  const out = [];
1068
1261
  for (const r of records) {
1262
+ const fnView = needsFnView ? decodeForFns(r) : void 0;
1069
1263
  let matches = true;
1070
1264
  for (const clause of clauses) {
1071
- if (!evaluateClause(r, clause)) {
1265
+ if (!evaluateClause(r, clause, fnView)) {
1072
1266
  matches = false;
1073
1267
  break;
1074
1268
  }
@@ -1080,10 +1274,11 @@ function filterRecords(records, clauses) {
1080
1274
  function executeClausePipeline(source, clauses, joinContext) {
1081
1275
  let rel = [...source.snapshot()];
1082
1276
  let filterBatch = [];
1277
+ const decodeForFns = fnViewDecoder(source);
1083
1278
  for (const clause of clauses) {
1084
1279
  if (clause.type === "crossJoin") {
1085
1280
  if (filterBatch.length > 0) {
1086
- rel = filterRecords(rel, filterBatch);
1281
+ rel = filterRecords(rel, filterBatch, decodeForFns);
1087
1282
  filterBatch = [];
1088
1283
  }
1089
1284
  const rightSource = joinContext.resolveSource(clause.target);
@@ -1096,7 +1291,7 @@ function executeClausePipeline(source, clauses, joinContext) {
1096
1291
  }
1097
1292
  }
1098
1293
  if (filterBatch.length > 0) {
1099
- rel = filterRecords(rel, filterBatch);
1294
+ rel = filterRecords(rel, filterBatch, decodeForFns);
1100
1295
  }
1101
1296
  return rel;
1102
1297
  }
@@ -1331,7 +1526,8 @@ var ScanBuilder = class _ScanBuilder {
1331
1526
  * evaluates clauses per record in O(1) per clause.
1332
1527
  */
1333
1528
  where(field, op, value) {
1334
- const clause = { type: "field", field, op, value };
1529
+ const desc = this.moneyFields?.[field];
1530
+ const clause = desc ? moneyFieldClause(field, op, value, desc) : { type: "field", field, op, value };
1335
1531
  return new _ScanBuilder(
1336
1532
  this.pageProvider,
1337
1533
  this.pageSize,
@@ -1677,8 +1873,9 @@ var ScanBuilder = class _ScanBuilder {
1677
1873
  */
1678
1874
  recordMatches(record) {
1679
1875
  if (this.clauses.length === 0) return true;
1876
+ const fnView = this.moneyFields && Object.keys(this.moneyFields).length > 0 && hasFnClause(this.clauses) ? this.decodeMoney(record) : void 0;
1680
1877
  for (const clause of this.clauses) {
1681
- if (!evaluateClause(record, clause)) return false;
1878
+ if (!evaluateClause(record, clause, fnView)) return false;
1682
1879
  }
1683
1880
  return true;
1684
1881
  }
@@ -1691,6 +1888,9 @@ function coerceRefKey2(value) {
1691
1888
  }
1692
1889
 
1693
1890
  export {
1891
+ validateMoneyFieldPaths,
1892
+ canonicalizeStoredMoney,
1893
+ canonicalizeIncomingMoney,
1694
1894
  quantizeMoneyFields,
1695
1895
  decodeMoneyFields,
1696
1896
  DEFAULT_JOIN_MAX_ROWS,
@@ -1703,4 +1903,4 @@ export {
1703
1903
  executePlan,
1704
1904
  ScanBuilder
1705
1905
  };
1706
- //# sourceMappingURL=chunk-KGCORI4L.js.map
1906
+ //# sourceMappingURL=chunk-EYVQHAGH.js.map