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.
Files changed (344) hide show
  1. package/README.md +40 -353
  2. package/dist/do/logger.d.ts +50 -0
  3. package/dist/do/logger.d.ts.map +1 -0
  4. package/dist/do/logger.js +122 -0
  5. package/dist/do/logger.js.map +1 -0
  6. package/dist/{durable-object → do}/schema.d.ts +3 -3
  7. package/dist/do/schema.d.ts.map +1 -0
  8. package/dist/{durable-object → do}/schema.js +4 -3
  9. package/dist/do/schema.js.map +1 -0
  10. package/dist/do/types.d.ts +267 -0
  11. package/dist/do/types.d.ts.map +1 -0
  12. package/dist/do/types.js +62 -0
  13. package/dist/do/types.js.map +1 -0
  14. package/dist/index.d.ts +15 -415
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +31 -483
  17. package/dist/index.js.map +1 -1
  18. package/package.json +13 -21
  19. package/dist/cli/commands/add.d.ts +0 -174
  20. package/dist/cli/commands/add.d.ts.map +0 -1
  21. package/dist/cli/commands/add.js +0 -131
  22. package/dist/cli/commands/add.js.map +0 -1
  23. package/dist/cli/commands/blame.d.ts +0 -259
  24. package/dist/cli/commands/blame.d.ts.map +0 -1
  25. package/dist/cli/commands/blame.js +0 -609
  26. package/dist/cli/commands/blame.js.map +0 -1
  27. package/dist/cli/commands/branch.d.ts +0 -249
  28. package/dist/cli/commands/branch.d.ts.map +0 -1
  29. package/dist/cli/commands/branch.js +0 -693
  30. package/dist/cli/commands/branch.js.map +0 -1
  31. package/dist/cli/commands/commit.d.ts +0 -182
  32. package/dist/cli/commands/commit.d.ts.map +0 -1
  33. package/dist/cli/commands/commit.js +0 -437
  34. package/dist/cli/commands/commit.js.map +0 -1
  35. package/dist/cli/commands/diff.d.ts +0 -464
  36. package/dist/cli/commands/diff.d.ts.map +0 -1
  37. package/dist/cli/commands/diff.js +0 -958
  38. package/dist/cli/commands/diff.js.map +0 -1
  39. package/dist/cli/commands/log.d.ts +0 -239
  40. package/dist/cli/commands/log.d.ts.map +0 -1
  41. package/dist/cli/commands/log.js +0 -535
  42. package/dist/cli/commands/log.js.map +0 -1
  43. package/dist/cli/commands/merge.d.ts +0 -106
  44. package/dist/cli/commands/merge.d.ts.map +0 -1
  45. package/dist/cli/commands/merge.js +0 -55
  46. package/dist/cli/commands/merge.js.map +0 -1
  47. package/dist/cli/commands/review.d.ts +0 -457
  48. package/dist/cli/commands/review.d.ts.map +0 -1
  49. package/dist/cli/commands/review.js +0 -533
  50. package/dist/cli/commands/review.js.map +0 -1
  51. package/dist/cli/commands/status.d.ts +0 -269
  52. package/dist/cli/commands/status.d.ts.map +0 -1
  53. package/dist/cli/commands/status.js +0 -493
  54. package/dist/cli/commands/status.js.map +0 -1
  55. package/dist/cli/commands/web.d.ts +0 -199
  56. package/dist/cli/commands/web.d.ts.map +0 -1
  57. package/dist/cli/commands/web.js +0 -696
  58. package/dist/cli/commands/web.js.map +0 -1
  59. package/dist/cli/fs-adapter.d.ts +0 -656
  60. package/dist/cli/fs-adapter.d.ts.map +0 -1
  61. package/dist/cli/fs-adapter.js +0 -1179
  62. package/dist/cli/fs-adapter.js.map +0 -1
  63. package/dist/cli/fsx-cli-adapter.d.ts +0 -359
  64. package/dist/cli/fsx-cli-adapter.d.ts.map +0 -1
  65. package/dist/cli/fsx-cli-adapter.js +0 -619
  66. package/dist/cli/fsx-cli-adapter.js.map +0 -1
  67. package/dist/cli/index.d.ts +0 -387
  68. package/dist/cli/index.d.ts.map +0 -1
  69. package/dist/cli/index.js +0 -523
  70. package/dist/cli/index.js.map +0 -1
  71. package/dist/cli/ui/components/DiffView.d.ts +0 -7
  72. package/dist/cli/ui/components/DiffView.d.ts.map +0 -1
  73. package/dist/cli/ui/components/DiffView.js +0 -11
  74. package/dist/cli/ui/components/DiffView.js.map +0 -1
  75. package/dist/cli/ui/components/ErrorDisplay.d.ts +0 -6
  76. package/dist/cli/ui/components/ErrorDisplay.d.ts.map +0 -1
  77. package/dist/cli/ui/components/ErrorDisplay.js +0 -11
  78. package/dist/cli/ui/components/ErrorDisplay.js.map +0 -1
  79. package/dist/cli/ui/components/FuzzySearch.d.ts +0 -9
  80. package/dist/cli/ui/components/FuzzySearch.d.ts.map +0 -1
  81. package/dist/cli/ui/components/FuzzySearch.js +0 -12
  82. package/dist/cli/ui/components/FuzzySearch.js.map +0 -1
  83. package/dist/cli/ui/components/LoadingSpinner.d.ts +0 -6
  84. package/dist/cli/ui/components/LoadingSpinner.d.ts.map +0 -1
  85. package/dist/cli/ui/components/LoadingSpinner.js +0 -10
  86. package/dist/cli/ui/components/LoadingSpinner.js.map +0 -1
  87. package/dist/cli/ui/components/NavigationList.d.ts +0 -9
  88. package/dist/cli/ui/components/NavigationList.d.ts.map +0 -1
  89. package/dist/cli/ui/components/NavigationList.js +0 -11
  90. package/dist/cli/ui/components/NavigationList.js.map +0 -1
  91. package/dist/cli/ui/components/ScrollableContent.d.ts +0 -8
  92. package/dist/cli/ui/components/ScrollableContent.d.ts.map +0 -1
  93. package/dist/cli/ui/components/ScrollableContent.js +0 -11
  94. package/dist/cli/ui/components/ScrollableContent.js.map +0 -1
  95. package/dist/cli/ui/components/index.d.ts +0 -7
  96. package/dist/cli/ui/components/index.d.ts.map +0 -1
  97. package/dist/cli/ui/components/index.js +0 -9
  98. package/dist/cli/ui/components/index.js.map +0 -1
  99. package/dist/cli/ui/terminal-ui.d.ts +0 -52
  100. package/dist/cli/ui/terminal-ui.d.ts.map +0 -1
  101. package/dist/cli/ui/terminal-ui.js +0 -121
  102. package/dist/cli/ui/terminal-ui.js.map +0 -1
  103. package/dist/do/BashModule.d.ts +0 -871
  104. package/dist/do/BashModule.d.ts.map +0 -1
  105. package/dist/do/BashModule.js +0 -1143
  106. package/dist/do/BashModule.js.map +0 -1
  107. package/dist/do/FsModule.d.ts +0 -601
  108. package/dist/do/FsModule.d.ts.map +0 -1
  109. package/dist/do/FsModule.js +0 -1120
  110. package/dist/do/FsModule.js.map +0 -1
  111. package/dist/do/GitModule.d.ts +0 -635
  112. package/dist/do/GitModule.d.ts.map +0 -1
  113. package/dist/do/GitModule.js +0 -781
  114. package/dist/do/GitModule.js.map +0 -1
  115. package/dist/do/GitRepoDO.d.ts +0 -281
  116. package/dist/do/GitRepoDO.d.ts.map +0 -1
  117. package/dist/do/GitRepoDO.js +0 -479
  118. package/dist/do/GitRepoDO.js.map +0 -1
  119. package/dist/do/bash-ast.d.ts +0 -246
  120. package/dist/do/bash-ast.d.ts.map +0 -1
  121. package/dist/do/bash-ast.js +0 -888
  122. package/dist/do/bash-ast.js.map +0 -1
  123. package/dist/do/container-executor.d.ts +0 -491
  124. package/dist/do/container-executor.d.ts.map +0 -1
  125. package/dist/do/container-executor.js +0 -730
  126. package/dist/do/container-executor.js.map +0 -1
  127. package/dist/do/index.d.ts +0 -53
  128. package/dist/do/index.d.ts.map +0 -1
  129. package/dist/do/index.js +0 -91
  130. package/dist/do/index.js.map +0 -1
  131. package/dist/do/tiered-storage.d.ts +0 -403
  132. package/dist/do/tiered-storage.d.ts.map +0 -1
  133. package/dist/do/tiered-storage.js +0 -689
  134. package/dist/do/tiered-storage.js.map +0 -1
  135. package/dist/do/withBash.d.ts +0 -231
  136. package/dist/do/withBash.d.ts.map +0 -1
  137. package/dist/do/withBash.js +0 -244
  138. package/dist/do/withBash.js.map +0 -1
  139. package/dist/do/withFs.d.ts +0 -237
  140. package/dist/do/withFs.d.ts.map +0 -1
  141. package/dist/do/withFs.js +0 -387
  142. package/dist/do/withFs.js.map +0 -1
  143. package/dist/do/withGit.d.ts +0 -180
  144. package/dist/do/withGit.d.ts.map +0 -1
  145. package/dist/do/withGit.js +0 -271
  146. package/dist/do/withGit.js.map +0 -1
  147. package/dist/durable-object/object-store.d.ts +0 -633
  148. package/dist/durable-object/object-store.d.ts.map +0 -1
  149. package/dist/durable-object/object-store.js +0 -1161
  150. package/dist/durable-object/object-store.js.map +0 -1
  151. package/dist/durable-object/schema.d.ts.map +0 -1
  152. package/dist/durable-object/schema.js.map +0 -1
  153. package/dist/durable-object/wal.d.ts +0 -416
  154. package/dist/durable-object/wal.d.ts.map +0 -1
  155. package/dist/durable-object/wal.js +0 -445
  156. package/dist/durable-object/wal.js.map +0 -1
  157. package/dist/mcp/adapter.d.ts +0 -772
  158. package/dist/mcp/adapter.d.ts.map +0 -1
  159. package/dist/mcp/adapter.js +0 -895
  160. package/dist/mcp/adapter.js.map +0 -1
  161. package/dist/mcp/sandbox/miniflare-evaluator.d.ts +0 -22
  162. package/dist/mcp/sandbox/miniflare-evaluator.d.ts.map +0 -1
  163. package/dist/mcp/sandbox/miniflare-evaluator.js +0 -140
  164. package/dist/mcp/sandbox/miniflare-evaluator.js.map +0 -1
  165. package/dist/mcp/sandbox/object-store-proxy.d.ts +0 -32
  166. package/dist/mcp/sandbox/object-store-proxy.d.ts.map +0 -1
  167. package/dist/mcp/sandbox/object-store-proxy.js +0 -30
  168. package/dist/mcp/sandbox/object-store-proxy.js.map +0 -1
  169. package/dist/mcp/sandbox/template.d.ts +0 -17
  170. package/dist/mcp/sandbox/template.d.ts.map +0 -1
  171. package/dist/mcp/sandbox/template.js +0 -71
  172. package/dist/mcp/sandbox/template.js.map +0 -1
  173. package/dist/mcp/sandbox.d.ts +0 -764
  174. package/dist/mcp/sandbox.d.ts.map +0 -1
  175. package/dist/mcp/sandbox.js +0 -1362
  176. package/dist/mcp/sandbox.js.map +0 -1
  177. package/dist/mcp/sdk-adapter.d.ts +0 -835
  178. package/dist/mcp/sdk-adapter.d.ts.map +0 -1
  179. package/dist/mcp/sdk-adapter.js +0 -974
  180. package/dist/mcp/sdk-adapter.js.map +0 -1
  181. package/dist/mcp/tools/do.d.ts +0 -32
  182. package/dist/mcp/tools/do.d.ts.map +0 -1
  183. package/dist/mcp/tools/do.js +0 -115
  184. package/dist/mcp/tools/do.js.map +0 -1
  185. package/dist/mcp/tools.d.ts +0 -548
  186. package/dist/mcp/tools.d.ts.map +0 -1
  187. package/dist/mcp/tools.js +0 -1934
  188. package/dist/mcp/tools.js.map +0 -1
  189. package/dist/ops/blame.d.ts +0 -551
  190. package/dist/ops/blame.d.ts.map +0 -1
  191. package/dist/ops/blame.js +0 -1037
  192. package/dist/ops/blame.js.map +0 -1
  193. package/dist/ops/branch.d.ts +0 -766
  194. package/dist/ops/branch.d.ts.map +0 -1
  195. package/dist/ops/branch.js +0 -950
  196. package/dist/ops/branch.js.map +0 -1
  197. package/dist/ops/commit-traversal.d.ts +0 -349
  198. package/dist/ops/commit-traversal.d.ts.map +0 -1
  199. package/dist/ops/commit-traversal.js +0 -821
  200. package/dist/ops/commit-traversal.js.map +0 -1
  201. package/dist/ops/commit.d.ts +0 -555
  202. package/dist/ops/commit.d.ts.map +0 -1
  203. package/dist/ops/commit.js +0 -826
  204. package/dist/ops/commit.js.map +0 -1
  205. package/dist/ops/merge-base.d.ts +0 -397
  206. package/dist/ops/merge-base.d.ts.map +0 -1
  207. package/dist/ops/merge-base.js +0 -691
  208. package/dist/ops/merge-base.js.map +0 -1
  209. package/dist/ops/merge.d.ts +0 -855
  210. package/dist/ops/merge.d.ts.map +0 -1
  211. package/dist/ops/merge.js +0 -1551
  212. package/dist/ops/merge.js.map +0 -1
  213. package/dist/ops/tag.d.ts +0 -247
  214. package/dist/ops/tag.d.ts.map +0 -1
  215. package/dist/ops/tag.js +0 -649
  216. package/dist/ops/tag.js.map +0 -1
  217. package/dist/ops/tree-builder.d.ts +0 -178
  218. package/dist/ops/tree-builder.d.ts.map +0 -1
  219. package/dist/ops/tree-builder.js +0 -271
  220. package/dist/ops/tree-builder.js.map +0 -1
  221. package/dist/ops/tree-diff.d.ts +0 -291
  222. package/dist/ops/tree-diff.d.ts.map +0 -1
  223. package/dist/ops/tree-diff.js +0 -705
  224. package/dist/ops/tree-diff.js.map +0 -1
  225. package/dist/pack/delta.d.ts +0 -248
  226. package/dist/pack/delta.d.ts.map +0 -1
  227. package/dist/pack/delta.js +0 -736
  228. package/dist/pack/delta.js.map +0 -1
  229. package/dist/pack/format.d.ts +0 -446
  230. package/dist/pack/format.d.ts.map +0 -1
  231. package/dist/pack/format.js +0 -572
  232. package/dist/pack/format.js.map +0 -1
  233. package/dist/pack/full-generation.d.ts +0 -612
  234. package/dist/pack/full-generation.d.ts.map +0 -1
  235. package/dist/pack/full-generation.js +0 -1378
  236. package/dist/pack/full-generation.js.map +0 -1
  237. package/dist/pack/generation.d.ts +0 -441
  238. package/dist/pack/generation.d.ts.map +0 -1
  239. package/dist/pack/generation.js +0 -707
  240. package/dist/pack/generation.js.map +0 -1
  241. package/dist/pack/index.d.ts +0 -502
  242. package/dist/pack/index.d.ts.map +0 -1
  243. package/dist/pack/index.js +0 -833
  244. package/dist/pack/index.js.map +0 -1
  245. package/dist/refs/branch.d.ts +0 -668
  246. package/dist/refs/branch.d.ts.map +0 -1
  247. package/dist/refs/branch.js +0 -897
  248. package/dist/refs/branch.js.map +0 -1
  249. package/dist/refs/storage.d.ts +0 -833
  250. package/dist/refs/storage.d.ts.map +0 -1
  251. package/dist/refs/storage.js +0 -1023
  252. package/dist/refs/storage.js.map +0 -1
  253. package/dist/refs/tag.d.ts +0 -860
  254. package/dist/refs/tag.d.ts.map +0 -1
  255. package/dist/refs/tag.js +0 -996
  256. package/dist/refs/tag.js.map +0 -1
  257. package/dist/storage/backend.d.ts +0 -425
  258. package/dist/storage/backend.d.ts.map +0 -1
  259. package/dist/storage/backend.js +0 -41
  260. package/dist/storage/backend.js.map +0 -1
  261. package/dist/storage/fsx-adapter.d.ts +0 -204
  262. package/dist/storage/fsx-adapter.d.ts.map +0 -1
  263. package/dist/storage/fsx-adapter.js +0 -470
  264. package/dist/storage/fsx-adapter.js.map +0 -1
  265. package/dist/storage/lru-cache.d.ts +0 -691
  266. package/dist/storage/lru-cache.d.ts.map +0 -1
  267. package/dist/storage/lru-cache.js +0 -813
  268. package/dist/storage/lru-cache.js.map +0 -1
  269. package/dist/storage/object-index.d.ts +0 -585
  270. package/dist/storage/object-index.d.ts.map +0 -1
  271. package/dist/storage/object-index.js +0 -532
  272. package/dist/storage/object-index.js.map +0 -1
  273. package/dist/storage/r2-pack.d.ts +0 -1257
  274. package/dist/storage/r2-pack.d.ts.map +0 -1
  275. package/dist/storage/r2-pack.js +0 -1770
  276. package/dist/storage/r2-pack.js.map +0 -1
  277. package/dist/tiered/cdc-pipeline.d.ts +0 -1888
  278. package/dist/tiered/cdc-pipeline.d.ts.map +0 -1
  279. package/dist/tiered/cdc-pipeline.js +0 -1880
  280. package/dist/tiered/cdc-pipeline.js.map +0 -1
  281. package/dist/tiered/migration.d.ts +0 -1104
  282. package/dist/tiered/migration.d.ts.map +0 -1
  283. package/dist/tiered/migration.js +0 -1214
  284. package/dist/tiered/migration.js.map +0 -1
  285. package/dist/tiered/parquet-writer.d.ts +0 -1145
  286. package/dist/tiered/parquet-writer.d.ts.map +0 -1
  287. package/dist/tiered/parquet-writer.js +0 -1183
  288. package/dist/tiered/parquet-writer.js.map +0 -1
  289. package/dist/tiered/read-path.d.ts +0 -835
  290. package/dist/tiered/read-path.d.ts.map +0 -1
  291. package/dist/tiered/read-path.js +0 -487
  292. package/dist/tiered/read-path.js.map +0 -1
  293. package/dist/types/capability.d.ts +0 -1385
  294. package/dist/types/capability.d.ts.map +0 -1
  295. package/dist/types/capability.js +0 -36
  296. package/dist/types/capability.js.map +0 -1
  297. package/dist/types/index.d.ts +0 -13
  298. package/dist/types/index.d.ts.map +0 -1
  299. package/dist/types/index.js +0 -18
  300. package/dist/types/index.js.map +0 -1
  301. package/dist/types/objects.d.ts +0 -692
  302. package/dist/types/objects.d.ts.map +0 -1
  303. package/dist/types/objects.js +0 -837
  304. package/dist/types/objects.js.map +0 -1
  305. package/dist/types/storage.d.ts +0 -603
  306. package/dist/types/storage.d.ts.map +0 -1
  307. package/dist/types/storage.js +0 -191
  308. package/dist/types/storage.js.map +0 -1
  309. package/dist/types/worker-loader.d.ts +0 -60
  310. package/dist/types/worker-loader.d.ts.map +0 -1
  311. package/dist/types/worker-loader.js +0 -62
  312. package/dist/types/worker-loader.js.map +0 -1
  313. package/dist/utils/hash.d.ts +0 -197
  314. package/dist/utils/hash.d.ts.map +0 -1
  315. package/dist/utils/hash.js +0 -268
  316. package/dist/utils/hash.js.map +0 -1
  317. package/dist/utils/sha1.d.ts +0 -290
  318. package/dist/utils/sha1.d.ts.map +0 -1
  319. package/dist/utils/sha1.js +0 -582
  320. package/dist/utils/sha1.js.map +0 -1
  321. package/dist/wire/capabilities.d.ts +0 -1044
  322. package/dist/wire/capabilities.d.ts.map +0 -1
  323. package/dist/wire/capabilities.js +0 -941
  324. package/dist/wire/capabilities.js.map +0 -1
  325. package/dist/wire/path-security.d.ts +0 -157
  326. package/dist/wire/path-security.d.ts.map +0 -1
  327. package/dist/wire/path-security.js +0 -307
  328. package/dist/wire/path-security.js.map +0 -1
  329. package/dist/wire/pkt-line.d.ts +0 -345
  330. package/dist/wire/pkt-line.d.ts.map +0 -1
  331. package/dist/wire/pkt-line.js +0 -381
  332. package/dist/wire/pkt-line.js.map +0 -1
  333. package/dist/wire/receive-pack.d.ts +0 -1059
  334. package/dist/wire/receive-pack.d.ts.map +0 -1
  335. package/dist/wire/receive-pack.js +0 -1414
  336. package/dist/wire/receive-pack.js.map +0 -1
  337. package/dist/wire/smart-http.d.ts +0 -799
  338. package/dist/wire/smart-http.d.ts.map +0 -1
  339. package/dist/wire/smart-http.js +0 -945
  340. package/dist/wire/smart-http.js.map +0 -1
  341. package/dist/wire/upload-pack.d.ts +0 -727
  342. package/dist/wire/upload-pack.d.ts.map +0 -1
  343. package/dist/wire/upload-pack.js +0 -1138
  344. 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