git-fs-s3 0.4.0 → 0.5.0

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 (62) hide show
  1. package/README.md +23 -17
  2. package/dist/{chunk-Z4656PGE.js → chunk-2JP4MS6H.js} +2 -2
  3. package/dist/{chunk-YQFNY6PG.js → chunk-FIFWOMPM.js} +1 -1
  4. package/dist/chunk-FIFWOMPM.js.map +1 -0
  5. package/dist/http.js +3 -3
  6. package/dist/http.js.map +1 -1
  7. package/dist/index.js +2 -3
  8. package/dist/index.js.map +1 -1
  9. package/dist/ops.js +2 -2
  10. package/dist/types/cache.d.ts +81 -0
  11. package/dist/types/edge-utils.d.ts +43 -0
  12. package/dist/types/errors.d.ts +16 -0
  13. package/dist/types/git-errors.d.ts +70 -0
  14. package/dist/types/git-fs.d.ts +60 -0
  15. package/dist/types/git-layout.d.ts +52 -0
  16. package/dist/types/http/index.d.ts +7 -0
  17. package/dist/types/http/info-refs.d.ts +27 -0
  18. package/dist/types/http/pack-reuse.d.ts +26 -0
  19. package/dist/types/http/pkt-line.d.ts +14 -0
  20. package/dist/types/http/reachability.d.ts +36 -0
  21. package/dist/types/http/receive-pack.d.ts +54 -0
  22. package/dist/types/http/repack.d.ts +24 -0
  23. package/dist/types/http/types.d.ts +40 -0
  24. package/dist/types/http/upload-pack.d.ts +21 -0
  25. package/dist/types/index.d.ts +11 -0
  26. package/dist/types/ops/branch.d.ts +38 -0
  27. package/dist/types/ops/commit.d.ts +45 -0
  28. package/dist/types/ops/diff.d.ts +24 -0
  29. package/dist/types/ops/file-history.d.ts +41 -0
  30. package/dist/types/ops/history.d.ts +85 -0
  31. package/dist/types/ops/index.d.ts +9 -0
  32. package/dist/types/ops/last-commit.d.ts +23 -0
  33. package/dist/types/ops/merge.d.ts +28 -0
  34. package/dist/types/ops/tree.d.ts +19 -0
  35. package/dist/{types-BHoHOaQt.d.cts → types/ops/types.d.ts} +7 -9
  36. package/dist/types/pack-files.d.ts +28 -0
  37. package/dist/types/path.d.ts +9 -0
  38. package/dist/types/refs.d.ts +54 -0
  39. package/dist/types/retry.d.ts +52 -0
  40. package/dist/types/stores/memory.d.ts +16 -0
  41. package/dist/{s3.d.ts → types/stores/s3.d.ts} +4 -7
  42. package/dist/{types-dbHzZ4ed.d.ts → types/types.d.ts} +11 -22
  43. package/package.json +18 -22
  44. package/dist/chunk-YQFNY6PG.js.map +0 -1
  45. package/dist/http.cjs +0 -1063
  46. package/dist/http.cjs.map +0 -1
  47. package/dist/http.d.cts +0 -215
  48. package/dist/http.d.ts +0 -215
  49. package/dist/index.cjs +0 -944
  50. package/dist/index.cjs.map +0 -1
  51. package/dist/index.d.cts +0 -479
  52. package/dist/index.d.ts +0 -479
  53. package/dist/ops.cjs +0 -1060
  54. package/dist/ops.cjs.map +0 -1
  55. package/dist/ops.d.cts +0 -302
  56. package/dist/ops.d.ts +0 -302
  57. package/dist/s3.cjs +0 -123
  58. package/dist/s3.cjs.map +0 -1
  59. package/dist/s3.d.cts +0 -36
  60. package/dist/types-BHoHOaQt.d.ts +0 -53
  61. package/dist/types-dbHzZ4ed.d.cts +0 -131
  62. /package/dist/{chunk-Z4656PGE.js.map → chunk-2JP4MS6H.js.map} +0 -0
package/dist/ops.d.ts DELETED
@@ -1,302 +0,0 @@
1
- import { R as Repo, O as OpsHooks } from './types-BHoHOaQt.js';
2
- export { I as IsoGitFs, a as ResultCache, r as resultKeyPrefixes } from './types-BHoHOaQt.js';
3
- import * as git from 'isomorphic-git';
4
-
5
- interface Branch {
6
- name: string;
7
- commit: string;
8
- isDefault: boolean;
9
- }
10
- /**
11
- * Defense in depth for every branch-name argument below: `git.deleteBranch`
12
- * and raw resolveRef/writeRef reads don't validate ref names internally the
13
- * way `git.branch` does (see refs.ts) — guard at the point the primitives are
14
- * actually called, not just at an API boundary far above.
15
- */
16
- declare function assertSafeBranchName(name: string): void;
17
- /**
18
- * Resolve a fully-qualified ref's oid with one read instead of isomorphic-
19
- * git's own `resolveRef`, which does a stat *then* a read for a loose ref
20
- * (two round trips against object storage) — wasteful specifically here,
21
- * where the caller already knows the ref exists (it came from a directory
22
- * listing moments earlier). Reads the loose file directly and falls back to
23
- * `git.resolveRef` only when that doesn't pan out (packed-refs, or anything
24
- * else the plain-loose-file assumption doesn't cover), so correctness for
25
- * those cases is unchanged — this only removes the redundant round trip on
26
- * the common path.
27
- */
28
- declare function resolveLooseRefFast(repo: Repo, ref: string): Promise<string>;
29
- /** All branches with their tip commits; [] for an empty repository. */
30
- declare function listBranches(repo: Repo): Promise<Branch[]>;
31
- /** Create `name` pointing at the tip of `startPoint` (no checkout). */
32
- declare function createBranchFrom(repo: Repo, name: string, startPoint?: string): Promise<void>;
33
- /** Delete a branch ref (validated — deleteBranch has no internal ref check). */
34
- declare function deleteBranchByName(repo: Repo, name: string): Promise<void>;
35
- /** Throws (NotFoundError) unless the branch resolves. */
36
- declare function assertBranchExists(repo: Repo, name: string): Promise<void>;
37
-
38
- interface CommitAuthor {
39
- name: string;
40
- email: string;
41
- timestamp: number;
42
- timezoneOffset: number;
43
- }
44
- /** An author stamped with the current time. */
45
- declare function authorNow(name: string, email: string): CommitAuthor;
46
- /**
47
- * Write a commit directly to a bare repository — no worktree, no checkout.
48
- * `buildTree` receives the parent commit's tree oid (undefined on an empty
49
- * repo / unborn branch) and returns the new root tree oid; this function
50
- * writes the commit object and force-updates `refs/heads/<branch>`.
51
- *
52
- * Serialize concurrent writers externally (a per-repo lock): the
53
- * resolve-ref → write-ref sequence is not atomic on object storage.
54
- */
55
- declare function writeCommitToBare(repo: Repo, options: {
56
- branch: string;
57
- message: string;
58
- author: CommitAuthor;
59
- buildTree: (parentTreeOid: string | undefined) => Promise<string>;
60
- }): Promise<string>;
61
- /**
62
- * Commit a set of files onto a branch, straight to the bare repo. Each blob
63
- * is written to its own content-addressed key — no shared state between
64
- * files, so they're written in parallel.
65
- */
66
- declare function commitFilesToBare(repo: Repo, options: {
67
- branch: string;
68
- message: string;
69
- author: CommitAuthor;
70
- files: Array<{
71
- path: string;
72
- content: string | Uint8Array;
73
- }>;
74
- }): Promise<string>;
75
- /** Commit the removal of one file from a branch, straight to the bare repo. */
76
- declare function deleteFileFromBare(repo: Repo, options: {
77
- branch: string;
78
- filePath: string;
79
- message: string;
80
- author: CommitAuthor;
81
- }): Promise<string>;
82
-
83
- interface DiffFile {
84
- path: string;
85
- status: "added" | "modified" | "deleted" | "renamed";
86
- additions: number;
87
- deletions: number;
88
- patch: string;
89
- oldPath?: string;
90
- isBinary?: boolean;
91
- oldContent?: string;
92
- newContent?: string;
93
- oldSize?: number;
94
- newSize?: number;
95
- }
96
- interface DiffResult {
97
- files: DiffFile[];
98
- totalAdditions: number;
99
- totalDeletions: number;
100
- totalFiles: number;
101
- }
102
- /** The diff a single commit introduced (against its first parent). */
103
- declare function getCommitDiff(repo: Repo, commitSha: string): Promise<DiffResult>;
104
- /** The diff between two refs (base -> compare). */
105
- declare function getDiffBetweenRefs(repo: Repo, baseRef: string, compareRef: string): Promise<DiffResult>;
106
-
107
- interface FileHistoryEntry {
108
- sha: string;
109
- message: string;
110
- authorName: string;
111
- authorEmail: string;
112
- createdAt: string;
113
- }
114
- interface FileHistoryResult {
115
- entries: FileHistoryEntry[];
116
- /**
117
- * True when the walk hit its depth budget (or the requested `limit`)
118
- * before exhausting the branch's full commit chain — there may be older
119
- * commits touching this file that a deeper walk would surface.
120
- */
121
- truncated: boolean;
122
- }
123
- /**
124
- * Default walk bound for a caller that actually wants deep history (a file's
125
- * "History" tab). Walking the full chain is round-trip-bound on object
126
- * storage, so cap how far back a single request will look.
127
- */
128
- declare const HISTORY_WALK_DEPTH = 400;
129
- /**
130
- * Much shallower default for a "latest commit touching this file" banner that
131
- * only displays `entries[0]` — trades "always finds the true last-touching
132
- * commit" for "finds it if it's reasonably recent", the right call for a
133
- * banner with a full History view a click away.
134
- */
135
- declare const BANNER_WALK_DEPTH = 60;
136
- /**
137
- * All commits (newest first) that changed a single file's blob oid, walking
138
- * the first-parent chain — same approach as getLastCommitsForTree but for one
139
- * path and collecting every match instead of stopping at the first.
140
- */
141
- declare function getFileHistory(repo: Repo, options: {
142
- ref: string;
143
- filePath: string;
144
- limit?: number;
145
- maxDepth?: number;
146
- }, hooks?: OpsHooks): Promise<FileHistoryResult>;
147
-
148
- interface TreeEntry {
149
- path: string;
150
- mode: string;
151
- type: "blob" | "tree";
152
- oid: string;
153
- size?: number;
154
- }
155
- /**
156
- * Build/update a git tree by overlaying new blobs onto an existing tree,
157
- * returning the new root tree oid. `entries` maps relative paths to blob oids.
158
- */
159
- declare function upsertTree(repo: Repo, treeOid: string | undefined, entries: Map<string, string>): Promise<string>;
160
- /** Remove a file path from a tree, returning the new root tree oid. */
161
- declare function deleteFromTree(repo: Repo, treeOid: string, filePath: string): Promise<string>;
162
- /** Resolve a path inside a tree to its entry, or null when absent. */
163
- declare function findTreeEntry(repo: Repo, rootTreeOid: string, treePath: string): Promise<TreeEntry | null>;
164
- /** List a tree's direct entries, with paths prefixed by `prefix`. */
165
- declare function listTreeEntries(repo: Repo, treeOid: string, prefix?: string): Promise<TreeEntry[]>;
166
-
167
- interface CommitInfo {
168
- oid: string;
169
- commit: {
170
- message: string;
171
- tree: string;
172
- parent: string[];
173
- author: {
174
- name: string;
175
- email: string;
176
- timestamp: number;
177
- timezoneOffset: number;
178
- };
179
- committer: {
180
- name: string;
181
- email: string;
182
- timestamp: number;
183
- timezoneOffset: number;
184
- };
185
- };
186
- payload: string;
187
- }
188
- /**
189
- * Resolve a branch name / full ref / sha to its commit. The ref not
190
- * resolving (unborn branch, genuinely empty repo) and the ref resolving but
191
- * its commit object being unreadable (storage inconsistency — see
192
- * `wrapMissingObject` above) are different failures with different meanings,
193
- * so only the first is left as a raw isomorphic-git NotFoundError for
194
- * callers to treat as "empty"; the second is wrapped into
195
- * GitObjectNotFoundError specifically so it can't be mistaken for the first
196
- * by an `isNotFound`-style check downstream (see getTreeFromRef/getCommitLog).
197
- */
198
- declare function resolveCommit(repo: Repo, ref: string): Promise<{
199
- oid: string;
200
- commit: git.CommitObject;
201
- }>;
202
- /** Read a blob's bytes by oid. */
203
- declare function getBlob(repo: Repo, sha: string): Promise<Uint8Array>;
204
- /** Read a file's bytes at a ref. Throws GitPathNotFoundError when absent. */
205
- declare function getFileContent(repo: Repo, filePath: string, ref?: string, hooks?: OpsHooks): Promise<Uint8Array>;
206
- /** Read one commit by sha. */
207
- declare function getCommit(repo: Repo, sha: string): Promise<CommitInfo>;
208
- interface CommitLogOptions {
209
- ref?: string;
210
- depth?: number;
211
- /**
212
- * Pass the head sha when the caller already resolved `ref` — resolveRef
213
- * tries several candidate paths in sequence and misses the first few every
214
- * time for a normal branch name, which is pure waste when the sha is known.
215
- */
216
- knownHeadSha?: string;
217
- }
218
- /**
219
- * The commit chain from a ref, newest first. Walking is inherently sequential
220
- * (each commit's oid is only discoverable by reading its child first) and
221
- * network-round-trip-bound against object storage, so the deepest walk seen
222
- * per head is memoized in `hooks.resultCache` and sliced for shallower or
223
- * repeated requests — don't bypass this by calling `git.log` directly.
224
- */
225
- declare function getCommitLog(repo: Repo, options?: CommitLogOptions, hooks?: OpsHooks): Promise<CommitInfo[]>;
226
- /** A file at a ref, decoded for display: utf8 text or base64 when binary. */
227
- declare function getFileFromRef(repo: Repo, filePath: string, ref: string, hooks?: OpsHooks): Promise<{
228
- content: string;
229
- size: number;
230
- isBinary: boolean;
231
- }>;
232
- /**
233
- * List a directory at the tip of a ref. Returns [] for an empty repo/unborn
234
- * branch; throws GitPathNotFoundError when `treePath` doesn't exist. Results
235
- * are memoized per head sha (auto-invalidates on push).
236
- */
237
- declare function getTreeFromRef(repo: Repo, options?: {
238
- ref?: string;
239
- treePath?: string;
240
- }, hooks?: OpsHooks): Promise<TreeEntry[]>;
241
- /**
242
- * A page of commit history from a branch tip. Memoized per head sha; builds
243
- * on {@link getCommitLog}'s walk cache for the underlying chain.
244
- */
245
- declare function getCommitHistory(repo: Repo, options: {
246
- ref: string;
247
- limit?: number;
248
- skip?: number;
249
- }, hooks?: OpsHooks): Promise<CommitInfo[]>;
250
-
251
- interface LastCommitInfo {
252
- sha: string;
253
- message: string;
254
- authorName: string;
255
- authorEmail: string;
256
- createdAt: string;
257
- }
258
- /**
259
- * For each direct child of `treePath` (at the tip of `ref`), find the most
260
- * recent commit that changed it — the tree view's "last commit" column. Walks
261
- * history newest-to-oldest, comparing the directory's tree oid
262
- * commit-to-commit and only descending one level to diff child oids when
263
- * something under the directory actually changed. Preserve the two-phase
264
- * structure (parallel prefetch, then sequential resolve) when touching this —
265
- * the "which entries are still unresolved" state must advance
266
- * commit-by-commit.
267
- */
268
- declare function getLastCommitsForTree(repo: Repo, options: {
269
- ref: string;
270
- treePath?: string;
271
- depth?: number;
272
- }, hooks?: OpsHooks): Promise<Record<string, LastCommitInfo>>;
273
-
274
- interface MergeAnalysis {
275
- canMerge: boolean;
276
- hasConflicts: boolean;
277
- conflictingFiles: string[];
278
- fastForward: boolean;
279
- }
280
- /**
281
- * Cheap pre-merge check: do both branches exist, and is this a fast-forward?
282
- * `canMerge`/`fastForward` are the only fields this actually determines —
283
- * `hasConflicts`/`conflictingFiles` are NOT a real content-conflict check
284
- * (isomorphic-git's `git.merge` doesn't expose a dry-run), they only ever
285
- * reflect "one of the branches couldn't be resolved" (`canMerge: false`).
286
- * Real merge conflicts are only discoverable by actually attempting the
287
- * merge.
288
- */
289
- declare function analyzeMerge(repo: Repo, sourceBranch: string, targetBranch: string): Promise<MergeAnalysis>;
290
- /**
291
- * Attempt a fast-forward merge directly against the bare repo: when source is
292
- * a descendant of target, just move the target ref — no worktree, no new
293
- * commit. Returns null when the merge is not a fast-forward (callers fall
294
- * back to a real three-way merge, which needs a worktree). Serialize with a
295
- * per-repo lock: resolve → writeRef is not atomic.
296
- */
297
- declare function fastForwardMerge(repo: Repo, sourceBranch: string, targetBranch: string): Promise<{
298
- success: true;
299
- commitSha: string;
300
- } | null>;
301
-
302
- export { BANNER_WALK_DEPTH, type Branch, type CommitAuthor, type CommitInfo, type CommitLogOptions, type DiffFile, type DiffResult, type FileHistoryEntry, type FileHistoryResult, HISTORY_WALK_DEPTH, type LastCommitInfo, type MergeAnalysis, OpsHooks, Repo, type TreeEntry, analyzeMerge, assertBranchExists, assertSafeBranchName, authorNow, commitFilesToBare, createBranchFrom, deleteBranchByName, deleteFileFromBare, deleteFromTree, fastForwardMerge, findTreeEntry, getBlob, getCommit, getCommitDiff, getCommitHistory, getCommitLog, getDiffBetweenRefs, getFileContent, getFileFromRef, getFileHistory, getLastCommitsForTree, getTreeFromRef, listBranches, listTreeEntries, resolveCommit, resolveLooseRefFast, upsertTree, writeCommitToBare };
package/dist/s3.cjs DELETED
@@ -1,123 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/stores/s3.ts
21
- var s3_exports = {};
22
- __export(s3_exports, {
23
- S3ObjectStore: () => S3ObjectStore
24
- });
25
- module.exports = __toCommonJS(s3_exports);
26
- var import_client_s3 = require("@aws-sdk/client-s3");
27
- function isNotFound(error) {
28
- if (typeof error !== "object" || error === null) return false;
29
- const err = error;
30
- return err.name === "NoSuchKey" || err.name === "NotFound" || err.$metadata?.httpStatusCode === 404;
31
- }
32
- var S3ObjectStore = class {
33
- client;
34
- bucket;
35
- prefix;
36
- contentType;
37
- constructor(options) {
38
- this.client = options.client;
39
- this.bucket = options.bucket;
40
- this.contentType = options.contentType;
41
- this.prefix = options.prefix ? options.prefix.replace(/\/+$/, "").concat("/") : "";
42
- }
43
- fullKey(key) {
44
- return this.prefix + key;
45
- }
46
- async get(key) {
47
- try {
48
- const response = await this.client.send(
49
- new import_client_s3.GetObjectCommand({ Bucket: this.bucket, Key: this.fullKey(key) })
50
- );
51
- if (!response.Body) return new Uint8Array(0);
52
- return await response.Body.transformToByteArray();
53
- } catch (error) {
54
- if (isNotFound(error)) return null;
55
- throw error;
56
- }
57
- }
58
- async put(key, data) {
59
- await this.client.send(
60
- new import_client_s3.PutObjectCommand({
61
- Bucket: this.bucket,
62
- Key: this.fullKey(key),
63
- Body: data,
64
- ContentType: this.contentType?.(key)
65
- })
66
- );
67
- }
68
- async delete(key) {
69
- await this.client.send(
70
- new import_client_s3.DeleteObjectCommand({ Bucket: this.bucket, Key: this.fullKey(key) })
71
- );
72
- }
73
- async head(key) {
74
- try {
75
- const response = await this.client.send(
76
- new import_client_s3.HeadObjectCommand({ Bucket: this.bucket, Key: this.fullKey(key) })
77
- );
78
- return { size: response.ContentLength ?? 0 };
79
- } catch (error) {
80
- if (isNotFound(error)) return null;
81
- throw error;
82
- }
83
- }
84
- async list(prefix, options) {
85
- const fullPrefix = this.fullKey(prefix);
86
- const limit = options?.limit;
87
- const objects = [];
88
- const prefixes = /* @__PURE__ */ new Set();
89
- let continuationToken;
90
- do {
91
- const response = await this.client.send(
92
- new import_client_s3.ListObjectsV2Command({
93
- Bucket: this.bucket,
94
- Prefix: fullPrefix,
95
- Delimiter: options?.delimiter,
96
- ContinuationToken: continuationToken,
97
- MaxKeys: limit !== void 0 ? Math.min(limit, 1e3) : void 0
98
- })
99
- );
100
- for (const item of response.Contents ?? []) {
101
- if (item.Key === void 0) continue;
102
- objects.push({
103
- key: item.Key.slice(this.prefix.length),
104
- size: item.Size ?? 0
105
- });
106
- }
107
- for (const p of response.CommonPrefixes ?? []) {
108
- if (p.Prefix === void 0) continue;
109
- prefixes.add(p.Prefix.slice(this.prefix.length));
110
- }
111
- if (limit !== void 0 && objects.length + prefixes.size >= limit) {
112
- break;
113
- }
114
- continuationToken = response.NextContinuationToken;
115
- } while (continuationToken);
116
- return { objects, prefixes: [...prefixes] };
117
- }
118
- };
119
- // Annotate the CommonJS export names for ESM import in node:
120
- 0 && (module.exports = {
121
- S3ObjectStore
122
- });
123
- //# sourceMappingURL=s3.cjs.map
package/dist/s3.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/stores/s3.ts"],"sourcesContent":["import {\n\tDeleteObjectCommand,\n\tGetObjectCommand,\n\tHeadObjectCommand,\n\tListObjectsV2Command,\n\tPutObjectCommand,\n\ttype S3Client,\n} from \"@aws-sdk/client-s3\";\nimport type {\n\tListOptions,\n\tListResult,\n\tObjectStat,\n\tObjectStore,\n} from \"../types.js\";\n\nexport interface S3ObjectStoreOptions {\n\t/** A configured S3Client. Works with AWS S3, Cloudflare R2, MinIO, Backblaze B2, … */\n\tclient: S3Client;\n\tbucket: string;\n\t/** Key prefix for every object, e.g. `\"git\"`. Optional. */\n\tprefix?: string;\n\t/**\n\t * Derive a Content-Type header for uploads from the (un-prefixed) key.\n\t * Return `undefined` to let S3 apply its default. Cosmetic — git never\n\t * reads it back — but keeps refs and config human-readable in bucket UIs.\n\t */\n\tcontentType?: (key: string) => string | undefined;\n}\n\nfunction isNotFound(error: unknown): boolean {\n\tif (typeof error !== \"object\" || error === null) return false;\n\tconst err = error as {\n\t\tname?: string;\n\t\t$metadata?: { httpStatusCode?: number };\n\t};\n\treturn (\n\t\terr.name === \"NoSuchKey\" ||\n\t\terr.name === \"NotFound\" ||\n\t\terr.$metadata?.httpStatusCode === 404\n\t);\n}\n\n/**\n * {@link ObjectStore} over any S3-compatible API via `@aws-sdk/client-s3`\n * (peer dependency). One instance per bucket/prefix; reuse a single\n * `S3Client` across stores so HTTP connections are pooled.\n */\nexport class S3ObjectStore implements ObjectStore {\n\tprivate readonly client: S3Client;\n\tprivate readonly bucket: string;\n\tprivate readonly prefix: string;\n\tprivate readonly contentType?: (key: string) => string | undefined;\n\n\tconstructor(options: S3ObjectStoreOptions) {\n\t\tthis.client = options.client;\n\t\tthis.bucket = options.bucket;\n\t\tthis.contentType = options.contentType;\n\t\tthis.prefix = options.prefix\n\t\t\t? options.prefix.replace(/\\/+$/, \"\").concat(\"/\")\n\t\t\t: \"\";\n\t}\n\n\tprivate fullKey(key: string): string {\n\t\treturn this.prefix + key;\n\t}\n\n\tasync get(key: string): Promise<Uint8Array | null> {\n\t\ttry {\n\t\t\tconst response = await this.client.send(\n\t\t\t\tnew GetObjectCommand({ Bucket: this.bucket, Key: this.fullKey(key) }),\n\t\t\t);\n\t\t\tif (!response.Body) return new Uint8Array(0);\n\t\t\treturn await response.Body.transformToByteArray();\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return null;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync put(key: string, data: Uint8Array): Promise<void> {\n\t\tawait this.client.send(\n\t\t\tnew PutObjectCommand({\n\t\t\t\tBucket: this.bucket,\n\t\t\t\tKey: this.fullKey(key),\n\t\t\t\tBody: data,\n\t\t\t\tContentType: this.contentType?.(key),\n\t\t\t}),\n\t\t);\n\t}\n\n\tasync delete(key: string): Promise<void> {\n\t\tawait this.client.send(\n\t\t\tnew DeleteObjectCommand({ Bucket: this.bucket, Key: this.fullKey(key) }),\n\t\t);\n\t}\n\n\tasync head(key: string): Promise<ObjectStat | null> {\n\t\ttry {\n\t\t\tconst response = await this.client.send(\n\t\t\t\tnew HeadObjectCommand({ Bucket: this.bucket, Key: this.fullKey(key) }),\n\t\t\t);\n\t\t\treturn { size: response.ContentLength ?? 0 };\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return null;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync list(prefix: string, options?: ListOptions): Promise<ListResult> {\n\t\tconst fullPrefix = this.fullKey(prefix);\n\t\tconst limit = options?.limit;\n\t\tconst objects: ListResult[\"objects\"] = [];\n\t\tconst prefixes = new Set<string>();\n\t\tlet continuationToken: string | undefined;\n\n\t\tdo {\n\t\t\tconst response = await this.client.send(\n\t\t\t\tnew ListObjectsV2Command({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tPrefix: fullPrefix,\n\t\t\t\t\tDelimiter: options?.delimiter,\n\t\t\t\t\tContinuationToken: continuationToken,\n\t\t\t\t\tMaxKeys: limit !== undefined ? Math.min(limit, 1000) : undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tfor (const item of response.Contents ?? []) {\n\t\t\t\tif (item.Key === undefined) continue;\n\t\t\t\tobjects.push({\n\t\t\t\t\tkey: item.Key.slice(this.prefix.length),\n\t\t\t\t\tsize: item.Size ?? 0,\n\t\t\t\t});\n\t\t\t}\n\t\t\tfor (const p of response.CommonPrefixes ?? []) {\n\t\t\t\tif (p.Prefix === undefined) continue;\n\t\t\t\tprefixes.add(p.Prefix.slice(this.prefix.length));\n\t\t\t}\n\t\t\tif (limit !== undefined && objects.length + prefixes.size >= limit) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcontinuationToken = response.NextContinuationToken;\n\t\t} while (continuationToken);\n\n\t\treturn { objects, prefixes: [...prefixes] };\n\t}\n}\n"],"mappings":"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","names":[]}
package/dist/s3.d.cts DELETED
@@ -1,36 +0,0 @@
1
- import { S3Client } from '@aws-sdk/client-s3';
2
- import { O as ObjectStore, c as ObjectStat, L as ListOptions, d as ListResult } from './types-dbHzZ4ed.cjs';
3
-
4
- interface S3ObjectStoreOptions {
5
- /** A configured S3Client. Works with AWS S3, Cloudflare R2, MinIO, Backblaze B2, … */
6
- client: S3Client;
7
- bucket: string;
8
- /** Key prefix for every object, e.g. `"git"`. Optional. */
9
- prefix?: string;
10
- /**
11
- * Derive a Content-Type header for uploads from the (un-prefixed) key.
12
- * Return `undefined` to let S3 apply its default. Cosmetic — git never
13
- * reads it back — but keeps refs and config human-readable in bucket UIs.
14
- */
15
- contentType?: (key: string) => string | undefined;
16
- }
17
- /**
18
- * {@link ObjectStore} over any S3-compatible API via `@aws-sdk/client-s3`
19
- * (peer dependency). One instance per bucket/prefix; reuse a single
20
- * `S3Client` across stores so HTTP connections are pooled.
21
- */
22
- declare class S3ObjectStore implements ObjectStore {
23
- private readonly client;
24
- private readonly bucket;
25
- private readonly prefix;
26
- private readonly contentType?;
27
- constructor(options: S3ObjectStoreOptions);
28
- private fullKey;
29
- get(key: string): Promise<Uint8Array | null>;
30
- put(key: string, data: Uint8Array): Promise<void>;
31
- delete(key: string): Promise<void>;
32
- head(key: string): Promise<ObjectStat | null>;
33
- list(prefix: string, options?: ListOptions): Promise<ListResult>;
34
- }
35
-
36
- export { S3ObjectStore, type S3ObjectStoreOptions };
@@ -1,53 +0,0 @@
1
- import git__default from 'isomorphic-git';
2
-
3
- /** The fs shape isomorphic-git accepts, derived from its own signatures. */
4
- type IsoGitFs = Parameters<typeof git__default.readTree>[0]["fs"];
5
- /**
6
- * A repository handle: everything isomorphic-git needs to address one bare
7
- * repo. Create it once per request (sharing `cache` across calls is what lets
8
- * isomorphic-git reuse parsed pack indexes) and pass it to every op.
9
- */
10
- interface Repo {
11
- fs: IsoGitFs;
12
- gitdir: string;
13
- /** isomorphic-git's shared parse cache — strongly recommended per repo. */
14
- cache?: object;
15
- }
16
- /**
17
- * Key/value store for memoizing expensive walk results (commit logs, tree
18
- * listings, per-file history). Keys are namespaced `kind:gitdir:headSha:…`,
19
- * so entries self-invalidate on push (new head, new key) — but evict entries
20
- * under {@link resultKeyPrefixes} after rewriting a repo's storage out of
21
- * band, or stale walks leak until your store's own eviction.
22
- */
23
- interface ResultCache {
24
- get<T>(key: string): T | null | undefined;
25
- set(key: string, value: unknown): void;
26
- }
27
- /** Optional instrumentation and tuning hooks accepted by every op. */
28
- interface OpsHooks {
29
- resultCache?: ResultCache;
30
- /** Wrap a timed sub-step (network walk, tree listing). Default: run directly. */
31
- step?: <T>(label: string, fn: () => Promise<T>) => Promise<T>;
32
- /** Diagnostic sink for cache hit/miss and walk summaries. */
33
- onNote?: (message: string) => void;
34
- /**
35
- * Wire pack prefetching (e.g. `GitFs.prefetchPacks`) here so a sequential
36
- * walk doesn't pay one network round trip per commit. Called once before
37
- * history walks of depth >= `prefetchMinDepth` (see below), and
38
- * unconditionally on every cache-miss tree read ({@link getTreeFromRef}) —
39
- * a tree read has no shallow case, it always needs at least the head
40
- * commit's tree object.
41
- */
42
- prefetch?: () => Promise<void>;
43
- /** Minimum walk depth before `prefetch` fires for history walks. Default 5. */
44
- prefetchMinDepth?: number;
45
- }
46
- /**
47
- * The result-cache key prefixes holding entries for `gitdir` — evict these
48
- * from your {@link ResultCache} when the repo's storage was rewritten outside
49
- * a normal push (bulk sync, rename, repack cleanup).
50
- */
51
- declare function resultKeyPrefixes(gitdir: string): string[];
52
-
53
- export { type IsoGitFs as I, type OpsHooks as O, type Repo as R, type ResultCache as a, resultKeyPrefixes as r };
@@ -1,131 +0,0 @@
1
- /**
2
- * Minimal key/value object-storage contract the git filesystem is built on.
3
- *
4
- * Implement this interface to back git with any storage system. Two
5
- * implementations ship with the package: {@link ../stores/memory.MemoryObjectStore}
6
- * and {@link ../stores/s3.S3ObjectStore}.
7
- */
8
- interface ObjectStore {
9
- /** Return the object's bytes, or `null` if the key does not exist. */
10
- get(key: string): Promise<Uint8Array | null>;
11
- /** Create or overwrite the object at `key`. */
12
- put(key: string, data: Uint8Array): Promise<void>;
13
- /** Delete the object at `key`. Must succeed silently if it does not exist. */
14
- delete(key: string): Promise<void>;
15
- /** Return object metadata without fetching the body, or `null` if absent. */
16
- head(key: string): Promise<ObjectStat | null>;
17
- /**
18
- * List keys under `prefix`.
19
- *
20
- * With `delimiter: "/"` the result groups keys the way S3 ListObjectsV2
21
- * does: `objects` holds direct children, `prefixes` holds the common
22
- * prefixes ("subdirectories"). With `limit`, implementations may return
23
- * early after finding that many entries (used for cheap existence checks).
24
- */
25
- list(prefix: string, options?: ListOptions): Promise<ListResult>;
26
- }
27
- interface ObjectStat {
28
- size: number;
29
- }
30
- interface ListOptions {
31
- delimiter?: string;
32
- limit?: number;
33
- }
34
- interface ListResult {
35
- objects: {
36
- key: string;
37
- size: number;
38
- }[];
39
- prefixes: string[];
40
- }
41
- /** What a caller knows about a gitdir it registers with `registerGitdir`. */
42
- interface GitdirFacts {
43
- /**
44
- * Top-level gitdir files this backend never writes, such as
45
- * `packed-refs` or `shallow`; reading or statting them answers ENOENT
46
- * with zero store calls. isomorphic-git probes both on most commands.
47
- */
48
- absentFiles?: readonly string[];
49
- }
50
- /** Options accepted by {@link ../git-fs.createGitFs}. */
51
- interface GitFsOptions {
52
- /**
53
- * Key prefix all paths are stored under, e.g. `"repos/alice/blog"`.
54
- * Defaults to `""` (paths map directly to keys).
55
- */
56
- prefix?: string;
57
- /**
58
- * Track, per git directory, whether any loose objects exist at all.
59
- * Fully packed repositories then skip the doomed round trip probing a
60
- * loose-object path that is guaranteed to miss. The first loose-object
61
- * read under a gitdir detects its hint (one listing) if no explicit
62
- * `detectLooseObjects(gitdir)` call already has.
63
- * Default false.
64
- */
65
- looseObjectHints?: boolean;
66
- /**
67
- * Paths (relative to the fs, before `prefix` is applied) that are known
68
- * never to exist; `readFile`/`stat` answer ENOENT for them with zero
69
- * store calls. Useful for files git probes on every operation but this
70
- * backend never writes, such as `packed-refs` or `shallow` under a known
71
- * gitdir layout. Match precisely — a plain suffix check is wrong, since
72
- * e.g. `refs/heads/packed-refs` is a legal branch ref.
73
- */
74
- isStructurallyAbsent?: (path: string) => boolean;
75
- /** Time-to-live for loose-object hints in milliseconds. Default 3 600 000. */
76
- hintTtlMs?: number;
77
- /** Diagnostic sink for notable fs events (hint detection results). */
78
- onNote?: (message: string) => void;
79
- }
80
- type Encoding = "utf8";
81
- interface ReadFileOptions {
82
- encoding?: Encoding;
83
- }
84
- interface WriteFileOptions {
85
- encoding?: Encoding;
86
- mode?: number;
87
- }
88
- /**
89
- * The stat shape isomorphic-git expects. Object storage has no inodes,
90
- * owners, or modification times, so numeric fields are zero.
91
- */
92
- interface Stat {
93
- type: "file" | "dir";
94
- mode: number;
95
- size: number;
96
- ino: number;
97
- mtimeMs: number;
98
- ctimeMs: number;
99
- uid: number;
100
- gid: number;
101
- dev: number;
102
- mtime: Date;
103
- ctime: Date;
104
- isFile(): boolean;
105
- isDirectory(): boolean;
106
- isSymbolicLink(): boolean;
107
- }
108
- /**
109
- * Promise-based filesystem client compatible with isomorphic-git's `fs`
110
- * option. Declared locally so the package has no dependency on
111
- * isomorphic-git itself.
112
- */
113
- interface GitFsClient {
114
- promises: {
115
- readFile(filepath: string, options?: ReadFileOptions | Encoding): Promise<Uint8Array | string>;
116
- writeFile(filepath: string, data: Uint8Array | string, options?: WriteFileOptions | Encoding): Promise<void>;
117
- unlink(filepath: string): Promise<void>;
118
- readdir(dirpath: string): Promise<string[]>;
119
- mkdir(dirpath: string, options?: {
120
- mode?: number;
121
- }): Promise<void>;
122
- rmdir(dirpath: string): Promise<void>;
123
- stat(filepath: string): Promise<Stat>;
124
- lstat(filepath: string): Promise<Stat>;
125
- readlink(filepath: string): Promise<never>;
126
- symlink(target: string, filepath: string): Promise<never>;
127
- chmod(filepath: string, mode: number): Promise<void>;
128
- };
129
- }
130
-
131
- export type { GitFsClient as G, ListOptions as L, ObjectStore as O, Stat as S, GitdirFacts as a, GitFsOptions as b, ObjectStat as c, ListResult as d };