@lomray/react-mobx-manager 3.1.0 → 3.1.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
@@ -342,11 +342,13 @@ const relations = storeManager.getStoresRelations();
342
342
  /**
343
343
  * Manually create stores for component
344
344
  * NOTE: 'withStores' wrapper use this method, probably you won't need it
345
+ * WARNING: Avoid using this method directly, it may cause unexpected behavior
345
346
  */
346
347
  const stores = storeManager.createStores(['someStore', MyStore], 'parent-id', 'context-id', 'suspense-id', 'HomePage', { componentProp: 'test' });
347
348
 
348
349
  /**
349
350
  * Mount/Unmount simple stores to component
351
+ * WARNING: Avoid using this method directly, it may cause unexpected behavior
350
352
  */
351
353
  const unmount = storeManager.mountStores(stores);
352
354
 
@@ -386,13 +388,20 @@ const storeClass = Manager.persistStore(class MyStore {}, 'my-store');
386
388
  ```typescript
387
389
  import { withStores } from '@lomray/react-mobx-manager';
388
390
 
391
+ const stores = {
392
+ myStore: MyStore,
393
+ anotherStore: AnotherStore,
394
+ // assign static id to future store
395
+ demoStore: { store: SomeStore, id: 'my-id' },
396
+ // get parent store, do this only inside children components
397
+ parentStore: { store: SomeParentStore, isParent: true },
398
+ };
399
+
389
400
  /**
390
401
  * Create and connect 'stores' to component with custom context id
391
402
  * NOTE: In most cases, you don't need to pass a third argument (contextId).
392
403
  */
393
404
  withStores(Component, stores, { customContextId: 'optional-context-id' });
394
-
395
- const stores = { myStore: MyStore, anotherStore: AnotherStore };
396
405
  ```
397
406
 
398
407
  ### StoreManagerProvider
package/constants.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ declare const ROOT_CONTEXT_ID = "root";
2
+ export { ROOT_CONTEXT_ID };
package/constants.js ADDED
@@ -0,0 +1,2 @@
1
+ const o="root";export{o as ROOT_CONTEXT_ID};
2
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sources":["../src/constants.ts"],"sourcesContent":["// eslint-disable-next-line import/prefer-default-export\nexport const ROOT_CONTEXT_ID = 'root';\n"],"names":["ROOT_CONTEXT_ID"],"mappings":"AACO,MAAMA,EAAkB"}
package/context.d.ts CHANGED
@@ -12,7 +12,7 @@ interface IStoreManagerProvider {
12
12
  interface IStoreManagerParentProvider {
13
13
  parentId: string;
14
14
  children?: React.ReactNode;
15
- initStores?: TStores;
15
+ touchableStores?: TStores;
16
16
  }
17
17
  /**
18
18
  * Mobx store manager context
package/context.js CHANGED
@@ -1,2 +1,2 @@
1
- import e,{useState as t,useEffect as r,useContext as n}from"react";const o=e.createContext({}),a=e.createContext("root"),c=({parentId:t,children:r,initStores:n})=>{const o=l();return n&&o.touchedStores(n),e.createElement(a.Provider,{value:t,children:r})},i=({children:n,storeManager:a,fallback:i,shouldInit:l=!1})=>{const[d,s]=t(!l);return r((()=>{l&&a.init().then((()=>s(!0))).catch((e=>{console.error("Failed initialized store manager: ",e)}))}),[l,a]),e.createElement(o.Provider,{value:a},e.createElement(c,{parentId:"root"},d?n:i||n))},l=()=>n(o),d=()=>n(a);export{o as StoreManagerContext,a as StoreManagerParentContext,c as StoreManagerParentProvider,i as StoreManagerProvider,l as useStoreManager,d as useStoreManagerParent};
1
+ import e,{useState as t,useEffect as r,useContext as o}from"react";import{ROOT_CONTEXT_ID as n}from"./constants.js";const a=e.createContext({}),c=e.createContext(n),i=({parentId:t,children:r,touchableStores:o})=>{const n=s();return o&&n.touchedStores(o),e.createElement(c.Provider,{value:t,children:r})},l=({children:o,storeManager:n,fallback:c,shouldInit:l=!1})=>{const[s,d]=t(!l);return r((()=>{l&&n.init().then((()=>d(!0))).catch((e=>{console.error("Failed initialized store manager: ",e)}))}),[l,n]),e.createElement(a.Provider,{value:n},e.createElement(i,{parentId:"root"},s?o:c||o))},s=()=>o(a),d=()=>o(c);export{a as StoreManagerContext,c as StoreManagerParentContext,i as StoreManagerParentProvider,l as StoreManagerProvider,s as useStoreManager,d as useStoreManagerParent};
2
2
  //# sourceMappingURL=context.js.map
package/context.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sources":["../src/context.tsx"],"sourcesContent":["import type { FC, ReactElement } from 'react';\nimport React, { useContext, useEffect, useState } from 'react';\nimport type Manager from './manager';\nimport type { TStores } from './types';\n\ninterface IStoreManagerProvider {\n storeManager: Manager;\n shouldInit?: boolean;\n fallback?: ReactElement;\n children?: React.ReactNode;\n}\n\ninterface IStoreManagerParentProvider {\n parentId: string;\n children?: React.ReactNode;\n initStores?: TStores;\n}\n\n/**\n * Mobx store manager context\n */\nconst StoreManagerContext = React.createContext<Manager>({} as Manager);\n\n/**\n * To spread relationships\n */\nconst StoreManagerParentContext =\n React.createContext<IStoreManagerParentProvider['parentId']>('root');\n\n/**\n * Mobx store manager parent provider\n * @constructor\n */\nconst StoreManagerParentProvider: FC<Omit<IStoreManagerParentProvider, 'contextId'>> = ({\n parentId,\n children,\n initStores,\n}) => {\n const storeManager = useStoreManager();\n\n if (initStores) {\n storeManager.touchedStores(initStores);\n }\n\n return <StoreManagerParentContext.Provider value={parentId} children={children} />;\n};\n\n/**\n * Mobx store manager provider\n * @constructor\n */\nconst StoreManagerProvider: FC<IStoreManagerProvider> = ({\n children,\n storeManager,\n fallback,\n shouldInit = false,\n}) => {\n const [isInit, setInit] = useState(!shouldInit);\n\n useEffect(() => {\n if (!shouldInit) {\n return;\n }\n\n storeManager\n .init()\n .then(() => setInit(true))\n .catch((e: Error) => {\n console.error('Failed initialized store manager: ', e);\n });\n }, [shouldInit, storeManager]);\n\n return (\n <StoreManagerContext.Provider value={storeManager}>\n <StoreManagerParentProvider parentId=\"root\">\n {isInit ? children : fallback || children}\n </StoreManagerParentProvider>\n </StoreManagerContext.Provider>\n );\n};\n\nconst useStoreManager = (): Manager => useContext(StoreManagerContext);\n\nconst useStoreManagerParent = (): IStoreManagerParentProvider['parentId'] =>\n useContext(StoreManagerParentContext);\n\nexport {\n StoreManagerContext,\n StoreManagerParentContext,\n StoreManagerProvider,\n StoreManagerParentProvider,\n useStoreManager,\n useStoreManagerParent,\n};\n"],"names":["StoreManagerContext","React","createContext","StoreManagerParentContext","StoreManagerParentProvider","parentId","children","initStores","storeManager","useStoreManager","touchedStores","createElement","Provider","value","StoreManagerProvider","fallback","shouldInit","isInit","setInit","useState","useEffect","init","then","catch","e","console","error","useContext","useStoreManagerParent"],"mappings":"mEAqBM,MAAAA,EAAsBC,EAAMC,cAAuB,IAKnDC,EACJF,EAAMC,cAAuD,QAMzDE,EAAiF,EACrFC,WACAC,WACAC,iBAEA,MAAMC,EAAeC,IAMrB,OAJIF,GACFC,EAAaE,cAAcH,GAGtBN,EAACU,cAAAR,EAA0BS,SAAS,CAAAC,MAAOR,EAAUC,SAAUA,GAAY,EAO9EQ,EAAkD,EACtDR,WACAE,eACAO,WACAC,cAAa,MAEb,MAAOC,EAAQC,GAAWC,GAAUH,GAepC,OAbAI,GAAU,KACHJ,GAILR,EACGa,OACAC,MAAK,IAAMJ,GAAQ,KACnBK,OAAOC,IACNC,QAAQC,MAAM,qCAAsCF,EAAE,GACtD,GACH,CAACR,EAAYR,IAGdP,gBAACD,EAAoBY,SAAS,CAAAC,MAAOL,GACnCP,EAACU,cAAAP,GAA2BC,SAAS,QAClCY,EAASX,EAAWS,GAAYT,GAGrC,EAGEG,EAAkB,IAAekB,EAAW3B,GAE5C4B,EAAwB,IAC5BD,EAAWxB"}
1
+ {"version":3,"file":"context.js","sources":["../src/context.tsx"],"sourcesContent":["import type { FC, ReactElement } from 'react';\nimport React, { useContext, useEffect, useState } from 'react';\nimport { ROOT_CONTEXT_ID } from './constants';\nimport type Manager from './manager';\nimport type { TStores } from './types';\n\ninterface IStoreManagerProvider {\n storeManager: Manager;\n shouldInit?: boolean;\n fallback?: ReactElement;\n children?: React.ReactNode;\n}\n\ninterface IStoreManagerParentProvider {\n parentId: string;\n children?: React.ReactNode;\n touchableStores?: TStores;\n}\n\n/**\n * Mobx store manager context\n */\nconst StoreManagerContext = React.createContext<Manager>({} as Manager);\n\n/**\n * To spread relationships\n */\nconst StoreManagerParentContext =\n React.createContext<IStoreManagerParentProvider['parentId']>(ROOT_CONTEXT_ID);\n\n/**\n * Mobx store manager parent provider\n * @constructor\n */\nconst StoreManagerParentProvider: FC<Omit<IStoreManagerParentProvider, 'contextId'>> = ({\n parentId,\n children,\n touchableStores,\n}) => {\n const storeManager = useStoreManager();\n\n if (touchableStores) {\n storeManager.touchedStores(touchableStores);\n }\n\n return <StoreManagerParentContext.Provider value={parentId} children={children} />;\n};\n\n/**\n * Mobx store manager provider\n * @constructor\n */\nconst StoreManagerProvider: FC<IStoreManagerProvider> = ({\n children,\n storeManager,\n fallback,\n shouldInit = false,\n}) => {\n const [isInit, setInit] = useState(!shouldInit);\n\n useEffect(() => {\n if (!shouldInit) {\n return;\n }\n\n storeManager\n .init()\n .then(() => setInit(true))\n .catch((e: Error) => {\n console.error('Failed initialized store manager: ', e);\n });\n }, [shouldInit, storeManager]);\n\n return (\n <StoreManagerContext.Provider value={storeManager}>\n <StoreManagerParentProvider parentId=\"root\">\n {isInit ? children : fallback || children}\n </StoreManagerParentProvider>\n </StoreManagerContext.Provider>\n );\n};\n\nconst useStoreManager = (): Manager => useContext(StoreManagerContext);\n\nconst useStoreManagerParent = (): IStoreManagerParentProvider['parentId'] =>\n useContext(StoreManagerParentContext);\n\nexport {\n StoreManagerContext,\n StoreManagerParentContext,\n StoreManagerProvider,\n StoreManagerParentProvider,\n useStoreManager,\n useStoreManagerParent,\n};\n"],"names":["StoreManagerContext","React","createContext","StoreManagerParentContext","ROOT_CONTEXT_ID","StoreManagerParentProvider","parentId","children","touchableStores","storeManager","useStoreManager","touchedStores","createElement","Provider","value","StoreManagerProvider","fallback","shouldInit","isInit","setInit","useState","useEffect","init","then","catch","e","console","error","useContext","useStoreManagerParent"],"mappings":"oHAsBM,MAAAA,EAAsBC,EAAMC,cAAuB,IAKnDC,EACJF,EAAMC,cAAuDE,GAMzDC,EAAiF,EACrFC,WACAC,WACAC,sBAEA,MAAMC,EAAeC,IAMrB,OAJIF,GACFC,EAAaE,cAAcH,GAGtBP,EAACW,cAAAT,EAA0BU,SAAS,CAAAC,MAAOR,EAAUC,SAAUA,GAAY,EAO9EQ,EAAkD,EACtDR,WACAE,eACAO,WACAC,cAAa,MAEb,MAAOC,EAAQC,GAAWC,GAAUH,GAepC,OAbAI,GAAU,KACHJ,GAILR,EACGa,OACAC,MAAK,IAAMJ,GAAQ,KACnBK,OAAOC,IACNC,QAAQC,MAAM,qCAAsCF,EAAE,GACtD,GACH,CAACR,EAAYR,IAGdR,gBAACD,EAAoBa,SAAS,CAAAC,MAAOL,GACnCR,EAACW,cAAAP,GAA2BC,SAAS,QAClCY,EAASX,EAAWS,GAAYT,GAGrC,EAGEG,EAAkB,IAAekB,EAAW5B,GAE5C6B,EAAwB,IAC5BD,EAAWzB"}
package/manager.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import StoreStatus from "./store-status.js";
2
- import { IConstructableStore, IManagerOptions, IManagerParams, IStorage, IStoreParams, IStorePersisted, TAnyStore, TInitStore, TStoreDefinition, TStores } from "./types.js";
2
+ import { IConstructableStore, IGroupedStores, IManagerOptions, IManagerParams, IStorage, IStoreParams, IStorePersisted, TAnyStore, TInitStore, TStoreDefinition, TStores } from "./types.js";
3
3
  /**
4
4
  * Mobx stores manager
5
5
  */
@@ -147,11 +147,29 @@ declare class Manager {
147
147
  protected createStore<T>(store: IConstructableStore<T>, params: Omit<Required<IStoreParams>, 'key'>): T;
148
148
  /**
149
149
  * Create stores for component
150
+ *
151
+ * NOTE: use only inside withStores wrapper
150
152
  */
151
153
  /**
152
154
  * Create stores for component
155
+ *
156
+ * NOTE: use only inside withStores wrapper
153
157
  */
154
- createStores(map: [string, TStoreDefinition][], parentId: string, contextId: string, suspenseId: string, componentName: string, componentProps?: Record<string, any>): TStores;
158
+ createStores(map: [string, TStoreDefinition][], parentId: string, contextId: string, suspenseId: string, componentName: string, componentProps?: Record<string, any>): IGroupedStores;
159
+ /**
160
+ * Create empty relation context
161
+ */
162
+ /**
163
+ * Create empty relation context
164
+ */
165
+ protected createRelationContext(contextId: string, parentId?: string, componentName?: string): void;
166
+ /**
167
+ * Delete relation context id
168
+ */
169
+ /**
170
+ * Delete relation context id
171
+ */
172
+ protected removeRelationContext(contextId: string): void;
155
173
  /**
156
174
  * Prepare store before usage
157
175
  */
@@ -168,11 +186,15 @@ declare class Manager {
168
186
  protected removeStore(store: TStores[string]): void;
169
187
  /**
170
188
  * Mount stores to component
189
+ *
190
+ * NOTE: use only inside withStores wrapper
171
191
  */
172
192
  /**
173
193
  * Mount stores to component
194
+ *
195
+ * NOTE: use only inside withStores wrapper
174
196
  */
175
- mountStores(stores: TStores): () => void;
197
+ mountStores(contextId: string, { globalStores, relativeStores }: Partial<IGroupedStores>): () => void;
176
198
  /**
177
199
  * Change the stores status to touched
178
200
  */
package/manager.js CHANGED
@@ -1,2 +1,2 @@
1
- import t from"@lomray/event-manager";import{toJS as e,isObservableProp as s}from"mobx";import r from"./deep-merge.js";import o from"./events.js";import{isPropSimpleExported as i,isPropObservableExported as n}from"./make-exported.js";import a from"./on-change-listener.js";import h from"./store-status.js";import d from"./wakeup.js";class p{static instance;stores=new Map;storesRelations=new Map;static persistedStores=new Set;initState;storage;persistData={};storesParams;options={shouldDisablePersist:!1,shouldRemoveInitState:!0};suspenseRelations=new Map;constructor({initState:t,storesParams:e,storage:s,options:r}={}){if(this.initState=t||{},this.storesParams=e||{},this.storage=s,Object.assign(this.options,r||{}),p.instance=this,"undefined"!=typeof window){const t=window.mbxM;window.mbxM={push:this.pushInitState},(Array.isArray(t)?t:[]).forEach(this.pushInitState)}}async init(){return this.storage&&(this.persistData=await this.storage.get()||{}),this}static get(){if(!p.instance)throw new Error("Store manager is not initialized.");return p.instance}getStores(){return this.stores}getStoresRelations(){return this.storesRelations}getSuspenseRelations(){return this.suspenseRelations}static getPersistedStoresIds(){return p.persistedStores}pushInitState=(t={})=>{for(const[e,s]of Object.entries(t))this.initState[e]=s};getStoreId(t,e={}){const{id:s,contextId:r,key:o}=e;if(s)return s;if(t.libStoreId)return t.libStoreId;let i=t.id||t.name||t.constructor.name;return t.isGlobal?i:(i=`${i}--${r}`,o?`${i}--${o}`:i)}getStore(t,e={}){const s=this.getStoreId(t,e);return this.stores.has(s)?this.stores.get(s):t.isGlobal?this.createStore(t,{id:s,contextId:"global",parentId:"root",suspenseId:"",componentName:"root-app",componentProps:{}}):this.lookupStore(s,e)}lookupStore(t,e){const{contextId:s,parentId:r}=e,o=t.split("--")?.[0],{ids:i,parentId:n}=this.storesRelations.get(s)??{ids:new Set,parentId:r},a=[...i].filter((t=>t.startsWith(`${o}--`)));if(1===a.length)return this.stores.get(a[0]);if(a.length>1)console.error("Parent context has multiple stores with the same id, please pass key to getStore function.");else if(n&&"root"!==n)return this.lookupStore(t,{contextId:this.getBiggerContext(n,r)})}getBiggerContext(t,e){if(!t)return e;if(!e)return t;const s=/[^a-zA-Z]/g;return t.replace(s,"")>e.replace(s,"")?t:e}createStore(e,s){const{id:r,contextId:i,parentId:n,suspenseId:a,componentName:d,componentProps:p}=s;if(this.stores.has(r))return this.stores.get(r);const l=new e({...this.storesParams,storeManager:this,getStore:(t,e={contextId:i,parentId:n})=>this.getStore(t,e),componentProps:p,initState:this.initState[r]});return l.libStoreId=r,l.isGlobal=e.isGlobal,l.libStoreContextId=e.isGlobal?"global":i,l.libStoreParentId=e.isGlobal||!n||n===i?"root":n,l.libStoreSuspenseId=a,l.libStoreComponentName=d,this.setStoreStatus(l,e.isGlobal?h.inUse:h.init),this.prepareStore(l),t.publish(o.CREATE_STORE,{store:e}),l}createStores(t,e,s,r,o,i={}){return t.reduce(((t,[n,a])=>{const{id:h,store:d,isParent:p=!1}="store"in a?a:{store:a,id:void 0,isParent:!1},l=h||(p?this.getStore(d,{contextId:s,parentId:e})?.libStoreId:this.getStoreId(d,{key:n,contextId:s}));return{...t,[n]:l?this.createStore(d,{id:l,contextId:s,parentId:e,suspenseId:r,componentName:o,componentProps:i}):void 0}}),{})}prepareStore(t){const e=t.libStoreId,s=t.libStoreContextId,o=t.libStoreSuspenseId,i=this.initState[e],n=this.persistData[e];if(this.stores.has(e))return;if(i&&r(t,i),"wakeup"in t&&p.persistedStores.has(e)&&t.wakeup?.({initState:i,persistedState:n,manager:this}),p.persistedStores.has(e)&&"addOnChangeListener"in t){const e=t.onDestroy?.bind(t),s=t.addOnChangeListener(t,this);t.onDestroy=()=>{s?.(),e?.()}}t.init?.(),this.storesRelations.has(s)||this.storesRelations.set(s,{ids:new Set,parentId:t.libStoreParentId&&t.libStoreParentId!==s?t.libStoreParentId:"root",componentName:t.libStoreComponentName}),this.suspenseRelations.has(o)||this.suspenseRelations.set(o,new Set);const{ids:a}=this.storesRelations.get(s);this.stores.set(e,t),a.add(e),this.suspenseRelations.get(o).add(e)}removeStore(e){const s=e.libStoreId,r=e.libStoreSuspenseId,{ids:i}=this.storesRelations.get(e.libStoreContextId)??{ids:new Set};this.stores.has(s)&&(this.stores.delete(s),i.delete(s),r&&this.suspenseRelations.get(r)?.has(s)&&this.suspenseRelations.get(r).delete(s),i.size||this.storesRelations.delete(e.libStoreContextId),"onDestroy"in e&&e.onDestroy?.(),t.publish(o.DELETE_STORE,{store:e}))}mountStores(e){const{shouldRemoveInitState:s}=this.options;return Object.values(e).forEach((e=>{const r=e.libStoreId;s&&this.initState[r]&&delete this.initState[r],this.setStoreStatus(e,h.inUse),t.publish(o.MOUNT_STORE,{store:e})})),()=>{Object.values(e).forEach((e=>{e.isGlobal||(this.setStoreStatus(e,h.unused),t.publish(o.UNMOUNT_STORE,{store:e}))}))}}touchedStores(t){Object.values(t).forEach((t=>{t.libStoreStatus!==h.init||t.isGlobal||this.setStoreStatus(t,h.touched)}))}setStoreStatus(t,e){const{destroyTimers:{init:s=500,touched:r=1e4,unused:o=1e3}={}}=this.options;t.libStoreStatus=e,clearTimeout(t.libDestroyTimer);let i=0;switch(e){case h.init:i=s;break;case h.touched:i=r;break;case h.unused:i=o}i&&(t.libDestroyTimer=setTimeout((()=>this.removeStore(t)),i))}getStoreState(t){return t.toJSON?.()??p.getObservableProps(t)}toJSON(t){const e={},s=Array.isArray(t)?t.reduce(((t,e)=>(this.stores.has(e)&&t.set(e,this.stores.get(e)),t)),new Map):this.stores;for(const[t,r]of s.entries())e[t]=this.getStoreState(r);return e}async savePersistedStore(t){if(this.options.shouldDisablePersist||!this.storage)return!1;try{return this.persistData={...this.persistData,[this.getStoreId(t)]:this.getStoreState(t)},await(this.storage?.set(this.persistData)),!0}catch(t){console.error("Failed to persist stores: ",t)}return!1}static getObservableProps(t){const r=e(t);return Object.entries(r).reduce(((e,[r,o])=>({...e,...s(t,r)||i(t,r)?{[r]:o}:{},...n(t,r)?{[r]:p.getObservableProps(t[r])}:{}})),{})}static persistStore(t,e){return p.persistedStores.has(e)?(console.warn(`Duplicate serializable store key: ${e}`),t):(p.persistedStores.add(e),t.libStoreId=e,"wakeup"in t.prototype||(t.prototype.wakeup=d),"addOnChangeListener"in t.prototype||(t.prototype.addOnChangeListener=a),t)}}export{p as default};
1
+ import t from"@lomray/event-manager";import{toJS as e,isObservableProp as s}from"mobx";import{ROOT_CONTEXT_ID as o}from"./constants.js";import r from"./deep-merge.js";import i from"./events.js";import{isPropSimpleExported as n,isPropObservableExported as a}from"./make-exported.js";import l from"./on-change-listener.js";import h from"./store-status.js";import p from"./wakeup.js";class d{static instance;stores=new Map;storesRelations=new Map;static persistedStores=new Set;initState;storage;persistData={};storesParams;options={shouldDisablePersist:!1,shouldRemoveInitState:!0};suspenseRelations=new Map;constructor({initState:t,storesParams:e,storage:s,options:o}={}){if(this.initState=t||{},this.storesParams=e||{},this.storage=s,Object.assign(this.options,o||{}),d.instance=this,"undefined"!=typeof window){const t=window.mbxM;window.mbxM={push:this.pushInitState},(Array.isArray(t)?t:[]).forEach(this.pushInitState)}}async init(){return this.storage&&(this.persistData=await this.storage.get()||{}),this}static get(){if(!d.instance)throw new Error("Store manager is not initialized.");return d.instance}getStores(){return this.stores}getStoresRelations(){return this.storesRelations}getSuspenseRelations(){return this.suspenseRelations}static getPersistedStoresIds(){return d.persistedStores}pushInitState=(t={})=>{for(const[e,s]of Object.entries(t))this.initState[e]=s};getStoreId(t,e={}){const{id:s,contextId:o,key:r}=e;if(s)return s;if(t.libStoreId)return t.libStoreId;let i=t.id||t.name||t.constructor.name;return t.isGlobal?i:(i=`${i}--${o}`,r?`${i}--${r}`:i)}getStore(t,e={}){const s=this.getStoreId(t,e);return this.stores.has(s)?this.stores.get(s):t.isGlobal?this.createStore(t,{id:s,contextId:"global",parentId:o,suspenseId:"",componentName:"root-app",componentProps:{}}):this.lookupStore(s,e)}lookupStore(t,e){const{contextId:s,parentId:r}=e,i=t.split("--")?.[0],{ids:n,parentId:a}=this.storesRelations.get(s)??{ids:new Set,parentId:r},l=[...n].filter((t=>t.startsWith(`${i}--`)));if(1===l.length)return this.stores.get(l[0]);if(l.length>1)console.error("Parent context has multiple stores with the same id, please pass key to getStore function.");else if(a&&a!==o)return this.lookupStore(t,{contextId:this.getBiggerContext(a,r)})}getBiggerContext(t,e){if(!t)return e;if(!e)return t;const s=/[^a-zA-Z]/g;return t.replace(s,"")>e.replace(s,"")?t:e}createStore(e,s){const{id:r,contextId:n,parentId:a,suspenseId:l,componentName:p,componentProps:d}=s;if(this.stores.has(r))return this.stores.get(r);const S=new e({...this.storesParams,storeManager:this,getStore:(t,e={contextId:n,parentId:a})=>this.getStore(t,e),componentProps:d,initState:this.initState[r]});return S.libStoreId=r,S.isGlobal=e.isGlobal,S.libStoreContextId=e.isGlobal?"global":n,S.libStoreParentId=e.isGlobal||!a||a===n?o:a,S.libStoreSuspenseId=l,S.libStoreComponentName=p,this.setStoreStatus(S,e.isGlobal?h.inUse:h.init),this.prepareStore(S),t.publish(i.CREATE_STORE,{store:e}),S}createStores(t,e,s,o,r,i={}){const n=t.reduce(((t,[n,a])=>{const{id:l,store:h,isParent:p=!1}="store"in a?a:{store:a,id:void 0,isParent:!1},d=l||(p?this.getStore(h,{contextId:s,parentId:e})?.libStoreId:this.getStoreId(h,{key:n,contextId:s}));if(!d)return t;const S=this.createStore(h,{id:d,contextId:s,parentId:e,suspenseId:o,componentName:r,componentProps:i});return p?t.parentStores[n]=S:S.isGlobal?t.globalStores[n]=S:t.relativeStores[n]=S,t}),{relativeStores:{},parentStores:{},globalStores:{}});return this.createRelationContext(s,e,r),n}createRelationContext(t,e,s){this.storesRelations.has(t)||this.storesRelations.set(t,{ids:new Set,parentId:e&&e!==t?e:o,componentName:s})}removeRelationContext(t){const e=this.storesRelations.get(t);!e||t===o||e.ids.size>0||this.storesRelations.delete(t)}prepareStore(t){const e=t.libStoreId,s=t.libStoreContextId,o=t.libStoreSuspenseId,i=this.initState[e],n=this.persistData[e];if(this.stores.has(e))return;if(i&&r(t,i),"wakeup"in t&&d.persistedStores.has(e)&&t.wakeup?.({initState:i,persistedState:n,manager:this}),d.persistedStores.has(e)&&"addOnChangeListener"in t){const e=t.onDestroy?.bind(t),s=t.addOnChangeListener(t,this);t.onDestroy=()=>{s?.(),e?.()}}t.init?.(),this.createRelationContext(s,t.libStoreParentId,t.libStoreComponentName),this.suspenseRelations.has(o)||this.suspenseRelations.set(o,new Set);const{ids:a}=this.storesRelations.get(s);this.stores.set(e,t),a.add(e),this.suspenseRelations.get(o).add(e)}removeStore(e){const s=e.libStoreId,o=e.libStoreSuspenseId,{ids:r}=this.storesRelations.get(e.libStoreContextId)??{ids:new Set};this.stores.has(s)&&(this.stores.delete(s),r.delete(s),o&&this.suspenseRelations.get(o)?.has(s)&&this.suspenseRelations.get(o).delete(s),this.removeRelationContext(e.libStoreContextId),"onDestroy"in e&&e.onDestroy?.(),t.publish(i.DELETE_STORE,{store:e}))}mountStores(e,{globalStores:s={},relativeStores:o={}}){const{shouldRemoveInitState:r}=this.options,n={...s,...o};return Object.values(n).forEach((e=>{const s=e.libStoreId;r&&this.initState[s]&&delete this.initState[s],this.setStoreStatus(e,h.inUse),t.publish(i.MOUNT_STORE,{store:e})})),()=>{Object.values(n).forEach((e=>{e.isGlobal||(this.setStoreStatus(e,h.unused),t.publish(i.UNMOUNT_STORE,{store:e}))})),this.removeRelationContext(e)}}touchedStores(t){Object.values(t).forEach((t=>{t.libStoreStatus!==h.init||t.isGlobal||this.setStoreStatus(t,h.touched)}))}setStoreStatus(t,e){const{destroyTimers:{init:s=500,touched:o=1e4,unused:r=1e3}={}}=this.options;t.libStoreStatus=e,clearTimeout(t.libDestroyTimer);let i=0;switch(e){case h.init:i=s;break;case h.touched:i=o;break;case h.unused:i=r}i&&(t.libDestroyTimer=setTimeout((()=>this.removeStore(t)),i))}getStoreState(t){return t.toJSON?.()??d.getObservableProps(t)}toJSON(t){const e={},s=Array.isArray(t)?t.reduce(((t,e)=>(this.stores.has(e)&&t.set(e,this.stores.get(e)),t)),new Map):this.stores;for(const[t,o]of s.entries())e[t]=this.getStoreState(o);return e}async savePersistedStore(t){if(this.options.shouldDisablePersist||!this.storage)return!1;try{return this.persistData={...this.persistData,[this.getStoreId(t)]:this.getStoreState(t)},await(this.storage?.set(this.persistData)),!0}catch(t){console.error("Failed to persist stores: ",t)}return!1}static getObservableProps(t){const o=e(t);return Object.entries(o).reduce(((e,[o,r])=>({...e,...s(t,o)||n(t,o)?{[o]:r}:{},...a(t,o)?{[o]:d.getObservableProps(t[o])}:{}})),{})}static persistStore(t,e){return d.persistedStores.has(e)?(console.warn(`Duplicate serializable store key: ${e}`),t):(d.persistedStores.add(e),t.libStoreId=e,"wakeup"in t.prototype||(t.prototype.wakeup=p),"addOnChangeListener"in t.prototype||(t.prototype.addOnChangeListener=l),t)}}export{d as default};
2
2
  //# sourceMappingURL=manager.js.map
package/manager.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sources":["../src/manager.ts"],"sourcesContent":["import EventManager from '@lomray/event-manager';\nimport { isObservableProp, toJS } from 'mobx';\nimport deepMerge from './deep-merge';\nimport Events from './events';\nimport { isPropObservableExported, isPropSimpleExported } from './make-exported';\nimport onChangeListener from './on-change-listener';\nimport StoreStatus from './store-status';\nimport type {\n IConstructableStore,\n IManagerOptions,\n IManagerParams,\n IStorage,\n IStoreParams,\n IStorePersisted,\n TAnyStore,\n TInitStore,\n TStoreDefinition,\n TStores,\n} from './types';\nimport wakeup from './wakeup';\n\n/**\n * Mobx stores manager\n */\nclass Manager {\n /**\n * Manger instance\n */\n protected static instance: Manager;\n\n /**\n * Created stores\n */\n protected readonly stores = new Map<string, TInitStore>();\n\n /**\n * Relations between stores\n * @protected\n */\n protected readonly storesRelations = new Map<\n string, // contextId\n { ids: Set<string>; parentId: string | null; componentName?: string }\n >();\n\n /**\n * Save persisted stores identities\n * @private\n */\n protected static readonly persistedStores = new Set<string>();\n\n /**\n * Initial stores state (local storage, custom etc.)\n * @private\n */\n protected readonly initState: Record<string, any>;\n\n /**\n * Storage for persisted stores\n */\n public readonly storage: IStorage | undefined;\n\n /**\n * Restored persist storage data\n * @protected\n */\n protected persistData: Record<string, any> = {};\n\n /**\n * Additional store's constructor params\n * @private\n */\n protected readonly storesParams: IManagerParams['storesParams'];\n\n /**\n * Manager options\n */\n public readonly options: IManagerOptions = {\n shouldDisablePersist: false,\n shouldRemoveInitState: true,\n };\n\n /**\n * Suspense stores relations\n * @see withStores\n */\n protected suspenseRelations: Map<string, Set<string>> = new Map();\n\n /**\n * @constructor\n */\n public constructor({ initState, storesParams, storage, options }: IManagerParams = {}) {\n this.initState = initState || {};\n this.storesParams = storesParams || {};\n this.storage = storage;\n\n Object.assign(this.options, options || {});\n\n Manager.instance = this;\n\n // only client side\n if (typeof window !== 'undefined') {\n const state = window.mbxM;\n\n window.mbxM = { push: this.pushInitState };\n\n (Array.isArray(state) ? state : []).forEach(this.pushInitState);\n }\n }\n\n /**\n * Init store manager\n */\n public async init(): Promise<Manager> {\n if (this.storage) {\n this.persistData = (await this.storage.get()) || {};\n }\n\n return this;\n }\n\n /**\n * Get manager instance\n */\n public static get(): Manager {\n if (!Manager.instance) {\n throw new Error('Store manager is not initialized.');\n }\n\n return Manager.instance;\n }\n\n /**\n * Get all stores\n */\n public getStores(): Manager['stores'] {\n return this.stores;\n }\n\n /**\n * Get stores relations\n */\n public getStoresRelations(): Manager['storesRelations'] {\n return this.storesRelations;\n }\n\n /**\n * Get suspense relations with stores\n */\n public getSuspenseRelations(): Manager['suspenseRelations'] {\n return this.suspenseRelations;\n }\n\n /**\n * Get persisted stores ids\n */\n public static getPersistedStoresIds(): Set<string> {\n return Manager.persistedStores;\n }\n\n /**\n * Push initial state dynamically\n * E.g. when stream html\n */\n public pushInitState = (storesState: Record<string, any> = {}): void => {\n for (const [storeId, state] of Object.entries(storesState)) {\n this.initState[storeId] = state;\n }\n };\n\n /**\n * Get store identity\n * @protected\n */\n protected getStoreId<T extends TAnyStore>(\n store: IConstructableStore<T> | TInitStore,\n params: IStoreParams = {},\n ): string {\n const { id, contextId, key } = params;\n\n if (id) {\n return id;\n }\n\n if (store.libStoreId) {\n return store.libStoreId;\n }\n\n let storeId = (store['id'] as string) || (store['name'] as string) || store.constructor.name;\n\n if (store.isGlobal) {\n return storeId;\n }\n\n storeId = `${storeId}--${contextId!}`;\n\n return key ? `${storeId}--${key}` : storeId;\n }\n\n /**\n * Get exist store\n */\n public getStore<T>(store: IConstructableStore<T>, params: IStoreParams = {}): T | undefined {\n const storeId = this.getStoreId(store, params);\n\n // full match\n if (this.stores.has(storeId)) {\n return this.stores.get(storeId) as T;\n }\n\n // in case with global store (create if not exist)\n if (store.isGlobal) {\n return this.createStore(store, {\n id: storeId,\n contextId: 'global',\n parentId: 'root',\n suspenseId: '',\n componentName: 'root-app',\n componentProps: {},\n });\n }\n\n // try to look up store in current or parent context\n return this.lookupStore(storeId, params) as T;\n }\n\n /**\n * Lookup store\n */\n protected lookupStore(id: string, params: IStoreParams): TInitStore<TAnyStore> | undefined {\n const { contextId, parentId: defaultParentId } = params;\n const clearId = id.split('--')?.[0];\n const { ids, parentId } = this.storesRelations.get(contextId!) ?? {\n ids: new Set(),\n parentId: defaultParentId,\n };\n\n const matchedIds = [...ids].filter((storeId) => storeId.startsWith(`${clearId}--`));\n\n if (matchedIds.length === 1) {\n return this.stores.get(matchedIds[0]);\n } else if (matchedIds.length > 1) {\n console.error(\n 'Parent context has multiple stores with the same id, please pass key to getStore function.',\n );\n\n return undefined;\n }\n\n if (!parentId || parentId === 'root') {\n return undefined;\n }\n\n return this.lookupStore(id, { contextId: this.getBiggerContext(parentId, defaultParentId) });\n }\n\n /**\n * Get bigger context from two\n */\n protected getBiggerContext(ctx1?: string, ctx2?: string): string | undefined {\n if (!ctx1) {\n return ctx2;\n } else if (!ctx2) {\n return ctx1;\n }\n\n const regexp = /[^a-zA-Z]/g;\n\n return ctx1.replace(regexp, '') > ctx2.replace(regexp, '') ? ctx1 : ctx2;\n }\n\n /**\n * Create new store instance\n */\n protected createStore<T>(\n store: IConstructableStore<T>,\n params: Omit<Required<IStoreParams>, 'key'>,\n ): T {\n const { id, contextId, parentId, suspenseId, componentName, componentProps } = params;\n\n // only for global store\n if (this.stores.has(id)) {\n return this.stores.get(id) as T;\n }\n\n const newStore = new store({\n ...this.storesParams,\n storeManager: this,\n getStore: <TS>(\n targetStore: IConstructableStore<TS>,\n targetParams = { contextId, parentId },\n ) => this.getStore(targetStore, targetParams),\n componentProps,\n initState: this.initState[id],\n });\n\n // assign params to new store\n newStore.libStoreId = id;\n newStore.isGlobal = store.isGlobal;\n newStore.libStoreContextId = store.isGlobal ? 'global' : contextId;\n newStore.libStoreParentId =\n store.isGlobal || !parentId || parentId === contextId ? 'root' : parentId;\n newStore.libStoreSuspenseId = suspenseId;\n newStore.libStoreComponentName = componentName;\n\n this.setStoreStatus(newStore, store.isGlobal ? StoreStatus.inUse : StoreStatus.init);\n this.prepareStore(newStore);\n EventManager.publish(Events.CREATE_STORE, { store });\n\n return newStore as T;\n }\n\n /**\n * Create stores for component\n */\n public createStores(\n map: [string, TStoreDefinition][],\n parentId: string,\n contextId: string,\n suspenseId: string,\n componentName: string,\n componentProps: Record<string, any> = {},\n ): TStores {\n return map.reduce((res, [key, store]) => {\n const {\n id,\n store: s,\n isParent = false,\n } = 'store' in store ? store : { store, id: undefined, isParent: false };\n const storeId =\n id ||\n (isParent\n ? (this.getStore(s, { contextId, parentId })?.libStoreId as string)\n : this.getStoreId(s, { key, contextId }));\n\n return {\n ...res,\n [key]: storeId\n ? this.createStore(s, {\n id: storeId,\n contextId,\n parentId,\n suspenseId,\n componentName,\n componentProps,\n })\n : undefined,\n };\n }, {});\n }\n\n /**\n * Prepare store before usage\n */\n protected prepareStore(store: TStores[string]): void {\n const storeId = store.libStoreId!;\n const contextId = store.libStoreContextId!;\n const suspenseId = store.libStoreSuspenseId!;\n\n // restore initial state from server\n const initState = this.initState[storeId];\n const persistedState = this.persistData[storeId];\n\n if (this.stores.has(storeId)) {\n return;\n }\n\n if (initState) {\n deepMerge(store, initState);\n }\n\n // restore persisted state\n if ('wakeup' in store && Manager.persistedStores.has(storeId)) {\n store.wakeup?.({ initState, persistedState, manager: this });\n }\n\n // track changes in persisted store\n if (Manager.persistedStores.has(storeId) && 'addOnChangeListener' in store) {\n const onDestroyDefault = store.onDestroy?.bind(store);\n const removeListener = store.addOnChangeListener!(store, this);\n\n store.onDestroy = () => {\n removeListener?.();\n onDestroyDefault?.();\n };\n }\n\n store.init?.();\n\n if (!this.storesRelations.has(contextId)) {\n this.storesRelations.set(contextId, {\n ids: new Set(),\n parentId:\n !store.libStoreParentId || store.libStoreParentId === contextId\n ? 'root'\n : store.libStoreParentId,\n componentName: store.libStoreComponentName,\n });\n }\n\n if (!this.suspenseRelations.has(suspenseId)) {\n this.suspenseRelations.set(suspenseId, new Set());\n }\n\n const { ids } = this.storesRelations.get(contextId)!;\n\n // add store to manager\n this.stores.set(storeId, store);\n ids.add(storeId);\n // add store relation with suspense\n this.suspenseRelations.get(suspenseId)!.add(storeId);\n }\n\n /**\n * Remove store\n */\n protected removeStore(store: TStores[string]): void {\n const storeId = store.libStoreId!;\n const suspenseId = store.libStoreSuspenseId!;\n const { ids } = this.storesRelations.get(store.libStoreContextId!) ?? { ids: new Set() };\n\n if (!this.stores.has(storeId)) {\n return;\n }\n\n this.stores.delete(storeId);\n ids.delete(storeId);\n\n if (suspenseId && this.suspenseRelations.get(suspenseId)?.has(storeId)) {\n this.suspenseRelations.get(suspenseId)!.delete(storeId);\n }\n\n // cleanup store relations\n if (!ids.size) {\n this.storesRelations.delete(store.libStoreContextId!);\n }\n\n if ('onDestroy' in store) {\n store.onDestroy?.();\n }\n\n EventManager.publish(Events.DELETE_STORE, { store });\n }\n\n /**\n * Mount stores to component\n */\n public mountStores(stores: TStores): () => void {\n const { shouldRemoveInitState } = this.options;\n\n Object.values(stores).forEach((store) => {\n const storeId = store.libStoreId!;\n\n // cleanup init state\n if (shouldRemoveInitState && this.initState[storeId]) {\n delete this.initState[storeId];\n }\n\n this.setStoreStatus(store, StoreStatus.inUse);\n EventManager.publish(Events.MOUNT_STORE, { store });\n });\n\n return () => {\n Object.values(stores).forEach((store) => {\n if (store.isGlobal) {\n return;\n }\n\n this.setStoreStatus(store, StoreStatus.unused);\n EventManager.publish(Events.UNMOUNT_STORE, { store });\n });\n };\n }\n\n /**\n * Change the stores status to touched\n */\n public touchedStores(stores: TStores): void {\n Object.values(stores).forEach((store) => {\n if (store.libStoreStatus !== StoreStatus.init || store.isGlobal) {\n return;\n }\n\n this.setStoreStatus(store, StoreStatus.touched);\n });\n }\n\n /**\n * Change store status\n */\n protected setStoreStatus(store: TStores[string], status: StoreStatus): void {\n const { destroyTimers: { init = 500, touched = 10000, unused = 1000 } = {} } = this.options;\n\n store.libStoreStatus = status;\n\n clearTimeout(store.libDestroyTimer);\n\n let destroyTime = 0;\n\n switch (status) {\n case StoreStatus.init:\n destroyTime = init;\n break;\n\n case StoreStatus.touched:\n destroyTime = touched;\n break;\n\n case StoreStatus.unused:\n destroyTime = unused;\n break;\n }\n\n if (!destroyTime) {\n return;\n }\n\n store.libDestroyTimer = setTimeout(() => this.removeStore(store), destroyTime);\n }\n\n /**\n * Get store state\n */\n public getStoreState(store: TAnyStore): Record<string, any> {\n return store.toJSON?.() ?? Manager.getObservableProps(store);\n }\n\n /**\n * Get store's state\n */\n public toJSON(ids?: string[]): Record<string, any> {\n const result = {};\n const stores = Array.isArray(ids)\n ? ids.reduce((res, id) => {\n if (this.stores.has(id)) {\n res.set(id, this.stores.get(id)!);\n }\n\n return res;\n }, new Map<string, TInitStore>())\n : this.stores;\n\n for (const [storeId, store] of stores.entries()) {\n result[storeId] = this.getStoreState(store);\n }\n\n return result;\n }\n\n /**\n * Save persisted store state to provided storage\n */\n public async savePersistedStore(store: IStorePersisted): Promise<boolean> {\n if (this.options.shouldDisablePersist || !this.storage) {\n return false;\n }\n\n try {\n this.persistData = {\n ...this.persistData,\n [this.getStoreId(store)]: this.getStoreState(store),\n };\n\n await this.storage?.set(this.persistData);\n\n return true;\n } catch (e) {\n console.error('Failed to persist stores: ', e);\n }\n\n return false;\n }\n\n /**\n * Get observable store props (fields)\n */\n public static getObservableProps(store: TAnyStore): Record<string, any> {\n const props = toJS(store);\n\n return Object.entries(props).reduce(\n (res, [prop, value]) => ({\n ...res,\n ...(isObservableProp(store, prop) || isPropSimpleExported(store, prop)\n ? { [prop]: value }\n : {}),\n ...(isPropObservableExported(store, prop)\n ? { [prop]: Manager.getObservableProps(store[prop] as TAnyStore) }\n : {}),\n }),\n {},\n );\n }\n\n /**\n * Persist store\n */\n public static persistStore<TSt>(\n store: IConstructableStore<TSt>,\n id: string,\n ): IConstructableStore<TSt> {\n if (Manager.persistedStores.has(id)) {\n console.warn(`Duplicate serializable store key: ${id}`);\n\n return store;\n }\n\n Manager.persistedStores.add(id);\n\n store.libStoreId = id;\n\n // add default wakeup handler\n if (!('wakeup' in store.prototype)) {\n store.prototype.wakeup = wakeup;\n }\n\n // add default changes listener\n if (!('addOnChangeListener' in store.prototype)) {\n store.prototype.addOnChangeListener = onChangeListener;\n }\n\n return store;\n }\n}\n\nexport default Manager;\n"],"names":["Manager","static","stores","Map","storesRelations","Set","initState","storage","persistData","storesParams","options","shouldDisablePersist","shouldRemoveInitState","suspenseRelations","constructor","this","Object","assign","instance","window","state","mbxM","push","pushInitState","Array","isArray","forEach","async","get","Error","getStores","getStoresRelations","getSuspenseRelations","persistedStores","storesState","storeId","entries","getStoreId","store","params","id","contextId","key","libStoreId","name","isGlobal","getStore","has","createStore","parentId","suspenseId","componentName","componentProps","lookupStore","defaultParentId","clearId","split","ids","matchedIds","filter","startsWith","length","console","error","getBiggerContext","ctx1","ctx2","regexp","replace","newStore","storeManager","targetStore","targetParams","libStoreContextId","libStoreParentId","libStoreSuspenseId","libStoreComponentName","setStoreStatus","StoreStatus","inUse","init","prepareStore","EventManager","publish","Events","CREATE_STORE","createStores","map","reduce","res","s","isParent","undefined","persistedState","deepMerge","wakeup","manager","onDestroyDefault","onDestroy","bind","removeListener","addOnChangeListener","set","add","removeStore","delete","size","DELETE_STORE","mountStores","values","MOUNT_STORE","unused","UNMOUNT_STORE","touchedStores","libStoreStatus","touched","status","destroyTimers","clearTimeout","libDestroyTimer","destroyTime","setTimeout","getStoreState","toJSON","getObservableProps","result","e","props","toJS","prop","value","isObservableProp","isPropSimpleExported","isPropObservableExported","warn","prototype","onChangeListener"],"mappings":"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"}
1
+ {"version":3,"file":"manager.js","sources":["../src/manager.ts"],"sourcesContent":["import EventManager from '@lomray/event-manager';\nimport { isObservableProp, toJS } from 'mobx';\nimport { ROOT_CONTEXT_ID } from './constants';\nimport deepMerge from './deep-merge';\nimport Events from './events';\nimport { isPropObservableExported, isPropSimpleExported } from './make-exported';\nimport onChangeListener from './on-change-listener';\nimport StoreStatus from './store-status';\nimport type {\n IConstructableStore,\n IGroupedStores,\n IManagerOptions,\n IManagerParams,\n IStorage,\n IStoreParams,\n IStorePersisted,\n TAnyStore,\n TInitStore,\n TStoreDefinition,\n TStores,\n} from './types';\nimport wakeup from './wakeup';\n\n/**\n * Mobx stores manager\n */\nclass Manager {\n /**\n * Manger instance\n */\n protected static instance: Manager;\n\n /**\n * Created stores\n */\n protected readonly stores = new Map<string, TInitStore>();\n\n /**\n * Relations between stores\n * @protected\n */\n protected readonly storesRelations = new Map<\n string, // contextId\n { ids: Set<string>; parentId: string | null; componentName?: string }\n >();\n\n /**\n * Save persisted stores identities\n * @private\n */\n protected static readonly persistedStores = new Set<string>();\n\n /**\n * Initial stores state (local storage, custom etc.)\n * @private\n */\n protected readonly initState: Record<string, any>;\n\n /**\n * Storage for persisted stores\n */\n public readonly storage: IStorage | undefined;\n\n /**\n * Restored persist storage data\n * @protected\n */\n protected persistData: Record<string, any> = {};\n\n /**\n * Additional store's constructor params\n * @private\n */\n protected readonly storesParams: IManagerParams['storesParams'];\n\n /**\n * Manager options\n */\n public readonly options: IManagerOptions = {\n shouldDisablePersist: false,\n shouldRemoveInitState: true,\n };\n\n /**\n * Suspense stores relations\n * @see withStores\n */\n protected suspenseRelations: Map<string, Set<string>> = new Map();\n\n /**\n * @constructor\n */\n public constructor({ initState, storesParams, storage, options }: IManagerParams = {}) {\n this.initState = initState || {};\n this.storesParams = storesParams || {};\n this.storage = storage;\n\n Object.assign(this.options, options || {});\n\n Manager.instance = this;\n\n // only client side\n if (typeof window !== 'undefined') {\n const state = window.mbxM;\n\n window.mbxM = { push: this.pushInitState };\n\n (Array.isArray(state) ? state : []).forEach(this.pushInitState);\n }\n }\n\n /**\n * Init store manager\n */\n public async init(): Promise<Manager> {\n if (this.storage) {\n this.persistData = (await this.storage.get()) || {};\n }\n\n return this;\n }\n\n /**\n * Get manager instance\n */\n public static get(): Manager {\n if (!Manager.instance) {\n throw new Error('Store manager is not initialized.');\n }\n\n return Manager.instance;\n }\n\n /**\n * Get all stores\n */\n public getStores(): Manager['stores'] {\n return this.stores;\n }\n\n /**\n * Get stores relations\n */\n public getStoresRelations(): Manager['storesRelations'] {\n return this.storesRelations;\n }\n\n /**\n * Get suspense relations with stores\n */\n public getSuspenseRelations(): Manager['suspenseRelations'] {\n return this.suspenseRelations;\n }\n\n /**\n * Get persisted stores ids\n */\n public static getPersistedStoresIds(): Set<string> {\n return Manager.persistedStores;\n }\n\n /**\n * Push initial state dynamically\n * E.g. when stream html\n */\n public pushInitState = (storesState: Record<string, any> = {}): void => {\n for (const [storeId, state] of Object.entries(storesState)) {\n this.initState[storeId] = state;\n }\n };\n\n /**\n * Get store identity\n * @protected\n */\n protected getStoreId<T extends TAnyStore>(\n store: IConstructableStore<T> | TInitStore,\n params: IStoreParams = {},\n ): string {\n const { id, contextId, key } = params;\n\n if (id) {\n return id;\n }\n\n if (store.libStoreId) {\n return store.libStoreId;\n }\n\n let storeId = (store['id'] as string) || (store['name'] as string) || store.constructor.name;\n\n if (store.isGlobal) {\n return storeId;\n }\n\n storeId = `${storeId}--${contextId!}`;\n\n return key ? `${storeId}--${key}` : storeId;\n }\n\n /**\n * Get exist store\n */\n public getStore<T>(store: IConstructableStore<T>, params: IStoreParams = {}): T | undefined {\n const storeId = this.getStoreId(store, params);\n\n // full match\n if (this.stores.has(storeId)) {\n return this.stores.get(storeId) as T;\n }\n\n // in case with global store (create if not exist)\n if (store.isGlobal) {\n return this.createStore(store, {\n id: storeId,\n contextId: 'global',\n parentId: ROOT_CONTEXT_ID,\n suspenseId: '',\n componentName: 'root-app',\n componentProps: {},\n });\n }\n\n // try to look up store in current or parent context\n return this.lookupStore(storeId, params) as T;\n }\n\n /**\n * Lookup store\n */\n protected lookupStore(id: string, params: IStoreParams): TInitStore<TAnyStore> | undefined {\n const { contextId, parentId: defaultParentId } = params;\n const clearId = id.split('--')?.[0];\n const { ids, parentId } = this.storesRelations.get(contextId!) ?? {\n ids: new Set(),\n parentId: defaultParentId,\n };\n\n const matchedIds = [...ids].filter((storeId) => storeId.startsWith(`${clearId}--`));\n\n if (matchedIds.length === 1) {\n return this.stores.get(matchedIds[0]);\n } else if (matchedIds.length > 1) {\n console.error(\n 'Parent context has multiple stores with the same id, please pass key to getStore function.',\n );\n\n return undefined;\n }\n\n if (!parentId || parentId === ROOT_CONTEXT_ID) {\n return undefined;\n }\n\n return this.lookupStore(id, { contextId: this.getBiggerContext(parentId, defaultParentId) });\n }\n\n /**\n * Get bigger context from two\n */\n protected getBiggerContext(ctx1?: string, ctx2?: string): string | undefined {\n if (!ctx1) {\n return ctx2;\n } else if (!ctx2) {\n return ctx1;\n }\n\n const regexp = /[^a-zA-Z]/g;\n\n return ctx1.replace(regexp, '') > ctx2.replace(regexp, '') ? ctx1 : ctx2;\n }\n\n /**\n * Create new store instance\n */\n protected createStore<T>(\n store: IConstructableStore<T>,\n params: Omit<Required<IStoreParams>, 'key'>,\n ): T {\n const { id, contextId, parentId, suspenseId, componentName, componentProps } = params;\n\n // only for global store\n if (this.stores.has(id)) {\n return this.stores.get(id) as T;\n }\n\n const newStore = new store({\n ...this.storesParams,\n storeManager: this,\n getStore: <TS>(\n targetStore: IConstructableStore<TS>,\n targetParams = { contextId, parentId },\n ) => this.getStore(targetStore, targetParams),\n componentProps,\n initState: this.initState[id],\n });\n\n // assign params to new store\n newStore.libStoreId = id;\n newStore.isGlobal = store.isGlobal;\n newStore.libStoreContextId = store.isGlobal ? 'global' : contextId;\n newStore.libStoreParentId =\n store.isGlobal || !parentId || parentId === contextId ? ROOT_CONTEXT_ID : parentId;\n newStore.libStoreSuspenseId = suspenseId;\n newStore.libStoreComponentName = componentName;\n\n this.setStoreStatus(newStore, store.isGlobal ? StoreStatus.inUse : StoreStatus.init);\n this.prepareStore(newStore);\n EventManager.publish(Events.CREATE_STORE, { store });\n\n return newStore as T;\n }\n\n /**\n * Create stores for component\n *\n * NOTE: use only inside withStores wrapper\n */\n public createStores(\n map: [string, TStoreDefinition][],\n parentId: string,\n contextId: string,\n suspenseId: string,\n componentName: string,\n componentProps: Record<string, any> = {},\n ): IGroupedStores {\n const result = map.reduce(\n (res, [key, store]) => {\n const {\n id,\n store: s,\n isParent = false,\n } = 'store' in store ? store : { store, id: undefined, isParent: false };\n const storeId =\n id ||\n (isParent\n ? (this.getStore(s, { contextId, parentId })?.libStoreId as string)\n : this.getStoreId(s, { key, contextId }));\n\n if (!storeId) {\n return res;\n }\n\n const storeInstance = this.createStore(s, {\n id: storeId,\n contextId,\n parentId,\n suspenseId,\n componentName,\n componentProps,\n });\n\n if (isParent) {\n res.parentStores[key] = storeInstance;\n } else if (storeInstance.isGlobal) {\n res.globalStores[key] = storeInstance;\n } else {\n res.relativeStores[key] = storeInstance;\n }\n\n return res;\n },\n { relativeStores: {}, parentStores: {}, globalStores: {} },\n );\n\n // need create context relation in case when component doesn't include relative stores\n this.createRelationContext(contextId, parentId, componentName);\n\n return result;\n }\n\n /**\n * Create empty relation context\n */\n protected createRelationContext(\n contextId: string,\n parentId?: string,\n componentName?: string,\n ): void {\n if (this.storesRelations.has(contextId)) {\n return;\n }\n\n this.storesRelations.set(contextId, {\n ids: new Set(),\n parentId: !parentId || parentId === contextId ? ROOT_CONTEXT_ID : parentId,\n componentName,\n });\n }\n\n /**\n * Delete relation context id\n */\n protected removeRelationContext(contextId: string): void {\n const storesRelations = this.storesRelations.get(contextId);\n\n if (!storesRelations || contextId === ROOT_CONTEXT_ID || storesRelations.ids.size > 0) {\n return;\n }\n\n this.storesRelations.delete(contextId);\n }\n\n /**\n * Prepare store before usage\n */\n protected prepareStore(store: TStores[string]): void {\n const storeId = store.libStoreId!;\n const contextId = store.libStoreContextId!;\n const suspenseId = store.libStoreSuspenseId!;\n\n // restore initial state from server\n const initState = this.initState[storeId];\n const persistedState = this.persistData[storeId];\n\n if (this.stores.has(storeId)) {\n return;\n }\n\n if (initState) {\n deepMerge(store, initState);\n }\n\n // restore persisted state\n if ('wakeup' in store && Manager.persistedStores.has(storeId)) {\n store.wakeup?.({ initState, persistedState, manager: this });\n }\n\n // track changes in persisted store\n if (Manager.persistedStores.has(storeId) && 'addOnChangeListener' in store) {\n const onDestroyDefault = store.onDestroy?.bind(store);\n const removeListener = store.addOnChangeListener!(store, this);\n\n store.onDestroy = () => {\n removeListener?.();\n onDestroyDefault?.();\n };\n }\n\n store.init?.();\n this.createRelationContext(contextId, store.libStoreParentId, store.libStoreComponentName);\n\n if (!this.suspenseRelations.has(suspenseId)) {\n this.suspenseRelations.set(suspenseId, new Set());\n }\n\n const { ids } = this.storesRelations.get(contextId)!;\n\n // add store to manager\n this.stores.set(storeId, store);\n ids.add(storeId);\n // add store relation with suspense\n this.suspenseRelations.get(suspenseId)!.add(storeId);\n }\n\n /**\n * Remove store\n */\n protected removeStore(store: TStores[string]): void {\n const storeId = store.libStoreId!;\n const suspenseId = store.libStoreSuspenseId!;\n const { ids } = this.storesRelations.get(store.libStoreContextId!) ?? { ids: new Set() };\n\n if (!this.stores.has(storeId)) {\n return;\n }\n\n this.stores.delete(storeId);\n ids.delete(storeId);\n\n if (suspenseId && this.suspenseRelations.get(suspenseId)?.has(storeId)) {\n this.suspenseRelations.get(suspenseId)!.delete(storeId);\n }\n\n this.removeRelationContext(store.libStoreContextId!);\n\n if ('onDestroy' in store) {\n store.onDestroy?.();\n }\n\n EventManager.publish(Events.DELETE_STORE, { store });\n }\n\n /**\n * Mount stores to component\n *\n * NOTE: use only inside withStores wrapper\n */\n public mountStores(\n contextId: string,\n { globalStores = {}, relativeStores = {} }: Partial<IGroupedStores>,\n ): () => void {\n const { shouldRemoveInitState } = this.options;\n const touchableStores = { ...globalStores, ...relativeStores };\n\n Object.values(touchableStores).forEach((store) => {\n const storeId = store.libStoreId!;\n\n // cleanup init state\n if (shouldRemoveInitState && this.initState[storeId]) {\n delete this.initState[storeId];\n }\n\n this.setStoreStatus(store, StoreStatus.inUse);\n EventManager.publish(Events.MOUNT_STORE, { store });\n });\n\n return () => {\n Object.values(touchableStores).forEach((store) => {\n if (store.isGlobal) {\n return;\n }\n\n this.setStoreStatus(store, StoreStatus.unused);\n EventManager.publish(Events.UNMOUNT_STORE, { store });\n });\n\n this.removeRelationContext(contextId);\n };\n }\n\n /**\n * Change the stores status to touched\n */\n public touchedStores(stores: TStores): void {\n Object.values(stores).forEach((store) => {\n if (store.libStoreStatus !== StoreStatus.init || store.isGlobal) {\n return;\n }\n\n this.setStoreStatus(store, StoreStatus.touched);\n });\n }\n\n /**\n * Change store status\n */\n protected setStoreStatus(store: TStores[string], status: StoreStatus): void {\n const { destroyTimers: { init = 500, touched = 10000, unused = 1000 } = {} } = this.options;\n\n store.libStoreStatus = status;\n\n clearTimeout(store.libDestroyTimer);\n\n let destroyTime = 0;\n\n switch (status) {\n case StoreStatus.init:\n destroyTime = init;\n break;\n\n case StoreStatus.touched:\n destroyTime = touched;\n break;\n\n case StoreStatus.unused:\n destroyTime = unused;\n break;\n }\n\n if (!destroyTime) {\n return;\n }\n\n store.libDestroyTimer = setTimeout(() => this.removeStore(store), destroyTime);\n }\n\n /**\n * Get store state\n */\n public getStoreState(store: TAnyStore): Record<string, any> {\n return store.toJSON?.() ?? Manager.getObservableProps(store);\n }\n\n /**\n * Get store's state\n */\n public toJSON(ids?: string[]): Record<string, any> {\n const result = {};\n const stores = Array.isArray(ids)\n ? ids.reduce((res, id) => {\n if (this.stores.has(id)) {\n res.set(id, this.stores.get(id)!);\n }\n\n return res;\n }, new Map<string, TInitStore>())\n : this.stores;\n\n for (const [storeId, store] of stores.entries()) {\n result[storeId] = this.getStoreState(store);\n }\n\n return result;\n }\n\n /**\n * Save persisted store state to provided storage\n */\n public async savePersistedStore(store: IStorePersisted): Promise<boolean> {\n if (this.options.shouldDisablePersist || !this.storage) {\n return false;\n }\n\n try {\n this.persistData = {\n ...this.persistData,\n [this.getStoreId(store)]: this.getStoreState(store),\n };\n\n await this.storage?.set(this.persistData);\n\n return true;\n } catch (e) {\n console.error('Failed to persist stores: ', e);\n }\n\n return false;\n }\n\n /**\n * Get observable store props (fields)\n */\n public static getObservableProps(store: TAnyStore): Record<string, any> {\n const props = toJS(store);\n\n return Object.entries(props).reduce(\n (res, [prop, value]) => ({\n ...res,\n ...(isObservableProp(store, prop) || isPropSimpleExported(store, prop)\n ? { [prop]: value }\n : {}),\n ...(isPropObservableExported(store, prop)\n ? { [prop]: Manager.getObservableProps(store[prop] as TAnyStore) }\n : {}),\n }),\n {},\n );\n }\n\n /**\n * Persist store\n */\n public static persistStore<TSt>(\n store: IConstructableStore<TSt>,\n id: string,\n ): IConstructableStore<TSt> {\n if (Manager.persistedStores.has(id)) {\n console.warn(`Duplicate serializable store key: ${id}`);\n\n return store;\n }\n\n Manager.persistedStores.add(id);\n\n store.libStoreId = id;\n\n // add default wakeup handler\n if (!('wakeup' in store.prototype)) {\n store.prototype.wakeup = wakeup;\n }\n\n // add default changes listener\n if (!('addOnChangeListener' in store.prototype)) {\n store.prototype.addOnChangeListener = onChangeListener;\n }\n\n return store;\n }\n}\n\nexport default Manager;\n"],"names":["Manager","static","stores","Map","storesRelations","Set","initState","storage","persistData","storesParams","options","shouldDisablePersist","shouldRemoveInitState","suspenseRelations","constructor","this","Object","assign","instance","window","state","mbxM","push","pushInitState","Array","isArray","forEach","async","get","Error","getStores","getStoresRelations","getSuspenseRelations","persistedStores","storesState","storeId","entries","getStoreId","store","params","id","contextId","key","libStoreId","name","isGlobal","getStore","has","createStore","parentId","ROOT_CONTEXT_ID","suspenseId","componentName","componentProps","lookupStore","defaultParentId","clearId","split","ids","matchedIds","filter","startsWith","length","console","error","getBiggerContext","ctx1","ctx2","regexp","replace","newStore","storeManager","targetStore","targetParams","libStoreContextId","libStoreParentId","libStoreSuspenseId","libStoreComponentName","setStoreStatus","StoreStatus","inUse","init","prepareStore","EventManager","publish","Events","CREATE_STORE","createStores","map","result","reduce","res","s","isParent","undefined","storeInstance","parentStores","globalStores","relativeStores","createRelationContext","set","removeRelationContext","size","delete","persistedState","deepMerge","wakeup","manager","onDestroyDefault","onDestroy","bind","removeListener","addOnChangeListener","add","removeStore","DELETE_STORE","mountStores","touchableStores","values","MOUNT_STORE","unused","UNMOUNT_STORE","touchedStores","libStoreStatus","touched","status","destroyTimers","clearTimeout","libDestroyTimer","destroyTime","setTimeout","getStoreState","toJSON","getObservableProps","e","props","toJS","prop","value","isObservableProp","isPropSimpleExported","isPropObservableExported","warn","prototype","onChangeListener"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lomray/react-mobx-manager",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "This package provides Mobx stores manager for react.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -1,2 +1,2 @@
1
- import t from"lodash";import{spy as e}from"mobx";import r from"../../manager.js";var o;!function(t){t.SPY="spy"}(o||(o={}));class s{manager;static listeners={};constructor(t){this.manager=t,Object.values(s.listeners).forEach((t=>{t()}))}getContextKey(t,e){if("root"===t)return t;const{parentId:r}=this.manager.getStoresRelations().get(t)??{};return r&&"root"!==r?this.getContextKey(r,`${r}.${e??t}`):`${r??"root"}.${e??t}`}getStoresState(){const e={root:{}};try{const o=this.manager.getStores();this.manager.getStoresRelations().forEach((({ids:s,componentName:n},a)=>{const i=this.getContextKey(a);s.forEach((s=>{const a=o.get(s);if(a){const o=a?.toJSON?.()??r.getObservableProps(a);t.set(e,`${i}.stores.${s}`,o),t.set(e,`${i}.componentName`,n)}}))}))}catch(t){}return e}subscribe(){return s.listeners[o.SPY]=e((e=>{["report-end","reaction"].includes(e.type)||this.manager?.__devOnChange?.({event:t.cloneDeep(e),storesState:this.getStoresState()})})),this.manager}}export{s as default};
1
+ import t from"lodash";import{spy as e}from"mobx";import{ROOT_CONTEXT_ID as s}from"../../constants.js";import r from"../../manager.js";var o;!function(t){t.SPY="spy"}(o||(o={}));class n{manager;static listeners={};constructor(t){this.manager=t,Object.values(n.listeners).forEach((t=>{t()}))}getContextKey(t,e){if(t===s)return t;const{parentId:r}=this.manager.getStoresRelations().get(t)??{};return r&&r!==s?this.getContextKey(r,`${r}.${e??t}`):`${r??s}.${e??t}`}getStoresState(){const e={root:{}};try{const s=this.manager.getStores();this.manager.getStoresRelations().forEach((({ids:o,componentName:n},a)=>{const i=this.getContextKey(a);o.forEach((o=>{const a=s.get(o);if(a){const s=a?.toJSON?.()??r.getObservableProps(a);t.set(e,`${i}.stores.${o}`,s),t.set(e,`${i}.componentName`,n)}}))}))}catch(t){}return e}subscribe(){return n.listeners[o.SPY]=e((e=>{["report-end","reaction"].includes(e.type)||this.manager?.__devOnChange?.({event:t.cloneDeep(e),storesState:this.getStoresState()})})),this.manager}}export{n as default};
2
2
  //# sourceMappingURL=state-listener.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"state-listener.js","sources":["../../../src/plugins/dev-extension/state-listener.ts"],"sourcesContent":["import _ from 'lodash';\nimport { spy } from 'mobx';\nimport Manager from '../../manager';\n\nenum Listeners {\n SPY = 'spy',\n}\n\n/**\n * State listener\n */\nclass StateListener {\n /**\n * @protected\n */\n protected manager: Manager;\n\n /**\n * Store global listeners\n * @protected\n */\n protected static listeners: Record<Listeners | string, () => void> = {} as never;\n\n /**\n * @constructor\n */\n public constructor(manager: Manager) {\n this.manager = manager;\n\n Object.values(StateListener.listeners).forEach((unsubscribe) => {\n unsubscribe();\n });\n }\n\n /**\n * Get context tree key\n * @protected\n */\n protected getContextKey(contextId: string, nestedKey?: string): string {\n if (contextId === 'root') {\n return contextId;\n }\n\n const { parentId } = this.manager.getStoresRelations().get(contextId) ?? {};\n\n if (!parentId || parentId === 'root') {\n return `${parentId ?? 'root'}.${nestedKey ?? contextId}`;\n }\n\n return this.getContextKey(parentId, `${parentId}.${nestedKey ?? contextId}`);\n }\n\n /**\n * Get stores state\n * @protected\n */\n protected getStoresState(): { root: Record<string, any> } {\n const state: { root: Record<string, any> } = { root: {} };\n\n try {\n const stores = this.manager.getStores();\n\n this.manager.getStoresRelations().forEach(({ ids, componentName }, contextId) => {\n const key = this.getContextKey(contextId);\n\n ids.forEach((id) => {\n const store = stores.get(id);\n\n if (store) {\n const storeState = store?.toJSON?.() ?? Manager.getObservableProps(store);\n\n _.set(state, `${key}.stores.${id}`, storeState);\n _.set(state, `${key}.componentName`, componentName);\n }\n });\n });\n } catch (e) {\n // manager has not initialized yet\n }\n\n return state;\n }\n\n /**\n * Subscribe on stores changes\n * @protected\n */\n public subscribe(): Manager {\n StateListener.listeners[Listeners.SPY] = spy((event) => {\n if (['report-end', 'reaction'].includes(event.type)) {\n return;\n }\n\n this.manager?.['__devOnChange']?.({\n event: _.cloneDeep(event),\n storesState: this.getStoresState(),\n });\n });\n\n return this.manager;\n }\n}\n\nexport default StateListener;\n"],"names":["Listeners","StateListener","manager","static","constructor","this","Object","values","listeners","forEach","unsubscribe","getContextKey","contextId","nestedKey","parentId","getStoresRelations","get","getStoresState","state","root","stores","getStores","ids","componentName","key","id","store","storeState","toJSON","Manager","getObservableProps","_","set","e","subscribe","SPY","spy","event","includes","type","cloneDeep","storesState"],"mappings":"iFAIA,IAAKA,GAAL,SAAKA,GACHA,EAAA,IAAA,KACD,CAFD,CAAKA,IAAAA,EAEJ,CAAA,IAKD,MAAMC,EAIMC,QAMAC,iBAA2D,CAAA,EAKrEC,YAAmBF,GACjBG,KAAKH,QAAUA,EAEfI,OAAOC,OAAON,EAAcO,WAAWC,SAASC,IAC9CA,GAAa,GAEhB,CAMSC,cAAcC,EAAmBC,GACzC,GAAkB,SAAdD,EACF,OAAOA,EAGT,MAAME,SAAEA,GAAaT,KAAKH,QAAQa,qBAAqBC,IAAIJ,IAAc,GAEzE,OAAKE,GAAyB,SAAbA,EAIVT,KAAKM,cAAcG,EAAU,GAAGA,KAAYD,GAAaD,KAHvD,GAAGE,GAAY,UAAUD,GAAaD,GAIhD,CAMSK,iBACR,MAAMC,EAAuC,CAAEC,KAAM,CAAA,GAErD,IACE,MAAMC,EAASf,KAAKH,QAAQmB,YAE5BhB,KAAKH,QAAQa,qBAAqBN,SAAQ,EAAGa,MAAKC,iBAAiBX,KACjE,MAAMY,EAAMnB,KAAKM,cAAcC,GAE/BU,EAAIb,SAASgB,IACX,MAAMC,EAAQN,EAAOJ,IAAIS,GAEzB,GAAIC,EAAO,CACT,MAAMC,EAAaD,GAAOE,YAAcC,EAAQC,mBAAmBJ,GAEnEK,EAAEC,IAAId,EAAO,GAAGM,YAAcC,IAAME,GACpCI,EAAEC,IAAId,EAAO,GAAGM,kBAAqBD,EACtC,IACD,GAEL,CAAC,MAAOU,GAER,CAED,OAAOf,CACR,CAMMgB,YAYL,OAXAjC,EAAcO,UAAUR,EAAUmC,KAAOC,GAAKC,IACxC,CAAC,aAAc,YAAYC,SAASD,EAAME,OAI9ClC,KAAKH,SAAyB,gBAAI,CAChCmC,MAAON,EAAES,UAAUH,GACnBI,YAAapC,KAAKY,kBAClB,IAGGZ,KAAKH,OACb"}
1
+ {"version":3,"file":"state-listener.js","sources":["../../../src/plugins/dev-extension/state-listener.ts"],"sourcesContent":["import _ from 'lodash';\nimport { spy } from 'mobx';\nimport { ROOT_CONTEXT_ID } from '@src/constants';\nimport Manager from '../../manager';\n\nenum Listeners {\n SPY = 'spy',\n}\n\n/**\n * State listener\n */\nclass StateListener {\n /**\n * @protected\n */\n protected manager: Manager;\n\n /**\n * Store global listeners\n * @protected\n */\n protected static listeners: Record<Listeners | string, () => void> = {} as never;\n\n /**\n * @constructor\n */\n public constructor(manager: Manager) {\n this.manager = manager;\n\n Object.values(StateListener.listeners).forEach((unsubscribe) => {\n unsubscribe();\n });\n }\n\n /**\n * Get context tree key\n * @protected\n */\n protected getContextKey(contextId: string, nestedKey?: string): string {\n if (contextId === ROOT_CONTEXT_ID) {\n return contextId;\n }\n\n const { parentId } = this.manager.getStoresRelations().get(contextId) ?? {};\n\n if (!parentId || parentId === ROOT_CONTEXT_ID) {\n return `${parentId ?? ROOT_CONTEXT_ID}.${nestedKey ?? contextId}`;\n }\n\n return this.getContextKey(parentId, `${parentId}.${nestedKey ?? contextId}`);\n }\n\n /**\n * Get stores state\n * @protected\n */\n protected getStoresState(): { root: Record<string, any> } {\n const state: { root: Record<string, any> } = { root: {} };\n\n try {\n const stores = this.manager.getStores();\n\n this.manager.getStoresRelations().forEach(({ ids, componentName }, contextId) => {\n const key = this.getContextKey(contextId);\n\n ids.forEach((id) => {\n const store = stores.get(id);\n\n if (store) {\n const storeState = store?.toJSON?.() ?? Manager.getObservableProps(store);\n\n _.set(state, `${key}.stores.${id}`, storeState);\n _.set(state, `${key}.componentName`, componentName);\n }\n });\n });\n } catch (e) {\n // manager has not initialized yet\n }\n\n return state;\n }\n\n /**\n * Subscribe on stores changes\n * @protected\n */\n public subscribe(): Manager {\n StateListener.listeners[Listeners.SPY] = spy((event) => {\n if (['report-end', 'reaction'].includes(event.type)) {\n return;\n }\n\n this.manager?.['__devOnChange']?.({\n event: _.cloneDeep(event),\n storesState: this.getStoresState(),\n });\n });\n\n return this.manager;\n }\n}\n\nexport default StateListener;\n"],"names":["Listeners","StateListener","manager","static","constructor","this","Object","values","listeners","forEach","unsubscribe","getContextKey","contextId","nestedKey","ROOT_CONTEXT_ID","parentId","getStoresRelations","get","getStoresState","state","root","stores","getStores","ids","componentName","key","id","store","storeState","toJSON","Manager","getObservableProps","_","set","e","subscribe","SPY","spy","event","includes","type","cloneDeep","storesState"],"mappings":"sIAKA,IAAKA,GAAL,SAAKA,GACHA,EAAA,IAAA,KACD,CAFD,CAAKA,IAAAA,EAEJ,CAAA,IAKD,MAAMC,EAIMC,QAMAC,iBAA2D,CAAA,EAKrEC,YAAmBF,GACjBG,KAAKH,QAAUA,EAEfI,OAAOC,OAAON,EAAcO,WAAWC,SAASC,IAC9CA,GAAa,GAEhB,CAMSC,cAAcC,EAAmBC,GACzC,GAAID,IAAcE,EAChB,OAAOF,EAGT,MAAMG,SAAEA,GAAaV,KAAKH,QAAQc,qBAAqBC,IAAIL,IAAc,GAEzE,OAAKG,GAAYA,IAAaD,EAIvBT,KAAKM,cAAcI,EAAU,GAAGA,KAAYF,GAAaD,KAHvD,GAAGG,GAAYD,KAAmBD,GAAaD,GAIzD,CAMSM,iBACR,MAAMC,EAAuC,CAAEC,KAAM,CAAA,GAErD,IACE,MAAMC,EAAShB,KAAKH,QAAQoB,YAE5BjB,KAAKH,QAAQc,qBAAqBP,SAAQ,EAAGc,MAAKC,iBAAiBZ,KACjE,MAAMa,EAAMpB,KAAKM,cAAcC,GAE/BW,EAAId,SAASiB,IACX,MAAMC,EAAQN,EAAOJ,IAAIS,GAEzB,GAAIC,EAAO,CACT,MAAMC,EAAaD,GAAOE,YAAcC,EAAQC,mBAAmBJ,GAEnEK,EAAEC,IAAId,EAAO,GAAGM,YAAcC,IAAME,GACpCI,EAAEC,IAAId,EAAO,GAAGM,kBAAqBD,EACtC,IACD,GAEL,CAAC,MAAOU,GAER,CAED,OAAOf,CACR,CAMMgB,YAYL,OAXAlC,EAAcO,UAAUR,EAAUoC,KAAOC,GAAKC,IACxC,CAAC,aAAc,YAAYC,SAASD,EAAME,OAI9CnC,KAAKH,SAAyB,gBAAI,CAChCoC,MAAON,EAAES,UAAUH,GACnBI,YAAarC,KAAKa,kBAClB,IAGGb,KAAKH,OACb"}
package/types.d.ts CHANGED
@@ -115,4 +115,9 @@ interface IMobxManagerEvents {
115
115
  store: TAnyStore;
116
116
  };
117
117
  }
118
- export { IWindowManager, IConstructorParams, IStoreLifecycle, IStore, IStorePersisted, TInitStore, IConstructableStore, IStoreConfig, TStoreDefinition, TMapStores, IManagerParams, TWakeup, IStorage, IManagerOptions, TAnyStore, TStores, ClassReturnType, StoresType, IStoreParams, IWithStoreOptions, IMobxManagerEvents };
118
+ interface IGroupedStores {
119
+ relativeStores: TStores;
120
+ parentStores: TStores;
121
+ globalStores: TStores;
122
+ }
123
+ export { IWindowManager, IConstructorParams, IStoreLifecycle, IStore, IStorePersisted, TInitStore, IConstructableStore, IStoreConfig, TStoreDefinition, TMapStores, IManagerParams, TWakeup, IStorage, IManagerOptions, TAnyStore, TStores, ClassReturnType, StoresType, IStoreParams, IWithStoreOptions, IMobxManagerEvents, IGroupedStores };
package/with-stores.js CHANGED
@@ -1,2 +1,2 @@
1
- import{useConsistentSuspense as t,useId as e}from"@lomray/consistent-suspense";import o from"hoist-non-react-statics";import{observer as r}from"mobx-react-lite";import n,{useState as s,useEffect as m}from"react";import{useStoreManager as a,useStoreManagerParent as i,StoreManagerParentProvider as c}from"./context.js";const p=(p,l,{customContextId:u}={})=>{const d=r(p),x=u||p.libStoreContextId,S=p.displayName||p.name,b=o=>{const r=a(),p=i(),{suspenseId:u}=t(),b=e(),[{contextId:f,initStores:I,mountStores:y}]=s((()=>{const t=x||b;return{contextId:t,initStores:r.createStores(Object.entries(l),p,t,u,S,o),mountStores:()=>r.mountStores(I)}}));return m(y,[y]),n.createElement(c,{parentId:f,initStores:I},n.createElement(d,{...o,...I}))};return o(b,p),b.displayName=`Mobx(${S})`,Object.defineProperty(b,"name",{value:b.displayName,writable:!1,enumerable:!1})};export{p as default};
1
+ import{useConsistentSuspense as e,useId as t}from"@lomray/consistent-suspense";import o from"hoist-non-react-statics";import{observer as r}from"mobx-react-lite";import n,{useState as s,useEffect as a}from"react";import{useStoreManager as m,useStoreManagerParent as c,StoreManagerParentProvider as l}from"./context.js";const i=(i,p,{customContextId:u}={})=>{const S=r(i),b=u||i.libStoreContextId,d=i.displayName||i.name,x=o=>{const r=m(),i=c(),{suspenseId:u}=e(),x=t(),[{contextId:f,componentStores:I,touchableStores:y,mountStores:h}]=s((()=>{const e=b||x,t=r.createStores(Object.entries(p),i,e,u,d,o),{globalStores:n,relativeStores:s,parentStores:a}=t,m={...s,...n};return{touchableStores:m,componentStores:{...m,...a},contextId:e,mountStores:()=>r.mountStores(e,t)}}));return a(h,[h]),n.createElement(l,{parentId:f,touchableStores:y},n.createElement(S,{...o,...I}))};return o(x,i),x.displayName=`Mobx(${d})`,Object.defineProperty(x,"name",{value:x.displayName,writable:!1,enumerable:!1})};export{i as default};
2
2
  //# sourceMappingURL=with-stores.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"with-stores.js","sources":["../src/with-stores.tsx"],"sourcesContent":["import { useConsistentSuspense, useId } from '@lomray/consistent-suspense';\nimport hoistNonReactStatics from 'hoist-non-react-statics';\nimport { observer } from 'mobx-react-lite';\nimport type { FC } from 'react';\nimport React, { useEffect, useState } from 'react';\nimport { useStoreManager, useStoreManagerParent, StoreManagerParentProvider } from './context';\nimport type { TMapStores, IWithStoreOptions } from './types';\n\n/**\n * Make component observable and pass stores as props\n */\nconst withStores = <T extends Record<string, any>, TS extends TMapStores>(\n Component: FC<T>,\n stores: TS,\n { customContextId }: IWithStoreOptions = {},\n): FC<Omit<T, keyof TS>> => {\n const ObservableComponent = observer(Component) as FC;\n const manualContextId = customContextId || (Component['libStoreContextId'] as string);\n const componentName = Component.displayName || Component.name;\n\n const Element: FC<Omit<T, keyof TS>> = (props) => {\n const storeManager = useStoreManager();\n const parentId = useStoreManagerParent();\n const { suspenseId } = useConsistentSuspense();\n const id = useId();\n const [{ contextId, initStores, mountStores }] = useState(() => {\n const ctxId = manualContextId || id;\n const initS = storeManager.createStores(\n Object.entries(stores),\n parentId,\n ctxId,\n suspenseId,\n componentName,\n props,\n );\n\n return {\n contextId: ctxId,\n initStores: initS,\n mountStores: () => storeManager.mountStores(initStores),\n };\n });\n\n useEffect(mountStores, [mountStores]);\n\n return (\n <StoreManagerParentProvider parentId={contextId} initStores={initStores}>\n <ObservableComponent {...props} {...initStores} />\n </StoreManagerParentProvider>\n );\n };\n\n hoistNonReactStatics(Element, Component);\n Element.displayName = `Mobx(${componentName})`;\n\n return Object.defineProperty(Element, 'name', {\n value: Element.displayName,\n writable: false,\n enumerable: false,\n });\n};\n\nexport default withStores;\n"],"names":["withStores","Component","stores","customContextId","ObservableComponent","observer","manualContextId","componentName","displayName","name","Element","props","storeManager","useStoreManager","parentId","useStoreManagerParent","suspenseId","useConsistentSuspense","id","useId","contextId","initStores","mountStores","useState","ctxId","createStores","Object","entries","useEffect","React","createElement","StoreManagerParentProvider","hoistNonReactStatics","defineProperty","value","writable","enumerable"],"mappings":"8TAWA,MAAMA,EAAa,CACjBC,EACAC,GACEC,mBAAuC,CAAA,KAEzC,MAAMC,EAAsBC,EAASJ,GAC/BK,EAAkBH,GAAoBF,EAA6B,kBACnEM,EAAgBN,EAAUO,aAAeP,EAAUQ,KAEnDC,EAAkCC,IACtC,MAAMC,EAAeC,IACfC,EAAWC,KACXC,WAAEA,GAAeC,IACjBC,EAAKC,MACJC,UAAEA,EAASC,WAAEA,EAAUC,YAAEA,IAAiBC,GAAS,KACxD,MAAMC,EAAQlB,GAAmBY,EAUjC,MAAO,CACLE,UAAWI,EACXH,WAXYT,EAAaa,aACzBC,OAAOC,QAAQzB,GACfY,EACAU,EACAR,EACAT,EACAI,GAMAW,YAAa,IAAMV,EAAaU,YAAYD,GAC7C,IAKH,OAFAO,EAAUN,EAAa,CAACA,IAGtBO,EAACC,cAAAC,EAA2B,CAAAjB,SAAUM,EAAWC,WAAYA,GAC3DQ,EAACC,cAAA1B,MAAwBO,KAAWU,IAEtC,EAMJ,OAHAW,EAAqBtB,EAAST,GAC9BS,EAAQF,YAAc,QAAQD,KAEvBmB,OAAOO,eAAevB,EAAS,OAAQ,CAC5CwB,MAAOxB,EAAQF,YACf2B,UAAU,EACVC,YAAY,GACZ"}
1
+ {"version":3,"file":"with-stores.js","sources":["../src/with-stores.tsx"],"sourcesContent":["import { useConsistentSuspense, useId } from '@lomray/consistent-suspense';\nimport hoistNonReactStatics from 'hoist-non-react-statics';\nimport { observer } from 'mobx-react-lite';\nimport type { FC } from 'react';\nimport React, { useEffect, useState } from 'react';\nimport { useStoreManager, useStoreManagerParent, StoreManagerParentProvider } from './context';\nimport type { TMapStores, IWithStoreOptions } from './types';\n\n/**\n * Make component observable and pass stores as props\n */\nconst withStores = <T extends Record<string, any>, TS extends TMapStores>(\n Component: FC<T>,\n stores: TS,\n { customContextId }: IWithStoreOptions = {},\n): FC<Omit<T, keyof TS>> => {\n const ObservableComponent = observer(Component) as FC;\n const manualContextId = customContextId || (Component['libStoreContextId'] as string);\n const componentName = Component.displayName || Component.name;\n\n const Element: FC<Omit<T, keyof TS>> = (props) => {\n const storeManager = useStoreManager();\n const parentId = useStoreManagerParent();\n const { suspenseId } = useConsistentSuspense();\n const id = useId();\n const [{ contextId, componentStores, touchableStores, mountStores }] = useState(() => {\n const ctxId = manualContextId || id;\n const groupedStores = storeManager.createStores(\n Object.entries(stores),\n parentId,\n ctxId,\n suspenseId,\n componentName,\n props,\n );\n const { globalStores, relativeStores, parentStores } = groupedStores;\n const tStores = { ...relativeStores, ...globalStores };\n\n return {\n touchableStores: tStores,\n componentStores: { ...tStores, ...parentStores },\n contextId: ctxId,\n mountStores: () => storeManager.mountStores(ctxId, groupedStores),\n };\n });\n\n useEffect(mountStores, [mountStores]);\n\n return (\n <StoreManagerParentProvider parentId={contextId} touchableStores={touchableStores}>\n <ObservableComponent {...props} {...componentStores} />\n </StoreManagerParentProvider>\n );\n };\n\n hoistNonReactStatics(Element, Component);\n Element.displayName = `Mobx(${componentName})`;\n\n return Object.defineProperty(Element, 'name', {\n value: Element.displayName,\n writable: false,\n enumerable: false,\n });\n};\n\nexport default withStores;\n"],"names":["withStores","Component","stores","customContextId","ObservableComponent","observer","manualContextId","componentName","displayName","name","Element","props","storeManager","useStoreManager","parentId","useStoreManagerParent","suspenseId","useConsistentSuspense","id","useId","contextId","componentStores","touchableStores","mountStores","useState","ctxId","groupedStores","createStores","Object","entries","globalStores","relativeStores","parentStores","tStores","useEffect","React","createElement","StoreManagerParentProvider","hoistNonReactStatics","defineProperty","value","writable","enumerable"],"mappings":"8TAWA,MAAMA,EAAa,CACjBC,EACAC,GACEC,mBAAuC,CAAA,KAEzC,MAAMC,EAAsBC,EAASJ,GAC/BK,EAAkBH,GAAoBF,EAA6B,kBACnEM,EAAgBN,EAAUO,aAAeP,EAAUQ,KAEnDC,EAAkCC,IACtC,MAAMC,EAAeC,IACfC,EAAWC,KACXC,WAAEA,GAAeC,IACjBC,EAAKC,MACJC,UAAEA,EAASC,gBAAEA,EAAeC,gBAAEA,EAAeC,YAAEA,IAAiBC,GAAS,KAC9E,MAAMC,EAAQnB,GAAmBY,EAC3BQ,EAAgBd,EAAae,aACjCC,OAAOC,QAAQ3B,GACfY,EACAW,EACAT,EACAT,EACAI,IAEImB,aAAEA,EAAYC,eAAEA,EAAcC,aAAEA,GAAiBN,EACjDO,EAAU,IAAKF,KAAmBD,GAExC,MAAO,CACLR,gBAAiBW,EACjBZ,gBAAiB,IAAKY,KAAYD,GAClCZ,UAAWK,EACXF,YAAa,IAAMX,EAAaW,YAAYE,EAAOC,GACpD,IAKH,OAFAQ,EAAUX,EAAa,CAACA,IAGtBY,EAACC,cAAAC,EAA2B,CAAAvB,SAAUM,EAAWE,gBAAiBA,GAChEa,EAACC,cAAAhC,MAAwBO,KAAWU,IAEtC,EAMJ,OAHAiB,EAAqB5B,EAAST,GAC9BS,EAAQF,YAAc,QAAQD,KAEvBqB,OAAOW,eAAe7B,EAAS,OAAQ,CAC5C8B,MAAO9B,EAAQF,YACfiC,UAAU,EACVC,YAAY,GACZ"}