just-git 1.1.11 → 1.2.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.
@@ -1,4 +1,4 @@
1
- import { f as GitRepo, X as Rejection } from '../hooks-OMCbhUGB.js';
1
+ import { f as GitRepo, X as Rejection } from '../hooks-4DvkF2xT.js';
2
2
 
3
3
  interface GitServerConfig {
4
4
  /**
@@ -37,6 +37,14 @@ interface GitServerConfig {
37
37
  /** Delta window size (default 10). Smaller = faster, worse compression ratio. */
38
38
  deltaWindow?: number;
39
39
  };
40
+ /**
41
+ * Called when the server catches an unhandled error.
42
+ *
43
+ * Defaults to logging `err.message` (no stack trace) to `console.error`.
44
+ * Override to integrate with your own logging, or set to `false` to
45
+ * suppress all error output.
46
+ */
47
+ onError?: false | ((err: unknown, request: Request) => void);
40
48
  }
41
49
  interface GitServer {
42
50
  /** Standard fetch-API handler: (Request) => Response */
@@ -67,32 +75,43 @@ interface ServerHooks {
67
75
  */
68
76
  advertiseRefs?: (event: AdvertiseRefsEvent) => RefAdvertisement[] | void | Promise<RefAdvertisement[] | void>;
69
77
  }
78
+ /** A single ref update within a push. */
70
79
  interface RefUpdate {
80
+ /** Full ref name, e.g. "refs/heads/main". */
71
81
  ref: string;
82
+ /** Previous hash, or null if creating a new ref. */
72
83
  oldHash: string | null;
84
+ /** New hash being pushed. */
73
85
  newHash: string;
86
+ /** Whether the update is a fast-forward. */
74
87
  isFF: boolean;
88
+ /** Whether this creates a new ref. */
75
89
  isCreate: boolean;
90
+ /** Whether this deletes an existing ref. */
76
91
  isDelete: boolean;
77
92
  }
93
+ /** Fired after objects are unpacked but before refs are updated. */
78
94
  interface PreReceiveEvent {
79
95
  repo: GitRepo;
80
96
  repoPath: string;
81
97
  updates: readonly RefUpdate[];
82
98
  request: Request;
83
99
  }
100
+ /** Fired per-ref after preReceive passes. */
84
101
  interface UpdateEvent {
85
102
  repo: GitRepo;
86
103
  repoPath: string;
87
104
  update: RefUpdate;
88
105
  request: Request;
89
106
  }
107
+ /** Fired after all ref updates succeed. */
90
108
  interface PostReceiveEvent {
91
109
  repo: GitRepo;
92
110
  repoPath: string;
93
111
  updates: readonly RefUpdate[];
94
112
  request: Request;
95
113
  }
114
+ /** Fired during ref advertisement (info/refs). */
96
115
  interface AdvertiseRefsEvent {
97
116
  repo: GitRepo;
98
117
  repoPath: string;
@@ -100,6 +119,7 @@ interface AdvertiseRefsEvent {
100
119
  service: "git-upload-pack" | "git-receive-pack";
101
120
  request: Request;
102
121
  }
122
+ /** A ref name and hash advertised to clients during fetch/push discovery. */
103
123
  interface RefAdvertisement {
104
124
  name: string;
105
125
  hash: string;
@@ -161,94 +181,33 @@ declare function toNodeHandler(server: GitServer): (req: NodeHttpRequest, res: N
161
181
  declare function composeHooks(...hookSets: (ServerHooks | undefined)[]): ServerHooks;
162
182
 
163
183
  /**
164
- * High-level server operations for Git Smart HTTP.
165
- *
166
- * Each operation accepts a `GitRepo` (ObjectStore + RefStore)
167
- * and returns protocol-level results. The handler layer is
168
- * responsible for hook invocation and ref application.
184
+ * Opinionated hook presets built on top of the minimal ServerHooks interface.
169
185
  */
170
186
 
171
- interface PackCacheEntry {
172
- packData: Uint8Array;
173
- objectCount: number;
174
- deltaCount: number;
175
- }
187
+ type ResolveRepo = GitServerConfig["resolveRepo"];
176
188
  /**
177
- * Bounded LRU-ish cache for generated packfiles.
189
+ * Wrap a `resolveRepo` function with an authorization check that
190
+ * gates **all** access (clone, fetch, and push).
178
191
  *
179
- * Keyed on `(repoPath, sorted wants)` only caches full clones
180
- * (requests with no `have` lines). Incremental fetches always
181
- * compute fresh packs.
192
+ * The `authorize` callback receives the raw `Request` and returns:
193
+ * - `true` request is allowed, delegate to the inner `resolveRepo`
194
+ * - `false` — respond with 403 Forbidden
195
+ * - `Response` — send as-is (e.g. 401 with `WWW-Authenticate` header)
182
196
  *
183
- * Entries are automatically invalidated when refs change: since the
184
- * cache key includes the exact want hashes, a ref update changes
185
- * the want set on the next client request, producing a cache miss.
186
- */
187
- declare class PackCache {
188
- private entries;
189
- private currentBytes;
190
- private maxBytes;
191
- private hits;
192
- private misses;
193
- constructor(maxBytes?: number);
194
- /** Build a cache key. Returns null for requests with haves (not cacheable). */
195
- static key(repoPath: string, wants: string[], haves: string[]): string | null;
196
- get(key: string): PackCacheEntry | undefined;
197
- set(key: string, entry: PackCacheEntry): void;
198
- get stats(): {
199
- entries: number;
200
- bytes: number;
201
- hits: number;
202
- misses: number;
203
- };
204
- }
205
- interface RefsData {
206
- refs: RefAdvertisement[];
207
- headTarget?: string;
208
- }
209
- /**
210
- * Collect the structured ref list from a repo (no wire encoding).
211
- * The handler can pass this through an advertiseRefs hook to filter,
212
- * then call `buildRefAdvertisementBytes` to produce the wire format.
213
- */
214
- declare function collectRefs(repo: GitRepo): Promise<RefsData>;
215
- /**
216
- * Build the wire-format ref advertisement from a (possibly filtered) ref list.
217
- */
218
- declare function buildRefAdvertisementBytes(refs: RefAdvertisement[], service: "git-upload-pack" | "git-receive-pack", headTarget?: string): Uint8Array;
219
- interface UploadPackOptions {
220
- /** Pack cache instance. When provided, full clones (no haves) are cached. */
221
- cache?: PackCache;
222
- /** Repo path used as part of the cache key. Required when cache is set. */
223
- cacheKey?: string;
224
- /** Skip delta compression — faster pack generation, larger output. */
225
- noDelta?: boolean;
226
- /** Delta window size (default 10). Ignored when noDelta is true. */
227
- deltaWindow?: number;
228
- }
229
- /**
230
- * Handle a `POST /git-upload-pack` request.
197
+ * For push-only authorization, use `createStandardHooks({ authorizePush })`.
198
+ * The two compose naturally:
231
199
  *
232
- * Returns `Uint8Array` for buffered responses (cache hits, deltified packs)
233
- * or `ReadableStream<Uint8Array>` for streaming no-delta responses.
234
- */
235
- declare function handleUploadPack(repo: GitRepo, requestBody: Uint8Array, options?: UploadPackOptions): Promise<Uint8Array | ReadableStream<Uint8Array>>;
236
- interface ReceivePackResult {
237
- updates: RefUpdate[];
238
- unpackOk: boolean;
239
- capabilities: string[];
240
- }
241
- /**
242
- * Ingest a receive-pack request: parse commands, ingest the packfile,
243
- * and compute enriched RefUpdate objects. Does NOT apply ref updates —
244
- * the handler runs hooks first, then applies surviving updates.
245
- */
246
- declare function ingestReceivePack(repo: GitRepo, requestBody: Uint8Array): Promise<ReceivePackResult>;
247
-
248
- /**
249
- * Opinionated hook presets built on top of the minimal ServerHooks interface.
200
+ * ```ts
201
+ * const server = createGitServer({
202
+ * resolveRepo: withAuth(
203
+ * (req) => req.headers.get("Authorization") === `Bearer ${token}`,
204
+ * (repoPath) => storage.repo(repoPath),
205
+ * ),
206
+ * hooks: createStandardHooks({ protectedBranches: ["main"] }),
207
+ * });
208
+ * ```
250
209
  */
251
-
210
+ declare function withAuth(authorize: (request: Request) => boolean | Response | Promise<boolean | Response>, resolveRepo: ResolveRepo): ResolveRepo;
252
211
  interface StandardHooksConfig {
253
212
  /** Branches that cannot be force-pushed to or deleted. */
254
213
  protectedBranches?: string[];
@@ -275,7 +234,7 @@ declare function createStandardHooks(config: StandardHooksConfig): ServerHooks;
275
234
  /**
276
235
  * Abstract storage backend for multi-repo git object and ref storage.
277
236
  *
278
- * Implemented by `SqliteStorage` and `PgStorage`.
237
+ * Implemented by `BunSqliteStorage`, `BetterSqlite3Storage`, and `PgStorage`.
279
238
  */
280
239
  interface Storage {
281
240
  /** Get a `GitRepo` scoped to a specific repo. */
@@ -306,76 +265,79 @@ declare class MemoryStorage implements Storage {
306
265
  private getRefs;
307
266
  }
308
267
 
309
- interface SqliteStatement {
268
+ /** Minimal prepared statement interface matching `bun:sqlite`. */
269
+ interface BunSqliteStatement {
310
270
  run(...params: any[]): void;
311
271
  get(...params: any[]): any;
312
272
  all(...params: any[]): any[];
313
273
  }
314
- interface SqliteDatabase {
274
+ /** Minimal database interface matching `bun:sqlite`'s `Database` class. */
275
+ interface BunSqliteDatabase {
315
276
  run(sql: string): void;
316
- prepare(sql: string): SqliteStatement;
277
+ prepare(sql: string): BunSqliteStatement;
317
278
  transaction<F extends (...args: any[]) => any>(fn: F): (...args: Parameters<F>) => ReturnType<F>;
318
279
  }
280
+ /**
281
+ * SQLite-backed git storage using `bun:sqlite`.
282
+ *
283
+ * ```ts
284
+ * import { Database } from "bun:sqlite";
285
+ * const storage = new BunSqliteStorage(new Database("repos.db"));
286
+ * ```
287
+ */
288
+ declare class BunSqliteStorage implements Storage {
289
+ private db;
290
+ private stmts;
291
+ private ingestTx;
292
+ constructor(db: BunSqliteDatabase);
293
+ repo(repoId: string): GitRepo;
294
+ deleteRepo(repoId: string): Promise<void>;
295
+ }
296
+
297
+ /** Minimal prepared statement interface matching `better-sqlite3`. */
319
298
  interface BetterSqlite3Statement {
320
299
  run(...params: any[]): any;
321
300
  get(...params: any[]): any;
322
301
  all(...params: any[]): any[];
323
302
  }
303
+ /** Minimal database interface matching the `better-sqlite3` `Database` class. */
324
304
  interface BetterSqlite3Database {
325
305
  exec(sql: string): any;
326
306
  prepare(sql: string): BetterSqlite3Statement;
327
307
  transaction<F extends (...args: any[]) => any>(fn: F): (...args: Parameters<F>) => ReturnType<F>;
328
308
  }
329
309
  /**
330
- * Wrap a `better-sqlite3` database into a `SqliteDatabase`.
331
- *
332
- * Adapts `exec` → `run` and coerces `get` results from `undefined`
333
- * to `null` to match the `bun:sqlite` convention.
310
+ * SQLite-backed git storage using `better-sqlite3`.
334
311
  *
335
312
  * ```ts
336
313
  * import Database from "better-sqlite3";
337
- * const db = wrapBetterSqlite3(new Database("repos.sqlite"));
338
- * const storage = new SqliteStorage(db);
314
+ * const storage = new BetterSqlite3Storage(new Database("repos.db"));
339
315
  * ```
340
316
  */
341
- declare function wrapBetterSqlite3(raw: BetterSqlite3Database): SqliteDatabase;
342
- /**
343
- * SQLite-backed git storage with multi-repo support.
344
- *
345
- * Creates and manages `git_objects` and `git_refs` tables in the
346
- * provided database. Multiple repos are partitioned by `repo_id`.
347
- *
348
- * ```ts
349
- * const db = new Database("repos.sqlite");
350
- * const storage = new SqliteStorage(db);
351
- * const server = createGitServer({
352
- * resolve: async (repoPath) => storage.repo(repoPath),
353
- * });
354
- * ```
355
- */
356
- declare class SqliteStorage implements Storage {
317
+ declare class BetterSqlite3Storage implements Storage {
357
318
  private db;
358
319
  private stmts;
359
320
  private ingestTx;
360
- constructor(db: SqliteDatabase);
361
- /** Get a `GitRepo` scoped to a specific repo. */
321
+ constructor(db: BetterSqlite3Database);
362
322
  repo(repoId: string): GitRepo;
363
- /** Delete all objects and refs for a repo. */
364
323
  deleteRepo(repoId: string): Promise<void>;
365
324
  }
366
325
 
326
+ /** Minimal database interface for PostgreSQL. Use {@link wrapPgPool} to adapt a `pg` Pool. */
367
327
  interface PgDatabase {
368
328
  query<T = any>(text: string, values?: any[]): Promise<{
369
329
  rows: T[];
370
330
  }>;
371
331
  transaction<R>(fn: (tx: PgDatabase) => Promise<R>): Promise<R>;
372
332
  }
333
+ /** Minimal pool interface matching the `pg` package's `Pool` class. */
373
334
  interface PgPool {
374
335
  query(text: string, values?: any[]): Promise<{
375
336
  rows: any[];
376
337
  }>;
377
338
  connect(): Promise<PgPoolClient>;
378
339
  }
340
+ /** Minimal pool client interface matching the `pg` package's `PoolClient`. */
379
341
  interface PgPoolClient {
380
342
  query(text: string, values?: any[]): Promise<{
381
343
  rows: any[];
@@ -421,4 +383,4 @@ declare class PgStorage implements Storage {
421
383
  deleteRepo(repoId: string): Promise<void>;
422
384
  }
423
385
 
424
- export { type AdvertiseRefsEvent, type BetterSqlite3Database, type BetterSqlite3Statement, type GitServer, type GitServerConfig, MemoryStorage, type NodeHttpRequest, type NodeHttpResponse, PackCache, type PgDatabase, type PgPool, type PgPoolClient, PgStorage, type PostReceiveEvent, type PreReceiveEvent, type ReceivePackResult, type RefAdvertisement, type RefUpdate, type RefsData, Rejection, type ServerHooks, type SqliteDatabase, type SqliteStatement, SqliteStorage, type StandardHooksConfig, type Storage, type UpdateEvent, type UploadPackOptions, buildRefAdvertisementBytes, collectRefs, composeHooks, createGitServer, createStandardHooks, handleUploadPack, ingestReceivePack, toNodeHandler, wrapBetterSqlite3, wrapPgPool };
386
+ export { type AdvertiseRefsEvent, type BetterSqlite3Database, type BetterSqlite3Statement, BetterSqlite3Storage, type BunSqliteDatabase, type BunSqliteStatement, BunSqliteStorage, type GitServer, type GitServerConfig, MemoryStorage, type PgDatabase, type PgPool, type PgPoolClient, PgStorage, type PostReceiveEvent, type PreReceiveEvent, type RefAdvertisement, type RefUpdate, Rejection, type ServerHooks, type StandardHooksConfig, type Storage, type UpdateEvent, composeHooks, createGitServer, createStandardHooks, toNodeHandler, withAuth, wrapPgPool };