@absolutejs/sync 2.1.0 → 2.2.1

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.
@@ -1,4 +1,4 @@
1
- import type { RowKey } from './types';
1
+ import type { RowChange, RowKey } from './types';
2
2
  /**
3
3
  * App-provided context for a subscription — typically the authenticated session
4
4
  * (user id, roles). Passed to `authorize`, `hydrate`, and `match` so a
@@ -32,6 +32,19 @@ export type CollectionDefinition<T, P = void, Ctx = CollectionContext> = {
32
32
  * two in lockstep — the planned adapter convenience.)
33
33
  */
34
34
  match?: (row: T, params: P, ctx: Ctx) => boolean;
35
+ /**
36
+ * Refetch-fallback gate (multi-table / shape-mismatched collections that can't
37
+ * use `match`). Without it, ANY change to a read table re-hydrates EVERY
38
+ * subscription — even ones the change can't touch. Given the RAW change (the
39
+ * source row, which may differ from `T` and be partial), return `false` ONLY
40
+ * when the change provably can't affect this subscription's result, to skip
41
+ * its re-hydrate; the fan-out drops from O(all subscribers) to O(affected).
42
+ *
43
+ * Conservative: a `false` that should have been `true` DROPS an update, so
44
+ * default to `true` when unsure (e.g. a delete whose row lacks your scope
45
+ * field). Ignored when `match` is set (incremental routing is already exact).
46
+ */
47
+ affects?: (change: RowChange<unknown>, params: P, ctx: Ctx) => boolean;
35
48
  /**
36
49
  * Access control: return `false` (or throw) to deny the subscription. Runs
37
50
  * before `hydrate`. Without it a collection is world-readable, so treat it as
@@ -1799,6 +1799,9 @@ var createSyncEngine = (options = {}) => {
1799
1799
  return subscription.view.reset(await subscription.rehydrate());
1800
1800
  }
1801
1801
  }
1802
+ if (subscription.affects && !subscription.affects(change)) {
1803
+ return EMPTY_DIFF;
1804
+ }
1802
1805
  return subscription.view.reset(await subscription.rehydrate());
1803
1806
  };
1804
1807
  const subscriptionsForTable = function* (table) {
@@ -2591,6 +2594,7 @@ var createSyncEngine = (options = {}) => {
2591
2594
  return readRule ? rows.filter((row) => readRule(ctx, row)) : rows;
2592
2595
  };
2593
2596
  const incremental = match !== undefined && tables.length === 1;
2597
+ const boundAffects = !incremental && definition.affects ? (change) => definition.affects(change, params, ctx) : undefined;
2594
2598
  const boundMatch = incremental ? (row) => match(row, params, ctx) && (readRule ? readRule(ctx, row) : true) : () => true;
2595
2599
  const view = createMaterializedView({
2596
2600
  key,
@@ -2605,6 +2609,7 @@ var createSyncEngine = (options = {}) => {
2605
2609
  view,
2606
2610
  incremental,
2607
2611
  rehydrate,
2612
+ ...boundAffects ? { affects: boundAffects } : {},
2608
2613
  key,
2609
2614
  onDiff: typedOnDiff
2610
2615
  };
@@ -3788,5 +3793,5 @@ export {
3788
3793
  CdcConsumerSlowError
3789
3794
  };
3790
3795
 
3791
- //# debugId=34D5A585C92FDCCE64756E2164756E21
3796
+ //# debugId=40999B3553DAC88C64756E2164756E21
3792
3797
  //# sourceMappingURL=index.js.map