gitx.do 0.1.0 → 0.1.2
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/README.md +40 -353
- package/dist/do/logger.d.ts +50 -0
- package/dist/do/logger.d.ts.map +1 -0
- package/dist/do/logger.js +122 -0
- package/dist/do/logger.js.map +1 -0
- package/dist/{durable-object → do}/schema.d.ts +3 -3
- package/dist/do/schema.d.ts.map +1 -0
- package/dist/{durable-object → do}/schema.js +4 -3
- package/dist/do/schema.js.map +1 -0
- package/dist/do/types.d.ts +267 -0
- package/dist/do/types.d.ts.map +1 -0
- package/dist/do/types.js +62 -0
- package/dist/do/types.js.map +1 -0
- package/dist/index.d.ts +15 -415
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -483
- package/dist/index.js.map +1 -1
- package/package.json +13 -21
- package/dist/cli/commands/add.d.ts +0 -174
- package/dist/cli/commands/add.d.ts.map +0 -1
- package/dist/cli/commands/add.js +0 -131
- package/dist/cli/commands/add.js.map +0 -1
- package/dist/cli/commands/blame.d.ts +0 -259
- package/dist/cli/commands/blame.d.ts.map +0 -1
- package/dist/cli/commands/blame.js +0 -609
- package/dist/cli/commands/blame.js.map +0 -1
- package/dist/cli/commands/branch.d.ts +0 -249
- package/dist/cli/commands/branch.d.ts.map +0 -1
- package/dist/cli/commands/branch.js +0 -693
- package/dist/cli/commands/branch.js.map +0 -1
- package/dist/cli/commands/commit.d.ts +0 -182
- package/dist/cli/commands/commit.d.ts.map +0 -1
- package/dist/cli/commands/commit.js +0 -437
- package/dist/cli/commands/commit.js.map +0 -1
- package/dist/cli/commands/diff.d.ts +0 -464
- package/dist/cli/commands/diff.d.ts.map +0 -1
- package/dist/cli/commands/diff.js +0 -958
- package/dist/cli/commands/diff.js.map +0 -1
- package/dist/cli/commands/log.d.ts +0 -239
- package/dist/cli/commands/log.d.ts.map +0 -1
- package/dist/cli/commands/log.js +0 -535
- package/dist/cli/commands/log.js.map +0 -1
- package/dist/cli/commands/merge.d.ts +0 -106
- package/dist/cli/commands/merge.d.ts.map +0 -1
- package/dist/cli/commands/merge.js +0 -55
- package/dist/cli/commands/merge.js.map +0 -1
- package/dist/cli/commands/review.d.ts +0 -457
- package/dist/cli/commands/review.d.ts.map +0 -1
- package/dist/cli/commands/review.js +0 -533
- package/dist/cli/commands/review.js.map +0 -1
- package/dist/cli/commands/status.d.ts +0 -269
- package/dist/cli/commands/status.d.ts.map +0 -1
- package/dist/cli/commands/status.js +0 -493
- package/dist/cli/commands/status.js.map +0 -1
- package/dist/cli/commands/web.d.ts +0 -199
- package/dist/cli/commands/web.d.ts.map +0 -1
- package/dist/cli/commands/web.js +0 -696
- package/dist/cli/commands/web.js.map +0 -1
- package/dist/cli/fs-adapter.d.ts +0 -656
- package/dist/cli/fs-adapter.d.ts.map +0 -1
- package/dist/cli/fs-adapter.js +0 -1179
- package/dist/cli/fs-adapter.js.map +0 -1
- package/dist/cli/fsx-cli-adapter.d.ts +0 -359
- package/dist/cli/fsx-cli-adapter.d.ts.map +0 -1
- package/dist/cli/fsx-cli-adapter.js +0 -619
- package/dist/cli/fsx-cli-adapter.js.map +0 -1
- package/dist/cli/index.d.ts +0 -387
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -523
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/ui/components/DiffView.d.ts +0 -7
- package/dist/cli/ui/components/DiffView.d.ts.map +0 -1
- package/dist/cli/ui/components/DiffView.js +0 -11
- package/dist/cli/ui/components/DiffView.js.map +0 -1
- package/dist/cli/ui/components/ErrorDisplay.d.ts +0 -6
- package/dist/cli/ui/components/ErrorDisplay.d.ts.map +0 -1
- package/dist/cli/ui/components/ErrorDisplay.js +0 -11
- package/dist/cli/ui/components/ErrorDisplay.js.map +0 -1
- package/dist/cli/ui/components/FuzzySearch.d.ts +0 -9
- package/dist/cli/ui/components/FuzzySearch.d.ts.map +0 -1
- package/dist/cli/ui/components/FuzzySearch.js +0 -12
- package/dist/cli/ui/components/FuzzySearch.js.map +0 -1
- package/dist/cli/ui/components/LoadingSpinner.d.ts +0 -6
- package/dist/cli/ui/components/LoadingSpinner.d.ts.map +0 -1
- package/dist/cli/ui/components/LoadingSpinner.js +0 -10
- package/dist/cli/ui/components/LoadingSpinner.js.map +0 -1
- package/dist/cli/ui/components/NavigationList.d.ts +0 -9
- package/dist/cli/ui/components/NavigationList.d.ts.map +0 -1
- package/dist/cli/ui/components/NavigationList.js +0 -11
- package/dist/cli/ui/components/NavigationList.js.map +0 -1
- package/dist/cli/ui/components/ScrollableContent.d.ts +0 -8
- package/dist/cli/ui/components/ScrollableContent.d.ts.map +0 -1
- package/dist/cli/ui/components/ScrollableContent.js +0 -11
- package/dist/cli/ui/components/ScrollableContent.js.map +0 -1
- package/dist/cli/ui/components/index.d.ts +0 -7
- package/dist/cli/ui/components/index.d.ts.map +0 -1
- package/dist/cli/ui/components/index.js +0 -9
- package/dist/cli/ui/components/index.js.map +0 -1
- package/dist/cli/ui/terminal-ui.d.ts +0 -52
- package/dist/cli/ui/terminal-ui.d.ts.map +0 -1
- package/dist/cli/ui/terminal-ui.js +0 -121
- package/dist/cli/ui/terminal-ui.js.map +0 -1
- package/dist/do/BashModule.d.ts +0 -871
- package/dist/do/BashModule.d.ts.map +0 -1
- package/dist/do/BashModule.js +0 -1143
- package/dist/do/BashModule.js.map +0 -1
- package/dist/do/FsModule.d.ts +0 -601
- package/dist/do/FsModule.d.ts.map +0 -1
- package/dist/do/FsModule.js +0 -1120
- package/dist/do/FsModule.js.map +0 -1
- package/dist/do/GitModule.d.ts +0 -635
- package/dist/do/GitModule.d.ts.map +0 -1
- package/dist/do/GitModule.js +0 -781
- package/dist/do/GitModule.js.map +0 -1
- package/dist/do/GitRepoDO.d.ts +0 -281
- package/dist/do/GitRepoDO.d.ts.map +0 -1
- package/dist/do/GitRepoDO.js +0 -479
- package/dist/do/GitRepoDO.js.map +0 -1
- package/dist/do/bash-ast.d.ts +0 -246
- package/dist/do/bash-ast.d.ts.map +0 -1
- package/dist/do/bash-ast.js +0 -888
- package/dist/do/bash-ast.js.map +0 -1
- package/dist/do/container-executor.d.ts +0 -491
- package/dist/do/container-executor.d.ts.map +0 -1
- package/dist/do/container-executor.js +0 -730
- package/dist/do/container-executor.js.map +0 -1
- package/dist/do/index.d.ts +0 -53
- package/dist/do/index.d.ts.map +0 -1
- package/dist/do/index.js +0 -91
- package/dist/do/index.js.map +0 -1
- package/dist/do/tiered-storage.d.ts +0 -403
- package/dist/do/tiered-storage.d.ts.map +0 -1
- package/dist/do/tiered-storage.js +0 -689
- package/dist/do/tiered-storage.js.map +0 -1
- package/dist/do/withBash.d.ts +0 -231
- package/dist/do/withBash.d.ts.map +0 -1
- package/dist/do/withBash.js +0 -244
- package/dist/do/withBash.js.map +0 -1
- package/dist/do/withFs.d.ts +0 -237
- package/dist/do/withFs.d.ts.map +0 -1
- package/dist/do/withFs.js +0 -387
- package/dist/do/withFs.js.map +0 -1
- package/dist/do/withGit.d.ts +0 -180
- package/dist/do/withGit.d.ts.map +0 -1
- package/dist/do/withGit.js +0 -271
- package/dist/do/withGit.js.map +0 -1
- package/dist/durable-object/object-store.d.ts +0 -633
- package/dist/durable-object/object-store.d.ts.map +0 -1
- package/dist/durable-object/object-store.js +0 -1161
- package/dist/durable-object/object-store.js.map +0 -1
- package/dist/durable-object/schema.d.ts.map +0 -1
- package/dist/durable-object/schema.js.map +0 -1
- package/dist/durable-object/wal.d.ts +0 -416
- package/dist/durable-object/wal.d.ts.map +0 -1
- package/dist/durable-object/wal.js +0 -445
- package/dist/durable-object/wal.js.map +0 -1
- package/dist/mcp/adapter.d.ts +0 -772
- package/dist/mcp/adapter.d.ts.map +0 -1
- package/dist/mcp/adapter.js +0 -895
- package/dist/mcp/adapter.js.map +0 -1
- package/dist/mcp/sandbox/miniflare-evaluator.d.ts +0 -22
- package/dist/mcp/sandbox/miniflare-evaluator.d.ts.map +0 -1
- package/dist/mcp/sandbox/miniflare-evaluator.js +0 -140
- package/dist/mcp/sandbox/miniflare-evaluator.js.map +0 -1
- package/dist/mcp/sandbox/object-store-proxy.d.ts +0 -32
- package/dist/mcp/sandbox/object-store-proxy.d.ts.map +0 -1
- package/dist/mcp/sandbox/object-store-proxy.js +0 -30
- package/dist/mcp/sandbox/object-store-proxy.js.map +0 -1
- package/dist/mcp/sandbox/template.d.ts +0 -17
- package/dist/mcp/sandbox/template.d.ts.map +0 -1
- package/dist/mcp/sandbox/template.js +0 -71
- package/dist/mcp/sandbox/template.js.map +0 -1
- package/dist/mcp/sandbox.d.ts +0 -764
- package/dist/mcp/sandbox.d.ts.map +0 -1
- package/dist/mcp/sandbox.js +0 -1362
- package/dist/mcp/sandbox.js.map +0 -1
- package/dist/mcp/sdk-adapter.d.ts +0 -835
- package/dist/mcp/sdk-adapter.d.ts.map +0 -1
- package/dist/mcp/sdk-adapter.js +0 -974
- package/dist/mcp/sdk-adapter.js.map +0 -1
- package/dist/mcp/tools/do.d.ts +0 -32
- package/dist/mcp/tools/do.d.ts.map +0 -1
- package/dist/mcp/tools/do.js +0 -115
- package/dist/mcp/tools/do.js.map +0 -1
- package/dist/mcp/tools.d.ts +0 -548
- package/dist/mcp/tools.d.ts.map +0 -1
- package/dist/mcp/tools.js +0 -1934
- package/dist/mcp/tools.js.map +0 -1
- package/dist/ops/blame.d.ts +0 -551
- package/dist/ops/blame.d.ts.map +0 -1
- package/dist/ops/blame.js +0 -1037
- package/dist/ops/blame.js.map +0 -1
- package/dist/ops/branch.d.ts +0 -766
- package/dist/ops/branch.d.ts.map +0 -1
- package/dist/ops/branch.js +0 -950
- package/dist/ops/branch.js.map +0 -1
- package/dist/ops/commit-traversal.d.ts +0 -349
- package/dist/ops/commit-traversal.d.ts.map +0 -1
- package/dist/ops/commit-traversal.js +0 -821
- package/dist/ops/commit-traversal.js.map +0 -1
- package/dist/ops/commit.d.ts +0 -555
- package/dist/ops/commit.d.ts.map +0 -1
- package/dist/ops/commit.js +0 -826
- package/dist/ops/commit.js.map +0 -1
- package/dist/ops/merge-base.d.ts +0 -397
- package/dist/ops/merge-base.d.ts.map +0 -1
- package/dist/ops/merge-base.js +0 -691
- package/dist/ops/merge-base.js.map +0 -1
- package/dist/ops/merge.d.ts +0 -855
- package/dist/ops/merge.d.ts.map +0 -1
- package/dist/ops/merge.js +0 -1551
- package/dist/ops/merge.js.map +0 -1
- package/dist/ops/tag.d.ts +0 -247
- package/dist/ops/tag.d.ts.map +0 -1
- package/dist/ops/tag.js +0 -649
- package/dist/ops/tag.js.map +0 -1
- package/dist/ops/tree-builder.d.ts +0 -178
- package/dist/ops/tree-builder.d.ts.map +0 -1
- package/dist/ops/tree-builder.js +0 -271
- package/dist/ops/tree-builder.js.map +0 -1
- package/dist/ops/tree-diff.d.ts +0 -291
- package/dist/ops/tree-diff.d.ts.map +0 -1
- package/dist/ops/tree-diff.js +0 -705
- package/dist/ops/tree-diff.js.map +0 -1
- package/dist/pack/delta.d.ts +0 -248
- package/dist/pack/delta.d.ts.map +0 -1
- package/dist/pack/delta.js +0 -736
- package/dist/pack/delta.js.map +0 -1
- package/dist/pack/format.d.ts +0 -446
- package/dist/pack/format.d.ts.map +0 -1
- package/dist/pack/format.js +0 -572
- package/dist/pack/format.js.map +0 -1
- package/dist/pack/full-generation.d.ts +0 -612
- package/dist/pack/full-generation.d.ts.map +0 -1
- package/dist/pack/full-generation.js +0 -1378
- package/dist/pack/full-generation.js.map +0 -1
- package/dist/pack/generation.d.ts +0 -441
- package/dist/pack/generation.d.ts.map +0 -1
- package/dist/pack/generation.js +0 -707
- package/dist/pack/generation.js.map +0 -1
- package/dist/pack/index.d.ts +0 -502
- package/dist/pack/index.d.ts.map +0 -1
- package/dist/pack/index.js +0 -833
- package/dist/pack/index.js.map +0 -1
- package/dist/refs/branch.d.ts +0 -668
- package/dist/refs/branch.d.ts.map +0 -1
- package/dist/refs/branch.js +0 -897
- package/dist/refs/branch.js.map +0 -1
- package/dist/refs/storage.d.ts +0 -833
- package/dist/refs/storage.d.ts.map +0 -1
- package/dist/refs/storage.js +0 -1023
- package/dist/refs/storage.js.map +0 -1
- package/dist/refs/tag.d.ts +0 -860
- package/dist/refs/tag.d.ts.map +0 -1
- package/dist/refs/tag.js +0 -996
- package/dist/refs/tag.js.map +0 -1
- package/dist/storage/backend.d.ts +0 -425
- package/dist/storage/backend.d.ts.map +0 -1
- package/dist/storage/backend.js +0 -41
- package/dist/storage/backend.js.map +0 -1
- package/dist/storage/fsx-adapter.d.ts +0 -204
- package/dist/storage/fsx-adapter.d.ts.map +0 -1
- package/dist/storage/fsx-adapter.js +0 -470
- package/dist/storage/fsx-adapter.js.map +0 -1
- package/dist/storage/lru-cache.d.ts +0 -691
- package/dist/storage/lru-cache.d.ts.map +0 -1
- package/dist/storage/lru-cache.js +0 -813
- package/dist/storage/lru-cache.js.map +0 -1
- package/dist/storage/object-index.d.ts +0 -585
- package/dist/storage/object-index.d.ts.map +0 -1
- package/dist/storage/object-index.js +0 -532
- package/dist/storage/object-index.js.map +0 -1
- package/dist/storage/r2-pack.d.ts +0 -1257
- package/dist/storage/r2-pack.d.ts.map +0 -1
- package/dist/storage/r2-pack.js +0 -1770
- package/dist/storage/r2-pack.js.map +0 -1
- package/dist/tiered/cdc-pipeline.d.ts +0 -1888
- package/dist/tiered/cdc-pipeline.d.ts.map +0 -1
- package/dist/tiered/cdc-pipeline.js +0 -1880
- package/dist/tiered/cdc-pipeline.js.map +0 -1
- package/dist/tiered/migration.d.ts +0 -1104
- package/dist/tiered/migration.d.ts.map +0 -1
- package/dist/tiered/migration.js +0 -1214
- package/dist/tiered/migration.js.map +0 -1
- package/dist/tiered/parquet-writer.d.ts +0 -1145
- package/dist/tiered/parquet-writer.d.ts.map +0 -1
- package/dist/tiered/parquet-writer.js +0 -1183
- package/dist/tiered/parquet-writer.js.map +0 -1
- package/dist/tiered/read-path.d.ts +0 -835
- package/dist/tiered/read-path.d.ts.map +0 -1
- package/dist/tiered/read-path.js +0 -487
- package/dist/tiered/read-path.js.map +0 -1
- package/dist/types/capability.d.ts +0 -1385
- package/dist/types/capability.d.ts.map +0 -1
- package/dist/types/capability.js +0 -36
- package/dist/types/capability.js.map +0 -1
- package/dist/types/index.d.ts +0 -13
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -18
- package/dist/types/index.js.map +0 -1
- package/dist/types/objects.d.ts +0 -692
- package/dist/types/objects.d.ts.map +0 -1
- package/dist/types/objects.js +0 -837
- package/dist/types/objects.js.map +0 -1
- package/dist/types/storage.d.ts +0 -603
- package/dist/types/storage.d.ts.map +0 -1
- package/dist/types/storage.js +0 -191
- package/dist/types/storage.js.map +0 -1
- package/dist/types/worker-loader.d.ts +0 -60
- package/dist/types/worker-loader.d.ts.map +0 -1
- package/dist/types/worker-loader.js +0 -62
- package/dist/types/worker-loader.js.map +0 -1
- package/dist/utils/hash.d.ts +0 -197
- package/dist/utils/hash.d.ts.map +0 -1
- package/dist/utils/hash.js +0 -268
- package/dist/utils/hash.js.map +0 -1
- package/dist/utils/sha1.d.ts +0 -290
- package/dist/utils/sha1.d.ts.map +0 -1
- package/dist/utils/sha1.js +0 -582
- package/dist/utils/sha1.js.map +0 -1
- package/dist/wire/capabilities.d.ts +0 -1044
- package/dist/wire/capabilities.d.ts.map +0 -1
- package/dist/wire/capabilities.js +0 -941
- package/dist/wire/capabilities.js.map +0 -1
- package/dist/wire/path-security.d.ts +0 -157
- package/dist/wire/path-security.d.ts.map +0 -1
- package/dist/wire/path-security.js +0 -307
- package/dist/wire/path-security.js.map +0 -1
- package/dist/wire/pkt-line.d.ts +0 -345
- package/dist/wire/pkt-line.d.ts.map +0 -1
- package/dist/wire/pkt-line.js +0 -381
- package/dist/wire/pkt-line.js.map +0 -1
- package/dist/wire/receive-pack.d.ts +0 -1059
- package/dist/wire/receive-pack.d.ts.map +0 -1
- package/dist/wire/receive-pack.js +0 -1414
- package/dist/wire/receive-pack.js.map +0 -1
- package/dist/wire/smart-http.d.ts +0 -799
- package/dist/wire/smart-http.d.ts.map +0 -1
- package/dist/wire/smart-http.js +0 -945
- package/dist/wire/smart-http.js.map +0 -1
- package/dist/wire/upload-pack.d.ts +0 -727
- package/dist/wire/upload-pack.d.ts.map +0 -1
- package/dist/wire/upload-pack.js +0 -1138
- package/dist/wire/upload-pack.js.map +0 -1
|
@@ -1,813 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview LRU Cache Implementation for Hot Objects
|
|
3
|
-
*
|
|
4
|
-
* This module provides a high-performance Least Recently Used (LRU) cache
|
|
5
|
-
* implementation optimized for storing frequently accessed Git objects.
|
|
6
|
-
*
|
|
7
|
-
* ## Features
|
|
8
|
-
*
|
|
9
|
-
* - **Dual Limits**: Supports both count-based and byte-size-based limits
|
|
10
|
-
* - **TTL Support**: Optional time-to-live for automatic entry expiration
|
|
11
|
-
* - **Eviction Callbacks**: Hook into eviction events for cleanup or analytics
|
|
12
|
-
* - **Statistics Tracking**: Built-in hit/miss tracking and hit rate calculation
|
|
13
|
-
* - **O(1) Operations**: All get/set/delete operations are O(1) using a doubly linked list
|
|
14
|
-
*
|
|
15
|
-
* ## Implementation Details
|
|
16
|
-
*
|
|
17
|
-
* The cache uses a combination of:
|
|
18
|
-
* - A Map for O(1) key lookup
|
|
19
|
-
* - A doubly linked list for O(1) LRU ordering
|
|
20
|
-
*
|
|
21
|
-
* When the cache exceeds its limits, the least recently used items are evicted.
|
|
22
|
-
* Items can also be evicted due to TTL expiration.
|
|
23
|
-
*
|
|
24
|
-
* @module storage/lru-cache
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```typescript
|
|
28
|
-
* // Create a cache with 100 items max and 10MB size limit
|
|
29
|
-
* const cache = new LRUCache<string, Uint8Array>({
|
|
30
|
-
* maxCount: 100,
|
|
31
|
-
* maxBytes: 10 * 1024 * 1024,
|
|
32
|
-
* defaultTTL: 3600000, // 1 hour
|
|
33
|
-
* onEvict: (key, value, reason) => {
|
|
34
|
-
* console.log(`Evicted ${key}: ${reason}`);
|
|
35
|
-
* }
|
|
36
|
-
* });
|
|
37
|
-
*
|
|
38
|
-
* // Store and retrieve values
|
|
39
|
-
* cache.set('object-sha', objectData);
|
|
40
|
-
* const data = cache.get('object-sha');
|
|
41
|
-
*
|
|
42
|
-
* // Check statistics
|
|
43
|
-
* const stats = cache.getStats();
|
|
44
|
-
* console.log(`Hit rate: ${stats.hitRate}%`);
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
/**
|
|
48
|
-
* LRU Cache class for storing hot objects with size and count limits.
|
|
49
|
-
*
|
|
50
|
-
* @description
|
|
51
|
-
* A high-performance Least Recently Used cache with the following features:
|
|
52
|
-
*
|
|
53
|
-
* - **O(1) Operations**: Get, set, and delete are all constant time
|
|
54
|
-
* - **Dual Limits**: Supports both count and byte-size limits
|
|
55
|
-
* - **TTL Support**: Optional per-entry or default time-to-live
|
|
56
|
-
* - **Eviction Events**: Callbacks when items are removed
|
|
57
|
-
* - **Statistics**: Track hits, misses, and evictions
|
|
58
|
-
*
|
|
59
|
-
* The cache maintains items in order of recent use. When the cache is full,
|
|
60
|
-
* the least recently used items are evicted first.
|
|
61
|
-
*
|
|
62
|
-
* ## Type Parameters
|
|
63
|
-
*
|
|
64
|
-
* - `K`: The type of cache keys (default: string)
|
|
65
|
-
* - `V`: The type of cached values (default: unknown)
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```typescript
|
|
69
|
-
* // Basic usage with string keys and Uint8Array values
|
|
70
|
-
* const objectCache = new LRUCache<string, Uint8Array>({
|
|
71
|
-
* maxCount: 1000,
|
|
72
|
-
* maxBytes: 100 * 1024 * 1024 // 100MB
|
|
73
|
-
* });
|
|
74
|
-
*
|
|
75
|
-
* // Store a value
|
|
76
|
-
* objectCache.set(sha, objectData);
|
|
77
|
-
*
|
|
78
|
-
* // Retrieve a value (returns undefined if not found or expired)
|
|
79
|
-
* const data = objectCache.get(sha);
|
|
80
|
-
*
|
|
81
|
-
* // Check without affecting LRU order
|
|
82
|
-
* if (objectCache.has(sha)) {
|
|
83
|
-
* const peeked = objectCache.peek(sha);
|
|
84
|
-
* }
|
|
85
|
-
*
|
|
86
|
-
* // Remove expired entries
|
|
87
|
-
* const pruned = objectCache.prune();
|
|
88
|
-
* console.log(`Removed ${pruned} expired entries`);
|
|
89
|
-
* ```
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```typescript
|
|
93
|
-
* // With eviction callback for cleanup
|
|
94
|
-
* const cache = new LRUCache<string, Resource>({
|
|
95
|
-
* maxCount: 100,
|
|
96
|
-
* onEvict: (key, value, reason) => {
|
|
97
|
-
* if (reason !== 'clear') {
|
|
98
|
-
* value.dispose(); // Clean up resources
|
|
99
|
-
* }
|
|
100
|
-
* console.log(`Evicted ${key}: ${reason}`);
|
|
101
|
-
* }
|
|
102
|
-
* });
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
export class LRUCache {
|
|
106
|
-
cache = new Map();
|
|
107
|
-
head = null; // Most recently used
|
|
108
|
-
tail = null; // Least recently used
|
|
109
|
-
_bytes = 0;
|
|
110
|
-
_hits = 0;
|
|
111
|
-
_misses = 0;
|
|
112
|
-
_evictions = 0;
|
|
113
|
-
maxCount;
|
|
114
|
-
maxBytes;
|
|
115
|
-
defaultTTL;
|
|
116
|
-
sizeCalculator;
|
|
117
|
-
onEvict;
|
|
118
|
-
/**
|
|
119
|
-
* Creates a new LRU cache instance.
|
|
120
|
-
*
|
|
121
|
-
* @description
|
|
122
|
-
* Initializes the cache with the specified options. All options have
|
|
123
|
-
* sensible defaults for unlimited caching.
|
|
124
|
-
*
|
|
125
|
-
* @param options - Configuration options for the cache
|
|
126
|
-
*
|
|
127
|
-
* @example
|
|
128
|
-
* ```typescript
|
|
129
|
-
* // Simple cache with count limit
|
|
130
|
-
* const cache = new LRUCache({ maxCount: 100 });
|
|
131
|
-
*
|
|
132
|
-
* // Cache with size limit and TTL
|
|
133
|
-
* const cache = new LRUCache({
|
|
134
|
-
* maxBytes: 50 * 1024 * 1024, // 50MB
|
|
135
|
-
* defaultTTL: 3600000 // 1 hour
|
|
136
|
-
* });
|
|
137
|
-
*
|
|
138
|
-
* // Cache with custom size calculator for Uint8Array
|
|
139
|
-
* const binaryCache = new LRUCache<string, Uint8Array>({
|
|
140
|
-
* maxBytes: 100 * 1024 * 1024,
|
|
141
|
-
* sizeCalculator: (arr) => arr.byteLength
|
|
142
|
-
* });
|
|
143
|
-
* ```
|
|
144
|
-
*/
|
|
145
|
-
constructor(options) {
|
|
146
|
-
this.maxCount = options?.maxCount ?? Infinity;
|
|
147
|
-
this.maxBytes = options?.maxBytes ?? Infinity;
|
|
148
|
-
this.defaultTTL = options?.defaultTTL;
|
|
149
|
-
this.sizeCalculator = options?.sizeCalculator ?? defaultSizeCalculator;
|
|
150
|
-
this.onEvict = options?.onEvict;
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Checks if an entry is expired.
|
|
154
|
-
*
|
|
155
|
-
* @param entry - The cache entry to check
|
|
156
|
-
* @returns true if the entry has expired
|
|
157
|
-
*
|
|
158
|
-
* @internal
|
|
159
|
-
*/
|
|
160
|
-
isExpired(entry) {
|
|
161
|
-
if (entry.expiresAt === null)
|
|
162
|
-
return false;
|
|
163
|
-
return Date.now() > entry.expiresAt;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Moves a node to the head (most recently used position).
|
|
167
|
-
*
|
|
168
|
-
* @param node - The node to move
|
|
169
|
-
*
|
|
170
|
-
* @internal
|
|
171
|
-
*/
|
|
172
|
-
moveToHead(node) {
|
|
173
|
-
if (node === this.head)
|
|
174
|
-
return;
|
|
175
|
-
// Remove from current position
|
|
176
|
-
this.removeNode(node);
|
|
177
|
-
// Add to head
|
|
178
|
-
node.prev = null;
|
|
179
|
-
node.next = this.head;
|
|
180
|
-
if (this.head) {
|
|
181
|
-
this.head.prev = node;
|
|
182
|
-
}
|
|
183
|
-
this.head = node;
|
|
184
|
-
if (!this.tail) {
|
|
185
|
-
this.tail = node;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Removes a node from the linked list.
|
|
190
|
-
*
|
|
191
|
-
* @param node - The node to remove
|
|
192
|
-
*
|
|
193
|
-
* @internal
|
|
194
|
-
*/
|
|
195
|
-
removeNode(node) {
|
|
196
|
-
if (node.prev) {
|
|
197
|
-
node.prev.next = node.next;
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
this.head = node.next;
|
|
201
|
-
}
|
|
202
|
-
if (node.next) {
|
|
203
|
-
node.next.prev = node.prev;
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
this.tail = node.prev;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Adds a node to the head of the list.
|
|
211
|
-
*
|
|
212
|
-
* @param node - The node to add
|
|
213
|
-
*
|
|
214
|
-
* @internal
|
|
215
|
-
*/
|
|
216
|
-
addToHead(node) {
|
|
217
|
-
node.prev = null;
|
|
218
|
-
node.next = this.head;
|
|
219
|
-
if (this.head) {
|
|
220
|
-
this.head.prev = node;
|
|
221
|
-
}
|
|
222
|
-
this.head = node;
|
|
223
|
-
if (!this.tail) {
|
|
224
|
-
this.tail = node;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Evicts items until the cache can accommodate a new item.
|
|
229
|
-
*
|
|
230
|
-
* @param requiredSize - Size in bytes needed for the new item
|
|
231
|
-
*
|
|
232
|
-
* @internal
|
|
233
|
-
*/
|
|
234
|
-
evictToFit(requiredSize) {
|
|
235
|
-
// Evict until we have room for the new item
|
|
236
|
-
while (this.tail && ((this.maxCount !== Infinity && this.cache.size >= this.maxCount) ||
|
|
237
|
-
(this.maxBytes !== Infinity && this._bytes + requiredSize > this.maxBytes))) {
|
|
238
|
-
const lru = this.tail;
|
|
239
|
-
this.removeNode(lru);
|
|
240
|
-
this.cache.delete(lru.key);
|
|
241
|
-
this._bytes -= lru.entry.size;
|
|
242
|
-
this._evictions++;
|
|
243
|
-
if (this.onEvict) {
|
|
244
|
-
this.onEvict(lru.key, lru.entry.value, 'lru');
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Gets a value from the cache.
|
|
250
|
-
*
|
|
251
|
-
* @description
|
|
252
|
-
* Retrieves a value by key. If the key exists and hasn't expired,
|
|
253
|
-
* returns the value and moves the entry to the most recently used position.
|
|
254
|
-
* If the key doesn't exist or has expired, returns undefined.
|
|
255
|
-
*
|
|
256
|
-
* @param key - The cache key to look up
|
|
257
|
-
*
|
|
258
|
-
* @returns The cached value or undefined if not found/expired
|
|
259
|
-
*
|
|
260
|
-
* @example
|
|
261
|
-
* ```typescript
|
|
262
|
-
* const cache = new LRUCache<string, string>();
|
|
263
|
-
* cache.set('greeting', 'hello');
|
|
264
|
-
*
|
|
265
|
-
* const value = cache.get('greeting'); // 'hello'
|
|
266
|
-
* const missing = cache.get('nonexistent'); // undefined
|
|
267
|
-
* ```
|
|
268
|
-
*/
|
|
269
|
-
get(key) {
|
|
270
|
-
const node = this.cache.get(key);
|
|
271
|
-
if (!node) {
|
|
272
|
-
this._misses++;
|
|
273
|
-
return undefined;
|
|
274
|
-
}
|
|
275
|
-
if (this.isExpired(node.entry)) {
|
|
276
|
-
// Remove expired entry
|
|
277
|
-
this.removeNode(node);
|
|
278
|
-
this.cache.delete(key);
|
|
279
|
-
this._bytes -= node.entry.size;
|
|
280
|
-
this._misses++;
|
|
281
|
-
if (this.onEvict) {
|
|
282
|
-
this.onEvict(key, node.entry.value, 'ttl');
|
|
283
|
-
}
|
|
284
|
-
return undefined;
|
|
285
|
-
}
|
|
286
|
-
// Update access time and move to head
|
|
287
|
-
node.entry.lastAccessed = Date.now();
|
|
288
|
-
this.moveToHead(node);
|
|
289
|
-
this._hits++;
|
|
290
|
-
return node.entry.value;
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Sets a value in the cache.
|
|
294
|
-
*
|
|
295
|
-
* @description
|
|
296
|
-
* Stores a value with the given key. If the key already exists,
|
|
297
|
-
* updates the value. If storing the value would exceed limits,
|
|
298
|
-
* evicts least recently used items first.
|
|
299
|
-
*
|
|
300
|
-
* Returns false if the value is larger than maxBytes (cannot fit).
|
|
301
|
-
*
|
|
302
|
-
* @param key - The cache key
|
|
303
|
-
* @param value - The value to cache
|
|
304
|
-
* @param options - Optional per-entry settings (TTL, size)
|
|
305
|
-
*
|
|
306
|
-
* @returns true if successfully stored, false if value too large
|
|
307
|
-
*
|
|
308
|
-
* @example
|
|
309
|
-
* ```typescript
|
|
310
|
-
* const cache = new LRUCache<string, Uint8Array>({
|
|
311
|
-
* maxBytes: 1024
|
|
312
|
-
* });
|
|
313
|
-
*
|
|
314
|
-
* // Basic set
|
|
315
|
-
* cache.set('key1', new Uint8Array([1, 2, 3]));
|
|
316
|
-
*
|
|
317
|
-
* // Set with custom TTL
|
|
318
|
-
* cache.set('key2', data, { ttl: 60000 }); // 1 minute
|
|
319
|
-
*
|
|
320
|
-
* // Set with explicit size
|
|
321
|
-
* cache.set('key3', complexObject, { size: 1000 });
|
|
322
|
-
*
|
|
323
|
-
* // Returns false if value too large
|
|
324
|
-
* const hugeData = new Uint8Array(10000);
|
|
325
|
-
* cache.set('huge', hugeData); // returns false
|
|
326
|
-
* ```
|
|
327
|
-
*/
|
|
328
|
-
set(key, value, options) {
|
|
329
|
-
const size = options?.size ?? this.sizeCalculator(value);
|
|
330
|
-
// Reject items larger than maxBytes
|
|
331
|
-
if (this.maxBytes !== Infinity && size > this.maxBytes) {
|
|
332
|
-
return false;
|
|
333
|
-
}
|
|
334
|
-
const now = Date.now();
|
|
335
|
-
const ttl = options?.ttl ?? this.defaultTTL;
|
|
336
|
-
const expiresAt = ttl !== undefined ? now + ttl : null;
|
|
337
|
-
// Check if key already exists
|
|
338
|
-
const existingNode = this.cache.get(key);
|
|
339
|
-
if (existingNode) {
|
|
340
|
-
// Update existing entry
|
|
341
|
-
this._bytes -= existingNode.entry.size;
|
|
342
|
-
existingNode.entry = {
|
|
343
|
-
value,
|
|
344
|
-
size,
|
|
345
|
-
createdAt: now,
|
|
346
|
-
expiresAt,
|
|
347
|
-
lastAccessed: now
|
|
348
|
-
};
|
|
349
|
-
this._bytes += size;
|
|
350
|
-
this.moveToHead(existingNode);
|
|
351
|
-
return true;
|
|
352
|
-
}
|
|
353
|
-
// Evict items to make room
|
|
354
|
-
this.evictToFit(size);
|
|
355
|
-
// Create new entry
|
|
356
|
-
const entry = {
|
|
357
|
-
value,
|
|
358
|
-
size,
|
|
359
|
-
createdAt: now,
|
|
360
|
-
expiresAt,
|
|
361
|
-
lastAccessed: now
|
|
362
|
-
};
|
|
363
|
-
const node = {
|
|
364
|
-
key,
|
|
365
|
-
entry,
|
|
366
|
-
prev: null,
|
|
367
|
-
next: null
|
|
368
|
-
};
|
|
369
|
-
this.cache.set(key, node);
|
|
370
|
-
this.addToHead(node);
|
|
371
|
-
this._bytes += size;
|
|
372
|
-
return true;
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Checks if a key exists in the cache.
|
|
376
|
-
*
|
|
377
|
-
* @description
|
|
378
|
-
* Returns true if the key exists and hasn't expired.
|
|
379
|
-
* Does NOT update LRU order (use peek() for that too).
|
|
380
|
-
*
|
|
381
|
-
* @param key - The cache key to check
|
|
382
|
-
*
|
|
383
|
-
* @returns true if the key exists and is not expired
|
|
384
|
-
*
|
|
385
|
-
* @example
|
|
386
|
-
* ```typescript
|
|
387
|
-
* if (cache.has('important-key')) {
|
|
388
|
-
* // Key exists and is valid
|
|
389
|
-
* const value = cache.get('important-key');
|
|
390
|
-
* }
|
|
391
|
-
* ```
|
|
392
|
-
*/
|
|
393
|
-
has(key) {
|
|
394
|
-
const node = this.cache.get(key);
|
|
395
|
-
if (!node)
|
|
396
|
-
return false;
|
|
397
|
-
if (this.isExpired(node.entry))
|
|
398
|
-
return false;
|
|
399
|
-
return true;
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Deletes a key from the cache.
|
|
403
|
-
*
|
|
404
|
-
* @description
|
|
405
|
-
* Removes an entry from the cache. Triggers the onEvict callback
|
|
406
|
-
* with reason 'manual'.
|
|
407
|
-
*
|
|
408
|
-
* @param key - The cache key to delete
|
|
409
|
-
*
|
|
410
|
-
* @returns true if the key was deleted, false if it didn't exist
|
|
411
|
-
*
|
|
412
|
-
* @example
|
|
413
|
-
* ```typescript
|
|
414
|
-
* cache.set('key', 'value');
|
|
415
|
-
* cache.delete('key'); // returns true
|
|
416
|
-
* cache.delete('key'); // returns false (already deleted)
|
|
417
|
-
* ```
|
|
418
|
-
*/
|
|
419
|
-
delete(key) {
|
|
420
|
-
const node = this.cache.get(key);
|
|
421
|
-
if (!node)
|
|
422
|
-
return false;
|
|
423
|
-
this.removeNode(node);
|
|
424
|
-
this.cache.delete(key);
|
|
425
|
-
this._bytes -= node.entry.size;
|
|
426
|
-
if (this.onEvict) {
|
|
427
|
-
this.onEvict(key, node.entry.value, 'manual');
|
|
428
|
-
}
|
|
429
|
-
return true;
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Clears all entries from the cache.
|
|
433
|
-
*
|
|
434
|
-
* @description
|
|
435
|
-
* Removes all entries and resets the byte counter. If an onEvict
|
|
436
|
-
* callback is configured, it's called for each entry with reason 'clear'.
|
|
437
|
-
*
|
|
438
|
-
* Does NOT reset statistics (use resetStats() for that).
|
|
439
|
-
*
|
|
440
|
-
* @example
|
|
441
|
-
* ```typescript
|
|
442
|
-
* cache.set('a', 1);
|
|
443
|
-
* cache.set('b', 2);
|
|
444
|
-
* cache.clear();
|
|
445
|
-
* console.log(cache.size); // 0
|
|
446
|
-
* ```
|
|
447
|
-
*/
|
|
448
|
-
clear() {
|
|
449
|
-
if (this.onEvict) {
|
|
450
|
-
// Call onEvict for each entry
|
|
451
|
-
for (const [key, node] of this.cache) {
|
|
452
|
-
this.onEvict(key, node.entry.value, 'clear');
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
this.cache.clear();
|
|
456
|
-
this.head = null;
|
|
457
|
-
this.tail = null;
|
|
458
|
-
this._bytes = 0;
|
|
459
|
-
}
|
|
460
|
-
/**
|
|
461
|
-
* Gets cache statistics.
|
|
462
|
-
*
|
|
463
|
-
* @description
|
|
464
|
-
* Returns current statistics about cache performance including
|
|
465
|
-
* hits, misses, item count, byte usage, evictions, and hit rate.
|
|
466
|
-
*
|
|
467
|
-
* @returns Current cache statistics
|
|
468
|
-
*
|
|
469
|
-
* @example
|
|
470
|
-
* ```typescript
|
|
471
|
-
* const stats = cache.getStats();
|
|
472
|
-
* console.log(`Hit rate: ${stats.hitRate}%`);
|
|
473
|
-
* console.log(`Cache size: ${stats.count} items, ${stats.bytes} bytes`);
|
|
474
|
-
* console.log(`Evictions: ${stats.evictions}`);
|
|
475
|
-
* ```
|
|
476
|
-
*/
|
|
477
|
-
getStats() {
|
|
478
|
-
const total = this._hits + this._misses;
|
|
479
|
-
const hitRate = total === 0 ? 0 : Math.round((this._hits / total) * 100);
|
|
480
|
-
return {
|
|
481
|
-
hits: this._hits,
|
|
482
|
-
misses: this._misses,
|
|
483
|
-
count: this.cache.size,
|
|
484
|
-
bytes: this._bytes,
|
|
485
|
-
evictions: this._evictions,
|
|
486
|
-
hitRate
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
/**
|
|
490
|
-
* Resets cache statistics.
|
|
491
|
-
*
|
|
492
|
-
* @description
|
|
493
|
-
* Resets hit, miss, and eviction counters to zero.
|
|
494
|
-
* Does NOT clear cached data.
|
|
495
|
-
*
|
|
496
|
-
* @example
|
|
497
|
-
* ```typescript
|
|
498
|
-
* // After warmup period, reset stats
|
|
499
|
-
* cache.resetStats();
|
|
500
|
-
* // Now stats reflect production traffic
|
|
501
|
-
* ```
|
|
502
|
-
*/
|
|
503
|
-
resetStats() {
|
|
504
|
-
this._hits = 0;
|
|
505
|
-
this._misses = 0;
|
|
506
|
-
this._evictions = 0;
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Gets the number of items currently in the cache.
|
|
510
|
-
*
|
|
511
|
-
* @returns Current item count
|
|
512
|
-
*
|
|
513
|
-
* @example
|
|
514
|
-
* ```typescript
|
|
515
|
-
* console.log(`Cache has ${cache.size} items`);
|
|
516
|
-
* ```
|
|
517
|
-
*/
|
|
518
|
-
get size() {
|
|
519
|
-
return this.cache.size;
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* Gets the current byte size of the cache.
|
|
523
|
-
*
|
|
524
|
-
* @returns Current size in bytes
|
|
525
|
-
*
|
|
526
|
-
* @example
|
|
527
|
-
* ```typescript
|
|
528
|
-
* console.log(`Cache using ${cache.bytes} bytes`);
|
|
529
|
-
* ```
|
|
530
|
-
*/
|
|
531
|
-
get bytes() {
|
|
532
|
-
return this._bytes;
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* Gets all keys in the cache in LRU order.
|
|
536
|
-
*
|
|
537
|
-
* @description
|
|
538
|
-
* Returns keys from most recently used to least recently used.
|
|
539
|
-
* Does NOT affect LRU ordering.
|
|
540
|
-
*
|
|
541
|
-
* @returns Array of keys in LRU order (most recent first)
|
|
542
|
-
*
|
|
543
|
-
* @example
|
|
544
|
-
* ```typescript
|
|
545
|
-
* cache.set('a', 1);
|
|
546
|
-
* cache.set('b', 2);
|
|
547
|
-
* cache.get('a');
|
|
548
|
-
* console.log(cache.keys()); // ['a', 'b']
|
|
549
|
-
* ```
|
|
550
|
-
*/
|
|
551
|
-
keys() {
|
|
552
|
-
const keys = [];
|
|
553
|
-
let node = this.head;
|
|
554
|
-
while (node) {
|
|
555
|
-
keys.push(node.key);
|
|
556
|
-
node = node.next;
|
|
557
|
-
}
|
|
558
|
-
return keys;
|
|
559
|
-
}
|
|
560
|
-
/**
|
|
561
|
-
* Gets all values in the cache in LRU order.
|
|
562
|
-
*
|
|
563
|
-
* @description
|
|
564
|
-
* Returns values from most recently used to least recently used.
|
|
565
|
-
* Does NOT affect LRU ordering.
|
|
566
|
-
*
|
|
567
|
-
* @returns Array of values in LRU order (most recent first)
|
|
568
|
-
*
|
|
569
|
-
* @example
|
|
570
|
-
* ```typescript
|
|
571
|
-
* const recentValues = cache.values();
|
|
572
|
-
* ```
|
|
573
|
-
*/
|
|
574
|
-
values() {
|
|
575
|
-
const values = [];
|
|
576
|
-
let node = this.head;
|
|
577
|
-
while (node) {
|
|
578
|
-
values.push(node.entry.value);
|
|
579
|
-
node = node.next;
|
|
580
|
-
}
|
|
581
|
-
return values;
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Gets all entries in the cache in LRU order.
|
|
585
|
-
*
|
|
586
|
-
* @description
|
|
587
|
-
* Returns [key, value] pairs from most recently used to least recently used.
|
|
588
|
-
* Does NOT affect LRU ordering.
|
|
589
|
-
*
|
|
590
|
-
* @returns Array of [key, value] pairs in LRU order
|
|
591
|
-
*
|
|
592
|
-
* @example
|
|
593
|
-
* ```typescript
|
|
594
|
-
* for (const [key, value] of cache.entries()) {
|
|
595
|
-
* console.log(`${key}: ${value}`);
|
|
596
|
-
* }
|
|
597
|
-
* ```
|
|
598
|
-
*/
|
|
599
|
-
entries() {
|
|
600
|
-
const entries = [];
|
|
601
|
-
let node = this.head;
|
|
602
|
-
while (node) {
|
|
603
|
-
entries.push([node.key, node.entry.value]);
|
|
604
|
-
node = node.next;
|
|
605
|
-
}
|
|
606
|
-
return entries;
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* Peeks at a value without updating LRU order.
|
|
610
|
-
*
|
|
611
|
-
* @description
|
|
612
|
-
* Retrieves a value without marking it as recently used.
|
|
613
|
-
* Useful for inspection or when you don't want to affect eviction order.
|
|
614
|
-
*
|
|
615
|
-
* @param key - The cache key to peek at
|
|
616
|
-
*
|
|
617
|
-
* @returns The cached value or undefined if not found/expired
|
|
618
|
-
*
|
|
619
|
-
* @example
|
|
620
|
-
* ```typescript
|
|
621
|
-
* // Check value without affecting LRU order
|
|
622
|
-
* const value = cache.peek('key');
|
|
623
|
-
* // This won't prevent 'key' from being evicted next
|
|
624
|
-
* ```
|
|
625
|
-
*/
|
|
626
|
-
peek(key) {
|
|
627
|
-
const node = this.cache.get(key);
|
|
628
|
-
if (!node)
|
|
629
|
-
return undefined;
|
|
630
|
-
if (this.isExpired(node.entry))
|
|
631
|
-
return undefined;
|
|
632
|
-
return node.entry.value;
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* Evicts expired entries from the cache.
|
|
636
|
-
*
|
|
637
|
-
* @description
|
|
638
|
-
* Scans all entries and removes those that have expired.
|
|
639
|
-
* Triggers onEvict callback with reason 'ttl' for each removed entry.
|
|
640
|
-
*
|
|
641
|
-
* Call this periodically if you need proactive cleanup of expired entries.
|
|
642
|
-
* Note: Expired entries are also cleaned up lazily on get().
|
|
643
|
-
*
|
|
644
|
-
* @returns Number of entries evicted
|
|
645
|
-
*
|
|
646
|
-
* @example
|
|
647
|
-
* ```typescript
|
|
648
|
-
* // Run periodic cleanup
|
|
649
|
-
* setInterval(() => {
|
|
650
|
-
* const pruned = cache.prune();
|
|
651
|
-
* if (pruned > 0) {
|
|
652
|
-
* console.log(`Pruned ${pruned} expired entries`);
|
|
653
|
-
* }
|
|
654
|
-
* }, 60000); // Every minute
|
|
655
|
-
* ```
|
|
656
|
-
*/
|
|
657
|
-
prune() {
|
|
658
|
-
let pruned = 0;
|
|
659
|
-
const now = Date.now();
|
|
660
|
-
for (const [key, node] of this.cache) {
|
|
661
|
-
if (node.entry.expiresAt !== null && now > node.entry.expiresAt) {
|
|
662
|
-
this.removeNode(node);
|
|
663
|
-
this.cache.delete(key);
|
|
664
|
-
this._bytes -= node.entry.size;
|
|
665
|
-
pruned++;
|
|
666
|
-
if (this.onEvict) {
|
|
667
|
-
this.onEvict(key, node.entry.value, 'ttl');
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
return pruned;
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* Resizes the cache to new limits.
|
|
675
|
-
*
|
|
676
|
-
* @description
|
|
677
|
-
* Updates the maxCount and/or maxBytes limits. If the current cache
|
|
678
|
-
* exceeds the new limits, evicts LRU items until within limits.
|
|
679
|
-
*
|
|
680
|
-
* @param options - New size limits (maxCount and/or maxBytes)
|
|
681
|
-
*
|
|
682
|
-
* @example
|
|
683
|
-
* ```typescript
|
|
684
|
-
* // Reduce cache size under memory pressure
|
|
685
|
-
* cache.resize({ maxBytes: 10 * 1024 * 1024 }); // Reduce to 10MB
|
|
686
|
-
*
|
|
687
|
-
* // Increase limit when more memory is available
|
|
688
|
-
* cache.resize({ maxCount: 1000, maxBytes: 100 * 1024 * 1024 });
|
|
689
|
-
* ```
|
|
690
|
-
*/
|
|
691
|
-
resize(options) {
|
|
692
|
-
if (options.maxCount !== undefined) {
|
|
693
|
-
this.maxCount = options.maxCount;
|
|
694
|
-
}
|
|
695
|
-
if (options.maxBytes !== undefined) {
|
|
696
|
-
this.maxBytes = options.maxBytes;
|
|
697
|
-
}
|
|
698
|
-
// Evict items until we're under the new limits
|
|
699
|
-
while (this.tail && ((this.maxCount !== Infinity && this.cache.size > this.maxCount) ||
|
|
700
|
-
(this.maxBytes !== Infinity && this._bytes > this.maxBytes))) {
|
|
701
|
-
const lru = this.tail;
|
|
702
|
-
this.removeNode(lru);
|
|
703
|
-
this.cache.delete(lru.key);
|
|
704
|
-
this._bytes -= lru.entry.size;
|
|
705
|
-
this._evictions++;
|
|
706
|
-
if (this.onEvict) {
|
|
707
|
-
this.onEvict(lru.key, lru.entry.value, 'lru');
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
/**
|
|
713
|
-
* Creates a key serializer for complex key types.
|
|
714
|
-
*
|
|
715
|
-
* @description
|
|
716
|
-
* Helper function for creating serializers when using complex key types
|
|
717
|
-
* that need to be converted to/from strings.
|
|
718
|
-
*
|
|
719
|
-
* @param serialize - Function to convert key to string
|
|
720
|
-
* @param deserialize - Function to convert string back to key
|
|
721
|
-
*
|
|
722
|
-
* @returns Object with serialize and deserialize functions
|
|
723
|
-
*
|
|
724
|
-
* @example
|
|
725
|
-
* ```typescript
|
|
726
|
-
* interface ObjectKey {
|
|
727
|
-
* repo: string;
|
|
728
|
-
* sha: string;
|
|
729
|
-
* }
|
|
730
|
-
*
|
|
731
|
-
* const keySerializer = createKeySerializer<ObjectKey>(
|
|
732
|
-
* (key) => `${key.repo}:${key.sha}`,
|
|
733
|
-
* (str) => {
|
|
734
|
-
* const [repo, sha] = str.split(':');
|
|
735
|
-
* return { repo, sha };
|
|
736
|
-
* }
|
|
737
|
-
* );
|
|
738
|
-
*
|
|
739
|
-
* // Use with cache
|
|
740
|
-
* const serializedKey = keySerializer.serialize({ repo: 'foo', sha: 'abc' });
|
|
741
|
-
* cache.set(serializedKey, value);
|
|
742
|
-
* ```
|
|
743
|
-
*/
|
|
744
|
-
export function createKeySerializer(serialize, deserialize) {
|
|
745
|
-
return { serialize, deserialize };
|
|
746
|
-
}
|
|
747
|
-
/**
|
|
748
|
-
* Default size calculator for common value types.
|
|
749
|
-
*
|
|
750
|
-
* @description
|
|
751
|
-
* Estimates the byte size of common JavaScript value types:
|
|
752
|
-
* - `null/undefined`: 0 bytes
|
|
753
|
-
* - `string`: 2 bytes per character (UTF-16)
|
|
754
|
-
* - `number`: 8 bytes
|
|
755
|
-
* - `boolean`: 4 bytes
|
|
756
|
-
* - `Uint8Array/ArrayBuffer`: actual byteLength
|
|
757
|
-
* - `object`: JSON-serialized length * 2
|
|
758
|
-
* - `unknown`: 8 bytes (default)
|
|
759
|
-
*
|
|
760
|
-
* For more accurate size calculation with specific types,
|
|
761
|
-
* provide a custom sizeCalculator in CacheOptions.
|
|
762
|
-
*
|
|
763
|
-
* @param value - The value to calculate size for
|
|
764
|
-
*
|
|
765
|
-
* @returns Estimated size in bytes
|
|
766
|
-
*
|
|
767
|
-
* @example
|
|
768
|
-
* ```typescript
|
|
769
|
-
* defaultSizeCalculator('hello'); // 10 (5 chars * 2)
|
|
770
|
-
* defaultSizeCalculator(42); // 8
|
|
771
|
-
* defaultSizeCalculator(new Uint8Array(100)); // 100
|
|
772
|
-
* defaultSizeCalculator({ key: 'value' }); // ~30
|
|
773
|
-
* ```
|
|
774
|
-
*/
|
|
775
|
-
export function defaultSizeCalculator(value) {
|
|
776
|
-
if (value === null || value === undefined) {
|
|
777
|
-
return 0;
|
|
778
|
-
}
|
|
779
|
-
if (typeof value === 'string') {
|
|
780
|
-
// Approximate size: 2 bytes per character (UTF-16)
|
|
781
|
-
return value.length * 2;
|
|
782
|
-
}
|
|
783
|
-
if (typeof value === 'number') {
|
|
784
|
-
// Numbers are 8 bytes in JavaScript
|
|
785
|
-
return 8;
|
|
786
|
-
}
|
|
787
|
-
if (typeof value === 'boolean') {
|
|
788
|
-
return 4;
|
|
789
|
-
}
|
|
790
|
-
if (value instanceof Uint8Array) {
|
|
791
|
-
return value.byteLength;
|
|
792
|
-
}
|
|
793
|
-
if (value instanceof ArrayBuffer) {
|
|
794
|
-
return value.byteLength;
|
|
795
|
-
}
|
|
796
|
-
if (ArrayBuffer.isView(value)) {
|
|
797
|
-
return value.byteLength;
|
|
798
|
-
}
|
|
799
|
-
if (typeof value === 'object') {
|
|
800
|
-
// For objects, serialize to JSON and count characters
|
|
801
|
-
try {
|
|
802
|
-
const json = JSON.stringify(value);
|
|
803
|
-
return json.length * 2;
|
|
804
|
-
}
|
|
805
|
-
catch {
|
|
806
|
-
// If serialization fails, return a default size
|
|
807
|
-
return 64;
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
// Default size for unknown types
|
|
811
|
-
return 8;
|
|
812
|
-
}
|
|
813
|
-
//# sourceMappingURL=lru-cache.js.map
|