gitx.do 0.0.2 → 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 +1 -1
@@ -1,26 +1,68 @@
1
1
  /**
2
- * Git receive-pack protocol implementation
3
- *
4
- * The receive-pack service is the server-side of git push. It:
5
- * 1. Advertises refs and capabilities
6
- * 2. Receives ref updates and pack data
7
- * 3. Validates and applies the updates
8
- *
9
- * Protocol flow:
10
- * 1. Server advertises refs with capabilities
11
- * 2. Client sends ref update commands (old-sha new-sha refname)
12
- * 3. Client sends packfile with new objects
13
- * 4. Server validates packfile and updates refs
14
- * 5. Server sends status report (if report-status enabled)
15
- *
16
- * Reference: https://git-scm.com/docs/pack-protocol
17
- * https://git-scm.com/docs/git-receive-pack
2
+ * @fileoverview Git receive-pack Protocol Implementation
3
+ *
4
+ * This module implements the server-side of Git's receive-pack service, which
5
+ * handles `git-push` operations. It receives ref updates and packfile data
6
+ * from clients and applies them to the repository.
7
+ *
8
+ * @module wire/receive-pack
9
+ *
10
+ * ## Protocol Flow
11
+ *
12
+ * 1. **Ref Advertisement**: Server advertises current refs and capabilities
13
+ * 2. **Command Reception**: Client sends ref update commands (old-sha new-sha refname)
14
+ * 3. **Packfile Reception**: Client sends packfile with new objects (if needed)
15
+ * 4. **Validation**: Server validates packfile and ref updates
16
+ * 5. **Application**: Server applies updates and sends status report
17
+ *
18
+ * ## Security Considerations
19
+ *
20
+ * - Validates all SHA-1 hashes before processing
21
+ * - Checks fast-forward constraints for updates
22
+ * - Supports atomic pushes for consistency
23
+ * - Validates ref names according to Git rules
24
+ * - Supports pre-receive, update, and post-receive hooks
25
+ *
26
+ * @see {@link https://git-scm.com/docs/pack-protocol} Git Pack Protocol
27
+ * @see {@link https://git-scm.com/docs/git-receive-pack} git-receive-pack Documentation
28
+ *
29
+ * @example Basic push handling
30
+ * ```typescript
31
+ * import {
32
+ * createReceiveSession,
33
+ * advertiseReceiveRefs,
34
+ * handleReceivePack
35
+ * } from './wire/receive-pack'
36
+ *
37
+ * // Create session and advertise refs
38
+ * const session = createReceiveSession('my-repo')
39
+ * const advertisement = await advertiseReceiveRefs(store, { atomic: true })
40
+ *
41
+ * // Handle push request
42
+ * const response = await handleReceivePack(session, requestBody, store)
43
+ * ```
18
44
  */
19
45
  import { encodePktLine, FLUSH_PKT } from './pkt-line';
20
46
  // ============================================================================
21
47
  // Constants
22
48
  // ============================================================================
23
- /** Zero SHA - used for ref creation and deletion */
49
+ /**
50
+ * Zero SHA - used for ref creation and deletion.
51
+ *
52
+ * @description
53
+ * This 40-character string of zeros is used as a placeholder:
54
+ * - In `oldSha`: indicates a ref is being created (doesn't exist yet)
55
+ * - In `newSha`: indicates a ref is being deleted
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * // Check if this is a create operation
60
+ * const isCreate = cmd.oldSha === ZERO_SHA
61
+ *
62
+ * // Check if this is a delete operation
63
+ * const isDelete = cmd.newSha === ZERO_SHA
64
+ * ```
65
+ */
24
66
  export const ZERO_SHA = '0'.repeat(40);
25
67
  /** SHA-1 regex for validation */
26
68
  const SHA1_REGEX = /^[0-9a-f]{40}$/i;
@@ -31,7 +73,27 @@ const decoder = new TextDecoder();
31
73
  // Capability Functions
32
74
  // ============================================================================
33
75
  /**
34
- * Build capability string for receive-pack
76
+ * Build capability string for receive-pack advertisement.
77
+ *
78
+ * @description
79
+ * Converts a capabilities object into a space-separated string suitable
80
+ * for inclusion in the ref advertisement. Boolean capabilities become
81
+ * simple names, while capabilities with values become "name=value".
82
+ *
83
+ * @param capabilities - Capabilities to advertise
84
+ * @returns Space-separated capability string
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * const caps: ReceivePackCapabilities = {
89
+ * reportStatus: true,
90
+ * deleteRefs: true,
91
+ * atomic: true,
92
+ * agent: 'my-server/1.0'
93
+ * }
94
+ * const str = buildReceiveCapabilityString(caps)
95
+ * // 'report-status delete-refs atomic agent=my-server/1.0'
96
+ * ```
35
97
  */
36
98
  export function buildReceiveCapabilityString(capabilities) {
37
99
  const caps = [];
@@ -56,7 +118,25 @@ export function buildReceiveCapabilityString(capabilities) {
56
118
  return caps.join(' ');
57
119
  }
58
120
  /**
59
- * Parse capabilities from string
121
+ * Parse capabilities from string.
122
+ *
123
+ * @description
124
+ * Parses a space-separated capability string into a structured
125
+ * capabilities object.
126
+ *
127
+ * @param capsString - Space-separated capabilities
128
+ * @returns Parsed capabilities object
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const caps = parseReceiveCapabilities(
133
+ * 'report-status delete-refs atomic agent=git/2.30.0'
134
+ * )
135
+ * // caps.reportStatus === true
136
+ * // caps.deleteRefs === true
137
+ * // caps.atomic === true
138
+ * // caps.agent === 'git/2.30.0'
139
+ * ```
60
140
  */
61
141
  export function parseReceiveCapabilities(capsString) {
62
142
  const caps = {};
@@ -90,7 +170,21 @@ export function parseReceiveCapabilities(capsString) {
90
170
  // Session Management
91
171
  // ============================================================================
92
172
  /**
93
- * Create a new receive-pack session
173
+ * Create a new receive-pack session.
174
+ *
175
+ * @description
176
+ * Initializes a new session for a receive-pack operation. The session
177
+ * tracks state across the protocol phases.
178
+ *
179
+ * @param repoId - Repository identifier for logging/tracking
180
+ * @returns New session object
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const session = createReceiveSession('my-repo')
185
+ * // session.capabilities === {}
186
+ * // session.commands === []
187
+ * ```
94
188
  */
95
189
  export function createReceiveSession(repoId) {
96
190
  return {
@@ -103,7 +197,28 @@ export function createReceiveSession(repoId) {
103
197
  // Ref Advertisement
104
198
  // ============================================================================
105
199
  /**
106
- * Advertise refs to client
200
+ * Advertise refs to client.
201
+ *
202
+ * @description
203
+ * Generates the ref advertisement response for the initial phase of
204
+ * receive-pack. This includes:
205
+ * - HEAD reference with capabilities (or zero SHA for empty repos)
206
+ * - All refs sorted alphabetically
207
+ * - Peeled refs for annotated tags
208
+ *
209
+ * @param store - Object store to get refs from
210
+ * @param capabilities - Optional server capabilities to advertise
211
+ * @returns Pkt-line formatted ref advertisement
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const advertisement = await advertiseReceiveRefs(store, {
216
+ * reportStatus: true,
217
+ * deleteRefs: true,
218
+ * atomic: true
219
+ * })
220
+ * // Send as response to GET /info/refs?service=git-receive-pack
221
+ * ```
107
222
  */
108
223
  export async function advertiseReceiveRefs(store, capabilities) {
109
224
  const refs = await store.getRefs();
@@ -157,7 +272,31 @@ export async function advertiseReceiveRefs(store, capabilities) {
157
272
  // Command Parsing
158
273
  // ============================================================================
159
274
  /**
160
- * Parse a single command line
275
+ * Parse a single command line.
276
+ *
277
+ * @description
278
+ * Parses a ref update command line in the format:
279
+ * `<old-sha> <new-sha> <refname>[NUL<capabilities>]`
280
+ *
281
+ * The first command line may include capabilities after a NUL byte.
282
+ *
283
+ * @param line - Command line to parse
284
+ * @returns Parsed command object
285
+ *
286
+ * @throws {Error} If the line format is invalid or SHAs are malformed
287
+ *
288
+ * @example
289
+ * ```typescript
290
+ * // Simple command
291
+ * const cmd = parseCommandLine(
292
+ * 'abc123... def456... refs/heads/main'
293
+ * )
294
+ *
295
+ * // Command with capabilities (first line)
296
+ * const cmdWithCaps = parseCommandLine(
297
+ * 'abc123... def456... refs/heads/main\0report-status atomic'
298
+ * )
299
+ * ```
161
300
  */
162
301
  export function parseCommandLine(line) {
163
302
  // Check for capabilities after NUL byte
@@ -205,7 +344,9 @@ export function parseCommandLine(line) {
205
344
  }
206
345
  /**
207
346
  * Find flush packet index - must be at start of string or preceded by newline,
208
- * and not be part of a 40-character SHA
347
+ * and not be part of a 40-character SHA.
348
+ *
349
+ * @internal
209
350
  */
210
351
  function findFlushPacket(str, startPos = 0) {
211
352
  let searchPos = startPos;
@@ -232,7 +373,28 @@ function findFlushPacket(str, startPos = 0) {
232
373
  return -1;
233
374
  }
234
375
  /**
235
- * Parse complete receive-pack request
376
+ * Parse complete receive-pack request.
377
+ *
378
+ * @description
379
+ * Parses the full receive-pack request body, extracting:
380
+ * - Ref update commands
381
+ * - Capabilities (from first command)
382
+ * - Push options (if enabled)
383
+ * - Packfile data
384
+ *
385
+ * @param data - Raw request body as Uint8Array
386
+ * @returns Parsed request object
387
+ *
388
+ * @throws {Error} If the request format is invalid
389
+ *
390
+ * @example
391
+ * ```typescript
392
+ * const request = parseReceivePackRequest(requestBody)
393
+ * // request.commands - array of RefUpdateCommand
394
+ * // request.capabilities - capabilities from first command
395
+ * // request.packfile - packfile binary data
396
+ * // request.pushOptions - push options (if enabled)
397
+ * ```
236
398
  */
237
399
  export function parseReceivePackRequest(data) {
238
400
  const str = decoder.decode(data);
@@ -309,7 +471,28 @@ export function parseReceivePackRequest(data) {
309
471
  // Packfile Validation
310
472
  // ============================================================================
311
473
  /**
312
- * Validate packfile structure
474
+ * Validate packfile structure.
475
+ *
476
+ * @description
477
+ * Validates a packfile's structure, including:
478
+ * - PACK signature (4 bytes)
479
+ * - Version number (must be 2 or 3)
480
+ * - Object count
481
+ * - Checksum (if verifyChecksum option is true)
482
+ *
483
+ * @param packfile - Packfile binary data
484
+ * @param options - Validation options
485
+ * @returns Validation result
486
+ *
487
+ * @example
488
+ * ```typescript
489
+ * const result = await validatePackfile(packData, { verifyChecksum: true })
490
+ * if (!result.valid) {
491
+ * console.error('Invalid packfile:', result.error)
492
+ * } else {
493
+ * console.log('Objects in pack:', result.objectCount)
494
+ * }
495
+ * ```
313
496
  */
314
497
  export async function validatePackfile(packfile, options) {
315
498
  // Handle empty packfile
@@ -361,7 +544,27 @@ export async function validatePackfile(packfile, options) {
361
544
  return { valid: true, objectCount };
362
545
  }
363
546
  /**
364
- * Unpack objects from packfile
547
+ * Unpack objects from packfile.
548
+ *
549
+ * @description
550
+ * Extracts and stores objects from a packfile into the object store.
551
+ * Handles both regular objects and delta-compressed objects.
552
+ *
553
+ * @param packfile - Packfile binary data
554
+ * @param _store - Object store to store unpacked objects
555
+ * @param options - Unpack options
556
+ * @returns Unpack result
557
+ *
558
+ * @example
559
+ * ```typescript
560
+ * const result = await unpackObjects(packfile, store, {
561
+ * resolveDelta: true,
562
+ * onProgress: (msg) => console.log(msg)
563
+ * })
564
+ * if (result.success) {
565
+ * console.log('Unpacked', result.objectsUnpacked, 'objects')
566
+ * }
567
+ * ```
365
568
  */
366
569
  export async function unpackObjects(packfile, _store, options) {
367
570
  const unpackedShas = [];
@@ -409,7 +612,29 @@ export async function unpackObjects(packfile, _store, options) {
409
612
  // Ref Validation
410
613
  // ============================================================================
411
614
  /**
412
- * Validate ref name according to git rules
615
+ * Validate ref name according to git rules.
616
+ *
617
+ * @description
618
+ * Validates a ref name against Git's naming rules:
619
+ * - Must not be empty
620
+ * - Must not start or end with `/`
621
+ * - Must not contain `//` or `..`
622
+ * - Must not contain control characters
623
+ * - Must not contain spaces, `~`, `^`, `:`, or `@{`
624
+ * - Must not end with `.lock`
625
+ * - Components must not start with `.`
626
+ *
627
+ * @param refName - Ref name to validate
628
+ * @returns true if the ref name is valid
629
+ *
630
+ * @example
631
+ * ```typescript
632
+ * validateRefName('refs/heads/main') // true
633
+ * validateRefName('refs/heads/feature') // true
634
+ * validateRefName('refs/heads/.hidden') // false (starts with .)
635
+ * validateRefName('refs/heads/a..b') // false (contains ..)
636
+ * validateRefName('refs/heads/a b') // false (contains space)
637
+ * ```
413
638
  */
414
639
  export function validateRefName(refName) {
415
640
  // Must not be empty
@@ -461,7 +686,30 @@ export function validateRefName(refName) {
461
686
  return true;
462
687
  }
463
688
  /**
464
- * Validate fast-forward update
689
+ * Validate fast-forward update.
690
+ *
691
+ * @description
692
+ * Checks if updating a ref from oldSha to newSha is a fast-forward.
693
+ * A fast-forward means oldSha is an ancestor of newSha.
694
+ *
695
+ * Creation and deletion are always allowed (not fast-forward questions).
696
+ *
697
+ * @param oldSha - Current ref value (or ZERO_SHA for create)
698
+ * @param newSha - New ref value (or ZERO_SHA for delete)
699
+ * @param store - Object store to check ancestry
700
+ * @returns true if the update is allowed
701
+ *
702
+ * @example
703
+ * ```typescript
704
+ * // Fast-forward update
705
+ * const ok = await validateFastForward(parent, child, store) // true
706
+ *
707
+ * // Non-fast-forward update
708
+ * const notOk = await validateFastForward(child, parent, store) // false
709
+ *
710
+ * // Creation always allowed
711
+ * const create = await validateFastForward(ZERO_SHA, sha, store) // true
712
+ * ```
465
713
  */
466
714
  export async function validateFastForward(oldSha, newSha, store) {
467
715
  // Creation is always allowed
@@ -476,7 +724,29 @@ export async function validateFastForward(oldSha, newSha, store) {
476
724
  return store.isAncestor(oldSha, newSha);
477
725
  }
478
726
  /**
479
- * Check ref permissions
727
+ * Check ref permissions.
728
+ *
729
+ * @description
730
+ * Checks whether a ref operation is allowed based on:
731
+ * - Protected refs (cannot be modified)
732
+ * - Allowed ref patterns (must match at least one)
733
+ * - Force push restrictions on protected branches
734
+ *
735
+ * @param refName - Ref being modified
736
+ * @param operation - Type of operation
737
+ * @param options - Permission check options
738
+ * @returns Permission check result
739
+ *
740
+ * @example
741
+ * ```typescript
742
+ * const result = await checkRefPermissions(
743
+ * 'refs/heads/main',
744
+ * 'force-update',
745
+ * { protectedRefs: ['refs/heads/main'] }
746
+ * )
747
+ * // result.allowed === false
748
+ * // result.reason === 'force push not allowed on protected branch'
749
+ * ```
480
750
  */
481
751
  export async function checkRefPermissions(refName, operation, options) {
482
752
  // Check protected refs
@@ -502,7 +772,8 @@ export async function checkRefPermissions(refName, operation, options) {
502
772
  return { allowed: true };
503
773
  }
504
774
  /**
505
- * Simple glob pattern matching
775
+ * Simple glob pattern matching.
776
+ * @internal
506
777
  */
507
778
  function matchPattern(str, pattern) {
508
779
  // Convert glob pattern to regex
@@ -517,7 +788,31 @@ function matchPattern(str, pattern) {
517
788
  // Ref Updates
518
789
  // ============================================================================
519
790
  /**
520
- * Process ref update commands
791
+ * Process ref update commands.
792
+ *
793
+ * @description
794
+ * Validates and processes ref update commands without actually
795
+ * applying them. Checks:
796
+ * - Ref name validity
797
+ * - Current ref state matches expected old SHA
798
+ * - Fast-forward constraints (unless force push)
799
+ * - Delete-refs capability for deletions
800
+ *
801
+ * @param session - Current session state
802
+ * @param commands - Commands to process
803
+ * @param store - Object store
804
+ * @param options - Processing options
805
+ * @returns Processing result with per-ref status
806
+ *
807
+ * @example
808
+ * ```typescript
809
+ * const result = await processCommands(session, commands, store)
810
+ * for (const refResult of result.results) {
811
+ * if (!refResult.success) {
812
+ * console.error(`Failed to update ${refResult.refName}: ${refResult.error}`)
813
+ * }
814
+ * }
815
+ * ```
521
816
  */
522
817
  export async function processCommands(session, commands, store, options) {
523
818
  const results = [];
@@ -573,7 +868,20 @@ export async function processCommands(session, commands, store, options) {
573
868
  return { results };
574
869
  }
575
870
  /**
576
- * Update refs in the store
871
+ * Update refs in the store.
872
+ *
873
+ * @description
874
+ * Actually applies ref updates to the object store. Should only be
875
+ * called after validation via processCommands.
876
+ *
877
+ * @param commands - Commands to apply
878
+ * @param store - Object store
879
+ *
880
+ * @example
881
+ * ```typescript
882
+ * // After validation
883
+ * await updateRefs(commands, store)
884
+ * ```
577
885
  */
578
886
  export async function updateRefs(commands, store) {
579
887
  for (const cmd of commands) {
@@ -586,7 +894,25 @@ export async function updateRefs(commands, store) {
586
894
  }
587
895
  }
588
896
  /**
589
- * Atomic ref update - all or nothing
897
+ * Atomic ref update - all or nothing.
898
+ *
899
+ * @description
900
+ * Applies all ref updates atomically. If any update fails, all
901
+ * changes are rolled back to the original state.
902
+ *
903
+ * @param commands - Commands to apply
904
+ * @param store - Object store
905
+ * @returns Atomic update result
906
+ *
907
+ * @example
908
+ * ```typescript
909
+ * const result = await atomicRefUpdate(commands, store)
910
+ * if (result.success) {
911
+ * console.log('All refs updated successfully')
912
+ * } else {
913
+ * console.error('Atomic push failed, all changes rolled back')
914
+ * }
915
+ * ```
590
916
  */
591
917
  export async function atomicRefUpdate(commands, store) {
592
918
  const results = [];
@@ -642,7 +968,32 @@ export async function atomicRefUpdate(commands, store) {
642
968
  }
643
969
  }
644
970
  /**
645
- * Execute pre-receive hook
971
+ * Execute pre-receive hook.
972
+ *
973
+ * @description
974
+ * Runs the pre-receive hook before any refs are updated.
975
+ * The hook receives all commands and can reject the entire push.
976
+ *
977
+ * @param commands - Commands to be executed
978
+ * @param _store - Object store
979
+ * @param hookFn - Hook function to execute
980
+ * @param env - Environment variables for the hook
981
+ * @param options - Hook options
982
+ * @returns Hook result
983
+ *
984
+ * @example
985
+ * ```typescript
986
+ * const result = await executePreReceiveHook(
987
+ * commands,
988
+ * store,
989
+ * async (cmds, env) => {
990
+ * // Validate commands
991
+ * return { success: true }
992
+ * },
993
+ * { GIT_DIR: '/path/to/repo' },
994
+ * { timeout: 30000 }
995
+ * )
996
+ * ```
646
997
  */
647
998
  export async function executePreReceiveHook(commands, _store, hookFn, env = {}, options) {
648
999
  const timeout = options?.timeout || 30000;
@@ -661,7 +1012,30 @@ export async function executePreReceiveHook(commands, _store, hookFn, env = {},
661
1012
  }
662
1013
  }
663
1014
  /**
664
- * Execute update hook for each ref
1015
+ * Execute update hook for each ref.
1016
+ *
1017
+ * @description
1018
+ * Runs the update hook for each ref being updated.
1019
+ * Unlike pre-receive, this hook can reject individual refs.
1020
+ *
1021
+ * @param commands - Commands being executed
1022
+ * @param _store - Object store
1023
+ * @param hookFn - Hook function to execute per-ref
1024
+ * @param env - Environment variables for the hook
1025
+ * @returns Results for each ref
1026
+ *
1027
+ * @example
1028
+ * ```typescript
1029
+ * const { results } = await executeUpdateHook(
1030
+ * commands,
1031
+ * store,
1032
+ * async (refName, oldSha, newSha, env) => {
1033
+ * // Check if update is allowed for this ref
1034
+ * return { success: true }
1035
+ * },
1036
+ * { GIT_DIR: '/path/to/repo' }
1037
+ * )
1038
+ * ```
665
1039
  */
666
1040
  export async function executeUpdateHook(commands, _store, hookFn, env = {}) {
667
1041
  const results = [];
@@ -676,7 +1050,33 @@ export async function executeUpdateHook(commands, _store, hookFn, env = {}) {
676
1050
  return { results };
677
1051
  }
678
1052
  /**
679
- * Execute post-receive hook
1053
+ * Execute post-receive hook.
1054
+ *
1055
+ * @description
1056
+ * Runs the post-receive hook after all refs are updated.
1057
+ * This hook cannot affect the push result but is useful for
1058
+ * notifications, CI triggers, etc.
1059
+ *
1060
+ * @param commands - Commands that were executed
1061
+ * @param results - Results of ref updates
1062
+ * @param _store - Object store
1063
+ * @param hookFn - Hook function to execute
1064
+ * @param options - Hook options
1065
+ * @returns Hook execution result
1066
+ *
1067
+ * @example
1068
+ * ```typescript
1069
+ * const { hookSuccess } = await executePostReceiveHook(
1070
+ * commands,
1071
+ * results,
1072
+ * store,
1073
+ * async (cmds, results, env) => {
1074
+ * // Trigger CI, send notifications, etc.
1075
+ * return { success: true }
1076
+ * },
1077
+ * { pushOptions: ['ci.skip'] }
1078
+ * )
1079
+ * ```
680
1080
  */
681
1081
  export async function executePostReceiveHook(commands, results, _store, hookFn, options) {
682
1082
  // Filter to only successful updates
@@ -696,7 +1096,27 @@ export async function executePostReceiveHook(commands, results, _store, hookFn,
696
1096
  };
697
1097
  }
698
1098
  /**
699
- * Execute post-update hook
1099
+ * Execute post-update hook.
1100
+ *
1101
+ * @description
1102
+ * Runs the post-update hook with the names of successfully updated refs.
1103
+ * Simpler than post-receive, takes only ref names as arguments.
1104
+ *
1105
+ * @param _commands - Commands that were executed
1106
+ * @param results - Results of ref updates
1107
+ * @param hookFn - Hook function to execute
1108
+ *
1109
+ * @example
1110
+ * ```typescript
1111
+ * await executePostUpdateHook(
1112
+ * commands,
1113
+ * results,
1114
+ * async (refNames) => {
1115
+ * console.log('Updated refs:', refNames)
1116
+ * return { success: true }
1117
+ * }
1118
+ * )
1119
+ * ```
700
1120
  */
701
1121
  export async function executePostUpdateHook(_commands, results, hookFn) {
702
1122
  // Get successfully updated ref names
@@ -710,7 +1130,29 @@ export async function executePostUpdateHook(_commands, results, hookFn) {
710
1130
  // Report Status Formatting
711
1131
  // ============================================================================
712
1132
  /**
713
- * Format report-status response
1133
+ * Format report-status response.
1134
+ *
1135
+ * @description
1136
+ * Creates a pkt-line formatted status report response to send
1137
+ * to the client after processing the push. The format is:
1138
+ * 1. Unpack status: "unpack ok" or "unpack <error>"
1139
+ * 2. Ref status lines: "ok <refname>" or "ng <refname> <error>"
1140
+ * 3. Flush packet
1141
+ *
1142
+ * @param input - Status report data
1143
+ * @returns Pkt-line formatted status report
1144
+ *
1145
+ * @example
1146
+ * ```typescript
1147
+ * const report = formatReportStatus({
1148
+ * unpackStatus: 'ok',
1149
+ * refResults: [
1150
+ * { refName: 'refs/heads/main', success: true },
1151
+ * { refName: 'refs/heads/feature', success: false, error: 'non-fast-forward' }
1152
+ * ]
1153
+ * })
1154
+ * // "0010unpack ok\n0019ok refs/heads/main\n002cng refs/heads/feature non-fast-forward\n0000"
1155
+ * ```
714
1156
  */
715
1157
  export function formatReportStatus(input) {
716
1158
  const lines = [];
@@ -731,7 +1173,26 @@ export function formatReportStatus(input) {
731
1173
  return lines.join('');
732
1174
  }
733
1175
  /**
734
- * Format report-status-v2 response
1176
+ * Format report-status-v2 response.
1177
+ *
1178
+ * @description
1179
+ * Creates an extended status report for report-status-v2 capability.
1180
+ * Adds option lines before the unpack status and supports forced
1181
+ * update indication.
1182
+ *
1183
+ * @param input - Status report data
1184
+ * @returns Pkt-line formatted v2 status report
1185
+ *
1186
+ * @example
1187
+ * ```typescript
1188
+ * const report = formatReportStatusV2({
1189
+ * unpackStatus: 'ok',
1190
+ * refResults: [
1191
+ * { refName: 'refs/heads/main', success: true, forced: true }
1192
+ * ],
1193
+ * options: { 'object-format': 'sha1' }
1194
+ * })
1195
+ * ```
735
1196
  */
736
1197
  export function formatReportStatusV2(input) {
737
1198
  const lines = [];
@@ -762,7 +1223,27 @@ export function formatReportStatusV2(input) {
762
1223
  return lines.join('');
763
1224
  }
764
1225
  /**
765
- * Format rejection message
1226
+ * Format rejection message.
1227
+ *
1228
+ * @description
1229
+ * Creates a rejection message in the appropriate format based
1230
+ * on the client's capabilities (side-band or report-status).
1231
+ *
1232
+ * @param refName - Ref that was rejected
1233
+ * @param reason - Reason for rejection
1234
+ * @param options - Formatting options
1235
+ * @returns Formatted rejection message
1236
+ *
1237
+ * @example
1238
+ * ```typescript
1239
+ * // Side-band format
1240
+ * const msg = rejectPush('refs/heads/main', 'protected branch', { sideBand: true })
1241
+ * // Returns Uint8Array with side-band channel 3 message
1242
+ *
1243
+ * // Report-status format
1244
+ * const msg = rejectPush('refs/heads/main', 'protected branch', { reportStatus: true })
1245
+ * // Returns "ng refs/heads/main protected branch"
1246
+ * ```
766
1247
  */
767
1248
  export function rejectPush(refName, reason, options) {
768
1249
  if (options.sideBand) {
@@ -784,7 +1265,27 @@ export function rejectPush(refName, reason, options) {
784
1265
  // Full Receive-Pack Handler
785
1266
  // ============================================================================
786
1267
  /**
787
- * Handle complete receive-pack request
1268
+ * Handle complete receive-pack request.
1269
+ *
1270
+ * @description
1271
+ * This is the main entry point that handles the full receive-pack
1272
+ * protocol flow:
1273
+ * 1. Parse request (commands, capabilities, packfile)
1274
+ * 2. Validate and unpack packfile (if present)
1275
+ * 3. Process each ref update command
1276
+ * 4. Return status report (if requested)
1277
+ *
1278
+ * @param session - Receive pack session
1279
+ * @param request - Raw request data
1280
+ * @param store - Object store
1281
+ * @returns Response data (status report or empty)
1282
+ *
1283
+ * @example
1284
+ * ```typescript
1285
+ * const session = createReceiveSession('my-repo')
1286
+ * const response = await handleReceivePack(session, requestBody, store)
1287
+ * // response contains status report if report-status was enabled
1288
+ * ```
788
1289
  */
789
1290
  export async function handleReceivePack(session, request, store) {
790
1291
  // Parse the request