gitx.do 0.0.1 → 0.0.3

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 (237) hide show
  1. package/dist/cli/commands/blame.d.ts +259 -0
  2. package/dist/cli/commands/blame.d.ts.map +1 -0
  3. package/dist/cli/commands/blame.js +609 -0
  4. package/dist/cli/commands/blame.js.map +1 -0
  5. package/dist/cli/commands/branch.d.ts +249 -0
  6. package/dist/cli/commands/branch.d.ts.map +1 -0
  7. package/dist/cli/commands/branch.js +693 -0
  8. package/dist/cli/commands/branch.js.map +1 -0
  9. package/dist/cli/commands/commit.d.ts +182 -0
  10. package/dist/cli/commands/commit.d.ts.map +1 -0
  11. package/dist/cli/commands/commit.js +437 -0
  12. package/dist/cli/commands/commit.js.map +1 -0
  13. package/dist/cli/commands/diff.d.ts +464 -0
  14. package/dist/cli/commands/diff.d.ts.map +1 -0
  15. package/dist/cli/commands/diff.js +958 -0
  16. package/dist/cli/commands/diff.js.map +1 -0
  17. package/dist/cli/commands/log.d.ts +239 -0
  18. package/dist/cli/commands/log.d.ts.map +1 -0
  19. package/dist/cli/commands/log.js +535 -0
  20. package/dist/cli/commands/log.js.map +1 -0
  21. package/dist/cli/commands/review.d.ts +457 -0
  22. package/dist/cli/commands/review.d.ts.map +1 -0
  23. package/dist/cli/commands/review.js +533 -0
  24. package/dist/cli/commands/review.js.map +1 -0
  25. package/dist/cli/commands/status.d.ts +269 -0
  26. package/dist/cli/commands/status.d.ts.map +1 -0
  27. package/dist/cli/commands/status.js +493 -0
  28. package/dist/cli/commands/status.js.map +1 -0
  29. package/dist/cli/commands/web.d.ts +199 -0
  30. package/dist/cli/commands/web.d.ts.map +1 -0
  31. package/dist/cli/commands/web.js +696 -0
  32. package/dist/cli/commands/web.js.map +1 -0
  33. package/dist/cli/fs-adapter.d.ts +656 -0
  34. package/dist/cli/fs-adapter.d.ts.map +1 -0
  35. package/dist/cli/fs-adapter.js +1179 -0
  36. package/dist/cli/fs-adapter.js.map +1 -0
  37. package/dist/cli/index.d.ts +387 -0
  38. package/dist/cli/index.d.ts.map +1 -0
  39. package/dist/cli/index.js +523 -0
  40. package/dist/cli/index.js.map +1 -0
  41. package/dist/cli/ui/components/DiffView.d.ts +7 -0
  42. package/dist/cli/ui/components/DiffView.d.ts.map +1 -0
  43. package/dist/cli/ui/components/DiffView.js +11 -0
  44. package/dist/cli/ui/components/DiffView.js.map +1 -0
  45. package/dist/cli/ui/components/ErrorDisplay.d.ts +6 -0
  46. package/dist/cli/ui/components/ErrorDisplay.d.ts.map +1 -0
  47. package/dist/cli/ui/components/ErrorDisplay.js +11 -0
  48. package/dist/cli/ui/components/ErrorDisplay.js.map +1 -0
  49. package/dist/cli/ui/components/FuzzySearch.d.ts +9 -0
  50. package/dist/cli/ui/components/FuzzySearch.d.ts.map +1 -0
  51. package/dist/cli/ui/components/FuzzySearch.js +12 -0
  52. package/dist/cli/ui/components/FuzzySearch.js.map +1 -0
  53. package/dist/cli/ui/components/LoadingSpinner.d.ts +6 -0
  54. package/dist/cli/ui/components/LoadingSpinner.d.ts.map +1 -0
  55. package/dist/cli/ui/components/LoadingSpinner.js +10 -0
  56. package/dist/cli/ui/components/LoadingSpinner.js.map +1 -0
  57. package/dist/cli/ui/components/NavigationList.d.ts +9 -0
  58. package/dist/cli/ui/components/NavigationList.d.ts.map +1 -0
  59. package/dist/cli/ui/components/NavigationList.js +11 -0
  60. package/dist/cli/ui/components/NavigationList.js.map +1 -0
  61. package/dist/cli/ui/components/ScrollableContent.d.ts +8 -0
  62. package/dist/cli/ui/components/ScrollableContent.d.ts.map +1 -0
  63. package/dist/cli/ui/components/ScrollableContent.js +11 -0
  64. package/dist/cli/ui/components/ScrollableContent.js.map +1 -0
  65. package/dist/cli/ui/components/index.d.ts +7 -0
  66. package/dist/cli/ui/components/index.d.ts.map +1 -0
  67. package/dist/cli/ui/components/index.js +9 -0
  68. package/dist/cli/ui/components/index.js.map +1 -0
  69. package/dist/cli/ui/terminal-ui.d.ts +52 -0
  70. package/dist/cli/ui/terminal-ui.d.ts.map +1 -0
  71. package/dist/cli/ui/terminal-ui.js +121 -0
  72. package/dist/cli/ui/terminal-ui.js.map +1 -0
  73. package/dist/durable-object/object-store.d.ts +401 -23
  74. package/dist/durable-object/object-store.d.ts.map +1 -1
  75. package/dist/durable-object/object-store.js +414 -25
  76. package/dist/durable-object/object-store.js.map +1 -1
  77. package/dist/durable-object/schema.d.ts +188 -0
  78. package/dist/durable-object/schema.d.ts.map +1 -1
  79. package/dist/durable-object/schema.js +160 -0
  80. package/dist/durable-object/schema.js.map +1 -1
  81. package/dist/durable-object/wal.d.ts +336 -31
  82. package/dist/durable-object/wal.d.ts.map +1 -1
  83. package/dist/durable-object/wal.js +272 -27
  84. package/dist/durable-object/wal.js.map +1 -1
  85. package/dist/index.d.ts +379 -3
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +379 -7
  88. package/dist/index.js.map +1 -1
  89. package/dist/mcp/adapter.d.ts +579 -38
  90. package/dist/mcp/adapter.d.ts.map +1 -1
  91. package/dist/mcp/adapter.js +426 -33
  92. package/dist/mcp/adapter.js.map +1 -1
  93. package/dist/mcp/sandbox.d.ts +532 -29
  94. package/dist/mcp/sandbox.d.ts.map +1 -1
  95. package/dist/mcp/sandbox.js +389 -22
  96. package/dist/mcp/sandbox.js.map +1 -1
  97. package/dist/mcp/sdk-adapter.d.ts +478 -56
  98. package/dist/mcp/sdk-adapter.d.ts.map +1 -1
  99. package/dist/mcp/sdk-adapter.js +346 -44
  100. package/dist/mcp/sdk-adapter.js.map +1 -1
  101. package/dist/mcp/tools.d.ts +445 -30
  102. package/dist/mcp/tools.d.ts.map +1 -1
  103. package/dist/mcp/tools.js +363 -33
  104. package/dist/mcp/tools.js.map +1 -1
  105. package/dist/ops/blame.d.ts +424 -21
  106. package/dist/ops/blame.d.ts.map +1 -1
  107. package/dist/ops/blame.js +303 -20
  108. package/dist/ops/blame.js.map +1 -1
  109. package/dist/ops/branch.d.ts +583 -32
  110. package/dist/ops/branch.d.ts.map +1 -1
  111. package/dist/ops/branch.js +365 -23
  112. package/dist/ops/branch.js.map +1 -1
  113. package/dist/ops/commit-traversal.d.ts +164 -24
  114. package/dist/ops/commit-traversal.d.ts.map +1 -1
  115. package/dist/ops/commit-traversal.js +68 -2
  116. package/dist/ops/commit-traversal.js.map +1 -1
  117. package/dist/ops/commit.d.ts +387 -53
  118. package/dist/ops/commit.d.ts.map +1 -1
  119. package/dist/ops/commit.js +249 -29
  120. package/dist/ops/commit.js.map +1 -1
  121. package/dist/ops/merge-base.d.ts +195 -21
  122. package/dist/ops/merge-base.d.ts.map +1 -1
  123. package/dist/ops/merge-base.js +122 -12
  124. package/dist/ops/merge-base.js.map +1 -1
  125. package/dist/ops/merge.d.ts +600 -130
  126. package/dist/ops/merge.d.ts.map +1 -1
  127. package/dist/ops/merge.js +408 -60
  128. package/dist/ops/merge.js.map +1 -1
  129. package/dist/ops/tag.d.ts +67 -2
  130. package/dist/ops/tag.d.ts.map +1 -1
  131. package/dist/ops/tag.js +42 -1
  132. package/dist/ops/tag.js.map +1 -1
  133. package/dist/ops/tree-builder.d.ts +102 -6
  134. package/dist/ops/tree-builder.d.ts.map +1 -1
  135. package/dist/ops/tree-builder.js +30 -5
  136. package/dist/ops/tree-builder.js.map +1 -1
  137. package/dist/ops/tree-diff.d.ts +50 -2
  138. package/dist/ops/tree-diff.d.ts.map +1 -1
  139. package/dist/ops/tree-diff.js +50 -2
  140. package/dist/ops/tree-diff.js.map +1 -1
  141. package/dist/pack/delta.d.ts +211 -39
  142. package/dist/pack/delta.d.ts.map +1 -1
  143. package/dist/pack/delta.js +232 -46
  144. package/dist/pack/delta.js.map +1 -1
  145. package/dist/pack/format.d.ts +390 -28
  146. package/dist/pack/format.d.ts.map +1 -1
  147. package/dist/pack/format.js +344 -33
  148. package/dist/pack/format.js.map +1 -1
  149. package/dist/pack/full-generation.d.ts +313 -28
  150. package/dist/pack/full-generation.d.ts.map +1 -1
  151. package/dist/pack/full-generation.js +238 -19
  152. package/dist/pack/full-generation.js.map +1 -1
  153. package/dist/pack/generation.d.ts +346 -23
  154. package/dist/pack/generation.d.ts.map +1 -1
  155. package/dist/pack/generation.js +269 -21
  156. package/dist/pack/generation.js.map +1 -1
  157. package/dist/pack/index.d.ts +407 -86
  158. package/dist/pack/index.d.ts.map +1 -1
  159. package/dist/pack/index.js +351 -70
  160. package/dist/pack/index.js.map +1 -1
  161. package/dist/refs/branch.d.ts +517 -71
  162. package/dist/refs/branch.d.ts.map +1 -1
  163. package/dist/refs/branch.js +410 -26
  164. package/dist/refs/branch.js.map +1 -1
  165. package/dist/refs/storage.d.ts +610 -57
  166. package/dist/refs/storage.d.ts.map +1 -1
  167. package/dist/refs/storage.js +481 -29
  168. package/dist/refs/storage.js.map +1 -1
  169. package/dist/refs/tag.d.ts +677 -67
  170. package/dist/refs/tag.d.ts.map +1 -1
  171. package/dist/refs/tag.js +497 -30
  172. package/dist/refs/tag.js.map +1 -1
  173. package/dist/storage/lru-cache.d.ts +556 -53
  174. package/dist/storage/lru-cache.d.ts.map +1 -1
  175. package/dist/storage/lru-cache.js +439 -36
  176. package/dist/storage/lru-cache.js.map +1 -1
  177. package/dist/storage/object-index.d.ts +483 -38
  178. package/dist/storage/object-index.d.ts.map +1 -1
  179. package/dist/storage/object-index.js +388 -22
  180. package/dist/storage/object-index.js.map +1 -1
  181. package/dist/storage/r2-pack.d.ts +957 -94
  182. package/dist/storage/r2-pack.d.ts.map +1 -1
  183. package/dist/storage/r2-pack.js +756 -48
  184. package/dist/storage/r2-pack.js.map +1 -1
  185. package/dist/tiered/cdc-pipeline.d.ts +1610 -38
  186. package/dist/tiered/cdc-pipeline.d.ts.map +1 -1
  187. package/dist/tiered/cdc-pipeline.js +1131 -22
  188. package/dist/tiered/cdc-pipeline.js.map +1 -1
  189. package/dist/tiered/migration.d.ts +903 -41
  190. package/dist/tiered/migration.d.ts.map +1 -1
  191. package/dist/tiered/migration.js +646 -24
  192. package/dist/tiered/migration.js.map +1 -1
  193. package/dist/tiered/parquet-writer.d.ts +944 -47
  194. package/dist/tiered/parquet-writer.d.ts.map +1 -1
  195. package/dist/tiered/parquet-writer.js +667 -39
  196. package/dist/tiered/parquet-writer.js.map +1 -1
  197. package/dist/tiered/read-path.d.ts +728 -34
  198. package/dist/tiered/read-path.d.ts.map +1 -1
  199. package/dist/tiered/read-path.js +310 -27
  200. package/dist/tiered/read-path.js.map +1 -1
  201. package/dist/types/objects.d.ts +457 -0
  202. package/dist/types/objects.d.ts.map +1 -1
  203. package/dist/types/objects.js +305 -4
  204. package/dist/types/objects.js.map +1 -1
  205. package/dist/types/storage.d.ts +407 -35
  206. package/dist/types/storage.d.ts.map +1 -1
  207. package/dist/types/storage.js +27 -3
  208. package/dist/types/storage.js.map +1 -1
  209. package/dist/utils/hash.d.ts +133 -12
  210. package/dist/utils/hash.d.ts.map +1 -1
  211. package/dist/utils/hash.js +133 -12
  212. package/dist/utils/hash.js.map +1 -1
  213. package/dist/utils/sha1.d.ts +102 -9
  214. package/dist/utils/sha1.d.ts.map +1 -1
  215. package/dist/utils/sha1.js +114 -11
  216. package/dist/utils/sha1.js.map +1 -1
  217. package/dist/wire/capabilities.d.ts +896 -88
  218. package/dist/wire/capabilities.d.ts.map +1 -1
  219. package/dist/wire/capabilities.js +566 -62
  220. package/dist/wire/capabilities.js.map +1 -1
  221. package/dist/wire/pkt-line.d.ts +293 -15
  222. package/dist/wire/pkt-line.d.ts.map +1 -1
  223. package/dist/wire/pkt-line.js +251 -15
  224. package/dist/wire/pkt-line.js.map +1 -1
  225. package/dist/wire/receive-pack.d.ts +814 -64
  226. package/dist/wire/receive-pack.d.ts.map +1 -1
  227. package/dist/wire/receive-pack.js +542 -41
  228. package/dist/wire/receive-pack.js.map +1 -1
  229. package/dist/wire/smart-http.d.ts +575 -97
  230. package/dist/wire/smart-http.d.ts.map +1 -1
  231. package/dist/wire/smart-http.js +337 -46
  232. package/dist/wire/smart-http.js.map +1 -1
  233. package/dist/wire/upload-pack.d.ts +492 -98
  234. package/dist/wire/upload-pack.d.ts.map +1 -1
  235. package/dist/wire/upload-pack.js +347 -59
  236. package/dist/wire/upload-pack.js.map +1 -1
  237. package/package.json +10 -2
@@ -1,45 +1,140 @@
1
1
  /**
2
- * R2 Packfile Storage
3
- *
4
- * Manages Git packfiles stored in Cloudflare R2 object storage.
5
- * Provides functionality for:
6
- * - Uploading and downloading packfiles with their indices
7
- * - Multi-pack index (MIDX) for efficient object lookup across packs
8
- * - Concurrent access control with locking
9
- * - Pack verification and integrity checks
2
+ * @fileoverview R2 Packfile Storage Module
3
+ *
4
+ * This module manages Git packfiles stored in Cloudflare R2 object storage.
5
+ * It provides comprehensive functionality for:
6
+ *
7
+ * - **Uploading and downloading packfiles** with their indices using atomic operations
8
+ * - **Multi-pack index (MIDX)** for efficient object lookup across multiple packs
9
+ * - **Concurrent access control** with distributed locking using R2 conditional writes
10
+ * - **Pack verification** and integrity checks via SHA-1 checksums
11
+ * - **Atomic uploads** using a manifest-based pattern to ensure data consistency
12
+ *
13
+ * The module implements Git's packfile format (version 2 and 3) and provides
14
+ * both class-based (`R2PackStorage`) and standalone function APIs for flexibility.
15
+ *
16
+ * @module storage/r2-pack
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // Using the class-based API
21
+ * const storage = new R2PackStorage({
22
+ * bucket: myR2Bucket,
23
+ * prefix: 'repos/my-repo/',
24
+ * cacheSize: 100,
25
+ * cacheTTL: 3600
26
+ * });
27
+ *
28
+ * // Upload a packfile
29
+ * const result = await storage.uploadPackfile(packData, indexData);
30
+ * console.log(`Uploaded pack: ${result.packId}`);
31
+ *
32
+ * // Download with verification
33
+ * const download = await storage.downloadPackfile(result.packId, {
34
+ * verify: true,
35
+ * includeIndex: true
36
+ * });
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Using standalone functions
42
+ * const result = await uploadPackfile(bucket, packData, indexData, {
43
+ * prefix: 'repos/my-repo/'
44
+ * });
45
+ *
46
+ * const packfiles = await listPackfiles(bucket, {
47
+ * prefix: 'repos/my-repo/',
48
+ * limit: 10
49
+ * });
50
+ * ```
10
51
  */
11
52
  /**
12
- * Configuration options for R2PackStorage
53
+ * Configuration options for R2PackStorage.
54
+ *
55
+ * @description
56
+ * Defines the configuration parameters for initializing an R2PackStorage instance.
57
+ * The bucket is required, while other options have sensible defaults.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const options: R2PackStorageOptions = {
62
+ * bucket: env.MY_R2_BUCKET,
63
+ * prefix: 'git-objects/',
64
+ * cacheSize: 200,
65
+ * cacheTTL: 7200
66
+ * };
67
+ * ```
13
68
  */
14
69
  export interface R2PackStorageOptions {
15
- /** R2 bucket instance */
70
+ /**
71
+ * R2 bucket instance for storage operations.
72
+ * This is typically obtained from the Cloudflare Workers environment bindings.
73
+ */
16
74
  bucket: R2Bucket;
17
- /** Optional prefix for all keys (e.g., 'repos/my-repo/') */
75
+ /**
76
+ * Optional prefix for all keys in the bucket.
77
+ * Use this to namespace packfiles for different repositories.
78
+ * @example 'repos/my-repo/' or 'org/project/'
79
+ */
18
80
  prefix?: string;
19
- /** Maximum number of items to cache (default: 100) */
81
+ /**
82
+ * Maximum number of items to cache in memory.
83
+ * Used for caching multi-pack index and other frequently accessed data.
84
+ * @default 100
85
+ */
20
86
  cacheSize?: number;
21
- /** Cache TTL in seconds (default: 3600) */
87
+ /**
88
+ * Cache TTL (Time To Live) in seconds.
89
+ * Cached items will be invalidated after this duration.
90
+ * @default 3600 (1 hour)
91
+ */
22
92
  cacheTTL?: number;
23
93
  }
24
94
  /**
25
- * Result of uploading a packfile
95
+ * Result returned after successfully uploading a packfile.
96
+ *
97
+ * @description
98
+ * Contains metadata about the uploaded packfile including its unique identifier,
99
+ * size information, checksum for verification, and timestamp.
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const result = await storage.uploadPackfile(packData, indexData);
104
+ * console.log(`Pack ID: ${result.packId}`);
105
+ * console.log(`Objects: ${result.objectCount}`);
106
+ * console.log(`Size: ${result.packSize} bytes`);
107
+ * ```
26
108
  */
27
109
  export interface PackfileUploadResult {
28
- /** Unique identifier for the packfile */
110
+ /** Unique identifier for the packfile (format: 'pack-{hex}') */
29
111
  packId: string;
30
112
  /** Size of the pack file in bytes */
31
113
  packSize: number;
32
114
  /** Size of the index file in bytes */
33
115
  indexSize: number;
34
- /** SHA-1 checksum of the packfile */
116
+ /** SHA-1 checksum of the packfile for integrity verification */
35
117
  checksum: string;
36
- /** Number of objects in the packfile */
118
+ /** Number of objects contained in the packfile */
37
119
  objectCount: number;
38
120
  /** Timestamp when the packfile was uploaded */
39
121
  uploadedAt: Date;
40
122
  }
41
123
  /**
42
- * Metadata about a stored packfile
124
+ * Metadata about a stored packfile.
125
+ *
126
+ * @description
127
+ * Provides comprehensive metadata about a packfile stored in R2,
128
+ * including size, object count, creation time, and checksum.
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const metadata = await storage.getPackfileMetadata('pack-abc123');
133
+ * if (metadata) {
134
+ * console.log(`Created: ${metadata.createdAt}`);
135
+ * console.log(`Objects: ${metadata.objectCount}`);
136
+ * }
137
+ * ```
43
138
  */
44
139
  export interface PackfileMetadata {
45
140
  /** Unique identifier for the packfile */
@@ -56,44 +151,123 @@ export interface PackfileMetadata {
56
151
  checksum: string;
57
152
  }
58
153
  /**
59
- * Options for downloading a packfile
154
+ * Options for downloading a packfile.
155
+ *
156
+ * @description
157
+ * Configures the download behavior including whether to include the index,
158
+ * request byte ranges for partial reads, verify checksums, or throw on missing packs.
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * // Download with index and verification
163
+ * const result = await storage.downloadPackfile(packId, {
164
+ * includeIndex: true,
165
+ * verify: true
166
+ * });
167
+ *
168
+ * // Partial download (first 1MB)
169
+ * const partial = await storage.downloadPackfile(packId, {
170
+ * byteRange: { start: 0, end: 1048575 }
171
+ * });
172
+ * ```
60
173
  */
61
174
  export interface DownloadPackfileOptions {
62
175
  /** Include the index file in the download */
63
176
  includeIndex?: boolean;
64
- /** Byte range to download (for partial reads) */
177
+ /**
178
+ * Byte range to download for partial reads.
179
+ * Useful for streaming large packfiles or resuming interrupted downloads.
180
+ */
65
181
  byteRange?: {
66
182
  start: number;
67
183
  end: number;
68
184
  };
69
- /** Verify checksum on download */
185
+ /**
186
+ * Verify checksum on download.
187
+ * When true, computes SHA-1 of downloaded data and compares with stored checksum.
188
+ */
70
189
  verify?: boolean;
71
- /** Throw if packfile not found (default: false, returns null) */
190
+ /**
191
+ * Throw if packfile not found.
192
+ * When true, throws R2PackError instead of returning null.
193
+ * @default false
194
+ */
72
195
  required?: boolean;
73
196
  }
74
197
  /**
75
- * Result of downloading a packfile
198
+ * Result of downloading a packfile.
199
+ *
200
+ * @description
201
+ * Contains the downloaded packfile data and optionally the index data
202
+ * if `includeIndex` was specified in the download options.
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const result = await storage.downloadPackfile(packId, { includeIndex: true });
207
+ * if (result) {
208
+ * console.log(`Pack size: ${result.packData.length}`);
209
+ * if (result.indexData) {
210
+ * console.log(`Index size: ${result.indexData.length}`);
211
+ * }
212
+ * }
213
+ * ```
76
214
  */
77
215
  export interface DownloadPackfileResult {
78
- /** The packfile data */
216
+ /** The packfile data as a Uint8Array */
79
217
  packData: Uint8Array;
80
- /** The index file data (if includeIndex was true) */
218
+ /** The index file data (only present if includeIndex was true) */
81
219
  indexData?: Uint8Array;
82
- /** Whether the checksum was verified */
220
+ /** Whether the checksum was verified (only present if verify was true) */
83
221
  verified?: boolean;
84
222
  }
85
223
  /**
86
- * Options for uploading a packfile
224
+ * Options for uploading a packfile.
225
+ *
226
+ * @description
227
+ * Configures upload behavior including retry count and atomic upload settings.
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * const result = await storage.uploadPackfile(packData, indexData, {
232
+ * retries: 5,
233
+ * skipAtomic: false // Use atomic upload for safety
234
+ * });
235
+ * ```
87
236
  */
88
237
  export interface UploadPackfileOptions {
89
- /** Number of retries on failure */
238
+ /**
239
+ * Number of retries on failure.
240
+ * Each retry uses exponential backoff.
241
+ */
90
242
  retries?: number;
91
- /** Skip atomic upload (for testing/migration) */
243
+ /**
244
+ * Skip atomic upload pattern.
245
+ * Use only for testing or migration scenarios where atomicity is not required.
246
+ * @default false
247
+ */
92
248
  skipAtomic?: boolean;
93
249
  }
94
250
  /**
95
- * Pack manifest for atomic uploads
96
- * A manifest marks a pack as "complete" only after both pack and index are uploaded
251
+ * Pack manifest for atomic uploads.
252
+ *
253
+ * @description
254
+ * A manifest marks a pack as "complete" only after both pack and index are uploaded.
255
+ * This ensures atomic uploads where partial uploads are detected and can be cleaned up.
256
+ *
257
+ * The upload process follows these steps:
258
+ * 1. Upload pack and index to staging paths
259
+ * 2. Create manifest in 'staging' status
260
+ * 3. Copy from staging to final location
261
+ * 4. Update manifest to 'complete' status
262
+ * 5. Clean up staging files
263
+ *
264
+ * @example
265
+ * ```typescript
266
+ * const manifest = await storage.getPackManifest(packId);
267
+ * if (manifest?.status === 'complete') {
268
+ * console.log('Pack upload is complete and verified');
269
+ * }
270
+ * ```
97
271
  */
98
272
  export interface PackManifest {
99
273
  /** Version of the manifest format */
@@ -110,109 +284,290 @@ export interface PackManifest {
110
284
  indexSize: number;
111
285
  /** Number of objects in the packfile */
112
286
  objectCount: number;
113
- /** Timestamp when the pack was completed */
287
+ /** ISO 8601 timestamp when the pack was completed */
114
288
  completedAt: string;
115
- /** Status: 'staging' during upload, 'complete' when done */
289
+ /**
290
+ * Upload status.
291
+ * - 'staging': Upload in progress
292
+ * - 'complete': Upload finished and verified
293
+ */
116
294
  status: 'staging' | 'complete';
117
295
  }
118
296
  /**
119
- * Entry in the multi-pack index
297
+ * Entry in the multi-pack index (MIDX).
298
+ *
299
+ * @description
300
+ * Represents a single object's location within the multi-pack index.
301
+ * Used for efficient O(log n) binary search across all objects in all packs.
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * const entry = lookupObjectInMultiPack(midx, objectId);
306
+ * if (entry) {
307
+ * const packId = midx.packIds[entry.packIndex];
308
+ * console.log(`Object found in pack ${packId} at offset ${entry.offset}`);
309
+ * }
310
+ * ```
120
311
  */
121
312
  export interface MultiPackIndexEntry {
122
313
  /** 40-character hex SHA-1 object ID */
123
314
  objectId: string;
124
315
  /** Index of the pack in the packIds array */
125
316
  packIndex: number;
126
- /** Offset within the pack file */
317
+ /** Byte offset within the pack file where the object data begins */
127
318
  offset: number;
128
319
  }
129
320
  /**
130
- * Multi-pack index structure
321
+ * Multi-pack index (MIDX) structure.
322
+ *
323
+ * @description
324
+ * Provides a single index across multiple pack files for efficient object lookup.
325
+ * Entries are sorted by objectId to enable binary search.
326
+ *
327
+ * The MIDX format follows Git's multi-pack-index specification with:
328
+ * - MIDX signature (4 bytes)
329
+ * - Version number
330
+ * - Pack ID list
331
+ * - Sorted object entries
332
+ * - Trailing checksum
333
+ *
334
+ * @example
335
+ * ```typescript
336
+ * const midx = await storage.getMultiPackIndex();
337
+ * console.log(`Index contains ${midx.entries.length} objects across ${midx.packIds.length} packs`);
338
+ * ```
131
339
  */
132
340
  export interface MultiPackIndex {
133
341
  /** Version of the multi-pack index format */
134
342
  version: number;
135
- /** Array of pack IDs in this index */
343
+ /** Array of pack IDs included in this index */
136
344
  packIds: string[];
137
345
  /** Sorted entries for all objects across all packs */
138
346
  entries: MultiPackIndexEntry[];
139
- /** SHA-1 checksum of the index */
347
+ /** SHA-1 checksum of the index for integrity verification */
140
348
  checksum: Uint8Array;
141
349
  }
142
350
  /**
143
- * Handle for a distributed lock
144
- * Contains all information needed to release or refresh a lock
351
+ * Handle for a distributed lock.
352
+ *
353
+ * @description
354
+ * Contains all information needed to release or refresh a distributed lock.
355
+ * Locks are implemented using R2 conditional writes (ETags) for atomicity.
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * const handle = await storage.acquireDistributedLock('my-resource', 30000);
360
+ * if (handle) {
361
+ * try {
362
+ * // Do work while holding the lock
363
+ * await storage.refreshDistributedLock(handle, 30000); // Extend TTL
364
+ * } finally {
365
+ * await storage.releaseDistributedLock(handle);
366
+ * }
367
+ * }
368
+ * ```
145
369
  */
146
370
  export interface LockHandle {
147
- /** Resource that is locked */
371
+ /** Resource identifier that is locked */
148
372
  resource: string;
149
- /** Unique lock ID for this holder */
373
+ /** Unique lock ID for this holder (used for ownership verification) */
150
374
  lockId: string;
151
- /** ETag for conditional operations */
375
+ /** ETag for conditional operations (ensures lock hasn't been modified) */
152
376
  etag: string;
153
- /** When the lock expires (ms since epoch) */
377
+ /** When the lock expires (milliseconds since epoch) */
154
378
  expiresAt: number;
155
379
  }
156
380
  /**
157
- * Content stored in a lock file
381
+ * Content stored in a lock file.
382
+ *
383
+ * @description
384
+ * The JSON content stored in the R2 lock file. Used for lock ownership
385
+ * verification and debugging lock contention issues.
158
386
  */
159
387
  export interface LockFileContent {
160
- /** Unique lock ID */
388
+ /** Unique lock ID for ownership verification */
161
389
  lockId: string;
162
390
  /** Resource being locked */
163
391
  resource: string;
164
- /** When the lock expires (ms since epoch) */
392
+ /** When the lock expires (milliseconds since epoch) */
165
393
  expiresAt: number;
166
- /** When the lock was acquired (ms since epoch) */
394
+ /** When the lock was acquired (milliseconds since epoch) */
167
395
  acquiredAt: number;
168
- /** Worker/process identifier (for debugging) */
396
+ /** Worker/process identifier for debugging lock contention */
169
397
  holder?: string;
170
398
  }
171
399
  /**
172
- * Lock on a packfile for write operations
400
+ * Lock on a packfile for write operations.
401
+ *
402
+ * @description
403
+ * Provides methods to check lock status, release the lock, and optionally
404
+ * refresh the lock's TTL. Used to prevent concurrent modifications to packfiles.
405
+ *
406
+ * @example
407
+ * ```typescript
408
+ * const lock = await storage.acquireLock(packId, { ttl: 60000 });
409
+ * try {
410
+ * // Perform operations on the packfile
411
+ * if (!lock.isHeld()) {
412
+ * throw new Error('Lock expired!');
413
+ * }
414
+ * } finally {
415
+ * await lock.release();
416
+ * }
417
+ * ```
173
418
  */
174
419
  export interface PackLock {
175
420
  /** Pack ID that is locked */
176
421
  packId: string;
177
- /** Check if lock is still held */
422
+ /** Check if lock is still held (not expired and not released) */
178
423
  isHeld(): boolean;
179
- /** Release the lock */
424
+ /** Release the lock, allowing other processes to acquire it */
180
425
  release(): Promise<void>;
181
- /** Refresh the lock TTL (returns true if successful) */
426
+ /**
427
+ * Refresh the lock TTL.
428
+ * @returns true if refresh succeeded, false if lock was lost
429
+ */
182
430
  refresh?(): Promise<boolean>;
183
- /** Get the underlying distributed lock handle */
431
+ /** Get the underlying distributed lock handle (for advanced use) */
184
432
  handle?: LockHandle;
185
433
  }
186
434
  /**
187
- * Options for acquiring a lock
435
+ * Options for acquiring a lock.
436
+ *
437
+ * @description
438
+ * Configures lock acquisition behavior including timeout, TTL, and holder identification.
439
+ *
440
+ * @example
441
+ * ```typescript
442
+ * const lock = await storage.acquireLock(packId, {
443
+ * timeout: 10000, // Wait up to 10 seconds
444
+ * ttl: 30000, // Lock expires after 30 seconds
445
+ * holder: 'worker-1'
446
+ * });
447
+ * ```
188
448
  */
189
449
  export interface AcquireLockOptions {
190
- /** Timeout in milliseconds to wait for lock */
450
+ /**
451
+ * Timeout in milliseconds to wait for lock acquisition.
452
+ * If 0, fails immediately if lock is held.
453
+ * @default 0
454
+ */
191
455
  timeout?: number;
192
- /** TTL in milliseconds after which lock auto-expires */
456
+ /**
457
+ * TTL in milliseconds after which lock auto-expires.
458
+ * Prevents deadlocks if the holder crashes.
459
+ * @default 30000
460
+ */
193
461
  ttl?: number;
194
- /** Worker/process identifier for debugging */
462
+ /** Worker/process identifier for debugging lock contention */
195
463
  holder?: string;
196
464
  }
197
465
  /**
198
- * Result of listing packfiles
466
+ * Result of listing packfiles.
467
+ *
468
+ * @description
469
+ * Contains the list of packfile metadata and an optional cursor for pagination.
470
+ *
471
+ * @example
472
+ * ```typescript
473
+ * let cursor: string | undefined;
474
+ * do {
475
+ * const result = await storage.listPackfiles({ limit: 10, cursor });
476
+ * for (const pack of result.items) {
477
+ * console.log(pack.packId);
478
+ * }
479
+ * cursor = result.cursor;
480
+ * } while (cursor);
481
+ * ```
199
482
  */
200
483
  export interface ListPackfilesResult {
201
484
  /** Array of packfile metadata */
202
485
  items: PackfileMetadata[];
203
- /** Cursor for pagination */
486
+ /** Cursor for fetching the next page of results */
204
487
  cursor?: string;
205
488
  }
206
489
  /**
207
- * Error thrown by R2 pack operations
490
+ * Error thrown by R2 pack operations.
491
+ *
492
+ * @description
493
+ * Custom error class for R2 packfile operations with error codes for
494
+ * programmatic error handling.
495
+ *
496
+ * Error codes:
497
+ * - `NOT_FOUND`: Packfile does not exist
498
+ * - `LOCKED`: Packfile is locked by another process
499
+ * - `INVALID_DATA`: Packfile format is invalid
500
+ * - `CHECKSUM_MISMATCH`: Checksum verification failed
501
+ * - `NETWORK_ERROR`: R2 network/connectivity issue
502
+ *
503
+ * @example
504
+ * ```typescript
505
+ * try {
506
+ * await storage.downloadPackfile(packId, { required: true });
507
+ * } catch (error) {
508
+ * if (error instanceof R2PackError) {
509
+ * switch (error.code) {
510
+ * case 'NOT_FOUND':
511
+ * console.log('Pack does not exist');
512
+ * break;
513
+ * case 'CHECKSUM_MISMATCH':
514
+ * console.log('Pack is corrupted');
515
+ * break;
516
+ * }
517
+ * }
518
+ * }
519
+ * ```
208
520
  */
209
521
  export declare class R2PackError extends Error {
210
522
  readonly code: 'NOT_FOUND' | 'LOCKED' | 'INVALID_DATA' | 'CHECKSUM_MISMATCH' | 'NETWORK_ERROR';
211
523
  readonly packId?: string | undefined;
524
+ /**
525
+ * Creates a new R2PackError.
526
+ *
527
+ * @param message - Human-readable error message
528
+ * @param code - Error code for programmatic handling
529
+ * @param packId - Optional pack ID related to the error
530
+ */
212
531
  constructor(message: string, code: 'NOT_FOUND' | 'LOCKED' | 'INVALID_DATA' | 'CHECKSUM_MISMATCH' | 'NETWORK_ERROR', packId?: string | undefined);
213
532
  }
214
533
  /**
215
- * R2 Packfile Storage class
534
+ * R2 Packfile Storage class.
535
+ *
536
+ * @description
537
+ * Main class for managing Git packfiles in Cloudflare R2 object storage.
538
+ * Provides methods for uploading, downloading, listing, and managing packfiles
539
+ * with support for atomic uploads, distributed locking, and multi-pack indexing.
540
+ *
541
+ * @example
542
+ * ```typescript
543
+ * // Initialize storage
544
+ * const storage = new R2PackStorage({
545
+ * bucket: env.GIT_BUCKET,
546
+ * prefix: 'repos/my-repo/',
547
+ * cacheSize: 100,
548
+ * cacheTTL: 3600
549
+ * });
550
+ *
551
+ * // Upload a packfile atomically
552
+ * const result = await storage.uploadPackfile(packData, indexData);
553
+ *
554
+ * // Download with verification
555
+ * const download = await storage.downloadPackfile(result.packId, {
556
+ * verify: true,
557
+ * includeIndex: true
558
+ * });
559
+ *
560
+ * // List all packfiles
561
+ * const list = await storage.listPackfiles();
562
+ *
563
+ * // Acquire lock for write operations
564
+ * const lock = await storage.acquireLock(packId, { ttl: 30000 });
565
+ * try {
566
+ * // Perform operations
567
+ * } finally {
568
+ * await lock.release();
569
+ * }
570
+ * ```
216
571
  */
217
572
  export declare class R2PackStorage {
218
573
  private _bucket;
@@ -220,11 +575,27 @@ export declare class R2PackStorage {
220
575
  private _cacheTTL;
221
576
  private _midxCache;
222
577
  private _indexChecksums;
578
+ /**
579
+ * Creates a new R2PackStorage instance.
580
+ *
581
+ * @param options - Configuration options for the storage instance
582
+ *
583
+ * @example
584
+ * ```typescript
585
+ * const storage = new R2PackStorage({
586
+ * bucket: env.MY_BUCKET,
587
+ * prefix: 'repos/my-repo/',
588
+ * cacheSize: 100,
589
+ * cacheTTL: 3600
590
+ * });
591
+ * ```
592
+ */
223
593
  constructor(options: R2PackStorageOptions);
224
594
  private _buildKey;
225
595
  /**
226
- * Upload a packfile and its index to R2 atomically
596
+ * Uploads a packfile and its index to R2 atomically.
227
597
  *
598
+ * @description
228
599
  * Uses a manifest-based pattern to ensure atomic uploads:
229
600
  * 1. Upload pack and index to staging paths
230
601
  * 2. Create manifest in 'staging' status
@@ -234,55 +605,224 @@ export declare class R2PackStorage {
234
605
  *
235
606
  * If the process fails at any point, the pack is not considered complete
236
607
  * until a valid manifest with status 'complete' exists.
608
+ *
609
+ * @param packData - Raw packfile bytes (must have valid PACK signature)
610
+ * @param indexData - Pack index file bytes
611
+ * @param options - Optional upload configuration
612
+ *
613
+ * @returns Upload result with pack ID, sizes, checksum, and object count
614
+ *
615
+ * @throws {R2PackError} With code 'INVALID_DATA' if packfile is invalid
616
+ * @throws {R2PackError} With code 'NETWORK_ERROR' if bucket is unavailable
617
+ *
618
+ * @example
619
+ * ```typescript
620
+ * const result = await storage.uploadPackfile(packData, indexData);
621
+ * console.log(`Uploaded: ${result.packId}`);
622
+ * console.log(`Objects: ${result.objectCount}`);
623
+ * console.log(`Checksum: ${result.checksum}`);
624
+ * ```
237
625
  */
238
626
  uploadPackfile(packData: Uint8Array, indexData: Uint8Array, options?: UploadPackfileOptions): Promise<PackfileUploadResult>;
239
627
  /**
240
- * Get the manifest for a packfile
628
+ * Gets the manifest for a packfile.
629
+ *
630
+ * @description
631
+ * Retrieves the manifest JSON that tracks the upload status of a packfile.
632
+ * Returns null if no manifest exists (legacy packs or invalid pack ID).
633
+ *
634
+ * @param packId - Pack identifier to get manifest for
635
+ * @returns Pack manifest or null if not found
636
+ *
637
+ * @example
638
+ * ```typescript
639
+ * const manifest = await storage.getPackManifest('pack-abc123');
640
+ * if (manifest?.status === 'complete') {
641
+ * console.log('Pack is ready for use');
642
+ * } else {
643
+ * console.log('Pack upload is incomplete');
644
+ * }
645
+ * ```
241
646
  */
242
647
  getPackManifest(packId: string): Promise<PackManifest | null>;
243
648
  /**
244
- * Check if a packfile upload is complete
649
+ * Checks if a packfile upload is complete.
245
650
  *
651
+ * @description
246
652
  * A pack is considered complete if:
247
653
  * 1. It has a manifest with status 'complete', OR
248
654
  * 2. It was uploaded before the atomic upload feature (legacy packs without manifest)
249
655
  * AND both .pack and .idx files exist
656
+ *
657
+ * @param packId - Pack identifier to check
658
+ * @returns true if pack is complete and ready for use
659
+ *
660
+ * @example
661
+ * ```typescript
662
+ * if (await storage.isPackComplete(packId)) {
663
+ * const data = await storage.downloadPackfile(packId);
664
+ * }
665
+ * ```
250
666
  */
251
667
  isPackComplete(packId: string): Promise<boolean>;
252
668
  /**
253
- * Download a packfile from R2
669
+ * Downloads a packfile from R2.
670
+ *
671
+ * @description
672
+ * Downloads pack data with optional index file. Verifies pack completeness
673
+ * before downloading and optionally verifies checksum integrity.
674
+ *
675
+ * @param packId - Pack identifier to download
676
+ * @param options - Download options (includeIndex, verify, byteRange, required)
677
+ *
678
+ * @returns Download result with pack data, or null if not found (unless required=true)
679
+ *
680
+ * @throws {R2PackError} With code 'NOT_FOUND' if required=true and pack not found
681
+ * @throws {R2PackError} With code 'CHECKSUM_MISMATCH' if verify=true and verification fails
682
+ *
683
+ * @example
684
+ * ```typescript
685
+ * // Basic download
686
+ * const result = await storage.downloadPackfile(packId);
687
+ *
688
+ * // Download with verification and index
689
+ * const verified = await storage.downloadPackfile(packId, {
690
+ * verify: true,
691
+ * includeIndex: true
692
+ * });
693
+ *
694
+ * // Required download (throws if not found)
695
+ * const required = await storage.downloadPackfile(packId, { required: true });
696
+ * ```
254
697
  */
255
698
  downloadPackfile(packId: string, options?: DownloadPackfileOptions): Promise<DownloadPackfileResult | null>;
256
699
  /**
257
- * Get metadata for a packfile
700
+ * Gets metadata for a packfile.
701
+ *
702
+ * @description
703
+ * Retrieves metadata about a packfile including size, object count,
704
+ * creation time, and checksum without downloading the full pack.
705
+ *
706
+ * @param packId - Pack identifier to get metadata for
707
+ * @returns Packfile metadata or null if not found
708
+ *
709
+ * @example
710
+ * ```typescript
711
+ * const metadata = await storage.getPackfileMetadata(packId);
712
+ * if (metadata) {
713
+ * console.log(`Size: ${metadata.packSize} bytes`);
714
+ * console.log(`Objects: ${metadata.objectCount}`);
715
+ * }
716
+ * ```
258
717
  */
259
718
  getPackfileMetadata(packId: string): Promise<PackfileMetadata | null>;
260
719
  /**
261
- * List all packfiles
720
+ * Lists all packfiles in storage.
721
+ *
722
+ * @description
723
+ * Returns a paginated list of packfile metadata. Use the cursor for
724
+ * fetching subsequent pages of results.
725
+ *
726
+ * @param options - Pagination options (limit, cursor)
727
+ * @returns List of packfile metadata with optional cursor for pagination
728
+ *
729
+ * @example
730
+ * ```typescript
731
+ * // List first 10 packfiles
732
+ * const first = await storage.listPackfiles({ limit: 10 });
733
+ *
734
+ * // Get next page
735
+ * if (first.cursor) {
736
+ * const next = await storage.listPackfiles({ limit: 10, cursor: first.cursor });
737
+ * }
738
+ * ```
262
739
  */
263
740
  listPackfiles(options?: {
264
741
  limit?: number;
265
742
  cursor?: string;
266
743
  }): Promise<ListPackfilesResult & PackfileMetadata[]>;
267
744
  /**
268
- * Delete a packfile, its index, and manifest
745
+ * Deletes a packfile, its index, and manifest.
746
+ *
747
+ * @description
748
+ * Removes all files associated with a packfile and updates the
749
+ * multi-pack index if needed.
750
+ *
751
+ * @param packId - Pack identifier to delete
752
+ * @returns true if pack was deleted, false if it didn't exist
753
+ *
754
+ * @example
755
+ * ```typescript
756
+ * if (await storage.deletePackfile(packId)) {
757
+ * console.log('Pack deleted successfully');
758
+ * } else {
759
+ * console.log('Pack not found');
760
+ * }
761
+ * ```
269
762
  */
270
763
  deletePackfile(packId: string): Promise<boolean>;
271
764
  /**
272
- * Download just the index file for a packfile
765
+ * Downloads just the index file for a packfile.
766
+ *
767
+ * @description
768
+ * Retrieves only the pack index file, useful for object lookups
769
+ * without downloading the full packfile.
770
+ *
771
+ * @param packId - Pack identifier to download index for
772
+ * @returns Index data or null if not found
773
+ *
774
+ * @example
775
+ * ```typescript
776
+ * const indexData = await storage.downloadIndex(packId);
777
+ * if (indexData) {
778
+ * // Parse and use the index
779
+ * }
780
+ * ```
273
781
  */
274
782
  downloadIndex(packId: string): Promise<Uint8Array | null>;
275
783
  /**
276
- * Upload a new index for an existing packfile
784
+ * Uploads a new index for an existing packfile.
785
+ *
786
+ * @description
787
+ * Replaces the index file for an existing packfile. Useful for
788
+ * regenerating corrupted indices or updating index format.
789
+ *
790
+ * @param packId - Pack identifier to upload index for
791
+ * @param indexData - New index file data
792
+ *
793
+ * @throws {R2PackError} With code 'NOT_FOUND' if packfile doesn't exist
794
+ *
795
+ * @example
796
+ * ```typescript
797
+ * const newIndex = generatePackIndex(packData);
798
+ * await storage.uploadIndex(packId, newIndex);
799
+ * ```
277
800
  */
278
801
  uploadIndex(packId: string, indexData: Uint8Array): Promise<void>;
279
802
  /**
280
- * Verify that an index matches its packfile
803
+ * Verifies that an index matches its packfile.
804
+ *
805
+ * @description
806
+ * Compares the current index checksum against the stored checksum
807
+ * to detect corruption or tampering.
808
+ *
809
+ * @param packId - Pack identifier to verify index for
810
+ * @returns true if index is valid, false if missing or corrupted
811
+ *
812
+ * @example
813
+ * ```typescript
814
+ * if (await storage.verifyIndex(packId)) {
815
+ * console.log('Index is valid');
816
+ * } else {
817
+ * console.log('Index needs to be regenerated');
818
+ * }
819
+ * ```
281
820
  */
282
821
  verifyIndex(packId: string): Promise<boolean>;
283
822
  /**
284
- * Clean up orphaned staging files
823
+ * Cleans up orphaned staging files.
285
824
  *
825
+ * @description
286
826
  * This should be called on startup to clean up any staging files
287
827
  * left behind by failed uploads. It will:
288
828
  * 1. List all files in the staging directory
@@ -290,68 +830,277 @@ export declare class R2PackStorage {
290
830
  * 3. If not complete, delete the staging files and any partial final files
291
831
  *
292
832
  * @returns Array of pack IDs that were cleaned up
833
+ *
834
+ * @example
835
+ * ```typescript
836
+ * // Call on worker startup
837
+ * const cleaned = await storage.cleanupOrphanedStagingFiles();
838
+ * if (cleaned.length > 0) {
839
+ * console.log(`Cleaned up ${cleaned.length} orphaned uploads`);
840
+ * }
841
+ * ```
293
842
  */
294
843
  cleanupOrphanedStagingFiles(): Promise<string[]>;
295
844
  /**
296
- * Rebuild the multi-pack index from all packfiles
845
+ * Rebuilds the multi-pack index from all packfiles.
846
+ *
847
+ * @description
848
+ * Creates a new MIDX by scanning all packfiles and building a sorted
849
+ * index of all objects. Call this after adding or removing packs.
850
+ *
851
+ * @example
852
+ * ```typescript
853
+ * await storage.rebuildMultiPackIndex();
854
+ * const midx = await storage.getMultiPackIndex();
855
+ * console.log(`Indexed ${midx.entries.length} objects`);
856
+ * ```
297
857
  */
298
858
  rebuildMultiPackIndex(): Promise<void>;
299
859
  /**
300
- * Get the current multi-pack index
860
+ * Gets the current multi-pack index.
861
+ *
862
+ * @description
863
+ * Returns the MIDX from cache if available and not expired,
864
+ * otherwise fetches from R2. Returns an empty index if none exists.
865
+ *
866
+ * @returns Current multi-pack index
867
+ *
868
+ * @example
869
+ * ```typescript
870
+ * const midx = await storage.getMultiPackIndex();
871
+ * const entry = lookupObjectInMultiPack(midx, objectSha);
872
+ * if (entry) {
873
+ * const packId = midx.packIds[entry.packIndex];
874
+ * console.log(`Object is in pack ${packId}`);
875
+ * }
876
+ * ```
301
877
  */
302
878
  getMultiPackIndex(): Promise<MultiPackIndex>;
303
879
  /**
304
- * Acquire a distributed lock on a resource using R2 conditional writes
880
+ * Acquires a distributed lock on a resource using R2 conditional writes.
881
+ *
882
+ * @description
883
+ * Uses R2's conditional write feature (ETags) to implement distributed locking.
884
+ * Locks automatically expire after the TTL to prevent deadlocks.
885
+ *
305
886
  * @param resource - Resource identifier to lock
306
- * @param ttlMs - Time-to-live in milliseconds (default: 30000)
887
+ * @param ttlMs - Time-to-live in milliseconds
307
888
  * @param holder - Optional identifier for the lock holder (for debugging)
889
+ *
308
890
  * @returns LockHandle if acquired, null if lock is held by another process
891
+ *
892
+ * @example
893
+ * ```typescript
894
+ * const handle = await storage.acquireDistributedLock('my-resource', 30000, 'worker-1');
895
+ * if (handle) {
896
+ * try {
897
+ * // Do work while holding the lock
898
+ * } finally {
899
+ * await storage.releaseDistributedLock(handle);
900
+ * }
901
+ * } else {
902
+ * console.log('Could not acquire lock - resource is busy');
903
+ * }
904
+ * ```
309
905
  */
310
906
  acquireDistributedLock(resource: string, ttlMs?: number, holder?: string): Promise<LockHandle | null>;
311
907
  /**
312
- * Release a distributed lock
908
+ * Releases a distributed lock.
909
+ *
910
+ * @description
911
+ * Releases the lock only if the caller still owns it (verified by lockId).
912
+ * Safe to call even if lock has expired or been taken by another process.
913
+ *
313
914
  * @param handle - Lock handle returned from acquireDistributedLock
915
+ *
916
+ * @example
917
+ * ```typescript
918
+ * const handle = await storage.acquireDistributedLock('resource');
919
+ * if (handle) {
920
+ * try {
921
+ * // Do work
922
+ * } finally {
923
+ * await storage.releaseDistributedLock(handle);
924
+ * }
925
+ * }
926
+ * ```
314
927
  */
315
928
  releaseDistributedLock(handle: LockHandle): Promise<void>;
316
929
  /**
317
- * Refresh a distributed lock to extend its TTL
930
+ * Refreshes a distributed lock to extend its TTL.
931
+ *
932
+ * @description
933
+ * Extends the lock's expiration time. Useful for long-running operations
934
+ * that need to hold the lock longer than the original TTL.
935
+ *
318
936
  * @param handle - Lock handle to refresh
319
- * @param ttlMs - New TTL in milliseconds (default: 30000)
937
+ * @param ttlMs - New TTL in milliseconds
938
+ *
320
939
  * @returns true if refresh succeeded, false if lock was lost
940
+ *
941
+ * @example
942
+ * ```typescript
943
+ * const handle = await storage.acquireDistributedLock('resource', 30000);
944
+ * if (handle) {
945
+ * // Do some work...
946
+ *
947
+ * // Extend the lock for another 30 seconds
948
+ * if (await storage.refreshDistributedLock(handle, 30000)) {
949
+ * // Continue working
950
+ * } else {
951
+ * // Lock was lost, abort operation
952
+ * }
953
+ * }
954
+ * ```
321
955
  */
322
956
  refreshDistributedLock(handle: LockHandle, ttlMs?: number): Promise<boolean>;
323
957
  /**
324
- * Clean up expired locks from R2 storage
958
+ * Cleans up expired locks from R2 storage.
959
+ *
960
+ * @description
961
+ * Scans all lock files and removes those that have expired.
325
962
  * This should be called periodically to remove stale lock files
963
+ * left by crashed processes.
964
+ *
326
965
  * @returns Number of locks cleaned up
966
+ *
967
+ * @example
968
+ * ```typescript
969
+ * // Run periodically (e.g., every 5 minutes)
970
+ * const cleaned = await storage.cleanupExpiredLocks();
971
+ * console.log(`Cleaned up ${cleaned} expired locks`);
972
+ * ```
327
973
  */
328
974
  cleanupExpiredLocks(): Promise<number>;
329
975
  /**
330
- * Acquire a lock on a packfile (backward-compatible wrapper)
331
- * Uses distributed locking with R2 conditional writes
976
+ * Acquires a lock on a packfile (backward-compatible wrapper).
977
+ *
978
+ * @description
979
+ * High-level API for acquiring a pack lock with optional timeout.
980
+ * Uses distributed locking with R2 conditional writes internally.
981
+ *
982
+ * @param packId - Pack identifier to lock
983
+ * @param options - Lock acquisition options
984
+ *
985
+ * @returns PackLock interface for managing the lock
986
+ *
987
+ * @throws {R2PackError} With code 'LOCKED' if lock cannot be acquired
988
+ *
989
+ * @example
990
+ * ```typescript
991
+ * const lock = await storage.acquireLock(packId, {
992
+ * timeout: 10000,
993
+ * ttl: 30000,
994
+ * holder: 'my-worker'
995
+ * });
996
+ *
997
+ * try {
998
+ * // Perform pack operations
999
+ * if (lock.refresh) {
1000
+ * await lock.refresh(); // Extend lock if needed
1001
+ * }
1002
+ * } finally {
1003
+ * await lock.release();
1004
+ * }
1005
+ * ```
332
1006
  */
333
1007
  acquireLock(packId: string, options?: AcquireLockOptions): Promise<PackLock>;
334
1008
  }
335
1009
  /**
336
- * Upload a packfile to R2
1010
+ * Uploads a packfile to R2.
1011
+ *
1012
+ * @description
1013
+ * Standalone function for uploading a packfile. Creates a temporary
1014
+ * R2PackStorage instance internally.
1015
+ *
1016
+ * @param bucket - R2 bucket instance
1017
+ * @param packData - Raw packfile bytes
1018
+ * @param indexData - Pack index file bytes
1019
+ * @param options - Optional configuration including prefix
1020
+ *
1021
+ * @returns Upload result with pack ID, sizes, and checksum
1022
+ *
1023
+ * @throws {R2PackError} If packfile is invalid or upload fails
1024
+ *
1025
+ * @example
1026
+ * ```typescript
1027
+ * const result = await uploadPackfile(bucket, packData, indexData, {
1028
+ * prefix: 'repos/my-repo/'
1029
+ * });
1030
+ * console.log(`Uploaded: ${result.packId}`);
1031
+ * ```
337
1032
  */
338
1033
  export declare function uploadPackfile(bucket: R2Bucket, packData: Uint8Array, indexData: Uint8Array, options?: {
339
1034
  prefix?: string;
340
1035
  }): Promise<PackfileUploadResult>;
341
1036
  /**
342
- * Download a packfile from R2
1037
+ * Downloads a packfile from R2.
1038
+ *
1039
+ * @description
1040
+ * Standalone function for downloading a packfile. Creates a temporary
1041
+ * R2PackStorage instance internally.
1042
+ *
1043
+ * @param bucket - R2 bucket instance
1044
+ * @param packId - Pack identifier to download
1045
+ * @param options - Download options and prefix
1046
+ *
1047
+ * @returns Download result or null if not found
1048
+ *
1049
+ * @throws {R2PackError} If required=true and pack not found, or verification fails
1050
+ *
1051
+ * @example
1052
+ * ```typescript
1053
+ * const result = await downloadPackfile(bucket, packId, {
1054
+ * prefix: 'repos/my-repo/',
1055
+ * verify: true
1056
+ * });
1057
+ * ```
343
1058
  */
344
1059
  export declare function downloadPackfile(bucket: R2Bucket, packId: string, options?: DownloadPackfileOptions & {
345
1060
  prefix?: string;
346
1061
  }): Promise<DownloadPackfileResult | null>;
347
1062
  /**
348
- * Get packfile metadata
1063
+ * Gets packfile metadata.
1064
+ *
1065
+ * @description
1066
+ * Standalone function for retrieving packfile metadata without downloading
1067
+ * the full pack.
1068
+ *
1069
+ * @param bucket - R2 bucket instance
1070
+ * @param packId - Pack identifier
1071
+ * @param options - Optional prefix configuration
1072
+ *
1073
+ * @returns Packfile metadata or null if not found
1074
+ *
1075
+ * @example
1076
+ * ```typescript
1077
+ * const metadata = await getPackfileMetadata(bucket, packId);
1078
+ * if (metadata) {
1079
+ * console.log(`Objects: ${metadata.objectCount}`);
1080
+ * }
1081
+ * ```
349
1082
  */
350
1083
  export declare function getPackfileMetadata(bucket: R2Bucket, packId: string, options?: {
351
1084
  prefix?: string;
352
1085
  }): Promise<PackfileMetadata | null>;
353
1086
  /**
354
- * List all packfiles
1087
+ * Lists all packfiles.
1088
+ *
1089
+ * @description
1090
+ * Standalone function for listing packfiles with pagination support.
1091
+ *
1092
+ * @param bucket - R2 bucket instance
1093
+ * @param options - Prefix and pagination options
1094
+ *
1095
+ * @returns Array of packfile metadata
1096
+ *
1097
+ * @example
1098
+ * ```typescript
1099
+ * const packs = await listPackfiles(bucket, {
1100
+ * prefix: 'repos/my-repo/',
1101
+ * limit: 50
1102
+ * });
1103
+ * ```
355
1104
  */
356
1105
  export declare function listPackfiles(bucket: R2Bucket, options?: {
357
1106
  prefix?: string;
@@ -359,34 +1108,148 @@ export declare function listPackfiles(bucket: R2Bucket, options?: {
359
1108
  cursor?: string;
360
1109
  }): Promise<PackfileMetadata[]>;
361
1110
  /**
362
- * Delete a packfile
1111
+ * Deletes a packfile.
1112
+ *
1113
+ * @description
1114
+ * Standalone function for deleting a packfile and its associated files.
1115
+ *
1116
+ * @param bucket - R2 bucket instance
1117
+ * @param packId - Pack identifier to delete
1118
+ * @param options - Optional prefix configuration
1119
+ *
1120
+ * @returns true if deleted, false if not found
1121
+ *
1122
+ * @example
1123
+ * ```typescript
1124
+ * if (await deletePackfile(bucket, packId)) {
1125
+ * console.log('Deleted');
1126
+ * }
1127
+ * ```
363
1128
  */
364
1129
  export declare function deletePackfile(bucket: R2Bucket, packId: string, options?: {
365
1130
  prefix?: string;
366
1131
  }): Promise<boolean>;
367
1132
  /**
368
- * Create a multi-pack index from all packfiles in the bucket
1133
+ * Creates a multi-pack index from all packfiles in the bucket.
1134
+ *
1135
+ * @description
1136
+ * Standalone function that rebuilds the MIDX and returns the result.
1137
+ *
1138
+ * @param bucket - R2 bucket instance
1139
+ * @param options - Optional prefix configuration
1140
+ *
1141
+ * @returns The newly created multi-pack index
1142
+ *
1143
+ * @example
1144
+ * ```typescript
1145
+ * const midx = await createMultiPackIndex(bucket, { prefix: 'repos/my-repo/' });
1146
+ * console.log(`Indexed ${midx.entries.length} objects`);
1147
+ * ```
369
1148
  */
370
1149
  export declare function createMultiPackIndex(bucket: R2Bucket, options?: {
371
1150
  prefix?: string;
372
1151
  }): Promise<MultiPackIndex>;
373
1152
  /**
374
- * Parse a multi-pack index from raw bytes
1153
+ * Parses a multi-pack index from raw bytes.
1154
+ *
1155
+ * @description
1156
+ * Deserializes the binary MIDX format into a MultiPackIndex structure.
1157
+ * Validates the signature and format.
1158
+ *
1159
+ * @param data - Raw MIDX bytes
1160
+ * @returns Parsed multi-pack index
1161
+ *
1162
+ * @throws {R2PackError} With code 'INVALID_DATA' if format is invalid
1163
+ *
1164
+ * @example
1165
+ * ```typescript
1166
+ * const midxData = await bucket.get('packs/multi-pack-index');
1167
+ * if (midxData) {
1168
+ * const midx = parseMultiPackIndex(new Uint8Array(await midxData.arrayBuffer()));
1169
+ * console.log(`Contains ${midx.entries.length} objects`);
1170
+ * }
1171
+ * ```
375
1172
  */
376
1173
  export declare function parseMultiPackIndex(data: Uint8Array): MultiPackIndex;
377
1174
  /**
378
- * Look up an object in the multi-pack index using binary search
1175
+ * Looks up an object in the multi-pack index using binary search.
1176
+ *
1177
+ * @description
1178
+ * Efficiently finds an object's location across all packs using O(log n)
1179
+ * binary search on the sorted entries.
1180
+ *
1181
+ * @param midx - Multi-pack index to search
1182
+ * @param objectId - 40-character hex SHA-1 object ID to find
1183
+ *
1184
+ * @returns Entry with pack index and offset, or null if not found
1185
+ *
1186
+ * @example
1187
+ * ```typescript
1188
+ * const midx = await storage.getMultiPackIndex();
1189
+ * const entry = lookupObjectInMultiPack(midx, 'abc123...');
1190
+ * if (entry) {
1191
+ * const packId = midx.packIds[entry.packIndex];
1192
+ * const offset = entry.offset;
1193
+ * console.log(`Found in ${packId} at offset ${offset}`);
1194
+ * }
1195
+ * ```
379
1196
  */
380
1197
  export declare function lookupObjectInMultiPack(midx: MultiPackIndex, objectId: string): MultiPackIndexEntry | null;
381
1198
  /**
382
- * Acquire a lock on a packfile
1199
+ * Acquires a lock on a packfile.
1200
+ *
1201
+ * @description
1202
+ * Standalone function for acquiring a pack lock using distributed locking.
1203
+ *
1204
+ * @param bucket - R2 bucket instance
1205
+ * @param packId - Pack identifier to lock
1206
+ * @param options - Lock options and prefix
1207
+ *
1208
+ * @returns PackLock interface for managing the lock
1209
+ *
1210
+ * @throws {R2PackError} With code 'LOCKED' if lock cannot be acquired
1211
+ *
1212
+ * @example
1213
+ * ```typescript
1214
+ * const lock = await acquirePackLock(bucket, packId, {
1215
+ * prefix: 'repos/my-repo/',
1216
+ * timeout: 10000,
1217
+ * ttl: 30000
1218
+ * });
1219
+ *
1220
+ * try {
1221
+ * // Do work
1222
+ * } finally {
1223
+ * await lock.release();
1224
+ * }
1225
+ * ```
383
1226
  */
384
1227
  export declare function acquirePackLock(bucket: R2Bucket, packId: string, options?: AcquireLockOptions & {
385
1228
  prefix?: string;
386
1229
  }): Promise<PackLock>;
387
1230
  /**
388
- * Release a lock on a packfile
389
- * Note: This function requires a valid PackLock with a handle to properly release distributed locks
1231
+ * Releases a lock on a packfile.
1232
+ *
1233
+ * @description
1234
+ * Standalone function for releasing a pack lock.
1235
+ *
1236
+ * Note: This function requires a valid PackLock with a handle to properly
1237
+ * release distributed locks. For best results, use the lock.release() method
1238
+ * on the PackLock object returned from acquirePackLock.
1239
+ *
1240
+ * @param bucket - R2 bucket instance
1241
+ * @param packId - Pack identifier to unlock
1242
+ * @param options - Optional prefix configuration
1243
+ *
1244
+ * @example
1245
+ * ```typescript
1246
+ * // Preferred: use lock.release()
1247
+ * const lock = await acquirePackLock(bucket, packId);
1248
+ * await lock.release();
1249
+ *
1250
+ * // Alternative: use standalone function (less safe)
1251
+ * await releasePackLock(bucket, packId);
1252
+ * ```
390
1253
  */
391
1254
  export declare function releasePackLock(bucket: R2Bucket, packId: string, options?: {
392
1255
  prefix?: string;