@fjell/cache 4.4.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/LICENSE +202 -0
- package/dist/src/AItemAggregator.d.ts +35 -0
- package/dist/src/AItemAggregator.js +163 -0
- package/dist/src/AItemAggregator.js.map +1 -0
- package/dist/src/AItemCache.d.ts +21 -0
- package/dist/src/AItemCache.js +189 -0
- package/dist/src/AItemCache.js.map +1 -0
- package/dist/src/CItemCache.d.ts +17 -0
- package/dist/src/CItemCache.js +58 -0
- package/dist/src/CItemCache.js.map +1 -0
- package/dist/src/Cache.d.ts +14 -0
- package/dist/src/Cache.js +2 -0
- package/dist/src/Cache.js.map +1 -0
- package/dist/src/CacheMap.d.ts +12 -0
- package/dist/src/CacheMap.js +85 -0
- package/dist/src/CacheMap.js.map +1 -0
- package/dist/src/CacheRegistry.d.ts +14 -0
- package/dist/src/CacheRegistry.js +34 -0
- package/dist/src/CacheRegistry.js.map +1 -0
- package/dist/src/PItemCache.d.ts +17 -0
- package/dist/src/PItemCache.js +50 -0
- package/dist/src/PItemCache.js.map +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.js +7 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logger.d.ts +2 -0
- package/dist/src/logger.js +4 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/eslint.config.mjs +70 -0
- package/package.json +59 -0
- package/src/AItemAggregator.ts +251 -0
- package/src/AItemCache.ts +262 -0
- package/src/CItemCache.ts +117 -0
- package/src/Cache.ts +73 -0
- package/src/CacheMap.ts +132 -0
- package/src/CacheRegistry.ts +57 -0
- package/src/PItemCache.ts +99 -0
- package/src/index.ts +10 -0
- package/src/logger.ts +5 -0
package/src/CacheMap.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AllItemTypeArrays,
|
|
3
|
+
ComKey,
|
|
4
|
+
Dictionary,
|
|
5
|
+
isComKey,
|
|
6
|
+
isQueryMatch,
|
|
7
|
+
Item,
|
|
8
|
+
ItemQuery,
|
|
9
|
+
LocKeyArray,
|
|
10
|
+
PriKey
|
|
11
|
+
} from "@fjell/core";
|
|
12
|
+
import LibLogger from "./logger";
|
|
13
|
+
|
|
14
|
+
const logger = LibLogger.get("CacheMap");
|
|
15
|
+
|
|
16
|
+
// const isObj = (x: any) => typeof x === "object" && x !== null;
|
|
17
|
+
|
|
18
|
+
// const intersection = (a: object, b: object): object => {
|
|
19
|
+
// const result: { [key: string]: any } = {}
|
|
20
|
+
|
|
21
|
+
// if (([a, b]).every(isObj)) {
|
|
22
|
+
// Object.keys(a).forEach((key) => {
|
|
23
|
+
// // @ts-ignore
|
|
24
|
+
// const value = a[key]
|
|
25
|
+
// // @ts-ignore
|
|
26
|
+
// const other = b[key]
|
|
27
|
+
|
|
28
|
+
// if (isObj(value)) {
|
|
29
|
+
// result[key] = intersection(value, other)
|
|
30
|
+
// } else if (value === other) {
|
|
31
|
+
// result[key] = value
|
|
32
|
+
// }
|
|
33
|
+
// })
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
// return result
|
|
37
|
+
// }
|
|
38
|
+
|
|
39
|
+
// const removeEmptyObjects = (obj: object): object => {
|
|
40
|
+
// const result: { [key: string]: any } = {}
|
|
41
|
+
|
|
42
|
+
// Object.keys(obj).forEach((key) => {
|
|
43
|
+
// // @ts-ignore
|
|
44
|
+
// const value = obj[key];
|
|
45
|
+
|
|
46
|
+
// if (isObj(value)) {
|
|
47
|
+
// const nested = removeEmptyObjects(value);
|
|
48
|
+
|
|
49
|
+
// if (Object.keys(nested).length > 0) {
|
|
50
|
+
// result[key] = nested
|
|
51
|
+
// }
|
|
52
|
+
// } else if (value !== null) {
|
|
53
|
+
// result[key] = value
|
|
54
|
+
// }
|
|
55
|
+
// });
|
|
56
|
+
|
|
57
|
+
// return result;
|
|
58
|
+
// }
|
|
59
|
+
|
|
60
|
+
export class CacheMap<
|
|
61
|
+
V extends Item<S, L1, L2, L3, L4, L5>,
|
|
62
|
+
S extends string,
|
|
63
|
+
L1 extends string = never,
|
|
64
|
+
L2 extends string = never,
|
|
65
|
+
L3 extends string = never,
|
|
66
|
+
L4 extends string = never,
|
|
67
|
+
L5 extends string = never
|
|
68
|
+
> extends Dictionary<ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, V> {
|
|
69
|
+
|
|
70
|
+
private types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>;
|
|
71
|
+
|
|
72
|
+
public constructor(
|
|
73
|
+
types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>,
|
|
74
|
+
map?: { [key: string]: V },
|
|
75
|
+
) {
|
|
76
|
+
super(map);
|
|
77
|
+
this.types = types;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public get(
|
|
81
|
+
key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>,
|
|
82
|
+
): V | null {
|
|
83
|
+
return super.get(key) as V | null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public allIn(
|
|
87
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | []
|
|
88
|
+
): V[] {
|
|
89
|
+
if (locations.length === 0) {
|
|
90
|
+
logger.debug('Returning all items, LocKeys is empty');
|
|
91
|
+
return this.values();
|
|
92
|
+
} else {
|
|
93
|
+
const locKeys: LocKeyArray<L1, L2, L3, L4, L5> | [] = locations;
|
|
94
|
+
logger.debug('allIn', { locKeys, keys: this.keys().length });
|
|
95
|
+
return this.keys()
|
|
96
|
+
.filter((key) => key && isComKey(key))
|
|
97
|
+
.filter((key) => {
|
|
98
|
+
const ComKey = key as ComKey<S, L1, L2, L3, L4, L5>;
|
|
99
|
+
logger.debug('Comparing Location Keys', {
|
|
100
|
+
locKeys,
|
|
101
|
+
ComKey,
|
|
102
|
+
});
|
|
103
|
+
return JSON.stringify(locKeys) === JSON.stringify(ComKey.loc);
|
|
104
|
+
})
|
|
105
|
+
.map((key) => this.get(key) as V);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// TODO: Can we do case insensitive matching?
|
|
110
|
+
public contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): boolean {
|
|
111
|
+
logger.debug('contains', { query, locations });
|
|
112
|
+
const items = this.allIn(locations);
|
|
113
|
+
|
|
114
|
+
return items.some((item) => isQueryMatch(item, query));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public queryIn(
|
|
118
|
+
query: ItemQuery,
|
|
119
|
+
locations: LocKeyArray<L1, L2, L3, L4, L5> | [] = []
|
|
120
|
+
): V[] {
|
|
121
|
+
logger.debug('queryIn', { query, locations });
|
|
122
|
+
const items = this.allIn(locations);
|
|
123
|
+
|
|
124
|
+
return items.filter((item) => isQueryMatch(item, query));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public clone(): CacheMap<V, S, L1, L2, L3, L4, L5> {
|
|
128
|
+
const clone = new CacheMap<V, S, L1, L2, L3, L4, L5>(this.types, this.map);
|
|
129
|
+
return clone;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Item } from "@fjell/core";
|
|
2
|
+
import { PItemCache } from "./PItemCache";
|
|
3
|
+
import { CItemCache } from "./CItemCache";
|
|
4
|
+
|
|
5
|
+
import LibLogger from './logger';
|
|
6
|
+
|
|
7
|
+
const logger = LibLogger.get('CacheRegistry');
|
|
8
|
+
|
|
9
|
+
export class CacheRegistry {
|
|
10
|
+
|
|
11
|
+
private static instance: CacheRegistry;
|
|
12
|
+
private configured: boolean = false;
|
|
13
|
+
|
|
14
|
+
public constructor() {
|
|
15
|
+
logger.debug('CacheRegistry created');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public static getInstance(
|
|
19
|
+
): CacheRegistry {
|
|
20
|
+
if (!CacheRegistry.instance) {
|
|
21
|
+
CacheRegistry.instance = new CacheRegistry();
|
|
22
|
+
}
|
|
23
|
+
return CacheRegistry.instance;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// TODO: My use of Generics has Boxed me into a corner where I can't reference AbstractCache without the types
|
|
27
|
+
private cacheMap: { [kt: string]: any } = {};
|
|
28
|
+
|
|
29
|
+
public registerCache = <
|
|
30
|
+
S extends string,
|
|
31
|
+
L1 extends string = never,
|
|
32
|
+
L2 extends string = never,
|
|
33
|
+
L3 extends string = never,
|
|
34
|
+
L4 extends string = never,
|
|
35
|
+
L5 extends string = never
|
|
36
|
+
>(cache: PItemCache<Item<S>, S> |
|
|
37
|
+
CItemCache<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>): void => {
|
|
38
|
+
this.cacheMap[JSON.stringify(cache.getKeyTypes())] = cache;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
public isConfigured = (): boolean => {
|
|
42
|
+
return this.configured;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public markConfigured = (): void => {
|
|
46
|
+
this.configured = true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public getCache = (kts: string[]): any => {
|
|
50
|
+
if (!this.configured) {
|
|
51
|
+
logger.error('CacheRegistry must be configured before use');
|
|
52
|
+
throw new Error("CacheRegistry must be configured before use");
|
|
53
|
+
}
|
|
54
|
+
return this.cacheMap[JSON.stringify(kts)];
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* eslint-disable no-undefined, max-params */
|
|
2
|
+
|
|
3
|
+
import { ClientApi } from "@fjell/client-api";
|
|
4
|
+
import { Item, ItemQuery, PriKey, TypesProperties } from "@fjell/core";
|
|
5
|
+
import { AItemCache } from "./AItemCache";
|
|
6
|
+
import { CacheMap } from "./CacheMap";
|
|
7
|
+
import LibLogger from './logger';
|
|
8
|
+
|
|
9
|
+
const logger = LibLogger.get('PItemCache');
|
|
10
|
+
export class PItemCache<
|
|
11
|
+
V extends Item<S>,
|
|
12
|
+
S extends string
|
|
13
|
+
> extends AItemCache<V,S> {
|
|
14
|
+
|
|
15
|
+
public constructor(
|
|
16
|
+
cacheName: string,
|
|
17
|
+
api: ClientApi<V, S>,
|
|
18
|
+
pkType: S,
|
|
19
|
+
) {
|
|
20
|
+
super(cacheName, api, pkType);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public async all(
|
|
24
|
+
query: ItemQuery = {},
|
|
25
|
+
):
|
|
26
|
+
Promise<[CacheMap<V, S>, V[]]> {
|
|
27
|
+
logger.default('all', { query });
|
|
28
|
+
return await super.all(query) as [CacheMap<V, S>, V[]];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async one(
|
|
32
|
+
query: ItemQuery = {},
|
|
33
|
+
):
|
|
34
|
+
Promise<[CacheMap<V, S>, V | null]> {
|
|
35
|
+
logger.default('one', { query });
|
|
36
|
+
return await super.one(query) as [CacheMap<V, S>, V | null];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public async action(
|
|
40
|
+
key: PriKey<S>,
|
|
41
|
+
action: string,
|
|
42
|
+
body: any = {}
|
|
43
|
+
): Promise<[CacheMap<V, S>, V]> {
|
|
44
|
+
logger.default('action', { key, action, body });
|
|
45
|
+
return await super.action(key, action, body) as [CacheMap<V, S>, V];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public async allAction(
|
|
49
|
+
action: string,
|
|
50
|
+
body: any = {}
|
|
51
|
+
): Promise<[CacheMap<V, S>, V[]]> {
|
|
52
|
+
logger.default('action', { action, body });
|
|
53
|
+
return await super.allAction(action, body) as [CacheMap<V, S>, V[]];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public async create(
|
|
57
|
+
v: TypesProperties<V, S, never, never, never, never, never>,
|
|
58
|
+
): Promise<[CacheMap<V, S>, V]> {
|
|
59
|
+
logger.default('create', { v });
|
|
60
|
+
return await super.create(v) as [CacheMap<V, S>, V];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public async get(key: PriKey<S>,
|
|
64
|
+
): Promise<[CacheMap<V, S>, V | null]> {
|
|
65
|
+
logger.default('get', { key });
|
|
66
|
+
return await super.get(key) as [CacheMap<V, S>, V | null];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public async retrieve(
|
|
70
|
+
key: PriKey<S>,
|
|
71
|
+
): Promise<[CacheMap<V, S> | null, V | null]> {
|
|
72
|
+
logger.default('retrieve', { key });
|
|
73
|
+
return await super.retrieve(key) as [CacheMap<V, S> | null, V | null];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public async remove(
|
|
77
|
+
key: PriKey<S>
|
|
78
|
+
): Promise<CacheMap<V, S>> {
|
|
79
|
+
logger.default('remove', { key });
|
|
80
|
+
return await super.remove(key) as CacheMap<V, S>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public async update(
|
|
84
|
+
key: PriKey<S>,
|
|
85
|
+
v: TypesProperties<V, S>
|
|
86
|
+
): Promise<[CacheMap<V, S>, V]> {
|
|
87
|
+
logger.default('update', { key, v });
|
|
88
|
+
return await super.update(key, v) as [CacheMap<V, S>, V];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public async find(
|
|
92
|
+
finder: string,
|
|
93
|
+
finderParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,
|
|
94
|
+
): Promise<[CacheMap<V, S>, V[]]> {
|
|
95
|
+
logger.default('find', { finder, finderParams });
|
|
96
|
+
return await super.find(finder, finderParams) as [CacheMap<V, S>, V[]];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
export { Cache } from "./Cache";
|
|
3
|
+
export { CacheMap } from "./CacheMap";
|
|
4
|
+
export { CacheRegistry } from "./CacheRegistry";
|
|
5
|
+
|
|
6
|
+
export { AggregateConfig, AItemAggregator } from "./AItemAggregator";
|
|
7
|
+
|
|
8
|
+
export { AItemCache } from "./AItemCache";
|
|
9
|
+
export { CItemCache } from "./CItemCache";
|
|
10
|
+
export { PItemCache } from "./PItemCache";
|