limina 0.0.2 → 0.0.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 +4 -5
- package/chunks/{dep-jgc7X0zw.js → dep-DzYrmtQJ.js} +32 -49
- package/chunks/{dep-uPXyoC0V.js → dep-UWxsul2A.js} +179 -253
- package/cli.js +447 -84
- package/config.d.ts +1 -7
- package/config.js +1 -1
- package/index.d.ts +6 -19
- package/index.js +3 -3
- package/package.json +7 -2
package/cli.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./chunks/dep-lkQg1P9Q.js";
|
|
3
|
-
import { d as
|
|
4
|
-
import { A as shouldResolveThroughGraph$1, B as
|
|
5
|
-
import { builtinModules } from "node:module";
|
|
3
|
+
import { c as getCheckerAdapter, d as normalizeAbsolutePath, f as normalizeSlashes, g as toRelativePath, h as toPosixPath, i as loadConfig, l as normalizeExtensions, m as toAbsolutePath, n as getActiveCheckerExtensions, p as normalizeWorkspacePath, r as getActiveCheckers, u as isPathInsideDirectory } from "./chunks/dep-DzYrmtQJ.js";
|
|
4
|
+
import { A as shouldResolveThroughGraph$1, B as collectGraphProjectRoutes, C as formatArtifactDependencyPolicy, D as isRelativeSpecifier, E as isDtsProjectConfig, F as getPublishDependencySections, G as formatReferences, H as createExtensionPattern, I as isWorkspaceDependencySpecifier, J as isOrdinaryTypecheckConfigPath, K as getDtsCompanionConfigPath, L as collectCheckerEntryProjectRoutes, M as collectWorkspacePackages, N as findPackageForSpecifier, O as parseProject$1, P as getPackageRootSpecifier, Q as resolveReferencePath, R as collectGraphProjectRoute, S as findTargetProject, T as inferPackageProject$1, U as createExtraFileExtensions, V as collectSourceGraphProjectExtensions, W as createFormatHost, X as readJsonConfig, Y as parseProjectFileNamesForExtensions, Z as resolveProjectConfigPath, _ as normalizeGraphRules, a as runSourceCheck, b as findImporterForFile$1, c as GraphLogger, d as ProofLogger, f as clearCliScreen, g as getDeniedRefRule, h as getDeniedDepRuleForSpecifier, i as runCheckerTypecheck, j as collectImporters, k as resolveInternalImport$1, l as PackageLogger, m as getDeniedDepRuleForPackage, n as createLiminaFlowReporter, o as runInit, p as formatErrorMessage$1, q as getRawReferencePaths, r as runCheckerBuild, s as CliLogger, u as PathsLogger, v as collectImportsFromFile$1, w as getTypecheckConfigPath, x as findPackageForFile, y as createFileOwnerLookup$1, z as collectGraphProjectRouteFromRoot } from "./chunks/dep-UWxsul2A.js";
|
|
5
|
+
import { builtinModules, createRequire } from "node:module";
|
|
6
6
|
import { cac } from "cac";
|
|
7
7
|
import { createElapsedTimer } from "logaria/helper";
|
|
8
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import ts from "typescript";
|
|
11
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
11
|
+
import { execFile, spawn, spawnSync } from "node:child_process";
|
|
12
12
|
import { glob } from "tinyglobby";
|
|
13
13
|
import { mkdir, mkdtemp, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
14
14
|
import { checkPackage, createPackageFromTarballData } from "@arethetypeswrong/core";
|
|
15
|
-
import { pack } from "@publint/pack";
|
|
15
|
+
import { pack, unpack } from "@publint/pack";
|
|
16
16
|
import { init, parse } from "es-module-lexer";
|
|
17
17
|
import { tmpdir } from "node:os";
|
|
18
18
|
import { publint } from "publint";
|
|
@@ -112,7 +112,7 @@ function addTypecheckParityProblems(config, dtsProject, problems) {
|
|
|
112
112
|
].join("\n"));
|
|
113
113
|
return;
|
|
114
114
|
}
|
|
115
|
-
const typecheckProject = parseProject$1(config, typecheckConfigPath);
|
|
115
|
+
const typecheckProject = parseProject$1(config, typecheckConfigPath, dtsProject.extensions);
|
|
116
116
|
for (const optionName of comparableTypecheckOptions) {
|
|
117
117
|
const buildValue = dtsProject.options[optionName];
|
|
118
118
|
const typecheckValue = typecheckProject.options[optionName];
|
|
@@ -224,9 +224,9 @@ function addWorkspaceReferenceDependencyProblems(config, project, projectsByPath
|
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
async function runGraphCheckInternal(config, options = {}) {
|
|
227
|
-
const graphRoute =
|
|
228
|
-
const projectPaths = graphRoute.
|
|
229
|
-
const projects = projectPaths.map((projectPath) => parseProject$1(config, projectPath));
|
|
227
|
+
const graphRoute = collectSourceGraphProjectExtensions(config);
|
|
228
|
+
const projectPaths = [...graphRoute.projectExtensionsByPath.keys()].sort();
|
|
229
|
+
const projects = projectPaths.map((projectPath) => parseProject$1(config, projectPath, graphRoute.projectExtensionsByPath.get(projectPath)));
|
|
230
230
|
const projectsByPath = new Map(projects.map((project) => [project.configPath, project]));
|
|
231
231
|
const fileOwnerLookup = createFileOwnerLookup$1(projects);
|
|
232
232
|
const packages = await collectWorkspacePackages(config);
|
|
@@ -255,7 +255,7 @@ async function runGraphCheckInternal(config, options = {}) {
|
|
|
255
255
|
rules: graphRules
|
|
256
256
|
});
|
|
257
257
|
addWorkspaceReferenceDependencyProblems(config, project, projectsByPath, packages, importers, problems);
|
|
258
|
-
for (const filePath of project.fileNames) for (const importRecord of collectImportsFromFile$1(filePath)) {
|
|
258
|
+
for (const filePath of project.fileNames) for (const importRecord of collectImportsFromFile$1(filePath, config.rootDir)) {
|
|
259
259
|
const rawDeniedDepRule = getDeniedDepRuleForSpecifier(graphRules, project.label, importRecord.specifier);
|
|
260
260
|
if (rawDeniedDepRule) {
|
|
261
261
|
addDeniedDepImportProblem({
|
|
@@ -267,7 +267,7 @@ async function runGraphCheckInternal(config, options = {}) {
|
|
|
267
267
|
});
|
|
268
268
|
continue;
|
|
269
269
|
}
|
|
270
|
-
const resolvedFilePath = resolveInternalImport$1(importRecord.specifier, filePath, project.options);
|
|
270
|
+
const resolvedFilePath = resolveInternalImport$1(importRecord.specifier, filePath, project.options, project.extensions);
|
|
271
271
|
const targetPackage = findPackageForSpecifier(importRecord.specifier, packages);
|
|
272
272
|
const importer = findImporterForFile$1(importRecord.filePath, importers);
|
|
273
273
|
if (!resolvedFilePath) {
|
|
@@ -422,6 +422,362 @@ async function runGraphCheck(config, options = {}) {
|
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
+
//#endregion
|
|
426
|
+
//#region src/package-release-consistency.ts
|
|
427
|
+
var PackageReleaseConsistencyError = class extends Error {
|
|
428
|
+
name = "PackageReleaseConsistencyError";
|
|
429
|
+
};
|
|
430
|
+
const semver = createRequire(import.meta.url)("semver");
|
|
431
|
+
function isRecord$1(value) {
|
|
432
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
433
|
+
}
|
|
434
|
+
function isLinkDependencySpecifier(specifier) {
|
|
435
|
+
return specifier.startsWith("link:");
|
|
436
|
+
}
|
|
437
|
+
function createReleaseConsistencyState() {
|
|
438
|
+
return {
|
|
439
|
+
directWorkspaceDependencies: [],
|
|
440
|
+
edges: /* @__PURE__ */ new Map(),
|
|
441
|
+
missingWorkspaceDependencies: [],
|
|
442
|
+
packedManifestProblems: [],
|
|
443
|
+
privateWorkspaceDependencies: [],
|
|
444
|
+
registryMetadataCache: /* @__PURE__ */ new Map(),
|
|
445
|
+
registryProblems: [],
|
|
446
|
+
sourceLinkDependencies: [],
|
|
447
|
+
unpublishedPackageNames: /* @__PURE__ */ new Set(),
|
|
448
|
+
visitedPackages: /* @__PURE__ */ new Set()
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function collectPublishDependencyEntries(manifest) {
|
|
452
|
+
const entries = [];
|
|
453
|
+
for (const { dependencies, name } of getPublishDependencySections(manifest)) for (const [dependencyName, specifier] of Object.entries(dependencies)) entries.push({
|
|
454
|
+
dependencyName,
|
|
455
|
+
sectionName: name,
|
|
456
|
+
specifier
|
|
457
|
+
});
|
|
458
|
+
return entries;
|
|
459
|
+
}
|
|
460
|
+
function addEdge(edges, importerName, dependencyName) {
|
|
461
|
+
const dependencies = edges.get(importerName) ?? /* @__PURE__ */ new Set();
|
|
462
|
+
dependencies.add(dependencyName);
|
|
463
|
+
edges.set(importerName, dependencies);
|
|
464
|
+
}
|
|
465
|
+
function formatDependencyLocation(problem) {
|
|
466
|
+
const dependency = problem.dependencyName ? ` -> ${problem.dependencyName}` : "";
|
|
467
|
+
const section = problem.sectionName ? ` [${problem.sectionName}]` : "";
|
|
468
|
+
const specifier = problem.specifier ? ` (${problem.specifier})` : "";
|
|
469
|
+
return `${problem.importerName}${dependency}${section}${specifier}`;
|
|
470
|
+
}
|
|
471
|
+
function formatProblemLines(title, problems) {
|
|
472
|
+
if (problems.length === 0) return [];
|
|
473
|
+
return [
|
|
474
|
+
"",
|
|
475
|
+
title,
|
|
476
|
+
...problems.map((problem) => ` - ${formatDependencyLocation(problem)}: ${problem.message}`)
|
|
477
|
+
];
|
|
478
|
+
}
|
|
479
|
+
function getPackedDependencySpecifier(manifest, dependencyName) {
|
|
480
|
+
for (const { dependencies } of getPublishDependencySections(manifest)) {
|
|
481
|
+
const specifier = dependencies[dependencyName];
|
|
482
|
+
if (specifier) return specifier;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
function getNpmPackageMetadataUrl(packageName) {
|
|
486
|
+
return `https://registry.npmjs.org/${encodeURIComponent(packageName)}`;
|
|
487
|
+
}
|
|
488
|
+
async function fetchRegistryPackageMetadata(packageName, state) {
|
|
489
|
+
if (state.registryMetadataCache.has(packageName)) return state.registryMetadataCache.get(packageName) ?? null;
|
|
490
|
+
const response = await fetch(getNpmPackageMetadataUrl(packageName), { headers: { accept: "application/vnd.npm.install-v1+json, application/json" } });
|
|
491
|
+
if (!response.ok) {
|
|
492
|
+
state.registryMetadataCache.set(packageName, null);
|
|
493
|
+
return null;
|
|
494
|
+
}
|
|
495
|
+
const metadata = await response.json();
|
|
496
|
+
const registryMetadata = isRecord$1(metadata) ? metadata : null;
|
|
497
|
+
state.registryMetadataCache.set(packageName, registryMetadata);
|
|
498
|
+
return registryMetadata;
|
|
499
|
+
}
|
|
500
|
+
function findRegistryVersionMetadata(metadata, version) {
|
|
501
|
+
if (!isRecord$1(metadata.versions)) return null;
|
|
502
|
+
const versionMetadata = metadata.versions[version];
|
|
503
|
+
return isRecord$1(versionMetadata) ? versionMetadata : null;
|
|
504
|
+
}
|
|
505
|
+
function execGitCommand(config, args) {
|
|
506
|
+
return new Promise((resolve, reject) => {
|
|
507
|
+
execFile("git", [
|
|
508
|
+
"-C",
|
|
509
|
+
config.rootDir,
|
|
510
|
+
...args
|
|
511
|
+
], {
|
|
512
|
+
encoding: "utf8",
|
|
513
|
+
maxBuffer: 10 * 1024 * 1024
|
|
514
|
+
}, (error, stdout) => {
|
|
515
|
+
if (error) {
|
|
516
|
+
reject(error);
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
resolve(stdout);
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
async function hasWorkspacePackageChangesSinceGitHead(options) {
|
|
524
|
+
const relativeDirectory = toRelativePath(options.config.rootDir, options.workspacePackage.directory);
|
|
525
|
+
try {
|
|
526
|
+
await execGitCommand(options.config, [
|
|
527
|
+
"diff",
|
|
528
|
+
"--quiet",
|
|
529
|
+
options.gitHead,
|
|
530
|
+
"--",
|
|
531
|
+
relativeDirectory
|
|
532
|
+
]);
|
|
533
|
+
} catch (error) {
|
|
534
|
+
if (isRecord$1(error) && error.code === 1) return true;
|
|
535
|
+
throw error;
|
|
536
|
+
}
|
|
537
|
+
return (await execGitCommand(options.config, [
|
|
538
|
+
"ls-files",
|
|
539
|
+
"--others",
|
|
540
|
+
"--exclude-standard",
|
|
541
|
+
"--",
|
|
542
|
+
relativeDirectory
|
|
543
|
+
])).trim().length > 0;
|
|
544
|
+
}
|
|
545
|
+
async function verifyWorkspacePackagePublished(options) {
|
|
546
|
+
const { state, workspacePackage } = options;
|
|
547
|
+
const version = workspacePackage.manifest.version;
|
|
548
|
+
if (!version || !semver.valid(version)) {
|
|
549
|
+
state.unpublishedPackageNames.add(workspacePackage.name);
|
|
550
|
+
state.registryProblems.push({
|
|
551
|
+
importerName: workspacePackage.name,
|
|
552
|
+
message: ["workspace package must declare a valid semver version", "before another publishable package can depend on it"].join(" "),
|
|
553
|
+
packageName: workspacePackage.name
|
|
554
|
+
});
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
let metadata;
|
|
558
|
+
try {
|
|
559
|
+
metadata = await fetchRegistryPackageMetadata(workspacePackage.name, state);
|
|
560
|
+
} catch (error) {
|
|
561
|
+
state.unpublishedPackageNames.add(workspacePackage.name);
|
|
562
|
+
state.registryProblems.push({
|
|
563
|
+
importerName: workspacePackage.name,
|
|
564
|
+
message: [`unable to read npm registry metadata for ${workspacePackage.name}@${version}:`, formatErrorMessage$1(error)].join(" "),
|
|
565
|
+
packageName: workspacePackage.name
|
|
566
|
+
});
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
if (!metadata) {
|
|
570
|
+
state.unpublishedPackageNames.add(workspacePackage.name);
|
|
571
|
+
state.registryProblems.push({
|
|
572
|
+
importerName: workspacePackage.name,
|
|
573
|
+
message: `${workspacePackage.name}@${version} is not published to the npm registry`,
|
|
574
|
+
packageName: workspacePackage.name
|
|
575
|
+
});
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
const versionMetadata = findRegistryVersionMetadata(metadata, version);
|
|
579
|
+
if (!versionMetadata) {
|
|
580
|
+
state.unpublishedPackageNames.add(workspacePackage.name);
|
|
581
|
+
state.registryProblems.push({
|
|
582
|
+
importerName: workspacePackage.name,
|
|
583
|
+
message: `${workspacePackage.name}@${version} is not published to the npm registry`,
|
|
584
|
+
packageName: workspacePackage.name
|
|
585
|
+
});
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (typeof versionMetadata.gitHead !== "string" || versionMetadata.gitHead.trim().length === 0) {
|
|
589
|
+
state.unpublishedPackageNames.add(workspacePackage.name);
|
|
590
|
+
state.registryProblems.push({
|
|
591
|
+
importerName: workspacePackage.name,
|
|
592
|
+
message: [`${workspacePackage.name}@${version} registry metadata has no gitHead,`, "so limina cannot prove the published source baseline"].join(" "),
|
|
593
|
+
packageName: workspacePackage.name
|
|
594
|
+
});
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
let hasChanges;
|
|
598
|
+
try {
|
|
599
|
+
hasChanges = await hasWorkspacePackageChangesSinceGitHead({
|
|
600
|
+
config: options.config,
|
|
601
|
+
gitHead: versionMetadata.gitHead,
|
|
602
|
+
workspacePackage
|
|
603
|
+
});
|
|
604
|
+
} catch (error) {
|
|
605
|
+
state.unpublishedPackageNames.add(workspacePackage.name);
|
|
606
|
+
state.registryProblems.push({
|
|
607
|
+
importerName: workspacePackage.name,
|
|
608
|
+
message: [
|
|
609
|
+
`unable to compare ${workspacePackage.name}@${version}`,
|
|
610
|
+
`against published gitHead ${versionMetadata.gitHead}:`,
|
|
611
|
+
formatErrorMessage$1(error)
|
|
612
|
+
].join(" "),
|
|
613
|
+
packageName: workspacePackage.name
|
|
614
|
+
});
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
if (hasChanges) {
|
|
618
|
+
state.unpublishedPackageNames.add(workspacePackage.name);
|
|
619
|
+
state.registryProblems.push({
|
|
620
|
+
importerName: workspacePackage.name,
|
|
621
|
+
message: [`${workspacePackage.name}@${version} has workspace changes`, `after the published npm registry gitHead ${versionMetadata.gitHead}`].join(" "),
|
|
622
|
+
packageName: workspacePackage.name
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
async function visitWorkspacePackageDependencies(options) {
|
|
627
|
+
const { config, importerName, isRoot, manifest, state, workspacePackagesByName } = options;
|
|
628
|
+
for (const entry of collectPublishDependencyEntries(manifest)) {
|
|
629
|
+
if (isLinkDependencySpecifier(entry.specifier)) {
|
|
630
|
+
state.sourceLinkDependencies.push({
|
|
631
|
+
dependencyName: entry.dependencyName,
|
|
632
|
+
importerName,
|
|
633
|
+
message: "publishable dependency sections must not use link:",
|
|
634
|
+
sectionName: entry.sectionName,
|
|
635
|
+
specifier: entry.specifier
|
|
636
|
+
});
|
|
637
|
+
continue;
|
|
638
|
+
}
|
|
639
|
+
if (!isWorkspaceDependencySpecifier(entry.specifier)) continue;
|
|
640
|
+
const targetPackage = workspacePackagesByName.get(entry.dependencyName);
|
|
641
|
+
if (!targetPackage) {
|
|
642
|
+
state.missingWorkspaceDependencies.push({
|
|
643
|
+
dependencyName: entry.dependencyName,
|
|
644
|
+
importerName,
|
|
645
|
+
message: "workspace: publish dependency does not match a named workspace package",
|
|
646
|
+
sectionName: entry.sectionName,
|
|
647
|
+
specifier: entry.specifier
|
|
648
|
+
});
|
|
649
|
+
continue;
|
|
650
|
+
}
|
|
651
|
+
addEdge(state.edges, importerName, targetPackage.name);
|
|
652
|
+
if (isRoot) state.directWorkspaceDependencies.push({
|
|
653
|
+
dependencyName: entry.dependencyName,
|
|
654
|
+
sectionName: entry.sectionName,
|
|
655
|
+
targetPackage
|
|
656
|
+
});
|
|
657
|
+
if (targetPackage.manifest.private === true) {
|
|
658
|
+
state.privateWorkspaceDependencies.push({
|
|
659
|
+
dependencyName: entry.dependencyName,
|
|
660
|
+
importerName,
|
|
661
|
+
message: "publishable packages cannot depend on a private workspace package",
|
|
662
|
+
packageName: targetPackage.name,
|
|
663
|
+
sectionName: entry.sectionName,
|
|
664
|
+
specifier: entry.specifier
|
|
665
|
+
});
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
if (!state.visitedPackages.has(targetPackage.name)) {
|
|
669
|
+
state.visitedPackages.add(targetPackage.name);
|
|
670
|
+
await verifyWorkspacePackagePublished({
|
|
671
|
+
config,
|
|
672
|
+
state,
|
|
673
|
+
workspacePackage: targetPackage
|
|
674
|
+
});
|
|
675
|
+
await visitWorkspacePackageDependencies({
|
|
676
|
+
config,
|
|
677
|
+
importerName: targetPackage.name,
|
|
678
|
+
isRoot: false,
|
|
679
|
+
manifest: targetPackage.manifest,
|
|
680
|
+
state,
|
|
681
|
+
workspacePackagesByName
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
async function readPackedPackageJson(tarball) {
|
|
687
|
+
const unpacked = await unpack(tarball);
|
|
688
|
+
const packageJsonFile = unpacked.files.find((file) => file.name === `${unpacked.rootDir}/package.json`);
|
|
689
|
+
if (!packageJsonFile) throw new Error("packed tarball does not contain package.json");
|
|
690
|
+
return JSON.parse(Buffer.from(packageJsonFile.data).toString("utf8"));
|
|
691
|
+
}
|
|
692
|
+
function validatePackedManifest(options) {
|
|
693
|
+
const { manifest, rootPackageName, state } = options;
|
|
694
|
+
for (const entry of collectPublishDependencyEntries(manifest)) if (isWorkspaceDependencySpecifier(entry.specifier) || isLinkDependencySpecifier(entry.specifier)) state.packedManifestProblems.push({
|
|
695
|
+
dependencyName: entry.dependencyName,
|
|
696
|
+
importerName: rootPackageName,
|
|
697
|
+
message: "packed package manifest must not expose workspace: or link: dependency specifiers",
|
|
698
|
+
sectionName: entry.sectionName,
|
|
699
|
+
specifier: entry.specifier
|
|
700
|
+
});
|
|
701
|
+
for (const dependency of state.directWorkspaceDependencies) {
|
|
702
|
+
const packedSpecifier = getPackedDependencySpecifier(manifest, dependency.dependencyName);
|
|
703
|
+
if (!packedSpecifier) {
|
|
704
|
+
state.packedManifestProblems.push({
|
|
705
|
+
dependencyName: dependency.dependencyName,
|
|
706
|
+
importerName: rootPackageName,
|
|
707
|
+
message: "packed package manifest must keep every source workspace publish dependency",
|
|
708
|
+
sectionName: dependency.sectionName
|
|
709
|
+
});
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
if (isWorkspaceDependencySpecifier(packedSpecifier) || isLinkDependencySpecifier(packedSpecifier)) continue;
|
|
713
|
+
const targetVersion = dependency.targetPackage.manifest.version;
|
|
714
|
+
if (!targetVersion || !semver.satisfies(targetVersion, packedSpecifier, { includePrerelease: true })) state.packedManifestProblems.push({
|
|
715
|
+
dependencyName: dependency.dependencyName,
|
|
716
|
+
importerName: rootPackageName,
|
|
717
|
+
message: `packed dependency range must include ${dependency.targetPackage.name}@${targetVersion ?? "(missing version)"}`,
|
|
718
|
+
sectionName: dependency.sectionName,
|
|
719
|
+
specifier: packedSpecifier
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
function createPublishOrder(rootPackageName, state) {
|
|
724
|
+
const publishOrder = [];
|
|
725
|
+
const seen = /* @__PURE__ */ new Set();
|
|
726
|
+
function visit(packageName) {
|
|
727
|
+
if (seen.has(packageName)) return;
|
|
728
|
+
seen.add(packageName);
|
|
729
|
+
for (const dependencyName of state.edges.get(packageName) ?? []) visit(dependencyName);
|
|
730
|
+
if (packageName === rootPackageName || state.unpublishedPackageNames.has(packageName)) publishOrder.push(packageName);
|
|
731
|
+
}
|
|
732
|
+
visit(rootPackageName);
|
|
733
|
+
return publishOrder;
|
|
734
|
+
}
|
|
735
|
+
function createReleaseConsistencyError(options) {
|
|
736
|
+
const { config, label, outDir, rootPackageName, state } = options;
|
|
737
|
+
if (state.sourceLinkDependencies.length + state.privateWorkspaceDependencies.length + state.missingWorkspaceDependencies.length + state.registryProblems.length + state.packedManifestProblems.length === 0) return null;
|
|
738
|
+
const publishOrder = createPublishOrder(rootPackageName, state);
|
|
739
|
+
const lines = [
|
|
740
|
+
`package release dependency consistency failed for ${label}:`,
|
|
741
|
+
` output: ${toRelativePath(config.rootDir, outDir)}`,
|
|
742
|
+
...formatProblemLines("Source manifest contains local link: publish dependencies:", state.sourceLinkDependencies),
|
|
743
|
+
...formatProblemLines("Source manifest depends on private workspace packages:", state.privateWorkspaceDependencies),
|
|
744
|
+
...formatProblemLines("Source manifest has invalid workspace: publish dependencies:", state.missingWorkspaceDependencies),
|
|
745
|
+
...formatProblemLines("Workspace packages must be published before this package:", state.registryProblems),
|
|
746
|
+
...formatProblemLines("Packed package manifest is inconsistent with workspace publish dependencies:", state.packedManifestProblems)
|
|
747
|
+
];
|
|
748
|
+
if (publishOrder.length > 1) lines.push("", `Suggested publish order: ${publishOrder.join(" -> ")}`);
|
|
749
|
+
return new PackageReleaseConsistencyError(lines.join("\n"));
|
|
750
|
+
}
|
|
751
|
+
async function assertPackageReleaseConsistency(options) {
|
|
752
|
+
const workspacePackages = await collectWorkspacePackages(options.config);
|
|
753
|
+
const sourcePackage = workspacePackages.find((workspacePackage) => workspacePackage.name === options.outputManifest.name);
|
|
754
|
+
const state = createReleaseConsistencyState();
|
|
755
|
+
if (sourcePackage) {
|
|
756
|
+
state.visitedPackages.add(sourcePackage.name);
|
|
757
|
+
await visitWorkspacePackageDependencies({
|
|
758
|
+
config: options.config,
|
|
759
|
+
importerName: sourcePackage.name,
|
|
760
|
+
isRoot: true,
|
|
761
|
+
manifest: sourcePackage.manifest,
|
|
762
|
+
state,
|
|
763
|
+
workspacePackagesByName: new Map(workspacePackages.map((workspacePackage) => [workspacePackage.name, workspacePackage]))
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
validatePackedManifest({
|
|
767
|
+
manifest: await readPackedPackageJson(options.packedTarball),
|
|
768
|
+
rootPackageName: options.outputManifest.name,
|
|
769
|
+
state
|
|
770
|
+
});
|
|
771
|
+
const error = createReleaseConsistencyError({
|
|
772
|
+
config: options.config,
|
|
773
|
+
label: options.label,
|
|
774
|
+
outDir: options.outDir,
|
|
775
|
+
rootPackageName: options.outputManifest.name,
|
|
776
|
+
state
|
|
777
|
+
});
|
|
778
|
+
if (error) throw error;
|
|
779
|
+
}
|
|
780
|
+
|
|
425
781
|
//#endregion
|
|
426
782
|
//#region src/commands/package.ts
|
|
427
783
|
const DEFAULT_PACKAGE_CHECKS = [
|
|
@@ -666,13 +1022,14 @@ async function readDistPackageJson(options) {
|
|
|
666
1022
|
return JSON.parse(await readFile(options.packageJsonPath, "utf8"));
|
|
667
1023
|
}
|
|
668
1024
|
async function assertPublicPackageMetadata(options) {
|
|
669
|
-
|
|
1025
|
+
const manifest = await readDistPackageJson({
|
|
670
1026
|
config: options.config,
|
|
671
1027
|
label: options.label,
|
|
672
1028
|
packageJsonPath: options.packageJsonPath
|
|
673
|
-
})
|
|
1029
|
+
});
|
|
1030
|
+
if (manifest.private === true) return manifest;
|
|
674
1031
|
const missingFiles = REQUIRED_PUBLIC_PACKAGE_FILES.filter((fileName) => !existsSync(path.join(options.outDir, fileName)));
|
|
675
|
-
if (missingFiles.length === 0) return;
|
|
1032
|
+
if (missingFiles.length === 0) return manifest;
|
|
676
1033
|
throw new Error(`publishable package output for ${options.label} at ${toRelativePath(options.config.rootDir, options.outDir)} is missing required file(s): ${missingFiles.join(", ")}. Add them to the built output or set "private": true in the output package.json.`);
|
|
677
1034
|
}
|
|
678
1035
|
async function runPublintCheck(options) {
|
|
@@ -755,13 +1112,13 @@ async function runPackageCheckTarget(options) {
|
|
|
755
1112
|
const task = options.flow?.start(`package target: ${label}`, { depth: options.flowDepth ?? 0 });
|
|
756
1113
|
let packedDist;
|
|
757
1114
|
try {
|
|
758
|
-
await assertPublicPackageMetadata({
|
|
1115
|
+
const outputManifest = await assertPublicPackageMetadata({
|
|
759
1116
|
config: options.config,
|
|
760
1117
|
label,
|
|
761
1118
|
outDir: target.outDir,
|
|
762
1119
|
packageJsonPath: outputPackageJsonPath
|
|
763
1120
|
});
|
|
764
|
-
if (options.checks.includes("publint") || options.checks.includes("attw")) {
|
|
1121
|
+
if (outputManifest.private !== true || options.checks.includes("publint") || options.checks.includes("attw")) {
|
|
765
1122
|
const packTask = options.flow?.start(`package tarball: ${label}`, { depth: (options.flowDepth ?? 0) + 1 });
|
|
766
1123
|
PackageLogger.info(`package tarball packing started: ${label}`);
|
|
767
1124
|
const packElapsed = createElapsedTimer();
|
|
@@ -775,6 +1132,20 @@ async function runPackageCheckTarget(options) {
|
|
|
775
1132
|
if (!options.flow?.interactive) PackageLogger.success(`package tarball packed: ${label}`, packElapsed());
|
|
776
1133
|
packTask?.pass();
|
|
777
1134
|
}
|
|
1135
|
+
if (outputManifest.private !== true) try {
|
|
1136
|
+
await assertPackageReleaseConsistency({
|
|
1137
|
+
config: options.config,
|
|
1138
|
+
label,
|
|
1139
|
+
outDir: target.outDir,
|
|
1140
|
+
outputManifest,
|
|
1141
|
+
packedTarball: packedDist.tarball
|
|
1142
|
+
});
|
|
1143
|
+
} catch (error) {
|
|
1144
|
+
if (!(error instanceof PackageReleaseConsistencyError)) throw error;
|
|
1145
|
+
PackageLogger.error(formatErrorMessage$1(error));
|
|
1146
|
+
task?.fail(`package checks failed: ${label}`);
|
|
1147
|
+
return false;
|
|
1148
|
+
}
|
|
778
1149
|
let passed = true;
|
|
779
1150
|
if (options.checks.includes("publint")) passed = await runPublintCheck({
|
|
780
1151
|
flow: options.flow,
|
|
@@ -1444,6 +1815,14 @@ const ignoredSemanticCompilerOptions = new Set([
|
|
|
1444
1815
|
"sourceRoot",
|
|
1445
1816
|
"tsBuildInfoFile"
|
|
1446
1817
|
]);
|
|
1818
|
+
const typeScriptCheckerExtensions = getCheckerAdapter("tsc")?.defaultExtensions ?? [];
|
|
1819
|
+
function getFirstClassCoverageExtensions(extensions) {
|
|
1820
|
+
return normalizeExtensions([...typeScriptCheckerExtensions, ...extensions]);
|
|
1821
|
+
}
|
|
1822
|
+
function getCheckerCoverageExtensions(checker) {
|
|
1823
|
+
if (!getCheckerAdapter(checker.preset)?.sourceGraph) return checker.extensions;
|
|
1824
|
+
return getFirstClassCoverageExtensions(checker.extensions);
|
|
1825
|
+
}
|
|
1447
1826
|
async function collectTsconfigPaths(config, pattern) {
|
|
1448
1827
|
return (await glob(pattern, {
|
|
1449
1828
|
cwd: config.rootDir,
|
|
@@ -1605,24 +1984,19 @@ function addCoverage(coverageByFile, filePath, source) {
|
|
|
1605
1984
|
}
|
|
1606
1985
|
function collectCoverage(options) {
|
|
1607
1986
|
const coverageByFile = /* @__PURE__ */ new Map();
|
|
1608
|
-
const
|
|
1609
|
-
const typeScriptChecker = getActiveCheckers(options.config).find((checker) => checker.preset === "tsc");
|
|
1610
|
-
for (const graphProjectPath of options.graphProjectPaths) for (const filePath of parseProjectFileNames(options.config, graphProjectPath, proofFilePattern)) {
|
|
1987
|
+
for (const route of options.graphRoutes) for (const graphProjectPath of route.projectPaths) for (const filePath of parseProjectFileNamesForExtensions(options.config, graphProjectPath, getFirstClassCoverageExtensions(route.extensions))) {
|
|
1611
1988
|
if (!options.sourceFiles.has(filePath)) continue;
|
|
1612
1989
|
addCoverage(coverageByFile, filePath, {
|
|
1613
1990
|
label: toRelativePath(options.config.rootDir, graphProjectPath),
|
|
1614
1991
|
type: "graph"
|
|
1615
1992
|
});
|
|
1616
1993
|
}
|
|
1617
|
-
for (const checkerTarget of options.checkerTargets) {
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
type: "checker"
|
|
1624
|
-
});
|
|
1625
|
-
}
|
|
1994
|
+
for (const checkerTarget of options.checkerTargets) for (const configPath of checkerTarget.coverageConfigPaths) for (const filePath of parseProjectFileNamesForExtensions(options.config, configPath, getCheckerCoverageExtensions(checkerTarget.checker))) {
|
|
1995
|
+
if (!options.sourceFiles.has(filePath)) continue;
|
|
1996
|
+
addCoverage(coverageByFile, filePath, {
|
|
1997
|
+
label: `${toRelativePath(options.config.rootDir, configPath)} via ${checkerTarget.label}`,
|
|
1998
|
+
type: "checker"
|
|
1999
|
+
});
|
|
1626
2000
|
}
|
|
1627
2001
|
if (options.includeAllowlist !== false) for (const entry of options.allowlistEntries) {
|
|
1628
2002
|
if (!options.sourceFiles.has(entry.filePath)) continue;
|
|
@@ -1633,15 +2007,19 @@ function collectCoverage(options) {
|
|
|
1633
2007
|
}
|
|
1634
2008
|
return coverageByFile;
|
|
1635
2009
|
}
|
|
1636
|
-
function
|
|
2010
|
+
function collectProjectExtensionsByPath(routes) {
|
|
2011
|
+
const projectExtensionsByPath = /* @__PURE__ */ new Map();
|
|
2012
|
+
for (const route of routes) for (const projectPath of route.projectPaths) {
|
|
2013
|
+
const extensions = new Set([...projectExtensionsByPath.get(projectPath) ?? [], ...route.extensions]);
|
|
2014
|
+
projectExtensionsByPath.set(projectPath, [...extensions].sort());
|
|
2015
|
+
}
|
|
2016
|
+
return projectExtensionsByPath;
|
|
2017
|
+
}
|
|
2018
|
+
function parseConfig(config, configPath, extensions = []) {
|
|
1637
2019
|
const diagnostics = [];
|
|
1638
|
-
const
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
diagnostics.push(diagnostic);
|
|
1642
|
-
}
|
|
1643
|
-
});
|
|
1644
|
-
if (!parsed) throw new Error(ts.formatDiagnosticsWithColorAndContext(diagnostics, createFormatHost(config.rootDir)));
|
|
2020
|
+
const configObject = readJsonConfig(config, configPath);
|
|
2021
|
+
const parsed = ts.parseJsonConfigFileContent(configObject, ts.sys, path.dirname(configPath), {}, configPath, void 0, createExtraFileExtensions(extensions));
|
|
2022
|
+
if (diagnostics.length > 0) throw new Error(ts.formatDiagnosticsWithColorAndContext(diagnostics, createFormatHost(config.rootDir)));
|
|
1645
2023
|
if (parsed.errors.length > 0) throw new Error(ts.formatDiagnosticsWithColorAndContext(parsed.errors, createFormatHost(config.rootDir)));
|
|
1646
2024
|
return {
|
|
1647
2025
|
fileNames: parsed.fileNames.map(normalizeAbsolutePath).sort(),
|
|
@@ -1704,8 +2082,9 @@ function addDtsConfigProblems(options) {
|
|
|
1704
2082
|
].join("\n"));
|
|
1705
2083
|
continue;
|
|
1706
2084
|
}
|
|
1707
|
-
const
|
|
1708
|
-
const
|
|
2085
|
+
const extensions = options.projectExtensionsByPath.get(configPath) ?? [];
|
|
2086
|
+
const dtsConfig = parseConfig(options.config, configPath, extensions);
|
|
2087
|
+
const localConfig = parseConfig(options.config, localConfigPath, extensions);
|
|
1709
2088
|
if (dtsConfig.options.composite !== true) options.problems.push([
|
|
1710
2089
|
"DTS config is not valid for tsc -b:",
|
|
1711
2090
|
` config: ${toRelativePath(options.config.rootDir, configPath)}`,
|
|
@@ -1846,12 +2225,11 @@ function addDefaultTsconfigEnvironmentProblems(options) {
|
|
|
1846
2225
|
].join("\n"));
|
|
1847
2226
|
}
|
|
1848
2227
|
}
|
|
1849
|
-
function collectConfigFileOwners(config,
|
|
2228
|
+
function collectConfigFileOwners(config, graphRoutes, sourceFiles) {
|
|
1850
2229
|
const ownersByFile = /* @__PURE__ */ new Map();
|
|
1851
|
-
const
|
|
1852
|
-
for (const configPath of configPaths) {
|
|
2230
|
+
for (const route of graphRoutes) for (const configPath of route.projectPaths) {
|
|
1853
2231
|
if (!existsSync(configPath)) continue;
|
|
1854
|
-
for (const filePath of
|
|
2232
|
+
for (const filePath of parseProjectFileNamesForExtensions(config, configPath, route.extensions)) {
|
|
1855
2233
|
if (!sourceFiles.has(filePath)) continue;
|
|
1856
2234
|
const owners = ownersByFile.get(filePath) ?? [];
|
|
1857
2235
|
owners.push(configPath);
|
|
@@ -1873,19 +2251,6 @@ function addDuplicateGraphCoverageProblems(options) {
|
|
|
1873
2251
|
].join("\n"));
|
|
1874
2252
|
}
|
|
1875
2253
|
}
|
|
1876
|
-
function addDuplicateGraphOwnerProblems(options) {
|
|
1877
|
-
for (const [configPath, ownerCheckerNames] of options.graphOwnersByConfigPath.entries()) {
|
|
1878
|
-
const uniqueOwnerCheckerNames = [...new Set(ownerCheckerNames)].sort();
|
|
1879
|
-
if (uniqueOwnerCheckerNames.length <= 1) continue;
|
|
1880
|
-
options.problems.push([
|
|
1881
|
-
"Duplicate checker graph declaration owner:",
|
|
1882
|
-
` config: ${toRelativePath(options.config.rootDir, configPath)}`,
|
|
1883
|
-
" owned by:",
|
|
1884
|
-
...uniqueOwnerCheckerNames.map((checkerName) => ` - ${checkerName}`),
|
|
1885
|
-
" reason: each tsconfig*.dts.json must be reached by exactly one graph-capable checker entry."
|
|
1886
|
-
].join("\n"));
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
2254
|
function addAllowlistProblems(options) {
|
|
1890
2255
|
for (const entry of options.allowlistEntries) {
|
|
1891
2256
|
if (!existsSync(entry.filePath)) {
|
|
@@ -1913,34 +2278,25 @@ function addUncoveredSourceProblems(options) {
|
|
|
1913
2278
|
" reason: every file in config.source must be covered by a checker entry or an explicit allowlist entry."
|
|
1914
2279
|
].filter(Boolean).join("\n"));
|
|
1915
2280
|
}
|
|
1916
|
-
function addGraphOwner(ownersByConfigPath, configPath, checkerName) {
|
|
1917
|
-
const owners = ownersByConfigPath.get(configPath) ?? [];
|
|
1918
|
-
owners.push(checkerName);
|
|
1919
|
-
ownersByConfigPath.set(configPath, owners);
|
|
1920
|
-
}
|
|
1921
2281
|
async function runProofCheckInternal(config, options = {}) {
|
|
1922
2282
|
const problems = [];
|
|
1923
2283
|
const graphRouteCollection = collectGraphProjectRoutes(config);
|
|
1924
2284
|
const entryRouteCollection = collectCheckerEntryProjectRoutes(config);
|
|
1925
|
-
const graphProjectPaths = [...new Set(graphRouteCollection.routes.flatMap((route) => route.projectPaths))].sort();
|
|
1926
2285
|
const entryProjectPaths = [...new Set(entryRouteCollection.routes.flatMap((route) => route.projectPaths))].sort();
|
|
1927
2286
|
const entryProjectPathSet = new Set(entryProjectPaths);
|
|
2287
|
+
const entryProjectExtensionsByPath = collectProjectExtensionsByPath(entryRouteCollection.routes);
|
|
1928
2288
|
const dtsConfigPaths = await collectDtsConfigPaths(config);
|
|
1929
2289
|
const buildGraphConfigPaths = await collectBuildGraphConfigPaths(config);
|
|
1930
2290
|
const defaultTsconfigPaths = await collectDefaultTsconfigPaths(config);
|
|
1931
2291
|
const ordinaryTypecheckConfigPaths = await collectOrdinaryTypecheckConfigPaths(config);
|
|
1932
|
-
const graphOwnersByConfigPath = /* @__PURE__ */ new Map();
|
|
1933
2292
|
problems.push(...graphRouteCollection.problems);
|
|
1934
2293
|
problems.push(...entryRouteCollection.problems);
|
|
1935
|
-
for (const route of graphRouteCollection.routes) for (const projectPath of route.projectPaths) {
|
|
1936
|
-
if (!isDtsConfigPath(projectPath)) continue;
|
|
1937
|
-
addGraphOwner(graphOwnersByConfigPath, projectPath, route.checkerName);
|
|
1938
|
-
}
|
|
1939
2294
|
addDtsConfigProblems({
|
|
1940
2295
|
config,
|
|
1941
2296
|
dtsConfigPaths,
|
|
1942
2297
|
graphProjectPaths: entryProjectPathSet,
|
|
1943
|
-
problems
|
|
2298
|
+
problems,
|
|
2299
|
+
projectExtensionsByPath: entryProjectExtensionsByPath
|
|
1944
2300
|
});
|
|
1945
2301
|
addBuildGraphConfigProblems({
|
|
1946
2302
|
buildGraphConfigPaths,
|
|
@@ -1957,11 +2313,6 @@ async function runProofCheckInternal(config, options = {}) {
|
|
|
1957
2313
|
ordinaryConfigPaths: ordinaryTypecheckConfigPaths,
|
|
1958
2314
|
problems
|
|
1959
2315
|
});
|
|
1960
|
-
addDuplicateGraphOwnerProblems({
|
|
1961
|
-
config,
|
|
1962
|
-
graphOwnersByConfigPath,
|
|
1963
|
-
problems
|
|
1964
|
-
});
|
|
1965
2316
|
if (problems.length > 0) {
|
|
1966
2317
|
ProofLogger.error(problems.join("\n\n"));
|
|
1967
2318
|
return false;
|
|
@@ -1981,7 +2332,7 @@ async function runProofCheckInternal(config, options = {}) {
|
|
|
1981
2332
|
allowlistEntries,
|
|
1982
2333
|
checkerTargets,
|
|
1983
2334
|
config,
|
|
1984
|
-
|
|
2335
|
+
graphRoutes: graphRouteCollection.routes,
|
|
1985
2336
|
includeAllowlist: false,
|
|
1986
2337
|
sourceFiles
|
|
1987
2338
|
});
|
|
@@ -1989,12 +2340,12 @@ async function runProofCheckInternal(config, options = {}) {
|
|
|
1989
2340
|
allowlistEntries,
|
|
1990
2341
|
checkerTargets,
|
|
1991
2342
|
config,
|
|
1992
|
-
|
|
2343
|
+
graphRoutes: graphRouteCollection.routes,
|
|
1993
2344
|
sourceFiles
|
|
1994
2345
|
});
|
|
1995
2346
|
addDuplicateGraphCoverageProblems({
|
|
1996
2347
|
config,
|
|
1997
|
-
ownersByFile: collectConfigFileOwners(config,
|
|
2348
|
+
ownersByFile: collectConfigFileOwners(config, graphRouteCollection.routes, sourceFiles),
|
|
1998
2349
|
problems
|
|
1999
2350
|
});
|
|
2000
2351
|
addAllowlistProblems({
|
|
@@ -2061,8 +2412,26 @@ const defaultCheckPipeline = [
|
|
|
2061
2412
|
"graph:check",
|
|
2062
2413
|
"source:check",
|
|
2063
2414
|
"proof:check",
|
|
2415
|
+
"checker:build",
|
|
2064
2416
|
"checker:typecheck"
|
|
2065
2417
|
];
|
|
2418
|
+
function reportCheckerCapabilities(config, flow) {
|
|
2419
|
+
if (!flow) return;
|
|
2420
|
+
const firstClass = [];
|
|
2421
|
+
const sourceOnly = [];
|
|
2422
|
+
for (const checker of getActiveCheckers(config)) {
|
|
2423
|
+
const adapter = getCheckerAdapter(checker.preset);
|
|
2424
|
+
const label = `${checker.name} (${checker.preset})`;
|
|
2425
|
+
if (adapter?.tier === "first-class") firstClass.push(label);
|
|
2426
|
+
else if (adapter?.tier === "source-only") sourceOnly.push(label);
|
|
2427
|
+
}
|
|
2428
|
+
flow.info([
|
|
2429
|
+
"checker capability summary:",
|
|
2430
|
+
` first-class: ${firstClass.length > 0 ? firstClass.join(", ") : "(none)"}`,
|
|
2431
|
+
` source-only: ${sourceOnly.length > 0 ? sourceOnly.join(", ") : "(none)"}`,
|
|
2432
|
+
...sourceOnly.length > 0 ? [" note: source-only checkers get coverage proof and direct typecheck, but Limina does not parse their internal import graph."] : []
|
|
2433
|
+
].join("\n"), { depth: 1 });
|
|
2434
|
+
}
|
|
2066
2435
|
function isBuiltinTaskName(value) {
|
|
2067
2436
|
return builtInTaskNames.has(value);
|
|
2068
2437
|
}
|
|
@@ -2191,6 +2560,7 @@ async function runPipeline(config, pipelineName, options = {}) {
|
|
|
2191
2560
|
async function runDefaultCheck(config, options = {}) {
|
|
2192
2561
|
const normalizedSteps = defaultCheckPipeline.map(normalizePipelineStep);
|
|
2193
2562
|
const pipelineTask = options.flow?.start("default check", { collapseOnSuccess: false });
|
|
2563
|
+
reportCheckerCapabilities(config, options.flow);
|
|
2194
2564
|
for (const [stepIndex, step] of normalizedSteps.entries()) if (!(step.type === "task" ? await runBuiltinTask(config, step.name, options) : await runCommandStep(config, step, options))) {
|
|
2195
2565
|
const label = getPipelineStepLabel(step);
|
|
2196
2566
|
pipelineTask?.fail(`default check blocked at ${label}`);
|
|
@@ -2221,12 +2591,6 @@ function parsePackageAttwProfile(profile) {
|
|
|
2221
2591
|
if (profile === "strict" || profile === "node16" || profile === "esm-only") return profile;
|
|
2222
2592
|
throw new Error(`Invalid package check --attw-profile "${profile}". Expected one of: strict, node16, esm-only.`);
|
|
2223
2593
|
}
|
|
2224
|
-
function parseConcurrency(value) {
|
|
2225
|
-
if (value === void 0) return;
|
|
2226
|
-
const parsed = Number(value);
|
|
2227
|
-
if (!Number.isInteger(parsed) || parsed < 1) throw new Error("Invalid --concurrency value. Expected a positive integer.");
|
|
2228
|
-
return parsed;
|
|
2229
|
-
}
|
|
2230
2594
|
function createCliFlow() {
|
|
2231
2595
|
clearCliScreen();
|
|
2232
2596
|
return createLiminaFlowReporter();
|
|
@@ -2306,8 +2670,8 @@ async function main() {
|
|
|
2306
2670
|
if (!passed) process.exitCode = 1;
|
|
2307
2671
|
flow.outro(passed ? "limina source passed" : "limina source failed");
|
|
2308
2672
|
});
|
|
2309
|
-
cli.command("checker <action>", "Run configured checker
|
|
2310
|
-
if (action !== "typecheck" && action !== "build") throw new Error(`Unknown checker action "${action}". Expected
|
|
2673
|
+
cli.command("checker <action>", "Run configured checker build or typecheck entries").action(async (action, flags) => {
|
|
2674
|
+
if (action !== "typecheck" && action !== "build") throw new Error(`Unknown checker action "${action}". Expected build or typecheck.`);
|
|
2311
2675
|
const flow = createCliFlow();
|
|
2312
2676
|
flow.intro(`limina checker ${action}`);
|
|
2313
2677
|
if (action === "build") {
|
|
@@ -2324,7 +2688,6 @@ async function main() {
|
|
|
2324
2688
|
const result = await runCheckerTypecheck({
|
|
2325
2689
|
clearScreen: false,
|
|
2326
2690
|
config: await load(flags, "check"),
|
|
2327
|
-
concurrency: parseConcurrency(flags.concurrency),
|
|
2328
2691
|
cwd: process.cwd(),
|
|
2329
2692
|
flow
|
|
2330
2693
|
});
|