@playfast/reform 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +64 -0
  2. package/dist/cjs/boundary/boundary.js +86 -0
  3. package/dist/cjs/calc/asyncCalc.js +128 -0
  4. package/dist/cjs/calc/asyncData.js +37 -0
  5. package/dist/cjs/calc/calc.js +58 -0
  6. package/dist/cjs/calc/calcFamily.js +127 -0
  7. package/dist/cjs/channel/channel.js +142 -0
  8. package/dist/cjs/compose/composition.js +50 -0
  9. package/dist/cjs/compose/host.js +8 -0
  10. package/dist/cjs/compose/props.js +14 -0
  11. package/dist/cjs/compose/provide.js +30 -0
  12. package/dist/cjs/compose/slot.js +27 -0
  13. package/dist/cjs/compose/ui.js +61 -0
  14. package/dist/cjs/definition/definition.js +46 -0
  15. package/dist/cjs/event/event.js +36 -0
  16. package/dist/cjs/event/eventGroup.js +7 -0
  17. package/dist/cjs/feature/feature.js +102 -0
  18. package/dist/cjs/index.js +116 -0
  19. package/dist/cjs/internal/capture.js +14 -0
  20. package/dist/cjs/internal/ctx.js +2 -0
  21. package/dist/cjs/internal/errors.js +62 -0
  22. package/dist/cjs/internal/inspect.js +36 -0
  23. package/dist/cjs/internal/queryDriver.js +138 -0
  24. package/dist/cjs/internal/reuse.js +71 -0
  25. package/dist/cjs/internal/scheduler.js +73 -0
  26. package/dist/cjs/internal/seeds.js +19 -0
  27. package/dist/cjs/internal/sources.js +61 -0
  28. package/dist/cjs/internal/store.js +77 -0
  29. package/dist/cjs/internal/track.js +22 -0
  30. package/dist/cjs/package.json +4 -0
  31. package/dist/cjs/procedure/procedure.js +52 -0
  32. package/dist/cjs/reducer/reducer.js +64 -0
  33. package/dist/cjs/remote/remoteState.js +307 -0
  34. package/dist/cjs/runtime/bus.js +25 -0
  35. package/dist/cjs/runtime/loop.js +119 -0
  36. package/dist/cjs/scene/scene.js +36 -0
  37. package/dist/cjs/state/state.js +47 -0
  38. package/dist/cjs/state/stateFamily.js +101 -0
  39. package/dist/cjs/state/stateGroup.js +47 -0
  40. package/dist/cjs/state/token.js +23 -0
  41. package/dist/cjs/ui/node.js +2 -0
  42. package/dist/cjs/ui/trigger.js +2 -0
  43. package/dist/dts/boundary/boundary.d.ts +72 -0
  44. package/dist/dts/boundary/boundary.d.ts.map +1 -0
  45. package/dist/dts/calc/asyncCalc.d.ts +91 -0
  46. package/dist/dts/calc/asyncCalc.d.ts.map +1 -0
  47. package/dist/dts/calc/asyncData.d.ts +55 -0
  48. package/dist/dts/calc/asyncData.d.ts.map +1 -0
  49. package/dist/dts/calc/calc.d.ts +57 -0
  50. package/dist/dts/calc/calc.d.ts.map +1 -0
  51. package/dist/dts/calc/calcFamily.d.ts +57 -0
  52. package/dist/dts/calc/calcFamily.d.ts.map +1 -0
  53. package/dist/dts/channel/channel.d.ts +115 -0
  54. package/dist/dts/channel/channel.d.ts.map +1 -0
  55. package/dist/dts/compose/composition.d.ts +72 -0
  56. package/dist/dts/compose/composition.d.ts.map +1 -0
  57. package/dist/dts/compose/host.d.ts +17 -0
  58. package/dist/dts/compose/host.d.ts.map +1 -0
  59. package/dist/dts/compose/props.d.ts +13 -0
  60. package/dist/dts/compose/props.d.ts.map +1 -0
  61. package/dist/dts/compose/provide.d.ts +22 -0
  62. package/dist/dts/compose/provide.d.ts.map +1 -0
  63. package/dist/dts/compose/slot.d.ts +49 -0
  64. package/dist/dts/compose/slot.d.ts.map +1 -0
  65. package/dist/dts/compose/ui.d.ts +50 -0
  66. package/dist/dts/compose/ui.d.ts.map +1 -0
  67. package/dist/dts/definition/definition.d.ts +33 -0
  68. package/dist/dts/definition/definition.d.ts.map +1 -0
  69. package/dist/dts/event/event.d.ts +33 -0
  70. package/dist/dts/event/event.d.ts.map +1 -0
  71. package/dist/dts/event/eventGroup.d.ts +9 -0
  72. package/dist/dts/event/eventGroup.d.ts.map +1 -0
  73. package/dist/dts/feature/feature.d.ts +220 -0
  74. package/dist/dts/feature/feature.d.ts.map +1 -0
  75. package/dist/dts/index.d.ts +43 -0
  76. package/dist/dts/index.d.ts.map +1 -0
  77. package/dist/dts/internal/capture.d.ts +28 -0
  78. package/dist/dts/internal/capture.d.ts.map +1 -0
  79. package/dist/dts/internal/ctx.d.ts +12 -0
  80. package/dist/dts/internal/ctx.d.ts.map +1 -0
  81. package/dist/dts/internal/errors.d.ts +69 -0
  82. package/dist/dts/internal/errors.d.ts.map +1 -0
  83. package/dist/dts/internal/inspect.d.ts +17 -0
  84. package/dist/dts/internal/inspect.d.ts.map +1 -0
  85. package/dist/dts/internal/queryDriver.d.ts +65 -0
  86. package/dist/dts/internal/queryDriver.d.ts.map +1 -0
  87. package/dist/dts/internal/reuse.d.ts +10 -0
  88. package/dist/dts/internal/reuse.d.ts.map +1 -0
  89. package/dist/dts/internal/scheduler.d.ts +47 -0
  90. package/dist/dts/internal/scheduler.d.ts.map +1 -0
  91. package/dist/dts/internal/seeds.d.ts +17 -0
  92. package/dist/dts/internal/seeds.d.ts.map +1 -0
  93. package/dist/dts/internal/sources.d.ts +39 -0
  94. package/dist/dts/internal/sources.d.ts.map +1 -0
  95. package/dist/dts/internal/store.d.ts +47 -0
  96. package/dist/dts/internal/store.d.ts.map +1 -0
  97. package/dist/dts/internal/track.d.ts +33 -0
  98. package/dist/dts/internal/track.d.ts.map +1 -0
  99. package/dist/dts/procedure/procedure.d.ts +40 -0
  100. package/dist/dts/procedure/procedure.d.ts.map +1 -0
  101. package/dist/dts/reducer/reducer.d.ts +44 -0
  102. package/dist/dts/reducer/reducer.d.ts.map +1 -0
  103. package/dist/dts/remote/remoteState.d.ts +119 -0
  104. package/dist/dts/remote/remoteState.d.ts.map +1 -0
  105. package/dist/dts/runtime/bus.d.ts +27 -0
  106. package/dist/dts/runtime/bus.d.ts.map +1 -0
  107. package/dist/dts/runtime/loop.d.ts +45 -0
  108. package/dist/dts/runtime/loop.d.ts.map +1 -0
  109. package/dist/dts/scene/scene.d.ts +44 -0
  110. package/dist/dts/scene/scene.d.ts.map +1 -0
  111. package/dist/dts/state/state.d.ts +37 -0
  112. package/dist/dts/state/state.d.ts.map +1 -0
  113. package/dist/dts/state/stateFamily.d.ts +79 -0
  114. package/dist/dts/state/stateFamily.d.ts.map +1 -0
  115. package/dist/dts/state/stateGroup.d.ts +36 -0
  116. package/dist/dts/state/stateGroup.d.ts.map +1 -0
  117. package/dist/dts/state/token.d.ts +30 -0
  118. package/dist/dts/state/token.d.ts.map +1 -0
  119. package/dist/dts/ui/node.d.ts +9 -0
  120. package/dist/dts/ui/node.d.ts.map +1 -0
  121. package/dist/dts/ui/trigger.d.ts +7 -0
  122. package/dist/dts/ui/trigger.d.ts.map +1 -0
  123. package/dist/esm/boundary/boundary.js +83 -0
  124. package/dist/esm/boundary/boundary.js.map +1 -0
  125. package/dist/esm/calc/asyncCalc.js +95 -0
  126. package/dist/esm/calc/asyncCalc.js.map +1 -0
  127. package/dist/esm/calc/asyncData.js +34 -0
  128. package/dist/esm/calc/asyncData.js.map +1 -0
  129. package/dist/esm/calc/calc.js +58 -0
  130. package/dist/esm/calc/calc.js.map +1 -0
  131. package/dist/esm/calc/calcFamily.js +124 -0
  132. package/dist/esm/calc/calcFamily.js.map +1 -0
  133. package/dist/esm/channel/channel.js +136 -0
  134. package/dist/esm/channel/channel.js.map +1 -0
  135. package/dist/esm/compose/composition.js +46 -0
  136. package/dist/esm/compose/composition.js.map +1 -0
  137. package/dist/esm/compose/host.js +5 -0
  138. package/dist/esm/compose/host.js.map +1 -0
  139. package/dist/esm/compose/props.js +11 -0
  140. package/dist/esm/compose/props.js.map +1 -0
  141. package/dist/esm/compose/provide.js +28 -0
  142. package/dist/esm/compose/provide.js.map +1 -0
  143. package/dist/esm/compose/slot.js +23 -0
  144. package/dist/esm/compose/slot.js.map +1 -0
  145. package/dist/esm/compose/ui.js +57 -0
  146. package/dist/esm/compose/ui.js.map +1 -0
  147. package/dist/esm/definition/definition.js +42 -0
  148. package/dist/esm/definition/definition.js.map +1 -0
  149. package/dist/esm/event/event.js +30 -0
  150. package/dist/esm/event/event.js.map +1 -0
  151. package/dist/esm/event/eventGroup.js +4 -0
  152. package/dist/esm/event/eventGroup.js.map +1 -0
  153. package/dist/esm/feature/feature.js +98 -0
  154. package/dist/esm/feature/feature.js.map +1 -0
  155. package/dist/esm/index.js +45 -0
  156. package/dist/esm/index.js.map +1 -0
  157. package/dist/esm/internal/capture.js +11 -0
  158. package/dist/esm/internal/capture.js.map +1 -0
  159. package/dist/esm/internal/ctx.js +2 -0
  160. package/dist/esm/internal/ctx.js.map +1 -0
  161. package/dist/esm/internal/errors.js +54 -0
  162. package/dist/esm/internal/errors.js.map +1 -0
  163. package/dist/esm/internal/inspect.js +32 -0
  164. package/dist/esm/internal/inspect.js.map +1 -0
  165. package/dist/esm/internal/queryDriver.js +134 -0
  166. package/dist/esm/internal/queryDriver.js.map +1 -0
  167. package/dist/esm/internal/reuse.js +68 -0
  168. package/dist/esm/internal/reuse.js.map +1 -0
  169. package/dist/esm/internal/scheduler.js +69 -0
  170. package/dist/esm/internal/scheduler.js.map +1 -0
  171. package/dist/esm/internal/seeds.js +17 -0
  172. package/dist/esm/internal/seeds.js.map +1 -0
  173. package/dist/esm/internal/sources.js +59 -0
  174. package/dist/esm/internal/sources.js.map +1 -0
  175. package/dist/esm/internal/store.js +73 -0
  176. package/dist/esm/internal/store.js.map +1 -0
  177. package/dist/esm/internal/track.js +18 -0
  178. package/dist/esm/internal/track.js.map +1 -0
  179. package/dist/esm/package.json +4 -0
  180. package/dist/esm/procedure/procedure.js +50 -0
  181. package/dist/esm/procedure/procedure.js.map +1 -0
  182. package/dist/esm/reducer/reducer.js +63 -0
  183. package/dist/esm/reducer/reducer.js.map +1 -0
  184. package/dist/esm/remote/remoteState.js +270 -0
  185. package/dist/esm/remote/remoteState.js.map +1 -0
  186. package/dist/esm/runtime/bus.js +20 -0
  187. package/dist/esm/runtime/bus.js.map +1 -0
  188. package/dist/esm/runtime/loop.js +116 -0
  189. package/dist/esm/runtime/loop.js.map +1 -0
  190. package/dist/esm/scene/scene.js +31 -0
  191. package/dist/esm/scene/scene.js.map +1 -0
  192. package/dist/esm/state/state.js +43 -0
  193. package/dist/esm/state/state.js.map +1 -0
  194. package/dist/esm/state/stateFamily.js +96 -0
  195. package/dist/esm/state/stateFamily.js.map +1 -0
  196. package/dist/esm/state/stateGroup.js +46 -0
  197. package/dist/esm/state/stateGroup.js.map +1 -0
  198. package/dist/esm/state/token.js +20 -0
  199. package/dist/esm/state/token.js.map +1 -0
  200. package/dist/esm/ui/node.js +2 -0
  201. package/dist/esm/ui/node.js.map +1 -0
  202. package/dist/esm/ui/trigger.js +2 -0
  203. package/dist/esm/ui/trigger.js.map +1 -0
  204. package/package.json +33 -0
@@ -0,0 +1,270 @@
1
+ import { Context, Effect, Either, Layer, MutableRef, Option, Runtime, Schema } from 'effect';
2
+ import { AsyncData, narrowStore, widenStore } from '../calc/asyncData.js';
3
+ import * as Channel from '../channel/channel.js';
4
+ import { yieldableClass } from '../definition/definition.js';
5
+ import * as Event from '../event/event.js';
6
+ import { bumpRevision, gatedFlag, makeQueryDriver, RevisionSchema, revisionZero, } from '../internal/queryDriver.js';
7
+ import { reuse as shareStructure } from '../internal/reuse.js';
8
+ import { resolveScheduler } from '../internal/scheduler.js';
9
+ import { sameKey, } from '../internal/sources.js';
10
+ import { makeDerivedStore, makeStore } from '../internal/store.js';
11
+ import { readTracked } from '../internal/track.js';
12
+ import * as Reducer from '../reducer/reducer.js';
13
+ import { Bus, narrowHandled, publish } from '../runtime/bus.js';
14
+ import { Reducers } from '../runtime/loop.js';
15
+ import * as State from '../state/state.js';
16
+ import { StateToken } from '../state/token.js';
17
+ // Intent payloads are typed by the definition's `Intents`, but `Intents` is an
18
+ // open type parameter inside `make`/`live`, so the runtime schemas can only be
19
+ // structural (`Schema.Unknown` in the intent slot). Event schemas are
20
+ // reflective metadata — never decoded on the dispatch path — so the typed view
21
+ // is granted here once (the `narrowStore`/`narrowHandled` style; `any`
22
+ // short-circuits the schema's invariance, no value is cast).
23
+ const looseSchema = (schema) => schema;
24
+ /**
25
+ * Define a remote state: a query (like `AsyncCalc.make`) plus the intent
26
+ * events that mutate it. `yield* TheClass` reads the overlaid view;
27
+ * `TheClass.truth` / `TheClass.pending` / `TheClass.Failed` expose the rest of
28
+ * the surface. The query/send/apply logic is supplied by `RemoteState.live`.
29
+ */
30
+ export const make = (name, config) => {
31
+ const store = Context.GenericTag(`reform/remoteState/${name}`);
32
+ const truthTag = Context.GenericTag(`reform/remoteState/${name}/truth`);
33
+ const pendingTag = Context.GenericTag(`reform/remoteState/${name}/pending`);
34
+ const gated = gatedFlag(config.alwaysOn);
35
+ const manifest = {
36
+ kind: 'RemoteState',
37
+ name,
38
+ output: config.output,
39
+ gated,
40
+ intents: config.intents.map((event) => event.tag),
41
+ ...(config.error !== undefined ? { error: config.error } : {}),
42
+ };
43
+ // Annotated consts so the template literal expressions keep their literal
44
+ // types (contextual typing) — the statics must match the interface exactly.
45
+ const truthName = `${name}/truth`;
46
+ const pendingName = `${name}/pending`;
47
+ const failedName = `${name}/Failed`;
48
+ const read = Effect.flatMap(store, readTracked);
49
+ return yieldableClass(read, {
50
+ manifest,
51
+ store,
52
+ name,
53
+ inputs: config.inputs,
54
+ intents: config.intents,
55
+ gated,
56
+ truth: new StateToken(truthName, truthTag),
57
+ pending: new StateToken(pendingName, pendingTag),
58
+ Failed: Event.make(failedName, looseSchema(Schema.Struct({ intent: Schema.Unknown, error: Schema.Unknown }))),
59
+ });
60
+ };
61
+ /**
62
+ * Wire a remote state: the query driver (truth), the overlay (visible view),
63
+ * the hidden queue reducer, the send procedure, and the settle link between
64
+ * them — one layer. Hidden names minted per call, namespaced by the remote
65
+ * state's name: events `…/Queued`/`…/Acked`/`…/Settled`/`…/Invalidated`, state
66
+ * `…/revision`, reducers `…/pending`/`…/revision`, procedure `…/send`, default
67
+ * channel `…/sends`.
68
+ */
69
+ export const live = (remote, config) => {
70
+ const name = remote.manifest.name;
71
+ const truthTag = remote.truth.store;
72
+ const pendingTag = remote.pending.store;
73
+ // The hidden event vocabulary. `Queued` carries the intent (the queue
74
+ // reducer's only source of it); `Acked`/`Settled` name the op; `Invalidated`
75
+ // bumps the hidden revision exactly like an `invalidateOn` event.
76
+ const Queued = Event.make(`${name}/Queued`, looseSchema(Schema.Struct({ opId: Schema.String, intent: Schema.Unknown })));
77
+ const Acked = Event.make(`${name}/Acked`, Schema.Struct({ opId: Schema.String }));
78
+ const Settled = Event.make(`${name}/Settled`, Schema.Struct({ opId: Schema.String }));
79
+ const Invalidated = Event.make(`${name}/Invalidated`, Schema.Struct({}));
80
+ // The hidden revision pair (the `invalidateOn` machinery, unconditional here:
81
+ // `Invalidated` always drives it; user `invalidateOn` events join the same fold).
82
+ const revisionState = State.make(`${name}/revision`, RevisionSchema);
83
+ const revisionReducer = Reducer.make(`${name}/revision`, {
84
+ states: [revisionState],
85
+ events: [Invalidated, ...(config.invalidateOn ?? [])],
86
+ });
87
+ // The settle link, keyed per live so two remote states never cross-resolve.
88
+ const linkTag = Context.GenericTag(`reform/remoteState/${name}/link`);
89
+ // ── 1. Driver + link: the truth store and the generation bookkeeping. ──────
90
+ const driverLayer = Layer.scopedContext(Effect.gen(function* () {
91
+ // `disabled` is rejected at the type level for non-gated definitions
92
+ // (erased to `never` there); read it through a loose view for the runtime.
93
+ const cfg = config;
94
+ // Requirement-free read (`serviceOption`): the assembly below always
95
+ // provides the revision store alongside this driver.
96
+ const revision = Option.getOrUndefined(yield* Effect.serviceOption(revisionState.store));
97
+ const runtime = yield* Effect.runtime();
98
+ // Settle waiters: a plain registry, not fibers parked per intent — so the
99
+ // settle path is independent of the user channel's policy (`latest`/
100
+ // `exclusive` lanes can't orphan a pending entry by cancelling its fiber).
101
+ const waiters = MutableRef.make([]);
102
+ const onSettled = (generation) => {
103
+ const due = MutableRef.get(waiters).filter((waiter) => waiter.waitFor <= generation);
104
+ if (due.length === 0)
105
+ return;
106
+ MutableRef.update(waiters, (all) => all.filter((waiter) => waiter.waitFor > generation));
107
+ // Dispatch synchronously (`publish` only enqueues on the unbounded bus):
108
+ // the settle is enqueued in the same flush as the converged value write.
109
+ for (const waiter of due) {
110
+ Runtime.runSync(runtime)(publish('Normal', Event.construct(Settled, { opId: waiter.opId })));
111
+ }
112
+ };
113
+ const driver = yield* makeQueryDriver({
114
+ name,
115
+ label: 'RemoteState',
116
+ gated: remote.gated,
117
+ inputs: remote.inputs,
118
+ query: cfg.query,
119
+ invalidateBy: cfg.invalidateBy,
120
+ disabled: cfg.disabled,
121
+ coalesce: cfg.coalesce,
122
+ reuse: cfg.reuse,
123
+ extraKey: revision === undefined
124
+ ? undefined
125
+ : {
126
+ read: () => revision.getSnapshot(),
127
+ subscribe: (listener) => revision.subscribe(listener),
128
+ },
129
+ onSettled,
130
+ });
131
+ const link = {
132
+ requested: driver.requested,
133
+ register: (opId, waitFor) => MutableRef.update(waiters, (all) => [...all, { opId, waitFor }]),
134
+ };
135
+ return Context.make(truthTag, narrowStore(driver.store)).pipe(Context.add(linkTag, link));
136
+ }));
137
+ // ── 2. Overlay: visible = pending.reduce(apply, truth). ────────────────────
138
+ const overlayLayer = Layer.scoped(remote.store, Effect.gen(function* () {
139
+ const scheduler = yield* resolveScheduler;
140
+ // Widened so the arm dispatch below is a plain tag union (read-only view).
141
+ const feedStore = widenStore(yield* truthTag);
142
+ const queueStore = yield* pendingTag;
143
+ const memo = MutableRef.make(undefined);
144
+ const recompute = () => {
145
+ const feed = feedStore.getSnapshot();
146
+ const pending = queueStore.getSnapshot();
147
+ const key = [feed, pending];
148
+ const prev = MutableRef.get(memo);
149
+ if (prev !== undefined && sameKey(key, prev.key))
150
+ return prev.output;
151
+ // `apply` runs over every `Success` — including `refetching: true`, so
152
+ // queued intents stay visible while the server converges; the other
153
+ // arms pass through by reference.
154
+ const overlaid = feed._tag === 'Success'
155
+ ? AsyncData.success(pending.reduce((value, entry) => config.apply(value, entry.intent), feed.value), feed.refetching)
156
+ : feed;
157
+ // With `reuse`, also reconcile consecutive overlay outputs: the fold
158
+ // rebuilds the value per recompute, so untouched subtrees would
159
+ // otherwise lose identity every time the queue moves.
160
+ const output = config.reuse === true &&
161
+ prev !== undefined &&
162
+ prev.output._tag === 'Success' &&
163
+ overlaid._tag === 'Success'
164
+ ? AsyncData.success(shareStructure(prev.output.value, overlaid.value), overlaid.refetching)
165
+ : overlaid;
166
+ MutableRef.set(memo, { key, output });
167
+ return output;
168
+ };
169
+ const subscribe = (listener) => {
170
+ const offFeed = feedStore.subscribe(listener);
171
+ const offQueue = queueStore.subscribe(listener);
172
+ return () => {
173
+ offFeed();
174
+ offQueue();
175
+ };
176
+ };
177
+ const derived = makeDerivedStore(recompute, subscribe, scheduler);
178
+ yield* Effect.addFinalizer(() => Effect.sync(derived.unsubscribe));
179
+ return narrowStore(derived.store);
180
+ }));
181
+ // ── 3. Queue reducer: the pending queue's SOLE writer. ─────────────────────
182
+ // Assembled directly against the registry rather than through `Reducer.live`,
183
+ // whose parameter types are conditionals TS keeps deferred while `Intents` is
184
+ // an open type parameter (user code instantiates the public surface
185
+ // concretely, so this is the one generic caller).
186
+ const queueReducerName = `${name}/pending`;
187
+ const queueHandles = new Set([Queued.tag, Acked.tag, Settled.tag]);
188
+ const foldQueue = (queue, event) =>
189
+ // `Queued` is the arm carrying the intent (the `undefined` guard is for the
190
+ // type only — every `Queued` carries one). An ack/settle for an id that is
191
+ // absent (or already confirmed) keeps the same reference — a true no-op.
192
+ event._tag === Queued.tag
193
+ ? event.intent === undefined
194
+ ? queue
195
+ : [...queue, { opId: event.opId, intent: event.intent, status: 'sending' }]
196
+ : event._tag === Acked.tag
197
+ ? queue.some((entry) => entry.opId === event.opId && entry.status === 'sending')
198
+ ? queue.map((entry) => entry.opId === event.opId ? { ...entry, status: 'confirmed' } : entry)
199
+ : queue
200
+ : queue.some((entry) => entry.opId === event.opId)
201
+ ? queue.filter((entry) => entry.opId !== event.opId)
202
+ : queue;
203
+ const queueReducerLayer = Layer.scopedDiscard(Effect.gen(function* () {
204
+ const reducers = yield* Reducers;
205
+ if (reducers.entries.some((entry) => entry.name === queueReducerName)) {
206
+ yield* Effect.logWarning(`reform: duplicate reducer name '${queueReducerName}' registered`);
207
+ }
208
+ const store = yield* pendingTag;
209
+ const entry = {
210
+ name: queueReducerName,
211
+ handles: queueHandles,
212
+ // The loop only invokes `apply` for events in `handles`; `narrowHandled`
213
+ // restores that typed view from the erased envelope.
214
+ apply: (event) => store.set(foldQueue(store.get(), narrowHandled(event))),
215
+ };
216
+ yield* Effect.acquireRelease(Effect.sync(() => reducers.register(entry)), () => Effect.sync(() => reducers.unregister(entry)));
217
+ }));
218
+ // ── 4. Send procedure: intent dispatch → deliver → ack/settle bookkeeping. ─
219
+ // Hand-assembled `ProcedureEntry` for the same deferred-conditional reason as
220
+ // the queue reducer (the `Procedure.live` internals, verbatim).
221
+ const channel = config.channel ?? Channel.make(`${name}/sends`, { policy: { _tag: 'merge' } });
222
+ const procedureName = `${name}/send`;
223
+ const sendHandles = new Set(remote.intents.map((event) => event.tag));
224
+ const sendProcedureLayer = Layer.scopedDiscard(Effect.gen(function* () {
225
+ const procedures = yield* Channel.Procedures;
226
+ if (procedures.entries.some((entry) => entry.name === procedureName)) {
227
+ yield* Effect.logWarning(`reform: duplicate procedure name '${procedureName}' registered`);
228
+ }
229
+ const link = yield* linkTag;
230
+ // Snapshot the body's full context (Bus + the send's R2) so `run` is total.
231
+ const runtime = yield* Effect.runtime();
232
+ const deliver = (intent) => Effect.gen(function* () {
233
+ const opId = yield* Effect.sync(() => crypto.randomUUID());
234
+ yield* Event.dispatch(Queued, { opId, intent });
235
+ const outcome = yield* config.send(intent).pipe(
236
+ // A defect in `send` is a bug, but it must not strand the entry:
237
+ // fold it into the failure arm so the intent settles and `Failed`
238
+ // fires (the channel would otherwise swallow it after logging).
239
+ Effect.catchAllDefect((defect) => Effect.fail(defect)), Effect.either,
240
+ // A cancelled send (a `latest`/`exclusive` user channel tearing the
241
+ // run down) settles too: the overlay reverts, and if the request
242
+ // did reach the server the next refetch shows it as truth.
243
+ Effect.onInterrupt(() => Event.dispatch(Settled, { opId })));
244
+ yield* Either.match(outcome, {
245
+ onLeft: (error) => Effect.zipRight(Event.dispatch(remote.Failed, { intent, error }), Event.dispatch(Settled, { opId })),
246
+ onRight: () =>
247
+ // Register the waiter BEFORE the invalidation bump: `Invalidated`
248
+ // routes through the drain loop later, so the run it triggers is
249
+ // necessarily requested after `requested()` here — the waiter can
250
+ // never be satisfied by a refetch that predates the ack.
251
+ Effect.sync(() => link.register(opId, link.requested() + 1)).pipe(Effect.zipRight(Event.dispatch(Acked, { opId })), Effect.zipRight(Event.dispatch(Invalidated, {}))),
252
+ });
253
+ });
254
+ const entry = {
255
+ name: procedureName,
256
+ channelName: channel.manifest.name,
257
+ handles: sendHandles,
258
+ run: (event) => Effect.provide(deliver(narrowHandled(event)), runtime),
259
+ };
260
+ yield* Effect.acquireRelease(Effect.sync(() => procedures.register(entry)), () => Effect.sync(() => procedures.unregister(entry)));
261
+ }));
262
+ // ── Assembly. ───────────────────────────────────────────────────────────────
263
+ // The pending store backs both the overlay and the queue reducer; the hidden
264
+ // revision store feeds both the driver (`extraKey`) and its reducer; the
265
+ // channel `.live` is idempotent by name+policy, so a user channel shared with
266
+ // other procedures wires up exactly once.
267
+ const pendingStoreLayer = Layer.effect(pendingTag, Effect.map(resolveScheduler, (scheduler) => makeStore([], scheduler)));
268
+ return Layer.mergeAll(overlayLayer, queueReducerLayer, Reducer.live(revisionReducer, bumpRevision), sendProcedureLayer, Channel.live(channel)).pipe(Layer.provideMerge(driverLayer), Layer.provide(State.live(revisionState, revisionZero)), Layer.provideMerge(pendingStoreLayer));
269
+ };
270
+ //# sourceMappingURL=remoteState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteState.js","sourceRoot":"","sources":["../../../src/remote/remoteState.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { Context, Effect, Layer, PubSub } from 'effect';
2
+ /**
3
+ * Re-narrow an erased `Tagged` envelope to a handler's declared event union. The
4
+ * loop and channels only route events whose tag is in a handler's `handles`, so
5
+ * at runtime the envelope IS one of those events; the registries store it as the
6
+ * generic `Tagged`, and this restores the typed view. The one documented home
7
+ * for that boundary cast, shared by `Reducer.live` and `Procedure.live`.
8
+ */
9
+ export const narrowHandled = (event) => event;
10
+ /** The single dispatch bus: an unbounded PubSub fanned out to the loop and procedures. */
11
+ export class Bus extends Context.Tag('reform/Bus')() {
12
+ }
13
+ // Unbounded so `publish` never suspends: UI triggers dispatch synchronously
14
+ // (`Runtime.runSync`, no fiber fork per event), and an event storm can't apply
15
+ // backpressure to the UI thread. The single drain loop empties the bus every
16
+ // microtask, so it does not accumulate. Swap to `PubSub.dropping(N)` if bounded
17
+ // memory is preferred over never dropping (publish stays synchronous either way).
18
+ export const busLayer = Layer.scoped(Bus, PubSub.unbounded());
19
+ export const publish = (priority, event) => Effect.flatMap(Bus, (bus) => PubSub.publish(bus, { priority, event }));
20
+ //# sourceMappingURL=bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bus.js","sourceRoot":"","sources":["../../../src/runtime/bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAOvD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAI,KAAa,EAAK,EAAE,CAAC,KAAc,CAAA;AAUpE,0FAA0F;AAC1F,MAAM,OAAO,GAAI,SAAQ,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAgC;CAAG;AAErF,4EAA4E;AAC5E,+EAA+E;AAC/E,6EAA6E;AAC7E,gFAAgF;AAChF,kFAAkF;AAClF,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,SAAS,EAAY,CAAC,CAAA;AAEvE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,QAAkB,EAAE,KAAa,EAAmC,EAAE,CAC5F,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA"}
@@ -0,0 +1,116 @@
1
+ import { Chunk, Context, Effect, Layer, PubSub, Queue } from 'effect';
2
+ import { Channels, channelsLayer, Procedures, proceduresLayer, } from '../channel/channel.js';
3
+ import { notificationsLayer } from '../internal/scheduler.js';
4
+ import { Bus, busLayer } from './bus.js';
5
+ export class Reducers extends Context.Tag('reform/Reducers')() {
6
+ }
7
+ /** Drop an item from a `Map<string, Array>` bucket, pruning the key when it empties. */
8
+ const dropFromBuckets = (map, key, item) => {
9
+ const bucket = map.get(key);
10
+ if (bucket === undefined)
11
+ return;
12
+ const next = bucket.filter((entry) => entry !== item);
13
+ if (next.length === 0)
14
+ map.delete(key);
15
+ else
16
+ map.set(key, next);
17
+ };
18
+ const makeReducerRegistry = () => {
19
+ const entries = [];
20
+ const byTag = new Map();
21
+ return {
22
+ entries,
23
+ byTag,
24
+ register: (entry) => {
25
+ entries.push(entry);
26
+ for (const tag of entry.handles) {
27
+ const bucket = byTag.get(tag);
28
+ if (bucket === undefined)
29
+ byTag.set(tag, [entry]);
30
+ else
31
+ bucket.push(entry);
32
+ }
33
+ },
34
+ unregister: (entry) => {
35
+ const index = entries.indexOf(entry);
36
+ if (index >= 0)
37
+ entries.splice(index, 1);
38
+ for (const tag of entry.handles)
39
+ dropFromBuckets(byTag, tag, entry);
40
+ },
41
+ };
42
+ };
43
+ export const reducersLayer = Layer.sync(Reducers, makeReducerRegistry);
44
+ /** High before Normal; within a priority class, dispatch order is preserved. */
45
+ const rank = (priority) => (priority === 'High' ? 0 : 1);
46
+ // The single drain loop: one fiber that frame-batches the bus. Each tick it
47
+ // harvests every event dispatched in that microtask, runs all matching reducers
48
+ // in ONE synchronous pass (so the store notifier flushes once for the batch),
49
+ // then routes each event to the channels its procedures run on.
50
+ const drain = Effect.gen(function* () {
51
+ const bus = yield* Bus;
52
+ const reducers = yield* Reducers;
53
+ const { byName: channels } = yield* Channels;
54
+ const procedures = yield* Procedures;
55
+ const subscription = yield* PubSub.subscribe(bus);
56
+ yield* Effect.forkScoped(Effect.forever(Effect.gen(function* () {
57
+ // Block until the first event, then drain the rest of this tick.
58
+ const first = yield* Queue.take(subscription);
59
+ const rest = yield* Queue.takeAll(subscription);
60
+ const frame = [first, ...Chunk.toArray(rest)];
61
+ // Stable priority order: High-dispatched (UI) events fold before
62
+ // Normal-dispatched (procedure follow-up) events in the same frame. A
63
+ // two-bucket partition does this in O(m) with no comparator — push order
64
+ // preserves intra-priority dispatch order — instead of sorting the frame.
65
+ const high = [];
66
+ const normal = [];
67
+ for (const envelope of frame) {
68
+ if (rank(envelope.priority) === 0)
69
+ high.push(envelope);
70
+ else
71
+ normal.push(envelope);
72
+ }
73
+ const ordered = high.concat(normal);
74
+ // One synchronous block: every reducer write for the frame coalesces into
75
+ // a single notification flush. Routing to channels happens here too, so
76
+ // procedure bodies (run later, off their channel fibers) see post-batch
77
+ // state. No `yield*` in between, or the flush could fire early.
78
+ const failures = [];
79
+ yield* Effect.sync(() => {
80
+ for (const envelope of ordered) {
81
+ for (const reducer of reducers.byTag.get(envelope.event._tag) ?? []) {
82
+ // Isolate each fold: a synchronous throw in one reducer must not
83
+ // abandon the rest of the frame nor (via the `forever` below) kill
84
+ // the drain fiber and freeze the whole app. Collect and log after.
85
+ try {
86
+ reducer.apply(envelope.event);
87
+ }
88
+ catch (error) {
89
+ failures.push({ event: envelope.event, error });
90
+ }
91
+ }
92
+ }
93
+ for (const envelope of ordered) {
94
+ // Offer to each DISTINCT channel once. Routing per-procedure would
95
+ // offer a shared channel multiple times for one event, and each offer
96
+ // re-runs every procedure on it — duplicate execution.
97
+ for (const channelName of procedures.channelsByTag.get(envelope.event._tag) ?? []) {
98
+ channels.get(channelName)?.offer(envelope.event);
99
+ }
100
+ }
101
+ });
102
+ yield* Effect.forEach(failures, (failure) => Effect.logError(`reform: reducer threw handling '${failure.event._tag}'`, failure.error), { discard: true });
103
+ }).pipe(
104
+ // Belt-and-suspenders: even a defect outside the isolated fold (a bug in
105
+ // the loop itself) is logged and the tick restarts, so the bus never goes
106
+ // permanently deaf.
107
+ Effect.catchAllCause((cause) => Effect.logError('reform: drain tick crashed', cause)))));
108
+ });
109
+ /**
110
+ * The reform engine: provides the bus + reducer/channel/procedure registries +
111
+ * the per-runtime notification scheduler to the application and forks the single
112
+ * drain loop. Registration mutates the live collections, so reducers/procedures/
113
+ * channels merged alongside are picked up before the first dispatch (boot).
114
+ */
115
+ export const Engine = Layer.scopedDiscard(drain).pipe(Layer.provideMerge(Layer.mergeAll(busLayer, reducersLayer, channelsLayer, proceduresLayer, notificationsLayer)));
116
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../../src/runtime/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { Layer } from 'effect';
2
+ import { CurrentSeedOverrides } from '../internal/seeds.js';
3
+ /**
4
+ * Define a scene — `scene(TodoApp, { provide: [makeTestApp(client, seeds)] })`.
5
+ * The composition's contract flows through `C`, so consumers stay typed.
6
+ */
7
+ export const scene = (composition, config) => ({
8
+ kind: 'Scene',
9
+ composition,
10
+ provide: config.provide,
11
+ ...(config.boot !== undefined ? { boot: config.boot } : {}),
12
+ });
13
+ /**
14
+ * Overlay seed values onto a CLOSED scene — the tooling/test seam (dev-tool
15
+ * inspector overrides, proofs). Scenes stay closed for authors: this does not
16
+ * reopen `provide`, it wraps each layer with `Layer.locally(CurrentSeedOverrides,
17
+ * seeds)` so `State.live` boots matching stores from the override instead of
18
+ * the authored seed.
19
+ *
20
+ * Keys are state MEMBER NAMES as reflected in `manifest.states` (e.g. `count`),
21
+ * not group names. If two groups in one scene share a member name, both receive
22
+ * the override (documented limitation). Values are schema-validated at build:
23
+ * an invalid value silently falls back to the authored seed. `StateFamily`
24
+ * entries are not covered.
25
+ */
26
+ export const seedScene = (base, seeds) => Object.keys(seeds).length === 0
27
+ ? base
28
+ : { ...base, provide: base.provide.map(Layer.locally(CurrentSeedOverrides, seeds)) };
29
+ /** Reflection guard: is this exported value a scene? */
30
+ export const isScene = (v) => typeof v === 'object' && v !== null && v.kind === 'Scene';
31
+ //# sourceMappingURL=scene.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene.js","sourceRoot":"","sources":["../../../src/scene/scene.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAG9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAgCxD;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,WAAyC,EACzC,MAGC,EACS,EAAE,CAAC,CAAC;IACd,IAAI,EAAE,OAAO;IACb,WAAW;IACX,OAAO,EAAE,MAAM,CAAC,OAAO;IACvB,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CAC5D,CAAC,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,IAAc,EACd,KAAwC,EAC9B,EAAE,CACZ,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC;IAC7B,CAAC,CAAC,IAAI;IACN,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC,EAAE,CAAA;AAExF,wDAAwD;AACxD,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAU,EAAc,EAAE,CAChD,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAK,CAAiC,CAAC,IAAI,KAAK,OAAO,CAAA"}
@@ -0,0 +1,43 @@
1
+ import { Context, Effect, FiberRef, Layer, Option, Schema } from 'effect';
2
+ import { yieldableClass } from '../definition/definition.js';
3
+ import { resolveScheduler } from '../internal/scheduler.js';
4
+ import { CurrentSeedOverrides } from '../internal/seeds.js';
5
+ import { makeStore } from '../internal/store.js';
6
+ import { readTracked } from '../internal/track.js';
7
+ /**
8
+ * Atomic reactive state. `State.make` is the *definition* (a reflectable
9
+ * manifest + an internal store tag); it carries no starting value — the seed is
10
+ * an implementation detail supplied at create-time by `State.live(state, seed)`.
11
+ * Composed into a `StateGroup` exactly as `@effect/rpc` composes rpcs.
12
+ */
13
+ export const make = (name, schema, options = {}) => {
14
+ const store = Context.GenericTag(`reform/state/${name}`);
15
+ const manifest = {
16
+ kind: 'State',
17
+ name,
18
+ schema,
19
+ ...(options.title !== undefined ? { title: options.title } : {}),
20
+ ...(options.description !== undefined ? { description: options.description } : {}),
21
+ };
22
+ const read = Effect.flatMap(store, readTracked);
23
+ return yieldableClass(read, { manifest, store });
24
+ };
25
+ /**
26
+ * Resolve the value a store should boot from: the ambient seed override when
27
+ * one is present (and valid) for this state's member name, else the authored
28
+ * `initial`. Reads `CurrentSeedOverrides` — empty outside the tooling seam
29
+ * (`Scene.seedScene`), so production wiring always boots from `initial`. An
30
+ * override is decoded against the state's schema; an invalid value silently
31
+ * falls back to `initial` — a half-typed override from the dev tool must never
32
+ * crash a preview.
33
+ */
34
+ const resolveSeed = (state, initial) => Effect.map(FiberRef.get(CurrentSeedOverrides), (overrides) => state.manifest.name in overrides
35
+ ? Option.getOrElse(Schema.decodeUnknownOption(state.manifest.schema)(overrides[state.manifest.name]), () => initial)
36
+ : initial);
37
+ /**
38
+ * Allocate a state's store, seeded with `initial` — `State.live(Feed, seed)`.
39
+ * The seed lives here (implementation), not on the definition, so the same
40
+ * definition can boot from different values in app vs. test wiring.
41
+ */
42
+ export const live = (state, initial) => Layer.effect(state.store, Effect.zipWith(resolveScheduler, resolveSeed(state, initial), (scheduler, seed) => makeStore(seed, scheduler)));
43
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../../src/state/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACzE,OAAO,EAAiB,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,SAAS,EAAc,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA0B/C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,IAAO,EACP,MAA6B,EAC7B,UAAwB,EAAE,EACR,EAAE;IACpB,MAAM,KAAK,GAAG,OAAO,CAAC,UAAU,CAAqB,gBAAgB,IAAI,EAAE,CAAC,CAAA;IAC5E,MAAM,QAAQ,GAAwB;QACpC,IAAI,EAAE,OAAO;QACb,IAAI;QACJ,MAAM;QACN,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACnF,CAAA;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;IAC/C,OAAO,cAAc,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;AAClD,CAAC,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,GAAG,CAClB,KAAQ,EACR,OAAsB,EACQ,EAAE,CAChC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,CAC3D,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,SAAS;IAC9B,CAAC,CAAC,MAAM,CAAC,SAAS,CACd,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EACjF,GAAG,EAAE,CAAC,OAAO,CACd;IACH,CAAC,CAAC,OAAO,CACZ,CAAA;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,KAAQ,EACR,OAAsB,EACa,EAAE,CACrC,KAAK,CAAC,MAAM,CACV,KAAK,CAAC,KAAK,EACX,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAChF,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAC3B,CACF,CAAA"}
@@ -0,0 +1,96 @@
1
+ import { Context, Effect, Layer } from 'effect';
2
+ import { definitionClass } from '../definition/definition.js';
3
+ import { resolveScheduler } from '../internal/scheduler.js';
4
+ import { makeStore } from '../internal/store.js';
5
+ import { readTracked } from '../internal/track.js';
6
+ /**
7
+ * A reducer fold returns this to evict the key it folded over, instead of a new
8
+ * value. The loop drops the entry's store from the family, so a normalized
9
+ * collection (chat messages, search hits, transient rows) does not grow without
10
+ * bound — the one fix for the otherwise-unbounded per-key `Map`.
11
+ */
12
+ export const Tombstone = Symbol.for('reform/StateFamily/Tombstone');
13
+ const makeFamilyStore = (seed, scheduler, options = {}) => {
14
+ const entries = new Map();
15
+ const evictWhenUnused = options.evictWhenUnused === true;
16
+ // Live subscriber count per key — maintained only when eviction is on.
17
+ const subscribers = new Map();
18
+ // Wrap a store's `subscribe` to ref-count, evicting the key when it falls idle.
19
+ // `get`/`set`/`getVersion` are delegated unchanged, so the loop writes and the
20
+ // host reads see the same cell; only subscribe/unsubscribe are instrumented.
21
+ const refCounted = (key, store) => ({
22
+ ...store,
23
+ subscribe: (listener) => {
24
+ subscribers.set(key, (subscribers.get(key) ?? 0) + 1);
25
+ const off = store.subscribe(listener);
26
+ const released = { done: false };
27
+ return () => {
28
+ if (released.done)
29
+ return;
30
+ released.done = true;
31
+ off();
32
+ const remaining = (subscribers.get(key) ?? 1) - 1;
33
+ if (remaining > 0) {
34
+ subscribers.set(key, remaining);
35
+ return;
36
+ }
37
+ subscribers.delete(key);
38
+ queueMicrotask(() => {
39
+ if ((subscribers.get(key) ?? 0) === 0)
40
+ entries.delete(key);
41
+ });
42
+ };
43
+ },
44
+ });
45
+ return {
46
+ at: (key) => {
47
+ const existing = entries.get(key);
48
+ if (existing !== undefined)
49
+ return existing;
50
+ const base = makeStore(seed(key), scheduler);
51
+ const created = evictWhenUnused ? refCounted(key, base) : base;
52
+ entries.set(key, created);
53
+ return created;
54
+ },
55
+ forget: (key) => {
56
+ entries.delete(key);
57
+ subscribers.delete(key);
58
+ },
59
+ clear: () => {
60
+ entries.clear();
61
+ subscribers.clear();
62
+ },
63
+ size: () => entries.size,
64
+ };
65
+ };
66
+ /**
67
+ * Normalized keyed state: one logical State per key, backed by a single family
68
+ * store. Scales with the collection without re-rendering unrelated entries.
69
+ */
70
+ export const make = (name, key, value, options = {}) => {
71
+ const store = Context.GenericTag(`reform/family/${name}`);
72
+ const manifest = {
73
+ kind: 'StateFamily',
74
+ name,
75
+ key,
76
+ value,
77
+ ...(options.title !== undefined ? { title: options.title } : {}),
78
+ ...(options.description !== undefined ? { description: options.description } : {}),
79
+ };
80
+ return definitionClass({ manifest, store });
81
+ };
82
+ /**
83
+ * Read one entry by key — `StateFamily.read(ItemUi, id)`. Inside a render it
84
+ * subscribes that key's slice; elsewhere it just snapshots (D5).
85
+ */
86
+ export const read = (family, key) => Effect.flatMap(family.store, (fs) => readTracked(fs.at(key)));
87
+ /**
88
+ * Allocate a family's keyed store — `StateFamily.live(ItemUi, seed)`. The seed
89
+ * is a plain value or a factory; a factory receives the key, so a new entry can
90
+ * derive its starting value from its own id (`(id) => ({ ...blank, id }))`).
91
+ */
92
+ export const live = (family, initial, options = {}) => {
93
+ const seed = typeof initial === 'function' ? initial : () => initial;
94
+ return Layer.effect(family.store, Effect.map(resolveScheduler, (scheduler) => makeFamilyStore(seed, scheduler, options)));
95
+ };
96
+ //# sourceMappingURL=stateFamily.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateFamily.js","sourceRoot":"","sources":["../../../src/state/stateFamily.ts"],"names":[],"mappings":"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"}