git-fs-s3 0.15.2 → 0.15.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.
- package/README.md +5 -3
- package/dist/fetch-s3.js +137 -160
- package/dist/fetch-s3.js.map +1 -1
- package/dist/http.js +905 -849
- package/dist/http.js.map +1 -1
- package/dist/index.js +578 -658
- package/dist/index.js.map +1 -1
- package/dist/memory-M2cCuVF-.js +61 -0
- package/dist/memory-M2cCuVF-.js.map +1 -0
- package/dist/node.js +75 -72
- package/dist/node.js.map +1 -1
- package/dist/object-size-BJAsnZzw.js +191 -0
- package/dist/object-size-BJAsnZzw.js.map +1 -0
- package/dist/ops.js +662 -692
- package/dist/ops.js.map +1 -1
- package/dist/refs-Cb_NfKWI.js +550 -0
- package/dist/refs-Cb_NfKWI.js.map +1 -0
- package/dist/s3.js +111 -116
- package/dist/s3.js.map +1 -1
- package/dist/semaphore-BviNoQuJ.js +646 -0
- package/dist/semaphore-BviNoQuJ.js.map +1 -0
- package/dist/types/git-errors.d.ts +6 -0
- package/dist/types/http/repack.d.ts +7 -0
- package/dist/types/index.d.ts +1 -1
- package/package.json +8 -13
- package/dist/chunk-HLYCSNJ2.js +0 -53
- package/dist/chunk-HLYCSNJ2.js.map +0 -1
- package/dist/chunk-IAKZRWBZ.js +0 -598
- package/dist/chunk-IAKZRWBZ.js.map +0 -1
- package/dist/chunk-OKBQISUC.js +0 -442
- package/dist/chunk-OKBQISUC.js.map +0 -1
- package/dist/chunk-T5M5EYCZ.js +0 -143
- package/dist/chunk-T5M5EYCZ.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semaphore-BviNoQuJ.js","names":[],"sources":["../src/ops/tree.ts","../src/ops/types.ts","../src/ops/history.ts","../src/ops/branch.ts","../src/pack-write.ts","../src/semaphore.ts"],"sourcesContent":["import git from \"isomorphic-git\";\nimport { GitInvalidRequestError, GitPathNotFoundError } from \"../git-errors.js\";\nimport type { Repo } from \"./types.js\";\n\nexport interface TreeEntry {\n\tpath: string;\n\tmode: string;\n\ttype: \"blob\" | \"tree\" | \"commit\";\n\toid: string;\n\tsize?: number;\n}\n\nconst joinPath = (prefix: string, name: string) =>\n\tprefix ? `${prefix.replace(/\\/+$/, \"\")}/${name}` : name;\n\n/** File modes a blob entry can carry; anything else isn't a regular file. */\nconst BLOB_MODES = new Set([\"100644\", \"100755\", \"120000\"]);\n\n/**\n * Build/update a git tree by overlaying new blobs onto an existing tree,\n * returning the new root tree oid. `entries` maps relative paths to blob oids.\n *\n * An updated file keeps its existing mode (executable bit, symlink); a path\n * that names an existing directory, or runs through an existing file, is\n * rejected rather than silently replacing what's there.\n */\nexport async function upsertTree(\n\trepo: Repo,\n\ttreeOid: string | undefined,\n\tentries: Map<string, string>,\n): Promise<string> {\n\tconst existing = treeOid\n\t\t? (await git.readTree({ ...repo, oid: treeOid })).tree\n\t\t: [];\n\tconst byName = new Map(existing.map((e) => [e.path, e]));\n\tconst direct = new Map<string, string>();\n\tconst nested = new Map<string, Map<string, string>>();\n\tfor (const [filePath, blobOid] of entries) {\n\t\tconst slash = filePath.indexOf(\"/\");\n\t\tif (slash === -1) {\n\t\t\tdirect.set(filePath, blobOid);\n\t\t} else {\n\t\t\tconst dir = filePath.slice(0, slash);\n\t\t\tconst rest = filePath.slice(slash + 1);\n\t\t\tif (!nested.has(dir)) nested.set(dir, new Map());\n\t\t\tnested.get(dir)?.set(rest, blobOid);\n\t\t}\n\t}\n\tfor (const [name, blobOid] of direct) {\n\t\tconst current = byName.get(name);\n\t\tif (current && current.type !== \"blob\") {\n\t\t\tthrow new GitInvalidRequestError(`\"${name}\" is a directory, not a file`);\n\t\t}\n\t\tbyName.set(name, {\n\t\t\tmode: current && BLOB_MODES.has(current.mode) ? current.mode : \"100644\",\n\t\t\tpath: name,\n\t\t\toid: blobOid,\n\t\t\ttype: \"blob\",\n\t\t});\n\t}\n\t// Sibling subdirectories are independent subtree writes — no reason to\n\t// serialize them for multi-file commits touching several directories.\n\tconst nestedResults = await Promise.all(\n\t\tArray.from(nested, async ([dir, subEntries]) => {\n\t\t\tconst entry = byName.get(dir);\n\t\t\tif (entry && entry.type !== \"tree\") {\n\t\t\t\tthrow new GitInvalidRequestError(`\"${dir}\" is a file, not a directory`);\n\t\t\t}\n\t\t\tconst subtreeOid = entry?.oid;\n\t\t\tconst newOid = await upsertTree(repo, subtreeOid, subEntries);\n\t\t\treturn [dir, newOid] as const;\n\t\t}),\n\t);\n\tfor (const [dir, newOid] of nestedResults) {\n\t\tbyName.set(dir, { mode: \"040000\", path: dir, oid: newOid, type: \"tree\" });\n\t}\n\treturn git.writeTree({ ...repo, tree: Array.from(byName.values()) });\n}\n\n/**\n * Remove a file path from a tree, returning the new root tree oid. Throws\n * GitPathNotFoundError when there's no such file; directories left empty\n * are dropped, as git never stores an empty subtree.\n */\nexport async function deleteFromTree(\n\trepo: Repo,\n\ttreeOid: string,\n\tfilePath: string,\n): Promise<string> {\n\tconst result = await deleteFromSubtree(repo, treeOid, filePath, filePath);\n\treturn result ?? git.writeTree({ ...repo, tree: [] });\n}\n\n/** The new subtree oid, or null when removing the file left it empty. */\nasync function deleteFromSubtree(\n\trepo: Repo,\n\ttreeOid: string,\n\tfilePath: string,\n\tfullPath: string,\n): Promise<string | null> {\n\tconst existing = (await git.readTree({ ...repo, oid: treeOid })).tree;\n\tconst byName = new Map(existing.map((e) => [e.path, e]));\n\tconst slash = filePath.indexOf(\"/\");\n\tconst name = slash === -1 ? filePath : filePath.slice(0, slash);\n\tconst entry = byName.get(name);\n\tif (slash === -1) {\n\t\tif (entry?.type !== \"blob\") {\n\t\t\tthrow new GitPathNotFoundError(`No such file: ${fullPath}`);\n\t\t}\n\t\tbyName.delete(name);\n\t} else {\n\t\tif (entry?.type !== \"tree\") {\n\t\t\tthrow new GitPathNotFoundError(`No such file: ${fullPath}`);\n\t\t}\n\t\tconst newOid = await deleteFromSubtree(\n\t\t\trepo,\n\t\t\tentry.oid,\n\t\t\tfilePath.slice(slash + 1),\n\t\t\tfullPath,\n\t\t);\n\t\tif (newOid === null) byName.delete(name);\n\t\telse byName.set(name, { ...entry, oid: newOid });\n\t}\n\tif (byName.size === 0) return null;\n\treturn git.writeTree({ ...repo, tree: Array.from(byName.values()) });\n}\n\n/** Resolve a path inside a tree to its entry, or null when absent. */\nexport async function findTreeEntry(\n\trepo: Repo,\n\trootTreeOid: string,\n\ttreePath: string,\n): Promise<TreeEntry | null> {\n\tif (!treePath) {\n\t\treturn { path: \"\", mode: \"040000\", type: \"tree\", oid: rootTreeOid };\n\t}\n\n\tconst parts = treePath.split(\"/\").filter(Boolean);\n\tlet currentTreeOid = rootTreeOid;\n\tlet currentPath = \"\";\n\n\tfor (const [index, part] of parts.entries()) {\n\t\tconst tree = await git.readTree({ ...repo, oid: currentTreeOid });\n\t\tconst entry = tree.tree.find((candidate) => candidate.path === part);\n\n\t\tif (!entry) return null;\n\n\t\tcurrentPath = currentPath ? joinPath(currentPath, entry.path) : entry.path;\n\n\t\tif (index === parts.length - 1) {\n\t\t\treturn {\n\t\t\t\tpath: currentPath,\n\t\t\t\tmode: entry.mode,\n\t\t\t\ttype: entry.type,\n\t\t\t\toid: entry.oid,\n\t\t\t};\n\t\t}\n\n\t\tif (entry.type !== \"tree\") return null;\n\n\t\tcurrentTreeOid = entry.oid;\n\t}\n\n\treturn null;\n}\n\n/** List a tree's direct entries, with paths prefixed by `prefix`. */\nexport async function listTreeEntries(\n\trepo: Repo,\n\ttreeOid: string,\n\tprefix = \"\",\n): Promise<TreeEntry[]> {\n\tconst tree = await git.readTree({ ...repo, oid: treeOid });\n\n\treturn tree.tree.map((entry) => ({\n\t\tpath: prefix ? joinPath(prefix, entry.path) : entry.path,\n\t\tmode: entry.mode,\n\t\ttype: entry.type,\n\t\toid: entry.oid,\n\t}));\n}\n","import type git from \"isomorphic-git\";\n\n/** The fs shape isomorphic-git accepts, derived from its own signatures. */\nexport type IsoGitFs = Parameters<typeof git.readTree>[0][\"fs\"];\n\n/**\n * A repository handle: everything isomorphic-git needs to address one bare\n * repo. Create it once per request (sharing `cache` across calls is what lets\n * isomorphic-git reuse parsed pack indexes) and pass it to every op.\n */\nexport interface Repo {\n\tfs: IsoGitFs;\n\tgitdir: string;\n\t/** isomorphic-git's shared parse cache — strongly recommended per repo. */\n\tcache?: object;\n}\n\n/**\n * Key/value store for memoizing expensive walk results (commit logs, tree\n * listings, per-path history). Keys are namespaced `kind:gitdir:headSha:…`,\n * so entries self-invalidate on push (new head, new key); evict\n * {@link resultKeyPrefixes} to drop a repo's superseded entries early.\n * Values are always objects (arrays or records).\n */\nexport interface ResultCache {\n\tget<T extends object>(key: string): T | null | undefined;\n\tset(key: string, value: object): void;\n}\n\n/** Optional instrumentation hooks accepted by every op. */\nexport interface OpsHooks {\n\tresultCache?: ResultCache;\n\t/** Wrap a timed sub-step (network walk, tree listing). Default: run directly. */\n\tstep?: <T>(label: string, fn: () => Promise<T>) => Promise<T>;\n\t/** Diagnostic sink for cache hit/miss and walk summaries. */\n\tonNote?: (message: string) => void;\n\t/**\n\t * Warm every pack (e.g. `GitFs.prefetchPacks`) before a cache-miss read,\n\t * so a sequential walk doesn't discover packs one round trip at a time.\n\t */\n\tprefetch?: () => Promise<void>;\n}\n\nexport const runStep = <T>(\n\thooks: OpsHooks | undefined,\n\tlabel: string,\n\tfn: () => Promise<T>,\n): Promise<T> => (hooks?.step ? hooks.step(label, fn) : fn());\n\n/**\n * The result-cache key prefixes holding entries for `gitdir` — evict these\n * from your {@link ResultCache} when the repo's storage was rewritten outside\n * a normal push (rename, repack).\n */\nexport function resultKeyPrefixes(gitdir: string): string[] {\n\treturn [\n\t\t`commitlog:${gitdir}:`,\n\t\t`tree:${gitdir}:`,\n\t\t`last-commits:${gitdir}:`,\n\t\t`file-history:${gitdir}:`,\n\t];\n}\n","import git from \"isomorphic-git\";\nimport {\n\tGitObjectNotFoundError,\n\tGitPathNotFoundError,\n\tGitRefNotFoundError,\n} from \"../git-errors.js\";\nimport { qualifyBranchRef } from \"../refs.js\";\nimport { findTreeEntry, listTreeEntries, type TreeEntry } from \"./tree.js\";\nimport { type OpsHooks, type Repo, runStep } from \"./types.js\";\n\n/** How far back history walks look by default (commit count). */\nexport const HISTORY_WALK_DEPTH = 400;\n\nexport interface GitIdentity {\n\tname: string;\n\temail: string;\n\ttimestamp: number;\n\ttimezoneOffset: number;\n}\n\nexport interface CommitInfo {\n\toid: string;\n\tcommit: {\n\t\tmessage: string;\n\t\ttree: string;\n\t\tparent: string[];\n\t\tauthor: GitIdentity;\n\t\tcommitter: GitIdentity;\n\t};\n\tpayload: string;\n}\n\n/** The display summary of a commit (history lists, \"last commit\" columns). */\nexport interface CommitSummary {\n\tsha: string;\n\tmessage: string;\n\tauthorName: string;\n\tauthorEmail: string;\n\t/** ISO 8601 author date. */\n\tcreatedAt: string;\n}\n\nexport function summarizeCommit(commit: CommitInfo): CommitSummary {\n\treturn {\n\t\tsha: commit.oid,\n\t\tmessage: commit.commit.message.trim(),\n\t\tauthorName: commit.commit.author.name,\n\t\tauthorEmail: commit.commit.author.email,\n\t\tcreatedAt: new Date(commit.commit.author.timestamp * 1000).toISOString(),\n\t};\n}\n\nconst isNotFound = (err: unknown) =>\n\t(err as { code?: string } | null)?.code === \"NotFoundError\";\n\n/**\n * A ref that doesn't resolve is an expected condition (empty repo, unborn\n * branch) each caller handles. An object missing *underneath* a resolved ref\n * means storage is inconsistent — raised as GitObjectNotFoundError so it is\n * never mistaken for \"empty\".\n */\nfunction wrapMissingObject<T>(\n\tpromise: Promise<T>,\n\tcontext: string,\n): Promise<T> {\n\treturn promise.catch((err: unknown) => {\n\t\tif (isNotFound(err)) {\n\t\t\tthrow new GitObjectNotFoundError(\n\t\t\t\t`Git data for ${context} is missing from storage`,\n\t\t\t);\n\t\t}\n\t\tthrow err;\n\t});\n}\n\n/** The commit a branch name, full ref or sha points at; GitRefNotFoundError if none. */\n/**\n * A short name tries `refs/heads/<name>` first and then `refs/tags/<name>`,\n * so a branch wins over a same-named tag. Annotated tags are peeled to the\n * commit they point at, so every read accepts a tag wherever it accepts a\n * branch.\n */\nasync function resolveRefOid(repo: Repo, ref: string): Promise<string> {\n\tconst qualified = qualifyBranchRef(ref);\n\tconst candidates =\n\t\tqualified === `refs/heads/${ref}`\n\t\t\t? [qualified, `refs/tags/${ref}`]\n\t\t\t: [qualified];\n\tfor (const candidate of candidates) {\n\t\ttry {\n\t\t\treturn await peelToCommit(\n\t\t\t\trepo,\n\t\t\t\tawait git.resolveRef({ ...repo, ref: candidate }),\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (!isNotFound(err)) throw err;\n\t\t}\n\t}\n\tthrow new GitRefNotFoundError(`Ref ${ref} does not exist`);\n}\n\n/** Follow annotated tags (possibly nested) down to the object they name. */\nexport async function peelToCommit(repo: Repo, oid: string): Promise<string> {\n\tlet current = oid;\n\tfor (let depth = 0; depth < 10; depth++) {\n\t\tconst { type, object } = await git.readObject({\n\t\t\t...repo,\n\t\t\toid: current,\n\t\t\tformat: \"parsed\",\n\t\t});\n\t\tif (type !== \"tag\") return current;\n\t\tcurrent = (object as { object: string }).object;\n\t}\n\tthrow new GitRefNotFoundError(`Tag chain at ${oid} is too deep`);\n}\n\n/** Resolve a branch name / full ref / sha to its commit. */\nexport async function resolveCommit(repo: Repo, ref: string) {\n\tconst oid = await resolveRefOid(repo, ref);\n\tconst { commit } = await wrapMissingObject(\n\t\tgit.readCommit({ ...repo, oid }),\n\t\t`${repo.gitdir} commit ${oid}`,\n\t);\n\treturn { oid, commit };\n}\n\n/** Read a blob's bytes by oid. */\nexport async function getBlob(repo: Repo, sha: string): Promise<Uint8Array> {\n\tconst { blob } = await wrapMissingObject(\n\t\tgit.readBlob({ ...repo, oid: sha }),\n\t\t`${repo.gitdir} blob ${sha}`,\n\t);\n\treturn blob;\n}\n\n/** Read a file's bytes at a ref. Throws GitPathNotFoundError when absent. */\nexport async function getFileContent(\n\trepo: Repo,\n\tfilePath: string,\n\tref: string,\n\thooks?: OpsHooks,\n): Promise<Uint8Array> {\n\t// A commit, a tree per path segment, then the blob: warm every pack first\n\t// rather than discovering them one round trip at a time.\n\tif (hooks?.prefetch) await runStep(hooks, \"prefetch\", hooks.prefetch);\n\tconst { commit } = await resolveCommit(repo, ref);\n\tconst context = `${repo.gitdir}@${ref}:${filePath}`;\n\tconst entry = await wrapMissingObject(\n\t\tfindTreeEntry(repo, commit.tree, filePath),\n\t\tcontext,\n\t);\n\tif (entry?.type !== \"blob\") {\n\t\tthrow new GitPathNotFoundError(`File not found: ${filePath}`);\n\t}\n\tconst { blob } = await wrapMissingObject(\n\t\tgit.readBlob({ ...repo, oid: entry.oid }),\n\t\tcontext,\n\t);\n\treturn blob;\n}\n\n/** Read one commit by sha. */\nexport async function getCommit(repo: Repo, sha: string): Promise<CommitInfo> {\n\tconst result = await wrapMissingObject(\n\t\tgit.readCommit({ ...repo, oid: sha }),\n\t\t`${repo.gitdir} commit ${sha}`,\n\t);\n\treturn { oid: result.oid, commit: result.commit, payload: result.payload };\n}\n\nexport interface CommitLogOptions {\n\tref: string;\n\tdepth?: number;\n\t/** The ref's commit, when the caller already resolved it (saves a lookup). */\n\tknownHeadSha?: string;\n}\n\n/**\n * The commit chain from a ref, newest first; [] when the ref doesn't exist.\n * Walking is sequential and round-trip-bound on object storage, so the\n * deepest walk seen per head is memoized in `hooks.resultCache` and sliced\n * for shallower requests.\n */\nexport async function getCommitLog(\n\trepo: Repo,\n\toptions: CommitLogOptions,\n\thooks?: OpsHooks,\n): Promise<CommitInfo[]> {\n\tconst { ref } = options;\n\tconst depth = options.depth ?? 50;\n\tlet headSha = options.knownHeadSha;\n\tif (headSha === undefined) {\n\t\ttry {\n\t\t\theadSha = await resolveRefOid(repo, ref);\n\t\t} catch (err) {\n\t\t\tif (err instanceof GitRefNotFoundError) return [];\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tconst cacheKey = `commitlog:${repo.gitdir}:${headSha}`;\n\tconst cached = hooks?.resultCache?.get<CommitInfo[]>(cacheKey);\n\tconst fullyWalked = cached?.at(-1)?.commit.parent.length === 0;\n\tif (cached && (cached.length >= depth || fullyWalked)) {\n\t\thooks?.onNote?.(`getCommitLog: cache hit ${cacheKey} (depth=${depth})`);\n\t\treturn cached.slice(0, depth);\n\t}\n\thooks?.onNote?.(`getCommitLog: cache miss ${cacheKey} (depth=${depth})`);\n\tif (hooks?.prefetch) await runStep(hooks, \"prefetch\", hooks.prefetch);\n\n\tconst log = await wrapMissingObject(\n\t\trunStep(hooks, `git.log ${ref} depth=${depth}`, () =>\n\t\t\tgit.log({ ...repo, ref: headSha, depth }),\n\t\t),\n\t\t`${repo.gitdir}@${ref} history`,\n\t);\n\tconst result = log.map(({ oid, commit, payload }) => ({\n\t\toid,\n\t\tcommit,\n\t\tpayload: payload ?? \"\",\n\t}));\n\tif (!cached || result.length > cached.length) {\n\t\thooks?.resultCache?.set(cacheKey, result);\n\t}\n\treturn result;\n}\n\n/**\n * List a directory at the tip of a ref. Throws GitRefNotFoundError when the\n * ref doesn't resolve and GitPathNotFoundError when `treePath` doesn't exist.\n * Memoized per head sha.\n */\nexport async function getTreeFromRef(\n\trepo: Repo,\n\toptions: { ref: string; treePath?: string },\n\thooks?: OpsHooks,\n): Promise<TreeEntry[]> {\n\tconst { ref } = options;\n\tconst treePath = options.treePath ?? \"\";\n\tconst { commit, oid: headSha } = await resolveCommit(repo, ref);\n\n\tconst cacheKey = `tree:${repo.gitdir}:${headSha}:${treePath}`;\n\tconst cached = hooks?.resultCache?.get<TreeEntry[]>(cacheKey);\n\tif (cached) {\n\t\thooks?.onNote?.(`getTreeFromRef: cache hit ${cacheKey}`);\n\t\treturn cached;\n\t}\n\thooks?.onNote?.(`getTreeFromRef: cache miss ${cacheKey}`);\n\tif (hooks?.prefetch) await runStep(hooks, \"prefetch\", hooks.prefetch);\n\n\tconst context = `${repo.gitdir}@${ref}:${treePath || \"/\"}`;\n\tconst dir = treePath\n\t\t? await wrapMissingObject(\n\t\t\t\trunStep(hooks, `findTreeEntry ${treePath}`, () =>\n\t\t\t\t\tfindTreeEntry(repo, commit.tree, treePath),\n\t\t\t\t),\n\t\t\t\tcontext,\n\t\t\t)\n\t\t: { path: \"\", type: \"tree\" as const, oid: commit.tree };\n\tif (!dir) {\n\t\tthrow new GitPathNotFoundError(\n\t\t\t`Path \"${treePath}\" does not exist at ${ref}`,\n\t\t);\n\t}\n\tconst result =\n\t\tdir.type === \"tree\"\n\t\t\t? await wrapMissingObject(\n\t\t\t\t\trunStep(hooks, `listTreeEntries ${treePath || \"/\"}`, () =>\n\t\t\t\t\t\tlistTreeEntries(repo, dir.oid, dir.path),\n\t\t\t\t\t),\n\t\t\t\t\tcontext,\n\t\t\t\t)\n\t\t\t: [];\n\thooks?.resultCache?.set(cacheKey, result);\n\treturn result;\n}\n\n/**\n * A page of commit history from a ref tip; [] when the ref doesn't exist.\n * Pages are slices of {@link getCommitLog}'s memoized walk.\n */\nexport async function getCommitHistory(\n\trepo: Repo,\n\toptions: { ref: string; limit?: number; skip?: number },\n\thooks?: OpsHooks,\n): Promise<CommitInfo[]> {\n\tconst limit = options.limit ?? 50;\n\tconst skip = options.skip ?? 0;\n\tconst log = await getCommitLog(\n\t\trepo,\n\t\t{ ref: options.ref, depth: limit + skip },\n\t\thooks,\n\t);\n\treturn log.slice(skip, skip + limit);\n}\n","import git from \"isomorphic-git\";\nimport {\n\tGitConflictError,\n\tGitInvalidRequestError,\n\tisAbsentError,\n} from \"../git-errors.js\";\nimport { isSafeBranchName } from \"../refs.js\";\nimport { peelToCommit } from \"./history.js\";\nimport type { Repo } from \"./types.js\";\n\nexport interface Branch {\n\tname: string;\n\tcommit: string;\n\tisDefault: boolean;\n}\n\nexport interface Tag {\n\tname: string;\n\t/** The commit the tag names (annotated tags peeled). */\n\tcommit: string;\n\t/** The tag object's own oid, for annotated tags; absent for lightweight ones. */\n\ttagObject?: string;\n}\n\n/**\n * Defense in depth for every branch-name argument below: `git.deleteBranch`\n * and raw resolveRef/writeRef reads don't validate ref names internally the\n * way `git.branch` does (see refs.ts) — guard at the point the primitives are\n * actually called, not just at an API boundary far above.\n */\nexport function assertSafeBranchName(name: string): void {\n\tif (!isSafeBranchName(name)) {\n\t\tthrow new GitInvalidRequestError(`Invalid branch name: ${name}`);\n\t}\n}\n\nconst FULL_SHA_RE = /^[0-9a-f]{40}$/i;\n\ntype RecursiveFileLister = {\n\tlistFilesRecursively(dirpath: string): Promise<string[]>;\n};\n\nfunction hasRecursiveFileLister(\n\tfs: Repo[\"fs\"],\n): fs is Repo[\"fs\"] & RecursiveFileLister {\n\treturn (\n\t\ttypeof fs === \"object\" &&\n\t\tfs !== null &&\n\t\t\"listFilesRecursively\" in fs &&\n\t\ttypeof (fs as Partial<RecursiveFileLister>).listFilesRecursively ===\n\t\t\t\"function\"\n\t);\n}\n\ntype PromisesFs = {\n\treadFile(path: string, encoding: \"utf8\"): Promise<string | Uint8Array>;\n};\n\n// Repo.fs is typed as isomorphic-git's own fs union (promise- or\n// callback-based) since that's what git.readTree's signature allows, but\n// every fs this package actually constructs (git-fs.ts) is promise-based —\n// this just keeps the callback-style branch honest instead of crashing on\n// it. Shared by every loose-ref fast path below instead of each repeating\n// the same cast + presence check.\nfunction getPromisesFs(fs: Repo[\"fs\"]): PromisesFs | null {\n\tconst promises = (fs as { promises?: PromisesFs }).promises;\n\treturn promises ?? null;\n}\n\nfunction decodeFileContent(content: string | Uint8Array): string {\n\treturn typeof content === \"string\"\n\t\t? content\n\t\t: new TextDecoder().decode(content);\n}\n\n/**\n * Lists loose branch names without isomorphic-git's recursive readdir/stat\n * traversal. Object stores already return only leaf keys in a recursive LIST,\n * so this is one request regardless of branch-name nesting. Ordinary\n * filesystems retain isomorphic-git's implementation and packed refs remain\n * supported there.\n */\nasync function listLooseBranches(repo: Repo): Promise<string[] | null> {\n\treturn listLooseRefNames(repo, \"refs/heads\");\n}\n\n/**\n * Loose ref names under `dir` (e.g. `refs/tags`) in one recursive listing,\n * or `null` when the fs can't list recursively (use isomorphic-git's walk).\n */\nexport async function listLooseRefNames(\n\trepo: Repo,\n\tdir: \"refs/heads\" | \"refs/tags\",\n): Promise<string[] | null> {\n\tif (!hasRecursiveFileLister(repo.fs)) return null;\n\tconst names = await repo.fs.listFilesRecursively(`${repo.gitdir}/${dir}`);\n\treturn names.filter(isSafeBranchName);\n}\n\n/** Read packed branch refs so the object-store fast path preserves Git semantics. */\nasync function readPackedBranches(repo: Repo): Promise<Map<string, string>> {\n\tif (!hasRecursiveFileLister(repo.fs)) return new Map();\n\tconst promisesFs = getPromisesFs(repo.fs);\n\tif (!promisesFs) return new Map();\n\ttry {\n\t\tconst content = await promisesFs.readFile(\n\t\t\t`${repo.gitdir}/packed-refs`,\n\t\t\t\"utf8\",\n\t\t);\n\t\tconst refs = new Map<string, string>();\n\t\tfor (const line of decodeFileContent(content).split(\"\\n\")) {\n\t\t\tconst match = /^([0-9a-f]{40}) refs\\/heads\\/(.+)$/i.exec(line);\n\t\t\tif (match?.[1] && match[2] && isSafeBranchName(match[2])) {\n\t\t\t\trefs.set(match[2], match[1]);\n\t\t\t}\n\t\t}\n\t\treturn refs;\n\t} catch (error) {\n\t\tif (isAbsentError(error)) return new Map();\n\t\tthrow error;\n\t}\n}\n\n/** Read the symbolic HEAD directly when the object-store fs is available. */\nasync function getCurrentLooseBranch(repo: Repo): Promise<string | null> {\n\tif (!hasRecursiveFileLister(repo.fs)) return null;\n\tconst promisesFs = getPromisesFs(repo.fs);\n\tif (!promisesFs) return null;\n\ttry {\n\t\tconst content = await promisesFs.readFile(`${repo.gitdir}/HEAD`, \"utf8\");\n\t\tconst head = decodeFileContent(content).trim();\n\t\tconst match = /^ref: refs\\/heads\\/(.+)$/.exec(head);\n\t\treturn match?.[1] && isSafeBranchName(match[1]) ? match[1] : null;\n\t} catch (error) {\n\t\t// No HEAD file is \"no branch\"; a failed read is not (#93).\n\t\tif (isAbsentError(error)) return null;\n\t\tthrow error;\n\t}\n}\n\n/**\n * Resolve a fully-qualified ref's oid with one read instead of isomorphic-\n * git's own `resolveRef`, which does a stat *then* a read for a loose ref\n * (two round trips against object storage) — wasteful specifically here,\n * where the caller already knows the ref exists (it came from a directory\n * listing moments earlier). Reads the loose file directly and falls back to\n * `git.resolveRef` only when that doesn't pan out (packed-refs, or anything\n * else the plain-loose-file assumption doesn't cover), so correctness for\n * those cases is unchanged — this only removes the redundant round trip on\n * the common path.\n */\nexport async function resolveLooseRefFast(\n\trepo: Repo,\n\tref: string,\n): Promise<string> {\n\tconst promisesFs = getPromisesFs(repo.fs);\n\tif (promisesFs) {\n\t\ttry {\n\t\t\tconst content = await promisesFs.readFile(\n\t\t\t\t`${repo.gitdir}/${ref}`,\n\t\t\t\t\"utf8\",\n\t\t\t);\n\t\t\tconst oid = decodeFileContent(content).trim();\n\t\t\tif (FULL_SHA_RE.test(oid)) return oid;\n\t\t} catch {\n\t\t\t// Not a loose file (packed-refs, or genuinely absent) — fall through.\n\t\t}\n\t}\n\treturn git.resolveRef({ ...repo, ref });\n}\n\n/** All branches with their tip commits; [] for an empty repository. */\nexport async function listBranches(repo: Repo): Promise<Branch[]> {\n\ttry {\n\t\tconst [looseBranches, looseCurrentBranch, packedBranches] =\n\t\t\tawait Promise.all([\n\t\t\t\tlistLooseBranches(repo),\n\t\t\t\tgetCurrentLooseBranch(repo),\n\t\t\t\treadPackedBranches(repo),\n\t\t\t]);\n\t\tconst branches =\n\t\t\tlooseBranches === null\n\t\t\t\t? await git.listBranches(repo)\n\t\t\t\t: [...new Set([...looseBranches, ...packedBranches.keys()])].sort();\n\t\tconst currentBranch =\n\t\t\tlooseBranches === null\n\t\t\t\t? await git\n\t\t\t\t\t\t.currentBranch({ ...repo, fullname: false })\n\t\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\t\tif (isAbsentError(error)) return null;\n\t\t\t\t\t\t\tthrow error;\n\t\t\t\t\t\t})\n\t\t\t\t: looseCurrentBranch;\n\n\t\treturn Promise.all(\n\t\t\tbranches.map(async (branch) => {\n\t\t\t\tconst packedCommit = packedBranches.get(branch);\n\t\t\t\treturn {\n\t\t\t\t\tname: branch,\n\t\t\t\t\tcommit:\n\t\t\t\t\t\tpackedCommit && !looseBranches?.includes(branch)\n\t\t\t\t\t\t\t? packedCommit\n\t\t\t\t\t\t\t: await resolveLooseRefFast(repo, `refs/heads/${branch}`),\n\t\t\t\t\tisDefault: branch === currentBranch,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\t} catch (err: unknown) {\n\t\tif ((err as { code?: string }).code === \"NotFoundError\") return [];\n\t\tthrow err;\n\t}\n}\n\n/** Create `name` pointing at the tip of `startPoint` (no checkout). */\nexport async function createBranchFrom(\n\trepo: Repo,\n\tname: string,\n\tstartPoint: string,\n): Promise<void> {\n\tassertSafeBranchName(name);\n\tassertSafeBranchName(startPoint);\n\tconst object = await resolveLooseRefFast(repo, `refs/heads/${startPoint}`);\n\ttry {\n\t\tawait git.branch({ ...repo, ref: name, checkout: false, object });\n\t} catch (err) {\n\t\tif ((err as { code?: string }).code === \"AlreadyExistsError\") {\n\t\t\tthrow new GitConflictError(`Branch ${name} already exists`);\n\t\t}\n\t\tthrow err;\n\t}\n}\n\n/** Delete a branch ref (validated — deleteBranch has no internal ref check). */\nexport async function deleteBranchByName(\n\trepo: Repo,\n\tname: string,\n): Promise<void> {\n\tassertSafeBranchName(name);\n\t// Same rule as receive-pack: deleting the branch HEAD names leaves every\n\t// clone without a default branch.\n\tconst current =\n\t\t(await getCurrentLooseBranch(repo)) ??\n\t\t(await git\n\t\t\t.currentBranch({ ...repo, fullname: false })\n\t\t\t.catch((error: unknown) => {\n\t\t\t\t// A failed HEAD read must not skip this guard: isomorphic-git's\n\t\t\t\t// deleteBranch would then detach HEAD instead of refusing (#93).\n\t\t\t\tif (isAbsentError(error)) return null;\n\t\t\t\tthrow error;\n\t\t\t}));\n\tif (current === name) {\n\t\tthrow new GitInvalidRequestError(\n\t\t\t`Cannot delete ${name}: it is the default branch`,\n\t\t);\n\t}\n\tawait git.deleteBranch({ ...repo, ref: name });\n}\n\n/** Throws (NotFoundError) unless the branch resolves. */\nexport async function assertBranchExists(\n\trepo: Repo,\n\tname: string,\n): Promise<void> {\n\tassertSafeBranchName(name);\n\tawait resolveLooseRefFast(repo, `refs/heads/${name}`);\n}\n\n/** All tags with the commits they name, sorted by name; [] when there are none. */\nexport async function listTags(repo: Repo): Promise<Tag[]> {\n\tconst names = (await listLooseRefNames(repo, \"refs/tags\")) ?? [];\n\tconst all = new Set([\n\t\t...names,\n\t\t...(await git.listTags(repo).catch((error: unknown) => {\n\t\t\tif (isAbsentError(error)) return [] as string[];\n\t\t\tthrow error;\n\t\t})),\n\t]);\n\tconst tags = await Promise.all(\n\t\t[...all].filter(isSafeBranchName).map(async (name): Promise<Tag | null> => {\n\t\t\ttry {\n\t\t\t\tconst oid = await resolveLooseRefFast(repo, `refs/tags/${name}`);\n\t\t\t\tconst commit = await peelToCommit(repo, oid);\n\t\t\t\treturn commit === oid\n\t\t\t\t\t? { name, commit }\n\t\t\t\t\t: { name, commit, tagObject: oid };\n\t\t\t} catch (error) {\n\t\t\t\t// A tag deleted since the listing, or naming a missing object, is\n\t\t\t\t// not listed; a failed read fails the listing instead of\n\t\t\t\t// silently shortening it (#93).\n\t\t\t\tif (isAbsentError(error)) return null;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}),\n\t);\n\treturn tags\n\t\t.filter((tag): tag is Tag => tag !== null)\n\t\t.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }));\n}\n","/**\n * Writing packfiles: serialize whole (never deltified) objects into a pack,\n * and store a pack plus its index in a repository. Shared by repack (the\n * loose-object fallback) and packed writes (ops/packed-writes.ts).\n *\n * Edge-compatible: Web Crypto SHA-1, CompressionStream, Uint8Array only.\n */\nimport git from \"isomorphic-git\";\nimport {\n\tconcat,\n\tdeflate,\n\tencodeUtf8,\n\tfromHex,\n\tsha1,\n\ttoHex,\n} from \"./edge-utils.js\";\nimport { rawFs } from \"./http/types.js\";\nimport type { Repo } from \"./ops/types.js\";\nimport { packFileName } from \"./pack-files.js\";\n\nexport type PackObjectType = \"commit\" | \"tree\" | \"blob\" | \"tag\";\n\n// Git pack object type bits (bits 6-4 of the header's first byte).\nconst PACK_OBJECT_TYPE_BITS: Record<PackObjectType, number> = {\n\tcommit: 0b0010000,\n\ttree: 0b0100000,\n\tblob: 0b0110000,\n\ttag: 0b1000000,\n};\n\n// First byte: continuation bit | 3-bit type | low 4 bits of length; the rest\n// of the length follows 7 bits at a time, little-endian.\nfunction encodePackObjectHeader(\n\ttype: PackObjectType,\n\tlength: number,\n): Uint8Array {\n\tconst bytes: number[] = [];\n\tlet more = length > 0b1111;\n\tbytes.push(\n\t\t(more ? 0b10000000 : 0) | PACK_OBJECT_TYPE_BITS[type] | (length & 0b1111),\n\t);\n\tlet rest = Math.floor(length / 16);\n\twhile (more) {\n\t\tmore = rest > 0b01111111;\n\t\tbytes.push((more ? 0b10000000 : 0) | (rest & 0b01111111));\n\t\trest = Math.floor(rest / 128);\n\t}\n\treturn new Uint8Array(bytes);\n}\n\n/** Git's object id: sha1(\"<type> <byte length>\\0<content>\"). */\nexport function hashGitObject(\n\ttype: string,\n\tcontent: Uint8Array,\n): Promise<string> {\n\treturn sha1(concat(encodeUtf8(`${type} ${content.length}\\0`), content));\n}\n\nexport interface PackObject {\n\ttype: PackObjectType;\n\tcontent: Uint8Array<ArrayBuffer>;\n}\n\n/** A version-2 pack holding `objects` as full entries, in order. */\nexport async function encodePack(\n\tobjects: readonly PackObject[],\n): Promise<Uint8Array<ArrayBuffer>> {\n\tconst header = new Uint8Array(12);\n\tconst view = new DataView(header.buffer);\n\theader.set(encodeUtf8(\"PACK\"), 0);\n\tview.setUint32(4, 2, false);\n\tview.setUint32(8, objects.length, false);\n\n\tconst chunks: Uint8Array[] = [header];\n\tconst BATCH_SIZE = 100;\n\tfor (let i = 0; i < objects.length; i += BATCH_SIZE) {\n\t\tconst encoded = await Promise.all(\n\t\t\tobjects\n\t\t\t\t.slice(i, i + BATCH_SIZE)\n\t\t\t\t.map(async (object) =>\n\t\t\t\t\tconcat(\n\t\t\t\t\t\tencodePackObjectHeader(object.type, object.content.length),\n\t\t\t\t\t\tawait deflate(object.content),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t);\n\t\tchunks.push(...encoded);\n\t}\n\t// The trailer is the SHA-1 of every preceding byte.\n\tconst body = concat(...chunks);\n\treturn concat(body, fromHex(await sha1(body)));\n}\n\n/**\n * A pack's conventional base name, `pack-<checksum>`: the trailer SHA-1 is a\n * function of the content, so two writers can never pick the same name for\n * different packs, and rewriting the same pack is idempotent.\n */\nexport function packBaseName(pack: Uint8Array): string {\n\treturn `pack-${toHex(pack.subarray(pack.length - 20))}`;\n}\n\n/**\n * Store `pack` in `repo` and index it (isomorphic-git's `indexPack`, which\n * re-hashes every object). The `.idx` is written last: a pack only becomes\n * visible to readers once its index exists. Returns the base name and the\n * oids the index lists.\n */\nexport async function storePack(\n\trepo: Repo,\n\tpack: Uint8Array,\n): Promise<{ base: string; oids: string[] }> {\n\tconst fsp = rawFs(repo);\n\tconst packDir = `${repo.gitdir}/objects/pack`;\n\tconst base = packBaseName(pack);\n\tawait fsp.mkdir(packDir, { recursive: true });\n\tawait fsp.writeFile(`${packDir}/${packFileName(base, \"pack\")}`, pack);\n\tconst { oids } = await git.indexPack({\n\t\t...repo,\n\t\tdir: packDir,\n\t\tfilepath: packFileName(base, \"pack\"),\n\t});\n\treturn { base, oids };\n}\n","/**\n * A FIFO semaphore for bounding in-flight I/O.\n *\n * An unbounded `Promise.all` over a list whose size the caller (or an\n * attacker) controls — a git tree with tens of thousands of blob entries, say,\n * each costing one object-store read — issues that many concurrent requests\n * from a single push or clone. Sockets and memory then scale with the input,\n * and S3-compatible providers rate-limit per account, so one hostile push\n * degrades every other tenant. Bounding the *in-flight* count caps resource\n * use at `limit` no matter how wide the input is, while still letting reads\n * overlap up to that limit instead of running strictly sequentially.\n */\nexport interface Semaphore {\n\trun<T>(fn: () => Promise<T>): Promise<T>;\n}\n\n/**\n * Create a FIFO semaphore admitting at most `limit` concurrent `run`\n * executions. Waiters are queued as promises and released in call order — no\n * polling or timers — so a caller blocked on a full semaphore is woken the\n * instant a permit frees, not on the next tick of a poll loop.\n */\nexport function createSemaphore(limit: number): Semaphore {\n\tif (!Number.isInteger(limit) || limit < 1) {\n\t\tthrow new Error(\n\t\t\t`createSemaphore: limit must be an integer >= 1, got ${limit}`,\n\t\t);\n\t}\n\n\tlet active = 0;\n\tconst waiting: Array<() => void> = [];\n\n\t/**\n\t * Hand the permit to the next waiter instead of dropping it, so `active`\n\t * only decreases when nothing is queued and never exceeds `limit`.\n\t */\n\tfunction release(): void {\n\t\tconst next = waiting.shift();\n\t\tif (next) next();\n\t\telse active--;\n\t}\n\n\tfunction acquire(): Promise<void> {\n\t\tif (active < limit) {\n\t\t\tactive++;\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\treturn new Promise<void>((resolve) => {\n\t\t\twaiting.push(resolve);\n\t\t});\n\t}\n\n\treturn {\n\t\trun<T>(fn: () => Promise<T>): Promise<T> {\n\t\t\treturn acquire().then(async () => {\n\t\t\t\ttry {\n\t\t\t\t\treturn await fn();\n\t\t\t\t} finally {\n\t\t\t\t\trelease();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -70,3 +70,9 @@ export declare function formatErrorResponse(error: unknown): {
|
|
|
70
70
|
};
|
|
71
71
|
/** A missing repository, ref, path or object: on a read path that's a 404. */
|
|
72
72
|
export declare function isNotFoundError(error: unknown): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Nothing there: a not-found ref/object/path, or an fs `ENOENT` (no `HEAD`
|
|
75
|
+
* file, no `objects/pack` directory). Any other read failure is not absence,
|
|
76
|
+
* and a caller that reads it as absence changes what a write does (#91, #93).
|
|
77
|
+
*/
|
|
78
|
+
export declare function isAbsentError(error: unknown): boolean;
|
|
@@ -20,5 +20,12 @@ export interface RepackOptions {
|
|
|
20
20
|
* Consolidate all pack files into one, returning the gitdir-relative paths
|
|
21
21
|
* of the old .pack/.idx files it removed — after syncing the new pack to any
|
|
22
22
|
* secondary storage, delete those same paths there too.
|
|
23
|
+
*
|
|
24
|
+
* A failure rejects rather than being swallowed: whether a failed
|
|
25
|
+
* consolidation is fatal depends on the caller — a post-write repack must
|
|
26
|
+
* not fail an already-durable write, an explicit maintenance repack must
|
|
27
|
+
* report its failure — so the decision belongs at the call site. Leaving a
|
|
28
|
+
* failed run behind is safe (an unconsolidated repo still reads correctly),
|
|
29
|
+
* which is what lets those callers treat it as best-effort.
|
|
23
30
|
*/
|
|
24
31
|
export declare function repackRepository(repo: Repo, options?: RepackOptions, hooks?: HttpHooks): Promise<string[]>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { type CachedObjectStore, type CacheOptions, createCachedStore, } from "./cache.js";
|
|
2
2
|
export { concat, decodeAscii, decodeUtf8, deflate, encodeUtf8, fromHex, hasNullByte, readBlobContent, sha1, toBase64, toHex, } from "./edge-utils.js";
|
|
3
3
|
export { FsError } from "./errors.js";
|
|
4
|
-
export { formatErrorResponse, GitAuthenticationError, GitAuthorizationError, GitConflictError, GitError, GitInvalidRequestError, GitObjectNotFoundError, GitPathNotFoundError, GitProtocolError, GitRateLimitError, GitRefNotFoundError, GitRepositoryNotFoundError, isNotFoundError, type MergeConflictDetail, } from "./git-errors.js";
|
|
4
|
+
export { formatErrorResponse, GitAuthenticationError, GitAuthorizationError, GitConflictError, GitError, GitInvalidRequestError, GitObjectNotFoundError, GitPathNotFoundError, GitProtocolError, GitRateLimitError, GitRefNotFoundError, GitRepositoryNotFoundError, isAbsentError, isNotFoundError, type MergeConflictDetail, } from "./git-errors.js";
|
|
5
5
|
export { createGitFs, type GitFs } from "./git-fs.js";
|
|
6
6
|
export { classifyGitdirPath, type GitdirEntry, isMutableGitdirEntry, parseLooseObjectPath, } from "./git-layout.js";
|
|
7
7
|
export { getObjectSize } from "./object-size.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-fs-s3",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.3",
|
|
4
4
|
"description": "isomorphic-git filesystem backend for S3-compatible object storage (AWS S3, Cloudflare R2, MinIO) — run git servers without a disk",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"bugs": {
|
|
56
56
|
"url": "https://github.com/nandan-varma/pushstack/issues"
|
|
57
57
|
},
|
|
58
|
-
"homepage": "https://
|
|
58
|
+
"homepage": "https://docs.git.nandan.fyi/docs/libraries/git-fs-s3",
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
|
61
61
|
},
|
|
@@ -88,25 +88,20 @@
|
|
|
88
88
|
"devDependencies": {
|
|
89
89
|
"@aws-sdk/client-s3": "^3.1149.0",
|
|
90
90
|
"aws4fetch": "^1.0.20",
|
|
91
|
-
"@biomejs/biome": "^2.5.15",
|
|
92
91
|
"@types/node": "^26.6.5",
|
|
93
92
|
"isomorphic-git": "^1.44.3",
|
|
94
|
-
"
|
|
93
|
+
"tsdown": "^0.23.1",
|
|
95
94
|
"typescript": "^7.0.2",
|
|
96
|
-
"vitest": "^5.0.
|
|
97
|
-
"diff": "^9.0.0"
|
|
98
|
-
|
|
99
|
-
"allowScripts": {
|
|
100
|
-
"esbuild@0.27.7": true
|
|
95
|
+
"vitest": "^5.0.5",
|
|
96
|
+
"diff": "^9.0.0",
|
|
97
|
+
"@pushstack/tsconfig": "0.0.0"
|
|
101
98
|
},
|
|
102
99
|
"scripts": {
|
|
103
|
-
"build": "
|
|
100
|
+
"build": "tsdown && tsc -p tsconfig.build.json",
|
|
104
101
|
"test": "vitest run",
|
|
105
102
|
"test:watch": "vitest",
|
|
106
103
|
"coverage": "vitest run --coverage",
|
|
107
104
|
"typecheck": "tsc --noEmit",
|
|
108
|
-
"lint": "biome check
|
|
109
|
-
"lint:fix": "biome check --write src/ test/",
|
|
110
|
-
"format": "biome format --write src/ test/"
|
|
105
|
+
"lint": "biome check ."
|
|
111
106
|
}
|
|
112
107
|
}
|
package/dist/chunk-HLYCSNJ2.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// src/stores/memory.ts
|
|
2
|
-
var MemoryObjectStore = class {
|
|
3
|
-
objects = /* @__PURE__ */ new Map();
|
|
4
|
-
async get(key) {
|
|
5
|
-
const data = this.objects.get(key);
|
|
6
|
-
return data ? data.slice() : null;
|
|
7
|
-
}
|
|
8
|
-
async getRange(key, start, end) {
|
|
9
|
-
const data = this.objects.get(key);
|
|
10
|
-
return data ? data.slice(start, end + 1) : null;
|
|
11
|
-
}
|
|
12
|
-
async put(key, data) {
|
|
13
|
-
this.objects.set(key, data.slice());
|
|
14
|
-
}
|
|
15
|
-
async delete(key) {
|
|
16
|
-
this.objects.delete(key);
|
|
17
|
-
}
|
|
18
|
-
async head(key) {
|
|
19
|
-
const data = this.objects.get(key);
|
|
20
|
-
return data ? { size: data.byteLength } : null;
|
|
21
|
-
}
|
|
22
|
-
async list(prefix, options) {
|
|
23
|
-
const delimiter = options?.delimiter;
|
|
24
|
-
const limit = options?.limit ?? Number.POSITIVE_INFINITY;
|
|
25
|
-
const objects = [];
|
|
26
|
-
const prefixes = /* @__PURE__ */ new Set();
|
|
27
|
-
for (const [key, data] of this.objects) {
|
|
28
|
-
if (!key.startsWith(prefix)) continue;
|
|
29
|
-
const rest = key.slice(prefix.length);
|
|
30
|
-
if (delimiter !== void 0) {
|
|
31
|
-
const idx = rest.indexOf(delimiter);
|
|
32
|
-
if (idx !== -1) {
|
|
33
|
-
prefixes.add(prefix + rest.slice(0, idx + delimiter.length));
|
|
34
|
-
} else {
|
|
35
|
-
objects.push({ key, size: data.byteLength });
|
|
36
|
-
}
|
|
37
|
-
} else {
|
|
38
|
-
objects.push({ key, size: data.byteLength });
|
|
39
|
-
}
|
|
40
|
-
if (objects.length + prefixes.size >= limit) break;
|
|
41
|
-
}
|
|
42
|
-
return { objects, prefixes: [...prefixes] };
|
|
43
|
-
}
|
|
44
|
-
/** Number of stored objects (test convenience, not part of ObjectStore). */
|
|
45
|
-
get size() {
|
|
46
|
-
return this.objects.size;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export {
|
|
51
|
-
MemoryObjectStore
|
|
52
|
-
};
|
|
53
|
-
//# sourceMappingURL=chunk-HLYCSNJ2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/stores/memory.ts"],"sourcesContent":["import type {\n\tListOptions,\n\tListResult,\n\tObjectStat,\n\tObjectStore,\n} from \"../types.js\";\n\n/**\n * In-memory {@link ObjectStore}. Useful for tests, examples, and ephemeral\n * repositories; also the reference implementation for the list/delimiter\n * semantics other stores must match.\n */\nexport class MemoryObjectStore implements ObjectStore {\n\tprivate readonly objects = new Map<string, Uint8Array>();\n\n\tasync get(key: string): Promise<Uint8Array | null> {\n\t\tconst data = this.objects.get(key);\n\t\treturn data ? data.slice() : null;\n\t}\n\n\tasync getRange(\n\t\tkey: string,\n\t\tstart: number,\n\t\tend: number,\n\t): Promise<Uint8Array | null> {\n\t\tconst data = this.objects.get(key);\n\t\treturn data ? data.slice(start, end + 1) : null;\n\t}\n\n\tasync put(key: string, data: Uint8Array): Promise<void> {\n\t\tthis.objects.set(key, data.slice());\n\t}\n\n\tasync delete(key: string): Promise<void> {\n\t\tthis.objects.delete(key);\n\t}\n\n\tasync head(key: string): Promise<ObjectStat | null> {\n\t\tconst data = this.objects.get(key);\n\t\treturn data ? { size: data.byteLength } : null;\n\t}\n\n\tasync list(prefix: string, options?: ListOptions): Promise<ListResult> {\n\t\tconst delimiter = options?.delimiter;\n\t\tconst limit = options?.limit ?? Number.POSITIVE_INFINITY;\n\t\tconst objects: ListResult[\"objects\"] = [];\n\t\tconst prefixes = new Set<string>();\n\n\t\tfor (const [key, data] of this.objects) {\n\t\t\tif (!key.startsWith(prefix)) continue;\n\t\t\tconst rest = key.slice(prefix.length);\n\t\t\tif (delimiter !== undefined) {\n\t\t\t\tconst idx = rest.indexOf(delimiter);\n\t\t\t\tif (idx !== -1) {\n\t\t\t\t\tprefixes.add(prefix + rest.slice(0, idx + delimiter.length));\n\t\t\t\t} else {\n\t\t\t\t\tobjects.push({ key, size: data.byteLength });\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tobjects.push({ key, size: data.byteLength });\n\t\t\t}\n\t\t\tif (objects.length + prefixes.size >= limit) break;\n\t\t}\n\n\t\treturn { objects, prefixes: [...prefixes] };\n\t}\n\n\t/** Number of stored objects (test convenience, not part of ObjectStore). */\n\tget size(): number {\n\t\treturn this.objects.size;\n\t}\n}\n"],"mappings":";AAYO,IAAM,oBAAN,MAA+C;AAAA,EACpC,UAAU,oBAAI,IAAwB;AAAA,EAEvD,MAAM,IAAI,KAAyC;AAClD,UAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,WAAO,OAAO,KAAK,MAAM,IAAI;AAAA,EAC9B;AAAA,EAEA,MAAM,SACL,KACA,OACA,KAC6B;AAC7B,UAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,WAAO,OAAO,KAAK,MAAM,OAAO,MAAM,CAAC,IAAI;AAAA,EAC5C;AAAA,EAEA,MAAM,IAAI,KAAa,MAAiC;AACvD,SAAK,QAAQ,IAAI,KAAK,KAAK,MAAM,CAAC;AAAA,EACnC;AAAA,EAEA,MAAM,OAAO,KAA4B;AACxC,SAAK,QAAQ,OAAO,GAAG;AAAA,EACxB;AAAA,EAEA,MAAM,KAAK,KAAyC;AACnD,UAAM,OAAO,KAAK,QAAQ,IAAI,GAAG;AACjC,WAAO,OAAO,EAAE,MAAM,KAAK,WAAW,IAAI;AAAA,EAC3C;AAAA,EAEA,MAAM,KAAK,QAAgB,SAA4C;AACtE,UAAM,YAAY,SAAS;AAC3B,UAAM,QAAQ,SAAS,SAAS,OAAO;AACvC,UAAM,UAAiC,CAAC;AACxC,UAAM,WAAW,oBAAI,IAAY;AAEjC,eAAW,CAAC,KAAK,IAAI,KAAK,KAAK,SAAS;AACvC,UAAI,CAAC,IAAI,WAAW,MAAM,EAAG;AAC7B,YAAM,OAAO,IAAI,MAAM,OAAO,MAAM;AACpC,UAAI,cAAc,QAAW;AAC5B,cAAM,MAAM,KAAK,QAAQ,SAAS;AAClC,YAAI,QAAQ,IAAI;AACf,mBAAS,IAAI,SAAS,KAAK,MAAM,GAAG,MAAM,UAAU,MAAM,CAAC;AAAA,QAC5D,OAAO;AACN,kBAAQ,KAAK,EAAE,KAAK,MAAM,KAAK,WAAW,CAAC;AAAA,QAC5C;AAAA,MACD,OAAO;AACN,gBAAQ,KAAK,EAAE,KAAK,MAAM,KAAK,WAAW,CAAC;AAAA,MAC5C;AACA,UAAI,QAAQ,SAAS,SAAS,QAAQ,MAAO;AAAA,IAC9C;AAEA,WAAO,EAAE,SAAS,UAAU,CAAC,GAAG,QAAQ,EAAE;AAAA,EAC3C;AAAA;AAAA,EAGA,IAAI,OAAe;AAClB,WAAO,KAAK,QAAQ;AAAA,EACrB;AACD;","names":[]}
|