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.
@@ -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
- try {
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 registerByKey(rKey, key, scope, instance, config) {
152
- const existing = registry.get(rKey);
162
+ function registerNew(rKey, key, scope, instance, config, existing) {
153
163
  if (existing !== void 0) {
154
- if (existing.isDestroyed) {
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 = void 0;
333
- cachedValue = void 0;
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: Promise.resolve(),
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
- try {
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)) return;
557
- if (Object.keys(msg).length !== 1) return;
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 params = new URLSearchParams(window.location.search);
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) return defaultValue;
611
- return mergeKeys(serializer.parse(raw), defaultValue, persist);
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: Promise.resolve(),
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 Promise.resolve();
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 PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "session", "bucket"]);
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: RESOLVED2,
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: RESOLVED2,
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 ?? RESOLVED2;
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 = RESOLVED2;
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
- // Direct reference — avoids a getter cast on every get()/set() call
937
- _r;
974
+ _c;
938
975
  _hasIsEqual;
939
976
  constructor(key, rKey, options, config) {
940
- super(key, "memory", rKey, MEMORY_SHIM, options, config);
941
- const rs = this._s;
942
- rs.current = options.default;
943
- rs.memoryListeners = void 0;
944
- rs.notifyFn = void 0;
945
- this._r = rs;
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._r.current;
996
+ return this._c.current;
950
997
  }
951
998
  peek() {
952
- return this._r.current;
999
+ return this._c.current;
953
1000
  }
954
1001
  set(valueOrUpdater) {
955
- const s = this._r;
956
- if (s.isDestroyed) return;
957
- const prev = s.current;
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
- if (s.interceptors !== void 0 && s.interceptors.size > 0) {
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 s.interceptors) {
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
- s.current = next;
975
- if (s.notifyFn !== void 0) {
976
- notify(s.notifyFn);
1022
+ c.current = next;
1023
+ if (c.notifyFn !== void 0) {
1024
+ notify(c.notifyFn);
977
1025
  }
978
- if (s.changeHandlers !== void 0 && s.changeHandlers.size > 0) {
979
- for (const hook of s.changeHandlers) {
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 s = this._r;
987
- if (!s.memoryListeners) {
1034
+ const c = this._c;
1035
+ if (!c.listeners) {
988
1036
  const listeners = /* @__PURE__ */ new Set();
989
- s.memoryListeners = listeners;
990
- s.notifyFn = () => {
1037
+ c.listeners = listeners;
1038
+ c.notifyFn = () => {
991
1039
  for (const l of listeners) {
992
- try {
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 = s.memoryListeners;
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 s = this._r;
1008
- if (s.isDestroyed) return;
1009
- const prev = s.current;
1051
+ const c = this._c;
1052
+ if (c.isDestroyed) return;
1053
+ const prev = c.current;
1010
1054
  let next = this._defaultValue;
1011
- if (s.interceptors !== void 0 && s.interceptors.size > 0) {
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 s.interceptors) {
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
- s.current = next;
1027
- if (s.notifyFn !== void 0) {
1028
- notify(s.notifyFn);
1071
+ c.current = next;
1072
+ if (c.notifyFn !== void 0) {
1073
+ notify(c.notifyFn);
1029
1074
  }
1030
- if (s.changeHandlers !== void 0 && s.changeHandlers.size > 0) {
1031
- for (const hook of s.changeHandlers) {
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 RESOLVED2;
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 s = this._r;
1043
- if (s.watchUnsub) return;
1044
- s.watchPrev = s.current;
1045
- s.watchUnsub = this.subscribe((next) => {
1046
- if (s.watchers && s.watchers.size > 0) {
1047
- notifyWatchers(s.watchers, s.watchPrev, next);
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
- s.watchPrev = next;
1135
+ ext.watchPrev = next;
1050
1136
  });
1051
1137
  }
1052
1138
  destroy() {
1053
- const s = this._r;
1054
- if (s.isDestroyed) return;
1055
- s.lastValue = s.current;
1056
- s.isDestroyed = true;
1057
- s.interceptors?.clear();
1058
- s.changeHandlers?.clear();
1059
- s.watchers?.clear();
1060
- s.watchUnsub?.();
1061
- s.memoryListeners?.clear();
1062
- unregisterByKey(this._rKey);
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 (s.resolveDestroyed) {
1065
- s.resolveDestroyed();
1066
- } else {
1067
- s.destroyed = RESOLVED2;
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 resolveKeyAndScope(key, options) {
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 && PERSISTENT_SCOPES.has(scope) && !options.validate) {
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
- let instance;
1110
- if (scope === "memory" && !isSsrMode) {
1111
- instance = new MemoryStateImpl(key, rKey, options, config);
1112
- } else {
1113
- const storageKey = resolveStorageKey(key, options, config.prefix);
1114
- const baseAdapter = useMemoryFallback ? createMemoryAdapter(options.default) : resolveAdapter(storageKey, scope, options);
1115
- const shouldSync = effectiveSync && SYNCABLE_SCOPES.has(scope) && !useMemoryFallback;
1116
- const adapter = shouldSync ? withSync(baseAdapter, storageKey, scope) : baseAdapter;
1117
- instance = new StateImpl(key, scope, rKey, adapter, options, config);
1118
- if (isSsrMode && !isServer()) {
1119
- instance._s.hydrated = afterHydration(() => {
1120
- if (instance.isDestroyed) return;
1121
- const currentValue = instance.get();
1122
- if (!shallowEqual(currentValue, options.default)) return;
1123
- let realAdapter;
1124
- try {
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
- registerByKey(rKey, key, scope, instance, config);
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 };