gjendje 1.0.1 → 1.0.3
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-QSE3476L.js → chunk-ALDPHYTI.js} +246 -145
- package/dist/{chunk-AYE2CZGI.cjs → chunk-MPNZGKMR.cjs} +246 -144
- package/dist/index.cjs +48 -58
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +29 -39
- package/dist/server.cjs +4 -4
- package/dist/server.js +1 -1
- package/package.json +1 -1
|
@@ -46,8 +46,15 @@ function flush() {
|
|
|
46
46
|
|
|
47
47
|
// src/config.ts
|
|
48
48
|
var globalConfig = {};
|
|
49
|
+
var PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "session", "bucket"]);
|
|
49
50
|
function configure(config) {
|
|
50
51
|
globalConfig = { ...globalConfig, ...config };
|
|
52
|
+
if (globalConfig.registry === false && globalConfig.scope && PERSISTENT_SCOPES.has(globalConfig.scope)) {
|
|
53
|
+
log(
|
|
54
|
+
"warn",
|
|
55
|
+
`registry: false has no effect on scope "${globalConfig.scope}" \u2014 persistent scopes always use the registry.`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
51
58
|
}
|
|
52
59
|
function getConfig() {
|
|
53
60
|
return globalConfig;
|
|
@@ -65,6 +72,7 @@ function reportError(key, scope, error) {
|
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
// src/utils.ts
|
|
75
|
+
var RESOLVED = Promise.resolve();
|
|
68
76
|
function isRecord(value) {
|
|
69
77
|
return value !== null && typeof value === "object";
|
|
70
78
|
}
|
|
@@ -116,16 +124,19 @@ function createLazyDestroyed() {
|
|
|
116
124
|
}
|
|
117
125
|
|
|
118
126
|
// src/listeners.ts
|
|
127
|
+
function safeCall(listener, value) {
|
|
128
|
+
try {
|
|
129
|
+
listener(value);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error("[gjendje] Listener threw:", err);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
119
134
|
function createListeners() {
|
|
120
135
|
const set = /* @__PURE__ */ new Set();
|
|
121
136
|
return {
|
|
122
137
|
notify(value) {
|
|
123
138
|
for (const listener of set) {
|
|
124
|
-
|
|
125
|
-
listener(value);
|
|
126
|
-
} catch (err) {
|
|
127
|
-
console.error("[gjendje] Listener threw:", err);
|
|
128
|
-
}
|
|
139
|
+
safeCall(listener, value);
|
|
129
140
|
}
|
|
130
141
|
},
|
|
131
142
|
subscribe(listener) {
|
|
@@ -148,14 +159,9 @@ var registry = /* @__PURE__ */ new Map();
|
|
|
148
159
|
function getRegistered(rKey) {
|
|
149
160
|
return registry.get(rKey);
|
|
150
161
|
}
|
|
151
|
-
function
|
|
152
|
-
const existing = registry.get(rKey);
|
|
162
|
+
function registerNew(rKey, key, scope, instance, config, existing) {
|
|
153
163
|
if (existing !== void 0) {
|
|
154
|
-
|
|
155
|
-
registry.set(rKey, instance);
|
|
156
|
-
} else if (config.warnOnDuplicate) {
|
|
157
|
-
log("warn", `Duplicate state("${key}") with scope "${scope}". Returning cached instance.`);
|
|
158
|
-
}
|
|
164
|
+
registry.set(rKey, instance);
|
|
159
165
|
return;
|
|
160
166
|
}
|
|
161
167
|
if (config.maxKeys !== void 0 && registry.size >= config.maxKeys) {
|
|
@@ -218,7 +224,6 @@ function readAndMigrate(raw, options, key, scope) {
|
|
|
218
224
|
storedVersion = parsed.v;
|
|
219
225
|
data = parsed.data;
|
|
220
226
|
} else {
|
|
221
|
-
storedVersion = 1;
|
|
222
227
|
data = parsed;
|
|
223
228
|
}
|
|
224
229
|
if (storedVersion < currentVersion && options.migrate) {
|
|
@@ -329,8 +334,8 @@ function createStorageAdapter(storage, key, options) {
|
|
|
329
334
|
const toStore = pickKeys(value, persist);
|
|
330
335
|
const raw = serialize ? serialize.stringify(toStore) : wrapForStorage(toStore, version);
|
|
331
336
|
storage.setItem(key, raw);
|
|
332
|
-
cachedRaw =
|
|
333
|
-
cachedValue =
|
|
337
|
+
cachedRaw = raw;
|
|
338
|
+
cachedValue = persist ? mergeKeys(toStore, defaultValue, persist) : value;
|
|
334
339
|
} catch (e) {
|
|
335
340
|
cachedRaw = void 0;
|
|
336
341
|
cachedValue = void 0;
|
|
@@ -357,7 +362,7 @@ function createStorageAdapter(storage, key, options) {
|
|
|
357
362
|
window.addEventListener("storage", onStorageEvent);
|
|
358
363
|
}
|
|
359
364
|
return {
|
|
360
|
-
ready:
|
|
365
|
+
ready: RESOLVED,
|
|
361
366
|
get() {
|
|
362
367
|
return read();
|
|
363
368
|
},
|
|
@@ -506,17 +511,12 @@ function createBucketAdapter(key, bucketOptions, options) {
|
|
|
506
511
|
}
|
|
507
512
|
|
|
508
513
|
// src/adapters/memory.ts
|
|
509
|
-
var RESOLVED = Promise.resolve();
|
|
510
514
|
function createMemoryAdapter(defaultValue) {
|
|
511
515
|
let current = defaultValue;
|
|
512
516
|
const listeners = /* @__PURE__ */ new Set();
|
|
513
517
|
const notifyListeners = () => {
|
|
514
518
|
for (const listener of listeners) {
|
|
515
|
-
|
|
516
|
-
listener(current);
|
|
517
|
-
} catch (err) {
|
|
518
|
-
console.error("[gjendje] Listener threw:", err);
|
|
519
|
-
}
|
|
519
|
+
safeCall(listener, current);
|
|
520
520
|
}
|
|
521
521
|
};
|
|
522
522
|
return {
|
|
@@ -553,8 +553,8 @@ function withSync(adapter, key, scope) {
|
|
|
553
553
|
channel.onmessage = (event) => {
|
|
554
554
|
if (isDestroyed) return;
|
|
555
555
|
const msg = event.data;
|
|
556
|
-
if (msg == null || typeof msg !== "object" || !("value" in msg))
|
|
557
|
-
|
|
556
|
+
if (msg == null || typeof msg !== "object" || !("value" in msg) || Object.keys(msg).length !== 1)
|
|
557
|
+
return;
|
|
558
558
|
const value = msg.value;
|
|
559
559
|
try {
|
|
560
560
|
adapter.set(value);
|
|
@@ -603,12 +603,23 @@ function createUrlAdapter(key, defaultValue, serializer, persist) {
|
|
|
603
603
|
}
|
|
604
604
|
const listeners = createListeners();
|
|
605
605
|
const defaultSerialized = serializer.stringify(defaultValue);
|
|
606
|
+
let cachedSearch;
|
|
607
|
+
let cachedValue = defaultValue;
|
|
606
608
|
function read() {
|
|
607
609
|
try {
|
|
608
|
-
const
|
|
610
|
+
const search = window.location.search;
|
|
611
|
+
if (search === cachedSearch) return cachedValue;
|
|
612
|
+
const params = new URLSearchParams(search);
|
|
609
613
|
const raw = params.get(key);
|
|
610
|
-
if (raw === null)
|
|
611
|
-
|
|
614
|
+
if (raw === null) {
|
|
615
|
+
cachedSearch = search;
|
|
616
|
+
cachedValue = defaultValue;
|
|
617
|
+
return defaultValue;
|
|
618
|
+
}
|
|
619
|
+
const value = mergeKeys(serializer.parse(raw), defaultValue, persist);
|
|
620
|
+
cachedSearch = search;
|
|
621
|
+
cachedValue = value;
|
|
622
|
+
return value;
|
|
612
623
|
} catch {
|
|
613
624
|
return defaultValue;
|
|
614
625
|
}
|
|
@@ -627,18 +638,22 @@ function createUrlAdapter(key, defaultValue, serializer, persist) {
|
|
|
627
638
|
const search = params.toString();
|
|
628
639
|
const newUrl = search ? `${window.location.pathname}?${search}${window.location.hash}` : `${window.location.pathname}${window.location.hash}`;
|
|
629
640
|
window.history.pushState(null, "", newUrl);
|
|
641
|
+
cachedSearch = search ? `?${search}` : "";
|
|
642
|
+
cachedValue = persist ? mergeKeys(toStore, defaultValue, persist) : value;
|
|
630
643
|
} catch {
|
|
644
|
+
cachedSearch = void 0;
|
|
631
645
|
}
|
|
632
646
|
}
|
|
633
647
|
let lastNotifiedValue = defaultValue;
|
|
634
648
|
const notifyListeners = () => listeners.notify(lastNotifiedValue);
|
|
635
649
|
function onPopState() {
|
|
650
|
+
cachedSearch = void 0;
|
|
636
651
|
lastNotifiedValue = read();
|
|
637
652
|
notify(notifyListeners);
|
|
638
653
|
}
|
|
639
654
|
window.addEventListener("popstate", onPopState);
|
|
640
655
|
return {
|
|
641
|
-
ready:
|
|
656
|
+
ready: RESOLVED,
|
|
642
657
|
get() {
|
|
643
658
|
return read();
|
|
644
659
|
},
|
|
@@ -661,7 +676,7 @@ function isServer() {
|
|
|
661
676
|
}
|
|
662
677
|
var BROWSER_SCOPES = /* @__PURE__ */ new Set(["session", "local", "url", "bucket"]);
|
|
663
678
|
function afterHydration(fn) {
|
|
664
|
-
if (isServer()) return
|
|
679
|
+
if (isServer()) return RESOLVED;
|
|
665
680
|
return new Promise((resolve) => {
|
|
666
681
|
Promise.resolve().then(() => {
|
|
667
682
|
if (typeof requestAnimationFrame !== "undefined") {
|
|
@@ -684,11 +699,10 @@ var _serverAdapterFactory;
|
|
|
684
699
|
function registerServerAdapter(factory) {
|
|
685
700
|
_serverAdapterFactory = factory;
|
|
686
701
|
}
|
|
687
|
-
var
|
|
702
|
+
var PERSISTENT_SCOPES2 = /* @__PURE__ */ new Set(["local", "session", "bucket"]);
|
|
688
703
|
var SYNCABLE_SCOPES = /* @__PURE__ */ new Set(["local", "bucket"]);
|
|
689
|
-
var RESOLVED2 = Promise.resolve();
|
|
690
704
|
var MEMORY_SHIM = {
|
|
691
|
-
ready:
|
|
705
|
+
ready: RESOLVED,
|
|
692
706
|
get: () => void 0,
|
|
693
707
|
set: () => {
|
|
694
708
|
},
|
|
@@ -723,10 +737,7 @@ function resolveAdapter(storageKey, scope, options) {
|
|
|
723
737
|
return createUrlAdapter(
|
|
724
738
|
storageKey,
|
|
725
739
|
options.default,
|
|
726
|
-
options.serialize ?? {
|
|
727
|
-
stringify: (v) => JSON.stringify(v),
|
|
728
|
-
parse: (s) => JSON.parse(s)
|
|
729
|
-
},
|
|
740
|
+
options.serialize ?? { stringify: JSON.stringify, parse: JSON.parse },
|
|
730
741
|
options.persist
|
|
731
742
|
);
|
|
732
743
|
case "server":
|
|
@@ -759,7 +770,7 @@ var StateImpl = class {
|
|
|
759
770
|
_rKey;
|
|
760
771
|
_config;
|
|
761
772
|
_s;
|
|
762
|
-
constructor(key, scope, rKey, adapter, options, config) {
|
|
773
|
+
constructor(key, scope, rKey, adapter, options, config, preallocatedState) {
|
|
763
774
|
this.key = key;
|
|
764
775
|
this.scope = scope;
|
|
765
776
|
this._rKey = rKey;
|
|
@@ -767,12 +778,12 @@ var StateImpl = class {
|
|
|
767
778
|
this._defaultValue = options.default;
|
|
768
779
|
this._options = options;
|
|
769
780
|
this._config = config;
|
|
770
|
-
this._s = {
|
|
781
|
+
this._s = preallocatedState ?? {
|
|
771
782
|
lastValue: adapter.get(),
|
|
772
783
|
isDestroyed: false,
|
|
773
784
|
interceptors: void 0,
|
|
774
785
|
changeHandlers: void 0,
|
|
775
|
-
settled:
|
|
786
|
+
settled: RESOLVED,
|
|
776
787
|
resolveDestroyed: void 0,
|
|
777
788
|
destroyed: void 0,
|
|
778
789
|
hydrated: void 0,
|
|
@@ -847,7 +858,7 @@ var StateImpl = class {
|
|
|
847
858
|
return this._s.settled;
|
|
848
859
|
}
|
|
849
860
|
get hydrated() {
|
|
850
|
-
return this._s.hydrated ??
|
|
861
|
+
return this._s.hydrated ?? RESOLVED;
|
|
851
862
|
}
|
|
852
863
|
get destroyed() {
|
|
853
864
|
const s = this._s;
|
|
@@ -917,7 +928,7 @@ var StateImpl = class {
|
|
|
917
928
|
if (s.resolveDestroyed) {
|
|
918
929
|
s.resolveDestroyed();
|
|
919
930
|
} else {
|
|
920
|
-
s.destroyed =
|
|
931
|
+
s.destroyed = RESOLVED;
|
|
921
932
|
}
|
|
922
933
|
}
|
|
923
934
|
_ensureWatchSubscription() {
|
|
@@ -932,33 +943,70 @@ var StateImpl = class {
|
|
|
932
943
|
});
|
|
933
944
|
}
|
|
934
945
|
};
|
|
946
|
+
function getExt(c) {
|
|
947
|
+
if (c.ext === void 0) {
|
|
948
|
+
c.ext = {
|
|
949
|
+
interceptors: void 0,
|
|
950
|
+
changeHandlers: void 0,
|
|
951
|
+
watchers: void 0,
|
|
952
|
+
watchUnsub: void 0,
|
|
953
|
+
watchPrev: void 0,
|
|
954
|
+
resolveDestroyed: void 0,
|
|
955
|
+
destroyed: void 0
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
return c.ext;
|
|
959
|
+
}
|
|
960
|
+
var MEMORY_MUTABLE_SHIM = {
|
|
961
|
+
lastValue: void 0,
|
|
962
|
+
isDestroyed: false,
|
|
963
|
+
interceptors: void 0,
|
|
964
|
+
changeHandlers: void 0,
|
|
965
|
+
settled: RESOLVED,
|
|
966
|
+
resolveDestroyed: void 0,
|
|
967
|
+
destroyed: void 0,
|
|
968
|
+
hydrated: void 0,
|
|
969
|
+
watchers: void 0,
|
|
970
|
+
watchUnsub: void 0,
|
|
971
|
+
watchPrev: void 0
|
|
972
|
+
};
|
|
935
973
|
var MemoryStateImpl = class extends StateImpl {
|
|
936
|
-
|
|
937
|
-
_r;
|
|
974
|
+
_c;
|
|
938
975
|
_hasIsEqual;
|
|
939
976
|
constructor(key, rKey, options, config) {
|
|
940
|
-
super(
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
977
|
+
super(
|
|
978
|
+
key,
|
|
979
|
+
"memory",
|
|
980
|
+
rKey,
|
|
981
|
+
MEMORY_SHIM,
|
|
982
|
+
options,
|
|
983
|
+
config,
|
|
984
|
+
MEMORY_MUTABLE_SHIM
|
|
985
|
+
);
|
|
986
|
+
this._c = {
|
|
987
|
+
current: options.default,
|
|
988
|
+
isDestroyed: false,
|
|
989
|
+
listeners: void 0,
|
|
990
|
+
notifyFn: void 0,
|
|
991
|
+
ext: void 0
|
|
992
|
+
};
|
|
946
993
|
this._hasIsEqual = options.isEqual !== void 0;
|
|
947
994
|
}
|
|
948
995
|
get() {
|
|
949
|
-
return this.
|
|
996
|
+
return this._c.current;
|
|
950
997
|
}
|
|
951
998
|
peek() {
|
|
952
|
-
return this.
|
|
999
|
+
return this._c.current;
|
|
953
1000
|
}
|
|
954
1001
|
set(valueOrUpdater) {
|
|
955
|
-
const
|
|
956
|
-
if (
|
|
957
|
-
const prev =
|
|
1002
|
+
const c = this._c;
|
|
1003
|
+
if (c.isDestroyed) return;
|
|
1004
|
+
const prev = c.current;
|
|
958
1005
|
let next = typeof valueOrUpdater === "function" ? valueOrUpdater(prev) : valueOrUpdater;
|
|
959
|
-
|
|
1006
|
+
const ext = c.ext;
|
|
1007
|
+
if (ext !== void 0 && ext.interceptors !== void 0 && ext.interceptors.size > 0) {
|
|
960
1008
|
const original = next;
|
|
961
|
-
for (const interceptor of
|
|
1009
|
+
for (const interceptor of ext.interceptors) {
|
|
962
1010
|
next = interceptor(next, prev);
|
|
963
1011
|
}
|
|
964
1012
|
if (!Object.is(original, next)) {
|
|
@@ -971,46 +1019,43 @@ var MemoryStateImpl = class extends StateImpl {
|
|
|
971
1019
|
}
|
|
972
1020
|
}
|
|
973
1021
|
if (this._hasIsEqual && this._options.isEqual?.(next, prev)) return;
|
|
974
|
-
|
|
975
|
-
if (
|
|
976
|
-
notify(
|
|
1022
|
+
c.current = next;
|
|
1023
|
+
if (c.notifyFn !== void 0) {
|
|
1024
|
+
notify(c.notifyFn);
|
|
977
1025
|
}
|
|
978
|
-
if (
|
|
979
|
-
for (const hook of
|
|
1026
|
+
if (ext !== void 0 && ext.changeHandlers !== void 0 && ext.changeHandlers.size > 0) {
|
|
1027
|
+
for (const hook of ext.changeHandlers) {
|
|
980
1028
|
hook(next, prev);
|
|
981
1029
|
}
|
|
982
1030
|
}
|
|
983
1031
|
this._config.onChange?.({ key: this.key, scope: this.scope, value: next, previousValue: prev });
|
|
984
1032
|
}
|
|
985
1033
|
subscribe(listener) {
|
|
986
|
-
const
|
|
987
|
-
if (!
|
|
1034
|
+
const c = this._c;
|
|
1035
|
+
if (!c.listeners) {
|
|
988
1036
|
const listeners = /* @__PURE__ */ new Set();
|
|
989
|
-
|
|
990
|
-
|
|
1037
|
+
c.listeners = listeners;
|
|
1038
|
+
c.notifyFn = () => {
|
|
991
1039
|
for (const l of listeners) {
|
|
992
|
-
|
|
993
|
-
l(s.current);
|
|
994
|
-
} catch (err) {
|
|
995
|
-
console.error("[gjendje] Listener threw:", err);
|
|
996
|
-
}
|
|
1040
|
+
safeCall(l, c.current);
|
|
997
1041
|
}
|
|
998
1042
|
};
|
|
999
1043
|
}
|
|
1000
|
-
const set =
|
|
1044
|
+
const set = c.listeners;
|
|
1001
1045
|
set.add(listener);
|
|
1002
1046
|
return () => {
|
|
1003
1047
|
set.delete(listener);
|
|
1004
1048
|
};
|
|
1005
1049
|
}
|
|
1006
1050
|
reset() {
|
|
1007
|
-
const
|
|
1008
|
-
if (
|
|
1009
|
-
const prev =
|
|
1051
|
+
const c = this._c;
|
|
1052
|
+
if (c.isDestroyed) return;
|
|
1053
|
+
const prev = c.current;
|
|
1010
1054
|
let next = this._defaultValue;
|
|
1011
|
-
|
|
1055
|
+
const ext = c.ext;
|
|
1056
|
+
if (ext !== void 0 && ext.interceptors !== void 0 && ext.interceptors.size > 0) {
|
|
1012
1057
|
const original = next;
|
|
1013
|
-
for (const interceptor of
|
|
1058
|
+
for (const interceptor of ext.interceptors) {
|
|
1014
1059
|
next = interceptor(next, prev);
|
|
1015
1060
|
}
|
|
1016
1061
|
if (!Object.is(original, next)) {
|
|
@@ -1023,12 +1068,12 @@ var MemoryStateImpl = class extends StateImpl {
|
|
|
1023
1068
|
}
|
|
1024
1069
|
}
|
|
1025
1070
|
if (this._hasIsEqual && this._options.isEqual?.(next, prev)) return;
|
|
1026
|
-
|
|
1027
|
-
if (
|
|
1028
|
-
notify(
|
|
1071
|
+
c.current = next;
|
|
1072
|
+
if (c.notifyFn !== void 0) {
|
|
1073
|
+
notify(c.notifyFn);
|
|
1029
1074
|
}
|
|
1030
|
-
if (
|
|
1031
|
-
for (const hook of
|
|
1075
|
+
if (ext !== void 0 && ext.changeHandlers !== void 0 && ext.changeHandlers.size > 0) {
|
|
1076
|
+
for (const hook of ext.changeHandlers) {
|
|
1032
1077
|
hook(next, prev);
|
|
1033
1078
|
}
|
|
1034
1079
|
}
|
|
@@ -1036,39 +1081,82 @@ var MemoryStateImpl = class extends StateImpl {
|
|
|
1036
1081
|
this._config.onChange?.({ key: this.key, scope: this.scope, value: next, previousValue: prev });
|
|
1037
1082
|
}
|
|
1038
1083
|
get ready() {
|
|
1039
|
-
return
|
|
1084
|
+
return RESOLVED;
|
|
1085
|
+
}
|
|
1086
|
+
get settled() {
|
|
1087
|
+
return RESOLVED;
|
|
1088
|
+
}
|
|
1089
|
+
get hydrated() {
|
|
1090
|
+
return RESOLVED;
|
|
1091
|
+
}
|
|
1092
|
+
get isDestroyed() {
|
|
1093
|
+
return this._c.isDestroyed;
|
|
1094
|
+
}
|
|
1095
|
+
get destroyed() {
|
|
1096
|
+
if (this._c.isDestroyed) return RESOLVED;
|
|
1097
|
+
const ext = getExt(this._c);
|
|
1098
|
+
if (!ext.destroyed) {
|
|
1099
|
+
ext.destroyed = new Promise((resolve) => {
|
|
1100
|
+
ext.resolveDestroyed = resolve;
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
return ext.destroyed;
|
|
1104
|
+
}
|
|
1105
|
+
intercept(fn) {
|
|
1106
|
+
const ext = getExt(this._c);
|
|
1107
|
+
if (!ext.interceptors) ext.interceptors = /* @__PURE__ */ new Set();
|
|
1108
|
+
ext.interceptors.add(fn);
|
|
1109
|
+
return () => {
|
|
1110
|
+
ext.interceptors?.delete(fn);
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
onChange(fn) {
|
|
1114
|
+
const ext = getExt(this._c);
|
|
1115
|
+
if (!ext.changeHandlers) ext.changeHandlers = /* @__PURE__ */ new Set();
|
|
1116
|
+
ext.changeHandlers.add(fn);
|
|
1117
|
+
return () => {
|
|
1118
|
+
ext.changeHandlers?.delete(fn);
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
watch(watchKey, listener) {
|
|
1122
|
+
const ext = getExt(this._c);
|
|
1123
|
+
if (!ext.watchers) ext.watchers = /* @__PURE__ */ new Map();
|
|
1124
|
+
this._ensureWatchSubscription();
|
|
1125
|
+
return addWatcher(ext.watchers, watchKey, listener);
|
|
1040
1126
|
}
|
|
1041
1127
|
_ensureWatchSubscription() {
|
|
1042
|
-
const
|
|
1043
|
-
if (
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
if (
|
|
1047
|
-
notifyWatchers(
|
|
1128
|
+
const ext = getExt(this._c);
|
|
1129
|
+
if (ext.watchUnsub) return;
|
|
1130
|
+
ext.watchPrev = this._c.current;
|
|
1131
|
+
ext.watchUnsub = this.subscribe((next) => {
|
|
1132
|
+
if (ext.watchers && ext.watchers.size > 0) {
|
|
1133
|
+
notifyWatchers(ext.watchers, ext.watchPrev, next);
|
|
1048
1134
|
}
|
|
1049
|
-
|
|
1135
|
+
ext.watchPrev = next;
|
|
1050
1136
|
});
|
|
1051
1137
|
}
|
|
1052
1138
|
destroy() {
|
|
1053
|
-
const
|
|
1054
|
-
if (
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1139
|
+
const c = this._c;
|
|
1140
|
+
if (c.isDestroyed) return;
|
|
1141
|
+
c.isDestroyed = true;
|
|
1142
|
+
const ext = c.ext;
|
|
1143
|
+
if (ext !== void 0) {
|
|
1144
|
+
ext.interceptors?.clear();
|
|
1145
|
+
ext.changeHandlers?.clear();
|
|
1146
|
+
ext.watchers?.clear();
|
|
1147
|
+
ext.watchUnsub?.();
|
|
1148
|
+
}
|
|
1149
|
+
c.listeners?.clear();
|
|
1150
|
+
if (this._rKey) unregisterByKey(this._rKey);
|
|
1063
1151
|
this._config.onDestroy?.({ key: this.key, scope: this.scope });
|
|
1064
|
-
if (
|
|
1065
|
-
|
|
1066
|
-
} else {
|
|
1067
|
-
|
|
1152
|
+
if (ext?.resolveDestroyed) {
|
|
1153
|
+
ext.resolveDestroyed();
|
|
1154
|
+
} else if (ext !== void 0) {
|
|
1155
|
+
ext.destroyed = RESOLVED;
|
|
1068
1156
|
}
|
|
1069
1157
|
}
|
|
1070
1158
|
};
|
|
1071
|
-
function
|
|
1159
|
+
function createBase(key, options) {
|
|
1072
1160
|
if (!key) {
|
|
1073
1161
|
throw new Error("[gjendje] key must be a non-empty string.");
|
|
1074
1162
|
}
|
|
@@ -1080,19 +1168,37 @@ function resolveKeyAndScope(key, options) {
|
|
|
1080
1168
|
}
|
|
1081
1169
|
const rawScope = options.scope ?? config.scope ?? "memory";
|
|
1082
1170
|
const scope = rawScope === "render" ? "memory" : rawScope;
|
|
1171
|
+
if (scope === "memory") {
|
|
1172
|
+
if (options.sync || config.sync) {
|
|
1173
|
+
log(
|
|
1174
|
+
"warn",
|
|
1175
|
+
`sync: true is ignored for scope "memory". Only "local" and "bucket" scopes support cross-tab sync.`
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
if (config.registry === false) {
|
|
1179
|
+
return new MemoryStateImpl(key, "", options, config);
|
|
1180
|
+
}
|
|
1181
|
+
const rKey2 = scopedKey(key, scope);
|
|
1182
|
+
const existing2 = getRegistered(rKey2);
|
|
1183
|
+
if (existing2 && !existing2.isDestroyed) {
|
|
1184
|
+
if (config.warnOnDuplicate) {
|
|
1185
|
+
log("warn", `Duplicate state("${key}") with scope "${scope}". Returning cached instance.`);
|
|
1186
|
+
}
|
|
1187
|
+
return existing2;
|
|
1188
|
+
}
|
|
1189
|
+
const instance2 = new MemoryStateImpl(key, rKey2, options, config);
|
|
1190
|
+
registerNew(rKey2, key, scope, instance2, config, existing2);
|
|
1191
|
+
return instance2;
|
|
1192
|
+
}
|
|
1083
1193
|
const rKey = scopedKey(key, scope);
|
|
1084
1194
|
const existing = getRegistered(rKey);
|
|
1085
|
-
return { config, scope, rKey, existing };
|
|
1086
|
-
}
|
|
1087
|
-
function createBase(key, options) {
|
|
1088
|
-
const { config, scope, rKey, existing } = resolveKeyAndScope(key, options);
|
|
1089
1195
|
if (existing && !existing.isDestroyed) {
|
|
1090
1196
|
if (config.warnOnDuplicate) {
|
|
1091
1197
|
log("warn", `Duplicate state("${key}") with scope "${scope}". Returning cached instance.`);
|
|
1092
1198
|
}
|
|
1093
1199
|
return existing;
|
|
1094
1200
|
}
|
|
1095
|
-
if (config.requireValidation &&
|
|
1201
|
+
if (config.requireValidation && PERSISTENT_SCOPES2.has(scope) && !options.validate) {
|
|
1096
1202
|
throw new Error(
|
|
1097
1203
|
`[gjendje] A validate function is required for persisted scope "${scope}" on state("${key}"). Set requireValidation: false in configure() to disable.`
|
|
1098
1204
|
);
|
|
@@ -1106,44 +1212,39 @@ function createBase(key, options) {
|
|
|
1106
1212
|
`sync: true is ignored for scope "${scope}". Only "local" and "bucket" scopes support cross-tab sync.`
|
|
1107
1213
|
);
|
|
1108
1214
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
realAdapter = resolveAdapter(storageKey, scope, options);
|
|
1126
|
-
const storedValue = realAdapter.get();
|
|
1127
|
-
if (!shallowEqual(storedValue, options.default)) {
|
|
1128
|
-
instance.set(storedValue);
|
|
1129
|
-
}
|
|
1130
|
-
config.onHydrate?.({
|
|
1131
|
-
key,
|
|
1132
|
-
scope,
|
|
1133
|
-
serverValue: options.default,
|
|
1134
|
-
clientValue: storedValue
|
|
1135
|
-
});
|
|
1136
|
-
} catch (err) {
|
|
1137
|
-
log("debug", `Hydration adapter unavailable for state("${key}") \u2014 using memory fallback.`);
|
|
1138
|
-
reportError(key, scope, err);
|
|
1139
|
-
} finally {
|
|
1140
|
-
realAdapter?.destroy?.();
|
|
1215
|
+
const storageKey = resolveStorageKey(key, options, config.prefix);
|
|
1216
|
+
const baseAdapter = useMemoryFallback ? createMemoryAdapter(options.default) : resolveAdapter(storageKey, scope, options);
|
|
1217
|
+
const shouldSync = effectiveSync && SYNCABLE_SCOPES.has(scope) && !useMemoryFallback;
|
|
1218
|
+
const adapter = shouldSync ? withSync(baseAdapter, storageKey, scope) : baseAdapter;
|
|
1219
|
+
const instance = new StateImpl(key, scope, rKey, adapter, options, config);
|
|
1220
|
+
if (isSsrMode && !isServer()) {
|
|
1221
|
+
instance._s.hydrated = afterHydration(() => {
|
|
1222
|
+
if (instance.isDestroyed) return;
|
|
1223
|
+
const currentValue = instance.get();
|
|
1224
|
+
if (!shallowEqual(currentValue, options.default)) return;
|
|
1225
|
+
let realAdapter;
|
|
1226
|
+
try {
|
|
1227
|
+
realAdapter = resolveAdapter(storageKey, scope, options);
|
|
1228
|
+
const storedValue = realAdapter.get();
|
|
1229
|
+
if (!shallowEqual(storedValue, options.default)) {
|
|
1230
|
+
instance.set(storedValue);
|
|
1141
1231
|
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1232
|
+
config.onHydrate?.({
|
|
1233
|
+
key,
|
|
1234
|
+
scope,
|
|
1235
|
+
serverValue: options.default,
|
|
1236
|
+
clientValue: storedValue
|
|
1237
|
+
});
|
|
1238
|
+
} catch (err) {
|
|
1239
|
+
log("debug", `Hydration adapter unavailable for state("${key}") \u2014 using memory fallback.`);
|
|
1240
|
+
reportError(key, scope, err);
|
|
1241
|
+
} finally {
|
|
1242
|
+
realAdapter?.destroy?.();
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1144
1245
|
}
|
|
1145
|
-
|
|
1246
|
+
registerNew(rKey, key, scope, instance, config, existing);
|
|
1146
1247
|
return instance;
|
|
1147
1248
|
}
|
|
1148
1249
|
|
|
1149
|
-
export { addWatcher, batch, configure, createBase, createLazyDestroyed, createListeners, getRegistry, isRecord, notify, notifyWatchers, registerServerAdapter, shallowEqual };
|
|
1250
|
+
export { RESOLVED, addWatcher, batch, configure, createBase, createLazyDestroyed, createListeners, getRegistry, isRecord, notify, notifyWatchers, registerServerAdapter, shallowEqual };
|