@@ -102,17 +102,17 @@ context.get(key2); // 6
102
102
[ Context Value Target ] : #context-value-target
103
103
104
104
The ` provide() ` method accepts not only a ` ContextKey ` instance, but arbitrary ` ContextTarget ` . The latter is just an
105
- object with ` key ` property containing a ` ContextKey ` to provide.
105
+ object with ` [ContextKey__symbol] ` property containing a ` ContextKey ` to provide.
106
106
107
107
108
108
This can be handy e.g. when providing an instance of some known type:
109
109
``` typescript
110
- import { ContextKey , ContextRegistry , SingleContextKey } from ' context-values' ;
110
+ import { ContextKey , ContextKey__symbol , ContextRegistry , SingleContextKey } from ' context-values' ;
111
111
112
112
class MyService {
113
113
114
114
// MyService class (not instance) implements a `ContextRequest`
115
- static readonly key : ContextKey <MyService > = new SingleContextKey (' my-service' );
115
+ static readonly [ ContextKey__symbol ] : ContextKey <MyService > = new SingleContextKey (' my-service' );
116
116
117
117
}
118
118
@@ -138,11 +138,11 @@ This specifier defines a value (or, more precisely, the [value sources]). It may
138
138
- ` registry.provide({ a: key, by: (a, b) => calculateValue(a, b), with: [keyA, keyB] }) ` - evaluates the value based on
139
139
other context values with keys ` keyA ` and ` keyB ` .
140
140
- ` registry.provide({ a: key, as: MyService }) ` - constructs the value as ` new MyService(ctx) ` , where ` ctx ` is the
141
- target context. The ` a ` property may be omitted if ` MyService ` has a static property ` key ` .
141
+ target context. The ` a ` property may be omitted if ` MyService ` has a static ` [ContextKey__symbol] ` property .
142
142
See [ Context Value Target] .
143
143
- ` registry.provide({ a: key, as: MyService, with: [keyA, keyB] }) ` - constructs the value as ` new MyService(a, b) ` ,
144
144
where ` a ` and ` b ` are context values with keys ` keyA ` and ` keyB ` respectively. The ` a ` property may be omitted if
145
- ` MyService ` has a static property ` key ` . See [ Context Value Target] .
145
+ ` MyService ` has a static ` [ContextKey__symbol] ` property . See [ Context Value Target] .
146
146
- ` registry.provide({ a: key, via: otherKey }) ` - makes the value available under ` otherKey ` available under ` key ` .
147
147
I.e. aliases it.
148
148
@@ -187,7 +187,7 @@ The default value is evaluated by the function accepting a `ContextValues` insta
187
187
import { ContextRegistry , SingleContextKey , MultiContextKey } from ' context-values' ;
188
188
189
189
const key1 = new SingleContextKey <string >(' key1' );
190
- const key2 = new SingleContextKey <number >(' key2' , ctx => ctx .get (' key1' ).length );
190
+ const key2 = new SingleContextKey <number >(' key2' , { byDefault : ctx => ctx .get (' key1' ).length } );
191
191
const key3 = new MultiContextKey <number >(' key3' );
192
192
193
193
const registry = new ContextRegistry ();
@@ -209,63 +209,58 @@ context.get(key2); // 999 - provided explicitly
209
209
210
210
### Custom Context Key
211
211
212
- [ ContextKey.merge () ] : #custom-context-key
212
+ [ ContextKey.grow () ] : #custom-context-key
213
213
214
214
It is possible to implement a custom ` ContextKey ` .
215
215
216
- For that extend an ` AbstractContextKey ` that implements the boilerplate. The only method left to implement then is a
217
- ` merge() ` one.
218
-
219
- The ` merge() ` method takes three parameters:
220
- - a ` ContextValues ` instance (to consult other context values if necessary),
221
- - a ` ContextSources ` instance (containing provided [ value sources] ), and
222
- - a ` handleDefault ` function responsible for the default value selection.
216
+ For that extend e.g. a ` SimpleContextKey ` that implements the boilerplate. The only method left to implement then is a
217
+ ` grow() ` one.
223
218
224
- The method returns a context value constructed out of the provided value sources.
219
+ The ` grow() ` method takes a single ` ContextValueOpts ` parameter containing the value construction options and returns
220
+ a context value constructed out of the provided value sources.
225
221
226
222
227
- #### Value Sources
223
+ #### Value Sources and Seeds
228
224
229
225
[ value sources ] : #value-sources
230
226
231
- Instead of the values themselves , the registry allows to provide their sources. Those are used by [ ContextKey.merge() ]
232
- method to construct the value.
227
+ Instead of the value itself , the registry allows to provide its sources. Those are combined into _ value seed _ .
228
+ That is passed to [ ContextKey.grow() ] method to construct the value (or grow it from the seed) .
233
229
234
- There could be many sources per single value. And they could be of a type different from the final value .
230
+ There could be multiple sources per single value. And they could be of different type .
235
231
236
- The sources are passed to the ` merge() ` function as an [ AIterable] instance. The latter is an enhanced ` Iterable ` with
237
- Array-like API, including ` map() ` , ` flatMap() ` , ` forEach() ` , and other methods.
232
+ For example, the seed of ` SimpleValueKey ` and ` MultiValueKey ` is an [ AIterable] instance. The latter is enhanced
233
+ ` Iterable ` with Array-like API, including ` map() ` , ` flatMap() ` , ` forEach() ` , and other methods.
238
234
239
- [ AIterable] : https://www.npmjs.com/package/a-iterable
235
+ [ AIterable ] : https://www.npmjs.com/package/a-iterable
240
236
241
237
``` typescript
238
+ import { AIterable } from ' a-iterable' ;
242
239
import {
243
- AbstractContextKey ,
244
240
ContextRegistry ,
245
- ContextSources ,
241
+ ContextValueOpts ,
246
242
ContextValues ,
247
- Handler ,
248
- DefaultContextValueHandler
243
+ SimpleContextKey ,
249
244
} from ' context-values' ;
250
245
251
- class ConcatContextKey <V > extends AbstractContextKey < V , string > {
246
+ class ConcatContextKey <Src > extends SimpleContextKey < string , Src > {
252
247
253
248
constructor (name : string ) {
254
- super (name );
249
+ super (name );
255
250
}
256
251
257
- merge(
258
- context : ContextValues ,
259
- sources : ContextSources <string >,
260
- handleDefault : DefaultContextValueHandler <string >): string | null | undefined {
252
+ grow<Ctx extends ContextValues >(
253
+ opts : ContextValueOpts <Ctx , string , Src , AIterable <Src >>,
254
+ ): string | null | undefined {
261
255
262
- const result = sources .reduce ((p , s ) => p != null ? ` ${p }, ${s } ` : ` ${s } ` , null );
256
+ const result = opts . seed .reduce ((p , s ) => p != null ? ` ${p }, ${s } ` : ` ${s } ` , null );
263
257
264
258
if (result != null ) {
265
259
return result ;
266
260
}
267
-
268
- return handleDefault (() => ' ' ); // No sources provided. Returning empty string, unless a fallback value provided.
261
+
262
+ // No sources provided. Returning empty string, unless a fallback value provided.
263
+ return opts .byDefault (() => ' ' );
269
264
}
270
265
271
266
}
@@ -286,9 +281,43 @@ context.get(key2); // '' - empty string by default
286
281
context .get (key2 , { or: undefined }); // undefined - fallback value
287
282
```
288
283
289
- A context value for particular key is constructed at most once. Thus, the ` merge ()` method is called at most once per
284
+ A context value for particular key is constructed at most once. Thus, the ` grow ()` method is called at most once per
290
285
key.
291
286
292
- A [ context value specifier] ( #context-value-specifier ) is consulted at most once per key. And only when the ` merge ()`
287
+ A [ context value specifier] ( #context-value-specifier ) is consulted at most once per key. And only when the ` grow ()`
293
288
method requested the source value. So, for example, if multiple sources specified for the same ` SingleContextKey ` , only
294
289
the last one will be constructed and used as a context value. The rest of them won't be constructed at all.
290
+
291
+
292
+ Updatable Context Values
293
+ ------------------------
294
+
295
+ A ` SimpleContextKey ` , and thus ` SingleContextKey ` and ` MultiContextKey ` extending it, imply that once the associated
296
+ context value constructed, it no longer changes. I.e. event though more sources provided for the same key in
297
+ ` ContextRegistry ` , they won't affect the already constructed value.
298
+
299
+ However, it is possible to update context values. For that a ` ContextUpKey ` abstract context value key implementation
300
+ may be used, or ` SingleContextUpKey ` and ` MultiContextUpKey ` implementations.
301
+
302
+ They provide the values of [ AfterEvent] registrar of value receivers. This registrar is a function accepting a callback
303
+ that will be called with actual value each time it changes. E.g. when new value source is provided in ` ContextRegistry ` :
304
+
305
+ ``` typescript
306
+ import {
307
+ ContextRegistry ,
308
+ SingleContextUpKey ,
309
+ } from ' context-values' ;
310
+
311
+ const key = new SingleContextUpKey <string >(' updatable-value' );
312
+ const registry = new ContextRegistry ();
313
+
314
+ registry .provide ({ a: key , is: ' initial' });
315
+
316
+ const values = registry .newValues ();
317
+
318
+ values .get (key )(value => console .log (value )); // Log: 'initial'
319
+
320
+ registry .provide ({ a: key , is: ' updated' }); // Log: 'updated'
321
+ ```
322
+
323
+ [ AfterEvent ] : https://www.npmjs.com/package/fun-events
0 commit comments