@effect-atom/atom 0.1.0

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 (65) hide show
  1. package/Atom/package.json +6 -0
  2. package/AtomRef/package.json +6 -0
  3. package/Hydration/package.json +6 -0
  4. package/LICENSE +21 -0
  5. package/README.md +3 -0
  6. package/Registry/package.json +6 -0
  7. package/Result/package.json +6 -0
  8. package/dist/cjs/Atom.js +1079 -0
  9. package/dist/cjs/Atom.js.map +1 -0
  10. package/dist/cjs/AtomRef.js +261 -0
  11. package/dist/cjs/AtomRef.js.map +1 -0
  12. package/dist/cjs/Hydration.js +100 -0
  13. package/dist/cjs/Hydration.js.map +1 -0
  14. package/dist/cjs/Registry.js +128 -0
  15. package/dist/cjs/Registry.js.map +1 -0
  16. package/dist/cjs/Result.js +454 -0
  17. package/dist/cjs/Result.js.map +1 -0
  18. package/dist/cjs/index.js +37 -0
  19. package/dist/cjs/index.js.map +1 -0
  20. package/dist/cjs/internal/registry.js +701 -0
  21. package/dist/cjs/internal/registry.js.map +1 -0
  22. package/dist/cjs/internal/runtime.js +92 -0
  23. package/dist/cjs/internal/runtime.js.map +1 -0
  24. package/dist/dts/Atom.d.ts +597 -0
  25. package/dist/dts/Atom.d.ts.map +1 -0
  26. package/dist/dts/AtomRef.d.ts +55 -0
  27. package/dist/dts/AtomRef.d.ts.map +1 -0
  28. package/dist/dts/Hydration.d.ts +27 -0
  29. package/dist/dts/Hydration.d.ts.map +1 -0
  30. package/dist/dts/Registry.d.ts +115 -0
  31. package/dist/dts/Registry.d.ts.map +1 -0
  32. package/dist/dts/Result.d.ts +351 -0
  33. package/dist/dts/Result.d.ts.map +1 -0
  34. package/dist/dts/index.d.ts +21 -0
  35. package/dist/dts/index.d.ts.map +1 -0
  36. package/dist/dts/internal/registry.d.ts +2 -0
  37. package/dist/dts/internal/registry.d.ts.map +1 -0
  38. package/dist/dts/internal/runtime.d.ts +2 -0
  39. package/dist/dts/internal/runtime.d.ts.map +1 -0
  40. package/dist/esm/Atom.js +1029 -0
  41. package/dist/esm/Atom.js.map +1 -0
  42. package/dist/esm/AtomRef.js +232 -0
  43. package/dist/esm/AtomRef.js.map +1 -0
  44. package/dist/esm/Hydration.js +71 -0
  45. package/dist/esm/Hydration.js.map +1 -0
  46. package/dist/esm/Registry.js +98 -0
  47. package/dist/esm/Registry.js.map +1 -0
  48. package/dist/esm/Result.js +403 -0
  49. package/dist/esm/Result.js.map +1 -0
  50. package/dist/esm/index.js +21 -0
  51. package/dist/esm/index.js.map +1 -0
  52. package/dist/esm/internal/registry.js +672 -0
  53. package/dist/esm/internal/registry.js.map +1 -0
  54. package/dist/esm/internal/runtime.js +64 -0
  55. package/dist/esm/internal/runtime.js.map +1 -0
  56. package/dist/esm/package.json +4 -0
  57. package/package.json +72 -0
  58. package/src/Atom.ts +1865 -0
  59. package/src/AtomRef.ts +282 -0
  60. package/src/Hydration.ts +98 -0
  61. package/src/Registry.ts +204 -0
  62. package/src/Result.ts +767 -0
  63. package/src/index.ts +24 -0
  64. package/src/internal/registry.ts +810 -0
  65. package/src/internal/runtime.ts +63 -0
@@ -0,0 +1,672 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Equal from "effect/Equal";
3
+ import * as Exit from "effect/Exit";
4
+ import { pipe } from "effect/Function";
5
+ import { globalValue } from "effect/GlobalValue";
6
+ import * as Option from "effect/Option";
7
+ import * as Queue from "effect/Queue";
8
+ import * as Stream from "effect/Stream";
9
+ import * as Result from "../Result.js";
10
+ const constImmediate = {
11
+ immediate: true
12
+ };
13
+ function constListener(_) {}
14
+ /** @internal */
15
+ export const TypeId = "~effect-atom/atom/Registry";
16
+ /** @internal */
17
+ export const make = options => new RegistryImpl(options?.initialValues, options?.scheduleTask, options?.timeoutResolution, options?.defaultIdleTTL);
18
+ const SerializableTypeId = "~effect-atom/atom/Atom/Serializable";
19
+ const atomKey = atom => SerializableTypeId in atom ? atom[SerializableTypeId].key : atom;
20
+ class RegistryImpl {
21
+ scheduleTask;
22
+ defaultIdleTTL;
23
+ [TypeId];
24
+ timeoutResolution;
25
+ constructor(initialValues, scheduleTask = cb => queueMicrotask(cb), timeoutResolution, defaultIdleTTL) {
26
+ this.scheduleTask = scheduleTask;
27
+ this.defaultIdleTTL = defaultIdleTTL;
28
+ this[TypeId] = TypeId;
29
+ if (timeoutResolution === undefined && defaultIdleTTL !== undefined) {
30
+ this.timeoutResolution = Math.round(defaultIdleTTL / 2);
31
+ } else {
32
+ this.timeoutResolution = timeoutResolution ?? 1000;
33
+ }
34
+ if (initialValues !== undefined) {
35
+ for (const [atom, value] of initialValues) {
36
+ this.ensureNode(atom).setValue(value);
37
+ }
38
+ }
39
+ }
40
+ nodes = /*#__PURE__*/new Map();
41
+ preloadedSerializable = /*#__PURE__*/new Map();
42
+ timeoutBuckets = /*#__PURE__*/new Map();
43
+ nodeTimeoutBucket = /*#__PURE__*/new Map();
44
+ disposed = false;
45
+ getNodes() {
46
+ return this.nodes;
47
+ }
48
+ get(atom) {
49
+ return this.ensureNode(atom).value();
50
+ }
51
+ set(atom, value) {
52
+ atom.write(this.ensureNode(atom).writeContext, value);
53
+ }
54
+ setSerializable(key, encoded) {
55
+ this.preloadedSerializable.set(key, encoded);
56
+ }
57
+ modify(atom, f) {
58
+ const node = this.ensureNode(atom);
59
+ const result = f(node.value());
60
+ atom.write(node.writeContext, result[1]);
61
+ return result[0];
62
+ }
63
+ update(atom, f) {
64
+ const node = this.ensureNode(atom);
65
+ atom.write(node.writeContext, f(node.value()));
66
+ }
67
+ refresh = atom => {
68
+ if (atom.refresh !== undefined) {
69
+ atom.refresh(this.refresh);
70
+ } else {
71
+ this.invalidateAtom(atom);
72
+ }
73
+ };
74
+ subscribe(atom, f, options) {
75
+ const node = this.ensureNode(atom);
76
+ if (options?.immediate) {
77
+ f(node.value());
78
+ }
79
+ const remove = node.subscribe(function () {
80
+ f(node._value);
81
+ });
82
+ return () => {
83
+ remove();
84
+ if (node.canBeRemoved) {
85
+ this.scheduleNodeRemoval(node);
86
+ }
87
+ };
88
+ }
89
+ mount(atom) {
90
+ return this.subscribe(atom, constListener, constImmediate);
91
+ }
92
+ atomHasTtl(atom) {
93
+ return !atom.keepAlive && atom.idleTTL !== 0 && (atom.idleTTL !== undefined || this.defaultIdleTTL !== undefined);
94
+ }
95
+ ensureNode(atom) {
96
+ const key = atomKey(atom);
97
+ let node = this.nodes.get(key);
98
+ if (node === undefined) {
99
+ node = this.createNode(atom);
100
+ this.nodes.set(key, node);
101
+ } else if (this.atomHasTtl(atom)) {
102
+ this.removeNodeTimeout(node);
103
+ }
104
+ if (typeof key === "string" && this.preloadedSerializable.has(key)) {
105
+ const encoded = this.preloadedSerializable.get(key);
106
+ this.preloadedSerializable.delete(key);
107
+ const decoded = atom[SerializableTypeId].decode(encoded);
108
+ node.setValue(decoded);
109
+ }
110
+ return node;
111
+ }
112
+ createNode(atom) {
113
+ if (this.disposed) {
114
+ throw new Error(`Cannot access Atom ${atom}: registry is disposed`);
115
+ }
116
+ if (!atom.keepAlive) {
117
+ this.scheduleAtomRemoval(atom);
118
+ }
119
+ return new Node(this, atom);
120
+ }
121
+ invalidateAtom = atom => {
122
+ this.ensureNode(atom).invalidate();
123
+ };
124
+ scheduleAtomRemoval(atom) {
125
+ this.scheduleTask(() => {
126
+ const node = this.nodes.get(atomKey(atom));
127
+ if (node !== undefined && node.canBeRemoved) {
128
+ this.removeNode(node);
129
+ }
130
+ });
131
+ }
132
+ scheduleNodeRemoval(node) {
133
+ this.scheduleTask(() => {
134
+ if (node.canBeRemoved) {
135
+ this.removeNode(node);
136
+ }
137
+ });
138
+ }
139
+ removeNode(node) {
140
+ if (this.atomHasTtl(node.atom)) {
141
+ this.setNodeTimeout(node);
142
+ } else {
143
+ this.nodes.delete(atomKey(node.atom));
144
+ node.remove();
145
+ }
146
+ }
147
+ setNodeTimeout(node) {
148
+ if (this.nodeTimeoutBucket.has(node)) {
149
+ return;
150
+ }
151
+ let idleTTL = node.atom.idleTTL ?? this.defaultIdleTTL;
152
+ if (this.#currentSweepTTL !== null) {
153
+ idleTTL -= this.#currentSweepTTL;
154
+ if (idleTTL <= 0) {
155
+ this.nodes.delete(atomKey(node.atom));
156
+ node.remove();
157
+ return;
158
+ }
159
+ }
160
+ const ttl = Math.ceil(idleTTL / this.timeoutResolution) * this.timeoutResolution;
161
+ const timestamp = Date.now() + ttl;
162
+ const bucket = timestamp - timestamp % this.timeoutResolution + this.timeoutResolution;
163
+ let entry = this.timeoutBuckets.get(bucket);
164
+ if (entry === undefined) {
165
+ entry = [new Set(), setTimeout(() => this.sweepBucket(bucket), bucket - Date.now())];
166
+ this.timeoutBuckets.set(bucket, entry);
167
+ }
168
+ entry[0].add(node);
169
+ this.nodeTimeoutBucket.set(node, bucket);
170
+ }
171
+ removeNodeTimeout(node) {
172
+ const bucket = this.nodeTimeoutBucket.get(node);
173
+ if (bucket === undefined) {
174
+ return;
175
+ }
176
+ this.nodeTimeoutBucket.delete(node);
177
+ this.scheduleNodeRemoval(node);
178
+ const [nodes, handle] = this.timeoutBuckets.get(bucket);
179
+ nodes.delete(node);
180
+ if (nodes.size === 0) {
181
+ clearTimeout(handle);
182
+ this.timeoutBuckets.delete(bucket);
183
+ }
184
+ }
185
+ #currentSweepTTL = null;
186
+ sweepBucket(bucket) {
187
+ const nodes = this.timeoutBuckets.get(bucket)[0];
188
+ this.timeoutBuckets.delete(bucket);
189
+ nodes.forEach(node => {
190
+ if (!node.canBeRemoved) {
191
+ return;
192
+ }
193
+ this.nodeTimeoutBucket.delete(node);
194
+ this.nodes.delete(atomKey(node.atom));
195
+ this.#currentSweepTTL = node.atom.idleTTL ?? this.defaultIdleTTL;
196
+ node.remove();
197
+ this.#currentSweepTTL = null;
198
+ });
199
+ }
200
+ reset() {
201
+ this.timeoutBuckets.forEach(([, handle]) => clearTimeout(handle));
202
+ this.timeoutBuckets.clear();
203
+ this.nodeTimeoutBucket.clear();
204
+ this.nodes.forEach(node => node.remove());
205
+ this.nodes.clear();
206
+ }
207
+ dispose() {
208
+ this.disposed = true;
209
+ this.reset();
210
+ }
211
+ }
212
+ var NodeFlags;
213
+ (function (NodeFlags) {
214
+ NodeFlags[NodeFlags["alive"] = 1] = "alive";
215
+ NodeFlags[NodeFlags["initialized"] = 2] = "initialized";
216
+ NodeFlags[NodeFlags["waitingForValue"] = 4] = "waitingForValue";
217
+ })(NodeFlags || (NodeFlags = {}));
218
+ var NodeState;
219
+ (function (NodeState) {
220
+ NodeState[NodeState["uninitialized"] = 5] = "uninitialized";
221
+ NodeState[NodeState["stale"] = 7] = "stale";
222
+ NodeState[NodeState["valid"] = 3] = "valid";
223
+ NodeState[NodeState["removed"] = 0] = "removed";
224
+ })(NodeState || (NodeState = {}));
225
+ class Node {
226
+ registry;
227
+ atom;
228
+ constructor(registry, atom) {
229
+ this.registry = registry;
230
+ this.atom = atom;
231
+ this.writeContext = new WriteContextImpl(registry, this);
232
+ }
233
+ state = NodeState.uninitialized;
234
+ lifetime;
235
+ writeContext;
236
+ parents = [];
237
+ previousParents;
238
+ children = [];
239
+ listeners = [];
240
+ skipInvalidation = false;
241
+ get canBeRemoved() {
242
+ return !this.atom.keepAlive && this.listeners.length === 0 && this.children.length === 0 && this.state !== 0;
243
+ }
244
+ _value = undefined;
245
+ value() {
246
+ if ((this.state & NodeFlags.waitingForValue) !== 0) {
247
+ this.lifetime = makeLifetime(this);
248
+ const value = this.atom.read(this.lifetime);
249
+ if ((this.state & NodeFlags.waitingForValue) !== 0) {
250
+ this.setValue(value);
251
+ }
252
+ if (this.previousParents) {
253
+ const parents = this.previousParents;
254
+ this.previousParents = undefined;
255
+ for (let i = 0; i < parents.length; i++) {
256
+ parents[i].removeChild(this);
257
+ if (parents[i].canBeRemoved) {
258
+ this.registry.scheduleNodeRemoval(parents[i]);
259
+ }
260
+ }
261
+ }
262
+ }
263
+ return this._value;
264
+ }
265
+ valueOption() {
266
+ if ((this.state & NodeFlags.initialized) === 0) {
267
+ return Option.none();
268
+ }
269
+ return Option.some(this._value);
270
+ }
271
+ setValue(value) {
272
+ if ((this.state & NodeFlags.initialized) === 0) {
273
+ this.state = NodeState.valid;
274
+ this._value = value;
275
+ if (batchState.phase === BatchPhase.collect) {
276
+ batchState.notify.add(this);
277
+ } else {
278
+ this.notify();
279
+ }
280
+ return;
281
+ }
282
+ this.state = NodeState.valid;
283
+ if (Equal.equals(this._value, value)) {
284
+ return;
285
+ }
286
+ this._value = value;
287
+ if (this.skipInvalidation) {
288
+ this.skipInvalidation = false;
289
+ } else {
290
+ this.invalidateChildren();
291
+ }
292
+ if (this.listeners.length > 0) {
293
+ if (batchState.phase === BatchPhase.collect) {
294
+ batchState.notify.add(this);
295
+ } else {
296
+ this.notify();
297
+ }
298
+ }
299
+ }
300
+ addParent(parent) {
301
+ this.parents.push(parent);
302
+ if (this.previousParents !== undefined) {
303
+ const index = this.previousParents.indexOf(parent);
304
+ if (index !== -1) {
305
+ this.previousParents[index] = this.previousParents[this.previousParents.length - 1];
306
+ if (this.previousParents.pop() === undefined) {
307
+ this.previousParents = undefined;
308
+ }
309
+ }
310
+ }
311
+ if (parent.children.indexOf(this) === -1) {
312
+ parent.children.push(this);
313
+ }
314
+ }
315
+ removeChild(child) {
316
+ const index = this.children.indexOf(child);
317
+ if (index !== -1) {
318
+ this.children[index] = this.children[this.children.length - 1];
319
+ this.children.pop();
320
+ }
321
+ }
322
+ invalidate() {
323
+ if (this.state === NodeState.valid) {
324
+ this.state = NodeState.stale;
325
+ this.disposeLifetime();
326
+ }
327
+ if (batchState.phase === BatchPhase.collect) {
328
+ batchState.stale.push(this);
329
+ } else if (this.atom.lazy && this.listeners.length === 0 && !childrenAreActive(this.children)) {
330
+ this.invalidateChildren();
331
+ this.skipInvalidation = true;
332
+ } else {
333
+ this.value();
334
+ }
335
+ }
336
+ invalidateChildren() {
337
+ if (this.children.length === 0) {
338
+ return;
339
+ }
340
+ const children = this.children;
341
+ this.children = [];
342
+ for (let i = 0; i < children.length; i++) {
343
+ children[i].invalidate();
344
+ }
345
+ }
346
+ notify() {
347
+ for (let i = 0; i < this.listeners.length; i++) {
348
+ this.listeners[i]();
349
+ }
350
+ if (batchState.phase === BatchPhase.commit) {
351
+ batchState.notify.delete(this);
352
+ }
353
+ }
354
+ disposeLifetime() {
355
+ if (this.lifetime !== undefined) {
356
+ this.lifetime.dispose();
357
+ this.lifetime = undefined;
358
+ }
359
+ if (this.parents.length !== 0) {
360
+ this.previousParents = this.parents;
361
+ this.parents = [];
362
+ }
363
+ }
364
+ remove() {
365
+ this.state = NodeState.removed;
366
+ this.listeners = [];
367
+ if (this.lifetime === undefined) {
368
+ return;
369
+ }
370
+ this.disposeLifetime();
371
+ if (this.previousParents === undefined) {
372
+ return;
373
+ }
374
+ const parents = this.previousParents;
375
+ this.previousParents = undefined;
376
+ for (let i = 0; i < parents.length; i++) {
377
+ parents[i].removeChild(this);
378
+ if (parents[i].canBeRemoved) {
379
+ this.registry.removeNode(parents[i]);
380
+ }
381
+ }
382
+ }
383
+ subscribe(listener) {
384
+ this.listeners.push(listener);
385
+ return () => {
386
+ const index = this.listeners.indexOf(listener);
387
+ if (index !== -1) {
388
+ this.listeners[index] = this.listeners[this.listeners.length - 1];
389
+ this.listeners.pop();
390
+ }
391
+ };
392
+ }
393
+ }
394
+ function childrenAreActive(children) {
395
+ if (children.length === 0) {
396
+ return false;
397
+ }
398
+ for (let i = 0, len = children.length; i < len; i++) {
399
+ const child = children[i];
400
+ if (!child.atom.lazy || child.listeners.length > 0) {
401
+ return true;
402
+ }
403
+ }
404
+ for (let i = 0, len = children.length; i < len; i++) {
405
+ if (childrenAreActive(children[i].children)) {
406
+ return true;
407
+ }
408
+ }
409
+ return false;
410
+ }
411
+ const disposedError = atom => new Error(`Cannot use context of disposed Atom: ${atom}`);
412
+ const LifetimeProto = {
413
+ get registry() {
414
+ return this.node.registry;
415
+ },
416
+ addFinalizer(f) {
417
+ if (this.disposed) {
418
+ throw disposedError(this.node.atom);
419
+ }
420
+ this.finalizers ??= [];
421
+ this.finalizers.push(f);
422
+ },
423
+ get(atom) {
424
+ if (this.disposed) {
425
+ throw disposedError(this.node.atom);
426
+ }
427
+ const parent = this.node.registry.ensureNode(atom);
428
+ this.node.addParent(parent);
429
+ return parent.value();
430
+ },
431
+ result(atom, options) {
432
+ if (this.disposed) {
433
+ throw disposedError(this.node.atom);
434
+ } else if (this.isFn) {
435
+ return this.resultOnce(atom);
436
+ }
437
+ const result = this.get(atom);
438
+ if (options?.suspendOnWaiting && result.waiting) {
439
+ return Effect.never;
440
+ }
441
+ switch (result._tag) {
442
+ case "Initial":
443
+ {
444
+ return Effect.never;
445
+ }
446
+ case "Failure":
447
+ {
448
+ return Exit.failCause(result.cause);
449
+ }
450
+ case "Success":
451
+ {
452
+ return Effect.succeed(result.value);
453
+ }
454
+ }
455
+ },
456
+ resultOnce(atom, options) {
457
+ if (this.disposed) {
458
+ throw disposedError(this.node.atom);
459
+ }
460
+ return Effect.async(resume => {
461
+ const result = this.once(atom);
462
+ if (result._tag !== "Initial" && !(options?.suspendOnWaiting && result.waiting)) {
463
+ return resume(Result.toExit(result));
464
+ }
465
+ const cancel = this.node.registry.subscribe(atom, result => {
466
+ if (result._tag === "Initial" || options?.suspendOnWaiting && result.waiting) return;
467
+ cancel();
468
+ resume(Result.toExit(result));
469
+ }, {
470
+ immediate: false
471
+ });
472
+ return Effect.sync(cancel);
473
+ });
474
+ },
475
+ some(atom) {
476
+ if (this.disposed) {
477
+ throw disposedError(this.node.atom);
478
+ } else if (this.isFn) {
479
+ return this.someOnce(atom);
480
+ }
481
+ const result = this.get(atom);
482
+ return result._tag === "None" ? Effect.never : Effect.succeed(result.value);
483
+ },
484
+ someOnce(atom) {
485
+ if (this.disposed) {
486
+ throw disposedError(this.node.atom);
487
+ }
488
+ return Effect.async(resume => {
489
+ const result = this.once(atom);
490
+ if (Option.isSome(result)) {
491
+ return resume(Effect.succeed(result.value));
492
+ }
493
+ const cancel = this.node.registry.subscribe(atom, result => {
494
+ if (Option.isNone(result)) return;
495
+ cancel();
496
+ resume(Effect.succeed(result.value));
497
+ }, {
498
+ immediate: false
499
+ });
500
+ return Effect.sync(cancel);
501
+ });
502
+ },
503
+ once(atom) {
504
+ if (this.disposed) {
505
+ throw disposedError(this.node.atom);
506
+ }
507
+ return this.node.registry.get(atom);
508
+ },
509
+ self() {
510
+ if (this.disposed) {
511
+ throw disposedError(this.node.atom);
512
+ }
513
+ return this.node.valueOption();
514
+ },
515
+ refresh(atom) {
516
+ if (this.disposed) {
517
+ throw disposedError(this.node.atom);
518
+ }
519
+ this.node.registry.refresh(atom);
520
+ },
521
+ refreshSelf() {
522
+ if (this.disposed) {
523
+ throw disposedError(this.node.atom);
524
+ }
525
+ this.node.invalidate();
526
+ },
527
+ mount(atom) {
528
+ if (this.disposed) {
529
+ throw disposedError(this.node.atom);
530
+ }
531
+ this.addFinalizer(this.node.registry.mount(atom));
532
+ },
533
+ subscribe(atom, f, options) {
534
+ if (this.disposed) {
535
+ throw disposedError(this.node.atom);
536
+ }
537
+ this.addFinalizer(this.node.registry.subscribe(atom, f, options));
538
+ },
539
+ setSelf(a) {
540
+ if (this.disposed) {
541
+ throw disposedError(this.node.atom);
542
+ }
543
+ this.node.setValue(a);
544
+ },
545
+ set(atom, value) {
546
+ if (this.disposed) {
547
+ throw disposedError(this.node.atom);
548
+ }
549
+ this.node.registry.set(atom, value);
550
+ },
551
+ stream(atom, options) {
552
+ if (this.disposed) {
553
+ throw disposedError(this.node.atom);
554
+ }
555
+ return pipe(Effect.acquireRelease(Queue.bounded(options?.bufferSize ?? 16), Queue.shutdown), Effect.tap(queue => Effect.acquireRelease(Effect.sync(() => {
556
+ return this.node.registry.subscribe(atom, _ => {
557
+ Queue.unsafeOffer(queue, _);
558
+ }, {
559
+ immediate: options?.withoutInitialValue !== true
560
+ });
561
+ }), cancel => Effect.sync(cancel))), Effect.map(queue => Stream.fromQueue(queue)), Stream.unwrapScoped);
562
+ },
563
+ streamResult(atom, options) {
564
+ return pipe(this.stream(atom, options), Stream.filter(Result.isNotInitial), Stream.flatMap(result => result._tag === "Success" ? Stream.succeed(result.value) : Stream.failCause(result.cause)));
565
+ },
566
+ dispose() {
567
+ this.disposed = true;
568
+ if (this.finalizers === undefined) {
569
+ return;
570
+ }
571
+ const finalizers = this.finalizers;
572
+ this.finalizers = undefined;
573
+ for (let i = finalizers.length - 1; i >= 0; i--) {
574
+ finalizers[i]();
575
+ }
576
+ }
577
+ };
578
+ const makeLifetime = node => {
579
+ function get(atom) {
580
+ if (get.disposed) {
581
+ throw disposedError(atom);
582
+ } else if (get.isFn) {
583
+ return node.registry.get(atom);
584
+ }
585
+ const parent = node.registry.ensureNode(atom);
586
+ node.addParent(parent);
587
+ return parent.value();
588
+ }
589
+ Object.setPrototypeOf(get, LifetimeProto);
590
+ get.isFn = false;
591
+ get.disposed = false;
592
+ get.finalizers = undefined;
593
+ get.node = node;
594
+ return get;
595
+ };
596
+ class WriteContextImpl {
597
+ registry;
598
+ node;
599
+ constructor(registry, node) {
600
+ this.registry = registry;
601
+ this.node = node;
602
+ }
603
+ get(atom) {
604
+ return this.registry.get(atom);
605
+ }
606
+ set(atom, value) {
607
+ return this.registry.set(atom, value);
608
+ }
609
+ setSelf(value) {
610
+ return this.node.setValue(value);
611
+ }
612
+ refreshSelf() {
613
+ return this.node.invalidate();
614
+ }
615
+ }
616
+ // -----------------------------------------------------------------------------
617
+ // batching
618
+ // -----------------------------------------------------------------------------
619
+ /** @internal */
620
+ export var BatchPhase;
621
+ (function (BatchPhase) {
622
+ BatchPhase[BatchPhase["disabled"] = 0] = "disabled";
623
+ BatchPhase[BatchPhase["collect"] = 1] = "collect";
624
+ BatchPhase[BatchPhase["commit"] = 2] = "commit";
625
+ })(BatchPhase || (BatchPhase = {}));
626
+ /** @internal */
627
+ export const batchState = /*#__PURE__*/globalValue("@effect-atom/atom/Registry/batchState", () => ({
628
+ phase: BatchPhase.disabled,
629
+ depth: 0,
630
+ stale: [],
631
+ notify: new Set()
632
+ }));
633
+ /** @internal */
634
+ export function batch(f) {
635
+ batchState.phase = BatchPhase.collect;
636
+ batchState.depth++;
637
+ try {
638
+ f();
639
+ if (batchState.depth === 1) {
640
+ for (let i = 0; i < batchState.stale.length; i++) {
641
+ batchRebuildNode(batchState.stale[i]);
642
+ }
643
+ batchState.phase = BatchPhase.commit;
644
+ for (const node of batchState.notify) {
645
+ node.notify();
646
+ }
647
+ batchState.notify.clear();
648
+ }
649
+ } finally {
650
+ batchState.depth--;
651
+ if (batchState.depth === 0) {
652
+ batchState.phase = BatchPhase.disabled;
653
+ batchState.stale = [];
654
+ }
655
+ }
656
+ }
657
+ function batchRebuildNode(node) {
658
+ if (node.state === NodeState.valid) {
659
+ return;
660
+ }
661
+ for (let i = 0; i < node.parents.length; i++) {
662
+ const parent = node.parents[i];
663
+ if (parent.state !== NodeState.valid) {
664
+ batchRebuildNode(parent);
665
+ }
666
+ }
667
+ // @ts-ignore
668
+ if (node.state !== NodeState.valid) {
669
+ node.value();
670
+ }
671
+ }
672
+ //# sourceMappingURL=registry.js.map