just-git 1.2.5 → 1.2.7
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 +34 -76
- package/dist/index.d.ts +15 -7
- package/dist/index.js +255 -253
- package/dist/repo/index.d.ts +46 -1
- package/dist/repo/index.js +11 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,29 +18,6 @@ npm install just-git
|
|
|
18
18
|
|
|
19
19
|
### Client
|
|
20
20
|
|
|
21
|
-
```ts
|
|
22
|
-
import { createGit, MemoryFileSystem } from "just-git";
|
|
23
|
-
|
|
24
|
-
const fs = new MemoryFileSystem();
|
|
25
|
-
const git = createGit({
|
|
26
|
-
identity: { name: "Alice", email: "alice@example.com" },
|
|
27
|
-
credentials: (url) => ({ type: "bearer", token: process.env.GITHUB_TOKEN! }),
|
|
28
|
-
hooks: {
|
|
29
|
-
beforeCommand: ({ command }) => {
|
|
30
|
-
if (command === "push") return { reject: true, message: "push requires approval" };
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
await git.exec("git init", { fs, cwd: "/repo" });
|
|
36
|
-
await fs.writeFile("/repo/README.md", "# Hello\n");
|
|
37
|
-
await git.exec("git add .", { fs, cwd: "/repo" });
|
|
38
|
-
await git.exec('git commit -m "initial commit"', { fs, cwd: "/repo" });
|
|
39
|
-
await git.exec("git log --oneline", { fs, cwd: "/repo" });
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
`MemoryFileSystem` is a minimal in-memory filesystem for standalone use. Tokenization handles single and double quotes; pass `env` as a plain object when needed (e.g. `GIT_AUTHOR_NAME`). The `FileSystem` interface is built around [just-bash](https://github.com/vercel-labs/just-bash)'s implementations. For anything beyond bare git commands, it's recommended to use just-git as a custom command in just-bash:
|
|
43
|
-
|
|
44
21
|
```ts
|
|
45
22
|
import { Bash } from "just-bash";
|
|
46
23
|
import { createGit } from "just-git";
|
|
@@ -54,76 +31,61 @@ await bash.exec("echo 'hello' > README.md");
|
|
|
54
31
|
await bash.exec("git add . && git commit -m 'initial commit'");
|
|
55
32
|
```
|
|
56
33
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Stand up a git server with built-in storage (SQLite or [PostgreSQL](docs/SERVER.md#pgstorage)), branch protection, and push hooks:
|
|
34
|
+
Pass a `Git` instance into [just-bash](https://github.com/vercel-labs/just-bash) as a custom command and you get pipes, redirects, `&&` chaining, and the full shell environment alongside git. For standalone use without just-bash, `MemoryFileSystem` provides a minimal in-memory filesystem and `git.exec` accepts a command string with basic quote-aware splitting:
|
|
60
35
|
|
|
61
36
|
```ts
|
|
62
|
-
import {
|
|
63
|
-
import { Database } from "bun:sqlite";
|
|
64
|
-
|
|
65
|
-
const storage = new BunSqliteStorage(new Database("repos.sqlite"));
|
|
37
|
+
import { createGit, MemoryFileSystem } from "just-git";
|
|
66
38
|
|
|
67
|
-
const
|
|
68
|
-
|
|
39
|
+
const fs = new MemoryFileSystem();
|
|
40
|
+
const git = createGit({
|
|
41
|
+
fs,
|
|
42
|
+
identity: { name: "Alice", email: "alice@example.com" },
|
|
43
|
+
credentials: (url) => ({ type: "bearer", token: process.env.GITHUB_TOKEN! }),
|
|
69
44
|
hooks: {
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
return { reject: true, message: "no force-push to main" };
|
|
73
|
-
},
|
|
74
|
-
postReceive: ({ repoPath, updates }) => {
|
|
75
|
-
console.log(`${repoPath}: ${updates.length} ref(s) updated`);
|
|
45
|
+
beforeCommand: ({ command }) => {
|
|
46
|
+
if (command === "push") return { reject: true, message: "push requires approval" };
|
|
76
47
|
},
|
|
77
48
|
},
|
|
78
49
|
});
|
|
79
50
|
|
|
80
|
-
|
|
81
|
-
|
|
51
|
+
await git.exec("git init");
|
|
52
|
+
await fs.writeFile("/README.md", "# Hello\n");
|
|
53
|
+
await git.exec("git add .");
|
|
54
|
+
await git.exec('git commit -m "initial commit"');
|
|
82
55
|
```
|
|
83
56
|
|
|
84
|
-
|
|
57
|
+
`createGit` also supports [command restrictions, network policies, and config overrides](docs/CLIENT.md#options) for sandboxing, a [lifecycle hooks API](docs/CLIENT.md#hooks) covering pre-commit secret scanning to push gating, and [cross-VFS remote resolution](docs/CLIENT.md#multi-agent-collaboration) for multi-agent collaboration. See [CLIENT.md](docs/CLIENT.md) for the full reference.
|
|
85
58
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
`createGit(options?)` accepts:
|
|
89
|
-
|
|
90
|
-
| Option | Description |
|
|
91
|
-
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
92
|
-
| `identity` | Author/committer override. With `locked: true`, always wins over env vars and git config. Without `locked`, acts as a fallback. |
|
|
93
|
-
| `credentials` | `(url) => HttpAuth \| null` callback for Smart HTTP transport auth. |
|
|
94
|
-
| `disabled` | `GitCommandName[]` of subcommands to block (e.g. `["push", "rebase"]`). |
|
|
95
|
-
| `network` | `{ allowed?: string[], fetch? }` to restrict HTTP access. Set to `false` to block all network access. |
|
|
96
|
-
| `config` | `{ locked?, defaults? }` config overrides. `locked` values always win over `.git/config`; `defaults` supply fallbacks when a key is absent. |
|
|
97
|
-
| `hooks` | Lifecycle hooks for pre/post command interception, commit gating, message enforcement, and audit logging. |
|
|
98
|
-
| `resolveRemote` | `(url) => GitRepo \| null` callback for cross-VFS remote resolution (multi-agent setups). |
|
|
99
|
-
|
|
100
|
-
See [CLIENT.md](docs/CLIENT.md) for detailed usage, config overrides, and multi-agent collaboration.
|
|
101
|
-
|
|
102
|
-
## Client hooks
|
|
59
|
+
### Server
|
|
103
60
|
|
|
104
|
-
|
|
61
|
+
Stand up a git server with built-in storage (SQLite or PostgreSQL), branch protection, auth, and push hooks:
|
|
105
62
|
|
|
106
63
|
```ts
|
|
107
|
-
import {
|
|
64
|
+
import { createGitServer, createStandardHooks, BunSqliteStorage } from "just-git/server";
|
|
108
65
|
import { getChangedFiles } from "just-git/repo";
|
|
66
|
+
import { Database } from "bun:sqlite";
|
|
109
67
|
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
68
|
+
const storage = new BunSqliteStorage(new Database("repos.sqlite"));
|
|
69
|
+
|
|
70
|
+
const server = createGitServer({
|
|
71
|
+
resolveRepo: (path) => storage.repo(path),
|
|
72
|
+
hooks: createStandardHooks({
|
|
73
|
+
protectedBranches: ["main"],
|
|
74
|
+
authorizePush: (request) => request.headers.has("Authorization"),
|
|
75
|
+
onPush: async ({ repo, repoPath, updates }) => {
|
|
76
|
+
for (const u of updates) {
|
|
77
|
+
const files = await getChangedFiles(repo, u.oldHash, u.newHash);
|
|
78
|
+
console.log(`${repoPath}: ${u.ref} — ${files.length} files changed`);
|
|
116
79
|
}
|
|
117
80
|
},
|
|
118
|
-
|
|
119
|
-
const files = await getChangedFiles(repo, parents[0] ?? null, hash);
|
|
120
|
-
onAgentCommit({ hash, branch, changedFiles: files });
|
|
121
|
-
},
|
|
122
|
-
},
|
|
81
|
+
}),
|
|
123
82
|
});
|
|
83
|
+
|
|
84
|
+
Bun.serve({ fetch: server.fetch });
|
|
85
|
+
// git clone http://localhost:3000/my-repo ← works with real git
|
|
124
86
|
```
|
|
125
87
|
|
|
126
|
-
|
|
88
|
+
Uses web-standard `Request`/`Response`. Works with Bun, Hono, Cloudflare Workers, or any fetch-compatible runtime. For Node.js, use `toNodeHandler(server)` with `http.createServer` and `BetterSqlite3Storage` for `better-sqlite3`. Use `withAuth` to gate clone and fetch access as well. See [SERVER.md](docs/SERVER.md) for the full API.
|
|
127
89
|
|
|
128
90
|
## Repo module
|
|
129
91
|
|
|
@@ -141,10 +103,6 @@ const result = await mergeTrees(repo, oursCommit, theirsCommit);
|
|
|
141
103
|
|
|
142
104
|
See [REPO.md](docs/REPO.md) for the full API, the `GitRepo` interface, and the hybrid worktree pattern.
|
|
143
105
|
|
|
144
|
-
## Multi-agent collaboration
|
|
145
|
-
|
|
146
|
-
Multiple agents can clone, fetch, push, and pull across isolated in-memory filesystems within the same process via the `resolveRemote` option, without needing a network or shared filesystem. Concurrent pushes are automatically serialized with proper non-fast-forward rejection. See [CLIENT.md](docs/CLIENT.md#multi-agent-collaboration) and [`examples/multi-agent.ts`](examples/multi-agent.ts).
|
|
147
|
-
|
|
148
106
|
## Commands
|
|
149
107
|
|
|
150
108
|
34 commands: `init`, `clone`, `fetch`, `push`, `pull`, `add`, `rm`, `mv`, `commit`, `status`, `log`, `show`, `diff`, `blame`, `branch`, `tag`, `checkout`, `switch`, `restore`, `reset`, `merge`, `rebase`, `cherry-pick`, `revert`, `stash`, `remote`, `config`, `bisect`, `clean`, `reflog`, `gc`, `repack`, `rev-parse`, `ls-files`. See [CLI.md](docs/CLI.md) for full usage details.
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,12 @@ type GitCommandName = "init" | "clone" | "fetch" | "pull" | "push" | "add" | "bl
|
|
|
32
32
|
* this instance.
|
|
33
33
|
*/
|
|
34
34
|
interface GitOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Default filesystem for {@link Git.exec}. When set, `exec` calls
|
|
37
|
+
* don't need to pass `fs` in the context. Ignored by `execute`
|
|
38
|
+
* (just-bash always provides its own filesystem).
|
|
39
|
+
*/
|
|
40
|
+
fs?: FileSystem;
|
|
35
41
|
hooks?: GitHooks;
|
|
36
42
|
credentials?: CredentialProvider;
|
|
37
43
|
identity?: IdentityOverride;
|
|
@@ -64,8 +70,10 @@ interface GitOptions {
|
|
|
64
70
|
}
|
|
65
71
|
/** Simplified context for {@link Git.exec}. */
|
|
66
72
|
interface ExecContext {
|
|
67
|
-
fs
|
|
68
|
-
|
|
73
|
+
/** Filesystem to operate on. Falls back to the `fs` set in {@link GitOptions}. */
|
|
74
|
+
fs?: FileSystem;
|
|
75
|
+
/** Working directory. Defaults to `"/"`. */
|
|
76
|
+
cwd?: string;
|
|
69
77
|
env?: Record<string, string>;
|
|
70
78
|
stdin?: string;
|
|
71
79
|
}
|
|
@@ -77,13 +85,13 @@ interface ExecContext {
|
|
|
77
85
|
* to make `git` available inside a virtual shell.
|
|
78
86
|
*
|
|
79
87
|
* ```ts
|
|
80
|
-
* const git = createGit();
|
|
81
|
-
*
|
|
82
|
-
* await git.exec("init", { fs, cwd: "/repo" });
|
|
88
|
+
* const git = createGit({ fs: new MemoryFileSystem() });
|
|
89
|
+
* await git.exec("init");
|
|
83
90
|
* ```
|
|
84
91
|
*/
|
|
85
92
|
declare class Git {
|
|
86
93
|
readonly name = "git";
|
|
94
|
+
private defaultFs;
|
|
87
95
|
private blocked;
|
|
88
96
|
private hooks;
|
|
89
97
|
private inner;
|
|
@@ -98,10 +106,10 @@ declare class Git {
|
|
|
98
106
|
* features like pipes, redirections, variable expansion, or `&&`.
|
|
99
107
|
*
|
|
100
108
|
* ```ts
|
|
101
|
-
* await git.exec('commit -m "initial commit"'
|
|
109
|
+
* await git.exec('commit -m "initial commit"');
|
|
102
110
|
* ```
|
|
103
111
|
*/
|
|
104
|
-
exec: (command: string, ctx
|
|
112
|
+
exec: (command: string, ctx?: ExecContext) => Promise<ExecResult>;
|
|
105
113
|
execute: (args: string[], ctx: CommandContext) => Promise<ExecResult>;
|
|
106
114
|
}
|
|
107
115
|
/** Create a new {@link Git} command handler with the given options. */
|