@fluixi/reactive 1.0.0-alpha.92 → 1.0.0-alpha.94

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 (92) hide show
  1. package/dist/cdn/reactive.cjs +105 -35
  2. package/dist/cdn/reactive.global.js +2 -2
  3. package/dist/cdn/reactive.mjs +105 -35
  4. package/dist/cdn/signal.cjs +1 -1
  5. package/dist/cdn/signal.global.js +2 -2
  6. package/dist/cdn/signal.mjs +1 -1
  7. package/dist/index.cjs +105 -35
  8. package/dist/index.mjs +105 -35
  9. package/dist/lib/index.cjs +106 -36
  10. package/dist/lib/index.mjs +106 -36
  11. package/dist/lib/observable/index.cjs +1 -1
  12. package/dist/lib/observable/index.mjs +1 -1
  13. package/dist/lib/signal/api.cjs +11 -10
  14. package/dist/lib/signal/api.d.ts +5 -1
  15. package/dist/lib/signal/api.d.ts.map +1 -1
  16. package/dist/lib/signal/api.js +4 -2
  17. package/dist/lib/signal/api.mjs +11 -10
  18. package/dist/lib/signal/cached-resource.cjs +77 -34
  19. package/dist/lib/signal/cached-resource.d.ts +48 -68
  20. package/dist/lib/signal/cached-resource.d.ts.map +1 -1
  21. package/dist/lib/signal/cached-resource.js +59 -72
  22. package/dist/lib/signal/cached-resource.mjs +77 -34
  23. package/dist/lib/signal/graph/children.cjs +3 -2
  24. package/dist/lib/signal/graph/children.mjs +3 -2
  25. package/dist/lib/signal/graph/compat.cjs +10 -9
  26. package/dist/lib/signal/graph/compat.d.ts +3 -1
  27. package/dist/lib/signal/graph/compat.d.ts.map +1 -1
  28. package/dist/lib/signal/graph/compat.js +2 -2
  29. package/dist/lib/signal/graph/compat.mjs +10 -9
  30. package/dist/lib/signal/graph/core.cjs +2 -2
  31. package/dist/lib/signal/graph/core.mjs +2 -2
  32. package/dist/lib/signal/graph/debounced.cjs +9 -8
  33. package/dist/lib/signal/graph/debounced.mjs +9 -8
  34. package/dist/lib/signal/graph/derived.cjs +9 -8
  35. package/dist/lib/signal/graph/derived.mjs +9 -8
  36. package/dist/lib/signal/graph/error-boundary.cjs +3 -2
  37. package/dist/lib/signal/graph/error-boundary.mjs +3 -2
  38. package/dist/lib/signal/graph/index.cjs +2 -2
  39. package/dist/lib/signal/graph/index.mjs +2 -2
  40. package/dist/lib/signal/graph/observe.cjs +38 -3
  41. package/dist/lib/signal/graph/observe.d.ts +44 -0
  42. package/dist/lib/signal/graph/observe.d.ts.map +1 -1
  43. package/dist/lib/signal/graph/observe.js +50 -1
  44. package/dist/lib/signal/graph/observe.mjs +38 -3
  45. package/dist/lib/signal/graph/resource.cjs +9 -8
  46. package/dist/lib/signal/graph/resource.mjs +9 -8
  47. package/dist/lib/signal/graph/runtime.cjs +7 -6
  48. package/dist/lib/signal/graph/runtime.d.ts +1 -1
  49. package/dist/lib/signal/graph/runtime.d.ts.map +1 -1
  50. package/dist/lib/signal/graph/runtime.js +4 -4
  51. package/dist/lib/signal/graph/runtime.mjs +7 -6
  52. package/dist/lib/signal/graph/signal-next.cjs +39 -9
  53. package/dist/lib/signal/graph/signal-next.d.ts +1 -1
  54. package/dist/lib/signal/graph/signal-next.d.ts.map +1 -1
  55. package/dist/lib/signal/graph/signal-next.js +1 -1
  56. package/dist/lib/signal/graph/signal-next.mjs +39 -9
  57. package/dist/lib/signal/graph/ssr-hooks.cjs +29 -0
  58. package/dist/lib/signal/graph/ssr-hooks.d.ts +24 -0
  59. package/dist/lib/signal/graph/ssr-hooks.d.ts.map +1 -1
  60. package/dist/lib/signal/graph/ssr-hooks.js +36 -0
  61. package/dist/lib/signal/graph/ssr-hooks.mjs +29 -0
  62. package/dist/lib/signal/graph/state.cjs +1 -1
  63. package/dist/lib/signal/graph/state.mjs +1 -1
  64. package/dist/lib/signal/graph/suspense.cjs +3 -2
  65. package/dist/lib/signal/graph/suspense.mjs +3 -2
  66. package/dist/lib/signal/index-legacy.cjs +65 -34
  67. package/dist/lib/signal/index-legacy.mjs +65 -34
  68. package/dist/lib/signal/index.cjs +76 -12
  69. package/dist/lib/signal/index.d.ts +2 -1
  70. package/dist/lib/signal/index.d.ts.map +1 -1
  71. package/dist/lib/signal/index.js +1 -1
  72. package/dist/lib/signal/index.mjs +76 -12
  73. package/dist/lib/signal/list.cjs +3 -2
  74. package/dist/lib/signal/list.mjs +3 -2
  75. package/dist/lib/signal/resource-api.cjs +9 -8
  76. package/dist/lib/signal/resource-api.mjs +9 -8
  77. package/dist/lib/signal/signal.cjs +9 -8
  78. package/dist/lib/signal/signal.mjs +9 -8
  79. package/dist/lib/signal/utilities.cjs +10 -9
  80. package/dist/lib/signal/utilities.mjs +10 -9
  81. package/dist/lib/store/api.cjs +3 -2
  82. package/dist/lib/store/api.mjs +3 -2
  83. package/dist/lib/store/index.cjs +4 -3
  84. package/dist/lib/store/index.mjs +4 -3
  85. package/dist/lib/store/store.cjs +3 -2
  86. package/dist/lib/store/store.mjs +3 -2
  87. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  88. package/dist/version.generated.cjs +2 -2
  89. package/dist/version.generated.d.ts +1 -1
  90. package/dist/version.generated.js +1 -1
  91. package/dist/version.generated.mjs +2 -2
  92. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- /*! @fluixi/reactive v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/reactive v1.0.0-alpha.94 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -40,15 +40,16 @@ __export(index_exports, {
40
40
  SuspenseContext: () => SuspenseContext,
41
41
  VERSION: () => VERSION,
42
42
  __DEV__: () => __DEV__,
43
+ adoptReactiveScope: () => adoptReactiveScope,
43
44
  batch: () => batch2,
45
+ cachedResource: () => cachedResource,
44
46
  childOwner: () => childOwner,
45
- clearAllCachedResources: () => clearAllCachedResources,
46
- clearCachedResourceNamespace: () => clearCachedResourceNamespace,
47
+ clearCachedResources: () => clearCachedResources,
48
+ closeReactiveScope: () => closeReactiveScope,
47
49
  combineSignal: () => combineSignal,
48
50
  combineSignals: () => combineSignals,
49
51
  computed: () => computed,
50
52
  context: () => context,
51
- createCachedResource: () => createCachedResource,
52
53
  createChildOwner: () => createChildOwner,
53
54
  createComputed: () => createComputed,
54
55
  createComputedStore: () => createComputedStore,
@@ -63,6 +64,7 @@ __export(index_exports, {
63
64
  createMutableStore: () => createMutableStore,
64
65
  createRenderEffect: () => createRenderEffect,
65
66
  createResource: () => createResource,
67
+ createResourceCache: () => createResourceCache,
66
68
  createRoot: () => createRoot,
67
69
  createSelector: () => createSelector,
68
70
  createSignal: () => createSignal,
@@ -70,6 +72,7 @@ __export(index_exports, {
70
72
  createStoreEffect: () => createStoreEffect,
71
73
  createStoreMemo: () => createStoreMemo,
72
74
  createSuspenseBoundary: () => createSuspenseBoundary,
75
+ currentResourceCache: () => currentResourceCache,
73
76
  debounceSignal: () => debounceSignal,
74
77
  disposeScope: () => disposeScope,
75
78
  distinctSignal: () => distinctSignal,
@@ -98,6 +101,7 @@ __export(index_exports, {
98
101
  makeArrayFlat: () => makeArrayFlat,
99
102
  mapArray: () => mapArray,
100
103
  mapSignal: () => mapSignal,
104
+ markReactiveScope: () => markReactiveScope,
101
105
  memo: () => memo,
102
106
  mergeSignal: () => mergeSignal,
103
107
  modifiable: () => modifiable,
@@ -106,12 +110,14 @@ __export(index_exports, {
106
110
  omitSignal: () => omitSignal,
107
111
  on: () => on,
108
112
  onCleanup: () => onCleanup,
113
+ openReactiveScope: () => openReactiveScope,
109
114
  operate: () => operate,
110
115
  pickSignal: () => pickSignal,
111
116
  produceUtil: () => produce,
112
117
  provide: () => provide,
113
118
  provideErrorBoundary: () => provideErrorBoundary,
114
119
  provideSuspense: () => provideSuspense,
120
+ reactiveScopeOf: () => reactiveScopeOf,
115
121
  readChildren: () => readChildren,
116
122
  readSignal: () => readSignal,
117
123
  reconcileUtil: () => reconcile,
@@ -128,6 +134,7 @@ __export(index_exports, {
128
134
  runWithOwner: () => runWithOwner,
129
135
  selectSignal: () => selectSignal,
130
136
  setOwner: () => setOwner,
137
+ setResourceCacheScope: () => setResourceCacheScope,
131
138
  setResourceDataSink: () => setResourceDataSink,
132
139
  setResourceIdSource: () => setResourceIdSource,
133
140
  setResourceTracker: () => setResourceTracker,
@@ -145,13 +152,14 @@ __export(index_exports, {
145
152
  useContext: () => useContext,
146
153
  useTransition: () => useTransition,
147
154
  whenSignal: () => whenSignal,
155
+ withReactiveScope: () => withReactiveScope,
148
156
  wrap: () => wrap,
149
157
  zipSignal: () => zipSignal
150
158
  });
151
159
  module.exports = __toCommonJS(index_exports);
152
160
 
153
161
  // src/version.generated.ts
154
- var VERSION = "1.0.0-alpha.92";
162
+ var VERSION = "1.0.0-alpha.94";
155
163
 
156
164
  // src/lib/predicates.ts
157
165
  function isFunction(value) {
@@ -642,11 +650,40 @@ function withReactiveOrigin(owner, fn) {
642
650
  origin = previous;
643
651
  }
644
652
  }
653
+ var currentScope;
654
+ function openReactiveScope(info) {
655
+ const scope = {};
656
+ G.observer?.scope?.(scope, info, currentScope);
657
+ return scope;
658
+ }
659
+ function withReactiveScope(scope, fn) {
660
+ if (!G.observer) return fn();
661
+ const previous = currentScope;
662
+ currentScope = scope;
663
+ try {
664
+ return fn();
665
+ } finally {
666
+ currentScope = previous;
667
+ }
668
+ }
669
+ function closeReactiveScope(scope) {
670
+ G.observer?.scopeEnded?.(scope);
671
+ }
672
+ function adoptReactiveScope(scope, parent) {
673
+ G.observer?.scopeAdopted?.(scope, parent);
674
+ }
675
+ var SCOPE_OF = /* @__PURE__ */ Symbol.for("fluixi.reactiveScope");
676
+ function markReactiveScope(value, scope) {
677
+ Object.defineProperty(value, SCOPE_OF, { value: scope, configurable: true, enumerable: false });
678
+ }
679
+ function reactiveScopeOf(value) {
680
+ return value !== null && (typeof value === "object" || typeof value === "function") ? value[SCOPE_OF] ?? void 0 : void 0;
681
+ }
645
682
  function reportReactiveNode(report) {
646
683
  const observer = G.observer;
647
684
  if (observer) {
648
685
  observer.created(
649
- report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin } : report
686
+ report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin, scope: report.scope ?? currentScope } : { ...report, scope: report.scope ?? currentScope }
650
687
  );
651
688
  }
652
689
  }
@@ -1066,7 +1103,7 @@ function batch(fn) {
1066
1103
  }
1067
1104
  }
1068
1105
  var EffectNode = class {
1069
- constructor(fn, report = false) {
1106
+ constructor(fn, report = false, name) {
1070
1107
  this.queued = false;
1071
1108
  this.disposed = false;
1072
1109
  this.owner = makeOwner(G.owner);
@@ -1078,7 +1115,7 @@ var EffectNode = class {
1078
1115
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
1079
1116
  });
1080
1117
  });
1081
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report });
1118
+ reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
1082
1119
  this.watcher = new Watcher(() => enqueue(this));
1083
1120
  this.run();
1084
1121
  this.watcher.watch(this.computed);
@@ -1105,8 +1142,8 @@ var EffectNode = class {
1105
1142
  disposeOwner(this.owner);
1106
1143
  }
1107
1144
  };
1108
- function effect(fn, report = false) {
1109
- const node = new EffectNode(fn, report);
1145
+ function effect(fn, report = false, name) {
1146
+ const node = new EffectNode(fn, report, name);
1110
1147
  return () => node.dispose();
1111
1148
  }
1112
1149
 
@@ -1174,12 +1211,12 @@ function createMemo(fn, value, options) {
1174
1211
  if (isObserved()) onCleanup(() => reportReactiveDispose(c));
1175
1212
  return read;
1176
1213
  }
1177
- function createEffect(fn, value) {
1214
+ function createEffect(fn, value, options) {
1178
1215
  let prev = value;
1179
1216
  return effect(() => {
1180
1217
  const r = fn(prev);
1181
1218
  prev = r;
1182
- }, true);
1219
+ }, true, options?.name);
1183
1220
  }
1184
1221
  function createComputed(fn, value) {
1185
1222
  let prev = value;
@@ -1425,6 +1462,32 @@ function setResourceDataSink(fn) {
1425
1462
  function reportResourceData(id, value) {
1426
1463
  if (_resourceDataSink) _resourceDataSink(id, value);
1427
1464
  }
1465
+ function createResourceCache() {
1466
+ const entries = /* @__PURE__ */ new Map();
1467
+ const inflight = /* @__PURE__ */ new Map();
1468
+ return {
1469
+ get: (key) => entries.get(key),
1470
+ set: (key, entry) => void entries.set(key, entry),
1471
+ delete: (key) => void entries.delete(key),
1472
+ keys: () => entries.keys(),
1473
+ clear: () => {
1474
+ entries.clear();
1475
+ inflight.clear();
1476
+ },
1477
+ inflight
1478
+ };
1479
+ }
1480
+ var _cacheScope = null;
1481
+ function setResourceCacheScope(fn) {
1482
+ _cacheScope = fn;
1483
+ }
1484
+ var _pageCache;
1485
+ function currentResourceCache() {
1486
+ const scoped = _cacheScope?.();
1487
+ if (scoped) return scoped;
1488
+ if (typeof window === "undefined") return createResourceCache();
1489
+ return _pageCache ??= createResourceCache();
1490
+ }
1428
1491
 
1429
1492
  // src/lib/signal/graph/derived.ts
1430
1493
  function createSelector(source, fn = (k, v) => k === v) {
@@ -1744,8 +1807,8 @@ function signal(value, options) {
1744
1807
  function memo(fn, value, options) {
1745
1808
  return createMemo(fn, value, options);
1746
1809
  }
1747
- function effect2(fn, value) {
1748
- return createEffect(fn, value);
1810
+ function effect2(fn, value, options) {
1811
+ return createEffect(fn, value, options);
1749
1812
  }
1750
1813
  function root(fn) {
1751
1814
  return createRoot(fn);
@@ -2528,12 +2591,10 @@ function readSignal(signal2) {
2528
2591
  }
2529
2592
 
2530
2593
  // src/lib/signal/cached-resource.ts
2531
- var ttlCache = /* @__PURE__ */ new Map();
2532
- var inflight = /* @__PURE__ */ new Map();
2533
2594
  var _autoId = 0;
2534
2595
  var $SIGNAL4 = /* @__PURE__ */ Symbol.for("signal");
2535
2596
  var $RESOURCE2 = /* @__PURE__ */ Symbol.for("resource");
2536
- function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2597
+ function cachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2537
2598
  let sourceFn;
2538
2599
  let fetchFn;
2539
2600
  let options;
@@ -2552,7 +2613,13 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2552
2613
  staleWhileRevalidate = true
2553
2614
  } = options;
2554
2615
  const ns = name;
2555
- const buildKey = (key) => `${ns}:${JSON.stringify(key)}`;
2616
+ const cache = options.cache ?? currentResourceCache();
2617
+ const inflight = cache.inflight;
2618
+ const ssrId = options.transport === false ? void 0 : nextResourceId();
2619
+ const seed = ssrId !== void 0 ? getServerData(ssrId) : void 0;
2620
+ const deps = options.deps ?? [];
2621
+ const depValues = () => deps.map((dep) => dep());
2622
+ const buildKey = (key, values = untrack2(depValues)) => `${ns}:${JSON.stringify(key)}` + (deps.length ? `:${JSON.stringify(values)}` : "");
2556
2623
  const isFresh = (entry) => ttl === Infinity || Date.now() - entry.timestamp <= ttl;
2557
2624
  const [value, setValue] = createSignal(void 0, { equals: false });
2558
2625
  const [resourceState, setResourceState] = createSignal("unresolved", { equals: false });
@@ -2565,8 +2632,9 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2565
2632
  let flagRefetch = false;
2566
2633
  let flagInvalidate = false;
2567
2634
  function doFetch(key, ck, background, isCancelled) {
2568
- if (inflight.has(ck)) {
2569
- inflight.get(ck).then(
2635
+ const running2 = inflight.get(ck);
2636
+ if (running2) {
2637
+ running2.then(
2570
2638
  (v) => {
2571
2639
  if (!isCancelled()) settle(v, background);
2572
2640
  },
@@ -2574,12 +2642,15 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2574
2642
  if (!isCancelled() && !background) fail(e);
2575
2643
  }
2576
2644
  );
2577
- if (!background) setPendingP(inflight.get(ck));
2645
+ if (!background) {
2646
+ trackResourcePromise(running2);
2647
+ setPendingP(running2);
2648
+ }
2578
2649
  return;
2579
2650
  }
2580
2651
  const promise = Promise.resolve(fetchFn(key)).then(
2581
2652
  (v) => {
2582
- ttlCache.set(ck, { value: v, timestamp: Date.now() });
2653
+ cache.set(ck, { value: v, timestamp: Date.now() });
2583
2654
  inflight.delete(ck);
2584
2655
  return v;
2585
2656
  },
@@ -2602,7 +2673,8 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2602
2673
  }
2603
2674
  );
2604
2675
  }
2605
- function settle(v, background) {
2676
+ function settle(v, _background) {
2677
+ if (ssrId !== void 0) reportResourceData(ssrId, v);
2606
2678
  batch2(() => {
2607
2679
  setValue(() => v);
2608
2680
  setResourceState("ready");
@@ -2620,6 +2692,7 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2620
2692
  }
2621
2693
  createEffect(() => {
2622
2694
  const key = sourceFn();
2695
+ const values = depValues();
2623
2696
  tick();
2624
2697
  if (key === false || key === null || key === void 0) {
2625
2698
  prevKey = UNSET2;
@@ -2634,16 +2707,18 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2634
2707
  const doInvalidate = flagInvalidate;
2635
2708
  flagRefetch = false;
2636
2709
  flagInvalidate = false;
2637
- const ck = buildKey(key);
2638
- if (doInvalidate) ttlCache.delete(ck);
2710
+ const ck = buildKey(key, values);
2711
+ if (seed && prevKey === UNSET2 && !cache.get(ck)) cache.set(ck, { value: seed.value, timestamp: Date.now() });
2712
+ if (doInvalidate) cache.delete(ck);
2639
2713
  const keyChanged = prevKey === UNSET2 || key !== prevKey;
2640
2714
  prevKey = key;
2641
2715
  let cancelled = false;
2642
2716
  onCleanup(() => {
2643
2717
  cancelled = true;
2644
2718
  });
2645
- const cached = ttlCache.get(ck);
2719
+ const cached = cache.get(ck);
2646
2720
  if (cached && isFresh(cached) && !doRefetch && !doInvalidate) {
2721
+ if (ssrId !== void 0) reportResourceData(ssrId, cached.value);
2647
2722
  const cur2 = untrack2(resourceState);
2648
2723
  if (cur2 !== "ready" || untrack2(value) !== cached.value) {
2649
2724
  batch2(() => {
@@ -2704,20 +2779,15 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2704
2779
  const invalidate = () => {
2705
2780
  const key = untrack2(sourceFn);
2706
2781
  if (key !== null && key !== void 0 && key !== false) {
2707
- ttlCache.delete(buildKey(key));
2782
+ cache.delete(buildKey(key));
2708
2783
  }
2709
2784
  flagInvalidate = true;
2710
2785
  setTick((v) => v + 1);
2711
2786
  };
2712
- return [resource2, { mutate: setValue, refetch, invalidate }];
2787
+ return Object.assign(resource2, { mutate: setValue, refetch, invalidate });
2713
2788
  }
2714
- function clearCachedResourceNamespace(name) {
2789
+ function clearCachedResources(name, cache = currentResourceCache()) {
2790
+ if (name === void 0) return cache.clear();
2715
2791
  const prefix = `${name}:`;
2716
- for (const key of ttlCache.keys()) {
2717
- if (key.startsWith(prefix)) ttlCache.delete(key);
2718
- }
2719
- }
2720
- function clearAllCachedResources() {
2721
- ttlCache.clear();
2722
- inflight.clear();
2792
+ for (const key of [...cache.keys()]) if (key.startsWith(prefix)) cache.delete(key);
2723
2793
  }
@@ -1,7 +1,7 @@
1
- /*! @fluixi/reactive v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/reactive v1.0.0-alpha.94 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
 
3
3
  // src/version.generated.ts
4
- var VERSION = "1.0.0-alpha.92";
4
+ var VERSION = "1.0.0-alpha.94";
5
5
 
6
6
  // src/lib/predicates.ts
7
7
  function isFunction(value) {
@@ -492,11 +492,40 @@ function withReactiveOrigin(owner, fn) {
492
492
  origin = previous;
493
493
  }
494
494
  }
495
+ var currentScope;
496
+ function openReactiveScope(info) {
497
+ const scope = {};
498
+ G.observer?.scope?.(scope, info, currentScope);
499
+ return scope;
500
+ }
501
+ function withReactiveScope(scope, fn) {
502
+ if (!G.observer) return fn();
503
+ const previous = currentScope;
504
+ currentScope = scope;
505
+ try {
506
+ return fn();
507
+ } finally {
508
+ currentScope = previous;
509
+ }
510
+ }
511
+ function closeReactiveScope(scope) {
512
+ G.observer?.scopeEnded?.(scope);
513
+ }
514
+ function adoptReactiveScope(scope, parent) {
515
+ G.observer?.scopeAdopted?.(scope, parent);
516
+ }
517
+ var SCOPE_OF = /* @__PURE__ */ Symbol.for("fluixi.reactiveScope");
518
+ function markReactiveScope(value, scope) {
519
+ Object.defineProperty(value, SCOPE_OF, { value: scope, configurable: true, enumerable: false });
520
+ }
521
+ function reactiveScopeOf(value) {
522
+ return value !== null && (typeof value === "object" || typeof value === "function") ? value[SCOPE_OF] ?? void 0 : void 0;
523
+ }
495
524
  function reportReactiveNode(report) {
496
525
  const observer = G.observer;
497
526
  if (observer) {
498
527
  observer.created(
499
- report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin } : report
528
+ report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin, scope: report.scope ?? currentScope } : { ...report, scope: report.scope ?? currentScope }
500
529
  );
501
530
  }
502
531
  }
@@ -916,7 +945,7 @@ function batch(fn) {
916
945
  }
917
946
  }
918
947
  var EffectNode = class {
919
- constructor(fn, report = false) {
948
+ constructor(fn, report = false, name) {
920
949
  this.queued = false;
921
950
  this.disposed = false;
922
951
  this.owner = makeOwner(G.owner);
@@ -928,7 +957,7 @@ var EffectNode = class {
928
957
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
929
958
  });
930
959
  });
931
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report });
960
+ reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
932
961
  this.watcher = new Watcher(() => enqueue(this));
933
962
  this.run();
934
963
  this.watcher.watch(this.computed);
@@ -955,8 +984,8 @@ var EffectNode = class {
955
984
  disposeOwner(this.owner);
956
985
  }
957
986
  };
958
- function effect(fn, report = false) {
959
- const node = new EffectNode(fn, report);
987
+ function effect(fn, report = false, name) {
988
+ const node = new EffectNode(fn, report, name);
960
989
  return () => node.dispose();
961
990
  }
962
991
 
@@ -1024,12 +1053,12 @@ function createMemo(fn, value, options) {
1024
1053
  if (isObserved()) onCleanup(() => reportReactiveDispose(c));
1025
1054
  return read;
1026
1055
  }
1027
- function createEffect(fn, value) {
1056
+ function createEffect(fn, value, options) {
1028
1057
  let prev = value;
1029
1058
  return effect(() => {
1030
1059
  const r = fn(prev);
1031
1060
  prev = r;
1032
- }, true);
1061
+ }, true, options?.name);
1033
1062
  }
1034
1063
  function createComputed(fn, value) {
1035
1064
  let prev = value;
@@ -1275,6 +1304,32 @@ function setResourceDataSink(fn) {
1275
1304
  function reportResourceData(id, value) {
1276
1305
  if (_resourceDataSink) _resourceDataSink(id, value);
1277
1306
  }
1307
+ function createResourceCache() {
1308
+ const entries = /* @__PURE__ */ new Map();
1309
+ const inflight = /* @__PURE__ */ new Map();
1310
+ return {
1311
+ get: (key) => entries.get(key),
1312
+ set: (key, entry) => void entries.set(key, entry),
1313
+ delete: (key) => void entries.delete(key),
1314
+ keys: () => entries.keys(),
1315
+ clear: () => {
1316
+ entries.clear();
1317
+ inflight.clear();
1318
+ },
1319
+ inflight
1320
+ };
1321
+ }
1322
+ var _cacheScope = null;
1323
+ function setResourceCacheScope(fn) {
1324
+ _cacheScope = fn;
1325
+ }
1326
+ var _pageCache;
1327
+ function currentResourceCache() {
1328
+ const scoped = _cacheScope?.();
1329
+ if (scoped) return scoped;
1330
+ if (typeof window === "undefined") return createResourceCache();
1331
+ return _pageCache ??= createResourceCache();
1332
+ }
1278
1333
 
1279
1334
  // src/lib/signal/graph/derived.ts
1280
1335
  function createSelector(source, fn = (k, v) => k === v) {
@@ -1594,8 +1649,8 @@ function signal(value, options) {
1594
1649
  function memo(fn, value, options) {
1595
1650
  return createMemo(fn, value, options);
1596
1651
  }
1597
- function effect2(fn, value) {
1598
- return createEffect(fn, value);
1652
+ function effect2(fn, value, options) {
1653
+ return createEffect(fn, value, options);
1599
1654
  }
1600
1655
  function root(fn) {
1601
1656
  return createRoot(fn);
@@ -2385,12 +2440,10 @@ function readSignal(signal2) {
2385
2440
  }
2386
2441
 
2387
2442
  // src/lib/signal/cached-resource.ts
2388
- var ttlCache = /* @__PURE__ */ new Map();
2389
- var inflight = /* @__PURE__ */ new Map();
2390
2443
  var _autoId = 0;
2391
2444
  var $SIGNAL4 = /* @__PURE__ */ Symbol.for("signal");
2392
2445
  var $RESOURCE2 = /* @__PURE__ */ Symbol.for("resource");
2393
- function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2446
+ function cachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2394
2447
  let sourceFn;
2395
2448
  let fetchFn;
2396
2449
  let options;
@@ -2409,7 +2462,13 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2409
2462
  staleWhileRevalidate = true
2410
2463
  } = options;
2411
2464
  const ns = name;
2412
- const buildKey = (key) => `${ns}:${JSON.stringify(key)}`;
2465
+ const cache = options.cache ?? currentResourceCache();
2466
+ const inflight = cache.inflight;
2467
+ const ssrId = options.transport === false ? void 0 : nextResourceId();
2468
+ const seed = ssrId !== void 0 ? getServerData(ssrId) : void 0;
2469
+ const deps = options.deps ?? [];
2470
+ const depValues = () => deps.map((dep) => dep());
2471
+ const buildKey = (key, values = untrack2(depValues)) => `${ns}:${JSON.stringify(key)}` + (deps.length ? `:${JSON.stringify(values)}` : "");
2413
2472
  const isFresh = (entry) => ttl === Infinity || Date.now() - entry.timestamp <= ttl;
2414
2473
  const [value, setValue] = createSignal(void 0, { equals: false });
2415
2474
  const [resourceState, setResourceState] = createSignal("unresolved", { equals: false });
@@ -2422,8 +2481,9 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2422
2481
  let flagRefetch = false;
2423
2482
  let flagInvalidate = false;
2424
2483
  function doFetch(key, ck, background, isCancelled) {
2425
- if (inflight.has(ck)) {
2426
- inflight.get(ck).then(
2484
+ const running2 = inflight.get(ck);
2485
+ if (running2) {
2486
+ running2.then(
2427
2487
  (v) => {
2428
2488
  if (!isCancelled()) settle(v, background);
2429
2489
  },
@@ -2431,12 +2491,15 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2431
2491
  if (!isCancelled() && !background) fail(e);
2432
2492
  }
2433
2493
  );
2434
- if (!background) setPendingP(inflight.get(ck));
2494
+ if (!background) {
2495
+ trackResourcePromise(running2);
2496
+ setPendingP(running2);
2497
+ }
2435
2498
  return;
2436
2499
  }
2437
2500
  const promise = Promise.resolve(fetchFn(key)).then(
2438
2501
  (v) => {
2439
- ttlCache.set(ck, { value: v, timestamp: Date.now() });
2502
+ cache.set(ck, { value: v, timestamp: Date.now() });
2440
2503
  inflight.delete(ck);
2441
2504
  return v;
2442
2505
  },
@@ -2459,7 +2522,8 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2459
2522
  }
2460
2523
  );
2461
2524
  }
2462
- function settle(v, background) {
2525
+ function settle(v, _background) {
2526
+ if (ssrId !== void 0) reportResourceData(ssrId, v);
2463
2527
  batch2(() => {
2464
2528
  setValue(() => v);
2465
2529
  setResourceState("ready");
@@ -2477,6 +2541,7 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2477
2541
  }
2478
2542
  createEffect(() => {
2479
2543
  const key = sourceFn();
2544
+ const values = depValues();
2480
2545
  tick();
2481
2546
  if (key === false || key === null || key === void 0) {
2482
2547
  prevKey = UNSET2;
@@ -2491,16 +2556,18 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2491
2556
  const doInvalidate = flagInvalidate;
2492
2557
  flagRefetch = false;
2493
2558
  flagInvalidate = false;
2494
- const ck = buildKey(key);
2495
- if (doInvalidate) ttlCache.delete(ck);
2559
+ const ck = buildKey(key, values);
2560
+ if (seed && prevKey === UNSET2 && !cache.get(ck)) cache.set(ck, { value: seed.value, timestamp: Date.now() });
2561
+ if (doInvalidate) cache.delete(ck);
2496
2562
  const keyChanged = prevKey === UNSET2 || key !== prevKey;
2497
2563
  prevKey = key;
2498
2564
  let cancelled = false;
2499
2565
  onCleanup(() => {
2500
2566
  cancelled = true;
2501
2567
  });
2502
- const cached = ttlCache.get(ck);
2568
+ const cached = cache.get(ck);
2503
2569
  if (cached && isFresh(cached) && !doRefetch && !doInvalidate) {
2570
+ if (ssrId !== void 0) reportResourceData(ssrId, cached.value);
2504
2571
  const cur2 = untrack2(resourceState);
2505
2572
  if (cur2 !== "ready" || untrack2(value) !== cached.value) {
2506
2573
  batch2(() => {
@@ -2561,22 +2628,17 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
2561
2628
  const invalidate = () => {
2562
2629
  const key = untrack2(sourceFn);
2563
2630
  if (key !== null && key !== void 0 && key !== false) {
2564
- ttlCache.delete(buildKey(key));
2631
+ cache.delete(buildKey(key));
2565
2632
  }
2566
2633
  flagInvalidate = true;
2567
2634
  setTick((v) => v + 1);
2568
2635
  };
2569
- return [resource2, { mutate: setValue, refetch, invalidate }];
2636
+ return Object.assign(resource2, { mutate: setValue, refetch, invalidate });
2570
2637
  }
2571
- function clearCachedResourceNamespace(name) {
2638
+ function clearCachedResources(name, cache = currentResourceCache()) {
2639
+ if (name === void 0) return cache.clear();
2572
2640
  const prefix = `${name}:`;
2573
- for (const key of ttlCache.keys()) {
2574
- if (key.startsWith(prefix)) ttlCache.delete(key);
2575
- }
2576
- }
2577
- function clearAllCachedResources() {
2578
- ttlCache.clear();
2579
- inflight.clear();
2641
+ for (const key of [...cache.keys()]) if (key.startsWith(prefix)) cache.delete(key);
2580
2642
  }
2581
2643
  export {
2582
2644
  $NAME,
@@ -2598,15 +2660,16 @@ export {
2598
2660
  SuspenseContext,
2599
2661
  VERSION,
2600
2662
  __DEV__,
2663
+ adoptReactiveScope,
2601
2664
  batch2 as batch,
2665
+ cachedResource,
2602
2666
  childOwner,
2603
- clearAllCachedResources,
2604
- clearCachedResourceNamespace,
2667
+ clearCachedResources,
2668
+ closeReactiveScope,
2605
2669
  combineSignal,
2606
2670
  combineSignals,
2607
2671
  computed,
2608
2672
  context,
2609
- createCachedResource,
2610
2673
  createChildOwner,
2611
2674
  createComputed,
2612
2675
  createComputedStore,
@@ -2621,6 +2684,7 @@ export {
2621
2684
  createMutableStore,
2622
2685
  createRenderEffect,
2623
2686
  createResource,
2687
+ createResourceCache,
2624
2688
  createRoot,
2625
2689
  createSelector,
2626
2690
  createSignal,
@@ -2628,6 +2692,7 @@ export {
2628
2692
  createStoreEffect,
2629
2693
  createStoreMemo,
2630
2694
  createSuspenseBoundary,
2695
+ currentResourceCache,
2631
2696
  debounceSignal,
2632
2697
  disposeScope,
2633
2698
  distinctSignal,
@@ -2656,6 +2721,7 @@ export {
2656
2721
  makeArrayFlat,
2657
2722
  mapArray,
2658
2723
  mapSignal,
2724
+ markReactiveScope,
2659
2725
  memo,
2660
2726
  mergeSignal,
2661
2727
  modifiable,
@@ -2664,12 +2730,14 @@ export {
2664
2730
  omitSignal,
2665
2731
  on,
2666
2732
  onCleanup,
2733
+ openReactiveScope,
2667
2734
  operate,
2668
2735
  pickSignal,
2669
2736
  produce as produceUtil,
2670
2737
  provide,
2671
2738
  provideErrorBoundary,
2672
2739
  provideSuspense,
2740
+ reactiveScopeOf,
2673
2741
  readChildren,
2674
2742
  readSignal,
2675
2743
  reconcile as reconcileUtil,
@@ -2686,6 +2754,7 @@ export {
2686
2754
  runWithOwner,
2687
2755
  selectSignal,
2688
2756
  setOwner,
2757
+ setResourceCacheScope,
2689
2758
  setResourceDataSink,
2690
2759
  setResourceIdSource,
2691
2760
  setResourceTracker,
@@ -2703,6 +2772,7 @@ export {
2703
2772
  useContext,
2704
2773
  useTransition,
2705
2774
  whenSignal,
2775
+ withReactiveScope,
2706
2776
  wrap,
2707
2777
  zipSignal
2708
2778
  };
@@ -1,4 +1,4 @@
1
- /*! @fluixi/reactive v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/reactive v1.0.0-alpha.94 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -1,4 +1,4 @@
1
- /*! @fluixi/reactive v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/reactive v1.0.0-alpha.94 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
 
3
3
  // src/lib/predicates.ts
4
4
  function isFunction(value) {