@osdlc/typed-gh 0.14.1 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +48 -6
- package/dist/async.js +3 -3
- package/dist/doors.d.ts +5 -5
- package/dist/doors.js +5 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/sync.js +3 -3
- package/dist/verbs.d.ts +54 -15
- package/dist/verbs.js +56 -12
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @osdlc/typed-gh
|
|
2
2
|
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 51efdb6: `raw(argv)` and `rawChecked(argv)` are new verbs: `Gh.raw` and `Gh.rawChecked` as functions, so a tool can make a call the verb table lacks without constructing a `Gh`. Through `runVerb`, `raw` returns the `CommandResult` whatever the exit code, and `rawChecked` returns it when `gh` exits 0 with its whole output and throws the classified `GhFailure` otherwise. Neither is `readOnly`. Both clients' `raw` and `rawChecked` methods now run these verbs. The one visible change is that `AsyncGh.raw` rejects, rather than throwing at the call site, when a runner throws synchronously, as `rawChecked` already did.
|
|
8
|
+
|
|
9
|
+
The README has a new section, "Keeping a bundle small": a bundled tool that makes a few calls should import the verbs it calls and run them with `runVerb`, because a bundler cannot drop a class's unused methods. For a diff and one raw checked call, that is 14.4 KB against 68.0 KB through `Gh` (`bun build --minify`). The decision and the measurements are in `docs/planning/decisions/bundle-size.md`.
|
|
10
|
+
|
|
11
|
+
## 0.15.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- 4f764b7: `graphql` (experimental): fill the target's owner or repo name with the new `fromTarget('owner')` / `fromTarget('repo')` markers. **Breaking for `graphql` callers:** a plain string variable is now always sent as written, so a real value of `{owner}` or `{repo}` (a branch name, say) is no longer replaced. Change `{ owner: '{owner}', name: '{repo}' }` to `{ owner: fromTarget('owner'), name: fromTarget('repo') }`. REST endpoints keep the `{owner}/{repo}` path template, which mirrors gh's own syntax.
|
|
16
|
+
|
|
3
17
|
## 0.14.1
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -419,6 +419,34 @@ const repos = await runVerbAsync(repoList('acme', {}, { hostname: 'ghe.example.c
|
|
|
419
419
|
`(binary, argv, opts) => result` function is not a runner; wrap it yourself as
|
|
420
420
|
`{ run: (argv, opts) => fn('gh', argv, opts) }`.
|
|
421
421
|
|
|
422
|
+
`raw(argv)` and `rawChecked(argv)` are `Gh.raw` and `Gh.rawChecked` as verbs, for a call the verb
|
|
423
|
+
table does not have. Through `runVerb`, `raw` returns the `CommandResult` whatever the exit code,
|
|
424
|
+
and `rawChecked` returns it when `gh` exits 0 with its whole output and throws the classified
|
|
425
|
+
failure otherwise. Like the methods, they add no `--repo` and no host.
|
|
426
|
+
|
|
427
|
+
## Keeping a bundle small
|
|
428
|
+
|
|
429
|
+
A tool that is bundled and makes a few `gh` calls should import the verbs it calls and run them
|
|
430
|
+
with `runVerb`, and not construct a `Gh`. A bundler drops a function that nothing imports, but it
|
|
431
|
+
cannot drop a method a class never calls. So one `new Gh()` keeps every verb and parser in the
|
|
432
|
+
bundle, and the verb path keeps only the verbs you import:
|
|
433
|
+
|
|
434
|
+
```ts
|
|
435
|
+
import { defaultRunnerFactory, prDiff, rawChecked, runVerb } from '@osdlc/typed-gh'
|
|
436
|
+
|
|
437
|
+
const runner = defaultRunnerFactory('gh')
|
|
438
|
+
const opts = { cwd: '/repo' }
|
|
439
|
+
const diff = runVerb(prDiff(42), runner, opts)
|
|
440
|
+
const files = runVerb(rawChecked(['api', 'repos/{owner}/{repo}/pulls/42/files']), runner, opts)
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Built with `bun build --minify`, those two calls take 14.4 KB through `runVerb` and 68.0 KB through
|
|
444
|
+
`Gh` (7.6 KB of each is command-seam's runner). The verb path gives up `try`, `soft` and the
|
|
445
|
+
helpers that make several calls (`prFind`, `openPrFor`, `prViewSettled`): catch the `FailureError`
|
|
446
|
+
instead. A tool that already uses many methods loses little by constructing `Gh`. The measurements
|
|
447
|
+
and the reasons `Gh` is not split into entry points are in
|
|
448
|
+
[docs/planning/decisions/bundle-size.md](docs/planning/decisions/bundle-size.md).
|
|
449
|
+
|
|
422
450
|
## `AsyncGh`
|
|
423
451
|
|
|
424
452
|
The awaitable form of `Gh`, with the same methods, for code that runs many calls at once and must
|
|
@@ -466,6 +494,9 @@ const branches = gh.api('repos/{owner}/{repo}/branches', { paginate: true }).bod
|
|
|
466
494
|
`graphql` (experimental) runs a query and returns each page's `data`. It throws when the
|
|
467
495
|
call failed or any page has `errors` or no `data` (`soft.graphql` is `null`). A partial answer counts as a failure. `nodesAt` joins
|
|
468
496
|
one connection's `nodes` across the pages, and is `null` when any page lacks them.
|
|
497
|
+
`fromTarget('owner')` and `fromTarget('repo')` fill a variable from the client's repo, or let gh
|
|
498
|
+
fill it from the clone. A plain string is always sent as written, so a real value of `{owner}` stays
|
|
499
|
+
`{owner}`.
|
|
469
500
|
|
|
470
501
|
```ts
|
|
471
502
|
const query = `query($owner: String!, $name: String!, $endCursor: String) {
|
|
@@ -476,7 +507,11 @@ const query = `query($owner: String!, $name: String!, $endCursor: String) {
|
|
|
476
507
|
}
|
|
477
508
|
}
|
|
478
509
|
}`
|
|
479
|
-
const pages = gh.graphql(
|
|
510
|
+
const pages = gh.graphql(
|
|
511
|
+
query,
|
|
512
|
+
{ owner: fromTarget('owner'), name: fromTarget('repo') },
|
|
513
|
+
{ paginate: true },
|
|
514
|
+
)
|
|
480
515
|
const prs = nodesAt(pages, ['repository', 'pullRequests'])
|
|
481
516
|
```
|
|
482
517
|
|
|
@@ -566,7 +601,9 @@ experimental.
|
|
|
566
601
|
- `AsyncCallOptions`: `timeoutMs` and `signal`, accepted by sixteen methods of `AsyncGh`.
|
|
567
602
|
- `defaultRunnerFactory` and `RunnerFactory`: how a client makes its default runner for `gh`.
|
|
568
603
|
- `runVerb` and `runVerbAsync`, with `RunVerbOptions` and `RunVerbAsyncOptions`: run one verb through
|
|
569
|
-
a runner you own, with its `env`, `input`, timeout and checked contract applied.
|
|
604
|
+
a runner you own, with its `env`, `input`, timeout and checked contract applied. With the verb
|
|
605
|
+
functions, they are the way to call `gh` without a `Gh`, which keeps a bundle small (see
|
|
606
|
+
"Keeping a bundle small").
|
|
570
607
|
|
|
571
608
|
Methods on both clients:
|
|
572
609
|
|
|
@@ -594,10 +631,11 @@ Methods on both clients:
|
|
|
594
631
|
|
|
595
632
|
A verb is plain data: argv, a `checked` flag, a `readOnly` flag, optional stdin and environment,
|
|
596
633
|
and a `parse` function. `readOnly` is true for every query and `prDiff`, and false for every
|
|
597
|
-
mutation
|
|
598
|
-
Each verb takes an optional `GhTarget` last
|
|
599
|
-
`
|
|
600
|
-
`
|
|
634
|
+
mutation and for `raw` and `rawChecked`, so a caller that keeps an allowlist of safe calls can check
|
|
635
|
+
a verb before running it. Each verb takes an optional `GhTarget` last, except `raw` and
|
|
636
|
+
`rawChecked`, which take only argv. Each client method has a verb of the same name, except `at`,
|
|
637
|
+
`withRepo`, `prViewSettled`, `openPrFor`, `prFind`, `authenticated`, `ready` and `ownerRepo`.
|
|
638
|
+
`openPrsForBranch` is a verb with no method.
|
|
601
639
|
|
|
602
640
|
- `GhVerb`: the shape of a verb. `GhTarget`: the `repo` and `hostname` a verb talks to.
|
|
603
641
|
- Verb builders: `prList`, `prView`, `prBody`, `openPrsForBranch`, `prReviewThreads`, `prDiff`,
|
|
@@ -605,6 +643,9 @@ Each verb takes an optional `GhTarget` last. Each client method has a verb of th
|
|
|
605
643
|
`createReview`, `issueList`, `issueView`, `labelList`, `setIssueLabel`, `createLabel`,
|
|
606
644
|
`editLabel`, `issueCommentEdit`, `repoList`, `repoView`, `searchPrs`, `api`, `graphql`,
|
|
607
645
|
`installed` and `authStatus`.
|
|
646
|
+
- `raw` and `rawChecked`: any argv as a verb whose value is the `CommandResult`. `raw` returns it
|
|
647
|
+
whatever the exit code; `rawChecked` throws the classified failure unless `gh` exits 0 with its
|
|
648
|
+
whole output.
|
|
608
649
|
- `pickPrForBranch`: the first row whose head branch is exactly the one you name. `prList({ head })`
|
|
609
650
|
already filters exactly. This is for rows from elsewhere, such as a `head:` search. It takes plain
|
|
610
651
|
rows or a `ListResult`, so `openPrsForBranch`'s or `prList`'s parsed answer passes straight in.
|
|
@@ -663,6 +704,7 @@ The experimental items:
|
|
|
663
704
|
- `nodesAt`
|
|
664
705
|
- `GraphqlOptions`
|
|
665
706
|
- `GraphqlVariable`
|
|
707
|
+
- `fromTarget` and `FromTarget`
|
|
666
708
|
|
|
667
709
|
Every other export and method is stable, `prDiff` included. So is `@osdlc/typed-gh/testing`: its
|
|
668
710
|
builders and their row types. Their default values may change in any minor release.
|
package/dist/async.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* block the event loop, such as many per-PR queries at once.
|
|
12
12
|
*/
|
|
13
13
|
import { spawnRunnerAsync } from '@osdlc/command-seam';
|
|
14
|
-
import {
|
|
14
|
+
import { softAsync, triedAsync } from "./doors.js";
|
|
15
15
|
import { runVerbAsync } from "./run.js";
|
|
16
16
|
import { ownerRepoSlug, parseOwnerRepo, parsePrRef } from "./repo.js";
|
|
17
17
|
import * as v from "./verbs.js";
|
|
@@ -80,11 +80,11 @@ export class AsyncGh {
|
|
|
80
80
|
* `.at(dir)` first.
|
|
81
81
|
*/
|
|
82
82
|
raw(argv, opts = {}) {
|
|
83
|
-
return this.
|
|
83
|
+
return this.exec(v.raw(argv), opts);
|
|
84
84
|
}
|
|
85
85
|
/** Run any `gh` call. Rejects with the classified failure on a non-zero exit. Adds no `--repo`, as {@link AsyncGh.raw}. */
|
|
86
86
|
rawChecked(argv, opts = {}) {
|
|
87
|
-
return
|
|
87
|
+
return this.exec(v.rawChecked(argv), opts);
|
|
88
88
|
}
|
|
89
89
|
/** Run one verb from the table, checked or unchecked as the verb says. */
|
|
90
90
|
async exec(verb, call = {}) {
|
package/dist/doors.d.ts
CHANGED
|
@@ -27,11 +27,11 @@ import type { GhVerb } from './verbs.ts';
|
|
|
27
27
|
* Read the result of running `verb` as the methods that throw do.
|
|
28
28
|
*
|
|
29
29
|
* A checked verb has already thrown on a non-zero exit (the runner is
|
|
30
|
-
* {@link runCheckedGh}). A probe (`installed`, `authStatus`, `api`)
|
|
31
|
-
* failure in its value. A read that exited non-zero throws the
|
|
32
|
-
* failure, unless the verb's `absent` says gh's answer was "there
|
|
33
|
-
* thing", which `parse` turns into `null`. A read that exited 0 but
|
|
34
|
-
* could not be read completely, and throws.
|
|
30
|
+
* {@link runCheckedGh}). A probe (`installed`, `authStatus`, `api`, `raw`)
|
|
31
|
+
* carries its failure in its value. A read that exited non-zero throws the
|
|
32
|
+
* classified failure, unless the verb's `absent` says gh's answer was "there
|
|
33
|
+
* is no such thing", which `parse` turns into `null`. A read that exited 0 but
|
|
34
|
+
* parsed to `null` could not be read completely, and throws.
|
|
35
35
|
*
|
|
36
36
|
* A result flagged `outputIncomplete` throws for every verb but a probe, as
|
|
37
37
|
* typed-git's `gate` does: gh exited, but the runner stopped reading at the
|
package/dist/doors.js
CHANGED
|
@@ -26,11 +26,11 @@ import { classifyGhFailure, unreadableFailure } from "./failure.js";
|
|
|
26
26
|
* Read the result of running `verb` as the methods that throw do.
|
|
27
27
|
*
|
|
28
28
|
* A checked verb has already thrown on a non-zero exit (the runner is
|
|
29
|
-
* {@link runCheckedGh}). A probe (`installed`, `authStatus`, `api`)
|
|
30
|
-
* failure in its value. A read that exited non-zero throws the
|
|
31
|
-
* failure, unless the verb's `absent` says gh's answer was "there
|
|
32
|
-
* thing", which `parse` turns into `null`. A read that exited 0 but
|
|
33
|
-
* could not be read completely, and throws.
|
|
29
|
+
* {@link runCheckedGh}). A probe (`installed`, `authStatus`, `api`, `raw`)
|
|
30
|
+
* carries its failure in its value. A read that exited non-zero throws the
|
|
31
|
+
* classified failure, unless the verb's `absent` says gh's answer was "there
|
|
32
|
+
* is no such thing", which `parse` turns into `null`. A read that exited 0 but
|
|
33
|
+
* parsed to `null` could not be read completely, and throws.
|
|
34
34
|
*
|
|
35
35
|
* A result flagged `outputIncomplete` throws for every verb but a probe, as
|
|
36
36
|
* typed-git's `gate` does: gh exited, but the runner stopped reading at the
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export { classifyGhFailure, type GhFailure, type GhFailureKind } from './failure
|
|
|
23
23
|
export { type Soft, type TriedAsync, type TriedSync } from './doors.ts';
|
|
24
24
|
export { runVerb, runVerbAsync, type RunVerbAsyncOptions, type RunVerbOptions } from './run.ts';
|
|
25
25
|
export { Gh, defaultRunnerFactory, type GhOptions, type GhRepoOptions, type RunnerFactory, } from './sync.ts';
|
|
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, type ApiOptions, type ApiResponse, type AuthStatus, type CreateLabelOptions, type CreatePrOptions, type CreateReviewOptions, type GhTarget, type GraphqlOptions, type GraphqlVariable, type GhVerb, type IssueListOptions, type ListResult, type PrListOptions, type PrMergeMethod, type RepoListOptions, type ReviewComment, type ReviewThread, type SearchPrsOptions, } from './verbs.ts';
|
|
26
|
+
export { api, authStatus, createPr, editPr, editPrBody, fromTarget, graphql, createLabel, createReview, editLabel, installed, issueList, issueView, labelList, nodesAt, openPrsForBranch, pickPrForBranch, prBody, prComment, prSetDraft, issueCommentEdit, prDiff, prList, prMerge, prReviewThreads, prUpdateBranch, prView, raw, rawChecked, repoList, repoView, searchPrs, setIssueLabel, PR_LIST_FIELDS, PR_REF_FIELDS, PR_VIEW_FIELDS, REPO_FIELDS, SEARCH_PR_FIELDS, type ApiOptions, type ApiResponse, type AuthStatus, type CreateLabelOptions, type CreatePrOptions, type CreateReviewOptions, type FromTarget, type GhTarget, type GraphqlOptions, type GraphqlVariable, type GhVerb, type IssueListOptions, type ListResult, type PrListOptions, type PrMergeMethod, type RepoListOptions, type ReviewComment, type ReviewThread, type SearchPrsOptions, } from './verbs.ts';
|
|
27
27
|
export { anyCheckFailed, normalizeAuthorLogin, parsePullRequest } from './parse.ts';
|
|
28
28
|
export { ownerRepoSlug, parseOwnerRepo, parsePrRef, parsePrUrl, type PrRef, type PullRequestRef, } from './repo.ts';
|
|
29
29
|
export type { Actor, CheckConclusion, CheckRun, Comment, IssueRow, Label, MergeableState, MergeStateStatus, OwnerRepo, PullRequest, PrSearchHit, PullRequestState, Repository, RepositoryVisibility, Review, ReviewDecision, ReviewState, } from './types.ts';
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ export { classifyGhFailure } from "./failure.js";
|
|
|
23
23
|
export {} from "./doors.js";
|
|
24
24
|
export { runVerb, runVerbAsync } from "./run.js";
|
|
25
25
|
export { Gh, defaultRunnerFactory, } from "./sync.js";
|
|
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";
|
|
26
|
+
export { api, authStatus, createPr, editPr, editPrBody, fromTarget, graphql, createLabel, createReview, editLabel, installed, issueList, issueView, labelList, nodesAt, openPrsForBranch, pickPrForBranch, prBody, prComment, prSetDraft, issueCommentEdit, prDiff, prList, prMerge, prReviewThreads, prUpdateBranch, prView, raw, rawChecked, repoList, repoView, searchPrs, setIssueLabel, PR_LIST_FIELDS, PR_REF_FIELDS, PR_VIEW_FIELDS, REPO_FIELDS, SEARCH_PR_FIELDS, } from "./verbs.js";
|
|
27
27
|
export { anyCheckFailed, normalizeAuthorLogin, parsePullRequest } from "./parse.js";
|
|
28
28
|
export { ownerRepoSlug, parseOwnerRepo, parsePrRef, parsePrUrl, } from "./repo.js";
|
|
29
29
|
// command-seam's error and runner types appear in this package's signatures, so
|
package/dist/sync.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* `raw` and `rawChecked` run any `gh` call.
|
|
18
18
|
*/
|
|
19
19
|
import { spawnRunner } from '@osdlc/command-seam';
|
|
20
|
-
import {
|
|
20
|
+
import { softSync, triedSync } from "./doors.js";
|
|
21
21
|
import { runVerb } from "./run.js";
|
|
22
22
|
import * as v from "./verbs.js";
|
|
23
23
|
import { ownerRepoSlug, parseOwnerRepo, parsePrRef } from "./repo.js";
|
|
@@ -122,11 +122,11 @@ export class Gh {
|
|
|
122
122
|
* `.at(dir)` first.
|
|
123
123
|
*/
|
|
124
124
|
raw(argv, opts = {}) {
|
|
125
|
-
return this.
|
|
125
|
+
return this.exec(v.raw(argv), opts.timeoutMs);
|
|
126
126
|
}
|
|
127
127
|
/** Run any `gh` call. Throws the classified failure on a non-zero exit. Adds no `--repo`, as {@link Gh.raw}. */
|
|
128
128
|
rawChecked(argv, opts = {}) {
|
|
129
|
-
return
|
|
129
|
+
return this.exec(v.rawChecked(argv), opts.timeoutMs);
|
|
130
130
|
}
|
|
131
131
|
/** Run one verb from the table, checked or unchecked as the verb says. */
|
|
132
132
|
exec(verb, timeoutMs) {
|
package/dist/verbs.d.ts
CHANGED
|
@@ -7,22 +7,23 @@
|
|
|
7
7
|
* their own runner all use the same definitions and the same parsing.
|
|
8
8
|
*
|
|
9
9
|
* `checked` marks a verb the runner throws for on a non-zero exit, with
|
|
10
|
-
* stderr. That is every mutation,
|
|
11
|
-
* queries run unchecked, and `parse` turns a failure into
|
|
12
|
-
* what `soft` returns. The clients' methods that throw read
|
|
13
|
-
* `settle` (see `doors.ts`) instead. There a failure throws,
|
|
14
|
-
* verb declares `absent` or is a `probe`.
|
|
10
|
+
* stderr. That is every mutation, `prDiff`, which is a read, and
|
|
11
|
+
* `rawChecked`. Other queries run unchecked, and `parse` turns a failure into
|
|
12
|
+
* `null`, which is what `soft` returns. The clients' methods that throw read
|
|
13
|
+
* them through `settle` (see `doors.ts`) instead. There a failure throws,
|
|
14
|
+
* except where the verb declares `absent` or is a `probe`.
|
|
15
15
|
*/
|
|
16
16
|
import { type CommandResult } from '@osdlc/command-seam';
|
|
17
17
|
import type { IssueRow, Label, PrSearchHit, PullRequest, Repository } from './types.ts';
|
|
18
18
|
/** One `gh` invocation: what to run, and how to read what came back. */
|
|
19
19
|
export interface GhVerb<T> {
|
|
20
20
|
argv: string[];
|
|
21
|
-
/** True for every mutation and
|
|
21
|
+
/** True for every mutation, `prDiff` and `rawChecked`: throw on a non-zero exit instead of parsing. */
|
|
22
22
|
checked: boolean;
|
|
23
23
|
/**
|
|
24
24
|
* True when the call only reads and changes nothing on GitHub. Every query
|
|
25
|
-
* is read-only, and so is `prDiff`. No mutation is
|
|
25
|
+
* is read-only, and so is `prDiff`. No mutation is, and neither are `raw`
|
|
26
|
+
* and `rawChecked`, whose argv the library cannot judge. A caller that
|
|
26
27
|
* keeps an allowlist of safe calls can check this before running a verb.
|
|
27
28
|
*/
|
|
28
29
|
readOnly: boolean;
|
|
@@ -34,10 +35,10 @@ export interface GhVerb<T> {
|
|
|
34
35
|
*/
|
|
35
36
|
env?: Record<string, string> | undefined;
|
|
36
37
|
/**
|
|
37
|
-
* True for a
|
|
38
|
-
* `authStatus` and `
|
|
39
|
-
* plain method and from `try`; they have no soft form. Other reads
|
|
40
|
-
* from the plain method when gh exits non-zero.
|
|
38
|
+
* True for a call whose failure is part of its answer. `installed`,
|
|
39
|
+
* `authStatus`, `api` and `raw` return what `parse` makes of any result,
|
|
40
|
+
* from the plain method and from `try`; they have no soft form. Other reads
|
|
41
|
+
* throw from the plain method when gh exits non-zero.
|
|
41
42
|
*/
|
|
42
43
|
probe?: boolean | undefined;
|
|
43
44
|
/**
|
|
@@ -223,11 +224,34 @@ export interface ApiOptions {
|
|
|
223
224
|
*/
|
|
224
225
|
export declare function api(endpoint: string, opts?: ApiOptions, target?: GhTarget): GhVerb<ApiResponse>;
|
|
225
226
|
/**
|
|
226
|
-
* A GraphQL variable
|
|
227
|
+
* A GraphQL variable filled from the target's repository: its owner, or its
|
|
228
|
+
* name. Make one with {@link fromTarget}.
|
|
227
229
|
*
|
|
228
230
|
* @experimental
|
|
229
231
|
*/
|
|
230
|
-
export
|
|
232
|
+
export interface FromTarget {
|
|
233
|
+
readonly fromTarget: 'owner' | 'repo';
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* A {@link graphql} variable that holds the target repository's owner or
|
|
237
|
+
* name. With a target repo, the value comes from it. Without one, gh fills
|
|
238
|
+
* it from the clone's repository. A plain string is always sent as written,
|
|
239
|
+
* so a real value of `{owner}` stays `{owner}`.
|
|
240
|
+
*
|
|
241
|
+
* ```ts
|
|
242
|
+
* gh.graphql(query, { owner: fromTarget('owner'), name: fromTarget('repo') })
|
|
243
|
+
* ```
|
|
244
|
+
*
|
|
245
|
+
* @experimental
|
|
246
|
+
*/
|
|
247
|
+
export declare function fromTarget(part: 'owner' | 'repo'): FromTarget;
|
|
248
|
+
/**
|
|
249
|
+
* A GraphQL variable. gh sends a string with `-f`, as written, and the rest
|
|
250
|
+
* with `-F`. A {@link FromTarget} is filled from the target's repository.
|
|
251
|
+
*
|
|
252
|
+
* @experimental
|
|
253
|
+
*/
|
|
254
|
+
export type GraphqlVariable = string | number | boolean | null | FromTarget;
|
|
231
255
|
/**
|
|
232
256
|
* Options for {@link graphql}.
|
|
233
257
|
*
|
|
@@ -249,8 +273,8 @@ export interface GraphqlOptions {
|
|
|
249
273
|
* carries `errors` or lacks `data`. A partial answer counts as a failure. Read one
|
|
250
274
|
* connection across the pages with {@link nodesAt}.
|
|
251
275
|
*
|
|
252
|
-
* A
|
|
253
|
-
*
|
|
276
|
+
* A {@link fromTarget} variable is filled from the target's repo, or by gh
|
|
277
|
+
* from the clone. A plain string is sent as written. A document holding any mutation or
|
|
254
278
|
* subscription throws `RangeError`, as does a variable named `query` or
|
|
255
279
|
* `operationName`, which gh would send as the request's own fields. This is a
|
|
256
280
|
* read, and changes go through `raw`.
|
|
@@ -484,6 +508,21 @@ export interface CreateReviewOptions {
|
|
|
484
508
|
* @experimental
|
|
485
509
|
*/
|
|
486
510
|
export declare function createReview(number: number, opts: CreateReviewOptions, target?: GhTarget): GhVerb<string>;
|
|
511
|
+
/**
|
|
512
|
+
* Any `gh` call, as a verb whose value is the `CommandResult`, whatever the
|
|
513
|
+
* exit code: `Gh.raw` as data. It adds no `--repo` and no host, so put them
|
|
514
|
+
* in `argv`. It is a `probe`, so `runVerb` returns a failed or cut-short
|
|
515
|
+
* result rather than throwing, and it is not `readOnly`, since the library
|
|
516
|
+
* cannot tell what `argv` does.
|
|
517
|
+
*/
|
|
518
|
+
export declare function raw(argv: readonly string[]): GhVerb<CommandResult>;
|
|
519
|
+
/**
|
|
520
|
+
* {@link raw}, checked: `Gh.rawChecked` as data. `runVerb` returns the
|
|
521
|
+
* `CommandResult` when gh exits 0 with its whole output, and otherwise throws
|
|
522
|
+
* a `FailureError` carrying the classified `GhFailure`. So a tool that runs
|
|
523
|
+
* one call the verb table lacks needs no `Gh` for it.
|
|
524
|
+
*/
|
|
525
|
+
export declare function rawChecked(argv: readonly string[]): GhVerb<CommandResult>;
|
|
487
526
|
/**
|
|
488
527
|
* The first row whose `headRefName` exactly equals `branch`, or null.
|
|
489
528
|
*
|
package/dist/verbs.js
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* their own runner all use the same definitions and the same parsing.
|
|
8
8
|
*
|
|
9
9
|
* `checked` marks a verb the runner throws for on a non-zero exit, with
|
|
10
|
-
* stderr. That is every mutation,
|
|
11
|
-
* queries run unchecked, and `parse` turns a failure into
|
|
12
|
-
* what `soft` returns. The clients' methods that throw read
|
|
13
|
-
* `settle` (see `doors.ts`) instead. There a failure throws,
|
|
14
|
-
* verb declares `absent` or is a `probe`.
|
|
10
|
+
* stderr. That is every mutation, `prDiff`, which is a read, and
|
|
11
|
+
* `rawChecked`. Other queries run unchecked, and `parse` turns a failure into
|
|
12
|
+
* `null`, which is what `soft` returns. The clients' methods that throw read
|
|
13
|
+
* them through `settle` (see `doors.ts`) instead. There a failure throws,
|
|
14
|
+
* except where the verb declares `absent` or is a `probe`.
|
|
15
15
|
*/
|
|
16
16
|
import { notAnOption, stderrOrError } from '@osdlc/command-seam';
|
|
17
17
|
import { parseLabels, parsePrSearchHit, parsePullRequest, parseRepository } from "./parse.js";
|
|
@@ -410,6 +410,24 @@ function flattenPages(body) {
|
|
|
410
410
|
return body;
|
|
411
411
|
return body.flat();
|
|
412
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* A {@link graphql} variable that holds the target repository's owner or
|
|
415
|
+
* name. With a target repo, the value comes from it. Without one, gh fills
|
|
416
|
+
* it from the clone's repository. A plain string is always sent as written,
|
|
417
|
+
* so a real value of `{owner}` stays `{owner}`.
|
|
418
|
+
*
|
|
419
|
+
* ```ts
|
|
420
|
+
* gh.graphql(query, { owner: fromTarget('owner'), name: fromTarget('repo') })
|
|
421
|
+
* ```
|
|
422
|
+
*
|
|
423
|
+
* @experimental
|
|
424
|
+
*/
|
|
425
|
+
export function fromTarget(part) {
|
|
426
|
+
if (part !== 'owner' && part !== 'repo') {
|
|
427
|
+
throw new RangeError(`fromTarget: expected 'owner' or 'repo', got ${JSON.stringify(part)}`);
|
|
428
|
+
}
|
|
429
|
+
return Object.freeze({ fromTarget: part });
|
|
430
|
+
}
|
|
413
431
|
/**
|
|
414
432
|
* True when any operation in a GraphQL document is a `mutation` or a
|
|
415
433
|
* `subscription`. Strings and comments are dropped first, and only the words
|
|
@@ -439,8 +457,8 @@ function writesOrStreams(document) {
|
|
|
439
457
|
* carries `errors` or lacks `data`. A partial answer counts as a failure. Read one
|
|
440
458
|
* connection across the pages with {@link nodesAt}.
|
|
441
459
|
*
|
|
442
|
-
* A
|
|
443
|
-
*
|
|
460
|
+
* A {@link fromTarget} variable is filled from the target's repo, or by gh
|
|
461
|
+
* from the clone. A plain string is sent as written. A document holding any mutation or
|
|
444
462
|
* subscription throws `RangeError`, as does a variable named `query` or
|
|
445
463
|
* `operationName`, which gh would send as the request's own fields. This is a
|
|
446
464
|
* read, and changes go through `raw`.
|
|
@@ -467,14 +485,20 @@ export function graphql(query, variables = {}, opts = {}, target) {
|
|
|
467
485
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key) || key === 'query' || key === 'operationName') {
|
|
468
486
|
throw new RangeError(`graphql: bad variable name ${JSON.stringify(key)}`);
|
|
469
487
|
}
|
|
470
|
-
if (typeof value === '
|
|
471
|
-
const
|
|
488
|
+
if (typeof value === 'object' && value !== null) {
|
|
489
|
+
const part = value.fromTarget;
|
|
490
|
+
if (part !== 'owner' && part !== 'repo') {
|
|
491
|
+
throw new RangeError(`graphql: variable ${key} is not a fromTarget marker`);
|
|
492
|
+
}
|
|
493
|
+
const filled = part === 'owner' ? owner : name;
|
|
494
|
+
// `-F` lets gh fill the placeholder from the clone; `-f` never fills.
|
|
472
495
|
if (filled !== undefined)
|
|
473
496
|
argv.push('-f', `${key}=${filled}`);
|
|
474
|
-
else if (value === '{owner}' || value === '{repo}')
|
|
475
|
-
argv.push('-F', `${key}=${value}`);
|
|
476
497
|
else
|
|
477
|
-
argv.push('-
|
|
498
|
+
argv.push('-F', `${key}={${part}}`);
|
|
499
|
+
}
|
|
500
|
+
else if (typeof value === 'string') {
|
|
501
|
+
argv.push('-f', `${key}=${value}`);
|
|
478
502
|
}
|
|
479
503
|
else {
|
|
480
504
|
argv.push('-F', `${key}=${value === null ? 'null' : String(value)}`);
|
|
@@ -1074,6 +1098,26 @@ export function createReview(number, opts, target) {
|
|
|
1074
1098
|
},
|
|
1075
1099
|
};
|
|
1076
1100
|
}
|
|
1101
|
+
// ── raw calls ───────────────────────────────────────────────────────────────
|
|
1102
|
+
/**
|
|
1103
|
+
* Any `gh` call, as a verb whose value is the `CommandResult`, whatever the
|
|
1104
|
+
* exit code: `Gh.raw` as data. It adds no `--repo` and no host, so put them
|
|
1105
|
+
* in `argv`. It is a `probe`, so `runVerb` returns a failed or cut-short
|
|
1106
|
+
* result rather than throwing, and it is not `readOnly`, since the library
|
|
1107
|
+
* cannot tell what `argv` does.
|
|
1108
|
+
*/
|
|
1109
|
+
export function raw(argv) {
|
|
1110
|
+
return { argv: [...argv], checked: false, readOnly: false, probe: true, parse: (r) => r };
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* {@link raw}, checked: `Gh.rawChecked` as data. `runVerb` returns the
|
|
1114
|
+
* `CommandResult` when gh exits 0 with its whole output, and otherwise throws
|
|
1115
|
+
* a `FailureError` carrying the classified `GhFailure`. So a tool that runs
|
|
1116
|
+
* one call the verb table lacks needs no `Gh` for it.
|
|
1117
|
+
*/
|
|
1118
|
+
export function rawChecked(argv) {
|
|
1119
|
+
return { argv: [...argv], checked: true, readOnly: false, parse: (r) => r };
|
|
1120
|
+
}
|
|
1077
1121
|
// ── helpers over the parsed rows ────────────────────────────────────────────
|
|
1078
1122
|
/**
|
|
1079
1123
|
* The first row whose `headRefName` exactly equals `branch`, or null.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osdlc/typed-gh",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "A typed GitHub client for TypeScript over the gh CLI. A total PullRequest/Review/CheckRun model, pure argv builders and parsers, and a tri-modal client — queries return parsed values, mutations throw, raw() is the escape hatch. Uses gh's own credentials; reads no token.",
|
|
5
5
|
"license": "MIT OR Apache-2.0",
|
|
6
6
|
"author": "sksizer",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"@vitest/coverage-v8": "^5.0.5",
|
|
57
57
|
"oxlint": "^1.65.0",
|
|
58
58
|
"prettier": "3.9.6",
|
|
59
|
+
"rolldown": "^1.2.14",
|
|
59
60
|
"typescript": "~6.0.3",
|
|
60
61
|
"vitest": "^5.0.5",
|
|
61
62
|
"@osdlc/prettier-config": "^0.3.1",
|