git-fs-s3 0.4.0 → 0.6.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.
- package/README.md +23 -17
- package/dist/{chunk-YQFNY6PG.js → chunk-FIFWOMPM.js} +1 -1
- package/dist/chunk-FIFWOMPM.js.map +1 -0
- package/dist/{chunk-Z4656PGE.js → chunk-XNSZTA4Y.js} +3 -3
- package/dist/{chunk-Z4656PGE.js.map → chunk-XNSZTA4Y.js.map} +1 -1
- package/dist/http.js +8 -8
- package/dist/http.js.map +1 -1
- package/dist/index.js +2 -3
- package/dist/index.js.map +1 -1
- package/dist/ops.js +15 -18
- package/dist/ops.js.map +1 -1
- package/dist/types/cache.d.ts +81 -0
- package/dist/types/edge-utils.d.ts +43 -0
- package/dist/types/errors.d.ts +16 -0
- package/dist/types/git-errors.d.ts +70 -0
- package/dist/types/git-fs.d.ts +60 -0
- package/dist/types/git-layout.d.ts +52 -0
- package/dist/types/http/index.d.ts +7 -0
- package/dist/types/http/info-refs.d.ts +28 -0
- package/dist/types/http/pack-reuse.d.ts +26 -0
- package/dist/types/http/pkt-line.d.ts +14 -0
- package/dist/types/http/reachability.d.ts +36 -0
- package/dist/types/http/receive-pack.d.ts +55 -0
- package/dist/types/http/repack.d.ts +24 -0
- package/dist/types/http/types.d.ts +40 -0
- package/dist/types/http/upload-pack.d.ts +21 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/ops/branch.d.ts +38 -0
- package/dist/types/ops/commit.d.ts +45 -0
- package/dist/types/ops/diff.d.ts +24 -0
- package/dist/types/ops/file-history.d.ts +41 -0
- package/dist/types/ops/history.d.ts +86 -0
- package/dist/types/ops/index.d.ts +9 -0
- package/dist/types/ops/last-commit.d.ts +23 -0
- package/dist/types/ops/merge.d.ts +28 -0
- package/dist/types/ops/tree.d.ts +19 -0
- package/dist/{types-BHoHOaQt.d.cts → types/ops/types.d.ts} +7 -9
- package/dist/types/pack-files.d.ts +28 -0
- package/dist/types/path.d.ts +9 -0
- package/dist/types/refs.d.ts +54 -0
- package/dist/types/retry.d.ts +52 -0
- package/dist/types/stores/memory.d.ts +16 -0
- package/dist/{s3.d.ts → types/stores/s3.d.ts} +4 -7
- package/dist/{types-dbHzZ4ed.d.ts → types/types.d.ts} +11 -22
- package/package.json +18 -22
- package/dist/chunk-YQFNY6PG.js.map +0 -1
- package/dist/http.cjs +0 -1063
- package/dist/http.cjs.map +0 -1
- package/dist/http.d.cts +0 -215
- package/dist/http.d.ts +0 -215
- package/dist/index.cjs +0 -944
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -479
- package/dist/index.d.ts +0 -479
- package/dist/ops.cjs +0 -1060
- package/dist/ops.cjs.map +0 -1
- package/dist/ops.d.cts +0 -302
- package/dist/ops.d.ts +0 -302
- package/dist/s3.cjs +0 -123
- package/dist/s3.cjs.map +0 -1
- package/dist/s3.d.cts +0 -36
- package/dist/types-BHoHOaQt.d.ts +0 -53
- package/dist/types-dbHzZ4ed.d.cts +0 -131
package/dist/index.cjs
DELETED
|
@@ -1,944 +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/index.ts
|
|
21
|
-
var src_exports = {};
|
|
22
|
-
__export(src_exports, {
|
|
23
|
-
CircuitOpenError: () => CircuitOpenError,
|
|
24
|
-
FsError: () => FsError,
|
|
25
|
-
GitAuthenticationError: () => GitAuthenticationError,
|
|
26
|
-
GitAuthorizationError: () => GitAuthorizationError,
|
|
27
|
-
GitConflictError: () => GitConflictError,
|
|
28
|
-
GitError: () => GitError,
|
|
29
|
-
GitInvalidRequestError: () => GitInvalidRequestError,
|
|
30
|
-
GitObjectNotFoundError: () => GitObjectNotFoundError,
|
|
31
|
-
GitPathNotFoundError: () => GitPathNotFoundError,
|
|
32
|
-
GitProtocolError: () => GitProtocolError,
|
|
33
|
-
GitRateLimitError: () => GitRateLimitError,
|
|
34
|
-
GitRefNotFoundError: () => GitRefNotFoundError,
|
|
35
|
-
GitRepositoryNotFoundError: () => GitRepositoryNotFoundError,
|
|
36
|
-
MemoryObjectStore: () => MemoryObjectStore,
|
|
37
|
-
PACK_FILE_KINDS: () => PACK_FILE_KINDS,
|
|
38
|
-
READABLE_PACK_FILE_KINDS: () => READABLE_PACK_FILE_KINDS,
|
|
39
|
-
classifyGitdirPath: () => classifyGitdirPath,
|
|
40
|
-
concat: () => concat,
|
|
41
|
-
createCachedStore: () => createCachedStore,
|
|
42
|
-
createGitFs: () => createGitFs,
|
|
43
|
-
createRetryStore: () => createRetryStore,
|
|
44
|
-
decodeAscii: () => decodeAscii,
|
|
45
|
-
decodeUtf8: () => decodeUtf8,
|
|
46
|
-
deflate: () => deflate,
|
|
47
|
-
encodeUtf8: () => encodeUtf8,
|
|
48
|
-
formatErrorResponse: () => formatErrorResponse,
|
|
49
|
-
fromHex: () => fromHex,
|
|
50
|
-
hasNullByte: () => hasNullByte,
|
|
51
|
-
isFullSha: () => isFullSha,
|
|
52
|
-
isMutableGitdirEntry: () => isMutableGitdirEntry,
|
|
53
|
-
isSafeBranchName: () => isSafeBranchName,
|
|
54
|
-
isSafeFullRefName: () => isSafeFullRefName,
|
|
55
|
-
isSafeRefName: () => isSafeRefName,
|
|
56
|
-
isSafeRepoPath: () => isSafeRepoPath,
|
|
57
|
-
packFileName: () => packFileName,
|
|
58
|
-
parseLooseObjectPath: () => parseLooseObjectPath,
|
|
59
|
-
parsePackDirectory: () => parsePackDirectory,
|
|
60
|
-
parsePackFileName: () => parsePackFileName,
|
|
61
|
-
qualifyBranchRef: () => qualifyBranchRef,
|
|
62
|
-
readBlobContent: () => readBlobContent,
|
|
63
|
-
sha1: () => sha1,
|
|
64
|
-
toBase64: () => toBase64,
|
|
65
|
-
toHex: () => toHex
|
|
66
|
-
});
|
|
67
|
-
module.exports = __toCommonJS(src_exports);
|
|
68
|
-
|
|
69
|
-
// src/cache.ts
|
|
70
|
-
var import_lru_cache = require("lru-cache");
|
|
71
|
-
var MISS = /* @__PURE__ */ Symbol("miss");
|
|
72
|
-
function listEntrySize(entry) {
|
|
73
|
-
let size = entry.prefix.length + 16;
|
|
74
|
-
for (const o of entry.result.objects) size += o.key.length + 8;
|
|
75
|
-
for (const p of entry.result.prefixes) size += p.length;
|
|
76
|
-
return size;
|
|
77
|
-
}
|
|
78
|
-
function copyListResult(result) {
|
|
79
|
-
return {
|
|
80
|
-
objects: result.objects.map((o) => ({ ...o })),
|
|
81
|
-
prefixes: [...result.prefixes]
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function createCachedStore(store, options = {}) {
|
|
85
|
-
const maxBytes = options.maxBytes ?? 50 * 1024 * 1024;
|
|
86
|
-
const maxEntryBytes = options.maxEntryBytes ?? Math.ceil(maxBytes / 10);
|
|
87
|
-
const ttl = options.ttlMs ?? 6e4;
|
|
88
|
-
const ttlForKey = options.ttlForKey;
|
|
89
|
-
const cacheMisses = options.cacheMisses ?? false;
|
|
90
|
-
const cacheLists = options.cacheLists ?? false;
|
|
91
|
-
const coalesce = options.coalesce ?? true;
|
|
92
|
-
const copy = options.copy ?? true;
|
|
93
|
-
const clone = (data) => copy ? data.slice() : data;
|
|
94
|
-
const onHit = options.onHit;
|
|
95
|
-
const onMiss = options.onMiss;
|
|
96
|
-
const cache = new import_lru_cache.LRUCache({
|
|
97
|
-
maxSize: maxBytes,
|
|
98
|
-
sizeCalculation: (value) => value === MISS ? 1 : value.byteLength || 1,
|
|
99
|
-
ttl
|
|
100
|
-
});
|
|
101
|
-
const listCache = new import_lru_cache.LRUCache({
|
|
102
|
-
maxSize: Math.max(1, Math.ceil(maxBytes / 10)),
|
|
103
|
-
sizeCalculation: listEntrySize,
|
|
104
|
-
ttl
|
|
105
|
-
});
|
|
106
|
-
const pendingGets = /* @__PURE__ */ new Map();
|
|
107
|
-
const pendingHeads = /* @__PURE__ */ new Map();
|
|
108
|
-
const pendingLists = /* @__PURE__ */ new Map();
|
|
109
|
-
const admit = (key, data) => {
|
|
110
|
-
if (data.byteLength <= maxEntryBytes) {
|
|
111
|
-
cache.set(key, clone(data), { ttl: ttlForKey?.(key) });
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
function clearStaleListEntries(key) {
|
|
115
|
-
for (const [listKey, entry] of listCache.entries()) {
|
|
116
|
-
if (!key.startsWith(entry.prefix)) continue;
|
|
117
|
-
if (entry.probe && !entry.empty) continue;
|
|
118
|
-
listCache.delete(listKey);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
function coalesced(pending, key, fn) {
|
|
122
|
-
if (!coalesce) return fn();
|
|
123
|
-
const inflight = pending.get(key);
|
|
124
|
-
if (inflight !== void 0) return inflight;
|
|
125
|
-
const p = fn().finally(() => pending.delete(key));
|
|
126
|
-
pending.set(key, p);
|
|
127
|
-
return p;
|
|
128
|
-
}
|
|
129
|
-
return {
|
|
130
|
-
async get(key) {
|
|
131
|
-
const cached = cache.get(key);
|
|
132
|
-
if (cached !== void 0) {
|
|
133
|
-
onHit?.(key);
|
|
134
|
-
return cached === MISS ? null : clone(cached);
|
|
135
|
-
}
|
|
136
|
-
const data = await coalesced(pendingGets, key, async () => {
|
|
137
|
-
onMiss?.(key);
|
|
138
|
-
const fetched = await store.get(key);
|
|
139
|
-
if (fetched !== null) {
|
|
140
|
-
admit(key, fetched);
|
|
141
|
-
} else if (cacheMisses) {
|
|
142
|
-
cache.set(key, MISS, { ttl: ttlForKey?.(key) });
|
|
143
|
-
}
|
|
144
|
-
return fetched;
|
|
145
|
-
});
|
|
146
|
-
return data === null ? null : clone(data);
|
|
147
|
-
},
|
|
148
|
-
async put(key, data) {
|
|
149
|
-
await store.put(key, data);
|
|
150
|
-
admit(key, data);
|
|
151
|
-
if (data.byteLength > maxEntryBytes) cache.delete(key);
|
|
152
|
-
clearStaleListEntries(key);
|
|
153
|
-
},
|
|
154
|
-
async delete(key) {
|
|
155
|
-
await store.delete(key);
|
|
156
|
-
if (cacheMisses) {
|
|
157
|
-
cache.set(key, MISS, { ttl: ttlForKey?.(key) });
|
|
158
|
-
} else {
|
|
159
|
-
cache.delete(key);
|
|
160
|
-
}
|
|
161
|
-
clearStaleListEntries(key);
|
|
162
|
-
},
|
|
163
|
-
async head(key) {
|
|
164
|
-
const cached = cache.get(key);
|
|
165
|
-
if (cached !== void 0) {
|
|
166
|
-
onHit?.(key);
|
|
167
|
-
return cached === MISS ? null : { size: cached.byteLength };
|
|
168
|
-
}
|
|
169
|
-
return coalesced(pendingHeads, key, async () => {
|
|
170
|
-
onMiss?.(key);
|
|
171
|
-
const stat = await store.head(key);
|
|
172
|
-
if (stat === null && cacheMisses) {
|
|
173
|
-
cache.set(key, MISS, { ttl: ttlForKey?.(key) });
|
|
174
|
-
}
|
|
175
|
-
return stat;
|
|
176
|
-
});
|
|
177
|
-
},
|
|
178
|
-
async list(prefix, listOptions) {
|
|
179
|
-
if (!cacheLists) return store.list(prefix, listOptions);
|
|
180
|
-
const listKey = `${listOptions?.delimiter ?? ""}|${listOptions?.limit ?? ""}|${prefix}`;
|
|
181
|
-
const cached = listCache.get(listKey);
|
|
182
|
-
if (cached !== void 0) {
|
|
183
|
-
onHit?.(prefix);
|
|
184
|
-
return copyListResult(cached.result);
|
|
185
|
-
}
|
|
186
|
-
const result = await coalesced(pendingLists, listKey, async () => {
|
|
187
|
-
onMiss?.(prefix);
|
|
188
|
-
const fetched = await store.list(prefix, listOptions);
|
|
189
|
-
listCache.set(
|
|
190
|
-
listKey,
|
|
191
|
-
{
|
|
192
|
-
result: copyListResult(fetched),
|
|
193
|
-
prefix,
|
|
194
|
-
probe: listOptions?.limit === 1,
|
|
195
|
-
empty: fetched.objects.length === 0 && fetched.prefixes.length === 0
|
|
196
|
-
},
|
|
197
|
-
{ ttl: ttlForKey?.(prefix) }
|
|
198
|
-
);
|
|
199
|
-
return fetched;
|
|
200
|
-
});
|
|
201
|
-
return copyListResult(result);
|
|
202
|
-
},
|
|
203
|
-
invalidate(prefix) {
|
|
204
|
-
for (const key of cache.keys()) {
|
|
205
|
-
if (key.startsWith(prefix)) cache.delete(key);
|
|
206
|
-
}
|
|
207
|
-
for (const [listKey, entry] of listCache.entries()) {
|
|
208
|
-
if (entry.prefix.startsWith(prefix) || prefix.startsWith(entry.prefix)) {
|
|
209
|
-
listCache.delete(listKey);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// src/edge-utils.ts
|
|
217
|
-
var textEncoder = new TextEncoder();
|
|
218
|
-
var textDecoder = new TextDecoder();
|
|
219
|
-
function encodeUtf8(data) {
|
|
220
|
-
return textEncoder.encode(data);
|
|
221
|
-
}
|
|
222
|
-
function decodeUtf8(data) {
|
|
223
|
-
return textDecoder.decode(data);
|
|
224
|
-
}
|
|
225
|
-
function decodeAscii(data) {
|
|
226
|
-
let s = "";
|
|
227
|
-
for (let i = 0; i < data.length; i++)
|
|
228
|
-
s += String.fromCharCode(data[i]);
|
|
229
|
-
return s;
|
|
230
|
-
}
|
|
231
|
-
function concat(...parts) {
|
|
232
|
-
let total = 0;
|
|
233
|
-
for (const p of parts) total += p.length;
|
|
234
|
-
const out = new Uint8Array(total);
|
|
235
|
-
let offset = 0;
|
|
236
|
-
for (const p of parts) {
|
|
237
|
-
out.set(p, offset);
|
|
238
|
-
offset += p.length;
|
|
239
|
-
}
|
|
240
|
-
return out;
|
|
241
|
-
}
|
|
242
|
-
function toHex(data) {
|
|
243
|
-
let hex = "";
|
|
244
|
-
for (let i = 0; i < data.length; i++)
|
|
245
|
-
hex += data[i].toString(16).padStart(2, "0");
|
|
246
|
-
return hex;
|
|
247
|
-
}
|
|
248
|
-
function toBase64(data) {
|
|
249
|
-
let binary = "";
|
|
250
|
-
for (let i = 0; i < data.length; i++)
|
|
251
|
-
binary += String.fromCharCode(data[i]);
|
|
252
|
-
return btoa(binary);
|
|
253
|
-
}
|
|
254
|
-
function fromHex(hex) {
|
|
255
|
-
const bytes = new Uint8Array(hex.length / 2);
|
|
256
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
257
|
-
bytes[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
258
|
-
}
|
|
259
|
-
return bytes;
|
|
260
|
-
}
|
|
261
|
-
async function sha1(data) {
|
|
262
|
-
const bytes = typeof data === "string" ? encodeUtf8(data) : data;
|
|
263
|
-
const hash = await globalThis.crypto.subtle.digest("SHA-1", bytes);
|
|
264
|
-
return toHex(new Uint8Array(hash));
|
|
265
|
-
}
|
|
266
|
-
async function deflate(data) {
|
|
267
|
-
const stream = new Blob([data]).stream().pipeThrough(new CompressionStream("deflate"));
|
|
268
|
-
return new Uint8Array(await new Response(stream).arrayBuffer());
|
|
269
|
-
}
|
|
270
|
-
function hasNullByte(data) {
|
|
271
|
-
return data.includes(0);
|
|
272
|
-
}
|
|
273
|
-
function readBlobContent(blob) {
|
|
274
|
-
const isBinary = hasNullByte(blob);
|
|
275
|
-
return {
|
|
276
|
-
isBinary,
|
|
277
|
-
text: isBinary ? "" : decodeUtf8(blob),
|
|
278
|
-
bytes: blob
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// src/errors.ts
|
|
283
|
-
var FsError = class extends Error {
|
|
284
|
-
code;
|
|
285
|
-
syscall;
|
|
286
|
-
path;
|
|
287
|
-
constructor(code, syscall, path) {
|
|
288
|
-
super(`${code}: ${syscall} '${path}'`);
|
|
289
|
-
this.name = "FsError";
|
|
290
|
-
this.code = code;
|
|
291
|
-
this.syscall = syscall;
|
|
292
|
-
this.path = path;
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
var enoent = (syscall, path) => new FsError("ENOENT", syscall, path);
|
|
296
|
-
var enotdir = (syscall, path) => new FsError("ENOTDIR", syscall, path);
|
|
297
|
-
var enotempty = (syscall, path) => new FsError("ENOTEMPTY", syscall, path);
|
|
298
|
-
var einval = (syscall, path) => new FsError("EINVAL", syscall, path);
|
|
299
|
-
var eperm = (syscall, path) => new FsError("EPERM", syscall, path);
|
|
300
|
-
|
|
301
|
-
// src/git-errors.ts
|
|
302
|
-
var GitError = class extends Error {
|
|
303
|
-
statusCode;
|
|
304
|
-
retryable;
|
|
305
|
-
constructor(message, statusCode = 500, retryable = false) {
|
|
306
|
-
super(message);
|
|
307
|
-
this.name = this.constructor.name;
|
|
308
|
-
this.statusCode = statusCode;
|
|
309
|
-
this.retryable = retryable;
|
|
310
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
311
|
-
}
|
|
312
|
-
toJSON() {
|
|
313
|
-
return {
|
|
314
|
-
error: this.name,
|
|
315
|
-
message: this.message,
|
|
316
|
-
statusCode: this.statusCode,
|
|
317
|
-
retryable: this.retryable
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
var GitPathNotFoundError = class extends GitError {
|
|
322
|
-
constructor(message) {
|
|
323
|
-
super(message, 404, false);
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
var GitObjectNotFoundError = class extends GitError {
|
|
327
|
-
constructor(message) {
|
|
328
|
-
super(message, 404, false);
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
var GitRefNotFoundError = class extends GitError {
|
|
332
|
-
constructor(message) {
|
|
333
|
-
super(message, 404, false);
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
var GitRepositoryNotFoundError = class extends GitError {
|
|
337
|
-
constructor(message) {
|
|
338
|
-
super(message, 404, false);
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
var GitConflictError = class extends GitError {
|
|
342
|
-
conflicts;
|
|
343
|
-
constructor(message, conflicts = []) {
|
|
344
|
-
super(message, 409, false);
|
|
345
|
-
this.conflicts = conflicts;
|
|
346
|
-
}
|
|
347
|
-
toJSON() {
|
|
348
|
-
return { ...super.toJSON(), conflicts: this.conflicts };
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
var GitAuthenticationError = class extends GitError {
|
|
352
|
-
constructor(message) {
|
|
353
|
-
super(message, 401, false);
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
var GitAuthorizationError = class extends GitError {
|
|
357
|
-
constructor(message) {
|
|
358
|
-
super(message, 403, false);
|
|
359
|
-
}
|
|
360
|
-
};
|
|
361
|
-
var GitRateLimitError = class extends GitError {
|
|
362
|
-
constructor(message) {
|
|
363
|
-
super(message, 429, false);
|
|
364
|
-
}
|
|
365
|
-
};
|
|
366
|
-
var GitInvalidRequestError = class extends GitError {
|
|
367
|
-
constructor(message) {
|
|
368
|
-
super(message, 400, false);
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
var GitProtocolError = class extends GitError {
|
|
372
|
-
constructor(message) {
|
|
373
|
-
super(message, 400, false);
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
function formatErrorResponse(error) {
|
|
377
|
-
if (error instanceof GitError) {
|
|
378
|
-
return {
|
|
379
|
-
status: error.statusCode,
|
|
380
|
-
body: error.toJSON(),
|
|
381
|
-
headers: error.statusCode === 401 ? { "WWW-Authenticate": 'Basic realm="Git Repository"' } : void 0
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
if (error instanceof Error) {
|
|
385
|
-
return {
|
|
386
|
-
status: 500,
|
|
387
|
-
body: {
|
|
388
|
-
error: "InternalServerError",
|
|
389
|
-
message: "An internal error occurred",
|
|
390
|
-
retryable: true
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
return {
|
|
395
|
-
status: 500,
|
|
396
|
-
body: {
|
|
397
|
-
error: "UnknownError",
|
|
398
|
-
message: "An unknown error occurred",
|
|
399
|
-
retryable: true
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// src/git-fs.ts
|
|
405
|
-
var import_lru_cache2 = require("lru-cache");
|
|
406
|
-
|
|
407
|
-
// src/pack-files.ts
|
|
408
|
-
var PACK_FILE_KINDS = [
|
|
409
|
-
"pack",
|
|
410
|
-
"idx",
|
|
411
|
-
"keep",
|
|
412
|
-
"bitmap",
|
|
413
|
-
"rev"
|
|
414
|
-
];
|
|
415
|
-
var READABLE_PACK_FILE_KINDS = /* @__PURE__ */ new Set([
|
|
416
|
-
"pack",
|
|
417
|
-
"idx"
|
|
418
|
-
]);
|
|
419
|
-
var KNOWN_KINDS = new Set(PACK_FILE_KINDS);
|
|
420
|
-
function isPackFileKind(value) {
|
|
421
|
-
return KNOWN_KINDS.has(value);
|
|
422
|
-
}
|
|
423
|
-
function parsePackFileName(name) {
|
|
424
|
-
const dot = name.lastIndexOf(".");
|
|
425
|
-
if (dot <= 0) return null;
|
|
426
|
-
const kind = name.slice(dot + 1);
|
|
427
|
-
if (!isPackFileKind(kind)) return null;
|
|
428
|
-
return { base: name.slice(0, dot), kind, name };
|
|
429
|
-
}
|
|
430
|
-
function packFileName(base, kind) {
|
|
431
|
-
return `${base}.${kind}`;
|
|
432
|
-
}
|
|
433
|
-
function parsePackDirectory(entries) {
|
|
434
|
-
return entries.map(parsePackFileName).filter((file) => file !== null);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
// src/git-layout.ts
|
|
438
|
-
var HEX = new Set("0123456789abcdef");
|
|
439
|
-
function isHex(value, length) {
|
|
440
|
-
if (value.length !== length) return false;
|
|
441
|
-
for (const char of value) if (!HEX.has(char)) return false;
|
|
442
|
-
return true;
|
|
443
|
-
}
|
|
444
|
-
function classifyGitdirPath(path) {
|
|
445
|
-
const segments = path.split("/");
|
|
446
|
-
const [first, second, third, ...rest] = segments;
|
|
447
|
-
if (segments.length === 1) {
|
|
448
|
-
if (first === "HEAD") return { kind: "head" };
|
|
449
|
-
if (first === "config") return { kind: "config" };
|
|
450
|
-
if (first === "refs") return { kind: "refs", path };
|
|
451
|
-
return { kind: "other" };
|
|
452
|
-
}
|
|
453
|
-
if (first === "refs") return { kind: "refs", path };
|
|
454
|
-
if (first !== "objects" || second === void 0) return { kind: "other" };
|
|
455
|
-
if (segments.length === 2 && second === "") return { kind: "objects-dir" };
|
|
456
|
-
if (second === "pack" && third !== void 0 && rest.length === 0) {
|
|
457
|
-
if (third === "") return { kind: "pack-dir" };
|
|
458
|
-
const file = parsePackFileName(third);
|
|
459
|
-
return file ? { kind: "pack-file", file } : { kind: "other" };
|
|
460
|
-
}
|
|
461
|
-
if (third !== void 0 && rest.length === 0 && isHex(second, 2) && isHex(third, 38)) {
|
|
462
|
-
return { kind: "loose-object", oid: second + third };
|
|
463
|
-
}
|
|
464
|
-
return { kind: "other" };
|
|
465
|
-
}
|
|
466
|
-
function isMutableGitdirEntry(entry) {
|
|
467
|
-
switch (entry.kind) {
|
|
468
|
-
case "head":
|
|
469
|
-
case "refs":
|
|
470
|
-
case "objects-dir":
|
|
471
|
-
case "pack-dir":
|
|
472
|
-
return true;
|
|
473
|
-
default:
|
|
474
|
-
return false;
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
function parseLooseObjectPath(path) {
|
|
478
|
-
const segments = path.split("/");
|
|
479
|
-
if (segments.length < 3) return null;
|
|
480
|
-
const gitdirSegments = segments.slice(0, -3);
|
|
481
|
-
const entry = classifyGitdirPath(segments.slice(-3).join("/"));
|
|
482
|
-
if (entry.kind !== "loose-object") return null;
|
|
483
|
-
return { gitdir: gitdirSegments.join("/"), oid: entry.oid };
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// src/path.ts
|
|
487
|
-
function normalizePath(filepath) {
|
|
488
|
-
const segments = filepath.split("/");
|
|
489
|
-
const out = [];
|
|
490
|
-
for (const segment of segments) {
|
|
491
|
-
if (segment === "" || segment === ".") continue;
|
|
492
|
-
if (segment === "..") {
|
|
493
|
-
if (out.length === 0) throw einval("resolve", filepath);
|
|
494
|
-
out.pop();
|
|
495
|
-
continue;
|
|
496
|
-
}
|
|
497
|
-
out.push(segment);
|
|
498
|
-
}
|
|
499
|
-
return out.join("/");
|
|
500
|
-
}
|
|
501
|
-
function toKey(prefix, filepath) {
|
|
502
|
-
const normalized = normalizePath(filepath);
|
|
503
|
-
if (prefix === "") return normalized;
|
|
504
|
-
return normalized === "" ? prefix : `${prefix}/${normalized}`;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// src/git-fs.ts
|
|
508
|
-
var FILE_MODE = 33188;
|
|
509
|
-
var DIR_MODE = 16384;
|
|
510
|
-
var textEncoder2 = new TextEncoder();
|
|
511
|
-
var textDecoder2 = new TextDecoder();
|
|
512
|
-
function makeStat(type, size) {
|
|
513
|
-
const epoch = /* @__PURE__ */ new Date(0);
|
|
514
|
-
return {
|
|
515
|
-
type,
|
|
516
|
-
mode: type === "file" ? FILE_MODE : DIR_MODE,
|
|
517
|
-
size,
|
|
518
|
-
ino: 0,
|
|
519
|
-
mtimeMs: 0,
|
|
520
|
-
ctimeMs: 0,
|
|
521
|
-
uid: 0,
|
|
522
|
-
gid: 0,
|
|
523
|
-
dev: 0,
|
|
524
|
-
mtime: epoch,
|
|
525
|
-
ctime: epoch,
|
|
526
|
-
isFile: () => type === "file",
|
|
527
|
-
isDirectory: () => type === "dir",
|
|
528
|
-
isSymbolicLink: () => false
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
function resolveEncoding(options) {
|
|
532
|
-
if (typeof options === "string") return options;
|
|
533
|
-
return options?.encoding;
|
|
534
|
-
}
|
|
535
|
-
function createGitFs(store, options = {}) {
|
|
536
|
-
const prefix = options.prefix ?? "";
|
|
537
|
-
const structurallyAbsent = options.isStructurallyAbsent;
|
|
538
|
-
const useLooseHints = options.looseObjectHints ?? false;
|
|
539
|
-
const onNote = options.onNote;
|
|
540
|
-
const toKey2 = (path) => toKey(prefix, path);
|
|
541
|
-
const looseHints = new import_lru_cache2.LRUCache({
|
|
542
|
-
max: 1024,
|
|
543
|
-
ttl: options.hintTtlMs ?? 36e5
|
|
544
|
-
});
|
|
545
|
-
const registeredGitdirs = new import_lru_cache2.LRUCache({
|
|
546
|
-
max: 4096
|
|
547
|
-
});
|
|
548
|
-
function registeredAbsent(path) {
|
|
549
|
-
const slash = path.lastIndexOf("/");
|
|
550
|
-
if (slash < 0) return false;
|
|
551
|
-
const absent = registeredGitdirs.get(path.slice(0, slash));
|
|
552
|
-
return absent?.has(path.slice(slash + 1)) ?? false;
|
|
553
|
-
}
|
|
554
|
-
function looseScope(path) {
|
|
555
|
-
return parseLooseObjectPath(path)?.gitdir ?? null;
|
|
556
|
-
}
|
|
557
|
-
const pendingDetections = /* @__PURE__ */ new Map();
|
|
558
|
-
async function knownAbsent(path) {
|
|
559
|
-
if (structurallyAbsent?.(path) || registeredAbsent(path)) return true;
|
|
560
|
-
if (!useLooseHints) return false;
|
|
561
|
-
const scope = looseScope(path);
|
|
562
|
-
if (scope === null) return false;
|
|
563
|
-
if (!looseHints.has(scope)) {
|
|
564
|
-
let pending = pendingDetections.get(scope);
|
|
565
|
-
if (!pending) {
|
|
566
|
-
pending = detectLooseObjects(scope).finally(
|
|
567
|
-
() => pendingDetections.delete(scope)
|
|
568
|
-
);
|
|
569
|
-
pendingDetections.set(scope, pending);
|
|
570
|
-
}
|
|
571
|
-
await pending;
|
|
572
|
-
}
|
|
573
|
-
return looseHints.get(scope) === "none";
|
|
574
|
-
}
|
|
575
|
-
async function isDirectory(dirKey) {
|
|
576
|
-
const { objects, prefixes } = await store.list(`${dirKey}/`, {
|
|
577
|
-
limit: 1
|
|
578
|
-
});
|
|
579
|
-
return objects.length > 0 || prefixes.length > 0;
|
|
580
|
-
}
|
|
581
|
-
async function stat(filepath, syscall) {
|
|
582
|
-
const path = normalizePath(filepath);
|
|
583
|
-
if (await knownAbsent(path)) throw enoent(syscall, filepath);
|
|
584
|
-
const k = toKey2(path);
|
|
585
|
-
if (k === prefix || k === "" || registeredGitdirs.has(path)) {
|
|
586
|
-
return makeStat("dir", 0);
|
|
587
|
-
}
|
|
588
|
-
const fileStat = await store.head(k);
|
|
589
|
-
if (fileStat) return makeStat("file", fileStat.size);
|
|
590
|
-
if (useLooseHints && looseScope(path) !== null) {
|
|
591
|
-
throw enoent(syscall, filepath);
|
|
592
|
-
}
|
|
593
|
-
if (await isDirectory(k)) return makeStat("dir", 0);
|
|
594
|
-
throw enoent(syscall, filepath);
|
|
595
|
-
}
|
|
596
|
-
const promises = {
|
|
597
|
-
async readFile(filepath, opts) {
|
|
598
|
-
const path = normalizePath(filepath);
|
|
599
|
-
if (await knownAbsent(path)) throw enoent("open", filepath);
|
|
600
|
-
const data = await store.get(toKey2(path));
|
|
601
|
-
if (data === null) throw enoent("open", filepath);
|
|
602
|
-
return resolveEncoding(opts) === "utf8" ? textDecoder2.decode(data) : data;
|
|
603
|
-
},
|
|
604
|
-
async writeFile(filepath, data, _opts) {
|
|
605
|
-
const path = normalizePath(filepath);
|
|
606
|
-
if (useLooseHints) {
|
|
607
|
-
const scope = looseScope(path);
|
|
608
|
-
if (scope !== null) looseHints.set(scope, "present");
|
|
609
|
-
}
|
|
610
|
-
const bytes = typeof data === "string" ? textEncoder2.encode(data) : data;
|
|
611
|
-
await store.put(toKey2(path), bytes);
|
|
612
|
-
},
|
|
613
|
-
async unlink(filepath) {
|
|
614
|
-
const k = toKey2(normalizePath(filepath));
|
|
615
|
-
if (await store.head(k) === null) throw enoent("unlink", filepath);
|
|
616
|
-
await store.delete(k);
|
|
617
|
-
},
|
|
618
|
-
async readdir(dirpath) {
|
|
619
|
-
const k = toKey2(normalizePath(dirpath));
|
|
620
|
-
const isRoot = k === prefix || k === "";
|
|
621
|
-
const listPrefix = isRoot && k === "" ? "" : `${k}/`;
|
|
622
|
-
const { objects, prefixes } = await store.list(listPrefix, {
|
|
623
|
-
delimiter: "/"
|
|
624
|
-
});
|
|
625
|
-
if (objects.length === 0 && prefixes.length === 0) {
|
|
626
|
-
if (!isRoot && await store.head(k) !== null) {
|
|
627
|
-
throw enotdir("scandir", dirpath);
|
|
628
|
-
}
|
|
629
|
-
if (!isRoot) throw enoent("scandir", dirpath);
|
|
630
|
-
}
|
|
631
|
-
const names = objects.map((o) => o.key.slice(listPrefix.length));
|
|
632
|
-
const dirNames = prefixes.map(
|
|
633
|
-
(p) => p.slice(listPrefix.length).replace(/\/$/, "")
|
|
634
|
-
);
|
|
635
|
-
return [...names, ...dirNames].sort();
|
|
636
|
-
},
|
|
637
|
-
async mkdir(_dirpath, _opts) {
|
|
638
|
-
},
|
|
639
|
-
async rmdir(dirpath) {
|
|
640
|
-
const k = toKey2(normalizePath(dirpath));
|
|
641
|
-
const { objects, prefixes } = await store.list(`${k}/`, { limit: 1 });
|
|
642
|
-
if (objects.length > 0 || prefixes.length > 0) {
|
|
643
|
-
throw enotempty("rmdir", dirpath);
|
|
644
|
-
}
|
|
645
|
-
},
|
|
646
|
-
stat: (filepath) => stat(filepath, "stat"),
|
|
647
|
-
lstat: (filepath) => stat(filepath, "lstat"),
|
|
648
|
-
async readlink(filepath) {
|
|
649
|
-
throw enoent("readlink", filepath);
|
|
650
|
-
},
|
|
651
|
-
async symlink(_target, filepath) {
|
|
652
|
-
throw eperm("symlink", filepath);
|
|
653
|
-
},
|
|
654
|
-
async chmod(_filepath, _mode) {
|
|
655
|
-
}
|
|
656
|
-
};
|
|
657
|
-
async function detectLooseObjects(gitdir) {
|
|
658
|
-
if (!useLooseHints) return;
|
|
659
|
-
const scope = normalizePath(gitdir);
|
|
660
|
-
if (looseHints.has(scope)) return;
|
|
661
|
-
try {
|
|
662
|
-
const { objects } = await store.list(`${toKey2(scope)}/objects/`, {
|
|
663
|
-
limit: 1
|
|
664
|
-
});
|
|
665
|
-
const first = objects[0]?.key;
|
|
666
|
-
const hint = first !== void 0 && parseLooseObjectPath(first) !== null ? "present" : "none";
|
|
667
|
-
looseHints.set(scope, hint);
|
|
668
|
-
onNote?.(`loose objects ${hint} under ${scope}`);
|
|
669
|
-
} catch {
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
async function prefetchPacks(gitdir, prefetchOptions) {
|
|
673
|
-
const maxPacks = prefetchOptions?.maxPacks ?? 30;
|
|
674
|
-
const packDir = `${normalizePath(gitdir)}/objects/pack`;
|
|
675
|
-
const entries = parsePackDirectory(
|
|
676
|
-
await promises.readdir(packDir).catch(() => [])
|
|
677
|
-
).filter((file) => READABLE_PACK_FILE_KINDS.has(file.kind)).map((file) => file.name);
|
|
678
|
-
if (entries.length > maxPacks * 2) {
|
|
679
|
-
await detectLooseObjects(gitdir);
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
await Promise.all([
|
|
683
|
-
detectLooseObjects(gitdir),
|
|
684
|
-
...entries.map(
|
|
685
|
-
(name) => promises.readFile(`${packDir}/${name}`).catch(() => void 0)
|
|
686
|
-
)
|
|
687
|
-
]);
|
|
688
|
-
}
|
|
689
|
-
async function listFilesRecursively(dirpath) {
|
|
690
|
-
const directory = toKey2(normalizePath(dirpath));
|
|
691
|
-
const listPrefix = directory === "" ? "" : `${directory}/`;
|
|
692
|
-
const { objects } = await store.list(listPrefix);
|
|
693
|
-
return objects.map((object) => object.key.slice(listPrefix.length)).filter((path) => path.length > 0).sort();
|
|
694
|
-
}
|
|
695
|
-
function registerGitdir(gitdir, facts) {
|
|
696
|
-
registeredGitdirs.set(
|
|
697
|
-
normalizePath(gitdir),
|
|
698
|
-
new Set(facts?.absentFiles ?? [])
|
|
699
|
-
);
|
|
700
|
-
}
|
|
701
|
-
function invalidate(pathPrefix) {
|
|
702
|
-
const normalized = normalizePath(pathPrefix);
|
|
703
|
-
for (const dir of registeredGitdirs.keys()) {
|
|
704
|
-
if (dir.startsWith(normalized)) registeredGitdirs.delete(dir);
|
|
705
|
-
}
|
|
706
|
-
for (const scope of looseHints.keys()) {
|
|
707
|
-
if (scope.startsWith(normalized)) looseHints.delete(scope);
|
|
708
|
-
}
|
|
709
|
-
const maybe = store;
|
|
710
|
-
maybe.invalidate?.(toKey2(normalized));
|
|
711
|
-
}
|
|
712
|
-
return {
|
|
713
|
-
promises,
|
|
714
|
-
listFilesRecursively,
|
|
715
|
-
detectLooseObjects,
|
|
716
|
-
prefetchPacks,
|
|
717
|
-
invalidate,
|
|
718
|
-
registerGitdir
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
// src/refs.ts
|
|
723
|
-
var BAD_REF_COMPONENT = (
|
|
724
|
-
// biome-ignore lint/suspicious/noControlCharactersInRegex: control chars are exactly what git's own ref-name rules reject — this needs to match the same range.
|
|
725
|
-
/(^|[/.])([/.]|$)|^@$|@\{|[\x00-\x20\x7f~^:?*[\\]|\.lock(\/|$)/
|
|
726
|
-
);
|
|
727
|
-
var FULL_SHA_RE = /^[0-9a-f]{40}$/i;
|
|
728
|
-
function isSafeFullRefName(ref) {
|
|
729
|
-
if (!ref.startsWith("refs/heads/") && !ref.startsWith("refs/tags/")) {
|
|
730
|
-
return false;
|
|
731
|
-
}
|
|
732
|
-
return !BAD_REF_COMPONENT.test(ref);
|
|
733
|
-
}
|
|
734
|
-
function isSafeBranchName(name) {
|
|
735
|
-
if (!name || name.startsWith("refs/") || name === "HEAD") return false;
|
|
736
|
-
if (FULL_SHA_RE.test(name)) return false;
|
|
737
|
-
return !BAD_REF_COMPONENT.test(name);
|
|
738
|
-
}
|
|
739
|
-
function isFullSha(value) {
|
|
740
|
-
return FULL_SHA_RE.test(value);
|
|
741
|
-
}
|
|
742
|
-
function isSafeRefName(value) {
|
|
743
|
-
return isSafeBranchName(value) || isFullSha(value);
|
|
744
|
-
}
|
|
745
|
-
function isSafeRepoPath(p) {
|
|
746
|
-
if (p.startsWith("/")) return false;
|
|
747
|
-
if (p.split("/").some((segment) => segment === "..")) return false;
|
|
748
|
-
if (/^\.git(\/|$)/i.test(p)) return false;
|
|
749
|
-
if (p.includes("\0")) return false;
|
|
750
|
-
return true;
|
|
751
|
-
}
|
|
752
|
-
function qualifyBranchRef(ref) {
|
|
753
|
-
if (ref.startsWith("refs/") || ref === "HEAD" || FULL_SHA_RE.test(ref)) {
|
|
754
|
-
return ref;
|
|
755
|
-
}
|
|
756
|
-
return `refs/heads/${ref}`;
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
// src/retry.ts
|
|
760
|
-
var CircuitOpenError = class extends Error {
|
|
761
|
-
code = "EUNAVAILABLE";
|
|
762
|
-
constructor() {
|
|
763
|
-
super("Circuit breaker is open, object store unavailable");
|
|
764
|
-
this.name = "CircuitOpenError";
|
|
765
|
-
}
|
|
766
|
-
};
|
|
767
|
-
var RETRYABLE_NAMES = /* @__PURE__ */ new Set([
|
|
768
|
-
"TimeoutError",
|
|
769
|
-
"RequestTimeout",
|
|
770
|
-
"RequestTimeoutException",
|
|
771
|
-
"SlowDown",
|
|
772
|
-
"ThrottlingException",
|
|
773
|
-
"TooManyRequestsException"
|
|
774
|
-
]);
|
|
775
|
-
var RETRYABLE_CODES = /* @__PURE__ */ new Set([
|
|
776
|
-
"ECONNRESET",
|
|
777
|
-
"ECONNREFUSED",
|
|
778
|
-
"EPIPE",
|
|
779
|
-
"ETIMEDOUT",
|
|
780
|
-
"ENOTFOUND",
|
|
781
|
-
"EAI_AGAIN",
|
|
782
|
-
"EPROTO"
|
|
783
|
-
]);
|
|
784
|
-
function defaultIsRetryable(error) {
|
|
785
|
-
if (typeof error !== "object" || error === null) return false;
|
|
786
|
-
const err = error;
|
|
787
|
-
if (err.name !== void 0 && RETRYABLE_NAMES.has(err.name)) return true;
|
|
788
|
-
if (err.code !== void 0 && RETRYABLE_CODES.has(err.code)) return true;
|
|
789
|
-
const status = err.$metadata?.httpStatusCode;
|
|
790
|
-
return status !== void 0 && (status >= 500 || status === 429);
|
|
791
|
-
}
|
|
792
|
-
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
793
|
-
function createRetryStore(store, options = {}) {
|
|
794
|
-
const retries = options.retries ?? 3;
|
|
795
|
-
const initialDelayMs = options.initialDelayMs ?? 100;
|
|
796
|
-
const maxDelayMs = options.maxDelayMs ?? 5e3;
|
|
797
|
-
const jitter = options.jitter ?? 0.3;
|
|
798
|
-
const isRetryable = options.isRetryable ?? defaultIsRetryable;
|
|
799
|
-
const breaker = options.breaker === false ? null : {
|
|
800
|
-
threshold: options.breaker?.threshold ?? 5,
|
|
801
|
-
resetMs: options.breaker?.resetMs ?? 3e4
|
|
802
|
-
};
|
|
803
|
-
let failures = 0;
|
|
804
|
-
let lastFailureAt = 0;
|
|
805
|
-
let state = "closed";
|
|
806
|
-
async function guarded(fn) {
|
|
807
|
-
if (breaker === null) return fn();
|
|
808
|
-
if (state === "open") {
|
|
809
|
-
if (Date.now() - lastFailureAt < breaker.resetMs) {
|
|
810
|
-
throw new CircuitOpenError();
|
|
811
|
-
}
|
|
812
|
-
state = "half-open";
|
|
813
|
-
}
|
|
814
|
-
try {
|
|
815
|
-
const result = await fn();
|
|
816
|
-
if (state === "half-open") {
|
|
817
|
-
state = "closed";
|
|
818
|
-
failures = 0;
|
|
819
|
-
}
|
|
820
|
-
return result;
|
|
821
|
-
} catch (error) {
|
|
822
|
-
failures++;
|
|
823
|
-
lastFailureAt = Date.now();
|
|
824
|
-
if (failures >= breaker.threshold) state = "open";
|
|
825
|
-
throw error;
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
async function run(op, key, fn) {
|
|
829
|
-
let lastError;
|
|
830
|
-
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
831
|
-
try {
|
|
832
|
-
return await guarded(fn);
|
|
833
|
-
} catch (error) {
|
|
834
|
-
lastError = error;
|
|
835
|
-
if (error instanceof CircuitOpenError) throw error;
|
|
836
|
-
if (!isRetryable(error) || attempt === retries) throw error;
|
|
837
|
-
const base = Math.min(initialDelayMs * 2 ** attempt, maxDelayMs);
|
|
838
|
-
const delayMs = Math.round(base + Math.random() * base * jitter);
|
|
839
|
-
options.onRetry?.({ key, op, attempt: attempt + 1, delayMs });
|
|
840
|
-
await sleep(delayMs);
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
throw lastError;
|
|
844
|
-
}
|
|
845
|
-
return {
|
|
846
|
-
get: (key) => run("get", key, () => store.get(key)),
|
|
847
|
-
put: (key, data) => run("put", key, () => store.put(key, data)),
|
|
848
|
-
delete: (key) => run("delete", key, () => store.delete(key)),
|
|
849
|
-
head: (key) => run("head", key, () => store.head(key)),
|
|
850
|
-
list: (prefix, listOptions) => run("list", prefix, () => store.list(prefix, listOptions))
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
// src/stores/memory.ts
|
|
855
|
-
var MemoryObjectStore = class {
|
|
856
|
-
objects = /* @__PURE__ */ new Map();
|
|
857
|
-
async get(key) {
|
|
858
|
-
const data = this.objects.get(key);
|
|
859
|
-
return data ? data.slice() : null;
|
|
860
|
-
}
|
|
861
|
-
async put(key, data) {
|
|
862
|
-
this.objects.set(key, data.slice());
|
|
863
|
-
}
|
|
864
|
-
async delete(key) {
|
|
865
|
-
this.objects.delete(key);
|
|
866
|
-
}
|
|
867
|
-
async head(key) {
|
|
868
|
-
const data = this.objects.get(key);
|
|
869
|
-
return data ? { size: data.byteLength } : null;
|
|
870
|
-
}
|
|
871
|
-
async list(prefix, options) {
|
|
872
|
-
const delimiter = options?.delimiter;
|
|
873
|
-
const limit = options?.limit ?? Number.POSITIVE_INFINITY;
|
|
874
|
-
const objects = [];
|
|
875
|
-
const prefixes = /* @__PURE__ */ new Set();
|
|
876
|
-
for (const [key, data] of this.objects) {
|
|
877
|
-
if (!key.startsWith(prefix)) continue;
|
|
878
|
-
const rest = key.slice(prefix.length);
|
|
879
|
-
if (delimiter !== void 0) {
|
|
880
|
-
const idx = rest.indexOf(delimiter);
|
|
881
|
-
if (idx !== -1) {
|
|
882
|
-
prefixes.add(prefix + rest.slice(0, idx + delimiter.length));
|
|
883
|
-
} else {
|
|
884
|
-
objects.push({ key, size: data.byteLength });
|
|
885
|
-
}
|
|
886
|
-
} else {
|
|
887
|
-
objects.push({ key, size: data.byteLength });
|
|
888
|
-
}
|
|
889
|
-
if (objects.length + prefixes.size >= limit) break;
|
|
890
|
-
}
|
|
891
|
-
return { objects, prefixes: [...prefixes] };
|
|
892
|
-
}
|
|
893
|
-
/** Number of stored objects (test convenience, not part of ObjectStore). */
|
|
894
|
-
get size() {
|
|
895
|
-
return this.objects.size;
|
|
896
|
-
}
|
|
897
|
-
};
|
|
898
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
899
|
-
0 && (module.exports = {
|
|
900
|
-
CircuitOpenError,
|
|
901
|
-
FsError,
|
|
902
|
-
GitAuthenticationError,
|
|
903
|
-
GitAuthorizationError,
|
|
904
|
-
GitConflictError,
|
|
905
|
-
GitError,
|
|
906
|
-
GitInvalidRequestError,
|
|
907
|
-
GitObjectNotFoundError,
|
|
908
|
-
GitPathNotFoundError,
|
|
909
|
-
GitProtocolError,
|
|
910
|
-
GitRateLimitError,
|
|
911
|
-
GitRefNotFoundError,
|
|
912
|
-
GitRepositoryNotFoundError,
|
|
913
|
-
MemoryObjectStore,
|
|
914
|
-
PACK_FILE_KINDS,
|
|
915
|
-
READABLE_PACK_FILE_KINDS,
|
|
916
|
-
classifyGitdirPath,
|
|
917
|
-
concat,
|
|
918
|
-
createCachedStore,
|
|
919
|
-
createGitFs,
|
|
920
|
-
createRetryStore,
|
|
921
|
-
decodeAscii,
|
|
922
|
-
decodeUtf8,
|
|
923
|
-
deflate,
|
|
924
|
-
encodeUtf8,
|
|
925
|
-
formatErrorResponse,
|
|
926
|
-
fromHex,
|
|
927
|
-
hasNullByte,
|
|
928
|
-
isFullSha,
|
|
929
|
-
isMutableGitdirEntry,
|
|
930
|
-
isSafeBranchName,
|
|
931
|
-
isSafeFullRefName,
|
|
932
|
-
isSafeRefName,
|
|
933
|
-
isSafeRepoPath,
|
|
934
|
-
packFileName,
|
|
935
|
-
parseLooseObjectPath,
|
|
936
|
-
parsePackDirectory,
|
|
937
|
-
parsePackFileName,
|
|
938
|
-
qualifyBranchRef,
|
|
939
|
-
readBlobContent,
|
|
940
|
-
sha1,
|
|
941
|
-
toBase64,
|
|
942
|
-
toHex
|
|
943
|
-
});
|
|
944
|
-
//# sourceMappingURL=index.cjs.map
|