pocket-state 0.1.9 → 0.1.11

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
@@ -14,6 +14,7 @@ Works seamlessly **inside React** with hooks or **outside React** with a simple
14
14
  - 🔌 Framework-agnostic – Works in plain TS/JS and React.
15
15
  - 🛠 Middleware – Logging, persistence, batching, devtools bridges, etc.
16
16
  - 🔔 Event Emitter – Subscribe to store and custom events.
17
+ - ⚖️ EqualityFn – Custom comparator (shallow by default, can use deep/custom).
17
18
  - ✅ TypeScript-first – Fully type-safe.
18
19
 
19
20
  ---
@@ -183,17 +184,33 @@ export function CounterComponent() {
183
184
 
184
185
  ---
185
186
 
186
- ## 🎯 Selectors
187
+ ## ⚖️ EqualityFn
187
188
 
188
- Selectors let you subscribe to **just part of the state**.
189
+ By default, `createStore` uses a shallow equality function to detect changes.
190
+ You can override this by providing a custom comparator as the 3rd argument:
189
191
 
190
- ```tsx
191
- function FlagDisplay() {
192
- const flag = useStore(counterStore, s => s.flag);
193
- return <Text>Flag is {flag ? 'ON' : 'OFF'}</Text>;
192
+ ```ts
193
+ import {createStore} from 'pocket-state';
194
+ import deepEqual from 'fast-deep-equal';
195
+
196
+ interface State {
197
+ count: number;
198
+ nested: {a: number; b: number};
194
199
  }
200
+
201
+ // shallow equality (default)
202
+ const store1 = createStore<State>({count: 0, nested: {a: 1, b: 2}});
203
+
204
+ // deep equality
205
+ const store2 = createStore<State>(
206
+ {count: 0, nested: {a: 1, b: 2}},
207
+ [],
208
+ deepEqual,
209
+ );
195
210
  ```
196
211
 
212
+ This is useful when working with nested state objects and you want to avoid unnecessary re-renders.
213
+
197
214
  ---
198
215
 
199
216
  ## 🧩 API Reference
@@ -224,6 +241,6 @@ Generates a custom hook for your store.
224
241
 
225
242
  ## 📜 License
226
243
 
227
- MIT — use it however you like.
244
+ MIT
228
245
 
229
- keywords: pocket-state, state-management, react, react-native, typescript, hooks, store
246
+ keywords: pocket-state, state-management, react, react-native, typescript, hooks, store, equalityFn
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pocket-state",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "tiny global store",
5
5
  "main": "src/index",
6
6
  "codegenConfig": {
@@ -10,7 +10,12 @@ export function createStore<T>(
10
10
  equalityFn?: (a: any, b: any) => boolean,
11
11
  ): Store<T> {
12
12
  const emitter: IEventEmitter = new EventEmitter();
13
- let state = initialState;
13
+ const _initialState = Array.isArray(initialState)
14
+ ? (initialState as any).slice()
15
+ : initialState && typeof initialState === 'object'
16
+ ? {...initialState}
17
+ : initialState;
18
+ let state = _initialState;
14
19
 
15
20
  const areEqual = equalityFn ?? shallow;
16
21
 
@@ -35,7 +40,7 @@ export function createStore<T>(
35
40
  );
36
41
 
37
42
  const getValue = ((key?: keyof T) => {
38
- if (!key) return state;
43
+ if (key === undefined) return state;
39
44
  return state[key];
40
45
  }) as UseStoreGet<T>;
41
46
 
@@ -70,18 +75,20 @@ export function createStore<T>(
70
75
  function setValue(
71
76
  patch: Partial<T> | ((state: T) => Partial<T> | Promise<Partial<T>>),
72
77
  ): void {
73
- (async () => {
74
- try {
75
- const resolved =
76
- typeof patch === 'function' ? await patch(state) : patch;
77
-
78
- if (resolved && typeof resolved === 'object') {
79
- setFn(resolved as Partial<T>);
80
- }
81
- } catch (error) {
82
- console.warn('[store.setValue] patch error:', error);
78
+ let resolved = typeof patch === 'function' ? patch(state) : patch;
79
+ if (resolved instanceof Promise) {
80
+ resolved
81
+ .then(res => {
82
+ if (res && typeof res === 'object') {
83
+ setFn(res as Partial<T>);
84
+ }
85
+ })
86
+ .catch(error => console.warn('[store.setValue] patch error:', error));
87
+ } else {
88
+ if (resolved && typeof resolved === 'object') {
89
+ setFn(resolved as Partial<T>);
83
90
  }
84
- })();
91
+ }
85
92
  }
86
93
 
87
94
  function setImmer(updater: (draft: Draft<T>) => void): void {
@@ -95,17 +102,17 @@ export function createStore<T>(
95
102
  }
96
103
  const delta = {} as Partial<T>;
97
104
  let changed = false;
98
- for (const k in nextState) {
99
- const nv = nextState[k];
100
- const ov = state[k];
105
+ for (const k in nextState as any) {
106
+ const nv = (nextState as any)[k];
107
+ const ov = (state as any)[k];
101
108
  if (nv !== ov) {
102
- delta[k] = nv;
109
+ (delta as any)[k] = nv;
103
110
  changed = true;
104
111
  }
105
112
  }
106
- for (const k in state) {
113
+ for (const k in state as any) {
107
114
  if (!(k in (nextState as any))) {
108
- delta[k] = undefined;
115
+ (delta as any)[k] = undefined;
109
116
  changed = true;
110
117
  }
111
118
  }
@@ -150,22 +157,23 @@ export function createStore<T>(
150
157
  }
151
158
 
152
159
  function getInitialValue(): T {
153
- if (Array.isArray(state)) {
154
- return (state as any).slice();
160
+ if (Array.isArray(_initialState)) {
161
+ return (_initialState as any).slice();
155
162
  }
156
- if (state && typeof state === 'object') {
157
- return {...state};
163
+ if (_initialState && typeof _initialState === 'object') {
164
+ return {..._initialState};
158
165
  }
159
- return state;
166
+ return _initialState;
160
167
  }
161
168
 
162
169
  function isDirty() {
163
- return !areEqual(state, initialState);
170
+ return !areEqual(state, _initialState);
164
171
  }
165
172
 
166
173
  function getNumberOfSubscriber() {
167
174
  return emitter.getNumberOfSubscriber();
168
175
  }
176
+
169
177
  return {
170
178
  getValue,
171
179
  getInitialValue,