@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
@@ -1,24 +1,75 @@
1
- import type { Computed, Signal } from "./types.js";
1
+ import type { ChangeOrigin } from "./attribution.js";
2
+ import type { Transaction } from "./scheduler.js";
3
+ import type { Computed, Owner, Signal } from "./types.js";
4
+ /** The hold the engine records against (L2: scheduler.ts `Transaction`).
5
+ * Outward-facing language says *holds*; the engine's hook names keep their
6
+ * historical `transition` wording. */
7
+ export type Transition = Transaction;
2
8
  /**
3
- * Dev-only observability hook points for the reactive core.
9
+ * Observe-tier hook points for the reactive core.
4
10
  *
5
11
  * Core's obligation is to call these with true facts at the moments they
6
12
  * happen; ALL attribution semantics (stamps, cause chains, timings, warnings)
7
- * live in the engine that installs them (attribution.ts — same pattern as the
8
- * GlobalQueue._* feature slots). `attrHooks` is null unless an engine is
9
- * installed, so the disabled cost is one null check per site, and prod builds
10
- * fold every site out behind __DEV__.
13
+ * live in the engine that installs them — `@solidjs/signals/attribution`, a
14
+ * separate entry so an observe build that never enables it never ships it
15
+ * (same pattern as the GlobalQueue._* feature slots). `attrHooks` is null
16
+ * unless an engine is installed, so the disabled cost is one null check per
17
+ * site, and prod builds fold every site out behind __OBSERVE__.
18
+ *
19
+ * The contract is internal: the built-in engine installs through
20
+ * `setAttributionHooks`, and nothing public names this interface
21
+ * (`OBSERVE.attribution.installed` exposes the installed table as an opaque
22
+ * object). It becomes public surface again the day a second engine exists.
11
23
  *
12
24
  * IMPORTANT for implementers of call sites: a hook call must never sit inside
13
25
  * a `try` block — rollup's tryCatchDeoptimization retains functions referenced
14
- * inside `try` even behind a folded __DEV__ guard, which re-couples the dev
26
+ * inside `try` even behind a folded __OBSERVE__ guard, which re-couples the
15
27
  * engine into prod bundles (#2883 harness). Set a local flag inside the try
16
28
  * and call the hook after the catch.
17
29
  */
18
30
  export interface AttributionHooks {
31
+ /**
32
+ * `withInteraction` opened a user-interaction frame: root writes until the
33
+ * matching `interactionEnd` were performed by the handler of `ref`. Frames
34
+ * nest strictly (synchronous dispatch), so the engine keeps a stack.
35
+ */
36
+ interactionStart(ref: InteractionRef): void;
37
+ /**
38
+ * The handler returned. `returned` is its return value: a thenable means
39
+ * the handler continues past this frame (`async () => { await … }`), and
40
+ * the engine may keep the interaction's record open until it settles —
41
+ * the wait the person experiences is that continuation, not the frame.
42
+ */
43
+ interactionEnd(returned?: unknown): void;
44
+ /**
45
+ * `withOrigin` opened a declared-origin frame: root writes until the
46
+ * matching `originEnd` are the unit of work `ref` describes (a router's
47
+ * navigation). Nests inside an interaction frame — a link click that
48
+ * navigates — or stands alone (a redirect from an action, a programmatic
49
+ * `navigate()`). Frames nest strictly, so the engine keeps a stack.
50
+ */
51
+ originStart(ref: NavigationRef): void;
52
+ originEnd(): void;
53
+ /**
54
+ * A `flush()` drain is starting: work is scheduled or a transition is
55
+ * active, so the loop will run at least once. Always paired with
56
+ * `flushEnd` for the same drain, and never nested (`flush()` is a no-op
57
+ * while the queue is running), so start → end is the wall time of one
58
+ * drain — the scheduler's own span.
59
+ */
60
+ flushStart(): void;
61
+ /**
62
+ * A `flush()` drain finished: every batch it processed either committed
63
+ * (its effects have run) or was parked in a held transition (`holdStart`
64
+ * fired for it). Fires once per drain, after the loop — not per batch, and
65
+ * not for a `flush()` call that found nothing to do. Gives the engine the
66
+ * "committed, screen updated" instant for writes no transition ever held.
67
+ */
68
+ flushEnd(): void;
19
69
  /**
20
70
  * A recompute is starting; `el._deps` still holds the previous run's links.
21
- * Always paired with `recomputeEnd` (recompute has no early returns).
71
+ * Always paired with `recomputeEnd` (recompute's one early return — a node
72
+ * disposed during its own pass, #3621 — fires it before leaving).
22
73
  */
23
74
  recomputeStart(el: Computed<any>, create: boolean): void;
24
75
  /**
@@ -36,6 +87,17 @@ export interface AttributionHooks {
36
87
  write(el: Signal<any> | Computed<any>, prev: unknown, value: unknown): void;
37
88
  /** refresh() invalidated this node (self-invalidation, no dep changed). */
38
89
  refreshed(el: Computed<any>): void;
90
+ /**
91
+ * A new async flight entered the system (`_inFlight` was just assigned
92
+ * during a recompute of `el`). Always fired inside the owning recompute —
93
+ * both call paths (core's recompute and the projection self-registration)
94
+ * run within one — so the engine can read the current frame stack to link
95
+ * the flight to the change that caused it (waterfall chaining). `flight`
96
+ * is the registered thenable/iterable itself: the engine keys a first-seen
97
+ * origin registry on its identity, so shared and preloader-marked promises
98
+ * carry their true start time instead of the moment the graph saw them.
99
+ */
100
+ flightStart(el: Computed<any>, flight: object): void;
39
101
  /** An async landing is about to apply its value (before any branch). */
40
102
  asyncStart(el: Computed<any>): void;
41
103
  /**
@@ -47,6 +109,243 @@ export interface AttributionHooks {
47
109
  * from the node's state against its asyncStart snapshot.
48
110
  */
49
111
  asyncEnd(el: Computed<any>, prev: unknown, value: unknown, direct: boolean): void;
112
+ /**
113
+ * An effect's imperative half (its effect callback) is about to run /
114
+ * has run. Both fire outside the run's try; `effectRunEnd` fires whether
115
+ * or not the callback threw. Writes between the two are the effect's.
116
+ */
117
+ effectRunStart(el: Computed<any>): void;
118
+ effectRunEnd(el: Computed<any>): void;
119
+ /**
120
+ * One synchronous step of an `action()` generator is about to run / has
121
+ * run (`it.next()`/`it.throw()` up to the next yield). `it` is the
122
+ * invocation's iterator — stable identity across its steps; `name` the
123
+ * generator function's name. Writes between the two are the action's.
124
+ */
125
+ actionStepStart(it: object, name: string | undefined): void;
126
+ actionStepEnd(it: object): void;
127
+ /**
128
+ * A flush found `t` incomplete (transitionComplete's false verdict): its
129
+ * writes stay staged and its queues are about to be parked. Fired BEFORE
130
+ * this flush's lane effects (the visible acknowledgers — isPending
131
+ * companions, optimistic values) run; `holdEnd` fires from the root
132
+ * stashQueues call after them, so effect runs between the two are runs that
133
+ * painted *during* the hold.
134
+ */
135
+ holdStart(t: Transition): void;
136
+ holdEnd(): void;
137
+ /**
138
+ * `t` was judged complete (transitionComplete's true verdict, before `_done`
139
+ * flips). Fired before its held writes commit, so `t._pendingNodes` still
140
+ * lists what was staged.
141
+ */
142
+ transitionSettled(t: Transition): void;
143
+ /** `outgoing` was folded into `target` (`outgoing._done = target`). */
144
+ transitionMerged(target: Transition, outgoing: Transition): void;
145
+ /**
146
+ * A store setter batch replaced the container at `path` (e.g. `store.user`)
147
+ * with a different one (both non-null, same array-ness, not the same
148
+ * logical slot), and this is the leaf census of the new container against
149
+ * the old: `total` leaves (own keys, or items) in the new one, `unchanged`
150
+ * of which are the same value as before (identity, judged on unwrapped
151
+ * values — object keys compared by key, array items by membership), and
152
+ * `prevTotal` leaves in the old one. Containers above 64 leaves are not
153
+ * announced. Fired per written key from the write channel's notify. The
154
+ * engine decides whether the replacement was a spread-copy worth a
155
+ * diagnostic. `owner` is the owner the store root was created under
156
+ * (undefined when unrecorded): the finding is about the store, not about
157
+ * whoever wrote it, so an `OBSERVE.exclude`d panel's store stays silent
158
+ * however its writes arrive.
159
+ */
160
+ storeReplaced(path: string, isArray: boolean, total: number, unchanged: number, prevTotal: number, owner: Owner | null | undefined): void;
161
+ /**
162
+ * A `mapArray` update both disposed and created rows: `removed` are the
163
+ * items whose rows were disposed, `created` the items that got new rows,
164
+ * `newLen` the list's new length, `keyed` whether a key function is in use
165
+ * (false = identity or by-index). Fired after commit. The engine judges
166
+ * whether the churn replaced equivalent records (unstable identity).
167
+ */
168
+ listChurn(el: Computed<any>, removed: unknown[], created: unknown[], newLen: number, keyed: boolean): void;
169
+ /**
170
+ * A loading boundary started (`shown` true) or stopped showing its
171
+ * fallback. `boundary` is the boundary's queue (stable identity); `tree`
172
+ * its bound subtree computed when already constructed — the first show can
173
+ * fire while the subtree is still being built — whose owner chain names
174
+ * the boundary. Fired at the source-set transitions (first pending source
175
+ * registers / last one clears), not per flush.
176
+ *
177
+ * A show is the boundary's SWAP, a staged write: `transition` is the one
178
+ * it lands with (`transitionSettled` is its display instant), or `null`
179
+ * when this drain commits it (`flushEnd`) — the lane swap included, whose
180
+ * readers run in this drain. A hide before that commit means the fallback
181
+ * was never displayed — the content landed first and the sweep cleared the
182
+ * swap ahead of the frame (#3540).
183
+ */
184
+ boundaryFallback(boundary: object, tree: Computed<any> | undefined, shown: boolean, transition?: Transition | null): void;
185
+ /**
186
+ * An optimistic override the screen displayed is being replaced by a
187
+ * different value. `"superseded"`: a new authoritative value landed that
188
+ * differs from the guess (tracked readers re-derive to it). `"reverted"`:
189
+ * nothing new landed and the guess lifts back to the committed value it
190
+ * covered (the action failed, or never wrote what it promised). `shown`
191
+ * is the override as displayed. Fired when the two differ by identity;
192
+ * the engine applies the node's own equality before judging.
193
+ */
194
+ optimisticReverted(el: Signal<any> | Computed<any>, shown: unknown, truth: unknown, how: "superseded" | "reverted"): void;
195
+ /**
196
+ * The one query on the surface: the provenance a root write performed at
197
+ * this moment would be stamped with — the innermost open frame (an effect
198
+ * callback, an action step, a navigation), the interaction the handler
199
+ * runs under, or, inside a recompute, the origin of the change that caused
200
+ * it — or `undefined` when none applies (external). For a runtime that
201
+ * records a fact of its own beside the engine's records — `@solidjs/web`'s
202
+ * `"call"` record stamps the server-function call it is about to make —
203
+ * so the fact joins the engine's interaction and navigation records by the
204
+ * identity of the object returned, not by time.
205
+ */
206
+ currentOrigin(): ChangeOrigin | undefined;
207
+ }
208
+ /** A user interaction, as a rendering runtime describes it to `withInteraction`. */
209
+ export interface InteractionRef {
210
+ /** Event type — `click`, `keydown`, `input`… */
211
+ type: string;
212
+ /**
213
+ * The element hit, e.g. `button#next "Next →"` — the tag, then `#id` or
214
+ * `[name=…]`, then the element's text in quotes. Describe fully; the
215
+ * engine keeps the quoted text as its `values` option allows (the
216
+ * record's `target` is its own string, this one is never mutated).
217
+ */
218
+ target?: string;
219
+ /** Dispatch time on the `performance.now()` clock; defaults to now. */
220
+ at?: number;
221
+ /**
222
+ * The dispatch this frame handles — the DOM `Event` itself. Frames with the
223
+ * same `event` are one interaction: the first opens the record (its `type`,
224
+ * `target` and `at` describe it) and every later one re-enters it, so each
225
+ * listener of one dispatch adds its work to one record. Such a record stays
226
+ * open for joining until the next task — every listener of a dispatch runs
227
+ * within its task — and is recorded no earlier; a frame for the event after
228
+ * that opens a new interaction. Without `event` the record is the frame's
229
+ * alone and can settle as it closes.
230
+ *
231
+ * A join key only, compared by identity and held weakly: it is never
232
+ * recorded — no `InteractionEvent`, origin or other record carries it — and
233
+ * the engine keeps no strong reference to it.
234
+ */
235
+ event?: object;
236
+ }
237
+ /**
238
+ * A navigation, as a router describes it to `withOrigin` around the location
239
+ * write it is about to perform — what `withOrigin` accepts: a declared unit
240
+ * of work whose writes the engine attributes as a whole, discriminated by
241
+ * `kind` so another kind (a form submission, a tab switch) can join without
242
+ * the seam changing shape; the engine knows `navigation` today. Match
243
+ * eagerly and describe before writing: the engine keys the work the write
244
+ * causes — the hold behind route data, the re-runs, the verdicts — to this
245
+ * record, and names it by the parametrized route so occurrences fold
246
+ * together.
247
+ *
248
+ * The engine keeps the object and reads `name`, `to` and `params` again when
249
+ * the navigation settles (and when a hold on it is judged), so a router whose
250
+ * match is not final at write time — a lazy route subtree that resolves inside
251
+ * the hold — may describe coarsely (`/admin/*`) and assign the exact pattern
252
+ * and params onto the same object once it knows them. `from` and `at` are
253
+ * read once, when the frame opens.
254
+ */
255
+ export interface NavigationRef {
256
+ kind: "navigation";
257
+ /** The matched route pattern — `/users/:id`. The name every consumer groups by. */
258
+ name?: string;
259
+ /** Concrete destination path. */
260
+ to?: string;
261
+ /** Concrete path being left. */
262
+ from?: string;
263
+ /** Route params the pattern bound — `{ id: "42" }` (optional params unbound: `undefined`). */
264
+ params?: Readonly<Record<string, string | undefined>>;
265
+ /**
266
+ * When the navigation was requested on the `performance.now()` clock;
267
+ * defaults to now. A router whose request predates the write (loaders
268
+ * awaited before the location moves) passes its own start here.
269
+ */
270
+ at?: number;
271
+ /**
272
+ * `>= 1`: this frame is the Nth redirect hop of the navigation still
273
+ * pending — a guard or loader sent it elsewhere before it landed — not a
274
+ * new navigation. The engine folds it onto that pending record: the record
275
+ * keeps the user's request time and interaction, its destination becomes
276
+ * this one, and the abandoned destination is kept in `redirects`. Without
277
+ * a pending navigation to fold onto it opens a navigation of its own.
278
+ */
279
+ redirect?: number;
280
+ /**
281
+ * The route the document arrived on — declared by the router around the
282
+ * work that establishes its initial match (building its context), not
283
+ * around a write: there is no location write on a fresh document, and
284
+ * without this a consumer has the route pattern for every navigation
285
+ * but the first. The record opens at `at`, which defaults to `0` (the
286
+ * `performance.now()` origin — the document's own navigation start, so
287
+ * the record joins Navigation Timing); a router mounted long after the
288
+ * document loaded passes its own start. It settles when the frame closes,
289
+ * `committed` with no writes: it declares the route, it does not time the
290
+ * mount — the holds the mount waits in are their own records. `from` is
291
+ * meaningless for it and ignored.
292
+ */
293
+ initial?: boolean;
294
+ /**
295
+ * The interaction the navigation is for, when the router already knows it
296
+ * will not be on the stack at write time. A router that awaits between
297
+ * the request and the write (guards or loaders resolved in its core before
298
+ * it publishes the location) captures `OBSERVE.attribution.currentOrigin()`
299
+ * in the request and hands it back here, and the record — and every hold
300
+ * and re-run its write causes — joins the click as if the write had been
301
+ * synchronous. Any origin will do: the engine takes the interaction it
302
+ * carries. Declared beats ambient: the key's presence is the declaration
303
+ * — `interaction: currentOrigin()` with nothing in effect at the request
304
+ * (`undefined`) declares that the navigation was for no interaction, and an
305
+ * interaction on the stack at write time is used only when the key is absent.
306
+ */
307
+ interaction?: ChangeOrigin;
50
308
  }
51
309
  export declare let attrHooks: AttributionHooks | null;
52
310
  export declare function setAttributionHooks(hooks: AttributionHooks | null): void;
311
+ /**
312
+ * Run `fn` as the handler of a user interaction: every root write it performs
313
+ * (and every action step, effect or flight the write causes) is attributed to
314
+ * `ref` by whichever engine is installed. The web runtime wraps event
315
+ * dispatch in this; custom renderers and test harnesses call it themselves.
316
+ * With no engine installed it is `fn()` — the wiring, not the engine, so it
317
+ * lives in core and is reachable as `OBSERVE.attribution.withInteraction`.
318
+ *
319
+ * The `finally` is deliberate and safe under the try rule above: this
320
+ * function is referenced only from the `OBSERVE` object, which prod builds
321
+ * fold to `undefined`, so nothing retains it there.
322
+ */
323
+ export declare function withInteraction<T>(ref: InteractionRef, fn: () => T): T;
324
+ /**
325
+ * Run `fn` as a declared unit of work — a router's navigation: every root
326
+ * write it performs is attributed to `ref` (and, through it, to the enclosing
327
+ * interaction when there is one), so the hold those writes wait in, the
328
+ * re-runs they cause and the verdicts on them all carry the route's name
329
+ * instead of a bare signal's. Same contract as `withInteraction`: the wiring,
330
+ * not the engine; `fn()` with no engine installed. Reachable as
331
+ * `OBSERVE.attribution.withOrigin`.
332
+ *
333
+ * ```ts
334
+ * OBSERVE
335
+ * ? OBSERVE.attribution.withOrigin(
336
+ * { kind: "navigation", name: match.pattern, to, from, params: match.params },
337
+ * () => setLocation(to)
338
+ * )
339
+ * : setLocation(to);
340
+ * ```
341
+ */
342
+ export declare function withOrigin<T>(ref: NavigationRef, fn: () => T): T;
343
+ /**
344
+ * The provenance a root write performed now would carry, as the installed
345
+ * engine sees it (`AttributionHooks.currentOrigin`); `undefined` with no
346
+ * engine, or when nothing is in effect. Reachable as
347
+ * `OBSERVE.attribution.currentOrigin` — how a runtime stamps a fact of its
348
+ * own (a server-function call) with the interaction or navigation it ran
349
+ * for, so an observer joins the two by identity.
350
+ */
351
+ export declare function currentOrigin(): ChangeOrigin | undefined;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Point queries over the engine's live state — the devtools/console view of
3
+ * one scope. Their own module so a records-only consumer never ships them;
4
+ * they read the engine's ring buffer and the graph, and register nothing.
5
+ */
6
+ import { type RerunEvent } from "./attribution.js";
7
+ /**
8
+ * Re-run history for one scope — pass a memo/effect accessor or raw node,
9
+ * or a scope's name as a string (an out-of-process consumer such as the
10
+ * diagnostics bridge holds no node, only the `nodeName` the records
11
+ * carry). Records name their scope by `nodeId`; a node that has never run
12
+ * under the engine has none, and no history. By name, every scope of that
13
+ * name answers. A view of `history("rerun")`, so it shares that buffer's
14
+ * gate: runs nothing wanted a record of (no `rerun` listener, fold or log
15
+ * at the time) left no record and are not here — a console session that
16
+ * wants them subscribes or imports a fold first.
17
+ */
18
+ export declare function why(target: unknown): RerunEvent[];
19
+ /**
20
+ * Current dependency names of one scope — the devtools subscription view.
21
+ * Read from the graph, not a record, so it answers with or without an
22
+ * audience for re-run records (and with the engine disabled).
23
+ */
24
+ export declare function subscriptions(target: unknown): string[];