@outfitter/tooling 0.3.3 → 0.3.5
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/.markdownlint-cli2.jsonc +55 -55
- package/README.md +33 -24
- package/dist/bun-version-compat.d.ts +2 -0
- package/dist/bun-version-compat.js +10 -0
- package/dist/cli/check-boundary-invocations.d.ts +34 -0
- package/dist/cli/check-boundary-invocations.js +14 -0
- package/dist/cli/check-bunup-registry.d.ts +36 -0
- package/dist/cli/check-bunup-registry.js +12 -0
- package/dist/cli/check-changeset.d.ts +82 -0
- package/dist/cli/check-changeset.js +24 -0
- package/dist/cli/check-clean-tree.d.ts +36 -0
- package/dist/cli/check-clean-tree.js +14 -0
- package/dist/cli/check-exports.d.ts +3 -0
- package/dist/cli/check-exports.js +17 -0
- package/dist/cli/check-home-paths.d.ts +31 -0
- package/dist/cli/check-home-paths.js +12 -0
- package/dist/cli/check-markdown-links.d.ts +42 -0
- package/dist/cli/check-markdown-links.js +13 -0
- package/dist/cli/check-readme-imports.d.ts +61 -0
- package/dist/{shared/chunk-7tdgbqb0.js → cli/check-readme-imports.js} +7 -6
- package/dist/cli/check-tsdoc.d.ts +5 -0
- package/dist/cli/check-tsdoc.js +42 -0
- package/dist/cli/check.d.ts +19 -0
- package/dist/cli/check.js +10 -0
- package/dist/cli/fix.d.ts +19 -0
- package/dist/cli/fix.js +10 -0
- package/dist/cli/index.js +61 -1218
- package/dist/cli/init.d.ts +31 -0
- package/dist/cli/init.js +12 -0
- package/dist/cli/internal/exports-analysis.d.ts +2 -0
- package/dist/cli/internal/exports-analysis.js +10 -0
- package/dist/cli/internal/exports-fs.d.ts +17 -0
- package/dist/cli/internal/exports-fs.js +9 -0
- package/dist/cli/internal/pre-push-checks.d.ts +2 -0
- package/dist/cli/internal/pre-push-checks.js +37 -0
- package/dist/cli/internal/tsdoc-analysis.d.ts +3 -0
- package/dist/cli/internal/tsdoc-analysis.js +26 -0
- package/dist/cli/internal/tsdoc-formatting.d.ts +3 -0
- package/dist/cli/internal/tsdoc-formatting.js +10 -0
- package/dist/cli/internal/tsdoc-types.d.ts +2 -0
- package/dist/cli/internal/tsdoc-types.js +16 -0
- package/dist/cli/pre-push.d.ts +7 -0
- package/dist/cli/pre-push.js +29 -0
- package/dist/cli/upgrade-bun.d.ts +8 -0
- package/dist/cli/upgrade-bun.js +9 -0
- package/dist/index.d.ts +9 -186
- package/dist/index.js +4 -42
- package/dist/registry/build.d.ts +4 -0
- package/dist/registry/build.js +279 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.js +1 -0
- package/dist/registry/schema.d.ts +2 -0
- package/dist/registry/schema.js +28 -0
- package/dist/shared/@outfitter/tooling-0zjz8eg9.js +106 -0
- package/dist/shared/@outfitter/tooling-1hez6j9d.js +21 -0
- package/dist/shared/@outfitter/tooling-2vv5y3s4.js +145 -0
- package/dist/shared/{chunk-cmde0fwx.js → @outfitter/tooling-5xxctk9b.js} +12 -138
- package/dist/shared/@outfitter/tooling-5ynz680q.js +59 -0
- package/dist/shared/@outfitter/tooling-7437rmy6.js +39 -0
- package/dist/shared/@outfitter/tooling-8qcwr06t.d.ts +74 -0
- package/dist/shared/@outfitter/tooling-9ram55dd.js +69 -0
- package/dist/shared/@outfitter/tooling-9vs606gq.d.ts +3 -0
- package/dist/shared/@outfitter/tooling-a4bfx4be.js +21 -0
- package/dist/shared/@outfitter/tooling-a59br34g.js +32 -0
- package/dist/shared/@outfitter/tooling-a6q3zh7t.js +86 -0
- package/dist/shared/@outfitter/tooling-amrbp7cm.js +102 -0
- package/dist/shared/@outfitter/tooling-ayps7c4x.js +58 -0
- package/dist/shared/@outfitter/tooling-c8q6mj8z.js +228 -0
- package/dist/shared/@outfitter/tooling-cb0b8wsx.d.ts +57 -0
- package/dist/shared/@outfitter/tooling-ctmgnap5.js +19 -0
- package/dist/shared/@outfitter/tooling-f8q38e9z.d.ts +16 -0
- package/dist/shared/@outfitter/tooling-gcdvsqqp.js +73 -0
- package/dist/shared/@outfitter/tooling-h5dnevjw.js +139 -0
- package/dist/shared/@outfitter/tooling-j8d1h2zd.d.ts +10 -0
- package/dist/shared/@outfitter/tooling-ja1zg5yc.js +214 -0
- package/dist/shared/@outfitter/tooling-jnrs9rqd.js +4 -0
- package/dist/shared/@outfitter/tooling-mkynjra9.js +23 -0
- package/dist/shared/@outfitter/tooling-mq2xvz96.js +285 -0
- package/dist/shared/@outfitter/tooling-pq47jv6t.js +213 -0
- package/dist/shared/@outfitter/tooling-sjm8nebx.d.ts +109 -0
- package/dist/shared/@outfitter/tooling-stgnc2zx.d.ts +85 -0
- package/dist/shared/@outfitter/tooling-tj9p41vj.d.ts +55 -0
- package/dist/shared/@outfitter/tooling-vjmhvpjq.d.ts +29 -0
- package/dist/shared/@outfitter/tooling-wwm97f47.js +81 -0
- package/dist/shared/@outfitter/tooling-y43b117h.d.ts +13 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +8 -0
- package/lefthook.yml +5 -1
- package/package.json +140 -131
- package/registry/registry.json +19 -12
- package/tsconfig.preset.bun.json +5 -5
- package/tsconfig.preset.json +33 -33
- package/biome.json +0 -81
- package/dist/shared/chunk-3s189drz.js +0 -4
|
@@ -1,45 +1,11 @@
|
|
|
1
|
+
// @bun
|
|
1
2
|
import {
|
|
2
3
|
__require
|
|
3
|
-
} from "./
|
|
4
|
+
} from "./tooling-jnrs9rqd.js";
|
|
4
5
|
|
|
5
|
-
// src/cli/
|
|
6
|
-
import { resolve } from "
|
|
6
|
+
// packages/tooling/src/cli/internal/tsdoc-analysis.ts
|
|
7
|
+
import { resolve } from "path";
|
|
7
8
|
import ts from "typescript";
|
|
8
|
-
import { z } from "zod";
|
|
9
|
-
var coverageLevelSchema = z.enum([
|
|
10
|
-
"documented",
|
|
11
|
-
"partial",
|
|
12
|
-
"undocumented"
|
|
13
|
-
]);
|
|
14
|
-
var declarationCoverageSchema = z.object({
|
|
15
|
-
name: z.string(),
|
|
16
|
-
kind: z.string(),
|
|
17
|
-
level: coverageLevelSchema,
|
|
18
|
-
file: z.string(),
|
|
19
|
-
line: z.number()
|
|
20
|
-
});
|
|
21
|
-
var coverageSummarySchema = z.object({
|
|
22
|
-
documented: z.number(),
|
|
23
|
-
partial: z.number(),
|
|
24
|
-
undocumented: z.number(),
|
|
25
|
-
total: z.number(),
|
|
26
|
-
percentage: z.number()
|
|
27
|
-
});
|
|
28
|
-
var packageCoverageSchema = z.object({
|
|
29
|
-
name: z.string(),
|
|
30
|
-
path: z.string(),
|
|
31
|
-
declarations: z.array(declarationCoverageSchema),
|
|
32
|
-
documented: z.number(),
|
|
33
|
-
partial: z.number(),
|
|
34
|
-
undocumented: z.number(),
|
|
35
|
-
total: z.number(),
|
|
36
|
-
percentage: z.number()
|
|
37
|
-
});
|
|
38
|
-
var tsDocCheckResultSchema = z.object({
|
|
39
|
-
ok: z.boolean(),
|
|
40
|
-
packages: z.array(packageCoverageSchema),
|
|
41
|
-
summary: coverageSummarySchema
|
|
42
|
-
});
|
|
43
9
|
function isExportedDeclaration(node) {
|
|
44
10
|
if (ts.isExportDeclaration(node))
|
|
45
11
|
return false;
|
|
@@ -158,24 +124,6 @@ function calculateCoverage(declarations) {
|
|
|
158
124
|
const percentage = Math.round(score / total * 100);
|
|
159
125
|
return { documented, partial, undocumented, total, percentage };
|
|
160
126
|
}
|
|
161
|
-
var COLORS = {
|
|
162
|
-
reset: "\x1B[0m",
|
|
163
|
-
red: "\x1B[31m",
|
|
164
|
-
green: "\x1B[32m",
|
|
165
|
-
yellow: "\x1B[33m",
|
|
166
|
-
blue: "\x1B[34m",
|
|
167
|
-
dim: "\x1B[2m",
|
|
168
|
-
bold: "\x1B[1m"
|
|
169
|
-
};
|
|
170
|
-
function resolveJsonMode(options = {}) {
|
|
171
|
-
return options.json ?? process.env["OUTFITTER_JSON"] === "1";
|
|
172
|
-
}
|
|
173
|
-
function bar(percentage, width = 20) {
|
|
174
|
-
const filled = Math.round(percentage / 100 * width);
|
|
175
|
-
const empty = width - filled;
|
|
176
|
-
const color = percentage >= 80 ? COLORS.green : percentage >= 50 ? COLORS.yellow : COLORS.red;
|
|
177
|
-
return `${color}${"█".repeat(filled)}${COLORS.dim}${"░".repeat(empty)}${COLORS.reset}`;
|
|
178
|
-
}
|
|
179
127
|
function discoverPackages(cwd) {
|
|
180
128
|
const packages = [];
|
|
181
129
|
const seenEntryPoints = new Set;
|
|
@@ -195,7 +143,7 @@ function discoverPackages(cwd) {
|
|
|
195
143
|
const pkgRoot = resolve(cwd, rootDir, pkgDir);
|
|
196
144
|
let pkgName = pkgDir;
|
|
197
145
|
try {
|
|
198
|
-
const pkgJson = JSON.parse(__require("
|
|
146
|
+
const pkgJson = JSON.parse(__require("fs").readFileSync(resolve(pkgRoot, "package.json"), "utf-8"));
|
|
199
147
|
if (pkgJson.name)
|
|
200
148
|
pkgName = pkgJson.name;
|
|
201
149
|
} catch {}
|
|
@@ -209,10 +157,10 @@ function discoverPackages(cwd) {
|
|
|
209
157
|
if (packages.length === 0) {
|
|
210
158
|
const entryPoint = resolve(cwd, "src/index.ts");
|
|
211
159
|
try {
|
|
212
|
-
__require("
|
|
160
|
+
__require("fs").accessSync(entryPoint);
|
|
213
161
|
let pkgName = "root";
|
|
214
162
|
try {
|
|
215
|
-
const pkgJson = JSON.parse(__require("
|
|
163
|
+
const pkgJson = JSON.parse(__require("fs").readFileSync(resolve(cwd, "package.json"), "utf-8"));
|
|
216
164
|
if (pkgJson.name)
|
|
217
165
|
pkgName = pkgJson.name;
|
|
218
166
|
} catch {}
|
|
@@ -224,7 +172,7 @@ function discoverPackages(cwd) {
|
|
|
224
172
|
seenEntryPoints.add(entryPoint);
|
|
225
173
|
} catch {}
|
|
226
174
|
}
|
|
227
|
-
return packages.
|
|
175
|
+
return packages.toSorted((a, b) => a.name.localeCompare(b.name));
|
|
228
176
|
}
|
|
229
177
|
function collectReExportedSourceFiles(sourceFile, program, pkgPath) {
|
|
230
178
|
const result = [];
|
|
@@ -256,7 +204,7 @@ function collectReExportedSourceFiles(sourceFile, program, pkgPath) {
|
|
|
256
204
|
}
|
|
257
205
|
function analyzePackage(pkg, workspaceCwd) {
|
|
258
206
|
try {
|
|
259
|
-
__require("
|
|
207
|
+
__require("fs").accessSync(pkg.entryPoint);
|
|
260
208
|
} catch {
|
|
261
209
|
return {
|
|
262
210
|
name: pkg.name,
|
|
@@ -271,7 +219,7 @@ function analyzePackage(pkg, workspaceCwd) {
|
|
|
271
219
|
}
|
|
272
220
|
let tsconfigPath = resolve(pkg.path, "tsconfig.json");
|
|
273
221
|
try {
|
|
274
|
-
__require("
|
|
222
|
+
__require("fs").accessSync(tsconfigPath);
|
|
275
223
|
} catch {
|
|
276
224
|
tsconfigPath = resolve(workspaceCwd, "tsconfig.json");
|
|
277
225
|
}
|
|
@@ -318,7 +266,7 @@ function analyzeCheckTsdoc(options = {}) {
|
|
|
318
266
|
const entryPoint = resolve(absPath, "src/index.ts");
|
|
319
267
|
let name = p;
|
|
320
268
|
try {
|
|
321
|
-
const pkgJson = JSON.parse(__require("
|
|
269
|
+
const pkgJson = JSON.parse(__require("fs").readFileSync(resolve(absPath, "package.json"), "utf-8"));
|
|
322
270
|
if (pkgJson.name)
|
|
323
271
|
name = pkgJson.name;
|
|
324
272
|
} catch {}
|
|
@@ -343,79 +291,5 @@ function analyzeCheckTsdoc(options = {}) {
|
|
|
343
291
|
summary
|
|
344
292
|
};
|
|
345
293
|
}
|
|
346
|
-
function printCheckTsdocHuman(result, options) {
|
|
347
|
-
process.stdout.write(`
|
|
348
|
-
${COLORS.bold}TSDoc Coverage Report${COLORS.reset}
|
|
349
|
-
|
|
350
|
-
`);
|
|
351
|
-
for (const pkg of result.packages) {
|
|
352
|
-
const color = pkg.percentage >= 80 ? COLORS.green : pkg.percentage >= 50 ? COLORS.yellow : COLORS.red;
|
|
353
|
-
process.stdout.write(` ${color}${pkg.percentage.toString().padStart(3)}%${COLORS.reset} ${bar(pkg.percentage)} ${pkg.name}
|
|
354
|
-
`);
|
|
355
|
-
if (pkg.total > 0) {
|
|
356
|
-
const parts = [];
|
|
357
|
-
if (pkg.documented > 0)
|
|
358
|
-
parts.push(`${COLORS.green}${pkg.documented} documented${COLORS.reset}`);
|
|
359
|
-
if (pkg.partial > 0)
|
|
360
|
-
parts.push(`${COLORS.yellow}${pkg.partial} partial${COLORS.reset}`);
|
|
361
|
-
if (pkg.undocumented > 0)
|
|
362
|
-
parts.push(`${COLORS.red}${pkg.undocumented} undocumented${COLORS.reset}`);
|
|
363
|
-
process.stdout.write(` ${COLORS.dim}${pkg.total} declarations:${COLORS.reset} ${parts.join(", ")}
|
|
364
|
-
`);
|
|
365
|
-
} else {
|
|
366
|
-
process.stdout.write(` ${COLORS.dim}no exported declarations${COLORS.reset}
|
|
367
|
-
`);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
const { summary } = result;
|
|
371
|
-
process.stdout.write(`
|
|
372
|
-
${COLORS.bold}Summary:${COLORS.reset} ${summary.percentage}% coverage (${summary.documented} documented, ${summary.partial} partial, ${summary.undocumented} undocumented of ${summary.total} total)
|
|
373
|
-
`);
|
|
374
|
-
const minCoverage = options?.minCoverage ?? 0;
|
|
375
|
-
if (options?.strict && summary.percentage < minCoverage) {
|
|
376
|
-
process.stderr.write(`
|
|
377
|
-
${COLORS.red}Coverage ${summary.percentage}% is below minimum threshold of ${minCoverage}%${COLORS.reset}
|
|
378
|
-
`);
|
|
379
|
-
}
|
|
380
|
-
process.stdout.write(`
|
|
381
|
-
`);
|
|
382
|
-
}
|
|
383
|
-
async function runCheckTsdoc(options = {}) {
|
|
384
|
-
const result = analyzeCheckTsdoc(options);
|
|
385
|
-
if (!result) {
|
|
386
|
-
process.stderr.write(`No packages found with src/index.ts entry points.
|
|
387
|
-
` + `Searched: packages/*/src/index.ts, apps/*/src/index.ts, src/index.ts
|
|
388
|
-
` + `Use --package <path> to specify a package path explicitly.
|
|
389
|
-
`);
|
|
390
|
-
process.exit(1);
|
|
391
|
-
}
|
|
392
|
-
if (resolveJsonMode(options)) {
|
|
393
|
-
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
394
|
-
`);
|
|
395
|
-
} else {
|
|
396
|
-
printCheckTsdocHuman(result, {
|
|
397
|
-
strict: options.strict,
|
|
398
|
-
minCoverage: options.minCoverage
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
process.exit(result.ok ? 0 : 1);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// src/version.ts
|
|
405
|
-
import { readFileSync } from "node:fs";
|
|
406
|
-
import { createRequire } from "node:module";
|
|
407
|
-
var DEFAULT_VERSION = "0.0.0";
|
|
408
|
-
function readPackageVersion() {
|
|
409
|
-
try {
|
|
410
|
-
const require2 = createRequire(import.meta.url);
|
|
411
|
-
const pkgPath = require2.resolve("@outfitter/tooling/package.json");
|
|
412
|
-
const packageJson = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
413
|
-
if (typeof packageJson.version === "string" && packageJson.version.length > 0) {
|
|
414
|
-
return packageJson.version;
|
|
415
|
-
}
|
|
416
|
-
} catch {}
|
|
417
|
-
return DEFAULT_VERSION;
|
|
418
|
-
}
|
|
419
|
-
var VERSION = readPackageVersion();
|
|
420
294
|
|
|
421
|
-
export {
|
|
295
|
+
export { isExportedDeclaration, getDeclarationName, getDeclarationKind, classifyDeclaration, analyzeSourceFile, calculateCoverage, discoverPackages, collectReExportedSourceFiles, analyzePackage, analyzeCheckTsdoc };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/tooling/src/cli/internal/tsdoc-formatting.ts
|
|
3
|
+
var COLORS = {
|
|
4
|
+
reset: "\x1B[0m",
|
|
5
|
+
red: "\x1B[31m",
|
|
6
|
+
green: "\x1B[32m",
|
|
7
|
+
yellow: "\x1B[33m",
|
|
8
|
+
blue: "\x1B[34m",
|
|
9
|
+
dim: "\x1B[2m",
|
|
10
|
+
bold: "\x1B[1m"
|
|
11
|
+
};
|
|
12
|
+
function resolveJsonMode(options = {}) {
|
|
13
|
+
return options.json ?? process.env["OUTFITTER_JSON"] === "1";
|
|
14
|
+
}
|
|
15
|
+
function bar(percentage, width = 20) {
|
|
16
|
+
const filled = Math.round(percentage / 100 * width);
|
|
17
|
+
const empty = width - filled;
|
|
18
|
+
const color = percentage >= 80 ? COLORS.green : percentage >= 50 ? COLORS.yellow : COLORS.red;
|
|
19
|
+
return `${color}${"\u2588".repeat(filled)}${COLORS.dim}${"\u2591".repeat(empty)}${COLORS.reset}`;
|
|
20
|
+
}
|
|
21
|
+
function printCheckTsdocHuman(result, options) {
|
|
22
|
+
process.stdout.write(`
|
|
23
|
+
${COLORS.bold}TSDoc Coverage Report${COLORS.reset}
|
|
24
|
+
|
|
25
|
+
`);
|
|
26
|
+
for (const pkg of result.packages) {
|
|
27
|
+
const color = pkg.percentage >= 80 ? COLORS.green : pkg.percentage >= 50 ? COLORS.yellow : COLORS.red;
|
|
28
|
+
process.stdout.write(` ${color}${pkg.percentage.toString().padStart(3)}%${COLORS.reset} ${bar(pkg.percentage)} ${pkg.name}
|
|
29
|
+
`);
|
|
30
|
+
if (pkg.total > 0) {
|
|
31
|
+
const parts = [];
|
|
32
|
+
if (pkg.documented > 0)
|
|
33
|
+
parts.push(`${COLORS.green}${pkg.documented} documented${COLORS.reset}`);
|
|
34
|
+
if (pkg.partial > 0)
|
|
35
|
+
parts.push(`${COLORS.yellow}${pkg.partial} partial${COLORS.reset}`);
|
|
36
|
+
if (pkg.undocumented > 0)
|
|
37
|
+
parts.push(`${COLORS.red}${pkg.undocumented} undocumented${COLORS.reset}`);
|
|
38
|
+
process.stdout.write(` ${COLORS.dim}${pkg.total} declarations:${COLORS.reset} ${parts.join(", ")}
|
|
39
|
+
`);
|
|
40
|
+
} else {
|
|
41
|
+
process.stdout.write(` ${COLORS.dim}no exported declarations${COLORS.reset}
|
|
42
|
+
`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const { summary } = result;
|
|
46
|
+
process.stdout.write(`
|
|
47
|
+
${COLORS.bold}Summary:${COLORS.reset} ${summary.percentage}% coverage (${summary.documented} documented, ${summary.partial} partial, ${summary.undocumented} undocumented of ${summary.total} total)
|
|
48
|
+
`);
|
|
49
|
+
const minCoverage = options?.minCoverage ?? 0;
|
|
50
|
+
if (options?.strict && summary.percentage < minCoverage) {
|
|
51
|
+
process.stderr.write(`
|
|
52
|
+
${COLORS.red}Coverage ${summary.percentage}% is below minimum threshold of ${minCoverage}%${COLORS.reset}
|
|
53
|
+
`);
|
|
54
|
+
}
|
|
55
|
+
process.stdout.write(`
|
|
56
|
+
`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { resolveJsonMode, printCheckTsdocHuman };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/tooling/src/cli/internal/tsdoc-types.ts
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
var coverageLevelSchema = z.enum([
|
|
5
|
+
"documented",
|
|
6
|
+
"partial",
|
|
7
|
+
"undocumented"
|
|
8
|
+
]);
|
|
9
|
+
var declarationCoverageSchema = z.object({
|
|
10
|
+
name: z.string(),
|
|
11
|
+
kind: z.string(),
|
|
12
|
+
level: coverageLevelSchema,
|
|
13
|
+
file: z.string(),
|
|
14
|
+
line: z.number()
|
|
15
|
+
});
|
|
16
|
+
var coverageSummarySchema = z.object({
|
|
17
|
+
documented: z.number(),
|
|
18
|
+
partial: z.number(),
|
|
19
|
+
undocumented: z.number(),
|
|
20
|
+
total: z.number(),
|
|
21
|
+
percentage: z.number()
|
|
22
|
+
});
|
|
23
|
+
var packageCoverageSchema = z.object({
|
|
24
|
+
name: z.string(),
|
|
25
|
+
path: z.string(),
|
|
26
|
+
declarations: z.array(declarationCoverageSchema),
|
|
27
|
+
documented: z.number(),
|
|
28
|
+
partial: z.number(),
|
|
29
|
+
undocumented: z.number(),
|
|
30
|
+
total: z.number(),
|
|
31
|
+
percentage: z.number()
|
|
32
|
+
});
|
|
33
|
+
var tsDocCheckResultSchema = z.object({
|
|
34
|
+
ok: z.boolean(),
|
|
35
|
+
packages: z.array(packageCoverageSchema),
|
|
36
|
+
summary: coverageSummarySchema
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export { coverageLevelSchema, declarationCoverageSchema, coverageSummarySchema, packageCoverageSchema, tsDocCheckResultSchema };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/** Get current git branch name */
|
|
2
|
+
declare function getCurrentBranch(): string;
|
|
3
|
+
declare function runGit(args: readonly string[]): {
|
|
4
|
+
readonly ok: boolean;
|
|
5
|
+
readonly lines: readonly string[];
|
|
6
|
+
};
|
|
7
|
+
/** Check if branch is a TDD RED phase branch */
|
|
8
|
+
declare function isRedPhaseBranch(branch: string): boolean;
|
|
9
|
+
/** Check if branch is a scaffold branch */
|
|
10
|
+
declare function isScaffoldBranch(branch: string): boolean;
|
|
11
|
+
/** Check if branch is a changeset release branch */
|
|
12
|
+
declare function isReleaseBranch(branch: string): boolean;
|
|
13
|
+
/** Determine if a file path is test-related */
|
|
14
|
+
declare function isTestOnlyPath(path: string): boolean;
|
|
15
|
+
/** Check if all paths in the list are test-related */
|
|
16
|
+
declare function areFilesTestOnly(paths: readonly string[]): boolean;
|
|
17
|
+
interface PushChangedFiles {
|
|
18
|
+
readonly files: readonly string[];
|
|
19
|
+
readonly deterministic: boolean;
|
|
20
|
+
readonly source: "upstream" | "baseRef" | "undetermined";
|
|
21
|
+
}
|
|
22
|
+
/** Check if bypass is safe: deterministic range with test-only changes */
|
|
23
|
+
declare function canBypassRedPhaseByChangedFiles(changedFiles: PushChangedFiles): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Check whether any changed files are package source files.
|
|
26
|
+
*
|
|
27
|
+
* Matches files under "packages/PKGNAME/src/" (any depth).
|
|
28
|
+
*/
|
|
29
|
+
declare function hasPackageSourceChanges(changedFiles: PushChangedFiles): boolean;
|
|
30
|
+
/** Determine which files have changed for the current push */
|
|
31
|
+
declare function getChangedFilesForPush(): PushChangedFiles;
|
|
32
|
+
/** Check if any branch in context is a RED phase branch */
|
|
33
|
+
declare function hasRedPhaseBranchInContext(currentBranch: string): boolean;
|
|
34
|
+
type ScriptMap = Readonly<Record<string, string | undefined>>;
|
|
35
|
+
type VerificationPlan = {
|
|
36
|
+
readonly ok: true;
|
|
37
|
+
readonly scripts: readonly string[];
|
|
38
|
+
readonly source: "verify:push" | "verify:ci" | "fallback";
|
|
39
|
+
} | {
|
|
40
|
+
readonly ok: false;
|
|
41
|
+
readonly error: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Derive strict pre-push verification from package scripts.
|
|
45
|
+
*
|
|
46
|
+
* Priority:
|
|
47
|
+
* 1) `verify:push`
|
|
48
|
+
* 2) `verify:ci`
|
|
49
|
+
* 3) fallback sequence: `typecheck`, `check|lint`, `build`, `test`
|
|
50
|
+
*/
|
|
51
|
+
declare function createVerificationPlan(scripts: ScriptMap): VerificationPlan;
|
|
52
|
+
/** Read and normalize scripts from package.json */
|
|
53
|
+
declare function readPackageScripts(cwd?: string): ScriptMap;
|
|
54
|
+
interface BunVersionCheckResult {
|
|
55
|
+
readonly matches: boolean;
|
|
56
|
+
readonly expected?: string;
|
|
57
|
+
readonly actual?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check that the local Bun version matches the pinned version in ".bun-version".
|
|
61
|
+
*
|
|
62
|
+
* @param projectRoot - Directory containing ".bun-version" (defaults to cwd)
|
|
63
|
+
* @returns Result indicating whether versions match
|
|
64
|
+
*/
|
|
65
|
+
declare function checkBunVersion(projectRoot?: string): BunVersionCheckResult;
|
|
66
|
+
/**
|
|
67
|
+
* Print a one-line TSDoc coverage summary across all workspace packages.
|
|
68
|
+
*
|
|
69
|
+
* Discovers package entry points ("packages/STAR/src/index.ts"), analyzes
|
|
70
|
+
* TSDoc coverage, and outputs a single summary line. This is advisory
|
|
71
|
+
* only -- the result does not affect the exit code.
|
|
72
|
+
*/
|
|
73
|
+
declare function printTsdocSummary(log: (msg: string) => void): Promise<void>;
|
|
74
|
+
export { getCurrentBranch, runGit, isRedPhaseBranch, isScaffoldBranch, isReleaseBranch, isTestOnlyPath, areFilesTestOnly, PushChangedFiles, canBypassRedPhaseByChangedFiles, hasPackageSourceChanges, getChangedFilesForPush, hasRedPhaseBranchInContext, VerificationPlan, createVerificationPlan, readPackageScripts, BunVersionCheckResult, checkBunVersion, printTsdocSummary };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/tooling/src/cli/init.ts
|
|
3
|
+
var FRAMEWORK_DETECTORS = {
|
|
4
|
+
react: ["react", "react-dom"],
|
|
5
|
+
next: ["next"],
|
|
6
|
+
vue: ["vue"],
|
|
7
|
+
nuxt: ["nuxt"],
|
|
8
|
+
svelte: ["svelte"],
|
|
9
|
+
angular: ["@angular/core"],
|
|
10
|
+
solid: ["solid-js"],
|
|
11
|
+
astro: ["astro"],
|
|
12
|
+
remix: ["@remix-run/react"],
|
|
13
|
+
qwik: ["@builder.io/qwik"]
|
|
14
|
+
};
|
|
15
|
+
function detectFrameworks(pkg) {
|
|
16
|
+
const allDeps = {
|
|
17
|
+
...pkg.dependencies,
|
|
18
|
+
...pkg.devDependencies
|
|
19
|
+
};
|
|
20
|
+
const detected = [];
|
|
21
|
+
for (const [framework, packages] of Object.entries(FRAMEWORK_DETECTORS)) {
|
|
22
|
+
if (packages.some((p) => (p in allDeps))) {
|
|
23
|
+
detected.push(framework);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (detected.length === 0) {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
return ["--frameworks", ...detected];
|
|
30
|
+
}
|
|
31
|
+
function buildUltraciteCommand(options) {
|
|
32
|
+
const cmd = [
|
|
33
|
+
"ultracite",
|
|
34
|
+
"init",
|
|
35
|
+
"--linter",
|
|
36
|
+
"oxlint",
|
|
37
|
+
"--pm",
|
|
38
|
+
"bun",
|
|
39
|
+
"--quiet"
|
|
40
|
+
];
|
|
41
|
+
if (options.frameworks && options.frameworks.length > 0) {
|
|
42
|
+
cmd.push("--frameworks", ...options.frameworks);
|
|
43
|
+
}
|
|
44
|
+
return cmd;
|
|
45
|
+
}
|
|
46
|
+
async function runInit(cwd = process.cwd()) {
|
|
47
|
+
const pkgPath = `${cwd}/package.json`;
|
|
48
|
+
const pkgFile = Bun.file(pkgPath);
|
|
49
|
+
if (!await pkgFile.exists()) {
|
|
50
|
+
process.stderr.write(`No package.json found in current directory
|
|
51
|
+
`);
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const pkg = await pkgFile.json();
|
|
56
|
+
const frameworkFlags = detectFrameworks(pkg);
|
|
57
|
+
const frameworks = frameworkFlags.length > 0 ? frameworkFlags.slice(1) : [];
|
|
58
|
+
const cmd = buildUltraciteCommand({ frameworks });
|
|
59
|
+
process.stdout.write(`Running: bun x ${cmd.join(" ")}
|
|
60
|
+
`);
|
|
61
|
+
const proc = Bun.spawn(["bun", "x", ...cmd], {
|
|
62
|
+
cwd,
|
|
63
|
+
stdio: ["inherit", "inherit", "inherit"]
|
|
64
|
+
});
|
|
65
|
+
const exitCode = await proc.exited;
|
|
66
|
+
process.exitCode = exitCode;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { detectFrameworks, buildUltraciteCommand, runInit };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/tooling/src/cli/check.ts
|
|
3
|
+
function buildCheckCommand(options) {
|
|
4
|
+
const cmd = ["ultracite", "check"];
|
|
5
|
+
if (options.paths && options.paths.length > 0) {
|
|
6
|
+
cmd.push(...options.paths);
|
|
7
|
+
}
|
|
8
|
+
return cmd;
|
|
9
|
+
}
|
|
10
|
+
async function runCheck(paths = []) {
|
|
11
|
+
const cmd = buildCheckCommand({ paths });
|
|
12
|
+
process.stdout.write(`Running: bun x ${cmd.join(" ")}
|
|
13
|
+
`);
|
|
14
|
+
const proc = Bun.spawn(["bun", "x", ...cmd], {
|
|
15
|
+
stdio: ["inherit", "inherit", "inherit"]
|
|
16
|
+
});
|
|
17
|
+
const exitCode = await proc.exited;
|
|
18
|
+
process.exitCode = exitCode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { buildCheckCommand, runCheck };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
printCheckTsdocHuman,
|
|
4
|
+
resolveJsonMode
|
|
5
|
+
} from "./tooling-5ynz680q.js";
|
|
6
|
+
import {
|
|
7
|
+
analyzeCheckTsdoc
|
|
8
|
+
} from "./tooling-5xxctk9b.js";
|
|
9
|
+
// packages/tooling/src/cli/check-tsdoc.ts
|
|
10
|
+
async function runCheckTsdoc(options = {}) {
|
|
11
|
+
const result = analyzeCheckTsdoc(options);
|
|
12
|
+
if (!result) {
|
|
13
|
+
process.stderr.write(`No packages found with src/index.ts entry points.
|
|
14
|
+
` + `Searched: packages/*/src/index.ts, apps/*/src/index.ts, src/index.ts
|
|
15
|
+
` + `Use --package <path> to specify a package path explicitly.
|
|
16
|
+
`);
|
|
17
|
+
process.exitCode = 1;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (resolveJsonMode(options)) {
|
|
21
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
22
|
+
`);
|
|
23
|
+
} else {
|
|
24
|
+
printCheckTsdocHuman(result, {
|
|
25
|
+
strict: options.strict,
|
|
26
|
+
minCoverage: options.minCoverage
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
process.exitCode = result.ok ? 0 : 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { runCheckTsdoc };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
entryToSubpath
|
|
4
|
+
} from "./tooling-ayps7c4x.js";
|
|
5
|
+
|
|
6
|
+
// packages/tooling/src/cli/internal/exports-fs.ts
|
|
7
|
+
function matchesExclude(subpath, excludes) {
|
|
8
|
+
return excludes.some((pattern) => new Bun.Glob(pattern).match(subpath));
|
|
9
|
+
}
|
|
10
|
+
var CLI_EXCLUSION_PATTERNS = [
|
|
11
|
+
"**/cli.ts",
|
|
12
|
+
"**/cli/index.ts",
|
|
13
|
+
"**/bin.ts",
|
|
14
|
+
"**/bin/index.ts"
|
|
15
|
+
];
|
|
16
|
+
function isCliEntrypoint(entry) {
|
|
17
|
+
return CLI_EXCLUSION_PATTERNS.some((pattern) => new Bun.Glob(pattern).match(entry));
|
|
18
|
+
}
|
|
19
|
+
function buildExportValue(entry) {
|
|
20
|
+
const distPath = entry.replace(/^src\//, "").replace(/\.[cm]?[jt]sx?$/, "");
|
|
21
|
+
return {
|
|
22
|
+
import: {
|
|
23
|
+
types: `./dist/${distPath}.d.ts`,
|
|
24
|
+
default: `./dist/${distPath}.js`
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function discoverEntries(packageRoot) {
|
|
29
|
+
const glob = new Bun.Glob("src/**/*.ts");
|
|
30
|
+
const entries = [];
|
|
31
|
+
for (const match of glob.scanSync({ cwd: packageRoot, dot: false })) {
|
|
32
|
+
if (match.includes("__tests__") || match.endsWith(".test.ts")) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
entries.push(match);
|
|
36
|
+
}
|
|
37
|
+
return entries.toSorted();
|
|
38
|
+
}
|
|
39
|
+
function addConfigFileExports(expected, pkg) {
|
|
40
|
+
const CONFIG_RE = /\.(json|jsonc|yml|yaml|toml)$/;
|
|
41
|
+
const configFiles = (pkg.files ?? []).filter((file) => CONFIG_RE.test(file) && file !== "package.json");
|
|
42
|
+
for (const file of configFiles) {
|
|
43
|
+
expected[`./${file}`] = `./${file}`;
|
|
44
|
+
let base = file.replace(CONFIG_RE, "");
|
|
45
|
+
const match = base.match(/^(.+)\.preset(?:\.(.+))?$/);
|
|
46
|
+
if (match?.[1]) {
|
|
47
|
+
base = match[2] ? `${match[1]}-${match[2]}` : match[1];
|
|
48
|
+
}
|
|
49
|
+
if (base !== file) {
|
|
50
|
+
expected[`./${base}`] = `./${file}`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function computeExpectedExports(packageRoot, workspace, pkg) {
|
|
55
|
+
const entries = discoverEntries(packageRoot);
|
|
56
|
+
const exportsConfig = typeof workspace.config?.exports === "object" ? workspace.config.exports : undefined;
|
|
57
|
+
const excludes = exportsConfig?.exclude ?? [];
|
|
58
|
+
const customExports = exportsConfig?.customExports ?? {};
|
|
59
|
+
const expected = {};
|
|
60
|
+
const subpathEntries = new Map;
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
if (isCliEntrypoint(entry))
|
|
63
|
+
continue;
|
|
64
|
+
const subpath = entryToSubpath(entry);
|
|
65
|
+
if (matchesExclude(subpath, excludes))
|
|
66
|
+
continue;
|
|
67
|
+
const existing = subpathEntries.get(subpath);
|
|
68
|
+
if (existing) {
|
|
69
|
+
if (!existing.endsWith("/index.ts") && entry.endsWith("/index.ts")) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
subpathEntries.set(subpath, entry);
|
|
74
|
+
}
|
|
75
|
+
for (const [subpath, entry] of subpathEntries) {
|
|
76
|
+
expected[subpath] = buildExportValue(entry);
|
|
77
|
+
}
|
|
78
|
+
for (const [key, value] of Object.entries(customExports)) {
|
|
79
|
+
expected[`./${key.replace(/^\.\//, "")}`] = value;
|
|
80
|
+
}
|
|
81
|
+
addConfigFileExports(expected, pkg);
|
|
82
|
+
expected["./package.json"] = "./package.json";
|
|
83
|
+
return expected;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export { computeExpectedExports };
|