@codefast/cli 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/README.md +152 -56
- package/dist/arrange/command.js +24 -25
- package/dist/arrange/domain/ast/collectors-cn.d.ts +2 -2
- package/dist/arrange/domain/ast/collectors-cn.js +2 -2
- package/dist/arrange/domain/ast/collectors-jsx.d.ts +2 -2
- package/dist/arrange/domain/ast/collectors-jsx.js +1 -1
- package/dist/arrange/domain/ast/collectors-tv.d.ts +2 -2
- package/dist/arrange/domain/ast/collectors-tv.js +5 -5
- package/dist/arrange/domain/ast/helpers.d.ts +2 -2
- package/dist/arrange/domain/ast/helpers.js +3 -4
- package/dist/arrange/domain/ast/simplify-targets.d.ts +1 -1
- package/dist/arrange/domain/ast/simplify-targets.js +5 -5
- package/dist/arrange/domain/ast/targets.d.ts +2 -2
- package/dist/arrange/domain/ast/targets.js +9 -9
- package/dist/arrange/domain/ast/translator.d.ts +1 -1
- package/dist/arrange/domain/ast/translator.js +43 -29
- package/dist/arrange/domain/constants.d.ts +1 -1
- package/dist/arrange/domain/grouping-service.d.ts +2 -2
- package/dist/arrange/domain/grouping-service.js +3 -3
- package/dist/arrange/domain/grouping.js +3 -3
- package/dist/arrange/domain/imports.d.ts +1 -1
- package/dist/arrange/domain/imports.js +2 -2
- package/dist/arrange/domain/source-text-formatters.js +1 -1
- package/dist/arrange/domain/tailwind-token.js +1 -1
- package/dist/arrange/domain/token-classifier.d.ts +1 -1
- package/dist/arrange/domain/token-classifier.js +2 -2
- package/dist/arrange/domain/types.d.ts +3 -3
- package/dist/arrange/group/cli-result.d.ts +1 -1
- package/dist/arrange/group/output.d.ts +1 -1
- package/dist/arrange/group/output.js +1 -1
- package/dist/arrange/group/suggest.d.ts +2 -2
- package/dist/arrange/group/suggest.js +2 -2
- package/dist/arrange/inspect/cli-result.d.ts +1 -1
- package/dist/arrange/inspect/domain/analyze-service.d.ts +2 -2
- package/dist/arrange/inspect/domain/analyze-service.js +7 -7
- package/dist/arrange/inspect/output.d.ts +1 -1
- package/dist/arrange/inspect/output.js +2 -2
- package/dist/arrange/inspect/run.d.ts +4 -4
- package/dist/arrange/inspect/run.js +6 -6
- package/dist/arrange/prepare.d.ts +4 -4
- package/dist/arrange/prepare.js +5 -5
- package/dist/arrange/regroup/cli-result.d.ts +1 -1
- package/dist/arrange/regroup/cli-result.js +1 -1
- package/dist/arrange/regroup/output.d.ts +2 -2
- package/dist/arrange/regroup/output.js +2 -2
- package/dist/arrange/regroup/process-file.d.ts +2 -2
- package/dist/arrange/regroup/process-file.js +3 -3
- package/dist/arrange/regroup/run.d.ts +5 -5
- package/dist/arrange/regroup/run.js +4 -4
- package/dist/arrange/resolve-target.d.ts +1 -1
- package/dist/arrange/resolve-target.js +2 -2
- package/dist/arrange/scan-target.d.ts +1 -1
- package/dist/arrange/scan-target.js +3 -3
- package/dist/arrange/simplify/cli-result.d.ts +1 -1
- package/dist/arrange/simplify/fold-targets.d.ts +3 -3
- package/dist/arrange/simplify/fold-targets.js +3 -3
- package/dist/arrange/simplify/output.d.ts +1 -1
- package/dist/arrange/simplify/output.js +1 -1
- package/dist/arrange/simplify/process-file.d.ts +4 -4
- package/dist/arrange/simplify/process-file.js +5 -5
- package/dist/arrange/simplify/run.d.ts +4 -4
- package/dist/arrange/simplify/run.js +4 -4
- package/dist/arrange/simplify/variant-classname-probe.js +1 -1
- package/dist/arrange/source-parse.d.ts +1 -1
- package/dist/arrange/source-parse.js +3 -3
- package/dist/audit/assertions/cli-result.d.ts +13 -0
- package/dist/audit/assertions/cli-result.js +22 -0
- package/dist/audit/assertions/cli-schema.d.ts +18 -0
- package/dist/audit/assertions/cli-schema.js +12 -0
- package/dist/audit/assertions/domain/double-assertion.d.ts +20 -0
- package/dist/audit/assertions/domain/double-assertion.js +122 -0
- package/dist/audit/assertions/output.d.ts +7 -0
- package/dist/audit/assertions/output.js +21 -0
- package/dist/audit/assertions/prepare.d.ts +16 -0
- package/dist/audit/assertions/prepare.js +12 -0
- package/dist/audit/assertions/run.d.ts +14 -0
- package/dist/audit/assertions/run.js +40 -0
- package/dist/audit/command.js +89 -28
- package/dist/audit/comments/cli-result.d.ts +1 -1
- package/dist/audit/comments/cli-result.js +1 -1
- package/dist/audit/comments/output.d.ts +1 -1
- package/dist/audit/comments/output.js +1 -1
- package/dist/audit/comments/prepare.d.ts +4 -4
- package/dist/audit/comments/prepare.js +1 -1
- package/dist/audit/comments/run.d.ts +4 -4
- package/dist/audit/comments/run.js +9 -9
- package/dist/audit/constants/cli-result.d.ts +13 -0
- package/dist/audit/constants/cli-result.js +22 -0
- package/dist/audit/constants/cli-schema.d.ts +18 -0
- package/dist/audit/constants/cli-schema.js +12 -0
- package/dist/audit/constants/domain/constants.d.ts +8 -0
- package/dist/audit/constants/domain/constants.js +66 -0
- package/dist/audit/constants/output.d.ts +7 -0
- package/dist/audit/constants/output.js +21 -0
- package/dist/audit/constants/prepare.d.ts +16 -0
- package/dist/audit/constants/prepare.js +37 -0
- package/dist/audit/constants/run.d.ts +14 -0
- package/dist/audit/constants/run.js +64 -0
- package/dist/audit/display-names/cli-result.d.ts +1 -1
- package/dist/audit/display-names/cli-result.js +1 -1
- package/dist/audit/display-names/domain/display-names.d.ts +1 -1
- package/dist/audit/display-names/domain/display-names.js +1 -9
- package/dist/audit/display-names/output.d.ts +1 -1
- package/dist/audit/display-names/output.js +1 -1
- package/dist/audit/display-names/prepare.d.ts +4 -4
- package/dist/audit/display-names/prepare.js +1 -1
- package/dist/audit/display-names/run.d.ts +4 -4
- package/dist/audit/display-names/run.js +5 -5
- package/dist/audit/domain/types.d.ts +128 -0
- package/dist/audit/imports/cli-result.d.ts +1 -1
- package/dist/audit/imports/cli-result.js +1 -1
- package/dist/audit/imports/domain/import-policy.d.ts +1 -1
- package/dist/audit/imports/domain/import-policy.js +4 -18
- package/dist/audit/imports/output.d.ts +1 -1
- package/dist/audit/imports/output.js +1 -1
- package/dist/audit/imports/prepare.d.ts +4 -4
- package/dist/audit/imports/prepare.js +1 -1
- package/dist/audit/imports/run.d.ts +4 -4
- package/dist/audit/imports/run.js +6 -6
- package/dist/audit/links/cli-result.d.ts +1 -1
- package/dist/audit/links/cli-result.js +1 -1
- package/dist/audit/links/domain/markdown-links.d.ts +3 -3
- package/dist/audit/links/domain/markdown-links.js +22 -8
- package/dist/audit/links/output.d.ts +1 -1
- package/dist/audit/links/output.js +1 -1
- package/dist/audit/links/prepare.d.ts +4 -4
- package/dist/audit/links/prepare.js +1 -1
- package/dist/audit/links/run.d.ts +4 -4
- package/dist/audit/links/run.js +4 -4
- package/dist/audit/prepare.d.ts +4 -4
- package/dist/audit/prepare.js +4 -4
- package/dist/audit/publish/cli-result.d.ts +13 -0
- package/dist/audit/publish/cli-result.js +25 -0
- package/dist/audit/publish/cli-schema.d.ts +18 -0
- package/dist/audit/publish/cli-schema.js +12 -0
- package/dist/audit/publish/domain/legacy-subpath.d.ts +8 -0
- package/dist/audit/publish/domain/legacy-subpath.js +22 -0
- package/dist/audit/publish/domain/stylesheet-sources.d.ts +22 -0
- package/dist/audit/publish/domain/stylesheet-sources.js +64 -0
- package/dist/audit/publish/output.d.ts +7 -0
- package/dist/audit/publish/output.js +33 -0
- package/dist/audit/publish/prepare.d.ts +16 -0
- package/dist/audit/publish/prepare.js +12 -0
- package/dist/audit/publish/run.d.ts +15 -0
- package/dist/audit/publish/run.js +91 -0
- package/dist/audit/publish/shipped-files.d.ts +21 -0
- package/dist/audit/publish/shipped-files.js +36 -0
- package/dist/audit/rtl/cli-result.d.ts +1 -1
- package/dist/audit/rtl/cli-result.js +1 -1
- package/dist/audit/rtl/domain/audit-file.d.ts +1 -1
- package/dist/audit/rtl/domain/audit-file.js +2 -2
- package/dist/audit/rtl/domain/tokenize.d.ts +1 -1
- package/dist/audit/rtl/output.d.ts +1 -1
- package/dist/audit/rtl/output.js +1 -1
- package/dist/audit/rtl/prepare.d.ts +4 -4
- package/dist/audit/rtl/prepare.js +5 -5
- package/dist/audit/rtl/run.d.ts +4 -4
- package/dist/audit/rtl/run.js +4 -4
- package/dist/bin.js +1 -1
- package/dist/cli.js +5 -5
- package/dist/core/cli/command-pipeline.d.ts +4 -5
- package/dist/core/cli/command-pipeline.js +7 -7
- package/dist/core/cli/format-error.d.ts +1 -1
- package/dist/core/cli/resolve-root.d.ts +3 -3
- package/dist/core/cli/resolve-root.js +3 -3
- package/dist/core/cli/result-handle.d.ts +2 -2
- package/dist/core/cli/result-handle.js +4 -4
- package/dist/core/config/define-config.d.ts +1 -1
- package/dist/core/config/loader.d.ts +2 -2
- package/dist/core/config/loader.js +2 -2
- package/dist/core/config/schema.d.ts +5 -0
- package/dist/core/config/schema.js +2 -0
- package/dist/core/config/warnings.js +1 -1
- package/dist/core/config.d.ts +4 -4
- package/dist/core/config.js +4 -4
- package/dist/core/filesystem/filesystem.d.ts +3 -4
- package/dist/core/filesystem/node.d.ts +1 -1
- package/dist/core/filesystem/node.js +1 -7
- package/dist/core/oxc-node.d.ts +32 -0
- package/dist/core/oxc-node.js +25 -0
- package/dist/core/schema-parse.d.ts +2 -2
- package/dist/core/schema-parse.js +2 -2
- package/dist/core/source-position.d.ts +15 -0
- package/dist/core/source-position.js +26 -0
- package/dist/core/workspace/markdown-walk.d.ts +1 -1
- package/dist/core/workspace/markdown-walk.js +1 -1
- package/dist/core/workspace/package-version.d.ts +1 -1
- package/dist/core/workspace/package-version.js +2 -2
- package/dist/core/workspace/resolver.d.ts +1 -1
- package/dist/core/workspace/resolver.js +5 -5
- package/dist/core/workspace/source-walk.d.ts +1 -1
- package/dist/core/workspace/source-walk.js +1 -1
- package/dist/core/workspace/typescript-walk.d.ts +1 -1
- package/dist/core/workspace/typescript-walk.js +1 -1
- package/dist/core/workspace/walk-files.d.ts +1 -1
- package/dist/core/workspace/walk-files.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/mirror/cli-result.d.ts +1 -1
- package/dist/mirror/cli-result.js +1 -1
- package/dist/mirror/cli-schema.d.ts +1 -1
- package/dist/mirror/command.js +7 -7
- package/dist/mirror/dist-filesystem-node.d.ts +2 -2
- package/dist/mirror/dist-filesystem-node.js +5 -15
- package/dist/mirror/domain/exports.d.ts +2 -2
- package/dist/mirror/domain/exports.js +1 -1
- package/dist/mirror/domain/types.d.ts +2 -2
- package/dist/mirror/output.d.ts +1 -1
- package/dist/mirror/output.js +2 -2
- package/dist/mirror/package-path.d.ts +3 -3
- package/dist/mirror/package-path.js +3 -3
- package/dist/mirror/prepare.d.ts +5 -5
- package/dist/mirror/prepare.js +4 -4
- package/dist/mirror/run.d.ts +6 -6
- package/dist/mirror/run.js +7 -7
- package/dist/mirror/supplement-exports.d.ts +1 -1
- package/dist/mirror/supplement-exports.js +2 -2
- package/dist/mirror/sync-workspace-package.d.ts +3 -3
- package/dist/mirror/sync-workspace-package.js +11 -14
- package/dist/mirror/write-exports.d.ts +2 -2
- package/dist/mirror/write-exports.js +3 -3
- package/dist/pack-slim/cli-result.d.ts +1 -1
- package/dist/pack-slim/cli-result.js +1 -1
- package/dist/pack-slim/command.js +9 -9
- package/dist/pack-slim/domain/transform.d.ts +22 -1
- package/dist/pack-slim/domain/transform.js +65 -8
- package/dist/pack-slim/output.d.ts +1 -1
- package/dist/pack-slim/output.js +1 -1
- package/dist/pack-slim/prepare.d.ts +3 -3
- package/dist/pack-slim/prepare.js +2 -2
- package/dist/pack-slim/run.d.ts +5 -5
- package/dist/pack-slim/run.js +6 -6
- package/dist/pack-slim/working-tree.d.ts +2 -2
- package/dist/pack-slim/working-tree.js +2 -2
- package/dist/tag/cli-result.d.ts +1 -1
- package/dist/tag/cli-result.js +1 -1
- package/dist/tag/cli-schema.d.ts +1 -1
- package/dist/tag/command.js +7 -7
- package/dist/tag/domain/skip-filter.d.ts +1 -1
- package/dist/tag/domain/skip-filter.js +1 -1
- package/dist/tag/domain/types.d.ts +1 -1
- package/dist/tag/domain/version-summary.d.ts +5 -2
- package/dist/tag/output.d.ts +1 -1
- package/dist/tag/output.js +1 -1
- package/dist/tag/prepare.d.ts +4 -4
- package/dist/tag/prepare.js +4 -4
- package/dist/tag/run.d.ts +4 -4
- package/dist/tag/run.js +7 -7
- package/dist/tag/target/candidates.d.ts +2 -2
- package/dist/tag/target/candidates.js +2 -2
- package/dist/tag/target/resolve-path.d.ts +1 -1
- package/dist/tag/target/runner.d.ts +2 -2
- package/dist/tag/target/runner.js +3 -3
- package/dist/tag/writer/since-writer.d.ts +2 -2
- package/dist/tag/writer/since-writer.js +3 -5
- package/dist/tag/writer/version-resolver.d.ts +1 -1
- package/dist/tag/writer/version-resolver.js +1 -1
- package/package.json +7 -7
- package/dist/mirror/domain/dirent-guard.d.ts +0 -10
- package/dist/mirror/domain/dirent-guard.js +0 -15
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Collects cn() calls whose override classes can fold into a variant function's `className` option. */
|
|
2
|
-
import type { DomainSourceFile } from "
|
|
3
|
-
import type { PlannedSimplifyEdit } from "
|
|
4
|
-
import type { FileClassNameProbe } from "
|
|
2
|
+
import type { DomainSourceFile } from "#arrange/domain/ast/ast-node";
|
|
3
|
+
import type { PlannedSimplifyEdit } from "#arrange/domain/ast/simplify-targets";
|
|
4
|
+
import type { FileClassNameProbe } from "#arrange/simplify/variant-classname-probe";
|
|
5
5
|
/**
|
|
6
6
|
* Collects `className` fold edits for every foldable `cn(variant({…}), …)` call in a source file.
|
|
7
7
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Collects cn() calls whose override classes can fold into a variant function's `className` option. */
|
|
2
|
-
import { forEachDomainChild, isDomainCallExpression, isDomainIdentifier, isDomainObjectLiteralExpression, isDomainPropertyAccessExpression, isDomainPropertyAssignment, isDomainTailwindClassLiteral, } from "
|
|
3
|
-
import { buildKnownCnTvBindings, isCnOrTvIdentifier, propertyAssignmentNameText } from "
|
|
4
|
-
import { escapeTsStringLiteralContent } from "
|
|
2
|
+
import { forEachDomainChild, isDomainCallExpression, isDomainIdentifier, isDomainObjectLiteralExpression, isDomainPropertyAccessExpression, isDomainPropertyAssignment, isDomainTailwindClassLiteral, } from "#arrange/domain/ast/ast-node";
|
|
3
|
+
import { buildKnownCnTvBindings, isCnOrTvIdentifier, propertyAssignmentNameText } from "#arrange/domain/ast/helpers";
|
|
4
|
+
import { escapeTsStringLiteralContent } from "#arrange/domain/source-text-formatters";
|
|
5
5
|
/** Groups a run of trailing cn() arguments, coalescing adjacent static literals into one piece. */
|
|
6
6
|
function coalesceTrailingArgs(args, sourceText) {
|
|
7
7
|
const pieces = [];
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { GroupFileResult } from "
|
|
2
|
-
import type { VariantClassNameProbe } from "
|
|
3
|
-
import type { Filesystem } from "
|
|
1
|
+
import type { GroupFileResult } from "#arrange/domain/types";
|
|
2
|
+
import type { VariantClassNameProbe } from "#arrange/simplify/variant-classname-probe";
|
|
3
|
+
import type { Filesystem } from "#core/filesystem/filesystem";
|
|
4
4
|
/**
|
|
5
5
|
* Runs the simplify pass on one file — flattening class expressions and pruning an unused `cn` import.
|
|
6
6
|
*
|
|
7
7
|
* @since 0.3.16-canary.0
|
|
8
8
|
*/
|
|
9
|
-
export declare function processArrangeSimplifyFile(fs: Filesystem, args: {
|
|
9
|
+
export declare function processArrangeSimplifyFile(fs: Pick<Filesystem, "readFileSync" | "writeFileSync">, args: {
|
|
10
10
|
readonly filePath: string;
|
|
11
11
|
readonly write: boolean;
|
|
12
12
|
readonly probe?: VariantClassNameProbe | null;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { collectSimplifyTargets } from "
|
|
2
|
-
import { dropCnImportIfUnused } from "
|
|
3
|
-
import { collectClassNameFoldTargets } from "
|
|
4
|
-
import { parseDomainSourceFile } from "
|
|
5
|
-
import { applyEditsDescending, dropOverlappingEdits } from "
|
|
1
|
+
import { collectSimplifyTargets } from "#arrange/domain/ast/simplify-targets";
|
|
2
|
+
import { dropCnImportIfUnused } from "#arrange/domain/imports";
|
|
3
|
+
import { collectClassNameFoldTargets } from "#arrange/simplify/fold-targets";
|
|
4
|
+
import { parseDomainSourceFile } from "#arrange/source-parse";
|
|
5
|
+
import { applyEditsDescending, dropOverlappingEdits } from "#core/source-text-edit";
|
|
6
6
|
// A file simplify can act on names `cn`/`tv` (a call or an import to prune) or carries a `class`/`className`;
|
|
7
7
|
// a source with none of these has nothing to flatten or fold, so it never needs parsing.
|
|
8
8
|
const SIMPLIFY_MARKER = /\b(?:cn|tv)\b|className|\bclass\s*[=:]/;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ArrangeRunResult } from "
|
|
2
|
-
import type { AppError } from "
|
|
3
|
-
import type { Filesystem } from "
|
|
4
|
-
import type { Result } from "
|
|
1
|
+
import type { ArrangeRunResult } from "#arrange/domain/types";
|
|
2
|
+
import type { AppError } from "#core/errors";
|
|
3
|
+
import type { Filesystem } from "#core/filesystem/filesystem";
|
|
4
|
+
import type { Result } from "#core/result";
|
|
5
5
|
/**
|
|
6
6
|
* Runs the simplify pass over every target file and returns the aggregated result.
|
|
7
7
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { scanArrangeTargets } from "
|
|
2
|
-
import { processArrangeSimplifyFile } from "
|
|
3
|
-
import { createVariantClassNameProbe } from "
|
|
4
|
-
import { ok } from "
|
|
1
|
+
import { scanArrangeTargets } from "#arrange/scan-target";
|
|
2
|
+
import { processArrangeSimplifyFile } from "#arrange/simplify/process-file";
|
|
3
|
+
import { createVariantClassNameProbe } from "#arrange/simplify/variant-classname-probe";
|
|
4
|
+
import { ok } from "#core/result";
|
|
5
5
|
/**
|
|
6
6
|
* Runs the simplify pass over every target file and returns the aggregated result.
|
|
7
7
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Type probe that asks whether a variant function's options accept a folded `className`. */
|
|
2
|
-
import { AppError, messageFrom } from "
|
|
2
|
+
import { AppError, messageFrom } from "#core/errors";
|
|
3
3
|
// ── Type inspection ──────────────────────────────────────────────────────────────────────────────────────────────────
|
|
4
4
|
/** The type of the callee's first-parameter `className` (preferred) or `class` option, if any. */
|
|
5
5
|
function classNameOptionType(checker, optionsType) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { TypeScriptAstTranslator } from "
|
|
2
|
-
import { messageFrom } from "
|
|
3
|
-
import { logger } from "
|
|
1
|
+
import { TypeScriptAstTranslator } from "#arrange/domain/ast/translator";
|
|
2
|
+
import { messageFrom } from "#core/errors";
|
|
3
|
+
import { logger } from "#core/logger";
|
|
4
4
|
const translator = new TypeScriptAstTranslator();
|
|
5
5
|
/**
|
|
6
6
|
* Parses source text into a domain source file via the shared `oxc-parser` translator.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AssertionAuditResult } from "#audit/domain/types";
|
|
2
|
+
/**
|
|
3
|
+
* Exit `1` when any non-allowlisted type-assertion violation remains.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.13.0
|
|
6
|
+
*/
|
|
7
|
+
export declare function exitCodeForAssertionAuditResult(result: AssertionAuditResult): number;
|
|
8
|
+
/**
|
|
9
|
+
* Machine-readable type-assertion summary for `--json`.
|
|
10
|
+
*
|
|
11
|
+
* @since 0.13.0
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatAssertionAuditJsonOutput(result: AssertionAuditResult, rootDir: string): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CLI_EXIT_GENERAL_ERROR, CLI_EXIT_SUCCESS } from "#core/exit-codes";
|
|
2
|
+
/**
|
|
3
|
+
* Exit `1` when any non-allowlisted type-assertion violation remains.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.13.0
|
|
6
|
+
*/
|
|
7
|
+
export function exitCodeForAssertionAuditResult(result) {
|
|
8
|
+
return result.violationCount > 0 ? CLI_EXIT_GENERAL_ERROR : CLI_EXIT_SUCCESS;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Machine-readable type-assertion summary for `--json`.
|
|
12
|
+
*
|
|
13
|
+
* @since 0.13.0
|
|
14
|
+
*/
|
|
15
|
+
export function formatAssertionAuditJsonOutput(result, rootDir) {
|
|
16
|
+
return JSON.stringify({
|
|
17
|
+
schemaVersion: 1,
|
|
18
|
+
ok: result.violationCount === 0,
|
|
19
|
+
cwd: rootDir,
|
|
20
|
+
result,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Resolved request for a single type-assertion audit run.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.13.0
|
|
6
|
+
*/
|
|
7
|
+
export type AssertionAuditRunRequest = {
|
|
8
|
+
readonly rootDir: string;
|
|
9
|
+
readonly targetPath: string;
|
|
10
|
+
readonly allowlist?: ReadonlyArray<string> | undefined;
|
|
11
|
+
readonly json: boolean;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Zod schema for {@link AssertionAuditRunRequest}.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.13.0
|
|
17
|
+
*/
|
|
18
|
+
export declare const assertionAuditRunRequestSchema: z.ZodType<AssertionAuditRunRequest>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for {@link AssertionAuditRunRequest}.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.13.0
|
|
6
|
+
*/
|
|
7
|
+
export const assertionAuditRunRequestSchema = z.object({
|
|
8
|
+
rootDir: z.string().min(1),
|
|
9
|
+
targetPath: z.string().min(1),
|
|
10
|
+
allowlist: z.array(z.string()).optional(),
|
|
11
|
+
json: z.boolean(),
|
|
12
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AssertionViolation } from "#audit/domain/types";
|
|
2
|
+
/**
|
|
3
|
+
* The comment that keeps one double assertion, with the reason it has to stay.
|
|
4
|
+
*
|
|
5
|
+
* @remarks It covers an assertion on its own line or the line below it, and must carry a reason
|
|
6
|
+
* after the colon; one that covers nothing is reported, so a kept assertion cannot outlive its cause.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.13.0
|
|
9
|
+
*/
|
|
10
|
+
export declare const DOUBLE_ASSERTION_DIRECTIVE = "codefast-allow-double-assertion";
|
|
11
|
+
/**
|
|
12
|
+
* Scans one TypeScript source for double assertions through `unknown` or `any`, and for directives
|
|
13
|
+
* that keep none or give no reason.
|
|
14
|
+
*
|
|
15
|
+
* @remarks `x as unknown as T`, `(x as unknown) as T` and `<T><unknown>x` are one shape: the
|
|
16
|
+
* compiler found the two types unrelated, and the pair silences it instead of reconciling them.
|
|
17
|
+
*
|
|
18
|
+
* @since 0.13.0
|
|
19
|
+
*/
|
|
20
|
+
export declare function auditDoubleAssertionSource(filePath: string, sourceText: string): Array<AssertionViolation>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { parseSync } from "oxc-parser";
|
|
2
|
+
import { isOxcNode } from "#core/oxc-node";
|
|
3
|
+
import { firstLineOf, lineOfOffset } from "#core/source-position";
|
|
4
|
+
/**
|
|
5
|
+
* The comment that keeps one double assertion, with the reason it has to stay.
|
|
6
|
+
*
|
|
7
|
+
* @remarks It covers an assertion on its own line or the line below it, and must carry a reason
|
|
8
|
+
* after the colon; one that covers nothing is reported, so a kept assertion cannot outlive its cause.
|
|
9
|
+
*
|
|
10
|
+
* @since 0.13.0
|
|
11
|
+
*/
|
|
12
|
+
export const DOUBLE_ASSERTION_DIRECTIVE = "codefast-allow-double-assertion";
|
|
13
|
+
const DOUBLE_ASSERTION_REASON = "double assertion through `unknown`/`any` — make the types agree, narrow with a type guard, or keep it " +
|
|
14
|
+
`with // ${DOUBLE_ASSERTION_DIRECTIVE}: <reason>`;
|
|
15
|
+
// Most files hold neither, so a text probe spares them the parse.
|
|
16
|
+
const CANDIDATE_TEXT = new RegExp(`\\bas\\s+(?:unknown|any)\\b|<(?:unknown|any)>|${DOUBLE_ASSERTION_DIRECTIVE}`);
|
|
17
|
+
function isAssertion(node) {
|
|
18
|
+
return node.type === "TSAsExpression" || node.type === "TSTypeAssertion";
|
|
19
|
+
}
|
|
20
|
+
/** The assertion an outer one wraps, through any parentheses, when it erases to `unknown` or `any`. */
|
|
21
|
+
function erasingInnerAssertion(outer) {
|
|
22
|
+
let inner = outer.expression;
|
|
23
|
+
while (isOxcNode(inner) && inner.type === "ParenthesizedExpression") {
|
|
24
|
+
inner = inner.expression;
|
|
25
|
+
}
|
|
26
|
+
if (!isOxcNode(inner) || !isAssertion(inner) || !isOxcNode(inner.typeAnnotation)) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
const erasedTo = inner.typeAnnotation.type;
|
|
30
|
+
return erasedTo === "TSUnknownKeyword" || erasedTo === "TSAnyKeyword" ? inner : undefined;
|
|
31
|
+
}
|
|
32
|
+
function collectDoubleAssertions(node, found) {
|
|
33
|
+
let next = node;
|
|
34
|
+
if (isAssertion(node)) {
|
|
35
|
+
const inner = erasingInnerAssertion(node);
|
|
36
|
+
if (inner !== undefined) {
|
|
37
|
+
found.push(node);
|
|
38
|
+
// The erased pair is one finding; what it wraps is walked on its own.
|
|
39
|
+
next = inner;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
for (const value of Object.values(next)) {
|
|
43
|
+
if (Array.isArray(value)) {
|
|
44
|
+
for (const item of value) {
|
|
45
|
+
if (isOxcNode(item)) {
|
|
46
|
+
collectDoubleAssertions(item, found);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (isOxcNode(value)) {
|
|
51
|
+
collectDoubleAssertions(value, found);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function parseDirective(sourceText, comment) {
|
|
56
|
+
if (comment.type !== "Line") {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
const text = comment.value.trim();
|
|
60
|
+
if (!text.startsWith(DOUBLE_ASSERTION_DIRECTIVE)) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
const reason = /^:\s*(\S.*)$/.exec(text.slice(DOUBLE_ASSERTION_DIRECTIVE.length))?.[1] ?? "";
|
|
64
|
+
return {
|
|
65
|
+
line: lineOfOffset(sourceText, comment.start),
|
|
66
|
+
raw: sourceText.slice(comment.start, comment.end),
|
|
67
|
+
reason,
|
|
68
|
+
isUsed: false,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Scans one TypeScript source for double assertions through `unknown` or `any`, and for directives
|
|
73
|
+
* that keep none or give no reason.
|
|
74
|
+
*
|
|
75
|
+
* @remarks `x as unknown as T`, `(x as unknown) as T` and `<T><unknown>x` are one shape: the
|
|
76
|
+
* compiler found the two types unrelated, and the pair silences it instead of reconciling them.
|
|
77
|
+
*
|
|
78
|
+
* @since 0.13.0
|
|
79
|
+
*/
|
|
80
|
+
export function auditDoubleAssertionSource(filePath, sourceText) {
|
|
81
|
+
if (!CANDIDATE_TEXT.test(sourceText)) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
const { program, comments } = parseSync(filePath, sourceText);
|
|
85
|
+
const directives = comments.map((comment) => parseDirective(sourceText, comment)).filter((d) => d !== undefined);
|
|
86
|
+
const found = [];
|
|
87
|
+
if (isOxcNode(program)) {
|
|
88
|
+
collectDoubleAssertions(program, found);
|
|
89
|
+
}
|
|
90
|
+
const violations = [];
|
|
91
|
+
for (const assertion of found) {
|
|
92
|
+
const line = lineOfOffset(sourceText, assertion.start);
|
|
93
|
+
const directive = directives.find((candidate) => candidate.reason !== "" && (candidate.line === line || candidate.line === line - 1));
|
|
94
|
+
if (directive !== undefined) {
|
|
95
|
+
directive.isUsed = true;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
violations.push({
|
|
99
|
+
line,
|
|
100
|
+
raw: firstLineOf(sourceText.slice(assertion.start, assertion.end)),
|
|
101
|
+
reason: DOUBLE_ASSERTION_REASON,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
for (const directive of directives) {
|
|
105
|
+
if (directive.reason === "") {
|
|
106
|
+
violations.push({
|
|
107
|
+
line: directive.line,
|
|
108
|
+
raw: directive.raw,
|
|
109
|
+
reason: `a ${DOUBLE_ASSERTION_DIRECTIVE} directive states why after a colon`,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
else if (!directive.isUsed) {
|
|
113
|
+
violations.push({
|
|
114
|
+
line: directive.line,
|
|
115
|
+
raw: directive.raw,
|
|
116
|
+
reason: `this ${DOUBLE_ASSERTION_DIRECTIVE} directive keeps no double assertion — remove it`,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
violations.sort((a, b) => a.line - b.line);
|
|
121
|
+
return violations;
|
|
122
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { logger } from "#core/logger";
|
|
2
|
+
/**
|
|
3
|
+
* Human-readable type-assertion report.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.13.0
|
|
6
|
+
*/
|
|
7
|
+
export function presentAssertionAuditResult(result) {
|
|
8
|
+
for (const file of result.files) {
|
|
9
|
+
logger.out(`\n${file.relativePath}`);
|
|
10
|
+
for (const { line, raw, reason } of file.violations) {
|
|
11
|
+
logger.out(` ${line}: ${raw} → ${reason}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const allowlistSuffix = result.allowlistedCount > 0 ? ` (${result.allowlistedCount} allowlisted)` : "";
|
|
15
|
+
if (result.violationCount > 0) {
|
|
16
|
+
logger.out(`\n✖ ${result.violationCount} type-assertion violation(s)${allowlistSuffix}`);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
logger.out(`✓ No double assertions across ${result.scannedFileCount} file(s)${allowlistSuffix}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AuditCommandPrelude } from "#audit/prepare";
|
|
2
|
+
import type { AppError } from "#core/errors";
|
|
3
|
+
import type { Filesystem } from "#core/filesystem/filesystem";
|
|
4
|
+
import type { Result } from "#core/result";
|
|
5
|
+
/**
|
|
6
|
+
* Loads config and resolves the scan target for `audit assertions`.
|
|
7
|
+
*
|
|
8
|
+
* @remarks Defaults to the repo root, tests included: a double assertion in a test silences the
|
|
9
|
+
* compiler on the code the test is meant to hold to its types.
|
|
10
|
+
*
|
|
11
|
+
* @since 0.13.0
|
|
12
|
+
*/
|
|
13
|
+
export declare function prepareAssertionAudit(fs: Filesystem, args: {
|
|
14
|
+
readonly currentWorkingDirectory: string;
|
|
15
|
+
readonly rawTarget: string | undefined;
|
|
16
|
+
}): Promise<Result<AuditCommandPrelude, AppError>>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { prepareRepoRootAudit } from "#audit/prepare";
|
|
2
|
+
/**
|
|
3
|
+
* Loads config and resolves the scan target for `audit assertions`.
|
|
4
|
+
*
|
|
5
|
+
* @remarks Defaults to the repo root, tests included: a double assertion in a test silences the
|
|
6
|
+
* compiler on the code the test is meant to hold to its types.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.13.0
|
|
9
|
+
*/
|
|
10
|
+
export async function prepareAssertionAudit(fs, args) {
|
|
11
|
+
return prepareRepoRootAudit(fs, args, (config) => config.audit?.assertions?.allowlist ?? []);
|
|
12
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AssertionAuditResult } from "#audit/domain/types";
|
|
2
|
+
import { AppError } from "#core/errors";
|
|
3
|
+
import type { Filesystem } from "#core/filesystem/filesystem";
|
|
4
|
+
import type { Result } from "#core/result";
|
|
5
|
+
/**
|
|
6
|
+
* Scans a target path for double assertions through `unknown` or `any`, tests included.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.13.0
|
|
9
|
+
*/
|
|
10
|
+
export declare function runAssertionAudit(fs: Filesystem, args: {
|
|
11
|
+
readonly rootDir: string;
|
|
12
|
+
readonly targetPath: string;
|
|
13
|
+
readonly allowlist: ReadonlyArray<string>;
|
|
14
|
+
}): Result<AssertionAuditResult, AppError>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { auditDoubleAssertionSource } from "#audit/assertions/domain/double-assertion";
|
|
3
|
+
import { AppError, messageFrom } from "#core/errors";
|
|
4
|
+
import { err, ok } from "#core/result";
|
|
5
|
+
import { walkTsxFiles } from "#core/workspace/typescript-walk";
|
|
6
|
+
/**
|
|
7
|
+
* Scans a target path for double assertions through `unknown` or `any`, tests included.
|
|
8
|
+
*
|
|
9
|
+
* @since 0.13.0
|
|
10
|
+
*/
|
|
11
|
+
export function runAssertionAudit(fs, args) {
|
|
12
|
+
try {
|
|
13
|
+
const allowlist = new Set(args.allowlist);
|
|
14
|
+
const { rootDir, targetPath } = args;
|
|
15
|
+
const filesToScan = fs.statSync(targetPath).isFile() ? [targetPath] : walkTsxFiles(targetPath, fs);
|
|
16
|
+
const files = [];
|
|
17
|
+
let violationCount = 0;
|
|
18
|
+
let allowlistedCount = 0;
|
|
19
|
+
for (const absolutePath of filesToScan) {
|
|
20
|
+
const relativePath = path.relative(rootDir, absolutePath).split(path.sep).join("/");
|
|
21
|
+
const content = fs.readFileSync(absolutePath, "utf8");
|
|
22
|
+
const remaining = auditDoubleAssertionSource(absolutePath, content).filter(({ raw }) => {
|
|
23
|
+
const isAllowed = allowlist.has(raw) || allowlist.has(`${relativePath}:${raw}`);
|
|
24
|
+
if (isAllowed) {
|
|
25
|
+
allowlistedCount++;
|
|
26
|
+
}
|
|
27
|
+
return !isAllowed;
|
|
28
|
+
});
|
|
29
|
+
if (remaining.length === 0) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
violationCount += remaining.length;
|
|
33
|
+
files.push({ relativePath, violations: remaining });
|
|
34
|
+
}
|
|
35
|
+
return ok({ files, violationCount, allowlistedCount, scannedFileCount: filesToScan.length });
|
|
36
|
+
}
|
|
37
|
+
catch (caughtError) {
|
|
38
|
+
return err(new AppError("INFRA_FAILURE", messageFrom(caughtError), caughtError));
|
|
39
|
+
}
|
|
40
|
+
}
|
package/dist/audit/command.js
CHANGED
|
@@ -1,31 +1,46 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
2
|
+
import { exitCodeForAssertionAuditResult, formatAssertionAuditJsonOutput } from "#audit/assertions/cli-result";
|
|
3
|
+
import { assertionAuditRunRequestSchema } from "#audit/assertions/cli-schema";
|
|
4
|
+
import { presentAssertionAuditResult } from "#audit/assertions/output";
|
|
5
|
+
import { prepareAssertionAudit } from "#audit/assertions/prepare";
|
|
6
|
+
import { runAssertionAudit } from "#audit/assertions/run";
|
|
7
|
+
import { exitCodeForCommentAuditResult, formatCommentAuditJsonOutput } from "#audit/comments/cli-result";
|
|
8
|
+
import { commentAuditRunRequestSchema } from "#audit/comments/cli-schema";
|
|
9
|
+
import { presentCommentAuditResult } from "#audit/comments/output";
|
|
10
|
+
import { prepareCommentAudit } from "#audit/comments/prepare";
|
|
11
|
+
import { runCommentAudit } from "#audit/comments/run";
|
|
12
|
+
import { exitCodeForConstantAuditResult, formatConstantAuditJsonOutput } from "#audit/constants/cli-result";
|
|
13
|
+
import { constantAuditRunRequestSchema } from "#audit/constants/cli-schema";
|
|
14
|
+
import { presentConstantAuditResult } from "#audit/constants/output";
|
|
15
|
+
import { prepareConstantAudit } from "#audit/constants/prepare";
|
|
16
|
+
import { runConstantAudit } from "#audit/constants/run";
|
|
17
|
+
import { exitCodeForDisplayNameAuditResult, formatDisplayNameAuditJsonOutput } from "#audit/display-names/cli-result";
|
|
18
|
+
import { displayNameAuditRunRequestSchema } from "#audit/display-names/cli-schema";
|
|
19
|
+
import { presentDisplayNameAuditResult } from "#audit/display-names/output";
|
|
20
|
+
import { prepareDisplayNameAudit } from "#audit/display-names/prepare";
|
|
21
|
+
import { runDisplayNameAudit } from "#audit/display-names/run";
|
|
22
|
+
import { exitCodeForImportsAuditResult, formatImportsAuditJsonOutput } from "#audit/imports/cli-result";
|
|
23
|
+
import { importsAuditRunRequestSchema } from "#audit/imports/cli-schema";
|
|
24
|
+
import { presentImportsAuditResult } from "#audit/imports/output";
|
|
25
|
+
import { prepareImportsAudit } from "#audit/imports/prepare";
|
|
26
|
+
import { runImportsAudit } from "#audit/imports/run";
|
|
27
|
+
import { exitCodeForLinkAuditResult, formatLinkAuditJsonOutput } from "#audit/links/cli-result";
|
|
28
|
+
import { linkAuditRunRequestSchema } from "#audit/links/cli-schema";
|
|
29
|
+
import { presentLinkAuditResult } from "#audit/links/output";
|
|
30
|
+
import { prepareLinkAudit } from "#audit/links/prepare";
|
|
31
|
+
import { runLinkAudit } from "#audit/links/run";
|
|
32
|
+
import { exitCodeForPublishAuditResult, formatPublishAuditJsonOutput } from "#audit/publish/cli-result";
|
|
33
|
+
import { publishAuditRunRequestSchema } from "#audit/publish/cli-schema";
|
|
34
|
+
import { presentPublishAuditResult } from "#audit/publish/output";
|
|
35
|
+
import { preparePublishAudit } from "#audit/publish/prepare";
|
|
36
|
+
import { runPublishAudit } from "#audit/publish/run";
|
|
37
|
+
import { exitCodeForRtlAuditResult, formatRtlAuditJsonOutput } from "#audit/rtl/cli-result";
|
|
38
|
+
import { rtlAuditRunRequestSchema } from "#audit/rtl/cli-schema";
|
|
39
|
+
import { presentRtlAuditResult } from "#audit/rtl/output";
|
|
40
|
+
import { prepareRtlAudit } from "#audit/rtl/prepare";
|
|
41
|
+
import { runRtlAudit } from "#audit/rtl/run";
|
|
42
|
+
import { registerPipelineSubcommand } from "#core/cli/command-pipeline";
|
|
43
|
+
import { nodeFilesystem } from "#core/filesystem/node";
|
|
29
44
|
function baseAuditRequest(prelude, opts) {
|
|
30
45
|
return {
|
|
31
46
|
rootDir: prelude.rootDir,
|
|
@@ -74,6 +89,22 @@ const importsCheck = {
|
|
|
74
89
|
formatJson: formatImportsAuditJsonOutput,
|
|
75
90
|
exitCode: exitCodeForImportsAuditResult,
|
|
76
91
|
};
|
|
92
|
+
const assertionsCheck = {
|
|
93
|
+
name: "assertions",
|
|
94
|
+
description: "Report double type assertions through unknown or any (x as unknown as T), tests included",
|
|
95
|
+
targetHelp: "Directory or file to scan (default: the repo root)",
|
|
96
|
+
schema: assertionAuditRunRequestSchema,
|
|
97
|
+
prepare: prepareAssertionAudit,
|
|
98
|
+
buildRequest: baseAuditRequest,
|
|
99
|
+
run: (fs, request) => runAssertionAudit(fs, {
|
|
100
|
+
rootDir: request.rootDir,
|
|
101
|
+
targetPath: request.targetPath,
|
|
102
|
+
allowlist: request.allowlist ?? [],
|
|
103
|
+
}),
|
|
104
|
+
present: presentAssertionAuditResult,
|
|
105
|
+
formatJson: formatAssertionAuditJsonOutput,
|
|
106
|
+
exitCode: exitCodeForAssertionAuditResult,
|
|
107
|
+
};
|
|
77
108
|
const displayNamesCheck = {
|
|
78
109
|
name: "display-names",
|
|
79
110
|
description: "Report token(), tag() and module display names that break the <namespace>:<Name> convention",
|
|
@@ -90,6 +121,22 @@ const displayNamesCheck = {
|
|
|
90
121
|
formatJson: formatDisplayNameAuditJsonOutput,
|
|
91
122
|
exitCode: exitCodeForDisplayNameAuditResult,
|
|
92
123
|
};
|
|
124
|
+
const constantsCheck = {
|
|
125
|
+
name: "constants",
|
|
126
|
+
description: "Report numeric constants whose comment names none of the three kinds a number may be",
|
|
127
|
+
targetHelp: "Directory or file to scan (default: audit.constants.target from config)",
|
|
128
|
+
schema: constantAuditRunRequestSchema,
|
|
129
|
+
prepare: prepareConstantAudit,
|
|
130
|
+
buildRequest: baseAuditRequest,
|
|
131
|
+
run: (fs, request) => runConstantAudit(fs, {
|
|
132
|
+
rootDir: request.rootDir,
|
|
133
|
+
targetPath: request.targetPath,
|
|
134
|
+
allowlist: request.allowlist ?? [],
|
|
135
|
+
}),
|
|
136
|
+
present: presentConstantAuditResult,
|
|
137
|
+
formatJson: formatConstantAuditJsonOutput,
|
|
138
|
+
exitCode: exitCodeForConstantAuditResult,
|
|
139
|
+
};
|
|
93
140
|
const commentsCheck = {
|
|
94
141
|
name: "comments",
|
|
95
142
|
description: "Report section dividers that are not in the repo's one allowed form",
|
|
@@ -110,6 +157,18 @@ const commentsCheck = {
|
|
|
110
157
|
command.option("--fix", "Rewrite every mechanically fixable divider in place", false);
|
|
111
158
|
},
|
|
112
159
|
};
|
|
160
|
+
const publishCheck = {
|
|
161
|
+
name: "publish",
|
|
162
|
+
description: "Report what breaks a consumer's install: #/ imports, unshipped exports/imports targets, and stylesheet @source paths reaching nothing shipped",
|
|
163
|
+
targetHelp: "Directory or file to scan (default: the repo root)",
|
|
164
|
+
schema: publishAuditRunRequestSchema,
|
|
165
|
+
prepare: preparePublishAudit,
|
|
166
|
+
buildRequest: baseAuditRequest,
|
|
167
|
+
run: (fs, request) => runPublishAudit(fs, { rootDir: request.rootDir, targetPath: request.targetPath }),
|
|
168
|
+
present: presentPublishAuditResult,
|
|
169
|
+
formatJson: formatPublishAuditJsonOutput,
|
|
170
|
+
exitCode: exitCodeForPublishAuditResult,
|
|
171
|
+
};
|
|
113
172
|
/**
|
|
114
173
|
* Adapts an `AuditCheck` descriptor onto the shared command pipeline.
|
|
115
174
|
*/
|
|
@@ -118,7 +177,6 @@ function auditCheckToPipeline(check) {
|
|
|
118
177
|
name: check.name,
|
|
119
178
|
description: check.description,
|
|
120
179
|
positional: { name: "[target]", help: check.targetHelp },
|
|
121
|
-
jsonHelp: "Print one JSON summary on stdout",
|
|
122
180
|
schema: check.schema,
|
|
123
181
|
configureArgv: check.extraOptions,
|
|
124
182
|
prepare: (fs, input) => check.prepare(fs, { currentWorkingDirectory: input.currentWorkingDirectory, rawTarget: input.rawArg }),
|
|
@@ -140,7 +198,10 @@ export function createAuditCommand() {
|
|
|
140
198
|
registerPipelineSubcommand(cmd, nodeFilesystem, auditCheckToPipeline(rtlCheck));
|
|
141
199
|
registerPipelineSubcommand(cmd, nodeFilesystem, auditCheckToPipeline(linksCheck));
|
|
142
200
|
registerPipelineSubcommand(cmd, nodeFilesystem, auditCheckToPipeline(importsCheck));
|
|
201
|
+
registerPipelineSubcommand(cmd, nodeFilesystem, auditCheckToPipeline(assertionsCheck));
|
|
143
202
|
registerPipelineSubcommand(cmd, nodeFilesystem, auditCheckToPipeline(displayNamesCheck));
|
|
203
|
+
registerPipelineSubcommand(cmd, nodeFilesystem, auditCheckToPipeline(constantsCheck));
|
|
144
204
|
registerPipelineSubcommand(cmd, nodeFilesystem, auditCheckToPipeline(commentsCheck));
|
|
205
|
+
registerPipelineSubcommand(cmd, nodeFilesystem, auditCheckToPipeline(publishCheck));
|
|
145
206
|
return cmd;
|
|
146
207
|
}
|