@solidjs/signals 2.0.0-rc.2 → 2.0.0-rc.20

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 (198) hide show
  1. package/dist/dev-shared.js +6505 -0
  2. package/dist/dev.attribution.js +3484 -0
  3. package/dist/dev.js +10227 -9508
  4. package/dist/observe/affects-marks.js +86 -0
  5. package/dist/observe/affects.js +112 -0
  6. package/dist/observe/attribution.js +7 -0
  7. package/dist/observe/boundaries.js +696 -0
  8. package/dist/observe/core/action.js +182 -0
  9. package/dist/observe/core/async.js +824 -0
  10. package/dist/observe/core/attribution-costs.js +66 -0
  11. package/dist/observe/core/attribution-feedback.js +280 -0
  12. package/dist/observe/core/attribution-hooks.js +83 -0
  13. package/dist/observe/core/attribution-queries.js +43 -0
  14. package/dist/observe/core/attribution.js +3079 -0
  15. package/dist/observe/core/constants.js +269 -0
  16. package/dist/observe/core/context.js +63 -0
  17. package/dist/observe/core/copies.js +10 -0
  18. package/dist/observe/core/core.js +1707 -0
  19. package/dist/observe/core/dev.js +394 -0
  20. package/dist/observe/core/effect.js +193 -0
  21. package/dist/observe/core/error-hooks.js +71 -0
  22. package/dist/observe/core/error.js +82 -0
  23. package/dist/observe/core/external.js +97 -0
  24. package/dist/observe/core/graph.js +162 -0
  25. package/dist/observe/core/heap.js +124 -0
  26. package/dist/observe/core/identities.js +62 -0
  27. package/dist/observe/core/invariants.js +12 -0
  28. package/dist/observe/core/lanes.js +972 -0
  29. package/dist/observe/core/owner.js +371 -0
  30. package/dist/observe/core/scheduler.js +1157 -0
  31. package/dist/observe/core/truth.js +47 -0
  32. package/dist/observe/core/verdict.js +470 -0
  33. package/dist/observe/deferred.js +186 -0
  34. package/dist/observe/flatten.js +79 -0
  35. package/dist/observe/from.js +248 -0
  36. package/dist/observe/index.js +71 -0
  37. package/dist/observe/map.js +593 -0
  38. package/dist/observe/reveal.js +212 -0
  39. package/dist/observe/signals.js +717 -0
  40. package/dist/observe/store/affects.js +142 -0
  41. package/dist/observe/store/edges.js +39 -0
  42. package/dist/observe/store/hooks.js +16 -0
  43. package/dist/observe/store/index.js +47 -0
  44. package/dist/observe/store/optimistic.js +713 -0
  45. package/dist/observe/store/projection.js +345 -0
  46. package/dist/observe/store/reconcile.js +281 -0
  47. package/dist/observe/store/store.js +2127 -0
  48. package/dist/observe/store/storePath.js +103 -0
  49. package/dist/observe/store/target.js +46 -0
  50. package/dist/observe/store/types.js +83 -0
  51. package/dist/observe/store/utils.js +1063 -0
  52. package/dist/prod/affects-marks.js +86 -0
  53. package/dist/prod/affects.js +98 -112
  54. package/dist/prod/attribution.js +45 -0
  55. package/dist/prod/boundaries.js +578 -468
  56. package/dist/prod/core/action.js +92 -59
  57. package/dist/prod/core/async.js +522 -336
  58. package/dist/prod/core/attribution-hooks.js +3 -0
  59. package/dist/prod/core/constants.js +168 -44
  60. package/dist/prod/core/context.js +12 -16
  61. package/dist/prod/core/copies.js +10 -0
  62. package/dist/prod/core/core.js +1345 -627
  63. package/dist/prod/core/dev.js +123 -1
  64. package/dist/prod/core/effect.js +113 -80
  65. package/dist/prod/core/error-hooks.js +71 -0
  66. package/dist/prod/core/error.js +18 -4
  67. package/dist/prod/core/external.js +6 -7
  68. package/dist/prod/core/graph.js +119 -72
  69. package/dist/prod/core/heap.js +85 -109
  70. package/dist/prod/core/identities.js +62 -0
  71. package/dist/prod/core/invariants.js +1 -32
  72. package/dist/prod/core/lanes.js +931 -132
  73. package/dist/prod/core/owner.js +192 -129
  74. package/dist/prod/core/scheduler.js +948 -642
  75. package/dist/prod/core/truth.js +47 -0
  76. package/dist/prod/core/verdict.js +409 -420
  77. package/dist/prod/deferred.js +184 -0
  78. package/dist/prod/flatten.js +77 -0
  79. package/dist/prod/from.js +248 -0
  80. package/dist/prod/index.js +40 -16
  81. package/dist/prod/map.js +481 -211
  82. package/dist/prod/reveal.js +212 -0
  83. package/dist/prod/signals.js +401 -84
  84. package/dist/prod/store/affects.js +142 -0
  85. package/dist/prod/store/edges.js +39 -0
  86. package/dist/prod/store/hooks.js +16 -0
  87. package/dist/prod/store/index.js +27 -18
  88. package/dist/prod/store/optimistic.js +707 -0
  89. package/dist/prod/store/projection.js +331 -0
  90. package/dist/prod/store/reconcile.js +281 -0
  91. package/dist/prod/store/store.js +1952 -267
  92. package/dist/prod/store/storePath.js +1 -1
  93. package/dist/prod/store/target.js +43 -0
  94. package/dist/prod/store/types.js +83 -0
  95. package/dist/prod/store/utils.js +997 -138
  96. package/dist/types/affects-marks.d.ts +14 -0
  97. package/dist/types/affects.d.ts +12 -30
  98. package/dist/types/attribution.d.ts +19 -0
  99. package/dist/types/attribution.prod.d.ts +22 -0
  100. package/dist/types/boundaries.d.ts +99 -124
  101. package/dist/types/carved.d.ts +1 -0
  102. package/dist/types/core/action.d.ts +23 -9
  103. package/dist/types/core/async.d.ts +34 -6
  104. package/dist/types/core/attribution-costs.d.ts +35 -0
  105. package/dist/types/core/attribution-feedback.d.ts +133 -0
  106. package/dist/types/core/attribution-hooks.d.ts +307 -8
  107. package/dist/types/core/attribution-queries.d.ts +24 -0
  108. package/dist/types/core/attribution.d.ts +802 -72
  109. package/dist/types/core/constants.d.ts +195 -38
  110. package/dist/types/core/copies.d.ts +54 -0
  111. package/dist/types/core/core.d.ts +295 -65
  112. package/dist/types/core/dev.d.ts +509 -22
  113. package/dist/types/core/effect.d.ts +1 -1
  114. package/dist/types/core/error-hooks.d.ts +71 -0
  115. package/dist/types/core/error.d.ts +18 -1
  116. package/dist/types/core/graph.d.ts +40 -1
  117. package/dist/types/core/heap.d.ts +5 -5
  118. package/dist/types/core/identities.d.ts +17 -0
  119. package/dist/types/core/index.d.ts +11 -7
  120. package/dist/types/core/invariants.d.ts +1 -26
  121. package/dist/types/core/lanes.d.ts +74 -43
  122. package/dist/types/core/owner.d.ts +27 -9
  123. package/dist/types/core/scheduler.d.ts +353 -102
  124. package/dist/types/core/truth.d.ts +18 -0
  125. package/dist/types/core/types.d.ts +97 -71
  126. package/dist/types/core/verdict.d.ts +35 -0
  127. package/dist/types/deferred.d.ts +28 -0
  128. package/dist/types/flatten.d.ts +8 -0
  129. package/dist/types/from.d.ts +47 -0
  130. package/dist/types/index.d.ts +33 -7
  131. package/dist/types/map.d.ts +4 -2
  132. package/dist/types/reveal.d.ts +19 -0
  133. package/dist/types/signals.d.ts +196 -45
  134. package/dist/types/store/affects.d.ts +12 -0
  135. package/dist/types/store/edges.d.ts +9 -0
  136. package/dist/types/store/hooks.d.ts +62 -0
  137. package/dist/types/store/index.d.ts +42 -15
  138. package/dist/types/store/optimistic.d.ts +24 -45
  139. package/dist/types/store/projection.d.ts +17 -68
  140. package/dist/types/store/reconcile.d.ts +3 -46
  141. package/dist/types/store/store.d.ts +133 -136
  142. package/dist/types/store/storePath.d.ts +1 -1
  143. package/dist/types/store/target.d.ts +166 -0
  144. package/dist/types/store/types.d.ts +105 -0
  145. package/dist/types/store/utils.d.ts +188 -0
  146. package/package.json +31 -26
  147. package/dist/node.cjs +0 -8745
  148. package/dist/prod/core/optimistic.js +0 -265
  149. package/dist/prod/store/next/optimistic.js +0 -385
  150. package/dist/prod/store/next/projection.js +0 -172
  151. package/dist/prod/store/next/reconcile.js +0 -331
  152. package/dist/prod/store/next/store.js +0 -1499
  153. package/dist/prod/store/next/target.js +0 -20
  154. package/dist/types/core/optimistic.d.ts +0 -6
  155. package/dist/types/store/next/optimistic.d.ts +0 -20
  156. package/dist/types/store/next/projection.d.ts +0 -8
  157. package/dist/types/store/next/reconcile.d.ts +0 -3
  158. package/dist/types/store/next/store.d.ts +0 -77
  159. package/dist/types/store/next/target.d.ts +0 -117
  160. package/dist/types-cjs/affects.d.cts +0 -47
  161. package/dist/types-cjs/boundaries.d.cts +0 -175
  162. package/dist/types-cjs/core/action.d.cts +0 -64
  163. package/dist/types-cjs/core/async.d.cts +0 -21
  164. package/dist/types-cjs/core/attribution-hooks.d.cts +0 -52
  165. package/dist/types-cjs/core/attribution.d.cts +0 -186
  166. package/dist/types-cjs/core/constants.d.cts +0 -97
  167. package/dist/types-cjs/core/context.d.cts +0 -36
  168. package/dist/types-cjs/core/core.d.cts +0 -163
  169. package/dist/types-cjs/core/dev.d.cts +0 -81
  170. package/dist/types-cjs/core/effect.d.cts +0 -30
  171. package/dist/types-cjs/core/error.d.cts +0 -47
  172. package/dist/types-cjs/core/external.d.cts +0 -15
  173. package/dist/types-cjs/core/graph.d.cts +0 -6
  174. package/dist/types-cjs/core/heap.d.cts +0 -22
  175. package/dist/types-cjs/core/index.d.cts +0 -13
  176. package/dist/types-cjs/core/invariants.d.cts +0 -59
  177. package/dist/types-cjs/core/lanes.d.cts +0 -44
  178. package/dist/types-cjs/core/optimistic.d.cts +0 -6
  179. package/dist/types-cjs/core/owner.d.cts +0 -124
  180. package/dist/types-cjs/core/scheduler.d.cts +0 -180
  181. package/dist/types-cjs/core/types.d.cts +0 -192
  182. package/dist/types-cjs/core/verdict.d.cts +0 -2
  183. package/dist/types-cjs/index.d.cts +0 -10
  184. package/dist/types-cjs/map.d.cts +0 -69
  185. package/dist/types-cjs/package.json +0 -3
  186. package/dist/types-cjs/signals.d.cts +0 -624
  187. package/dist/types-cjs/store/index.d.cts +0 -19
  188. package/dist/types-cjs/store/next/optimistic.d.cts +0 -20
  189. package/dist/types-cjs/store/next/projection.d.cts +0 -8
  190. package/dist/types-cjs/store/next/reconcile.d.cts +0 -3
  191. package/dist/types-cjs/store/next/store.d.cts +0 -77
  192. package/dist/types-cjs/store/next/target.d.cts +0 -117
  193. package/dist/types-cjs/store/optimistic.d.cts +0 -45
  194. package/dist/types-cjs/store/projection.d.cts +0 -70
  195. package/dist/types-cjs/store/reconcile.d.cts +0 -46
  196. package/dist/types-cjs/store/store.d.cts +0 -138
  197. package/dist/types-cjs/store/storePath.d.cts +0 -58
  198. package/dist/types-cjs/store/utils.d.cts +0 -74
@@ -26,6 +26,12 @@ import type { Disposable, Refreshable } from "./core/index.js";
26
26
  * Cannot be used inside `createTrackedEffect` or `onSettled` — return a
27
27
  * cleanup function from the callback body instead.
28
28
  *
29
+ * Cleanups run in unwind order: an owner's children are disposed before its
30
+ * own cleanups, and within one owner later registrations run before earlier
31
+ * ones. In production a component body shares its enclosing owner, so
32
+ * register cleanup before creating children when the order between them
33
+ * matters.
34
+ *
29
35
  * @example
30
36
  * ```ts
31
37
  * // Library shape: thread a resource's disposal into a *captured* owner
@@ -86,6 +92,13 @@ export type EffectBundle<Prev, Next extends Prev = Prev> = {
86
92
  interface BaseEffectOptions {
87
93
  /** Debug name (dev mode only) */
88
94
  name?: string;
95
+ /**
96
+ * Source location (`file:line:col`, root-relative) written by the
97
+ * compiler's `sourceNames` `locations` kind beside `name`; dev and observe
98
+ * builds keep it for console reports and diagnostic events, production
99
+ * ignores it. Not meant to be written by hand.
100
+ */
101
+ loc?: string;
89
102
  }
90
103
  /** Options for effect primitives that support deferring/scheduling their initial run (`createEffect`, `createRenderEffect`, `createReaction`). */
91
104
  export interface EffectOptions extends BaseEffectOptions {
@@ -138,6 +151,13 @@ export interface EffectOptions extends BaseEffectOptions {
138
151
  export interface SignalOptions<T> {
139
152
  /** Debug name (dev mode only) */
140
153
  name?: string;
154
+ /**
155
+ * Source location (`file:line:col`, root-relative) written by the
156
+ * compiler's `sourceNames` `locations` kind beside `name`; dev and observe
157
+ * builds keep it for console reports and diagnostic events, production
158
+ * ignores it. Not meant to be written by hand.
159
+ */
160
+ loc?: string;
141
161
  /**
142
162
  * Custom equality function, or `false` to always notify subscribers.
143
163
  * Defaults to reference equality (`isEqual`). Pass a comparator (e.g.
@@ -160,6 +180,13 @@ export interface MemoOptions<T> {
160
180
  id?: string;
161
181
  /** Debug name (dev mode only) */
162
182
  name?: string;
183
+ /**
184
+ * Source location (`file:line:col`, root-relative) written by the
185
+ * compiler's `sourceNames` `locations` kind beside `name`; dev and observe
186
+ * builds keep it for console reports and diagnostic events, production
187
+ * ignores it. Not meant to be written by hand.
188
+ */
189
+ loc?: string;
163
190
  /**
164
191
  * Advanced (integration tier). When true, the memo is invisible to the
165
192
  * hydration id scheme: it inherits its parent's id instead of consuming a
@@ -169,6 +196,13 @@ export interface MemoOptions<T> {
169
196
  * the full semantics. No-op outside hydration.
170
197
  */
171
198
  transparent?: boolean;
199
+ /**
200
+ * @internal Framework plumbing (the `solid-js/refresh` HMR memo): in the
201
+ * observe tiers the memo has no name, is no owner-path segment, and the
202
+ * attribution engine records nothing about it, while what it owns stays
203
+ * observed. Not part of the public API.
204
+ */
205
+ _plumbing?: boolean;
172
206
  /**
173
207
  * Custom equality function, or `false` to always notify subscribers.
174
208
  * Defaults to reference equality (`isEqual`). Pass a comparator (e.g.
@@ -251,17 +285,43 @@ export type NoInfer<T extends any> = [T][T extends any ? 0 : never];
251
285
  *
252
286
  * @example
253
287
  * ```ts
254
- * // Writable memo: starts as `fn()`, can be locally overwritten by setter.
288
+ * // Writable memo: derives from `fn()` and can be written like a signal.
255
289
  * const [user, setUser] = createSignal(() => fetchUser(userId()));
256
290
  *
257
- * setUser({ ...user(), name: "Alice" }); // optimistic local edit
291
+ * // A write lands at once and never re-runs `fn` on its own; when `userId`
292
+ * // changes, in the same update or later, `fn` re-runs and receives the
293
+ * // written value as `prev`. While a transaction holds a re-derived value, a
294
+ * // write from outside it does not replace that derivation — it becomes its
295
+ * // `prev`.
296
+ * setUser({ ...user(), name: "Alice" });
258
297
  * ```
259
298
  *
260
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-signal
299
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/create-signal
261
300
  */
262
301
  export declare function createSignal<T>(): Signal<T | undefined>;
263
302
  export declare function createSignal<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;
264
303
  export declare function createSignal<T>(fn: ComputeFunction<T>, options?: SignalOptions<T> & MemoOptions<T>): Signal<T>;
304
+ /**
305
+ * Creates an optimistic signal: a value that can be set optimistically inside
306
+ * a transition and reverts to the value it covered when the transition ends.
307
+ *
308
+ * The write is a guess over the transition of the frame it is made in — the
309
+ * frame's held writes are its base, and it shows at once while they wait.
310
+ * Outside such a frame (nothing is held) the write is as if it never
311
+ * happened. With a function, the memo form: its own recompute is the truth
312
+ * — equal to the guess it confirms silently, different it corrects at the
313
+ * transition's commit.
314
+ *
315
+ * ```typescript
316
+ * const [state, setState] = createOptimistic<T>(value, options?: SignalOptions<T>);
317
+ * const [state, setState] = createOptimistic<T>(fn, options?: SignalOptions<T> & MemoOptions<T>);
318
+ * ```
319
+ *
320
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/create-optimistic
321
+ */
322
+ export declare function createOptimistic<T>(): Signal<T | undefined>;
323
+ export declare function createOptimistic<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;
324
+ export declare function createOptimistic<T>(fn: ComputeFunction<T>, options?: SignalOptions<T> & MemoOptions<T>): Signal<T>;
265
325
  /**
266
326
  * Creates a readonly derived reactive memoized signal.
267
327
  *
@@ -290,7 +350,7 @@ export declare function createSignal<T>(fn: ComputeFunction<T>, options?: Signal
290
350
  * });
291
351
  * ```
292
352
  *
293
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-memo
353
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/create-memo
294
354
  */
295
355
  export declare function createMemo<T>(compute: ComputeFunction<NoInfer<T>, T>, options: MemoOptions<T> & {
296
356
  loadingValue: T;
@@ -362,20 +422,9 @@ export declare function createMemo<T>(compute: ComputeFunction<undefined | NoInf
362
422
  * );
363
423
  * ```
364
424
  *
365
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-effect
366
- */
367
- export declare function createEffect<T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T> | EffectBundle<NoInfer<T>, T>, options?: EffectOptions): void;
368
- /**
369
- * @deprecated `createEffect(compute)` (single argument) is no longer supported.
370
- * Pass a separate effect function as the second argument:
371
- * `createEffect(compute, effect)`. See [MISSING_EFFECT_FN].
372
- *
373
- * - For a side effect that reacts to changes, split the work:
374
- * `createEffect(() => signal(), value => doWork(value))`.
375
- * - For a derived value, use `createMemo(() => signal())`.
376
- * - For a one-shot side effect at construction time, just call the function.
425
+ * @description https://v2.solidjs.com/reference/solid-js/reactivity/create-effect
377
426
  */
378
- export declare function createEffect<T>(compute: ComputeFunction<undefined | NoInfer<T>, T>): never;
427
+ export declare function createEffect<const T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T> | EffectBundle<NoInfer<T>, T>, options?: EffectOptions): void;
379
428
  /**
380
429
  * Creates a reactive computation that runs during the render phase as DOM elements
381
430
  * are created and updated but not necessarily connected.
@@ -403,13 +452,23 @@ export declare function createEffect<T>(compute: ComputeFunction<undefined | NoI
403
452
  * }
404
453
  * ```
405
454
  *
406
- * @description https://docs.solidjs.com/reference/secondary-primitives/create-render-effect
455
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/specialized-reactivity/create-render-effect
407
456
  */
408
- export declare function createRenderEffect<T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T>, options?: EffectOptions): void;
457
+ export declare function createRenderEffect<const T>(compute: ComputeFunction<undefined | NoInfer<T>, T>, effectFn: EffectFunction<NoInfer<T>, T>, options?: EffectOptions): void;
409
458
  /**
410
459
  * Creates a tracked reactive effect where dependency tracking and side effects happen
411
460
  * in the same scope.
412
461
  *
462
+ * @deprecated Do not use in new code. For a side effect that follows reactive
463
+ * state, use `createEffect(compute, effect)` — it separates tracking from the
464
+ * side effect, knows its dependencies before it runs, and participates in
465
+ * async and transitions. For one-time DOM work after render (measuring,
466
+ * attaching third-party widgets to a ref), use `onSettled`. Tracking from
467
+ * inside the effect phase — the only thing this primitive adds — is retained
468
+ * solely to ease 1.x migration: it runs beside user-effect callbacks after
469
+ * values commit, never holds a transition, and cannot observe a write staged
470
+ * earlier in the same flush by a signal it has not read yet.
471
+ *
413
472
  * WARNING: Because tracking and effects happen in the same scope, this primitive
414
473
  * may run multiple times for a single change or show tearing (reading inconsistent
415
474
  * state). Use only when dynamic subscription patterns require same-scope tracking.
@@ -439,7 +498,7 @@ export declare function createRenderEffect<T>(compute: ComputeFunction<undefined
439
498
  * });
440
499
  * ```
441
500
  *
442
- * @description https://docs.solidjs.com/reference/secondary-primitives/create-tracked-effect
501
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/specialized-reactivity/create-tracked-effect
443
502
  */
444
503
  export declare function createTrackedEffect(compute: () => void | (() => void), options?: BaseEffectOptions): void;
445
504
  /**
@@ -466,7 +525,7 @@ export declare function createTrackedEffect(compute: () => void | (() => void),
466
525
  * setCount(1); // logs once, reaction re-armed for next change
467
526
  * ```
468
527
  *
469
- * @description https://docs.solidjs.com/reference/secondary-primitives/create-reaction
528
+ * @description https://v2.solidjs.com/reference/solid-js/advanced/specialized-reactivity/create-reaction
470
529
  */
471
530
  export declare function createReaction(effectFn: EffectFunction<undefined> | EffectBundle<undefined>, options?: EffectOptions): (tracking: () => void) => void;
472
531
  /**
@@ -492,40 +551,95 @@ export declare function createReaction(effectFn: EffectFunction<undefined> | Eff
492
551
  */
493
552
  export declare function resolve<T>(fn: () => T): Promise<T>;
494
553
  /**
495
- * Creates an optimistic signal that can be used to optimistically update a value
496
- * and then revert it back to the previous value at end of transition.
554
+ * Invalidates one reactive source, forcing it to re-execute even if its inputs
555
+ * haven't changed, and returns a promise for the target's NEXT QUIESCENT
556
+ * STATE — the re-ask (and anything that supersedes it) has settled.
557
+ *
558
+ * Pass either a Solid-created accessor or a projected store created from
559
+ * `createStore(fn, ...)` / `createProjection(...)`. `refresh()` is a
560
+ * write-like invalidation operation: it does not read the target's value, and
561
+ * refreshing a plain signal accessor is a no-op that resolves immediately.
562
+ *
563
+ * The returned promise is safe to ignore (fire-and-forget refresh is
564
+ * unchanged, and a failed refetch will not surface an unhandled rejection).
565
+ * Awaiting it gives imperative flows the settle point without a reactive
566
+ * read:
567
+ * - Accessor targets resolve with the settled value; store targets resolve
568
+ * with the store node passed (reads through it are fresh after the await).
569
+ * - A failed re-ask rejects with the error.
570
+ * - Semantics are quiescence, not flight identity: if another refresh (or
571
+ * any invalidation) supersedes this one mid-flight, the promise waits for
572
+ * — and delivers — whatever finally lands.
573
+ *
574
+ * @example
575
+ * ```ts
576
+ * const user = createMemo(async () => fetch(`/users/${id()}`).then(r => r.json()));
497
577
  *
498
- * When called with a plain value, creates an optimistic signal with `SignalOptions` (name, equals, ownedWrite, unobserved).
499
- * When called with a function, creates a writable optimistic memo with `SignalOptions & MemoOptions` (adds id, lazy).
578
+ * // Fire-and-forget re-fetch
579
+ * <button onClick={() => refresh(user)}>Reload</button>;
500
580
  *
501
- * ```typescript
502
- * // Plain optimistic signal
503
- * const [state, setState] = createOptimistic<T>(value, options?: SignalOptions<T>);
504
- * // Writable optimistic memo (function overload)
505
- * const [state, setState] = createOptimistic<T>(fn, options?: SignalOptions<T> & MemoOptions<T>);
581
+ * // Imperative settle point
582
+ * const fresh = await refresh(user);
506
583
  * ```
507
- * @param value initial value of the signal; if empty, the signal's type will automatically extended with undefined
508
- * @param options optional object with a name for debugging purposes and equals, a comparator function for the previous and next value to allow fine-grained control over the reactivity
584
+ */
585
+ export declare function refresh<T>(target: Refreshable<T>): Promise<T extends (...args: any) => infer V ? V : T>;
586
+ /** Falsy values a truthy predicate result is narrowed against. */
587
+ export type Truthy<T> = Exclude<T, false | 0 | 0n | "" | null | undefined>;
588
+ /**
589
+ * The global `AbortSignal` when the consumer's libs declare one (DOM,
590
+ * WebWorker, `@types/node`), else the surface `until` uses — so these
591
+ * declarations check under neither lib without widening the global type.
592
+ */
593
+ type GlobalAbortSignal = typeof globalThis extends {
594
+ AbortSignal: {
595
+ prototype: infer S;
596
+ };
597
+ } ? S : {
598
+ readonly aborted: boolean;
599
+ readonly reason: any;
600
+ addEventListener(type: "abort", listener: () => void, options?: {
601
+ once?: boolean;
602
+ }): void;
603
+ removeEventListener(type: "abort", listener: () => void): void;
604
+ };
605
+ export interface UntilOptions {
606
+ /** Reject with `TimeoutError` if the predicate has not turned truthy within
607
+ * this many milliseconds. Strongly recommended when the confirming truth
608
+ * arrives over a transport that can drop (sockets, subscriptions). */
609
+ timeout?: number;
610
+ /** Reject with `signal.reason` on abort. */
611
+ signal?: GlobalAbortSignal;
612
+ }
613
+ /**
614
+ * Awaits a reactive predicate and resolves the first time it settles *truthy*,
615
+ * with that (narrowed) value. Falsy results and pending async reads both mean
616
+ * "not yet": the subscription stays live and re-evaluates as sources change.
617
+ * If the predicate settles with an error — a throw, or an async source that
618
+ * rejects — the promise rejects with it, as do timeout and abort.
509
619
  *
510
- * @returns `[state: Accessor<T>, setState: Setter<T>]`
620
+ * Where {@link resolve} answers "what is this value" (first settled value,
621
+ * whatever it is), `until` answers "when does the world confirm this
622
+ * condition".
623
+ *
624
+ * This is the acknowledgment mechanism for mutations confirmed on a live data
625
+ * channel (sockets, subscriptions, live queries) rather than by the mutation's
626
+ * own response: correlate by a client-generated id or version in the predicate,
627
+ * and let truth arrive however it arrives — push, refetch, or another tab.
628
+ *
629
+ * Must be called *outside* a tracking scope.
511
630
  *
512
631
  * @example
513
632
  * ```ts
514
- * const [todos, setTodos] = createOptimistic(initialTodos);
515
- *
516
- * const addTodo = action(function* (text: string) {
517
- * const tempId = crypto.randomUUID();
518
- * setTodos(t => [...t, { id: tempId, text, pending: true }]); // optimistic
519
- * const saved = yield api.createTodo(text);
520
- * setTodos(t => t.map(x => (x.id === tempId ? saved : x))); // reconcile
521
- * });
633
+ * const clientId = crypto.randomUUID();
634
+ * await socket.send({ clientId, text }); // fire-and-forget transport
635
+ * // Wait until the live source echoes the write:
636
+ * await until(() => messages.some(m => m.clientId === clientId), { timeout: 10_000 });
522
637
  * ```
523
638
  *
524
- * @description https://docs.solidjs.com/reference/basic-reactivity/create-optimistic-signal
639
+ * @param fn a reactive predicate
640
+ * @param options optional `timeout` (ms) and abort `signal`
525
641
  */
526
- export declare function createOptimistic<T>(): Signal<T | undefined>;
527
- export declare function createOptimistic<T>(value: Exclude<T, Function>, options?: SignalOptions<T>): Signal<T>;
528
- export declare function createOptimistic<T>(fn: ComputeFunction<T>, options?: SignalOptions<T> & MemoOptions<T>): Signal<T>;
642
+ export declare function until<T>(fn: () => T, options?: UntilOptions): Promise<Truthy<T>>;
529
643
  /**
530
644
  * Schedules `callback` to run **once** after the reactive graph has fully
531
645
  * settled — i.e. once every pending async read inside the current owner has
@@ -621,4 +735,41 @@ export declare function createOptimistic<T>(fn: ComputeFunction<T>, options?: Si
621
735
  * on owner disposal
622
736
  */
623
737
  export declare function onSettled(callback: () => void | (() => void)): void;
738
+ /**
739
+ * Schedules `callback` to run **once**, right after the pending flush
740
+ * finishes, in the same microtask checkpoint (before the browser paints).
741
+ * Unlike `onSettled`, it never waits on async work: if that flush is held by
742
+ * a pending transition, the callback still runs.
743
+ *
744
+ * Its main use is keeping a write out of another update's hold. Writes made
745
+ * in the same synchronous frame are applied together, so when one of them
746
+ * starts async work (a route change, a fetch), the others are held with it
747
+ * until it resolves. A write made in `onFlush` happens after that flush, so
748
+ * it is its own update: it commits on its own unless something it changes
749
+ * also derives from the held work (a memo or `createEffect` reading both),
750
+ * in which case it joins that hold as any later write would.
751
+ *
752
+ * Call it from event handlers and effect callbacks (including
753
+ * `createTrackedEffect` and `onSettled` bodies). In an owned scope such as a
754
+ * component body or a computation it warns in dev: use `onSettled` there.
755
+ *
756
+ * - A write in the callback lands after any write made inline in the same
757
+ * frame. Don't write the same signal both inside and outside it; use a
758
+ * functional setter if the order matters.
759
+ * - Several `onFlush` callbacks run in call order and batch into one flush.
760
+ * - `queueMicrotask` is not a substitute: called before the frame's first
761
+ * write, it runs before that flush and its write joins it.
762
+ *
763
+ * @example
764
+ * ```tsx
765
+ * // A menu closes now even when the consumer's onSelect starts async work.
766
+ * const select = (id: string) => {
767
+ * onFlush(() => setOpen(false));
768
+ * props.onSelect?.(id);
769
+ * };
770
+ * ```
771
+ *
772
+ * @param callback Function to run once after the pending flush
773
+ */
774
+ export declare function onFlush(callback: () => void): void;
624
775
  export {};
@@ -0,0 +1,12 @@
1
+ import type { Computed, Signal } from "../core/types.js";
2
+ import { type StoreTarget } from "./target.js";
3
+ type Marked = Signal<any> | Computed<any>;
4
+ /** The nodes an `affects(store[, key])` declaration marks (affects.ts
5
+ * registers each). */
6
+ export declare function storeMarks(t: StoreTarget, key: PropertyKey | undefined): Marked[];
7
+ /** `affects()` calls it before a store-targeted declaration (idempotent). */
8
+ export declare function installStoreAffects(): void;
9
+ /** The carrier's last mark released (affects.ts): its scope dies, and the
10
+ * nodes that inherited the mark release theirs. */
11
+ export declare function releaseMarkScope(carrier: Marked): void;
12
+ export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @internal The name of the store `x` belongs to — `x` a store proxy (a
3
+ * setter's entry) or one of its property nodes (the setter notifying it) —
4
+ * or undefined when it has none or it cannot be placed: a projection or
5
+ * optimistic family, a store chained over another store's proxy, a root
6
+ * named twice, or a proxy reached through a store other than the one it
7
+ * was named as the root of.
8
+ */
9
+ export declare function storeName(x: object | undefined): string | undefined;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Store — the engine's optional-machinery slots, in a module of their own so
3
+ * an installer reaches them without importing store.ts (whose top level
4
+ * installs the engine): the store half of `affects()` installs through here
5
+ * from `affects()`, and an app without stores carries none of the engine.
6
+ * A slot no installer reaches stays `null`, and a bundler folds its sites.
7
+ */
8
+ import type { Transaction } from "../core/scheduler.js";
9
+ import type { Signal } from "../core/types.js";
10
+ import type { StoreFamily, StoreTarget } from "./target.js";
11
+ /** The optimistic machinery (optimistic.ts, S4), installed when it loads
12
+ * — a plain store pays nothing for it (#2883): the plain paths reach it
13
+ * only through a family with `opt` set, which only `createOptimisticStore`
14
+ * sets. */
15
+ export interface OptHooks {
16
+ /** A user setter's draft on an optimistic family: a clone of the
17
+ * writer's view (a staging already on the target is set aside). */
18
+ draft(t: StoreTarget): Record<PropertyKey, any>;
19
+ /** The setter's exit: the draft becomes guesses; returns the staging the
20
+ * draft set aside (`null`: none). */
21
+ writes(t: StoreTarget, pb: Record<PropertyKey, any>): Record<PropertyKey, any> | null;
22
+ /** `src` with the lanes' values over it (`writer`: the next write's base
23
+ * — the unflushed guesses too). */
24
+ view(t: StoreTarget, src: Record<PropertyKey, any>, writer?: boolean): Record<PropertyKey, any>;
25
+ /** An untracked `key in store`: the presence guess, or `undefined`. */
26
+ has(t: StoreTarget, key: PropertyKey): boolean | undefined;
27
+ /** A guessed key's descriptor (`null`: removed; `undefined`: no guess). */
28
+ descriptor(t: StoreTarget, key: PropertyKey): PropertyDescriptor | null | undefined;
29
+ /** The flush's commit: targets no lane holds leave `overlaid`. */
30
+ sweep(): void;
31
+ /** The container comparator's lane arm: an arrangement guess against a
32
+ * landing (or another arrangement), by row identity. */
33
+ arrangement(t: StoreTarget, a: any, b: any): boolean;
34
+ /** A user's `reconcile` on an optimistic family: the keyed diff written
35
+ * into the draft. */
36
+ reconcile(draft: any, incoming: any, keyFn: ((item: any) => any) | null): void;
37
+ /** The derive's draft wrote `pb` on `t`: the new object at a guessed
38
+ * row's slot (by key in a keyed list) is adopted by that row's target. */
39
+ pair(t: StoreTarget, pb: Record<PropertyKey, any>): void;
40
+ /** The derive of `fam` went in flight (#4336): a new question asked over
41
+ * the family's guesses is judged by its reads (`stands`) and at the seam
42
+ * (`park`). */
43
+ ask(fam: StoreFamily): void;
44
+ /** The flush parks with `t`: a guess a frame still reads, over a family
45
+ * asked a new question this flush, holds `t` with its action (D-34). */
46
+ park(t: Transaction): void;
47
+ /** A read of `t` while its family's derive is in flight: the family's
48
+ * guesses stand in for the flight (no suspension). */
49
+ stands(t: StoreTarget): boolean;
50
+ }
51
+ export declare let optHooks: OptHooks | null;
52
+ export declare function installOptHooks(hooks: OptHooks): void;
53
+ /** The store half of `affects()` (store/affects.ts), installed by the first
54
+ * store-targeted declaration: a node born on a covered record inherits the
55
+ * live mark; an untracked verdict probe through a record with no node is
56
+ * witnessed. */
57
+ export interface AffectsHooks {
58
+ _born(t: StoreTarget, node: Signal<any>, key: PropertyKey): void;
59
+ _witness(t: StoreTarget, key: PropertyKey | undefined): void;
60
+ }
61
+ export declare let affectsHooks: AffectsHooks | null;
62
+ export declare function installAffectsHooks(hooks: AffectsHooks): void;
@@ -1,19 +1,46 @@
1
- export type { Store, StoreReturn, ProjectionStoreReturn, StoreSetter, StoreNode, StoreOptions, ProjectionOptions, NotWrappable, SolidStore } from "./store.js";
1
+ /**
2
+ * Store — public surface. Plain stores (S1) are live; the derived form
3
+ * (`createStore(fn, seed)`), projections, optimistic stores and reconcile
4
+ * return on later steps (plan sec. 31.5).
5
+ */
6
+ export type { NoArray, NoFn, NotWrappable, ProjectionOptions, ProjectionStoreReturn, SolidStore, Store, StoreOptions, StoreReturn, StoreSetter } from "./types.js";
7
+ export { $PROXY, $RECORD, $TARGET, $TRACK, isWrappable, markRaw } from "./types.js";
8
+ export { storeIsShallow, storeHasFamily, storeHasOptimisticFamily } from "./store.js";
9
+ export { storePath } from "./storePath.js";
10
+ export type { StorePathRange, PathSetter, Part, CustomPartial, ArrayFilterFn } from "./storePath.js";
11
+ import { createOptimisticStore } from "./optimistic.js";
12
+ import { createProjection } from "./projection.js";
13
+ import type { NoArray, NoFn, ProjectionOptions, ProjectionStoreReturn, Store, StoreOptions, StoreReturn } from "./types.js";
14
+ export { createOptimisticStore, createProjection };
15
+ /** The store's internal record behind a proxy (`store[$TARGET]`). Kept
16
+ * under `next`'s public name; its shape is the L2 target's (plan plan sec. 31–32:
17
+ * the symbol-keyed legacy record is gone with the representation). */
18
+ export type { StoreTarget as StoreNode } from "./target.js";
2
19
  export type { Merge, Omit } from "./utils.js";
3
- export { isWrappable, $TRACK, $PROXY, $TARGET } from "./store.js";
4
- import type { NoFn, ProjectionOptions, Store, StoreOptions, StoreSetter } from "./store.js";
5
- import type { Refreshable } from "../core/index.js";
6
- export { createProjectionNext as createProjection } from "./next/projection.js";
7
- export { createOptimisticStoreNext as createOptimisticStore } from "./next/optimistic.js";
8
- /** Public createStore: plain form `(init, options?)` and derived writable
9
- * form `(fn, seed, options?)`. */
10
- export declare function createStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions & {
11
- shallow?: boolean;
12
- }): [get: Store<T>, set: StoreSetter<T>];
13
- export declare function createStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
20
+ export { mergeSources, mergeView, viewOf, omitView, sourceKeys, sourceHas, sourceGet, hasStaticKeys, isStatic, resolvedTable, OmitView, MergeView, SOURCE_PLAIN, SOURCE_OMIT, SOURCE_PROXY, SOURCE_MEMO, SOURCE_MERGE, sourceOwners, merge, omit } from "./utils.js";
21
+ export type { SourceKind } from "./utils.js";
22
+ /**
23
+ * Create a reactive store: a proxy over plain data with fine-grained
24
+ * subscriptions per read path, written through its setter's draft — or, in
25
+ * the derived form, a projection with a setter.
26
+ *
27
+ * The derived form comes in two shapes. Seedless, `createStore(fn)`: `fn`
28
+ * takes no draft and every answer is a complete `T` (plain-object roots only;
29
+ * pass `undefined` for the seed to reach the options). Seeded,
30
+ * `createStore(fn, seed)`: the seed is a complete `T` the derive drafts
31
+ * against — `[]` for an array.
32
+ */
33
+ export declare function createStore<T extends object = {}>(initialValue: NoFn<T>, options?: StoreOptions): StoreReturn<T>;
34
+ export declare function createStore<T extends object = {}>(fn: (() => T | Promise<T> | AsyncIterable<T>) & NoArray<T>, seed?: null, options?: Omit<ProjectionOptions, "seedLoadingValue">): ProjectionStoreReturn<T>;
35
+ export declare function createStore<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): ProjectionStoreReturn<T>;
36
+ /**
37
+ * A setter transform that reconciles `value` into the store by key
38
+ * (`"id"` by default; `null` positional), preserving store identity for
39
+ * surviving rows.
40
+ */
14
41
  export declare function reconcile<T extends U, U>(value: T, key?: string | ((item: NonNullable<any>) => any) | null): (state: U) => T;
42
+ /** Non-tracking snapshot of a store's current value (source identity for
43
+ * unmodified subtrees). */
15
44
  export declare function snapshot<T>(value: T): T;
45
+ /** Tracking snapshot: subscribes to every reachable record. */
16
46
  export declare function deep<T>(value: T): T;
17
- export { storePath } from "./storePath.js";
18
- export type { PathSetter, Part, StorePathRange, ArrayFilterFn, CustomPartial } from "./storePath.js";
19
- export { merge, omit } from "./utils.js";
@@ -1,45 +1,24 @@
1
- import { type Refreshable } from "../core/index.js";
2
- import { type NoFn, type ProjectionOptions, type Store, type StoreSetter } from "./store.js";
3
- /**
4
- * The store equivalent of `createOptimistic`. Writes inside an `action`
5
- * transition are tentative — they show up immediately but auto-revert (or
6
- * reconcile to the action's resolved value) once the transition finishes.
7
- *
8
- * Use this for optimistic UI on collection-shaped data. For single-value
9
- * optimistic state, prefer `createOptimistic`.
10
- *
11
- * - Plain form: `createOptimisticStore(initialValue)`.
12
- * - Derived form: `createOptimisticStore(fn, seed, options?)` — a projection
13
- * store whose authoritative value is recomputed by `fn` and whose
14
- * optimistic overlay reverts after each transition.
15
- *
16
- * `options.key` defaults to `"id"`; specify it only when your data uses a
17
- * different identity field (e.g. `{ key: "uuid" }` or `{ key: t => t.slug }`),
18
- * or `null` to merge positionally. Restating the default just adds noise.
19
- *
20
- * @example
21
- * ```ts
22
- * const [todos, setTodos] = createOptimisticStore<Todo[]>([]);
23
- *
24
- * // Mutation: optimistic add, then in-place reconcile to the saved row.
25
- * const addTodo = action(function* (text: string) {
26
- * const tempId = crypto.randomUUID();
27
- * setTodos(t => { t.push({ id: tempId, text, pending: true }); });
28
- * const saved = yield api.createTodo(text);
29
- * setTodos(t => {
30
- * const i = t.findIndex(x => x.id === tempId);
31
- * if (i >= 0) t[i] = saved;
32
- * });
33
- * });
34
- *
35
- * // Return form: filter is the natural shape for removal.
36
- * const removeTodo = action(function* (id: string) {
37
- * setTodos(t => t.filter(x => x.id !== id));
38
- * yield api.removeTodo(id);
39
- * });
40
- * ```
41
- *
42
- * @returns `[store: Store<T>, setStore: StoreSetter<T>]`
43
- */
44
- export declare function createOptimisticStore<T extends object = {}>(store: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Store<T>, set: StoreSetter<T>];
45
- export declare function createOptimisticStore<T extends object = {}>(fn: (store: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, store: Partial<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
1
+ import type { Refreshable } from "../core/index.js";
2
+ import { type StoreTarget } from "./target.js";
3
+ import { type NoArray, type NoFn, type ProjectionOptions, type Store, type StoreOptions, type StoreSetter } from "./types.js";
4
+ export declare function notifyOptimisticWrites(t: StoreTarget, pb: Record<PropertyKey, any>): Record<PropertyKey, any> | null;
5
+ export declare function sweepOverlaid(): void;
6
+ /** An untracked `key in store` on an optimistic family: the presence guess
7
+ * (what its lane shows) when the key carries one; `undefined` when not —
8
+ * the backing answers. */
9
+ export declare function optimisticHas(t: StoreTarget, key: PropertyKey): boolean | undefined;
10
+ /** A descriptor read of a guessed key: synthesized from the lane's value
11
+ * (`null`: the guess removed the key; `undefined`: no guess — the backing
12
+ * describes it). */
13
+ export declare function optimisticOwnDescriptor(t: StoreTarget, key: PropertyKey): PropertyDescriptor | null | undefined;
14
+ /** The truth `src` with the target's lane values over it: each overlaid
15
+ * leaf's value (`pick`: what the lane shows, or — for `latest` — the lane's
16
+ * latest), each presence guess as a key added or removed, the array
17
+ * length. Returns `src` itself when nothing is overlaid. */
18
+ export declare function optimisticView(t: StoreTarget, src: Record<PropertyKey, any>, pick?: (n: any) => unknown, writer?: boolean): Record<PropertyKey, any>;
19
+ /** `latest()`'s view: the lanes' latest values (a landing staged beneath a
20
+ * guess is what lands). */
21
+ export declare function latestView(t: StoreTarget, src: Record<PropertyKey, any>): Record<PropertyKey, any>;
22
+ export declare function createOptimisticStore<T extends object = {}>(initialValue: NoFn<T> | Store<NoFn<T>>, options?: StoreOptions): [get: Store<T>, set: StoreSetter<T>];
23
+ export declare function createOptimisticStore<T extends object = {}>(fn: (() => T | Promise<T> | AsyncIterable<T>) & NoArray<T>, seed?: null, options?: Omit<ProjectionOptions, "seedLoadingValue">): [get: Refreshable<Store<T>>, set: StoreSetter<T>];
24
+ export declare function createOptimisticStore<T extends object = {}>(fn: (draft: T) => void | T | Promise<void | T> | AsyncIterable<void | T>, seed: NoFn<T> | Store<NoFn<T>>, options?: ProjectionOptions): [get: Refreshable<Store<T>>, set: StoreSetter<T>];