jj-octo 0.2.4 → 0.3.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 +8 -0
- package/dist/jj-octo.js +66 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,6 +56,14 @@ bun update --global --latest jj-octo
|
|
|
56
56
|
|
|
57
57
|
It uses only GitHub's REST API, so that it works in a [Claude Code](https://claude.com/claude-code) cloud session. There, GitHub is reached through a proxy that allows REST calls for the session's repository and blocks GraphQL, which `gh pr` depends on.
|
|
58
58
|
|
|
59
|
+
Where git reaches github.com through a proxy that adds the credentials itself, as in a Claude Code cloud session that keeps the token outside the sandbox, have `jj-octo` use that proxy too:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
jj config set --repo jj-octo.github-auth git-proxy
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`jj-octo` then sends its requests through the `http.proxy` that git uses for `https://github.com`, trusts the certificate authorities in git's `http.sslCAInfo` for it, and sends a placeholder token that the proxy replaces. It reads git's settings on each run, so it follows a proxy that moves to another port. `token`, the default, sends your own token.
|
|
66
|
+
|
|
59
67
|
## Development
|
|
60
68
|
|
|
61
69
|
```
|
package/dist/jj-octo.js
CHANGED
|
@@ -18112,7 +18112,7 @@ var layer14 = /* @__PURE__ */ layerMergedContext(/* @__PURE__ */ succeed6(fetch)
|
|
|
18112
18112
|
// package.json
|
|
18113
18113
|
var package_default = {
|
|
18114
18114
|
name: "jj-octo",
|
|
18115
|
-
version: "0.
|
|
18115
|
+
version: "0.3.0",
|
|
18116
18116
|
description: "A jj subcommand for working with GitHub that supports stacking",
|
|
18117
18117
|
license: "MIT",
|
|
18118
18118
|
repository: {
|
|
@@ -18493,24 +18493,21 @@ var MergeRequest = Struct({
|
|
|
18493
18493
|
});
|
|
18494
18494
|
var StartedMerge = responseOf()(MergeRequest);
|
|
18495
18495
|
var MergeResult = responseOf()(MergeRequest);
|
|
18496
|
-
var
|
|
18497
|
-
const fromEnvironment = yield* option2(Redacted2("GH_TOKEN").pipe(orElse(() => Redacted2("GITHUB_TOKEN"))));
|
|
18498
|
-
if (isSome2(fromEnvironment)) {
|
|
18499
|
-
return fromEnvironment.value;
|
|
18500
|
-
}
|
|
18501
|
-
const spawner = yield* ChildProcessSpawner;
|
|
18502
|
-
const stored = (yield* spawner.string(make14("gh", ["auth", "token"]))).trim();
|
|
18503
|
-
return stored === "" ? yield* fail6("no token") : make19(stored);
|
|
18504
|
-
}).pipe(mapError2(() => new GitHubFailed({ message: "no GitHub token: set GH_TOKEN, or run `gh auth login`" })));
|
|
18505
|
-
var GitHubLive = (repository) => {
|
|
18496
|
+
var GitHubLive = (repository, connection) => {
|
|
18506
18497
|
const repo = (path) => `/repos/${repository.owner}/${repository.name}${path}`;
|
|
18507
18498
|
return effect(GitHub, gen2(function* () {
|
|
18508
|
-
const
|
|
18509
|
-
|
|
18499
|
+
const requestInit = match(connection.proxy, {
|
|
18500
|
+
onNone: () => ({}),
|
|
18501
|
+
onSome: ({ ca, url }) => match(ca, {
|
|
18502
|
+
onNone: () => ({ proxy: url }),
|
|
18503
|
+
onSome: (certificates) => ({ proxy: url, tls: { ca: certificates } })
|
|
18504
|
+
})
|
|
18505
|
+
});
|
|
18506
|
+
const client = (yield* HttpClient).pipe(mapRequest((request) => request.pipe(prependUrl("https://api.github.com"), acceptJson, bearerToken(connection.token), setHeaders({
|
|
18510
18507
|
"user-agent": "jj-octo",
|
|
18511
18508
|
"x-github-api-version": "2022-11-28"
|
|
18512
18509
|
}))));
|
|
18513
|
-
const send = (request) => client.execute(request).pipe(flatMap4((response) => response.status < 400 ? succeed6(response) : response.text.pipe(orElseSucceed2(() => ""), flatMap4((text) => fail6(new GitHubFailed({
|
|
18510
|
+
const send = (request) => client.execute(request).pipe(provideService2(RequestInit, requestInit), flatMap4((response) => response.status < 400 ? succeed6(response) : response.text.pipe(orElseSucceed2(() => ""), flatMap4((text) => fail6(new GitHubFailed({
|
|
18514
18511
|
message: `${request.method} ${request.url} returned ${response.status}: ${text}`
|
|
18515
18512
|
}))))), catchTag2("HttpClientError", (error) => fail6(new GitHubFailed({ message: error.message }))));
|
|
18516
18513
|
const json = (schema) => (request) => send(request).pipe(flatMap4(schemaBodyJson(schema)), catchTags2({
|
|
@@ -18567,6 +18564,60 @@ var GitHubLive = (repository) => {
|
|
|
18567
18564
|
}));
|
|
18568
18565
|
};
|
|
18569
18566
|
|
|
18567
|
+
// src/clients/github/connection.ts
|
|
18568
|
+
var authKey = "jj-octo.github-auth";
|
|
18569
|
+
var ownToken = gen2(function* () {
|
|
18570
|
+
const fromEnvironment = yield* option2(Redacted2("GH_TOKEN").pipe(orElse(() => Redacted2("GITHUB_TOKEN"))));
|
|
18571
|
+
if (isSome2(fromEnvironment)) {
|
|
18572
|
+
return fromEnvironment.value;
|
|
18573
|
+
}
|
|
18574
|
+
const spawner = yield* ChildProcessSpawner;
|
|
18575
|
+
const stored = (yield* spawner.string(make14("gh", ["auth", "token"]))).trim();
|
|
18576
|
+
return stored === "" ? yield* fail6("no token") : make19(stored);
|
|
18577
|
+
}).pipe(mapError2(() => new GitHubFailed({ message: "no GitHub token: set GH_TOKEN, or run `gh auth login`" })));
|
|
18578
|
+
var gitSetting = (name) => gen2(function* () {
|
|
18579
|
+
const git = yield* Git;
|
|
18580
|
+
const value = (yield* git.read(["config", "--get-urlmatch", name, "https://github.com"]).pipe(orElseSucceed2(() => ""))).trim();
|
|
18581
|
+
return value === "" ? none2() : some2(value);
|
|
18582
|
+
});
|
|
18583
|
+
var gitProxy = gen2(function* () {
|
|
18584
|
+
const fs = yield* FileSystem;
|
|
18585
|
+
const url = yield* gitSetting("http.proxy");
|
|
18586
|
+
if (isNone2(url)) {
|
|
18587
|
+
return yield* new GitHubFailed({
|
|
18588
|
+
message: `${authKey} is git-proxy, but git has no http.proxy for https://github.com`
|
|
18589
|
+
});
|
|
18590
|
+
}
|
|
18591
|
+
const caFile = yield* gitSetting("http.sslCAInfo");
|
|
18592
|
+
const ca = isNone2(caFile) ? none2() : some2(yield* fs.readFileString(caFile.value).pipe(mapError2((error) => new GitHubFailed({
|
|
18593
|
+
message: `can't read git's http.sslCAInfo ${caFile.value}: ${error.message}`
|
|
18594
|
+
}))));
|
|
18595
|
+
const connection = {
|
|
18596
|
+
proxy: some2({ ca, url: url.value }),
|
|
18597
|
+
token: make19("proxy-injected")
|
|
18598
|
+
};
|
|
18599
|
+
return connection;
|
|
18600
|
+
});
|
|
18601
|
+
var connection = gen2(function* () {
|
|
18602
|
+
const jj = yield* Jj;
|
|
18603
|
+
const auth = (yield* jj.read(["config", "get", authKey]).pipe(orElseSucceed2(() => ""))).trim();
|
|
18604
|
+
switch (auth) {
|
|
18605
|
+
case "":
|
|
18606
|
+
case "token": {
|
|
18607
|
+
const own = { proxy: none2(), token: yield* ownToken };
|
|
18608
|
+
return own;
|
|
18609
|
+
}
|
|
18610
|
+
case "git-proxy": {
|
|
18611
|
+
return yield* gitProxy;
|
|
18612
|
+
}
|
|
18613
|
+
default: {
|
|
18614
|
+
return yield* new GitHubFailed({
|
|
18615
|
+
message: `${authKey} is ${JSON.stringify(auth)}; set it to token or git-proxy`
|
|
18616
|
+
});
|
|
18617
|
+
}
|
|
18618
|
+
}
|
|
18619
|
+
});
|
|
18620
|
+
|
|
18570
18621
|
// src/clients/github/repository.ts
|
|
18571
18622
|
var repositoryFromUrl = (url) => {
|
|
18572
18623
|
const match = /github\.com[:/](?<owner>[^/]+)\/(?<name>[^/]+?)(?:\.git)?\/?$/u.exec(url.trim());
|
|
@@ -18585,7 +18636,7 @@ var GitHubFromOrigin = unwrap(gen2(function* () {
|
|
|
18585
18636
|
if (isNone2(repository)) {
|
|
18586
18637
|
return yield* new GitHubFailed({ message: "the `origin` remote isn't a GitHub repository" });
|
|
18587
18638
|
}
|
|
18588
|
-
return GitHubLive(repository.value);
|
|
18639
|
+
return GitHubLive(repository.value, yield* connection);
|
|
18589
18640
|
}));
|
|
18590
18641
|
|
|
18591
18642
|
// src/cli/gh/log.ts
|