@codeleap/store 6.8.0 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/array.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Returns a `Proxy` that mirrors every property access on the atom's current array value.
3
+ *
4
+ * When a function property (e.g. `push`, `splice`, `sort`) is accessed, the proxy wraps the call so that after the native method executes it writes the mutated array back to the store with `store.set`.
5
+ * This makes mutating array methods reactive: callers interact with a familiar `Array` API while nanostores' subscriber notifications fire automatically.
6
+ *
7
+ * Non-function properties (indices, `length`, etc.) are forwarded as-is.
8
+ */
9
+ export function arrayHandler(store) {
10
+ return new Proxy([], {
11
+ get(target, p, receiver) {
12
+ const val = store.get();
13
+ const property = val[p];
14
+ if (typeof property == 'function') {
15
+ return (...args) => {
16
+ const r = val[p](...args);
17
+ store.set(val);
18
+ return r;
19
+ };
20
+ }
21
+ return property;
22
+ }
23
+ });
24
+ }
25
+ /**
26
+ * Complete list of own property names on `Array.prototype`.
27
+ * Used by the `globalState` proxy to detect when a caller is accessing an array method so it can delegate to `arrayHandler` instead of the raw atom.
28
+ */
29
+ export const arrayOps = Object.getOwnPropertyNames(Array.prototype);
30
+ //# sourceMappingURL=array.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.js","sourceRoot":"","sources":["../src/array.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAkB,KAAsB;IAClE,OAAO,IAAI,KAAK,CAAC,EAAE,EAAE;QACnB,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ;YACrB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAkC,CAAA;YAEvD,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;YAEvB,IAAG,OAAO,QAAQ,IAAI,UAAU,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,IAAe,EAAE,EAAE;oBAC5B,MAAM,CAAC,GAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;oBAE1B,KAAK,CAAC,GAAG,CAAC,GAAQ,CAAC,CAAA;oBAEnB,OAAO,CAAC,CAAA;gBACV,CAAC,CAAA;YACH,CAAC;YAED,OAAO,QAAQ,CAAA;QACjB,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA"}
@@ -0,0 +1,71 @@
1
+ import { useStore } from '@nanostores/react';
2
+ import { setPersistentEngine, persistentAtom } from '@nanostores/persistent';
3
+ import { atom } from 'nanostores';
4
+ import { stateAssign, useStateSelector } from './utils';
5
+ import { arrayHandler, arrayOps } from './array';
6
+ const defaultConfig = {
7
+ persistKey: undefined,
8
+ };
9
+ /**
10
+ * Registers the storage engine used by all persistent atoms in this process.
11
+ * Must be called once at app startup — before any `globalState` with a `persistKey` is created — otherwise the persistent atom falls back to an in-memory store.
12
+ * Thin re-export of `@nanostores/persistent`'s `setPersistentEngine`.
13
+ */
14
+ export const setGlobalStatePersistor = setPersistentEngine;
15
+ /**
16
+ * Creates a `GlobalState<T>` atom backed by nanostores.
17
+ *
18
+ * The returned value is a `Proxy` over the raw atom that intercepts property access to:
19
+ * - Route `use` / `get` through optional selector functions so components subscribe only to the slice they need.
20
+ * - Merge partial updates on `set` for object atoms (primitives and arrays are replaced outright).
21
+ * - Expose `reset` as an alias for the raw `WritableAtom.set`, bypassing merge logic.
22
+ * - Forward any `Array.prototype` property access to `arrayHandler`, which commits mutations back to the store.
23
+ *
24
+ * When `config.persistKey` is provided, the atom is created with `persistentAtom` and serialised via `JSON.stringify` / `JSON.parse`.
25
+ * Call `setGlobalStatePersistor` before using persistence so the engine is ready.
26
+ */
27
+ export function globalState(value, config = defaultConfig) {
28
+ const { persistKey } = config;
29
+ const isPersistState = typeof persistKey === 'string';
30
+ const store = isPersistState ? persistentAtom(persistKey, value, {
31
+ encode: JSON.stringify,
32
+ decode: JSON.parse,
33
+ }) : atom(value);
34
+ return new Proxy(store, {
35
+ get(target, prop, receiver) {
36
+ if (prop === 'use') {
37
+ return (selector) => {
38
+ if (!selector)
39
+ return useStore(target);
40
+ return useStateSelector(target, selector);
41
+ };
42
+ }
43
+ if (prop === 'get') {
44
+ return (selector) => {
45
+ if (!selector)
46
+ return target.get();
47
+ return selector(target.get());
48
+ };
49
+ }
50
+ if (prop === 'set') {
51
+ return (newValue) => {
52
+ const value = stateAssign(newValue, target.get());
53
+ target.set(value);
54
+ };
55
+ }
56
+ if (prop == 'reset') {
57
+ return Reflect.get(target, 'set', receiver);
58
+ }
59
+ if (arrayOps.includes(prop)) {
60
+ const currentValue = target.get();
61
+ if (!Array.isArray(currentValue)) {
62
+ throw new Error('Cannot call array methods on a non array store');
63
+ }
64
+ const handle = arrayHandler(target);
65
+ return Reflect.get(handle, prop, receiver);
66
+ }
67
+ return Reflect.get(target, prop, receiver);
68
+ },
69
+ });
70
+ }
71
+ //# sourceMappingURL=globalState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globalState.js","sourceRoot":"","sources":["../src/globalState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC5E,OAAO,EAAE,IAAI,EAAgB,MAAM,YAAY,CAAA;AAE/C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAEhD,MAAM,aAAa,GAAsB;IACvC,UAAU,EAAE,SAAS;CACtB,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,mBAAmB,CAAA;AAE1D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,WAAW,CAAI,KAAQ,EAAE,SAA4B,aAAa;IAChF,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAAA;IAE7B,MAAM,cAAc,GAAG,OAAO,UAAU,KAAK,QAAQ,CAAA;IAErD,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,cAAc,CAAI,UAAU,EAAE,KAAK,EAAE;QAClE,MAAM,EAAE,IAAI,CAAC,SAAS;QACtB,MAAM,EAAE,IAAI,CAAC,KAAK;KACnB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAEhB,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE;QACtB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ;YACxB,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,OAAO,CAAC,QAAgC,EAAE,EAAE;oBAC1C,IAAI,CAAC,QAAQ;wBAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAA;oBACtC,OAAO,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;gBAC3C,CAAC,CAAA;YACH,CAAC;YAED,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,OAAO,CAAC,QAAgC,EAAE,EAAE;oBAC1C,IAAI,CAAC,QAAQ;wBAAE,OAAO,MAAM,CAAC,GAAG,EAAE,CAAA;oBAClC,OAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;gBAC/B,CAAC,CAAA;YACH,CAAC;YAED,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;gBACnB,OAAO,CAAC,QAAiC,EAAE,EAAE;oBAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAA;oBACjD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;gBACnB,CAAC,CAAA;YACH,CAAC;YAED,IAAI,IAAI,IAAI,OAAO,EAAE,CAAC;gBACpB,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;YAC7C,CAAC;YAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAc,CAAC,EAAE,CAAC;gBACtC,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,EAAE,CAAA;gBAEjC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;oBACjC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;gBACnE,CAAC;gBAED,MAAM,MAAM,GAAG,YAAY,CAAC,MAA6B,CAAC,CAAA;gBAE1D,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;YAC5C,CAAC;YAED,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;QAC5C,CAAC;KACF,CAA8B,CAAA;AACjC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './globalState';
2
+ export * from './types';
3
+ export * from './utils';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/dist/utils.js ADDED
@@ -0,0 +1,67 @@
1
+ import { useStore } from '@nanostores/react';
2
+ import { useMemo } from 'react';
3
+ /** Type guard that distinguishes a functional setter from a plain value so `resolveSetter` can call it correctly. */
4
+ function isFunctionSetter(x) {
5
+ return typeof x === 'function';
6
+ }
7
+ /** Evaluates a `StateSetter`: calls it with `currentValue` if it is a function, otherwise returns it as-is. */
8
+ function resolveSetter(setter, currentValue) {
9
+ if (isFunctionSetter(setter)) {
10
+ return setter(currentValue);
11
+ }
12
+ return setter;
13
+ }
14
+ /**
15
+ * Resolves `newValue` against `stateValue` and returns the next state.
16
+ *
17
+ * For object atoms the resolved value is shallow-merged onto the existing state, so callers only need to supply changed keys.
18
+ * For primitives and arrays the resolved value replaces the current state entirely.
19
+ */
20
+ export function stateAssign(newValue, stateValue) {
21
+ const resolvedValue = resolveSetter(newValue, stateValue);
22
+ if (typeof stateValue === 'object' && stateValue !== null) {
23
+ return Object.assign(Object.assign({}, stateValue), resolvedValue);
24
+ }
25
+ return resolvedValue;
26
+ }
27
+ /**
28
+ * Derives a virtual `WritableAtom<R>` that projects a slice of a parent atom through `selector`.
29
+ *
30
+ * - `get` — applies `selector` to the parent snapshot without subscribing.
31
+ * - `listen` — subscribes to the parent atom and calls `listener` with the projected value on every change.
32
+ * - `set` — requires a `deselector` to map the slice value back to a `Partial<T>`, then merges it into the parent atom via `stateAssign`. Throws if `deselector` is absent.
33
+ *
34
+ * The returned object satisfies the `WritableAtom<R>` interface so it can be passed anywhere a nanostores atom is expected, including `useStore`.
35
+ */
36
+ export const createStateSlice = (store, selector, deselector) => ({
37
+ get: () => selector(store.get()),
38
+ listen: (listener) => {
39
+ return store.listen((state) => {
40
+ listener(selector(state));
41
+ });
42
+ },
43
+ set(v) {
44
+ if (!deselector) {
45
+ throw new Error('[createStateSelector] deselector must be implemented to call set on state slices');
46
+ }
47
+ const parsed = deselector(v);
48
+ const newValue = stateAssign(parsed, store.get());
49
+ store.set(newValue);
50
+ },
51
+ get value() {
52
+ return store.value;
53
+ }
54
+ });
55
+ /**
56
+ * React hook that subscribes a component to a derived slice of an atom.
57
+ *
58
+ * Internally it memoises a `createStateSlice` projection keyed on `selector` identity, then passes the virtual atom to `useStore`.
59
+ * Components re-render only when the selected value changes — not on every atom update — which avoids the cost of subscribing to the full atom shape.
60
+ *
61
+ * Caution: because the slice is memoised on `selector` reference, prefer stable (module-level or `useCallback`) selector functions to avoid unnecessary slice recreation.
62
+ */
63
+ export function useStateSelector(store, selector) {
64
+ const slice = useMemo(() => createStateSlice(store, selector), [selector]);
65
+ return useStore(slice);
66
+ }
67
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAG/B,qHAAqH;AACrH,SAAS,gBAAgB,CAAI,CAAM;IACjC,OAAO,OAAO,CAAC,KAAK,UAAU,CAAA;AAChC,CAAC;AAED,+GAA+G;AAC/G,SAAS,aAAa,CAAI,MAAsB,EAAE,YAAc;IAC9D,IAAI,gBAAgB,CAAI,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,YAAY,CAAC,CAAA;IAC7B,CAAC;IAED,OAAO,MAAW,CAAA;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAI,QAAiC,EAAE,UAAa;IAC7E,MAAM,aAAa,GAAG,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACzD,IACE,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,KAAK,IAAI,EACrD,CAAC;QACD,OAAO,gCACF,UAAU,GACV,aAAa,CACZ,CAAA;IACR,CAAC;IAED,OAAO,aAAkB,CAAA;AAC3B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAQ,EACR,QAAyB,EACzB,UAAsC,EACtC,EAAE,CAAC,CAAC;IACF,GAAG,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAChC,MAAM,EAAE,CAAC,QAA4B,EAAE,EAAE;QACvC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAC5B,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC;IACD,GAAG,CAAC,CAAI;QACN,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAA;QACrG,CAAC;QAED,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;QAE5B,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;QAEjD,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACrB,CAAC;IACD,IAAI,KAAK;QACP,OAAO,KAAK,CAAC,KAAK,CAAA;IACpB,CAAC;CACkB,CAAA,CAAA;AAEvB;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAQ,EACR,QAAyB;IAEzB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAE1E,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxB,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codeleap/store",
3
- "version": "6.8.0",
4
- "main": "src/index.ts",
3
+ "version": "7.0.1",
4
+ "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
7
7
  ".": {
@@ -22,7 +22,7 @@
22
22
  "directory": "packages/store"
23
23
  },
24
24
  "devDependencies": {
25
- "@codeleap/config": "6.8.0",
25
+ "@codeleap/config": "7.0.1",
26
26
  "ts-node-dev": "1.1.8"
27
27
  },
28
28
  "scripts": {