@fluixi/reactive 1.0.0-alpha.91 → 1.0.0-alpha.93

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
@@ -32,7 +32,7 @@ __export(api_exports, {
32
32
  module.exports = __toCommonJS(api_exports);
33
33
 
34
34
  // src/version.generated.ts
35
- var VERSION = "1.0.0-alpha.91";
35
+ var VERSION = "1.0.0-alpha.93";
36
36
 
37
37
  // src/lib/signal/graph/state.ts
38
38
  var MAJOR = VERSION.split(".")[0];
@@ -82,11 +82,12 @@ function observeReactiveNodes(next) {
82
82
  }
83
83
  var running = [];
84
84
  var origin;
85
+ var currentScope;
85
86
  function reportReactiveNode(report) {
86
87
  const observer = G.observer;
87
88
  if (observer) {
88
89
  observer.created(
89
- report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin } : report
90
+ report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin, scope: report.scope ?? currentScope } : { ...report, scope: report.scope ?? currentScope }
90
91
  );
91
92
  }
92
93
  }
@@ -415,7 +416,7 @@ function afterWrite() {
415
416
  if (G.batchDepth === 0) flushSync();
416
417
  }
417
418
  var EffectNode = class {
418
- constructor(fn, report = false) {
419
+ constructor(fn, report = false, name) {
419
420
  this.queued = false;
420
421
  this.disposed = false;
421
422
  this.owner = makeOwner(G.owner);
@@ -427,7 +428,7 @@ var EffectNode = class {
427
428
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
428
429
  });
429
430
  });
430
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report });
431
+ reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
431
432
  this.watcher = new Watcher(() => enqueue(this));
432
433
  this.run();
433
434
  this.watcher.watch(this.computed);
@@ -454,8 +455,8 @@ var EffectNode = class {
454
455
  disposeOwner(this.owner);
455
456
  }
456
457
  };
457
- function effect(fn, report = false) {
458
- const node = new EffectNode(fn, report);
458
+ function effect(fn, report = false, name) {
459
+ const node = new EffectNode(fn, report, name);
459
460
  return () => node.dispose();
460
461
  }
461
462
 
@@ -523,12 +524,12 @@ function createMemo(fn, value, options) {
523
524
  if (isObserved()) onCleanup(() => reportReactiveDispose(c));
524
525
  return read;
525
526
  }
526
- function createEffect(fn, value) {
527
+ function createEffect(fn, value, options) {
527
528
  let prev = value;
528
529
  return effect(() => {
529
530
  const r = fn(prev);
530
531
  prev = r;
531
- }, true);
532
+ }, true, options?.name);
532
533
  }
533
534
  function createComputed(fn, value) {
534
535
  let prev = value;
@@ -551,8 +552,8 @@ function signal(value, options) {
551
552
  function memo(fn, value, options) {
552
553
  return createMemo(fn, value, options);
553
554
  }
554
- function effect2(fn, value) {
555
- return createEffect(fn, value);
555
+ function effect2(fn, value, options) {
556
+ return createEffect(fn, value, options);
556
557
  }
557
558
  function root(fn) {
558
559
  return createRoot(fn);
@@ -102,7 +102,11 @@ export declare function memo<T>(fn: (prev?: T) => T, value?: T, options?: Signal
102
102
  *
103
103
  * @returns Its disposer, for an effect created outside a root.
104
104
  */
105
- export declare function effect<T>(fn: (prev?: T) => T | (() => void), value?: T): () => void;
105
+ export declare function effect<T>(fn: (prev?: T) => T | (() => void), value?: T,
106
+ /** `name` is what a devtools graph calls it, as for `signal` and `memo`. */
107
+ options?: {
108
+ name?: string;
109
+ }): () => void;
106
110
  /**
107
111
  * The rest of the `create` prefix, dropped.
108
112
  *
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/lib/signal/api.ts"],"names":[],"mappings":"AAiCA,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,KAAK,EACX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,qEAAqE;AACrE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC;AAE/D,8DAA8D;AAC9D,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AACjF,wBAAgB,MAAM,CAAC,CAAC,GAAG,SAAS,KAAK,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAMrE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAEjG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,CAEnF;AAED;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAEzD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,CAEzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAEhE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAEtE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAEtD"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/lib/signal/api.ts"],"names":[],"mappings":"AAiCA,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,KAAK,EACX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,qEAAqE;AACrE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC;AAE/D,8DAA8D;AAC9D,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AACjF,wBAAgB,MAAM,CAAC,CAAC,GAAG,SAAS,KAAK,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAMrE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAEjG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,MAAM,CAAC,CAAC,EACtB,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,EAClC,KAAK,CAAC,EAAE,CAAC;AACT,4EAA4E;AAC5E,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,MAAM,IAAI,CAEZ;AAED;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAEzD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,IAAI,CAEzF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAEhE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAEtE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAEtD"}
@@ -94,8 +94,10 @@ export function memo(fn, value, options) {
94
94
  *
95
95
  * @returns Its disposer, for an effect created outside a root.
96
96
  */
97
- export function effect(fn, value) {
98
- return createEffect(fn, value);
97
+ export function effect(fn, value,
98
+ /** `name` is what a devtools graph calls it, as for `signal` and `memo`. */
99
+ options) {
100
+ return createEffect(fn, value, options);
99
101
  }
100
102
  /**
101
103
  * The rest of the `create` prefix, dropped.
@@ -1,5 +1,5 @@
1
1
  // src/version.generated.ts
2
- var VERSION = "1.0.0-alpha.91";
2
+ var VERSION = "1.0.0-alpha.93";
3
3
 
4
4
  // src/lib/signal/graph/state.ts
5
5
  var MAJOR = VERSION.split(".")[0];
@@ -49,11 +49,12 @@ function observeReactiveNodes(next) {
49
49
  }
50
50
  var running = [];
51
51
  var origin;
52
+ var currentScope;
52
53
  function reportReactiveNode(report) {
53
54
  const observer = G.observer;
54
55
  if (observer) {
55
56
  observer.created(
56
- report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin } : report
57
+ report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin, scope: report.scope ?? currentScope } : { ...report, scope: report.scope ?? currentScope }
57
58
  );
58
59
  }
59
60
  }
@@ -382,7 +383,7 @@ function afterWrite() {
382
383
  if (G.batchDepth === 0) flushSync();
383
384
  }
384
385
  var EffectNode = class {
385
- constructor(fn, report = false) {
386
+ constructor(fn, report = false, name) {
386
387
  this.queued = false;
387
388
  this.disposed = false;
388
389
  this.owner = makeOwner(G.owner);
@@ -394,7 +395,7 @@ var EffectNode = class {
394
395
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
395
396
  });
396
397
  });
397
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report });
398
+ reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
398
399
  this.watcher = new Watcher(() => enqueue(this));
399
400
  this.run();
400
401
  this.watcher.watch(this.computed);
@@ -421,8 +422,8 @@ var EffectNode = class {
421
422
  disposeOwner(this.owner);
422
423
  }
423
424
  };
424
- function effect(fn, report = false) {
425
- const node = new EffectNode(fn, report);
425
+ function effect(fn, report = false, name) {
426
+ const node = new EffectNode(fn, report, name);
426
427
  return () => node.dispose();
427
428
  }
428
429
 
@@ -490,12 +491,12 @@ function createMemo(fn, value, options) {
490
491
  if (isObserved()) onCleanup(() => reportReactiveDispose(c));
491
492
  return read;
492
493
  }
493
- function createEffect(fn, value) {
494
+ function createEffect(fn, value, options) {
494
495
  let prev = value;
495
496
  return effect(() => {
496
497
  const r = fn(prev);
497
498
  prev = r;
498
- }, true);
499
+ }, true, options?.name);
499
500
  }
500
501
  function createComputed(fn, value) {
501
502
  let prev = value;
@@ -518,8 +519,8 @@ function signal(value, options) {
518
519
  function memo(fn, value, options) {
519
520
  return createMemo(fn, value, options);
520
521
  }
521
- function effect2(fn, value) {
522
- return createEffect(fn, value);
522
+ function effect2(fn, value, options) {
523
+ return createEffect(fn, value, options);
523
524
  }
524
525
  function root(fn) {
525
526
  return createRoot(fn);
@@ -1,4 +1,4 @@
1
- /*! @fluixi/reactive v1.0.0-alpha.91 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/reactive v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -21,14 +21,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/lib/signal/cached-resource.ts
22
22
  var cached_resource_exports = {};
23
23
  __export(cached_resource_exports, {
24
- clearAllCachedResources: () => clearAllCachedResources,
25
- clearCachedResourceNamespace: () => clearCachedResourceNamespace,
26
- createCachedResource: () => createCachedResource
24
+ cachedResource: () => cachedResource,
25
+ clearCachedResources: () => clearCachedResources,
26
+ createResourceCache: () => createResourceCache
27
27
  });
28
28
  module.exports = __toCommonJS(cached_resource_exports);
29
29
 
30
30
  // src/version.generated.ts
31
- var VERSION = "1.0.0-alpha.91";
31
+ var VERSION = "1.0.0-alpha.93";
32
32
 
33
33
  // src/lib/signal/graph/state.ts
34
34
  var MAJOR = VERSION.split(".")[0];
@@ -78,11 +78,12 @@ function observeReactiveNodes(next) {
78
78
  }
79
79
  var running = [];
80
80
  var origin;
81
+ var currentScope;
81
82
  function reportReactiveNode(report) {
82
83
  const observer = G.observer;
83
84
  if (observer) {
84
85
  observer.created(
85
- report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin } : report
86
+ report.parents === void 0 ? { ...report, parents: running, origin: report.origin ?? origin, scope: report.scope ?? currentScope } : { ...report, scope: report.scope ?? currentScope }
86
87
  );
87
88
  }
88
89
  }
@@ -376,7 +377,7 @@ function batch(fn) {
376
377
  }
377
378
  }
378
379
  var EffectNode = class {
379
- constructor(fn, report = false) {
380
+ constructor(fn, report = false, name) {
380
381
  this.queued = false;
381
382
  this.disposed = false;
382
383
  this.owner = makeOwner(G.owner);
@@ -388,7 +389,7 @@ var EffectNode = class {
388
389
  if (typeof r === "function") (this.owner.cleanups ??= []).push(r);
389
390
  });
390
391
  });
391
- reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report });
392
+ reportReactiveNode({ kind: "effect", node: this.computed, handle: this, internal: !report, ...name ? { name } : {} });
392
393
  this.watcher = new Watcher(() => enqueue(this));
393
394
  this.run();
394
395
  this.watcher.watch(this.computed);
@@ -415,8 +416,8 @@ var EffectNode = class {
415
416
  disposeOwner(this.owner);
416
417
  }
417
418
  };
418
- function effect(fn, report = false) {
419
- const node = new EffectNode(fn, report);
419
+ function effect(fn, report = false, name) {
420
+ const node = new EffectNode(fn, report, name);
420
421
  return () => node.dispose();
421
422
  }
422
423
 
@@ -456,12 +457,12 @@ function createSignal(value, options) {
456
457
  if (isObserved()) onCleanup(() => reportReactiveDispose(state));
457
458
  return [read, write];
458
459
  }
459
- function createEffect(fn, value) {
460
+ function createEffect(fn, value, options) {
460
461
  let prev = value;
461
462
  return effect(() => {
462
463
  const r = fn(prev);
463
464
  prev = r;
464
- }, true);
465
+ }, true, options?.name);
465
466
  }
466
467
  function batch2(fn) {
467
468
  return batch(fn);
@@ -475,14 +476,47 @@ var _resourceTracker = null;
475
476
  function trackResourcePromise(p) {
476
477
  if (_resourceTracker) _resourceTracker(p);
477
478
  }
479
+ var _serverDataGetter = null;
480
+ function getServerData(id) {
481
+ return _serverDataGetter ? _serverDataGetter(id) : void 0;
482
+ }
483
+ var _resourceIdSource = null;
484
+ function nextResourceId() {
485
+ return _resourceIdSource ? _resourceIdSource() : void 0;
486
+ }
487
+ var _resourceDataSink = null;
488
+ function reportResourceData(id, value) {
489
+ if (_resourceDataSink) _resourceDataSink(id, value);
490
+ }
491
+ function createResourceCache() {
492
+ const entries = /* @__PURE__ */ new Map();
493
+ const inflight = /* @__PURE__ */ new Map();
494
+ return {
495
+ get: (key) => entries.get(key),
496
+ set: (key, entry) => void entries.set(key, entry),
497
+ delete: (key) => void entries.delete(key),
498
+ keys: () => entries.keys(),
499
+ clear: () => {
500
+ entries.clear();
501
+ inflight.clear();
502
+ },
503
+ inflight
504
+ };
505
+ }
506
+ var _cacheScope = null;
507
+ var _pageCache;
508
+ function currentResourceCache() {
509
+ const scoped = _cacheScope?.();
510
+ if (scoped) return scoped;
511
+ if (typeof window === "undefined") return createResourceCache();
512
+ return _pageCache ??= createResourceCache();
513
+ }
478
514
 
479
515
  // src/lib/signal/cached-resource.ts
480
- var ttlCache = /* @__PURE__ */ new Map();
481
- var inflight = /* @__PURE__ */ new Map();
482
516
  var _autoId = 0;
483
517
  var $SIGNAL2 = /* @__PURE__ */ Symbol.for("signal");
484
518
  var $RESOURCE = /* @__PURE__ */ Symbol.for("resource");
485
- function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
519
+ function cachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
486
520
  let sourceFn;
487
521
  let fetchFn;
488
522
  let options;
@@ -501,7 +535,13 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
501
535
  staleWhileRevalidate = true
502
536
  } = options;
503
537
  const ns = name;
504
- const buildKey = (key) => `${ns}:${JSON.stringify(key)}`;
538
+ const cache = options.cache ?? currentResourceCache();
539
+ const inflight = cache.inflight;
540
+ const ssrId = options.transport === false ? void 0 : nextResourceId();
541
+ const seed = ssrId !== void 0 ? getServerData(ssrId) : void 0;
542
+ const deps = options.deps ?? [];
543
+ const depValues = () => deps.map((dep) => dep());
544
+ const buildKey = (key, values = untrack2(depValues)) => `${ns}:${JSON.stringify(key)}` + (deps.length ? `:${JSON.stringify(values)}` : "");
505
545
  const isFresh = (entry) => ttl === Infinity || Date.now() - entry.timestamp <= ttl;
506
546
  const [value, setValue] = createSignal(void 0, { equals: false });
507
547
  const [resourceState, setResourceState] = createSignal("unresolved", { equals: false });
@@ -514,8 +554,9 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
514
554
  let flagRefetch = false;
515
555
  let flagInvalidate = false;
516
556
  function doFetch(key, ck, background, isCancelled) {
517
- if (inflight.has(ck)) {
518
- inflight.get(ck).then(
557
+ const running2 = inflight.get(ck);
558
+ if (running2) {
559
+ running2.then(
519
560
  (v) => {
520
561
  if (!isCancelled()) settle(v, background);
521
562
  },
@@ -523,12 +564,15 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
523
564
  if (!isCancelled() && !background) fail(e);
524
565
  }
525
566
  );
526
- if (!background) setPendingP(inflight.get(ck));
567
+ if (!background) {
568
+ trackResourcePromise(running2);
569
+ setPendingP(running2);
570
+ }
527
571
  return;
528
572
  }
529
573
  const promise = Promise.resolve(fetchFn(key)).then(
530
574
  (v) => {
531
- ttlCache.set(ck, { value: v, timestamp: Date.now() });
575
+ cache.set(ck, { value: v, timestamp: Date.now() });
532
576
  inflight.delete(ck);
533
577
  return v;
534
578
  },
@@ -551,7 +595,8 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
551
595
  }
552
596
  );
553
597
  }
554
- function settle(v, background) {
598
+ function settle(v, _background) {
599
+ if (ssrId !== void 0) reportResourceData(ssrId, v);
555
600
  batch2(() => {
556
601
  setValue(() => v);
557
602
  setResourceState("ready");
@@ -569,6 +614,7 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
569
614
  }
570
615
  createEffect(() => {
571
616
  const key = sourceFn();
617
+ const values = depValues();
572
618
  tick();
573
619
  if (key === false || key === null || key === void 0) {
574
620
  prevKey = UNSET;
@@ -583,16 +629,18 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
583
629
  const doInvalidate = flagInvalidate;
584
630
  flagRefetch = false;
585
631
  flagInvalidate = false;
586
- const ck = buildKey(key);
587
- if (doInvalidate) ttlCache.delete(ck);
632
+ const ck = buildKey(key, values);
633
+ if (seed && prevKey === UNSET && !cache.get(ck)) cache.set(ck, { value: seed.value, timestamp: Date.now() });
634
+ if (doInvalidate) cache.delete(ck);
588
635
  const keyChanged = prevKey === UNSET || key !== prevKey;
589
636
  prevKey = key;
590
637
  let cancelled = false;
591
638
  onCleanup(() => {
592
639
  cancelled = true;
593
640
  });
594
- const cached = ttlCache.get(ck);
641
+ const cached = cache.get(ck);
595
642
  if (cached && isFresh(cached) && !doRefetch && !doInvalidate) {
643
+ if (ssrId !== void 0) reportResourceData(ssrId, cached.value);
596
644
  const cur2 = untrack2(resourceState);
597
645
  if (cur2 !== "ready" || untrack2(value) !== cached.value) {
598
646
  batch2(() => {
@@ -653,20 +701,15 @@ function createCachedResource(sourceOrFetcher, fetcherOrOptions, opts = {}) {
653
701
  const invalidate = () => {
654
702
  const key = untrack2(sourceFn);
655
703
  if (key !== null && key !== void 0 && key !== false) {
656
- ttlCache.delete(buildKey(key));
704
+ cache.delete(buildKey(key));
657
705
  }
658
706
  flagInvalidate = true;
659
707
  setTick((v) => v + 1);
660
708
  };
661
- return [resource, { mutate: setValue, refetch, invalidate }];
709
+ return Object.assign(resource, { mutate: setValue, refetch, invalidate });
662
710
  }
663
- function clearCachedResourceNamespace(name) {
711
+ function clearCachedResources(name, cache = currentResourceCache()) {
712
+ if (name === void 0) return cache.clear();
664
713
  const prefix = `${name}:`;
665
- for (const key of ttlCache.keys()) {
666
- if (key.startsWith(prefix)) ttlCache.delete(key);
667
- }
668
- }
669
- function clearAllCachedResources() {
670
- ttlCache.clear();
671
- inflight.clear();
714
+ for (const key of [...cache.keys()]) if (key.startsWith(prefix)) cache.delete(key);
672
715
  }
@@ -1,53 +1,29 @@
1
1
  /**
2
- * createCachedResource: a reactive resource with TTL-based caching.
2
+ * `cachedResource`: a resource whose results are kept, by key, for a TTL.
3
3
  *
4
- * Fetches once and returns the cached result for subsequent reads within the
5
- * TTL window. After the TTL expires the next read triggers a re-fetch.
4
+ * Fetches once and serves the cached result to later reads within the TTL; after it, the
5
+ * next read fetches again, showing the stale value meanwhile unless `staleWhileRevalidate`
6
+ * is off. Readers of the same key share one request in flight.
6
7
  *
7
- * It runs on the live graph, as of this change. It used to build on `./signal.js`,
8
- * which tracks its current consumer in a module-level `Listener` while everything on
9
- * the default entry tracks through `G.consumer`. The two never saw each other, so
10
- * `createEffect(() => data())` subscribed to nothing and a binding kept whatever it
11
- * first rendered, which on an initial load is the loading state. `cross-graph.spec.ts`
12
- * holds the general shape of that hazard; this file is no longer an instance of it.
8
+ * const workspace = cachedResource(workspaceId, (id) => api.get(`/workspaces/${id}`), {
9
+ * name: 'workspace',
10
+ * ttl: 5 * 60_000,
11
+ * });
12
+ * workspace(); // the value; suspends under <Suspense> on the first load
13
+ * workspace.stale; // true while a background refetch runs
14
+ * workspace.invalidate(); // drop the entry and fetch again
13
15
  *
14
- * Suspense needs no bookkeeping here. The accessor throws the pending promise and the
15
- * runtime's suspend handler finds the nearest boundary from the effect that was
16
- * reading, which is what `graph/resource.ts` relies on too. The manual increment and
17
- * decrement against a lazily-resolved context went with the port.
16
+ * Where entries live is the cache's business (`ResourceCache`). By default: one cache per
17
+ * request on the server, so visitors never share an entry or an in-flight fetch; the page in
18
+ * a browser. Pass `cache` to keep them elsewhere, for instance a storage that survives a reload.
18
19
  *
19
- * Two forms (mirrors createResource):
20
+ * A value fetched during the server render travels to the browser with the page, like a
21
+ * plain resource's, and seeds the first read there instead of a second fetch.
20
22
  *
21
- * // 1. no reactive source
22
- * const [data, { refetch, invalidate }] = createCachedResource(
23
- * () => apiClient.get('/data'),
24
- * { ttl: 5 * 60_000, name: 'my-data' }
25
- * );
26
- *
27
- * // 2. reactive source (re-fetches when source value changes)
28
- * const [data, { refetch, invalidate }] = createCachedResource(
29
- * () => workspaceId(),
30
- * (id) => apiClient.get(`/workspaces/${id}`),
31
- * { ttl: 5 * 60_000, name: 'workspace' }
32
- * );
33
- *
34
- * Options:
35
- * ttl: cache lifetime in ms. Default: Infinity (manual invalidate only)
36
- * name: cache namespace. If omitted, each call-site gets its own isolated cache.
37
- * staleWhileRevalidate, when true (default), show stale data while background-fetching.
38
- * When false, show a loading state during revalidation.
39
- *
40
- * Resource shape (same as createResource):
41
- * data(): current value (throws pending promise during initial load for Suspense)
42
- * data.loading: true during initial load
43
- * data.latest: value without throwing
44
- * data.error: last error
45
- * data.stale: true when showing stale data during background revalidation
46
- *
47
- * Actions:
48
- * refetch(): force re-fetch regardless of TTL, keeps showing current value while loading
49
- * invalidate(): delete cache entry and re-fetch (shows loading on next read)
23
+ * It runs on the live graph. Suspense needs no bookkeeping here: the accessor throws the
24
+ * pending promise and the runtime finds the nearest boundary from the reading effect.
50
25
  */
26
+ import { type ResourceCache } from './graph/ssr-hooks.js';
51
27
  import type { Setter, Resource } from './signal.js';
52
28
  export interface CachedResourceOptions {
53
29
  /**
@@ -57,7 +33,7 @@ export interface CachedResourceOptions {
57
33
  ttl?: number;
58
34
  /**
59
35
  * Cache namespace. Two calls that share the same `name` share their cache
60
- * entries. When omitted, each `createCachedResource` call-site gets a
36
+ * entries. When omitted, each `cachedResource` call gets a
61
37
  * private cache isolated from all others.
62
38
  */
63
39
  name?: string;
@@ -70,37 +46,41 @@ export interface CachedResourceOptions {
70
46
  * `state='refreshing'` (data is still visible but `loading=true`).
71
47
  */
72
48
  staleWhileRevalidate?: boolean;
49
+ /** Where entries live. Defaults to the request's cache on the server and the page's in a browser. */
50
+ cache?: ResourceCache;
51
+ /** Carry the server-fetched value to the browser with the page. Default true. */
52
+ transport?: boolean;
53
+ /**
54
+ * Other values the data depends on: the signed-in user, the active organisation. Each
55
+ * combination is cached apart and a change reads (or fetches) its own entry. The fetcher
56
+ * still receives only the source's key.
57
+ */
58
+ deps?: ReadonlyArray<() => unknown>;
73
59
  }
74
60
  export type CachedResource<T> = Resource<T> & {
75
61
  /** `true` while serving stale data during a background re-fetch. */
76
62
  stale: boolean;
77
63
  };
78
- export type CachedResourceReturn<T> = [
79
- CachedResource<T>,
80
- {
81
- mutate: Setter<T | undefined>;
82
- /** Force re-fetch, bypassing TTL. Current value stays visible. */
83
- refetch: () => void;
84
- /** Delete the cache entry for the current key and trigger a fresh fetch. */
85
- invalidate: () => void;
86
- }
87
- ];
88
- /**
89
- * No-source overload: fetch is not keyed by any reactive value.
90
- */
91
- export declare function createCachedResource<T>(fetcher: () => Promise<T> | T, options?: CachedResourceOptions): CachedResourceReturn<T>;
92
- /**
93
- * With-source overload: fetch re-runs whenever the source accessor returns a
94
- * new value (falsy source suspends the fetch, same as `createResource`).
95
- */
96
- export declare function createCachedResource<T, S>(source: () => S | false | null | undefined, fetcher: (key: S) => Promise<T> | T, options?: CachedResourceOptions): CachedResourceReturn<T>;
64
+ export interface CachedResourceActions<T> {
65
+ mutate: Setter<T | undefined>;
66
+ /** Fetch again now, whatever the TTL. The current value stays visible. */
67
+ refetch: () => void;
68
+ /** Drop the entry for the current key and fetch again. */
69
+ invalidate: () => void;
70
+ }
71
+ /** One binding: the accessor, with the actions on it. */
72
+ export type CachedResourceHandle<T> = CachedResource<T> & CachedResourceActions<T>;
73
+ /** Not keyed by a reactive value. */
74
+ export declare function cachedResource<T>(fetcher: () => Promise<T> | T, options?: CachedResourceOptions): CachedResourceHandle<T>;
97
75
  /**
98
- * Clear all TTL cache entries for a given namespace (name).
99
- * Useful to invalidate a whole category of data at once.
76
+ * Keyed by `source`: a new key reads its own entry, or fetches. A falsy source holds the
77
+ * fetch, as for `resource`.
100
78
  */
101
- export declare function clearCachedResourceNamespace(name: string): void;
79
+ export declare function cachedResource<T, S>(source: () => S | false | null | undefined, fetcher: (key: S) => Promise<T> | T, options?: CachedResourceOptions): CachedResourceHandle<T>;
102
80
  /**
103
- * Clear the entire TTL cache. Useful on logout / workspace switch.
81
+ * Drops cached entries in the current scope: those of one `name`, or all of them. On a
82
+ * logout or a workspace switch, so nothing fetched for the previous one is served.
104
83
  */
105
- export declare function clearAllCachedResources(): void;
84
+ export declare function clearCachedResources(name?: string, cache?: ResourceCache): void;
85
+ export { createResourceCache, type ResourceCache, type ResourceCacheEntry } from './graph/ssr-hooks.js';
106
86
  //# sourceMappingURL=cached-resource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cached-resource.d.ts","sourceRoot":"","sources":["../../../src/lib/signal/cached-resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAYH,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAiB,MAAM,aAAa,CAAC;AAgBnE,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IAC5C,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI;IACpC,cAAc,CAAC,CAAC,CAAC;IACjB;QACE,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;QAC9B,kEAAkE;QAClE,OAAO,EAAE,MAAM,IAAI,CAAC;QACpB,4EAA4E;QAC5E,UAAU,EAAE,MAAM,IAAI,CAAC;KACxB;CACF,CAAC;AAUF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAC7B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAE3B;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EACvC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,EAC1C,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACnC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAwO3B;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAK/D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C"}
1
+ {"version":3,"file":"cached-resource.d.ts","sourceRoot":"","sources":["../../../src/lib/signal/cached-resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAUH,OAAO,EAML,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAiB,MAAM,aAAa,CAAC;AAMnE,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qGAAqG;IACrG,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG;IAC5C,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9B,0EAA0E;IAC1E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,yDAAyD;AACzD,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAUnF,qCAAqC;AACrC,wBAAgB,cAAc,CAAC,CAAC,EAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAC7B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAE3B;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,EACjC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,EAC1C,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACnC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,oBAAoB,CAAC,CAAC,CAAC,CAAC;AA2P3B;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,aAAsC,GAAG,IAAI,CAIvG;AAED,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}