@fjell/cache 4.6.4 → 4.6.7

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