@slimlib/store 1.0.0 → 1.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/README.md CHANGED
@@ -40,6 +40,9 @@ Publish/subscribe/read pattern implementation. Ment to be used in components / s
40
40
 
41
41
  `Map`, `Set`, `WeakMap`, `WeakSet` cannot be used as values in current implementation.
42
42
 
43
+ Mixing proxied values and values from underlying object can fail for cases where code needs checking for equality.
44
+
45
+ For example searching array element from underlying object in proxified array will fail.
43
46
  # License
44
47
 
45
48
  [MIT](./LICENSE)
package/dist/index.cjs CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ const unwrap = Symbol();
6
+ const unwrapValue = (value) => (value != null && value[unwrap]) || value;
5
7
  const createStoreFactory = (notifyAfterCreation) => {
6
8
  return (object = {}) => {
7
9
  let willNotifyNextTick = false;
@@ -21,14 +23,17 @@ const createStoreFactory = (notifyAfterCreation) => {
21
23
  const handler = {
22
24
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
25
  set(target, p, value, receiver) {
24
- if (Reflect.get(target, p, receiver) !== value) {
25
- Reflect.set(target, p, value, receiver);
26
+ const realValue = unwrapValue(value);
27
+ if (Reflect.get(target, p, receiver) !== realValue) {
28
+ Reflect.set(target, p, realValue, receiver);
26
29
  enqueueNotification();
27
30
  }
28
31
  return true;
29
32
  },
30
33
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
34
  get(target, p, receiver) {
35
+ if (p === unwrap)
36
+ return target;
32
37
  const value = Reflect.get(target, p, receiver);
33
38
  return value !== null && typeof value === 'object' && !(value instanceof RegExp) ? createProxy(value) : value;
34
39
  },
package/dist/index.d.ts CHANGED
@@ -2,6 +2,6 @@ export declare type StoreCallback<T> = (value: T) => void;
2
2
  export declare type UnsubscribeCallback = () => void;
3
3
  export interface Store<T> {
4
4
  (cb: StoreCallback<T>): UnsubscribeCallback;
5
- (): T;
5
+ (): Readonly<T>;
6
6
  }
7
7
  export declare const createStoreFactory: (notifyAfterCreation: boolean) => <T extends object>(object?: T) => [T, Store<T>];
package/dist/index.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ const unwrap = Symbol();
2
+ const unwrapValue = (value) => (value != null && value[unwrap]) || value;
1
3
  const createStoreFactory = (notifyAfterCreation) => {
2
4
  return (object = {}) => {
3
5
  let willNotifyNextTick = false;
@@ -17,14 +19,17 @@ const createStoreFactory = (notifyAfterCreation) => {
17
19
  const handler = {
18
20
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
21
  set(target, p, value, receiver) {
20
- if (Reflect.get(target, p, receiver) !== value) {
21
- Reflect.set(target, p, value, receiver);
22
+ const realValue = unwrapValue(value);
23
+ if (Reflect.get(target, p, receiver) !== realValue) {
24
+ Reflect.set(target, p, realValue, receiver);
22
25
  enqueueNotification();
23
26
  }
24
27
  return true;
25
28
  },
26
29
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
30
  get(target, p, receiver) {
31
+ if (p === unwrap)
32
+ return target;
28
33
  const value = Reflect.get(target, p, receiver);
29
34
  return value !== null && typeof value === 'object' && !(value instanceof RegExp) ? createProxy(value) : value;
30
35
  },
package/dist/index.umd.js CHANGED
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).slimlibStore={})}(this,(function(e){"use strict";e.createStoreFactory=e=>(t={})=>{let n=!1;const o=new WeakMap,f=new Set,r=()=>{n||(n=!0,queueMicrotask((()=>{n=!1;for(const e of f)e(t)})))},c={set:(e,t,n,o)=>(Reflect.get(e,t,o)!==n&&(Reflect.set(e,t,n,o),r()),!0),get(e,t,n){const o=Reflect.get(e,t,n);return null===o||"object"!=typeof o||o instanceof RegExp?o:s(o)},defineProperty:(...e)=>(r(),Reflect.defineProperty(...e)),deleteProperty(e,t){const n=Reflect.deleteProperty(e,t);return n&&r(),n}};return[s(t),n=>n?(f.add(n),e&&n(t),()=>f.delete(n)):t];function s(e){if(o.has(e))return o.get(e);{const t=new Proxy(e,c);return o.set(e,t),t}}},Object.defineProperty(e,"__esModule",{value:!0})}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).slimlibStore={})}(this,(function(e){"use strict";const t=Symbol();e.createStoreFactory=e=>(n={})=>{let o=!1;const f=new WeakMap,r=new Set,c=()=>{o||(o=!0,queueMicrotask((()=>{o=!1;for(const e of r)e(n)})))},u={set(e,n,o,f){const r=(e=>null!=e&&e[t]||e)(o);return Reflect.get(e,n,f)!==r&&(Reflect.set(e,n,r,f),c()),!0},get(e,n,o){if(n===t)return e;const f=Reflect.get(e,n,o);return null===f||"object"!=typeof f||f instanceof RegExp?f:l(f)},defineProperty:(...e)=>(c(),Reflect.defineProperty(...e)),deleteProperty(e,t){const n=Reflect.deleteProperty(e,t);return n&&c(),n}};return[l(n),t=>t?(r.add(t),e&&t(n),()=>r.delete(t)):n];function l(e){if(f.has(e))return f.get(e);{const t=new Proxy(e,u);return f.set(e,t),t}}},Object.defineProperty(e,"__esModule",{value:!0})}));
2
2
  //# sourceMappingURL=index.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/index.ts"],"sourcesContent":["export type StoreCallback<T> = (value: T) => void;\nexport type UnsubscribeCallback = () => void;\n\nexport interface Store<T> {\n (cb: StoreCallback<T>): UnsubscribeCallback;\n (): T; // return bare object without Proxy, put into documentation not to change state through it\n}\n\nexport const createStoreFactory = (notifyAfterCreation: boolean) => {\n return <T extends object>(object: T = {} as T): [T, Store<T>] => {\n let willNotifyNextTick = false;\n const proxiesCache = new WeakMap<T, T>();\n const storeListeners = new Set<StoreCallback<T>>();\n const enqueueNotification = () => {\n if (!willNotifyNextTick) {\n willNotifyNextTick = true;\n queueMicrotask(() => {\n willNotifyNextTick = false;\n for (const listener of storeListeners) {\n listener(object);\n }\n });\n }\n };\n const handler = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n set(target: T, p: string | symbol, value: any, receiver: any) {\n if (Reflect.get(target, p, receiver) !== value) {\n Reflect.set(target, p, value, receiver);\n enqueueNotification();\n }\n return true;\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n get(target: T, p: string | symbol, receiver: any) {\n const value = Reflect.get(target, p, receiver);\n return value !== null && typeof value === 'object' && !(value instanceof RegExp) ? createProxy(value) : value;\n },\n defineProperty(...args: [T, string | symbol, PropertyDescriptor]) {\n enqueueNotification();\n return Reflect.defineProperty(...args);\n },\n deleteProperty(target: T, p: string | symbol) {\n const result = Reflect.deleteProperty(target, p);\n if (result) {\n enqueueNotification();\n }\n return result;\n }\n };\n const proxy = createProxy(object);\n return [\n proxy,\n ((cb?: StoreCallback<T>): UnsubscribeCallback | T => {\n if (!cb) {\n return object;\n }\n storeListeners.add(cb);\n if (notifyAfterCreation) {\n cb(object);\n }\n return () => storeListeners.delete(cb);\n }) as Store<T>\n ];\n function createProxy(object: T): T {\n if (proxiesCache.has(object)) {\n return proxiesCache.get(object) as T;\n } else {\n const proxy = new Proxy(object, handler);\n proxiesCache.set(object, proxy);\n return proxy;\n }\n }\n };\n};"],"names":["notifyAfterCreation","object","willNotifyNextTick","proxiesCache","WeakMap","storeListeners","Set","enqueueNotification","queueMicrotask","listener","handler","set","target","p","value","receiver","Reflect","get","RegExp","createProxy","defineProperty","args","deleteProperty","result","cb","add","delete","has","proxy","Proxy"],"mappings":"yQAQmCA,GACxB,CAAmBC,EAAY,MAClC,IAAIC,GAAqB,EACzB,MAAMC,EAAe,IAAIC,QACnBC,EAAiB,IAAIC,IACrBC,EAAsB,KACnBL,IACDA,GAAqB,EACrBM,gBAAe,KACXN,GAAqB,EACrB,IAAK,MAAMO,KAAYJ,EACnBI,EAASR,QAKnBS,EAAU,CAEZC,IAAG,CAACC,EAAWC,EAAoBC,EAAYC,KACvCC,QAAQC,IAAIL,EAAQC,EAAGE,KAAcD,IACrCE,QAAQL,IAAIC,EAAQC,EAAGC,EAAOC,GAC9BR,MAEG,GAGXU,IAAIL,EAAWC,EAAoBE,GAC/B,MAAMD,EAAQE,QAAQC,IAAIL,EAAQC,EAAGE,GACrC,OAAiB,OAAVD,GAAmC,iBAAVA,GAAwBA,aAAiBI,OAA+BJ,EAArBK,EAAYL,IAEnGM,eAAc,IAAIC,KACdd,IACOS,QAAQI,kBAAkBC,IAErCC,eAAeV,EAAWC,GACtB,MAAMU,EAASP,QAAQM,eAAeV,EAAQC,GAI9C,OAHIU,GACAhB,IAEGgB,IAIf,MAAO,CADOJ,EAAYlB,GAGpBuB,GACOA,GAGLnB,EAAeoB,IAAID,GACfxB,GACAwB,EAAGvB,GAEA,IAAMI,EAAeqB,OAAOF,IANxBvB,GASnB,SAASkB,EAAYlB,GACjB,GAAIE,EAAawB,IAAI1B,GACjB,OAAOE,EAAac,IAAIhB,GACrB,CACH,MAAM2B,EAAQ,IAAIC,MAAM5B,EAAQS,GAEhC,OADAP,EAAaQ,IAAIV,EAAQ2B,GAClBA"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/index.ts"],"sourcesContent":["export type StoreCallback<T> = (value: T) => void;\nexport type UnsubscribeCallback = () => void;\n\nexport interface Store<T> {\n (cb: StoreCallback<T>): UnsubscribeCallback;\n (): Readonly<T>;\n}\n\nconst unwrap = Symbol();\n\ntype Unwrappable<T> = {\n [unwrap]: T;\n} & T;\n\nconst unwrapValue = <T>(value: T) => (value != null && (value as Unwrappable<T>)[unwrap]) || value;\n\nexport const createStoreFactory = (notifyAfterCreation: boolean) => {\n return <T extends object>(object: T = {} as T): [T, Store<T>] => {\n let willNotifyNextTick = false;\n const proxiesCache = new WeakMap<T, T>();\n const storeListeners = new Set<StoreCallback<T>>();\n const enqueueNotification = () => {\n if (!willNotifyNextTick) {\n willNotifyNextTick = true;\n queueMicrotask(() => {\n willNotifyNextTick = false;\n for (const listener of storeListeners) {\n listener(object);\n }\n });\n }\n };\n const handler: ProxyHandler<T> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n set(target: T, p: string | symbol, value: any, receiver: any) {\n const realValue = unwrapValue(value);\n if (Reflect.get(target, p, receiver) !== realValue) {\n Reflect.set(target, p, realValue, receiver);\n enqueueNotification();\n }\n return true;\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n get(target: T, p: string | symbol, receiver: any) {\n if (p === unwrap) return target;\n const value = Reflect.get(target, p, receiver);\n return value !== null && typeof value === 'object' && !(value instanceof RegExp) ? createProxy(value) : value;\n },\n defineProperty(...args: [T, string | symbol, PropertyDescriptor]) {\n enqueueNotification();\n return Reflect.defineProperty(...args);\n },\n deleteProperty(target: T, p: string | symbol) {\n const result = Reflect.deleteProperty(target, p);\n if (result) {\n enqueueNotification();\n }\n return result;\n }\n };\n const proxy = createProxy(object);\n return [\n proxy,\n ((cb?: StoreCallback<T>): UnsubscribeCallback | T => {\n if (!cb) {\n return object;\n }\n storeListeners.add(cb);\n if (notifyAfterCreation) {\n cb(object);\n }\n return () => storeListeners.delete(cb);\n }) as Store<T>\n ];\n function createProxy(object: T): T {\n if (proxiesCache.has(object)) {\n return proxiesCache.get(object) as T;\n } else {\n const proxy = new Proxy(object, handler);\n proxiesCache.set(object, proxy);\n return proxy;\n }\n }\n };\n};"],"names":["unwrap","Symbol","notifyAfterCreation","object","willNotifyNextTick","proxiesCache","WeakMap","storeListeners","Set","enqueueNotification","queueMicrotask","listener","handler","set","target","p","value","receiver","realValue","unwrapValue","Reflect","get","RegExp","createProxy","defineProperty","args","deleteProperty","result","cb","add","delete","has","proxy","Proxy"],"mappings":"oPAQA,MAAMA,EAASC,8BAQoBC,GACxB,CAAmBC,EAAY,MAClC,IAAIC,GAAqB,EACzB,MAAMC,EAAe,IAAIC,QACnBC,EAAiB,IAAIC,IACrBC,EAAsB,KACnBL,IACDA,GAAqB,EACrBM,gBAAe,KACXN,GAAqB,EACrB,IAAK,MAAMO,KAAYJ,EACnBI,EAASR,QAKnBS,EAA2B,CAE7BC,IAAIC,EAAWC,EAAoBC,EAAYC,GAC3C,MAAMC,EArBF,CAAIF,GAAuB,MAATA,GAAkBA,EAAyBhB,IAAYgB,EAqB3DG,CAAYH,GAK9B,OAJII,QAAQC,IAAIP,EAAQC,EAAGE,KAAcC,IACrCE,QAAQP,IAAIC,EAAQC,EAAGG,EAAWD,GAClCR,MAEG,GAGXY,IAAIP,EAAWC,EAAoBE,GAC/B,GAAIF,IAAMf,EAAQ,OAAOc,EACzB,MAAME,EAAQI,QAAQC,IAAIP,EAAQC,EAAGE,GACrC,OAAiB,OAAVD,GAAmC,iBAAVA,GAAwBA,aAAiBM,OAA+BN,EAArBO,EAAYP,IAEnGQ,eAAc,IAAIC,KACdhB,IACOW,QAAQI,kBAAkBC,IAErCC,eAAeZ,EAAWC,GACtB,MAAMY,EAASP,QAAQM,eAAeZ,EAAQC,GAI9C,OAHIY,GACAlB,IAEGkB,IAIf,MAAO,CADOJ,EAAYpB,GAGpByB,GACOA,GAGLrB,EAAesB,IAAID,GACf1B,GACA0B,EAAGzB,GAEA,IAAMI,EAAeuB,OAAOF,IANxBzB,GASnB,SAASoB,EAAYpB,GACjB,GAAIE,EAAa0B,IAAI5B,GACjB,OAAOE,EAAagB,IAAIlB,GACrB,CACH,MAAM6B,EAAQ,IAAIC,MAAM9B,EAAQS,GAEhC,OADAP,EAAaQ,IAAIV,EAAQ6B,GAClBA"}
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.0",
2
+ "version": "1.0.1",
3
3
  "license": "MIT",
4
4
  "name": "@slimlib/store",
5
5
  "author": "Konstantin Shutkin",