@outfitter/tooling 0.2.4 → 0.3.3
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/README.md +69 -1
- package/biome.json +1 -1
- package/dist/cli/index.js +163 -24
- package/dist/index.d.ts +79 -4
- package/dist/index.js +17 -6
- package/dist/shared/chunk-cmde0fwx.js +421 -0
- package/package.json +14 -7
- package/registry/registry.json +6 -6
- package/dist/cli/check-boundary-invocations.d.ts +0 -34
- package/dist/cli/check-boundary-invocations.js +0 -14
- package/dist/cli/check-bunup-registry.d.ts +0 -36
- package/dist/cli/check-bunup-registry.js +0 -12
- package/dist/cli/check-changeset.d.ts +0 -64
- package/dist/cli/check-changeset.js +0 -14
- package/dist/cli/check-clean-tree.d.ts +0 -36
- package/dist/cli/check-clean-tree.js +0 -14
- package/dist/cli/check-exports.d.ts +0 -2
- package/dist/cli/check-exports.js +0 -14
- package/dist/cli/check-readme-imports.d.ts +0 -61
- package/dist/cli/check-readme-imports.js +0 -198
- package/dist/cli/check.d.ts +0 -19
- package/dist/cli/check.js +0 -10
- package/dist/cli/fix.d.ts +0 -19
- package/dist/cli/fix.js +0 -10
- package/dist/cli/init.d.ts +0 -31
- package/dist/cli/init.js +0 -12
- package/dist/cli/pre-push.d.ts +0 -41
- package/dist/cli/pre-push.js +0 -20
- package/dist/cli/upgrade-bun.d.ts +0 -8
- package/dist/cli/upgrade-bun.js +0 -8
- package/dist/registry/build.d.ts +0 -6
- package/dist/registry/build.js +0 -147
- package/dist/registry/index.d.ts +0 -3
- package/dist/registry/index.js +0 -13
- package/dist/registry/schema.d.ts +0 -2
- package/dist/registry/schema.js +0 -12
- package/dist/shared/@outfitter/tooling-0x5q15ec.js +0 -21
- package/dist/shared/@outfitter/tooling-1y8w5ahg.js +0 -70
- package/dist/shared/@outfitter/tooling-3w8vr2w3.js +0 -94
- package/dist/shared/@outfitter/tooling-8sd32ts6.js +0 -277
- package/dist/shared/@outfitter/tooling-9errkcvk.js +0 -21
- package/dist/shared/@outfitter/tooling-9vs606gq.d.ts +0 -3
- package/dist/shared/@outfitter/tooling-9yzd08v1.js +0 -146
- package/dist/shared/@outfitter/tooling-ctmgnap5.js +0 -19
- package/dist/shared/@outfitter/tooling-dvwh9qve.js +0 -4
- package/dist/shared/@outfitter/tooling-enjcenja.js +0 -229
- package/dist/shared/@outfitter/tooling-g83d0kjv.js +0 -23
- package/dist/shared/@outfitter/tooling-kcvs6mys.js +0 -1
- package/dist/shared/@outfitter/tooling-mxwc1n8w.js +0 -68
- package/dist/shared/@outfitter/tooling-r9976n43.js +0 -100
- package/dist/shared/@outfitter/tooling-sjm8nebx.d.ts +0 -109
- package/dist/shared/@outfitter/tooling-t17gnh9b.js +0 -78
- package/dist/shared/@outfitter/tooling-wesswf21.d.ts +0 -59
- package/dist/shared/chunk-8aenrm6f.js +0 -18
- package/dist/version.d.ts +0 -2
- package/dist/version.js +0 -8
package/README.md
CHANGED
|
@@ -98,6 +98,75 @@ bunx @outfitter/tooling check-boundary-invocations
|
|
|
98
98
|
When this fails, replace direct source execution with canonical command surfaces
|
|
99
99
|
(`outfitter repo ...` in monorepo scripts, or package bins for standalone use).
|
|
100
100
|
|
|
101
|
+
### `tooling check-bunup-registry`
|
|
102
|
+
|
|
103
|
+
Validate that packages using `bunup --filter` are registered in `bunup.config.ts`.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
bunx @outfitter/tooling check-bunup-registry
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### `tooling check-changeset`
|
|
110
|
+
|
|
111
|
+
Validate that PRs touching package source include a changeset.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
bunx @outfitter/tooling check-changeset
|
|
115
|
+
|
|
116
|
+
# Skip the check (e.g. for non-package changes)
|
|
117
|
+
bunx @outfitter/tooling check-changeset --skip
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `tooling check-exports`
|
|
121
|
+
|
|
122
|
+
Validate that `package.json` exports match source entry points.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
bunx @outfitter/tooling check-exports
|
|
126
|
+
|
|
127
|
+
# Machine-readable output
|
|
128
|
+
bunx @outfitter/tooling check-exports --json
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `tooling check-tsdoc`
|
|
132
|
+
|
|
133
|
+
Check TSDoc coverage on exported declarations.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
bunx @outfitter/tooling check-tsdoc
|
|
137
|
+
|
|
138
|
+
# Check specific packages
|
|
139
|
+
bunx @outfitter/tooling check-tsdoc packages/cli packages/contracts
|
|
140
|
+
|
|
141
|
+
# Strict mode with coverage threshold
|
|
142
|
+
bunx @outfitter/tooling check-tsdoc --strict --min-coverage 80
|
|
143
|
+
|
|
144
|
+
# JSON output
|
|
145
|
+
bunx @outfitter/tooling check-tsdoc --json
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### `tooling check-clean-tree`
|
|
149
|
+
|
|
150
|
+
Assert the working tree is clean (no modified or untracked files).
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
bunx @outfitter/tooling check-clean-tree
|
|
154
|
+
|
|
155
|
+
# Check specific paths only
|
|
156
|
+
bunx @outfitter/tooling check-clean-tree --paths packages/cli packages/contracts
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `tooling check-readme-imports`
|
|
160
|
+
|
|
161
|
+
Validate that README import examples match package exports.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
bunx @outfitter/tooling check-readme-imports
|
|
165
|
+
|
|
166
|
+
# Machine-readable output
|
|
167
|
+
bunx @outfitter/tooling check-readme-imports --json
|
|
168
|
+
```
|
|
169
|
+
|
|
101
170
|
## Configuration Presets
|
|
102
171
|
|
|
103
172
|
### Biome
|
|
@@ -188,7 +257,6 @@ bun run apps/outfitter/src/cli.ts repo check boundary-invocations --cwd .
|
|
|
188
257
|
|
|
189
258
|
- [@outfitter/contracts](../contracts/README.md) — Result types and error patterns
|
|
190
259
|
- [@outfitter/cli](../cli/README.md) — CLI framework
|
|
191
|
-
- [@outfitter/kit](../kit/README.md) — Version coordination
|
|
192
260
|
|
|
193
261
|
## License
|
|
194
262
|
|
package/biome.json
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import {
|
|
3
|
-
VERSION
|
|
4
|
-
|
|
3
|
+
VERSION,
|
|
4
|
+
analyzeSourceFile,
|
|
5
|
+
calculateCoverage,
|
|
6
|
+
runCheckTsdoc
|
|
7
|
+
} from "../shared/chunk-cmde0fwx.js";
|
|
5
8
|
import {
|
|
6
9
|
__require
|
|
7
10
|
} from "../shared/chunk-3s189drz.js";
|
|
@@ -205,6 +208,8 @@ Add the missing entries to ${COLORS.blue}bunup.config.ts${COLORS.reset} defineWo
|
|
|
205
208
|
}
|
|
206
209
|
|
|
207
210
|
// src/cli/check-changeset.ts
|
|
211
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
212
|
+
import { join } from "node:path";
|
|
208
213
|
function getChangedPackagePaths(files) {
|
|
209
214
|
const packageNames = new Set;
|
|
210
215
|
const pattern = /^packages\/([^/]+)\/src\//;
|
|
@@ -236,6 +241,73 @@ function checkChangesetRequired(changedPackages, changesetFiles) {
|
|
|
236
241
|
}
|
|
237
242
|
return { ok: false, missingFor: changedPackages };
|
|
238
243
|
}
|
|
244
|
+
function parseIgnoredPackagesFromChangesetConfig(jsonContent) {
|
|
245
|
+
try {
|
|
246
|
+
const parsed = JSON.parse(jsonContent);
|
|
247
|
+
if (!Array.isArray(parsed.ignore)) {
|
|
248
|
+
return [];
|
|
249
|
+
}
|
|
250
|
+
return parsed.ignore.filter((entry) => typeof entry === "string");
|
|
251
|
+
} catch {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function parseChangesetFrontmatterPackageNames(markdownContent) {
|
|
256
|
+
const frontmatterMatch = /^---\r?\n([\s\S]*?)\r?\n---/.exec(markdownContent);
|
|
257
|
+
if (!frontmatterMatch?.[1]) {
|
|
258
|
+
return [];
|
|
259
|
+
}
|
|
260
|
+
const packages = new Set;
|
|
261
|
+
for (const line of frontmatterMatch[1].split(/\r?\n/)) {
|
|
262
|
+
const trimmed = line.trim();
|
|
263
|
+
const match = /^(["']?)(@[^"':\s]+\/[^"':\s]+)\1\s*:/.exec(trimmed);
|
|
264
|
+
if (match?.[2]) {
|
|
265
|
+
packages.add(match[2]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return [...packages].sort();
|
|
269
|
+
}
|
|
270
|
+
function findIgnoredPackageReferences(input) {
|
|
271
|
+
if (input.ignoredPackages.length === 0 || input.changesetFiles.length === 0) {
|
|
272
|
+
return [];
|
|
273
|
+
}
|
|
274
|
+
const ignored = new Set(input.ignoredPackages);
|
|
275
|
+
const results = [];
|
|
276
|
+
for (const file of input.changesetFiles) {
|
|
277
|
+
const content = input.readChangesetFile(file);
|
|
278
|
+
const referencedPackages = parseChangesetFrontmatterPackageNames(content);
|
|
279
|
+
const invalidReferences = referencedPackages.filter((pkg) => ignored.has(pkg));
|
|
280
|
+
if (invalidReferences.length > 0) {
|
|
281
|
+
results.push({ file, packages: invalidReferences.sort() });
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return results.sort((a, b) => a.file.localeCompare(b.file));
|
|
285
|
+
}
|
|
286
|
+
function loadIgnoredPackages(cwd) {
|
|
287
|
+
const configPath = join(cwd, ".changeset", "config.json");
|
|
288
|
+
if (!existsSync(configPath)) {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
return parseIgnoredPackagesFromChangesetConfig(readFileSync(configPath, "utf-8"));
|
|
293
|
+
} catch {
|
|
294
|
+
return [];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function getIgnoredReferencesForChangedChangesets(cwd, changesetFiles) {
|
|
298
|
+
const ignoredPackages = loadIgnoredPackages(cwd);
|
|
299
|
+
return findIgnoredPackageReferences({
|
|
300
|
+
changesetFiles,
|
|
301
|
+
ignoredPackages,
|
|
302
|
+
readChangesetFile: (filename) => {
|
|
303
|
+
try {
|
|
304
|
+
return readFileSync(join(cwd, ".changeset", filename), "utf-8");
|
|
305
|
+
} catch {
|
|
306
|
+
return "";
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
239
311
|
var COLORS2 = {
|
|
240
312
|
reset: "\x1B[0m",
|
|
241
313
|
red: "\x1B[31m",
|
|
@@ -275,25 +347,43 @@ async function runCheckChangeset(options = {}) {
|
|
|
275
347
|
}
|
|
276
348
|
const changesetFiles = getChangedChangesetFiles(changedFiles);
|
|
277
349
|
const check = checkChangesetRequired(changedPackages, changesetFiles);
|
|
278
|
-
if (check.ok) {
|
|
279
|
-
process.
|
|
350
|
+
if (!check.ok) {
|
|
351
|
+
process.stderr.write(`${COLORS2.yellow}No changeset found.${COLORS2.reset} ` + "Consider adding one with `bun run changeset` for a custom changelog entry.\n\n");
|
|
352
|
+
process.stderr.write(`Packages with source changes:
|
|
353
|
+
|
|
354
|
+
`);
|
|
355
|
+
for (const pkg of check.missingFor) {
|
|
356
|
+
process.stderr.write(` ${COLORS2.yellow}@outfitter/${pkg}${COLORS2.reset}
|
|
357
|
+
`);
|
|
358
|
+
}
|
|
359
|
+
process.stderr.write(`
|
|
360
|
+
Run ${COLORS2.blue}bun run changeset${COLORS2.reset} for a custom changelog entry, ` + `or add ${COLORS2.blue}release:none${COLORS2.reset} to skip.
|
|
280
361
|
`);
|
|
281
|
-
process.exit(0);
|
|
282
362
|
}
|
|
283
|
-
|
|
363
|
+
const ignoredReferences = getIgnoredReferencesForChangedChangesets(cwd, changesetFiles);
|
|
364
|
+
if (ignoredReferences.length > 0) {
|
|
365
|
+
process.stderr.write(`${COLORS2.red}Invalid changeset package reference(s).${COLORS2.reset}
|
|
284
366
|
|
|
285
367
|
`);
|
|
286
|
-
|
|
368
|
+
process.stderr.write(`Changesets must not reference packages listed in .changeset/config.json ignore:
|
|
287
369
|
|
|
288
370
|
`);
|
|
289
|
-
|
|
290
|
-
|
|
371
|
+
for (const reference of ignoredReferences) {
|
|
372
|
+
process.stderr.write(` ${COLORS2.yellow}${reference.file}${COLORS2.reset}
|
|
291
373
|
`);
|
|
374
|
+
for (const pkg of reference.packages) {
|
|
375
|
+
process.stderr.write(` - ${pkg}
|
|
376
|
+
`);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
process.stderr.write(`
|
|
380
|
+
Update the affected changeset files to remove ignored packages before merging.
|
|
381
|
+
`);
|
|
382
|
+
process.exit(1);
|
|
292
383
|
}
|
|
293
|
-
process.
|
|
294
|
-
Run ${COLORS2.blue}bun run changeset${COLORS2.reset} to add a changeset, ` + `or add the ${COLORS2.blue}no-changeset${COLORS2.reset} label to skip.
|
|
384
|
+
process.stdout.write(`${COLORS2.green}Changeset found for ${changedPackages.length} changed package(s).${COLORS2.reset}
|
|
295
385
|
`);
|
|
296
|
-
process.exit(
|
|
386
|
+
process.exit(0);
|
|
297
387
|
}
|
|
298
388
|
|
|
299
389
|
// src/cli/check-clean-tree.ts
|
|
@@ -674,8 +764,9 @@ async function runInit(cwd = process.cwd()) {
|
|
|
674
764
|
}
|
|
675
765
|
|
|
676
766
|
// src/cli/pre-push.ts
|
|
677
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
678
|
-
import { join } from "node:path";
|
|
767
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
768
|
+
import { join as join2, resolve as resolve4 } from "node:path";
|
|
769
|
+
import ts from "typescript";
|
|
679
770
|
var COLORS5 = {
|
|
680
771
|
reset: "\x1B[0m",
|
|
681
772
|
red: "\x1B[31m",
|
|
@@ -712,6 +803,9 @@ function isRedPhaseBranch(branch) {
|
|
|
712
803
|
function isScaffoldBranch(branch) {
|
|
713
804
|
return branch.endsWith("-scaffold") || branch.endsWith("/scaffold") || branch.endsWith("_scaffold");
|
|
714
805
|
}
|
|
806
|
+
function isReleaseBranch(branch) {
|
|
807
|
+
return branch.startsWith("changeset-release/");
|
|
808
|
+
}
|
|
715
809
|
var TEST_PATH_PATTERNS = [
|
|
716
810
|
/(^|\/)__tests__\//,
|
|
717
811
|
/(^|\/)__snapshots__\//,
|
|
@@ -731,6 +825,32 @@ function areFilesTestOnly(paths) {
|
|
|
731
825
|
function canBypassRedPhaseByChangedFiles(changedFiles) {
|
|
732
826
|
return changedFiles.deterministic && areFilesTestOnly(changedFiles.files);
|
|
733
827
|
}
|
|
828
|
+
function hasPackageSourceChanges(changedFiles) {
|
|
829
|
+
const packageSrcPattern = /^packages\/[^/]+\/src\//;
|
|
830
|
+
return changedFiles.files.some((f) => packageSrcPattern.test(f));
|
|
831
|
+
}
|
|
832
|
+
async function printTsdocSummary() {
|
|
833
|
+
const glob = new Bun.Glob("packages/*/src/index.ts");
|
|
834
|
+
const cwd = process.cwd();
|
|
835
|
+
const allDeclarations = [];
|
|
836
|
+
for (const entry of glob.scanSync({ cwd })) {
|
|
837
|
+
const filePath = resolve4(cwd, entry);
|
|
838
|
+
const content = await Bun.file(filePath).text();
|
|
839
|
+
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
840
|
+
allDeclarations.push(...analyzeSourceFile(sourceFile));
|
|
841
|
+
}
|
|
842
|
+
if (allDeclarations.length === 0)
|
|
843
|
+
return;
|
|
844
|
+
const coverage = calculateCoverage(allDeclarations);
|
|
845
|
+
const parts = [];
|
|
846
|
+
if (coverage.documented > 0)
|
|
847
|
+
parts.push(`${coverage.documented} documented`);
|
|
848
|
+
if (coverage.partial > 0)
|
|
849
|
+
parts.push(`${coverage.partial} partial`);
|
|
850
|
+
if (coverage.undocumented > 0)
|
|
851
|
+
parts.push(`${coverage.undocumented} undocumented`);
|
|
852
|
+
log(`${COLORS5.blue}TSDoc${COLORS5.reset}: ${coverage.percentage}% coverage (${parts.join(", ")} of ${coverage.total} total)`);
|
|
853
|
+
}
|
|
734
854
|
function resolveBaseRef() {
|
|
735
855
|
const candidates = [
|
|
736
856
|
"origin/main",
|
|
@@ -868,12 +988,12 @@ function createVerificationPlan(scripts) {
|
|
|
868
988
|
};
|
|
869
989
|
}
|
|
870
990
|
function readPackageScripts(cwd = process.cwd()) {
|
|
871
|
-
const packageJsonPath =
|
|
872
|
-
if (!
|
|
991
|
+
const packageJsonPath = join2(cwd, "package.json");
|
|
992
|
+
if (!existsSync2(packageJsonPath)) {
|
|
873
993
|
return {};
|
|
874
994
|
}
|
|
875
995
|
try {
|
|
876
|
-
const parsed = JSON.parse(
|
|
996
|
+
const parsed = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
877
997
|
const scripts = parsed.scripts ?? {};
|
|
878
998
|
const normalized = {};
|
|
879
999
|
for (const [name, value] of Object.entries(scripts)) {
|
|
@@ -898,6 +1018,11 @@ async function runPrePush(options = {}) {
|
|
|
898
1018
|
log(`${COLORS5.blue}Pre-push verify${COLORS5.reset} (TDD-aware)`);
|
|
899
1019
|
log("");
|
|
900
1020
|
const branch = getCurrentBranch();
|
|
1021
|
+
if (isReleaseBranch(branch)) {
|
|
1022
|
+
log(`${COLORS5.yellow}Release branch detected${COLORS5.reset}: ${COLORS5.blue}${branch}${COLORS5.reset}`);
|
|
1023
|
+
log(`${COLORS5.yellow}Skipping strict verification${COLORS5.reset} for automated changeset release push`);
|
|
1024
|
+
process.exit(0);
|
|
1025
|
+
}
|
|
901
1026
|
if (isRedPhaseBranch(branch)) {
|
|
902
1027
|
if (maybeSkipForRedPhase("branch", branch)) {
|
|
903
1028
|
process.exit(0);
|
|
@@ -943,14 +1068,20 @@ async function runPrePush(options = {}) {
|
|
|
943
1068
|
log(" - feature_tests");
|
|
944
1069
|
process.exit(1);
|
|
945
1070
|
}
|
|
1071
|
+
const changedFiles = getChangedFilesForPush();
|
|
1072
|
+
if (hasPackageSourceChanges(changedFiles)) {
|
|
1073
|
+
try {
|
|
1074
|
+
await printTsdocSummary();
|
|
1075
|
+
} catch {}
|
|
1076
|
+
}
|
|
946
1077
|
log("");
|
|
947
1078
|
log(`${COLORS5.green}Strict verification passed${COLORS5.reset}`);
|
|
948
1079
|
process.exit(0);
|
|
949
1080
|
}
|
|
950
1081
|
|
|
951
1082
|
// src/cli/upgrade-bun.ts
|
|
952
|
-
import { existsSync as
|
|
953
|
-
import { join as
|
|
1083
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "node:fs";
|
|
1084
|
+
import { join as join3 } from "node:path";
|
|
954
1085
|
var COLORS6 = {
|
|
955
1086
|
reset: "\x1B[0m",
|
|
956
1087
|
red: "\x1B[31m",
|
|
@@ -988,13 +1119,13 @@ function findPackageJsonFiles(dir) {
|
|
|
988
1119
|
const glob = new Bun.Glob("**/package.json");
|
|
989
1120
|
for (const path of glob.scanSync({ cwd: dir })) {
|
|
990
1121
|
if (!path.includes("node_modules")) {
|
|
991
|
-
results.push(
|
|
1122
|
+
results.push(join3(dir, path));
|
|
992
1123
|
}
|
|
993
1124
|
}
|
|
994
1125
|
return results;
|
|
995
1126
|
}
|
|
996
1127
|
function updateEnginesBun(filePath, version) {
|
|
997
|
-
const content =
|
|
1128
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
998
1129
|
const pattern = /"bun":\s*">=[\d.]+"/;
|
|
999
1130
|
if (!pattern.test(content)) {
|
|
1000
1131
|
return false;
|
|
@@ -1007,7 +1138,7 @@ function updateEnginesBun(filePath, version) {
|
|
|
1007
1138
|
return false;
|
|
1008
1139
|
}
|
|
1009
1140
|
function updateTypesBun(filePath, version) {
|
|
1010
|
-
const content =
|
|
1141
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
1011
1142
|
const pattern = /"@types\/bun":\s*"\^[\d.]+"/;
|
|
1012
1143
|
if (!pattern.test(content)) {
|
|
1013
1144
|
return false;
|
|
@@ -1021,14 +1152,14 @@ function updateTypesBun(filePath, version) {
|
|
|
1021
1152
|
}
|
|
1022
1153
|
async function runUpgradeBun(targetVersion, options = {}) {
|
|
1023
1154
|
const cwd = process.cwd();
|
|
1024
|
-
const bunVersionFile =
|
|
1155
|
+
const bunVersionFile = join3(cwd, ".bun-version");
|
|
1025
1156
|
let version = targetVersion;
|
|
1026
1157
|
if (!version) {
|
|
1027
1158
|
info("Fetching latest Bun version...");
|
|
1028
1159
|
version = await fetchLatestVersion();
|
|
1029
1160
|
log2(`Latest version: ${version}`);
|
|
1030
1161
|
}
|
|
1031
|
-
const currentVersion =
|
|
1162
|
+
const currentVersion = existsSync3(bunVersionFile) ? readFileSync3(bunVersionFile, "utf-8").trim() : "unknown";
|
|
1032
1163
|
log2(`Current version: ${currentVersion}`);
|
|
1033
1164
|
if (currentVersion === version) {
|
|
1034
1165
|
success(`Already on version ${version}`);
|
|
@@ -1129,6 +1260,14 @@ register(new Command("check-changeset").description("Validate PRs touching packa
|
|
|
1129
1260
|
register(new Command("check-exports").description("Validate package.json exports match source entry points").option("--json", "Output results as JSON").action(async (options) => {
|
|
1130
1261
|
await runCheckExports(options);
|
|
1131
1262
|
}));
|
|
1263
|
+
register(new Command("check-tsdoc").description("Check TSDoc coverage on exported declarations").argument("[paths...]", "Specific package paths to check").option("--strict", "Exit non-zero when coverage is below threshold").option("--json", "Output results as JSON").option("--min-coverage <percentage>", "Minimum coverage percentage", "0").action(async (paths, options) => {
|
|
1264
|
+
await runCheckTsdoc({
|
|
1265
|
+
paths: paths.length > 0 ? paths : undefined,
|
|
1266
|
+
strict: options.strict,
|
|
1267
|
+
json: options.json,
|
|
1268
|
+
minCoverage: options.minCoverage ? Number.parseInt(options.minCoverage, 10) : undefined
|
|
1269
|
+
});
|
|
1270
|
+
}));
|
|
1132
1271
|
register(new Command("check-clean-tree").description("Assert working tree is clean (no modified or untracked files)").option("--paths <paths...>", "Limit check to specific paths").action(async (options) => {
|
|
1133
1272
|
await runCheckCleanTree(options);
|
|
1134
1273
|
}));
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,79 @@
|
|
|
1
1
|
import { ZodType } from "zod";
|
|
2
|
+
/** Coverage classification for a single declaration. */
|
|
3
|
+
type CoverageLevel = "documented" | "partial" | "undocumented";
|
|
4
|
+
/** Result for a single exported declaration. */
|
|
5
|
+
interface DeclarationCoverage {
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly kind: string;
|
|
8
|
+
readonly level: CoverageLevel;
|
|
9
|
+
readonly file: string;
|
|
10
|
+
readonly line: number;
|
|
11
|
+
}
|
|
12
|
+
/** Coverage summary statistics. */
|
|
13
|
+
interface CoverageSummary {
|
|
14
|
+
readonly documented: number;
|
|
15
|
+
readonly partial: number;
|
|
16
|
+
readonly undocumented: number;
|
|
17
|
+
readonly total: number;
|
|
18
|
+
readonly percentage: number;
|
|
19
|
+
}
|
|
20
|
+
/** Per-package TSDoc coverage stats. */
|
|
21
|
+
interface PackageCoverage {
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly path: string;
|
|
24
|
+
readonly declarations: readonly DeclarationCoverage[];
|
|
25
|
+
readonly documented: number;
|
|
26
|
+
readonly partial: number;
|
|
27
|
+
readonly undocumented: number;
|
|
28
|
+
readonly total: number;
|
|
29
|
+
readonly percentage: number;
|
|
30
|
+
}
|
|
31
|
+
/** Aggregated result across all packages. */
|
|
32
|
+
interface TsDocCheckResult {
|
|
33
|
+
readonly ok: boolean;
|
|
34
|
+
readonly packages: readonly PackageCoverage[];
|
|
35
|
+
readonly summary: CoverageSummary;
|
|
36
|
+
}
|
|
37
|
+
/** Zod schema for {@link CoverageLevel}. */
|
|
38
|
+
declare const coverageLevelSchema: ZodType<CoverageLevel>;
|
|
39
|
+
/** Zod schema for {@link DeclarationCoverage}. */
|
|
40
|
+
declare const declarationCoverageSchema: ZodType<DeclarationCoverage>;
|
|
41
|
+
/** Zod schema for {@link PackageCoverage}. */
|
|
42
|
+
declare const packageCoverageSchema: ZodType<PackageCoverage>;
|
|
43
|
+
/** Zod schema for {@link TsDocCheckResult}. */
|
|
44
|
+
declare const tsDocCheckResultSchema: ZodType<TsDocCheckResult>;
|
|
45
|
+
/** Options for the check-tsdoc command. */
|
|
46
|
+
interface CheckTsDocOptions {
|
|
47
|
+
readonly strict?: boolean | undefined;
|
|
48
|
+
readonly json?: boolean | undefined;
|
|
49
|
+
readonly minCoverage?: number | undefined;
|
|
50
|
+
readonly cwd?: string | undefined;
|
|
51
|
+
readonly paths?: readonly string[] | undefined;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Analyze TSDoc coverage across workspace packages.
|
|
55
|
+
*
|
|
56
|
+
* Pure function that discovers packages, analyzes TSDoc coverage on exported
|
|
57
|
+
* declarations, and returns the aggregated result. Does not print output or
|
|
58
|
+
* call `process.exit()`.
|
|
59
|
+
*
|
|
60
|
+
* @param options - Analysis options (paths, strict mode, coverage threshold)
|
|
61
|
+
* @returns Aggregated coverage result across all packages, or `null` if no packages found
|
|
62
|
+
*/
|
|
63
|
+
declare function analyzeCheckTsdoc(options?: CheckTsDocOptions): TsDocCheckResult | null;
|
|
64
|
+
/**
|
|
65
|
+
* Print a TSDoc coverage result in human-readable format.
|
|
66
|
+
*
|
|
67
|
+
* Renders a bar chart per package with summary statistics. Writes to stdout/stderr.
|
|
68
|
+
*
|
|
69
|
+
* @param result - The coverage result to print
|
|
70
|
+
* @param options - Display options (strict mode, coverage threshold for warning)
|
|
71
|
+
*/
|
|
72
|
+
declare function printCheckTsdocHuman(result: TsDocCheckResult, options?: {
|
|
73
|
+
strict?: boolean | undefined;
|
|
74
|
+
minCoverage?: number | undefined;
|
|
75
|
+
}): void;
|
|
76
|
+
import { ZodType as ZodType2 } from "zod";
|
|
2
77
|
/**
|
|
3
78
|
* File entry in a block.
|
|
4
79
|
*/
|
|
@@ -16,7 +91,7 @@ interface FileEntry {
|
|
|
16
91
|
* Schema for a file entry in a block.
|
|
17
92
|
* Represents a file that will be copied to the user's project.
|
|
18
93
|
*/
|
|
19
|
-
declare const FileEntrySchema:
|
|
94
|
+
declare const FileEntrySchema: ZodType2<FileEntry>;
|
|
20
95
|
/**
|
|
21
96
|
* Block in the registry.
|
|
22
97
|
*/
|
|
@@ -38,7 +113,7 @@ interface Block {
|
|
|
38
113
|
* Schema for a block in the registry.
|
|
39
114
|
* A block is a collection of related files that can be added together.
|
|
40
115
|
*/
|
|
41
|
-
declare const BlockSchema:
|
|
116
|
+
declare const BlockSchema: ZodType2<Block>;
|
|
42
117
|
/**
|
|
43
118
|
* Complete registry structure.
|
|
44
119
|
*/
|
|
@@ -52,7 +127,7 @@ interface Registry {
|
|
|
52
127
|
* Schema for the complete registry.
|
|
53
128
|
* Contains all available blocks with their files and metadata.
|
|
54
129
|
*/
|
|
55
|
-
declare const RegistrySchema:
|
|
130
|
+
declare const RegistrySchema: ZodType2<Registry>;
|
|
56
131
|
/**
|
|
57
132
|
* Block definition used in the build script.
|
|
58
133
|
* Specifies how to collect source files into a block.
|
|
@@ -108,4 +183,4 @@ interface AddBlockOptions {
|
|
|
108
183
|
}
|
|
109
184
|
/** Package version, read from package.json at load time. */
|
|
110
185
|
declare const VERSION: string;
|
|
111
|
-
export { VERSION, RegistrySchema, RegistryBuildConfig, Registry, FileEntrySchema, FileEntry, BlockSchema, BlockDefinition, Block, AddBlockResult, AddBlockOptions };
|
|
186
|
+
export { tsDocCheckResultSchema, printCheckTsdocHuman, packageCoverageSchema, declarationCoverageSchema, coverageLevelSchema, analyzeCheckTsdoc, VERSION, TsDocCheckResult, RegistrySchema, RegistryBuildConfig, Registry, PackageCoverage, FileEntrySchema, FileEntry, DeclarationCoverage, CoverageLevel, CheckTsDocOptions, BlockSchema, BlockDefinition, Block, AddBlockResult, AddBlockOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
-
VERSION
|
|
3
|
-
|
|
2
|
+
VERSION,
|
|
3
|
+
analyzeCheckTsdoc,
|
|
4
|
+
coverageLevelSchema,
|
|
5
|
+
declarationCoverageSchema,
|
|
6
|
+
packageCoverageSchema,
|
|
7
|
+
printCheckTsdocHuman,
|
|
8
|
+
tsDocCheckResultSchema
|
|
9
|
+
} from "./shared/chunk-cmde0fwx.js";
|
|
4
10
|
import"./shared/chunk-3s189drz.js";
|
|
5
|
-
|
|
6
11
|
// src/registry/schema.ts
|
|
7
12
|
import { z } from "zod";
|
|
8
13
|
var FileEntrySchema = z.object({
|
|
@@ -15,15 +20,21 @@ var BlockSchema = z.object({
|
|
|
15
20
|
name: z.string().min(1),
|
|
16
21
|
description: z.string().min(1),
|
|
17
22
|
files: z.array(FileEntrySchema).optional(),
|
|
18
|
-
dependencies: z.record(z.string()).optional(),
|
|
19
|
-
devDependencies: z.record(z.string()).optional(),
|
|
23
|
+
dependencies: z.record(z.string(), z.string()).optional(),
|
|
24
|
+
devDependencies: z.record(z.string(), z.string()).optional(),
|
|
20
25
|
extends: z.array(z.string()).optional()
|
|
21
26
|
});
|
|
22
27
|
var RegistrySchema = z.object({
|
|
23
28
|
version: z.string(),
|
|
24
|
-
blocks: z.record(BlockSchema)
|
|
29
|
+
blocks: z.record(z.string(), BlockSchema)
|
|
25
30
|
});
|
|
26
31
|
export {
|
|
32
|
+
tsDocCheckResultSchema,
|
|
33
|
+
printCheckTsdocHuman,
|
|
34
|
+
packageCoverageSchema,
|
|
35
|
+
declarationCoverageSchema,
|
|
36
|
+
coverageLevelSchema,
|
|
37
|
+
analyzeCheckTsdoc,
|
|
27
38
|
VERSION,
|
|
28
39
|
RegistrySchema,
|
|
29
40
|
FileEntrySchema,
|