as-model 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,558 +1,571 @@
1
- [![npm][npm-image]][npm-url]
2
- [![NPM downloads][npm-downloads-image]][npm-url]
3
- [![standard][standard-image]][standard-url]
4
-
5
- [npm-image]: https://img.shields.io/npm/v/as-model.svg?style=flat-square
6
- [npm-url]: https://www.npmjs.com/package/as-model
7
- [standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
8
- [standard-url]: http://npm.im/standard
9
- [npm-downloads-image]: https://img.shields.io/npm/dm/as-model.svg?style=flat-square
10
-
11
-
12
- # as-model
13
-
14
- This is a simple state management library with model coding style for javascript/typescript.
15
-
16
- ## Code first
17
-
18
- Create a model function:
19
-
20
- ```js
21
- // model.js
22
- // A parameter for model state.
23
- export function counting(state){
24
- // Define instance object for outside usage.
25
- return {
26
- // Define properties for instance.
27
- count: state,
28
- symbol: !state? '': (state > 0? '+' : '-'),
29
- // Create action methods for changing state.
30
- increase:()=> state + 1,
31
- decrease:()=> state - 1,
32
- add(...additions){
33
- return additions.reduce((result, current)=>{
34
- return result + current;
35
- }, state);
36
- }
37
- };
38
- }
39
- ```
40
-
41
- Create store:
42
-
43
- ```js
44
- // store.js
45
- import {counting} from './model';
46
- import {createStore} from 'as-model';
47
-
48
- // Create and initialize a model store.
49
- const store = createStore(counting, 0);
50
- // Get instance and call action methods to change state.
51
- store.getInstance().increase();
52
- // Get new properties from instance.
53
- console.log(store.getInstance().count); // 1
54
- store.getInstance().add(2,3);
55
- console.log(store.getInstance().count); // 6
56
- ```
57
-
58
- Create multiple stores:
59
-
60
- ```js
61
- import {counting} from './model';
62
- import {createKey, createStores} from 'as-model';
63
-
64
- // Create model key with initial state.
65
- const countingKey0 = createKey(counting, 0);
66
- const countingKey1 = createKey(counting, 1);
67
-
68
- // Use model keys as templates to create multiple stores.
69
- const stores = createStores(countingKey0, countingKey1);
70
- // Find store by model key
71
- const store0 = stores.find(countingKey0);
72
- store0?.getInstance().increase();
73
- console.log(store0?.getInstance().count); // 1
74
- ```
75
-
76
- Model key is a template for creating multiple stores, and it is also an identifier to find the right store from multiple stores.
77
-
78
- Use **model** API to create store or key.
79
-
80
- ```js
81
- import {counting} from './model';
82
- import {model} from 'as-model';
83
-
84
- const store = model(counting).createStore(0);
85
- const key = model(counting).createKey(0);
86
- ......
87
- ```
88
-
89
- In typescript develop environment, `model` API can do a type check for making sure every model action method returns a correct type.
90
-
91
- ```js
92
- // ts
93
- import {model} from 'as-model';
94
-
95
- // The model api ensures every action method returns a same type value with model state.
96
- const counting = model((state: number)=>{
97
- return {
98
- count: state,
99
- increase:()=>state + 1 + '', // type error, should be number, but returns string.
100
- decrease:()=>state - 1,
101
- add(...additions: number[]){
102
- return additions.reduce((result, current)=>{
103
- return result + current;
104
- }, state);
105
- }
106
- };
107
- });
108
-
109
- const store = counting.createStore(0);
110
- const key = counting.createKey(0);
111
- ......
112
- ```
113
-
114
- Subscribe store
115
-
116
- ```js
117
- import {counting} from './model';
118
- import {model} from 'as-model';
119
-
120
- const store = model(counting).createStore(0);
121
- const {getInstance} = store;
122
- // Subscribe the state changes.
123
- const unsubscribe = store.subscribe((action)=>{
124
- console.log(store.getInstance());
125
- });
126
- getInstance().increase(); // output: {count: 1}
127
- // Destroy subscription.
128
- unsubscribe();
129
- ```
130
-
131
- Want to use async operations?
132
-
133
- ```js
134
- import {counting} from './model';
135
- import {model, createSelector} from 'as-model';
136
-
137
- const store = model(counting).select((getInstance)=>{
138
- const instance = getInstance();
139
- return {
140
- ...instance,
141
- async delayIncrease(){
142
- const ok = await new Promise((resolve)=>{
143
- setTimeout(()=>{
144
- resolve(true);
145
- },200);
146
- });
147
- if(ok){
148
- getInstance().increase();
149
- }
150
- }
151
- }
152
- }).createStore(0);
153
-
154
- const {subscribe, select} = createSelector(store);
155
- const unsubscribe = subscribe();
156
- // When use select with no parameter,
157
- // select method finds default selector for reproducing result
158
- const {delayIncrease} = select();
159
- await delayIncrease();
160
- select().count // 1
161
- ```
162
-
163
- Subscribe store in react hooks:
164
-
165
- ```js
166
- import {model, createStores} from 'as-model';
167
- import {
168
- createContext,
169
- useRef,
170
- useState,
171
- useEffect,
172
- useContext
173
- } from 'react';
174
-
175
- // Local state management
176
- function useModel(modelFn, defaultState){
177
- // Use ref to persist the store object.
178
- const storeRef = useRef(model(modelFn).createStore(defaultState));
179
- const store = storeRef.current;
180
- // Set store instance as an initial state for useState.
181
- const [state, setState] = useState(store.getInstance());
182
-
183
- useEffect(()=>{
184
- // Subscribe the state changes.
185
- const unsubscribe = store.subscribe((action)=>{
186
- setState(store.getInstance());
187
- });
188
- // Destroy subscription when component unmounts.
189
- return unsubscribe;
190
- }, []);
191
-
192
- return state;
193
- }
194
-
195
- function App(){
196
- const {
197
- count,
198
- increase
199
- } = useModel(counting, 0);
200
- }
201
-
202
- // global static state management
203
- function useModelStore(store){
204
- const [state, setState] = useState(store.getInstance());
205
-
206
- useEffect(()=>{
207
- const unsubscribe = store.subscribe((action)=>{
208
- setState(store.getInstance());
209
- });
210
- return unsubscribe;
211
- }, []);
212
-
213
- return state;
214
- }
215
-
216
- const store = model(counting).createStore({state: 0});
217
-
218
- function App(){
219
- const {
220
- count,
221
- increase
222
- } = useModelStore(store);
223
- }
224
-
225
- // global dynamic state management
226
- const ModelContext = createContext(null);
227
-
228
- function create(...keys){
229
- return {
230
- provide(Component){
231
- return function Provider(props){
232
- // Create and persist multiple stores in Component, that makes different elements from this Component carry different stores.
233
- const storesRef = useRef(createStores(...keys));
234
- const stores = storesRef.current;
235
- // Use Context to provide multiple stores to all the children.
236
- return (
237
- <ModelContext.Provider value={stores}>
238
- <Component {...props} />
239
- </ModelContext.Provider>
240
- );
241
- }
242
- }
243
- }
244
- }
245
-
246
- function useModelKey(key){
247
- const stores = useContext(ModelContext);
248
- if(stores==null){
249
- throw new Error('ModelContext is not provided');
250
- }
251
- // Use model key to find the right store.
252
- const store = stores.find(key);
253
- if(store==null){
254
- throw new Error('Can not find store by model key');
255
- }
256
- const [state, setState] = useState(store.getInstance());
257
-
258
- useEffect(()=>{
259
- const unsubscribe = store.subscribe((action)=>{
260
- setState(store.getInstance());
261
- });
262
- return unsubscribe;
263
- }, []);
264
-
265
- return state;
266
- }
267
-
268
- const countingKey = model(counting).createKey(0);
269
-
270
- const App = create(countingKey).provide(function App(){
271
- const {
272
- count,
273
- increase
274
- } = useModelKey(countingKey);
275
- });
276
- ```
277
-
278
- ## Install
279
-
280
- ```
281
- npm install as-model
282
- ```
283
-
284
- ## Simplify API
285
-
286
- ### createStore
287
-
288
- ```js
289
- function createStore(modelFnOrKey, initialState?):store
290
- ```
291
-
292
- #### parameters
293
-
294
- * modelFnOrKey - a model function accepts a state parameter and returns an object with action methods, or a model key of model function.
295
- * initialState - the initial state of the model.
296
-
297
- #### return
298
-
299
- A store object with model key and methods. The store object has `getInstance` method to get the instance of the model; `subscribe` method to subscribe the state changes; `update` method to update the store with new model function and initial state; `destroy` method to destroy the store.
300
-
301
- **store** structure:
302
-
303
- ```js
304
- {
305
- getInstance: ()=>instance,
306
- subscribe: (listener)=>unsubscribe,
307
- key: modelKey,
308
- destroy: ()=>void,
309
- update: (
310
- data:{
311
- model?:modelFn,
312
- key?: modelKey,
313
- initialState?: any
314
- state?: any;
315
- }
316
- )=>void,
317
- }
318
- ```
319
-
320
- ### createKey
321
-
322
- ```js
323
- function createKey(modelFn, initialState?):key
324
- ```
325
-
326
- #### parameters
327
-
328
- * modelFn - a model function accepts a state parameter and returns an object with action methods.
329
- * initialState - the initial state of the model.
330
-
331
- #### return
332
-
333
- A model key function with `createStore` method to create a store with the model key.
334
-
335
- **key** structure:
336
-
337
- ```js
338
- {
339
- createStore: (initialState?)=>Store
340
- }
341
- ```
342
-
343
- ### createStores
344
-
345
- ```js
346
- function createStores(...keys):StoreCollection
347
- ```
348
-
349
- #### parameters
350
-
351
- * keys - multiple model keys of model functions.
352
-
353
- #### return
354
-
355
- StoreCollection created by the model keys.
356
-
357
- **StoreCollection** structure:
358
-
359
- ```js
360
- {
361
- find: (key)=>store,
362
- destroy: ()=>void
363
- }
364
- ```
365
-
366
- ### createSignal
367
-
368
- ```js
369
- function createSignal(store):SignalStore
370
- ```
371
-
372
- #### parameters
373
-
374
- * store - a store object created by `createStore` method.
375
-
376
- #### return
377
-
378
- Signal store object with `subscribe` method to subscribe the state changes, and `getSignal` method to get the Signal callback function.
379
-
380
- **SignalStore** structure:
381
-
382
- ```js
383
- {
384
- subscribe: (listener)=>unsubscribe,
385
- getSignal: ()=>Signal,
386
- key: modelKey,
387
- }
388
- ```
389
-
390
- The Signal function returns a real time instance from store. Only when the properties picked from real time instance are changed, the subscribed listener can receive an action notification.
391
-
392
- ```js
393
- // Signal
394
- function signal():instance;
395
- // to start statistic the picked properties change
396
- signal.startStatistics():void;
397
- // to end statistic the picked properties change
398
- signal.stopStatistics():void;
399
- ```
400
-
401
- ### createSelector
402
-
403
- ```js
404
- function createSelector(store, opts?:SelectorOptions):SelectorStore
405
- ```
406
-
407
- #### parameters
408
-
409
- * store - a store object created by `createStore` method.
410
- * opts - (Optional) an object config to optimize createSelector.
411
-
412
- ```js
413
- // opts
414
- {
415
- // When the selector is drived to reproduce a new data,
416
- // it compares if the result is different with the previous one,
417
- // if the camparing result is true, it represents no differ happens,
418
- // the subscribed callback will not be called.
419
- equality?: (current: T, next: T) => boolean;
420
- }
421
- ```
422
-
423
- #### return
424
-
425
- Selector store object with `subscribe` method to subscribe the state changes, and `select` method for reselecting instance.
426
-
427
- ```js
428
- {
429
- subscribe: (listener)=>unsubscribe,
430
- select: (selector?:(getInstance:()=>Instance)=>)=>any,
431
- key: modelKey,
432
- }
433
- ```
434
-
435
-
436
- ### model
437
-
438
- ```js
439
- function model(modelFn):ModelUsage
440
- ```
441
-
442
- #### parameters
443
-
444
- * modelFn - a model function accepts a state parameter and returns an object with action methods.
445
-
446
- #### return
447
-
448
- ModelUsage object with `createStore`, `createKey` methods to create store, key for the model function, and `select` method to set a default selector function (Use `createSelector(store).select()` to select the default one).
449
-
450
- **ModelUsage** structure:
451
-
452
- ```js
453
- {
454
- createStore: (initialState?)=> store,
455
- createKey: (initialState?)=> key,
456
- select: (
457
- selector:(getInstance:()=>Instance)=>Record<string, any>|Array<any>
458
- )=>ModelUsage
459
- }
460
- ```
461
-
462
- ### config
463
-
464
- ```js
465
- function config(options):configAPI
466
- ```
467
-
468
- #### parameters
469
-
470
- ##### options - (Optional) an object with the following properties:
471
- * notify - (Optional) a callback function for noticing an action to every subscriber, it accepts a notifier function and an action as parameters.
472
- * controlled - (Optional) a boolean state to tell as-model use controlled mode to output instance changes.
473
- * middleWares - (Optional) a middleWare array for reproducing state or ignore actions.
474
-
475
- #### return
476
-
477
- All apis above except `createSignal` and `createSelector` API.
478
-
479
- ```js
480
- {
481
- createStore: (modelFnOrKey, initialState?)=>store,
482
- createKey: (modelFn, initialState?)=>key,
483
- createStores: (...keys)=>stores,
484
- model: (modelFn)=>ModelUsage
485
- }
486
- ```
487
-
488
- ### validations
489
-
490
- A validate callback collection object.
491
-
492
- #### validations.isInstanceFromNoStateModel
493
-
494
- ```js
495
- function isInstanceFromNoStateModel(instance: any): boolean
496
- ```
497
-
498
- To validate if the parameter object is a uninitialized store instance.
499
-
500
- #### validations.isModelKey
501
-
502
- ```js
503
- function isModelKey<
504
- S,
505
- T extends ModelInstance,
506
- R extends (ins: () => T) => any = (ins: () => T) => T
507
- >(
508
- data: any
509
- ): data is ModelKey<S, T, R>;
510
- ```
511
-
512
- To validate if the parameter object is a model key.
513
-
514
- #### validations.isModelStore
515
-
516
- ```js
517
- function isModelStore<
518
- S,
519
- T extends ModelInstance,
520
- R extends (ins: () => T) => any = (ins: () => T) => T
521
- >(
522
- data: any
523
- ): data is Store<S, T, R>;
524
- ```
525
-
526
- To validate if the parameter object is a store.
527
-
528
- #### validations.isModelUsage
529
-
530
- ```js
531
- function isModelUsage<
532
- S,
533
- T extends ModelInstance,
534
- R extends (ins: () => T) => any = (ins: () => T) => T
535
- >(
536
- data: any
537
- ): data is ModelUsage<S, T, R>;
538
- ```
539
-
540
- To validate if the parameter object is a model usage. A model usage is created by API **model**, it is a tool collection provides **createKey**, **createStore**, **select** APIs based on the model.
541
-
542
- ### shallowEqual
543
-
544
- ```js
545
- function shallowEqual(prev: any, current: any): boolean
546
- ```
547
-
548
- To validate if the value of left is shallow equal with the value of right.
549
-
550
- ## Browser Support
551
-
552
- ```
553
- chrome: '>=91',
554
- edge: '>=91',
555
- firefox: '=>90',
556
- safari: '>=15'
557
- ```
558
-
1
+ [![npm][npm-image]][npm-url]
2
+ [![NPM downloads][npm-downloads-image]][npm-url]
3
+ [![standard][standard-image]][standard-url]
4
+
5
+ [npm-image]: https://img.shields.io/npm/v/as-model.svg?style=flat-square
6
+ [npm-url]: https://www.npmjs.com/package/as-model
7
+ [standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
8
+ [standard-url]: http://npm.im/standard
9
+ [npm-downloads-image]: https://img.shields.io/npm/dm/as-model.svg?style=flat-square
10
+
11
+
12
+ # as-model
13
+
14
+ This is a simple state management library with model coding style for javascript/typescript.
15
+
16
+ ## Code first
17
+
18
+ Create a model function:
19
+
20
+ ```js
21
+ // model.js
22
+ // A parameter for model state.
23
+ export function counting(state){
24
+ // Define instance object for outside usage.
25
+ return {
26
+ // Define properties for instance.
27
+ count: state,
28
+ symbol: !state? '': (state > 0? '+' : '-'),
29
+ // Create action methods for changing state.
30
+ increase:()=> state + 1,
31
+ decrease:()=> state - 1,
32
+ add(...additions){
33
+ return additions.reduce((result, current)=>{
34
+ return result + current;
35
+ }, state);
36
+ }
37
+ };
38
+ }
39
+ ```
40
+
41
+ Create store:
42
+
43
+ ```js
44
+ // store.js
45
+ import {counting} from './model';
46
+ import {config} from 'as-model';
47
+
48
+ const {createStore} = config();
49
+
50
+ // Create and initialize a model store.
51
+ const store = createStore(counting, 0);
52
+ // Get instance and call action methods to change state.
53
+ store.getInstance().increase();
54
+ // Get new properties from instance.
55
+ console.log(store.getInstance().count); // 1
56
+ store.getInstance().add(2,3);
57
+ console.log(store.getInstance().count); // 6
58
+ ```
59
+
60
+ Create multiple stores:
61
+
62
+ ```js
63
+ import {counting} from './model';
64
+ import {config} from 'as-model';
65
+
66
+ const {createKey, createStores} = config();
67
+
68
+ // Create model key with initial state.
69
+ const countingKey0 = createKey(counting, 0);
70
+ const countingKey1 = createKey(counting, 1);
71
+
72
+ // Use model keys as templates to create multiple stores.
73
+ const stores = createStores(countingKey0, countingKey1);
74
+ // Find store by model key
75
+ const store0 = stores.find(countingKey0);
76
+ store0?.getInstance().increase();
77
+ console.log(store0?.getInstance().count); // 1
78
+ ```
79
+
80
+ Model key is a template for creating multiple stores, and it is also an identifier to find the right store from multiple stores.
81
+
82
+ Use **model** API to create store or key.
83
+
84
+ ```js
85
+ import {counting} from './model';
86
+ import {config} from 'as-model';
87
+
88
+ const {model} = config();
89
+
90
+ const store = model(counting).createStore(0);
91
+ const key = model(counting).createKey(0);
92
+ ......
93
+ ```
94
+
95
+ In typescript develop environment, `model` API can do a type check for making sure every model action method returns a correct type.
96
+
97
+ ```js
98
+ // ts
99
+ import {config} from 'as-model';
100
+
101
+ const {model} = config();
102
+
103
+ // The model api ensures every action method returns a same type value with model state.
104
+ const counting = model((state: number)=>{
105
+ return {
106
+ count: state,
107
+ increase:()=>state + 1 + '', // type error, should be number, but returns string.
108
+ decrease:()=>state - 1,
109
+ add(...additions: number[]){
110
+ return additions.reduce((result, current)=>{
111
+ return result + current;
112
+ }, state);
113
+ }
114
+ };
115
+ });
116
+
117
+ const store = counting.createStore(0);
118
+ const key = counting.createKey(0);
119
+ ......
120
+ ```
121
+
122
+ Subscribe store
123
+
124
+ ```js
125
+ import {counting} from './model';
126
+ import {config} from 'as-model';
127
+
128
+ const {model} = config();
129
+
130
+ const store = model(counting).createStore(0);
131
+ const {getInstance} = store;
132
+ // Subscribe the state changes.
133
+ const unsubscribe = store.subscribe((action)=>{
134
+ console.log(store.getInstance());
135
+ });
136
+ getInstance().increase(); // output: {count: 1}
137
+ // Destroy subscription.
138
+ unsubscribe();
139
+ ```
140
+
141
+ Want to use async operations?
142
+
143
+ ```js
144
+ import {counting} from './model';
145
+ import {config, createSelector} from 'as-model';
146
+
147
+ const {model} = config();
148
+
149
+ const store = model(counting).select((getInstance)=>{
150
+ const instance = getInstance();
151
+ return {
152
+ ...instance,
153
+ async delayIncrease(){
154
+ const ok = await new Promise((resolve)=>{
155
+ setTimeout(()=>{
156
+ resolve(true);
157
+ },200);
158
+ });
159
+ if(ok){
160
+ getInstance().increase();
161
+ }
162
+ }
163
+ }
164
+ }).createStore(0);
165
+
166
+ const {subscribe, select} = createSelector(store);
167
+ const unsubscribe = subscribe();
168
+ // When use select with no parameter,
169
+ // select method finds default selector for reproducing result
170
+ const {delayIncrease} = select();
171
+ await delayIncrease();
172
+ select().count // 1
173
+ ```
174
+
175
+ Subscribe store in react hooks:
176
+
177
+ ```js
178
+ import {config} from 'as-model';
179
+ import {
180
+ createContext,
181
+ useRef,
182
+ useState,
183
+ useEffect,
184
+ useContext
185
+ } from 'react';
186
+
187
+ const {model, createStores} = config();
188
+
189
+ // Local state management
190
+ function useModel(modelFn, defaultState){
191
+ // Use ref to persist the store object.
192
+ const storeRef = useRef(model(modelFn).createStore(defaultState));
193
+ const store = storeRef.current;
194
+ // Set store instance as an initial state for useState.
195
+ const [state, setState] = useState(store.getInstance());
196
+
197
+ useEffect(()=>{
198
+ // Subscribe the state changes.
199
+ const unsubscribe = store.subscribe((action)=>{
200
+ setState(store.getInstance());
201
+ });
202
+ // Destroy subscription when component unmounts.
203
+ return unsubscribe;
204
+ }, []);
205
+
206
+ return state;
207
+ }
208
+
209
+ function App(){
210
+ const {
211
+ count,
212
+ increase
213
+ } = useModel(counting, 0);
214
+ }
215
+
216
+ // global static state management
217
+ function useModelStore(store){
218
+ const [state, setState] = useState(store.getInstance());
219
+
220
+ useEffect(()=>{
221
+ const unsubscribe = store.subscribe((action)=>{
222
+ setState(store.getInstance());
223
+ });
224
+ return unsubscribe;
225
+ }, []);
226
+
227
+ return state;
228
+ }
229
+
230
+ const store = model(counting).createStore({state: 0});
231
+
232
+ function App(){
233
+ const {
234
+ count,
235
+ increase
236
+ } = useModelStore(store);
237
+ }
238
+
239
+ // global dynamic state management
240
+ const ModelContext = createContext(null);
241
+
242
+ function create(...keys){
243
+ return {
244
+ provide(Component){
245
+ return function Provider(props){
246
+ // Create and persist multiple stores in Component, that makes different elements from this Component carry different stores.
247
+ const storesRef = useRef(createStores(...keys));
248
+ const stores = storesRef.current;
249
+ // Use Context to provide multiple stores to all the children.
250
+ return (
251
+ <ModelContext.Provider value={stores}>
252
+ <Component {...props} />
253
+ </ModelContext.Provider>
254
+ );
255
+ }
256
+ }
257
+ }
258
+ }
259
+
260
+ function useModelKey(key){
261
+ const stores = useContext(ModelContext);
262
+ if(stores==null){
263
+ throw new Error('ModelContext is not provided');
264
+ }
265
+ // Use model key to find the right store.
266
+ const store = stores.find(key);
267
+ if(store==null){
268
+ throw new Error('Can not find store by model key');
269
+ }
270
+ const [state, setState] = useState(store.getInstance());
271
+
272
+ useEffect(()=>{
273
+ const unsubscribe = store.subscribe((action)=>{
274
+ setState(store.getInstance());
275
+ });
276
+ return unsubscribe;
277
+ }, []);
278
+
279
+ return state;
280
+ }
281
+
282
+ const countingKey = model(counting).createKey(0);
283
+
284
+ const App = create(countingKey).provide(function App(){
285
+ const {
286
+ count,
287
+ increase
288
+ } = useModelKey(countingKey);
289
+ });
290
+ ```
291
+
292
+ ## Install
293
+
294
+ ```
295
+ npm install as-model
296
+ ```
297
+
298
+ ## Simplify API
299
+
300
+ ### config
301
+
302
+ ```js
303
+ function config(options):configAPI
304
+ ```
305
+
306
+ #### parameters
307
+
308
+ ##### options - (Optional) an object with the following properties:
309
+ * notify - (Optional) a callback function for noticing an action to every subscriber, it accepts a notifier function and an action as parameters.
310
+ * controlled - (Optional) a boolean state to tell as-model use controlled mode to output instance changes.
311
+ * middleWares - (Optional) a middleWare array for reproducing state or ignore actions.
312
+
313
+ #### return
314
+
315
+ All apis above except `createSignal` and `createSelector` API.
316
+
317
+ ```js
318
+ {
319
+ createStore: (modelFnOrKey, initialState?)=>store,
320
+ createKey: (modelFn, initialState?)=>key,
321
+ createStores: (...keys)=>stores,
322
+ model: (modelFn)=>ModelUsage
323
+ }
324
+ ```
325
+
326
+ ### config(...).createStore
327
+
328
+ ```js
329
+ function createStore(modelFnOrKey, initialState?):store
330
+ ```
331
+
332
+ #### parameters
333
+
334
+ * modelFnOrKey - a model function accepts a state parameter and returns an object with action methods, or a model key of model function.
335
+ * initialState - the initial state of the model.
336
+
337
+ #### return
338
+
339
+ A store object with model key and methods. The store object has `getInstance` method to get the instance of the model; `subscribe` method to subscribe the state changes; `update` method to update the store with new model function and initial state; `destroy` method to destroy the store.
340
+
341
+ **store** structure:
342
+
343
+ ```js
344
+ {
345
+ getInstance: ()=>instance,
346
+ subscribe: (listener)=>unsubscribe,
347
+ key: modelKey,
348
+ destroy: ()=>void,
349
+ update: (
350
+ data:{
351
+ model?:modelFn,
352
+ key?: modelKey,
353
+ initialState?: any
354
+ state?: any;
355
+ }
356
+ )=>void,
357
+ }
358
+ ```
359
+
360
+ ### config(...).createKey
361
+
362
+ ```js
363
+ function createKey(modelFn, initialState?):key
364
+ ```
365
+
366
+ #### parameters
367
+
368
+ * modelFn - a model function accepts a state parameter and returns an object with action methods.
369
+ * initialState - the initial state of the model.
370
+
371
+ #### return
372
+
373
+ A model key function with `createStore` method to create a store with the model key.
374
+
375
+ **key** structure:
376
+
377
+ ```js
378
+ {
379
+ createStore: (initialState?)=>Store
380
+ }
381
+ ```
382
+
383
+ ### config(...).createStores
384
+
385
+ ```js
386
+ function createStores(...keys):StoreCollection
387
+ ```
388
+
389
+ #### parameters
390
+
391
+ * keys - multiple model keys of model functions.
392
+
393
+ #### return
394
+
395
+ StoreCollection created by the model keys.
396
+
397
+ **StoreCollection** structure:
398
+
399
+ ```js
400
+ {
401
+ find: (key)=>store,
402
+ destroy: ()=>void
403
+ }
404
+ ```
405
+
406
+ ### config(...).model
407
+
408
+ ```js
409
+ function model(modelFn):ModelUsage
410
+ ```
411
+
412
+ #### parameters
413
+
414
+ * modelFn - a model function accepts a state parameter and returns an object with action methods.
415
+
416
+ #### return
417
+
418
+ ModelUsage object with `createStore`, `createKey` methods to create store, key for the model function, and `select` method to set a default selector function (Use `createSelector(store).select()` to select the default one).
419
+
420
+ **ModelUsage** structure:
421
+
422
+ ```js
423
+ {
424
+ createStore: (initialState?)=> store,
425
+ createKey: (initialState?)=> key,
426
+ select: (
427
+ selector:(getInstance:()=>Instance)=>Record<string, any>|Array<any>
428
+ )=>ModelUsage
429
+ }
430
+ ```
431
+
432
+ ### createSignal
433
+
434
+ ```js
435
+ function createSignal(store):SignalStore
436
+ ```
437
+
438
+ #### parameters
439
+
440
+ * store - a store object created by `createStore` method.
441
+
442
+ #### return
443
+
444
+ Signal store object with `subscribe` method to subscribe the state changes, and `getSignal` method to get the Signal callback function.
445
+
446
+ **SignalStore** structure:
447
+
448
+ ```js
449
+ {
450
+ subscribe: (listener)=>unsubscribe,
451
+ getSignal: ()=>Signal,
452
+ key: modelKey,
453
+ }
454
+ ```
455
+
456
+ The Signal function returns a real time instance from store. Only when the properties picked from real time instance are changed, the subscribed listener can receive an action notification.
457
+
458
+ ```js
459
+ // Signal
460
+ function signal():instance;
461
+ // to start statistic the picked properties change
462
+ signal.startStatistics():void;
463
+ // to end statistic the picked properties change
464
+ signal.stopStatistics():void;
465
+ ```
466
+
467
+ ### createSelector
468
+
469
+ ```js
470
+ function createSelector(store, opts?:SelectorOptions):SelectorStore
471
+ ```
472
+
473
+ #### parameters
474
+
475
+ * store - a store object created by `createStore` method.
476
+ * opts - (Optional) an object config to optimize createSelector.
477
+
478
+ ```js
479
+ // opts
480
+ {
481
+ // When the selector is drived to reproduce a new data,
482
+ // it compares if the result is different with the previous one,
483
+ // if the camparing result is true, it represents no differ happens,
484
+ // the subscribed callback will not be called.
485
+ equality?: (current: T, next: T) => boolean;
486
+ }
487
+ ```
488
+
489
+ #### return
490
+
491
+ Selector store object with `subscribe` method to subscribe the state changes, and `select` method for reselecting instance.
492
+
493
+ ```js
494
+ {
495
+ subscribe: (listener)=>unsubscribe,
496
+ select: (selector?:(getInstance:()=>Instance)=>)=>any,
497
+ key: modelKey,
498
+ }
499
+ ```
500
+
501
+ ### validations
502
+
503
+ A validate callback collection object.
504
+
505
+ #### validations.isInstanceFromNoStateModel
506
+
507
+ ```js
508
+ function isInstanceFromNoStateModel(instance: any): boolean
509
+ ```
510
+
511
+ To validate if the parameter object is a uninitialized store instance.
512
+
513
+ #### validations.isModelKey
514
+
515
+ ```js
516
+ function isModelKey<
517
+ S,
518
+ T extends ModelInstance,
519
+ R extends (ins: () => T) => any = (ins: () => T) => T
520
+ >(
521
+ data: any
522
+ ): data is ModelKey<S, T, R>;
523
+ ```
524
+
525
+ To validate if the parameter object is a model key.
526
+
527
+ #### validations.isModelStore
528
+
529
+ ```js
530
+ function isModelStore<
531
+ S,
532
+ T extends ModelInstance,
533
+ R extends (ins: () => T) => any = (ins: () => T) => T
534
+ >(
535
+ data: any
536
+ ): data is Store<S, T, R>;
537
+ ```
538
+
539
+ To validate if the parameter object is a store.
540
+
541
+ #### validations.isModelUsage
542
+
543
+ ```js
544
+ function isModelUsage<
545
+ S,
546
+ T extends ModelInstance,
547
+ R extends (ins: () => T) => any = (ins: () => T) => T
548
+ >(
549
+ data: any
550
+ ): data is ModelUsage<S, T, R>;
551
+ ```
552
+
553
+ To validate if the parameter object is a model usage. A model usage is created by API **model**, it is a tool collection provides **createKey**, **createStore**, **select** APIs based on the model.
554
+
555
+ ### shallowEqual
556
+
557
+ ```js
558
+ function shallowEqual(prev: any, current: any): boolean
559
+ ```
560
+
561
+ To validate if the value of left is shallow equal with the value of right.
562
+
563
+ ## Browser Support
564
+
565
+ ```
566
+ chrome: '>=91',
567
+ edge: '>=91',
568
+ firefox: '=>90',
569
+ safari: '>=15'
570
+ ```
571
+