@fjell/cache 4.7.0 → 4.7.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/CACHE_EVENTS.md +306 -0
- package/CACHE_IMPLEMENTATIONS.md +117 -0
- package/MEMORY_LEAK_FIXES.md +270 -0
- package/README.md +7 -0
- package/dist/Aggregator.d.ts +27 -16
- package/dist/Cache.d.ts +55 -0
- package/dist/CacheContext.d.ts +13 -5
- package/dist/CacheMap.d.ts +67 -24
- package/dist/CacheStats.d.ts +51 -0
- package/dist/Operations.d.ts +20 -17
- package/dist/Options.d.ts +1 -3
- package/dist/browser/AsyncIndexDBCacheMap.d.ts +19 -2
- package/dist/browser/IndexDBCacheMap.d.ts +49 -36
- package/dist/browser/LocalStorageCacheMap.d.ts +38 -22
- package/dist/browser/SessionStorageCacheMap.d.ts +35 -19
- package/dist/events/CacheEventEmitter.d.ts +83 -0
- package/dist/events/CacheEventFactory.d.ts +121 -0
- package/dist/events/CacheEventTypes.d.ts +122 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/eviction/EvictionManager.d.ts +57 -0
- package/dist/eviction/EvictionStrategy.d.ts +102 -10
- package/dist/eviction/index.d.ts +2 -1
- package/dist/eviction/strategies/ARCEvictionStrategy.d.ts +10 -5
- package/dist/eviction/strategies/FIFOEvictionStrategy.d.ts +6 -5
- package/dist/eviction/strategies/LFUEvictionStrategy.d.ts +6 -5
- package/dist/eviction/strategies/LRUEvictionStrategy.d.ts +6 -5
- package/dist/eviction/strategies/MRUEvictionStrategy.d.ts +6 -5
- package/dist/eviction/strategies/RandomEvictionStrategy.d.ts +6 -5
- package/dist/eviction/strategies/TwoQueueEvictionStrategy.d.ts +6 -5
- package/dist/index.d.ts +9 -3
- package/dist/index.js +4959 -2920
- package/dist/index.js.map +4 -4
- package/dist/memory/EnhancedMemoryCacheMap.d.ts +36 -30
- package/dist/memory/MemoryCacheMap.d.ts +34 -19
- package/dist/normalization.d.ts +1 -2
- package/dist/ops/get.d.ts +1 -0
- package/dist/ttl/TTLManager.d.ts +100 -0
- package/dist/ttl/index.d.ts +2 -0
- package/dist/utils/CacheSize.d.ts +0 -7
- package/fix-async-tests.js +116 -0
- package/package.json +19 -16
- package/debug_test2.js +0 -0
- package/debug_test3.js +0 -0
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
import { AllItemTypeArrays, ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
|
|
2
2
|
import { CacheMap } from "../CacheMap";
|
|
3
3
|
import { CacheSizeConfig } from "../Options";
|
|
4
|
+
import { CacheItemMetadata } from "../eviction";
|
|
4
5
|
/**
|
|
5
6
|
* Enhanced in-memory implementation of CacheMap with size limits and eviction policies.
|
|
6
7
|
* Supports byte-based and item-count limits with configurable eviction strategies.
|
|
7
8
|
*/
|
|
8
9
|
export declare class EnhancedMemoryCacheMap<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> extends CacheMap<V, S, L1, L2, L3, L4, L5> {
|
|
10
|
+
readonly implementationType = "memory/enhanced";
|
|
9
11
|
private map;
|
|
10
12
|
private normalizedHashFunction;
|
|
11
13
|
private queryResultCache;
|
|
12
|
-
private ttlOperationsInProgress;
|
|
13
14
|
private currentSizeBytes;
|
|
14
15
|
private currentItemCount;
|
|
15
16
|
private queryResultsCacheSize;
|
|
16
17
|
private readonly maxSizeBytes?;
|
|
17
18
|
private readonly maxItems?;
|
|
18
|
-
private readonly evictionStrategy;
|
|
19
19
|
constructor(types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>, sizeConfig?: CacheSizeConfig, initialData?: {
|
|
20
20
|
[key: string]: V;
|
|
21
21
|
});
|
|
22
|
-
get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): V | null
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
keys(): (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]
|
|
28
|
-
values(): V[]
|
|
29
|
-
clear(): void
|
|
30
|
-
allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): V[]
|
|
31
|
-
contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): boolean
|
|
32
|
-
queryIn(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): V[]
|
|
33
|
-
clone():
|
|
22
|
+
get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
|
|
23
|
+
set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, value: V): Promise<void>;
|
|
24
|
+
includesKey(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<boolean>;
|
|
25
|
+
delete(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<void>;
|
|
26
|
+
private deleteInternal;
|
|
27
|
+
keys(): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]>;
|
|
28
|
+
values(): Promise<V[]>;
|
|
29
|
+
clear(): Promise<void>;
|
|
30
|
+
allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
|
|
31
|
+
contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<boolean>;
|
|
32
|
+
queryIn(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
|
|
33
|
+
clone(): Promise<CacheMap<V, S, L1, L2, L3, L4, L5>>;
|
|
34
34
|
/**
|
|
35
35
|
* Get current cache statistics
|
|
36
36
|
*/
|
|
@@ -44,22 +44,15 @@ export declare class EnhancedMemoryCacheMap<V extends Item<S, L1, L2, L3, L4, L5
|
|
|
44
44
|
items?: number;
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
setQueryResult(queryHash: string, itemKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[], ttl?: number): void;
|
|
57
|
-
getQueryResult(queryHash: string): (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[] | null;
|
|
58
|
-
hasQueryResult(queryHash: string): boolean;
|
|
59
|
-
deleteQueryResult(queryHash: string): void;
|
|
60
|
-
clearQueryResults(): void;
|
|
61
|
-
invalidateItemKeys(keys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): void;
|
|
62
|
-
invalidateLocation(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): void;
|
|
47
|
+
setQueryResult(queryHash: string, itemKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): Promise<void>;
|
|
48
|
+
getQueryResult(queryHash: string): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[] | null>;
|
|
49
|
+
hasQueryResult(queryHash: string): Promise<boolean>;
|
|
50
|
+
deleteQueryResult(queryHash: string): Promise<void>;
|
|
51
|
+
clearQueryResults(): Promise<void>;
|
|
52
|
+
invalidateItemKeys(keys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): Promise<void>;
|
|
53
|
+
private filterQueriesReferencingKeys;
|
|
54
|
+
private invalidateQueriesReferencingKeys;
|
|
55
|
+
invalidateLocation(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<void>;
|
|
63
56
|
/**
|
|
64
57
|
* Add query result to size tracking
|
|
65
58
|
*/
|
|
@@ -72,4 +65,17 @@ export declare class EnhancedMemoryCacheMap<V extends Item<S, L1, L2, L3, L4, L5
|
|
|
72
65
|
* Get total cache size including query results
|
|
73
66
|
*/
|
|
74
67
|
getTotalSizeBytes(): number;
|
|
68
|
+
getMetadata(key: string): Promise<CacheItemMetadata | null>;
|
|
69
|
+
setMetadata(key: string, metadata: CacheItemMetadata): Promise<void>;
|
|
70
|
+
deleteMetadata(_key: string): Promise<void>;
|
|
71
|
+
getAllMetadata(): Promise<Map<string, CacheItemMetadata>>;
|
|
72
|
+
clearMetadata(): Promise<void>;
|
|
73
|
+
getCurrentSize(): Promise<{
|
|
74
|
+
itemCount: number;
|
|
75
|
+
sizeBytes: number;
|
|
76
|
+
}>;
|
|
77
|
+
getSizeLimits(): Promise<{
|
|
78
|
+
maxItems: number | null;
|
|
79
|
+
maxSizeBytes: number | null;
|
|
80
|
+
}>;
|
|
75
81
|
}
|
|
@@ -1,33 +1,48 @@
|
|
|
1
1
|
import { AllItemTypeArrays, ComKey, Item, ItemQuery, LocKeyArray, PriKey } from "@fjell/core";
|
|
2
2
|
import { CacheMap } from "../CacheMap";
|
|
3
|
+
import { CacheItemMetadata } from "../eviction/EvictionStrategy";
|
|
3
4
|
/**
|
|
4
5
|
* In-memory implementation of CacheMap using a plain object as the underlying storage.
|
|
5
6
|
* This implementation stores all data in memory and will be lost when the application restarts.
|
|
6
7
|
*/
|
|
7
8
|
export declare class MemoryCacheMap<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> extends CacheMap<V, S, L1, L2, L3, L4, L5> {
|
|
9
|
+
readonly implementationType = "memory/memory";
|
|
8
10
|
private map;
|
|
9
11
|
private normalizedHashFunction;
|
|
10
12
|
private queryResultCache;
|
|
13
|
+
private metadataMap;
|
|
11
14
|
constructor(types: AllItemTypeArrays<S, L1, L2, L3, L4, L5>, initialData?: {
|
|
12
15
|
[key: string]: V;
|
|
13
16
|
});
|
|
14
|
-
get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): V | null
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
get(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<V | null>;
|
|
18
|
+
set(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, value: V): Promise<void>;
|
|
19
|
+
includesKey(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<boolean>;
|
|
20
|
+
delete(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>): Promise<void>;
|
|
21
|
+
keys(): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]>;
|
|
22
|
+
values(): Promise<V[]>;
|
|
23
|
+
clear(): Promise<void>;
|
|
24
|
+
allIn(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
|
|
25
|
+
contains(query: ItemQuery, locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<boolean>;
|
|
26
|
+
queryIn(query: ItemQuery, locations?: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<V[]>;
|
|
27
|
+
clone(): Promise<MemoryCacheMap<V, S, L1, L2, L3, L4, L5>>;
|
|
28
|
+
setQueryResult(queryHash: string, itemKeys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): Promise<void>;
|
|
29
|
+
getQueryResult(queryHash: string): Promise<(ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[] | null>;
|
|
30
|
+
hasQueryResult(queryHash: string): Promise<boolean>;
|
|
31
|
+
deleteQueryResult(queryHash: string): Promise<void>;
|
|
32
|
+
invalidateItemKeys(keys: (ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>)[]): Promise<void>;
|
|
33
|
+
invalidateLocation(locations: LocKeyArray<L1, L2, L3, L4, L5> | []): Promise<void>;
|
|
34
|
+
clearQueryResults(): Promise<void>;
|
|
35
|
+
getMetadata(key: string): Promise<CacheItemMetadata | null>;
|
|
36
|
+
setMetadata(key: string, metadata: CacheItemMetadata): Promise<void>;
|
|
37
|
+
deleteMetadata(key: string): Promise<void>;
|
|
38
|
+
getAllMetadata(): Promise<Map<string, CacheItemMetadata>>;
|
|
39
|
+
clearMetadata(): Promise<void>;
|
|
40
|
+
getCurrentSize(): Promise<{
|
|
41
|
+
itemCount: number;
|
|
42
|
+
sizeBytes: number;
|
|
43
|
+
}>;
|
|
44
|
+
getSizeLimits(): Promise<{
|
|
45
|
+
maxItems: number | null;
|
|
46
|
+
maxSizeBytes: number | null;
|
|
47
|
+
}>;
|
|
33
48
|
}
|
package/dist/normalization.d.ts
CHANGED
|
@@ -4,11 +4,10 @@ export declare const createNormalizedHashFunction: <T>() => (key: T) => string;
|
|
|
4
4
|
export declare const isLocKeyArrayEqual: (a: any[], b: any[]) => boolean;
|
|
5
5
|
export declare const normalizeLocKeyItem: (item: any) => any;
|
|
6
6
|
/**
|
|
7
|
-
* Interface for storing query results
|
|
7
|
+
* Interface for storing query results
|
|
8
8
|
*/
|
|
9
9
|
export interface QueryCacheEntry {
|
|
10
10
|
itemKeys: (any)[];
|
|
11
|
-
expiresAt?: number;
|
|
12
11
|
}
|
|
13
12
|
/**
|
|
14
13
|
* Generate a safe hash for all/one query parameters
|
package/dist/ops/get.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { ComKey, Item, PriKey } from "@fjell/core";
|
|
2
2
|
import { CacheContext } from "../CacheContext";
|
|
3
|
+
export declare const cleanup: () => void;
|
|
3
4
|
export declare const get: <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>(key: ComKey<S, L1, L2, L3, L4, L5> | PriKey<S>, context: CacheContext<V, S, L1, L2, L3, L4, L5>) => Promise<[CacheContext<V, S, L1, L2, L3, L4, L5>, V | null]>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { CacheItemMetadata, CacheMapMetadataProvider } from '../eviction/EvictionStrategy';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for TTL behavior
|
|
4
|
+
*/
|
|
5
|
+
export interface TTLConfig {
|
|
6
|
+
/** Default TTL in milliseconds for all items */
|
|
7
|
+
defaultTTL?: number;
|
|
8
|
+
/** Whether to automatically clean up expired items */
|
|
9
|
+
autoCleanup?: boolean;
|
|
10
|
+
/** Interval for automatic cleanup in milliseconds */
|
|
11
|
+
cleanupInterval?: number;
|
|
12
|
+
/** Whether to validate TTL on access */
|
|
13
|
+
validateOnAccess?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* TTL-aware item wrapper that extends cache metadata
|
|
17
|
+
*/
|
|
18
|
+
export interface TTLItemMetadata extends CacheItemMetadata {
|
|
19
|
+
/** Expiration timestamp (addedAt + TTL) */
|
|
20
|
+
expiresAt?: number;
|
|
21
|
+
/** TTL value used for this specific item */
|
|
22
|
+
ttl?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Manages TTL (Time To Live) logic independently of CacheMap implementations.
|
|
26
|
+
* This allows any CacheMap to support TTL without implementing TTL-specific logic.
|
|
27
|
+
*/
|
|
28
|
+
export declare class TTLManager {
|
|
29
|
+
private config;
|
|
30
|
+
private cleanupTimer?;
|
|
31
|
+
constructor(config?: TTLConfig);
|
|
32
|
+
/**
|
|
33
|
+
* Check if TTL is enabled
|
|
34
|
+
*/
|
|
35
|
+
isTTLEnabled(): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Get the default TTL value
|
|
38
|
+
*/
|
|
39
|
+
getDefaultTTL(): number | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Update TTL configuration
|
|
42
|
+
*/
|
|
43
|
+
updateConfig(config: Partial<TTLConfig>): void;
|
|
44
|
+
/**
|
|
45
|
+
* Set TTL metadata for an item when it's added
|
|
46
|
+
*/
|
|
47
|
+
onItemAdded(key: string, metadataProvider: CacheMapMetadataProvider, itemTTL?: number): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Check if an item has expired
|
|
50
|
+
*/
|
|
51
|
+
isExpired(key: string, metadataProvider: CacheMapMetadataProvider): Promise<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Check if an item is valid (not expired) before returning it
|
|
54
|
+
* Returns true if item is valid, false if expired
|
|
55
|
+
*/
|
|
56
|
+
validateItem(key: string, metadataProvider: CacheMapMetadataProvider): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Get TTL information for an item
|
|
59
|
+
*/
|
|
60
|
+
getItemTTLInfo(key: string, metadataProvider: CacheMapMetadataProvider): Promise<{
|
|
61
|
+
hasTTL: boolean;
|
|
62
|
+
ttl?: number;
|
|
63
|
+
expiresAt?: number;
|
|
64
|
+
remainingTTL?: number;
|
|
65
|
+
isExpired: boolean;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Find all expired items
|
|
69
|
+
*/
|
|
70
|
+
findExpiredItems(metadataProvider: CacheMapMetadataProvider): Promise<string[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Manually clean up expired items
|
|
73
|
+
* Returns the keys of items that were expired
|
|
74
|
+
*/
|
|
75
|
+
cleanupExpiredItems(metadataProvider: CacheMapMetadataProvider): Promise<string[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Get remaining TTL for an item in milliseconds
|
|
78
|
+
*/
|
|
79
|
+
getRemainingTTL(key: string, metadataProvider: CacheMapMetadataProvider): Promise<number | null>;
|
|
80
|
+
/**
|
|
81
|
+
* Extend TTL for an item
|
|
82
|
+
*/
|
|
83
|
+
extendTTL(key: string, metadataProvider: CacheMapMetadataProvider, additionalTTL: number): Promise<boolean>;
|
|
84
|
+
/**
|
|
85
|
+
* Reset TTL for an item (refresh expiration)
|
|
86
|
+
*/
|
|
87
|
+
refreshTTL(key: string, metadataProvider: CacheMapMetadataProvider, newTTL?: number): Promise<boolean>;
|
|
88
|
+
/**
|
|
89
|
+
* Start automatic cleanup of expired items
|
|
90
|
+
*/
|
|
91
|
+
private startAutoCleanup;
|
|
92
|
+
/**
|
|
93
|
+
* Stop automatic cleanup
|
|
94
|
+
*/
|
|
95
|
+
private stopAutoCleanup;
|
|
96
|
+
/**
|
|
97
|
+
* Cleanup resources
|
|
98
|
+
*/
|
|
99
|
+
destroy(): void;
|
|
100
|
+
}
|
|
@@ -17,13 +17,6 @@ export declare function parseSizeString(sizeStr: string): number;
|
|
|
17
17
|
* @returns Formatted size string
|
|
18
18
|
*/
|
|
19
19
|
export declare function formatBytes(bytes: number, binary?: boolean): string;
|
|
20
|
-
/**
|
|
21
|
-
* Estimate the serialized size of a value in bytes
|
|
22
|
-
* This is an approximation for cache size calculations
|
|
23
|
-
*
|
|
24
|
-
* @param value - The value to estimate size for
|
|
25
|
-
* @returns Estimated size in bytes
|
|
26
|
-
*/
|
|
27
20
|
export declare function estimateValueSize(value: any): number;
|
|
28
21
|
/**
|
|
29
22
|
* Check if a size configuration is valid
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
// List of async methods that need await
|
|
5
|
+
const asyncMethods = [
|
|
6
|
+
'get',
|
|
7
|
+
'includesKey',
|
|
8
|
+
'values',
|
|
9
|
+
'allIn',
|
|
10
|
+
'contains',
|
|
11
|
+
'queryIn',
|
|
12
|
+
'clone',
|
|
13
|
+
'getQueryResult',
|
|
14
|
+
'invalidateLocation'
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
// Function to fix async calls in a file
|
|
18
|
+
function fixAsyncCalls(content) {
|
|
19
|
+
let updatedContent = content;
|
|
20
|
+
|
|
21
|
+
// First pass: Add await to all async method calls
|
|
22
|
+
asyncMethods.forEach(method => {
|
|
23
|
+
// Fix direct method calls that need await (but don't already have it)
|
|
24
|
+
// Match cache variable names (cache, locCache, containedCache, cacheMap, etc.) but avoid things like mockLocalStorage.store
|
|
25
|
+
const methodCallRegex = new RegExp(`(?<!await\\s)((cache|locCache|containedCache|cacheMap|cache1|cache2|complexCacheMap)\\s*\\.\\s*${method}\\s*\\([^)]*\\))`, 'g');
|
|
26
|
+
updatedContent = updatedContent.replace(methodCallRegex, (match, methodCall) => {
|
|
27
|
+
// Don't add await if it's already there
|
|
28
|
+
return `await ${methodCall}`;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Fix method calls in expect statements
|
|
32
|
+
const expectRegex = new RegExp(`expect\\((?!await\\s)((cache|locCache|containedCache|cacheMap|cache1|cache2|complexCacheMap)\\s*\\.\\s*${method}\\s*\\([^)]*\\))\\)`, 'g');
|
|
33
|
+
updatedContent = updatedContent.replace(expectRegex, 'expect(await $1)');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Second pass: Find all it() functions that contain await and make them async
|
|
37
|
+
const lines = updatedContent.split('\n');
|
|
38
|
+
const updatedLines = [];
|
|
39
|
+
let inTestFunction = false;
|
|
40
|
+
let testFunctionStart = -1;
|
|
41
|
+
let braceCount = 0;
|
|
42
|
+
let hasAwait = false;
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < lines.length; i++) {
|
|
45
|
+
const line = lines[i];
|
|
46
|
+
|
|
47
|
+
// Check if this line starts a test function
|
|
48
|
+
const testMatch = line.match(/(\s*)(it\s*\(\s*['"][^'"]*['"],\s*)(\(\)\s*=>\s*\{)/);
|
|
49
|
+
if (testMatch) {
|
|
50
|
+
inTestFunction = true;
|
|
51
|
+
testFunctionStart = i;
|
|
52
|
+
braceCount = 1;
|
|
53
|
+
hasAwait = false;
|
|
54
|
+
updatedLines.push(line);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (inTestFunction) {
|
|
59
|
+
// Count braces to track when we're out of the test function
|
|
60
|
+
const openBraces = (line.match(/\{/g) || []).length;
|
|
61
|
+
const closeBraces = (line.match(/\}/g) || []).length;
|
|
62
|
+
braceCount += openBraces - closeBraces;
|
|
63
|
+
|
|
64
|
+
// Check if this line contains await
|
|
65
|
+
if (line.includes('await ')) {
|
|
66
|
+
hasAwait = true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// If we've closed all braces, we're done with this test function
|
|
70
|
+
if (braceCount === 0) {
|
|
71
|
+
inTestFunction = false;
|
|
72
|
+
|
|
73
|
+
// If this test function contains await, make it async
|
|
74
|
+
if (hasAwait) {
|
|
75
|
+
const testLine = updatedLines[testFunctionStart];
|
|
76
|
+
const testMatch = testLine.match(/(\s*)(it\s*\(\s*['"][^'"]*['"],\s*)(\(\)\s*=>\s*\{)/);
|
|
77
|
+
if (testMatch && !testMatch[3].includes('async')) {
|
|
78
|
+
updatedLines[testFunctionStart] = testMatch[1] + testMatch[2] + 'async () => {';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
updatedLines.push(line);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return updatedLines.join('\n');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Process all browser cache test files
|
|
91
|
+
const testFiles = [
|
|
92
|
+
'/Users/tobrien/gitw/getfjell/fjell-cache/tests/browser/LocalStorageCacheMap.test.ts',
|
|
93
|
+
'/Users/tobrien/gitw/getfjell/fjell-cache/tests/browser/SessionStorageCacheMap.test.ts',
|
|
94
|
+
'/Users/tobrien/gitw/getfjell/fjell-cache/tests/browser/IndexDBCacheMap.test.ts',
|
|
95
|
+
'/Users/tobrien/gitw/getfjell/fjell-cache/tests/browser/AsyncIndexDBCacheMap.test.ts'
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
testFiles.forEach(testFile => {
|
|
99
|
+
try {
|
|
100
|
+
if (fs.existsSync(testFile)) {
|
|
101
|
+
const content = fs.readFileSync(testFile, 'utf8');
|
|
102
|
+
const fixedContent = fixAsyncCalls(content);
|
|
103
|
+
|
|
104
|
+
if (content !== fixedContent) {
|
|
105
|
+
fs.writeFileSync(testFile, fixedContent, 'utf8');
|
|
106
|
+
console.log(`Fixed async calls in ${path.basename(testFile)}`);
|
|
107
|
+
} else {
|
|
108
|
+
console.log(`No changes needed in ${path.basename(testFile)}`);
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
console.log(`File not found: ${testFile}`);
|
|
112
|
+
}
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.error(`Error fixing file ${path.basename(testFile)}: ${error.message}`);
|
|
115
|
+
}
|
|
116
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjell/cache",
|
|
3
3
|
"description": "Cache for Fjell",
|
|
4
|
-
"version": "4.7.
|
|
4
|
+
"version": "4.7.4",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cache",
|
|
7
7
|
"fjell"
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|
|
15
15
|
"types": "./dist/index.d.ts",
|
|
16
|
-
"import": "./dist/index.js"
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"default": "./dist/index.js"
|
|
17
18
|
}
|
|
18
19
|
},
|
|
19
20
|
"scripts": {
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
"typecheck": "tsc --noEmit",
|
|
23
24
|
"lint": "eslint . --ext .ts --fix",
|
|
24
25
|
"clean": "rm -rf dist",
|
|
25
|
-
"test": "
|
|
26
|
+
"test": "vitest run --coverage",
|
|
26
27
|
"prepublishOnly": "npm run clean && npm run build",
|
|
27
28
|
"docs:dev": "cd docs && npm run dev",
|
|
28
29
|
"docs:build": "cd docs && npm run build",
|
|
@@ -30,31 +31,33 @@
|
|
|
30
31
|
"docs:test": "cd docs && npm run test"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@fjell/client-api": "^4.4.
|
|
34
|
-
"@fjell/core": "^4.4.
|
|
35
|
-
"@fjell/http-api": "^4.4.
|
|
36
|
-
"@fjell/logging": "^4.4.
|
|
37
|
-
"@fjell/registry": "^4.4.
|
|
34
|
+
"@fjell/client-api": "^4.4.24",
|
|
35
|
+
"@fjell/core": "^4.4.34",
|
|
36
|
+
"@fjell/http-api": "^4.4.33",
|
|
37
|
+
"@fjell/logging": "^4.4.40",
|
|
38
|
+
"@fjell/registry": "^4.4.28",
|
|
39
|
+
"fast-safe-stringify": "^2.1.1",
|
|
40
|
+
"flatted": "^3.3.3"
|
|
38
41
|
},
|
|
39
42
|
"devDependencies": {
|
|
40
43
|
"@eslint/eslintrc": "^3.3.1",
|
|
41
|
-
"@eslint/js": "^9.
|
|
42
|
-
"@fjell/eslint-config": "^1.1.
|
|
43
|
-
"@swc/core": "^1.13.
|
|
44
|
+
"@eslint/js": "^9.33.0",
|
|
45
|
+
"@fjell/eslint-config": "^1.1.19",
|
|
46
|
+
"@swc/core": "^1.13.3",
|
|
44
47
|
"@tsconfig/recommended": "^1.0.10",
|
|
45
48
|
"@types/multer": "^2.0.0",
|
|
46
|
-
"@types/node": "^24.1
|
|
47
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
48
|
-
"@typescript-eslint/parser": "^8.
|
|
49
|
+
"@types/node": "^24.2.1",
|
|
50
|
+
"@typescript-eslint/eslint-plugin": "^8.39.0",
|
|
51
|
+
"@typescript-eslint/parser": "^8.39.0",
|
|
49
52
|
"@vitest/coverage-v8": "^3.2.4",
|
|
50
53
|
"@vitest/ui": "^3.2.4",
|
|
51
54
|
"concurrently": "^9.2.0",
|
|
52
55
|
"esbuild": "^0.25.8",
|
|
53
|
-
"eslint": "^9.
|
|
56
|
+
"eslint": "^9.33.0",
|
|
54
57
|
"nodemon": "^3.1.10",
|
|
55
58
|
"ts-node": "^10.9.2",
|
|
56
59
|
"tsc-alias": "^1.8.16",
|
|
57
|
-
"typescript": "^5.
|
|
60
|
+
"typescript": "^5.9.2",
|
|
58
61
|
"vitest": "^3.2.4"
|
|
59
62
|
},
|
|
60
63
|
"repository": {
|
package/debug_test2.js
DELETED
|
File without changes
|
package/debug_test3.js
DELETED
|
File without changes
|