@hanzogui/use-store 7.0.0 → 7.3.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/LICENSE CHANGED
@@ -1,21 +1,42 @@
1
- MIT License
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026-present, Hanzo AI, Inc.
4
+
5
+ Portions of this software are derived from upstream code originally licensed under
6
+ the MIT License, with the following copyright notices retained per its terms:
2
7
 
3
8
  Copyright (c) 2020 Nate Wienert
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
9
+ Copyright (c) 2015-present, Nicolas Gallagher.
10
+ Copyright (c) 2015-present, Facebook, Inc.
11
+ Copyright (c) 2021 Radix
12
+ Copyright (c) 2017 Carmelo Pullara
13
+ Copyright (c) 2018 Framer B.V.
14
+ Copyright (c) 2022 WorkOS
15
+
16
+ All rights reserved.
17
+
18
+ Redistribution and use in source and binary forms, with or without
19
+ modification, are permitted provided that the following conditions are met:
20
+
21
+ 1. Redistributions of source code must retain the above copyright notice, this
22
+ list of conditions and the following disclaimer.
23
+
24
+ 2. Redistributions in binary form must reproduce the above copyright notice,
25
+ this list of conditions and the following disclaimer in the documentation
26
+ and/or other materials provided with the distribution.
27
+
28
+ 3. Neither the name of the copyright holder nor the names of its contributors
29
+ may be used to endorse or promote products derived from this software
30
+ without specific prior written permission.
31
+
32
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42
+ POSSIBILITY OF SUCH DAMAGE.
@@ -58,8 +58,7 @@ var import_helpers = require("./helpers.cjs");
58
58
  var import_useStoreDebug = require("./useStoreDebug.cjs");
59
59
  const idFn = _ => _;
60
60
  function useStore(StoreKlass, props, options = import_constants.defaultOptions) {
61
- const info = getOrCreateStoreInfo(StoreKlass, props, options);
62
- return useStoreFromInfo(info, options.selector, options);
61
+ return useStoreFromInfo(getOrCreateStoreInfo(StoreKlass, props, options), options.selector, options);
63
62
  }
64
63
  function useStoreDebug(StoreKlass, props) {
65
64
  return useStore(StoreKlass, props, {
@@ -73,9 +72,7 @@ function useGlobalStore(instance, debug) {
73
72
  const store = instance[import_constants.UNWRAP_PROXY];
74
73
  const uid = (0, import_helpers.getStoreUid)(store.constructor, store.props);
75
74
  const info = import_helpers.cache.get(uid);
76
- if (!info) {
77
- throw new Error(`This store not created using createStore()`);
78
- }
75
+ if (!info) throw new Error(`This store not created using createStore()`);
79
76
  return useStoreFromInfo(info, void 0, {
80
77
  debug
81
78
  });
@@ -84,9 +81,7 @@ function useGlobalStoreSelector(instance, selector, debug) {
84
81
  const store = instance[import_constants.UNWRAP_PROXY];
85
82
  const uid = (0, import_helpers.getStoreUid)(store.constructor, store.props);
86
83
  const info = import_helpers.cache.get(uid);
87
- if (!info) {
88
- throw new Error(`This store not created using createStore()`);
89
- }
84
+ if (!info) throw new Error(`This store not created using createStore()`);
90
85
  return useStoreFromInfo(info, selector, {
91
86
  debug
92
87
  });
@@ -134,16 +129,10 @@ function onCreateStore(cb) {
134
129
  };
135
130
  }
136
131
  function getOrCreateStoreInfo(StoreKlass, props, options, propsKeyCalculated) {
137
- if (!StoreKlass) {
138
- return null;
139
- }
132
+ if (!StoreKlass) return null;
140
133
  const uid = (0, import_helpers.getStoreUid)(StoreKlass, propsKeyCalculated ?? props);
141
- if (!options?.avoidCache && import_helpers.cache.has(uid)) {
142
- return import_helpers.cache.get(uid);
143
- }
144
- if (options?.refuseCreation) {
145
- throw new Error(`No store exists (${StoreKlass.name}) with props: ${props}`);
146
- }
134
+ if (!options?.avoidCache && import_helpers.cache.has(uid)) return import_helpers.cache.get(uid);
135
+ if (options?.refuseCreation) throw new Error(`No store exists (${StoreKlass.name}) with props: ${props}`);
147
136
  const storeInstance = new StoreKlass(props);
148
137
  storeInstance.props = props;
149
138
  const getters = {};
@@ -152,15 +141,7 @@ function getOrCreateStoreInfo(StoreKlass, props, options, propsKeyCalculated) {
152
141
  const descriptors = (0, import_helpers.getStoreDescriptors)(storeInstance);
153
142
  for (const key in descriptors) {
154
143
  const descriptor = descriptors[key];
155
- if (typeof descriptor.value === "function") {
156
- actions[key] = descriptor.value;
157
- } else if (typeof descriptor.get === "function") {
158
- getters[key] = descriptor.get;
159
- } else {
160
- if (key !== "props" && key[0] !== "_") {
161
- stateKeys.add(key);
162
- }
163
- }
144
+ if (typeof descriptor.value === "function") actions[key] = descriptor.value;else if (typeof descriptor.get === "function") getters[key] = descriptor.get;else if (key !== "props" && key[0] !== "_") stateKeys.add(key);
164
145
  }
165
146
  const keyComparators = storeInstance["_comparators"];
166
147
  const listeners = /* @__PURE__ */new Set();
@@ -191,17 +172,13 @@ function getOrCreateStoreInfo(StoreKlass, props, options, propsKeyCalculated) {
191
172
  },
192
173
  triggerUpdate: () => {
193
174
  storeInfo.version = (storeInfo.version + 1) % Number.MAX_SAFE_INTEGER;
194
- for (const cb of listeners) {
195
- cb();
196
- }
175
+ for (const cb of listeners) cb();
197
176
  }
198
177
  };
199
178
  const store = createProxiedStore(
200
179
  // we assign store right after and proxiedStore never accesses it until later on
201
180
  storeInfo);
202
- if (process.env.NODE_ENV === "development") {
203
- allStores[StoreKlass.name + uid] = store;
204
- }
181
+ if (process.env.NODE_ENV === "development") allStores[StoreKlass.name + uid] = store;
205
182
  store.mount?.();
206
183
  storeInfo.store = store;
207
184
  const result = storeInfo;
@@ -210,18 +187,12 @@ function getOrCreateStoreInfo(StoreKlass, props, options, propsKeyCalculated) {
210
187
  return result;
211
188
  }
212
189
  const allStores = {};
213
- if (process.env.NODE_ENV === "development") {
214
- globalThis["Store"] ||= allStores;
215
- }
190
+ if (process.env.NODE_ENV === "development") globalThis["Store"] ||= allStores;
216
191
  const emptyObj = {};
217
192
  const selectKeys = (obj, keys) => {
218
- if (!keys.length) {
219
- return emptyObj;
220
- }
193
+ if (!keys.length) return emptyObj;
221
194
  const res = {};
222
- for (const key of keys) {
223
- res[key] = obj[key];
224
- }
195
+ for (const key of keys) res[key] = obj[key];
225
196
  return res;
226
197
  };
227
198
  let isInReaction = false;
@@ -232,14 +203,12 @@ function useStoreFromInfo(info, userSelector, options) {
232
203
  const store = info?.store;
233
204
  const internal = import_react.default.useRef(void 0);
234
205
  const component = (0, import_useStoreDebug.useCurrentComponent)();
235
- if (!internal.current) {
236
- internal.current = {
237
- component,
238
- tracked: /* @__PURE__ */new Set(),
239
- last: null,
240
- lastKeys: null
241
- };
242
- }
206
+ if (!internal.current) internal.current = {
207
+ component,
208
+ tracked: /* @__PURE__ */new Set(),
209
+ last: null,
210
+ lastKeys: null
211
+ };
243
212
  const curInternal = internal.current;
244
213
  const shouldPrintDebug = options?.debug;
245
214
  const getSnapshot = import_react.default.useCallback(() => {
@@ -249,66 +218,46 @@ function useStoreFromInfo(info, userSelector, options) {
249
218
  const keys = [...(!isTracking ? info.stateKeys : curInternal2.tracked)];
250
219
  const nextKeys = `${info.version}${keys.join("")}${userSelector || ""}`;
251
220
  const lastKeys = curInternal2.lastKeys;
252
- if (nextKeys === curInternal2.lastKeys) {
253
- return curInternal2.last;
254
- }
221
+ if (nextKeys === curInternal2.lastKeys) return curInternal2.last;
255
222
  curInternal2.lastKeys = nextKeys;
256
223
  let snap;
257
224
  info.disableTracking = true;
258
225
  const last = curInternal2.last;
259
- if (userSelector) {
260
- snap = userSelector(store);
261
- } else {
262
- snap = selectKeys(store, keys);
263
- }
226
+ if (userSelector) snap = userSelector(store);else snap = selectKeys(store, keys);
264
227
  info.disableTracking = false;
265
228
  const isUnchanged = !userSelector && !isTracking && last || typeof last !== "undefined" && (0, import_comparators.isEqualSubsetShallow)(last, snap, {
266
229
  keyComparators: info.keyComparators
267
230
  });
268
- if (shouldPrintDebug) {
269
- console.info("\u{1F311} getSnapshot", {
270
- storeState: selectKeys(store, Object.keys(store)),
271
- userSelector,
272
- info,
273
- isUnchanged,
274
- component,
275
- keys,
276
- last,
277
- snap,
278
- curInternal: curInternal2,
279
- nextKeys,
280
- lastKeys
281
- });
282
- }
283
- if (isUnchanged) {
284
- return last;
285
- }
231
+ if (shouldPrintDebug) console.info("🌑 getSnapshot", {
232
+ storeState: selectKeys(store, Object.keys(store)),
233
+ userSelector,
234
+ info,
235
+ isUnchanged,
236
+ component,
237
+ keys,
238
+ last,
239
+ snap,
240
+ curInternal: curInternal2,
241
+ nextKeys,
242
+ lastKeys
243
+ });
244
+ if (isUnchanged) return last;
286
245
  curInternal2.last = snap;
287
246
  return snap;
288
247
  }, [store]);
289
248
  const state = import_react.default.useSyncExternalStore(info?.subscribe || idFn, getSnapshot, getSnapshot);
290
- if (!info || !store || !state) {
291
- return state;
292
- }
293
- if (userSelector) {
294
- return state;
295
- }
249
+ if (!info || !store || !state) return state;
250
+ if (userSelector) return state;
296
251
  return new Proxy(store, {
297
252
  get(target, key) {
298
253
  const curVal = Reflect.get(target, key);
299
- if (isInReaction) {
300
- return curVal;
301
- }
254
+ if (isInReaction) return curVal;
302
255
  const keyString = key;
303
256
  if (info.stateKeys.has(keyString) || keyString in info.getters) {
304
- if (shouldPrintDebug) {
305
- console.info("\u{1F440} tracking", keyString);
306
- }
257
+ if (shouldPrintDebug) console.info("👀 tracking", keyString);
307
258
  curInternal.tracked.add(keyString);
308
259
  }
309
- if (Reflect.has(state, key)) {
310
- return Reflect.get(state, key);
311
- }
260
+ if (Reflect.has(state, key)) return Reflect.get(state, key);
312
261
  return curVal;
313
262
  }
314
263
  });
@@ -332,32 +281,22 @@ function createProxiedStore(storeInfo) {
332
281
  let didSet = false;
333
282
  const wrappedActions = {};
334
283
  for (const key in actions) {
335
- if (key === "subscribe") {
336
- continue;
337
- }
284
+ if (key === "subscribe") continue;
338
285
  const actionFn = actions[key];
339
286
  const isGetFn = key.startsWith("get");
340
287
  wrappedActions[key] = function useStoreAction(...args) {
341
288
  let res;
342
- if (isGetFn || gettersState.isGetting) {
343
- return Reflect.apply(actionFn, proxiedStore, args);
344
- }
345
- if (process.env.NODE_ENV === "development" && shouldDebug2) {
346
- console.info("(debug) startAction", key);
347
- }
289
+ if (isGetFn || gettersState.isGetting) return Reflect.apply(actionFn, proxiedStore, args);
290
+ if (process.env.NODE_ENV === "development" && shouldDebug2) console.info("(debug) startAction", key);
348
291
  res = Reflect.apply(actionFn, proxiedStore, args);
349
- if (res instanceof Promise) {
350
- return res.then(finishAction);
351
- }
292
+ if (res instanceof Promise) return res.then(finishAction);
352
293
  finishAction();
353
294
  return res;
354
295
  };
355
296
  if (process.env.NODE_ENV === "development") {
356
297
  let hashCode = function (str) {
357
298
  let hash = 0;
358
- for (let i = 0; i < str.length; i++) {
359
- hash = str.charCodeAt(i) + ((hash << 5) - hash);
360
- }
299
+ for (let i = 0; i < str.length; i++) hash = str.charCodeAt(i) + ((hash << 5) - hash);
361
300
  return hash;
362
301
  },
363
302
  strColor = function (str) {
@@ -368,10 +307,7 @@ function createProxiedStore(storeInfo) {
368
307
  wrappedActions[key] = new Proxy(ogAction, {
369
308
  apply(target, thisArg, args) {
370
309
  const isDebugging = shouldDebug2 || storeInfo.debug;
371
- const shouldLog = process.env.LOG_LEVEL !== "0" && (isDebugging || import_configureUseStore.configureOpts.logLevel !== "error");
372
- if (!shouldLog) {
373
- return Reflect.apply(target, thisArg, args);
374
- }
310
+ if (!(process.env.LOG_LEVEL !== "0" && (isDebugging || import_configureUseStore.configureOpts.logLevel !== "error"))) return Reflect.apply(target, thisArg, args);
375
311
  setters = /* @__PURE__ */new Set();
376
312
  const curSetters = setters;
377
313
  const isTopLevelLogger = logStack.size == 0;
@@ -390,18 +326,12 @@ function createProxiedStore(storeInfo) {
390
326
  const color = strColor(name);
391
327
  const simpleArgs = args.map(import_helpers.simpleStr);
392
328
  logs.add([`%c \u{1F311} ${id} ${name.padStart(isTopLevelLogger ? 8 : 4)}%c.${key}(${simpleArgs.join(", ")})${isTopLevelLogger && logStack.size > 1 ? ` (+${logStack.size - 1})` : ""}`, `color: ${color};`, "color: black;"]);
393
- if (curSetters.size) {
394
- curSetters.forEach(({
395
- key: key2,
396
- value
397
- }) => {
398
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
399
- logs.add([` SET ${key2} ${value}`, value]);
400
- } else {
401
- logs.add([` SET ${key2}`, value]);
402
- }
403
- });
404
- }
329
+ if (curSetters.size) curSetters.forEach(({
330
+ key: key2,
331
+ value
332
+ }) => {
333
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") logs.add([` SET ${key2} ${value}`, value]);else logs.add([` SET ${key2}`, value]);
334
+ });
405
335
  if (isTopLevelLogger) {
406
336
  let error = null;
407
337
  try {
@@ -425,19 +355,13 @@ function createProxiedStore(storeInfo) {
425
355
  console.info(...log);
426
356
  console.groupEnd();
427
357
  }
428
- } else {
429
- console.info("Weird log", head, ...rest);
430
- }
358
+ } else console.info("Weird log", head, ...rest);
431
359
  }
432
360
  } catch (err) {
433
361
  error = err;
434
362
  }
435
- for (const _ of logStack) {
436
- console.groupEnd();
437
- }
438
- if (error) {
439
- console.error(`error loggin`, error);
440
- }
363
+ for (const _ of logStack) console.groupEnd();
364
+ if (error) console.error(`error loggin`, error);
441
365
  logStack.clear();
442
366
  }
443
367
  return res;
@@ -448,11 +372,9 @@ function createProxiedStore(storeInfo) {
448
372
  }
449
373
  }
450
374
  const finishAction = val => {
451
- if (process.env.NODE_ENV === "development" && shouldDebug2) {
452
- console.info("(debug) finishAction", {
453
- didSet
454
- });
455
- }
375
+ if (process.env.NODE_ENV === "development" && shouldDebug2) console.info("(debug) finishAction", {
376
+ didSet
377
+ });
456
378
  if (didSet) {
457
379
  storeInfo.triggerUpdate();
458
380
  didSet = false;
@@ -461,55 +383,32 @@ function createProxiedStore(storeInfo) {
461
383
  };
462
384
  let isTriggering = false;
463
385
  const proxiedStore = new Proxy(storeInstance, {
464
- // GET
465
386
  get(_, key) {
466
- if (key in wrappedActions) {
467
- return wrappedActions[key];
468
- }
469
- if (key in passThroughKeys) {
470
- return Reflect.get(storeInstance, key);
471
- }
472
- if (key === import_constants.UNWRAP_PROXY) {
473
- return storeInstance;
474
- }
475
- if (key === import_helpers.UNWRAP_STORE_INFO) {
476
- return storeInfo;
477
- }
478
- if (storeAccessTrackers.size) {
479
- storeAccessTrackers.forEach(cb => cb(storeInfo));
480
- }
481
- if (typeof key !== "string") {
482
- return Reflect.get(storeInstance, key);
483
- }
387
+ if (key in wrappedActions) return wrappedActions[key];
388
+ if (key in passThroughKeys) return Reflect.get(storeInstance, key);
389
+ if (key === import_constants.UNWRAP_PROXY) return storeInstance;
390
+ if (key === import_helpers.UNWRAP_STORE_INFO) return storeInfo;
391
+ if (storeAccessTrackers.size) storeAccessTrackers.forEach(cb => cb(storeInfo));
392
+ if (typeof key !== "string") return Reflect.get(storeInstance, key);
484
393
  if (!storeInfo.disableTracking) {
485
- if (gettersState.isGetting) {
486
- gettersState.curGetKeys.add(key);
487
- } else {}
394
+ if (gettersState.isGetting) gettersState.curGetKeys.add(key);
488
395
  }
489
396
  if (key in getters) {
490
- if (getCache.has(key)) {
491
- return getCache.get(key);
492
- }
397
+ if (getCache.has(key)) return getCache.get(key);
493
398
  curGetKeys.clear();
494
399
  const isSubGetter = gettersState.isGetting;
495
400
  gettersState.isGetting = true;
496
401
  const res = getters[key].call(proxiedStore);
497
- if (!isSubGetter) {
498
- gettersState.isGetting = false;
499
- }
402
+ if (!isSubGetter) gettersState.isGetting = false;
500
403
  for (const gk of curGetKeys) {
501
- if (!depsToGetter.has(gk)) {
502
- depsToGetter.set(gk, /* @__PURE__ */new Set());
503
- }
504
- const cur = depsToGetter.get(gk);
505
- cur.add(key);
404
+ if (!depsToGetter.has(gk)) depsToGetter.set(gk, /* @__PURE__ */new Set());
405
+ depsToGetter.get(gk).add(key);
506
406
  }
507
407
  getCache.set(key, res);
508
408
  return res;
509
409
  }
510
410
  return Reflect.get(storeInstance, key);
511
411
  },
512
- // SET
513
412
  set(target, key, value, receiver) {
514
413
  const cur = Reflect.get(target, key);
515
414
  const res = Reflect.set(target, key, value, receiver);
@@ -521,16 +420,12 @@ function createProxiedStore(storeInfo) {
521
420
  key,
522
421
  value
523
422
  });
524
- if (getShouldDebug(storeInfo)) {
525
- console.info("(debug) SET", res, key, value);
526
- }
527
- }
528
- if (process.env.NODE_ENV === "development" && shouldDebug2) {
529
- console.info("SET...", {
530
- key,
531
- value
532
- });
423
+ if (getShouldDebug(storeInfo)) console.info("(debug) SET", res, key, value);
533
424
  }
425
+ if (process.env.NODE_ENV === "development" && shouldDebug2) console.info("SET...", {
426
+ key,
427
+ value
428
+ });
534
429
  }
535
430
  if (!isTriggering) {
536
431
  isTriggering = true;
@@ -546,14 +441,10 @@ function createProxiedStore(storeInfo) {
546
441
  function clearGetterCache(setKey) {
547
442
  const parentGetters = depsToGetter.get(setKey);
548
443
  getCache.delete(setKey);
549
- if (!parentGetters) {
550
- return;
551
- }
444
+ if (!parentGetters) return;
552
445
  for (const gk of parentGetters) {
553
446
  getCache.delete(gk);
554
- if (depsToGetter.has(gk)) {
555
- clearGetterCache(gk);
556
- }
447
+ if (depsToGetter.has(gk)) clearGetterCache(gk);
557
448
  }
558
449
  }
559
450
  return proxiedStore;
@@ -572,6 +463,5 @@ function getShouldDebug(storeInfo) {
572
463
  const info = {
573
464
  storeInstance: storeInfo.store
574
465
  };
575
- const trackers = storeInfo.trackers;
576
- return [...trackers].some(tracker => tracker.component && (0, import_useStoreDebug.shouldDebug)(tracker.component, info));
466
+ return [...storeInfo.trackers].some(tracker => tracker.component && (0, import_useStoreDebug.shouldDebug)(tracker.component, info));
577
467
  }