just-git 1.1.2 → 1.1.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 +52 -69
- package/dist/index.d.ts +26 -1
- package/dist/index.js +137 -137
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/just-git)
|
|
5
5
|
[](https://bundlejs.com/?q=just-git)
|
|
6
6
|
|
|
7
|
-
Pure TypeScript git implementation. Zero dependencies. 34 commands. Works in Node, Bun, Deno, and the browser. [Tested against real git](TESTING.md) across more than a million randomized operations
|
|
7
|
+
Pure TypeScript git implementation. Zero dependencies. 34 commands. Works in Node, Bun, Deno, Cloudflare Workers, and the browser. [Tested against real git](TESTING.md) across more than a million randomized operations.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Two entry points: a **virtual filesystem client** for sandboxed environments (pairs with [just-bash](https://github.com/vercel-labs/just-bash), or use standalone), and an **[embeddable git server](SERVER.md)** that any standard `git` client can clone, fetch, and push to.
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
@@ -16,26 +16,67 @@ npm install just-git
|
|
|
16
16
|
|
|
17
17
|
## Quick start
|
|
18
18
|
|
|
19
|
+
### Client
|
|
20
|
+
|
|
21
|
+
Provide any `FileSystem` implementation and call `git.exec()`:
|
|
22
|
+
|
|
19
23
|
```ts
|
|
20
|
-
import { Bash } from "just-bash";
|
|
21
24
|
import { createGit } from "just-git";
|
|
22
25
|
|
|
23
|
-
const git = createGit({
|
|
24
|
-
|
|
25
|
-
});
|
|
26
|
+
const git = createGit({ identity: { name: "Alice", email: "alice@example.com" } });
|
|
27
|
+
|
|
28
|
+
await git.exec("git init", { fs, cwd: "/repo" });
|
|
29
|
+
await git.exec("git add .", { fs, cwd: "/repo" });
|
|
30
|
+
await git.exec('git commit -m "initial commit"', { fs, cwd: "/repo" });
|
|
31
|
+
await git.exec("git log --oneline", { fs, cwd: "/repo" });
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Tokenization handles single and double quotes. Pass `env` as a plain object when needed (e.g. `GIT_AUTHOR_NAME`).
|
|
35
|
+
|
|
36
|
+
For a full virtual shell with file I/O, pipes, and scripting, pair with [just-bash](https://github.com/vercel-labs/just-bash):
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { Bash } from "just-bash";
|
|
40
|
+
import { createGit } from "just-git";
|
|
26
41
|
|
|
27
42
|
const bash = new Bash({
|
|
28
43
|
cwd: "/repo",
|
|
29
|
-
customCommands: [
|
|
44
|
+
customCommands: [createGit({ identity: { name: "Alice", email: "alice@example.com" } })],
|
|
30
45
|
});
|
|
31
46
|
|
|
32
|
-
await bash.exec("git init");
|
|
33
47
|
await bash.exec("echo 'hello' > README.md");
|
|
34
|
-
await bash.exec("git add .");
|
|
35
|
-
|
|
36
|
-
|
|
48
|
+
await bash.exec("git add . && git commit -m 'initial commit'");
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Server
|
|
52
|
+
|
|
53
|
+
Stand up a git server with SQLite-backed storage, branch protection, and push hooks:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { createGitServer, SqliteStorage } from "just-git/server";
|
|
57
|
+
import { Database } from "bun:sqlite";
|
|
58
|
+
|
|
59
|
+
const storage = new SqliteStorage(new Database("repos.sqlite"));
|
|
60
|
+
|
|
61
|
+
const server = createGitServer({
|
|
62
|
+
resolveRepo: (path) => storage.repo(path),
|
|
63
|
+
hooks: {
|
|
64
|
+
preReceive: ({ updates }) => {
|
|
65
|
+
if (updates.some((u) => u.ref === "refs/heads/main" && !u.isFF))
|
|
66
|
+
return { reject: true, message: "no force-push to main" };
|
|
67
|
+
},
|
|
68
|
+
postReceive: ({ repoPath, updates }) => {
|
|
69
|
+
console.log(`${repoPath}: ${updates.length} ref(s) updated`);
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
Bun.serve({ fetch: server.fetch });
|
|
75
|
+
// git clone http://localhost:3000/my-repo ← works with real git
|
|
37
76
|
```
|
|
38
77
|
|
|
78
|
+
Uses web-standard `Request`/`Response` — works with Bun, Hono, Cloudflare Workers, or any fetch-compatible runtime. See [SERVER.md](SERVER.md) for the full API.
|
|
79
|
+
|
|
39
80
|
## Options
|
|
40
81
|
|
|
41
82
|
`createGit(options?)` accepts:
|
|
@@ -205,43 +246,6 @@ Concurrent pushes to the same remote are automatically serialized — if two age
|
|
|
205
246
|
|
|
206
247
|
See [`examples/multi-agent.ts`](examples/multi-agent.ts) for a full working example with a coordinator agent that merges feature branches.
|
|
207
248
|
|
|
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
|
-
|
|
245
249
|
## Command coverage
|
|
246
250
|
|
|
247
251
|
See [CLI.md](CLI.md) for full usage details.
|
|
@@ -305,27 +309,6 @@ Targets high fidelity to real git (2.53.0). Validated with an [oracle testing fr
|
|
|
305
309
|
|
|
306
310
|
When backed by a real filesystem (e.g. just-bash `ReadWriteFs`), interoperable with real git on the same repo. Try `bun sandbox "git init"` to explore interactively.
|
|
307
311
|
|
|
308
|
-
## Without just-bash
|
|
309
|
-
|
|
310
|
-
`git.execute()` takes an args array and a `CommandContext`. Provide any `FileSystem` implementation:
|
|
311
|
-
|
|
312
|
-
```ts
|
|
313
|
-
import { createGit } from "just-git";
|
|
314
|
-
|
|
315
|
-
const git = createGit({ identity: { name: "Bot", email: "bot@example.com" } });
|
|
316
|
-
|
|
317
|
-
const result = await git.execute(["init"], {
|
|
318
|
-
fs: myFileSystem, // any FileSystem implementation
|
|
319
|
-
cwd: "/repo",
|
|
320
|
-
env: new Map(),
|
|
321
|
-
stdin: "",
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
console.log(result.exitCode); // 0
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
The `FileSystem` interface requires: `readFile`, `readFileBuffer`, `writeFile`, `exists`, `stat`, `mkdir`, `readdir`, `rm`. Optional: `lstat`, `readlink`, `symlink`.
|
|
328
|
-
|
|
329
312
|
## Examples
|
|
330
313
|
|
|
331
314
|
Runnable examples in [`examples/`](examples/):
|
package/dist/index.d.ts
CHANGED
|
@@ -63,14 +63,39 @@ interface GitExtensions {
|
|
|
63
63
|
objectStore?: ObjectStore;
|
|
64
64
|
refStore?: RefStore;
|
|
65
65
|
}
|
|
66
|
+
/** Simplified context for {@link Git.exec}. */
|
|
67
|
+
interface ExecContext {
|
|
68
|
+
fs: FileSystem;
|
|
69
|
+
cwd: string;
|
|
70
|
+
env?: Record<string, string>;
|
|
71
|
+
stdin?: string;
|
|
72
|
+
}
|
|
66
73
|
declare class Git {
|
|
67
74
|
readonly name = "git";
|
|
68
75
|
private blocked;
|
|
69
76
|
private hooks;
|
|
70
77
|
private inner;
|
|
71
78
|
constructor(options?: GitOptions);
|
|
79
|
+
/**
|
|
80
|
+
* Run a git command from a string.
|
|
81
|
+
*
|
|
82
|
+
* Tokenizes the input with basic shell quoting (single/double quotes).
|
|
83
|
+
* Strips a leading `git ` prefix if present. Does not support shell
|
|
84
|
+
* features like pipes, redirections, variable expansion, or `&&`.
|
|
85
|
+
*
|
|
86
|
+
* ```ts
|
|
87
|
+
* await git.exec('commit -m "initial commit"', { fs, cwd: "/repo" });
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
exec: (command: string, ctx: ExecContext) => Promise<ExecResult>;
|
|
72
91
|
execute: (args: string[], ctx: CommandContext) => Promise<ExecResult>;
|
|
73
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Tokenize a command string with basic shell quoting.
|
|
95
|
+
* Supports single quotes, double quotes (with backslash escapes),
|
|
96
|
+
* and whitespace splitting. Strips a leading "git" token if present.
|
|
97
|
+
*/
|
|
98
|
+
declare function tokenizeCommand(input: string): string[];
|
|
74
99
|
declare function createGit(options?: GitOptions): Git;
|
|
75
100
|
|
|
76
101
|
/**
|
|
@@ -81,4 +106,4 @@ declare function createGit(options?: GitOptions): Git;
|
|
|
81
106
|
*/
|
|
82
107
|
declare function findRepo(fs: FileSystem, startPath: string): Promise<GitContext | null>;
|
|
83
108
|
|
|
84
|
-
export { type CommandContext, type CommandExecOptions, CredentialProvider, ExecResult, FetchFunction, FileSystem, Git, type GitCommandName, GitContext, type GitExtensions, GitHooks, type GitOptions, IdentityOverride, NetworkPolicy, ObjectStore, RefStore, RemoteResolver, createGit, findRepo };
|
|
109
|
+
export { type CommandContext, type CommandExecOptions, CredentialProvider, type ExecContext, ExecResult, FetchFunction, FileSystem, Git, type GitCommandName, GitContext, type GitExtensions, GitHooks, type GitOptions, IdentityOverride, NetworkPolicy, ObjectStore, RefStore, RemoteResolver, createGit, findRepo, tokenizeCommand };
|