@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.
@@ -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";
package/src/logger.ts ADDED
@@ -0,0 +1,5 @@
1
+ import Logging from '@fjell/logging';
2
+
3
+ const LibLogger = Logging.getLogger('@fjellproject/cache');
4
+
5
+ export default LibLogger;