@volynets/reflex-store 0.0.0-stage → 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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +239 -2
  3. package/SPECIFICATION.md +137 -0
  4. package/dist/advanced.d.ts +13 -0
  5. package/dist/advanced.js +9 -0
  6. package/dist/chunks/compiler-CW_P8WsZ.js +2526 -0
  7. package/dist/chunks/createStore-DHj16Ehk.js +12 -0
  8. package/dist/chunks/hydrate-Bdtl9XyA.js +137 -0
  9. package/dist/chunks/keyed-C-QvvUv4.js +647 -0
  10. package/dist/chunks/names-BF36AyM3.js +11 -0
  11. package/dist/chunks/shared-BHHficW8.js +202 -0
  12. package/dist/compiled-store.d.ts +4 -0
  13. package/dist/compiled-store.js +4 -0
  14. package/dist/compiler/swc.wasm +0 -0
  15. package/dist/index.d.ts +23 -0
  16. package/dist/index.js +7 -0
  17. package/dist/licenses/NOTICE.txt +1 -0
  18. package/dist/licenses/SWC-APACHE-2.0.txt +202 -0
  19. package/dist/runtime/core.d.ts +2 -0
  20. package/dist/runtime/core.js +1 -0
  21. package/dist/runtime/internal.d.ts +3 -0
  22. package/dist/runtime/internal.js +41 -0
  23. package/dist/runtime/types.d.ts +45 -0
  24. package/dist/runtime/types.js +1 -0
  25. package/dist/runtime.d.ts +25 -0
  26. package/dist/runtime.js +78 -0
  27. package/dist/selectors/index.d.ts +13 -0
  28. package/dist/selectors/index.js +15 -0
  29. package/dist/selectors/shared.d.ts +3 -0
  30. package/dist/selectors/shared.js +2 -0
  31. package/dist/store.d.ts +9 -0
  32. package/dist/store.js +4 -0
  33. package/dist/types/contracts-BCsRPdQb.d.ts +78 -0
  34. package/dist/types/createStore-BJ66-pfq.d.ts +43 -0
  35. package/dist/types/internal-BIzJSPwN.d.ts +18 -0
  36. package/dist/types/keyed-CdSYzIOc.d.ts +18 -0
  37. package/dist/types/shared-CdTKzvLe.d.ts +114 -0
  38. package/dist/vite.d.ts +68 -0
  39. package/dist/vite.js +87 -0
  40. package/examples/task-board/README.md +15 -0
  41. package/examples/task-board/src/task-board.ts +159 -0
  42. package/examples/task-board/vite.config.ts +6 -0
  43. package/package.json +125 -4
  44. package/src/store/README.md +59 -0
  45. package/src/store/TRANSFORM_SPEC.md +85 -0
@@ -0,0 +1,647 @@
1
+ import { setCurrentConsumer, currentConsumer, createConsumer, readConsumerLazy, disposeNode, untracked, unlinkAllSources, CONSUMER_INITIAL_STATE, createProducer, readProducer, getActiveRuntimeContext, enterReactiveBatch, leaveReactiveBatch, writeProducer, disposeWatcher, createWatcher, runWatcher, Both } from '@volynets/reflex-runtime/internal';
2
+ import { h as cloneValue, j as readProjectionPath, k as storeControls, f as depthOf, l as isStructural } from './shared-BHHficW8.js';
3
+ import { s as storeName, a as setStoreName } from './names-BF36AyM3.js';
4
+ import { batch } from '@volynets/reflex';
5
+
6
+ /** A memo with owner-controlled suspension; no node exists until its first read. */ class Demand {
7
+ constructor(compute){
8
+ this.compute = compute;
9
+ this.disposed = false;
10
+ }
11
+ read() {
12
+ if (this.disposed) throw new Error("Cannot read a disposed store derivation");
13
+ const node = this.node ??= createConsumer(this.compute);
14
+ return readConsumerLazy.call(node);
15
+ }
16
+ peek() {
17
+ return untracked(()=>this.read());
18
+ }
19
+ collect() {
20
+ const node = this.node;
21
+ if (!node || node.firstOut !== null) return;
22
+ unlinkAllSources(node);
23
+ node.state = CONSUMER_INITIAL_STATE;
24
+ node.payload = undefined;
25
+ }
26
+ dispose() {
27
+ this.disposed = true;
28
+ if (this.node) disposeNode(this.node);
29
+ this.node = undefined;
30
+ }
31
+ }
32
+ /** Retain tracked semantic locations until their owner's next collection boundary. */ class Observations {
33
+ constructor(compute, equals = Object.is, keyEquals){
34
+ this.compute = compute;
35
+ this.equals = equals;
36
+ this.keyEquals = keyEquals;
37
+ }
38
+ read(key) {
39
+ if (this.keyEquals && this.entries) {
40
+ const previous = currentConsumer;
41
+ setCurrentConsumer(null);
42
+ try {
43
+ for (const known of this.entries.keys()){
44
+ if (this.keyEquals(known, key)) {
45
+ key = known;
46
+ break;
47
+ }
48
+ }
49
+ } finally{
50
+ setCurrentConsumer(previous);
51
+ }
52
+ }
53
+ let node = this.entries?.get(key);
54
+ if (!node) {
55
+ if (currentConsumer === null) return this.compute(key);
56
+ let initialized = false;
57
+ let previous;
58
+ node = createConsumer(()=>{
59
+ const next = this.compute(key);
60
+ if (!initialized || !(this.equals === Object.is ? Object.is(previous, next) : untracked(()=>this.equals(previous, next)))) previous = next;
61
+ initialized = true;
62
+ return previous;
63
+ });
64
+ (this.entries ??= new Map()).set(key, node);
65
+ }
66
+ return readConsumerLazy.call(node);
67
+ }
68
+ collect() {
69
+ if (!this.entries) return;
70
+ for (const [key, node] of this.entries){
71
+ if (node.firstOut !== null) continue;
72
+ this.entries.delete(key);
73
+ disposeNode(node);
74
+ }
75
+ }
76
+ dispose() {
77
+ if (!this.entries) return;
78
+ for (const node of this.entries.values())disposeNode(node);
79
+ this.entries = undefined;
80
+ }
81
+ }
82
+
83
+ const sameKeys = (a, b)=>{
84
+ if (a.length !== b.length) return false;
85
+ for(let i = 0; i < a.length; i++)if (a[i] !== b[i]) return false;
86
+ return true;
87
+ };
88
+ class Projection {
89
+ constructor(fn, seed, options, returnsValue = false){
90
+ this.options = options;
91
+ this.views = new Set();
92
+ this.disposed = false;
93
+ const clone = options.clone ?? cloneValue;
94
+ let initialSeed = seed;
95
+ let current;
96
+ let initialized = false;
97
+ this.state = new Demand(()=>{
98
+ const draft = returnsValue ? undefined : untracked(()=>clone(initialized ? current : initialSeed));
99
+ const result = fn(draft);
100
+ const next = result === undefined ? draft : untracked(()=>clone(result));
101
+ const equals = options.equals;
102
+ if (!initialized || !(equals === undefined || equals === Object.is ? Object.is(current, next) : untracked(()=>equals(current, next)))) current = next;
103
+ initialSeed = undefined;
104
+ initialized = true;
105
+ return current;
106
+ });
107
+ }
108
+ view(path, array) {
109
+ const view = new View(this, path, array);
110
+ this.views.add(new WeakRef(view));
111
+ return view;
112
+ }
113
+ read(path) {
114
+ if (this.disposed) throw new Error("Cannot read a disposed store projection");
115
+ const value = this.state.read();
116
+ return path.length === 0 ? value : readProjectionPath(value, path);
117
+ }
118
+ collect() {
119
+ for (const ref of this.views){
120
+ const view = ref.deref();
121
+ if (view) view.collect();
122
+ else this.views.delete(ref);
123
+ }
124
+ this.state.collect();
125
+ }
126
+ dispose() {
127
+ this.disposed = true;
128
+ for (const ref of this.views)ref.deref()?.dispose();
129
+ this.views.clear();
130
+ this.state.dispose();
131
+ }
132
+ }
133
+ class View {
134
+ constructor(owner, path, array){
135
+ this.owner = owner;
136
+ this.path = path;
137
+ this.children = new Map();
138
+ const read = ()=>owner.read(path);
139
+ const parent = ()=>{
140
+ const value = read();
141
+ return typeof value === "object" && value !== null ? value : undefined;
142
+ };
143
+ const get = (key)=>{
144
+ const value = parent();
145
+ return value === undefined ? undefined : Reflect.get(value, key);
146
+ };
147
+ const valueAt = (key)=>{
148
+ const value = parent();
149
+ return this.wrap(key, value === undefined ? undefined : Reflect.get(value, key), value);
150
+ };
151
+ const existsAt = (key)=>{
152
+ const value = parent();
153
+ return value !== undefined && key in value;
154
+ };
155
+ const descriptorAt = (key)=>{
156
+ const value = parent();
157
+ return value === undefined ? undefined : Object.getOwnPropertyDescriptor(value, key)?.enumerable;
158
+ };
159
+ const keysAt = ()=>{
160
+ const value = parent();
161
+ return value === undefined ? [] : Reflect.ownKeys(value);
162
+ };
163
+ const dispose = ()=>owner.dispose();
164
+ this.proxy = new Proxy(array ? [] : Object.create(null), {
165
+ get: (_target, key)=>{
166
+ if (key === storeName) return owner.options.name;
167
+ if (key === Symbol.dispose) return dispose;
168
+ // Inspect one parent snapshot without subscribing to structural identity.
169
+ const previous = currentConsumer;
170
+ let container;
171
+ let value;
172
+ setCurrentConsumer(null);
173
+ try {
174
+ container = parent();
175
+ value = container === undefined ? undefined : Reflect.get(container, key);
176
+ } finally{
177
+ setCurrentConsumer(previous);
178
+ }
179
+ if (this.shouldWrap(value, container)) return this.child(key, Array.isArray(value));
180
+ return (this.values ??= new Observations(valueAt)).read(key);
181
+ },
182
+ has: (_target, key)=>(this.exists ??= new Observations(existsAt)).read(key),
183
+ ownKeys: ()=>{
184
+ const keys = (this.keys ??= new Observations(keysAt, sameKeys)).read(undefined);
185
+ return array && !keys.includes("length") ? [
186
+ ...keys,
187
+ "length"
188
+ ] : [
189
+ ...keys
190
+ ];
191
+ },
192
+ getOwnPropertyDescriptor: (_target, key)=>{
193
+ const enumerable = (this.descriptors ??= new Observations(descriptorAt)).read(key);
194
+ if (array && key === "length") return {
195
+ configurable: false,
196
+ enumerable: false,
197
+ writable: true,
198
+ value: untracked(()=>get(key)) ?? 0
199
+ };
200
+ if (enumerable === undefined) return undefined;
201
+ return {
202
+ configurable: true,
203
+ enumerable,
204
+ writable: false,
205
+ value: untracked(()=>get(key))
206
+ };
207
+ },
208
+ set: ()=>false,
209
+ deleteProperty: ()=>false,
210
+ defineProperty: ()=>false,
211
+ setPrototypeOf: ()=>false,
212
+ preventExtensions: ()=>false
213
+ });
214
+ storeControls.set(this.proxy, {
215
+ raw: read,
216
+ collect: ()=>owner.collect(),
217
+ dispose
218
+ });
219
+ }
220
+ shouldWrap(value, parent) {
221
+ return this.owner.options.depth !== "shallow" && (parent === undefined || depthOf(parent) !== "shallow") && isStructural(value);
222
+ }
223
+ wrap(key, value, parent) {
224
+ return this.shouldWrap(value, parent) ? this.child(key, Array.isArray(value)) : value;
225
+ }
226
+ child(key, array) {
227
+ const existing = this.children.get(key);
228
+ const cached = existing?.view.deref();
229
+ if (cached && existing.array === array) return cached.proxy;
230
+ const view = this.owner.view([
231
+ ...this.path,
232
+ key
233
+ ], array);
234
+ this.children.set(key, {
235
+ array,
236
+ view: new WeakRef(view)
237
+ });
238
+ return view.proxy;
239
+ }
240
+ collect() {
241
+ this.values?.collect();
242
+ this.exists?.collect();
243
+ this.descriptors?.collect();
244
+ this.keys?.collect();
245
+ for (const [key, entry] of this.children)if (!entry.view.deref()) this.children.delete(key);
246
+ }
247
+ dispose() {
248
+ this.values?.dispose();
249
+ this.exists?.dispose();
250
+ this.descriptors?.dispose();
251
+ this.keys?.dispose();
252
+ this.children.clear();
253
+ }
254
+ }
255
+ function createStoreProjection(fn, seed, options = {}) {
256
+ const owner = new Projection(fn, seed, options);
257
+ return owner.view([], Array.isArray(seed)).proxy;
258
+ }
259
+ /** Pure-return derivations never consume a mutable draft of their previous state. */ function createDerivedProjection(compute, options) {
260
+ const owner = new Projection(compute, {}, options, true);
261
+ return owner.view([], false).proxy;
262
+ }
263
+
264
+ function createSignalNode(payload) {
265
+ return createProducer(payload);
266
+ }
267
+
268
+ let transactionContext;
269
+ /** Publish a synchronous logical action at one runtime batch boundary. */ function transaction(action) {
270
+ if (transactionContext !== undefined && transactionContext === getActiveRuntimeContext()) return action();
271
+ return batch(()=>{
272
+ const previous = transactionContext;
273
+ transactionContext = getActiveRuntimeContext();
274
+ enterReactiveBatch();
275
+ try {
276
+ return action();
277
+ } finally{
278
+ transactionContext = previous;
279
+ leaveReactiveBatch();
280
+ }
281
+ });
282
+ }
283
+ class Cells {
284
+ read(key, value) {
285
+ if (currentConsumer === null) return value;
286
+ let entry = this.nodes.get(key);
287
+ if (!entry) {
288
+ entry = {
289
+ node: createProducer(0),
290
+ value
291
+ };
292
+ this.nodes.set(key, entry);
293
+ }
294
+ readProducer(entry.node);
295
+ return value;
296
+ }
297
+ write(key, value) {
298
+ const entry = this.nodes.get(key);
299
+ if (!entry || Object.is(entry.value, value)) return;
300
+ entry.value = value;
301
+ writeProducer(entry.node, entry.node.payload + 1);
302
+ }
303
+ clear(value) {
304
+ for (const entry of this.nodes.values()){
305
+ if (Object.is(entry.value, value)) continue;
306
+ entry.value = value;
307
+ writeProducer(entry.node, entry.node.payload + 1);
308
+ }
309
+ }
310
+ collect() {
311
+ for (const [key, { node }] of this.nodes){
312
+ if (node.firstOut !== null) continue;
313
+ this.nodes.delete(key);
314
+ disposeNode(node);
315
+ }
316
+ }
317
+ dispose() {
318
+ for (const { node } of this.nodes.values())disposeNode(node);
319
+ this.nodes.clear();
320
+ }
321
+ constructor(){
322
+ // Values live outside producer payloads so foreign objects remain valid even
323
+ // when runtime dev validation accepts only primitive/plain payloads.
324
+ this.nodes = new Map();
325
+ }
326
+ }
327
+ class ReactiveMap {
328
+ constructor(initial, options = {}){
329
+ this.initial = initial;
330
+ this.options = options;
331
+ this.disposed = false;
332
+ this.valuesByKey = new Cells();
333
+ this.existsByKey = new Cells();
334
+ setStoreName(this, options.name);
335
+ storeControls.set(this, {
336
+ raw: ()=>this.backing(),
337
+ collect: ()=>this.collect(),
338
+ dispose: ()=>this.dispose()
339
+ });
340
+ }
341
+ backing() {
342
+ if (this.disposed) throw new Error("Cannot use a disposed reactive map");
343
+ if (!this.data) {
344
+ this.data = untracked(()=>new Map(typeof this.initial === "function" ? this.initial() : this.initial));
345
+ this.initial = undefined;
346
+ }
347
+ return this.data;
348
+ }
349
+ get size() {
350
+ const size = this.backing().size;
351
+ if (currentConsumer !== null) readProducer(this.sizeNode ??= createProducer(size));
352
+ return size;
353
+ }
354
+ get [Symbol.toStringTag]() {
355
+ return "ReactiveMap";
356
+ }
357
+ get(key) {
358
+ return this.valuesByKey.read(key, this.backing().get(key));
359
+ }
360
+ has(key) {
361
+ return this.existsByKey.read(key, this.backing().has(key));
362
+ }
363
+ set(key, value) {
364
+ const data = this.backing();
365
+ const previous = data.get(key);
366
+ const existed = previous !== undefined || data.has(key);
367
+ if (existed) {
368
+ const equals = this.options.equals;
369
+ if (equals == null || equals === Object.is ? Object.is(previous, value) : untracked(()=>equals(previous, value))) return this;
370
+ }
371
+ this.commitSet(data, key, value, existed);
372
+ return this;
373
+ }
374
+ commitSet(data, key, value, existed) {
375
+ transaction(()=>{
376
+ data.set(key, value);
377
+ this.valuesByKey.write(key, value);
378
+ if (!existed) {
379
+ this.existsByKey.write(key, true);
380
+ if (this.sizeNode) writeProducer(this.sizeNode, data.size);
381
+ if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
382
+ }
383
+ if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
384
+ });
385
+ }
386
+ delete(key) {
387
+ const data = this.backing();
388
+ if (!data.has(key)) return false;
389
+ transaction(()=>{
390
+ data.delete(key);
391
+ this.valuesByKey.write(key, undefined);
392
+ this.existsByKey.write(key, false);
393
+ if (this.sizeNode) writeProducer(this.sizeNode, data.size);
394
+ if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
395
+ if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
396
+ });
397
+ return true;
398
+ }
399
+ clear() {
400
+ const data = this.backing();
401
+ if (data.size === 0) return;
402
+ transaction(()=>{
403
+ data.clear();
404
+ // Only materialized semantic locations need invalidation, even for a large map.
405
+ this.valuesByKey.clear(undefined);
406
+ this.existsByKey.clear(false);
407
+ if (this.sizeNode) writeProducer(this.sizeNode, 0);
408
+ if (this.keysNode) writeProducer(this.keysNode, this.keysNode.payload + 1);
409
+ if (this.valuesNode) writeProducer(this.valuesNode, this.valuesNode.payload + 1);
410
+ });
411
+ }
412
+ keys() {
413
+ const data = this.backing();
414
+ if (currentConsumer !== null) readProducer(this.keysNode ??= createProducer(0));
415
+ return data.keys();
416
+ }
417
+ values() {
418
+ const data = this.backing();
419
+ if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
420
+ return data.values();
421
+ }
422
+ entries() {
423
+ const data = this.backing();
424
+ if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
425
+ return data.entries();
426
+ }
427
+ [Symbol.iterator]() {
428
+ return this.entries();
429
+ }
430
+ forEach(callback, thisArg) {
431
+ const data = this.backing();
432
+ if (currentConsumer !== null) readProducer(this.valuesNode ??= createProducer(0));
433
+ data.forEach((value, key)=>callback.call(thisArg, value, key, this));
434
+ }
435
+ collect() {
436
+ this.valuesByKey.collect();
437
+ this.existsByKey.collect();
438
+ if (this.sizeNode?.firstOut === null) {
439
+ disposeNode(this.sizeNode);
440
+ this.sizeNode = undefined;
441
+ }
442
+ if (this.keysNode?.firstOut === null) {
443
+ disposeNode(this.keysNode);
444
+ this.keysNode = undefined;
445
+ }
446
+ if (this.valuesNode?.firstOut === null) {
447
+ disposeNode(this.valuesNode);
448
+ this.valuesNode = undefined;
449
+ }
450
+ }
451
+ [Symbol.dispose]() {
452
+ this.dispose();
453
+ }
454
+ dispose() {
455
+ this.disposed = true;
456
+ this.valuesByKey.dispose();
457
+ this.existsByKey.dispose();
458
+ if (this.sizeNode) disposeNode(this.sizeNode);
459
+ if (this.keysNode) disposeNode(this.keysNode);
460
+ if (this.valuesNode) disposeNode(this.valuesNode);
461
+ this.sizeNode = this.keysNode = this.valuesNode = undefined;
462
+ this.data = undefined;
463
+ this.initial = undefined;
464
+ }
465
+ }
466
+ /** A native Set-shaped membership collection over keyed reactive observations. */ class ReactiveSet {
467
+ constructor(initial, options = {}){
468
+ this.members = new ReactiveMap(()=>Array.from(typeof initial === "function" ? initial() : initial ?? [], (value)=>[
469
+ value,
470
+ true
471
+ ]));
472
+ setStoreName(this, options.name);
473
+ storeControls.set(this, {
474
+ raw: ()=>new Set(this.members.keys()),
475
+ collect: ()=>this.collect(),
476
+ dispose: ()=>this.dispose()
477
+ });
478
+ }
479
+ get size() {
480
+ return this.members.size;
481
+ }
482
+ get [Symbol.toStringTag]() {
483
+ return "ReactiveSet";
484
+ }
485
+ has(value) {
486
+ return this.members.has(value);
487
+ }
488
+ add(value) {
489
+ this.members.set(value, true);
490
+ return this;
491
+ }
492
+ delete(value) {
493
+ return this.members.delete(value);
494
+ }
495
+ clear() {
496
+ this.members.clear();
497
+ }
498
+ values() {
499
+ return this.members.keys();
500
+ }
501
+ keys() {
502
+ return this.values();
503
+ }
504
+ *entries() {
505
+ for (const value of this.values())yield [
506
+ value,
507
+ value
508
+ ];
509
+ }
510
+ [Symbol.iterator]() {
511
+ return this.values();
512
+ }
513
+ forEach(callback, thisArg) {
514
+ for (const value of this.values())callback.call(thisArg, value, value, this);
515
+ }
516
+ collect() {
517
+ this.members.collect();
518
+ }
519
+ dispose() {
520
+ this.members.dispose();
521
+ }
522
+ [Symbol.dispose]() {
523
+ this.dispose();
524
+ }
525
+ }
526
+ function reactiveSet(initial, options) {
527
+ return new ReactiveSet(initial, options);
528
+ }
529
+ function createReactiveMap(initial, options) {
530
+ return new ReactiveMap(initial, options);
531
+ }
532
+
533
+ /// <reference lib="esnext.disposable" />
534
+ function withDispose(resource, name) {
535
+ setStoreName(resource, name);
536
+ Object.defineProperty(resource, Symbol.dispose, {
537
+ configurable: true,
538
+ value: ()=>resource.dispose()
539
+ });
540
+ return resource;
541
+ }
542
+
543
+ // Map uses SameValueZero. Preserve Object.is semantics for signed zero.
544
+ const negativeZero = Symbol("negative zero");
545
+ function identityKey(key) {
546
+ return key === 0 && 1 / key === -Infinity ? negativeZero : key;
547
+ }
548
+ function createSelector(source, options = {}) {
549
+ const equals = options.equals ?? Object.is;
550
+ const identityEquality = equals === Object.is;
551
+ const entries = new Map();
552
+ let watcher;
553
+ let current;
554
+ let initialized = false;
555
+ let disposed = false;
556
+ const lookup = (key)=>{
557
+ if (identityEquality) return entries.get(identityKey(key));
558
+ return untracked(()=>{
559
+ for (const entry of entries.values())if (equals(entry.key, key)) return entry;
560
+ return undefined;
561
+ });
562
+ };
563
+ const sync = (next)=>{
564
+ if (initialized && (identityEquality ? Object.is(current, next) : untracked(()=>equals(current, next)))) return;
565
+ const previous = initialized ? lookup(current) : undefined;
566
+ current = next;
567
+ initialized = true;
568
+ const selected = lookup(next);
569
+ if (!previous && !selected) return;
570
+ transaction(()=>{
571
+ if (previous) writeProducer(previous.node, false);
572
+ if (selected) writeProducer(selected.node, true);
573
+ });
574
+ };
575
+ const read = (key)=>{
576
+ if (disposed) throw new Error("Cannot read a disposed selector");
577
+ if (currentConsumer === null) return identityEquality ? Object.is(source(), key) : untracked(()=>equals(source(), key));
578
+ if (!watcher) {
579
+ watcher = createWatcher(()=>sync(source()));
580
+ try {
581
+ runWatcher(watcher);
582
+ } catch (error) {
583
+ disposeWatcher(watcher);
584
+ watcher = undefined;
585
+ throw error;
586
+ }
587
+ } else if ((watcher.state & Both) !== 0) {
588
+ sync(untracked(source));
589
+ }
590
+ let entry = lookup(key);
591
+ if (!entry) {
592
+ entry = {
593
+ key,
594
+ node: createSignalNode(identityEquality ? Object.is(current, key) : untracked(()=>equals(current, key)))
595
+ };
596
+ entries.set(identityKey(key), entry);
597
+ }
598
+ return readProducer(entry.node);
599
+ };
600
+ return withDispose(Object.assign(read, {
601
+ collect () {
602
+ for (const [key, entry] of entries){
603
+ if (entry.node.firstOut !== null) continue;
604
+ entries.delete(key);
605
+ disposeNode(entry.node);
606
+ }
607
+ if (entries.size === 0 && watcher) {
608
+ disposeWatcher(watcher);
609
+ watcher = undefined;
610
+ initialized = false;
611
+ }
612
+ },
613
+ dispose () {
614
+ disposed = true;
615
+ if (watcher) disposeWatcher(watcher);
616
+ watcher = undefined;
617
+ for (const entry of entries.values())disposeNode(entry.node);
618
+ entries.clear();
619
+ }
620
+ }), options.name);
621
+ }
622
+ function createKeyedProjection(source, keyOf, project, options = {}) {
623
+ const keyEquals = options.keyEquals ?? Object.is;
624
+ const valueEquals = options.equals ?? Object.is;
625
+ const sourceValue = new Demand(source);
626
+ const projected = new Demand(()=>project(sourceValue.read()));
627
+ const keys = new Observations((key)=>{
628
+ const activeKey = keyOf(sourceValue.read());
629
+ const requestedKey = key === negativeZero ? -0 : key;
630
+ const matches = keyEquals === Object.is ? Object.is(activeKey, requestedKey) : untracked(()=>keyEquals(activeKey, requestedKey));
631
+ return matches ? projected.read() : options.fallback;
632
+ }, valueEquals === Object.is ? Object.is : (a, b)=>a === undefined || b === undefined ? Object.is(a, b) : valueEquals(a, b), options.keyEquals ? (a, b)=>keyEquals(a === negativeZero ? -0 : a, b === negativeZero ? -0 : b) : undefined);
633
+ return withDispose(Object.assign((key)=>keys.read(identityKey(key)), {
634
+ collect () {
635
+ keys.collect();
636
+ projected.collect();
637
+ sourceValue.collect();
638
+ },
639
+ dispose () {
640
+ keys.dispose();
641
+ projected.dispose();
642
+ sourceValue.dispose();
643
+ }
644
+ }), options.name);
645
+ }
646
+
647
+ export { ReactiveMap as R, createSelector as a, ReactiveSet as b, createReactiveMap as c, createKeyedProjection as d, createStoreProjection as e, createDerivedProjection as f, reactiveSet as r, transaction as t };
@@ -0,0 +1,11 @@
1
+ const storeName = Symbol.for("@volynets/reflex-store/name");
2
+ function getStoreName(resource) {
3
+ return resource[storeName];
4
+ }
5
+ function setStoreName(resource, name) {
6
+ if (name !== undefined) Object.defineProperty(resource, storeName, {
7
+ value: name
8
+ });
9
+ }
10
+
11
+ export { setStoreName as a, getStoreName as g, storeName as s };