@osdlc/typed-gh 0.7.0 → 0.9.1

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/sync.js CHANGED
@@ -1,24 +1,26 @@
1
1
  /**
2
- * `Gh` — the synchronous GitHub client, the companion of `@osdlc/typed-git`'s
2
+ * `Gh`: the synchronous GitHub client, the companion of `@osdlc/typed-git`'s
3
3
  * `Git`, bound to one working directory and one {@link CommandRunner}.
4
4
  *
5
- * Authentication is `gh`'s, not ours: no token is read, stored, or passed.
6
- * That is the whole reason this shells out to the CLI instead of speaking
7
- * REST — the credential already exists in the user's keychain, and a library
8
- * that reaches for `GITHUB_TOKEN` is a library that can leak one.
5
+ * `gh` handles authentication. No token is read, stored, or passed. That is
6
+ * why this runs the CLI instead of calling the REST API. The credential is
7
+ * already in the user's keychain. A library that reads `GITHUB_TOKEN` can
8
+ * leak it.
9
9
  *
10
- * The same three doors as the git client. The plain method returns a value
11
- * or throws: a failed `gh` throws a `FailureError` carrying the classified
12
- * `GhFailure`, output that cannot be read throws one of kind `unreadable`, and a query for one thing (`prView`, `issueView`,
13
- * `repoView`) answers `null` when GitHub says there is no such thing.
14
- * `gh.try.*` returns the failure as a `Result<T, GhFailure>`; `gh.soft.*` returns
15
- * `null` for it. `raw`/`rawChecked` are the escape hatches.
10
+ * It has the same three call styles as the git client. The plain method
11
+ * returns a value or throws. A failed `gh` throws a `FailureError` carrying
12
+ * the classified `GhFailure`. Output that cannot be read throws one of kind
13
+ * `unreadable`. A query for one thing (`prView`, `issueView`, `repoView`)
14
+ * returns `null` when GitHub says there is no such thing. `gh.try.*` returns
15
+ * the failure as a `Result<T, GhFailure>`. `gh.soft.*` returns `null` for it.
16
+ * `raw` and `rawChecked` run any `gh` call.
16
17
  */
17
18
  import { resolveRunner, spawnRunner, } from '@osdlc/command-seam';
18
- import { runCheckedGh, settle, softSync, triedSync } from "./doors.js";
19
+ import { runCheckedGh, softSync, triedSync } from "./doors.js";
20
+ import { runVerb } from "./run.js";
19
21
  import * as v from "./verbs.js";
20
22
  import { ownerRepoSlug, parseOwnerRepo, parsePrRef } from "./repo.js";
21
- /** Default factory: real, spawnSync-backed runners. */
23
+ /** The default factory: real runners that use `spawnSync`. */
22
24
  export const defaultRunnerFactory = spawnRunner;
23
25
  /** How long to wait between merge-state retries, in milliseconds. */
24
26
  const MERGE_STATE_RETRY_DELAY_MS = 1_500;
@@ -62,69 +64,61 @@ export class Gh {
62
64
  }
63
65
  /**
64
66
  * The whole surface again, returning a `Result<T, GhFailure>` instead of
65
- * throwing: `gh.try.prList()` is `{ ok: true, value } | { ok: false, error }`.
67
+ * throwing. `gh.try.prList()` is `{ ok: true, value } | { ok: false, error }`.
66
68
  * A query for one thing that finds nothing is `ok: true` with `null`. See
67
69
  * `./doors.ts`.
68
70
  *
69
- * The type leaves out the escape hatches and the pure helpers; at runtime
70
- * the proxy wraps `raw` and `rawChecked` too. Call those on the client itself.
71
+ * The type leaves out `raw`, `rawChecked` and the helpers that run nothing.
72
+ * At runtime the proxy wraps `raw` and `rawChecked` too. Call those on the
73
+ * client itself.
71
74
  */
72
75
  get try() {
73
76
  return (this.tried ??= triedSync(this));
74
77
  }
75
78
  /**
76
79
  * Each query again, returning `null` instead of throwing when `gh` fails. A
77
- * mutation has no soft form. Do not gate a write on a `null` from `soft`:
78
- * it is the answer for "could not ask" as well as for "nothing there". Use
80
+ * mutation has no soft form. Do not decide a write on a `null` from `soft`.
81
+ * It is the answer for "could not ask" as well as for "nothing there". Use
79
82
  * `try` where the difference matters.
80
83
  */
81
84
  get soft() {
82
85
  return (this.softened ??= softSync(this));
83
86
  }
84
- // ── escape hatches ────────────────────────────────────────────────────────
85
- /** Unchecked passthrough for verbs not yet lifted into the API. */
87
+ // ── raw calls ─────────────────────────────────────────────────────────────
88
+ /** Run any `gh` call and return the result, whatever the exit code. */
86
89
  raw(argv, opts = {}) {
87
90
  return this.runner.run(argv, { cwd: this.cwd, ...opts });
88
91
  }
89
- /** Checked passthrough — throws the classified failure on a non-zero exit. */
92
+ /** Run any `gh` call. Throws the classified failure on a non-zero exit. */
90
93
  rawChecked(argv, opts = {}) {
91
94
  return runCheckedGh(this.runner, argv, { cwd: this.cwd, ...opts });
92
95
  }
93
- /** Run one verb from the table, honouring its checked/unchecked contract. */
96
+ /** Run one verb from the table, checked or unchecked as the verb says. */
94
97
  exec(verb, timeoutMs) {
95
- const opts = { cwd: this.cwd };
96
- if (verb.input !== undefined)
97
- opts.input = verb.input;
98
- if (verb.env !== undefined)
99
- opts.env = verb.env;
100
- if (timeoutMs !== undefined)
101
- opts.timeoutMs = timeoutMs;
102
- const result = verb.checked
103
- ? runCheckedGh(this.runner, verb.argv, opts)
104
- : this.runner.run(verb.argv, opts);
105
- return settle(verb, result, this.runner.binary);
106
- }
107
- /** {@link exec} for a verb that never answers `null` as a value: a failed or unreadable run throws. */
98
+ return runVerb(verb, this.runner, { cwd: this.cwd, timeoutMs });
99
+ }
100
+ /** {@link exec} for a verb that never returns `null` as a value. A failed or unreadable run throws. */
108
101
  read(verb, timeoutMs) {
109
102
  return this.exec(verb, timeoutMs);
110
103
  }
111
104
  // ── queries ───────────────────────────────────────────────────────────────
112
- /** Pull requests matching `opts`. Throws when gh fails; `soft.prList` gives null instead. */
105
+ /** Pull requests matching `opts`. Throws when gh fails. `soft.prList` gives null instead. */
113
106
  prList(opts = {}) {
114
107
  return this.read(v.prList(opts, this.target), opts.timeoutMs);
115
108
  }
116
109
  /**
117
- * One PR by number, branch or URL, with the heavy fields; null when there is
118
- * no such PR. Throws when gh fails otherwise.
110
+ * One PR by number, branch or URL, with the full field set. Null when there
111
+ * is no such PR. Throws when gh fails otherwise.
119
112
  */
120
113
  prView(ref, opts = {}) {
121
114
  return this.exec(v.prView(ref, opts.fields ?? v.PR_VIEW_FIELDS, this.target), opts.timeoutMs);
122
115
  }
123
116
  /**
124
- * The one PR that `input` names, or null: what a person typed, such as `42`,
125
- * `#42`, `owner/name#42`, a URL or a branch (read by `parsePrRef`).
117
+ * The one PR that `input` names, or null. `input` is what a person typed,
118
+ * such as `42`, `#42`, `owner/name#42`, a URL or a branch (read by
119
+ * `parsePrRef`).
126
120
  *
127
- * Digits are a PR number first; when no such PR comes back, they are tried
121
+ * Digits are a PR number first. When no such PR comes back, they are tried
128
122
  * as a branch. A branch gives its open PR, or else its newest closed or
129
123
  * merged one, so a tool run after the merge still finds it. Fields default
130
124
  * to {@link PR_LIST_FIELDS}.
@@ -146,12 +140,10 @@ export class Gh {
146
140
  /**
147
141
  * The open PR whose head exactly equals `branch`, or null.
148
142
  *
149
- * Defaults to {@link PR_REF_FIELDS}: identifying a PR must not cost a
150
- * merge-state computation. Pass `opts.fields` to ask for more (e.g.
151
- * `isDraft`) in the SAME call, when a caller needs a field beyond identity
152
- * before deciding whether to act on the PR at all — asking `prList`/`prView`
153
- * separately would cost a second round trip for the common case where the
154
- * caller already knows it wants that field up front.
143
+ * Defaults to {@link PR_REF_FIELDS}, so finding a PR does not make GitHub
144
+ * compute the merge state. Pass `opts.fields` to ask for more (such as
145
+ * `isDraft`) in the same call. That saves a second `prList` or `prView`
146
+ * call when the caller already knows it needs the field.
155
147
  */
156
148
  openPrFor(branch, opts = {}) {
157
149
  const rows = this.prList({
@@ -162,16 +154,16 @@ export class Gh {
162
154
  return v.pickPrForBranch(rows.rows, branch);
163
155
  }
164
156
  /**
165
- * {@link prView}, re-asked until GitHub settles the merge state.
157
+ * {@link prView}, asked again until GitHub has computed the merge state.
166
158
  *
167
- * GitHub computes mergeability lazily: the first query kicks it off and
168
- * answers `UNKNOWN` while it runs. A caller that believes that first answer
169
- * mis-triages every PR that is merely slow to compute, so this re-asks
170
- * `attempts` times before returning what it has. The last answer is
171
- * returned whether or not it settled — `UNKNOWN` is a legitimate final
172
- * verdict and callers must still handle it.
159
+ * GitHub computes mergeability only when asked. The first query starts it
160
+ * and answers `UNKNOWN` while it runs. A caller that trusts that first
161
+ * answer misjudges every PR whose computation is slow. So this asks up to
162
+ * `attempts` times while the answer is `UNKNOWN`. The last answer is
163
+ * returned either way. `UNKNOWN` can be the final answer, and callers must
164
+ * still handle it.
173
165
  *
174
- * `sleep` is injected so a test does not spend real seconds waiting.
166
+ * `sleep` is an option so a test does not spend real seconds waiting.
175
167
  */
176
168
  prViewSettled(number, opts = {}) {
177
169
  const attempts = Math.max(1, opts.attempts ?? 3);
@@ -191,15 +183,15 @@ export class Gh {
191
183
  return this.read(v.prBody(number, this.target), opts.timeoutMs);
192
184
  }
193
185
  /**
194
- * A REST GET through `gh api`. Never throws for a failed call, in any door:
195
- * failure is `ok: false` on the returned {@link ApiResponse}.
186
+ * A REST GET through `gh api`. Never throws for a failed call, in any call
187
+ * style. Failure is `ok: false` on the returned {@link ApiResponse}.
196
188
  */
197
189
  api(endpoint, opts = {}) {
198
190
  return this.exec(v.api(endpoint, opts, this.target), opts.timeoutMs);
199
191
  }
200
192
  /**
201
- * A GraphQL query; each page's `data`. Throws on a failed or partial result;
202
- * `soft.graphql` gives null. See the `graphql` verb.
193
+ * A GraphQL query. Returns each page's `data`. Throws on a failed or partial
194
+ * result. `soft.graphql` gives null. See the `graphql` verb.
203
195
  *
204
196
  * @experimental
205
197
  */
@@ -214,7 +206,7 @@ export class Gh {
214
206
  issueList(opts = {}) {
215
207
  return this.read(v.issueList(opts, this.target), opts.timeoutMs);
216
208
  }
217
- /** One issue with its labels; null when there is no such issue. Throws when gh fails otherwise. */
209
+ /** One issue with its labels, or null when there is no such issue. Throws when gh fails otherwise. */
218
210
  issueView(number, opts = {}) {
219
211
  return this.exec(v.issueView(number, this.target), opts.timeoutMs);
220
212
  }
@@ -235,22 +227,23 @@ export class Gh {
235
227
  return this.exec(v.installed());
236
228
  }
237
229
  /**
238
- * True iff `gh` holds credentials. Asked on its own only by a caller that
239
- * reports the two halves separately — "gh is missing" and "gh is not logged
240
- * in" are different things to tell a person, and a report that collapses
241
- * them sends someone to install software they already have.
230
+ * True iff `gh` holds credentials. Call it on its own to report the two
231
+ * checks separately. "gh is missing" and "gh is not logged in" need
232
+ * different fixes. A report that merges them sends someone to install
233
+ * software they already have.
242
234
  */
243
235
  authenticated() {
244
236
  return this.authStatus().ok;
245
237
  }
246
- /** Login state and what `gh auth status` printed; `authenticated()` is its `ok`. */
238
+ /** Login state and what `gh auth status` printed. `authenticated()` is its `ok`. */
247
239
  authStatus() {
248
240
  return this.exec(v.authStatus(this.target));
249
241
  }
250
242
  /**
251
- * True iff `gh` is installed AND authenticated — the two-step probe.
243
+ * True iff `gh` is installed and authenticated.
252
244
  *
253
- * Short-circuits: an absent binary cannot be asked about credentials.
245
+ * Skips the auth check when `gh` is not installed, since there is nothing to
246
+ * ask.
254
247
  */
255
248
  ready() {
256
249
  return this.installed() && this.authenticated();
@@ -259,7 +252,7 @@ export class Gh {
259
252
  * `{owner, repo}` parsed from the remote URL you pass, or null when it is
260
253
  * null or names no project.
261
254
  *
262
- * Pure: it reads no git config, starts no process and does not ask GitHub.
255
+ * It reads no git config, starts no process and does not ask GitHub.
263
256
  */
264
257
  ownerRepo(remoteUrl) {
265
258
  return remoteUrl === null ? null : parseOwnerRepo(remoteUrl);
@@ -273,16 +266,16 @@ export class Gh {
273
266
  editPr(number, opts) {
274
267
  this.exec(v.editPr(number, opts, this.target));
275
268
  }
276
- /** The PR's unified diff; throws the classified failure when gh cannot produce it. */
269
+ /** The PR's unified diff. Throws the classified failure when gh cannot produce it. */
277
270
  prDiff(number) {
278
271
  return this.exec(v.prDiff(number, this.target));
279
272
  }
280
- /** Post one conversation comment on a PR; returns its URL ('' if gh printed none). */
273
+ /** Post one conversation comment on a PR. Returns its URL ('' if gh printed none). */
281
274
  prComment(number, body) {
282
275
  return this.exec(v.prComment(number, body, this.target));
283
276
  }
284
277
  /**
285
- * Create a `COMMENT` review with inline comments; returns the review's URL ('' if none came back).
278
+ * Create a `COMMENT` review with inline comments. Returns the review's URL ('' if none came back).
286
279
  *
287
280
  * @experimental
288
281
  */
@@ -302,14 +295,14 @@ export class Gh {
302
295
  this.exec(v.prSetDraft(number, draft, this.target));
303
296
  }
304
297
  /**
305
- * Rewrite one PR conversation comment's body. `commentId` is the numeric REST id; anything else throws `RangeError`.
298
+ * Rewrite one PR conversation comment's body. `commentId` is the numeric REST id. Anything else throws `RangeError`.
306
299
  *
307
300
  * @experimental
308
301
  */
309
302
  issueCommentEdit(commentId, body) {
310
303
  this.exec(v.issueCommentEdit(commentId, body, this.target));
311
304
  }
312
- /** Merge a PR; GitHub refuses when its head is no longer `opts.headSha`. */
305
+ /** Merge a PR. GitHub refuses when its head is no longer `opts.headSha`. */
313
306
  prMerge(number, opts) {
314
307
  this.exec(v.prMerge(number, opts, this.target));
315
308
  }
@@ -327,8 +320,8 @@ export class Gh {
327
320
  }
328
321
  /**
329
322
  * Swap an issue's label: remove `currentLabel` (when given) and add
330
- * `newLabel`, in a single `gh issue edit` call — never a briefly-unlabeled
331
- * or briefly-double-labeled intermediate state.
323
+ * `newLabel`, in a single `gh issue edit` call. The issue is never left
324
+ * with neither label or both labels in between.
332
325
  */
333
326
  setIssueLabel(number, currentLabel, newLabel) {
334
327
  this.exec(v.setIssueLabel(number, currentLabel, newLabel, this.target));
@@ -346,9 +339,9 @@ function prForBranchOn(gh, branch, call) {
346
339
  return v.branchPr(rows);
347
340
  }
348
341
  /**
349
- * Block the calling thread. Crude on purpose: the synchronous client has no
350
- * event loop to await on, and the alternative — making every caller async to
351
- * accommodate one retry delay — colors the whole call graph.
342
+ * Block the calling thread. The synchronous client has no event loop to
343
+ * await on. The alternative is to make every caller async for one retry
344
+ * delay.
352
345
  */
353
346
  function sleepSync(ms) {
354
347
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
package/dist/types.d.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * The GitHub model, typed.
3
3
  *
4
- * `gh` returns GraphQL-shaped JSON whose fields depend on what you asked for,
5
- * so every field here is total: a value, or the enum member that means "not
6
- * known". Absent and unknowable are the same answer to a caller, and giving
7
- * them one representation is what keeps a consumer from reading a field it
8
- * never requested as a fact.
4
+ * `gh` returns GraphQL-shaped JSON whose fields depend on what you asked for.
5
+ * So every field here always has a value: a real one, or the value that means
6
+ * "not known". Absent and unknowable are the same answer to a caller. Giving
7
+ * them one value keeps a caller from reading a field it never requested as a
8
+ * fact.
9
9
  *
10
10
  * Most enums are open on purpose. GitHub adds members, and a client that
11
- * crashes on an unrecognized one is worse than a client that carries it
12
- * through: unions end in `(string & {})` so a new value still types as the
13
- * enum while the known members keep their autocomplete.
11
+ * crashes on an unknown one is worse than a client that passes it on. Unions
12
+ * end in `(string & {})`, so a new value still types as the enum and the known
13
+ * members keep their autocomplete.
14
14
  *
15
15
  * Two are closed: {@link MergeableState} and {@link ReviewDecision}. Callers
16
16
  * compare them member by member to decide whether to merge, so the parser
@@ -25,10 +25,10 @@ export type MergeableState = 'MERGEABLE' | 'CONFLICTING' | 'UNKNOWN';
25
25
  /**
26
26
  * The merge-button state.
27
27
  *
28
- * `BEHIND` only ever appears when branch protection *requires* an up-to-date
29
- * branch. Without that rule a branch a hundred commits behind still reports
30
- * `CLEAN`, so this is a corroborating hint about staleness and never the
31
- * measure of it — compute that from the commit graph.
28
+ * `BEHIND` appears only when branch protection requires an up-to-date branch.
29
+ * Without that rule, a branch a hundred commits behind still reports `CLEAN`.
30
+ * So `BEHIND` is a hint that a branch is out of date, not a measure of it.
31
+ * Compute that from the commit graph.
32
32
  */
33
33
  export type MergeStateStatus = 'BEHIND' | 'BLOCKED' | 'CLEAN' | 'DIRTY' | 'DRAFT' | 'HAS_HOOKS' | 'UNKNOWN' | 'UNSTABLE' | (string & {});
34
34
  /** Where a pull request is in its life: open, closed without a merge, or merged. */
@@ -41,23 +41,22 @@ export type PullRequestState = 'OPEN' | 'CLOSED' | 'MERGED' | (string & {});
41
41
  export type ReviewDecision = 'APPROVED' | 'CHANGES_REQUESTED' | 'REVIEW_REQUIRED' | null;
42
42
  /** The state of one review. `PENDING` is a review its author has not submitted yet. */
43
43
  export type ReviewState = 'APPROVED' | 'CHANGES_REQUESTED' | 'COMMENTED' | 'DISMISSED' | 'PENDING' | (string & {});
44
- /** Who wrote something. `login` is normalized — a `[bot]` suffix is stripped. */
44
+ /** Who wrote something. `login` is normalized: a `[bot]` suffix is stripped. */
45
45
  export interface Actor {
46
46
  login: string;
47
47
  /** True when GitHub marks the account as a bot, or the login carried `[bot]`. */
48
48
  isBot: boolean;
49
49
  }
50
- /** A repository label. `color` is hex digits such as `d73a4a`; a field the payload lacks is `''`. */
50
+ /** A repository label. `color` is hex digits such as `d73a4a`. A field the payload lacks is `''`. */
51
51
  export interface Label {
52
52
  name: string;
53
53
  color: string;
54
54
  description: string;
55
55
  }
56
56
  /**
57
- * A GitHub issue, off `gh issue list`/`gh issue view --json
58
- * number,title,body,labels,state`. Deliberately a small field set — not the
59
- * full PR-sized model, since nothing here reads reviews, checks or comments
60
- * off an issue.
57
+ * A GitHub issue, from `gh issue list`/`gh issue view --json
58
+ * number,title,body,labels,state`. It has a small field set on purpose,
59
+ * because nothing here reads reviews, checks or comments on an issue.
61
60
  */
62
61
  export interface IssueRow {
63
62
  number: number;
@@ -69,22 +68,22 @@ export interface IssueRow {
69
68
  /**
70
69
  * How a finished check ended, as GitHub reports it. Null while the check is
71
70
  * still running, and always null for a legacy status context. Read
72
- * {@link CheckRun.verdict} for the answer folded across both node types.
71
+ * {@link CheckRun.verdict} for one answer that covers both node types.
73
72
  */
74
73
  export type CheckConclusion = 'SUCCESS' | 'FAILURE' | 'NEUTRAL' | 'CANCELLED' | 'TIMED_OUT' | 'ACTION_REQUIRED' | 'SKIPPED' | 'STALE' | 'STARTUP_FAILURE' | (string & {}) | null;
75
- /** One rolled-up check, with the two GitHub shapes folded into one. */
74
+ /** One check from the status rollup, with GitHub's two node types mapped to one shape. */
76
75
  export interface CheckRun {
77
76
  /** A CheckRun's `name`, or a legacy StatusContext's `context`. */
78
77
  name: string;
79
- /** `QUEUED` / `IN_PROGRESS` / `COMPLETED`; null for a status context. */
78
+ /** `QUEUED` / `IN_PROGRESS` / `COMPLETED`. Null for a status context. */
80
79
  status: string | null;
81
80
  conclusion: CheckConclusion;
82
81
  /**
83
- * The normalized verdict. A check still running is `pending`, not a pass —
84
- * treating "no failure yet" as green is how a red build merges.
82
+ * The normalized verdict. A check still running is `pending`, not a pass.
83
+ * If "no failure yet" counted as green, a red build could merge.
85
84
  */
86
85
  verdict: 'pending' | 'success' | 'failure' | 'neutral';
87
- /** A CheckRun's `detailsUrl`, or a legacy StatusContext's `targetUrl` — where to read the log. Null when the code host gives none. */
86
+ /** A CheckRun's `detailsUrl`, or a legacy StatusContext's `targetUrl`: where to read the log. Null when GitHub gives none. */
88
87
  url: string | null;
89
88
  }
90
89
  /** One conversation comment on a pull request. */
@@ -114,7 +113,7 @@ export interface Review {
114
113
  *
115
114
  * Fields `gh` was not asked for come back at their "not known" value, so this
116
115
  * type is safe to build from any field subset. `number` is the only field
117
- * without one — a PR with no number is not a PR, and parsing returns null.
116
+ * without one. A payload with no number is not a PR, and parsing returns null.
118
117
  */
119
118
  export interface PullRequest {
120
119
  number: number;
@@ -125,11 +124,11 @@ export interface PullRequest {
125
124
  isDraft: boolean;
126
125
  baseRefName: string;
127
126
  headRefName: string;
128
- /** Head commit sha, when requested — the thing to pin a force-push lease to. */
127
+ /** Head commit sha, when requested. Use it as the expected value for `--force-with-lease`. */
129
128
  headRefOid: string | null;
130
129
  /**
131
- * True when the head branch lives in a fork. Its ref is then not on the
132
- * base repository's `origin`; fetch `refs/pull/<n>/head` instead.
130
+ * True when the head branch is in a fork. Its ref is then not on the
131
+ * base repository's `origin`. Fetch `refs/pull/<n>/head` instead.
133
132
  */
134
133
  isCrossRepository: boolean;
135
134
  mergeable: MergeableState;
@@ -152,7 +151,7 @@ export interface OwnerRepo {
152
151
  /** Who can see a repository. */
153
152
  export type RepositoryVisibility = 'PUBLIC' | 'PRIVATE' | 'INTERNAL' | (string & {});
154
153
  /**
155
- * A repository, off `gh repo list`/`gh repo view --json`. A field not asked
154
+ * A repository, from `gh repo list`/`gh repo view --json`. A field not asked
156
155
  * for comes back at its "not known" value. `nameWithOwner` is the only field
157
156
  * without one: a row without it is dropped.
158
157
  */
@@ -162,15 +161,15 @@ export interface Repository {
162
161
  owner: string;
163
162
  name: string;
164
163
  description: string;
165
- /** The default branch; null when not asked for, or the repository is empty. */
164
+ /** The default branch. Null when not asked for, or when the repository is empty. */
166
165
  defaultBranch: string | null;
167
166
  visibility: RepositoryVisibility | null;
168
167
  isArchived: boolean;
169
168
  url: string;
170
169
  }
171
170
  /**
172
- * One pull request found by `gh search prs`. Search has its own field set:
173
- * it names the repository but carries no head or base branch, so this is not
171
+ * One pull request found by `gh search prs`. Search has its own field set.
172
+ * It names the repository but carries no head or base branch, so this is not
174
173
  * a {@link PullRequest}. `state` is upper-cased to match `PullRequest`.
175
174
  */
176
175
  export interface PrSearchHit {
package/dist/types.js CHANGED
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * The GitHub model, typed.
3
3
  *
4
- * `gh` returns GraphQL-shaped JSON whose fields depend on what you asked for,
5
- * so every field here is total: a value, or the enum member that means "not
6
- * known". Absent and unknowable are the same answer to a caller, and giving
7
- * them one representation is what keeps a consumer from reading a field it
8
- * never requested as a fact.
4
+ * `gh` returns GraphQL-shaped JSON whose fields depend on what you asked for.
5
+ * So every field here always has a value: a real one, or the value that means
6
+ * "not known". Absent and unknowable are the same answer to a caller. Giving
7
+ * them one value keeps a caller from reading a field it never requested as a
8
+ * fact.
9
9
  *
10
10
  * Most enums are open on purpose. GitHub adds members, and a client that
11
- * crashes on an unrecognized one is worse than a client that carries it
12
- * through: unions end in `(string & {})` so a new value still types as the
13
- * enum while the known members keep their autocomplete.
11
+ * crashes on an unknown one is worse than a client that passes it on. Unions
12
+ * end in `(string & {})`, so a new value still types as the enum and the known
13
+ * members keep their autocomplete.
14
14
  *
15
15
  * Two are closed: {@link MergeableState} and {@link ReviewDecision}. Callers
16
16
  * compare them member by member to decide whether to merge, so the parser