@outcomeeng/spx 0.6.18 → 0.6.19
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/dist/cli.js +1293 -742
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/cli.ts
|
|
2
|
-
import { createRequire as
|
|
2
|
+
import { createRequire as createRequire3 } from "module";
|
|
3
3
|
|
|
4
4
|
// src/interfaces/cli/program.ts
|
|
5
5
|
import { Command } from "commander";
|
|
@@ -14647,6 +14647,9 @@ function formatMissingCitedDecisionError(citedPath, citingPath) {
|
|
|
14647
14647
|
function specContextBootstrap(nodeCount) {
|
|
14648
14648
|
return nodeCount === 0;
|
|
14649
14649
|
}
|
|
14650
|
+
function compareSpecContextOrdinal(left, right) {
|
|
14651
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
14652
|
+
}
|
|
14650
14653
|
var SPEC_CONTEXT_DIGEST_ALGORITHM = "sha256";
|
|
14651
14654
|
function specContextDigest(rawBytes) {
|
|
14652
14655
|
return `${SPEC_CONTEXT_DIGEST_ALGORITHM}:${createHash4(SPEC_CONTEXT_DIGEST_ALGORITHM).update(rawBytes).digest("hex")}`;
|
|
@@ -14661,9 +14664,6 @@ function formatUnreadableContextDocumentError(path4) {
|
|
|
14661
14664
|
return `Spec context document unreadable: ${path4}`;
|
|
14662
14665
|
}
|
|
14663
14666
|
|
|
14664
|
-
// src/lib/node-status/ci-projection.ts
|
|
14665
|
-
import { parse as parseYaml3 } from "yaml";
|
|
14666
|
-
|
|
14667
14667
|
// src/lib/node-status/classify.ts
|
|
14668
14668
|
var NODE_STATUS_SCHEMA_VERSION = 1;
|
|
14669
14669
|
var NODE_STATUS_JSON_INDENT = 2;
|
|
@@ -14739,9 +14739,11 @@ function verificationPassed(verification) {
|
|
|
14739
14739
|
import { readFileSync } from "fs";
|
|
14740
14740
|
import { join as join19 } from "path";
|
|
14741
14741
|
var NODE_STATUS_EXCLUDE_FILENAME = "EXCLUDE";
|
|
14742
|
-
var
|
|
14743
|
-
|
|
14744
|
-
|
|
14742
|
+
var NODE_STATUS_EXCLUDE_PATH_GRAMMAR = {
|
|
14743
|
+
SEGMENT_SEPARATOR: "/",
|
|
14744
|
+
CURRENT_DIRECTORY_SEGMENT: ".",
|
|
14745
|
+
PARENT_DIRECTORY_SEGMENT: ".."
|
|
14746
|
+
};
|
|
14745
14747
|
function isNodeError(err) {
|
|
14746
14748
|
return err instanceof Error && "code" in err;
|
|
14747
14749
|
}
|
|
@@ -14752,14 +14754,17 @@ function parseExcludeEntries(content) {
|
|
|
14752
14754
|
return content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map(validateExcludeEntry);
|
|
14753
14755
|
}
|
|
14754
14756
|
function validateExcludeEntry(entry) {
|
|
14755
|
-
const segments = entry.split(
|
|
14756
|
-
if (entry.startsWith(
|
|
14757
|
-
(segment) => segment.length === 0 || segment === CURRENT_DIRECTORY_SEGMENT || segment === PARENT_DIRECTORY_SEGMENT
|
|
14757
|
+
const segments = entry.split(NODE_STATUS_EXCLUDE_PATH_GRAMMAR.SEGMENT_SEPARATOR);
|
|
14758
|
+
if (entry.startsWith(NODE_STATUS_EXCLUDE_PATH_GRAMMAR.SEGMENT_SEPARATOR) || segments.some(
|
|
14759
|
+
(segment) => segment.length === 0 || segment === NODE_STATUS_EXCLUDE_PATH_GRAMMAR.CURRENT_DIRECTORY_SEGMENT || segment === NODE_STATUS_EXCLUDE_PATH_GRAMMAR.PARENT_DIRECTORY_SEGMENT
|
|
14758
14760
|
)) {
|
|
14759
|
-
throw new Error(
|
|
14761
|
+
throw new Error(nodeStatusInvalidExcludeEntryMessage(entry));
|
|
14760
14762
|
}
|
|
14761
14763
|
return entry;
|
|
14762
14764
|
}
|
|
14765
|
+
function nodeStatusInvalidExcludeEntryMessage(entry) {
|
|
14766
|
+
return `Invalid ${SPEC_TREE_CONFIG.ROOT_DIRECTORY}/${NODE_STATUS_EXCLUDE_FILENAME} entry: ${entry}`;
|
|
14767
|
+
}
|
|
14763
14768
|
function createNodeStatusExcludeReader(productDir) {
|
|
14764
14769
|
let content;
|
|
14765
14770
|
try {
|
|
@@ -14961,12 +14966,14 @@ async function updateNodeStatus(options) {
|
|
|
14961
14966
|
continue;
|
|
14962
14967
|
}
|
|
14963
14968
|
const evidence = evidenceByNode.get(node.id) ?? [];
|
|
14969
|
+
const statusPath = nodeStatusPath(productDir, node.id);
|
|
14970
|
+
const committedVerification = readNodeStatus(dirname11(statusPath))?.[NODE_STATUS_FIELD.VERIFICATION];
|
|
14964
14971
|
const verification = await resolveVerification(node, {
|
|
14965
14972
|
evidence,
|
|
14966
14973
|
isExcluded: excludeReader.isExcluded(node),
|
|
14967
|
-
resolveOutcome
|
|
14974
|
+
resolveOutcome,
|
|
14975
|
+
committedOutcomes: testOutcomes(committedVerification)
|
|
14968
14976
|
});
|
|
14969
|
-
const statusPath = nodeStatusPath(productDir, node.id);
|
|
14970
14977
|
liveStatusPaths.add(statusPath);
|
|
14971
14978
|
await writeNodeStatus(statusPath, verification);
|
|
14972
14979
|
}
|
|
@@ -14977,7 +14984,8 @@ async function resolveVerification(node, input) {
|
|
|
14977
14984
|
if (input.isExcluded) return createTestVerification(input.evidence, NODE_STATUS_EVIDENCE_OUTCOME.NOT_RUN);
|
|
14978
14985
|
return createTestVerificationFromOutcomes(
|
|
14979
14986
|
input.evidence,
|
|
14980
|
-
await input.resolveOutcome(node.id, evidencePaths(input.evidence))
|
|
14987
|
+
await input.resolveOutcome(node.id, evidencePaths(input.evidence)),
|
|
14988
|
+
input.committedOutcomes
|
|
14981
14989
|
);
|
|
14982
14990
|
}
|
|
14983
14991
|
function collectEvidenceByNode(snapshot) {
|
|
@@ -14993,16 +15001,23 @@ function collectEvidenceByNode(snapshot) {
|
|
|
14993
15001
|
}
|
|
14994
15002
|
function createTestVerification(evidence, outcome) {
|
|
14995
15003
|
const outcomes = Object.fromEntries(evidence.map((entry) => [evidencePath(entry), outcome]));
|
|
14996
|
-
return createTestVerificationFromOutcomes(evidence, outcomes);
|
|
15004
|
+
return createTestVerificationFromOutcomes(evidence, outcomes, {});
|
|
14997
15005
|
}
|
|
14998
|
-
function createTestVerificationFromOutcomes(evidence, resolvedOutcomes) {
|
|
15006
|
+
function createTestVerificationFromOutcomes(evidence, resolvedOutcomes, committedOutcomes) {
|
|
14999
15007
|
const outcomes = {};
|
|
15000
15008
|
for (const entry of evidence) {
|
|
15001
15009
|
const path4 = evidencePath(entry);
|
|
15002
|
-
outcomes[path4] = resolvedOutcomes[path4] ?? NODE_STATUS_EVIDENCE_OUTCOME.NOT_RUN;
|
|
15010
|
+
outcomes[path4] = resolvedOutcomes[path4] ?? committedOutcomes[path4] ?? NODE_STATUS_EVIDENCE_OUTCOME.NOT_RUN;
|
|
15003
15011
|
}
|
|
15004
15012
|
return { [NODE_STATUS_VERIFICATION_MECHANISM.TEST]: createNodeStatusMechanismRecord(outcomes) };
|
|
15005
15013
|
}
|
|
15014
|
+
function testOutcomes(verification) {
|
|
15015
|
+
const record7 = verification?.[NODE_STATUS_VERIFICATION_MECHANISM.TEST];
|
|
15016
|
+
if (record7 === void 0) return {};
|
|
15017
|
+
return Object.fromEntries(
|
|
15018
|
+
Object.entries(record7).filter(([reference]) => reference !== NODE_STATUS_FIELD.OVERALL)
|
|
15019
|
+
);
|
|
15020
|
+
}
|
|
15006
15021
|
function evidencePaths(evidence) {
|
|
15007
15022
|
return evidence.map(evidencePath);
|
|
15008
15023
|
}
|
|
@@ -15152,7 +15167,7 @@ function resolveSpecContextTarget(snapshot, input) {
|
|
|
15152
15167
|
if (candidates.length > 1) {
|
|
15153
15168
|
return {
|
|
15154
15169
|
failure: {
|
|
15155
|
-
candidates: candidates.map(nodeSegment).sort(
|
|
15170
|
+
candidates: candidates.map(nodeSegment).sort(compareSpecContextOrdinal),
|
|
15156
15171
|
input,
|
|
15157
15172
|
kind: SPEC_CONTEXT_TARGET_FAILURE_KIND.AMBIGUOUS_SEGMENT,
|
|
15158
15173
|
segment
|
|
@@ -15201,7 +15216,7 @@ function refPath(ref) {
|
|
|
15201
15216
|
return ref?.path;
|
|
15202
15217
|
}
|
|
15203
15218
|
function sortPaths(paths) {
|
|
15204
|
-
return [...paths].sort(
|
|
15219
|
+
return [...paths].sort(compareSpecContextOrdinal);
|
|
15205
15220
|
}
|
|
15206
15221
|
function fullSpecPath(path4) {
|
|
15207
15222
|
return path4.startsWith(SPEC_TREE_ROOT_PREFIX) ? path4 : `${SPEC_TREE_ROOT_PREFIX}${path4}`;
|
|
@@ -15247,11 +15262,11 @@ function lowerIndexSiblingsForContextNodes(snapshot, contextNodes) {
|
|
|
15247
15262
|
}
|
|
15248
15263
|
}
|
|
15249
15264
|
lowerSiblings.sort((left, right) => {
|
|
15250
|
-
const parentComparison = (left.parentId ?? ""
|
|
15265
|
+
const parentComparison = compareSpecContextOrdinal(left.parentId ?? "", right.parentId ?? "");
|
|
15251
15266
|
if (parentComparison !== 0) return parentComparison;
|
|
15252
15267
|
const orderComparison = left.order - right.order;
|
|
15253
15268
|
if (orderComparison !== 0) return orderComparison;
|
|
15254
|
-
return left.id
|
|
15269
|
+
return compareSpecContextOrdinal(left.id, right.id);
|
|
15255
15270
|
});
|
|
15256
15271
|
return lowerSiblings;
|
|
15257
15272
|
}
|
|
@@ -15386,9 +15401,7 @@ async function citedDecisionDocuments(productDir, sources, knownPaths, includePa
|
|
|
15386
15401
|
}
|
|
15387
15402
|
async function localOverlayPaths(productDir, trackedPaths) {
|
|
15388
15403
|
if (trackedPaths !== void 0) {
|
|
15389
|
-
return [...trackedPaths].filter((path4) => isLocalOverlayPath(path4)).sort(
|
|
15390
|
-
(left, right) => left.localeCompare(right)
|
|
15391
|
-
);
|
|
15404
|
+
return [...trackedPaths].filter((path4) => isLocalOverlayPath(path4)).sort(compareSpecContextOrdinal);
|
|
15392
15405
|
}
|
|
15393
15406
|
let entries;
|
|
15394
15407
|
try {
|
|
@@ -15396,7 +15409,7 @@ async function localOverlayPaths(productDir, trackedPaths) {
|
|
|
15396
15409
|
} catch {
|
|
15397
15410
|
return [];
|
|
15398
15411
|
}
|
|
15399
|
-
return entries.filter((name) => name.endsWith(SPEC_TREE_GRAMMAR.LOCAL_OVERLAYS.EXTENSION)).sort(
|
|
15412
|
+
return entries.filter((name) => name.endsWith(SPEC_TREE_GRAMMAR.LOCAL_OVERLAYS.EXTENSION)).sort(compareSpecContextOrdinal).map((name) => childSpecPath(SPEC_CONTEXT_LOCAL_OVERLAY_DIRECTORY, name));
|
|
15400
15413
|
}
|
|
15401
15414
|
async function withDocumentContent(productDir, read, scannedDocuments) {
|
|
15402
15415
|
const enriched = [];
|
|
@@ -15789,7 +15802,7 @@ function groupTestFiles(testFiles, languages) {
|
|
|
15789
15802
|
|
|
15790
15803
|
// src/domains/test/targeting.ts
|
|
15791
15804
|
var TESTS_DIRECTORY_NAME3 = SPEC_TREE_EVIDENCE_FILE.DIRECTORY_NAME;
|
|
15792
|
-
var
|
|
15805
|
+
var PATH_SEGMENT_SEPARATOR2 = "/";
|
|
15793
15806
|
function normalizeTargetOperand(operand) {
|
|
15794
15807
|
return normalizePathPrefix(operand);
|
|
15795
15808
|
}
|
|
@@ -15799,7 +15812,7 @@ function matchOperand(discovered, operand, recursive) {
|
|
|
15799
15812
|
return applyPathFilter(discovered, { include: [normalized] });
|
|
15800
15813
|
}
|
|
15801
15814
|
return applyPathFilter(discovered, {
|
|
15802
|
-
include: [`${normalized}${
|
|
15815
|
+
include: [`${normalized}${PATH_SEGMENT_SEPARATOR2}${TESTS_DIRECTORY_NAME3}`]
|
|
15803
15816
|
});
|
|
15804
15817
|
}
|
|
15805
15818
|
function resolveTargetedTestFiles(discovered, selection) {
|
|
@@ -15842,7 +15855,7 @@ async function runTests(options, deps) {
|
|
|
15842
15855
|
for (const group of groups) {
|
|
15843
15856
|
const invocation = await group.language.runTests(
|
|
15844
15857
|
{
|
|
15845
|
-
|
|
15858
|
+
productDir: options.productDir,
|
|
15846
15859
|
testPaths: group.testPaths,
|
|
15847
15860
|
excludedNodePaths: runnerExcludedNodePaths
|
|
15848
15861
|
},
|
|
@@ -16470,7 +16483,7 @@ async function relatedTestPaths(sourceFiles, options, baseRef, candidateTestPath
|
|
|
16470
16483
|
if (language.relatedTestPaths === void 0) continue;
|
|
16471
16484
|
const relatedDeps = deps.relatedDepsFor(language.name);
|
|
16472
16485
|
const languageResolution = await language.relatedTestPaths(
|
|
16473
|
-
{
|
|
16486
|
+
{ productDir: options.productDir, sourcePaths: sourceFiles, candidateTestPaths: candidateTestPaths2, baseRef },
|
|
16474
16487
|
options.staged === true ? { ...relatedDeps, readFile: (path4) => readStagedFile(options.productDir, path4, deps.git) } : relatedDeps
|
|
16475
16488
|
);
|
|
16476
16489
|
for (const sourceFile of languageResolution.resolvedSourcePaths) resolved.add(sourceFile);
|
|
@@ -16877,16 +16890,6 @@ async function runTestsCommand(options, deps) {
|
|
|
16877
16890
|
);
|
|
16878
16891
|
return { dispatch, runFile, recorded };
|
|
16879
16892
|
}
|
|
16880
|
-
async function runNodeCommand(options, deps) {
|
|
16881
|
-
const recording = resolveRecordingDependencies(deps);
|
|
16882
|
-
const runFile = await reserveRunFile(options.productDir, recording);
|
|
16883
|
-
const dispatch = await runTests(
|
|
16884
|
-
{ productDir: options.productDir, registry: deps.registry, passingScope: { include: [options.nodePath] } },
|
|
16885
|
-
{ runnerDepsFor: deps.runnerDepsFor }
|
|
16886
|
-
);
|
|
16887
|
-
const recorded = await recordRun(runFile, options.productDir, dispatch, recording, deps.registry);
|
|
16888
|
-
return { dispatch, runFile, recorded };
|
|
16889
|
-
}
|
|
16890
16893
|
|
|
16891
16894
|
// src/commands/spec/node-outcome-resolver.ts
|
|
16892
16895
|
var PATH_SEPARATOR3 = "/";
|
|
@@ -16895,9 +16898,6 @@ function createNodeOutcomeResolver(deps) {
|
|
|
16895
16898
|
let evidence;
|
|
16896
16899
|
const currentInputsByCoveredPaths = /* @__PURE__ */ new Map();
|
|
16897
16900
|
const sharedEvidence = () => evidence ??= loadResolverEvidence(deps);
|
|
16898
|
-
const refreshEvidence = () => {
|
|
16899
|
-
evidence = loadResolverEvidence(deps);
|
|
16900
|
-
};
|
|
16901
16901
|
const currentInputsFor = (coveredPaths) => {
|
|
16902
16902
|
const cacheKey = coveredPathCollectionKey(coveredPaths);
|
|
16903
16903
|
const cached = currentInputsByCoveredPaths.get(cacheKey);
|
|
@@ -16912,13 +16912,13 @@ function createNodeOutcomeResolver(deps) {
|
|
|
16912
16912
|
const { discoveredTestPaths, terminalRuns } = await sharedEvidence();
|
|
16913
16913
|
const nodePath = `${SPEC_TREE_CONFIG.ROOT_DIRECTORY}${PATH_SEPARATOR3}${nodeId}`;
|
|
16914
16914
|
const nodeTestPaths = filterNodeTestPaths(discoveredTestPaths, nodePath, evidencePaths2);
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
|
|
16918
|
-
|
|
16919
|
-
|
|
16920
|
-
|
|
16921
|
-
|
|
16915
|
+
return recordedOutcomes(
|
|
16916
|
+
discoveredTestPaths,
|
|
16917
|
+
terminalRuns,
|
|
16918
|
+
evidencePaths2,
|
|
16919
|
+
nodeTestPaths,
|
|
16920
|
+
currentInputsFor
|
|
16921
|
+
);
|
|
16922
16922
|
};
|
|
16923
16923
|
}
|
|
16924
16924
|
function coveredPathCollectionKey(coveredPaths) {
|
|
@@ -16934,24 +16934,27 @@ function filterNodeTestPaths(discoveredTestPaths, nodePath, evidencePaths2) {
|
|
|
16934
16934
|
const discovered = new Set(discoveredTestPaths.filter((path4) => path4.startsWith(prefix)));
|
|
16935
16935
|
return evidencePaths2.filter((path4) => discovered.has(path4));
|
|
16936
16936
|
}
|
|
16937
|
-
async function
|
|
16938
|
-
const
|
|
16939
|
-
|
|
16940
|
-
|
|
16941
|
-
}
|
|
16942
|
-
const runCoveredPaths = latest.state.runnerOutcomes.flatMap((outcome) => outcome.testPaths);
|
|
16937
|
+
async function recordedOutcomes(discoveredTestPaths, terminalRuns, evidencePaths2, nodeTestPaths, currentInputsFor) {
|
|
16938
|
+
const resolved = Object.fromEntries(
|
|
16939
|
+
evidencePaths2.map((path4) => [path4, NODE_STATUS_EVIDENCE_OUTCOME.NOT_RUN])
|
|
16940
|
+
);
|
|
16943
16941
|
const presentTestPaths = new Set(discoveredTestPaths);
|
|
16944
|
-
|
|
16945
|
-
|
|
16942
|
+
for (const path4 of nodeTestPaths) {
|
|
16943
|
+
const latest = selectLatestTerminalTestRunForNode(terminalRuns, [path4]);
|
|
16944
|
+
if (latest === void 0) continue;
|
|
16945
|
+
const runCoveredPaths = latest.state.runnerOutcomes.flatMap((outcome) => outcome.testPaths);
|
|
16946
|
+
if (!runCoveredPaths.every((coveredPath) => presentTestPaths.has(coveredPath))) {
|
|
16947
|
+
delete resolved[path4];
|
|
16948
|
+
continue;
|
|
16949
|
+
}
|
|
16950
|
+
const current = await currentInputsFor(runCoveredPaths);
|
|
16951
|
+
if (!isStalenessMatch(extractStalenessInputs(latest.state), current)) {
|
|
16952
|
+
delete resolved[path4];
|
|
16953
|
+
continue;
|
|
16954
|
+
}
|
|
16955
|
+
resolved[path4] = outcomeForPath(latest.state.runnerOutcomes, path4);
|
|
16946
16956
|
}
|
|
16947
|
-
|
|
16948
|
-
const fresh = isStalenessMatch(extractStalenessInputs(latest.state), current);
|
|
16949
|
-
return fresh && latest.state.status === TEST_RUN_STATE_STATUS.PASSED ? outcomesForPaths(latest.state.runnerOutcomes, nodeTestPaths) : void 0;
|
|
16950
|
-
}
|
|
16951
|
-
function outcomesForPaths(outcomes, nodeTestPaths) {
|
|
16952
|
-
return Object.fromEntries(
|
|
16953
|
-
nodeTestPaths.map((path4) => [path4, outcomeForPath(outcomes, path4)])
|
|
16954
|
-
);
|
|
16957
|
+
return resolved;
|
|
16955
16958
|
}
|
|
16956
16959
|
function outcomeForPath(outcomes, path4) {
|
|
16957
16960
|
const covering = outcomes.filter((outcome) => outcome.testPaths.includes(path4));
|
|
@@ -17173,11 +17176,11 @@ function coveredProductInputPaths(coveredTestPaths2) {
|
|
|
17173
17176
|
function excludeFlag(nodePath) {
|
|
17174
17177
|
return `${PYTHON_PYTEST_IGNORE_FLAG_PREFIX}${nodePath}${PYTHON_PYTEST_IGNORE_FLAG_SUFFIX}`;
|
|
17175
17178
|
}
|
|
17176
|
-
function detect(
|
|
17177
|
-
return deps?.isLanguagePresent?.(
|
|
17179
|
+
function detect(productDir, deps) {
|
|
17180
|
+
return deps?.isLanguagePresent?.(productDir) ?? detectPython(productDir).present;
|
|
17178
17181
|
}
|
|
17179
17182
|
async function runTests2(request, deps) {
|
|
17180
|
-
if (!detect(request.
|
|
17183
|
+
if (!detect(request.productDir, deps)) {
|
|
17181
17184
|
return { invoked: false };
|
|
17182
17185
|
}
|
|
17183
17186
|
const args = [
|
|
@@ -17248,7 +17251,7 @@ function createJournalReporter(sink) {
|
|
|
17248
17251
|
async function runTestsStreaming(request, deps) {
|
|
17249
17252
|
const reporter = createJournalReporter(deps.sink);
|
|
17250
17253
|
await deps.starter.start({
|
|
17251
|
-
|
|
17254
|
+
productDir: request.productDir,
|
|
17252
17255
|
testPaths: request.testPaths,
|
|
17253
17256
|
reporters: [reporter]
|
|
17254
17257
|
});
|
|
@@ -17261,7 +17264,7 @@ function createVitestRunStarter() {
|
|
|
17261
17264
|
const priorExitCode = process.exitCode;
|
|
17262
17265
|
try {
|
|
17263
17266
|
const vitest = await startVitest("test", [...options.testPaths], {
|
|
17264
|
-
root: options.
|
|
17267
|
+
root: options.productDir,
|
|
17265
17268
|
watch: false,
|
|
17266
17269
|
reporters: [...options.reporters]
|
|
17267
17270
|
});
|
|
@@ -17310,17 +17313,17 @@ function matchesTestFile2(filePath) {
|
|
|
17310
17313
|
function excludeFlag2(nodePath) {
|
|
17311
17314
|
return `${TYPESCRIPT_VITEST_EXCLUDE_FLAG_PREFIX}${nodePath}${TYPESCRIPT_VITEST_EXCLUDE_FLAG_SUFFIX}`;
|
|
17312
17315
|
}
|
|
17313
|
-
function detect2(
|
|
17314
|
-
return deps?.isLanguagePresent?.(
|
|
17316
|
+
function detect2(productDir, deps) {
|
|
17317
|
+
return deps?.isLanguagePresent?.(productDir) ?? detectTypeScript(productDir).present;
|
|
17315
17318
|
}
|
|
17316
17319
|
async function runTests3(request, deps) {
|
|
17317
|
-
if (!detect2(request.
|
|
17320
|
+
if (!detect2(request.productDir, deps)) {
|
|
17318
17321
|
return { invoked: false };
|
|
17319
17322
|
}
|
|
17320
17323
|
const args = [
|
|
17321
17324
|
...VITEST_INVOKE_ARGS,
|
|
17322
17325
|
VITEST_ROOT_FLAG,
|
|
17323
|
-
request.
|
|
17326
|
+
request.productDir,
|
|
17324
17327
|
...request.testPaths,
|
|
17325
17328
|
...request.excludedNodePaths.map(excludeFlag2)
|
|
17326
17329
|
];
|
|
@@ -17515,7 +17518,7 @@ async function readCandidateTest(path4, deps, moduleTextCache) {
|
|
|
17515
17518
|
return loaded;
|
|
17516
17519
|
}
|
|
17517
17520
|
async function relatedTestPaths2(request, deps) {
|
|
17518
|
-
if (!detect2(request.
|
|
17521
|
+
if (!detect2(request.productDir, deps)) {
|
|
17519
17522
|
return { testPaths: [], resolvedSourcePaths: [] };
|
|
17520
17523
|
}
|
|
17521
17524
|
const sourcePaths = new Set(request.sourcePaths);
|
|
@@ -17545,7 +17548,7 @@ async function relatedTestPaths2(request, deps) {
|
|
|
17545
17548
|
return { testPaths, resolvedSourcePaths: [...resolvedSourcePaths] };
|
|
17546
17549
|
}
|
|
17547
17550
|
async function runTestsStreaming2(request, deps) {
|
|
17548
|
-
if (!detect2(request.
|
|
17551
|
+
if (!detect2(request.productDir, deps)) {
|
|
17549
17552
|
return { invoked: false };
|
|
17550
17553
|
}
|
|
17551
17554
|
const terminalStatus = await runTestsStreaming(request, {
|
|
@@ -17571,141 +17574,13 @@ var testingRegistry = {
|
|
|
17571
17574
|
languages: [typescriptTestingLanguage, pythonTestingLanguage]
|
|
17572
17575
|
};
|
|
17573
17576
|
|
|
17574
|
-
// src/interfaces/cli/test-runner-deps.ts
|
|
17575
|
-
import { createWriteStream } from "fs";
|
|
17576
|
-
import { mkdtemp as mkdtemp3, readFile as readFile12 } from "fs/promises";
|
|
17577
|
-
import { tmpdir as tmpdir3 } from "os";
|
|
17578
|
-
import { join as join28 } from "path";
|
|
17579
|
-
import { finished } from "stream/promises";
|
|
17580
|
-
var PROCESS_FAILURE_EXIT_CODE = 1;
|
|
17581
|
-
var AGENT_ARTIFACT_DIR_PREFIX = "spx-test-agent-";
|
|
17582
|
-
var STDOUT_FILE_SUFFIX = "stdout.log";
|
|
17583
|
-
var STDERR_FILE_SUFFIX = "stderr.log";
|
|
17584
|
-
var ARTIFACT_INDEX_WIDTH = 3;
|
|
17585
|
-
var ARTIFACT_INDEX_RADIX = 10;
|
|
17586
|
-
var ARTIFACT_FILE_FLAGS = "wx";
|
|
17587
|
-
var EMPTY_RUNNER_ARGS = [];
|
|
17588
|
-
function createCommandRunner(productDir, outStream) {
|
|
17589
|
-
return (command, args) => new Promise((resolveResult) => {
|
|
17590
|
-
const child = spawnManagedSubprocess(lifecycleProcessRunner, command, args, {
|
|
17591
|
-
cwd: productDir
|
|
17592
|
-
});
|
|
17593
|
-
child.stdout?.pipe(outStream);
|
|
17594
|
-
child.stderr?.pipe(process.stderr);
|
|
17595
|
-
child.on("close", (code) => resolveResult({ exitCode: code ?? PROCESS_FAILURE_EXIT_CODE }));
|
|
17596
|
-
child.on("error", () => resolveResult({ exitCode: PROCESS_FAILURE_EXIT_CODE }));
|
|
17597
|
-
});
|
|
17598
|
-
}
|
|
17599
|
-
function createRelatedCommandRunner(productDir) {
|
|
17600
|
-
return (command, args) => new Promise((resolveResult) => {
|
|
17601
|
-
const stdout = [];
|
|
17602
|
-
const stderr = [];
|
|
17603
|
-
const child = spawnManagedSubprocess(lifecycleProcessRunner, command, args, {
|
|
17604
|
-
cwd: productDir
|
|
17605
|
-
});
|
|
17606
|
-
child.stdout?.on("data", (chunk) => stdout.push(String(chunk)));
|
|
17607
|
-
child.stderr?.on("data", (chunk) => stderr.push(String(chunk)));
|
|
17608
|
-
child.on("close", (code) => resolveResult({
|
|
17609
|
-
exitCode: code ?? PROCESS_FAILURE_EXIT_CODE,
|
|
17610
|
-
stdout: stdout.join(""),
|
|
17611
|
-
stderr: stderr.join("")
|
|
17612
|
-
}));
|
|
17613
|
-
child.on("error", (error) => resolveResult({
|
|
17614
|
-
exitCode: PROCESS_FAILURE_EXIT_CODE,
|
|
17615
|
-
stdout: stdout.join(""),
|
|
17616
|
-
stderr: error.message
|
|
17617
|
-
}));
|
|
17618
|
-
});
|
|
17619
|
-
}
|
|
17620
|
-
function createRunnerDepsFor(productDir, outStream = process.stdout) {
|
|
17621
|
-
const runCommand = createCommandRunner(productDir, outStream);
|
|
17622
|
-
return () => ({ runCommand });
|
|
17623
|
-
}
|
|
17624
|
-
function createRelatedDepsFor(productDir) {
|
|
17625
|
-
const runCommand = createRelatedCommandRunner(productDir);
|
|
17626
|
-
return () => ({ runCommand, readFile: (path4) => readFile12(join28(productDir, path4), "utf8") });
|
|
17627
|
-
}
|
|
17628
|
-
function artifactFileName(index, suffix) {
|
|
17629
|
-
return `${index.toString(ARTIFACT_INDEX_RADIX).padStart(ARTIFACT_INDEX_WIDTH, "0")}-${suffix}`;
|
|
17630
|
-
}
|
|
17631
|
-
function createArtifactWriters(root, index, createArtifactWriteStream) {
|
|
17632
|
-
const stdoutPath = join28(root, artifactFileName(index, STDOUT_FILE_SUFFIX));
|
|
17633
|
-
const stderrPath = join28(root, artifactFileName(index, STDERR_FILE_SUFFIX));
|
|
17634
|
-
const stdoutFile = createArtifactWriteStream(stdoutPath);
|
|
17635
|
-
const stderrFile = createArtifactWriteStream(stderrPath);
|
|
17636
|
-
return {
|
|
17637
|
-
stdoutPath,
|
|
17638
|
-
stderrPath,
|
|
17639
|
-
stdoutFile,
|
|
17640
|
-
stderrFile,
|
|
17641
|
-
completion: Promise.all([finished(stdoutFile), finished(stderrFile)])
|
|
17642
|
-
};
|
|
17643
|
-
}
|
|
17644
|
-
async function finishArtifactWriters(writers) {
|
|
17645
|
-
writers.stdoutFile.end();
|
|
17646
|
-
writers.stderrFile.end();
|
|
17647
|
-
await writers.completion;
|
|
17648
|
-
return {
|
|
17649
|
-
stdoutPath: writers.stdoutPath,
|
|
17650
|
-
stderrPath: writers.stderrPath
|
|
17651
|
-
};
|
|
17652
|
-
}
|
|
17653
|
-
function runCapturedCommand(request) {
|
|
17654
|
-
return new Promise((resolveResult) => {
|
|
17655
|
-
let settled = false;
|
|
17656
|
-
const resolveOnce = (result) => {
|
|
17657
|
-
if (settled) return;
|
|
17658
|
-
settled = true;
|
|
17659
|
-
resolveResult(result);
|
|
17660
|
-
};
|
|
17661
|
-
const child = spawnManagedSubprocess(request.processRunner, request.command, request.args, {
|
|
17662
|
-
cwd: request.productDir,
|
|
17663
|
-
env: request.inheritedEnv
|
|
17664
|
-
});
|
|
17665
|
-
child.stdout?.pipe(request.writers.stdoutFile);
|
|
17666
|
-
child.stderr?.pipe(request.writers.stderrFile);
|
|
17667
|
-
const resolveWithExitCode = (exitCode) => {
|
|
17668
|
-
finishArtifactWriters(request.writers).then((output) => resolveOnce({ exitCode, output })).catch(() => resolveOnce({ exitCode: PROCESS_FAILURE_EXIT_CODE }));
|
|
17669
|
-
};
|
|
17670
|
-
request.writers.completion.catch(() => {
|
|
17671
|
-
child.kill();
|
|
17672
|
-
resolveOnce({ exitCode: PROCESS_FAILURE_EXIT_CODE });
|
|
17673
|
-
});
|
|
17674
|
-
child.on("close", (code) => resolveWithExitCode(code ?? PROCESS_FAILURE_EXIT_CODE));
|
|
17675
|
-
child.on("error", () => resolveWithExitCode(PROCESS_FAILURE_EXIT_CODE));
|
|
17676
|
-
});
|
|
17677
|
-
}
|
|
17678
|
-
function createAgentOutputCommandRunner(productDir, options = {}) {
|
|
17679
|
-
let artifactRoot;
|
|
17680
|
-
const processRunner = options.processRunner ?? lifecycleProcessRunner;
|
|
17681
|
-
const inheritedEnv = options.env ?? process.env;
|
|
17682
|
-
const createArtifactWriteStream = options.createArtifactWriteStream ?? ((path4) => createWriteStream(path4, { flags: ARTIFACT_FILE_FLAGS }));
|
|
17683
|
-
let nextArtifactIndex = 0;
|
|
17684
|
-
return async (command, args = EMPTY_RUNNER_ARGS) => {
|
|
17685
|
-
nextArtifactIndex += 1;
|
|
17686
|
-
artifactRoot ??= mkdtemp3(join28(options.tmpDir ?? tmpdir3(), AGENT_ARTIFACT_DIR_PREFIX));
|
|
17687
|
-
const root = await artifactRoot;
|
|
17688
|
-
return runCapturedCommand({
|
|
17689
|
-
productDir,
|
|
17690
|
-
command,
|
|
17691
|
-
args,
|
|
17692
|
-
processRunner,
|
|
17693
|
-
inheritedEnv,
|
|
17694
|
-
writers: createArtifactWriters(root, nextArtifactIndex, createArtifactWriteStream)
|
|
17695
|
-
});
|
|
17696
|
-
};
|
|
17697
|
-
}
|
|
17698
|
-
function createAgentRunnerDepsFor(productDir, options = {}) {
|
|
17699
|
-
const runCommand = createAgentOutputCommandRunner(productDir, options);
|
|
17700
|
-
return () => ({ runCommand });
|
|
17701
|
-
}
|
|
17702
|
-
|
|
17703
17577
|
// src/interfaces/cli/spec.ts
|
|
17704
17578
|
var SPEC_DOMAIN_CLI = {
|
|
17705
17579
|
COMMAND: "spec",
|
|
17706
17580
|
STATUS_COMMAND: "status",
|
|
17707
17581
|
NEXT_COMMAND: "next",
|
|
17708
17582
|
CONTEXT_COMMAND: "context",
|
|
17583
|
+
RETIRED_APPLY_COMMAND: "apply",
|
|
17709
17584
|
JSON_OPTION: "--json",
|
|
17710
17585
|
CONTENT_OPTION: "--content",
|
|
17711
17586
|
FORMAT_OPTION_FLAG: "--format",
|
|
@@ -17826,8 +17701,7 @@ function registerSpecCommands(specCmd, invocation) {
|
|
|
17826
17701
|
update: true,
|
|
17827
17702
|
resolveOutcomeFor: (productDir2) => createNodeOutcomeResolver({
|
|
17828
17703
|
productDir: productDir2,
|
|
17829
|
-
registry: testingRegistry
|
|
17830
|
-
runnerDepsFor: createRunnerDepsFor(productDir2, process.stderr)
|
|
17704
|
+
registry: testingRegistry
|
|
17831
17705
|
})
|
|
17832
17706
|
}) : await statusCommand({ cwd: productDir(), format: format2, onWarning });
|
|
17833
17707
|
writeOutput3(invocation.io, output);
|
|
@@ -17951,68 +17825,197 @@ function formatAgentTestOutput(run) {
|
|
|
17951
17825
|
return `${lines.join(NEWLINE2)}${NEWLINE2}`;
|
|
17952
17826
|
}
|
|
17953
17827
|
|
|
17954
|
-
// src/interfaces/cli/test.ts
|
|
17955
|
-
|
|
17956
|
-
|
|
17957
|
-
|
|
17958
|
-
|
|
17959
|
-
|
|
17960
|
-
|
|
17961
|
-
|
|
17962
|
-
|
|
17963
|
-
|
|
17964
|
-
|
|
17965
|
-
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
|
|
17970
|
-
|
|
17971
|
-
|
|
17972
|
-
|
|
17973
|
-
|
|
17974
|
-
|
|
17975
|
-
|
|
17976
|
-
|
|
17977
|
-
|
|
17978
|
-
var UNRESOLVED_CHANGED_SOURCE_WARNING = "No related-test capability resolved these changed source files";
|
|
17979
|
-
var TESTING_PRODUCT_DIR_WARNING = {
|
|
17980
|
-
NOT_GIT_REPOSITORY: `Warning: Not in a git repository. Reading ${SPEC_TREE_CONFIG.ROOT_DIRECTORY} tests relative to the current working directory.`
|
|
17981
|
-
};
|
|
17982
|
-
async function resolveTestProductDir(cwd, writeWarning) {
|
|
17983
|
-
const { productDir, isGitRepo } = await detectWorktreeProductRoot(cwd);
|
|
17984
|
-
writeWarning(isGitRepo ? void 0 : TESTING_PRODUCT_DIR_WARNING.NOT_GIT_REPOSITORY);
|
|
17985
|
-
return productDir;
|
|
17828
|
+
// src/interfaces/cli/test-runner-deps.ts
|
|
17829
|
+
import { createWriteStream } from "fs";
|
|
17830
|
+
import { mkdtemp as mkdtemp3, readFile as readFile12 } from "fs/promises";
|
|
17831
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
17832
|
+
import { join as join28 } from "path";
|
|
17833
|
+
import { finished } from "stream/promises";
|
|
17834
|
+
var PROCESS_FAILURE_EXIT_CODE = 1;
|
|
17835
|
+
var AGENT_ARTIFACT_DIR_PREFIX = "spx-test-agent-";
|
|
17836
|
+
var STDOUT_FILE_SUFFIX = "stdout.log";
|
|
17837
|
+
var STDERR_FILE_SUFFIX = "stderr.log";
|
|
17838
|
+
var ARTIFACT_INDEX_WIDTH = 3;
|
|
17839
|
+
var ARTIFACT_INDEX_RADIX = 10;
|
|
17840
|
+
var ARTIFACT_FILE_FLAGS = "wx";
|
|
17841
|
+
var EMPTY_RUNNER_ARGS = [];
|
|
17842
|
+
function createCommandRunner(productDir, outStream, errStream, processRunner) {
|
|
17843
|
+
return (command, args) => new Promise((resolveResult) => {
|
|
17844
|
+
const child = spawnManagedSubprocess(processRunner, command, args, {
|
|
17845
|
+
cwd: productDir
|
|
17846
|
+
});
|
|
17847
|
+
child.stdout?.pipe(outStream);
|
|
17848
|
+
child.stderr?.pipe(errStream);
|
|
17849
|
+
child.on("close", (code) => resolveResult({ exitCode: code ?? PROCESS_FAILURE_EXIT_CODE }));
|
|
17850
|
+
child.on("error", () => resolveResult({ exitCode: PROCESS_FAILURE_EXIT_CODE }));
|
|
17851
|
+
});
|
|
17986
17852
|
}
|
|
17987
|
-
|
|
17988
|
-
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
17992
|
-
|
|
17993
|
-
|
|
17994
|
-
|
|
17995
|
-
|
|
17996
|
-
)
|
|
17997
|
-
|
|
17998
|
-
|
|
17999
|
-
|
|
18000
|
-
|
|
18001
|
-
|
|
17853
|
+
function createRelatedCommandRunner(productDir, processRunner) {
|
|
17854
|
+
return (command, args) => new Promise((resolveResult) => {
|
|
17855
|
+
const stdout = [];
|
|
17856
|
+
const stderr = [];
|
|
17857
|
+
const child = spawnManagedSubprocess(processRunner, command, args, {
|
|
17858
|
+
cwd: productDir
|
|
17859
|
+
});
|
|
17860
|
+
child.stdout?.on("data", (chunk) => stdout.push(String(chunk)));
|
|
17861
|
+
child.stderr?.on("data", (chunk) => stderr.push(String(chunk)));
|
|
17862
|
+
child.on("close", (code) => resolveResult({
|
|
17863
|
+
exitCode: code ?? PROCESS_FAILURE_EXIT_CODE,
|
|
17864
|
+
stdout: stdout.join(""),
|
|
17865
|
+
stderr: stderr.join("")
|
|
17866
|
+
}));
|
|
17867
|
+
child.on("error", (error) => resolveResult({
|
|
17868
|
+
exitCode: PROCESS_FAILURE_EXIT_CODE,
|
|
17869
|
+
stdout: stdout.join(""),
|
|
17870
|
+
stderr: error.message
|
|
17871
|
+
}));
|
|
17872
|
+
});
|
|
18002
17873
|
}
|
|
18003
|
-
|
|
18004
|
-
|
|
18005
|
-
|
|
18006
|
-
|
|
18007
|
-
|
|
18008
|
-
|
|
18009
|
-
|
|
18010
|
-
|
|
18011
|
-
|
|
18012
|
-
|
|
18013
|
-
|
|
18014
|
-
|
|
18015
|
-
|
|
17874
|
+
function createRunnerDepsFor(productDir, outStream = process.stdout, processRunner = lifecycleProcessRunner, errStream = process.stderr) {
|
|
17875
|
+
const runCommand = createCommandRunner(productDir, outStream, errStream, processRunner);
|
|
17876
|
+
return () => ({ runCommand });
|
|
17877
|
+
}
|
|
17878
|
+
function createRelatedDepsFor(productDir, processRunner = lifecycleProcessRunner) {
|
|
17879
|
+
const runCommand = createRelatedCommandRunner(productDir, processRunner);
|
|
17880
|
+
return () => ({ runCommand, readFile: (path4) => readFile12(join28(productDir, path4), "utf8") });
|
|
17881
|
+
}
|
|
17882
|
+
function artifactFileName(index, suffix) {
|
|
17883
|
+
return `${index.toString(ARTIFACT_INDEX_RADIX).padStart(ARTIFACT_INDEX_WIDTH, "0")}-${suffix}`;
|
|
17884
|
+
}
|
|
17885
|
+
function createArtifactWriters(root, index, createArtifactWriteStream) {
|
|
17886
|
+
const stdoutPath = join28(root, artifactFileName(index, STDOUT_FILE_SUFFIX));
|
|
17887
|
+
const stderrPath = join28(root, artifactFileName(index, STDERR_FILE_SUFFIX));
|
|
17888
|
+
const stdoutFile = createArtifactWriteStream(stdoutPath);
|
|
17889
|
+
const stderrFile = createArtifactWriteStream(stderrPath);
|
|
17890
|
+
return {
|
|
17891
|
+
stdoutPath,
|
|
17892
|
+
stderrPath,
|
|
17893
|
+
stdoutFile,
|
|
17894
|
+
stderrFile,
|
|
17895
|
+
completion: Promise.all([finished(stdoutFile), finished(stderrFile)])
|
|
17896
|
+
};
|
|
17897
|
+
}
|
|
17898
|
+
async function finishArtifactWriters(writers) {
|
|
17899
|
+
writers.stdoutFile.end();
|
|
17900
|
+
writers.stderrFile.end();
|
|
17901
|
+
await writers.completion;
|
|
17902
|
+
return {
|
|
17903
|
+
stdoutPath: writers.stdoutPath,
|
|
17904
|
+
stderrPath: writers.stderrPath
|
|
17905
|
+
};
|
|
17906
|
+
}
|
|
17907
|
+
function runCapturedCommand(request) {
|
|
17908
|
+
return new Promise((resolveResult) => {
|
|
17909
|
+
let settled = false;
|
|
17910
|
+
const resolveOnce = (result) => {
|
|
17911
|
+
if (settled) return;
|
|
17912
|
+
settled = true;
|
|
17913
|
+
resolveResult(result);
|
|
17914
|
+
};
|
|
17915
|
+
const child = spawnManagedSubprocess(request.processRunner, request.command, request.args, {
|
|
17916
|
+
cwd: request.productDir,
|
|
17917
|
+
env: request.inheritedEnv
|
|
17918
|
+
});
|
|
17919
|
+
child.stdout?.pipe(request.writers.stdoutFile);
|
|
17920
|
+
child.stderr?.pipe(request.writers.stderrFile);
|
|
17921
|
+
const resolveWithExitCode = (exitCode) => {
|
|
17922
|
+
finishArtifactWriters(request.writers).then((output) => resolveOnce({ exitCode, output })).catch(() => resolveOnce({ exitCode: PROCESS_FAILURE_EXIT_CODE }));
|
|
17923
|
+
};
|
|
17924
|
+
request.writers.completion.catch(() => {
|
|
17925
|
+
child.kill();
|
|
17926
|
+
resolveOnce({ exitCode: PROCESS_FAILURE_EXIT_CODE });
|
|
17927
|
+
});
|
|
17928
|
+
child.on("close", (code) => resolveWithExitCode(code ?? PROCESS_FAILURE_EXIT_CODE));
|
|
17929
|
+
child.on("error", () => resolveWithExitCode(PROCESS_FAILURE_EXIT_CODE));
|
|
17930
|
+
});
|
|
17931
|
+
}
|
|
17932
|
+
function createAgentOutputCommandRunner(productDir, options = {}) {
|
|
17933
|
+
let artifactRoot;
|
|
17934
|
+
const processRunner = options.processRunner ?? lifecycleProcessRunner;
|
|
17935
|
+
const inheritedEnv = options.env ?? process.env;
|
|
17936
|
+
const createArtifactWriteStream = options.createArtifactWriteStream ?? ((path4) => createWriteStream(path4, { flags: ARTIFACT_FILE_FLAGS }));
|
|
17937
|
+
let nextArtifactIndex = 0;
|
|
17938
|
+
return async (command, args = EMPTY_RUNNER_ARGS) => {
|
|
17939
|
+
nextArtifactIndex += 1;
|
|
17940
|
+
artifactRoot ??= mkdtemp3(join28(options.tmpDir ?? tmpdir3(), AGENT_ARTIFACT_DIR_PREFIX));
|
|
17941
|
+
const root = await artifactRoot;
|
|
17942
|
+
return runCapturedCommand({
|
|
17943
|
+
productDir,
|
|
17944
|
+
command,
|
|
17945
|
+
args,
|
|
17946
|
+
processRunner,
|
|
17947
|
+
inheritedEnv,
|
|
17948
|
+
writers: createArtifactWriters(root, nextArtifactIndex, createArtifactWriteStream)
|
|
17949
|
+
});
|
|
17950
|
+
};
|
|
17951
|
+
}
|
|
17952
|
+
function createAgentRunnerDepsFor(productDir, options = {}) {
|
|
17953
|
+
const runCommand = createAgentOutputCommandRunner(productDir, options);
|
|
17954
|
+
return () => ({ runCommand });
|
|
17955
|
+
}
|
|
17956
|
+
|
|
17957
|
+
// src/interfaces/cli/test.ts
|
|
17958
|
+
var TESTING_CLI = {
|
|
17959
|
+
commandName: "test",
|
|
17960
|
+
description: "Run spec-tree tests across product languages",
|
|
17961
|
+
agentOption: "--agent",
|
|
17962
|
+
agentDescription: "Capture raw runner output and print a compact agent summary",
|
|
17963
|
+
recursiveShortFlag: "-r",
|
|
17964
|
+
recursiveLongFlag: "--recursive",
|
|
17965
|
+
recursiveDescription: "Extend a node-path operand to its descendant nodes' tests",
|
|
17966
|
+
changedLongFlag: "--changed",
|
|
17967
|
+
changedDescription: "Run only tests affected by changes against the selected base",
|
|
17968
|
+
stagedLongFlag: "--staged",
|
|
17969
|
+
stagedDescription: "With --changed, diff the staged snapshot instead of the worktree",
|
|
17970
|
+
baseLongFlag: "--base",
|
|
17971
|
+
baseOperand: "<ref>",
|
|
17972
|
+
baseDescription: "Base ref for --changed; defaults to origin of the default branch",
|
|
17973
|
+
targetsArgument: "[targets...]",
|
|
17974
|
+
targetsDescription: "Node paths or test-file paths to run; omit to run the full discovered suite",
|
|
17975
|
+
passingSubcommand: "passing",
|
|
17976
|
+
passingDescription: "Run only the tests within the configured passing scope"
|
|
17977
|
+
};
|
|
17978
|
+
var UNMATCHED_TEST_FILES_WARNING = "Skipped test files with no registered runner";
|
|
17979
|
+
var GATED_TEST_RUNNERS_WARNING = "Skipped test files because their registered runner was gated out";
|
|
17980
|
+
var UNRESOLVED_TARGETS_WARNING = "No tests matched these operands";
|
|
17981
|
+
var UNRESOLVED_CHANGED_SOURCE_WARNING = "No related-test capability resolved these changed source files";
|
|
17982
|
+
var TESTING_PRODUCT_DIR_WARNING = {
|
|
17983
|
+
NOT_GIT_REPOSITORY: `Warning: Not in a git repository. Reading ${SPEC_TREE_CONFIG.ROOT_DIRECTORY} tests relative to the current working directory.`
|
|
17984
|
+
};
|
|
17985
|
+
async function resolveTestProductDir(cwd, writeWarning) {
|
|
17986
|
+
const { productDir, isGitRepo } = await detectWorktreeProductRoot(cwd);
|
|
17987
|
+
writeWarning(isGitRepo ? void 0 : TESTING_PRODUCT_DIR_WARNING.NOT_GIT_REPOSITORY);
|
|
17988
|
+
return productDir;
|
|
17989
|
+
}
|
|
17990
|
+
async function runTestsThroughCommand(productDir, passing, io, targets, changed) {
|
|
17991
|
+
try {
|
|
17992
|
+
return await runTestsCommand(
|
|
17993
|
+
{ productDir, passing, targets, changed },
|
|
17994
|
+
{
|
|
17995
|
+
registry: testingRegistry,
|
|
17996
|
+
runnerDepsFor: createRunnerDepsFor(productDir),
|
|
17997
|
+
relatedDepsFor: createRelatedDepsFor(productDir)
|
|
17998
|
+
}
|
|
17999
|
+
);
|
|
18000
|
+
} catch (error) {
|
|
18001
|
+
io.writeStderr(`${error instanceof Error ? error.message : String(error)}
|
|
18002
|
+
`);
|
|
18003
|
+
io.exit(PROCESS_FAILURE_EXIT_CODE);
|
|
18004
|
+
}
|
|
18005
|
+
}
|
|
18006
|
+
async function runAgentTestsThroughCommand(productDir, passing, io, targets, changed) {
|
|
18007
|
+
try {
|
|
18008
|
+
return await runTestsCommand(
|
|
18009
|
+
{ productDir, passing, targets, changed },
|
|
18010
|
+
{
|
|
18011
|
+
registry: testingRegistry,
|
|
18012
|
+
runnerDepsFor: createAgentRunnerDepsFor(productDir),
|
|
18013
|
+
relatedDepsFor: createRelatedDepsFor(productDir)
|
|
18014
|
+
}
|
|
18015
|
+
);
|
|
18016
|
+
} catch (error) {
|
|
18017
|
+
io.writeStderr(`${error instanceof Error ? error.message : String(error)}
|
|
18018
|
+
`);
|
|
18016
18019
|
io.exit(PROCESS_FAILURE_EXIT_CODE);
|
|
18017
18020
|
}
|
|
18018
18021
|
}
|
|
@@ -18138,6 +18141,12 @@ var testingDomain = createTestingDomain();
|
|
|
18138
18141
|
import { existsSync as existsSync9, realpathSync } from "fs";
|
|
18139
18142
|
import { relative as relative11, resolve as resolve16 } from "path";
|
|
18140
18143
|
|
|
18144
|
+
// src/validation/languages/types.ts
|
|
18145
|
+
var VALIDATION_STAGE_PARTICIPATION = {
|
|
18146
|
+
RUN: "run",
|
|
18147
|
+
SKIP: "skip"
|
|
18148
|
+
};
|
|
18149
|
+
|
|
18141
18150
|
// src/commands/validation/formatting.ts
|
|
18142
18151
|
import { existsSync, statSync } from "fs";
|
|
18143
18152
|
import { isAbsolute as isAbsolute6, join as join29, relative as relative6 } from "path";
|
|
@@ -18153,8 +18162,8 @@ function unique(values) {
|
|
|
18153
18162
|
function nonEmpty(values) {
|
|
18154
18163
|
return values?.filter((value) => value.length > 0) ?? [];
|
|
18155
18164
|
}
|
|
18156
|
-
function
|
|
18157
|
-
return isAbsolute5(path4) ? relative5(
|
|
18165
|
+
function toProductRelativeValidationPath(productDir, path4) {
|
|
18166
|
+
return isAbsolute5(path4) ? relative5(productDir, path4) : path4;
|
|
18158
18167
|
}
|
|
18159
18168
|
function intersectIncludes(baseInclude, toolInclude) {
|
|
18160
18169
|
const base = nonEmpty(baseInclude);
|
|
@@ -18259,6 +18268,9 @@ function applyValidationPathFilterToScope(scopeConfig, filter) {
|
|
|
18259
18268
|
};
|
|
18260
18269
|
}
|
|
18261
18270
|
|
|
18271
|
+
// src/validation/steps/formatting.ts
|
|
18272
|
+
import { createRequire } from "module";
|
|
18273
|
+
|
|
18262
18274
|
// src/validation/steps/subprocess-output.ts
|
|
18263
18275
|
var VALIDATION_SUBPROCESS_EVENTS = {
|
|
18264
18276
|
CLOSE: "close",
|
|
@@ -18270,6 +18282,13 @@ var defaultValidationSubprocessOutputStreams = {
|
|
|
18270
18282
|
stdout: process.stdout,
|
|
18271
18283
|
stderr: process.stderr
|
|
18272
18284
|
};
|
|
18285
|
+
var discardValidationSubprocessOutputStream = {
|
|
18286
|
+
write: () => true
|
|
18287
|
+
};
|
|
18288
|
+
var discardValidationSubprocessOutputStreams = {
|
|
18289
|
+
stdout: discardValidationSubprocessOutputStream,
|
|
18290
|
+
stderr: discardValidationSubprocessOutputStream
|
|
18291
|
+
};
|
|
18273
18292
|
function forwardValidationSubprocessOutput(child, streams = defaultValidationSubprocessOutputStreams) {
|
|
18274
18293
|
child.stdout?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, (chunk) => {
|
|
18275
18294
|
forwardChunkWithBackpressure(child.stdout, streams.stdout, chunk);
|
|
@@ -18290,7 +18309,12 @@ function forwardChunkWithBackpressure(source, stream, chunk) {
|
|
|
18290
18309
|
}
|
|
18291
18310
|
|
|
18292
18311
|
// src/validation/steps/formatting.ts
|
|
18293
|
-
var
|
|
18312
|
+
var DPRINT_EXECUTABLE_SPECIFIER = "dprint/bin.cjs";
|
|
18313
|
+
var cachedDprintCommand;
|
|
18314
|
+
function resolveDprintCommand() {
|
|
18315
|
+
cachedDprintCommand ??= createRequire(import.meta.url).resolve(DPRINT_EXECUTABLE_SPECIFIER);
|
|
18316
|
+
return cachedDprintCommand;
|
|
18317
|
+
}
|
|
18294
18318
|
var DPRINT_CHECK_SUBCOMMAND = "check";
|
|
18295
18319
|
var DPRINT_EXCLUDES_OPTION = "--excludes";
|
|
18296
18320
|
var DPRINT_OPTIONS_TERMINATOR = "--";
|
|
@@ -18306,16 +18330,17 @@ function buildDprintCheckArgs(options) {
|
|
|
18306
18330
|
...files
|
|
18307
18331
|
];
|
|
18308
18332
|
}
|
|
18309
|
-
async function validateFormatting(context, runner = defaultFormattingProcessRunner) {
|
|
18333
|
+
async function validateFormatting(context, runner = defaultFormattingProcessRunner, outputStreams) {
|
|
18310
18334
|
const args = buildDprintCheckArgs({ files: context.files, excludes: context.excludes });
|
|
18311
18335
|
return new Promise((resolve17) => {
|
|
18312
|
-
const child = spawnManagedSubprocess(runner,
|
|
18336
|
+
const child = spawnManagedSubprocess(runner, resolveDprintCommand(), args, { cwd: context.productDir });
|
|
18313
18337
|
const chunks = [];
|
|
18314
18338
|
const capture = (chunk) => {
|
|
18315
18339
|
chunks.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString());
|
|
18316
18340
|
};
|
|
18317
18341
|
child.stdout?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, capture);
|
|
18318
18342
|
child.stderr?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, capture);
|
|
18343
|
+
forwardValidationSubprocessOutput(child, outputStreams);
|
|
18319
18344
|
child.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {
|
|
18320
18345
|
resolve17({ success: code === 0, output: chunks.join("") });
|
|
18321
18346
|
});
|
|
@@ -18337,59 +18362,140 @@ var VALIDATION_STAGE_DISPLAY_NAMES = {
|
|
|
18337
18362
|
};
|
|
18338
18363
|
var VALIDATION_SKIP_LABELS = {
|
|
18339
18364
|
VERB: "Skipping",
|
|
18340
|
-
CIRCULAR_REASON: "skip-circular",
|
|
18341
|
-
LITERAL_REASON: "skip-literal",
|
|
18342
18365
|
DISABLED_BY_PREFIX: "disabled by",
|
|
18343
|
-
TYPESCRIPT_ABSENT_REASON: "TypeScript not detected in
|
|
18366
|
+
TYPESCRIPT_ABSENT_REASON: "TypeScript not detected in product",
|
|
18344
18367
|
VALIDATION_PATHS_NO_TARGETS_REASON: "validation paths matched no files",
|
|
18368
|
+
EXPLICIT_PATHS_NO_TARGETS_REASON: "explicit paths matched no files in tool scope",
|
|
18345
18369
|
MARKDOWN_NO_SCOPE_REASON: "no markdown files in explicit path scope",
|
|
18346
18370
|
MARKDOWN_NO_DEFAULT_DIRECTORIES_REASON: "no spx/ or docs/ directories found"
|
|
18347
18371
|
};
|
|
18372
|
+
var VALIDATION_STREAMED_STAGE_RESULT = "output streamed";
|
|
18373
|
+
var VALIDATION_PROBLEM_TERMS = {
|
|
18374
|
+
SINGULAR: "problem",
|
|
18375
|
+
PLURAL: "problems"
|
|
18376
|
+
};
|
|
18377
|
+
function formatValidationNoProblemsMessage(stageName) {
|
|
18378
|
+
return `${stageName}: \u2713 No ${VALIDATION_PROBLEM_TERMS.PLURAL}`;
|
|
18379
|
+
}
|
|
18380
|
+
function formatValidationProblemsFoundMessage(stageName, options = {}) {
|
|
18381
|
+
const countPrefix = options.count === void 0 ? "" : `${options.count} `;
|
|
18382
|
+
const term = options.count === 1 ? VALIDATION_PROBLEM_TERMS.SINGULAR : VALIDATION_PROBLEM_TERMS.PLURAL;
|
|
18383
|
+
const detailSuffix = options.detail === void 0 ? "" : ` (${options.detail})`;
|
|
18384
|
+
return `${stageName}: ${countPrefix}${term} found${detailSuffix}`;
|
|
18385
|
+
}
|
|
18386
|
+
function formatValidationConfigProblemMessage(stageName, detail) {
|
|
18387
|
+
return formatValidationProblemsFoundMessage(stageName, { count: 1, detail });
|
|
18388
|
+
}
|
|
18389
|
+
var VALIDATION_STAGE_PROBLEM_MESSAGES = {
|
|
18390
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR]: {
|
|
18391
|
+
clear: formatValidationNoProblemsMessage(VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR),
|
|
18392
|
+
attention: formatValidationProblemsFoundMessage(VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR, {
|
|
18393
|
+
detail: "circular dependencies"
|
|
18394
|
+
})
|
|
18395
|
+
},
|
|
18396
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.KNIP]: {
|
|
18397
|
+
clear: formatValidationNoProblemsMessage(VALIDATION_STAGE_DISPLAY_NAMES.KNIP),
|
|
18398
|
+
attention: formatValidationProblemsFoundMessage(VALIDATION_STAGE_DISPLAY_NAMES.KNIP, {
|
|
18399
|
+
detail: "unused code"
|
|
18400
|
+
})
|
|
18401
|
+
},
|
|
18402
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.ESLINT]: {
|
|
18403
|
+
clear: formatValidationNoProblemsMessage(VALIDATION_STAGE_DISPLAY_NAMES.ESLINT),
|
|
18404
|
+
attention: formatValidationProblemsFoundMessage(VALIDATION_STAGE_DISPLAY_NAMES.ESLINT)
|
|
18405
|
+
},
|
|
18406
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT]: {
|
|
18407
|
+
clear: formatValidationNoProblemsMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT),
|
|
18408
|
+
attention: formatValidationProblemsFoundMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT)
|
|
18409
|
+
},
|
|
18410
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN]: {
|
|
18411
|
+
clear: formatValidationNoProblemsMessage(VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN),
|
|
18412
|
+
attention: formatValidationProblemsFoundMessage(VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN)
|
|
18413
|
+
},
|
|
18414
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.LITERAL]: {
|
|
18415
|
+
clear: formatValidationNoProblemsMessage(VALIDATION_STAGE_DISPLAY_NAMES.LITERAL),
|
|
18416
|
+
attention: formatValidationProblemsFoundMessage(VALIDATION_STAGE_DISPLAY_NAMES.LITERAL)
|
|
18417
|
+
},
|
|
18418
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING]: {
|
|
18419
|
+
clear: formatValidationNoProblemsMessage(VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING),
|
|
18420
|
+
attention: formatValidationProblemsFoundMessage(VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING, {
|
|
18421
|
+
detail: "unformatted files"
|
|
18422
|
+
})
|
|
18423
|
+
}
|
|
18424
|
+
};
|
|
18348
18425
|
var VALIDATION_COMMAND_OUTPUT = {
|
|
18349
|
-
CIRCULAR_FOUND:
|
|
18350
|
-
CIRCULAR_NONE_FOUND:
|
|
18351
|
-
KNIP_CONFIG_ERROR:
|
|
18426
|
+
CIRCULAR_FOUND: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR].attention,
|
|
18427
|
+
CIRCULAR_NONE_FOUND: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR].clear,
|
|
18428
|
+
KNIP_CONFIG_ERROR: formatValidationConfigProblemMessage(
|
|
18429
|
+
VALIDATION_STAGE_DISPLAY_NAMES.KNIP,
|
|
18430
|
+
"configuration error"
|
|
18431
|
+
),
|
|
18352
18432
|
KNIP_DISABLED: `${VALIDATION_STAGE_DISPLAY_NAMES.KNIP}: skipped (${VALIDATION_SKIP_LABELS.DISABLED_BY_PREFIX} validation.knip.enabled)`,
|
|
18353
|
-
KNIP_SUCCESS:
|
|
18354
|
-
KNIP_FAILURE:
|
|
18355
|
-
ESLINT_SUCCESS:
|
|
18356
|
-
ESLINT_FAILURE:
|
|
18357
|
-
ESLINT_MISSING_CONFIG:
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18365
|
-
|
|
18366
|
-
|
|
18367
|
-
|
|
18368
|
-
|
|
18369
|
-
}
|
|
18370
|
-
|
|
18371
|
-
|
|
18372
|
-
|
|
18373
|
-
reason: VALIDATION_SKIP_LABELS.LITERAL_REASON
|
|
18374
|
-
});
|
|
18433
|
+
KNIP_SUCCESS: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.KNIP].clear,
|
|
18434
|
+
KNIP_FAILURE: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.KNIP].attention,
|
|
18435
|
+
ESLINT_SUCCESS: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.ESLINT].clear,
|
|
18436
|
+
ESLINT_FAILURE: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.ESLINT].attention,
|
|
18437
|
+
ESLINT_MISSING_CONFIG: formatValidationConfigProblemMessage(
|
|
18438
|
+
VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,
|
|
18439
|
+
"configuration missing: product has tsconfig.json but no eslint.config.{ts,js,mjs,cjs}"
|
|
18440
|
+
),
|
|
18441
|
+
TYPESCRIPT_SUCCESS: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT].clear,
|
|
18442
|
+
TYPESCRIPT_FAILURE: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT].attention,
|
|
18443
|
+
MARKDOWN_NO_ISSUES: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN].clear,
|
|
18444
|
+
FORMATTING_NO_ISSUES: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING].clear,
|
|
18445
|
+
FORMATTING_FAILURE_SUMMARY: VALIDATION_STAGE_PROBLEM_MESSAGES[VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING].attention
|
|
18446
|
+
};
|
|
18447
|
+
function formatValidationStageSkipOutput(stageName, reason) {
|
|
18448
|
+
return `${stageName}: skipped (${reason})`;
|
|
18449
|
+
}
|
|
18450
|
+
function formatValidationStageSkipJsonOutput(reason, durationMs) {
|
|
18451
|
+
return JSON.stringify({ skipped: true, reason, durationMs });
|
|
18452
|
+
}
|
|
18375
18453
|
function formatTypeScriptAbsentSkipMessage(stageName) {
|
|
18376
18454
|
return `\u23ED ${VALIDATION_SKIP_LABELS.VERB} ${stageName} (${VALIDATION_SKIP_LABELS.TYPESCRIPT_ABSENT_REASON})`;
|
|
18377
18455
|
}
|
|
18378
18456
|
function formatValidationPathsNoTargetsSkipMessage(stageName) {
|
|
18379
18457
|
return `\u23ED ${VALIDATION_SKIP_LABELS.VERB} ${stageName} (${VALIDATION_SKIP_LABELS.VALIDATION_PATHS_NO_TARGETS_REASON})`;
|
|
18380
18458
|
}
|
|
18459
|
+
function formatExplicitPathsNoTargetsSkipMessage(stageName) {
|
|
18460
|
+
return `\u23ED ${VALIDATION_SKIP_LABELS.VERB} ${stageName} (${VALIDATION_SKIP_LABELS.EXPLICIT_PATHS_NO_TARGETS_REASON})`;
|
|
18461
|
+
}
|
|
18462
|
+
function formatValidationScopeNoTargetsSkipMessage(stageName, metadata) {
|
|
18463
|
+
if (metadata.explicitPathNoMatches) {
|
|
18464
|
+
return formatExplicitPathsNoTargetsSkipMessage(stageName);
|
|
18465
|
+
}
|
|
18466
|
+
if (metadata.filteredByValidationPathNoMatches) {
|
|
18467
|
+
return formatValidationPathsNoTargetsSkipMessage(stageName);
|
|
18468
|
+
}
|
|
18469
|
+
return void 0;
|
|
18470
|
+
}
|
|
18471
|
+
|
|
18472
|
+
// src/commands/validation/types.ts
|
|
18473
|
+
var VALIDATION_OUTPUT_TARGET = {
|
|
18474
|
+
STDOUT: "stdout",
|
|
18475
|
+
STDERR: "stderr"
|
|
18476
|
+
};
|
|
18477
|
+
var VALIDATION_STREAMED_TERMINAL_OUTPUT = "";
|
|
18478
|
+
function streamedValidationTerminalOutput(subprocessOutput, json, streamedPipelineOutput) {
|
|
18479
|
+
return json !== true && streamedPipelineOutput === true && subprocessOutput !== void 0 && subprocessOutput.length > 0 ? VALIDATION_STREAMED_TERMINAL_OUTPUT : void 0;
|
|
18480
|
+
}
|
|
18381
18481
|
|
|
18382
18482
|
// src/commands/validation/formatting.ts
|
|
18483
|
+
var defaultFormattingCommandDependencies = {
|
|
18484
|
+
validateFormatting
|
|
18485
|
+
};
|
|
18383
18486
|
var FORMATTING_COMMAND_OUTPUT = {
|
|
18384
18487
|
NO_ISSUES: VALIDATION_COMMAND_OUTPUT.FORMATTING_NO_ISSUES,
|
|
18385
18488
|
FAILURE_SUMMARY: VALIDATION_COMMAND_OUTPUT.FORMATTING_FAILURE_SUMMARY,
|
|
18386
18489
|
EMPTY_SCOPE_REASON: "no files in scope",
|
|
18387
18490
|
NO_CONFIG_SKIP_REASON: `no ${DPRINT_CONFIG_FILENAME} at product root`
|
|
18388
18491
|
};
|
|
18389
|
-
var FORMATTING_CONFIG_ERROR_MESSAGE =
|
|
18492
|
+
var FORMATTING_CONFIG_ERROR_MESSAGE = formatValidationConfigProblemMessage(
|
|
18493
|
+
VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING,
|
|
18494
|
+
"configuration error"
|
|
18495
|
+
);
|
|
18390
18496
|
var DPRINT_RECURSIVE_DIRECTORY_GLOB_SUFFIX = "/**/*";
|
|
18391
|
-
async function formattingCommand(options) {
|
|
18392
|
-
const { cwd, files, quiet } = options;
|
|
18497
|
+
async function formattingCommand(options, dependencies = defaultFormattingCommandDependencies) {
|
|
18498
|
+
const { cwd, files, json, outputStreams, quiet, streamedPipelineOutput } = options;
|
|
18393
18499
|
const startTime = Date.now();
|
|
18394
18500
|
const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);
|
|
18395
18501
|
if (!loaded.ok) {
|
|
@@ -18409,32 +18515,52 @@ async function formattingCommand(options) {
|
|
|
18409
18515
|
VALIDATION_PATH_TOOL_SUBSECTIONS.FORMATTING
|
|
18410
18516
|
);
|
|
18411
18517
|
const hasExplicitScope = files !== void 0 && files.length > 0;
|
|
18412
|
-
const
|
|
18413
|
-
|
|
18414
|
-
|
|
18415
|
-
isAbsolute6(filePath) ? relative6(cwd, filePath) : filePath,
|
|
18416
|
-
pathFilter
|
|
18417
|
-
)
|
|
18418
|
-
) : void 0;
|
|
18419
|
-
const scopedExcludes = hasExplicitScope && files.some(
|
|
18420
|
-
(filePath) => isFormattingFileOperand(cwd, isAbsolute6(filePath) ? relative6(cwd, filePath) : filePath)
|
|
18421
|
-
) ? [] : validationPathFilterExcludes(pathFilter);
|
|
18422
|
-
if (hasExplicitScope && (scopedFiles === void 0 || scopedFiles.length === 0)) {
|
|
18518
|
+
const contexts = formattingValidationContexts(cwd, files, pathFilter);
|
|
18519
|
+
const scopedFiles = contexts.flatMap((context) => context.files ?? []);
|
|
18520
|
+
if (hasExplicitScope && scopedFiles.length === 0 || contexts.length === 0) {
|
|
18423
18521
|
const output2 = quiet ? "" : `${VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING}: skipped (${FORMATTING_COMMAND_OUTPUT.EMPTY_SCOPE_REASON})`;
|
|
18424
18522
|
return { exitCode: 0, output: output2, durationMs: Date.now() - startTime };
|
|
18425
18523
|
}
|
|
18426
|
-
const
|
|
18427
|
-
|
|
18428
|
-
|
|
18429
|
-
|
|
18430
|
-
}
|
|
18524
|
+
const results = [];
|
|
18525
|
+
const subprocessOutputStreams = outputStreams ?? discardValidationSubprocessOutputStreams;
|
|
18526
|
+
for (const context of contexts) {
|
|
18527
|
+
results.push(await dependencies.validateFormatting(context, void 0, subprocessOutputStreams));
|
|
18528
|
+
}
|
|
18431
18529
|
const durationMs = Date.now() - startTime;
|
|
18432
|
-
if (result.success) {
|
|
18530
|
+
if (results.every((result) => result.success)) {
|
|
18433
18531
|
return { exitCode: 0, output: quiet ? "" : FORMATTING_COMMAND_OUTPUT.NO_ISSUES, durationMs };
|
|
18434
18532
|
}
|
|
18435
|
-
const detail = result.
|
|
18533
|
+
const detail = results.filter((result) => !result.success).flatMap((result) => [result.output, result.error]).filter((output2) => output2 !== void 0).filter((output2) => output2.length > 0).join("\n");
|
|
18436
18534
|
const output = [FORMATTING_COMMAND_OUTPUT.FAILURE_SUMMARY, detail].filter((line) => line.length > 0).join("\n");
|
|
18437
|
-
|
|
18535
|
+
const terminalOutput = formattingTerminalOutput(results, outputStreams, json, streamedPipelineOutput);
|
|
18536
|
+
return { exitCode: 1, output, terminalOutput, durationMs };
|
|
18537
|
+
}
|
|
18538
|
+
function formattingValidationContexts(productDir, files, pathFilter) {
|
|
18539
|
+
if (files === void 0 || files.length === 0) {
|
|
18540
|
+
if (validationPathFilterHasNoMatchingIncludes(pathFilter)) return [];
|
|
18541
|
+
const automaticFiles = pathFilter.include?.map((path4) => normalizeFormattingPathOperand(productDir, path4));
|
|
18542
|
+
return [{
|
|
18543
|
+
productDir,
|
|
18544
|
+
files: automaticFiles !== void 0 && automaticFiles.length > 0 ? automaticFiles : void 0,
|
|
18545
|
+
excludes: validationPathFilterExcludes(pathFilter)
|
|
18546
|
+
}];
|
|
18547
|
+
}
|
|
18548
|
+
const relativeFiles = files.map((filePath) => isAbsolute6(filePath) ? relative6(productDir, filePath) : filePath);
|
|
18549
|
+
return [{
|
|
18550
|
+
productDir,
|
|
18551
|
+
files: relativeFiles.map((filePath) => normalizeFormattingPathOperand(productDir, filePath)),
|
|
18552
|
+
excludes: []
|
|
18553
|
+
}];
|
|
18554
|
+
}
|
|
18555
|
+
function formattingTerminalOutput(results, outputStreams, json, streamedPipelineOutput) {
|
|
18556
|
+
if (json === true || outputStreams === void 0) {
|
|
18557
|
+
return void 0;
|
|
18558
|
+
}
|
|
18559
|
+
const errors = results.flatMap((result) => result.error === void 0 ? [] : [result.error]);
|
|
18560
|
+
if (errors.length > 0) {
|
|
18561
|
+
return [FORMATTING_COMMAND_OUTPUT.FAILURE_SUMMARY, ...errors].join("\n");
|
|
18562
|
+
}
|
|
18563
|
+
return streamedPipelineOutput === true ? VALIDATION_STREAMED_TERMINAL_OUTPUT : FORMATTING_COMMAND_OUTPUT.FAILURE_SUMMARY;
|
|
18438
18564
|
}
|
|
18439
18565
|
function normalizeFormattingPathOperand(productDir, relativePath) {
|
|
18440
18566
|
if (isFormattingFileOperand(productDir, relativePath)) {
|
|
@@ -18450,22 +18576,35 @@ function isFormattingFileOperand(productDir, relativePath) {
|
|
|
18450
18576
|
const absolutePath = join29(productDir, relativePath);
|
|
18451
18577
|
return !existsSync(absolutePath) || !statSync(absolutePath).isDirectory();
|
|
18452
18578
|
}
|
|
18453
|
-
function formattingPathOperandsForValidationPathFilter(productDir, relativePath, pathFilter) {
|
|
18454
|
-
if (isFormattingFileOperand(productDir, relativePath)) {
|
|
18455
|
-
return [relativePath];
|
|
18456
|
-
}
|
|
18457
|
-
return validationPathFilterIntersections(relativePath, pathFilter).map((path4) => normalizeFormattingPathOperand(productDir, path4));
|
|
18458
|
-
}
|
|
18459
18579
|
|
|
18460
18580
|
// src/validation/languages/formatting.ts
|
|
18461
18581
|
var FORMATTING_LANGUAGE_NAME = "formatting";
|
|
18582
|
+
var SKIP_FORMATTING_REASON = "skip-formatting";
|
|
18583
|
+
var FORMATTING_VALIDATION_STAGE_PARTICIPATION = {
|
|
18584
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING]: {
|
|
18585
|
+
default: VALIDATION_STAGE_PARTICIPATION.RUN,
|
|
18586
|
+
skipReason: SKIP_FORMATTING_REASON,
|
|
18587
|
+
override: {
|
|
18588
|
+
flag: "--skip-formatting",
|
|
18589
|
+
description: "Skip formatting validation for this validation all run"
|
|
18590
|
+
}
|
|
18591
|
+
}
|
|
18592
|
+
};
|
|
18462
18593
|
var formattingValidationLanguage = {
|
|
18463
18594
|
name: FORMATTING_LANGUAGE_NAME,
|
|
18464
18595
|
stages: [
|
|
18465
18596
|
{
|
|
18466
18597
|
name: VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING,
|
|
18467
18598
|
failsPipeline: true,
|
|
18468
|
-
|
|
18599
|
+
participation: FORMATTING_VALIDATION_STAGE_PARTICIPATION[VALIDATION_STAGE_DISPLAY_NAMES.FORMATTING],
|
|
18600
|
+
run: (context) => formattingCommand({
|
|
18601
|
+
cwd: context.cwd,
|
|
18602
|
+
files: context.files,
|
|
18603
|
+
quiet: context.quiet,
|
|
18604
|
+
json: context.json,
|
|
18605
|
+
streamedPipelineOutput: true,
|
|
18606
|
+
outputStreams: context.outputStreams
|
|
18607
|
+
})
|
|
18469
18608
|
}
|
|
18470
18609
|
]
|
|
18471
18610
|
};
|
|
@@ -18506,6 +18645,11 @@ var MARKDOWN_VALIDATION_TARGET_DIAGNOSTICS = {
|
|
|
18506
18645
|
var defaultMarkdownValidationTargetDeps = {
|
|
18507
18646
|
statSync: statSync2
|
|
18508
18647
|
};
|
|
18648
|
+
var defaultMarkdownValidationDeps = {
|
|
18649
|
+
runMarkdownlint: async (options) => {
|
|
18650
|
+
await markdownlintMain(options);
|
|
18651
|
+
}
|
|
18652
|
+
};
|
|
18509
18653
|
function buildMarkdownlintConfig(directoryName) {
|
|
18510
18654
|
const md024Disabled = MD024_DISABLED_DIRECTORIES.includes(
|
|
18511
18655
|
directoryName
|
|
@@ -18517,8 +18661,8 @@ function buildMarkdownlintConfig(directoryName) {
|
|
|
18517
18661
|
[MARKDOWN_CONFIG_CONTROL_KEYS.CUSTOM_RULES]: [relativeLinksRule]
|
|
18518
18662
|
};
|
|
18519
18663
|
}
|
|
18520
|
-
function getDefaultDirectories(
|
|
18521
|
-
return MARKDOWN_DEFAULT_DIRECTORY_NAMES.map((name) => join30(
|
|
18664
|
+
function getDefaultDirectories(productDir) {
|
|
18665
|
+
return MARKDOWN_DEFAULT_DIRECTORY_NAMES.map((name) => join30(productDir, name)).filter((dir) => existsSync2(dir));
|
|
18522
18666
|
}
|
|
18523
18667
|
function resolveMarkdownValidationTarget(path4, deps = defaultMarkdownValidationTargetDeps) {
|
|
18524
18668
|
if (isExistingDirectory(path4, deps)) {
|
|
@@ -18534,10 +18678,10 @@ function resolveMarkdownValidationTarget(path4, deps = defaultMarkdownValidation
|
|
|
18534
18678
|
}
|
|
18535
18679
|
};
|
|
18536
18680
|
}
|
|
18537
|
-
function getExcludeGlobsForTarget(target,
|
|
18538
|
-
if (
|
|
18681
|
+
function getExcludeGlobsForTarget(target, productDir, entries) {
|
|
18682
|
+
if (productDir === void 0 || entries.length === 0) return [];
|
|
18539
18683
|
const directory = targetDirectory(target);
|
|
18540
|
-
const specTreeRoot = join30(
|
|
18684
|
+
const specTreeRoot = join30(productDir, SPEC_TREE_CONFIG.ROOT_DIRECTORY);
|
|
18541
18685
|
const targetPath = normalizePathPrefix(pathRelative(specTreeRoot, directory));
|
|
18542
18686
|
return entries.flatMap((entry) => {
|
|
18543
18687
|
const excludedPath = normalizePathPrefix(entry);
|
|
@@ -18615,24 +18759,24 @@ function isAsciiDigit(value) {
|
|
|
18615
18759
|
function isAsciiWhitespace(value) {
|
|
18616
18760
|
return value === " " || value === " ";
|
|
18617
18761
|
}
|
|
18618
|
-
async function validateMarkdown(options) {
|
|
18762
|
+
async function validateMarkdown(options, deps = defaultMarkdownValidationDeps) {
|
|
18619
18763
|
const {
|
|
18620
18764
|
targets,
|
|
18621
|
-
|
|
18765
|
+
productDir,
|
|
18622
18766
|
applyNodeStatusExcludes = true,
|
|
18623
18767
|
validationPathExcludes = []
|
|
18624
18768
|
} = options;
|
|
18625
18769
|
const errors = [];
|
|
18626
|
-
const specTreeExcludeEntries = applyNodeStatusExcludes ? getExcludeEntries(
|
|
18770
|
+
const specTreeExcludeEntries = applyNodeStatusExcludes ? getExcludeEntries(productDir) : [];
|
|
18627
18771
|
for (const target of targets) {
|
|
18628
18772
|
const directory = targetDirectory(target);
|
|
18629
|
-
const dirName = markdownlintConfigDirectoryName(directory,
|
|
18773
|
+
const dirName = markdownlintConfigDirectoryName(directory, productDir);
|
|
18630
18774
|
const config = buildMarkdownlintConfig(dirName);
|
|
18631
18775
|
const excludeGlobs = [
|
|
18632
|
-
...getExcludeGlobsForTarget(target,
|
|
18633
|
-
...validationPathExcludeGlobsForTarget(target,
|
|
18776
|
+
...getExcludeGlobsForTarget(target, productDir, specTreeExcludeEntries),
|
|
18777
|
+
...validationPathExcludeGlobsForTarget(target, productDir, validationPathExcludes)
|
|
18634
18778
|
];
|
|
18635
|
-
const dirErrors = await validateTarget(target, config,
|
|
18779
|
+
const dirErrors = await validateTarget(target, config, deps, productDir, excludeGlobs);
|
|
18636
18780
|
errors.push(...dirErrors);
|
|
18637
18781
|
}
|
|
18638
18782
|
return {
|
|
@@ -18640,11 +18784,11 @@ async function validateMarkdown(options) {
|
|
|
18640
18784
|
errors
|
|
18641
18785
|
};
|
|
18642
18786
|
}
|
|
18643
|
-
function getExcludeEntries(
|
|
18644
|
-
if (
|
|
18645
|
-
return createNodeStatusExcludeReader(
|
|
18787
|
+
function getExcludeEntries(productDir) {
|
|
18788
|
+
if (productDir === void 0) return [];
|
|
18789
|
+
return createNodeStatusExcludeReader(productDir).entries();
|
|
18646
18790
|
}
|
|
18647
|
-
async function validateTarget(target, config,
|
|
18791
|
+
async function validateTarget(target, config, deps, productDir, ignoreGlobs = []) {
|
|
18648
18792
|
const errors = [];
|
|
18649
18793
|
const directory = targetDirectory(target);
|
|
18650
18794
|
const argv = target.kind === MARKDOWN_VALIDATION_TARGET_KIND.FILE ? [basename7(target.path)] : [MARKDOWN_DIRECTORY_GLOB];
|
|
@@ -18652,14 +18796,14 @@ async function validateTarget(target, config, projectRoot, ignoreGlobs = []) {
|
|
|
18652
18796
|
const optionsOverride = {
|
|
18653
18797
|
config: {
|
|
18654
18798
|
...markdownlintConfig,
|
|
18655
|
-
"relative-links":
|
|
18799
|
+
"relative-links": productDir ? { root_path: productDir } : true
|
|
18656
18800
|
},
|
|
18657
18801
|
customRules,
|
|
18658
18802
|
noProgress: true,
|
|
18659
18803
|
noBanner: true,
|
|
18660
18804
|
...ignoreGlobs.length > 0 ? { ignores: ignoreGlobs } : {}
|
|
18661
18805
|
};
|
|
18662
|
-
await
|
|
18806
|
+
await deps.runMarkdownlint({
|
|
18663
18807
|
directory,
|
|
18664
18808
|
argv,
|
|
18665
18809
|
optionsOverride,
|
|
@@ -18681,10 +18825,10 @@ async function validateTarget(target, config, projectRoot, ignoreGlobs = []) {
|
|
|
18681
18825
|
function targetDirectory(target) {
|
|
18682
18826
|
return target.kind === MARKDOWN_VALIDATION_TARGET_KIND.FILE ? dirname13(target.path) : target.path;
|
|
18683
18827
|
}
|
|
18684
|
-
function validationPathExcludeGlobsForTarget(target,
|
|
18685
|
-
if (
|
|
18828
|
+
function validationPathExcludeGlobsForTarget(target, productDir, excludes) {
|
|
18829
|
+
if (productDir === void 0 || excludes.length === 0 || target.kind === MARKDOWN_VALIDATION_TARGET_KIND.FILE) return [];
|
|
18686
18830
|
const directory = targetDirectory(target);
|
|
18687
|
-
const targetPath = normalizePathPrefix(pathRelative(
|
|
18831
|
+
const targetPath = normalizePathPrefix(pathRelative(productDir, directory));
|
|
18688
18832
|
return excludes.flatMap((exclude) => {
|
|
18689
18833
|
const excludedPath = normalizePathPrefix(exclude);
|
|
18690
18834
|
if (targetPath === excludedPath) {
|
|
@@ -18693,11 +18837,11 @@ function validationPathExcludeGlobsForTarget(target, projectRoot, excludes) {
|
|
|
18693
18837
|
if (!pathContainsValidationPath(targetPath, excludedPath)) {
|
|
18694
18838
|
return [];
|
|
18695
18839
|
}
|
|
18696
|
-
const relativeExclude = normalizePathPrefix(pathRelative(directory, join30(
|
|
18840
|
+
const relativeExclude = normalizePathPrefix(pathRelative(directory, join30(productDir, excludedPath)));
|
|
18697
18841
|
if (relativeExclude.length === 0) {
|
|
18698
18842
|
return [MARKDOWN_DIRECTORY_GLOB];
|
|
18699
18843
|
}
|
|
18700
|
-
const absoluteExclude = join30(
|
|
18844
|
+
const absoluteExclude = join30(productDir, excludedPath);
|
|
18701
18845
|
return [
|
|
18702
18846
|
isExistingFile(absoluteExclude, defaultMarkdownValidationTargetDeps) ? relativeExclude : `${relativeExclude}/**`
|
|
18703
18847
|
];
|
|
@@ -18726,9 +18870,9 @@ function isExistingFile(path4, deps) {
|
|
|
18726
18870
|
return false;
|
|
18727
18871
|
}
|
|
18728
18872
|
}
|
|
18729
|
-
function markdownlintConfigDirectoryName(directory,
|
|
18730
|
-
if (
|
|
18731
|
-
const [rootSegment] = pathRelative(
|
|
18873
|
+
function markdownlintConfigDirectoryName(directory, productDir) {
|
|
18874
|
+
if (productDir !== void 0) {
|
|
18875
|
+
const [rootSegment] = pathRelative(productDir, directory).split(/[\\/]/);
|
|
18732
18876
|
if (MD024_DISABLED_DIRECTORIES.includes(rootSegment)) {
|
|
18733
18877
|
return rootSegment;
|
|
18734
18878
|
}
|
|
@@ -18738,11 +18882,14 @@ function markdownlintConfigDirectoryName(directory, projectRoot) {
|
|
|
18738
18882
|
|
|
18739
18883
|
// src/commands/validation/markdown.ts
|
|
18740
18884
|
var MARKDOWN_COMMAND_OUTPUT = {
|
|
18741
|
-
ERROR_SUMMARY_SUFFIX: VALIDATION_COMMAND_OUTPUT.MARKDOWN_ERROR_SUMMARY_SUFFIX,
|
|
18742
18885
|
NO_ISSUES: VALIDATION_COMMAND_OUTPUT.MARKDOWN_NO_ISSUES,
|
|
18886
|
+
PROBLEM_TERM: VALIDATION_PROBLEM_TERMS.SINGULAR,
|
|
18743
18887
|
SKIPPED_FILE_SCOPE_PREFIX: "Markdown skipped file scope"
|
|
18744
18888
|
};
|
|
18745
|
-
var MARKDOWN_CONFIG_ERROR_MESSAGE =
|
|
18889
|
+
var MARKDOWN_CONFIG_ERROR_MESSAGE = formatValidationConfigProblemMessage(
|
|
18890
|
+
VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN,
|
|
18891
|
+
"configuration error"
|
|
18892
|
+
);
|
|
18746
18893
|
async function markdownCommand(options) {
|
|
18747
18894
|
const { cwd, files, quiet } = options;
|
|
18748
18895
|
const startTime = Date.now();
|
|
@@ -18775,8 +18922,8 @@ async function markdownCommand(options) {
|
|
|
18775
18922
|
}
|
|
18776
18923
|
const result = await validateMarkdown({
|
|
18777
18924
|
targets,
|
|
18778
|
-
|
|
18779
|
-
validationPathExcludes: validationPathFilterExcludes(pathFilter)
|
|
18925
|
+
productDir: cwd,
|
|
18926
|
+
validationPathExcludes: targetResolutions === void 0 ? validationPathFilterExcludes(pathFilter) : []
|
|
18780
18927
|
});
|
|
18781
18928
|
const durationMs = Date.now() - startTime;
|
|
18782
18929
|
return formatMarkdownResult(result, skippedOutput, quiet, durationMs);
|
|
@@ -18786,7 +18933,7 @@ function markdownValidationOperandPath(productDir, filePath) {
|
|
|
18786
18933
|
}
|
|
18787
18934
|
function defaultMarkdownTargets(productDir, pathFilter) {
|
|
18788
18935
|
return getDefaultDirectories(productDir).flatMap(
|
|
18789
|
-
(directory) => validationPathFilterIntersections(
|
|
18936
|
+
(directory) => validationPathFilterIntersections(toProductRelativeValidationPath(productDir, directory), pathFilter).map((intersection) => resolveMarkdownValidationTarget(join31(productDir, intersection)).target).filter((target) => target !== void 0)
|
|
18790
18937
|
);
|
|
18791
18938
|
}
|
|
18792
18939
|
function formatSkippedFileScope(target) {
|
|
@@ -18802,7 +18949,9 @@ function formatMarkdownResult(result, skippedOutput, quiet, durationMs) {
|
|
|
18802
18949
|
);
|
|
18803
18950
|
const output = [
|
|
18804
18951
|
...skippedOutput,
|
|
18805
|
-
|
|
18952
|
+
formatValidationProblemsFoundMessage(VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN, {
|
|
18953
|
+
count: result.errors.length
|
|
18954
|
+
}),
|
|
18806
18955
|
...errorLines
|
|
18807
18956
|
].join("\n");
|
|
18808
18957
|
return { exitCode: 1, output, durationMs };
|
|
@@ -18810,12 +18959,24 @@ function formatMarkdownResult(result, skippedOutput, quiet, durationMs) {
|
|
|
18810
18959
|
|
|
18811
18960
|
// src/validation/languages/markdown.ts
|
|
18812
18961
|
var MARKDOWN_LANGUAGE_NAME = "markdown";
|
|
18962
|
+
var SKIP_MARKDOWN_REASON = "skip-markdown";
|
|
18963
|
+
var MARKDOWN_VALIDATION_STAGE_PARTICIPATION = {
|
|
18964
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN]: {
|
|
18965
|
+
default: VALIDATION_STAGE_PARTICIPATION.RUN,
|
|
18966
|
+
skipReason: SKIP_MARKDOWN_REASON,
|
|
18967
|
+
override: {
|
|
18968
|
+
flag: "--skip-markdown",
|
|
18969
|
+
description: "Skip Markdown validation for this validation all run"
|
|
18970
|
+
}
|
|
18971
|
+
}
|
|
18972
|
+
};
|
|
18813
18973
|
var markdownValidationLanguage = {
|
|
18814
18974
|
name: MARKDOWN_LANGUAGE_NAME,
|
|
18815
18975
|
stages: [
|
|
18816
18976
|
{
|
|
18817
18977
|
name: VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN,
|
|
18818
18978
|
failsPipeline: true,
|
|
18979
|
+
participation: MARKDOWN_VALIDATION_STAGE_PARTICIPATION[VALIDATION_STAGE_DISPLAY_NAMES.MARKDOWN],
|
|
18819
18980
|
run: (context) => markdownCommand({ cwd: context.cwd, files: context.files, quiet: context.quiet })
|
|
18820
18981
|
}
|
|
18821
18982
|
]
|
|
@@ -19687,7 +19848,7 @@ var TSCONFIG_FILES = {
|
|
|
19687
19848
|
full: "tsconfig.json",
|
|
19688
19849
|
production: "tsconfig.production.json"
|
|
19689
19850
|
};
|
|
19690
|
-
var
|
|
19851
|
+
var PATH_SEGMENT_SEPARATOR3 = "/";
|
|
19691
19852
|
var GLOB_MARKER = "*";
|
|
19692
19853
|
var RECURSIVE_GLOB_SEGMENT = "**";
|
|
19693
19854
|
var SINGLE_CHARACTER_GLOB_MARKER = "?";
|
|
@@ -19718,8 +19879,8 @@ var EXPLICIT_TYPESCRIPT_SCOPE_TARGET_KIND = {
|
|
|
19718
19879
|
DIRECTORY: "directory",
|
|
19719
19880
|
FILE: "file"
|
|
19720
19881
|
};
|
|
19721
|
-
function
|
|
19722
|
-
return isAbsolute8(path4) ? path4 : join32(
|
|
19882
|
+
function resolveProductPath(productDir, path4) {
|
|
19883
|
+
return isAbsolute8(path4) ? path4 : join32(productDir, path4);
|
|
19723
19884
|
}
|
|
19724
19885
|
function parseTypeScriptConfig(configPath, deps = defaultScopeDeps) {
|
|
19725
19886
|
try {
|
|
@@ -19733,11 +19894,11 @@ function parseTypeScriptConfig(configPath, deps = defaultScopeDeps) {
|
|
|
19733
19894
|
};
|
|
19734
19895
|
}
|
|
19735
19896
|
}
|
|
19736
|
-
function resolveTypeScriptConfig(scope2,
|
|
19897
|
+
function resolveTypeScriptConfig(scope2, productDir, deps = defaultScopeDeps) {
|
|
19737
19898
|
const configFile = TSCONFIG_FILES[scope2];
|
|
19738
|
-
const config = parseTypeScriptConfig(
|
|
19899
|
+
const config = parseTypeScriptConfig(resolveProductPath(productDir, configFile), deps);
|
|
19739
19900
|
if (config.extends) {
|
|
19740
|
-
const baseConfigs = normalizeExtends(config.extends).map((extendedConfig) => parseTypeScriptConfig(
|
|
19901
|
+
const baseConfigs = normalizeExtends(config.extends).map((extendedConfig) => parseTypeScriptConfig(resolveProductPath(productDir, extendedConfig), deps));
|
|
19741
19902
|
const inheritedInclude = [...baseConfigs].reverse().find((baseConfig) => baseConfig.include !== void 0)?.include ?? [];
|
|
19742
19903
|
const inheritedExclude = [...baseConfigs].reverse().find((baseConfig) => baseConfig.exclude !== void 0)?.exclude ?? [];
|
|
19743
19904
|
return {
|
|
@@ -19773,48 +19934,48 @@ function hasTypeScriptFilesRecursive(dirPath, maxDepth = 2, deps = defaultScopeD
|
|
|
19773
19934
|
}
|
|
19774
19935
|
}
|
|
19775
19936
|
function pathPassesTypeScriptFileDiscoveryExcludes(path4, options) {
|
|
19776
|
-
const { excludePatterns = [],
|
|
19777
|
-
if (
|
|
19937
|
+
const { excludePatterns = [], productDir } = options;
|
|
19938
|
+
if (productDir === void 0) {
|
|
19778
19939
|
return true;
|
|
19779
19940
|
}
|
|
19780
|
-
const projectRelativePath =
|
|
19941
|
+
const projectRelativePath = toProductRelativeTypeScriptScopePath(productDir, path4);
|
|
19781
19942
|
return !excludePatterns.some((pattern) => pathMatchesTypeScriptPattern(projectRelativePath, pattern));
|
|
19782
19943
|
}
|
|
19783
|
-
function getTopLevelDirectoriesWithTypeScript(config,
|
|
19944
|
+
function getTopLevelDirectoriesWithTypeScript(config, productDir, deps = defaultScopeDeps) {
|
|
19784
19945
|
const directories = /* @__PURE__ */ new Set();
|
|
19785
|
-
for (const dir of listTopLevelDirectories(
|
|
19786
|
-
if (directoryContributesTypeScriptScope(dir, config,
|
|
19946
|
+
for (const dir of listTopLevelDirectories(productDir, deps)) {
|
|
19947
|
+
if (directoryContributesTypeScriptScope(dir, config, productDir, deps)) {
|
|
19787
19948
|
directories.add(dir);
|
|
19788
19949
|
}
|
|
19789
19950
|
}
|
|
19790
|
-
for (const dir of explicitIncludeTopLevelDirectories(config,
|
|
19951
|
+
for (const dir of explicitIncludeTopLevelDirectories(config, productDir, deps)) {
|
|
19791
19952
|
directories.add(dir);
|
|
19792
19953
|
}
|
|
19793
19954
|
return Array.from(directories).sort(compareAsciiStrings);
|
|
19794
19955
|
}
|
|
19795
|
-
function listTopLevelDirectories(
|
|
19796
|
-
return deps.readdirSync(
|
|
19956
|
+
function listTopLevelDirectories(productDir, deps) {
|
|
19957
|
+
return deps.readdirSync(productDir, { withFileTypes: true }).filter((item) => item.isDirectory()).map((item) => item.name).filter((name) => !name.startsWith("."));
|
|
19797
19958
|
}
|
|
19798
|
-
function directoryContributesTypeScriptScope(dir, config,
|
|
19799
|
-
if (!directoryPassesIncludePatterns(dir, config.include ?? [],
|
|
19959
|
+
function directoryContributesTypeScriptScope(dir, config, productDir, deps) {
|
|
19960
|
+
if (!directoryPassesIncludePatterns(dir, config.include ?? [], productDir, deps)) {
|
|
19800
19961
|
return false;
|
|
19801
19962
|
}
|
|
19802
19963
|
try {
|
|
19803
|
-
return hasTypeScriptFilesRecursive(join32(
|
|
19964
|
+
return hasTypeScriptFilesRecursive(join32(productDir, dir), 2, deps, {
|
|
19804
19965
|
excludePatterns: config.exclude,
|
|
19805
|
-
|
|
19966
|
+
productDir
|
|
19806
19967
|
});
|
|
19807
19968
|
} catch {
|
|
19808
19969
|
return false;
|
|
19809
19970
|
}
|
|
19810
19971
|
}
|
|
19811
|
-
function explicitIncludeTopLevelDirectories(config,
|
|
19972
|
+
function explicitIncludeTopLevelDirectories(config, productDir, deps) {
|
|
19812
19973
|
if (!config.include) {
|
|
19813
19974
|
return [];
|
|
19814
19975
|
}
|
|
19815
19976
|
const directories = [];
|
|
19816
19977
|
for (const pattern of config.include) {
|
|
19817
|
-
if (includePatternTargetsTypeScriptScope(pattern,
|
|
19978
|
+
if (includePatternTargetsTypeScriptScope(pattern, productDir, deps) && pattern.includes(PATH_SEGMENT_SEPARATOR3)) {
|
|
19818
19979
|
const topLevelDir = getLiteralTopLevelPatternDirectory(pattern);
|
|
19819
19980
|
if (topLevelDir) {
|
|
19820
19981
|
directories.push(topLevelDir);
|
|
@@ -19824,39 +19985,39 @@ function explicitIncludeTopLevelDirectories(config, projectRoot, deps) {
|
|
|
19824
19985
|
return directories;
|
|
19825
19986
|
}
|
|
19826
19987
|
function getLiteralTopLevelPatternDirectory(pattern) {
|
|
19827
|
-
const topLevelDir = pattern.split(
|
|
19988
|
+
const topLevelDir = pattern.split(PATH_SEGMENT_SEPARATOR3)[0];
|
|
19828
19989
|
if (!topLevelDir || typeScriptScopePatternHasGlob(topLevelDir) || topLevelDir.startsWith(HIDDEN_PATH_PREFIX)) {
|
|
19829
19990
|
return null;
|
|
19830
19991
|
}
|
|
19831
19992
|
return topLevelDir;
|
|
19832
19993
|
}
|
|
19833
|
-
function directoryPassesIncludePatterns(directory, patterns,
|
|
19994
|
+
function directoryPassesIncludePatterns(directory, patterns, productDir, deps) {
|
|
19834
19995
|
return patterns.length === 0 || patterns.some(
|
|
19835
|
-
(pattern) => includePatternTargetsTypeScriptScope(pattern,
|
|
19996
|
+
(pattern) => includePatternTargetsTypeScriptScope(pattern, productDir, deps) && typeScriptScopePatternIntersectsDirectory(pattern, directory)
|
|
19836
19997
|
);
|
|
19837
19998
|
}
|
|
19838
19999
|
function stripTrailingPathSeparators2(value) {
|
|
19839
20000
|
let end = value.length;
|
|
19840
|
-
while (end > 0 && value.charAt(end - 1) ===
|
|
20001
|
+
while (end > 0 && value.charAt(end - 1) === PATH_SEGMENT_SEPARATOR3) {
|
|
19841
20002
|
end -= 1;
|
|
19842
20003
|
}
|
|
19843
20004
|
return value.slice(0, end);
|
|
19844
20005
|
}
|
|
19845
20006
|
function normalizeTypeScriptScopePath(path4) {
|
|
19846
|
-
const joined = path4.split(/[\\/]/gu).join(
|
|
20007
|
+
const joined = path4.split(/[\\/]/gu).join(PATH_SEGMENT_SEPARATOR3).replace(/^\.\//u, "");
|
|
19847
20008
|
return stripTrailingPathSeparators2(joined);
|
|
19848
20009
|
}
|
|
19849
20010
|
function pathMatchesLiteralPrefix(path4, prefix) {
|
|
19850
20011
|
const normalizedPath = normalizeTypeScriptScopePath(path4);
|
|
19851
20012
|
const normalizedPrefix = normalizeTypeScriptScopePath(prefix);
|
|
19852
|
-
return normalizedPath === normalizedPrefix || normalizedPath.startsWith(`${normalizedPrefix}${
|
|
20013
|
+
return normalizedPath === normalizedPrefix || normalizedPath.startsWith(`${normalizedPrefix}${PATH_SEGMENT_SEPARATOR3}`);
|
|
19853
20014
|
}
|
|
19854
20015
|
function splitTypeScriptScopePathSegments(path4) {
|
|
19855
20016
|
const normalizedPath = normalizeTypeScriptScopePath(path4);
|
|
19856
20017
|
if (normalizedPath.length === 0 || normalizedPath === ".") {
|
|
19857
20018
|
return [];
|
|
19858
20019
|
}
|
|
19859
|
-
return normalizedPath.split(
|
|
20020
|
+
return normalizedPath.split(PATH_SEGMENT_SEPARATOR3);
|
|
19860
20021
|
}
|
|
19861
20022
|
function globLiteralPrefix(pattern) {
|
|
19862
20023
|
const normalizedPattern = normalizeTypeScriptScopePath(pattern);
|
|
@@ -19930,16 +20091,16 @@ function typeScriptScopeGlobPatternToRegExp(pattern) {
|
|
|
19930
20091
|
const character = normalizedPattern[index];
|
|
19931
20092
|
const nextCharacter = normalizedPattern[index + 1];
|
|
19932
20093
|
const followingCharacter = normalizedPattern[index + 2];
|
|
19933
|
-
if (character === GLOB_MARKER && nextCharacter === GLOB_MARKER && followingCharacter ===
|
|
19934
|
-
source += `(?:.*${
|
|
20094
|
+
if (character === GLOB_MARKER && nextCharacter === GLOB_MARKER && followingCharacter === PATH_SEGMENT_SEPARATOR3) {
|
|
20095
|
+
source += `(?:.*${PATH_SEGMENT_SEPARATOR3})?`;
|
|
19935
20096
|
index += 2;
|
|
19936
20097
|
} else if (character === GLOB_MARKER && nextCharacter === GLOB_MARKER) {
|
|
19937
20098
|
source += ".*";
|
|
19938
20099
|
index += 1;
|
|
19939
20100
|
} else if (character === GLOB_MARKER) {
|
|
19940
|
-
source += `[^${
|
|
20101
|
+
source += `[^${PATH_SEGMENT_SEPARATOR3}]*`;
|
|
19941
20102
|
} else if (character === SINGLE_CHARACTER_GLOB_MARKER) {
|
|
19942
|
-
source += `[^${
|
|
20103
|
+
source += `[^${PATH_SEGMENT_SEPARATOR3}]`;
|
|
19943
20104
|
} else {
|
|
19944
20105
|
source += character.replaceAll(GLOB_REGEX_SPECIAL_CHARACTER_PATTERN, REGEX_ESCAPE_REPLACEMENT);
|
|
19945
20106
|
}
|
|
@@ -20007,12 +20168,12 @@ function typeScriptScopePatternTargetsTypeScriptSource(pattern) {
|
|
|
20007
20168
|
const terminalSegment = splitTypeScriptScopePathSegments(normalizedPattern).at(-1) ?? normalizedPattern;
|
|
20008
20169
|
return typeScriptScopePatternHasGlob(terminalSegment) && !TERMINAL_EXTENSION_PATTERN.test(terminalSegment);
|
|
20009
20170
|
}
|
|
20010
|
-
function includePatternTargetsTypeScriptScope(pattern,
|
|
20011
|
-
return includePatternIsLiteralDirectory(pattern,
|
|
20171
|
+
function includePatternTargetsTypeScriptScope(pattern, productDir, deps) {
|
|
20172
|
+
return includePatternIsLiteralDirectory(pattern, productDir, deps) || typeScriptScopePatternTargetsTypeScriptSource(pattern);
|
|
20012
20173
|
}
|
|
20013
|
-
function includePatternIsLiteralDirectory(pattern,
|
|
20174
|
+
function includePatternIsLiteralDirectory(pattern, productDir, deps) {
|
|
20014
20175
|
const normalizedPattern = normalizeTypeScriptScopePath(pattern);
|
|
20015
|
-
return !typeScriptScopePatternHasGlob(normalizedPattern) && pathIsDirectory(
|
|
20176
|
+
return !typeScriptScopePatternHasGlob(normalizedPattern) && pathIsDirectory(resolveProductPath(productDir, normalizedPattern), deps);
|
|
20016
20177
|
}
|
|
20017
20178
|
function pathIsDirectory(path4, deps) {
|
|
20018
20179
|
try {
|
|
@@ -20022,28 +20183,28 @@ function pathIsDirectory(path4, deps) {
|
|
|
20022
20183
|
return false;
|
|
20023
20184
|
}
|
|
20024
20185
|
}
|
|
20025
|
-
function normalizeActiveIncludePattern(pattern,
|
|
20186
|
+
function normalizeActiveIncludePattern(pattern, productDir, deps) {
|
|
20026
20187
|
const normalizedPattern = normalizeTypeScriptScopePath(pattern);
|
|
20027
|
-
return includePatternIsLiteralDirectory(normalizedPattern,
|
|
20188
|
+
return includePatternIsLiteralDirectory(normalizedPattern, productDir, deps) ? `${normalizedPattern}${TYPESCRIPT_SCOPE_DIRECTORY_PATTERN_SUFFIX}` : pattern;
|
|
20028
20189
|
}
|
|
20029
|
-
function filterActiveIncludePatterns(patterns, excludePatterns,
|
|
20030
|
-
return patterns.map((pattern) => normalizeActiveIncludePattern(pattern,
|
|
20190
|
+
function filterActiveIncludePatterns(patterns, excludePatterns, productDir, deps) {
|
|
20191
|
+
return patterns.map((pattern) => normalizeActiveIncludePattern(pattern, productDir, deps)).filter((pattern) => typeScriptScopePatternTargetsTypeScriptSource(pattern)).filter((pattern) => {
|
|
20031
20192
|
const topLevelDir = getLiteralTopLevelPatternDirectory(pattern);
|
|
20032
|
-
return topLevelDir === null || deps.existsSync(join32(
|
|
20193
|
+
return topLevelDir === null || deps.existsSync(join32(productDir, topLevelDir));
|
|
20033
20194
|
}).filter((pattern) => pathPassesValidationFilter(pattern, { exclude: excludePatterns }));
|
|
20034
20195
|
}
|
|
20035
|
-
function getValidationDirectories(scope2,
|
|
20036
|
-
const config = resolveTypeScriptConfig(scope2,
|
|
20037
|
-
const configDirectories = getTopLevelDirectoriesWithTypeScript(config,
|
|
20038
|
-
const existingDirectories = configDirectories.filter((dir) => deps.existsSync(join32(
|
|
20196
|
+
function getValidationDirectories(scope2, productDir, deps = defaultScopeDeps) {
|
|
20197
|
+
const config = resolveTypeScriptConfig(scope2, productDir, deps);
|
|
20198
|
+
const configDirectories = getTopLevelDirectoriesWithTypeScript(config, productDir, deps);
|
|
20199
|
+
const existingDirectories = configDirectories.filter((dir) => deps.existsSync(join32(productDir, dir)));
|
|
20039
20200
|
return existingDirectories;
|
|
20040
20201
|
}
|
|
20041
|
-
function getTypeScriptScope(scope2,
|
|
20042
|
-
const directories = getValidationDirectories(scope2,
|
|
20043
|
-
const config = resolveTypeScriptConfig(scope2,
|
|
20202
|
+
function getTypeScriptScope(scope2, productDir, deps = defaultScopeDeps) {
|
|
20203
|
+
const directories = getValidationDirectories(scope2, productDir, deps);
|
|
20204
|
+
const config = resolveTypeScriptConfig(scope2, productDir, deps);
|
|
20044
20205
|
return {
|
|
20045
20206
|
directories,
|
|
20046
|
-
filePatterns: filterActiveIncludePatterns(config.include ?? [], config.exclude ?? [],
|
|
20207
|
+
filePatterns: filterActiveIncludePatterns(config.include ?? [], config.exclude ?? [], productDir, deps),
|
|
20047
20208
|
excludePatterns: config.exclude ?? []
|
|
20048
20209
|
};
|
|
20049
20210
|
}
|
|
@@ -20055,31 +20216,31 @@ function pathPassesTypeScriptScope(path4, scopeConfig) {
|
|
|
20055
20216
|
const excluded = scopeConfig.excludePatterns.some((pattern) => pathMatchesTypeScriptPattern(path4, pattern));
|
|
20056
20217
|
return included && !excluded;
|
|
20057
20218
|
}
|
|
20058
|
-
function pathStaysInsideTypeScriptScopeRoot(
|
|
20059
|
-
const resolvedPath = isAbsolute8(path4) ? resolve14(path4) : resolve14(
|
|
20060
|
-
const relativePath = relative7(
|
|
20061
|
-
const segments = normalizeTypeScriptScopePath(relativePath).split(
|
|
20219
|
+
function pathStaysInsideTypeScriptScopeRoot(productDir, path4) {
|
|
20220
|
+
const resolvedPath = isAbsolute8(path4) ? resolve14(path4) : resolve14(productDir, path4);
|
|
20221
|
+
const relativePath = relative7(productDir, resolvedPath);
|
|
20222
|
+
const segments = normalizeTypeScriptScopePath(relativePath).split(PATH_SEGMENT_SEPARATOR3);
|
|
20062
20223
|
return relativePath.length === 0 || !segments.includes("..") && !isAbsolute8(relativePath);
|
|
20063
20224
|
}
|
|
20064
|
-
function
|
|
20065
|
-
const resolvedPath = isAbsolute8(path4) ? resolve14(path4) : resolve14(
|
|
20066
|
-
const relativePath = relative7(
|
|
20225
|
+
function toProductRelativeTypeScriptScopePath(productDir, path4) {
|
|
20226
|
+
const resolvedPath = isAbsolute8(path4) ? resolve14(path4) : resolve14(productDir, path4);
|
|
20227
|
+
const relativePath = relative7(productDir, resolvedPath);
|
|
20067
20228
|
return relativePath.length === 0 ? TYPESCRIPT_SCOPE_PROJECT_ROOT : normalizeTypeScriptScopePath(relativePath);
|
|
20068
20229
|
}
|
|
20069
|
-
function toExplicitTypeScriptScopeTarget(
|
|
20070
|
-
const path4 =
|
|
20230
|
+
function toExplicitTypeScriptScopeTarget(productDir, originalPath, deps = defaultScopeDeps) {
|
|
20231
|
+
const path4 = toProductRelativeTypeScriptScopePath(productDir, originalPath);
|
|
20071
20232
|
return {
|
|
20072
|
-
kind: pathIsDirectory(
|
|
20233
|
+
kind: pathIsDirectory(resolveProductPath(productDir, path4), deps) ? EXPLICIT_TYPESCRIPT_SCOPE_TARGET_KIND.DIRECTORY : EXPLICIT_TYPESCRIPT_SCOPE_TARGET_KIND.FILE,
|
|
20073
20234
|
path: path4
|
|
20074
20235
|
};
|
|
20075
20236
|
}
|
|
20076
|
-
function explicitTypeScriptScopeTargetExists(
|
|
20077
|
-
return deps.existsSync(
|
|
20237
|
+
function explicitTypeScriptScopeTargetExists(productDir, target, deps) {
|
|
20238
|
+
return deps.existsSync(resolveProductPath(productDir, target.path));
|
|
20078
20239
|
}
|
|
20079
20240
|
function filterExplicitTypeScriptScopeTargets(filter, deps = defaultScopeDeps) {
|
|
20080
20241
|
const {
|
|
20081
20242
|
paths,
|
|
20082
|
-
|
|
20243
|
+
productDir,
|
|
20083
20244
|
requireExistingPaths = true,
|
|
20084
20245
|
scopeConfig,
|
|
20085
20246
|
validationPathFilter,
|
|
@@ -20088,7 +20249,7 @@ function filterExplicitTypeScriptScopeTargets(filter, deps = defaultScopeDeps) {
|
|
|
20088
20249
|
if (paths === void 0) {
|
|
20089
20250
|
return void 0;
|
|
20090
20251
|
}
|
|
20091
|
-
return paths.filter((path4) => pathStaysInsideTypeScriptScopeRoot(
|
|
20252
|
+
return paths.filter((path4) => pathStaysInsideTypeScriptScopeRoot(productDir, path4)).map((path4) => toExplicitTypeScriptScopeTarget(productDir, path4, deps)).filter((target) => !requireExistingPaths || explicitTypeScriptScopeTargetExists(productDir, target, deps)).filter((target) => explicitTypeScriptScopeTargetPassesSourceKind(target)).filter(
|
|
20092
20253
|
(target) => bypassValidationPathFilter || explicitTypeScriptScopeTargetIntersectsValidationPathFilter(target, validationPathFilter)
|
|
20093
20254
|
).filter((target) => explicitTypeScriptScopeTargetPassesScope(target, scopeConfig));
|
|
20094
20255
|
}
|
|
@@ -20157,7 +20318,7 @@ function constrainTypeScriptScopeToExplicitTargets(scopeConfig, targets) {
|
|
|
20157
20318
|
const retainedDirectoryOperandPatterns = scopeConfig.filePatterns.length === 0 ? retainedDirectories.map(typeScriptLiteralDirectoryPattern) : [];
|
|
20158
20319
|
const explicitFileTargets = targets.filter((target) => target.kind === EXPLICIT_TYPESCRIPT_SCOPE_TARGET_KIND.FILE).map((target) => target.path).filter(
|
|
20159
20320
|
(path4) => !retainedDirectories.some(
|
|
20160
|
-
(directory) => path4 === directory || path4.startsWith(`${directory}${
|
|
20321
|
+
(directory) => path4 === directory || path4.startsWith(`${directory}${PATH_SEGMENT_SEPARATOR3}`)
|
|
20161
20322
|
)
|
|
20162
20323
|
);
|
|
20163
20324
|
const uncoveredExplicitFileTargets = explicitFileTargets.filter(
|
|
@@ -20182,28 +20343,28 @@ function typeScriptLiteralDirectoryPattern(pattern) {
|
|
|
20182
20343
|
return pattern === TYPESCRIPT_SCOPE_PROJECT_ROOT ? TYPESCRIPT_SCOPE_DIRECTORY_PATTERN_SUFFIX.slice(1) : `${pattern}${TYPESCRIPT_SCOPE_DIRECTORY_PATTERN_SUFFIX}`;
|
|
20183
20344
|
}
|
|
20184
20345
|
function resolveTypeScriptValidationScope(filter, deps = defaultScopeDeps) {
|
|
20185
|
-
const baseScopeConfig = getTypeScriptScope(filter.scope, filter.
|
|
20346
|
+
const baseScopeConfig = getTypeScriptScope(filter.scope, filter.productDir, deps);
|
|
20186
20347
|
const scopeConfig = applyValidationPathFilterToScope(baseScopeConfig, filter.validationPathFilter);
|
|
20187
|
-
const explicitTargetScopeConfig = filter.bypassExplicitPathValidationFilter === true ? baseScopeConfig : scopeConfig;
|
|
20188
20348
|
const explicitTargets = filterExplicitTypeScriptScopeTargets({
|
|
20189
20349
|
paths: filter.paths,
|
|
20190
|
-
|
|
20350
|
+
productDir: filter.productDir,
|
|
20191
20351
|
validationPathFilter: filter.validationPathFilter,
|
|
20192
|
-
scopeConfig:
|
|
20193
|
-
bypassValidationPathFilter:
|
|
20352
|
+
scopeConfig: baseScopeConfig,
|
|
20353
|
+
bypassValidationPathFilter: true
|
|
20194
20354
|
}, deps);
|
|
20195
20355
|
if (filter.paths !== void 0 && filter.paths.length > 0 && explicitTargets?.length === 0) {
|
|
20196
20356
|
return {
|
|
20197
20357
|
...scopeConfig,
|
|
20198
20358
|
directories: [],
|
|
20199
20359
|
filePatterns: [],
|
|
20200
|
-
|
|
20201
|
-
|
|
20202
|
-
|
|
20360
|
+
explicitPathNoMatches: true,
|
|
20361
|
+
filteredByValidationPaths: void 0,
|
|
20362
|
+
filteredByValidationPathIncludes: void 0,
|
|
20363
|
+
filteredByValidationPathNoMatches: void 0
|
|
20203
20364
|
};
|
|
20204
20365
|
}
|
|
20205
20366
|
if (explicitTargets !== void 0 && explicitTargets.length > 0) {
|
|
20206
|
-
const explicitScopeConfig = constrainTypeScriptScopeToExplicitTargets(
|
|
20367
|
+
const explicitScopeConfig = constrainTypeScriptScopeToExplicitTargets(baseScopeConfig, explicitTargets);
|
|
20207
20368
|
return filter.markExplicitPathsAsValidationFilter === true ? {
|
|
20208
20369
|
...explicitScopeConfig,
|
|
20209
20370
|
filteredByValidationPaths: true,
|
|
@@ -20216,7 +20377,7 @@ function resolveTypeScriptValidationScope(filter, deps = defaultScopeDeps) {
|
|
|
20216
20377
|
function constrainTypeScriptPatternToDirectory(pattern, directory) {
|
|
20217
20378
|
const normalizedPattern = normalizeTypeScriptScopePath(pattern);
|
|
20218
20379
|
const normalizedDirectory = normalizeTypeScriptScopePath(directory);
|
|
20219
|
-
if (normalizedPattern === normalizedDirectory || normalizedPattern.startsWith(`${normalizedDirectory}${
|
|
20380
|
+
if (normalizedPattern === normalizedDirectory || normalizedPattern.startsWith(`${normalizedDirectory}${PATH_SEGMENT_SEPARATOR3}`)) {
|
|
20220
20381
|
return normalizedPattern;
|
|
20221
20382
|
}
|
|
20222
20383
|
const patternSegments = splitTypeScriptScopePathSegments(normalizedPattern);
|
|
@@ -20229,7 +20390,7 @@ function constrainTypeScriptPatternToDirectory(pattern, directory) {
|
|
|
20229
20390
|
const suffixSegments = patternSegments.slice(patternIndex);
|
|
20230
20391
|
const constrainedSuffixSegments = directoryAdvance.recursiveGlobConsumedDirectory && suffixSegments.length > 0 ? [RECURSIVE_GLOB_SEGMENT, ...suffixSegments] : suffixSegments;
|
|
20231
20392
|
if (constrainedSuffixSegments.length > 0) {
|
|
20232
|
-
return [normalizedDirectory, ...constrainedSuffixSegments].join(
|
|
20393
|
+
return [normalizedDirectory, ...constrainedSuffixSegments].join(PATH_SEGMENT_SEPARATOR3);
|
|
20233
20394
|
}
|
|
20234
20395
|
return typeScriptScopePatternHasGlob(normalizedPattern) && typeScriptScopePatternCoversDirectorySourceSet(normalizedPattern, normalizedDirectory) ? `${normalizedDirectory}${TYPESCRIPT_SCOPE_DIRECTORY_PATTERN_SUFFIX}` : normalizedDirectory;
|
|
20235
20396
|
}
|
|
@@ -20263,7 +20424,7 @@ function patternSegmentMatchesDirectorySegment(patternSegment, directorySegment)
|
|
|
20263
20424
|
|
|
20264
20425
|
// src/validation/discovery/tool-finder.ts
|
|
20265
20426
|
import fs3 from "fs";
|
|
20266
|
-
import { createRequire } from "module";
|
|
20427
|
+
import { createRequire as createRequire2 } from "module";
|
|
20267
20428
|
import path3 from "path";
|
|
20268
20429
|
import { fileURLToPath } from "url";
|
|
20269
20430
|
|
|
@@ -20298,7 +20459,11 @@ var TOOL_DISCOVERY = {
|
|
|
20298
20459
|
};
|
|
20299
20460
|
|
|
20300
20461
|
// src/validation/discovery/tool-finder.ts
|
|
20301
|
-
var
|
|
20462
|
+
var TOOL_DISCOVERY_PRIORITY = {
|
|
20463
|
+
BUNDLED_FIRST: "bundled-first",
|
|
20464
|
+
PRODUCT_FIRST: "product-first"
|
|
20465
|
+
};
|
|
20466
|
+
var require2 = createRequire2(import.meta.url);
|
|
20302
20467
|
var FILE_URL_PROTOCOL = new URL(import.meta.url).protocol;
|
|
20303
20468
|
var PACKAGE_MANIFEST_FILENAME = "package.json";
|
|
20304
20469
|
var defaultToolDiscoveryDeps = {
|
|
@@ -20345,30 +20510,44 @@ function bundledToolPath(resolvedPath, existsSync10) {
|
|
|
20345
20510
|
return nearestPackageRoot(bundledFilePath, existsSync10) ?? path3.dirname(bundledFilePath);
|
|
20346
20511
|
}
|
|
20347
20512
|
async function discoverTool(tool, options = {}) {
|
|
20348
|
-
const {
|
|
20349
|
-
|
|
20513
|
+
const {
|
|
20514
|
+
productDir = CONFIG_PROCESS_CWD.read(),
|
|
20515
|
+
executableName = tool,
|
|
20516
|
+
bundledExecutable,
|
|
20517
|
+
includeBundled = true,
|
|
20518
|
+
priority = TOOL_DISCOVERY_PRIORITY.BUNDLED_FIRST,
|
|
20519
|
+
deps = defaultToolDiscoveryDeps
|
|
20520
|
+
} = options;
|
|
20521
|
+
const productBinPath = path3.join(productDir, "node_modules", ".bin", executableName);
|
|
20522
|
+
const productLocation = () => deps.existsSync(productBinPath) ? {
|
|
20523
|
+
found: true,
|
|
20524
|
+
location: {
|
|
20525
|
+
tool,
|
|
20526
|
+
path: productBinPath,
|
|
20527
|
+
source: TOOL_DISCOVERY.SOURCES.PROJECT
|
|
20528
|
+
}
|
|
20529
|
+
} : null;
|
|
20530
|
+
if (priority === TOOL_DISCOVERY_PRIORITY.PRODUCT_FIRST) {
|
|
20531
|
+
const productResult = productLocation();
|
|
20532
|
+
if (productResult !== null) return productResult;
|
|
20533
|
+
}
|
|
20534
|
+
const bundledSpecifier = bundledExecutable ?? `${tool}/package.json`;
|
|
20535
|
+
const bundledPath = includeBundled ? deps.resolveModule(bundledSpecifier) ?? deps.resolveImport?.(bundledExecutable ?? tool) : null;
|
|
20350
20536
|
if (bundledPath) {
|
|
20351
20537
|
return {
|
|
20352
20538
|
found: true,
|
|
20353
20539
|
location: {
|
|
20354
20540
|
tool,
|
|
20355
|
-
path: bundledToolPath(bundledPath, deps.existsSync),
|
|
20541
|
+
path: bundledExecutable === void 0 ? bundledToolPath(bundledPath, deps.existsSync) : resolvedModulePath(bundledPath),
|
|
20356
20542
|
source: TOOL_DISCOVERY.SOURCES.BUNDLED
|
|
20357
20543
|
}
|
|
20358
20544
|
};
|
|
20359
20545
|
}
|
|
20360
|
-
|
|
20361
|
-
|
|
20362
|
-
return
|
|
20363
|
-
found: true,
|
|
20364
|
-
location: {
|
|
20365
|
-
tool,
|
|
20366
|
-
path: projectBinPath,
|
|
20367
|
-
source: TOOL_DISCOVERY.SOURCES.PROJECT
|
|
20368
|
-
}
|
|
20369
|
-
};
|
|
20546
|
+
if (priority === TOOL_DISCOVERY_PRIORITY.BUNDLED_FIRST) {
|
|
20547
|
+
const productResult = productLocation();
|
|
20548
|
+
if (productResult !== null) return productResult;
|
|
20370
20549
|
}
|
|
20371
|
-
const globalPath = deps.whichSync(
|
|
20550
|
+
const globalPath = deps.whichSync(executableName);
|
|
20372
20551
|
if (globalPath) {
|
|
20373
20552
|
return {
|
|
20374
20553
|
found: true,
|
|
@@ -20519,13 +20698,13 @@ function dependencyCruiserGlobSegmentToRegExpSource(segment) {
|
|
|
20519
20698
|
}
|
|
20520
20699
|
return source;
|
|
20521
20700
|
}
|
|
20522
|
-
function buildDependencyCruiserOptions(typescriptScope,
|
|
20701
|
+
function buildDependencyCruiserOptions(typescriptScope, productDir, tsConfigFile) {
|
|
20523
20702
|
const excludePatterns = [
|
|
20524
20703
|
DEPENDENCY_CRUISER_PACKAGE_EXCLUDE_PATTERN,
|
|
20525
20704
|
...toDependencyCruiserExcludePatterns(typescriptScope.excludePatterns)
|
|
20526
20705
|
];
|
|
20527
20706
|
return {
|
|
20528
|
-
baseDir:
|
|
20707
|
+
baseDir: productDir,
|
|
20529
20708
|
enhancedResolveOptions: { extensions: [...DEPENDENCY_CRUISER_TYPESCRIPT_RESOLVE_EXTENSIONS] },
|
|
20530
20709
|
exclude: { path: excludePatterns },
|
|
20531
20710
|
includeOnly: { path: DEPENDENCY_CRUISER_TYPESCRIPT_SOURCE_PATTERN },
|
|
@@ -20633,16 +20812,16 @@ function circularDependencyCycles(result) {
|
|
|
20633
20812
|
);
|
|
20634
20813
|
return uniqueCycles(cycles);
|
|
20635
20814
|
}
|
|
20636
|
-
async function validateCircularDependencies(scope2, typescriptScope,
|
|
20815
|
+
async function validateCircularDependencies(scope2, typescriptScope, productDir, deps = defaultCircularDeps) {
|
|
20637
20816
|
try {
|
|
20638
20817
|
const analyzeSourcePatterns = toDependencyCruiserSourcePatterns(typescriptScope);
|
|
20639
20818
|
if (analyzeSourcePatterns.length === 0) {
|
|
20640
20819
|
return { success: true };
|
|
20641
20820
|
}
|
|
20642
|
-
const tsConfigFile = join33(
|
|
20821
|
+
const tsConfigFile = join33(productDir, TSCONFIG_FILES[scope2]);
|
|
20643
20822
|
const result = await deps.dependencyCruiser(
|
|
20644
20823
|
analyzeSourcePatterns,
|
|
20645
|
-
buildDependencyCruiserOptions(typescriptScope,
|
|
20824
|
+
buildDependencyCruiserOptions(typescriptScope, productDir, tsConfigFile),
|
|
20646
20825
|
void 0,
|
|
20647
20826
|
{ tsConfig: deps.extractTypeScriptConfig(tsConfigFile) }
|
|
20648
20827
|
);
|
|
@@ -20681,9 +20860,9 @@ var EXECUTION_MODES = {
|
|
|
20681
20860
|
|
|
20682
20861
|
// src/commands/validation/circular.ts
|
|
20683
20862
|
var TYPESCRIPT_ABSENT_MESSAGE = formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR);
|
|
20684
|
-
var CIRCULAR_CONFIG_ERROR_MESSAGE =
|
|
20685
|
-
|
|
20686
|
-
|
|
20863
|
+
var CIRCULAR_CONFIG_ERROR_MESSAGE = formatValidationConfigProblemMessage(
|
|
20864
|
+
VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR,
|
|
20865
|
+
"configuration error"
|
|
20687
20866
|
);
|
|
20688
20867
|
var CIRCULAR_DEPENDENCY_OUTPUT = {
|
|
20689
20868
|
FOUND: VALIDATION_COMMAND_OUTPUT.CIRCULAR_FOUND
|
|
@@ -20691,7 +20870,6 @@ var CIRCULAR_DEPENDENCY_OUTPUT = {
|
|
|
20691
20870
|
var defaultCircularCommandDeps = {
|
|
20692
20871
|
validateCircularDependencies
|
|
20693
20872
|
};
|
|
20694
|
-
var DEPENDENCY_CRUISER_PACKAGE_NAME = "dependency-cruiser";
|
|
20695
20873
|
function formatCircularValidationResult(result, quiet) {
|
|
20696
20874
|
if (result.success) {
|
|
20697
20875
|
return {
|
|
@@ -20723,11 +20901,6 @@ async function circularCommand(options, deps = defaultCircularCommandDeps) {
|
|
|
20723
20901
|
durationMs: Date.now() - startTime
|
|
20724
20902
|
};
|
|
20725
20903
|
}
|
|
20726
|
-
const toolResult = await discoverTool(DEPENDENCY_CRUISER_PACKAGE_NAME, { projectRoot: cwd });
|
|
20727
|
-
if (!toolResult.found) {
|
|
20728
|
-
const skipMessage = formatSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR, toolResult);
|
|
20729
|
-
return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };
|
|
20730
|
-
}
|
|
20731
20904
|
const loaded = await resolveConfig(cwd, [validationConfigDescriptor]);
|
|
20732
20905
|
if (!loaded.ok) {
|
|
20733
20906
|
return {
|
|
@@ -20738,19 +20911,22 @@ async function circularCommand(options, deps = defaultCircularCommandDeps) {
|
|
|
20738
20911
|
}
|
|
20739
20912
|
const validationConfig = loaded.value[validationConfigDescriptor.section];
|
|
20740
20913
|
const effectiveScopeConfig = resolveTypeScriptValidationScope({
|
|
20741
|
-
|
|
20914
|
+
productDir: cwd,
|
|
20742
20915
|
scope: scope2,
|
|
20743
20916
|
paths: files,
|
|
20744
20917
|
validationPathFilter: validationPathFilterForTool(
|
|
20745
20918
|
validationConfig.paths,
|
|
20746
20919
|
VALIDATION_PATH_TOOL_SUBSECTIONS.CIRCULAR
|
|
20747
|
-
)
|
|
20748
|
-
bypassExplicitPathValidationFilter: true
|
|
20920
|
+
)
|
|
20749
20921
|
});
|
|
20750
|
-
|
|
20922
|
+
const noTargetsMessage = formatValidationScopeNoTargetsSkipMessage(
|
|
20923
|
+
VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR,
|
|
20924
|
+
effectiveScopeConfig
|
|
20925
|
+
);
|
|
20926
|
+
if (noTargetsMessage !== void 0) {
|
|
20751
20927
|
return {
|
|
20752
20928
|
exitCode: 0,
|
|
20753
|
-
output: quiet ? "" :
|
|
20929
|
+
output: quiet ? "" : noTargetsMessage,
|
|
20754
20930
|
durationMs: Date.now() - startTime
|
|
20755
20931
|
};
|
|
20756
20932
|
}
|
|
@@ -20770,6 +20946,7 @@ var KNIP_COMMAND_TOKENS = {
|
|
|
20770
20946
|
TSCONFIG_FLAG: "--tsConfig",
|
|
20771
20947
|
USE_TSCONFIG_FILES_FLAG: "--use-tsconfig-files"
|
|
20772
20948
|
};
|
|
20949
|
+
var KNIP_LOCAL_BIN_SEGMENTS = ["node_modules", ".bin", KNIP_COMMAND_TOKENS.COMMAND];
|
|
20773
20950
|
var defaultKnipDeps = {
|
|
20774
20951
|
existsSync: existsSync4,
|
|
20775
20952
|
mkdir: mkdir7,
|
|
@@ -20777,9 +20954,9 @@ var defaultKnipDeps = {
|
|
|
20777
20954
|
rm: rm4,
|
|
20778
20955
|
writeFile: writeFile5
|
|
20779
20956
|
};
|
|
20780
|
-
async function validateKnip2(context, runner = defaultKnipProcessRunner, deps = defaultKnipDeps) {
|
|
20957
|
+
async function validateKnip2(context, runner = defaultKnipProcessRunner, deps = defaultKnipDeps, outputStreams = defaultValidationSubprocessOutputStreams) {
|
|
20781
20958
|
try {
|
|
20782
|
-
const {
|
|
20959
|
+
const { productDir, typescriptScope, toolPath } = context;
|
|
20783
20960
|
const analyzeTargets = [
|
|
20784
20961
|
...typescriptScope.directories,
|
|
20785
20962
|
...typescriptScope.filePatterns
|
|
@@ -20787,16 +20964,16 @@ async function validateKnip2(context, runner = defaultKnipProcessRunner, deps =
|
|
|
20787
20964
|
if (analyzeTargets.length === 0) {
|
|
20788
20965
|
return { success: true };
|
|
20789
20966
|
}
|
|
20790
|
-
return await runKnipSubprocess(
|
|
20967
|
+
return await runKnipSubprocess(productDir, typescriptScope, runner, deps, outputStreams, toolPath);
|
|
20791
20968
|
} catch (error) {
|
|
20792
20969
|
const errorMessage2 = error instanceof Error ? error.message : String(error);
|
|
20793
20970
|
return { success: false, error: errorMessage2 };
|
|
20794
20971
|
}
|
|
20795
20972
|
}
|
|
20796
|
-
async function runKnipSubprocess(
|
|
20797
|
-
const scopedTsconfig = typescriptScope.filteredByValidationPaths ? await createScopedKnipTsconfig(
|
|
20798
|
-
const localBin = join34(
|
|
20799
|
-
const binary = deps.existsSync(localBin) ? localBin : KNIP_COMMAND_TOKENS.NPX_COMMAND;
|
|
20973
|
+
async function runKnipSubprocess(productDir, typescriptScope, runner, deps, outputStreams, toolPath) {
|
|
20974
|
+
const scopedTsconfig = typescriptScope.filteredByValidationPaths ? await createScopedKnipTsconfig(productDir, typescriptScope, deps) : void 0;
|
|
20975
|
+
const localBin = join34(productDir, ...KNIP_LOCAL_BIN_SEGMENTS);
|
|
20976
|
+
const binary = toolPath ?? (deps.existsSync(localBin) ? localBin : KNIP_COMMAND_TOKENS.NPX_COMMAND);
|
|
20800
20977
|
const baseArgs = scopedTsconfig === void 0 ? [] : [
|
|
20801
20978
|
KNIP_COMMAND_TOKENS.USE_TSCONFIG_FILES_FLAG,
|
|
20802
20979
|
KNIP_COMMAND_TOKENS.TSCONFIG_FLAG,
|
|
@@ -20804,8 +20981,9 @@ async function runKnipSubprocess(projectRoot, typescriptScope, runner, deps) {
|
|
|
20804
20981
|
];
|
|
20805
20982
|
const args = binary === KNIP_COMMAND_TOKENS.NPX_COMMAND ? [KNIP_COMMAND_TOKENS.COMMAND, ...baseArgs] : baseArgs;
|
|
20806
20983
|
const knipProcess = spawnManagedSubprocess(runner, binary, args, {
|
|
20807
|
-
cwd:
|
|
20984
|
+
cwd: productDir
|
|
20808
20985
|
});
|
|
20986
|
+
forwardValidationSubprocessOutput(knipProcess, outputStreams);
|
|
20809
20987
|
const cleanup = scopedTsconfig?.cleanup ?? (async () => {
|
|
20810
20988
|
});
|
|
20811
20989
|
let cleanupStarted = false;
|
|
@@ -20835,7 +21013,7 @@ async function runKnipSubprocess(projectRoot, typescriptScope, runner, deps) {
|
|
|
20835
21013
|
};
|
|
20836
21014
|
knipProcess.on("close", (code) => {
|
|
20837
21015
|
if (code === 0) {
|
|
20838
|
-
resolveAfterCleanup({ success: true });
|
|
21016
|
+
resolveAfterCleanup({ success: true, output: knipOutput });
|
|
20839
21017
|
} else {
|
|
20840
21018
|
const errorOutput = knipOutput || knipError || "Unused code detected";
|
|
20841
21019
|
resolveAfterCleanup({
|
|
@@ -20849,12 +21027,12 @@ async function runKnipSubprocess(projectRoot, typescriptScope, runner, deps) {
|
|
|
20849
21027
|
});
|
|
20850
21028
|
});
|
|
20851
21029
|
}
|
|
20852
|
-
async function createScopedKnipTsconfig(
|
|
20853
|
-
const tempParentDir = join34(
|
|
21030
|
+
async function createScopedKnipTsconfig(productDir, typescriptScope, deps) {
|
|
21031
|
+
const tempParentDir = join34(productDir, ...TEMPORARY_TSCONFIG_PARENT_SEGMENTS);
|
|
20854
21032
|
await deps.mkdir(tempParentDir, { recursive: true });
|
|
20855
21033
|
const tempDir = await deps.mkdtemp(join34(tempParentDir, "validate-knip-"));
|
|
20856
21034
|
const configPath = join34(tempDir, TSCONFIG_FILES.full);
|
|
20857
|
-
const toProjectPathPattern = (pattern) => isAbsolute9(pattern) ? pattern : join34(
|
|
21035
|
+
const toProjectPathPattern = (pattern) => isAbsolute9(pattern) ? pattern : join34(productDir, pattern);
|
|
20858
21036
|
const project = [
|
|
20859
21037
|
...typescriptScope.directories.flatMap(
|
|
20860
21038
|
(directory) => TYPESCRIPT_FALLBACK_INCLUDE_PATTERNS.map((pattern) => `${directory}/${pattern}`)
|
|
@@ -20862,7 +21040,7 @@ async function createScopedKnipTsconfig(projectRoot, typescriptScope, deps) {
|
|
|
20862
21040
|
...typescriptScope.filePatterns
|
|
20863
21041
|
];
|
|
20864
21042
|
const config = {
|
|
20865
|
-
extends: join34(
|
|
21043
|
+
extends: join34(productDir, TSCONFIG_FILES.full),
|
|
20866
21044
|
include: project.map(toProjectPathPattern),
|
|
20867
21045
|
exclude: typescriptScope.excludePatterns.map(toProjectPathPattern)
|
|
20868
21046
|
};
|
|
@@ -20879,17 +21057,25 @@ var defaultKnipCommandDeps = {
|
|
|
20879
21057
|
discoverTool,
|
|
20880
21058
|
validateKnip: validateKnip2
|
|
20881
21059
|
};
|
|
20882
|
-
var
|
|
20883
|
-
var
|
|
21060
|
+
var KNIP_VALIDATION_STEP_NAME = "unused code detection";
|
|
21061
|
+
var KNIP_TYPESCRIPT_ABSENT_MESSAGE = formatTypeScriptAbsentSkipMessage(
|
|
20884
21062
|
VALIDATION_STAGE_DISPLAY_NAMES.KNIP
|
|
20885
21063
|
);
|
|
20886
21064
|
async function knipCommand(options, deps = defaultKnipCommandDeps) {
|
|
20887
|
-
const {
|
|
21065
|
+
const {
|
|
21066
|
+
cwd,
|
|
21067
|
+
files,
|
|
21068
|
+
json,
|
|
21069
|
+
outputStreams,
|
|
21070
|
+
quiet,
|
|
21071
|
+
scope: scope2 = VALIDATION_SCOPES.FULL,
|
|
21072
|
+
streamedPipelineOutput
|
|
21073
|
+
} = options;
|
|
20888
21074
|
const startTime = Date.now();
|
|
20889
21075
|
if (!deps.detectTypeScript(cwd).present) {
|
|
20890
21076
|
return {
|
|
20891
21077
|
exitCode: 0,
|
|
20892
|
-
output: quiet ? "" :
|
|
21078
|
+
output: quiet ? "" : KNIP_TYPESCRIPT_ABSENT_MESSAGE,
|
|
20893
21079
|
durationMs: Date.now() - startTime
|
|
20894
21080
|
};
|
|
20895
21081
|
}
|
|
@@ -20906,34 +21092,51 @@ async function knipCommand(options, deps = defaultKnipCommandDeps) {
|
|
|
20906
21092
|
const output = quiet ? "" : VALIDATION_COMMAND_OUTPUT.KNIP_DISABLED;
|
|
20907
21093
|
return { exitCode: 0, output, durationMs: Date.now() - startTime };
|
|
20908
21094
|
}
|
|
20909
|
-
const toolResult = await deps.discoverTool(
|
|
21095
|
+
const toolResult = await deps.discoverTool(KNIP_COMMAND_TOKENS.COMMAND, {
|
|
21096
|
+
productDir: cwd,
|
|
21097
|
+
includeBundled: false
|
|
21098
|
+
});
|
|
20910
21099
|
if (!toolResult.found) {
|
|
20911
|
-
const skipMessage = formatSkipMessage(
|
|
21100
|
+
const skipMessage = formatSkipMessage(KNIP_VALIDATION_STEP_NAME, toolResult);
|
|
20912
21101
|
return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };
|
|
20913
21102
|
}
|
|
20914
21103
|
const scopeConfig = resolveTypeScriptValidationScope({
|
|
20915
|
-
|
|
21104
|
+
productDir: cwd,
|
|
20916
21105
|
scope: scope2,
|
|
20917
21106
|
paths: files,
|
|
20918
21107
|
validationPathFilter: validationPathFilterForTool(validationConfig.paths, VALIDATION_PATH_TOOL_SUBSECTIONS.KNIP),
|
|
20919
|
-
markExplicitPathsAsValidationFilter: true
|
|
20920
|
-
bypassExplicitPathValidationFilter: true
|
|
21108
|
+
markExplicitPathsAsValidationFilter: true
|
|
20921
21109
|
});
|
|
20922
|
-
|
|
21110
|
+
const noTargetsMessage = formatValidationScopeNoTargetsSkipMessage(
|
|
21111
|
+
VALIDATION_STAGE_DISPLAY_NAMES.KNIP,
|
|
21112
|
+
scopeConfig
|
|
21113
|
+
);
|
|
21114
|
+
if (noTargetsMessage !== void 0) {
|
|
20923
21115
|
return {
|
|
20924
21116
|
exitCode: 0,
|
|
20925
|
-
output: quiet ? "" :
|
|
21117
|
+
output: quiet ? "" : noTargetsMessage,
|
|
20926
21118
|
durationMs: Date.now() - startTime
|
|
20927
21119
|
};
|
|
20928
21120
|
}
|
|
20929
|
-
const result = await deps.validateKnip(
|
|
21121
|
+
const result = await deps.validateKnip(
|
|
21122
|
+
{
|
|
21123
|
+
productDir: cwd,
|
|
21124
|
+
typescriptScope: scopeConfig,
|
|
21125
|
+
toolPath: toolResult.location.path
|
|
21126
|
+
},
|
|
21127
|
+
void 0,
|
|
21128
|
+
void 0,
|
|
21129
|
+
outputStreams ?? discardValidationSubprocessOutputStreams
|
|
21130
|
+
);
|
|
20930
21131
|
const durationMs = Date.now() - startTime;
|
|
20931
21132
|
if (result.success) {
|
|
20932
|
-
const output = quiet ? "" : VALIDATION_COMMAND_OUTPUT.KNIP_SUCCESS;
|
|
20933
|
-
|
|
21133
|
+
const output = quiet ? "" : [VALIDATION_COMMAND_OUTPUT.KNIP_SUCCESS, result.output].filter((line) => line !== void 0 && line.length > 0).join("\n");
|
|
21134
|
+
const terminalOutput = streamedValidationTerminalOutput(result.output, json, streamedPipelineOutput);
|
|
21135
|
+
return { exitCode: 0, output, terminalOutput, durationMs };
|
|
20934
21136
|
} else {
|
|
20935
21137
|
const output = result.error ?? VALIDATION_COMMAND_OUTPUT.KNIP_FAILURE;
|
|
20936
|
-
|
|
21138
|
+
const terminalOutput = streamedValidationTerminalOutput(result.error, json, streamedPipelineOutput);
|
|
21139
|
+
return { exitCode: 1, output, terminalOutput, durationMs };
|
|
20937
21140
|
}
|
|
20938
21141
|
}
|
|
20939
21142
|
|
|
@@ -21193,8 +21396,7 @@ function validateLintPolicy(productDir) {
|
|
|
21193
21396
|
}
|
|
21194
21397
|
}
|
|
21195
21398
|
|
|
21196
|
-
// src/validation/steps/eslint.ts
|
|
21197
|
-
var defaultEslintProcessRunner = lifecycleProcessRunner;
|
|
21399
|
+
// src/validation/steps/eslint-contract.ts
|
|
21198
21400
|
var DEFAULT_ESLINT_CONFIG_FILE = "eslint.config.ts";
|
|
21199
21401
|
var ESLINT_COMMAND_TOKENS = {
|
|
21200
21402
|
COMMAND: "eslint",
|
|
@@ -21205,6 +21407,9 @@ var ESLINT_COMMAND_TOKENS = {
|
|
|
21205
21407
|
IGNORE_PATTERN_FLAG: "--ignore-pattern"
|
|
21206
21408
|
};
|
|
21207
21409
|
var ESLINT_LOCAL_BIN_SEGMENTS = ["node_modules", ".bin", ESLINT_COMMAND_TOKENS.COMMAND];
|
|
21410
|
+
|
|
21411
|
+
// src/validation/steps/eslint.ts
|
|
21412
|
+
var defaultEslintProcessRunner = lifecycleProcessRunner;
|
|
21208
21413
|
function buildEslintArgs(context) {
|
|
21209
21414
|
const {
|
|
21210
21415
|
validatedFiles,
|
|
@@ -21252,8 +21457,8 @@ function buildIgnorePatternArgs(patterns) {
|
|
|
21252
21457
|
return patterns.flatMap((pattern) => [ESLINT_COMMAND_TOKENS.IGNORE_PATTERN_FLAG, pattern]);
|
|
21253
21458
|
}
|
|
21254
21459
|
async function validateESLint(context, runner = defaultEslintProcessRunner, outputStreams = defaultValidationSubprocessOutputStreams) {
|
|
21255
|
-
const {
|
|
21256
|
-
const lintPolicy = validateLintPolicy(
|
|
21460
|
+
const { productDir, scope: scope2, validatedFiles, mode, eslintConfigFile, toolPath } = context;
|
|
21461
|
+
const lintPolicy = validateLintPolicy(productDir);
|
|
21257
21462
|
if (!lintPolicy.ok) {
|
|
21258
21463
|
return { success: false, error: lintPolicy.error };
|
|
21259
21464
|
}
|
|
@@ -21269,47 +21474,57 @@ async function validateESLint(context, runner = defaultEslintProcessRunner, outp
|
|
|
21269
21474
|
scopeConfig: context.scopeConfig
|
|
21270
21475
|
});
|
|
21271
21476
|
return new Promise((resolve17) => {
|
|
21272
|
-
const localBin = join36(
|
|
21273
|
-
const binary = existsSync6(localBin) ? localBin : "npx";
|
|
21477
|
+
const localBin = join36(productDir, ...ESLINT_LOCAL_BIN_SEGMENTS);
|
|
21478
|
+
const binary = toolPath ?? (existsSync6(localBin) ? localBin : "npx");
|
|
21274
21479
|
const spawnArgs = binary === "npx" ? eslintArgs : eslintArgs.slice(1);
|
|
21275
21480
|
const eslintProcess = spawnManagedSubprocess(runner, binary, spawnArgs, {
|
|
21276
|
-
cwd:
|
|
21481
|
+
cwd: productDir
|
|
21277
21482
|
});
|
|
21483
|
+
const chunks = [];
|
|
21484
|
+
const capture = (chunk) => {
|
|
21485
|
+
chunks.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString());
|
|
21486
|
+
};
|
|
21487
|
+
eslintProcess.stdout?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, capture);
|
|
21488
|
+
eslintProcess.stderr?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, capture);
|
|
21278
21489
|
forwardValidationSubprocessOutput(eslintProcess, outputStreams);
|
|
21279
21490
|
eslintProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {
|
|
21491
|
+
const output = chunks.join("");
|
|
21280
21492
|
if (code === 0) {
|
|
21281
|
-
resolve17({ success: true });
|
|
21493
|
+
resolve17({ success: true, output });
|
|
21282
21494
|
} else {
|
|
21283
|
-
resolve17({ success: false, error: `ESLint exited with code ${code}` });
|
|
21495
|
+
resolve17({ success: false, output, error: `ESLint exited with code ${code}` });
|
|
21284
21496
|
}
|
|
21285
21497
|
});
|
|
21286
21498
|
eslintProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {
|
|
21287
|
-
resolve17({ success: false, error: error.message });
|
|
21499
|
+
resolve17({ success: false, output: chunks.join(""), error: error.message });
|
|
21288
21500
|
});
|
|
21289
21501
|
});
|
|
21290
21502
|
}
|
|
21291
21503
|
|
|
21292
21504
|
// src/commands/validation/lint.ts
|
|
21293
|
-
var
|
|
21294
|
-
var MISSING_CONFIG_MESSAGE = VALIDATION_COMMAND_OUTPUT.ESLINT_MISSING_CONFIG;
|
|
21295
|
-
var ESLINT_CONFIG_ERROR_MESSAGE = `${VALIDATION_STAGE_DISPLAY_NAMES.ESLINT}: \u2717 config error`;
|
|
21296
|
-
var VALIDATION_PATHS_NO_TARGETS_MESSAGE = formatValidationPathsNoTargetsSkipMessage(
|
|
21297
|
-
VALIDATION_STAGE_DISPLAY_NAMES.ESLINT
|
|
21298
|
-
);
|
|
21299
|
-
var defaultLintCommandDependencies = {
|
|
21505
|
+
var defaultLintCommandDeps = {
|
|
21300
21506
|
detectTypeScript,
|
|
21301
21507
|
discoverTool,
|
|
21302
21508
|
resolveConfig,
|
|
21303
21509
|
validateESLint
|
|
21304
21510
|
};
|
|
21305
|
-
|
|
21306
|
-
|
|
21511
|
+
var TYPESCRIPT_ABSENT_MESSAGE2 = formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.ESLINT);
|
|
21512
|
+
var MISSING_CONFIG_MESSAGE = VALIDATION_COMMAND_OUTPUT.ESLINT_MISSING_CONFIG;
|
|
21513
|
+
var ESLINT_CONFIG_ERROR_MESSAGE = formatValidationConfigProblemMessage(
|
|
21514
|
+
VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,
|
|
21515
|
+
"configuration error"
|
|
21516
|
+
);
|
|
21517
|
+
var VALIDATION_PATHS_NO_TARGETS_MESSAGE = formatValidationPathsNoTargetsSkipMessage(
|
|
21518
|
+
VALIDATION_STAGE_DISPLAY_NAMES.ESLINT
|
|
21519
|
+
);
|
|
21520
|
+
async function lintCommand(options, deps = defaultLintCommandDeps) {
|
|
21521
|
+
const { cwd, scope: scope2 = "full", files, fix, json, outputStreams, quiet, streamedPipelineOutput } = options;
|
|
21307
21522
|
const startTime = Date.now();
|
|
21308
21523
|
const tsDetection = deps.detectTypeScript(cwd);
|
|
21309
21524
|
if (!tsDetection.present) {
|
|
21310
21525
|
return {
|
|
21311
21526
|
exitCode: 0,
|
|
21312
|
-
output: quiet ? "" :
|
|
21527
|
+
output: quiet ? "" : TYPESCRIPT_ABSENT_MESSAGE2,
|
|
21313
21528
|
durationMs: Date.now() - startTime
|
|
21314
21529
|
};
|
|
21315
21530
|
}
|
|
@@ -21336,35 +21551,38 @@ async function lintCommand(options, deps = defaultLintCommandDependencies) {
|
|
|
21336
21551
|
);
|
|
21337
21552
|
const explicitMode = files !== void 0 && files.length > 0;
|
|
21338
21553
|
const scopeConfig = resolveTypeScriptValidationScope({
|
|
21339
|
-
|
|
21554
|
+
productDir: cwd,
|
|
21340
21555
|
scope: scope2,
|
|
21341
21556
|
paths: files,
|
|
21342
21557
|
validationPathFilter,
|
|
21343
|
-
markExplicitPathsAsValidationFilter: explicitMode
|
|
21344
|
-
bypassExplicitPathValidationFilter: true
|
|
21558
|
+
markExplicitPathsAsValidationFilter: explicitMode
|
|
21345
21559
|
});
|
|
21346
21560
|
const explicitTargets = explicitMode ? filterExplicitTypeScriptScopeTargets({
|
|
21347
21561
|
paths: files,
|
|
21348
|
-
|
|
21562
|
+
productDir: cwd,
|
|
21349
21563
|
validationPathFilter,
|
|
21350
21564
|
scopeConfig: getTypeScriptScope(scope2, cwd),
|
|
21351
21565
|
bypassValidationPathFilter: true
|
|
21352
21566
|
}) : void 0;
|
|
21353
|
-
const validatedFiles = explicitTargets?.every((target) => target.kind === EXPLICIT_TYPESCRIPT_SCOPE_TARGET_KIND.FILE) ? explicitTargets.map((target) => formatLintValidationOperand(
|
|
21354
|
-
|
|
21567
|
+
const validatedFiles = explicitTargets?.every((target) => target.kind === EXPLICIT_TYPESCRIPT_SCOPE_TARGET_KIND.FILE) ? explicitTargets.map((target) => formatLintValidationOperand(toProductRelativeValidationPath(cwd, target.path))) : void 0;
|
|
21568
|
+
const noTargetsMessage = formatValidationScopeNoTargetsSkipMessage(
|
|
21569
|
+
VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,
|
|
21570
|
+
scopeConfig
|
|
21571
|
+
);
|
|
21572
|
+
if (noTargetsMessage !== void 0) {
|
|
21355
21573
|
return {
|
|
21356
21574
|
exitCode: 0,
|
|
21357
|
-
output: quiet ? "" :
|
|
21575
|
+
output: quiet ? "" : noTargetsMessage,
|
|
21358
21576
|
durationMs: Date.now() - startTime
|
|
21359
21577
|
};
|
|
21360
21578
|
}
|
|
21361
|
-
const toolResult = await deps.discoverTool("eslint", {
|
|
21579
|
+
const toolResult = await deps.discoverTool("eslint", { productDir: cwd, includeBundled: false });
|
|
21362
21580
|
if (!toolResult.found) {
|
|
21363
21581
|
const skipMessage = formatSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.ESLINT, toolResult);
|
|
21364
21582
|
return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };
|
|
21365
21583
|
}
|
|
21366
21584
|
const context = {
|
|
21367
|
-
|
|
21585
|
+
productDir: cwd,
|
|
21368
21586
|
scope: scope2,
|
|
21369
21587
|
scopeConfig,
|
|
21370
21588
|
mode: fix ? "write" : "read",
|
|
@@ -21372,26 +21590,35 @@ async function lintCommand(options, deps = defaultLintCommandDependencies) {
|
|
|
21372
21590
|
validatedFiles,
|
|
21373
21591
|
validatedFileIgnorePatterns: void 0,
|
|
21374
21592
|
isFileSpecificMode: Boolean(validatedFiles && validatedFiles.length > 0),
|
|
21375
|
-
eslintConfigFile
|
|
21593
|
+
eslintConfigFile,
|
|
21594
|
+
toolPath: toolResult.location.path
|
|
21376
21595
|
};
|
|
21377
|
-
const result = await deps.validateESLint(
|
|
21596
|
+
const result = await deps.validateESLint(
|
|
21597
|
+
context,
|
|
21598
|
+
void 0,
|
|
21599
|
+
outputStreams ?? discardValidationSubprocessOutputStreams
|
|
21600
|
+
);
|
|
21378
21601
|
const durationMs = Date.now() - startTime;
|
|
21379
|
-
return formatLintResult(result, quiet, durationMs);
|
|
21602
|
+
return formatLintResult(result, quiet, durationMs, json, streamedPipelineOutput);
|
|
21380
21603
|
}
|
|
21381
21604
|
function formatLintValidationOperand(path4) {
|
|
21382
21605
|
return path4.length === 0 ? "." : path4;
|
|
21383
21606
|
}
|
|
21384
|
-
function formatLintResult(result, quiet, durationMs) {
|
|
21607
|
+
function formatLintResult(result, quiet, durationMs, json, streamedPipelineOutput) {
|
|
21385
21608
|
if (result.skipped) {
|
|
21386
21609
|
const output2 = quiet ? "" : VALIDATION_PATHS_NO_TARGETS_MESSAGE;
|
|
21387
21610
|
return { exitCode: 0, output: output2, durationMs };
|
|
21388
21611
|
}
|
|
21389
21612
|
if (result.success) {
|
|
21390
|
-
const output2 = quiet ? "" : VALIDATION_COMMAND_OUTPUT.ESLINT_SUCCESS
|
|
21391
|
-
|
|
21613
|
+
const output2 = quiet ? "" : [VALIDATION_COMMAND_OUTPUT.ESLINT_SUCCESS, result.output].filter(
|
|
21614
|
+
(line) => line !== void 0 && line.length > 0
|
|
21615
|
+
).join("\n");
|
|
21616
|
+
const terminalOutput2 = streamedValidationTerminalOutput(result.output, json, streamedPipelineOutput);
|
|
21617
|
+
return { exitCode: 0, output: output2, terminalOutput: terminalOutput2, durationMs };
|
|
21392
21618
|
}
|
|
21393
|
-
const output = result.error ?? VALIDATION_COMMAND_OUTPUT.ESLINT_FAILURE;
|
|
21394
|
-
|
|
21619
|
+
const output = [result.output, result.error ?? VALIDATION_COMMAND_OUTPUT.ESLINT_FAILURE].filter((line) => line !== void 0 && line.length > 0).join("\n");
|
|
21620
|
+
const terminalOutput = streamedValidationTerminalOutput(result.output, json, streamedPipelineOutput);
|
|
21621
|
+
return { exitCode: 1, output, terminalOutput, durationMs };
|
|
21395
21622
|
}
|
|
21396
21623
|
|
|
21397
21624
|
// src/domains/validation/literal-problem-kind.ts
|
|
@@ -21443,7 +21670,7 @@ var GIT_DEFAULT_GLOBAL_IGNORE_PATH = {
|
|
|
21443
21670
|
GIT_DIRECTORY: "git",
|
|
21444
21671
|
IGNORE_FILE: "ignore"
|
|
21445
21672
|
};
|
|
21446
|
-
var
|
|
21673
|
+
var PATH_SEGMENT_SEPARATOR4 = "/";
|
|
21447
21674
|
var CURRENT_DIRECTORY_PREFIX2 = ".";
|
|
21448
21675
|
var GIT_SCOPE_FAILURE_MESSAGE = "failed to read git scope";
|
|
21449
21676
|
var GIT_MISSING_CONTEXT_MESSAGE = "missing git working tree";
|
|
@@ -21576,11 +21803,11 @@ function readGlobalExcludesPath(productDir) {
|
|
|
21576
21803
|
}
|
|
21577
21804
|
function parentPrefixes(path4) {
|
|
21578
21805
|
const prefixes = [];
|
|
21579
|
-
let index = path4.lastIndexOf(
|
|
21806
|
+
let index = path4.lastIndexOf(PATH_SEGMENT_SEPARATOR4);
|
|
21580
21807
|
while (index > 0) {
|
|
21581
21808
|
const parent = path4.slice(0, index);
|
|
21582
21809
|
prefixes.push(parent);
|
|
21583
|
-
index = parent.lastIndexOf(
|
|
21810
|
+
index = parent.lastIndexOf(PATH_SEGMENT_SEPARATOR4);
|
|
21584
21811
|
}
|
|
21585
21812
|
return prefixes;
|
|
21586
21813
|
}
|
|
@@ -21635,7 +21862,7 @@ function createIgnoreSourceReader(productDir, config) {
|
|
|
21635
21862
|
},
|
|
21636
21863
|
hasIncludedDescendant(relativePath) {
|
|
21637
21864
|
return descendantParents.has(
|
|
21638
|
-
relativePath.endsWith(
|
|
21865
|
+
relativePath.endsWith(PATH_SEGMENT_SEPARATOR4) ? relativePath.slice(0, -1) : relativePath
|
|
21639
21866
|
);
|
|
21640
21867
|
},
|
|
21641
21868
|
appliedOverrides() {
|
|
@@ -22340,7 +22567,8 @@ async function validateLiteralReuse(input) {
|
|
|
22340
22567
|
return {
|
|
22341
22568
|
findings,
|
|
22342
22569
|
indexedOccurrencesByFile,
|
|
22343
|
-
filteredByValidationPathNoMatches: input.scopeConfig?.filteredByValidationPathNoMatches
|
|
22570
|
+
filteredByValidationPathNoMatches: input.scopeConfig?.filteredByValidationPathNoMatches,
|
|
22571
|
+
explicitPathNoMatches: input.scopeConfig?.explicitPathNoMatches
|
|
22344
22572
|
};
|
|
22345
22573
|
}
|
|
22346
22574
|
async function readSafe(path4) {
|
|
@@ -22388,29 +22616,29 @@ var OUTPUT_MODE_NAME = {
|
|
|
22388
22616
|
JSON: "json"
|
|
22389
22617
|
};
|
|
22390
22618
|
var OUTPUT_MODE_NAMES = Object.values(OUTPUT_MODE_NAME);
|
|
22619
|
+
var defaultLiteralCommandDeps = {
|
|
22620
|
+
validateLiteralReuse
|
|
22621
|
+
};
|
|
22391
22622
|
var LITERAL_EXIT_CODES = {
|
|
22392
22623
|
OK: 0,
|
|
22393
22624
|
FINDINGS: 1,
|
|
22394
22625
|
CONFIG_ERROR: 2
|
|
22395
22626
|
};
|
|
22396
|
-
var
|
|
22397
|
-
VALIDATION_STAGE_DISPLAY_NAMES.LITERAL
|
|
22398
|
-
);
|
|
22399
|
-
var VALIDATION_PATHS_NO_TARGETS_MESSAGE2 = formatValidationPathsNoTargetsSkipMessage(
|
|
22627
|
+
var TYPESCRIPT_ABSENT_MESSAGE3 = formatTypeScriptAbsentSkipMessage(
|
|
22400
22628
|
VALIDATION_STAGE_DISPLAY_NAMES.LITERAL
|
|
22401
22629
|
);
|
|
22402
22630
|
var LITERAL_DISABLED_MESSAGE = `\u23ED ${VALIDATION_SKIP_LABELS.VERB} ${VALIDATION_STAGE_DISPLAY_NAMES.LITERAL} (${VALIDATION_SKIP_LABELS.DISABLED_BY_PREFIX} validation.literal.enabled)`;
|
|
22403
|
-
var NO_PROBLEMS_MESSAGE =
|
|
22631
|
+
var NO_PROBLEMS_MESSAGE = formatValidationNoProblemsMessage(VALIDATION_STAGE_DISPLAY_NAMES.LITERAL);
|
|
22404
22632
|
function formatNoProblemsOfKind(kind) {
|
|
22405
22633
|
return `Literal: No problems of type ${kind}`;
|
|
22406
22634
|
}
|
|
22407
|
-
async function literalCommand(options) {
|
|
22635
|
+
async function literalCommand(options, deps = defaultLiteralCommandDeps) {
|
|
22408
22636
|
const start = Date.now();
|
|
22409
22637
|
const tsDetection = detectTypeScript(options.cwd);
|
|
22410
22638
|
if (!tsDetection.present) {
|
|
22411
22639
|
return {
|
|
22412
22640
|
exitCode: LITERAL_EXIT_CODES.OK,
|
|
22413
|
-
output: options.quiet ? "" :
|
|
22641
|
+
output: options.quiet ? "" : TYPESCRIPT_ABSENT_MESSAGE3,
|
|
22414
22642
|
durationMs: Date.now() - start
|
|
22415
22643
|
};
|
|
22416
22644
|
}
|
|
@@ -22418,7 +22646,10 @@ async function literalCommand(options) {
|
|
|
22418
22646
|
if (typeof resolved === "string") {
|
|
22419
22647
|
return {
|
|
22420
22648
|
exitCode: LITERAL_EXIT_CODES.CONFIG_ERROR,
|
|
22421
|
-
output:
|
|
22649
|
+
output: `${formatValidationConfigProblemMessage(
|
|
22650
|
+
VALIDATION_STAGE_DISPLAY_NAMES.LITERAL,
|
|
22651
|
+
"configuration error"
|
|
22652
|
+
)} \u2014 ${resolved}`,
|
|
22422
22653
|
durationMs: Date.now() - start
|
|
22423
22654
|
};
|
|
22424
22655
|
}
|
|
@@ -22429,17 +22660,18 @@ async function literalCommand(options) {
|
|
|
22429
22660
|
durationMs: Date.now() - start
|
|
22430
22661
|
};
|
|
22431
22662
|
}
|
|
22432
|
-
const result = await validateLiteralReuse({
|
|
22663
|
+
const result = await deps.validateLiteralReuse({
|
|
22433
22664
|
productDir: options.cwd,
|
|
22434
22665
|
explicitFiles: explicitLiteralPaths(options.files),
|
|
22435
22666
|
config: resolved.literalConfig,
|
|
22436
22667
|
pathConfig: resolved.pathConfig,
|
|
22437
22668
|
scopeConfig: resolveExplicitLiteralTypeScriptScope(options, resolved.pathConfig)
|
|
22438
22669
|
});
|
|
22439
|
-
|
|
22670
|
+
const noTargetsMessage = explicitLiteralNoTargetsSkipMessage(options, result);
|
|
22671
|
+
if (noTargetsMessage !== void 0) {
|
|
22440
22672
|
return {
|
|
22441
22673
|
exitCode: LITERAL_EXIT_CODES.OK,
|
|
22442
|
-
output: options.quiet ? "" :
|
|
22674
|
+
output: options.quiet ? "" : noTargetsMessage,
|
|
22443
22675
|
durationMs: Date.now() - start
|
|
22444
22676
|
};
|
|
22445
22677
|
}
|
|
@@ -22454,7 +22686,18 @@ async function literalCommand(options) {
|
|
|
22454
22686
|
} else {
|
|
22455
22687
|
output = formatLiteralCommandOutput(filteredFindings, options);
|
|
22456
22688
|
}
|
|
22457
|
-
return {
|
|
22689
|
+
return {
|
|
22690
|
+
exitCode,
|
|
22691
|
+
output,
|
|
22692
|
+
durationMs: Date.now() - start,
|
|
22693
|
+
outputTarget: VALIDATION_OUTPUT_TARGET.STDOUT
|
|
22694
|
+
};
|
|
22695
|
+
}
|
|
22696
|
+
function explicitLiteralNoTargetsSkipMessage(options, result) {
|
|
22697
|
+
if (options.files === void 0 || options.files.length === 0) {
|
|
22698
|
+
return void 0;
|
|
22699
|
+
}
|
|
22700
|
+
return formatValidationScopeNoTargetsSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.LITERAL, result);
|
|
22458
22701
|
}
|
|
22459
22702
|
async function resolveLiteralCommandConfig(options) {
|
|
22460
22703
|
if (options.config !== void 0) {
|
|
@@ -22481,12 +22724,11 @@ function resolveExplicitLiteralTypeScriptScope(options, pathConfig) {
|
|
|
22481
22724
|
return void 0;
|
|
22482
22725
|
}
|
|
22483
22726
|
return resolveTypeScriptValidationScope({
|
|
22484
|
-
|
|
22727
|
+
productDir: options.cwd,
|
|
22485
22728
|
scope: options.scope ?? VALIDATION_SCOPES.FULL,
|
|
22486
22729
|
paths: options.files,
|
|
22487
22730
|
validationPathFilter: pathConfig,
|
|
22488
|
-
markExplicitPathsAsValidationFilter: true
|
|
22489
|
-
bypassExplicitPathValidationFilter: true
|
|
22731
|
+
markExplicitPathsAsValidationFilter: true
|
|
22490
22732
|
});
|
|
22491
22733
|
}
|
|
22492
22734
|
function explicitLiteralPaths(files) {
|
|
@@ -22630,8 +22872,8 @@ function formatTypeScriptExitCodeError(code) {
|
|
|
22630
22872
|
}
|
|
22631
22873
|
var TEMPORARY_TSCONFIG_COMPILER_OPTIONS = { noEmit: true };
|
|
22632
22874
|
var TEMPORARY_TSCONFIG_DIR_PREFIX = "validate-ts-";
|
|
22633
|
-
async function createTemporaryTsconfigDir(
|
|
22634
|
-
const parent = join39(
|
|
22875
|
+
async function createTemporaryTsconfigDir(productDir, deps) {
|
|
22876
|
+
const parent = join39(productDir, ...TEMPORARY_TSCONFIG_PARENT_SEGMENTS);
|
|
22635
22877
|
deps.mkdirSync(parent, { recursive: true });
|
|
22636
22878
|
return deps.mkdtemp(join39(parent, TEMPORARY_TSCONFIG_DIR_PREFIX));
|
|
22637
22879
|
}
|
|
@@ -22639,13 +22881,13 @@ function buildTypeScriptArgs(context) {
|
|
|
22639
22881
|
const { scope: scope2, configFile } = context;
|
|
22640
22882
|
return scope2 === VALIDATION_SCOPES.FULL ? ["tsc", "--noEmit"] : ["tsc", "--project", configFile];
|
|
22641
22883
|
}
|
|
22642
|
-
async function createFileSpecificTsconfig(scope2, files,
|
|
22643
|
-
const tempDir = await createTemporaryTsconfigDir(
|
|
22884
|
+
async function createFileSpecificTsconfig(scope2, files, productDir, deps = defaultTypeScriptDeps) {
|
|
22885
|
+
const tempDir = await createTemporaryTsconfigDir(productDir, deps);
|
|
22644
22886
|
const configPath = join39(tempDir, "tsconfig.json");
|
|
22645
22887
|
const baseConfigFile = TSCONFIG_FILES[scope2];
|
|
22646
|
-
const absoluteFiles = files.map((file) => isAbsolute12(file) ? file : join39(
|
|
22888
|
+
const absoluteFiles = files.map((file) => isAbsolute12(file) ? file : join39(productDir, file));
|
|
22647
22889
|
const tempConfig = {
|
|
22648
|
-
extends: join39(
|
|
22890
|
+
extends: join39(productDir, baseConfigFile),
|
|
22649
22891
|
files: absoluteFiles,
|
|
22650
22892
|
include: [],
|
|
22651
22893
|
exclude: [],
|
|
@@ -22655,16 +22897,16 @@ async function createFileSpecificTsconfig(scope2, files, projectRoot, deps = def
|
|
|
22655
22897
|
const cleanup = createTemporaryTsconfigCleanup(tempDir, deps);
|
|
22656
22898
|
return { configPath, tempDir, cleanup };
|
|
22657
22899
|
}
|
|
22658
|
-
async function createScopeFilteredTsconfig(scope2,
|
|
22659
|
-
const tempDir = await createTemporaryTsconfigDir(
|
|
22900
|
+
async function createScopeFilteredTsconfig(scope2, productDir, scopeConfig, deps = defaultTypeScriptDeps) {
|
|
22901
|
+
const tempDir = await createTemporaryTsconfigDir(productDir, deps);
|
|
22660
22902
|
const configPath = join39(tempDir, "tsconfig.json");
|
|
22661
22903
|
const baseConfigFile = TSCONFIG_FILES[scope2];
|
|
22662
22904
|
const toTemporaryConfigPathPattern = (pattern) => {
|
|
22663
|
-
const absolutePattern = isAbsolute12(pattern) ? pattern : join39(
|
|
22905
|
+
const absolutePattern = isAbsolute12(pattern) ? pattern : join39(productDir, pattern);
|
|
22664
22906
|
return relative10(tempDir, absolutePattern);
|
|
22665
22907
|
};
|
|
22666
22908
|
const tempConfig = {
|
|
22667
|
-
extends: join39(
|
|
22909
|
+
extends: join39(productDir, baseConfigFile),
|
|
22668
22910
|
include: scopeConfigToTemporaryIncludes(scopeConfig).map(toTemporaryConfigPathPattern),
|
|
22669
22911
|
exclude: scopeConfig.excludePatterns.map(toTemporaryConfigPathPattern),
|
|
22670
22912
|
compilerOptions: TEMPORARY_TSCONFIG_COMPILER_OPTIONS
|
|
@@ -22693,19 +22935,20 @@ function createTemporaryTsconfigCleanup(tempDir, deps) {
|
|
|
22693
22935
|
};
|
|
22694
22936
|
}
|
|
22695
22937
|
async function validateTypeScript(context, options = {}) {
|
|
22696
|
-
const { scope: scope2,
|
|
22938
|
+
const { scope: scope2, productDir, files, scopeConfig } = context;
|
|
22697
22939
|
const {
|
|
22698
22940
|
runner = defaultTypeScriptProcessRunner,
|
|
22699
22941
|
deps = defaultTypeScriptDeps,
|
|
22942
|
+
toolPath,
|
|
22700
22943
|
outputStreams = defaultValidationSubprocessOutputStreams
|
|
22701
22944
|
} = options;
|
|
22702
22945
|
const configFile = TSCONFIG_FILES[scope2];
|
|
22703
22946
|
if (files && files.length > 0) {
|
|
22704
|
-
const { configPath, cleanup } = await createFileSpecificTsconfig(scope2, files,
|
|
22947
|
+
const { configPath, cleanup } = await createFileSpecificTsconfig(scope2, files, productDir, deps);
|
|
22705
22948
|
try {
|
|
22706
22949
|
return await runTypeScriptInvocation(
|
|
22707
|
-
|
|
22708
|
-
|
|
22950
|
+
productDir,
|
|
22951
|
+
resolveTscInvocation(productDir, deps, ["--project", configPath], toolPath),
|
|
22709
22952
|
runner,
|
|
22710
22953
|
outputStreams,
|
|
22711
22954
|
cleanup
|
|
@@ -22722,64 +22965,89 @@ async function validateTypeScript(context, options = {}) {
|
|
|
22722
22965
|
if (scopeConfig.filePatterns.length === 0 && scopeConfig.directories.length === 0) {
|
|
22723
22966
|
return { success: true, skipped: true };
|
|
22724
22967
|
}
|
|
22725
|
-
const { configPath, cleanup } = await createScopeFilteredTsconfig(scope2,
|
|
22968
|
+
const { configPath, cleanup } = await createScopeFilteredTsconfig(scope2, productDir, scopeConfig, deps);
|
|
22726
22969
|
return runTypeScriptInvocation(
|
|
22727
|
-
|
|
22728
|
-
|
|
22970
|
+
productDir,
|
|
22971
|
+
resolveTscInvocation(productDir, deps, ["--project", configPath], toolPath),
|
|
22729
22972
|
runner,
|
|
22730
22973
|
outputStreams,
|
|
22731
22974
|
cleanup
|
|
22732
22975
|
);
|
|
22733
22976
|
}
|
|
22734
22977
|
return runTypeScriptInvocation(
|
|
22735
|
-
|
|
22736
|
-
|
|
22978
|
+
productDir,
|
|
22979
|
+
resolveTscInvocation(productDir, deps, buildTypeScriptArgs({ scope: scope2, configFile }).slice(1), toolPath),
|
|
22737
22980
|
runner,
|
|
22738
22981
|
outputStreams
|
|
22739
22982
|
);
|
|
22740
22983
|
}
|
|
22741
|
-
function
|
|
22742
|
-
|
|
22984
|
+
function resolveTscInvocation(productDir, deps, tscArgs, toolPath) {
|
|
22985
|
+
if (toolPath !== void 0) {
|
|
22986
|
+
return { tool: toolPath, args: tscArgs };
|
|
22987
|
+
}
|
|
22988
|
+
const tscBin = join39(productDir, "node_modules", ".bin", "tsc");
|
|
22743
22989
|
const tool = deps.existsSync(tscBin) ? tscBin : "npx";
|
|
22744
22990
|
return {
|
|
22745
22991
|
tool,
|
|
22746
22992
|
args: tool === "npx" ? ["tsc", ...tscArgs] : tscArgs
|
|
22747
22993
|
};
|
|
22748
22994
|
}
|
|
22749
|
-
function runTypeScriptInvocation(
|
|
22995
|
+
function runTypeScriptInvocation(productDir, invocation, runner, outputStreams, cleanup = () => {
|
|
22750
22996
|
}) {
|
|
22751
22997
|
return new Promise((resolve17) => {
|
|
22752
22998
|
const tscProcess = spawnManagedSubprocess(runner, invocation.tool, invocation.args, {
|
|
22753
|
-
cwd:
|
|
22999
|
+
cwd: productDir
|
|
22754
23000
|
});
|
|
23001
|
+
const chunks = [];
|
|
23002
|
+
const capture = (chunk) => {
|
|
23003
|
+
chunks.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString());
|
|
23004
|
+
};
|
|
23005
|
+
tscProcess.stdout?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, capture);
|
|
23006
|
+
tscProcess.stderr?.on(VALIDATION_SUBPROCESS_EVENTS.DATA, capture);
|
|
22755
23007
|
forwardValidationSubprocessOutput(tscProcess, outputStreams);
|
|
22756
23008
|
tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.CLOSE, (code) => {
|
|
22757
23009
|
cleanup();
|
|
23010
|
+
const output = chunks.join("");
|
|
22758
23011
|
if (code === 0) {
|
|
22759
|
-
resolve17({ success: true, skipped: false });
|
|
23012
|
+
resolve17({ success: true, skipped: false, output });
|
|
22760
23013
|
} else {
|
|
22761
|
-
resolve17({ success: false, error: formatTypeScriptExitCodeError(code) });
|
|
23014
|
+
resolve17({ success: false, output, error: formatTypeScriptExitCodeError(code) });
|
|
22762
23015
|
}
|
|
22763
23016
|
});
|
|
22764
23017
|
tscProcess.on(VALIDATION_SUBPROCESS_EVENTS.ERROR, (error) => {
|
|
22765
23018
|
cleanup();
|
|
22766
|
-
resolve17({ success: false, error: error.message });
|
|
23019
|
+
resolve17({ success: false, output: chunks.join(""), error: error.message });
|
|
22767
23020
|
});
|
|
22768
23021
|
});
|
|
22769
23022
|
}
|
|
22770
23023
|
|
|
22771
23024
|
// src/commands/validation/typescript.ts
|
|
23025
|
+
var defaultTypeScriptCommandDeps = {
|
|
23026
|
+
detectTypeScript,
|
|
23027
|
+
discoverTool,
|
|
23028
|
+
validateTypeScript
|
|
23029
|
+
};
|
|
22772
23030
|
var TYPESCRIPT_VALIDATION_MESSAGES = {
|
|
22773
23031
|
ABSENT: formatTypeScriptAbsentSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT),
|
|
22774
|
-
CONFIG_ERROR:
|
|
23032
|
+
CONFIG_ERROR: formatValidationConfigProblemMessage(
|
|
23033
|
+
VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT,
|
|
23034
|
+
"configuration error"
|
|
23035
|
+
),
|
|
22775
23036
|
NO_VALIDATION_PATH_TARGETS: formatValidationPathsNoTargetsSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT),
|
|
23037
|
+
NO_EXPLICIT_PATH_TARGETS: formatExplicitPathsNoTargetsSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT),
|
|
22776
23038
|
SUCCESS: VALIDATION_COMMAND_OUTPUT.TYPESCRIPT_SUCCESS,
|
|
22777
23039
|
TOOL_LABEL: VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT
|
|
22778
23040
|
};
|
|
22779
|
-
|
|
22780
|
-
|
|
23041
|
+
var TYPESCRIPT_TOOL_DISCOVERY = {
|
|
23042
|
+
TOOL: "typescript",
|
|
23043
|
+
EXECUTABLE_NAME: "tsc",
|
|
23044
|
+
BUNDLED_EXECUTABLE: "typescript/bin/tsc",
|
|
23045
|
+
PRODUCT_EXECUTABLE_SEGMENTS: ["node_modules", ".bin", "tsc"]
|
|
23046
|
+
};
|
|
23047
|
+
async function typescriptCommand(options, deps = defaultTypeScriptCommandDeps) {
|
|
23048
|
+
const { cwd, scope: scope2 = "full", files, json, outputStreams, quiet, streamedPipelineOutput } = options;
|
|
22781
23049
|
const startTime = Date.now();
|
|
22782
|
-
const tsDetection = detectTypeScript(cwd);
|
|
23050
|
+
const tsDetection = deps.detectTypeScript(cwd);
|
|
22783
23051
|
if (!tsDetection.present) {
|
|
22784
23052
|
return {
|
|
22785
23053
|
exitCode: 0,
|
|
@@ -22797,53 +23065,69 @@ async function typescriptCommand(options) {
|
|
|
22797
23065
|
}
|
|
22798
23066
|
const validationConfig = loaded.value[validationConfigDescriptor.section];
|
|
22799
23067
|
const scopeConfig = resolveTypeScriptValidationScope({
|
|
22800
|
-
|
|
23068
|
+
productDir: cwd,
|
|
22801
23069
|
scope: scope2,
|
|
22802
23070
|
paths: files,
|
|
22803
23071
|
validationPathFilter: validationPathFilterForTool(
|
|
22804
23072
|
validationConfig.paths,
|
|
22805
23073
|
VALIDATION_PATH_TOOL_SUBSECTIONS.TYPESCRIPT
|
|
22806
23074
|
),
|
|
22807
|
-
markExplicitPathsAsValidationFilter: true
|
|
22808
|
-
bypassExplicitPathValidationFilter: true
|
|
23075
|
+
markExplicitPathsAsValidationFilter: true
|
|
22809
23076
|
});
|
|
22810
|
-
|
|
23077
|
+
const noTargetsMessage = formatValidationScopeNoTargetsSkipMessage(
|
|
23078
|
+
VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT,
|
|
23079
|
+
scopeConfig
|
|
23080
|
+
);
|
|
23081
|
+
if (noTargetsMessage !== void 0) {
|
|
22811
23082
|
return {
|
|
22812
23083
|
exitCode: 0,
|
|
22813
|
-
output: quiet ? "" :
|
|
23084
|
+
output: quiet ? "" : noTargetsMessage,
|
|
22814
23085
|
durationMs: Date.now() - startTime
|
|
22815
23086
|
};
|
|
22816
23087
|
}
|
|
22817
|
-
const toolResult = await discoverTool(
|
|
23088
|
+
const toolResult = await deps.discoverTool(TYPESCRIPT_TOOL_DISCOVERY.TOOL, {
|
|
23089
|
+
productDir: cwd,
|
|
23090
|
+
executableName: TYPESCRIPT_TOOL_DISCOVERY.EXECUTABLE_NAME,
|
|
23091
|
+
bundledExecutable: TYPESCRIPT_TOOL_DISCOVERY.BUNDLED_EXECUTABLE,
|
|
23092
|
+
priority: TOOL_DISCOVERY_PRIORITY.PRODUCT_FIRST
|
|
23093
|
+
});
|
|
22818
23094
|
if (!toolResult.found) {
|
|
22819
23095
|
const skipMessage = formatSkipMessage(VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT, toolResult);
|
|
22820
23096
|
return { exitCode: 0, output: skipMessage, durationMs: Date.now() - startTime };
|
|
22821
23097
|
}
|
|
22822
|
-
const result = await validateTypeScript({
|
|
23098
|
+
const result = await deps.validateTypeScript({
|
|
22823
23099
|
scope: scope2,
|
|
22824
|
-
|
|
23100
|
+
productDir: cwd,
|
|
22825
23101
|
scopeConfig
|
|
22826
23102
|
}, {
|
|
22827
|
-
|
|
23103
|
+
toolPath: toolResult.location.path,
|
|
23104
|
+
outputStreams: outputStreams ?? discardValidationSubprocessOutputStreams
|
|
22828
23105
|
});
|
|
22829
23106
|
const durationMs = Date.now() - startTime;
|
|
22830
|
-
return formatTypeScriptResult(result, quiet, durationMs);
|
|
23107
|
+
return formatTypeScriptResult(result, quiet, durationMs, json, streamedPipelineOutput);
|
|
22831
23108
|
}
|
|
22832
|
-
function formatTypeScriptResult(result, quiet, durationMs) {
|
|
23109
|
+
function formatTypeScriptResult(result, quiet, durationMs, json, streamedPipelineOutput) {
|
|
22833
23110
|
if (result.skipped) {
|
|
22834
23111
|
const output2 = quiet ? "" : TYPESCRIPT_VALIDATION_MESSAGES.NO_VALIDATION_PATH_TARGETS;
|
|
22835
23112
|
return { exitCode: 0, output: output2, durationMs };
|
|
22836
23113
|
}
|
|
22837
23114
|
if (result.success) {
|
|
22838
|
-
const output2 = quiet ? "" : TYPESCRIPT_VALIDATION_MESSAGES.SUCCESS;
|
|
22839
|
-
|
|
23115
|
+
const output2 = quiet ? "" : [TYPESCRIPT_VALIDATION_MESSAGES.SUCCESS, result.output].filter((line) => line !== void 0 && line.length > 0).join("\n");
|
|
23116
|
+
const terminalOutput2 = streamedValidationTerminalOutput(result.output, json, streamedPipelineOutput);
|
|
23117
|
+
return { exitCode: 0, output: output2, terminalOutput: terminalOutput2, durationMs };
|
|
22840
23118
|
}
|
|
22841
|
-
const output = result.error ?? VALIDATION_COMMAND_OUTPUT.TYPESCRIPT_FAILURE;
|
|
22842
|
-
|
|
23119
|
+
const output = [result.output, result.error ?? VALIDATION_COMMAND_OUTPUT.TYPESCRIPT_FAILURE].filter((line) => line !== void 0 && line.length > 0).join("\n");
|
|
23120
|
+
const terminalOutput = streamedValidationTerminalOutput(result.output, json, streamedPipelineOutput);
|
|
23121
|
+
return { exitCode: 1, output, terminalOutput, durationMs };
|
|
22843
23122
|
}
|
|
22844
23123
|
|
|
22845
23124
|
// src/validation/languages/typescript.ts
|
|
22846
23125
|
var TYPESCRIPT_LANGUAGE_NAME = "typescript";
|
|
23126
|
+
var SKIP_CIRCULAR_REASON = "skip-circular";
|
|
23127
|
+
var SKIP_KNIP_REASON = "skip-knip";
|
|
23128
|
+
var SKIP_LINT_REASON = "skip-lint";
|
|
23129
|
+
var SKIP_TYPESCRIPT_REASON = "skip-typescript";
|
|
23130
|
+
var SKIP_LITERAL_REASON = "skip-literal";
|
|
22847
23131
|
var TYPESCRIPT_VALIDATION_CONCERN = {
|
|
22848
23132
|
LINT: "lint",
|
|
22849
23133
|
TYPE_CHECK: "type-check",
|
|
@@ -22852,14 +23136,60 @@ var TYPESCRIPT_VALIDATION_CONCERN = {
|
|
|
22852
23136
|
LITERAL_REUSE: "literal-reuse",
|
|
22853
23137
|
UNUSED_CODE: "unused-code"
|
|
22854
23138
|
};
|
|
23139
|
+
var TYPESCRIPT_VALIDATION_STAGE_BY_CONCERN = {
|
|
23140
|
+
[TYPESCRIPT_VALIDATION_CONCERN.LINT]: VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,
|
|
23141
|
+
[TYPESCRIPT_VALIDATION_CONCERN.TYPE_CHECK]: VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT,
|
|
23142
|
+
[TYPESCRIPT_VALIDATION_CONCERN.AST_ENFORCEMENT]: VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,
|
|
23143
|
+
[TYPESCRIPT_VALIDATION_CONCERN.CIRCULAR_DEPS]: VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR,
|
|
23144
|
+
[TYPESCRIPT_VALIDATION_CONCERN.LITERAL_REUSE]: VALIDATION_STAGE_DISPLAY_NAMES.LITERAL,
|
|
23145
|
+
[TYPESCRIPT_VALIDATION_CONCERN.UNUSED_CODE]: VALIDATION_STAGE_DISPLAY_NAMES.KNIP
|
|
23146
|
+
};
|
|
23147
|
+
var TYPESCRIPT_VALIDATION_STAGE_PARTICIPATION = {
|
|
23148
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR]: {
|
|
23149
|
+
default: VALIDATION_STAGE_PARTICIPATION.RUN,
|
|
23150
|
+
skipReason: SKIP_CIRCULAR_REASON,
|
|
23151
|
+
override: {
|
|
23152
|
+
flag: "--skip-circular",
|
|
23153
|
+
description: "Skip circular dependency detection for this validation all run"
|
|
23154
|
+
}
|
|
23155
|
+
},
|
|
23156
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.KNIP]: {
|
|
23157
|
+
default: VALIDATION_STAGE_PARTICIPATION.RUN,
|
|
23158
|
+
skipReason: SKIP_KNIP_REASON,
|
|
23159
|
+
override: {
|
|
23160
|
+
flag: "--skip-knip",
|
|
23161
|
+
description: "Skip unused-code detection for this validation all run"
|
|
23162
|
+
}
|
|
23163
|
+
},
|
|
23164
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.ESLINT]: {
|
|
23165
|
+
default: VALIDATION_STAGE_PARTICIPATION.RUN,
|
|
23166
|
+
skipReason: SKIP_LINT_REASON,
|
|
23167
|
+
override: {
|
|
23168
|
+
flag: "--skip-lint",
|
|
23169
|
+
description: "Skip ESLint validation for this validation all run"
|
|
23170
|
+
}
|
|
23171
|
+
},
|
|
23172
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT]: {
|
|
23173
|
+
default: VALIDATION_STAGE_PARTICIPATION.RUN,
|
|
23174
|
+
skipReason: SKIP_TYPESCRIPT_REASON,
|
|
23175
|
+
override: {
|
|
23176
|
+
flag: "--skip-typescript",
|
|
23177
|
+
description: "Skip TypeScript validation for this validation all run"
|
|
23178
|
+
}
|
|
23179
|
+
},
|
|
23180
|
+
[VALIDATION_STAGE_DISPLAY_NAMES.LITERAL]: {
|
|
23181
|
+
default: VALIDATION_STAGE_PARTICIPATION.RUN,
|
|
23182
|
+
skipReason: SKIP_LITERAL_REASON,
|
|
23183
|
+
override: {
|
|
23184
|
+
flag: "--skip-literal",
|
|
23185
|
+
description: "Skip literal reuse detection for this validation all run"
|
|
23186
|
+
}
|
|
23187
|
+
}
|
|
23188
|
+
};
|
|
22855
23189
|
var defaultKnipStageDeps = {
|
|
22856
23190
|
knipCommand
|
|
22857
23191
|
};
|
|
22858
23192
|
async function runCircularStage(context) {
|
|
22859
|
-
if (context.skipCircular) {
|
|
22860
|
-
const skipOutput = context.json ? CIRCULAR_SKIP_JSON_OUTPUT : CIRCULAR_SKIP_OUTPUT;
|
|
22861
|
-
return { exitCode: 0, output: context.quiet ? "" : skipOutput };
|
|
22862
|
-
}
|
|
22863
23193
|
return circularCommand({
|
|
22864
23194
|
cwd: context.cwd,
|
|
22865
23195
|
scope: context.scope,
|
|
@@ -22869,10 +23199,6 @@ async function runCircularStage(context) {
|
|
|
22869
23199
|
});
|
|
22870
23200
|
}
|
|
22871
23201
|
async function runLiteralStage(context) {
|
|
22872
|
-
if (context.skipLiteral) {
|
|
22873
|
-
const skipOutput = context.json ? LITERAL_SKIP_JSON_OUTPUT : LITERAL_SKIP_OUTPUT;
|
|
22874
|
-
return { exitCode: 0, output: context.quiet ? "" : skipOutput };
|
|
22875
|
-
}
|
|
22876
23202
|
return literalCommand({
|
|
22877
23203
|
cwd: context.cwd,
|
|
22878
23204
|
scope: context.scope,
|
|
@@ -22887,27 +23213,32 @@ async function runKnipStage(context, deps = defaultKnipStageDeps) {
|
|
|
22887
23213
|
scope: context.scope,
|
|
22888
23214
|
files: context.files,
|
|
22889
23215
|
quiet: context.quiet,
|
|
22890
|
-
json: context.json
|
|
23216
|
+
json: context.json,
|
|
23217
|
+
streamedPipelineOutput: true,
|
|
23218
|
+
outputStreams: context.outputStreams
|
|
22891
23219
|
});
|
|
22892
23220
|
}
|
|
22893
23221
|
var typescriptValidationLanguage = {
|
|
22894
23222
|
name: TYPESCRIPT_LANGUAGE_NAME,
|
|
22895
23223
|
concerns: Object.values(TYPESCRIPT_VALIDATION_CONCERN),
|
|
23224
|
+
stageByConcern: TYPESCRIPT_VALIDATION_STAGE_BY_CONCERN,
|
|
22896
23225
|
stages: [
|
|
22897
23226
|
{
|
|
22898
23227
|
name: VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR,
|
|
22899
23228
|
failsPipeline: true,
|
|
23229
|
+
participation: TYPESCRIPT_VALIDATION_STAGE_PARTICIPATION[VALIDATION_STAGE_DISPLAY_NAMES.CIRCULAR],
|
|
22900
23230
|
run: runCircularStage
|
|
22901
23231
|
},
|
|
22902
23232
|
{
|
|
22903
23233
|
name: VALIDATION_STAGE_DISPLAY_NAMES.KNIP,
|
|
22904
|
-
|
|
22905
|
-
|
|
23234
|
+
failsPipeline: true,
|
|
23235
|
+
participation: TYPESCRIPT_VALIDATION_STAGE_PARTICIPATION[VALIDATION_STAGE_DISPLAY_NAMES.KNIP],
|
|
22906
23236
|
run: runKnipStage
|
|
22907
23237
|
},
|
|
22908
23238
|
{
|
|
22909
23239
|
name: VALIDATION_STAGE_DISPLAY_NAMES.ESLINT,
|
|
22910
23240
|
failsPipeline: true,
|
|
23241
|
+
participation: TYPESCRIPT_VALIDATION_STAGE_PARTICIPATION[VALIDATION_STAGE_DISPLAY_NAMES.ESLINT],
|
|
22911
23242
|
run: (context) => lintCommand({
|
|
22912
23243
|
cwd: context.cwd,
|
|
22913
23244
|
scope: context.scope,
|
|
@@ -22915,32 +23246,46 @@ var typescriptValidationLanguage = {
|
|
|
22915
23246
|
fix: context.fix,
|
|
22916
23247
|
quiet: context.quiet,
|
|
22917
23248
|
json: context.json,
|
|
23249
|
+
streamedPipelineOutput: true,
|
|
22918
23250
|
outputStreams: context.outputStreams
|
|
22919
23251
|
})
|
|
22920
23252
|
},
|
|
22921
23253
|
{
|
|
22922
23254
|
name: VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT,
|
|
22923
23255
|
failsPipeline: true,
|
|
23256
|
+
participation: TYPESCRIPT_VALIDATION_STAGE_PARTICIPATION[VALIDATION_STAGE_DISPLAY_NAMES.TYPESCRIPT],
|
|
22924
23257
|
run: (context) => typescriptCommand({
|
|
22925
23258
|
cwd: context.cwd,
|
|
22926
23259
|
scope: context.scope,
|
|
22927
23260
|
files: context.files,
|
|
22928
23261
|
quiet: context.quiet,
|
|
22929
23262
|
json: context.json,
|
|
23263
|
+
streamedPipelineOutput: true,
|
|
22930
23264
|
outputStreams: context.outputStreams
|
|
22931
23265
|
})
|
|
22932
23266
|
},
|
|
22933
23267
|
{
|
|
22934
23268
|
name: VALIDATION_STAGE_DISPLAY_NAMES.LITERAL,
|
|
22935
23269
|
failsPipeline: true,
|
|
23270
|
+
participation: TYPESCRIPT_VALIDATION_STAGE_PARTICIPATION[VALIDATION_STAGE_DISPLAY_NAMES.LITERAL],
|
|
22936
23271
|
run: runLiteralStage
|
|
22937
23272
|
}
|
|
22938
23273
|
]
|
|
22939
23274
|
};
|
|
22940
23275
|
|
|
22941
23276
|
// src/validation/registry.ts
|
|
23277
|
+
var VALIDATION_STAGE_PARTICIPATION_POLICIES = {
|
|
23278
|
+
...TYPESCRIPT_VALIDATION_STAGE_PARTICIPATION,
|
|
23279
|
+
...MARKDOWN_VALIDATION_STAGE_PARTICIPATION,
|
|
23280
|
+
...FORMATTING_VALIDATION_STAGE_PARTICIPATION
|
|
23281
|
+
};
|
|
23282
|
+
var VALIDATION_REGISTRY_LANGUAGES = [
|
|
23283
|
+
typescriptValidationLanguage,
|
|
23284
|
+
markdownValidationLanguage,
|
|
23285
|
+
formattingValidationLanguage
|
|
23286
|
+
];
|
|
22942
23287
|
var validationRegistry = {
|
|
22943
|
-
languages:
|
|
23288
|
+
languages: VALIDATION_REGISTRY_LANGUAGES
|
|
22944
23289
|
};
|
|
22945
23290
|
function composeValidationPipelineStages(languages) {
|
|
22946
23291
|
return languages.flatMap((language) => language.stages);
|
|
@@ -22974,10 +23319,17 @@ function formatSummary(options) {
|
|
|
22974
23319
|
}
|
|
22975
23320
|
|
|
22976
23321
|
// src/commands/validation/all.ts
|
|
22977
|
-
function formatStepWithTiming(stepNumber, totalSteps, result, quiet) {
|
|
22978
|
-
|
|
23322
|
+
function formatStepWithTiming(stepNumber, totalSteps, stageName, result, quiet) {
|
|
23323
|
+
const output = result.terminalOutput ?? result.output;
|
|
23324
|
+
if (quiet) return "";
|
|
23325
|
+
if (result.terminalOutput === VALIDATION_STREAMED_TERMINAL_OUTPUT) {
|
|
23326
|
+
const verdict = result.exitCode === 0 ? VALIDATION_SYMBOLS.SUCCESS : VALIDATION_SYMBOLS.FAILURE;
|
|
23327
|
+
const timing2 = result.durationMs === void 0 ? "" : ` (${formatDuration(result.durationMs)})`;
|
|
23328
|
+
return `[${stepNumber}/${totalSteps}] ${stageName}: ${verdict} ${VALIDATION_STREAMED_STAGE_RESULT}${timing2}`;
|
|
23329
|
+
}
|
|
23330
|
+
if (!output) return "";
|
|
22979
23331
|
const timing = result.durationMs === void 0 ? "" : ` (${formatDuration(result.durationMs)})`;
|
|
22980
|
-
return `[${stepNumber}/${totalSteps}] ${
|
|
23332
|
+
return `[${stepNumber}/${totalSteps}] ${output}${timing}`;
|
|
22981
23333
|
}
|
|
22982
23334
|
function parseStageOutput(output) {
|
|
22983
23335
|
if (output.length === 0) return null;
|
|
@@ -23011,12 +23363,39 @@ function recordStageResult(options) {
|
|
|
23011
23363
|
});
|
|
23012
23364
|
return;
|
|
23013
23365
|
}
|
|
23014
|
-
const stepOutput = formatStepWithTiming(stepNumber, totalSteps, result, quiet);
|
|
23366
|
+
const stepOutput = formatStepWithTiming(stepNumber, totalSteps, stage.name, result, quiet);
|
|
23015
23367
|
if (stepOutput) {
|
|
23016
23368
|
outputs.push(stepOutput);
|
|
23017
23369
|
writeOutput5?.(stepOutput);
|
|
23018
23370
|
}
|
|
23019
23371
|
}
|
|
23372
|
+
function resolveStageParticipation(stage, participationOverrides) {
|
|
23373
|
+
const override = stage.participation.override;
|
|
23374
|
+
if (participationOverrides.has(override.flag)) {
|
|
23375
|
+
const participation = stage.participation.default === VALIDATION_STAGE_PARTICIPATION.RUN ? VALIDATION_STAGE_PARTICIPATION.SKIP : VALIDATION_STAGE_PARTICIPATION.RUN;
|
|
23376
|
+
return {
|
|
23377
|
+
participation,
|
|
23378
|
+
reason: participation === VALIDATION_STAGE_PARTICIPATION.SKIP ? stage.participation.skipReason : void 0,
|
|
23379
|
+
flag: override.flag
|
|
23380
|
+
};
|
|
23381
|
+
}
|
|
23382
|
+
return {
|
|
23383
|
+
participation: stage.participation.default,
|
|
23384
|
+
reason: stage.participation.default === VALIDATION_STAGE_PARTICIPATION.SKIP ? stage.participation.skipReason : void 0
|
|
23385
|
+
};
|
|
23386
|
+
}
|
|
23387
|
+
function skippedStageResult(stage, participation, json, durationMs) {
|
|
23388
|
+
const reason = participation.reason;
|
|
23389
|
+
if (reason === void 0) {
|
|
23390
|
+
throw new Error(`validation stage ${stage.name} skipped without a configured reason`);
|
|
23391
|
+
}
|
|
23392
|
+
return {
|
|
23393
|
+
exitCode: 0,
|
|
23394
|
+
output: json ? formatValidationStageSkipJsonOutput(reason, durationMs) : formatValidationStageSkipOutput(stage.name, participation.flag ?? reason),
|
|
23395
|
+
structuredOutput: json,
|
|
23396
|
+
durationMs
|
|
23397
|
+
};
|
|
23398
|
+
}
|
|
23020
23399
|
function createCapturedSubprocessOutput() {
|
|
23021
23400
|
const stdout = [];
|
|
23022
23401
|
const stderr = [];
|
|
@@ -23037,14 +23416,72 @@ function createCaptureStream(chunks) {
|
|
|
23037
23416
|
}
|
|
23038
23417
|
};
|
|
23039
23418
|
}
|
|
23419
|
+
function resolveFullPipelineStages(validationStages, dependencyStages) {
|
|
23420
|
+
return validationStages ?? dependencyStages ?? validationPipelineStages;
|
|
23421
|
+
}
|
|
23422
|
+
async function executeValidationStages(options) {
|
|
23423
|
+
let hasFailure = false;
|
|
23424
|
+
for (const [index, stage] of options.stages.entries()) {
|
|
23425
|
+
const stepNumber = index + 1;
|
|
23426
|
+
const execution = await executeValidationStage(stage, options);
|
|
23427
|
+
recordStageResult({
|
|
23428
|
+
json: options.json,
|
|
23429
|
+
stepNumber,
|
|
23430
|
+
totalSteps: options.stages.length,
|
|
23431
|
+
stage,
|
|
23432
|
+
result: execution.result,
|
|
23433
|
+
quiet: options.quiet,
|
|
23434
|
+
outputs: options.outputs,
|
|
23435
|
+
jsonSteps: options.jsonSteps,
|
|
23436
|
+
subprocessOutput: execution.subprocessOutput,
|
|
23437
|
+
writeOutput: options.writeOutput
|
|
23438
|
+
});
|
|
23439
|
+
notifyStageCompletion(stage, execution.result, stepNumber, options);
|
|
23440
|
+
hasFailure ||= stage.failsPipeline && execution.result.exitCode !== 0;
|
|
23441
|
+
}
|
|
23442
|
+
return hasFailure;
|
|
23443
|
+
}
|
|
23444
|
+
async function executeValidationStage(stage, options) {
|
|
23445
|
+
const subprocessOutput = options.json ? createCapturedSubprocessOutput() : void 0;
|
|
23446
|
+
const stageStartTime = options.now();
|
|
23447
|
+
const participation = resolveStageParticipation(stage, options.participationOverrides);
|
|
23448
|
+
const stageResult = participation.participation === VALIDATION_STAGE_PARTICIPATION.RUN ? await stage.run({
|
|
23449
|
+
...options.context,
|
|
23450
|
+
outputStreams: subprocessOutput?.streams ?? options.outputStreams
|
|
23451
|
+
}) : skippedStageResult(stage, participation, options.json, options.now() - stageStartTime);
|
|
23452
|
+
const result = stageResult.durationMs === void 0 ? { ...stageResult, durationMs: options.now() - stageStartTime } : stageResult;
|
|
23453
|
+
return { result, subprocessOutput };
|
|
23454
|
+
}
|
|
23455
|
+
function notifyStageCompletion(stage, result, stepNumber, options) {
|
|
23456
|
+
if (options.json || options.onStageComplete === void 0) return;
|
|
23457
|
+
const output = formatStepWithTiming(stepNumber, options.stages.length, stage.name, result, options.quiet);
|
|
23458
|
+
if (output.length === 0) return;
|
|
23459
|
+
options.onStageComplete({
|
|
23460
|
+
stepNumber,
|
|
23461
|
+
totalSteps: options.stages.length,
|
|
23462
|
+
stageName: stage.name,
|
|
23463
|
+
result,
|
|
23464
|
+
output
|
|
23465
|
+
});
|
|
23466
|
+
}
|
|
23040
23467
|
async function allCommand(options, deps = {}) {
|
|
23041
|
-
const {
|
|
23042
|
-
|
|
23468
|
+
const {
|
|
23469
|
+
cwd,
|
|
23470
|
+
scope: scope2,
|
|
23471
|
+
files,
|
|
23472
|
+
fix,
|
|
23473
|
+
quiet = false,
|
|
23474
|
+
json,
|
|
23475
|
+
validationStages,
|
|
23476
|
+
participationOverrides = [],
|
|
23477
|
+
onStageComplete,
|
|
23478
|
+
outputStreams
|
|
23479
|
+
} = options;
|
|
23480
|
+
const stages = resolveFullPipelineStages(validationStages, deps.stages);
|
|
23043
23481
|
const now = deps.now ?? Date.now;
|
|
23044
23482
|
const startTime = now();
|
|
23045
23483
|
const outputs = [];
|
|
23046
23484
|
const jsonSteps = [];
|
|
23047
|
-
let hasFailure = false;
|
|
23048
23485
|
const context = {
|
|
23049
23486
|
cwd,
|
|
23050
23487
|
scope: scope2,
|
|
@@ -23052,28 +23489,21 @@ async function allCommand(options, deps = {}) {
|
|
|
23052
23489
|
fix,
|
|
23053
23490
|
quiet: json === true ? false : quiet,
|
|
23054
23491
|
json,
|
|
23055
|
-
|
|
23056
|
-
skipLiteral
|
|
23492
|
+
outputStreams
|
|
23057
23493
|
};
|
|
23058
|
-
|
|
23059
|
-
|
|
23060
|
-
|
|
23061
|
-
|
|
23062
|
-
|
|
23063
|
-
|
|
23064
|
-
|
|
23065
|
-
|
|
23066
|
-
|
|
23067
|
-
|
|
23068
|
-
|
|
23069
|
-
|
|
23070
|
-
|
|
23071
|
-
jsonSteps,
|
|
23072
|
-
subprocessOutput,
|
|
23073
|
-
writeOutput: deps.writeOutput
|
|
23074
|
-
});
|
|
23075
|
-
if (stage.failsPipeline && result.exitCode !== 0) hasFailure = true;
|
|
23076
|
-
}
|
|
23494
|
+
const hasFailure = await executeValidationStages({
|
|
23495
|
+
stages,
|
|
23496
|
+
context,
|
|
23497
|
+
participationOverrides: new Set(participationOverrides),
|
|
23498
|
+
json: json === true,
|
|
23499
|
+
quiet,
|
|
23500
|
+
outputs,
|
|
23501
|
+
jsonSteps,
|
|
23502
|
+
onStageComplete,
|
|
23503
|
+
outputStreams,
|
|
23504
|
+
writeOutput: deps.writeOutput,
|
|
23505
|
+
now
|
|
23506
|
+
});
|
|
23077
23507
|
const totalDurationMs = now() - startTime;
|
|
23078
23508
|
if (json === true) {
|
|
23079
23509
|
const jsonOutput = {
|
|
@@ -23086,18 +23516,26 @@ async function allCommand(options, deps = {}) {
|
|
|
23086
23516
|
return {
|
|
23087
23517
|
exitCode: hasFailure ? 1 : 0,
|
|
23088
23518
|
output,
|
|
23519
|
+
outputTarget: VALIDATION_OUTPUT_TARGET.STDOUT,
|
|
23089
23520
|
durationMs: totalDurationMs
|
|
23090
23521
|
};
|
|
23091
23522
|
}
|
|
23523
|
+
let terminalOutput;
|
|
23092
23524
|
if (!quiet) {
|
|
23093
23525
|
const summary = formatSummary({ success: !hasFailure, totalDurationMs });
|
|
23094
|
-
outputs.push("", summary);
|
|
23095
23526
|
deps.writeOutput?.(`
|
|
23096
23527
|
${summary}`);
|
|
23528
|
+
if (onStageComplete !== void 0) {
|
|
23529
|
+
terminalOutput = `
|
|
23530
|
+
${summary}`;
|
|
23531
|
+
} else {
|
|
23532
|
+
outputs.push("", summary);
|
|
23533
|
+
}
|
|
23097
23534
|
}
|
|
23098
23535
|
return {
|
|
23099
23536
|
exitCode: hasFailure ? 1 : 0,
|
|
23100
23537
|
output: outputs.join("\n"),
|
|
23538
|
+
terminalOutput,
|
|
23101
23539
|
durationMs: totalDurationMs
|
|
23102
23540
|
};
|
|
23103
23541
|
}
|
|
@@ -23117,36 +23555,44 @@ var validationCliDefinition = {
|
|
|
23117
23555
|
typescript: {
|
|
23118
23556
|
commandName: "typescript",
|
|
23119
23557
|
alias: "ts",
|
|
23120
|
-
description: "Run TypeScript type checking"
|
|
23558
|
+
description: "Run TypeScript type checking",
|
|
23559
|
+
options: { scope: true, json: false }
|
|
23121
23560
|
},
|
|
23122
23561
|
lint: {
|
|
23123
23562
|
commandName: "lint",
|
|
23124
|
-
description: "Run ESLint"
|
|
23563
|
+
description: "Run ESLint",
|
|
23564
|
+
options: { scope: true, json: false }
|
|
23125
23565
|
},
|
|
23126
23566
|
circular: {
|
|
23127
23567
|
commandName: "circular",
|
|
23128
|
-
description: "Check for circular dependencies"
|
|
23568
|
+
description: "Check for circular dependencies",
|
|
23569
|
+
options: { scope: true, json: false }
|
|
23129
23570
|
},
|
|
23130
23571
|
knip: {
|
|
23131
23572
|
commandName: "knip",
|
|
23132
|
-
description: "Detect unused code"
|
|
23573
|
+
description: "Detect unused code",
|
|
23574
|
+
options: { scope: true, json: false }
|
|
23133
23575
|
},
|
|
23134
23576
|
literal: {
|
|
23135
23577
|
commandName: "literal",
|
|
23136
|
-
description: "Detect cross-file literal reuse between source and tests"
|
|
23578
|
+
description: "Detect cross-file literal reuse between source and tests",
|
|
23579
|
+
options: { scope: true, json: true }
|
|
23137
23580
|
},
|
|
23138
23581
|
markdown: {
|
|
23139
23582
|
commandName: "markdown",
|
|
23140
23583
|
alias: "md",
|
|
23141
|
-
description: "Validate markdown link integrity and structure"
|
|
23584
|
+
description: "Validate markdown link integrity and structure",
|
|
23585
|
+
options: { scope: false, json: false }
|
|
23142
23586
|
},
|
|
23143
23587
|
format: {
|
|
23144
23588
|
commandName: "format",
|
|
23145
|
-
description: "Check code formatting with dprint"
|
|
23589
|
+
description: "Check code formatting with dprint",
|
|
23590
|
+
options: { scope: false, json: false }
|
|
23146
23591
|
},
|
|
23147
23592
|
all: {
|
|
23148
23593
|
commandName: "all",
|
|
23149
|
-
description: "Run all validations"
|
|
23594
|
+
description: "Run all validations",
|
|
23595
|
+
options: { scope: true, json: true }
|
|
23150
23596
|
}
|
|
23151
23597
|
},
|
|
23152
23598
|
commanderHelpOperands: {
|
|
@@ -23196,16 +23642,25 @@ var literalValidationCliOptions = {
|
|
|
23196
23642
|
description: "Print grouped problem details"
|
|
23197
23643
|
}
|
|
23198
23644
|
};
|
|
23199
|
-
var
|
|
23200
|
-
|
|
23201
|
-
flag: "--
|
|
23202
|
-
description: "Skip circular dependency detection for this validation all run"
|
|
23645
|
+
var validationCommonCliOptions = {
|
|
23646
|
+
scope: {
|
|
23647
|
+
flag: "--scope"
|
|
23203
23648
|
},
|
|
23204
|
-
|
|
23205
|
-
flag: "--
|
|
23206
|
-
|
|
23649
|
+
quiet: {
|
|
23650
|
+
flag: "--quiet"
|
|
23651
|
+
},
|
|
23652
|
+
json: {
|
|
23653
|
+
flag: "--json"
|
|
23207
23654
|
}
|
|
23208
23655
|
};
|
|
23656
|
+
var validationAllBuiltInCliOptions = {
|
|
23657
|
+
fix: {
|
|
23658
|
+
flag: "--fix"
|
|
23659
|
+
}
|
|
23660
|
+
};
|
|
23661
|
+
function isValidationLiteralProblemKind(value) {
|
|
23662
|
+
return validationLiteralProblemKinds.some((kind) => kind === value);
|
|
23663
|
+
}
|
|
23209
23664
|
var validationSubcommandOperands = Object.values(validationCliDefinition.subcommands).flatMap(
|
|
23210
23665
|
(subcommand) => {
|
|
23211
23666
|
const operands = [subcommand.commandName];
|
|
@@ -23218,6 +23673,7 @@ var validationKnownOperands = /* @__PURE__ */ new Set([
|
|
|
23218
23673
|
...Object.values(validationCliDefinition.commanderHelpOperands)
|
|
23219
23674
|
]);
|
|
23220
23675
|
var validationOptionPrefix = validationCliDefinition.commanderHelpOperands.longFlag.slice(0, 2);
|
|
23676
|
+
var validationShortOptionPrefix = validationCliDefinition.commanderHelpOperands.shortFlag.slice(0, 1);
|
|
23221
23677
|
|
|
23222
23678
|
// src/validation/literal/allowlist-existing.ts
|
|
23223
23679
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
@@ -23304,27 +23760,86 @@ function serializeWithUpdatedInclude(target, include) {
|
|
|
23304
23760
|
}
|
|
23305
23761
|
|
|
23306
23762
|
// src/interfaces/cli/validation.ts
|
|
23307
|
-
var
|
|
23308
|
-
|
|
23309
|
-
|
|
23310
|
-
|
|
23311
|
-
|
|
23312
|
-
|
|
23313
|
-
|
|
23314
|
-
|
|
23315
|
-
|
|
23316
|
-
|
|
23763
|
+
var LONG_OPTION_PREFIX = "--";
|
|
23764
|
+
var OPTION_PROPERTY_WORD_SEPARATOR_PATTERN = /-([a-z0-9])/g;
|
|
23765
|
+
var VALIDATION_ALL_OVERRIDE_FLAG_PATTERN = /^--(?!no-)[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
|
|
23766
|
+
var validationAllReservedOverrideFlags = /* @__PURE__ */ new Set([
|
|
23767
|
+
...Object.values(validationCommonCliOptions).map((option) => option.flag),
|
|
23768
|
+
...Object.values(validationAllBuiltInCliOptions).map((option) => option.flag),
|
|
23769
|
+
validationCliDefinition.commanderHelpOperands.longFlag
|
|
23770
|
+
]);
|
|
23771
|
+
function validationOptionPropertyName(flag) {
|
|
23772
|
+
return flag.slice(LONG_OPTION_PREFIX.length).replace(OPTION_PROPERTY_WORD_SEPARATOR_PATTERN, (_match, character) => character.toUpperCase());
|
|
23773
|
+
}
|
|
23774
|
+
function deriveValidationAllOverrideCliOptions(stages) {
|
|
23775
|
+
const optionPropertyNames = /* @__PURE__ */ new Set();
|
|
23776
|
+
return stages.flatMap((stage) => {
|
|
23777
|
+
validateStageParticipationMetadata(stage);
|
|
23778
|
+
const override = stage.participation.override;
|
|
23779
|
+
const optionPropertyName = validationOptionPropertyName(override.flag);
|
|
23780
|
+
if (optionPropertyNames.has(optionPropertyName)) {
|
|
23781
|
+
throw new Error(`duplicate validation all override option property: ${optionPropertyName}`);
|
|
23782
|
+
}
|
|
23783
|
+
optionPropertyNames.add(optionPropertyName);
|
|
23784
|
+
return [{
|
|
23785
|
+
stageName: stage.name,
|
|
23786
|
+
flag: override.flag,
|
|
23787
|
+
description: override.description,
|
|
23788
|
+
reason: stage.participation.skipReason,
|
|
23789
|
+
optionPropertyName
|
|
23790
|
+
}];
|
|
23791
|
+
});
|
|
23792
|
+
}
|
|
23793
|
+
function validateStageParticipationMetadata(stage) {
|
|
23794
|
+
if (stage.participation.skipReason.length === 0) {
|
|
23795
|
+
throw new Error(`validation stage ${stage.name} skip participation requires a reason`);
|
|
23796
|
+
}
|
|
23797
|
+
const override = stage.participation.override;
|
|
23798
|
+
if (!VALIDATION_ALL_OVERRIDE_FLAG_PATTERN.test(override.flag)) {
|
|
23799
|
+
throw new Error(`validation stage ${stage.name} override flag must be a bare long kebab-case boolean flag`);
|
|
23800
|
+
}
|
|
23801
|
+
if (validationAllReservedOverrideFlags.has(override.flag)) {
|
|
23802
|
+
throw new Error(`validation stage ${stage.name} override flag collides with a validation all built-in option`);
|
|
23803
|
+
}
|
|
23804
|
+
if (override.description.length === 0) {
|
|
23805
|
+
throw new Error(`validation stage ${stage.name} override flag requires a description`);
|
|
23806
|
+
}
|
|
23807
|
+
}
|
|
23808
|
+
var validationAllOverrideCliOptions = deriveValidationAllOverrideCliOptions(validationPipelineStages);
|
|
23809
|
+
var defaultValidationCommandHandlers = {
|
|
23810
|
+
typescript: typescriptCommand,
|
|
23811
|
+
lint: lintCommand,
|
|
23812
|
+
circular: circularCommand,
|
|
23813
|
+
knip: knipCommand,
|
|
23814
|
+
literal: literalCommand,
|
|
23815
|
+
markdown: markdownCommand,
|
|
23816
|
+
format: formattingCommand,
|
|
23817
|
+
all: allCommand
|
|
23317
23818
|
};
|
|
23318
23819
|
function emitValidationResult(result, io) {
|
|
23319
|
-
|
|
23320
|
-
|
|
23820
|
+
const output = result.terminalOutput ?? result.output;
|
|
23821
|
+
if (output.length > 0) {
|
|
23822
|
+
const outputTarget = result.outputTarget ?? (result.exitCode === 0 ? VALIDATION_OUTPUT_TARGET.STDOUT : VALIDATION_OUTPUT_TARGET.STDERR);
|
|
23823
|
+
const writeOutput5 = outputTarget === VALIDATION_OUTPUT_TARGET.STDOUT ? io.writeStdout : io.writeStderr;
|
|
23824
|
+
writeOutput5(`${output}
|
|
23321
23825
|
`);
|
|
23322
23826
|
}
|
|
23323
23827
|
return io.exit(result.exitCode);
|
|
23324
23828
|
}
|
|
23325
|
-
function addCommonOptions(cmd) {
|
|
23829
|
+
function addCommonOptions(cmd, definition) {
|
|
23326
23830
|
const { pathOperands } = validationCliDefinition;
|
|
23327
|
-
|
|
23831
|
+
let configured = cmd.argument(pathOperands.optionalVariadic, pathOperands.description).option(validationCommonCliOptions.quiet.flag, "Suppress progress output");
|
|
23832
|
+
if (definition.options.scope) {
|
|
23833
|
+
configured = configured.option(
|
|
23834
|
+
`${validationCommonCliOptions.scope.flag} <scope>`,
|
|
23835
|
+
"Validation scope (full|production)",
|
|
23836
|
+
"full"
|
|
23837
|
+
);
|
|
23838
|
+
}
|
|
23839
|
+
if (definition.options.json) {
|
|
23840
|
+
configured = configured.option(validationCommonCliOptions.json.flag, "Output results as JSON");
|
|
23841
|
+
}
|
|
23842
|
+
return configured;
|
|
23328
23843
|
}
|
|
23329
23844
|
async function normalizeProductPathOperand(productDir, effectiveInvocationDir, operand) {
|
|
23330
23845
|
const resolvedProductDir = await canonicalPathThroughExistingAncestor(resolve16(productDir));
|
|
@@ -23384,57 +23899,65 @@ function addValidationSubcommand(validationCmd, definition) {
|
|
|
23384
23899
|
}
|
|
23385
23900
|
return subcommand;
|
|
23386
23901
|
}
|
|
23387
|
-
function
|
|
23902
|
+
function selectedValidationAllOverrides(options, allOverrideCliOptions = validationAllOverrideCliOptions) {
|
|
23903
|
+
return allOverrideCliOptions.filter((option) => options[option.optionPropertyName] === true).map((option) => option.flag);
|
|
23904
|
+
}
|
|
23905
|
+
function registerValidationCommands(validationCmd, invocation, options = {}) {
|
|
23388
23906
|
const { subcommands } = validationCliDefinition;
|
|
23389
|
-
const
|
|
23907
|
+
const commandHandlers = {
|
|
23908
|
+
...defaultValidationCommandHandlers,
|
|
23909
|
+
...options.commandHandlers
|
|
23910
|
+
};
|
|
23911
|
+
const runAllowlistExisting = options.allowlistExisting ?? allowlistExisting;
|
|
23912
|
+
const validationStages = options.validationStages ?? validationPipelineStages;
|
|
23913
|
+
const allOverrideCliOptions = deriveValidationAllOverrideCliOptions(
|
|
23914
|
+
validationStages
|
|
23915
|
+
);
|
|
23916
|
+
const tsCmd = addValidationSubcommand(validationCmd, subcommands.typescript).action(async (pathOperands, options2) => {
|
|
23390
23917
|
const paths = await resolveValidationPaths(invocation, pathOperands);
|
|
23391
|
-
const result = await
|
|
23918
|
+
const result = await commandHandlers.typescript({
|
|
23392
23919
|
cwd: paths.productDir,
|
|
23393
|
-
scope:
|
|
23920
|
+
scope: options2.scope,
|
|
23394
23921
|
files: paths.files,
|
|
23395
|
-
quiet:
|
|
23396
|
-
json: options.json
|
|
23922
|
+
quiet: options2.quiet
|
|
23397
23923
|
});
|
|
23398
23924
|
emitValidationResult(result, invocation.io);
|
|
23399
23925
|
});
|
|
23400
|
-
addCommonOptions(tsCmd);
|
|
23401
|
-
const lintCmd = addValidationSubcommand(validationCmd, subcommands.lint).option("--fix", "Auto-fix issues").action(async (pathOperands,
|
|
23926
|
+
addCommonOptions(tsCmd, subcommands.typescript);
|
|
23927
|
+
const lintCmd = addValidationSubcommand(validationCmd, subcommands.lint).option("--fix", "Auto-fix issues").action(async (pathOperands, options2) => {
|
|
23402
23928
|
const paths = await resolveValidationPaths(invocation, pathOperands);
|
|
23403
|
-
const result = await
|
|
23929
|
+
const result = await commandHandlers.lint({
|
|
23404
23930
|
cwd: paths.productDir,
|
|
23405
|
-
scope:
|
|
23931
|
+
scope: options2.scope,
|
|
23406
23932
|
files: paths.files,
|
|
23407
|
-
fix:
|
|
23408
|
-
quiet:
|
|
23409
|
-
json: options.json
|
|
23933
|
+
fix: options2.fix,
|
|
23934
|
+
quiet: options2.quiet
|
|
23410
23935
|
});
|
|
23411
23936
|
emitValidationResult(result, invocation.io);
|
|
23412
23937
|
});
|
|
23413
|
-
addCommonOptions(lintCmd);
|
|
23414
|
-
const circularCmd = addValidationSubcommand(validationCmd, subcommands.circular).action(async (pathOperands,
|
|
23938
|
+
addCommonOptions(lintCmd, subcommands.lint);
|
|
23939
|
+
const circularCmd = addValidationSubcommand(validationCmd, subcommands.circular).action(async (pathOperands, options2) => {
|
|
23415
23940
|
const paths = await resolveValidationPaths(invocation, pathOperands);
|
|
23416
|
-
const result = await
|
|
23941
|
+
const result = await commandHandlers.circular({
|
|
23417
23942
|
cwd: paths.productDir,
|
|
23418
|
-
scope:
|
|
23943
|
+
scope: options2.scope,
|
|
23419
23944
|
files: paths.files,
|
|
23420
|
-
quiet:
|
|
23421
|
-
json: options.json
|
|
23945
|
+
quiet: options2.quiet
|
|
23422
23946
|
});
|
|
23423
23947
|
emitValidationResult(result, invocation.io);
|
|
23424
23948
|
});
|
|
23425
|
-
addCommonOptions(circularCmd);
|
|
23426
|
-
const knipCmd = addValidationSubcommand(validationCmd, subcommands.knip).action(async (pathOperands,
|
|
23949
|
+
addCommonOptions(circularCmd, subcommands.circular);
|
|
23950
|
+
const knipCmd = addValidationSubcommand(validationCmd, subcommands.knip).action(async (pathOperands, options2) => {
|
|
23427
23951
|
const paths = await resolveValidationPaths(invocation, pathOperands);
|
|
23428
|
-
const result = await
|
|
23952
|
+
const result = await commandHandlers.knip({
|
|
23429
23953
|
cwd: paths.productDir,
|
|
23430
|
-
scope:
|
|
23954
|
+
scope: options2.scope,
|
|
23431
23955
|
files: paths.files,
|
|
23432
|
-
quiet:
|
|
23433
|
-
json: options.json
|
|
23956
|
+
quiet: options2.quiet
|
|
23434
23957
|
});
|
|
23435
23958
|
emitValidationResult(result, invocation.io);
|
|
23436
23959
|
});
|
|
23437
|
-
addCommonOptions(knipCmd);
|
|
23960
|
+
addCommonOptions(knipCmd, subcommands.knip);
|
|
23438
23961
|
const literalCmd = addValidationSubcommand(validationCmd, subcommands.literal).option(
|
|
23439
23962
|
literalValidationCliOptions.allowlistExisting.flag,
|
|
23440
23963
|
literalValidationCliOptions.allowlistExisting.description
|
|
@@ -23444,106 +23967,127 @@ function registerValidationCommands(validationCmd, invocation, deps) {
|
|
|
23444
23967
|
).option(literalValidationCliOptions.literals.flag, literalValidationCliOptions.literals.description).option(literalValidationCliOptions.verbose.flag, literalValidationCliOptions.verbose.description).addHelpText(
|
|
23445
23968
|
"after",
|
|
23446
23969
|
"\nEnabled for TypeScript projects by default. Set validation.literal.enabled=false\nin spx.config.* to skip during migration."
|
|
23447
|
-
).action(async (pathOperands,
|
|
23970
|
+
).action(async (pathOperands, options2) => {
|
|
23448
23971
|
const paths = await resolveValidationPaths(invocation, pathOperands);
|
|
23449
|
-
if (
|
|
23450
|
-
const result2 = await
|
|
23972
|
+
if (options2.allowlistExisting) {
|
|
23973
|
+
const result2 = await runAllowlistExisting({ productDir: paths.productDir });
|
|
23451
23974
|
emitValidationResult(result2, invocation.io);
|
|
23452
23975
|
}
|
|
23453
23976
|
let kind;
|
|
23454
|
-
if (
|
|
23455
|
-
kind = parseLiteralProblemKind(
|
|
23977
|
+
if (options2.kind !== void 0) {
|
|
23978
|
+
kind = parseLiteralProblemKind(options2.kind);
|
|
23456
23979
|
if (kind === void 0) {
|
|
23457
23980
|
const { unknownLiteralProblemKind } = validationCliDefinition.diagnostics;
|
|
23458
23981
|
invocation.io.writeStderr(
|
|
23459
|
-
`spx validation literal: ${unknownLiteralProblemKind.messageLabel}: ${sanitizeCliArgument(
|
|
23982
|
+
`spx validation literal: ${unknownLiteralProblemKind.messageLabel}: ${sanitizeCliArgument(options2.kind)}
|
|
23460
23983
|
`
|
|
23461
23984
|
);
|
|
23462
23985
|
invocation.io.exit(unknownLiteralProblemKind.exitCode);
|
|
23463
23986
|
}
|
|
23464
23987
|
}
|
|
23465
|
-
const result = await
|
|
23988
|
+
const result = await commandHandlers.literal({
|
|
23466
23989
|
cwd: paths.productDir,
|
|
23467
|
-
scope:
|
|
23990
|
+
scope: options2.scope,
|
|
23468
23991
|
files: paths.files,
|
|
23469
23992
|
kind,
|
|
23470
|
-
filesWithProblems:
|
|
23471
|
-
literals:
|
|
23472
|
-
verbose:
|
|
23473
|
-
quiet:
|
|
23474
|
-
json:
|
|
23993
|
+
filesWithProblems: options2.filesWithProblems,
|
|
23994
|
+
literals: options2.literals,
|
|
23995
|
+
verbose: options2.verbose,
|
|
23996
|
+
quiet: options2.quiet,
|
|
23997
|
+
json: options2.json
|
|
23475
23998
|
});
|
|
23476
23999
|
emitValidationResult(result, invocation.io);
|
|
23477
24000
|
});
|
|
23478
|
-
addCommonOptions(literalCmd);
|
|
24001
|
+
addCommonOptions(literalCmd, subcommands.literal);
|
|
23479
24002
|
const markdownCmd = addValidationSubcommand(validationCmd, subcommands.markdown).addHelpText(
|
|
23480
24003
|
"after",
|
|
23481
24004
|
"\nValidates spx/ and docs/ by default. For nodes listed in spx/EXCLUDE,\nonly direct markdown files in that node directory are skipped;\nchild-node markdown remains in scope."
|
|
23482
|
-
).action(async (pathOperands,
|
|
24005
|
+
).action(async (pathOperands, options2) => {
|
|
23483
24006
|
const paths = await resolveValidationPaths(invocation, pathOperands);
|
|
23484
|
-
const result = await
|
|
24007
|
+
const result = await commandHandlers.markdown({
|
|
23485
24008
|
cwd: paths.productDir,
|
|
23486
24009
|
files: paths.files,
|
|
23487
|
-
quiet:
|
|
24010
|
+
quiet: options2.quiet
|
|
23488
24011
|
});
|
|
23489
24012
|
emitValidationResult(result, invocation.io);
|
|
23490
24013
|
});
|
|
23491
|
-
addCommonOptions(markdownCmd);
|
|
23492
|
-
const formatCmd = addValidationSubcommand(validationCmd, subcommands.format).action(async (pathOperands,
|
|
24014
|
+
addCommonOptions(markdownCmd, subcommands.markdown);
|
|
24015
|
+
const formatCmd = addValidationSubcommand(validationCmd, subcommands.format).action(async (pathOperands, options2) => {
|
|
23493
24016
|
const paths = await resolveValidationPaths(invocation, pathOperands);
|
|
23494
|
-
const result = await
|
|
24017
|
+
const result = await commandHandlers.format({
|
|
23495
24018
|
cwd: paths.productDir,
|
|
23496
24019
|
files: paths.files,
|
|
23497
|
-
quiet:
|
|
24020
|
+
quiet: options2.quiet
|
|
23498
24021
|
});
|
|
23499
24022
|
emitValidationResult(result, invocation.io);
|
|
23500
24023
|
});
|
|
23501
|
-
addCommonOptions(formatCmd);
|
|
23502
|
-
|
|
24024
|
+
addCommonOptions(formatCmd, subcommands.format);
|
|
24025
|
+
let allCmd = addValidationSubcommand(validationCmd, subcommands.all).option(validationAllBuiltInCliOptions.fix.flag, "Auto-fix ESLint issues");
|
|
24026
|
+
for (const option of allOverrideCliOptions) {
|
|
24027
|
+
allCmd = allCmd.option(option.flag, option.description);
|
|
24028
|
+
}
|
|
24029
|
+
allCmd = allCmd.action(async (pathOperands, options2) => {
|
|
23503
24030
|
const paths = await resolveValidationPaths(invocation, pathOperands);
|
|
23504
|
-
const result = await
|
|
24031
|
+
const result = await commandHandlers.all({
|
|
23505
24032
|
cwd: paths.productDir,
|
|
23506
|
-
scope:
|
|
24033
|
+
scope: options2.scope,
|
|
23507
24034
|
files: paths.files,
|
|
23508
|
-
fix:
|
|
23509
|
-
|
|
23510
|
-
|
|
23511
|
-
quiet:
|
|
23512
|
-
json:
|
|
23513
|
-
|
|
23514
|
-
|
|
23515
|
-
|
|
24035
|
+
fix: options2.fix,
|
|
24036
|
+
validationStages,
|
|
24037
|
+
participationOverrides: selectedValidationAllOverrides(options2, allOverrideCliOptions),
|
|
24038
|
+
quiet: options2.quiet,
|
|
24039
|
+
json: options2.json,
|
|
24040
|
+
onStageComplete: ({ output }) => invocation.io.writeStdout(`${output}
|
|
24041
|
+
`),
|
|
24042
|
+
outputStreams: validationSubprocessOutputStreams(invocation.io, options2.json)
|
|
23516
24043
|
});
|
|
23517
|
-
|
|
24044
|
+
emitValidationResult(result, invocation.io);
|
|
23518
24045
|
});
|
|
23519
|
-
addCommonOptions(allCmd);
|
|
24046
|
+
addCommonOptions(allCmd, subcommands.all);
|
|
24047
|
+
}
|
|
24048
|
+
function validationSubprocessOutputStreams(io, json) {
|
|
24049
|
+
if (json === true) return discardValidationSubprocessOutputStreams;
|
|
24050
|
+
return {
|
|
24051
|
+
stdout: {
|
|
24052
|
+
write: (chunk) => {
|
|
24053
|
+
io.writeStdout(Buffer.from(chunk).toString());
|
|
24054
|
+
return true;
|
|
24055
|
+
}
|
|
24056
|
+
},
|
|
24057
|
+
stderr: {
|
|
24058
|
+
write: (chunk) => {
|
|
24059
|
+
io.writeStderr(Buffer.from(chunk).toString());
|
|
24060
|
+
return true;
|
|
24061
|
+
}
|
|
24062
|
+
}
|
|
24063
|
+
};
|
|
23520
24064
|
}
|
|
23521
24065
|
function parseLiteralProblemKind(value) {
|
|
23522
|
-
|
|
24066
|
+
if (isValidationLiteralProblemKind(value)) {
|
|
24067
|
+
return value;
|
|
24068
|
+
}
|
|
24069
|
+
return void 0;
|
|
23523
24070
|
}
|
|
23524
24071
|
function handleUnknownSubcommand(operands, io) {
|
|
23525
24072
|
const [first] = operands;
|
|
23526
24073
|
const sanitized = sanitizeCliArgument(first);
|
|
23527
24074
|
const { domain, diagnostics } = validationCliDefinition;
|
|
23528
24075
|
const { unknownSubcommand } = diagnostics;
|
|
23529
|
-
io.writeStderr(
|
|
23530
|
-
|
|
23531
|
-
`
|
|
23532
|
-
);
|
|
24076
|
+
io.writeStderr(`${SPX_PROGRAM_NAME} ${domain.commandName}: ${unknownSubcommand.messageLabel}: ${sanitized}
|
|
24077
|
+
`);
|
|
23533
24078
|
return io.exit(unknownSubcommand.exitCode);
|
|
23534
24079
|
}
|
|
23535
|
-
function createValidationDomain(
|
|
23536
|
-
const deps = { ...defaultValidationCliDependencies, ...overrides };
|
|
24080
|
+
function createValidationDomain(options = {}) {
|
|
23537
24081
|
return {
|
|
23538
24082
|
name: validationCliDefinition.domain.commandName,
|
|
23539
24083
|
description: validationCliDefinition.domain.description,
|
|
23540
24084
|
register: (program, invocation) => {
|
|
23541
24085
|
const { domain } = validationCliDefinition;
|
|
23542
|
-
const validationCmd = program.command(domain.commandName).alias(domain.alias).description(domain.description);
|
|
24086
|
+
const validationCmd = program.command(domain.commandName).alias(domain.alias).description(domain.description).addHelpCommand(false);
|
|
23543
24087
|
validationCmd.on("command:*", (operands) => {
|
|
23544
24088
|
handleUnknownSubcommand(operands, invocation.io);
|
|
23545
24089
|
});
|
|
23546
|
-
registerValidationCommands(validationCmd, invocation,
|
|
24090
|
+
registerValidationCommands(validationCmd, invocation, options);
|
|
23547
24091
|
}
|
|
23548
24092
|
};
|
|
23549
24093
|
}
|
|
@@ -23850,6 +24394,10 @@ var REVIEW_TERMINAL_STATE = {
|
|
|
23850
24394
|
CHANGES_REQUESTED: "changes_requested",
|
|
23851
24395
|
COMMENTED: "commented"
|
|
23852
24396
|
};
|
|
24397
|
+
var REVIEW_TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
24398
|
+
JOURNAL_RUN_STATE_STATUS.APPROVED,
|
|
24399
|
+
JOURNAL_RUN_STATE_STATUS.REJECTED
|
|
24400
|
+
]);
|
|
23853
24401
|
var AUDIT_CLASS = {
|
|
23854
24402
|
IMPLEMENTATION: "implementation",
|
|
23855
24403
|
INSTRUCTIONS: "instructions",
|
|
@@ -24154,6 +24702,9 @@ function validateReviewTerminal(input) {
|
|
|
24154
24702
|
if (input.metadata !== void 0 && validated === void 0) {
|
|
24155
24703
|
return { ok: false, error: TERMINAL_METADATA_VALIDATION_ERROR.METADATA_INVALID };
|
|
24156
24704
|
}
|
|
24705
|
+
if (!REVIEW_TERMINAL_STATUSES.has(input.terminalStatus)) {
|
|
24706
|
+
return { ok: false, error: TERMINAL_METADATA_VALIDATION_ERROR.STATUS_CONFLICT };
|
|
24707
|
+
}
|
|
24157
24708
|
const evidenceStatus = expectedReviewEvidenceTerminalStatus(input.events);
|
|
24158
24709
|
const metadataStatus = expectedReviewMetadataTerminalStatus(validated);
|
|
24159
24710
|
if (evidenceStatus !== void 0 && metadataStatus !== void 0 && evidenceStatus !== metadataStatus) {
|
|
@@ -25685,7 +26236,7 @@ function createCliProgram(options = {}) {
|
|
|
25685
26236
|
|
|
25686
26237
|
// src/cli.ts
|
|
25687
26238
|
installLifecycle();
|
|
25688
|
-
var require3 =
|
|
26239
|
+
var require3 = createRequire3(import.meta.url);
|
|
25689
26240
|
var { version } = require3("../package.json");
|
|
25690
26241
|
createCliProgram({ version }).parse();
|
|
25691
26242
|
//# sourceMappingURL=cli.js.map
|