@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/dist/async.js CHANGED
@@ -1,13 +1,14 @@
1
1
  /**
2
- * `AsyncGh` — the awaitable GitHub client, with the same methods as {@link Gh}.
2
+ * `AsyncGh`: the awaitable GitHub client, with the same methods as {@link Gh}.
3
3
  *
4
- * Same three doors, promised: the plain method resolves to a value or rejects
5
- * (a `FailureError` carrying the classified `GhFailure` for a failed gh or output it cannot read;
6
- * a query for one thing resolves `null` when GitHub has no such thing),
7
- * `try` resolves to a `Result<T, GhFailure>`, `soft` resolves `null` for a
8
- * failure, and `raw`/`rawChecked` are the hatches. It is driven by the same pure verb
9
- * table as `Gh`, so the two cannot drift on argv or parsing. Use it where the
10
- * sync client would block the event loop: a fan-out of per-PR queries.
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
- // ── escape hatches ────────────────────────────────────────────────────────
60
- /** Unchecked passthrough for verbs not yet lifted into the API. */
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
- /** Checked passthrough — rejects with the classified failure on a non-zero exit. */
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, honouring its checked/unchecked contract. */
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 answers `null` as a value: a failed or unreadable run rejects. */
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; `soft.prList` resolves null instead. */
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}, re-asked until GitHub settles the merge state. See `Gh.prViewSettled`. */
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`; failure is `ok: false`, never a rejection. */
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; each page's `data`. Rejects on a failed or partial result. See `Gh.graphql`.
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; null when there is no such issue. */
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; null when there is no such repository. See `Gh.repoView`. */
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 AND authenticated; short-circuits. */
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. Pure, so it is sync on purpose.
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; rejects with the classified failure when gh cannot produce it. */
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; resolves to its URL ('' if gh printed none). */
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; resolves to the review's URL ('' if none came back).
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; anything else rejects with `RangeError`.
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; GitHub refuses when its head is no longer `opts.headSha`. */
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, or null when they could not be read completely. */
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 doors, as `@osdlc/typed-git` has them: the plain verb (checked),
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
- * - **Plain / checked**: a value, or a throw. A failed `gh` throws a
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`), so a caller that reports it, such as `runMain`, reads
8
- * "signed out" or "rate limited" and not a bare exit; output that exited 0
9
- * but could not be read throws one of kind `unreadable`. A verb that
10
- * reads one thing (`prView`, `issueView`, `repoView`) answers `null` when
11
- * GitHub says there is no such thing: absence is an answer.
12
- * - **`try`**: the same call, with the failure returned as
13
- * `Result<T, GhFailure>`. It catches a thrown failure (a `FailureError`, or a
14
- * `CommandFailed` from `raw`-level code) and nothing else: a `RangeError` for a bad argument still throws.
15
- * - **`soft`**: the same call, with `null` for a failure. Only the queries
16
- * have a soft form; no mutation does.
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
- * Both are facades over the whole client, so a new method costs nothing here.
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 plain door does.
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`), and a probe (`installed`, `authStatus`, `api`) carries its
29
- * failure in its value. A read that exited non-zero throws `CommandFailed`,
30
- * unless the verb's `absent` says gh's answer was "there is no such thing",
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 plain door throws for a failed run: a `FailureError` carrying
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 methods the doors leave out: the escape hatches, pure helpers and plain properties. */
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: swallowing the failure
60
- * of a write is how a caller ends up believing it worked.
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 doors, as `@osdlc/typed-git` has them: the plain verb (checked),
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
- * - **Plain / checked**: a value, or a throw. A failed `gh` throws a
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`), so a caller that reports it, such as `runMain`, reads
8
- * "signed out" or "rate limited" and not a bare exit; output that exited 0
9
- * but could not be read throws one of kind `unreadable`. A verb that
10
- * reads one thing (`prView`, `issueView`, `repoView`) answers `null` when
11
- * GitHub says there is no such thing: absence is an answer.
12
- * - **`try`**: the same call, with the failure returned as
13
- * `Result<T, GhFailure>`. It catches a thrown failure (a `FailureError`, or a
14
- * `CommandFailed` from `raw`-level code) and nothing else: a `RangeError` for a bad argument still throws.
15
- * - **`soft`**: the same call, with `null` for a failure. Only the queries
16
- * have a soft form; no mutation does.
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
- * Both are facades over the whole client, so a new method costs nothing here.
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 plain door does.
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`), and a probe (`installed`, `authStatus`, `api`) carries its
28
- * failure in its value. A read that exited non-zero throws `CommandFailed`,
29
- * unless the verb's `absent` says gh's answer was "there is no such thing",
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 plain door throws for a failed run: a `FailureError` carrying
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: swallowing the failure
78
- * of a write is how a caller ends up believing it worked.
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 hand back rather than a bug to let
98
- * through. By shape, not `instanceof`: two installed copies of command-seam or
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: a getter (`try` itself) must run
115
- // against the real client rather than recursing through the facade.
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.*` door
3
- * returns it as the error of a `Result`; its `cause` is the `CommandFailed`
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 the subprocess layer's come from `gh`'s stderr, matched in
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; `detail` is `gh`'s own output. */
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; `null` when it never reported one. */
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; absent for `unreadable`, where `gh` succeeded. */
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: an answer, not a failure.
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.*` door
3
- * returns it as the error of a `Result`; its `cause` is the `CommandFailed`
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 the subprocess layer's come from `gh`'s stderr, matched in
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: an answer, not a failure.
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; this is gh either way, so the
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` — a typed GitHub client for TypeScript, over the `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
- * Three things it is:
5
+ * It has three parts:
6
6
  *
7
- * - **A model.** `PullRequest`, `Review`, `CheckRun` and their enums, so a
8
- * caller stops reading `payload["mergeable"] as string | undefined`. Every
9
- * field is total: one a query did not ask for lands at its "not known"
10
- * value, because absent and unknowable are the same answer.
11
- * - **Pure argv builders and parsers.** The verb table and `parse.ts` never
12
- * spawn anything, so an async fan-out drives them through its own runner
13
- * without duplicating a line of parsing.
14
- * - **A client.** `Gh`, with `Git`'s three doors: the plain method returns a
15
- * value or throws a `FailureError` carrying the classified
16
- * `GhFailure`; `gh.try.*` returns a
17
- * `Result<T, GhFailure>`; `gh.soft.*` returns `null` for a failed query.
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` — a typed GitHub client for TypeScript, over the `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
- * Three things it is:
5
+ * It has three parts:
6
6
  *
7
- * - **A model.** `PullRequest`, `Review`, `CheckRun` and their enums, so a
8
- * caller stops reading `payload["mergeable"] as string | undefined`. Every
9
- * field is total: one a query did not ask for lands at its "not known"
10
- * value, because absent and unknowable are the same answer.
11
- * - **Pure argv builders and parsers.** The verb table and `parse.ts` never
12
- * spawn anything, so an async fan-out drives them through its own runner
13
- * without duplicating a line of parsing.
14
- * - **A client.** `Gh`, with `Git`'s three doors: the plain method returns a
15
- * value or throws a `FailureError` carrying the classified
16
- * `GhFailure`; `gh.try.*` returns a
17
- * `Result<T, GhFailure>`; `gh.soft.*` returns `null` for a failed query.
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
- // The seam's error and runner types appear in this package's signatures, so
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 → the typed model.
2
+ * Parsers from `gh --json` payloads to the typed model.
3
3
  *
4
- * Everything here is pure, so an async fan-out can reuse it without going
5
- * near a subprocess, and so the awkward cases can be tested as data.
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
- * Two shape hazards this file exists to absorb:
7
+ * It handles two payload differences:
8
8
  *
9
- * 1. **Author logins differ by transport.** GraphQL (`gh pr view --json`)
10
- * returns a suffix-less login (`github-actions`); REST (`gh api`) returns
11
- * the suffixed one (`github-actions[bot]`). Comparing one against the
12
- * other silently never matches, which is how bot noise gets treated as
13
- * human review feedback. Logins are normalized to the suffix-less form
14
- * here, once.
15
- * 2. **`statusCheckRollup` holds two different node types.** A modern
16
- * `CheckRun` carries `name`/`status`/`conclusion`; a legacy
17
- * `StatusContext` carries `context`/`state`. They are folded onto one
18
- * verdict axis so a caller never has to know which it got.
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 — REST shape folded to GraphQL shape.
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 either transport (`author` or REST's `user`).
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 — the one label-array parse every `gh` caller shares. Skips an item with no name, or an empty-string name (indistinguishable from absent). */
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
- * Total by construction: a field `gh` was not asked for lands at its "not
42
- * known" value rather than `undefined`, so the result is safe to build from
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;