@osdlc/typed-gh 0.6.0 → 0.7.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 +37 -1
- package/CONTRIBUTING.md +4 -3
- package/README.md +94 -35
- package/dist/async.d.ts +37 -23
- package/dist/async.js +48 -27
- package/dist/doors.d.ts +82 -0
- package/dist/doors.js +183 -0
- package/dist/failure.d.ts +59 -0
- package/dist/failure.js +93 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +7 -2
- package/dist/parse.d.ts +0 -1
- package/dist/repo.d.ts +0 -1
- package/dist/sync.d.ts +53 -29
- package/dist/sync.js +64 -33
- package/dist/types.d.ts +0 -1
- package/dist/verbs.d.ts +19 -4
- package/dist/verbs.js +23 -4
- package/package.json +13 -17
- package/async.ts +0 -379
- package/dist/async.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/parse.d.ts.map +0 -1
- package/dist/repo.d.ts.map +0 -1
- package/dist/sync.d.ts.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/verbs.d.ts.map +0 -1
- package/index.ts +0 -120
- package/parse.ts +0 -302
- package/repo.ts +0 -133
- package/sync.ts +0 -438
- package/types.ts +0 -226
- package/verbs.ts +0 -1324
package/dist/sync.js
CHANGED
|
@@ -7,11 +7,15 @@
|
|
|
7
7
|
* REST — the credential already exists in the user's keychain, and a library
|
|
8
8
|
* that reaches for `GITHUB_TOKEN` is a library that can leak one.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
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.
|
|
13
16
|
*/
|
|
14
|
-
import {
|
|
17
|
+
import { resolveRunner, spawnRunner, } from '@osdlc/command-seam';
|
|
18
|
+
import { runCheckedGh, settle, softSync, triedSync } from "./doors.js";
|
|
15
19
|
import * as v from "./verbs.js";
|
|
16
20
|
import { ownerRepoSlug, parseOwnerRepo, parsePrRef } from "./repo.js";
|
|
17
21
|
/** Default factory: real, spawnSync-backed runners. */
|
|
@@ -38,6 +42,8 @@ export class Gh {
|
|
|
38
42
|
hostname;
|
|
39
43
|
target;
|
|
40
44
|
runner;
|
|
45
|
+
tried;
|
|
46
|
+
softened;
|
|
41
47
|
constructor(cwd, opts = {}) {
|
|
42
48
|
v.checkTarget(opts);
|
|
43
49
|
this.cwd = cwd;
|
|
@@ -54,14 +60,35 @@ export class Gh {
|
|
|
54
60
|
withRepo(repo) {
|
|
55
61
|
return new Gh(this.cwd, { runner: this.runner, repo, hostname: this.hostname });
|
|
56
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* The whole surface again, returning a `Result<T, GhFailure>` instead of
|
|
65
|
+
* throwing: `gh.try.prList()` is `{ ok: true, value } | { ok: false, error }`.
|
|
66
|
+
* A query for one thing that finds nothing is `ok: true` with `null`. See
|
|
67
|
+
* `./doors.ts`.
|
|
68
|
+
*
|
|
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
|
+
*/
|
|
72
|
+
get try() {
|
|
73
|
+
return (this.tried ??= triedSync(this));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 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
|
|
79
|
+
* `try` where the difference matters.
|
|
80
|
+
*/
|
|
81
|
+
get soft() {
|
|
82
|
+
return (this.softened ??= softSync(this));
|
|
83
|
+
}
|
|
57
84
|
// ── escape hatches ────────────────────────────────────────────────────────
|
|
58
85
|
/** Unchecked passthrough for verbs not yet lifted into the API. */
|
|
59
86
|
raw(argv, opts = {}) {
|
|
60
87
|
return this.runner.run(argv, { cwd: this.cwd, ...opts });
|
|
61
88
|
}
|
|
62
|
-
/** Checked passthrough — throws
|
|
89
|
+
/** Checked passthrough — throws the classified failure on a non-zero exit. */
|
|
63
90
|
rawChecked(argv, opts = {}) {
|
|
64
|
-
return
|
|
91
|
+
return runCheckedGh(this.runner, argv, { cwd: this.cwd, ...opts });
|
|
65
92
|
}
|
|
66
93
|
/** Run one verb from the table, honouring its checked/unchecked contract. */
|
|
67
94
|
exec(verb, timeoutMs) {
|
|
@@ -73,18 +100,22 @@ export class Gh {
|
|
|
73
100
|
if (timeoutMs !== undefined)
|
|
74
101
|
opts.timeoutMs = timeoutMs;
|
|
75
102
|
const result = verb.checked
|
|
76
|
-
?
|
|
103
|
+
? runCheckedGh(this.runner, verb.argv, opts)
|
|
77
104
|
: this.runner.run(verb.argv, opts);
|
|
78
|
-
return verb.
|
|
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. */
|
|
108
|
+
read(verb, timeoutMs) {
|
|
109
|
+
return this.exec(verb, timeoutMs);
|
|
79
110
|
}
|
|
80
111
|
// ── queries ───────────────────────────────────────────────────────────────
|
|
81
|
-
/** Pull requests matching `opts
|
|
112
|
+
/** Pull requests matching `opts`. Throws when gh fails; `soft.prList` gives null instead. */
|
|
82
113
|
prList(opts = {}) {
|
|
83
|
-
return this.
|
|
114
|
+
return this.read(v.prList(opts, this.target), opts.timeoutMs);
|
|
84
115
|
}
|
|
85
116
|
/**
|
|
86
|
-
* One PR by number, branch or URL, with the heavy fields; null when
|
|
87
|
-
*
|
|
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.
|
|
88
119
|
*/
|
|
89
120
|
prView(ref, opts = {}) {
|
|
90
121
|
return this.exec(v.prView(ref, opts.fields ?? v.PR_VIEW_FIELDS, this.target), opts.timeoutMs);
|
|
@@ -128,7 +159,7 @@ export class Gh {
|
|
|
128
159
|
limit: opts.limit ?? 5,
|
|
129
160
|
fields: opts.fields ?? v.PR_REF_FIELDS,
|
|
130
161
|
});
|
|
131
|
-
return v.pickPrForBranch(rows
|
|
162
|
+
return v.pickPrForBranch(rows.rows, branch);
|
|
132
163
|
}
|
|
133
164
|
/**
|
|
134
165
|
* {@link prView}, re-asked until GitHub settles the merge state.
|
|
@@ -155,49 +186,49 @@ export class Gh {
|
|
|
155
186
|
}
|
|
156
187
|
return last;
|
|
157
188
|
}
|
|
158
|
-
/** A PR's body text
|
|
189
|
+
/** A PR's body text. Throws when gh fails. */
|
|
159
190
|
prBody(number, opts = {}) {
|
|
160
|
-
return this.
|
|
191
|
+
return this.read(v.prBody(number, this.target), opts.timeoutMs);
|
|
161
192
|
}
|
|
162
193
|
/**
|
|
163
|
-
* A REST GET through `gh api`. Never throws
|
|
164
|
-
* returned {@link ApiResponse}.
|
|
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}.
|
|
165
196
|
*/
|
|
166
197
|
api(endpoint, opts = {}) {
|
|
167
198
|
return this.exec(v.api(endpoint, opts, this.target), opts.timeoutMs);
|
|
168
199
|
}
|
|
169
200
|
/**
|
|
170
|
-
* A GraphQL query; each page's `data
|
|
171
|
-
*
|
|
201
|
+
* A GraphQL query; each page's `data`. Throws on a failed or partial result;
|
|
202
|
+
* `soft.graphql` gives null. See the `graphql` verb.
|
|
172
203
|
*
|
|
173
204
|
* @experimental
|
|
174
205
|
*/
|
|
175
206
|
graphql(query, variables = {}, opts = {}) {
|
|
176
|
-
return this.
|
|
207
|
+
return this.read(v.graphql(query, variables, opts, this.target), opts.timeoutMs);
|
|
177
208
|
}
|
|
178
|
-
/** Every label on the repository (up to `opts.limit`, default 1000)
|
|
209
|
+
/** Every label on the repository (up to `opts.limit`, default 1000). Throws when gh fails. */
|
|
179
210
|
labelList(opts = {}) {
|
|
180
|
-
return this.
|
|
211
|
+
return this.read(v.labelList(opts, this.target), opts.timeoutMs);
|
|
181
212
|
}
|
|
182
|
-
/** Issues matching `opts` (open by default, up to 200)
|
|
213
|
+
/** Issues matching `opts` (open by default, up to 200). Throws when gh fails. */
|
|
183
214
|
issueList(opts = {}) {
|
|
184
|
-
return this.
|
|
215
|
+
return this.read(v.issueList(opts, this.target), opts.timeoutMs);
|
|
185
216
|
}
|
|
186
|
-
/** One issue with its labels
|
|
217
|
+
/** One issue with its labels; null when there is no such issue. Throws when gh fails otherwise. */
|
|
187
218
|
issueView(number, opts = {}) {
|
|
188
219
|
return this.exec(v.issueView(number, this.target), opts.timeoutMs);
|
|
189
220
|
}
|
|
190
|
-
/** An owner's repositories (up to `opts.limit`, default 100)
|
|
221
|
+
/** An owner's repositories (up to `opts.limit`, default 100). Throws when gh fails. */
|
|
191
222
|
repoList(owner, opts = {}) {
|
|
192
|
-
return this.
|
|
223
|
+
return this.read(v.repoList(owner, opts, this.target), opts.timeoutMs);
|
|
193
224
|
}
|
|
194
|
-
/** One repository: `repo`, else the client's repo, else the clone at `cwd`. Null when
|
|
225
|
+
/** One repository: `repo`, else the client's repo, else the clone at `cwd`. Null when there is no such repository. */
|
|
195
226
|
repoView(repo, opts = {}) {
|
|
196
227
|
return this.exec(v.repoView(repo, opts.fields ?? v.REPO_FIELDS, this.target), opts.timeoutMs);
|
|
197
228
|
}
|
|
198
|
-
/** Pull requests across repositories matching a search query
|
|
229
|
+
/** Pull requests across repositories matching a search query. Throws when gh fails. */
|
|
199
230
|
searchPrs(query, opts = {}) {
|
|
200
|
-
return this.
|
|
231
|
+
return this.read(v.searchPrs(query, opts, this.target), opts.timeoutMs);
|
|
201
232
|
}
|
|
202
233
|
/** True iff the `gh` binary is on PATH and runs. */
|
|
203
234
|
installed() {
|
|
@@ -242,7 +273,7 @@ export class Gh {
|
|
|
242
273
|
editPr(number, opts) {
|
|
243
274
|
this.exec(v.editPr(number, opts, this.target));
|
|
244
275
|
}
|
|
245
|
-
/** The PR's unified diff; throws
|
|
276
|
+
/** The PR's unified diff; throws the classified failure when gh cannot produce it. */
|
|
246
277
|
prDiff(number) {
|
|
247
278
|
return this.exec(v.prDiff(number, this.target));
|
|
248
279
|
}
|
|
@@ -282,9 +313,9 @@ export class Gh {
|
|
|
282
313
|
prMerge(number, opts) {
|
|
283
314
|
this.exec(v.prMerge(number, opts, this.target));
|
|
284
315
|
}
|
|
285
|
-
/** A PR's review threads
|
|
316
|
+
/** A PR's review threads. Throws when they could not be read completely. */
|
|
286
317
|
prReviewThreads(number) {
|
|
287
|
-
return this.
|
|
318
|
+
return this.read(v.prReviewThreads(number, this.target));
|
|
288
319
|
}
|
|
289
320
|
/** Create a label (or force it to `opts`'s color/description if it already exists). */
|
|
290
321
|
createLabel(opts) {
|
package/dist/types.d.ts
CHANGED
package/dist/verbs.d.ts
CHANGED
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
* asynchronous fan-out drive the same definitions without either duplicating
|
|
8
8
|
* the other's parsing.
|
|
9
9
|
*
|
|
10
|
-
* `checked` marks a verb
|
|
11
|
-
* and `prDiff`, which is a read. Other queries are
|
|
12
|
-
* into
|
|
10
|
+
* `checked` marks a verb the runner throws for on a non-zero exit, with
|
|
11
|
+
* stderr: every mutation, and `prDiff`, which is a read. Other queries are run
|
|
12
|
+
* unchecked and `parse` folds a failure into `null`, which is the verb's
|
|
13
|
+
* *soft* reading. The clients' plain door reads them through `settle` (see
|
|
14
|
+
* `doors.ts`) instead: a failure throws, except where the verb declares
|
|
15
|
+
* `absent` or is a `probe`.
|
|
13
16
|
*/
|
|
14
17
|
import { type CommandResult } from '@osdlc/command-seam';
|
|
15
18
|
import type { IssueRow, Label, PrSearchHit, PullRequest, Repository } from './types.ts';
|
|
@@ -31,6 +34,19 @@ export interface GhVerb<T> {
|
|
|
31
34
|
* on `gh search` and `gh repo list`.
|
|
32
35
|
*/
|
|
33
36
|
env?: Record<string, string> | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* True for a read whose failure is part of its answer: `installed`,
|
|
39
|
+
* `authStatus` and `api` return what `parse` makes of any result, in every
|
|
40
|
+
* door. Other reads fail the plain door when gh exits non-zero.
|
|
41
|
+
*/
|
|
42
|
+
probe?: boolean | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* For a read of one thing: whether a non-zero result means GitHub has no such
|
|
45
|
+
* thing (`prView`, `issueView`, `repoView`). The plain door then returns what
|
|
46
|
+
* `parse` makes of it, `null`, because absence is an answer. Other non-zero
|
|
47
|
+
* results fail the call.
|
|
48
|
+
*/
|
|
49
|
+
absent?: ((result: CommandResult) => boolean) | undefined;
|
|
34
50
|
parse(result: CommandResult): T;
|
|
35
51
|
}
|
|
36
52
|
/**
|
|
@@ -461,4 +477,3 @@ export declare function branchPrFields(fields: readonly string[]): string[];
|
|
|
461
477
|
* slow, so re-ask a few times before believing it.
|
|
462
478
|
*/
|
|
463
479
|
export declare function needsMergeStateRetry(pr: PullRequest): boolean;
|
|
464
|
-
//# sourceMappingURL=verbs.d.ts.map
|
package/dist/verbs.js
CHANGED
|
@@ -7,13 +7,21 @@
|
|
|
7
7
|
* asynchronous fan-out drive the same definitions without either duplicating
|
|
8
8
|
* the other's parsing.
|
|
9
9
|
*
|
|
10
|
-
* `checked` marks a verb
|
|
11
|
-
* and `prDiff`, which is a read. Other queries are
|
|
12
|
-
* into
|
|
10
|
+
* `checked` marks a verb the runner throws for on a non-zero exit, with
|
|
11
|
+
* stderr: every mutation, and `prDiff`, which is a read. Other queries are run
|
|
12
|
+
* unchecked and `parse` folds a failure into `null`, which is the verb's
|
|
13
|
+
* *soft* reading. The clients' plain door reads them through `settle` (see
|
|
14
|
+
* `doors.ts`) instead: a failure throws, except where the verb declares
|
|
15
|
+
* `absent` or is a `probe`.
|
|
13
16
|
*/
|
|
14
17
|
import { stderrOrError } from '@osdlc/command-seam';
|
|
15
18
|
import { parseLabels, parsePrSearchHit, parsePullRequest, parseRepository } from "./parse.js";
|
|
19
|
+
import { isAbsent } from "./failure.js";
|
|
16
20
|
import { isRepoSlug, parsePrUrl } from "./repo.js";
|
|
21
|
+
/** Whether a failed run says GitHub has no such `thing`: read from the same text the classifier reads. */
|
|
22
|
+
function noSuch(thing) {
|
|
23
|
+
return (r) => isAbsent(thing, `${r.stderr}\n${r.stdout}`);
|
|
24
|
+
}
|
|
17
25
|
const HOSTNAME = /^[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?(?::\d+)?$/;
|
|
18
26
|
/**
|
|
19
27
|
* Throw `RangeError` unless `target.repo` is `owner/name` and
|
|
@@ -300,6 +308,7 @@ export function prView(ref, fields = PR_VIEW_FIELDS, target) {
|
|
|
300
308
|
],
|
|
301
309
|
checked: false,
|
|
302
310
|
readOnly: true,
|
|
311
|
+
absent: noSuch('pr'),
|
|
303
312
|
parse: oneOrNull,
|
|
304
313
|
};
|
|
305
314
|
}
|
|
@@ -354,6 +363,7 @@ export function api(endpoint, opts = {}, target) {
|
|
|
354
363
|
argv,
|
|
355
364
|
checked: false,
|
|
356
365
|
readOnly: true,
|
|
366
|
+
probe: true,
|
|
357
367
|
parse(r) {
|
|
358
368
|
const response = parseApi(r, withHeaders);
|
|
359
369
|
return paginate ? { ...response, body: flattenPages(response.body) } : response;
|
|
@@ -527,7 +537,13 @@ function parseApi(r, withHeaders) {
|
|
|
527
537
|
}
|
|
528
538
|
/** `gh --version` — the install probe. True when `gh` runs. */
|
|
529
539
|
export function installed() {
|
|
530
|
-
return {
|
|
540
|
+
return {
|
|
541
|
+
argv: ['--version'],
|
|
542
|
+
checked: false,
|
|
543
|
+
readOnly: true,
|
|
544
|
+
probe: true,
|
|
545
|
+
parse: (r) => r.exitCode === 0,
|
|
546
|
+
};
|
|
531
547
|
}
|
|
532
548
|
/** `gh auth status [--hostname <host>]` — the credential probe, for one host when the target names it. */
|
|
533
549
|
export function authStatus(target) {
|
|
@@ -535,6 +551,7 @@ export function authStatus(target) {
|
|
|
535
551
|
argv: ['auth', 'status', ...hostArgs(target)],
|
|
536
552
|
checked: false,
|
|
537
553
|
readOnly: true,
|
|
554
|
+
probe: true,
|
|
538
555
|
parse: (r) => ({ ok: r.exitCode === 0, detail: stderrOrError(r) || r.stdout.trim() }),
|
|
539
556
|
};
|
|
540
557
|
}
|
|
@@ -576,6 +593,7 @@ export function issueView(number, target) {
|
|
|
576
593
|
argv: ['issue', 'view', String(number), ...repoArgs(target), '--json', ISSUE_FIELDS],
|
|
577
594
|
checked: false,
|
|
578
595
|
readOnly: true,
|
|
596
|
+
absent: noSuch('issue'),
|
|
579
597
|
parse: oneIssueOrNull,
|
|
580
598
|
};
|
|
581
599
|
}
|
|
@@ -660,6 +678,7 @@ export function repoView(repo, fields = REPO_FIELDS, target) {
|
|
|
660
678
|
argv,
|
|
661
679
|
checked: false,
|
|
662
680
|
readOnly: true,
|
|
681
|
+
absent: noSuch('repo'),
|
|
663
682
|
parse(r) {
|
|
664
683
|
if (r.exitCode !== 0)
|
|
665
684
|
return null;
|
package/package.json
CHANGED
|
@@ -1,26 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@osdlc/typed-gh",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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
|
+
"author": "sksizer",
|
|
6
7
|
"type": "module",
|
|
7
8
|
"sideEffects": false,
|
|
8
9
|
"exports": {
|
|
9
10
|
".": {
|
|
10
|
-
"bun": "./index.ts",
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"files": [
|
|
16
16
|
"dist/",
|
|
17
|
-
"index.ts",
|
|
18
|
-
"sync.ts",
|
|
19
|
-
"async.ts",
|
|
20
|
-
"verbs.ts",
|
|
21
|
-
"parse.ts",
|
|
22
|
-
"repo.ts",
|
|
23
|
-
"types.ts",
|
|
24
17
|
"README.md",
|
|
25
18
|
"CHANGELOG.md",
|
|
26
19
|
"SECURITY.md",
|
|
@@ -29,11 +22,12 @@
|
|
|
29
22
|
"LICENSE-APACHE"
|
|
30
23
|
],
|
|
31
24
|
"dependencies": {
|
|
32
|
-
"@osdlc/
|
|
33
|
-
"@osdlc/
|
|
25
|
+
"@osdlc/command-seam": "^0.9.0",
|
|
26
|
+
"@osdlc/typed-git": "^0.6.0",
|
|
27
|
+
"@osdlc/result": "^0.1.0"
|
|
34
28
|
},
|
|
35
29
|
"engines": {
|
|
36
|
-
"node": ">=
|
|
30
|
+
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
|
|
37
31
|
},
|
|
38
32
|
"publishConfig": {
|
|
39
33
|
"access": "public"
|
|
@@ -54,22 +48,24 @@
|
|
|
54
48
|
"dependency-injection"
|
|
55
49
|
],
|
|
56
50
|
"devDependencies": {
|
|
57
|
-
"@types/bun": "^1.1.14",
|
|
58
51
|
"@types/node": "^26.1.0",
|
|
52
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
59
53
|
"oxlint": "^1.65.0",
|
|
60
54
|
"prettier": "3.9.6",
|
|
61
55
|
"typescript": "~6.0.3",
|
|
62
|
-
"
|
|
63
|
-
"@osdlc/
|
|
56
|
+
"vitest": "^5.0.5",
|
|
57
|
+
"@osdlc/prettier-config": "^0.3.1",
|
|
58
|
+
"@osdlc/tsconfig": "^0.4.1"
|
|
64
59
|
},
|
|
65
60
|
"scripts": {
|
|
66
61
|
"build": "tsc -p tsconfig.build.json",
|
|
67
62
|
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
68
|
-
"test": "
|
|
63
|
+
"test": "vitest run",
|
|
69
64
|
"smoke": "node tests/smoke.mjs",
|
|
70
65
|
"format": "prettier --write .",
|
|
71
66
|
"format:check": "prettier --check .",
|
|
72
67
|
"lint": "oxlint .",
|
|
73
|
-
"typecheck": "tsc --noEmit && tsc -p tsconfig.build.json --noEmit"
|
|
68
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.build.json --noEmit",
|
|
69
|
+
"coverage": "vitest run --coverage"
|
|
74
70
|
}
|
|
75
71
|
}
|