just-git 1.1.0 → 1.1.2

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 CHANGED
@@ -118,6 +118,40 @@ const git = createGit({
118
118
 
119
119
  Available pre-hooks: `preCommit`, `commitMsg`, `mergeMsg`, `preMergeCommit`, `preCheckout`, `prePush`, `preFetch`, `preClone`, `prePull`, `preRebase`, `preReset`, `preClean`, `preRm`, `preCherryPick`, `preRevert`, `preStash`. Available post-hooks: `postCommit`, `postMerge`, `postCheckout`, `postPush`, `postFetch`, `postClone`, `postPull`, `postReset`, `postClean`, `postRm`, `postCherryPick`, `postRevert`, `postStash`. Low-level events: `onRefUpdate`, `onRefDelete`, `onObjectWrite`. Command-level: `beforeCommand`, `afterCommand`.
120
120
 
121
+ ## Repo module
122
+
123
+ `just-git/repo` provides a high-level API for working with repositories programmatically — reading commits, diffing trees, creating objects, and merging — without going through command execution. This is what you use inside hooks (all hook payloads include `repo: GitRepo`) and anywhere else you need direct repo access.
124
+
125
+ ```ts
126
+ import {
127
+ readCommit,
128
+ readFileAtCommit,
129
+ getChangedFiles,
130
+ resolveRef,
131
+ listBranches,
132
+ diffTrees,
133
+ flattenTree,
134
+ createCommit,
135
+ writeBlob,
136
+ writeTree,
137
+ mergeTrees,
138
+ checkoutTo,
139
+ readonlyRepo,
140
+ } from "just-git/repo";
141
+
142
+ // Read a file at a specific commit
143
+ const content = await readFileAtCommit(repo, commitHash, "src/index.ts");
144
+
145
+ // Diff two commits
146
+ const changes = await getChangedFiles(repo, parentHash, commitHash);
147
+
148
+ // Merge two branches at the tree level (no worktree needed)
149
+ const result = await mergeTrees(repo, oursCommit, theirsCommit);
150
+ if (!result.clean) console.log("conflicts:", result.conflicts);
151
+ ```
152
+
153
+ Also re-exports `PackedObjectStore` and `FileSystemRefStore` for custom storage backends, and `readonlyRepo()` to wrap a repo so all write operations throw.
154
+
121
155
  ## Multi-agent collaboration
122
156
 
123
157
  Multiple agents can work on clones of the same repository in the same process, each with full VFS isolation. The `resolveRemote` option maps remote URLs to `GitRepo` instances (any object/ref store — VFS-backed, SQLite, etc.), so clone/fetch/push/pull cross VFS boundaries without any network or shared filesystem.
@@ -171,6 +205,43 @@ Concurrent pushes to the same remote are automatically serialized — if two age
171
205
 
172
206
  See [`examples/multi-agent.ts`](examples/multi-agent.ts) for a full working example with a coordinator agent that merges feature branches.
173
207
 
208
+ ## Server
209
+
210
+ `just-git/server` is an embeddable Git Smart HTTP server. Any standard git client can clone, fetch, and push. Uses web-standard `Request`/`Response` — works with Bun, Hono, Cloudflare Workers, or any fetch-compatible runtime.
211
+
212
+ ```ts
213
+ import { createGitServer, SqliteStorage } from "just-git/server";
214
+ import { getChangedFiles } from "just-git/repo";
215
+ import { Database } from "bun:sqlite";
216
+
217
+ const storage = new SqliteStorage(new Database("repos.sqlite"));
218
+
219
+ const server = createGitServer({
220
+ resolveRepo: async (repoPath) => storage.repo(repoPath),
221
+ hooks: {
222
+ preReceive: async ({ updates }) => {
223
+ for (const u of updates) {
224
+ if (u.ref === "refs/heads/main" && !u.isFF && !u.isCreate) {
225
+ return { reject: true, message: "no force-push to main" };
226
+ }
227
+ }
228
+ },
229
+ postReceive: async ({ repo, updates }) => {
230
+ for (const u of updates) {
231
+ const files = await getChangedFiles(repo, u.oldHash, u.newHash);
232
+ console.log(`${u.ref}: ${files.length} files changed`);
233
+ }
234
+ },
235
+ },
236
+ });
237
+
238
+ Bun.serve({ fetch: server.fetch });
239
+ ```
240
+
241
+ `SqliteStorage` persists repos in SQLite without a filesystem — works with `bun:sqlite`, `better-sqlite3`, or any compatible driver. Repos backed by `SqliteStorage` work with both the server (external HTTP) and `resolveRemote` (in-process), with CAS-protected ref updates ensuring correctness regardless of write path.
242
+
243
+ See [SERVER.md](SERVER.md) for the full API: hooks, `createStandardHooks`, `SqliteStorage`, configuration, and deployment patterns. See [`examples/sqlite-server.ts`](examples/sqlite-server.ts) for a runnable SQLite server and [`examples/server.ts`](examples/server.ts) for a VFS-backed server with virtual client. See [`src/platform/`](src/platform/) for a reference implementation that builds GitHub-like functionality (repos, pull requests, merge strategies) on top of these primitives.
244
+
174
245
  ## Command coverage
175
246
 
176
247
  See [CLI.md](CLI.md) for full usage details.
@@ -254,3 +325,18 @@ console.log(result.exitCode); // 0
254
325
  ```
255
326
 
256
327
  The `FileSystem` interface requires: `readFile`, `readFileBuffer`, `writeFile`, `exists`, `stat`, `mkdir`, `readdir`, `rm`. Optional: `lstat`, `readlink`, `symlink`.
328
+
329
+ ## Examples
330
+
331
+ Runnable examples in [`examples/`](examples/):
332
+
333
+ | File | What it demonstrates |
334
+ | --------------------------------------------------------------- | -------------------------------------------------------------------- |
335
+ | [`usage.ts`](examples/usage.ts) | Identity, disabled commands, hooks, compose, full sandbox setup |
336
+ | [`multi-agent.ts`](examples/multi-agent.ts) | Cross-VFS collaboration with clone/push/pull between isolated agents |
337
+ | [`server.ts`](examples/server.ts) | VFS-backed Smart HTTP server with virtual client clone and push |
338
+ | [`sqlite-server.ts`](examples/sqlite-server.ts) | SQLite-backed server with auto-creating repos, works with real `git` |
339
+ | [`platform-server.ts`](examples/platform-server.ts) | GitHub-like PR workflows: create, merge, close via REST API |
340
+ | [`agent-remote-workflow.ts`](examples/agent-remote-workflow.ts) | Clone from GitHub, work in sandbox, push back (requires token) |
341
+
342
+ Run any example with `bun examples/<file>`.
@@ -477,4 +477,4 @@ interface GitHooks {
477
477
  }
478
478
  declare function composeGitHooks(...hookSets: (GitHooks | undefined)[]): GitHooks;
479
479
 
480
- export { type Commit as $, type AfterCommandEvent as A, type BeforeCommandEvent as B, type CredentialProvider as C, type PrePullEvent as D, type ExecResult as E, type FileSystem as F, type GitHooks as G, type HttpAuth as H, type IdentityOverride as I, type PrePushEvent as J, type PreRebaseEvent as K, type PreResetEvent as L, type MergeMsgEvent as M, type NetworkPolicy as N, type ObjectStore as O, type PostCheckoutEvent as P, type PreRevertEvent as Q, type RemoteResolver as R, type PreRmEvent as S, type PreStashEvent as T, type RefDeleteEvent as U, type RefEntry as V, type RefUpdateEvent as W, type Rejection as X, composeGitHooks as Y, isRejection as Z, type ObjectId as _, type RefStore as a, type Identity as a0, type TreeDiffEntry as a1, type ObjectType as a2, type RawObject as a3, type Ref as a4, type FetchFunction as b, type GitContext as c, type CommitMsgEvent as d, type FileStat as e, type GitRepo as f, type ObjectWriteEvent as g, type PostCherryPickEvent as h, type PostCleanEvent as i, type PostCloneEvent as j, type PostCommitEvent as k, type PostFetchEvent as l, type PostMergeEvent as m, type PostPullEvent as n, type PostPushEvent as o, type PostResetEvent as p, type PostRevertEvent as q, type PostRmEvent as r, type PostStashEvent as s, type PreCheckoutEvent as t, type PreCherryPickEvent as u, type PreCleanEvent as v, type PreCloneEvent as w, type PreCommitEvent as x, type PreFetchEvent as y, type PreMergeCommitEvent as z };
480
+ export { type Identity as $, type AfterCommandEvent as A, type BeforeCommandEvent as B, type CredentialProvider as C, type PrePullEvent as D, type ExecResult as E, type FileSystem as F, type GitHooks as G, type HttpAuth as H, type IdentityOverride as I, type PrePushEvent as J, type PreRebaseEvent as K, type PreResetEvent as L, type MergeMsgEvent as M, type NetworkPolicy as N, type ObjectStore as O, type PostCheckoutEvent as P, type PreRevertEvent as Q, type RemoteResolver as R, type PreRmEvent as S, type PreStashEvent as T, type RefDeleteEvent as U, type RefEntry as V, type RefUpdateEvent as W, type Rejection as X, composeGitHooks as Y, isRejection as Z, type ObjectId as _, type RefStore as a, type TreeDiffEntry as a0, type Commit as a1, type ObjectType as a2, type RawObject as a3, type Ref as a4, type FetchFunction as b, type GitContext as c, type CommitMsgEvent as d, type FileStat as e, type GitRepo as f, type ObjectWriteEvent as g, type PostCherryPickEvent as h, type PostCleanEvent as i, type PostCloneEvent as j, type PostCommitEvent as k, type PostFetchEvent as l, type PostMergeEvent as m, type PostPullEvent as n, type PostPushEvent as o, type PostResetEvent as p, type PostRevertEvent as q, type PostRmEvent as r, type PostStashEvent as s, type PreCheckoutEvent as t, type PreCherryPickEvent as u, type PreCleanEvent as v, type PreCloneEvent as w, type PreCommitEvent as x, type PreFetchEvent as y, type PreMergeCommitEvent as z };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FileSystem, E as ExecResult, G as GitHooks, C as CredentialProvider, I as IdentityOverride, N as NetworkPolicy, R as RemoteResolver, O as ObjectStore, a as RefStore, b as FetchFunction, c as GitContext } from './hooks-jTfqkfs1.js';
2
- export { A as AfterCommandEvent, B as BeforeCommandEvent, d as CommitMsgEvent, e as FileStat, f as GitRepo, H as HttpAuth, M as MergeMsgEvent, g as ObjectWriteEvent, P as PostCheckoutEvent, h as PostCherryPickEvent, i as PostCleanEvent, j as PostCloneEvent, k as PostCommitEvent, l as PostFetchEvent, m as PostMergeEvent, n as PostPullEvent, o as PostPushEvent, p as PostResetEvent, q as PostRevertEvent, r as PostRmEvent, s as PostStashEvent, t as PreCheckoutEvent, u as PreCherryPickEvent, v as PreCleanEvent, w as PreCloneEvent, x as PreCommitEvent, y as PreFetchEvent, z as PreMergeCommitEvent, D as PrePullEvent, J as PrePushEvent, K as PreRebaseEvent, L as PreResetEvent, Q as PreRevertEvent, S as PreRmEvent, T as PreStashEvent, U as RefDeleteEvent, V as RefEntry, W as RefUpdateEvent, X as Rejection, Y as composeGitHooks, Z as isRejection } from './hooks-jTfqkfs1.js';
1
+ import { F as FileSystem, E as ExecResult, G as GitHooks, C as CredentialProvider, I as IdentityOverride, N as NetworkPolicy, R as RemoteResolver, O as ObjectStore, a as RefStore, b as FetchFunction, c as GitContext } from './hooks-1dcjVqc3.js';
2
+ export { A as AfterCommandEvent, B as BeforeCommandEvent, d as CommitMsgEvent, e as FileStat, f as GitRepo, H as HttpAuth, M as MergeMsgEvent, g as ObjectWriteEvent, P as PostCheckoutEvent, h as PostCherryPickEvent, i as PostCleanEvent, j as PostCloneEvent, k as PostCommitEvent, l as PostFetchEvent, m as PostMergeEvent, n as PostPullEvent, o as PostPushEvent, p as PostResetEvent, q as PostRevertEvent, r as PostRmEvent, s as PostStashEvent, t as PreCheckoutEvent, u as PreCherryPickEvent, v as PreCleanEvent, w as PreCloneEvent, x as PreCommitEvent, y as PreFetchEvent, z as PreMergeCommitEvent, D as PrePullEvent, J as PrePushEvent, K as PreRebaseEvent, L as PreResetEvent, Q as PreRevertEvent, S as PreRmEvent, T as PreStashEvent, U as RefDeleteEvent, V as RefEntry, W as RefUpdateEvent, X as Rejection, Y as composeGitHooks, Z as isRejection } from './hooks-1dcjVqc3.js';
3
3
 
4
4
  /** Options for subcommand execution (mirrors just-bash's CommandExecOptions). */
5
5
  interface CommandExecOptions {