@lomray/react-mobx-manager 2.0.0-beta.2 → 2.0.0-beta.20

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
@@ -5,10 +5,12 @@
5
5
  <h1 align='center'>Mobx stores manager for React</h1>
6
6
 
7
7
  - One way to escape state tree 🌲🌳🌴.
8
+ - Ready to use with Suspense.
9
+ - Support SSR.
10
+ - Support render to stream.
8
11
  - Manage your Mobx stores like a boss - debug like a hacker.
9
12
  - Simple idea - simple implementation.
10
13
  - Small package size.
11
- - Support render to stream.
12
14
  - Support code splitting out of the box.
13
15
  - Access stores from other stores.
14
16
  - Can be a replacement for react context.
@@ -37,9 +39,10 @@
37
39
  - [Manager](#manager)
38
40
  - [withStores](#withstores)
39
41
  - [StoreManagerProvider](#storemanagerprovider)
40
- - [useStoreManagerContext](#usestoremanagercontext)
41
- - [useStoreManagerParentContext](#usestoremanagerparentcontext)
42
+ - [useStoreManagerContext](#usestoremanager)
43
+ - [useStoreManagerParentContext](#usestoremanagerparent)
42
44
  - [Store](#store)
45
+ - [Example](#demo)
43
46
  - [React Native Debug Plugin](#react-native-debug-plugin)
44
47
  - [Bugs and feature requests](#bugs-and-feature-requests)
45
48
  - [License](#license)
@@ -49,26 +52,68 @@
49
52
  The React-mobx-manager package is distributed using [npm](https://www.npmjs.com/), the node package manager.
50
53
 
51
54
  ```
52
- npm i --save @lomray/react-mobx-manager
55
+ npm i --save @lomray/react-mobx-manager @lomray/consistent-suspense
53
56
  ```
54
57
 
55
- **Optional:** Configure your bundler to keep classnames and function names in production OR use `id` for each store:
58
+ __NOTE:__ this package use [@lomray/consistent-suspense](https://github.com/Lomray-Software/consistent-suspense) for generate stable id's inside Suspense.
59
+
60
+ __Choose one of store id generating strategy__:
56
61
 
62
+ 1. Configure your bundler to keep classnames and function names. Store id will be generated from class names (chose unique class names).
57
63
  - **React:** (craco or webpack config, terser options)
58
64
  ```bash
59
65
  terserOptions.keep_classnames = true;
60
66
  terserOptions.keep_fnames = true;
61
67
  ```
62
68
 
63
- - **React Native:** (metro bundler config)
69
+ - **React Native:** (metro bundler config: metro.config.js)
70
+ ```js
71
+ module.exports = {
72
+ transformer: {
73
+ minifierConfig: {
74
+ keep_classnames: true,
75
+ keep_fnames: true,
76
+ },
77
+ }
78
+ }
64
79
  ```
65
- transformer: {
66
- minifierConfig: {
67
- keep_classnames: true,
68
- keep_fnames: true,
69
- },
80
+ 2. Define `id` for each store.
81
+
82
+ ```typescript
83
+ import { makeObservable } from "mobx";
84
+
85
+ class MyStore {
86
+ /**
87
+ * Define unique store id
88
+ */
89
+ static id = 'Unique-store-id';
90
+
91
+ constructor() {
92
+ makeObservable(this, {})
93
+ }
70
94
  }
71
95
  ```
96
+ 3. Use `Vite plugins`.
97
+
98
+ ```typescript
99
+ import { defineConfig } from 'vite';
100
+ import react from '@vitejs/plugin-react';
101
+ import MobxManager from '@lomray/react-mobx-manager/plugins/vite/index';
102
+
103
+ // https://vitejs.dev/config/
104
+ export default defineConfig({
105
+ /**
106
+ * Store id's will be generated automatically, just chill
107
+ */
108
+ plugins: [react(), MobxManager()]
109
+ });
110
+
111
+ /**
112
+ * Detect mobx store:
113
+ - by makeObservable or makeAutoObservable
114
+ - by @mobx-store jsdoc before class
115
+ */
116
+ ```
72
117
 
73
118
  ## Usage
74
119
 
@@ -77,24 +122,27 @@ Import `Manager, StoreManagerProvider` from `@lomray/react-mobx-manager` into yo
77
122
  ```typescript jsx
78
123
  import React from 'react';
79
124
  import ReactDOM from 'react-dom/client';
80
- import './index.css';
125
+ import { ConsistentSuspenseProvider } from '@lomray/consistent-suspense';
81
126
  import { Manager, StoreManagerProvider, MobxLocalStorage } from '@lomray/react-mobx-manager';
82
127
  import App from './app';
83
128
  import MyApiClient from './services/my-api-client';
129
+ import './index.css';
84
130
 
85
131
  const apiClient = new MyApiClient();
86
132
  const storeManager = new Manager({
87
133
  storage: new MobxLocalStorage(), // optional: needs for persisting stores
88
- storesParams: { apiClient }, // optional: we can provide our api client for access from the store
134
+ storesParams: { apiClient }, // optional: we can provide our api client for access from the each store
89
135
  });
90
136
 
91
137
  const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
92
138
 
93
139
  root.render(
94
140
  <React.StrictMode>
95
- <StoreManagerProvider storeManager={storeManager} shouldInit>
96
- <App />
97
- </StoreManagerProvider>
141
+ <ConsistentSuspenseProvider> {/** required **/}
142
+ <StoreManagerProvider storeManager={storeManager} shouldInit>
143
+ <App />
144
+ </StoreManagerProvider>
145
+ </ConsistentSuspenseProvider>
98
146
  </React.StrictMode>,
99
147
  );
100
148
  ```
@@ -198,15 +246,16 @@ const User: FC<TProps> = ({ userStore: { name } }) => {
198
246
  export default withStores(User, stores);
199
247
  ```
200
248
 
201
- [See app example](example) for a better understanding.
249
+ [See app example](https://github.com/Lomray-Software/vite-template) for a better understanding.
202
250
 
203
251
  ## Support SSR
204
252
  Does this library support SSR? Short answer - yes, but we need some steps to prepare our framework.
253
+ - Look at [Vite demo app](https://github.com/Lomray-Software/vite-template) for a better understanding.
205
254
  - Look at [After.js (razzle) based project](https://github.com/Lomray-Software/microservices-dashboard/blob/staging/src/pages/user/index.tsx#L82) for a better understanding.
206
255
  - Look at [NextJS example](https://github.com/Lomray-Software/nextjs-mobx-store-manager-example) for a better understanding (needs writing a wrapper).
207
256
 
208
257
  ## Important Tips
209
- - Create **singleton** store only for global stores e.g, for application settings, logged user, etc.
258
+ - Create **singleton** store only for global stores e.g, for application settings, logged user, theme, etc.
210
259
  - To get started, stick to the concept: Store for Component. Don't connect (through withStores) not singleton store to several components.
211
260
 
212
261
  ## Documentation
@@ -253,10 +302,13 @@ const storeManager = new Manager({
253
302
  */
254
303
  shouldRemoveInitState: true,
255
304
  /**
256
- * Enable this option if your application support server-side rendering (on both side, client and server)
257
- * Default: false
305
+ * Configure store destroy timers
258
306
  */
259
- isSSR: false,
307
+ destroyTimers: {
308
+ init: 500,
309
+ touched: 10000, // NOTE: set to max request timeout
310
+ unused: 1000,
311
+ },
260
312
  }
261
313
  });
262
314
 
@@ -285,16 +337,11 @@ const store2 = storeManager.getStore(SomeStore, { contextId: 'necessary-context-
285
337
  */
286
338
  const relations = storeManager.getStoresRelations();
287
339
 
288
- /**
289
- * Generate unique context id
290
- */
291
- const contextId = storeManager.createContextId();
292
-
293
340
  /**
294
341
  * Manually create stores for component
295
342
  * NOTE: 'withStores' wrapper use this method, probably you won't need it
296
343
  */
297
- const stores = storeManager.createStores(['someStore', MyStore], 'parent-id', 'context-id', 'HomePage');
344
+ const stores = storeManager.createStores(['someStore', MyStore], 'parent-id', 'context-id', 'suspense-id', 'HomePage', { componentProp: 'test' });
298
345
 
299
346
  /**
300
347
  * Mount/Unmount simple stores to component
@@ -338,10 +385,10 @@ const storeClass = Manager.persistStore(class MyStore {}, 'my-store');
338
385
  import { withStores } from '@lomray/react-mobx-manager';
339
386
 
340
387
  /**
341
- * Create and connect 'stores' to component
388
+ * Create and connect 'stores' to component with custom context id
342
389
  * NOTE: In most cases, you don't need to pass a third argument (contextId).
343
390
  */
344
- withStores(Component, stores, 'optional-context-id');
391
+ withStores(Component, stores, { customContextId: 'optional-context-id' });
345
392
 
346
393
  const stores = { myStore: MyStore, anotherStore: AnotherStore };
347
394
  ```
@@ -361,27 +408,27 @@ import { StoreManagerProvider } from '@lomray/react-mobx-manager';
361
408
  </StoreManagerProvider>
362
409
  ```
363
410
 
364
- ### useStoreManagerContext
411
+ ### useStoreManager
365
412
  ```typescript jsx
366
- import { useStoreManagerContext } from '@lomray/react-mobx-manager';
413
+ import { useStoreManager } from '@lomray/react-mobx-manager';
367
414
 
368
415
  const MyComponent: FC = () => {
369
416
  /**
370
417
  * Get store manager inside your function component
371
418
  */
372
- const storeManager = useStoreManagerContext();
419
+ const storeManager = useStoreManager();
373
420
  }
374
421
  ```
375
422
 
376
- ### useStoreManagerParentContext
423
+ ### useStoreManagerParent
377
424
  ```typescript jsx
378
- import { useStoreManagerParentContext } from '@lomray/react-mobx-manager';
425
+ import { useStoreManagerParent } from '@lomray/react-mobx-manager';
379
426
 
380
427
  const MyComponent: FC = () => {
381
428
  /**
382
429
  * Get parent context id
383
430
  */
384
- const { parentId } = useStoreManagerParentContext();
431
+ const { parentId } = useStoreManagerParent();
385
432
  }
386
433
  ```
387
434
 
@@ -414,7 +461,7 @@ class MyStore {
414
461
  /**
415
462
  * @private
416
463
  */
417
- private someParentStore: ClassReturnType<typeof SomeParentStore>;
464
+ private readonly someParentStore: ClassReturnType<typeof SomeParentStore>;
418
465
 
419
466
  /**
420
467
  * @constructor
@@ -445,14 +492,6 @@ class MyStore {
445
492
  // do something
446
493
  }
447
494
 
448
- /**
449
- * Define this method if you want to do something when a component with this store is mount
450
- * @private
451
- */
452
- private onMount(): void {
453
- // do something
454
- }
455
-
456
495
  /**
457
496
  * Define this method if you want to do something when a component with this store is unmount
458
497
  * @private
@@ -476,9 +515,11 @@ Lifecycles:
476
515
  - constructor
477
516
  - wakeup (restore state from persisted store)
478
517
  - init
479
- - onMount
480
518
  - onDestroy
481
519
 
520
+ ## Demo
521
+ Explore [demo app](https://github.com/Lomray-Software/vite-template) to more understand.
522
+
482
523
  ## React Native debug plugin
483
524
  For debug state, you can use [Reactotron debug plugin](https://github.com/Lomray-Software/reactotron-mobx-store-manager)
484
525
 
package/lib/context.d.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  import React from 'react';
3
3
  import { FC, ReactElement } from "react";
4
4
  import Manager from "./manager.js";
5
+ import { TStores } from "./types-8fe84e04.js";
5
6
  interface IStoreManagerProvider {
6
7
  storeManager: Manager;
7
8
  shouldInit?: boolean;
@@ -9,12 +10,9 @@ interface IStoreManagerProvider {
9
10
  children?: React.ReactNode;
10
11
  }
11
12
  interface IStoreManagerParentProvider {
12
- children?: React.ReactNode;
13
13
  parentId: string;
14
- }
15
- interface IStoreManagerSuspenseProvider {
16
14
  children?: React.ReactNode;
17
- id: string | null;
15
+ initStores?: TStores;
18
16
  }
19
17
  /**
20
18
  * Mobx store manager context
@@ -24,15 +22,6 @@ declare const StoreManagerContext: React.Context<Manager>;
24
22
  * To spread relationships
25
23
  */
26
24
  declare const StoreManagerParentContext: React.Context<string>;
27
- /**
28
- * Generate id for suspended component stores
29
- */
30
- declare const StoreManagerSuspenseContext: React.Context<string | null>;
31
- /**
32
- * Mobx store manager parent provider
33
- * @constructor
34
- */
35
- declare const StoreManagerSuspenseProvider: FC<IStoreManagerSuspenseProvider>;
36
25
  /**
37
26
  * Mobx store manager parent provider
38
27
  * @constructor
@@ -43,7 +32,6 @@ declare const StoreManagerParentProvider: FC<Omit<IStoreManagerParentProvider, '
43
32
  * @constructor
44
33
  */
45
34
  declare const StoreManagerProvider: FC<IStoreManagerProvider>;
46
- declare const useStoreManagerContext: () => Manager;
47
- declare const useStoreManagerParentContext: () => IStoreManagerParentProvider['parentId'];
48
- declare const useStoreManagerSuspenseContext: () => IStoreManagerSuspenseProvider['id'];
49
- export { StoreManagerContext, StoreManagerParentContext, StoreManagerSuspenseContext, StoreManagerProvider, StoreManagerParentProvider, StoreManagerSuspenseProvider, useStoreManagerContext, useStoreManagerParentContext, useStoreManagerSuspenseContext };
35
+ declare const useStoreManager: () => Manager;
36
+ declare const useStoreManagerParent: () => IStoreManagerParentProvider['parentId'];
37
+ export { StoreManagerContext, StoreManagerParentContext, StoreManagerProvider, StoreManagerParentProvider, useStoreManager, useStoreManagerParent };
package/lib/context.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react");function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=t(e);const a=r.default.createContext({}),n=r.default.createContext("root"),o=r.default.createContext(null),s=({children:e,parentId:t})=>r.default.createElement(n.Provider,{value:t,children:e});exports.StoreManagerContext=a,exports.StoreManagerParentContext=n,exports.StoreManagerParentProvider=s,exports.StoreManagerProvider=({children:t,storeManager:n,fallback:o,shouldInit:u=!1})=>{const[l,d]=e.useState(!u);return e.useEffect((()=>{u&&n.init().then((()=>d(!0))).catch((e=>{console.error("Failed initialized store manager: ",e)}))}),[u,n]),r.default.createElement(a.Provider,{value:n},r.default.createElement(s,{parentId:"root"},l?t:o||t))},exports.StoreManagerSuspenseContext=o,exports.StoreManagerSuspenseProvider=({children:e,id:t})=>r.default.createElement(o.Provider,{value:t,children:e}),exports.useStoreManagerContext=()=>e.useContext(a),exports.useStoreManagerParentContext=()=>e.useContext(n),exports.useStoreManagerSuspenseContext=()=>e.useContext(o);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react");function t(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=t(e);const a=r.default.createContext({}),o=r.default.createContext("root"),n=({parentId:e,children:t,initStores:a})=>{const n=s();return a&&n.touchedStores(a),r.default.createElement(o.Provider,{value:e,children:t})},s=()=>e.useContext(a);exports.StoreManagerContext=a,exports.StoreManagerParentContext=o,exports.StoreManagerParentProvider=n,exports.StoreManagerProvider=({children:t,storeManager:o,fallback:s,shouldInit:u=!1})=>{const[l,c]=e.useState(!u);return e.useEffect((()=>{u&&o.init().then((()=>c(!0))).catch((e=>{console.error("Failed initialized store manager: ",e)}))}),[u,o]),r.default.createElement(a.Provider,{value:o},r.default.createElement(n,{parentId:"root"},l?t:s||t))},exports.useStoreManager=s,exports.useStoreManagerParent=()=>e.useContext(o);
package/lib/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
- export * from "./types-abd34741.js";
1
+ export * from "./types-8fe84e04.js";
2
2
  export * from "./context.js";
3
3
  export { default as Manager } from "./manager.js";
4
4
  export { default as onChangeListener } from "./on-change-listener.js";
5
5
  export { default as wakeup } from "./wakeup.js";
6
6
  export { default as withStores } from "./with-stores.js";
7
7
  export { default as Events } from "./events.js";
8
- export { default as MobxSuspense } from "./mobx-suspense.js";
package/lib/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./context.js"),r=require("./manager.js"),t=require("./on-change-listener.js"),o=require("./wakeup.js"),n=require("./with-stores.js"),s=require("./events.js"),a=require("./mobx-suspense.js");exports.StoreManagerContext=e.StoreManagerContext,exports.StoreManagerParentContext=e.StoreManagerParentContext,exports.StoreManagerParentProvider=e.StoreManagerParentProvider,exports.StoreManagerProvider=e.StoreManagerProvider,exports.StoreManagerSuspenseContext=e.StoreManagerSuspenseContext,exports.StoreManagerSuspenseProvider=e.StoreManagerSuspenseProvider,exports.useStoreManagerContext=e.useStoreManagerContext,exports.useStoreManagerParentContext=e.useStoreManagerParentContext,exports.useStoreManagerSuspenseContext=e.useStoreManagerSuspenseContext,exports.Manager=r,exports.onChangeListener=t,exports.wakeup=o,exports.withStores=n,exports.Events=s,exports.MobxSuspense=a;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./context.js"),r=require("./manager.js"),t=require("./on-change-listener.js"),a=require("./wakeup.js"),o=require("./with-stores.js"),n=require("./events.js");exports.StoreManagerContext=e.StoreManagerContext,exports.StoreManagerParentContext=e.StoreManagerParentContext,exports.StoreManagerParentProvider=e.StoreManagerParentProvider,exports.StoreManagerProvider=e.StoreManagerProvider,exports.useStoreManager=e.useStoreManager,exports.useStoreManagerParent=e.useStoreManagerParent,exports.Manager=r,exports.onChangeListener=t,exports.wakeup=a,exports.withStores=o,exports.Events=n;
@@ -0,0 +1,29 @@
1
+ import Manager from "./manager.js";
2
+ /**
3
+ * Stream mobx manager stores
4
+ */
5
+ declare class ManagerStream {
6
+ /**
7
+ * Already pushed preamble
8
+ */
9
+ protected isPreamblePushed: boolean;
10
+ /**
11
+ * Mobx store manager
12
+ */
13
+ protected manager: Manager;
14
+ /**
15
+ * @constructor
16
+ */
17
+ /**
18
+ * @constructor
19
+ */
20
+ constructor(manager: Manager);
21
+ /**
22
+ * Return script with suspense stores to push on stream
23
+ */
24
+ /**
25
+ * Return script with suspense stores to push on stream
26
+ */
27
+ take(suspenseId: string): string | void;
28
+ }
29
+ export { ManagerStream as default };
@@ -0,0 +1 @@
1
+ "use strict";module.exports=class{constructor(e){Object.defineProperty(this,"isPreamblePushed",{enumerable:!0,configurable:!0,writable:!0,value:!1}),Object.defineProperty(this,"manager",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.manager=e}take(e){const s=this.manager.getSuspenseRelations().get(e);if(!(null==s?void 0:s.size))return;const i=JSON.stringify(this.manager.toJSON([...s])),t=this.isPreamblePushed?"":"<script>!window.mbxM && (window.mbxM = []);<\/script>";return this.isPreamblePushed||(this.isPreamblePushed=!0),`${t}<script>window.mbxM.push(${i});<\/script>`}};
package/lib/manager.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { IConstructableStore, IManagerParams, IStorage, IStore, TStoreDefinition, IManagerOptions, TStores, IStoreLifecycle, TInitStore, IStoreParams } from "./types-abd34741.js";
1
+ import StoreStatus from "./store-status.js";
2
+ import { IConstructableStore, IManagerOptions, IManagerParams, IStorage, IStore, IStoreParams, TInitStore, TStoreDefinition, TStores } from "./types-8fe84e04.js";
2
3
  /**
3
4
  * Mobx stores manager
4
5
  */
@@ -48,6 +49,11 @@ declare class Manager {
48
49
  * Manager options
49
50
  */
50
51
  readonly options: IManagerOptions;
52
+ /**
53
+ * Suspense stores relations
54
+ * @see withStores
55
+ */
56
+ protected suspenseRelations: Map<string, Set<string>>;
51
57
  /**
52
58
  * @constructor
53
59
  */
@@ -83,6 +89,13 @@ declare class Manager {
83
89
  * Get stores relations
84
90
  */
85
91
  getStoresRelations(): Manager['storesRelations'];
92
+ /**
93
+ * Get suspense relations with stores
94
+ */
95
+ /**
96
+ * Get suspense relations with stores
97
+ */
98
+ getSuspenseRelations(): Manager['suspenseRelations'];
86
99
  /**
87
100
  * Get persisted stores ids
88
101
  */
@@ -104,13 +117,6 @@ declare class Manager {
104
117
  * @protected
105
118
  */
106
119
  protected getStoreId<T>(store: IConstructableStore<T> | TInitStore, params?: IStoreParams): string;
107
- /**
108
- * Generate new context id
109
- */
110
- /**
111
- * Generate new context id
112
- */
113
- createContextId(id?: string): string;
114
120
  /**
115
121
  * Get exist store
116
122
  */
@@ -142,25 +148,21 @@ declare class Manager {
142
148
  /**
143
149
  * Create stores for component
144
150
  */
145
- createStores(map: [string, TStoreDefinition][], parentId: string, contextId: string, componentName: string, componentProps?: Record<string, any>): TStores;
151
+ createStores(map: [string, TStoreDefinition][], parentId: string, contextId: string, suspenseId: string, componentName: string, componentProps?: Record<string, any>): TStores;
146
152
  /**
147
153
  * Prepare store before usage
148
- * @protected
149
154
  */
150
155
  /**
151
156
  * Prepare store before usage
152
- * @protected
153
157
  */
154
158
  protected prepareStore(store: TStores[string]): void;
155
159
  /**
156
- * Prepare store before mount to component
157
- * @protected
160
+ * Remove store
158
161
  */
159
162
  /**
160
- * Prepare store before mount to component
161
- * @protected
163
+ * Remove store
162
164
  */
163
- protected prepareMount(store: TStores[string]): Required<IStoreLifecycle>['onDestroy'][];
165
+ protected removeStore(store: TStores[string]): void;
164
166
  /**
165
167
  * Mount stores to component
166
168
  */
@@ -168,6 +170,20 @@ declare class Manager {
168
170
  * Mount stores to component
169
171
  */
170
172
  mountStores(stores: TStores): () => void;
173
+ /**
174
+ * Change the stores status to touched
175
+ */
176
+ /**
177
+ * Change the stores status to touched
178
+ */
179
+ touchedStores(stores: TStores): void;
180
+ /**
181
+ * Change store status
182
+ */
183
+ /**
184
+ * Change store status
185
+ */
186
+ protected setStoreStatus(store: TStores[string], status: StoreStatus): void;
171
187
  /**
172
188
  * Get store's state
173
189
  */
package/lib/manager.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e=require("@lomray/event-manager"),t=require("mobx"),s=require("./events.js"),r=require("./on-change-listener.js"),o=require("./wakeup.js");function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=i(e);class a{constructor({initState:e,storesParams:t,storage:s,options:r}={}){Object.defineProperty(this,"stores",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"storesRelations",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"initState",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"storage",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"persistData",{enumerable:!0,configurable:!0,writable:!0,value:{}}),Object.defineProperty(this,"storesParams",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"options",{enumerable:!0,configurable:!0,writable:!0,value:{shouldDisablePersist:!1,shouldRemoveInitState:!0,isSSR:!1}}),Object.defineProperty(this,"pushInitState",{enumerable:!0,configurable:!0,writable:!0,value:(e={})=>{for(const[t,s]of Object.entries(e))this.initState[t]=s}}),this.initState=e||{},this.storesParams=t||{},this.storage=s,Object.assign(this.options,r||{}),a.instance=this,"undefined"==typeof window||window.mobxManager||(window.mobxManager={pushInit:this.pushInitState})}async init(){return this.storage&&(this.persistData=await this.storage.get()||{}),this}static get(){if(!a.instance)throw new Error("Store manager is not initialized.");return a.instance}getStores(){return this.stores}getStoresRelations(){return this.storesRelations}static getPersistedStoresIds(){return a.persistedStores}getStoreId(e,t={}){const{id:s,contextId:r,key:o}=t;if(s)return s;if(e.libStoreId)return e.libStoreId;let i=e.name||e.constructor.name;return e.isSingleton?i:(i=`${i}--${r}`,o?`${i}--${o}`:i)}createContextId(e){return`ctx${e||this.storesRelations.size+1}`}getStore(e,t={}){const s=this.getStoreId(e,t);return this.stores.has(s)?this.stores.get(s):e.isSingleton?this.createStore(e,{id:s,contextId:"singleton",parentId:"root",componentName:"root-app",componentProps:{}}):this.lookupStore(s,t)}lookupStore(e,t){var s,r;const{contextId:o,parentId:i}=t,n=null===(s=e.split("--"))||void 0===s?void 0:s[0],{ids:a,parentId:l}=null!==(r=this.storesRelations.get(o))&&void 0!==r?r:{ids:new Set,parentId:i},d=[...a].filter((e=>e.startsWith(`${n}--`)));if(1===d.length)return this.stores.get(d[0]);if(d.length>1)console.error("Parent context has multiple stores with the same id, please pass key to getStore function.");else if(l&&"root"!==l)return this.lookupStore(e,{contextId:l})}createStore(e,t){var r,o;const{isSSR:i}=this.options,{id:l,contextId:d,parentId:u,componentName:p,componentProps:c}=t;if((e.isSingleton||i)&&this.stores.has(l))return this.stores.get(l);const h=new e({...this.storesParams,storeManager:this,getStore:(e,t={contextId:d,parentId:u})=>this.getStore(e,t),componentProps:c});h.libStoreId=l,h.isSingleton=e.isSingleton,h.libStoreContextId=e.isSingleton?"singleton":d,h.libStoreParentId=e.isSingleton||!u||u===d?"root":u,h.libStoreComponentName=p;const S=this.initState[l],b=this.persistData[l];return S&&Object.assign(h,S),n.default.publish(s.CREATE_STORE,{store:e}),"wakeup"in h&&a.persistedStores.has(l)&&(null===(r=h.wakeup)||void 0===r||r.call(h,h,{initState:S,persistedState:b})),null===(o=h.init)||void 0===o||o.call(h),this.prepareStore(h),(h.isSingleton||i)&&this.prepareMount(h),h}createStores(e,t,s,r,o={}){return e.reduce(((e,[i,n])=>{const[a,l]="store"in n?[n.store,n.id]:[n,this.getStoreId(n,{key:i,contextId:s})];return{...e,[i]:this.createStore(a,{id:l,contextId:s,parentId:t,componentName:r,componentProps:o})}}),{})}prepareStore(e){const t=e.libStoreId,r=e.libStoreContextId;this.storesRelations.has(r)||this.storesRelations.set(r,{ids:new Set,parentId:e.libStoreParentId&&e.libStoreParentId!==r?e.libStoreParentId:"root",componentName:e.libStoreComponentName});const{ids:o}=this.storesRelations.get(r);this.stores.has(t)||(this.stores.set(t,e),o.add(t),n.default.publish(s.ADD_STORE,{store:e}))}prepareMount(e){const{shouldRemoveInitState:t}=this.options,s=e.libStoreId,r=[];return a.persistedStores.has(s)&&"addOnChangeListener"in e&&r.push(e.addOnChangeListener(e,this)),t&&this.initState[s]&&delete this.initState[s],r}mountStores(e){const t=[];return Object.values(e).forEach((e=>{var r;if(this.prepareStore(e),t.push(...this.prepareMount(e)),n.default.publish(s.MOUNT_STORE,{store:e}),"onMount"in e){const s=null===(r=e.onMount)||void 0===r?void 0:r.call(e);"function"==typeof s&&t.push(s)}"onDestroy"in e&&t.push((()=>{var t;return null===(t=e.onDestroy)||void 0===t?void 0:t.call(e)}))})),()=>{t.forEach((e=>e())),Object.values(e).forEach((e=>{var t;const r=e.libStoreId;if(n.default.publish(s.UNMOUNT_STORE,{store:e}),!e.isSingleton){const{ids:o}=null!==(t=this.storesRelations.get(e.libStoreContextId))&&void 0!==t?t:{ids:new Set};this.stores.delete(r),o.delete(r),n.default.publish(s.DELETE_STORE,{store:e}),o.size||this.storesRelations.delete(e.libStoreContextId)}}))}}toJSON(e){var t,s,r;const o={},i=null!==(t=null==e?void 0:e.reduce(((e,t)=>(this.stores.has(t)&&e.set(t,this.stores.get(t)),e)),new Map))&&void 0!==t?t:this.stores;for(const[e,t]of i.entries())o[e]=null!==(r=null===(s=t.toJSON)||void 0===s?void 0:s.call(t))&&void 0!==r?r:a.getObservableProps(t);return o}toPersistedJSON(){var e,t;const s={};for(const r of a.persistedStores){const o=this.stores.get(r);o&&(s[r]=null!==(t=null===(e=o.toJSON)||void 0===e?void 0:e.call(o))&&void 0!==t?t:a.getObservableProps(o))}return s}static getObservableProps(e){const s=t.toJS(e);return Object.entries(s).reduce(((s,[r,o])=>({...s,...t.isObservableProp(e,r)?{[r]:o}:{}})),{})}static persistStore(e,t){return a.persistedStores.has(t)?(console.warn(`Duplicate serializable store key: ${t}`),e):(a.persistedStores.add(t),e.libStoreId=t,"wakeup"in e.prototype||(e.prototype.wakeup=o),"addOnChangeListener"in e.prototype||(e.prototype.addOnChangeListener=r),e)}}Object.defineProperty(a,"persistedStores",{enumerable:!0,configurable:!0,writable:!0,value:new Set}),module.exports=a;
1
+ "use strict";var e=require("@lomray/event-manager"),t=require("mobx"),s=require("./events.js"),r=require("./on-change-listener.js"),o=require("./store-status.js"),i=require("./wakeup.js");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=n(e);class l{constructor({initState:e,storesParams:t,storage:s,options:r}={}){if(Object.defineProperty(this,"stores",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"storesRelations",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"initState",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"storage",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"persistData",{enumerable:!0,configurable:!0,writable:!0,value:{}}),Object.defineProperty(this,"storesParams",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"options",{enumerable:!0,configurable:!0,writable:!0,value:{shouldDisablePersist:!1,shouldRemoveInitState:!0}}),Object.defineProperty(this,"suspenseRelations",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"pushInitState",{enumerable:!0,configurable:!0,writable:!0,value:(e={})=>{for(const[t,s]of Object.entries(e))this.initState[t]=s}}),this.initState=e||{},this.storesParams=t||{},this.storage=s,Object.assign(this.options,r||{}),l.instance=this,"undefined"!=typeof window){const e=window.mbxM;window.mbxM={push:this.pushInitState},(Array.isArray(e)?e:[]).forEach(this.pushInitState)}}async init(){return this.storage&&(this.persistData=await this.storage.get()||{}),this}static get(){if(!l.instance)throw new Error("Store manager is not initialized.");return l.instance}getStores(){return this.stores}getStoresRelations(){return this.storesRelations}getSuspenseRelations(){return this.suspenseRelations}static getPersistedStoresIds(){return l.persistedStores}getStoreId(e,t={}){const{id:s,contextId:r,key:o}=t;if(s)return s;if(e.libStoreId)return e.libStoreId;let i=e.id||e.name||e.constructor.name;return e.isSingleton?i:(i=`${i}--${r}`,o?`${i}--${o}`:i)}getStore(e,t={}){const s=this.getStoreId(e,t);return this.stores.has(s)?this.stores.get(s):e.isSingleton?this.createStore(e,{id:s,contextId:"singleton",parentId:"root",suspenseId:"",componentName:"root-app",componentProps:{}}):this.lookupStore(s,t)}lookupStore(e,t){var s,r;const{contextId:o,parentId:i}=t,n=null===(s=e.split("--"))||void 0===s?void 0:s[0],{ids:a,parentId:l}=null!==(r=this.storesRelations.get(o))&&void 0!==r?r:{ids:new Set,parentId:i},u=[...a].filter((e=>e.startsWith(`${n}--`)));if(1===u.length)return this.stores.get(u[0]);if(u.length>1)console.error("Parent context has multiple stores with the same id, please pass key to getStore function.");else if(l&&"root"!==l)return this.lookupStore(e,{contextId:l})}createStore(e,t){const{id:r,contextId:i,parentId:n,suspenseId:l,componentName:u,componentProps:d}=t;if(this.stores.has(r))return this.stores.get(r);const h=new e({...this.storesParams,storeManager:this,getStore:(e,t={contextId:i,parentId:n})=>this.getStore(e,t),componentProps:d});return h.libStoreId=r,h.isSingleton=e.isSingleton,h.libStoreContextId=e.isSingleton?"singleton":i,h.libStoreParentId=e.isSingleton||!n||n===i?"root":n,h.libStoreSuspenseId=l,h.libStoreComponentName=u,this.setStoreStatus(h,e.isSingleton?o.inUse:o.init),this.prepareStore(h),a.default.publish(s.CREATE_STORE,{store:e}),h}createStores(e,t,s,r,o,i={}){return e.reduce(((e,[n,a])=>{const[l,u]="store"in a?[a.store,a.id]:[a,this.getStoreId(a,{key:n,contextId:s})];return{...e,[n]:this.createStore(l,{id:u,contextId:s,parentId:t,suspenseId:r,componentName:o,componentProps:i})}}),{})}prepareStore(e){var t,r,o;const i=e.libStoreId,n=e.libStoreContextId,u=e.libStoreSuspenseId,d=this.initState[i],h=this.persistData[i];if(this.stores.has(i))return;if(d&&Object.assign(e,d),"wakeup"in e&&l.persistedStores.has(i)&&(null===(t=e.wakeup)||void 0===t||t.call(e,{initState:d,persistedState:h})),l.persistedStores.has(i)&&"addOnChangeListener"in e){const t=null===(r=e.onDestroy)||void 0===r?void 0:r.bind(e),s=e.addOnChangeListener(e,this);e.onDestroy=()=>{null==s||s(),null==t||t()}}null===(o=e.init)||void 0===o||o.call(e),this.storesRelations.has(n)||this.storesRelations.set(n,{ids:new Set,parentId:e.libStoreParentId&&e.libStoreParentId!==n?e.libStoreParentId:"root",componentName:e.libStoreComponentName}),this.suspenseRelations.has(u)||this.suspenseRelations.set(u,new Set);const{ids:c}=this.storesRelations.get(n);this.stores.set(i,e),c.add(i),this.suspenseRelations.get(u).add(i),a.default.publish(s.ADD_STORE,{store:e})}removeStore(e){var t,r,o;const i=e.libStoreId,n=e.libStoreSuspenseId,{ids:l}=null!==(t=this.storesRelations.get(e.libStoreContextId))&&void 0!==t?t:{ids:new Set};this.stores.has(i)&&(this.stores.delete(i),l.delete(i),n&&(null===(r=this.suspenseRelations.get(n))||void 0===r?void 0:r.has(i))&&this.suspenseRelations.get(n).delete(i),l.size||this.storesRelations.delete(e.libStoreContextId),"onDestroy"in e&&(null===(o=e.onDestroy)||void 0===o||o.call(e)),a.default.publish(s.DELETE_STORE,{store:e}))}mountStores(e){const{shouldRemoveInitState:t}=this.options;return Object.values(e).forEach((e=>{const r=e.libStoreId;t&&this.initState[r]&&delete this.initState[r],this.setStoreStatus(e,o.inUse),a.default.publish(s.MOUNT_STORE,{store:e})})),()=>{Object.values(e).forEach((e=>{e.isSingleton||(this.setStoreStatus(e,o.unused),a.default.publish(s.UNMOUNT_STORE,{store:e}))}))}}touchedStores(e){Object.values(e).forEach((e=>{e.libStoreStatus!==o.init||e.isSingleton||this.setStoreStatus(e,o.touched)}))}setStoreStatus(e,t){const{destroyTimers:{init:s=500,touched:r=1e4,unused:i=1e3}={}}=this.options;e.libStoreStatus=t,clearTimeout(e.libDestroyTimer);let n=0;switch(t){case o.init:n=s;break;case o.touched:n=r;break;case o.unused:n=i}n&&(e.libDestroyTimer=setTimeout((()=>this.removeStore(e)),n))}toJSON(e){var t,s,r;const o={},i=null!==(t=null==e?void 0:e.reduce(((e,t)=>(this.stores.has(t)&&e.set(t,this.stores.get(t)),e)),new Map))&&void 0!==t?t:this.stores;for(const[e,t]of i.entries())o[e]=null!==(r=null===(s=t.toJSON)||void 0===s?void 0:s.call(t))&&void 0!==r?r:l.getObservableProps(t);return o}toPersistedJSON(){var e,t;const s={};for(const r of l.persistedStores){const o=this.stores.get(r);o&&(s[r]=null!==(t=null===(e=o.toJSON)||void 0===e?void 0:e.call(o))&&void 0!==t?t:l.getObservableProps(o))}return s}static getObservableProps(e){const s=t.toJS(e);return Object.entries(s).reduce(((s,[r,o])=>({...s,...t.isObservableProp(e,r)?{[r]:o}:{}})),{})}static persistStore(e,t){return l.persistedStores.has(t)?(console.warn(`Duplicate serializable store key: ${t}`),e):(l.persistedStores.add(t),e.libStoreId=t,"wakeup"in e.prototype||(e.prototype.wakeup=i.bind(e)),"addOnChangeListener"in e.prototype||(e.prototype.addOnChangeListener=r),e)}}Object.defineProperty(l,"persistedStores",{enumerable:!0,configurable:!0,writable:!0,value:new Set}),module.exports=l;
@@ -1,4 +1,4 @@
1
- import { IStorePersisted } from "./types-abd34741.js";
1
+ import { IStorePersisted } from "./types-8fe84e04.js";
2
2
  /**
3
3
  * Listen persist store changes
4
4
  */
@@ -0,0 +1,43 @@
1
+ type ICache = Map<string, {
2
+ storeId: string;
3
+ classname: string;
4
+ }>;
5
+ /**
6
+ * Load cached store id's by file name
7
+ */
8
+ declare const loadCache: (isProd?: boolean) => ICache;
9
+ /**
10
+ * Save store id's cache
11
+ */
12
+ declare const saveCache: (cache: ICache) => void;
13
+ /**
14
+ * Get next letter
15
+ */
16
+ declare const getNextLetter: (str?: string) => string;
17
+ /**
18
+ * Store is generator
19
+ */
20
+ declare class Generator {
21
+ cache: ICache;
22
+ protected root: string;
23
+ protected lastId: string;
24
+ // keep last generated production store id (letter)
25
+ constructor(root: string, isProd?: boolean);
26
+ /**
27
+ * Inject store id
28
+ */
29
+ injectId: (code: string, fileId: string) => string;
30
+ /**
31
+ * Get development id
32
+ */
33
+ getDevId: (id: string, classname: string) => string;
34
+ /**
35
+ * Get production store id
36
+ */
37
+ getProdId: () => string;
38
+ /**
39
+ * Try to find mobx store
40
+ */
41
+ matchMobxStore: (code: string) => string | undefined;
42
+ }
43
+ export { saveCache, loadCache, getNextLetter, Generator };
@@ -0,0 +1 @@
1
+ "use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("node:fs"));const r=`${__dirname.split("node_modules")[0]}node_modules/.cache/@lomray/react-mobx-manager`,s=`${r}/store-ids.json`,a=(e=!1)=>{if(e&&t.default.existsSync(s)){const e=JSON.parse(t.default.readFileSync(s,{encoding:"utf-8"}));return new Map(e)}return new Map},i=(e="")=>{var t;const r=e.split(""),s=null!==(t=r.pop())&&void 0!==t?t:"`";if("z"===s)return[...r,"A"].join("");if("Z"===s){const e=r.pop();return e?[i([...r,e].join("")),"a"].join(""):"aa"}return[...r,String.fromCharCode(s.charCodeAt(0)+1)].join("")};exports.Generator=class{constructor(e,t=!1){Object.defineProperty(this,"cache",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"root",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"lastId",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"injectId",{enumerable:!0,configurable:!0,writable:!0,value:(e,t)=>{const{classname:r,storeId:s}=this.cache.get(t),a=new RegExp(`(class\\s${r}\\s+?{)`);return e.replace(a,`$1static id = '${s}';`)}}),Object.defineProperty(this,"getDevId",{enumerable:!0,configurable:!0,writable:!0,value:(e,t)=>`${e.replace(this.root,"").replace(/\/index.(js|ts|tsx)/,"").split("/").filter(Boolean).join("-")}-${t}`}),Object.defineProperty(this,"getProdId",{enumerable:!0,configurable:!0,writable:!0,value:()=>{const e=i(this.lastId),t=`S${e}`;return this.lastId=e,t}}),Object.defineProperty(this,"matchMobxStore",{enumerable:!0,configurable:!0,writable:!0,value:e=>{var t,r,s,a;const{classname:i}=null!==(r=null===(t=e.match(/class\s(?<classname>\w+)\s+?{(?!.*static\sid\s*=.*).+(makeObservable|makeAutoObservable)(?!.*persistStore\(\1.*)/s))||void 0===t?void 0:t.groups)&&void 0!==r?r:{};if(i)return i;const{classname:o}=null!==(a=null===(s=e.match(/(@mobx-store).+class\s(?<classname>\w+)\s+?{(?!.*static\sid\s*=.*).+}(?!.*persistStore.*)/s))||void 0===s?void 0:s.groups)&&void 0!==a?a:{};return o}}),this.root=e,this.cache=a(t)}},exports.getNextLetter=i,exports.loadCache=a,exports.saveCache=e=>{t.default.existsSync(r)||t.default.mkdirSync(r,{recursive:!0}),t.default.writeFileSync(s,JSON.stringify([...e.entries()],null,2),{encoding:"utf-8"})};
@@ -0,0 +1,7 @@
1
+ import { Plugin } from 'vite';
2
+ /**
3
+ * Fix mobx lite suspense hydration
4
+ * @constructor
5
+ */
6
+ declare function HydrationUpdateFix(): Plugin;
7
+ export { HydrationUpdateFix as default };
@@ -0,0 +1 @@
1
+ "use strict";var e=require("node:path");module.exports=function(){return{name:"@lomray/react-mobx-manager-hydration-fix",transform(r,t){const n=e.extname(t).split("?")[0];if([".js",".ts",".tsx"].includes(n)&&r.includes("function useObserver"))return{code:r.replace(/(}\);[^f]+)(forceUpdate\(\);)/s,"$1/*$2*/"),map:{mappings:""}}}}};
@@ -0,0 +1,15 @@
1
+ import { Plugin } from 'vite';
2
+ interface IPluginOptions {
3
+ root?: string;
4
+ isProd?: boolean;
5
+ }
6
+ /**
7
+ * Generate unique store id's
8
+ *
9
+ * Detect mobx store:
10
+ * - by makeObservable or makeAutoObservable
11
+ * - by @mobx-store jsdoc before class
12
+ * @constructor
13
+ */
14
+ declare function IdGenerator({ root, isProd }?: IPluginOptions): Plugin;
15
+ export { IdGenerator as default, IPluginOptions };
@@ -0,0 +1 @@
1
+ "use strict";var e=require("node:path"),r=require("node:process"),t=require("../helpers.js");module.exports=function({root:s=r.cwd(),isProd:a=!1}={}){const n=new t.Generator(s,a);return{name:"@lomray/react-mobx-manager-id-generator",transform(r,t){const s=e.extname(t).split("?")[0];if(t.includes("node_modules")||![".js",".ts",".tsx"].includes(s)||!/(makeObservable|makeAutoObservable)\(/.test(r))return;if(n.cache.has(t))return{code:n.injectId(r,t),map:{mappings:""}};const o=n.matchMobxStore(r);if(o){if(!n.cache.has(t)){const e=a?n.getProdId():n.getDevId(t,o);n.cache.set(t,{classname:o,storeId:e})}return{code:n.injectId(r,t),map:{mappings:""}}}},buildEnd(){a&&t.saveCache(n.cache)}}};
@@ -0,0 +1,7 @@
1
+ import { Plugin } from 'vite';
2
+ /**
3
+ * Mobx manager vite plugins
4
+ * @constructor
5
+ */
6
+ declare function ViteReactMobxManager(): Plugin[];
7
+ export { ViteReactMobxManager as default };
@@ -0,0 +1 @@
1
+ "use strict";var e=require("node:process"),r=require("./hydration-update-fix.js"),t=require("./id-generator.js");function n(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var o=n(e);const i=e=>"production"===e||"production"===o.env.NODE_ENV;module.exports=function(){let e;return[{...r(),apply:()=>!i()},{name:t().name,configResolved({root:r}){e=t({root:r,isProd:i()})},transform(...r){var t;return null===(t=e.transform)||void 0===t?void 0:t.call(this,...r)},buildEnd(...r){var t;null===(t=e.buildEnd)||void 0===t||t.call(this,...r)}}]};
@@ -1,4 +1,4 @@
1
- import { IStorage } from "../types-abd34741.js";
1
+ import { IStorage } from "../types-8fe84e04.js";
2
2
  interface IAsyncStorage {
3
3
  getItem: (key: string) => Promise<string | null>;
4
4
  setItem: (key: string, value: string) => Promise<void>;
@@ -1,4 +1,4 @@
1
- import { IStorage } from "../types-abd34741.js";
1
+ import { IStorage } from "../types-8fe84e04.js";
2
2
  /**
3
3
  * Local storage for mobx store manager
4
4
  */
@@ -0,0 +1,7 @@
1
+ declare enum StoreStatus {
2
+ init = "init",
3
+ touched = "touched",
4
+ inUse = "in-use",
5
+ unused = "unused"
6
+ }
7
+ export { StoreStatus as default };
@@ -0,0 +1 @@
1
+ "use strict";var u;!function(u){u.init="init",u.touched="touched",u.inUse="in-use",u.unused="unused"}(u||(u={}));var e=u;module.exports=e;
@@ -1,4 +1,4 @@
1
- import { TInitStore } from "./types-abd34741.js";
1
+ import { TInitStore } from "./types-8fe84e04.js";
2
2
  interface IPromise<TReturn> extends Promise<TReturn> {
3
3
  status?: 'fulfilled' | 'pending' | 'rejected';
4
4
  value?: TReturn;
@@ -6,6 +6,7 @@ interface IPromise<TReturn> extends Promise<TReturn> {
6
6
  }
7
7
  interface ISuspenseQueryParams {
8
8
  fieldName?: string;
9
+ errorFields?: string[];
9
10
  }
10
11
  /**
11
12
  * Run request and cache promise
@@ -16,10 +17,6 @@ declare class SuspenseQuery {
16
17
  * @private
17
18
  */
18
19
  protected promise: Promise<any> | undefined;
19
- /**
20
- * @private
21
- */
22
- protected error?: Error;
23
20
  /**
24
21
  * Target store
25
22
  * @private
@@ -35,7 +32,32 @@ declare class SuspenseQuery {
35
32
  /**
36
33
  * @constructor
37
34
  */
38
- constructor(store: TInitStore, { fieldName, ...rest }?: ISuspenseQueryParams);
35
+ constructor(store: TInitStore, { fieldName, errorFields }?: ISuspenseQueryParams);
36
+ /**
37
+ * Error to json
38
+ */
39
+ /**
40
+ * Error to json
41
+ */
42
+ protected errorJson(e: any): void;
43
+ /**
44
+ * Assign custom error fields to error
45
+ */
46
+ /**
47
+ * Assign custom error fields to error
48
+ */
49
+ protected jsonToError(e: Error, values: Record<string, any>): Error;
50
+ /**
51
+ * Detect if suspense is restored from server side:
52
+ * - throw error if exist
53
+ * - skip run suspense if already completed
54
+ */
55
+ /**
56
+ * Detect if suspense is restored from server side:
57
+ * - throw error if exist
58
+ * - skip run suspense if already completed
59
+ */
60
+ protected isComplete(): boolean;
39
61
  /**
40
62
  * Run request
41
63
  * Save request resolve status
@@ -1 +1 @@
1
- "use strict";var e=require("mobx");class r{constructor(t,{fieldName:i="isSuspenseDone",...s}={}){Object.defineProperty(this,"promise",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"error",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"store",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"params",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"query",{enumerable:!0,configurable:!0,writable:!0,value:e=>{const{fieldName:t}=this.params;if(!this.store[t])return this.promise||(this.promise=e(),this.promise.then((()=>{this.store[t]=!0}),(e=>{this.store[t]=!0,this.error=e}))),r.run(this.promise)}}),this.store=t,this.params={...s,fieldName:i},e.extendObservable(t,{[i]:!1},{[i]:e.observable})}}Object.defineProperty(r,"run",{enumerable:!0,configurable:!0,writable:!0,value:e=>{if(e){switch(e.status){case"fulfilled":return e.value;case"pending":throw e;case"rejected":throw e.reason;default:e.status="pending",e.then((r=>{e.status="fulfilled",e.value=r}),(r=>{e.status="rejected",e.reason=r}))}throw e}}}),module.exports=r;
1
+ "use strict";var e=require("mobx");class r{constructor(t,{fieldName:i="sR",errorFields:s=["name","message"]}={}){var o;Object.defineProperty(this,"promise",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"store",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"params",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"query",{enumerable:!0,configurable:!0,writable:!0,value:t=>{const{fieldName:i}=this.params;if(!this.isComplete())return this.promise||(this.promise=t(),this.promise.then((()=>{e.runInAction((()=>{this.store[i]=!0}))}),(r=>{e.runInAction((()=>{this.errorJson(r),this.store[i]=r}))}))),r.run(this.promise)}}),this.store=t,this.params={fieldName:i,errorFields:s};const a=null===(o=t.init)||void 0===o?void 0:o.bind(t);t.init=()=>{this.isComplete(),null==a||a()},e.extendObservable(t,{[i]:!1},{[i]:e.observable})}errorJson(e){e.toJSON=()=>this.params.errorFields.reduce(((r,t)=>({...r,[t]:null==e?void 0:e[t]})),{})}jsonToError(e,r){return this.params.errorFields.forEach((t=>{e[t]=null==r?void 0:r[t]})),e}isComplete(){var e;const r=this.store[this.params.fieldName];if("boolean"!==typeof r)throw this.jsonToError(new Error(null!==(e=null==r?void 0:r.message)&&void 0!==e?e:null==r?void 0:r.name),r);return!0===r}}Object.defineProperty(r,"run",{enumerable:!0,configurable:!0,writable:!0,value:e=>{if(e){switch(e.status){case"fulfilled":return e.value;case"pending":throw e;case"rejected":throw e.reason;default:e.status="pending",e.then((r=>{e.status="fulfilled",e.value=r}),(r=>{e.status="rejected",e.reason=r}))}throw e}}}),module.exports=r;
@@ -1,10 +1,12 @@
1
+ /// <reference types="node" />
1
2
  import Manager from "./manager.js";
3
+ import StoreStatus from "./store-status.js";
2
4
  interface IWindowManager {
3
- pushInit: (state: Record<string, any>) => void;
5
+ push: (state: Record<string, any>) => void;
4
6
  }
5
7
  declare global {
6
8
  interface Window {
7
- mobxManager: IWindowManager;
9
+ mbxM: Record<string, any>[] | IWindowManager;
8
10
  }
9
11
  }
10
12
  interface IConstructorParams<TProps = Record<string, any>> {
@@ -14,13 +16,15 @@ interface IConstructorParams<TProps = Record<string, any>> {
14
16
  }
15
17
  interface IStoreLifecycle {
16
18
  onDestroy?: () => void;
17
- onMount?: () => void | (() => void);
18
19
  }
19
20
  interface IStore extends IStoreLifecycle {
20
21
  libStoreId?: string;
21
22
  libStoreContextId?: string;
22
23
  libStoreParentId?: string;
24
+ libStoreSuspenseId?: string;
23
25
  libStoreComponentName?: string;
26
+ libStoreStatus?: StoreStatus;
27
+ libDestroyTimer?: NodeJS.Timeout;
24
28
  isSingleton?: boolean;
25
29
  init?: () => void;
26
30
  toJSON?: () => Record<string, any>;
@@ -47,7 +51,7 @@ interface IManagerParams {
47
51
  options?: IManagerOptions;
48
52
  initState?: Record<string, any>;
49
53
  }
50
- type TWakeup = (store: IStore, state: {
54
+ type TWakeup = (state: {
51
55
  initState?: Record<string, any>;
52
56
  persistedState?: Record<string, any>;
53
57
  }) => void;
@@ -59,7 +63,11 @@ interface IStorage {
59
63
  interface IManagerOptions {
60
64
  shouldDisablePersist?: boolean;
61
65
  shouldRemoveInitState?: boolean;
62
- isSSR?: boolean;
66
+ destroyTimers?: {
67
+ init?: number;
68
+ touched?: number;
69
+ unused?: number;
70
+ };
63
71
  }
64
72
  type TStores = {
65
73
  [storeKey: string]: IStore | IStorePersisted;
@@ -81,6 +89,7 @@ interface IStoreParams {
81
89
  key?: string;
82
90
  contextId?: string;
83
91
  parentId?: string;
92
+ suspenseId?: string;
84
93
  componentName?: string;
85
94
  componentProps?: Record<string, any>;
86
95
  }
package/lib/wakeup.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { IStorePersisted } from "./types-abd34741.js";
1
+ import { TStores, TWakeup } from "./types-8fe84e04.js";
2
2
  /**
3
- * Restore store state from initial state
3
+ * Restore persisted store state
4
4
  */
5
- declare const wakeup: IStorePersisted['wakeup'];
5
+ declare function wakeup(this: TStores[string], { persistedState }: Parameters<TWakeup>[0]): void;
6
6
  export { wakeup as default };
package/lib/wakeup.js CHANGED
@@ -1 +1 @@
1
- "use strict";module.exports=(e,{persistedState:s})=>{s&&Object.assign(e,s)};
1
+ "use strict";module.exports=function({persistedState:t}){t&&Object.assign(this,t)};
@@ -1,5 +1,5 @@
1
1
  import { FC } from 'react';
2
- import { TMapStores, IWithStoreOptions } from "./types-abd34741.js";
2
+ import { TMapStores, IWithStoreOptions } from "./types-8fe84e04.js";
3
3
  /**
4
4
  * Make component observable and pass stores as props
5
5
  */
@@ -1 +1 @@
1
- "use strict";var e=require("hoist-non-react-statics"),t=require("mobx-react-lite"),r=require("react"),n=require("./context.js");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=a(e),u=a(r);module.exports=(e,a,{customContextId:s}={})=>{const d=t.observer(e),i=s||e.libStoreContextId,c=e.displayName||e.name,l=e=>{var t;const o=n.useStoreManagerContext(),s=n.useStoreManagerParentContext(),l=n.useStoreManagerSuspenseContext(),S=null===(t=u.default.useId)||void 0===t?void 0:t.call(u.default),[{contextId:f,initStores:x}]=r.useState((()=>{const t=o.createContextId(i||l||S);return{contextId:t,initStores:o.createStores(Object.entries(a),s,t,c,e)}}));return r.useEffect((()=>o.mountStores(x)),[x,o]),u.default.createElement(n.StoreManagerSuspenseProvider,{id:null},u.default.createElement(n.StoreManagerParentProvider,{parentId:f},u.default.createElement(d,{...x,...e})))};return o.default(l,e),l.displayName=`Mobx(${c})`,l};
1
+ "use strict";var e=require("@lomray/consistent-suspense"),t=require("hoist-non-react-statics"),r=require("mobx-react-lite"),n=require("react"),s=require("./context.js");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=o(t),u=o(n);module.exports=(t,o,{customContextId:i}={})=>{const c=r.observer(t),d=i||t.libStoreContextId,l=t.displayName||t.name,m=t=>{const r=s.useStoreManager(),a=s.useStoreManagerParent(),{suspenseId:i}=e.useConsistentSuspense(),m=e.useId(),[{contextId:S,initStores:f,mountStores:p}]=n.useState((()=>{const e=d||m;return{contextId:e,initStores:r.createStores(Object.entries(o),a,e,i,l,t),mountStores:()=>r.mountStores(f)}}));return n.useEffect(p,[p]),u.default.createElement(s.StoreManagerParentProvider,{parentId:S,initStores:f},u.default.createElement(c,{...t,...f}))};return a.default(m,t),m.displayName=`Mobx(${l})`,Object.defineProperty(m,"name",{value:m.displayName,writable:!1,enumerable:!1})};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lomray/react-mobx-manager",
3
- "version": "2.0.0-beta.2",
3
+ "version": "2.0.0-beta.20",
4
4
  "description": "This package provides Mobx stores manager for react.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -12,8 +12,7 @@
12
12
  "*": {
13
13
  "./*": [
14
14
  "lib/*",
15
- "lib/storages/*",
16
- "lib/server/*"
15
+ "lib/storages/*"
17
16
  ]
18
17
  }
19
18
  },
@@ -52,15 +51,15 @@
52
51
  "prepare": "husky install"
53
52
  },
54
53
  "dependencies": {
54
+ "@lomray/consistent-suspense": "^1.3.0",
55
55
  "@lomray/event-manager": "^1.2.2"
56
56
  },
57
57
  "devDependencies": {
58
- "@commitlint/cli": "^17.6.3",
59
- "@commitlint/config-conventional": "^17.6.3",
58
+ "@commitlint/cli": "^17.6.6",
59
+ "@commitlint/config-conventional": "^17.6.6",
60
60
  "@lomray/eslint-config-react": "^3.0.0",
61
61
  "@lomray/prettier-config": "^1.2.0",
62
62
  "@rollup/plugin-terser": "^0.4.3",
63
- "@types/express": "^4.17.17",
64
63
  "@types/hoist-non-react-statics": "^3.3.1",
65
64
  "@types/react": "^18.2.7",
66
65
  "eslint": "^8.41.0",
@@ -74,7 +73,8 @@
74
73
  "rollup-plugin-ts": "^3.2.0",
75
74
  "semantic-release": "^21.0.2",
76
75
  "ttypescript": "^1.5.15",
77
- "typescript": "^4.7.4"
76
+ "typescript": "^4.7.4",
77
+ "vite": "^4.4.4"
78
78
  },
79
79
  "peerDependencies": {
80
80
  "hoist-non-react-statics": "^3.3.2",
@@ -1,8 +0,0 @@
1
- import { FC, SuspenseProps } from 'react';
2
- /**
3
- * Wrapper around react suspense
4
- * Create unique id for each suspense (used for create/stream stores state)
5
- * @constructor
6
- */
7
- declare const MobxSuspense: FC<SuspenseProps>;
8
- export { MobxSuspense as default };
@@ -1 +0,0 @@
1
- "use strict";var e=require("react"),t=require("./context.js");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var r=a(e);module.exports=({children:a,fallback:l,...n})=>{var u;const d=e.useId(),c=e.Children.map(a,((e,a)=>r.default.createElement(t.StoreManagerSuspenseProvider,{id:`${d}${a}`},e))),i=r.default.createElement(r.default.Fragment,null,r.default.createElement("script",{"data-context-id":d,"data-count":null!==(u=null==c?void 0:c.length)&&void 0!==u?u:0}),l);return r.default.createElement(e.Suspense,{...n,children:c,fallback:i})};
@@ -1,72 +0,0 @@
1
- import { Response } from 'express';
2
- import Manager from "../manager.js";
3
- /**
4
- * Stream mobx manager stores
5
- * NOTE: use with renderToPipeableStream
6
- */
7
- declare class StreamStores {
8
- /**
9
- * Obtained suspensions from application shell
10
- * @protected
11
- */
12
- protected suspendIds: Record<string, {
13
- contextId: string;
14
- count: number;
15
- }>;
16
- /**
17
- * Mobx store manager instance
18
- * @protected
19
- */
20
- protected readonly manager: Manager;
21
- /**
22
- * @constructor
23
- * @protected
24
- */
25
- /**
26
- * @constructor
27
- * @protected
28
- */
29
- protected constructor(manager: Manager);
30
- /**
31
- * Listen react stream and push suspense stores state to client
32
- */
33
- /**
34
- * Listen react stream and push suspense stores state to client
35
- */
36
- static stream(res: Response, manager: Manager): StreamStores;
37
- /**
38
- * Begin listen stream
39
- */
40
- /**
41
- * Begin listen stream
42
- */
43
- protected beginStream(res: Response): void;
44
- /**
45
- * Parse suspensions and related stores context id from application shell
46
- * @protected
47
- */
48
- /**
49
- * Parse suspensions and related stores context id from application shell
50
- * @protected
51
- */
52
- protected obtainSuspensions(html: string): void;
53
- /**
54
- * Replace suspend id
55
- * @protected
56
- */
57
- /**
58
- * Replace suspend id
59
- * @protected
60
- */
61
- protected replaceSuspendIds(formId: string, toId: string): string | undefined;
62
- /**
63
- * Parse complete suspense chunk
64
- * @protected
65
- */
66
- /**
67
- * Parse complete suspense chunk
68
- * @protected
69
- */
70
- protected obtainCompleteSuspense(html: string): Uint8Array | undefined;
71
- }
72
- export { StreamStores as default };
@@ -1 +0,0 @@
1
- "use strict";class t{constructor(t){Object.defineProperty(this,"suspendIds",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"manager",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.manager=t}static stream(e,s){const n=new t(s);return n.beginStream(e),n}beginStream(t){const e=t.write.bind(t);t.write=(t,...s)=>{const n=Buffer.from(t).toString();this.obtainSuspensions(n);const r=this.obtainCompleteSuspense(n);return r?e(Buffer.concat([r,t]),...s):e(t,...s)}}obtainSuspensions(t){if(this.suspendIds)return;const e=[...t.matchAll(/<template id="(?<templateId>[^"]+)".+?<script data-context-id="(?<contextId>[^"]+)".+?data-count="(?<count>[^"]+)">/g)];e.length&&(this.suspendIds=e.reduce(((t,{groups:e})=>{const{templateId:s,contextId:n,count:r}=null!=e?e:{};return s?{...t,[s]:{contextId:n,count:Number(r)}}:t}),{}))}replaceSuspendIds(t,e){if(t)return this.suspendIds[e]=this.suspendIds[t],delete this.suspendIds[t],e}obtainCompleteSuspense(t){var e,s,n;if(!t.startsWith("<div hidden id="))return;const{from:r,to:i}=null!==(s=null===(e=t.match(/\$RC\("(?<from>[^"]+)","(?<to>[^"]+)"\)/))||void 0===e?void 0:e.groups)&&void 0!==s?s:{},o=this.replaceSuspendIds(r,i);if(!o)return;const{contextId:u,count:d}=null!==(n=this.suspendIds[o])&&void 0!==n?n:{};if(!u||!d)return;const a=this.manager.getStoresRelations(),c=this.manager.createContextId(u),l=[...Array(d)].reduce(((t,e,s)=>{const n=`${c}${s}`;return a.has(n)&&t.push(...a.get(n).ids),t}),[]);if(!l.length)return;const p=JSON.stringify(this.manager.toJSON(l));return Buffer.from(`<script>window.mobxManager.pushInit(${p});<\/script>`,"utf8")}}module.exports=t;