gjendje 1.3.3 → 1.3.4
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.
- package/dist/{chunk-G6VLCNVY.cjs → chunk-FD2LRNLT.cjs} +1 -0
- package/dist/{chunk-PAJH64N4.js → chunk-TV5QHWN4.js} +1 -0
- package/dist/index.cjs +150 -48
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +124 -22
- package/dist/server.cjs +3 -3
- package/dist/server.js +1 -1
- package/package.json +21 -8
package/dist/index.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkFD2LRNLT_cjs = require('./chunk-FD2LRNLT.cjs');
|
|
4
4
|
var chunk3K5IERQC_cjs = require('./chunk-3K5IERQC.cjs');
|
|
5
5
|
|
|
6
6
|
// src/collection.ts
|
|
7
7
|
function collection(key, options) {
|
|
8
|
-
const base =
|
|
8
|
+
const base = chunkFD2LRNLT_cjs.createBase(key, options);
|
|
9
9
|
let watchers;
|
|
10
10
|
let prevItems;
|
|
11
11
|
let unsubscribe;
|
|
@@ -19,7 +19,8 @@ function collection(key, options) {
|
|
|
19
19
|
prevItems = next;
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
const
|
|
22
|
+
const prev = prevItems ?? [];
|
|
23
|
+
const lengthChanged = next.length !== prev.length;
|
|
23
24
|
if (lengthChanged) {
|
|
24
25
|
for (const [, listeners] of w) {
|
|
25
26
|
for (const listener of listeners) {
|
|
@@ -32,11 +33,11 @@ function collection(key, options) {
|
|
|
32
33
|
const len = next.length;
|
|
33
34
|
let changedKeys;
|
|
34
35
|
for (let i = 0; i < len; i++) {
|
|
35
|
-
const
|
|
36
|
+
const prevItem = prev[i];
|
|
36
37
|
const curr = next[i];
|
|
37
|
-
if (
|
|
38
|
-
const p =
|
|
39
|
-
const n =
|
|
38
|
+
if (prevItem === curr) continue;
|
|
39
|
+
const p = chunkFD2LRNLT_cjs.isRecord(prevItem) ? prevItem : void 0;
|
|
40
|
+
const n = chunkFD2LRNLT_cjs.isRecord(curr) ? curr : void 0;
|
|
40
41
|
if (!p || !n) {
|
|
41
42
|
for (const [, listeners] of w) {
|
|
42
43
|
for (const listener of listeners) {
|
|
@@ -72,7 +73,7 @@ function collection(key, options) {
|
|
|
72
73
|
const baseDestroy = base.destroy;
|
|
73
74
|
const col = base;
|
|
74
75
|
col.watch = (watchKey, listener) => {
|
|
75
|
-
return
|
|
76
|
+
return chunkFD2LRNLT_cjs.addWatcher(ensureWatchers(), watchKey, listener);
|
|
76
77
|
};
|
|
77
78
|
col.add = (...items) => {
|
|
78
79
|
base.set(base.get().concat(items));
|
|
@@ -136,7 +137,10 @@ function collection(key, options) {
|
|
|
136
137
|
col.destroy = () => {
|
|
137
138
|
try {
|
|
138
139
|
watchers?.clear();
|
|
140
|
+
watchers = void 0;
|
|
139
141
|
unsubscribe?.();
|
|
142
|
+
unsubscribe = void 0;
|
|
143
|
+
prevItems = void 0;
|
|
140
144
|
} finally {
|
|
141
145
|
baseDestroy.call(col);
|
|
142
146
|
}
|
|
@@ -149,7 +153,7 @@ function callDerivation(fn, depValues, key) {
|
|
|
149
153
|
try {
|
|
150
154
|
return fn(depValues);
|
|
151
155
|
} catch (err) {
|
|
152
|
-
const wrapped = new
|
|
156
|
+
const wrapped = new chunkFD2LRNLT_cjs.ComputedError(key, "memory", err);
|
|
153
157
|
chunk3K5IERQC_cjs.reportError(key, "memory", wrapped);
|
|
154
158
|
throw wrapped;
|
|
155
159
|
}
|
|
@@ -165,7 +169,7 @@ function computed(deps, fn, options) {
|
|
|
165
169
|
let cached;
|
|
166
170
|
let isDirty = true;
|
|
167
171
|
let isDestroyed = false;
|
|
168
|
-
const lazyDestroyed =
|
|
172
|
+
const lazyDestroyed = chunkFD2LRNLT_cjs.createLazyDestroyed();
|
|
169
173
|
const depValues = new Array(deps.length);
|
|
170
174
|
const depLen = deps.length;
|
|
171
175
|
function recompute() {
|
|
@@ -194,7 +198,7 @@ function computed(deps, fn, options) {
|
|
|
194
198
|
const markDirty = () => {
|
|
195
199
|
if (isDestroyed) return;
|
|
196
200
|
isDirty = true;
|
|
197
|
-
|
|
201
|
+
chunkFD2LRNLT_cjs.notify(notifyListeners);
|
|
198
202
|
};
|
|
199
203
|
const unsubscribers = new Array(depLen);
|
|
200
204
|
for (let i = 0; i < depLen; i++) {
|
|
@@ -202,12 +206,12 @@ function computed(deps, fn, options) {
|
|
|
202
206
|
unsubscribers[i] = dep.subscribe(markDirty);
|
|
203
207
|
}
|
|
204
208
|
recompute();
|
|
205
|
-
let readyPromise =
|
|
206
|
-
let hydratedPromise =
|
|
207
|
-
let settledPromise =
|
|
209
|
+
let readyPromise = chunkFD2LRNLT_cjs.RESOLVED;
|
|
210
|
+
let hydratedPromise = chunkFD2LRNLT_cjs.RESOLVED;
|
|
211
|
+
let settledPromise = chunkFD2LRNLT_cjs.RESOLVED;
|
|
208
212
|
let hasAsyncDep = false;
|
|
209
213
|
for (let i = 0; i < depLen; i++) {
|
|
210
|
-
if (deps[i].ready !==
|
|
214
|
+
if (deps[i].ready !== chunkFD2LRNLT_cjs.RESOLVED) {
|
|
211
215
|
hasAsyncDep = true;
|
|
212
216
|
break;
|
|
213
217
|
}
|
|
@@ -239,7 +243,7 @@ function computed(deps, fn, options) {
|
|
|
239
243
|
return hydratedPromise;
|
|
240
244
|
},
|
|
241
245
|
get destroyed() {
|
|
242
|
-
if (isDestroyed) return
|
|
246
|
+
if (isDestroyed) return chunkFD2LRNLT_cjs.RESOLVED;
|
|
243
247
|
return lazyDestroyed.promise;
|
|
244
248
|
},
|
|
245
249
|
get isDestroyed() {
|
|
@@ -338,6 +342,7 @@ function effect(deps, fn, options) {
|
|
|
338
342
|
for (let i = 0; i < depLen; i++) {
|
|
339
343
|
unsubscribers[i]();
|
|
340
344
|
}
|
|
345
|
+
unsubscribers.length = 0;
|
|
341
346
|
} finally {
|
|
342
347
|
if (cleanup) {
|
|
343
348
|
try {
|
|
@@ -420,15 +425,13 @@ function withWatch(instance) {
|
|
|
420
425
|
let watchers;
|
|
421
426
|
let unsubscribe;
|
|
422
427
|
let prev;
|
|
423
|
-
let initialized = false;
|
|
424
428
|
function ensureSubscription() {
|
|
425
|
-
if (unsubscribe
|
|
426
|
-
initialized = true;
|
|
429
|
+
if (unsubscribe) return;
|
|
427
430
|
prev = instance.get();
|
|
428
431
|
unsubscribe = instance.subscribe((next) => {
|
|
429
432
|
try {
|
|
430
433
|
if (watchers && watchers.size > 0) {
|
|
431
|
-
|
|
434
|
+
chunkFD2LRNLT_cjs.notifyWatchers(watchers, prev, next);
|
|
432
435
|
}
|
|
433
436
|
} finally {
|
|
434
437
|
prev = next;
|
|
@@ -439,14 +442,13 @@ function withWatch(instance) {
|
|
|
439
442
|
result.watch = (watchKey, listener) => {
|
|
440
443
|
if (!watchers) watchers = /* @__PURE__ */ new Map();
|
|
441
444
|
ensureSubscription();
|
|
442
|
-
return
|
|
445
|
+
return chunkFD2LRNLT_cjs.addWatcher(watchers, watchKey, listener);
|
|
443
446
|
};
|
|
444
447
|
result.destroy = () => {
|
|
445
448
|
watchers?.clear();
|
|
446
449
|
watchers = void 0;
|
|
447
450
|
unsubscribe?.();
|
|
448
451
|
unsubscribe = void 0;
|
|
449
|
-
initialized = false;
|
|
450
452
|
prev = void 0;
|
|
451
453
|
instance.destroy();
|
|
452
454
|
};
|
|
@@ -464,15 +466,21 @@ function previous(source, options) {
|
|
|
464
466
|
const notifyListeners = () => {
|
|
465
467
|
listeners.notify(prev);
|
|
466
468
|
};
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
469
|
+
let unsubscribe;
|
|
470
|
+
try {
|
|
471
|
+
unsubscribe = source.subscribe((next) => {
|
|
472
|
+
const old = prev;
|
|
473
|
+
prev = current;
|
|
474
|
+
current = next;
|
|
475
|
+
if (old !== prev) {
|
|
476
|
+
chunkFD2LRNLT_cjs.notify(notifyListeners);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
} catch {
|
|
480
|
+
listeners.clear();
|
|
481
|
+
throw new Error(`[gjendje] previous(): source.subscribe() threw for "${instanceKey}".`);
|
|
482
|
+
}
|
|
483
|
+
const lazyDestroyed = chunkFD2LRNLT_cjs.createLazyDestroyed();
|
|
476
484
|
return {
|
|
477
485
|
key: instanceKey,
|
|
478
486
|
scope: "memory",
|
|
@@ -501,7 +509,7 @@ function previous(source, options) {
|
|
|
501
509
|
destroy() {
|
|
502
510
|
if (isDestroyed) return;
|
|
503
511
|
isDestroyed = true;
|
|
504
|
-
unsubscribe();
|
|
512
|
+
unsubscribe?.();
|
|
505
513
|
listeners.clear();
|
|
506
514
|
lazyDestroyed.resolve();
|
|
507
515
|
}
|
|
@@ -519,10 +527,104 @@ function readonly(instance) {
|
|
|
519
527
|
|
|
520
528
|
// src/select.ts
|
|
521
529
|
var selectCounter = 0;
|
|
530
|
+
function callSelector(fn, value, key) {
|
|
531
|
+
try {
|
|
532
|
+
return fn(value);
|
|
533
|
+
} catch (err) {
|
|
534
|
+
const wrapped = new chunkFD2LRNLT_cjs.ComputedError(key, "memory", err);
|
|
535
|
+
chunk3K5IERQC_cjs.reportError(key, "memory", wrapped);
|
|
536
|
+
throw wrapped;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
522
539
|
function select(source, fn, options) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
540
|
+
const instanceKey = options?.key ?? `select:${selectCounter++}`;
|
|
541
|
+
const listenerSet = /* @__PURE__ */ new Set();
|
|
542
|
+
let singleListener;
|
|
543
|
+
let listenerCount = 0;
|
|
544
|
+
let cached;
|
|
545
|
+
let isDirty = true;
|
|
546
|
+
let isDestroyed = false;
|
|
547
|
+
const lazyDestroyed = chunkFD2LRNLT_cjs.createLazyDestroyed();
|
|
548
|
+
function recompute() {
|
|
549
|
+
if (!isDirty) return cached;
|
|
550
|
+
cached = callSelector(fn, source.get(), instanceKey);
|
|
551
|
+
isDirty = false;
|
|
552
|
+
return cached;
|
|
553
|
+
}
|
|
554
|
+
const notifyListeners = () => {
|
|
555
|
+
if (isDestroyed) return;
|
|
556
|
+
const prev = cached;
|
|
557
|
+
const value = recompute();
|
|
558
|
+
if (value === prev) return;
|
|
559
|
+
if (singleListener !== void 0) {
|
|
560
|
+
chunk3K5IERQC_cjs.safeCall(singleListener, value, instanceKey, "memory");
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
for (const l of listenerSet) {
|
|
564
|
+
chunk3K5IERQC_cjs.safeCall(l, value, instanceKey, "memory");
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
const markDirty = () => {
|
|
568
|
+
if (isDestroyed) return;
|
|
569
|
+
isDirty = true;
|
|
570
|
+
chunkFD2LRNLT_cjs.notify(notifyListeners);
|
|
571
|
+
};
|
|
572
|
+
const unsub = source.subscribe(markDirty);
|
|
573
|
+
recompute();
|
|
574
|
+
return {
|
|
575
|
+
key: instanceKey,
|
|
576
|
+
scope: "memory",
|
|
577
|
+
get ready() {
|
|
578
|
+
return source.ready;
|
|
579
|
+
},
|
|
580
|
+
get settled() {
|
|
581
|
+
return source.settled;
|
|
582
|
+
},
|
|
583
|
+
get hydrated() {
|
|
584
|
+
return source.hydrated;
|
|
585
|
+
},
|
|
586
|
+
get destroyed() {
|
|
587
|
+
if (isDestroyed) return chunkFD2LRNLT_cjs.RESOLVED;
|
|
588
|
+
return lazyDestroyed.promise;
|
|
589
|
+
},
|
|
590
|
+
get isDestroyed() {
|
|
591
|
+
return isDestroyed;
|
|
592
|
+
},
|
|
593
|
+
get() {
|
|
594
|
+
return recompute();
|
|
595
|
+
},
|
|
596
|
+
peek() {
|
|
597
|
+
return cached;
|
|
598
|
+
},
|
|
599
|
+
subscribe(listener) {
|
|
600
|
+
if (isDestroyed) return () => {
|
|
601
|
+
};
|
|
602
|
+
listenerSet.add(listener);
|
|
603
|
+
listenerCount++;
|
|
604
|
+
singleListener = listenerCount === 1 ? listener : void 0;
|
|
605
|
+
return () => {
|
|
606
|
+
listenerSet.delete(listener);
|
|
607
|
+
listenerCount--;
|
|
608
|
+
if (listenerCount === 1) {
|
|
609
|
+
singleListener = listenerSet.values().next().value;
|
|
610
|
+
} else {
|
|
611
|
+
singleListener = void 0;
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
},
|
|
615
|
+
destroy() {
|
|
616
|
+
if (isDestroyed) return;
|
|
617
|
+
isDestroyed = true;
|
|
618
|
+
try {
|
|
619
|
+
unsub();
|
|
620
|
+
listenerSet.clear();
|
|
621
|
+
listenerCount = 0;
|
|
622
|
+
singleListener = void 0;
|
|
623
|
+
} finally {
|
|
624
|
+
lazyDestroyed.resolve();
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
};
|
|
526
628
|
}
|
|
527
629
|
|
|
528
630
|
// src/shortcuts.ts
|
|
@@ -538,7 +640,7 @@ function extractEntry(entry) {
|
|
|
538
640
|
}
|
|
539
641
|
function scopeShortcut(scope, entry, options) {
|
|
540
642
|
const [key, defaultValue] = extractEntry(entry);
|
|
541
|
-
return
|
|
643
|
+
return chunkFD2LRNLT_cjs.createBase(key, { ...options, default: defaultValue, scope });
|
|
542
644
|
}
|
|
543
645
|
function _state(keyOrEntry, optionsOrDefault, extraOptions) {
|
|
544
646
|
let key;
|
|
@@ -551,7 +653,7 @@ function _state(keyOrEntry, optionsOrDefault, extraOptions) {
|
|
|
551
653
|
key = keyOrEntry;
|
|
552
654
|
options = extraOptions ? { ...extraOptions, default: optionsOrDefault } : optionsOrDefault !== null && typeof optionsOrDefault === "object" && "default" in optionsOrDefault ? optionsOrDefault : { default: optionsOrDefault };
|
|
553
655
|
}
|
|
554
|
-
return
|
|
656
|
+
return chunkFD2LRNLT_cjs.createBase(key, options);
|
|
555
657
|
}
|
|
556
658
|
_state.local = (e, o) => scopeShortcut("local", e, o);
|
|
557
659
|
_state.session = (e, o) => scopeShortcut("session", e, o);
|
|
@@ -562,47 +664,47 @@ var state = _state;
|
|
|
562
664
|
|
|
563
665
|
Object.defineProperty(exports, "ComputedError", {
|
|
564
666
|
enumerable: true,
|
|
565
|
-
get: function () { return
|
|
667
|
+
get: function () { return chunkFD2LRNLT_cjs.ComputedError; }
|
|
566
668
|
});
|
|
567
669
|
Object.defineProperty(exports, "GjendjeError", {
|
|
568
670
|
enumerable: true,
|
|
569
|
-
get: function () { return
|
|
671
|
+
get: function () { return chunkFD2LRNLT_cjs.GjendjeError; }
|
|
570
672
|
});
|
|
571
673
|
Object.defineProperty(exports, "HydrationError", {
|
|
572
674
|
enumerable: true,
|
|
573
|
-
get: function () { return
|
|
675
|
+
get: function () { return chunkFD2LRNLT_cjs.HydrationError; }
|
|
574
676
|
});
|
|
575
677
|
Object.defineProperty(exports, "InterceptorError", {
|
|
576
678
|
enumerable: true,
|
|
577
|
-
get: function () { return
|
|
679
|
+
get: function () { return chunkFD2LRNLT_cjs.InterceptorError; }
|
|
578
680
|
});
|
|
579
681
|
Object.defineProperty(exports, "MigrationError", {
|
|
580
682
|
enumerable: true,
|
|
581
|
-
get: function () { return
|
|
683
|
+
get: function () { return chunkFD2LRNLT_cjs.MigrationError; }
|
|
582
684
|
});
|
|
583
685
|
Object.defineProperty(exports, "StorageReadError", {
|
|
584
686
|
enumerable: true,
|
|
585
|
-
get: function () { return
|
|
687
|
+
get: function () { return chunkFD2LRNLT_cjs.StorageReadError; }
|
|
586
688
|
});
|
|
587
689
|
Object.defineProperty(exports, "StorageWriteError", {
|
|
588
690
|
enumerable: true,
|
|
589
|
-
get: function () { return
|
|
691
|
+
get: function () { return chunkFD2LRNLT_cjs.StorageWriteError; }
|
|
590
692
|
});
|
|
591
693
|
Object.defineProperty(exports, "SyncError", {
|
|
592
694
|
enumerable: true,
|
|
593
|
-
get: function () { return
|
|
695
|
+
get: function () { return chunkFD2LRNLT_cjs.SyncError; }
|
|
594
696
|
});
|
|
595
697
|
Object.defineProperty(exports, "ValidationError", {
|
|
596
698
|
enumerable: true,
|
|
597
|
-
get: function () { return
|
|
699
|
+
get: function () { return chunkFD2LRNLT_cjs.ValidationError; }
|
|
598
700
|
});
|
|
599
701
|
Object.defineProperty(exports, "batch", {
|
|
600
702
|
enumerable: true,
|
|
601
|
-
get: function () { return
|
|
703
|
+
get: function () { return chunkFD2LRNLT_cjs.batch; }
|
|
602
704
|
});
|
|
603
705
|
Object.defineProperty(exports, "shallowEqual", {
|
|
604
706
|
enumerable: true,
|
|
605
|
-
get: function () { return
|
|
707
|
+
get: function () { return chunkFD2LRNLT_cjs.shallowEqual; }
|
|
606
708
|
});
|
|
607
709
|
Object.defineProperty(exports, "configure", {
|
|
608
710
|
enumerable: true,
|
package/dist/index.d.cts
CHANGED
|
@@ -497,8 +497,8 @@ declare function destroyAll(): void;
|
|
|
497
497
|
|
|
498
498
|
/**
|
|
499
499
|
* A read-only reactive value derived from a single source.
|
|
500
|
-
* Lighter than `computed` —
|
|
501
|
-
*
|
|
500
|
+
* Lighter than `computed` — no array allocation, no dependency loop.
|
|
501
|
+
* Ideal for projecting a single field or transformation.
|
|
502
502
|
*/
|
|
503
503
|
interface SelectInstance<T> extends ReadonlyInstance<T> {
|
|
504
504
|
}
|
|
@@ -519,6 +519,8 @@ interface SelectOptions {
|
|
|
519
519
|
* userName.get() // 'Jane'
|
|
520
520
|
* userName.subscribe(name => console.log(name))
|
|
521
521
|
* ```
|
|
522
|
+
*
|
|
523
|
+
* @throws {ComputedError} If the selector function throws during recomputation.
|
|
522
524
|
*/
|
|
523
525
|
declare function select<TSource, TResult>(source: ReadonlyInstance<TSource>, fn: (value: TSource) => TResult, options?: SelectOptions): SelectInstance<TResult>;
|
|
524
526
|
|
package/dist/index.d.ts
CHANGED
|
@@ -497,8 +497,8 @@ declare function destroyAll(): void;
|
|
|
497
497
|
|
|
498
498
|
/**
|
|
499
499
|
* A read-only reactive value derived from a single source.
|
|
500
|
-
* Lighter than `computed` —
|
|
501
|
-
*
|
|
500
|
+
* Lighter than `computed` — no array allocation, no dependency loop.
|
|
501
|
+
* Ideal for projecting a single field or transformation.
|
|
502
502
|
*/
|
|
503
503
|
interface SelectInstance<T> extends ReadonlyInstance<T> {
|
|
504
504
|
}
|
|
@@ -519,6 +519,8 @@ interface SelectOptions {
|
|
|
519
519
|
* userName.get() // 'Jane'
|
|
520
520
|
* userName.subscribe(name => console.log(name))
|
|
521
521
|
* ```
|
|
522
|
+
*
|
|
523
|
+
* @throws {ComputedError} If the selector function throws during recomputation.
|
|
522
524
|
*/
|
|
523
525
|
declare function select<TSource, TResult>(source: ReadonlyInstance<TSource>, fn: (value: TSource) => TResult, options?: SelectOptions): SelectInstance<TResult>;
|
|
524
526
|
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createBase, addWatcher, createLazyDestroyed, RESOLVED, notify, isRecord, notifyWatchers, ComputedError } from './chunk-
|
|
2
|
-
export { ComputedError, GjendjeError, HydrationError, InterceptorError, MigrationError, StorageReadError, StorageWriteError, SyncError, ValidationError, batch, shallowEqual } from './chunk-
|
|
1
|
+
import { createBase, addWatcher, createLazyDestroyed, RESOLVED, notify, isRecord, notifyWatchers, ComputedError } from './chunk-TV5QHWN4.js';
|
|
2
|
+
export { ComputedError, GjendjeError, HydrationError, InterceptorError, MigrationError, StorageReadError, StorageWriteError, SyncError, ValidationError, batch, shallowEqual } from './chunk-TV5QHWN4.js';
|
|
3
3
|
import { getRegistry, createListeners, safeCall, reportError } from './chunk-N54IDKRP.js';
|
|
4
4
|
export { configure, destroyAll, resetConfig } from './chunk-N54IDKRP.js';
|
|
5
5
|
|
|
@@ -19,7 +19,8 @@ function collection(key, options) {
|
|
|
19
19
|
prevItems = next;
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
const
|
|
22
|
+
const prev = prevItems ?? [];
|
|
23
|
+
const lengthChanged = next.length !== prev.length;
|
|
23
24
|
if (lengthChanged) {
|
|
24
25
|
for (const [, listeners] of w) {
|
|
25
26
|
for (const listener of listeners) {
|
|
@@ -32,10 +33,10 @@ function collection(key, options) {
|
|
|
32
33
|
const len = next.length;
|
|
33
34
|
let changedKeys;
|
|
34
35
|
for (let i = 0; i < len; i++) {
|
|
35
|
-
const
|
|
36
|
+
const prevItem = prev[i];
|
|
36
37
|
const curr = next[i];
|
|
37
|
-
if (
|
|
38
|
-
const p = isRecord(
|
|
38
|
+
if (prevItem === curr) continue;
|
|
39
|
+
const p = isRecord(prevItem) ? prevItem : void 0;
|
|
39
40
|
const n = isRecord(curr) ? curr : void 0;
|
|
40
41
|
if (!p || !n) {
|
|
41
42
|
for (const [, listeners] of w) {
|
|
@@ -136,7 +137,10 @@ function collection(key, options) {
|
|
|
136
137
|
col.destroy = () => {
|
|
137
138
|
try {
|
|
138
139
|
watchers?.clear();
|
|
140
|
+
watchers = void 0;
|
|
139
141
|
unsubscribe?.();
|
|
142
|
+
unsubscribe = void 0;
|
|
143
|
+
prevItems = void 0;
|
|
140
144
|
} finally {
|
|
141
145
|
baseDestroy.call(col);
|
|
142
146
|
}
|
|
@@ -338,6 +342,7 @@ function effect(deps, fn, options) {
|
|
|
338
342
|
for (let i = 0; i < depLen; i++) {
|
|
339
343
|
unsubscribers[i]();
|
|
340
344
|
}
|
|
345
|
+
unsubscribers.length = 0;
|
|
341
346
|
} finally {
|
|
342
347
|
if (cleanup) {
|
|
343
348
|
try {
|
|
@@ -420,10 +425,8 @@ function withWatch(instance) {
|
|
|
420
425
|
let watchers;
|
|
421
426
|
let unsubscribe;
|
|
422
427
|
let prev;
|
|
423
|
-
let initialized = false;
|
|
424
428
|
function ensureSubscription() {
|
|
425
|
-
if (unsubscribe
|
|
426
|
-
initialized = true;
|
|
429
|
+
if (unsubscribe) return;
|
|
427
430
|
prev = instance.get();
|
|
428
431
|
unsubscribe = instance.subscribe((next) => {
|
|
429
432
|
try {
|
|
@@ -446,7 +449,6 @@ function withWatch(instance) {
|
|
|
446
449
|
watchers = void 0;
|
|
447
450
|
unsubscribe?.();
|
|
448
451
|
unsubscribe = void 0;
|
|
449
|
-
initialized = false;
|
|
450
452
|
prev = void 0;
|
|
451
453
|
instance.destroy();
|
|
452
454
|
};
|
|
@@ -464,14 +466,20 @@ function previous(source, options) {
|
|
|
464
466
|
const notifyListeners = () => {
|
|
465
467
|
listeners.notify(prev);
|
|
466
468
|
};
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
469
|
+
let unsubscribe;
|
|
470
|
+
try {
|
|
471
|
+
unsubscribe = source.subscribe((next) => {
|
|
472
|
+
const old = prev;
|
|
473
|
+
prev = current;
|
|
474
|
+
current = next;
|
|
475
|
+
if (old !== prev) {
|
|
476
|
+
notify(notifyListeners);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
} catch {
|
|
480
|
+
listeners.clear();
|
|
481
|
+
throw new Error(`[gjendje] previous(): source.subscribe() threw for "${instanceKey}".`);
|
|
482
|
+
}
|
|
475
483
|
const lazyDestroyed = createLazyDestroyed();
|
|
476
484
|
return {
|
|
477
485
|
key: instanceKey,
|
|
@@ -501,7 +509,7 @@ function previous(source, options) {
|
|
|
501
509
|
destroy() {
|
|
502
510
|
if (isDestroyed) return;
|
|
503
511
|
isDestroyed = true;
|
|
504
|
-
unsubscribe();
|
|
512
|
+
unsubscribe?.();
|
|
505
513
|
listeners.clear();
|
|
506
514
|
lazyDestroyed.resolve();
|
|
507
515
|
}
|
|
@@ -519,10 +527,104 @@ function readonly(instance) {
|
|
|
519
527
|
|
|
520
528
|
// src/select.ts
|
|
521
529
|
var selectCounter = 0;
|
|
530
|
+
function callSelector(fn, value, key) {
|
|
531
|
+
try {
|
|
532
|
+
return fn(value);
|
|
533
|
+
} catch (err) {
|
|
534
|
+
const wrapped = new ComputedError(key, "memory", err);
|
|
535
|
+
reportError(key, "memory", wrapped);
|
|
536
|
+
throw wrapped;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
522
539
|
function select(source, fn, options) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
540
|
+
const instanceKey = options?.key ?? `select:${selectCounter++}`;
|
|
541
|
+
const listenerSet = /* @__PURE__ */ new Set();
|
|
542
|
+
let singleListener;
|
|
543
|
+
let listenerCount = 0;
|
|
544
|
+
let cached;
|
|
545
|
+
let isDirty = true;
|
|
546
|
+
let isDestroyed = false;
|
|
547
|
+
const lazyDestroyed = createLazyDestroyed();
|
|
548
|
+
function recompute() {
|
|
549
|
+
if (!isDirty) return cached;
|
|
550
|
+
cached = callSelector(fn, source.get(), instanceKey);
|
|
551
|
+
isDirty = false;
|
|
552
|
+
return cached;
|
|
553
|
+
}
|
|
554
|
+
const notifyListeners = () => {
|
|
555
|
+
if (isDestroyed) return;
|
|
556
|
+
const prev = cached;
|
|
557
|
+
const value = recompute();
|
|
558
|
+
if (value === prev) return;
|
|
559
|
+
if (singleListener !== void 0) {
|
|
560
|
+
safeCall(singleListener, value, instanceKey, "memory");
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
for (const l of listenerSet) {
|
|
564
|
+
safeCall(l, value, instanceKey, "memory");
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
const markDirty = () => {
|
|
568
|
+
if (isDestroyed) return;
|
|
569
|
+
isDirty = true;
|
|
570
|
+
notify(notifyListeners);
|
|
571
|
+
};
|
|
572
|
+
const unsub = source.subscribe(markDirty);
|
|
573
|
+
recompute();
|
|
574
|
+
return {
|
|
575
|
+
key: instanceKey,
|
|
576
|
+
scope: "memory",
|
|
577
|
+
get ready() {
|
|
578
|
+
return source.ready;
|
|
579
|
+
},
|
|
580
|
+
get settled() {
|
|
581
|
+
return source.settled;
|
|
582
|
+
},
|
|
583
|
+
get hydrated() {
|
|
584
|
+
return source.hydrated;
|
|
585
|
+
},
|
|
586
|
+
get destroyed() {
|
|
587
|
+
if (isDestroyed) return RESOLVED;
|
|
588
|
+
return lazyDestroyed.promise;
|
|
589
|
+
},
|
|
590
|
+
get isDestroyed() {
|
|
591
|
+
return isDestroyed;
|
|
592
|
+
},
|
|
593
|
+
get() {
|
|
594
|
+
return recompute();
|
|
595
|
+
},
|
|
596
|
+
peek() {
|
|
597
|
+
return cached;
|
|
598
|
+
},
|
|
599
|
+
subscribe(listener) {
|
|
600
|
+
if (isDestroyed) return () => {
|
|
601
|
+
};
|
|
602
|
+
listenerSet.add(listener);
|
|
603
|
+
listenerCount++;
|
|
604
|
+
singleListener = listenerCount === 1 ? listener : void 0;
|
|
605
|
+
return () => {
|
|
606
|
+
listenerSet.delete(listener);
|
|
607
|
+
listenerCount--;
|
|
608
|
+
if (listenerCount === 1) {
|
|
609
|
+
singleListener = listenerSet.values().next().value;
|
|
610
|
+
} else {
|
|
611
|
+
singleListener = void 0;
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
},
|
|
615
|
+
destroy() {
|
|
616
|
+
if (isDestroyed) return;
|
|
617
|
+
isDestroyed = true;
|
|
618
|
+
try {
|
|
619
|
+
unsub();
|
|
620
|
+
listenerSet.clear();
|
|
621
|
+
listenerCount = 0;
|
|
622
|
+
singleListener = void 0;
|
|
623
|
+
} finally {
|
|
624
|
+
lazyDestroyed.resolve();
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
};
|
|
526
628
|
}
|
|
527
629
|
|
|
528
630
|
// src/shortcuts.ts
|
package/dist/server.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkFD2LRNLT_cjs = require('./chunk-FD2LRNLT.cjs');
|
|
4
4
|
var chunk3K5IERQC_cjs = require('./chunk-3K5IERQC.cjs');
|
|
5
5
|
var async_hooks = require('async_hooks');
|
|
6
6
|
|
|
@@ -32,7 +32,7 @@ function createServerAdapter(key, defaultValue) {
|
|
|
32
32
|
}
|
|
33
33
|
store.set(key, value);
|
|
34
34
|
lastNotifiedValue = value;
|
|
35
|
-
|
|
35
|
+
chunkFD2LRNLT_cjs.notify(notifyListeners);
|
|
36
36
|
},
|
|
37
37
|
subscribe: listeners.subscribe,
|
|
38
38
|
destroy() {
|
|
@@ -40,7 +40,7 @@ function createServerAdapter(key, defaultValue) {
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
chunkFD2LRNLT_cjs.registerServerAdapter(createServerAdapter);
|
|
44
44
|
|
|
45
45
|
exports.createServerAdapter = createServerAdapter;
|
|
46
46
|
exports.withServerSession = withServerSession;
|
package/dist/server.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gjendje",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"description": "Storage-agnostic state management library for TypeScript and JavaScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state",
|
|
@@ -104,7 +104,6 @@
|
|
|
104
104
|
"devDependencies": {
|
|
105
105
|
"@biomejs/biome": "^2.4.6",
|
|
106
106
|
"@changesets/cli": "^2.27.0",
|
|
107
|
-
"@size-limit/preset-small-lib": "^11.0.0",
|
|
108
107
|
"@testing-library/react": "^16.3.2",
|
|
109
108
|
"@types/node": "^20.0.0",
|
|
110
109
|
"@types/react": "^19.2.14",
|
|
@@ -116,7 +115,6 @@
|
|
|
116
115
|
"publint": "^0.3.0",
|
|
117
116
|
"react": "^19.2.4",
|
|
118
117
|
"react-dom": "^19.2.4",
|
|
119
|
-
"size-limit": "^11.0.0",
|
|
120
118
|
"tinybench": "^6.0.0",
|
|
121
119
|
"tsup": "^8.0.0",
|
|
122
120
|
"tsx": "^4.21.0",
|
|
@@ -133,16 +131,31 @@
|
|
|
133
131
|
"lint:check": "biome ci src/ __tests__/",
|
|
134
132
|
"lint:fix": "biome check src/ __tests__/ --fix",
|
|
135
133
|
"release": "pnpm build && pnpm changeset publish",
|
|
136
|
-
"size": "size-limit",
|
|
137
134
|
"test": "vitest run",
|
|
138
135
|
"test:coverage": "vitest run --coverage",
|
|
139
136
|
"test:watch": "vitest",
|
|
140
137
|
"typecheck": "tsc --project tsconfig.test.json --skipLibCheck",
|
|
141
138
|
"bench:setup": "pnpm add -D tsx zustand valtio",
|
|
142
139
|
"bench": "tsx benchmarks/state-management.bench.ts",
|
|
143
|
-
"bench:
|
|
144
|
-
"bench:
|
|
145
|
-
"bench:
|
|
146
|
-
"bench:
|
|
140
|
+
"bench:compare": "tsx benchmarks/edge-cases-comparison.bench.ts",
|
|
141
|
+
"bench:storage": "tsx benchmarks/storage-read.bench.ts",
|
|
142
|
+
"bench:url": "tsx benchmarks/url-read.bench.ts",
|
|
143
|
+
"bench:internal": "tsx benchmarks/internal/index.ts",
|
|
144
|
+
"bench:internal:lifecycle": "tsx benchmarks/internal/lifecycle.bench.ts",
|
|
145
|
+
"bench:internal:state-write": "tsx benchmarks/internal/state-write.bench.ts",
|
|
146
|
+
"bench:internal:computed": "tsx benchmarks/internal/computed.bench.ts",
|
|
147
|
+
"bench:internal:select": "tsx benchmarks/internal/select.bench.ts",
|
|
148
|
+
"bench:internal:effect": "tsx benchmarks/internal/effect.bench.ts",
|
|
149
|
+
"bench:internal:batch": "tsx benchmarks/internal/batch.bench.ts",
|
|
150
|
+
"bench:internal:collection": "tsx benchmarks/internal/collection.bench.ts",
|
|
151
|
+
"bench:internal:middleware": "tsx benchmarks/internal/middleware.bench.ts",
|
|
152
|
+
"bench:internal:subscription": "tsx benchmarks/internal/subscription.bench.ts",
|
|
153
|
+
"bench:internal:history": "tsx benchmarks/internal/history.bench.ts",
|
|
154
|
+
"bench:internal:readonly": "tsx benchmarks/internal/readonly.bench.ts",
|
|
155
|
+
"bench:internal:patch": "tsx benchmarks/internal/patch.bench.ts",
|
|
156
|
+
"bench:internal:registry": "tsx benchmarks/internal/registry.bench.ts",
|
|
157
|
+
"bench:internal:persist": "tsx benchmarks/internal/persist.bench.ts",
|
|
158
|
+
"bench:internal:read-cost": "tsx benchmarks/internal/read-cost.bench.ts",
|
|
159
|
+
"bench:internal:utilities": "tsx benchmarks/internal/utilities.bench.ts"
|
|
147
160
|
}
|
|
148
161
|
}
|