gjendje 0.9.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,12 @@
2
2
 
3
3
  # gjendje
4
4
 
5
- Every app juggles localStorage, URL params, sessionStorage, and in-memory state. **gjendje** replaces storage backends with a unified API. Choose where state lives. The rest is handled.
5
+ Replaces storage backends with a unified API. Choose where state lives. The rest is handled.
6
+
7
+ - Zero runtime dependencies
8
+ - ~5 kB core (minified + brotli)
9
+ - TypeScript-first with full type inference
10
+ - 6 storage backends, one API
6
11
 
7
12
  ## Install
8
13
 
@@ -15,113 +20,44 @@ npm install gjendje
15
20
  ```ts
16
21
  import { state } from 'gjendje'
17
22
 
18
- // Pass scope as an option
19
- const theme = state({ theme: 'light' }, { scope: 'local' })
20
-
21
- // Or use dot notation
22
- const theme = state.local({ theme: 'light' })
23
- ```
23
+ const store = state({ count: 0 })
24
24
 
25
- For in-memory state that doesn't persist, use `state` without a scope:
25
+ function increment() {
26
+ store.set((prev) => ({ ...prev, count: prev.count + 1 }))
27
+ }
26
28
 
27
- ```ts
28
- const user = state({ name: 'John', age: 30 })
29
+ const { counter} = store.get()
29
30
  ```
30
31
 
31
- ### Getting values
32
-
33
- ```ts
34
- user.get() // { name: 'John', age: 30 }
35
- const { name } = user.get() // Destructure specific values
36
- ```
37
-
38
- ### Updating values
39
-
40
- Replace the entire state with `set`, or use an updater function:
41
-
42
- ```ts
43
- user.set({ name: 'Jane', age: 25 })
44
- user.set((prev) => ({ ...prev, age: prev.age + 1 }))
45
- ```
46
-
47
- For object stores, `patch` lets you update specific properties without spreading:
48
-
49
- ```ts
50
- const form = state({ name: '', email: '', age: 0 })
51
-
52
- form.patch({ name: 'Alice' }) // Only updates name
53
- form.patch({ name: 'Bob', age: 30 }) // Update multiple properties at once
54
- ```
32
+ [Examples](https://github.com/charliebeckstrand/gjendje/blob/main/docs/examples.md)
55
33
 
56
- [More examples](https://github.com/charliebeckstrand/gjendje/blob/main/docs/examples.md)
34
+ ## Configure
57
35
 
58
- ## Configure
59
-
60
- Call once at app initialization. Sets global defaults for all state instances.
61
-
62
- ```ts
63
- import { configure } from 'gjendje'
64
-
65
- configure({ scope: 'local' })
66
- ```
67
-
68
- Now every `state` call inherits that default:
69
-
70
- ```ts
71
- const theme = state({ theme: 'light' })
72
-
73
- theme.scope // 'local' — derived from configure
74
- ```
75
-
76
- You can also configure global events:
77
-
78
- ```ts
79
- configure({
80
- onChange: ({ key, scope, value, previousValue }) => {
81
- console.log(`[${key}] (${scope}) changed:`, previousValue, '→', value)
82
- },
83
- })
84
- ```
85
-
86
- [Configure reference guide](https://github.com/charliebeckstrand/gjendje/blob/main/docs/configure.md)
36
+ [Configure guide](https://github.com/charliebeckstrand/gjendje/blob/main/docs/configure.md)
87
37
 
88
38
  ## Scopes
89
39
 
90
- | Scope | Backend | Shortcut |
91
- |----------|----------------------|--------------------|
92
- | `memory` | In-memory | `state()` |
93
- | `local` | `localStorage` | `state.local()` |
94
- | `session` | `sessionStorage` | `state.session()` |
95
- | `url` | `URLSearchParams` | `state.url()` |
96
- | `bucket` | Storage Buckets API | `state.bucket()` |
97
- | `server` | `AsyncLocalStorage` | `state.server()` |
40
+ `memory`, `local`, `session`, `url`, `bucket`, `server`
98
41
 
99
- [Scope decision guide](https://github.com/charliebeckstrand/gjendje/blob/main/docs/scopes.md) · [Persistence reference guide](https://github.com/charliebeckstrand/gjendje/blob/main/docs/persistence.md)
42
+ [Scope guide](https://github.com/charliebeckstrand/gjendje/blob/main/docs/scopes.md)
100
43
 
101
44
  ## API
102
45
 
103
- Every scope shares the same core API: `get`, `set`, `patch`, `reset`, `subscribe`, `watch`, `intercept`, `use`, `destroy`
104
-
105
- [API reference guide](https://github.com/charliebeckstrand/gjendje/blob/main/docs/api.md)
46
+ `get`, `peek`, `set`, `patch`, `reset`, `destroy`, `subscribe`, `watch`, `intercept`, `onChange`
106
47
 
107
- ## Derived state
48
+ [API reference](https://github.com/charliebeckstrand/gjendje/blob/main/docs/api.md)
108
49
 
109
- #### `computed(deps, fn)`
110
- Derives a reactive, read-only value from one or more state dependencies. Recomputes only when a dependency changes and caches the result between changes. Returns a `ReadonlyInstance` — no `set()` or `reset()`.
50
+ ## Primitives
111
51
 
112
- #### `select(source, fn)`
113
- Lightweight single-dependency alternative to `computed`. No array allocation or dependency loop — just `source.get()` → `fn(value)`. Ideal for projecting a single field or transformation.
52
+ `computed`, `select`, `previous`, `readonly`, `collection`, `effect`
114
53
 
115
- #### `collection(key, options)`
116
- Reactive array with first-class mutation methods — `add`, `remove`, `update`, `find`, `findAll`, `has`, `clear`. Supports all the same scopes, persistence, validation, and migration as `state`.
54
+ [Primitives reference](https://github.com/charliebeckstrand/gjendje/blob/main/docs/primitives.md)
117
55
 
118
- #### `effect(deps, fn)`
119
- Runs a side effect immediately and re-runs whenever any dependency changes. The callback can return a cleanup function that runs before the next execution and on `stop()`. Returns an `EffectHandle` with a `stop()` method.
56
+ ## Utilities
120
57
 
121
- #### `readonly(instance)`
122
- Creates a read-only view of any state or computed instance. Exposes `get`, `peek`, `subscribe`, and lifecycle — but no `set`, `reset`, `intercept`, or `use`. Zero runtime cost.
58
+ `configure`, `batch`, `snapshot`, `shallowEqual`, `withHistory`, `withWatch`, `withServerSession`
123
59
 
124
- [Derived state reference guide](https://github.com/charliebeckstrand/gjendje/blob/main/docs/derived.md)
60
+ [Utilities reference](https://github.com/charliebeckstrand/gjendje/blob/main/docs/utilities.md)
125
61
 
126
62
  ## License
127
63
 
@@ -367,7 +367,7 @@ function createBucketAdapter(key, bucketOptions, options) {
367
367
  const listeners = createListeners();
368
368
  let lastNotifiedValue = defaultValue;
369
369
  const notifyListeners = () => listeners.notify(lastNotifiedValue);
370
- const fallbackStorage = fallbackScope === "tab" ? sessionStorage : localStorage;
370
+ const fallbackStorage = fallbackScope === "session" ? sessionStorage : localStorage;
371
371
  let delegate = createStorageAdapter(fallbackStorage, key, options);
372
372
  let isDestroyed = false;
373
373
  const ready = (async () => {
@@ -447,9 +447,9 @@ function createBucketAdapter(key, bucketOptions, options) {
447
447
  };
448
448
  }
449
449
 
450
- // src/adapters/render.ts
450
+ // src/adapters/memory.ts
451
451
  var RESOLVED = Promise.resolve();
452
- function createRenderAdapter(defaultValue) {
452
+ function createMemoryAdapter(defaultValue) {
453
453
  let current = defaultValue;
454
454
  const listeners = /* @__PURE__ */ new Set();
455
455
  const notifyListeners = () => {
@@ -537,7 +537,7 @@ function withSync(adapter, key, scope) {
537
537
  // src/adapters/url.ts
538
538
  function createUrlAdapter(key, defaultValue, serializer, persist) {
539
539
  if (typeof window === "undefined") {
540
- throw new Error("[state] URL scope is not available in this environment.");
540
+ throw new Error("[gjendje] URL scope is not available in this environment.");
541
541
  }
542
542
  const listeners = createListeners();
543
543
  const defaultSerialized = serializer.stringify(defaultValue);
@@ -597,7 +597,7 @@ function createUrlAdapter(key, defaultValue, serializer, persist) {
597
597
  function isServer() {
598
598
  return typeof window === "undefined" || typeof document === "undefined";
599
599
  }
600
- var BROWSER_SCOPES = /* @__PURE__ */ new Set(["session", "tab", "local", "url", "bucket"]);
600
+ var BROWSER_SCOPES = /* @__PURE__ */ new Set(["session", "local", "url", "bucket"]);
601
601
  function afterHydration(fn) {
602
602
  if (isServer()) return Promise.resolve();
603
603
  return new Promise((resolve) => {
@@ -622,10 +622,10 @@ var _serverAdapterFactory;
622
622
  function registerServerAdapter(factory) {
623
623
  _serverAdapterFactory = factory;
624
624
  }
625
- var PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "session", "tab", "bucket"]);
625
+ var PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "session", "bucket"]);
626
626
  var SYNCABLE_SCOPES = /* @__PURE__ */ new Set(["local", "bucket"]);
627
627
  var RESOLVED2 = Promise.resolve();
628
- var RENDER_SHIM = {
628
+ var MEMORY_SHIM = {
629
629
  ready: RESOLVED2,
630
630
  get: () => void 0,
631
631
  set: () => {
@@ -642,19 +642,18 @@ function resolveAdapter(storageKey, scope, options) {
642
642
  switch (scope) {
643
643
  case "memory":
644
644
  case "render":
645
- return createRenderAdapter(options.default);
645
+ return createMemoryAdapter(options.default);
646
646
  case "session":
647
- case "tab":
648
647
  if (typeof sessionStorage === "undefined") {
649
648
  throw new Error(
650
- '[state] sessionStorage is not available. Use ssr: true or scope: "render" for server environments.'
649
+ '[gjendje] sessionStorage is not available. Use ssr: true or scope: "memory" for server environments.'
651
650
  );
652
651
  }
653
652
  return createStorageAdapter(sessionStorage, storageKey, options);
654
653
  case "local":
655
654
  if (typeof localStorage === "undefined") {
656
655
  throw new Error(
657
- '[state] localStorage is not available. Use ssr: true or scope: "server" for server environments.'
656
+ '[gjendje] localStorage is not available. Use ssr: true or scope: "server" for server environments.'
658
657
  );
659
658
  }
660
659
  return createStorageAdapter(localStorage, storageKey, options);
@@ -671,21 +670,21 @@ function resolveAdapter(storageKey, scope, options) {
671
670
  case "server":
672
671
  if (!_serverAdapterFactory) {
673
672
  throw new Error(
674
- '[state] scope: "server" requires the server adapter. Import { withServerSession } from "gjendje" or "gjendje/server" to enable it.'
673
+ '[gjendje] scope: "server" requires the server adapter. Import { withServerSession } from "gjendje" or "gjendje/server" to enable it.'
675
674
  );
676
675
  }
677
676
  return _serverAdapterFactory(storageKey, options.default);
678
677
  case "bucket": {
679
678
  if (!options.bucket) {
680
679
  throw new Error(
681
- '[state] scope: "bucket" requires a bucket option. Example: { scope: "bucket", bucket: { name: "my-bucket" } }'
680
+ '[gjendje] scope: "bucket" requires a bucket option. Example: { scope: "bucket", bucket: { name: "my-bucket" } }'
682
681
  );
683
682
  }
684
683
  return createBucketAdapter(storageKey, options.bucket, options);
685
684
  }
686
685
  default: {
687
686
  const _exhaustive = scope;
688
- throw new Error(`[state] Unknown scope: ${_exhaustive}`);
687
+ throw new Error(`[gjendje] Unknown scope: ${_exhaustive}`);
689
688
  }
690
689
  }
691
690
  }
@@ -902,15 +901,15 @@ var StateImpl = class {
902
901
  });
903
902
  }
904
903
  };
905
- var RenderStateImpl = class extends StateImpl {
904
+ var MemoryStateImpl = class extends StateImpl {
906
905
  // Direct reference — avoids a getter cast on every get()/set() call
907
906
  _r;
908
907
  _hasIsEqual;
909
908
  constructor(key, rKey, options, config) {
910
- super(key, "render", rKey, RENDER_SHIM, options, config);
909
+ super(key, "memory", rKey, MEMORY_SHIM, options, config);
911
910
  const rs = this._s;
912
911
  rs.current = options.default;
913
- rs.renderListeners = void 0;
912
+ rs.memoryListeners = void 0;
914
913
  rs.notifyFn = void 0;
915
914
  this._r = rs;
916
915
  this._hasIsEqual = options.isEqual !== void 0;
@@ -954,9 +953,9 @@ var RenderStateImpl = class extends StateImpl {
954
953
  }
955
954
  subscribe(listener) {
956
955
  const s = this._r;
957
- if (!s.renderListeners) {
956
+ if (!s.memoryListeners) {
958
957
  const listeners = /* @__PURE__ */ new Set();
959
- s.renderListeners = listeners;
958
+ s.memoryListeners = listeners;
960
959
  s.notifyFn = () => {
961
960
  for (const l of listeners) {
962
961
  try {
@@ -967,7 +966,7 @@ var RenderStateImpl = class extends StateImpl {
967
966
  }
968
967
  };
969
968
  }
970
- const set = s.renderListeners;
969
+ const set = s.memoryListeners;
971
970
  set.add(listener);
972
971
  return () => {
973
972
  set.delete(listener);
@@ -1038,7 +1037,7 @@ var RenderStateImpl = class extends StateImpl {
1038
1037
  s.changeHandlers?.clear();
1039
1038
  s.watchers?.clear();
1040
1039
  s.watchUnsub?.();
1041
- s.renderListeners?.clear();
1040
+ s.memoryListeners?.clear();
1042
1041
  unregisterByKey(this._rKey);
1043
1042
  this._config.onDestroy?.({ key: this.key, scope: this.scope });
1044
1043
  if (s.resolveDestroyed) {
@@ -1048,12 +1047,12 @@ var RenderStateImpl = class extends StateImpl {
1048
1047
  }
1049
1048
  }
1050
1049
  };
1051
- function createRenderState(key, rKey, options, config) {
1052
- return new RenderStateImpl(key, rKey, options, config);
1050
+ function createMemoryState(key, rKey, options, config) {
1051
+ return new MemoryStateImpl(key, rKey, options, config);
1053
1052
  }
1054
1053
  function createBase(key, options) {
1055
1054
  if (!key) {
1056
- throw new Error("[state] key must be a non-empty string.");
1055
+ throw new Error("[gjendje] key must be a non-empty string.");
1057
1056
  }
1058
1057
  const config = getConfig();
1059
1058
  if (config.keyPattern && !config.keyPattern.test(key)) {
@@ -1061,8 +1060,8 @@ function createBase(key, options) {
1061
1060
  `[gjendje] Key "${key}" does not match the configured keyPattern ${config.keyPattern}.`
1062
1061
  );
1063
1062
  }
1064
- const rawScope = options.scope ?? config.scope ?? "render";
1065
- const scope = rawScope === "memory" ? "render" : rawScope === "session" ? "tab" : rawScope;
1063
+ const rawScope = options.scope ?? config.scope ?? "memory";
1064
+ const scope = rawScope === "render" ? "memory" : rawScope;
1066
1065
  const rKey = scopedKey(key, scope);
1067
1066
  const existing = getRegistered(rKey);
1068
1067
  if (existing && !existing.isDestroyed) return existing;
@@ -1072,7 +1071,7 @@ function createBase(key, options) {
1072
1071
  );
1073
1072
  }
1074
1073
  const isSsrMode = (options.ssr ?? config.ssr) && BROWSER_SCOPES.has(scope);
1075
- const useRenderFallback = isSsrMode && isServer();
1074
+ const useMemoryFallback = isSsrMode && isServer();
1076
1075
  const effectiveSync = options.sync ?? (config.sync && SYNCABLE_SCOPES.has(scope));
1077
1076
  if (effectiveSync && !SYNCABLE_SCOPES.has(scope)) {
1078
1077
  log(
@@ -1081,12 +1080,12 @@ function createBase(key, options) {
1081
1080
  );
1082
1081
  }
1083
1082
  let instance;
1084
- if (scope === "render" && !isSsrMode) {
1085
- instance = new RenderStateImpl(key, rKey, options, config);
1083
+ if (scope === "memory" && !isSsrMode) {
1084
+ instance = new MemoryStateImpl(key, rKey, options, config);
1086
1085
  } else {
1087
1086
  const storageKey = resolveStorageKey(key, options, config.prefix);
1088
- const baseAdapter = useRenderFallback ? createRenderAdapter(options.default) : resolveAdapter(storageKey, scope, options);
1089
- const shouldSync = effectiveSync && SYNCABLE_SCOPES.has(scope) && !useRenderFallback;
1087
+ const baseAdapter = useMemoryFallback ? createMemoryAdapter(options.default) : resolveAdapter(storageKey, scope, options);
1088
+ const shouldSync = effectiveSync && SYNCABLE_SCOPES.has(scope) && !useMemoryFallback;
1090
1089
  const adapter = shouldSync ? withSync(baseAdapter, storageKey, scope) : baseAdapter;
1091
1090
  instance = new StateImpl(key, scope, rKey, adapter, options, config);
1092
1091
  if (isSsrMode && !isServer()) {
@@ -1102,7 +1101,7 @@ function createBase(key, options) {
1102
1101
  config.onHydrate?.({ key, scope, serverValue, clientValue });
1103
1102
  realAdapter.destroy?.();
1104
1103
  } catch (err) {
1105
- log("debug", `Hydration adapter unavailable for state("${key}") \u2014 using render fallback.`);
1104
+ log("debug", `Hydration adapter unavailable for state("${key}") \u2014 using memory fallback.`);
1106
1105
  reportError(key, scope, err);
1107
1106
  }
1108
1107
  });
@@ -1112,4 +1111,4 @@ function createBase(key, options) {
1112
1111
  return instance;
1113
1112
  }
1114
1113
 
1115
- export { batch, configure, createBase, createListeners, createRenderState, getConfig, getRegistered, getRegistry, log, notify, registerByKey, registerServerAdapter, scopedKey, shallowEqual };
1114
+ export { batch, configure, createBase, createListeners, createMemoryState, getConfig, getRegistered, getRegistry, log, notify, registerByKey, registerServerAdapter, scopedKey, shallowEqual };
@@ -369,7 +369,7 @@ function createBucketAdapter(key, bucketOptions, options) {
369
369
  const listeners = createListeners();
370
370
  let lastNotifiedValue = defaultValue;
371
371
  const notifyListeners = () => listeners.notify(lastNotifiedValue);
372
- const fallbackStorage = fallbackScope === "tab" ? sessionStorage : localStorage;
372
+ const fallbackStorage = fallbackScope === "session" ? sessionStorage : localStorage;
373
373
  let delegate = createStorageAdapter(fallbackStorage, key, options);
374
374
  let isDestroyed = false;
375
375
  const ready = (async () => {
@@ -449,9 +449,9 @@ function createBucketAdapter(key, bucketOptions, options) {
449
449
  };
450
450
  }
451
451
 
452
- // src/adapters/render.ts
452
+ // src/adapters/memory.ts
453
453
  var RESOLVED = Promise.resolve();
454
- function createRenderAdapter(defaultValue) {
454
+ function createMemoryAdapter(defaultValue) {
455
455
  let current = defaultValue;
456
456
  const listeners = /* @__PURE__ */ new Set();
457
457
  const notifyListeners = () => {
@@ -539,7 +539,7 @@ function withSync(adapter, key, scope) {
539
539
  // src/adapters/url.ts
540
540
  function createUrlAdapter(key, defaultValue, serializer, persist) {
541
541
  if (typeof window === "undefined") {
542
- throw new Error("[state] URL scope is not available in this environment.");
542
+ throw new Error("[gjendje] URL scope is not available in this environment.");
543
543
  }
544
544
  const listeners = createListeners();
545
545
  const defaultSerialized = serializer.stringify(defaultValue);
@@ -599,7 +599,7 @@ function createUrlAdapter(key, defaultValue, serializer, persist) {
599
599
  function isServer() {
600
600
  return typeof window === "undefined" || typeof document === "undefined";
601
601
  }
602
- var BROWSER_SCOPES = /* @__PURE__ */ new Set(["session", "tab", "local", "url", "bucket"]);
602
+ var BROWSER_SCOPES = /* @__PURE__ */ new Set(["session", "local", "url", "bucket"]);
603
603
  function afterHydration(fn) {
604
604
  if (isServer()) return Promise.resolve();
605
605
  return new Promise((resolve) => {
@@ -624,10 +624,10 @@ var _serverAdapterFactory;
624
624
  function registerServerAdapter(factory) {
625
625
  _serverAdapterFactory = factory;
626
626
  }
627
- var PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "session", "tab", "bucket"]);
627
+ var PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "session", "bucket"]);
628
628
  var SYNCABLE_SCOPES = /* @__PURE__ */ new Set(["local", "bucket"]);
629
629
  var RESOLVED2 = Promise.resolve();
630
- var RENDER_SHIM = {
630
+ var MEMORY_SHIM = {
631
631
  ready: RESOLVED2,
632
632
  get: () => void 0,
633
633
  set: () => {
@@ -644,19 +644,18 @@ function resolveAdapter(storageKey, scope, options) {
644
644
  switch (scope) {
645
645
  case "memory":
646
646
  case "render":
647
- return createRenderAdapter(options.default);
647
+ return createMemoryAdapter(options.default);
648
648
  case "session":
649
- case "tab":
650
649
  if (typeof sessionStorage === "undefined") {
651
650
  throw new Error(
652
- '[state] sessionStorage is not available. Use ssr: true or scope: "render" for server environments.'
651
+ '[gjendje] sessionStorage is not available. Use ssr: true or scope: "memory" for server environments.'
653
652
  );
654
653
  }
655
654
  return createStorageAdapter(sessionStorage, storageKey, options);
656
655
  case "local":
657
656
  if (typeof localStorage === "undefined") {
658
657
  throw new Error(
659
- '[state] localStorage is not available. Use ssr: true or scope: "server" for server environments.'
658
+ '[gjendje] localStorage is not available. Use ssr: true or scope: "server" for server environments.'
660
659
  );
661
660
  }
662
661
  return createStorageAdapter(localStorage, storageKey, options);
@@ -673,21 +672,21 @@ function resolveAdapter(storageKey, scope, options) {
673
672
  case "server":
674
673
  if (!_serverAdapterFactory) {
675
674
  throw new Error(
676
- '[state] scope: "server" requires the server adapter. Import { withServerSession } from "gjendje" or "gjendje/server" to enable it.'
675
+ '[gjendje] scope: "server" requires the server adapter. Import { withServerSession } from "gjendje" or "gjendje/server" to enable it.'
677
676
  );
678
677
  }
679
678
  return _serverAdapterFactory(storageKey, options.default);
680
679
  case "bucket": {
681
680
  if (!options.bucket) {
682
681
  throw new Error(
683
- '[state] scope: "bucket" requires a bucket option. Example: { scope: "bucket", bucket: { name: "my-bucket" } }'
682
+ '[gjendje] scope: "bucket" requires a bucket option. Example: { scope: "bucket", bucket: { name: "my-bucket" } }'
684
683
  );
685
684
  }
686
685
  return createBucketAdapter(storageKey, options.bucket, options);
687
686
  }
688
687
  default: {
689
688
  const _exhaustive = scope;
690
- throw new Error(`[state] Unknown scope: ${_exhaustive}`);
689
+ throw new Error(`[gjendje] Unknown scope: ${_exhaustive}`);
691
690
  }
692
691
  }
693
692
  }
@@ -904,15 +903,15 @@ var StateImpl = class {
904
903
  });
905
904
  }
906
905
  };
907
- var RenderStateImpl = class extends StateImpl {
906
+ var MemoryStateImpl = class extends StateImpl {
908
907
  // Direct reference — avoids a getter cast on every get()/set() call
909
908
  _r;
910
909
  _hasIsEqual;
911
910
  constructor(key, rKey, options, config) {
912
- super(key, "render", rKey, RENDER_SHIM, options, config);
911
+ super(key, "memory", rKey, MEMORY_SHIM, options, config);
913
912
  const rs = this._s;
914
913
  rs.current = options.default;
915
- rs.renderListeners = void 0;
914
+ rs.memoryListeners = void 0;
916
915
  rs.notifyFn = void 0;
917
916
  this._r = rs;
918
917
  this._hasIsEqual = options.isEqual !== void 0;
@@ -956,9 +955,9 @@ var RenderStateImpl = class extends StateImpl {
956
955
  }
957
956
  subscribe(listener) {
958
957
  const s = this._r;
959
- if (!s.renderListeners) {
958
+ if (!s.memoryListeners) {
960
959
  const listeners = /* @__PURE__ */ new Set();
961
- s.renderListeners = listeners;
960
+ s.memoryListeners = listeners;
962
961
  s.notifyFn = () => {
963
962
  for (const l of listeners) {
964
963
  try {
@@ -969,7 +968,7 @@ var RenderStateImpl = class extends StateImpl {
969
968
  }
970
969
  };
971
970
  }
972
- const set = s.renderListeners;
971
+ const set = s.memoryListeners;
973
972
  set.add(listener);
974
973
  return () => {
975
974
  set.delete(listener);
@@ -1040,7 +1039,7 @@ var RenderStateImpl = class extends StateImpl {
1040
1039
  s.changeHandlers?.clear();
1041
1040
  s.watchers?.clear();
1042
1041
  s.watchUnsub?.();
1043
- s.renderListeners?.clear();
1042
+ s.memoryListeners?.clear();
1044
1043
  unregisterByKey(this._rKey);
1045
1044
  this._config.onDestroy?.({ key: this.key, scope: this.scope });
1046
1045
  if (s.resolveDestroyed) {
@@ -1050,12 +1049,12 @@ var RenderStateImpl = class extends StateImpl {
1050
1049
  }
1051
1050
  }
1052
1051
  };
1053
- function createRenderState(key, rKey, options, config) {
1054
- return new RenderStateImpl(key, rKey, options, config);
1052
+ function createMemoryState(key, rKey, options, config) {
1053
+ return new MemoryStateImpl(key, rKey, options, config);
1055
1054
  }
1056
1055
  function createBase(key, options) {
1057
1056
  if (!key) {
1058
- throw new Error("[state] key must be a non-empty string.");
1057
+ throw new Error("[gjendje] key must be a non-empty string.");
1059
1058
  }
1060
1059
  const config = getConfig();
1061
1060
  if (config.keyPattern && !config.keyPattern.test(key)) {
@@ -1063,8 +1062,8 @@ function createBase(key, options) {
1063
1062
  `[gjendje] Key "${key}" does not match the configured keyPattern ${config.keyPattern}.`
1064
1063
  );
1065
1064
  }
1066
- const rawScope = options.scope ?? config.scope ?? "render";
1067
- const scope = rawScope === "memory" ? "render" : rawScope === "session" ? "tab" : rawScope;
1065
+ const rawScope = options.scope ?? config.scope ?? "memory";
1066
+ const scope = rawScope === "render" ? "memory" : rawScope;
1068
1067
  const rKey = scopedKey(key, scope);
1069
1068
  const existing = getRegistered(rKey);
1070
1069
  if (existing && !existing.isDestroyed) return existing;
@@ -1074,7 +1073,7 @@ function createBase(key, options) {
1074
1073
  );
1075
1074
  }
1076
1075
  const isSsrMode = (options.ssr ?? config.ssr) && BROWSER_SCOPES.has(scope);
1077
- const useRenderFallback = isSsrMode && isServer();
1076
+ const useMemoryFallback = isSsrMode && isServer();
1078
1077
  const effectiveSync = options.sync ?? (config.sync && SYNCABLE_SCOPES.has(scope));
1079
1078
  if (effectiveSync && !SYNCABLE_SCOPES.has(scope)) {
1080
1079
  log(
@@ -1083,12 +1082,12 @@ function createBase(key, options) {
1083
1082
  );
1084
1083
  }
1085
1084
  let instance;
1086
- if (scope === "render" && !isSsrMode) {
1087
- instance = new RenderStateImpl(key, rKey, options, config);
1085
+ if (scope === "memory" && !isSsrMode) {
1086
+ instance = new MemoryStateImpl(key, rKey, options, config);
1088
1087
  } else {
1089
1088
  const storageKey = resolveStorageKey(key, options, config.prefix);
1090
- const baseAdapter = useRenderFallback ? createRenderAdapter(options.default) : resolveAdapter(storageKey, scope, options);
1091
- const shouldSync = effectiveSync && SYNCABLE_SCOPES.has(scope) && !useRenderFallback;
1089
+ const baseAdapter = useMemoryFallback ? createMemoryAdapter(options.default) : resolveAdapter(storageKey, scope, options);
1090
+ const shouldSync = effectiveSync && SYNCABLE_SCOPES.has(scope) && !useMemoryFallback;
1092
1091
  const adapter = shouldSync ? withSync(baseAdapter, storageKey, scope) : baseAdapter;
1093
1092
  instance = new StateImpl(key, scope, rKey, adapter, options, config);
1094
1093
  if (isSsrMode && !isServer()) {
@@ -1104,7 +1103,7 @@ function createBase(key, options) {
1104
1103
  config.onHydrate?.({ key, scope, serverValue, clientValue });
1105
1104
  realAdapter.destroy?.();
1106
1105
  } catch (err) {
1107
- log("debug", `Hydration adapter unavailable for state("${key}") \u2014 using render fallback.`);
1106
+ log("debug", `Hydration adapter unavailable for state("${key}") \u2014 using memory fallback.`);
1108
1107
  reportError(key, scope, err);
1109
1108
  }
1110
1109
  });
@@ -1118,7 +1117,7 @@ exports.batch = batch;
1118
1117
  exports.configure = configure;
1119
1118
  exports.createBase = createBase;
1120
1119
  exports.createListeners = createListeners;
1121
- exports.createRenderState = createRenderState;
1120
+ exports.createMemoryState = createMemoryState;
1122
1121
  exports.getConfig = getConfig;
1123
1122
  exports.getRegistered = getRegistered;
1124
1123
  exports.getRegistry = getRegistry;
package/dist/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunkXACGL7LY_cjs = require('./chunk-XACGL7LY.cjs');
3
+ var chunkMEVW62P4_cjs = require('./chunk-MEVW62P4.cjs');
4
4
 
5
5
  // src/collection.ts
6
6
  function collection(key, options) {
7
- const base = chunkXACGL7LY_cjs.createBase(key, options);
7
+ const base = chunkMEVW62P4_cjs.createBase(key, options);
8
8
  const watchers = /* @__PURE__ */ new Map();
9
9
  let prevItems = base.get();
10
10
  const unsubscribe = base.subscribe((next) => {
@@ -139,7 +139,7 @@ function collection(key, options) {
139
139
  // src/computed.ts
140
140
  var computedCounter = 0;
141
141
  function computed(deps, fn, options) {
142
- const listeners = chunkXACGL7LY_cjs.createListeners();
142
+ const listeners = chunkMEVW62P4_cjs.createListeners();
143
143
  const instanceKey = options?.key ?? `computed:${computedCounter++}`;
144
144
  let cached;
145
145
  let isDirty = true;
@@ -164,7 +164,7 @@ function computed(deps, fn, options) {
164
164
  };
165
165
  const markDirty = () => {
166
166
  isDirty = true;
167
- chunkXACGL7LY_cjs.notify(notifyListeners);
167
+ chunkMEVW62P4_cjs.notify(notifyListeners);
168
168
  };
169
169
  const unsubscribers = new Array(depLen);
170
170
  for (let i = 0; i < depLen; i++) {
@@ -178,7 +178,7 @@ function computed(deps, fn, options) {
178
178
  const hydratedPromise = Promise.all(deps.map((d) => d.hydrated)).then(() => void 0);
179
179
  return {
180
180
  key: instanceKey,
181
- scope: "render",
181
+ scope: "memory",
182
182
  get ready() {
183
183
  return readyPromise;
184
184
  },
@@ -224,7 +224,7 @@ function computed(deps, fn, options) {
224
224
 
225
225
  // src/devtools.ts
226
226
  function snapshot() {
227
- const registry = chunkXACGL7LY_cjs.getRegistry();
227
+ const registry = chunkMEVW62P4_cjs.getRegistry();
228
228
  const result = [];
229
229
  for (const instance of registry.values()) {
230
230
  result.push({
@@ -407,7 +407,7 @@ function withWatch(instance) {
407
407
  // src/previous.ts
408
408
  var previousCounter = 0;
409
409
  function previous(source, options) {
410
- const listeners = chunkXACGL7LY_cjs.createListeners();
410
+ const listeners = chunkMEVW62P4_cjs.createListeners();
411
411
  const instanceKey = options?.key ?? `previous:${previousCounter++}`;
412
412
  let prev;
413
413
  let current = source.get();
@@ -417,14 +417,14 @@ function previous(source, options) {
417
417
  prev = current;
418
418
  current = next;
419
419
  if (old !== prev) {
420
- chunkXACGL7LY_cjs.notify(() => listeners.notify(prev));
420
+ chunkMEVW62P4_cjs.notify(() => listeners.notify(prev));
421
421
  }
422
422
  });
423
423
  let destroyedPromise;
424
424
  let resolveDestroyed;
425
425
  return {
426
426
  key: instanceKey,
427
- scope: "render",
427
+ scope: "memory",
428
428
  get ready() {
429
429
  return source.ready;
430
430
  },
@@ -479,7 +479,7 @@ function readonly(instance) {
479
479
  // src/select.ts
480
480
  var selectCounter = 0;
481
481
  function select(source, fn, options) {
482
- const listeners = chunkXACGL7LY_cjs.createListeners();
482
+ const listeners = chunkMEVW62P4_cjs.createListeners();
483
483
  const instanceKey = options?.key ?? `select:${selectCounter++}`;
484
484
  let cached;
485
485
  let isDirty = true;
@@ -498,7 +498,7 @@ function select(source, fn, options) {
498
498
  };
499
499
  const markDirty = () => {
500
500
  isDirty = true;
501
- chunkXACGL7LY_cjs.notify(notifyListeners);
501
+ chunkMEVW62P4_cjs.notify(notifyListeners);
502
502
  };
503
503
  const unsubscribe = source.subscribe(markDirty);
504
504
  recompute();
@@ -506,7 +506,7 @@ function select(source, fn, options) {
506
506
  let resolveDestroyed;
507
507
  return {
508
508
  key: instanceKey,
509
- scope: "render",
509
+ scope: "memory",
510
510
  get ready() {
511
511
  return source.ready;
512
512
  },
@@ -551,36 +551,36 @@ function select(source, fn, options) {
551
551
  // src/factory.ts
552
552
  function createState(key, options) {
553
553
  if (!key) {
554
- throw new Error("[state] key must be a non-empty string.");
554
+ throw new Error("[gjendje] key must be a non-empty string.");
555
555
  }
556
- const config = chunkXACGL7LY_cjs.getConfig();
556
+ const config = chunkMEVW62P4_cjs.getConfig();
557
557
  if (config.keyPattern && !config.keyPattern.test(key)) {
558
558
  throw new Error(
559
559
  `[gjendje] Key "${key}" does not match the configured keyPattern ${config.keyPattern}.`
560
560
  );
561
561
  }
562
- const rawScope = options.scope ?? config.scope ?? "render";
563
- const scope = rawScope === "memory" ? "render" : rawScope === "session" ? "tab" : rawScope;
564
- const rKey = chunkXACGL7LY_cjs.scopedKey(key, scope);
565
- const existing = chunkXACGL7LY_cjs.getRegistered(rKey);
562
+ const rawScope = options.scope ?? config.scope ?? "memory";
563
+ const scope = rawScope === "render" ? "memory" : rawScope;
564
+ const rKey = chunkMEVW62P4_cjs.scopedKey(key, scope);
565
+ const existing = chunkMEVW62P4_cjs.getRegistered(rKey);
566
566
  if (existing && !existing.isDestroyed) {
567
567
  if (config.warnOnDuplicate) {
568
- chunkXACGL7LY_cjs.log("warn", `Duplicate state("${key}") with scope "${scope}". Returning cached instance.`);
568
+ chunkMEVW62P4_cjs.log("warn", `Duplicate state("${key}") with scope "${scope}". Returning cached instance.`);
569
569
  }
570
570
  return existing;
571
571
  }
572
- if (scope === "render" && !options.ssr && !config.ssr) {
572
+ if (scope === "memory" && !options.ssr && !config.ssr) {
573
573
  if (options.sync) {
574
- chunkXACGL7LY_cjs.log(
574
+ chunkMEVW62P4_cjs.log(
575
575
  "warn",
576
- `sync: true is ignored for scope "render". Only "local" and "bucket" scopes support cross-tab sync.`
576
+ `sync: true is ignored for scope "memory". Only "local" and "bucket" scopes support cross-tab sync.`
577
577
  );
578
578
  }
579
- const instance = chunkXACGL7LY_cjs.createRenderState(key, rKey, options, config);
580
- chunkXACGL7LY_cjs.registerByKey(rKey, key, scope, instance, config);
579
+ const instance = chunkMEVW62P4_cjs.createMemoryState(key, rKey, options, config);
580
+ chunkMEVW62P4_cjs.registerByKey(rKey, key, scope, instance, config);
581
581
  return instance;
582
582
  }
583
- return chunkXACGL7LY_cjs.createBase(key, options);
583
+ return chunkMEVW62P4_cjs.createBase(key, options);
584
584
  }
585
585
 
586
586
  // src/shortcuts.ts
@@ -594,14 +594,6 @@ function extractEntry(entry) {
594
594
  const key = keys[0];
595
595
  return [key, entry[key]];
596
596
  }
597
- var _deprecationWarned = /* @__PURE__ */ new Set();
598
- function warnDeprecated(name) {
599
- if (_deprecationWarned.has(name)) return;
600
- _deprecationWarned.add(name);
601
- console.warn(
602
- `[gjendje] ${name}() is deprecated and will be removed in the next major version. Use state.${name}() instead. Example: state.${name}({ key: value })`
603
- );
604
- }
605
597
  function _local(entry, options) {
606
598
  const [key, defaultValue] = extractEntry(entry);
607
599
  return createState(key, { ...options, default: defaultValue, scope: "local" });
@@ -641,51 +633,26 @@ _state.url = _url;
641
633
  _state.bucket = _bucket;
642
634
  _state.server = _server;
643
635
  var state = _state;
644
- function local(entry, options) {
645
- warnDeprecated("local");
646
- return _local(entry, options);
647
- }
648
- function session(entry, options) {
649
- warnDeprecated("session");
650
- return _session(entry, options);
651
- }
652
- function url(entry, options) {
653
- warnDeprecated("url");
654
- return _url(entry, options);
655
- }
656
- function server(entry, options) {
657
- warnDeprecated("server");
658
- return _server(entry, options);
659
- }
660
- function bucket(entry, options) {
661
- warnDeprecated("bucket");
662
- return _bucket(entry, options);
663
- }
664
636
 
665
637
  Object.defineProperty(exports, "batch", {
666
638
  enumerable: true,
667
- get: function () { return chunkXACGL7LY_cjs.batch; }
639
+ get: function () { return chunkMEVW62P4_cjs.batch; }
668
640
  });
669
641
  Object.defineProperty(exports, "configure", {
670
642
  enumerable: true,
671
- get: function () { return chunkXACGL7LY_cjs.configure; }
643
+ get: function () { return chunkMEVW62P4_cjs.configure; }
672
644
  });
673
645
  Object.defineProperty(exports, "shallowEqual", {
674
646
  enumerable: true,
675
- get: function () { return chunkXACGL7LY_cjs.shallowEqual; }
647
+ get: function () { return chunkMEVW62P4_cjs.shallowEqual; }
676
648
  });
677
- exports.bucket = bucket;
678
649
  exports.collection = collection;
679
650
  exports.computed = computed;
680
651
  exports.effect = effect;
681
- exports.local = local;
682
652
  exports.previous = previous;
683
653
  exports.readonly = readonly;
684
654
  exports.select = select;
685
- exports.server = server;
686
- exports.session = session;
687
655
  exports.snapshot = snapshot;
688
656
  exports.state = state;
689
- exports.url = url;
690
657
  exports.withHistory = withHistory;
691
658
  exports.withWatch = withWatch;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BaseInstance, U as Unsubscribe, S as StateOptions, R as ReadonlyInstance, a as Scope, b as StateInstance } from './types-D-VJhL7I.cjs';
2
- export { A as Adapter, c as BucketOptions, E as Enhancer, L as Listener, d as Serializer } from './types-D-VJhL7I.cjs';
1
+ import { B as BaseInstance, U as Unsubscribe, S as StateOptions, R as ReadonlyInstance, a as Scope, b as StateInstance } from './types-DbzCHTo8.cjs';
2
+ export { A as Adapter, c as BucketOptions, E as Enhancer, L as Listener, d as Serializer } from './types-DbzCHTo8.cjs';
3
3
 
4
4
  /**
5
5
  * Runs all state updates inside fn as a single batch.
@@ -173,7 +173,7 @@ interface ExpireContext {
173
173
  expiredAt: number;
174
174
  }
175
175
  interface GjendjeConfig {
176
- /** Default scope for all state instances. Defaults to `'render'`. */
176
+ /** Default scope for all state instances. Defaults to `'memory'`. */
177
177
  scope?: Scope | undefined;
178
178
  /** Enforce a naming pattern for state keys. */
179
179
  keyPattern?: RegExp | undefined;
@@ -183,7 +183,7 @@ interface GjendjeConfig {
183
183
  maxKeys?: number | undefined;
184
184
  /** Prepends to all storage keys (e.g. `myapp:theme`) */
185
185
  prefix?: string | undefined;
186
- /** Require a validate option for persisted scopes (local, tab, bucket). */
186
+ /** Require a validate option for persisted scopes (local, session, bucket). */
187
187
  requireValidation?: boolean | undefined;
188
188
  /** Enable SSR mode globally for all instances. */
189
189
  ssr?: boolean | undefined;
@@ -287,7 +287,7 @@ interface HistoryOptions {
287
287
  * Enhance a state instance with undo/redo capabilities.
288
288
  *
289
289
  * ```ts
290
- * const counter = state('counter', { default: 0, scope: 'render' })
290
+ * const counter = state('counter', { default: 0, scope: 'memory' })
291
291
  * const h = withHistory(counter)
292
292
  *
293
293
  * h.set(1)
@@ -423,56 +423,6 @@ interface StateFunction {
423
423
  server: <T>(entry: Record<string, T>, options?: ShortcutOptions<T>) => StateInstance<T>;
424
424
  }
425
425
  declare const state: StateFunction;
426
- /**
427
- * @deprecated Use `state.local()` instead. Will be removed in the next major version.
428
- *
429
- * Create state stored in `localStorage`.
430
- *
431
- * ```ts
432
- * const theme = state.local({ theme: 'light' })
433
- * ```
434
- */
435
- declare function local<T>(entry: Record<string, T>, options?: ShortcutOptions<T>): StateInstance<T>;
436
- /**
437
- * @deprecated Use `state.session()` instead. Will be removed in the next major version.
438
- *
439
- * Create state stored in `sessionStorage`.
440
- *
441
- * ```ts
442
- * const draft = state.session({ draft: '' })
443
- * ```
444
- */
445
- declare function session<T>(entry: Record<string, T>, options?: ShortcutOptions<T>): StateInstance<T>;
446
- /**
447
- * @deprecated Use `state.url()` instead. Will be removed in the next major version.
448
- *
449
- * Create state stored in `URLSearchParams`.
450
- *
451
- * ```ts
452
- * const filters = state.url({ q: '' })
453
- * ```
454
- */
455
- declare function url<T>(entry: Record<string, T>, options?: ShortcutOptions<T>): StateInstance<T>;
456
- /**
457
- * @deprecated Use `state.server()` instead. Will be removed in the next major version.
458
- *
459
- * Create state stored in server-side `AsyncLocalStorage`.
460
- *
461
- * ```ts
462
- * const user = state.server({ user: null })
463
- * ```
464
- */
465
- declare function server<T>(entry: Record<string, T>, options?: ShortcutOptions<T>): StateInstance<T>;
466
- /**
467
- * @deprecated Use `state.bucket()` instead. Will be removed in the next major version.
468
- *
469
- * Create state stored in a Storage Bucket.
470
- *
471
- * ```ts
472
- * const data = state.bucket({ cache: [] }, { bucket: { name: 'my-bucket' } })
473
- * ```
474
- */
475
- declare function bucket<T>(entry: Record<string, T>, options: BucketShortcutOptions<T>): StateInstance<T>;
476
426
 
477
427
  /**
478
428
  * Shallow equality check for primitives, arrays, and plain objects.
@@ -480,4 +430,4 @@ declare function bucket<T>(entry: Record<string, T>, options: BucketShortcutOpti
480
430
  */
481
431
  declare function shallowEqual(a: unknown, b: unknown): boolean;
482
432
 
483
- export { BaseInstance, type ChangeContext, type CollectionInstance, type ComputedInstance, type ComputedOptions, type DestroyContext, type EffectHandle, type ErrorContext, type ExpireContext, type GjendjeConfig, type HistoryOptions, type HydrateContext, type InterceptContext, type LogLevel, type MigrateContext, type PreviousInstance, type PreviousOptions, type QuotaExceededContext, ReadonlyInstance, type RegisterContext, type ResetContext, Scope, type SelectInstance, type SelectOptions, type StateFunction, StateInstance, StateOptions, type StateSnapshot, type SyncContext, Unsubscribe, type ValidationFailContext, type WithHistoryInstance, type WithWatch, batch, bucket, collection, computed, configure, effect, local, previous, readonly, select, server, session, shallowEqual, snapshot, state, url, withHistory, withWatch };
433
+ export { BaseInstance, type ChangeContext, type CollectionInstance, type ComputedInstance, type ComputedOptions, type DestroyContext, type EffectHandle, type ErrorContext, type ExpireContext, type GjendjeConfig, type HistoryOptions, type HydrateContext, type InterceptContext, type LogLevel, type MigrateContext, type PreviousInstance, type PreviousOptions, type QuotaExceededContext, ReadonlyInstance, type RegisterContext, type ResetContext, Scope, type SelectInstance, type SelectOptions, type StateFunction, StateInstance, StateOptions, type StateSnapshot, type SyncContext, Unsubscribe, type ValidationFailContext, type WithHistoryInstance, type WithWatch, batch, collection, computed, configure, effect, previous, readonly, select, shallowEqual, snapshot, state, withHistory, withWatch };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { B as BaseInstance, U as Unsubscribe, S as StateOptions, R as ReadonlyInstance, a as Scope, b as StateInstance } from './types-D-VJhL7I.js';
2
- export { A as Adapter, c as BucketOptions, E as Enhancer, L as Listener, d as Serializer } from './types-D-VJhL7I.js';
1
+ import { B as BaseInstance, U as Unsubscribe, S as StateOptions, R as ReadonlyInstance, a as Scope, b as StateInstance } from './types-DbzCHTo8.js';
2
+ export { A as Adapter, c as BucketOptions, E as Enhancer, L as Listener, d as Serializer } from './types-DbzCHTo8.js';
3
3
 
4
4
  /**
5
5
  * Runs all state updates inside fn as a single batch.
@@ -173,7 +173,7 @@ interface ExpireContext {
173
173
  expiredAt: number;
174
174
  }
175
175
  interface GjendjeConfig {
176
- /** Default scope for all state instances. Defaults to `'render'`. */
176
+ /** Default scope for all state instances. Defaults to `'memory'`. */
177
177
  scope?: Scope | undefined;
178
178
  /** Enforce a naming pattern for state keys. */
179
179
  keyPattern?: RegExp | undefined;
@@ -183,7 +183,7 @@ interface GjendjeConfig {
183
183
  maxKeys?: number | undefined;
184
184
  /** Prepends to all storage keys (e.g. `myapp:theme`) */
185
185
  prefix?: string | undefined;
186
- /** Require a validate option for persisted scopes (local, tab, bucket). */
186
+ /** Require a validate option for persisted scopes (local, session, bucket). */
187
187
  requireValidation?: boolean | undefined;
188
188
  /** Enable SSR mode globally for all instances. */
189
189
  ssr?: boolean | undefined;
@@ -287,7 +287,7 @@ interface HistoryOptions {
287
287
  * Enhance a state instance with undo/redo capabilities.
288
288
  *
289
289
  * ```ts
290
- * const counter = state('counter', { default: 0, scope: 'render' })
290
+ * const counter = state('counter', { default: 0, scope: 'memory' })
291
291
  * const h = withHistory(counter)
292
292
  *
293
293
  * h.set(1)
@@ -423,56 +423,6 @@ interface StateFunction {
423
423
  server: <T>(entry: Record<string, T>, options?: ShortcutOptions<T>) => StateInstance<T>;
424
424
  }
425
425
  declare const state: StateFunction;
426
- /**
427
- * @deprecated Use `state.local()` instead. Will be removed in the next major version.
428
- *
429
- * Create state stored in `localStorage`.
430
- *
431
- * ```ts
432
- * const theme = state.local({ theme: 'light' })
433
- * ```
434
- */
435
- declare function local<T>(entry: Record<string, T>, options?: ShortcutOptions<T>): StateInstance<T>;
436
- /**
437
- * @deprecated Use `state.session()` instead. Will be removed in the next major version.
438
- *
439
- * Create state stored in `sessionStorage`.
440
- *
441
- * ```ts
442
- * const draft = state.session({ draft: '' })
443
- * ```
444
- */
445
- declare function session<T>(entry: Record<string, T>, options?: ShortcutOptions<T>): StateInstance<T>;
446
- /**
447
- * @deprecated Use `state.url()` instead. Will be removed in the next major version.
448
- *
449
- * Create state stored in `URLSearchParams`.
450
- *
451
- * ```ts
452
- * const filters = state.url({ q: '' })
453
- * ```
454
- */
455
- declare function url<T>(entry: Record<string, T>, options?: ShortcutOptions<T>): StateInstance<T>;
456
- /**
457
- * @deprecated Use `state.server()` instead. Will be removed in the next major version.
458
- *
459
- * Create state stored in server-side `AsyncLocalStorage`.
460
- *
461
- * ```ts
462
- * const user = state.server({ user: null })
463
- * ```
464
- */
465
- declare function server<T>(entry: Record<string, T>, options?: ShortcutOptions<T>): StateInstance<T>;
466
- /**
467
- * @deprecated Use `state.bucket()` instead. Will be removed in the next major version.
468
- *
469
- * Create state stored in a Storage Bucket.
470
- *
471
- * ```ts
472
- * const data = state.bucket({ cache: [] }, { bucket: { name: 'my-bucket' } })
473
- * ```
474
- */
475
- declare function bucket<T>(entry: Record<string, T>, options: BucketShortcutOptions<T>): StateInstance<T>;
476
426
 
477
427
  /**
478
428
  * Shallow equality check for primitives, arrays, and plain objects.
@@ -480,4 +430,4 @@ declare function bucket<T>(entry: Record<string, T>, options: BucketShortcutOpti
480
430
  */
481
431
  declare function shallowEqual(a: unknown, b: unknown): boolean;
482
432
 
483
- export { BaseInstance, type ChangeContext, type CollectionInstance, type ComputedInstance, type ComputedOptions, type DestroyContext, type EffectHandle, type ErrorContext, type ExpireContext, type GjendjeConfig, type HistoryOptions, type HydrateContext, type InterceptContext, type LogLevel, type MigrateContext, type PreviousInstance, type PreviousOptions, type QuotaExceededContext, ReadonlyInstance, type RegisterContext, type ResetContext, Scope, type SelectInstance, type SelectOptions, type StateFunction, StateInstance, StateOptions, type StateSnapshot, type SyncContext, Unsubscribe, type ValidationFailContext, type WithHistoryInstance, type WithWatch, batch, bucket, collection, computed, configure, effect, local, previous, readonly, select, server, session, shallowEqual, snapshot, state, url, withHistory, withWatch };
433
+ export { BaseInstance, type ChangeContext, type CollectionInstance, type ComputedInstance, type ComputedOptions, type DestroyContext, type EffectHandle, type ErrorContext, type ExpireContext, type GjendjeConfig, type HistoryOptions, type HydrateContext, type InterceptContext, type LogLevel, type MigrateContext, type PreviousInstance, type PreviousOptions, type QuotaExceededContext, ReadonlyInstance, type RegisterContext, type ResetContext, Scope, type SelectInstance, type SelectOptions, type StateFunction, StateInstance, StateOptions, type StateSnapshot, type SyncContext, Unsubscribe, type ValidationFailContext, type WithHistoryInstance, type WithWatch, batch, collection, computed, configure, effect, previous, readonly, select, shallowEqual, snapshot, state, withHistory, withWatch };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createBase, createListeners, getRegistry, notify, getConfig, scopedKey, getRegistered, log, createRenderState, registerByKey } from './chunk-ZCZG3Y2B.js';
2
- export { batch, configure, shallowEqual } from './chunk-ZCZG3Y2B.js';
1
+ import { createBase, createListeners, getRegistry, notify, getConfig, scopedKey, getRegistered, log, createMemoryState, registerByKey } from './chunk-4ZTPYOIR.js';
2
+ export { batch, configure, shallowEqual } from './chunk-4ZTPYOIR.js';
3
3
 
4
4
  // src/collection.ts
5
5
  function collection(key, options) {
@@ -177,7 +177,7 @@ function computed(deps, fn, options) {
177
177
  const hydratedPromise = Promise.all(deps.map((d) => d.hydrated)).then(() => void 0);
178
178
  return {
179
179
  key: instanceKey,
180
- scope: "render",
180
+ scope: "memory",
181
181
  get ready() {
182
182
  return readyPromise;
183
183
  },
@@ -423,7 +423,7 @@ function previous(source, options) {
423
423
  let resolveDestroyed;
424
424
  return {
425
425
  key: instanceKey,
426
- scope: "render",
426
+ scope: "memory",
427
427
  get ready() {
428
428
  return source.ready;
429
429
  },
@@ -505,7 +505,7 @@ function select(source, fn, options) {
505
505
  let resolveDestroyed;
506
506
  return {
507
507
  key: instanceKey,
508
- scope: "render",
508
+ scope: "memory",
509
509
  get ready() {
510
510
  return source.ready;
511
511
  },
@@ -550,7 +550,7 @@ function select(source, fn, options) {
550
550
  // src/factory.ts
551
551
  function createState(key, options) {
552
552
  if (!key) {
553
- throw new Error("[state] key must be a non-empty string.");
553
+ throw new Error("[gjendje] key must be a non-empty string.");
554
554
  }
555
555
  const config = getConfig();
556
556
  if (config.keyPattern && !config.keyPattern.test(key)) {
@@ -558,8 +558,8 @@ function createState(key, options) {
558
558
  `[gjendje] Key "${key}" does not match the configured keyPattern ${config.keyPattern}.`
559
559
  );
560
560
  }
561
- const rawScope = options.scope ?? config.scope ?? "render";
562
- const scope = rawScope === "memory" ? "render" : rawScope === "session" ? "tab" : rawScope;
561
+ const rawScope = options.scope ?? config.scope ?? "memory";
562
+ const scope = rawScope === "render" ? "memory" : rawScope;
563
563
  const rKey = scopedKey(key, scope);
564
564
  const existing = getRegistered(rKey);
565
565
  if (existing && !existing.isDestroyed) {
@@ -568,14 +568,14 @@ function createState(key, options) {
568
568
  }
569
569
  return existing;
570
570
  }
571
- if (scope === "render" && !options.ssr && !config.ssr) {
571
+ if (scope === "memory" && !options.ssr && !config.ssr) {
572
572
  if (options.sync) {
573
573
  log(
574
574
  "warn",
575
- `sync: true is ignored for scope "render". Only "local" and "bucket" scopes support cross-tab sync.`
575
+ `sync: true is ignored for scope "memory". Only "local" and "bucket" scopes support cross-tab sync.`
576
576
  );
577
577
  }
578
- const instance = createRenderState(key, rKey, options, config);
578
+ const instance = createMemoryState(key, rKey, options, config);
579
579
  registerByKey(rKey, key, scope, instance, config);
580
580
  return instance;
581
581
  }
@@ -593,14 +593,6 @@ function extractEntry(entry) {
593
593
  const key = keys[0];
594
594
  return [key, entry[key]];
595
595
  }
596
- var _deprecationWarned = /* @__PURE__ */ new Set();
597
- function warnDeprecated(name) {
598
- if (_deprecationWarned.has(name)) return;
599
- _deprecationWarned.add(name);
600
- console.warn(
601
- `[gjendje] ${name}() is deprecated and will be removed in the next major version. Use state.${name}() instead. Example: state.${name}({ key: value })`
602
- );
603
- }
604
596
  function _local(entry, options) {
605
597
  const [key, defaultValue] = extractEntry(entry);
606
598
  return createState(key, { ...options, default: defaultValue, scope: "local" });
@@ -640,25 +632,5 @@ _state.url = _url;
640
632
  _state.bucket = _bucket;
641
633
  _state.server = _server;
642
634
  var state = _state;
643
- function local(entry, options) {
644
- warnDeprecated("local");
645
- return _local(entry, options);
646
- }
647
- function session(entry, options) {
648
- warnDeprecated("session");
649
- return _session(entry, options);
650
- }
651
- function url(entry, options) {
652
- warnDeprecated("url");
653
- return _url(entry, options);
654
- }
655
- function server(entry, options) {
656
- warnDeprecated("server");
657
- return _server(entry, options);
658
- }
659
- function bucket(entry, options) {
660
- warnDeprecated("bucket");
661
- return _bucket(entry, options);
662
- }
663
635
 
664
- export { bucket, collection, computed, effect, local, previous, readonly, select, server, session, snapshot, state, url, withHistory, withWatch };
636
+ export { collection, computed, effect, previous, readonly, select, snapshot, state, withHistory, withWatch };
package/dist/server.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkXACGL7LY_cjs = require('./chunk-XACGL7LY.cjs');
3
+ var chunkMEVW62P4_cjs = require('./chunk-MEVW62P4.cjs');
4
4
  var async_hooks = require('async_hooks');
5
5
 
6
6
  var als = new async_hooks.AsyncLocalStorage();
@@ -9,7 +9,7 @@ async function withServerSession(fn) {
9
9
  return als.run(store, fn);
10
10
  }
11
11
  function createServerAdapter(key, defaultValue) {
12
- const listeners = chunkXACGL7LY_cjs.createListeners();
12
+ const listeners = chunkMEVW62P4_cjs.createListeners();
13
13
  function getStore() {
14
14
  return als.getStore();
15
15
  }
@@ -26,12 +26,12 @@ function createServerAdapter(key, defaultValue) {
26
26
  const store = getStore();
27
27
  if (!store) {
28
28
  throw new Error(
29
- "[state] Cannot set server-scoped state outside of a server session. Wrap your request handler with withServerSession()."
29
+ "[gjendje] Cannot set server-scoped state outside of a server session. Wrap your request handler with withServerSession()."
30
30
  );
31
31
  }
32
32
  store.set(key, value);
33
33
  lastNotifiedValue = value;
34
- chunkXACGL7LY_cjs.notify(notifyListeners);
34
+ chunkMEVW62P4_cjs.notify(notifyListeners);
35
35
  },
36
36
  subscribe: listeners.subscribe,
37
37
  destroy() {
@@ -39,7 +39,7 @@ function createServerAdapter(key, defaultValue) {
39
39
  }
40
40
  };
41
41
  }
42
- chunkXACGL7LY_cjs.registerServerAdapter(createServerAdapter);
42
+ chunkMEVW62P4_cjs.registerServerAdapter(createServerAdapter);
43
43
 
44
44
  exports.createServerAdapter = createServerAdapter;
45
45
  exports.withServerSession = withServerSession;
package/dist/server.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as Adapter } from './types-D-VJhL7I.cjs';
1
+ import { A as Adapter } from './types-DbzCHTo8.cjs';
2
2
 
3
3
  declare function withServerSession<T>(fn: () => T): Promise<T>;
4
4
  declare function createServerAdapter<T>(key: string, defaultValue: T): Adapter<T>;
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as Adapter } from './types-D-VJhL7I.js';
1
+ import { A as Adapter } from './types-DbzCHTo8.js';
2
2
 
3
3
  declare function withServerSession<T>(fn: () => T): Promise<T>;
4
4
  declare function createServerAdapter<T>(key: string, defaultValue: T): Adapter<T>;
package/dist/server.js CHANGED
@@ -1,4 +1,4 @@
1
- import { registerServerAdapter, createListeners, notify } from './chunk-ZCZG3Y2B.js';
1
+ import { registerServerAdapter, createListeners, notify } from './chunk-4ZTPYOIR.js';
2
2
  import { AsyncLocalStorage } from 'async_hooks';
3
3
 
4
4
  var als = new AsyncLocalStorage();
@@ -24,7 +24,7 @@ function createServerAdapter(key, defaultValue) {
24
24
  const store = getStore();
25
25
  if (!store) {
26
26
  throw new Error(
27
- "[state] Cannot set server-scoped state outside of a server session. Wrap your request handler with withServerSession()."
27
+ "[gjendje] Cannot set server-scoped state outside of a server session. Wrap your request handler with withServerSession()."
28
28
  );
29
29
  }
30
30
  store.set(key, value);
@@ -1,4 +1,4 @@
1
- type Scope = 'memory' | 'render' | 'session' | 'tab' | 'local' | 'url' | 'server' | 'bucket';
1
+ type Scope = 'memory' | 'render' | 'session' | 'local' | 'url' | 'server' | 'bucket';
2
2
  interface Adapter<T> {
3
3
  get(): T;
4
4
  set(value: T): void;
@@ -106,12 +106,12 @@ interface BucketOptions {
106
106
  * Scope to use if the Storage Buckets API is not available.
107
107
  * Defaults to 'local'.
108
108
  */
109
- fallback?: 'local' | 'session' | 'tab';
109
+ fallback?: 'local' | 'session';
110
110
  }
111
111
  interface StateOptions<T> {
112
112
  /** Initial / default value */
113
113
  default: T;
114
- /** Where state should live. Defaults to 'render'. */
114
+ /** Where state should live. Defaults to 'memory'. */
115
115
  scope?: Scope;
116
116
  /**
117
117
  * Storage bucket options. Required when scope is 'bucket'.
@@ -125,7 +125,7 @@ interface StateOptions<T> {
125
125
  serialize?: Serializer<T>;
126
126
  /**
127
127
  * Enable SSR safety. When true:
128
- * - On server: silently falls back to 'render' scope
128
+ * - On server: silently falls back to 'memory' scope
129
129
  * - On client before hydration: uses default value to match server output
130
130
  * - On client after hydration: reads real storage and emits update if different
131
131
  */
@@ -156,7 +156,7 @@ interface StateOptions<T> {
156
156
  * When true, any set() call is also sent to other open tabs,
157
157
  * and incoming changes from other tabs update this instance.
158
158
  *
159
- * Works with any persistent scope (local, tab, bucket).
159
+ * Works with `local` and `bucket` scopes only.
160
160
  */
161
161
  sync?: boolean;
162
162
  /**
@@ -1,4 +1,4 @@
1
- type Scope = 'memory' | 'render' | 'session' | 'tab' | 'local' | 'url' | 'server' | 'bucket';
1
+ type Scope = 'memory' | 'render' | 'session' | 'local' | 'url' | 'server' | 'bucket';
2
2
  interface Adapter<T> {
3
3
  get(): T;
4
4
  set(value: T): void;
@@ -106,12 +106,12 @@ interface BucketOptions {
106
106
  * Scope to use if the Storage Buckets API is not available.
107
107
  * Defaults to 'local'.
108
108
  */
109
- fallback?: 'local' | 'session' | 'tab';
109
+ fallback?: 'local' | 'session';
110
110
  }
111
111
  interface StateOptions<T> {
112
112
  /** Initial / default value */
113
113
  default: T;
114
- /** Where state should live. Defaults to 'render'. */
114
+ /** Where state should live. Defaults to 'memory'. */
115
115
  scope?: Scope;
116
116
  /**
117
117
  * Storage bucket options. Required when scope is 'bucket'.
@@ -125,7 +125,7 @@ interface StateOptions<T> {
125
125
  serialize?: Serializer<T>;
126
126
  /**
127
127
  * Enable SSR safety. When true:
128
- * - On server: silently falls back to 'render' scope
128
+ * - On server: silently falls back to 'memory' scope
129
129
  * - On client before hydration: uses default value to match server output
130
130
  * - On client after hydration: reads real storage and emits update if different
131
131
  */
@@ -156,7 +156,7 @@ interface StateOptions<T> {
156
156
  * When true, any set() call is also sent to other open tabs,
157
157
  * and incoming changes from other tabs update this instance.
158
158
  *
159
- * Works with any persistent scope (local, tab, bucket).
159
+ * Works with `local` and `bucket` scopes only.
160
160
  */
161
161
  sync?: boolean;
162
162
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gjendje",
3
- "version": "0.9.3",
3
+ "version": "1.0.0",
4
4
  "description": "Unified storage backend state management, built with TypeScript",
5
5
  "keywords": [
6
6
  "state",