@osdlc/typed-gh 0.9.0 → 0.9.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/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +98 -96
- package/SECURITY.md +4 -4
- package/dist/async.d.ts +28 -27
- package/dist/async.js +29 -28
- package/dist/doors.d.ts +25 -23
- package/dist/doors.js +29 -27
- package/dist/failure.d.ts +8 -8
- package/dist/failure.js +6 -6
- package/dist/index.d.ts +13 -14
- package/dist/index.js +14 -15
- package/dist/parse.d.ts +21 -21
- package/dist/parse.js +34 -36
- package/dist/repo.d.ts +13 -13
- package/dist/repo.js +13 -13
- package/dist/run.d.ts +12 -13
- package/dist/run.js +11 -12
- package/dist/sync.d.ts +66 -64
- package/dist/sync.js +67 -65
- package/dist/types.d.ts +31 -32
- package/dist/types.js +8 -8
- package/dist/verbs.d.ts +120 -122
- package/dist/verbs.js +119 -110
- package/package.json +3 -3
package/dist/async.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `AsyncGh
|
|
2
|
+
* `AsyncGh`: the awaitable GitHub client, with the same methods as {@link Gh}.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* a
|
|
7
|
-
* `
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
4
|
+
* It has the same three call styles, as Promises. The plain method resolves to
|
|
5
|
+
* a value or rejects with a `FailureError` carrying the classified `GhFailure`,
|
|
6
|
+
* for a failed gh or output it cannot read. A query for one thing resolves
|
|
7
|
+
* `null` when GitHub has no such thing. `try` resolves to a
|
|
8
|
+
* `Result<T, GhFailure>`. `soft` resolves `null` for a failure. `raw` and
|
|
9
|
+
* `rawChecked` run any `gh` call. It uses the same verb table as `Gh`, so the
|
|
10
|
+
* two cannot differ on argv or parsing. Use it where the sync client would
|
|
11
|
+
* block the event loop, such as many per-PR queries at once.
|
|
11
12
|
*/
|
|
12
13
|
import { resolveRunnerAsync, } from '@osdlc/command-seam';
|
|
13
14
|
import { runCheckedGhAsync, softAsync, triedAsync } from "./doors.js";
|
|
@@ -56,16 +57,16 @@ export class AsyncGh {
|
|
|
56
57
|
get soft() {
|
|
57
58
|
return (this.softened ??= softAsync(this));
|
|
58
59
|
}
|
|
59
|
-
// ──
|
|
60
|
-
/**
|
|
60
|
+
// ── raw calls ─────────────────────────────────────────────────────────────
|
|
61
|
+
/** Run any `gh` call and return the result, whatever the exit code. */
|
|
61
62
|
raw(argv, opts = {}) {
|
|
62
63
|
return this.runner.run(argv, { cwd: this.cwd, ...opts });
|
|
63
64
|
}
|
|
64
|
-
/**
|
|
65
|
+
/** Run any `gh` call. Rejects with the classified failure on a non-zero exit. */
|
|
65
66
|
rawChecked(argv, opts = {}) {
|
|
66
67
|
return runCheckedGhAsync(this.runner, argv, { cwd: this.cwd, ...opts });
|
|
67
68
|
}
|
|
68
|
-
/** Run one verb from the table,
|
|
69
|
+
/** Run one verb from the table, checked or unchecked as the verb says. */
|
|
69
70
|
async exec(verb, call = {}) {
|
|
70
71
|
return runVerbAsync(verb, this.runner, {
|
|
71
72
|
cwd: this.cwd,
|
|
@@ -73,12 +74,12 @@ export class AsyncGh {
|
|
|
73
74
|
signal: call.signal,
|
|
74
75
|
});
|
|
75
76
|
}
|
|
76
|
-
/** {@link exec} for a verb that never
|
|
77
|
+
/** {@link exec} for a verb that never returns `null` as a value. A failed or unreadable run rejects. */
|
|
77
78
|
async read(verb, call = {}) {
|
|
78
79
|
return (await this.exec(verb, call));
|
|
79
80
|
}
|
|
80
81
|
// ── queries ───────────────────────────────────────────────────────────────
|
|
81
|
-
/** Pull requests matching `opts`. Rejects when gh fails
|
|
82
|
+
/** Pull requests matching `opts`. Rejects when gh fails. `soft.prList` resolves null instead. */
|
|
82
83
|
prList(opts = {}) {
|
|
83
84
|
return this.read(v.prList(opts, this.target), opts);
|
|
84
85
|
}
|
|
@@ -111,7 +112,7 @@ export class AsyncGh {
|
|
|
111
112
|
});
|
|
112
113
|
return v.pickPrForBranch(rows.rows, branch);
|
|
113
114
|
}
|
|
114
|
-
/** {@link prView},
|
|
115
|
+
/** {@link prView}, asked again until GitHub has computed the merge state. See `Gh.prViewSettled`. */
|
|
115
116
|
async prViewSettled(number, opts = {}) {
|
|
116
117
|
const attempts = Math.max(1, opts.attempts ?? 3);
|
|
117
118
|
const sleep = opts.sleep ?? sleepAsync;
|
|
@@ -129,12 +130,12 @@ export class AsyncGh {
|
|
|
129
130
|
prBody(number, opts = {}) {
|
|
130
131
|
return this.read(v.prBody(number, this.target), opts);
|
|
131
132
|
}
|
|
132
|
-
/** A REST GET through `gh api
|
|
133
|
+
/** A REST GET through `gh api`. Failure is `ok: false`, never a rejection. */
|
|
133
134
|
api(endpoint, opts = {}) {
|
|
134
135
|
return this.exec(v.api(endpoint, opts, this.target), opts);
|
|
135
136
|
}
|
|
136
137
|
/**
|
|
137
|
-
* A GraphQL query
|
|
138
|
+
* A GraphQL query. Resolves to each page's `data`. Rejects on a failed or partial result. See `Gh.graphql`.
|
|
138
139
|
*
|
|
139
140
|
* @experimental
|
|
140
141
|
*/
|
|
@@ -149,7 +150,7 @@ export class AsyncGh {
|
|
|
149
150
|
issueList(opts = {}) {
|
|
150
151
|
return this.read(v.issueList(opts, this.target), opts);
|
|
151
152
|
}
|
|
152
|
-
/** One issue with its labels
|
|
153
|
+
/** One issue with its labels, or null when there is no such issue. */
|
|
153
154
|
issueView(number, opts = {}) {
|
|
154
155
|
return this.exec(v.issueView(number, this.target), opts);
|
|
155
156
|
}
|
|
@@ -157,7 +158,7 @@ export class AsyncGh {
|
|
|
157
158
|
repoList(owner, opts = {}) {
|
|
158
159
|
return this.read(v.repoList(owner, opts, this.target), opts);
|
|
159
160
|
}
|
|
160
|
-
/** One repository
|
|
161
|
+
/** One repository, or null when there is no such repository. See `Gh.repoView`. */
|
|
161
162
|
repoView(repo, opts = {}) {
|
|
162
163
|
return this.exec(v.repoView(repo, opts.fields ?? v.REPO_FIELDS, this.target), opts);
|
|
163
164
|
}
|
|
@@ -177,13 +178,13 @@ export class AsyncGh {
|
|
|
177
178
|
authStatus() {
|
|
178
179
|
return this.exec(v.authStatus(this.target));
|
|
179
180
|
}
|
|
180
|
-
/** True iff `gh` is installed
|
|
181
|
+
/** True iff `gh` is installed and authenticated. Skips the auth check when `gh` is not installed. */
|
|
181
182
|
async ready() {
|
|
182
183
|
return (await this.installed()) && (await this.authenticated());
|
|
183
184
|
}
|
|
184
185
|
/**
|
|
185
186
|
* `{owner, repo}` parsed from the remote URL you pass, or null when it is
|
|
186
|
-
* null or names no project.
|
|
187
|
+
* null or names no project. It starts no process, so it is sync on purpose.
|
|
187
188
|
*/
|
|
188
189
|
ownerRepo(remoteUrl) {
|
|
189
190
|
return remoteUrl === null ? null : parseOwnerRepo(remoteUrl);
|
|
@@ -201,16 +202,16 @@ export class AsyncGh {
|
|
|
201
202
|
editPrBody(number, body) {
|
|
202
203
|
return this.exec(v.editPrBody(number, body, this.target));
|
|
203
204
|
}
|
|
204
|
-
/** The PR's unified diff
|
|
205
|
+
/** The PR's unified diff. Rejects with the classified failure when gh cannot produce it. */
|
|
205
206
|
prDiff(number) {
|
|
206
207
|
return this.exec(v.prDiff(number, this.target));
|
|
207
208
|
}
|
|
208
|
-
/** Post one conversation comment on a PR
|
|
209
|
+
/** Post one conversation comment on a PR. Resolves to its URL ('' if gh printed none). */
|
|
209
210
|
prComment(number, body) {
|
|
210
211
|
return this.exec(v.prComment(number, body, this.target));
|
|
211
212
|
}
|
|
212
213
|
/**
|
|
213
|
-
* Create a `COMMENT` review with inline comments
|
|
214
|
+
* Create a `COMMENT` review with inline comments. Resolves to the review's URL ('' if none came back).
|
|
214
215
|
*
|
|
215
216
|
* @experimental
|
|
216
217
|
*/
|
|
@@ -226,19 +227,19 @@ export class AsyncGh {
|
|
|
226
227
|
return this.exec(v.prSetDraft(number, draft, this.target));
|
|
227
228
|
}
|
|
228
229
|
/**
|
|
229
|
-
* Rewrite one PR conversation comment's body. `commentId` is the numeric REST id
|
|
230
|
+
* Rewrite one PR conversation comment's body. `commentId` is the numeric REST id. Anything else rejects with `RangeError`.
|
|
230
231
|
*
|
|
231
232
|
* @experimental
|
|
232
233
|
*/
|
|
233
234
|
async issueCommentEdit(commentId, body) {
|
|
234
|
-
// async, so a bad id rejects the Promise instead of throwing at the call.
|
|
235
|
+
// async, so a bad id rejects the Promise instead of throwing at the call site.
|
|
235
236
|
return this.exec(v.issueCommentEdit(commentId, body, this.target));
|
|
236
237
|
}
|
|
237
|
-
/** Merge a PR
|
|
238
|
+
/** Merge a PR. GitHub refuses when its head is no longer `opts.headSha`. */
|
|
238
239
|
prMerge(number, opts) {
|
|
239
240
|
return this.exec(v.prMerge(number, opts, this.target));
|
|
240
241
|
}
|
|
241
|
-
/** A PR's review threads
|
|
242
|
+
/** A PR's review threads. Rejects when they could not be read completely. `soft.prReviewThreads` resolves null instead. */
|
|
242
243
|
prReviewThreads(number) {
|
|
243
244
|
return this.read(v.prReviewThreads(number, this.target));
|
|
244
245
|
}
|
package/dist/doors.d.ts
CHANGED
|
@@ -1,34 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The three
|
|
3
|
-
* `gh.try.*` and `gh.soft.*`.
|
|
2
|
+
* The three call styles, as `@osdlc/typed-git` has them: the method that
|
|
3
|
+
* throws, `gh.try.*` and `gh.soft.*`.
|
|
4
4
|
*
|
|
5
|
-
* -
|
|
5
|
+
* - The method that throws returns a value or throws. A failed `gh` throws a
|
|
6
6
|
* `FailureError` carrying the classified `GhFailure` (its `cause` is the
|
|
7
|
-
* `CommandFailed`)
|
|
8
|
-
* "signed out" or "rate limited" and not a bare exit
|
|
9
|
-
* but could not be read throws one of kind `unreadable`. A verb
|
|
10
|
-
* reads one thing (`prView`, `issueView`, `repoView`)
|
|
11
|
-
* GitHub says there is no such thing
|
|
12
|
-
* -
|
|
13
|
-
* `Result<T, GhFailure>`. It catches a thrown failure (a `FailureError`, or
|
|
14
|
-
* `CommandFailed` from `raw`-level code) and nothing else
|
|
15
|
-
*
|
|
16
|
-
*
|
|
7
|
+
* `CommandFailed`). So a caller that reports it, such as `runMain`, shows
|
|
8
|
+
* "signed out" or "rate limited" and not a bare exit code. Output that
|
|
9
|
+
* exited 0 but could not be read throws one of kind `unreadable`. A verb
|
|
10
|
+
* that reads one thing (`prView`, `issueView`, `repoView`) returns `null`
|
|
11
|
+
* when GitHub says there is no such thing.
|
|
12
|
+
* - `try` makes the same call and returns the failure as
|
|
13
|
+
* `Result<T, GhFailure>`. It catches a thrown failure (a `FailureError`, or
|
|
14
|
+
* a `CommandFailed` from `raw`-level code) and nothing else. A `RangeError`
|
|
15
|
+
* for a bad argument still throws.
|
|
16
|
+
* - `soft` makes the same call and returns `null` for a failure. Only the
|
|
17
|
+
* queries have a soft form. No mutation does.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
+
* `try` and `soft` are proxies over the whole client, so a new method needs no
|
|
20
|
+
* change here.
|
|
19
21
|
*/
|
|
20
22
|
import { type AsyncCommandRunner, type AsyncCommandRunOptions, type CommandResult, type CommandRunner, type CommandRunOptions } from '@osdlc/command-seam';
|
|
21
23
|
import { type Failure, type Result } from '@osdlc/result';
|
|
22
24
|
import { type GhFailure } from './failure.ts';
|
|
23
25
|
import type { GhVerb } from './verbs.ts';
|
|
24
26
|
/**
|
|
25
|
-
* Read the result of running `verb` as the
|
|
27
|
+
* Read the result of running `verb` as the methods that throw do.
|
|
26
28
|
*
|
|
27
29
|
* A checked verb has already thrown on a non-zero exit (the runner is
|
|
28
|
-
* `runChecked`)
|
|
29
|
-
* failure in its value. A read that exited non-zero throws
|
|
30
|
-
* unless the verb's `absent` says gh's answer was "there is no such
|
|
31
|
-
* which `parse` turns into `null`. A read that exited 0 but parsed to `null`
|
|
30
|
+
* `runChecked`). A probe (`installed`, `authStatus`, `api`) carries its
|
|
31
|
+
* failure in its value. A read that exited non-zero throws the classified
|
|
32
|
+
* failure, unless the verb's `absent` says gh's answer was "there is no such
|
|
33
|
+
* thing", which `parse` turns into `null`. A read that exited 0 but parsed to `null`
|
|
32
34
|
* could not be read completely, and throws.
|
|
33
35
|
*
|
|
34
36
|
* @throws `FailureError` carrying the classified {@link GhFailure} for a failed run.
|
|
@@ -36,7 +38,7 @@ import type { GhVerb } from './verbs.ts';
|
|
|
36
38
|
*/
|
|
37
39
|
export declare function settle<T>(verb: GhVerb<T>, result: CommandResult, binary: string | undefined): T;
|
|
38
40
|
/**
|
|
39
|
-
* The error the
|
|
41
|
+
* The error the methods that throw raise for a failed run: a `FailureError` carrying
|
|
40
42
|
* the {@link GhFailure} that {@link classifyGhFailure} reads from it, with the
|
|
41
43
|
* `CommandFailed` as its `cause`. Anything else is returned as it is.
|
|
42
44
|
*/
|
|
@@ -45,7 +47,7 @@ export declare function ghFailureError(error: unknown): unknown;
|
|
|
45
47
|
export declare function runCheckedGh(runner: CommandRunner, argv: string[], opts: CommandRunOptions): CommandResult;
|
|
46
48
|
/** {@link runCheckedAsync}, rejecting with {@link ghFailureError}'s classified failure. */
|
|
47
49
|
export declare function runCheckedGhAsync(runner: AsyncCommandRunner, argv: string[], opts: AsyncCommandRunOptions): Promise<CommandResult>;
|
|
48
|
-
/** The
|
|
50
|
+
/** The members `try` and `soft` leave out: `raw`, `rawChecked`, helpers that run nothing, and properties. */
|
|
49
51
|
type Triable<C> = Omit<C, 'raw' | 'rawChecked' | 'at' | 'withRepo' | 'ownerRepo' | 'try' | 'soft' | 'cwd' | 'repo' | 'hostname'>;
|
|
50
52
|
/** Every synchronous client method, returning a `Result<T, GhFailure>`. */
|
|
51
53
|
export type TriedSync<C> = {
|
|
@@ -56,8 +58,8 @@ export type TriedAsync<C> = {
|
|
|
56
58
|
[K in keyof Triable<C>]: Triable<C>[K] extends (...a: infer A) => Promise<infer R> ? (...a: A) => Promise<Result<R, GhFailure>> : never;
|
|
57
59
|
};
|
|
58
60
|
/**
|
|
59
|
-
* The queries that have a soft form. A mutation has none
|
|
60
|
-
*
|
|
61
|
+
* The queries that have a soft form. A mutation has none. If a write's failure
|
|
62
|
+
* were dropped, the caller would believe the write worked.
|
|
61
63
|
*/
|
|
62
64
|
export declare const SOFT_METHODS: readonly ["prList", "prView", "prFind", "openPrFor", "prViewSettled", "prBody", "graphql", "labelList", "issueList", "issueView", "repoList", "repoView", "searchPrs", "prReviewThreads"];
|
|
63
65
|
/** The name of a method with a soft form. */
|
package/dist/doors.js
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The three
|
|
3
|
-
* `gh.try.*` and `gh.soft.*`.
|
|
2
|
+
* The three call styles, as `@osdlc/typed-git` has them: the method that
|
|
3
|
+
* throws, `gh.try.*` and `gh.soft.*`.
|
|
4
4
|
*
|
|
5
|
-
* -
|
|
5
|
+
* - The method that throws returns a value or throws. A failed `gh` throws a
|
|
6
6
|
* `FailureError` carrying the classified `GhFailure` (its `cause` is the
|
|
7
|
-
* `CommandFailed`)
|
|
8
|
-
* "signed out" or "rate limited" and not a bare exit
|
|
9
|
-
* but could not be read throws one of kind `unreadable`. A verb
|
|
10
|
-
* reads one thing (`prView`, `issueView`, `repoView`)
|
|
11
|
-
* GitHub says there is no such thing
|
|
12
|
-
* -
|
|
13
|
-
* `Result<T, GhFailure>`. It catches a thrown failure (a `FailureError`, or
|
|
14
|
-
* `CommandFailed` from `raw`-level code) and nothing else
|
|
15
|
-
*
|
|
16
|
-
*
|
|
7
|
+
* `CommandFailed`). So a caller that reports it, such as `runMain`, shows
|
|
8
|
+
* "signed out" or "rate limited" and not a bare exit code. Output that
|
|
9
|
+
* exited 0 but could not be read throws one of kind `unreadable`. A verb
|
|
10
|
+
* that reads one thing (`prView`, `issueView`, `repoView`) returns `null`
|
|
11
|
+
* when GitHub says there is no such thing.
|
|
12
|
+
* - `try` makes the same call and returns the failure as
|
|
13
|
+
* `Result<T, GhFailure>`. It catches a thrown failure (a `FailureError`, or
|
|
14
|
+
* a `CommandFailed` from `raw`-level code) and nothing else. A `RangeError`
|
|
15
|
+
* for a bad argument still throws.
|
|
16
|
+
* - `soft` makes the same call and returns `null` for a failure. Only the
|
|
17
|
+
* queries have a soft form. No mutation does.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
+
* `try` and `soft` are proxies over the whole client, so a new method needs no
|
|
20
|
+
* change here.
|
|
19
21
|
*/
|
|
20
22
|
import { CommandFailed, isCommandFailed, runChecked, runCheckedAsync, } from '@osdlc/command-seam';
|
|
21
23
|
import { err, FailureError, isFailure, ok } from '@osdlc/result';
|
|
22
24
|
import { classifyGhFailure, unreadableFailure } from "./failure.js";
|
|
23
25
|
/**
|
|
24
|
-
* Read the result of running `verb` as the
|
|
26
|
+
* Read the result of running `verb` as the methods that throw do.
|
|
25
27
|
*
|
|
26
28
|
* A checked verb has already thrown on a non-zero exit (the runner is
|
|
27
|
-
* `runChecked`)
|
|
28
|
-
* failure in its value. A read that exited non-zero throws
|
|
29
|
-
* unless the verb's `absent` says gh's answer was "there is no such
|
|
30
|
-
* which `parse` turns into `null`. A read that exited 0 but parsed to `null`
|
|
29
|
+
* `runChecked`). A probe (`installed`, `authStatus`, `api`) carries its
|
|
30
|
+
* failure in its value. A read that exited non-zero throws the classified
|
|
31
|
+
* failure, unless the verb's `absent` says gh's answer was "there is no such
|
|
32
|
+
* thing", which `parse` turns into `null`. A read that exited 0 but parsed to `null`
|
|
31
33
|
* could not be read completely, and throws.
|
|
32
34
|
*
|
|
33
35
|
* @throws `FailureError` carrying the classified {@link GhFailure} for a failed run.
|
|
@@ -48,7 +50,7 @@ export function settle(verb, result, binary) {
|
|
|
48
50
|
return value;
|
|
49
51
|
}
|
|
50
52
|
/**
|
|
51
|
-
* The error the
|
|
53
|
+
* The error the methods that throw raise for a failed run: a `FailureError` carrying
|
|
52
54
|
* the {@link GhFailure} that {@link classifyGhFailure} reads from it, with the
|
|
53
55
|
* `CommandFailed` as its `cause`. Anything else is returned as it is.
|
|
54
56
|
*/
|
|
@@ -74,8 +76,8 @@ export async function runCheckedGhAsync(runner, argv, opts) {
|
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
/**
|
|
77
|
-
* The queries that have a soft form. A mutation has none
|
|
78
|
-
*
|
|
79
|
+
* The queries that have a soft form. A mutation has none. If a write's failure
|
|
80
|
+
* were dropped, the caller would believe the write worked.
|
|
79
81
|
*/
|
|
80
82
|
export const SOFT_METHODS = [
|
|
81
83
|
'prList',
|
|
@@ -94,9 +96,9 @@ export const SOFT_METHODS = [
|
|
|
94
96
|
'prReviewThreads',
|
|
95
97
|
];
|
|
96
98
|
/**
|
|
97
|
-
* Whether `error` carries a failure to
|
|
98
|
-
*
|
|
99
|
-
* result each have their own classes.
|
|
99
|
+
* Whether `error` carries a failure to return, rather than a bug to rethrow.
|
|
100
|
+
* Checked by shape, not `instanceof`, because two installed copies of
|
|
101
|
+
* command-seam or result each have their own classes.
|
|
100
102
|
*/
|
|
101
103
|
function isGhFailure(error) {
|
|
102
104
|
return (typeof error === 'object' &&
|
|
@@ -111,8 +113,8 @@ export function failureOf(error) {
|
|
|
111
113
|
function facade(client, wrap) {
|
|
112
114
|
return new Proxy(client, {
|
|
113
115
|
get(target, prop) {
|
|
114
|
-
// Read from the target, not the proxy
|
|
115
|
-
// against the real client
|
|
116
|
+
// Read from the target, not the proxy. A getter (`try` itself) must run
|
|
117
|
+
// against the real client, not recurse through the proxy.
|
|
116
118
|
const value = Reflect.get(target, prop);
|
|
117
119
|
if (typeof value !== 'function')
|
|
118
120
|
return value;
|
package/dist/failure.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* {@link GhFailure}: a failed `gh` call, classified. The `gh.try.*`
|
|
3
|
-
*
|
|
2
|
+
* {@link GhFailure}: a failed `gh` call, classified. The `gh.try.*` methods
|
|
3
|
+
* return it as the error of a `Result`. Its `cause` is the `CommandFailed`
|
|
4
4
|
* it was read from.
|
|
5
5
|
*
|
|
6
|
-
* The kinds beyond
|
|
7
|
-
* English. A message that matches none stays the subprocess layer's `exit`
|
|
6
|
+
* The kinds beyond command-seam's come from `gh`'s stderr and stdout, matched
|
|
7
|
+
* in English. A message that matches none stays the subprocess layer's `exit`
|
|
8
8
|
* with `gh`'s first stderr line, never a wrong kind.
|
|
9
9
|
*/
|
|
10
10
|
import { type CommandFailed, type CommandFailureKind } from '@osdlc/command-seam';
|
|
@@ -26,17 +26,17 @@ import { type Failure } from '@osdlc/result';
|
|
|
26
26
|
* (malformed JSON, a partial GraphQL answer, a review-thread list cut short).
|
|
27
27
|
*/
|
|
28
28
|
export type GhFailureKind = CommandFailureKind | 'not-authenticated' | 'network' | 'not-found' | 'rate-limited' | 'unreadable';
|
|
29
|
-
/** A failed `gh` call. `message` is one line for a person
|
|
29
|
+
/** A failed `gh` call. `message` is one line for a person. `detail` is `gh`'s own output. */
|
|
30
30
|
export interface GhFailure extends Failure<GhFailureKind> {
|
|
31
31
|
/** The binary that ran (`gh`), when known. */
|
|
32
32
|
binary?: string | undefined;
|
|
33
33
|
/** The arguments `gh` ran with, without the binary name. */
|
|
34
34
|
argv: string[];
|
|
35
|
-
/** `gh`'s exit code
|
|
35
|
+
/** `gh`'s exit code, or `null` when it never reported one. */
|
|
36
36
|
exitCode: number | null;
|
|
37
37
|
/** The signal that ended `gh`, when the runner knows it. */
|
|
38
38
|
signal?: NodeJS.Signals | null | undefined;
|
|
39
|
-
/** The `CommandFailed` this was classified from
|
|
39
|
+
/** The `CommandFailed` this was classified from. Absent for `unreadable`, where `gh` succeeded. */
|
|
40
40
|
cause?: CommandFailed | undefined;
|
|
41
41
|
}
|
|
42
42
|
/** What a verb that reads one thing asks GitHub for. */
|
|
@@ -44,7 +44,7 @@ export type Thing = 'pr' | 'issue' | 'repo';
|
|
|
44
44
|
/**
|
|
45
45
|
* Whether the text of a failed `gh` run (stderr then stdout, as
|
|
46
46
|
* {@link classifyGhFailure} reads it) means "there is no such `thing`", for a
|
|
47
|
-
* verb that reads one thing
|
|
47
|
+
* verb that reads one thing. That is an answer, not a failure.
|
|
48
48
|
*
|
|
49
49
|
* Narrower than the `not-found` failure kind on purpose. A mistyped `--repo`
|
|
50
50
|
* makes `gh pr view 7` say "Could not resolve to a Repository", which is a
|
package/dist/failure.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* {@link GhFailure}: a failed `gh` call, classified. The `gh.try.*`
|
|
3
|
-
*
|
|
2
|
+
* {@link GhFailure}: a failed `gh` call, classified. The `gh.try.*` methods
|
|
3
|
+
* return it as the error of a `Result`. Its `cause` is the `CommandFailed`
|
|
4
4
|
* it was read from.
|
|
5
5
|
*
|
|
6
|
-
* The kinds beyond
|
|
7
|
-
* English. A message that matches none stays the subprocess layer's `exit`
|
|
6
|
+
* The kinds beyond command-seam's come from `gh`'s stderr and stdout, matched
|
|
7
|
+
* in English. A message that matches none stays the subprocess layer's `exit`
|
|
8
8
|
* with `gh`'s first stderr line, never a wrong kind.
|
|
9
9
|
*/
|
|
10
10
|
import { classifyFailure } from '@osdlc/command-seam';
|
|
@@ -22,7 +22,7 @@ const ABSENT = {
|
|
|
22
22
|
/**
|
|
23
23
|
* Whether the text of a failed `gh` run (stderr then stdout, as
|
|
24
24
|
* {@link classifyGhFailure} reads it) means "there is no such `thing`", for a
|
|
25
|
-
* verb that reads one thing
|
|
25
|
+
* verb that reads one thing. That is an answer, not a failure.
|
|
26
26
|
*
|
|
27
27
|
* Narrower than the `not-found` failure kind on purpose. A mistyped `--repo`
|
|
28
28
|
* makes `gh pr view 7` say "Could not resolve to a Repository", which is a
|
|
@@ -35,7 +35,7 @@ export function isAbsent(thing, text) {
|
|
|
35
35
|
}
|
|
36
36
|
/** The gh failure for a failed `gh` run. */
|
|
37
37
|
export function classifyGhFailure(failed) {
|
|
38
|
-
// The client's runner may not name its binary
|
|
38
|
+
// The client's runner may not name its binary. It is gh either way, so the
|
|
39
39
|
// messages say `gh` rather than "The command".
|
|
40
40
|
const f = failed.binary === undefined
|
|
41
41
|
? (classifyFailure(failed.result, { binary: 'gh', argv: failed.argv }) ?? failed.failure)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@osdlc/typed-gh
|
|
2
|
+
* `@osdlc/typed-gh`: a typed GitHub client for TypeScript, over the `gh`
|
|
3
3
|
* CLI. The GitHub-side companion of `@osdlc/typed-git`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* It has three parts:
|
|
6
6
|
*
|
|
7
|
-
* -
|
|
8
|
-
* caller
|
|
9
|
-
* field
|
|
10
|
-
* value, because absent and unknowable are the same answer.
|
|
11
|
-
* -
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* -
|
|
15
|
-
* value or throws a `FailureError` carrying the
|
|
16
|
-
* `GhFailure
|
|
17
|
-
* `
|
|
18
|
-
* `raw` is the hatch.
|
|
7
|
+
* - A model. `PullRequest`, `Review`, `CheckRun` and their enums, so a
|
|
8
|
+
* caller does not read `payload["mergeable"] as string | undefined`. Every
|
|
9
|
+
* field always has a value. A field the query did not ask for gets its
|
|
10
|
+
* "not known" value, because absent and unknowable are the same answer.
|
|
11
|
+
* - Argv builders and parsers with no side effects. The verb table and
|
|
12
|
+
* `parse.ts` never start a process, so code that runs many calls at once
|
|
13
|
+
* can run them through its own runner and reuse the parsing.
|
|
14
|
+
* - A client. `Gh` has the same three call styles as `Git`. The method that
|
|
15
|
+
* throws returns a value or throws a `FailureError` carrying the
|
|
16
|
+
* classified `GhFailure`. `gh.try.*` returns a `Result<T, GhFailure>`.
|
|
17
|
+
* `gh.soft.*` returns `null` for a failed query. `raw` runs any `gh` call.
|
|
19
18
|
*
|
|
20
19
|
* Authentication is `gh`'s. No token is read, stored, or forwarded.
|
|
21
20
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@osdlc/typed-gh
|
|
2
|
+
* `@osdlc/typed-gh`: a typed GitHub client for TypeScript, over the `gh`
|
|
3
3
|
* CLI. The GitHub-side companion of `@osdlc/typed-git`.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* It has three parts:
|
|
6
6
|
*
|
|
7
|
-
* -
|
|
8
|
-
* caller
|
|
9
|
-
* field
|
|
10
|
-
* value, because absent and unknowable are the same answer.
|
|
11
|
-
* -
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* -
|
|
15
|
-
* value or throws a `FailureError` carrying the
|
|
16
|
-
* `GhFailure
|
|
17
|
-
* `
|
|
18
|
-
* `raw` is the hatch.
|
|
7
|
+
* - A model. `PullRequest`, `Review`, `CheckRun` and their enums, so a
|
|
8
|
+
* caller does not read `payload["mergeable"] as string | undefined`. Every
|
|
9
|
+
* field always has a value. A field the query did not ask for gets its
|
|
10
|
+
* "not known" value, because absent and unknowable are the same answer.
|
|
11
|
+
* - Argv builders and parsers with no side effects. The verb table and
|
|
12
|
+
* `parse.ts` never start a process, so code that runs many calls at once
|
|
13
|
+
* can run them through its own runner and reuse the parsing.
|
|
14
|
+
* - A client. `Gh` has the same three call styles as `Git`. The method that
|
|
15
|
+
* throws returns a value or throws a `FailureError` carrying the
|
|
16
|
+
* classified `GhFailure`. `gh.try.*` returns a `Result<T, GhFailure>`.
|
|
17
|
+
* `gh.soft.*` returns `null` for a failed query. `raw` runs any `gh` call.
|
|
19
18
|
*
|
|
20
19
|
* Authentication is `gh`'s. No token is read, stored, or forwarded.
|
|
21
20
|
*/
|
|
@@ -27,7 +26,7 @@ export { Gh, defaultRunnerFactory } from "./sync.js";
|
|
|
27
26
|
export { api, authStatus, createPr, editPr, editPrBody, graphql, createLabel, createReview, editLabel, installed, issueList, issueView, labelList, nodesAt, openPrsForBranch, pickPrForBranch, prBody, prComment, prSetDraft, issueCommentEdit, prDiff, prList, prMerge, prReviewThreads, prUpdateBranch, prView, repoList, repoView, searchPrs, setIssueLabel, PR_LIST_FIELDS, PR_REF_FIELDS, PR_VIEW_FIELDS, REPO_FIELDS, SEARCH_PR_FIELDS, } from "./verbs.js";
|
|
28
27
|
export { anyCheckFailed, normalizeAuthorLogin, parsePullRequest } from "./parse.js";
|
|
29
28
|
export { ownerRepoSlug, parseOwnerRepo, parsePrRef, parsePrUrl, } from "./repo.js";
|
|
30
|
-
//
|
|
29
|
+
// command-seam's error and runner types appear in this package's signatures, so
|
|
31
30
|
// they are re-exported. Its functions are not: import them from
|
|
32
31
|
// `@osdlc/command-seam`.
|
|
33
32
|
export { CommandFailed, } from '@osdlc/command-seam';
|
package/dist/parse.d.ts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `gh --json` payloads
|
|
2
|
+
* Parsers from `gh --json` payloads to the typed model.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Nothing here has side effects, so code that runs its own calls can reuse
|
|
5
|
+
* it without starting a process, and the hard cases can be tested as data.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* It handles two payload differences:
|
|
8
8
|
*
|
|
9
|
-
* 1.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* here, once
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* `
|
|
18
|
-
* verdict
|
|
9
|
+
* 1. Author logins differ between GraphQL and REST. GraphQL
|
|
10
|
+
* (`gh pr view --json`) returns a login without a suffix
|
|
11
|
+
* (`github-actions`). REST (`gh api`) returns the suffixed one
|
|
12
|
+
* (`github-actions[bot]`). Comparing one with the other never matches,
|
|
13
|
+
* and no error shows it. Then a bot's comments are treated as human
|
|
14
|
+
* review feedback. Logins are normalized here, once, to the form without
|
|
15
|
+
* the suffix.
|
|
16
|
+
* 2. `statusCheckRollup` holds two node types. A modern `CheckRun` carries
|
|
17
|
+
* `name`/`status`/`conclusion`. A legacy `StatusContext` carries
|
|
18
|
+
* `context`/`state`. Both map to one verdict, so a caller never has to
|
|
19
|
+
* know which it got.
|
|
19
20
|
*/
|
|
20
21
|
import type { Actor, CheckRun, Label, PrSearchHit, PullRequest, Repository } from './types.ts';
|
|
21
22
|
/**
|
|
22
|
-
* Strip a single trailing `[bot]` suffix
|
|
23
|
-
*
|
|
24
|
-
* The one normalization that makes a login from either transport comparable.
|
|
23
|
+
* Strip a single trailing `[bot]` suffix, so a REST login matches the
|
|
24
|
+
* GraphQL one.
|
|
25
25
|
*/
|
|
26
26
|
export declare function normalizeAuthorLogin(login: string): string;
|
|
27
27
|
/**
|
|
28
|
-
* Parse an author node from
|
|
28
|
+
* Parse an author node from GraphQL (`author`) or REST (`user`).
|
|
29
29
|
* Null when there is no login, or the login is empty once `[bot]` is removed.
|
|
30
30
|
*/
|
|
31
31
|
export declare function parseActor(x: unknown): Actor | null;
|
|
@@ -33,13 +33,13 @@ export declare function parseActor(x: unknown): Actor | null;
|
|
|
33
33
|
export declare function parseCheckRun(x: unknown): CheckRun | null;
|
|
34
34
|
/** True iff any check in the rollup failed. */
|
|
35
35
|
export declare function anyCheckFailed(checks: readonly CheckRun[]): boolean;
|
|
36
|
-
/** Parse a `labels` field (PR, issue, or a bare `gh label list` array) into {@link Label} rows
|
|
36
|
+
/** Parse a `labels` field (PR, issue, or a bare `gh label list` array) into {@link Label} rows. Every label list in this package goes through it. Skips an item with no name, or an empty name, which reads the same as no name. */
|
|
37
37
|
export declare function parseLabels(x: unknown): Label[];
|
|
38
38
|
/**
|
|
39
39
|
* One PR from a `gh --json` object, or null when it carries no usable number.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
* known" value
|
|
41
|
+
* Every field gets a value. A field `gh` was not asked for gets its "not
|
|
42
|
+
* known" value, not `undefined`, so the result is safe to build from
|
|
43
43
|
* any field subset.
|
|
44
44
|
*/
|
|
45
45
|
export declare function parsePullRequest(raw: unknown): PullRequest | null;
|