@fjell/cache 4.4.3 → 4.5.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/dist/src/Aggregator.d.ts +19 -0
- package/dist/src/Aggregator.js +174 -0
- package/dist/src/Aggregator.js.map +1 -0
- package/dist/src/Cache.d.ts +6 -1
- package/dist/src/Cache.js +196 -1
- package/dist/src/Cache.js.map +1 -1
- package/dist/src/CacheRegistry.d.ts +2 -3
- package/dist/src/CacheRegistry.js +1 -1
- package/dist/src/CacheRegistry.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -9
- package/src/{AItemAggregator.ts → Aggregator.ts} +115 -90
- package/src/Cache.ts +265 -2
- package/src/CacheRegistry.ts +3 -6
- package/dist/src/AItemAggregator.d.ts +0 -35
- package/dist/src/AItemAggregator.js +0 -163
- package/dist/src/AItemAggregator.js.map +0 -1
- package/dist/src/AItemCache.d.ts +0 -21
- package/dist/src/AItemCache.js +0 -189
- package/dist/src/AItemCache.js.map +0 -1
- package/dist/src/CItemCache.d.ts +0 -17
- package/dist/src/CItemCache.js +0 -58
- package/dist/src/CItemCache.js.map +0 -1
- package/dist/src/PItemCache.d.ts +0 -17
- package/dist/src/PItemCache.js +0 -50
- package/dist/src/PItemCache.js.map +0 -1
- package/dist/src/index.d.ts +0 -7
- package/dist/src/index.js +0 -7
- package/dist/src/index.js.map +0 -1
- package/src/AItemCache.ts +0 -262
- package/src/CItemCache.ts +0 -117
- package/src/PItemCache.ts +0 -99
- package/src/index.ts +0 -10
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
/* eslint-disable no-undefined
|
|
2
|
-
|
|
1
|
+
/* eslint-disable no-undefined */
|
|
3
2
|
import {
|
|
4
3
|
ComKey,
|
|
5
4
|
Item,
|
|
@@ -8,11 +7,26 @@ import {
|
|
|
8
7
|
PriKey,
|
|
9
8
|
TypesProperties
|
|
10
9
|
} from "@fjell/core";
|
|
11
|
-
import { AItemCache } from "./AItemCache";
|
|
12
10
|
import { Cache } from "./Cache";
|
|
13
11
|
import { CacheMap } from "./CacheMap";
|
|
14
12
|
import LibLogger from "./logger";
|
|
15
13
|
|
|
14
|
+
const logger = LibLogger.get('ItemAggregator');
|
|
15
|
+
|
|
16
|
+
export interface Aggregator<
|
|
17
|
+
V extends Item<S, L1, L2, L3, L4, L5>,
|
|
18
|
+
S extends string,
|
|
19
|
+
L1 extends string = never,
|
|
20
|
+
L2 extends string = never,
|
|
21
|
+
L3 extends string = never,
|
|
22
|
+
L4 extends string = never,
|
|
23
|
+
L5 extends string = never
|
|
24
|
+
> extends Cache<V, S, L1, L2, L3, L4, L5> {
|
|
25
|
+
populate: (item: V) => Promise<V>;
|
|
26
|
+
populateAggregate: (key: string, item: V) => Promise<void>;
|
|
27
|
+
populateEvent: (key: string, item: V) => Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
|
|
16
30
|
export interface CacheConfig { cache: any, optional: boolean }
|
|
17
31
|
|
|
18
32
|
export interface AggregateConfig { [key: string]: (CacheConfig) }
|
|
@@ -35,7 +49,7 @@ export const toCacheConfig = <
|
|
|
35
49
|
return cacheConfig;
|
|
36
50
|
}
|
|
37
51
|
|
|
38
|
-
export
|
|
52
|
+
export const createAggregator = <
|
|
39
53
|
V extends Item<S, L1, L2, L3, L4, L5>,
|
|
40
54
|
S extends string,
|
|
41
55
|
L1 extends string = never,
|
|
@@ -43,51 +57,38 @@ export class AItemAggregator<
|
|
|
43
57
|
L3 extends string = never,
|
|
44
58
|
L4 extends string = never,
|
|
45
59
|
L5 extends string = never
|
|
46
|
-
>
|
|
47
|
-
|
|
48
|
-
private cache: AItemCache<V, S, L1, L2, L3, L4, L5>;
|
|
49
|
-
private logger;
|
|
50
|
-
private aggregates: AggregateConfig = {};
|
|
51
|
-
private events: AggregateConfig = {};
|
|
52
|
-
|
|
53
|
-
public constructor(
|
|
54
|
-
cache: AItemCache<V, S, L1, L2, L3, L4, L5>,
|
|
60
|
+
>(
|
|
61
|
+
cache: Cache<V, S, L1, L2, L3, L4, L5>,
|
|
55
62
|
{ aggregates = {}, events = {} }:
|
|
56
63
|
{
|
|
57
64
|
aggregates?: AggregateConfig,
|
|
58
65
|
events?: AggregateConfig
|
|
59
|
-
}
|
|
60
|
-
) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private async populate(item: V): Promise<V> {
|
|
69
|
-
this.logger.default('populate', { item });
|
|
70
|
-
for (const key in this.aggregates) {
|
|
71
|
-
await this.populateAggregate(key, item);
|
|
66
|
+
}
|
|
67
|
+
): Aggregator<V, S, L1, L2, L3, L4, L5> => {
|
|
68
|
+
|
|
69
|
+
const populate = async (item: V): Promise<V> => {
|
|
70
|
+
logger.default('populate', { item });
|
|
71
|
+
for (const key in aggregates) {
|
|
72
|
+
await populateAggregate(key, item);
|
|
72
73
|
}
|
|
73
|
-
for (const key in
|
|
74
|
-
await
|
|
74
|
+
for (const key in events) {
|
|
75
|
+
await populateEvent(key, item);
|
|
75
76
|
}
|
|
76
|
-
|
|
77
|
+
logger.default('populate done', { item });
|
|
77
78
|
return item;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const cacheConfig = toCacheConfig(
|
|
81
|
+
const populateAggregate = async (key: string, item: V) => {
|
|
82
|
+
logger.default('populate aggregate key', { key });
|
|
83
|
+
const cacheConfig = toCacheConfig(aggregates[key]);
|
|
83
84
|
if (item.refs === undefined) {
|
|
84
85
|
if (cacheConfig.optional === false) {
|
|
85
|
-
|
|
86
|
+
logger.error('Item does not have refs an is not optional ' + JSON.stringify(item));
|
|
86
87
|
throw new Error('Item does not have refs an is not optional ' + JSON.stringify(item));
|
|
87
88
|
}
|
|
88
89
|
} else if (item.refs[key] === undefined) {
|
|
89
90
|
if (cacheConfig.optional === false) {
|
|
90
|
-
|
|
91
|
+
logger.error('Item does not have mandatory ref with key, not optional ' +
|
|
91
92
|
key + ' ' + JSON.stringify(item));
|
|
92
93
|
throw new Error('Item does not have mandatory ref with key, not optional ' +
|
|
93
94
|
key + ' ' + JSON.stringify(item));
|
|
@@ -96,7 +97,7 @@ export class AItemAggregator<
|
|
|
96
97
|
|
|
97
98
|
const ref = item.refs[key];
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
logger.default('AGG Retrieving Item in Populate', { key: ref });
|
|
100
101
|
const [, newItem] = await cacheConfig.cache.retrieve(ref);
|
|
101
102
|
if (newItem) {
|
|
102
103
|
if (item.aggs === undefined) {
|
|
@@ -111,27 +112,27 @@ export class AItemAggregator<
|
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
// TODO: I'm not a big fan that this just "automatically" assumes that the "by" key in event is a ref.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const cacheConfig = toCacheConfig(
|
|
115
|
+
const populateEvent = async (key: string, item: V) => {
|
|
116
|
+
logger.default('populate event key', { key });
|
|
117
|
+
const cacheConfig = toCacheConfig(events[key]);
|
|
117
118
|
|
|
118
119
|
if (item.events === undefined) {
|
|
119
120
|
throw new Error('Item does not have events ' + JSON.stringify(item));
|
|
120
121
|
} else if (item.events[key] === undefined) {
|
|
121
122
|
if (cacheConfig.optional === false) {
|
|
122
|
-
|
|
123
|
+
logger.error('Item does not have mandatory event with key ' + key + ' ' + JSON.stringify(item));
|
|
123
124
|
throw new Error('Item does not have mandatory event with key ' + key + ' ' + JSON.stringify(item));
|
|
124
125
|
}
|
|
125
126
|
} else {
|
|
126
127
|
const event = item.events[key];
|
|
127
128
|
|
|
128
129
|
if (event.by === undefined) {
|
|
129
|
-
|
|
130
|
+
logger.error(
|
|
130
131
|
'populateEvent with an Event that does not have by', { event, ik: item.key, eventKey: key });
|
|
131
132
|
throw new Error('populateEvent with an Event that does not have by: ' + JSON.stringify({ key, event }));
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
|
|
135
|
+
logger.default('EVENT Retrieving Item in Populate', { key: event.by });
|
|
135
136
|
const [, newItem] = await cacheConfig.cache.retrieve(event.by);
|
|
136
137
|
if (newItem) {
|
|
137
138
|
event.agg = newItem as Item;
|
|
@@ -139,113 +140,137 @@ export class AItemAggregator<
|
|
|
139
140
|
}
|
|
140
141
|
}
|
|
141
142
|
|
|
142
|
-
|
|
143
|
+
const all = async (
|
|
143
144
|
query: ItemQuery = {},
|
|
144
145
|
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
145
146
|
):
|
|
146
|
-
Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> {
|
|
147
|
-
|
|
148
|
-
const [cacheMap, items] = await
|
|
149
|
-
const populatedItems = await Promise.all(items.map(async (item) =>
|
|
147
|
+
Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> => {
|
|
148
|
+
logger.default('all', { query, locations });
|
|
149
|
+
const [cacheMap, items] = await cache.all(query, locations);
|
|
150
|
+
const populatedItems = await Promise.all(items.map(async (item) => populate(item)));
|
|
150
151
|
return [cacheMap, populatedItems];
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
|
|
154
|
+
const one = async (
|
|
154
155
|
query: ItemQuery = {},
|
|
155
156
|
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
156
157
|
):
|
|
157
|
-
Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]> {
|
|
158
|
-
|
|
159
|
-
const [cacheMap, item] = await
|
|
158
|
+
Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]> => {
|
|
159
|
+
logger.default('one', { query, locations });
|
|
160
|
+
const [cacheMap, item] = await cache.one(query, locations);
|
|
160
161
|
let populatedItem = null;
|
|
161
162
|
if (item) {
|
|
162
|
-
populatedItem = await
|
|
163
|
+
populatedItem = await populate(item);
|
|
163
164
|
}
|
|
164
165
|
return [cacheMap, populatedItem];
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
|
|
168
|
+
const action = async (
|
|
168
169
|
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
169
170
|
action: string,
|
|
170
171
|
body: any = {},
|
|
171
|
-
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> {
|
|
172
|
-
|
|
173
|
-
const [cacheMap, item] = await
|
|
174
|
-
const populatedItem = await
|
|
172
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> => {
|
|
173
|
+
logger.default('action', { key, action, body });
|
|
174
|
+
const [cacheMap, item] = await cache.action(key, action, body);
|
|
175
|
+
const populatedItem = await populate(item);
|
|
175
176
|
return [cacheMap, populatedItem];
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
|
|
179
|
+
const allAction = async (
|
|
179
180
|
action: string,
|
|
180
181
|
body: any = {},
|
|
181
182
|
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
182
|
-
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> {
|
|
183
|
-
|
|
184
|
-
const [cacheMap, items] = await
|
|
185
|
-
const populatedItems = await Promise.all(items.map(async (item) =>
|
|
183
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> => {
|
|
184
|
+
logger.default('action', { action, body, locations });
|
|
185
|
+
const [cacheMap, items] = await cache.allAction(action, body, locations);
|
|
186
|
+
const populatedItems = await Promise.all(items.map(async (item) => populate(item)));
|
|
186
187
|
return [cacheMap, populatedItems];
|
|
187
188
|
}
|
|
188
189
|
|
|
189
|
-
|
|
190
|
+
const create = async (
|
|
190
191
|
v: TypesProperties<V, S, L1, L2, L3, L4, L5>,
|
|
191
192
|
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
192
|
-
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> {
|
|
193
|
-
|
|
194
|
-
const [cacheMap, item] = await
|
|
195
|
-
const populatedItem = await
|
|
193
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> => {
|
|
194
|
+
logger.default('create', { v, locations });
|
|
195
|
+
const [cacheMap, item] = await cache.create(v, locations);
|
|
196
|
+
const populatedItem = await populate(item);
|
|
196
197
|
return [cacheMap, populatedItem];
|
|
197
198
|
}
|
|
198
199
|
|
|
199
|
-
|
|
200
|
+
const get = async (
|
|
200
201
|
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
201
|
-
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]> {
|
|
202
|
-
|
|
203
|
-
const [cacheMap, item] = await
|
|
202
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]> => {
|
|
203
|
+
logger.default('get', { key });
|
|
204
|
+
const [cacheMap, item] = await cache.get(key);
|
|
204
205
|
let populatedItem = null;
|
|
205
206
|
if (item) {
|
|
206
|
-
populatedItem = await
|
|
207
|
+
populatedItem = await populate(item);
|
|
207
208
|
}
|
|
208
209
|
return [cacheMap, populatedItem];
|
|
209
210
|
}
|
|
210
211
|
|
|
211
|
-
|
|
212
|
+
const retrieve = async (
|
|
212
213
|
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
213
|
-
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5> | null, V | null]> {
|
|
214
|
-
|
|
215
|
-
const [cacheMap, item] = await
|
|
214
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5> | null, V | null]> => {
|
|
215
|
+
logger.default('retrieve', { key });
|
|
216
|
+
const [cacheMap, item] = await cache.retrieve(key);
|
|
216
217
|
let populatedItem = null;
|
|
217
218
|
if (item) {
|
|
218
|
-
populatedItem = await
|
|
219
|
+
populatedItem = await populate(item);
|
|
219
220
|
}
|
|
220
221
|
return [cacheMap, populatedItem];
|
|
221
222
|
}
|
|
222
223
|
|
|
223
|
-
|
|
224
|
+
const remove = async (
|
|
224
225
|
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
225
|
-
): Promise<CacheMap<V, S, L1, L2, L3, L4, L5>> {
|
|
226
|
-
|
|
227
|
-
const cacheMap = await
|
|
226
|
+
): Promise<CacheMap<V, S, L1, L2, L3, L4, L5>> => {
|
|
227
|
+
logger.default('remove', { key });
|
|
228
|
+
const cacheMap = await cache.remove(key);
|
|
228
229
|
return cacheMap;
|
|
229
230
|
}
|
|
230
231
|
|
|
231
|
-
|
|
232
|
+
const update = async (
|
|
232
233
|
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
233
234
|
v: TypesProperties<V, S, L1, L2, L3, L4, L5>,
|
|
234
|
-
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> {
|
|
235
|
-
|
|
236
|
-
const [cacheMap, item] = await
|
|
237
|
-
const populatedItem = await
|
|
235
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> => {
|
|
236
|
+
logger.default('update', { key, v });
|
|
237
|
+
const [cacheMap, item] = await cache.update(key, v);
|
|
238
|
+
const populatedItem = await populate(item);
|
|
238
239
|
return [cacheMap, populatedItem];
|
|
239
240
|
}
|
|
240
241
|
|
|
241
|
-
|
|
242
|
+
const find = async (
|
|
242
243
|
finder: string,
|
|
243
244
|
finderParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,
|
|
244
245
|
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
245
|
-
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> {
|
|
246
|
-
|
|
247
|
-
const [cacheMap, items] = await
|
|
248
|
-
const populatedItems = await Promise.all(items.map(async (item) =>
|
|
246
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> => {
|
|
247
|
+
logger.default('find', { finder, finderParams, locations });
|
|
248
|
+
const [cacheMap, items] = await cache.find(finder, finderParams, locations);
|
|
249
|
+
const populatedItems = await Promise.all(items.map(async (item) => populate(item)));
|
|
249
250
|
return [cacheMap, populatedItems];
|
|
250
251
|
}
|
|
252
|
+
|
|
253
|
+
const reset = async (): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>]> => {
|
|
254
|
+
const cacheMap = await cache.reset();
|
|
255
|
+
return cacheMap;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
all,
|
|
260
|
+
one,
|
|
261
|
+
action,
|
|
262
|
+
allAction,
|
|
263
|
+
create,
|
|
264
|
+
get,
|
|
265
|
+
retrieve,
|
|
266
|
+
remove,
|
|
267
|
+
update,
|
|
268
|
+
find,
|
|
269
|
+
reset,
|
|
270
|
+
pkTypes: cache.pkTypes,
|
|
271
|
+
cacheMap: cache.cacheMap,
|
|
272
|
+
populate,
|
|
273
|
+
populateAggregate,
|
|
274
|
+
populateEvent
|
|
275
|
+
}
|
|
251
276
|
}
|
package/src/Cache.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
/* eslint-disable no-undefined */
|
|
2
1
|
import {
|
|
2
|
+
AllItemTypeArrays,
|
|
3
3
|
ComKey,
|
|
4
|
+
isValidItemKey,
|
|
4
5
|
Item,
|
|
5
6
|
ItemQuery,
|
|
6
7
|
LocKeyArray,
|
|
7
8
|
PriKey,
|
|
8
|
-
TypesProperties
|
|
9
|
+
TypesProperties,
|
|
10
|
+
validatePK
|
|
9
11
|
} from "@fjell/core";
|
|
10
12
|
import { CacheMap } from "./CacheMap";
|
|
13
|
+
import LibLogger from "./logger";
|
|
14
|
+
|
|
15
|
+
import { ClientApi } from "@fjell/client-api";
|
|
16
|
+
import { NotFoundError } from "@fjell/http-api";
|
|
17
|
+
|
|
18
|
+
const logger = LibLogger.get('Cache');
|
|
11
19
|
|
|
12
20
|
export interface Cache<
|
|
13
21
|
V extends Item<S, L1, L2, L3, L4, L5>,
|
|
@@ -70,4 +78,259 @@ export interface Cache<
|
|
|
70
78
|
locations?: LocKeyArray<L1, L2, L3, L4, L5> | []
|
|
71
79
|
) => Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]>;
|
|
72
80
|
|
|
81
|
+
reset: () => Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>]>;
|
|
82
|
+
|
|
83
|
+
pkTypes: AllItemTypeArrays<S, L1, L2, L3, L4, L5>;
|
|
84
|
+
|
|
85
|
+
cacheMap: CacheMap<V, S, L1, L2, L3, L4, L5>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export const createCache = <
|
|
89
|
+
V extends Item<S, L1, L2, L3, L4, L5>,
|
|
90
|
+
S extends string,
|
|
91
|
+
L1 extends string = never,
|
|
92
|
+
L2 extends string = never,
|
|
93
|
+
L3 extends string = never,
|
|
94
|
+
L4 extends string = never,
|
|
95
|
+
L5 extends string = never
|
|
96
|
+
>(
|
|
97
|
+
api: ClientApi<V, S, L1, L2, L3, L4, L5>,
|
|
98
|
+
pkType: S,
|
|
99
|
+
parentCache?: Cache<Item<L1, L2, L3, L4, L5>, L1, L2, L3, L4, L5>
|
|
100
|
+
): Cache<V, S, L1, L2, L3, L4, L5> => {
|
|
101
|
+
|
|
102
|
+
let pkTypes: AllItemTypeArrays<S, L1, L2, L3, L4, L5> = [ pkType ];
|
|
103
|
+
if( parentCache ) {
|
|
104
|
+
pkTypes = pkTypes.concat(parentCache.pkTypes as any) as unknown as AllItemTypeArrays<S, L1, L2, L3, L4, L5>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let cacheMap: CacheMap<V, S, L1, L2, L3, L4, L5> =
|
|
108
|
+
new CacheMap<V, S, L1, L2, L3, L4, L5>(pkTypes as AllItemTypeArrays<S, L1, L2, L3, L4, L5>);
|
|
109
|
+
|
|
110
|
+
const all = async (
|
|
111
|
+
query: ItemQuery = {},
|
|
112
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
113
|
+
):
|
|
114
|
+
Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> => {
|
|
115
|
+
logger.default('all', { query, locations });
|
|
116
|
+
let ret: V[] = [];
|
|
117
|
+
try {
|
|
118
|
+
ret = await api.all(query, {}, locations);
|
|
119
|
+
ret.forEach((v) => {
|
|
120
|
+
cacheMap.set(v.key, v);
|
|
121
|
+
});
|
|
122
|
+
} catch (e: unknown) {
|
|
123
|
+
if (e instanceof NotFoundError) {
|
|
124
|
+
} else {
|
|
125
|
+
throw e;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
return [cacheMap, validatePK(ret, pkType) as V[]];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const one = async (
|
|
133
|
+
query: ItemQuery = {},
|
|
134
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
135
|
+
):
|
|
136
|
+
Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]> => {
|
|
137
|
+
logger.default('one', { query, locations });
|
|
138
|
+
|
|
139
|
+
let retItem: V | null = null;
|
|
140
|
+
try {
|
|
141
|
+
retItem = await api.one(query, {}, locations);
|
|
142
|
+
if (retItem) {
|
|
143
|
+
cacheMap.set(retItem.key, retItem);
|
|
144
|
+
}
|
|
145
|
+
} catch (e: unknown) {
|
|
146
|
+
if (e instanceof NotFoundError) {
|
|
147
|
+
} else {
|
|
148
|
+
throw e;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
}
|
|
152
|
+
return [
|
|
153
|
+
cacheMap,
|
|
154
|
+
retItem ?
|
|
155
|
+
validatePK(retItem, pkType) as V :
|
|
156
|
+
null
|
|
157
|
+
];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const action = async (
|
|
161
|
+
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
162
|
+
action: string,
|
|
163
|
+
body: any = {},
|
|
164
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> => {
|
|
165
|
+
logger.default('action', { key, action, body });
|
|
166
|
+
|
|
167
|
+
if (!isValidItemKey(key)) {
|
|
168
|
+
logger.error('Key for Action is not a valid ItemKey: %j', key);
|
|
169
|
+
throw new Error('Key for Action is not a valid ItemKey');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const updated = await api.action(key, action, body, {});
|
|
173
|
+
cacheMap.set(updated.key, updated);
|
|
174
|
+
return [cacheMap, validatePK(updated, pkType) as V];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const allAction = async (
|
|
178
|
+
action: string,
|
|
179
|
+
body: any = {},
|
|
180
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
181
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> => {
|
|
182
|
+
logger.default('allAction', { action, body, locations });
|
|
183
|
+
let ret: V[] = [];
|
|
184
|
+
try {
|
|
185
|
+
ret = await api.allAction(action, body, {}, locations);
|
|
186
|
+
ret.forEach((v) => {
|
|
187
|
+
cacheMap.set(v.key, v);
|
|
188
|
+
});
|
|
189
|
+
} catch (e: unknown) {
|
|
190
|
+
// istanbul ignore next
|
|
191
|
+
if (e instanceof NotFoundError) {
|
|
192
|
+
} else {
|
|
193
|
+
throw e;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
return [cacheMap, validatePK(ret, pkType) as V[]];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const create = async (
|
|
201
|
+
v: TypesProperties<V, S, L1, L2, L3, L4, L5>,
|
|
202
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
203
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> => {
|
|
204
|
+
logger.default('create', { v, locations });
|
|
205
|
+
const created = await api.create(v, {}, locations);
|
|
206
|
+
cacheMap.set(created.key, created);
|
|
207
|
+
return [cacheMap, validatePK(created, pkType) as V];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const get = async (
|
|
211
|
+
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
212
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]> => {
|
|
213
|
+
logger.default('get', { key });
|
|
214
|
+
if (!isValidItemKey(key)) {
|
|
215
|
+
logger.error('Key for Get is not a valid ItemKey: %j', key);
|
|
216
|
+
throw new Error('Key for Get is not a valid ItemKey');
|
|
217
|
+
}
|
|
218
|
+
let ret: V | null;
|
|
219
|
+
try {
|
|
220
|
+
ret = await api.get(key, {});
|
|
221
|
+
if (ret) {
|
|
222
|
+
cacheMap.set(ret.key, ret);
|
|
223
|
+
}
|
|
224
|
+
} catch (e: any) {
|
|
225
|
+
logger.error("Error getting item for key", { key, message: e.message, stack: e.stack });
|
|
226
|
+
throw e;
|
|
227
|
+
}
|
|
228
|
+
return [
|
|
229
|
+
cacheMap,
|
|
230
|
+
ret ?
|
|
231
|
+
validatePK(ret, pkType) as V :
|
|
232
|
+
null
|
|
233
|
+
];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const retrieve = async (
|
|
237
|
+
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
238
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5> | null, V | null]> => {
|
|
239
|
+
logger.default('retrieve', { key });
|
|
240
|
+
if (!isValidItemKey(key)) {
|
|
241
|
+
logger.error('Key for Retrieve is not a valid ItemKey: %j', key);
|
|
242
|
+
throw new Error('Key for Retrieve is not a valid ItemKey');
|
|
243
|
+
}
|
|
244
|
+
const containsItemKey = cacheMap.includesKey(key);
|
|
245
|
+
|
|
246
|
+
let retrieved: V | null;
|
|
247
|
+
if (containsItemKey) {
|
|
248
|
+
logger.default('Looking for Object in Cache', key);
|
|
249
|
+
retrieved = cacheMap.get(key);
|
|
250
|
+
} else {
|
|
251
|
+
logger.default('Object Not Found in Cache, Retrieving from Server API', { key });
|
|
252
|
+
[, retrieved] = await get(key);
|
|
253
|
+
}
|
|
254
|
+
const retValue: [CacheMap<V, S, L1, L2, L3, L4, L5> | null, V | null] = [
|
|
255
|
+
containsItemKey ? null : cacheMap,
|
|
256
|
+
retrieved ?
|
|
257
|
+
validatePK(retrieved, pkType) as V:
|
|
258
|
+
null
|
|
259
|
+
];
|
|
260
|
+
// logger.debug('Returning from retrieve', { retValue });
|
|
261
|
+
return retValue;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const remove = async (
|
|
265
|
+
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
266
|
+
): Promise<CacheMap<V, S, L1, L2, L3, L4, L5>> => {
|
|
267
|
+
logger.default('remove', { key });
|
|
268
|
+
if (!isValidItemKey(key)) {
|
|
269
|
+
logger.error('Key for Remove is not a valid ItemKey: %j', key);
|
|
270
|
+
throw new Error('Key for Remove is not a valid ItemKey');
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
await api.remove(key, {});
|
|
274
|
+
cacheMap.delete(key);
|
|
275
|
+
} catch (e) {
|
|
276
|
+
logger.error("Error deleting item", { error: e });
|
|
277
|
+
throw e;
|
|
278
|
+
}
|
|
279
|
+
return cacheMap;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const update = async (
|
|
283
|
+
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
284
|
+
v: TypesProperties<V, S, L1, L2, L3, L4, L5>,
|
|
285
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]> => {
|
|
286
|
+
logger.default('update', { key, v });
|
|
287
|
+
|
|
288
|
+
if (!isValidItemKey(key)) {
|
|
289
|
+
logger.error('Key for Update is not a valid ItemKey: %j', key);
|
|
290
|
+
throw new Error('Key for Update is not a valid ItemKey');
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
const updated = await api.update(key, v, {});
|
|
295
|
+
cacheMap.set(updated.key, updated);
|
|
296
|
+
return [cacheMap, validatePK(updated, pkType) as V];
|
|
297
|
+
} catch (e) {
|
|
298
|
+
logger.error("Error updating chat", { error: e });
|
|
299
|
+
throw e;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const find = async (
|
|
304
|
+
finder: string,
|
|
305
|
+
finderParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,
|
|
306
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
307
|
+
): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]> => {
|
|
308
|
+
logger.default('find', { finder, finderParams, locations });
|
|
309
|
+
const ret: V[] = await api.find(finder, finderParams, {}, locations);
|
|
310
|
+
ret.forEach((v) => {
|
|
311
|
+
cacheMap.set(v.key, v);
|
|
312
|
+
});
|
|
313
|
+
return [cacheMap, validatePK(ret, pkType) as V[]];
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const reset = async (): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>]> => {
|
|
317
|
+
cacheMap = new CacheMap<V, S, L1, L2, L3, L4, L5>(pkTypes);
|
|
318
|
+
return [cacheMap];
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
all,
|
|
323
|
+
one,
|
|
324
|
+
action,
|
|
325
|
+
allAction,
|
|
326
|
+
create,
|
|
327
|
+
get,
|
|
328
|
+
retrieve,
|
|
329
|
+
remove,
|
|
330
|
+
update,
|
|
331
|
+
find,
|
|
332
|
+
reset,
|
|
333
|
+
pkTypes,
|
|
334
|
+
cacheMap
|
|
335
|
+
}
|
|
73
336
|
}
|
package/src/CacheRegistry.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Item } from "@fjell/core";
|
|
2
|
-
import {
|
|
3
|
-
import { CItemCache } from "./CItemCache";
|
|
4
|
-
|
|
2
|
+
import { Cache } from "./Cache";
|
|
5
3
|
import LibLogger from './logger';
|
|
6
4
|
|
|
7
5
|
const logger = LibLogger.get('CacheRegistry');
|
|
@@ -33,9 +31,8 @@ export class CacheRegistry {
|
|
|
33
31
|
L3 extends string = never,
|
|
34
32
|
L4 extends string = never,
|
|
35
33
|
L5 extends string = never
|
|
36
|
-
>(cache:
|
|
37
|
-
|
|
38
|
-
this.cacheMap[JSON.stringify(cache.getKeyTypes())] = cache;
|
|
34
|
+
>(cache: Cache<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>): void => {
|
|
35
|
+
this.cacheMap[JSON.stringify(cache.pkTypes)] = cache;
|
|
39
36
|
};
|
|
40
37
|
|
|
41
38
|
public isConfigured = (): boolean => {
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { ComKey, Item, ItemQuery, LocKeyArray, PriKey, TypesProperties } from "@fjell/core";
|
|
2
|
-
import { AItemCache } from "./AItemCache";
|
|
3
|
-
import { Cache } from "./Cache";
|
|
4
|
-
import { CacheMap } from "./CacheMap";
|
|
5
|
-
export interface CacheConfig {
|
|
6
|
-
cache: any;
|
|
7
|
-
optional: boolean;
|
|
8
|
-
}
|
|
9
|
-
export interface AggregateConfig {
|
|
10
|
-
[key: string]: (CacheConfig);
|
|
11
|
-
}
|
|
12
|
-
export declare const toCacheConfig: <V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never>(config: CacheConfig | Cache<V, S, L1, L2, L3, L4, L5>) => CacheConfig;
|
|
13
|
-
export declare class AItemAggregator<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> implements Cache<V, S, L1, L2, L3, L4, L5> {
|
|
14
|
-
private cache;
|
|
15
|
-
private logger;
|
|
16
|
-
private aggregates;
|
|
17
|
-
private events;
|
|
18
|
-
constructor(cache: AItemCache<V, S, L1, L2, L3, L4, L5>, { aggregates, events }: {
|
|
19
|
-
aggregates?: AggregateConfig;
|
|
20
|
-
events?: AggregateConfig;
|
|
21
|
-
});
|
|
22
|
-
private populate;
|
|
23
|
-
private populateAggregate;
|
|
24
|
-
private populateEvent;
|
|
25
|
-
all(query?: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]>;
|
|
26
|
-
one(query?: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]>;
|
|
27
|
-
action(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, action: string, body?: any): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]>;
|
|
28
|
-
allAction(action: string, body?: any, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]>;
|
|
29
|
-
create(v: TypesProperties<V, S, L1, L2, L3, L4, L5>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]>;
|
|
30
|
-
get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V | null]>;
|
|
31
|
-
retrieve(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5> | null, V | null]>;
|
|
32
|
-
remove(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<CacheMap<V, S, L1, L2, L3, L4, L5>>;
|
|
33
|
-
update(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, v: TypesProperties<V, S, L1, L2, L3, L4, L5>): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V]>;
|
|
34
|
-
find(finder: string, finderParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<[CacheMap<V, S, L1, L2, L3, L4, L5>, V[]]>;
|
|
35
|
-
}
|