varstor 0.6.61 → 0.6.63

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
@@ -18,126 +18,223 @@ import Varstor from 'varstor/webextension'
18
18
  ```
19
19
  in your script file.
20
20
 
21
- ## Usage
21
+ ## Contents
22
+ 1. [Usage](#overview)
23
+ [1.1 Creation ```.add()```/```.addPersistent()```](#creation)
24
+ [1.2 Dynamic reevaluation (```ReactiveFunction```)](#reactivefunction)
25
+ [1.3 Accessing ```.get()```](#accessing)
26
+ [1.4 Mutating ```.set()```/```.reset()```](#mutating)
27
+ [1.5 Listening ```.onChange()```/```.removeListener()```](#listening)
28
+ [1.6 Data encapsulation ```.actions()```](#actions)
29
+ [1.7 Namespacing ```.get(Namespace)```](#namespacing)
30
+ [1.8 Method chaining](#chaining)
31
+ 2. [Shortcuts](#shortcuts)
32
+ 3. [Example](#example)
33
+
34
+ ## Usage <a name="overview"></a>
22
35
  The library object features the following methods:
23
36
  ```js
24
37
  .add ()
25
38
  .addPersistent ()
26
39
  .get ()
27
40
  .set ()
28
- .resetAll ()
41
+ .reset ()
29
42
  .onChange ()
30
43
  .removeListener ()
44
+ .actions ()
31
45
  ```
32
46
 
33
- Values are added to the store with ```add``` or ```addPersistent``` methods. They perform the same functionality, except ```addPersistent``` allows state to be saved in storage and reused between browser sessions.
34
- Signature of those methods is:
47
+ ## Creation ```.add()```/```.addPersistent()``` <a name="creation"></a>
48
+ Values are added to the store with add or addPersistent methods. They perform the same functionality, except addPersistent saves state to the storage and lets you reuse it between browser sessions.
49
+
35
50
  ```js
36
51
  async Varstor.add(
37
52
  KeysValues {
38
53
  key1: value1,
39
54
  key2: value2,
40
- key3: ComputeFunction(...dependencies) => computedValue
41
- ...
42
- }
43
- ) =>
44
- StateAccessors {
45
- key: StateAccessor
55
+ key3: ReactiveFunction(...valueNames[]) => computedValue
46
56
  ...
47
57
  }
58
+ ) => Varstor
48
59
  ```
49
60
  Where:
50
- ```KeysValues``` - a standard object with keys and values, where ```key``` is used to identify a piece of state, and ```value``` to give it a default value or ```ComputeFunction```
51
- ```ComputeFunction``` - reevalutes and updates its value automatically each time ```dependencies``` parameters change. ```dependencies``` parameters are any state values defined before the ```ComputeFunction```. ```computedValue```s are not saved in storage.
52
- ```StateAccessors``` - a map linking state ```key```s to special ```StateAccessor``` objects which will perform data manipulations and listener management.
61
+ ```KeysValues {}``` - a standard object with keys and values, where ```key``` is a name of piece of state, and ```value``` is a default value or ```ReactiveFunction```
62
+ ```ReactiveFunction``` - re-evalutes and updates its value automatically each time arguments in ```valueNames``` list change. ```valueNames``` are any state values defined before the ```ReactiveFunction```. ```computedValue```s are not saved in storage.
53
63
 
54
64
  **Important: ```add``` and ```addPersistent``` are asynchronous operations; you must `await` or use ```Promise.then``` to ensure all the data is ready to work with!**
55
65
 
56
-
66
+ ## Dynamic reevaluation (```ReactiveFunction```) <a name="reactivefunction"></a>
67
+ Values can change automatically with the help of ```ReactiveFunction```s when one or more of the other values in the namespace change.
57
68
 
58
- Values can be accessed with:
59
69
  ```js
60
- Varstor.get () => StateValues
70
+ ReactiveFunction (...valueNames[]) => computedValue
71
+ ```
72
+ Put the names of dependencies in the ```valueNames``` arguments list of the ```ReactiveFunction```, and describe the calculation in the body of the function.
73
+ ```js
74
+ Varstor.add({
75
+ a: 1
76
+ b: 2,
77
+ c: (a, b) => a + b // 3
78
+ })
61
79
  ```
62
- Where:
63
- ```StateValues``` - an object representing all the values in the store in the current namespace at the current moment
64
80
 
65
81
 
66
- or
82
+ ## Accessing ```.get()``` <a name="accessing"></a>
83
+ Values are accessed with:
67
84
  ```js
68
- Varstor.get (AccessorsCallback (StateAccessors {}, Varstor) => value) => value
85
+ Varstor.get() => NamespaceValues {}
69
86
  ```
70
87
  Where:
71
- ```AccessorsCallback``` - a function that takes all ```StateAccessors``` and a ```Varstor``` instance from the current namespace, manipulates them, and can return any ```value```, which in turn will be returned from the whole ```get(Callback)``` call.
72
-
88
+ ```NamespaceValues {}``` - an object representing all the values in the current namespace at the current moment
73
89
 
74
- Values can be mutated with:
90
+
91
+
92
+ ## Mutating ```.set()```/```.reset()``` <a name="mutating"></a>
93
+ Values are mutated with:
75
94
  ```js
76
- async Varstor.set (
95
+ async Varstor.set(
77
96
  KeysValues {
78
97
  key: value
79
98
  ...
80
99
  }
81
100
  ) => Varstor
82
101
  ```
83
- **Important: values are updated asynchronously; don't assume the script will recognize the change immediately. Instead, make use of ```onChange``` listeners!**
102
+ **Important: values are updated asynchronously; don't assume the script will recognize the change immediately on the next line. Instead, ```await``` or make use of ```onChange``` listeners!**
84
103
 
85
- To reset all stored values back to defaults:
104
+ To reset values back to defaults:
86
105
  ```js
87
- async Varstor.resetAll () => Varstor
106
+ async Varstor.reset(Keys []) => Varstor
88
107
  ```
108
+ Where:
109
+ ```Keys[]``` (optional) - array of keys to return to default values. If omitted all values will be returned to defaults.
110
+
111
+
112
+ ## Listening ```.onChange()```/```.removeListener()``` <a name="listening"></a>
89
113
 
90
114
  To listen and react to state changes:
91
115
  ```js
92
- Varstor.onChange (Keys[], ChangeCallback(newValue, allValues, previousValue) => void) => Varstor
116
+ Varstor.onChange(
117
+ Keys[],
118
+ ChangeCallback(ChangedKeys [], allValues {}, PreviousValues {}) => void
119
+ ) => Varstor
93
120
  ```
94
121
  Where:
95
- ```Keys``` - array of keys of the state in the current namespace that you want to listen to
122
+ ```Keys[]``` (optional) - array of keys of the state in the current namespace that you want to listen to. If omitted, ```ChangeCallback``` will run on any value change in the namespace.
96
123
  ```ChangeCallback``` - function to run when a change happens
97
124
 
98
125
  To remove the listener:
99
126
  ```js
100
- Varstor.removeListener(Keys, ChangeCallback) => Varstor
127
+ Varstor.removeListener(
128
+ Keys[],
129
+ ChangeCallback(ChangedKeys [], allValues {}, PreviousValues {}) => void
130
+ ) => Varstor
101
131
  ```
102
132
  the same parameter usage.
103
-
104
-
105
-
106
133
 
107
134
 
108
- Methods ```.set()```, ```.resetAll()```, ```onChange```, and ```removeListener``` all return a new instance of ```Varstor``` with the same namespace, so command chaining is possible.
109
- Method ```.get(() => {})``` may return a new ```Varstor``` instance.
110
135
 
111
- ## Namespacing
136
+ ## Data encapsulation ```.actions()``` <a name="actions"></a>
137
+ Hide away all public data access and mutation into dedicated functions with the help of ```IStateAction```s.
138
+ ```js
139
+ Varstor.actions({
140
+ KeysActions {
141
+ key1: IStateAction1 (Varstor, ...arguments[]) => void
142
+ key2: IStateAction2 (Varstor, ...arguments[]) => void
143
+ ...
144
+ }
145
+ })
146
+ ```
147
+ ```IStateAction``` function type binds ```Varstor``` instance as the first argument, followed by all other ```arguments``` provided by the user at the time of the call.
148
+ These actions reside in the same scope as regular variables. So you can access them by the ```key```s defined in ```KeysActions``` object through the ```.get()``` method.
149
+ ```js
150
+ Varstor.add({ x: 1 });
151
+
152
+ Varstor.actions({
153
+ changeX: (varstor, newX) => varstor.set({ x: newX }),
154
+ }),
155
+
156
+ Varstor.get().changeX(10);
157
+ ```
158
+
159
+ ## Namespacing ```.get(Namespace)``` <a name="namespacing"></a>
112
160
  To avoid name collisions, put keys with the same name in different namespaces. You can create a new or get an existing namespace with
113
161
  ```js
114
- Varstor.get(String Namespace) => Varstor
162
+ Varstor.get(Namespace string) => Varstor
115
163
  ```
116
- which will return a new instance of ```Varstor``` with the specified ```Namespace```.
164
+ which will return a new instance of ```Varstor``` with the specified ```Namespace```.
165
+
166
+
167
+ ## Method chaining <a name="chaining"></a>
168
+ Methods ```.add```, ```.addPersistent```, ```.set()```, ```.reset()```, ```onChange```, and ```removeListener``` all return a new instance of ```Varstor``` with the same namespace, so method chaining is possible.
117
169
 
118
- ## Shortcuts
119
- The library object itself can be called with different types of arguments, which will mirror almost all of its API.
170
+
171
+ ## Shortcuts <a name="shortcuts"></a>
172
+ The library/namespace object itself can be called with different types of arguments, which will mirror almost all of its API.
120
173
  ```js
121
174
  Varstor() -> Varstor.get()
122
175
  Varstor(String namespace) -> Varstor.get(namespace)
123
- Varstor(() => {}) -> Varstor.get(() => {})
124
176
  Varstor({ key: value }) -> Varstor.set({ key: value })
125
- Varstor({}) -> Varstor.resetAll()
126
177
  Varstor([], () => {}) -> Varstor.onChange([], () => {})
127
178
  ```
128
179
 
129
- ## StateAccessor
130
- ```StateAccessor``` is a way to manipulate each piece of state individually. It's a function that can be called itself, but also an object with a set of methods:
180
+ ## Example <a name="example"></a>
131
181
  ```js
132
- .()
133
- .set(value)
134
- .reset()
135
- .onChange(Callback)
136
- .removeListener(Callback)
137
- ```
138
- Where:
139
- ```()``` (call the object itself) - returns the value
140
- ```.set(value)``` - sets the value
141
- ```.reset()``` - resets the value
142
- ```.onChange(Callback)``` - adds the listener
143
- ```.removeListener(Callback)``` - removes the listener
182
+ function onChange(changes, values, data) {
183
+ console.log("onChange", changes, values, data);
184
+ }
185
+
186
+ await Varstor.add({
187
+ a: 10,
188
+ b: 20,
189
+ c: (a, b) => a + b,
190
+ });
191
+
192
+ await Varstor.addPersistent({
193
+ d: 40,
194
+ });
195
+
196
+ console.log(Varstor.get()); // {a: 10, b: 20, c: 30, d: 40}
197
+
198
+ Varstor.onChange(["a", "b", "c", "d"], onChange);
199
+ Varstor.onChange(onChange);
200
+
201
+ await Varstor.set({ a: 20, b: 88, d: 60 });
202
+ console.log(Varstor.get()); // {a: 20, b: 88, c: 108, d: 60}
203
+
204
+ await Varstor.reset(["b"]);
205
+ console.log(Varstor.get()); // {a: 20, b: 20, c: 40, d: 60}
206
+
207
+ await Varstor.reset();
208
+ console.log(Varstor.get()); // {a: 10, b: 20, c: 30, d: 40}
209
+
210
+ Varstor.removeListener(["a", "b", "c", "d"], onChange);
211
+ Varstor.removeListener(onChange);
212
+
213
+ const newNamespace = Varstor("new namespace");
214
+
215
+ await newNamespace.add({
216
+ x: 1,
217
+ y: 2,
218
+ z: 3,
219
+ });
220
+
221
+ newNamespace.actions({
222
+ logValues: ({ get }) => {
223
+ const { x, y, z } = get();
224
+ console.log(`x: ${x}, y: ${y}, z: ${z}`);
225
+ },
226
+ multiplyX: ({ get, set }, num) => set({ x: get().x * num }),
227
+ incrementY: ({ get, set }) => set({ y: get().y + 1 }),
228
+ })
229
+
230
+ const { logValues, multiplyX, incrementY } = newNamespace.get();
231
+
232
+ logValues(); // x: 1, y: 2, z: 3
233
+ multiplyX(10)
234
+ incrementY();
235
+ logValues(); // x: 10, y: 3, z: 3
236
+
237
+ await newNamespace({ z: 110 });
238
+
239
+ console.log(Varstor("new namespace").get()); // {x: 10, y: 3, z: 110, logValues: ƒ, multiplyX: ƒ, …}
240
+ ```