@twin.org/core 0.9.3-next.2 → 0.9.3-next.4
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/dist/es/factories/facadeFactory.js +9 -0
- package/dist/es/factories/facadeFactory.js.map +1 -0
- package/dist/es/factories/factory.js +127 -6
- package/dist/es/factories/factory.js.map +1 -1
- package/dist/es/index.js +2 -0
- package/dist/es/index.js.map +1 -1
- package/dist/es/models/IFacade.js +4 -0
- package/dist/es/models/IFacade.js.map +1 -0
- package/dist/es/utils/lfuCache.js +91 -13
- package/dist/es/utils/lfuCache.js.map +1 -1
- package/dist/es/utils/lruCache.js +83 -10
- package/dist/es/utils/lruCache.js.map +1 -1
- package/dist/types/factories/facadeFactory.d.ts +6 -0
- package/dist/types/factories/factory.d.ts +20 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/models/IFacade.d.ts +12 -0
- package/dist/types/utils/lfuCache.d.ts +8 -2
- package/dist/types/utils/lruCache.d.ts +8 -2
- package/docs/changelog.md +34 -0
- package/docs/examples.md +38 -1
- package/docs/reference/classes/Factory.md +73 -2
- package/docs/reference/classes/LfuCache.md +18 -2
- package/docs/reference/classes/LruCache.md +18 -2
- package/docs/reference/index.md +2 -0
- package/docs/reference/interfaces/IFacade.md +32 -0
- package/docs/reference/variables/FacadeFactory.md +5 -0
- package/locales/en.json +4 -1
- package/package.json +2 -2
package/docs/examples.md
CHANGED
|
@@ -171,12 +171,49 @@ class SimpleHasher implements IHasher {
|
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
const factory =
|
|
174
|
+
const factory = Factory.createFactory<IHasher>('hashers');
|
|
175
175
|
factory.register('simple', () => new SimpleHasher());
|
|
176
176
|
|
|
177
177
|
factory.create('simple').hash('abc'); // 'abc-hash'
|
|
178
178
|
```
|
|
179
179
|
|
|
180
|
+
## Factory Facades
|
|
181
|
+
|
|
182
|
+
A facade wraps the components a factory produces, so a cross cutting concern can be applied without modifying them.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { ComponentFactory, FacadeFactory, Is, type IFacade } from '@twin.org/core';
|
|
186
|
+
|
|
187
|
+
class LoggingFacade implements IFacade {
|
|
188
|
+
public wrap(target: unknown): unknown {
|
|
189
|
+
return new Proxy(target as object, {
|
|
190
|
+
get(t, prop, receiver): unknown {
|
|
191
|
+
const value = Reflect.get(t, prop, receiver);
|
|
192
|
+
|
|
193
|
+
if (!Is.function(value)) {
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return (...args: unknown[]): unknown => {
|
|
198
|
+
globalThis.console.log('calling', String(prop));
|
|
199
|
+
return value.apply(t, args);
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
FacadeFactory.register('logging', () => new LoggingFacade());
|
|
207
|
+
|
|
208
|
+
// Every component the factory produces from here on is wrapped.
|
|
209
|
+
ComponentFactory.useFacade('logging');
|
|
210
|
+
|
|
211
|
+
// No longer wrapped, for instances produced after this call.
|
|
212
|
+
ComponentFactory.unuseFacade('logging');
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
An instance is passed through the facades in the order they were activated, so the first activated is the outermost.
|
|
216
|
+
|
|
180
217
|
## Encoding and Compression
|
|
181
218
|
|
|
182
219
|
```typescript
|
|
@@ -366,12 +366,75 @@ Remove all the instances and the generators.
|
|
|
366
366
|
|
|
367
367
|
***
|
|
368
368
|
|
|
369
|
+
### useFacade() {#usefacade}
|
|
370
|
+
|
|
371
|
+
> **useFacade**(`name`): `void`
|
|
372
|
+
|
|
373
|
+
Activate a facade for this factory, so every instance it produces is wrapped by it.
|
|
374
|
+
An instance is passed through the facades in the order they were activated, so the facade
|
|
375
|
+
activated first is the outermost. Activating a facade which is already active does nothing.
|
|
376
|
+
|
|
377
|
+
#### Parameters
|
|
378
|
+
|
|
379
|
+
##### name
|
|
380
|
+
|
|
381
|
+
`string`
|
|
382
|
+
|
|
383
|
+
The name of the facade, as registered with the facade factory.
|
|
384
|
+
|
|
385
|
+
#### Returns
|
|
386
|
+
|
|
387
|
+
`void`
|
|
388
|
+
|
|
389
|
+
#### Throws
|
|
390
|
+
|
|
391
|
+
GuardError if the parameters are invalid.
|
|
392
|
+
|
|
393
|
+
#### Throws
|
|
394
|
+
|
|
395
|
+
GeneralError if no facade is registered with the name, or the factory is the facade
|
|
396
|
+
factory itself.
|
|
397
|
+
|
|
398
|
+
***
|
|
399
|
+
|
|
400
|
+
### unuseFacade() {#unusefacade}
|
|
401
|
+
|
|
402
|
+
> **unuseFacade**(`name`): `void`
|
|
403
|
+
|
|
404
|
+
Deactivate a facade for this factory. Deactivating a facade which is not active does nothing.
|
|
405
|
+
|
|
406
|
+
#### Parameters
|
|
407
|
+
|
|
408
|
+
##### name
|
|
409
|
+
|
|
410
|
+
`string`
|
|
411
|
+
|
|
412
|
+
The name of the facade to deactivate.
|
|
413
|
+
|
|
414
|
+
#### Returns
|
|
415
|
+
|
|
416
|
+
`void`
|
|
417
|
+
|
|
418
|
+
#### Throws
|
|
419
|
+
|
|
420
|
+
GuardError if the parameters are invalid.
|
|
421
|
+
|
|
422
|
+
***
|
|
423
|
+
|
|
369
424
|
### instancesMap() {#instancesmap}
|
|
370
425
|
|
|
371
|
-
> **instancesMap**(): `object`
|
|
426
|
+
> **instancesMap**(`withFacade?`): `object`
|
|
372
427
|
|
|
373
428
|
Get all the instances as a map.
|
|
374
429
|
|
|
430
|
+
#### Parameters
|
|
431
|
+
|
|
432
|
+
##### withFacade?
|
|
433
|
+
|
|
434
|
+
`boolean`
|
|
435
|
+
|
|
436
|
+
Return the instances with the active facades applied, defaults to false.
|
|
437
|
+
|
|
375
438
|
#### Returns
|
|
376
439
|
|
|
377
440
|
`object`
|
|
@@ -382,10 +445,18 @@ The instances as a map.
|
|
|
382
445
|
|
|
383
446
|
### instancesList() {#instanceslist}
|
|
384
447
|
|
|
385
|
-
> **instancesList**(): `T`[]
|
|
448
|
+
> **instancesList**(`withFacade?`): `T`[]
|
|
386
449
|
|
|
387
450
|
Get all the instances as a list in the order they were registered.
|
|
388
451
|
|
|
452
|
+
#### Parameters
|
|
453
|
+
|
|
454
|
+
##### withFacade?
|
|
455
|
+
|
|
456
|
+
`boolean`
|
|
457
|
+
|
|
458
|
+
Return the instances with the active facades applied, defaults to false.
|
|
459
|
+
|
|
389
460
|
#### Returns
|
|
390
461
|
|
|
391
462
|
`T`[]
|
|
@@ -10,6 +10,8 @@ minimum frequency is evicted.
|
|
|
10
10
|
The timer only runs while there are entries; it stops automatically when the cache empties.
|
|
11
11
|
|
|
12
12
|
`get` and `set` increment an entry's access frequency and reset its idle timer.
|
|
13
|
+
`set` and `getOrSet` accept an optional hard expiry timestamp; the entry is removed once that
|
|
14
|
+
time is reached however recently it was used, and the TTI still applies alongside it.
|
|
13
15
|
`has` and `keys` are pure peeks they evict idle entries but do not affect frequency or TTI.
|
|
14
16
|
Call `destroy` when the cache is no longer needed to stop the background timer.
|
|
15
17
|
|
|
@@ -125,7 +127,7 @@ The cached value, or undefined on a miss or idle eviction.
|
|
|
125
127
|
|
|
126
128
|
### set() {#set}
|
|
127
129
|
|
|
128
|
-
> **set**(`key`, `value`): `void`
|
|
130
|
+
> **set**(`key`, `value`, `expires?`): `void`
|
|
129
131
|
|
|
130
132
|
Store a value in the cache.
|
|
131
133
|
If the key already exists its value and frequency are updated.
|
|
@@ -146,6 +148,13 @@ The key to store.
|
|
|
146
148
|
|
|
147
149
|
The value to cache.
|
|
148
150
|
|
|
151
|
+
##### expires?
|
|
152
|
+
|
|
153
|
+
`number`
|
|
154
|
+
|
|
155
|
+
Hard expiry timestamp in milliseconds since the epoch. The entry is removed
|
|
156
|
+
once this time is reached regardless of how recently it was used. Must be an integer.
|
|
157
|
+
|
|
149
158
|
#### Returns
|
|
150
159
|
|
|
151
160
|
`void`
|
|
@@ -154,7 +163,7 @@ The value to cache.
|
|
|
154
163
|
|
|
155
164
|
### getOrSet() {#getorset}
|
|
156
165
|
|
|
157
|
-
> **getOrSet**(`key`, `valueFactory`): `Promise`\<`T`\>
|
|
166
|
+
> **getOrSet**(`key`, `valueFactory`, `expires?`): `Promise`\<`T`\>
|
|
158
167
|
|
|
159
168
|
Atomically get an existing value or create and store it once using an async factory.
|
|
160
169
|
Concurrent calls for the same key are serialized via a mutex.
|
|
@@ -173,6 +182,13 @@ The key to get or create.
|
|
|
173
182
|
|
|
174
183
|
Async callback used to build a value when the key is absent.
|
|
175
184
|
|
|
185
|
+
##### expires?
|
|
186
|
+
|
|
187
|
+
`number`
|
|
188
|
+
|
|
189
|
+
Hard expiry timestamp in milliseconds since the epoch, applied to the entry
|
|
190
|
+
when one is created. Must be an integer.
|
|
191
|
+
|
|
176
192
|
#### Returns
|
|
177
193
|
|
|
178
194
|
`Promise`\<`T`\>
|
|
@@ -8,6 +8,8 @@ Entries are removed in two ways:
|
|
|
8
8
|
The timer only runs while there are entries; it stops automatically when the cache empties.
|
|
9
9
|
|
|
10
10
|
`get` and `set` both update an entry's LRU position and reset its idle timer.
|
|
11
|
+
`set` and `getOrSet` accept an optional hard expiry timestamp; the entry is removed once that
|
|
12
|
+
time is reached however recently it was used, and the TTI still applies alongside it.
|
|
11
13
|
`has` is a pure peek it evicts idle entries but does not refresh a live entry's TTI.
|
|
12
14
|
Call `destroy` when the cache is no longer needed to stop the background timer.
|
|
13
15
|
|
|
@@ -123,7 +125,7 @@ The cached value, or undefined on a miss or idle eviction.
|
|
|
123
125
|
|
|
124
126
|
### set() {#set}
|
|
125
127
|
|
|
126
|
-
> **set**(`key`, `value`): `void`
|
|
128
|
+
> **set**(`key`, `value`, `expires?`): `void`
|
|
127
129
|
|
|
128
130
|
Store a value in the cache.
|
|
129
131
|
If the key already exists its value and idle timer are refreshed.
|
|
@@ -144,6 +146,13 @@ The key to store.
|
|
|
144
146
|
|
|
145
147
|
The value to cache.
|
|
146
148
|
|
|
149
|
+
##### expires?
|
|
150
|
+
|
|
151
|
+
`number`
|
|
152
|
+
|
|
153
|
+
Hard expiry timestamp in milliseconds since the epoch. The entry is removed
|
|
154
|
+
once this time is reached regardless of how recently it was used. Must be an integer.
|
|
155
|
+
|
|
147
156
|
#### Returns
|
|
148
157
|
|
|
149
158
|
`void`
|
|
@@ -152,7 +161,7 @@ The value to cache.
|
|
|
152
161
|
|
|
153
162
|
### getOrSet() {#getorset}
|
|
154
163
|
|
|
155
|
-
> **getOrSet**(`key`, `valueFactory`): `Promise`\<`T`\>
|
|
164
|
+
> **getOrSet**(`key`, `valueFactory`, `expires?`): `Promise`\<`T`\>
|
|
156
165
|
|
|
157
166
|
Atomically get an existing value or create and store it once using an async factory.
|
|
158
167
|
Concurrent calls for the same key are serialized via a mutex.
|
|
@@ -171,6 +180,13 @@ The key to get or create.
|
|
|
171
180
|
|
|
172
181
|
Async callback used to build a value when the key is absent.
|
|
173
182
|
|
|
183
|
+
##### expires?
|
|
184
|
+
|
|
185
|
+
`number`
|
|
186
|
+
|
|
187
|
+
Hard expiry timestamp in milliseconds since the epoch, applied to the entry
|
|
188
|
+
when one is created. Must be an integer.
|
|
189
|
+
|
|
174
190
|
#### Returns
|
|
175
191
|
|
|
176
192
|
`Promise`\<`T`\>
|
package/docs/reference/index.md
CHANGED
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
- [IComponent](interfaces/IComponent.md)
|
|
53
53
|
- [IDuration](interfaces/IDuration.md)
|
|
54
54
|
- [IError](interfaces/IError.md)
|
|
55
|
+
- [IFacade](interfaces/IFacade.md)
|
|
55
56
|
- [II18nShared](interfaces/II18nShared.md)
|
|
56
57
|
- [IKeyValue](interfaces/IKeyValue.md)
|
|
57
58
|
- [ILabelledValue](interfaces/ILabelledValue.md)
|
|
@@ -78,6 +79,7 @@
|
|
|
78
79
|
## Variables
|
|
79
80
|
|
|
80
81
|
- [ComponentFactory](variables/ComponentFactory.md)
|
|
82
|
+
- [FacadeFactory](variables/FacadeFactory.md)
|
|
81
83
|
- [CoerceType](variables/CoerceType.md)
|
|
82
84
|
- [CompressionType](variables/CompressionType.md)
|
|
83
85
|
- [MutexMessageTypes](variables/MutexMessageTypes.md)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Interface: IFacade\<T\>
|
|
2
|
+
|
|
3
|
+
A facade wraps a component so a cross cutting concern can be applied to it without the
|
|
4
|
+
component being modified. The wrapped component is returned in place of the original.
|
|
5
|
+
|
|
6
|
+
## Type Parameters
|
|
7
|
+
|
|
8
|
+
### T
|
|
9
|
+
|
|
10
|
+
`T` = `unknown`
|
|
11
|
+
|
|
12
|
+
## Methods
|
|
13
|
+
|
|
14
|
+
### wrap() {#wrap}
|
|
15
|
+
|
|
16
|
+
> **wrap**(`target`): `T`
|
|
17
|
+
|
|
18
|
+
Wrap the target, returning a replacement.
|
|
19
|
+
|
|
20
|
+
#### Parameters
|
|
21
|
+
|
|
22
|
+
##### target
|
|
23
|
+
|
|
24
|
+
`T`
|
|
25
|
+
|
|
26
|
+
The component to wrap.
|
|
27
|
+
|
|
28
|
+
#### Returns
|
|
29
|
+
|
|
30
|
+
`T`
|
|
31
|
+
|
|
32
|
+
The wrapped component.
|
package/locales/en.json
CHANGED
|
@@ -91,7 +91,10 @@
|
|
|
91
91
|
"factory": {
|
|
92
92
|
"noUnregister": "There is no {typeName} registered with the name \"{name}\"",
|
|
93
93
|
"noGet": "The requested {typeName} \"{name}\" does not exist in the factory",
|
|
94
|
-
"noCreate": "The requested {typeName} \"{name}\" cannot be created by the factory, with params \"{params}\""
|
|
94
|
+
"noCreate": "The requested {typeName} \"{name}\" cannot be created by the factory, with params \"{params}\"",
|
|
95
|
+
"noFacade": "The requested facade \"{name}\" is not registered, so it cannot be applied to the {typeName} factory",
|
|
96
|
+
"noFacadeOnFacades": "Facades cannot be applied to the facade factory itself",
|
|
97
|
+
"noFacadeWrap": "The facade \"{name}\" did not return a wrapped instance for the {typeName} factory"
|
|
95
98
|
},
|
|
96
99
|
"bitString": {
|
|
97
100
|
"outOfRange": "The index should be >= 0 and less than the length of the bit string, the index is \"{index}\" and the number of bit is \"{numberBits}\""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/core",
|
|
3
|
-
"version": "0.9.3-next.
|
|
3
|
+
"version": "0.9.3-next.4",
|
|
4
4
|
"description": "Helper methods/classes for data type checking/validation/guarding/error handling",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"node": ">=24.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@twin.org/nameof": "0.9.3-next.
|
|
17
|
+
"@twin.org/nameof": "0.9.3-next.4",
|
|
18
18
|
"intl-messageformat": "11.2.13",
|
|
19
19
|
"rfc6902": "5.3.0"
|
|
20
20
|
},
|