@shivaedev/quality 0.22.0 → 0.24.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 +13 -0
- package/README.md +4 -0
- package/dist/baseline/compare.d.ts +2 -2
- package/dist/baseline/compare.d.ts.map +1 -1
- package/dist/baseline/compare.js +5 -3
- package/dist/baseline/compare.js.map +1 -1
- package/dist/baseline/format.d.ts +5 -5
- package/dist/baseline/format.d.ts.map +1 -1
- package/dist/baseline/format.js +23 -13
- package/dist/baseline/format.js.map +1 -1
- package/dist/baseline/legacy.d.ts +2 -2
- package/dist/baseline/legacy.d.ts.map +1 -1
- package/dist/baseline/legacy.js +4 -4
- package/dist/baseline/legacy.js.map +1 -1
- package/dist/baseline/rewrite.d.ts +1 -1
- package/dist/baseline/rewrite.d.ts.map +1 -1
- package/dist/baseline/rewrite.js +2 -2
- package/dist/baseline/rewrite.js.map +1 -1
- package/dist/baseline/update.d.ts +2 -2
- package/dist/baseline/update.d.ts.map +1 -1
- package/dist/baseline/update.js +24 -18
- package/dist/baseline/update.js.map +1 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +15 -9
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/baseline.d.ts +1 -1
- package/dist/cli/baseline.d.ts.map +1 -1
- package/dist/cli/baseline.js +10 -6
- package/dist/cli/baseline.js.map +1 -1
- package/dist/cli/fix.d.ts +2 -2
- package/dist/cli/fix.d.ts.map +1 -1
- package/dist/cli/fix.js +34 -40
- package/dist/cli/fix.js.map +1 -1
- package/dist/cli/lint.d.ts +1 -1
- package/dist/cli/lint.d.ts.map +1 -1
- package/dist/cli/lint.js +1 -1
- package/dist/cli/lint.js.map +1 -1
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/migrate.js +1 -1
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/program.d.ts +9 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +44 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/run-main.d.ts +5 -2
- package/dist/cli/run-main.d.ts.map +1 -1
- package/dist/cli/run-main.js +16 -12
- package/dist/cli/run-main.js.map +1 -1
- package/dist/cli/shrink.d.ts +2 -2
- package/dist/cli/shrink.d.ts.map +1 -1
- package/dist/cli/shrink.js +9 -3
- package/dist/cli/shrink.js.map +1 -1
- package/dist/cli.js +2 -49
- package/dist/cli.js.map +1 -1
- package/dist/config/decode.d.ts +1 -1
- package/dist/config/decode.d.ts.map +1 -1
- package/dist/config/decode.js +13 -9
- package/dist/config/decode.js.map +1 -1
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +26 -20
- package/dist/config/load.js.map +1 -1
- package/dist/config/resolve.d.ts +22 -2
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +18 -10
- package/dist/config/resolve.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/decoded.d.ts +2 -2
- package/dist/decoded.d.ts.map +1 -1
- package/dist/decoded.js +7 -5
- package/dist/decoded.js.map +1 -1
- package/dist/engine/baseline-file.d.ts +1 -1
- package/dist/engine/baseline-file.d.ts.map +1 -1
- package/dist/engine/baseline-file.js +4 -2
- package/dist/engine/baseline-file.js.map +1 -1
- package/dist/engine/evaluate.d.ts +2 -2
- package/dist/engine/evaluate.d.ts.map +1 -1
- package/dist/engine/evaluate.js +5 -3
- package/dist/engine/evaluate.js.map +1 -1
- package/dist/engine/run-rules.d.ts +1 -1
- package/dist/engine/run-rules.d.ts.map +1 -1
- package/dist/engine/run-rules.js +24 -14
- package/dist/engine/run-rules.js.map +1 -1
- package/dist/engine/session.d.ts.map +1 -1
- package/dist/engine/session.js +8 -4
- package/dist/engine/session.js.map +1 -1
- package/dist/engine/violation.d.ts +7 -7
- package/dist/engine/violation.d.ts.map +1 -1
- package/dist/engine/violation.js +22 -10
- package/dist/engine/violation.js.map +1 -1
- package/dist/exceptions/registry.d.ts +2 -2
- package/dist/exceptions/registry.d.ts.map +1 -1
- package/dist/exceptions/registry.js +10 -6
- package/dist/exceptions/registry.js.map +1 -1
- package/dist/git/base.d.ts +1 -2
- package/dist/git/base.d.ts.map +1 -1
- package/dist/git/base.js +22 -10
- package/dist/git/base.js.map +1 -1
- package/dist/git/command.d.ts +2 -2
- package/dist/git/command.d.ts.map +1 -1
- package/dist/git/command.js +13 -9
- package/dist/git/command.js.map +1 -1
- package/dist/git/history.d.ts +1 -1
- package/dist/git/history.d.ts.map +1 -1
- package/dist/git/history.js +5 -3
- package/dist/git/history.js.map +1 -1
- package/dist/inventory/collect.d.ts +1 -1
- package/dist/inventory/collect.d.ts.map +1 -1
- package/dist/inventory/collect.js +7 -5
- package/dist/inventory/collect.js.map +1 -1
- package/dist/inventory/filesystem.d.ts +1 -1
- package/dist/inventory/filesystem.d.ts.map +1 -1
- package/dist/inventory/filesystem.js +11 -7
- package/dist/inventory/filesystem.js.map +1 -1
- package/dist/inventory/ignore-scope.d.ts +4 -4
- package/dist/inventory/ignore-scope.d.ts.map +1 -1
- package/dist/inventory/ignore-scope.js +18 -9
- package/dist/inventory/ignore-scope.js.map +1 -1
- package/dist/manifests/sorted.d.ts +1 -1
- package/dist/manifests/sorted.d.ts.map +1 -1
- package/dist/manifests/sorted.js +14 -16
- package/dist/manifests/sorted.js.map +1 -1
- package/dist/report/plural.d.ts +1 -1
- package/dist/report/plural.d.ts.map +1 -1
- package/dist/report/plural.js +3 -1
- package/dist/report/plural.js.map +1 -1
- package/dist/report/render.d.ts +1 -1
- package/dist/report/render.d.ts.map +1 -1
- package/dist/report/render.js +29 -21
- package/dist/report/render.js.map +1 -1
- package/dist/report/stale.d.ts +1 -1
- package/dist/report/stale.d.ts.map +1 -1
- package/dist/report/stale.js +18 -8
- package/dist/report/stale.js.map +1 -1
- package/dist/rule.d.ts +13 -13
- package/dist/rule.d.ts.map +1 -1
- package/dist/rule.js +10 -8
- package/dist/rule.js.map +1 -1
- package/dist/rules/built-in.d.ts +2 -2
- package/dist/rules/built-in.d.ts.map +1 -1
- package/dist/rules/built-in.js +6 -0
- package/dist/rules/built-in.js.map +1 -1
- package/dist/rules/comments/kinds.d.ts +4 -4
- package/dist/rules/comments/kinds.d.ts.map +1 -1
- package/dist/rules/comments/kinds.js +16 -8
- package/dist/rules/comments/kinds.js.map +1 -1
- package/dist/rules/comments/max-per-file.d.ts.map +1 -1
- package/dist/rules/comments/max-per-file.js +13 -9
- package/dist/rules/comments/max-per-file.js.map +1 -1
- package/dist/rules/comments/pattern-rule.d.ts +1 -1
- package/dist/rules/comments/pattern-rule.d.ts.map +1 -1
- package/dist/rules/comments/pattern-rule.js +12 -10
- package/dist/rules/comments/pattern-rule.js.map +1 -1
- package/dist/rules/comments/scan.d.ts +3 -3
- package/dist/rules/comments/scan.d.ts.map +1 -1
- package/dist/rules/comments/scan.js +23 -19
- package/dist/rules/comments/scan.js.map +1 -1
- package/dist/rules/max-lines.d.ts.map +1 -1
- package/dist/rules/max-lines.js +12 -10
- package/dist/rules/max-lines.js.map +1 -1
- package/dist/rules/maxDepth.d.ts +2 -0
- package/dist/rules/maxDepth.d.ts.map +1 -0
- package/dist/rules/maxDepth.js +20 -0
- package/dist/rules/maxDepth.js.map +1 -0
- package/dist/rules/noBarrel.d.ts +2 -0
- package/dist/rules/noBarrel.d.ts.map +1 -0
- package/dist/rules/noBarrel.js +14 -0
- package/dist/rules/noBarrel.js.map +1 -0
- package/dist/rules/stories/origins.d.ts +10 -0
- package/dist/rules/stories/origins.d.ts.map +1 -0
- package/dist/rules/stories/origins.js +129 -0
- package/dist/rules/stories/origins.js.map +1 -0
- package/dist/rules/stories/prerequisites.d.ts +4 -0
- package/dist/rules/stories/prerequisites.d.ts.map +1 -0
- package/dist/rules/stories/prerequisites.js +32 -0
- package/dist/rules/stories/prerequisites.js.map +1 -0
- package/dist/rules/stories/program.d.ts +5 -0
- package/dist/rules/stories/program.d.ts.map +1 -0
- package/dist/rules/stories/program.js +22 -0
- package/dist/rules/stories/program.js.map +1 -0
- package/dist/rules/stories/specs.d.ts +2 -0
- package/dist/rules/stories/specs.d.ts.map +1 -0
- package/dist/rules/stories/specs.js +80 -0
- package/dist/rules/stories/specs.js.map +1 -0
- package/dist/rules/suppressions/biome/configs.d.ts +1 -1
- package/dist/rules/suppressions/biome/configs.d.ts.map +1 -1
- package/dist/rules/suppressions/biome/configs.js +23 -17
- package/dist/rules/suppressions/biome/configs.js.map +1 -1
- package/dist/rules/suppressions/biome/declarations.d.ts +4 -4
- package/dist/rules/suppressions/biome/declarations.d.ts.map +1 -1
- package/dist/rules/suppressions/biome/declarations.js +15 -7
- package/dist/rules/suppressions/biome/declarations.js.map +1 -1
- package/dist/rules/suppressions/biome/json.d.ts +6 -6
- package/dist/rules/suppressions/biome/json.d.ts.map +1 -1
- package/dist/rules/suppressions/biome/json.js +27 -13
- package/dist/rules/suppressions/biome/json.js.map +1 -1
- package/dist/rules/suppressions/biome/resolve.d.ts +1 -1
- package/dist/rules/suppressions/biome/resolve.d.ts.map +1 -1
- package/dist/rules/suppressions/biome/resolve.js +23 -17
- package/dist/rules/suppressions/biome/resolve.js.map +1 -1
- package/dist/rules/suppressions/biome/weakenings.d.ts +1 -1
- package/dist/rules/suppressions/biome/weakenings.d.ts.map +1 -1
- package/dist/rules/suppressions/biome/weakenings.js +78 -52
- package/dist/rules/suppressions/biome/weakenings.js.map +1 -1
- package/dist/rules/suppressions/biome-overrides.d.ts.map +1 -1
- package/dist/rules/suppressions/biome-overrides.js +45 -33
- package/dist/rules/suppressions/biome-overrides.js.map +1 -1
- package/dist/rules/suppressions/directives.d.ts +1 -1
- package/dist/rules/suppressions/directives.d.ts.map +1 -1
- package/dist/rules/suppressions/directives.js +5 -3
- package/dist/rules/suppressions/directives.js.map +1 -1
- package/dist/rules/suppressions/no-double-cast.d.ts.map +1 -1
- package/dist/rules/suppressions/no-double-cast.js +14 -10
- package/dist/rules/suppressions/no-double-cast.js.map +1 -1
- package/dist/rules/suppressions/no-inline.d.ts.map +1 -1
- package/dist/rules/suppressions/no-inline.js +8 -6
- package/dist/rules/suppressions/no-inline.js.map +1 -1
- package/dist/rules/suppressions/stylesheet-comments.d.ts +1 -1
- package/dist/rules/suppressions/stylesheet-comments.d.ts.map +1 -1
- package/dist/rules/suppressions/stylesheet-comments.js +11 -5
- package/dist/rules/suppressions/stylesheet-comments.js.map +1 -1
- package/dist/rules/syntax.d.ts +1 -1
- package/dist/rules/syntax.d.ts.map +1 -1
- package/dist/rules/syntax.js +2 -2
- package/dist/rules/syntax.js.map +1 -1
- package/dist/standard-schema.d.ts +6 -6
- package/dist/standard-schema.d.ts.map +1 -1
- package/docs/modules.md +19 -1
- package/docs/roadmap.md +1 -1
- package/docs/rules.md +9 -1
- package/package.json +2 -2
- package/src/baseline/compare.ts +5 -3
- package/src/baseline/format.ts +17 -10
- package/src/baseline/legacy.ts +4 -4
- package/src/baseline/rewrite.ts +2 -2
- package/src/baseline/update.ts +20 -16
- package/src/cli/args.ts +15 -10
- package/src/cli/baseline.ts +36 -35
- package/src/cli/fix.ts +39 -42
- package/src/cli/lint.ts +17 -19
- package/src/cli/migrate.ts +20 -21
- package/src/cli/program.ts +50 -0
- package/src/cli/run-main.ts +19 -13
- package/src/cli/shrink.ts +11 -8
- package/src/cli.ts +2 -51
- package/src/config/decode.ts +15 -10
- package/src/config/load.ts +44 -37
- package/src/config/resolve.ts +32 -27
- package/src/config.ts +3 -1
- package/src/decoded.ts +5 -4
- package/src/engine/baseline-file.ts +14 -12
- package/src/engine/evaluate.ts +6 -5
- package/src/engine/run-rules.ts +21 -13
- package/src/engine/session.ts +32 -25
- package/src/engine/violation.ts +22 -11
- package/src/exceptions/registry.ts +10 -8
- package/src/git/base.ts +45 -37
- package/src/git/command.ts +6 -4
- package/src/git/history.ts +5 -4
- package/src/inventory/collect.ts +39 -34
- package/src/inventory/filesystem.ts +38 -30
- package/src/inventory/ignore-scope.ts +20 -10
- package/src/manifests/sorted.ts +18 -18
- package/src/report/plural.ts +3 -1
- package/src/report/render.ts +23 -18
- package/src/report/stale.ts +33 -25
- package/src/rule.ts +25 -19
- package/src/rules/built-in.ts +6 -0
- package/src/rules/comments/kinds.ts +16 -9
- package/src/rules/comments/max-per-file.ts +15 -11
- package/src/rules/comments/pattern-rule.ts +5 -4
- package/src/rules/comments/scan.ts +18 -15
- package/src/rules/max-lines.ts +3 -2
- package/src/rules/maxDepth.ts +24 -0
- package/src/rules/noBarrel.ts +16 -0
- package/src/rules/stories/origins.ts +147 -0
- package/src/rules/stories/prerequisites.ts +37 -0
- package/src/rules/stories/program.ts +29 -0
- package/src/rules/stories/specs.ts +93 -0
- package/src/rules/suppressions/biome/configs.ts +23 -17
- package/src/rules/suppressions/biome/declarations.ts +15 -10
- package/src/rules/suppressions/biome/json.ts +25 -13
- package/src/rules/suppressions/biome/resolve.ts +23 -18
- package/src/rules/suppressions/biome/weakenings.ts +60 -41
- package/src/rules/suppressions/biome-overrides.ts +32 -22
- package/src/rules/suppressions/directives.ts +5 -4
- package/src/rules/suppressions/no-double-cast.ts +14 -10
- package/src/rules/suppressions/no-inline.ts +5 -4
- package/src/rules/suppressions/stylesheet-comments.ts +11 -6
- package/src/rules/syntax.ts +2 -2
- package/src/standard-schema.ts +4 -4
package/src/cli/run-main.ts
CHANGED
|
@@ -11,27 +11,28 @@ import type { Git } from "#git/command.ts";
|
|
|
11
11
|
const INTERRUPTED = 130;
|
|
12
12
|
const COULD_NOT_RUN = 2;
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
function explain(cause: Cause.Cause<unknown>): Effect.Effect<void> {
|
|
15
15
|
const error = Cause.squash(cause);
|
|
16
16
|
if (error instanceof SetupFailure) {
|
|
17
17
|
return Console.error(`quality: ${error.message}`);
|
|
18
18
|
}
|
|
19
19
|
return Runtime.getErrorReported(error) ? Console.error(`quality: internal error\n${Cause.pretty(cause)}`) : Effect.void;
|
|
20
|
-
}
|
|
20
|
+
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
typeof error === "object" && error !== null && Runtime.errorExitCode in error ? Runtime.getErrorExitCode(error) : COULD_NOT_RUN;
|
|
22
|
+
function exitCodeOf(error: unknown): number {
|
|
23
|
+
return typeof error === "object" && error !== null && Runtime.errorExitCode in error ? Runtime.getErrorExitCode(error) : COULD_NOT_RUN;
|
|
24
|
+
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
export function exitCode(exit: Exit.Exit<unknown, unknown>): number {
|
|
26
27
|
if (Exit.isSuccess(exit)) {
|
|
27
28
|
return 0;
|
|
28
29
|
}
|
|
29
30
|
return Cause.hasInterruptsOnly(exit.cause) ? INTERRUPTED : exitCodeOf(Cause.squash(exit.cause));
|
|
30
|
-
}
|
|
31
|
+
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
function teardown(exit: Parameters<Runtime.Teardown>[0], onExit: Parameters<Runtime.Teardown>[1]): void {
|
|
33
34
|
process.stdout.write("", () => process.stderr.write("", () => onExit(exitCode(exit))));
|
|
34
|
-
}
|
|
35
|
+
}
|
|
35
36
|
|
|
36
37
|
function isClosedPipe(error: unknown): boolean {
|
|
37
38
|
return error instanceof Error && "code" in error && error.code === "EPIPE";
|
|
@@ -45,11 +46,16 @@ export function quietOnClosedPipe(stream: EventEmitter): void {
|
|
|
45
46
|
});
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
const services = NodeChildProcessSpawner.layer.pipe(Layer.provideMerge(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer)));
|
|
49
|
+
export const services = NodeChildProcessSpawner.layer.pipe(Layer.provideMerge(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer)));
|
|
49
50
|
|
|
50
|
-
export
|
|
51
|
+
export function explained<TValue, TError, TRequirements>(
|
|
52
|
+
program: Effect.Effect<TValue, TError, TRequirements>,
|
|
53
|
+
): Effect.Effect<TValue, TError, TRequirements> {
|
|
54
|
+
return Effect.tapCause(program, (cause) => (Cause.hasInterruptsOnly(cause) ? Effect.void : explain(cause)));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function runMain<TValue, TError>(program: Effect.Effect<TValue, TError, FileSystem.FileSystem | Git>): void {
|
|
51
58
|
quietOnClosedPipe(process.stdout);
|
|
52
59
|
quietOnClosedPipe(process.stderr);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
};
|
|
60
|
+
NodeRuntime.runMain(Effect.provide(explained(program), services), { disableErrorReporting: true, teardown });
|
|
61
|
+
}
|
package/src/cli/shrink.ts
CHANGED
|
@@ -6,8 +6,8 @@ import type { Git } from "#git/command.ts";
|
|
|
6
6
|
import { changesSince } from "#git/history.ts";
|
|
7
7
|
import { shrinkBaseline } from "./baseline.ts";
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
resolveBase(root, against).pipe(
|
|
9
|
+
function followedMoves(root: string, against: string | undefined): Effect.Effect<Scope, SetupFailure, Git> {
|
|
10
|
+
return resolveBase(root, against).pipe(
|
|
11
11
|
Effect.flatMap((base) => changesSince(root, [base.commit])),
|
|
12
12
|
Effect.map((changes): Scope => ({ moves: changes.moves })),
|
|
13
13
|
Effect.catchIf(
|
|
@@ -15,17 +15,20 @@ const followedMoves = (root: string, against: string | undefined): Effect.Effect
|
|
|
15
15
|
(failure) => Effect.as(Console.error(`quality: moved files are not followed: ${failure.message}`), { moves: new Map() }),
|
|
16
16
|
),
|
|
17
17
|
);
|
|
18
|
+
}
|
|
18
19
|
|
|
19
|
-
export
|
|
20
|
+
export function pruneBaseline(
|
|
20
21
|
cwd: string,
|
|
21
22
|
config: string | undefined,
|
|
22
23
|
against: string | undefined,
|
|
23
|
-
): Effect.Effect<void, SetupFailure, FileSystem.FileSystem | Git>
|
|
24
|
-
shrinkBaseline(cwd, config, (session) => followedMoves(session.config.root, against));
|
|
24
|
+
): Effect.Effect<void, SetupFailure, FileSystem.FileSystem | Git> {
|
|
25
|
+
return shrinkBaseline(cwd, config, (session) => followedMoves(session.config.root, against));
|
|
26
|
+
}
|
|
25
27
|
|
|
26
|
-
export
|
|
28
|
+
export function tightenBaseline(
|
|
27
29
|
cwd: string,
|
|
28
30
|
config: string | undefined,
|
|
29
31
|
staged: boolean,
|
|
30
|
-
): Effect.Effect<void, SetupFailure, FileSystem.FileSystem | Git>
|
|
31
|
-
shrinkBaseline(cwd, config, (session) => changesSince(session.config.root, staged ? ["--cached"] : ["HEAD"]));
|
|
32
|
+
): Effect.Effect<void, SetupFailure, FileSystem.FileSystem | Git> {
|
|
33
|
+
return shrinkBaseline(cwd, config, (session) => changesSince(session.config.root, staged ? ["--cached"] : ["HEAD"]));
|
|
34
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -1,55 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import process from "node:process";
|
|
3
|
-
import {
|
|
4
|
-
import { parseCommand, USAGE } from "#cli/args.ts";
|
|
5
|
-
import { writeBaseline } from "#cli/baseline.ts";
|
|
6
|
-
import { fix } from "#cli/fix.ts";
|
|
7
|
-
import { lint } from "#cli/lint.ts";
|
|
8
|
-
import { migrateBaseline } from "#cli/migrate.ts";
|
|
9
|
-
import { migrateExceptions } from "#cli/migrateExceptions.ts";
|
|
3
|
+
import { program } from "#cli/program.ts";
|
|
10
4
|
import { runMain } from "#cli/run-main.ts";
|
|
11
|
-
import { pruneBaseline, tightenBaseline } from "#cli/shrink.ts";
|
|
12
|
-
import { installHook } from "#hooks/install.ts";
|
|
13
|
-
import { preCommitHook } from "#hooks/preCommit.ts";
|
|
14
|
-
import { uninstallHook } from "#hooks/uninstall.ts";
|
|
15
|
-
import { SetupFailure } from "./failure.ts";
|
|
16
5
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const program = Effect.gen(function* () {
|
|
20
|
-
if (parsed._tag === "Usage") {
|
|
21
|
-
return yield* new SetupFailure({ message: `${parsed.problem}\n\n${USAGE}` });
|
|
22
|
-
}
|
|
23
|
-
const command = parsed.command;
|
|
24
|
-
switch (command._tag) {
|
|
25
|
-
case "Help":
|
|
26
|
-
return yield* Console.log(USAGE);
|
|
27
|
-
case "Lint":
|
|
28
|
-
return yield* lint(process.cwd(), command.config, command.warnings);
|
|
29
|
-
case "Fix":
|
|
30
|
-
return yield* fix(process.cwd(), command.config);
|
|
31
|
-
case "BaselineWrite":
|
|
32
|
-
return yield* writeBaseline(process.cwd(), command.config, command.rules);
|
|
33
|
-
case "BaselinePrune":
|
|
34
|
-
return yield* pruneBaseline(process.cwd(), command.config, command.against);
|
|
35
|
-
case "BaselineTighten":
|
|
36
|
-
return yield* tightenBaseline(process.cwd(), command.config, command.staged);
|
|
37
|
-
case "ExceptionsMigrate":
|
|
38
|
-
return yield* migrateExceptions(process.cwd(), command.config, command.from);
|
|
39
|
-
case "BaselineMigrate":
|
|
40
|
-
return yield* migrateBaseline(process.cwd(), command.config, command.from);
|
|
41
|
-
case "HooksInstall":
|
|
42
|
-
return yield* installHook({
|
|
43
|
-
config: command.config,
|
|
44
|
-
cwd: process.cwd(),
|
|
45
|
-
force: command.force,
|
|
46
|
-
launch: { options: process.execArgv, script: process.argv[1] ?? "" },
|
|
47
|
-
});
|
|
48
|
-
case "HooksUninstall":
|
|
49
|
-
return yield* uninstallHook(process.cwd());
|
|
50
|
-
case "HooksPreCommit":
|
|
51
|
-
return yield* preCommitHook(process.cwd(), command.config);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
runMain(program);
|
|
6
|
+
runMain(program(process.argv.slice(2), { cwd: process.cwd(), launch: { options: process.execArgv, script: process.argv[1] ?? "" } }));
|
package/src/config/decode.ts
CHANGED
|
@@ -3,15 +3,18 @@ import { type Decoded, decodeWith } from "#decoded.ts";
|
|
|
3
3
|
import { ExceptionDeclaration } from "#exceptions/declaration.ts";
|
|
4
4
|
import type { Rule } from "#rule.ts";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
function isRule(value: unknown): value is Rule {
|
|
7
|
+
return (
|
|
8
|
+
typeof value === "object"
|
|
9
|
+
&& value !== null
|
|
10
|
+
&& "id" in value
|
|
11
|
+
&& typeof value.id === "string"
|
|
12
|
+
&& "description" in value
|
|
13
|
+
&& typeof value.description === "string"
|
|
14
|
+
&& "configure" in value
|
|
15
|
+
&& typeof value.configure === "function"
|
|
16
|
+
);
|
|
17
|
+
}
|
|
15
18
|
|
|
16
19
|
const Level = Schema.Literal("error");
|
|
17
20
|
|
|
@@ -44,4 +47,6 @@ export type ConfigInput = typeof ConfigInput.Type;
|
|
|
44
47
|
|
|
45
48
|
const standard = Schema.toStandardSchemaV1(ConfigInput, { parseOptions: { errors: "all", onExcessProperty: "error" } });
|
|
46
49
|
|
|
47
|
-
export
|
|
50
|
+
export function decodeConfig(value: unknown): Promise<Decoded<ConfigInput>> {
|
|
51
|
+
return decodeWith(standard, value);
|
|
52
|
+
}
|
package/src/config/load.ts
CHANGED
|
@@ -22,10 +22,12 @@ export interface ResolvedConfig extends ResolvedRules, InventoryScope {
|
|
|
22
22
|
readonly root: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
function messageOf(cause: unknown): string {
|
|
26
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
27
|
+
}
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
Effect.flatMap(
|
|
29
|
+
function importDefault(file: string): Effect.Effect<unknown, SetupFailure> {
|
|
30
|
+
return Effect.flatMap(
|
|
29
31
|
Effect.tryPromise({
|
|
30
32
|
catch: (cause) => new SetupFailure({ message: `cannot load ${file}: ${messageOf(cause)}` }),
|
|
31
33
|
try: async (): Promise<unknown> => import(pathToFileURL(file).href),
|
|
@@ -35,6 +37,7 @@ const importDefault = (file: string): Effect.Effect<unknown, SetupFailure> =>
|
|
|
35
37
|
? Effect.succeed(loaded.default)
|
|
36
38
|
: Effect.fail(new SetupFailure({ message: `${file} has no default export. Export defineConfig({ ... }) as the default.` })),
|
|
37
39
|
);
|
|
40
|
+
}
|
|
38
41
|
|
|
39
42
|
const LegacyOptions = Schema.Struct({ declared: Schema.Array(ConsumerDeclaration) });
|
|
40
43
|
function biomeDeclarations(config: ConfigInput): readonly Declaration[] {
|
|
@@ -43,38 +46,42 @@ function biomeDeclarations(config: ConfigInput): readonly Declaration[] {
|
|
|
43
46
|
return Schema.is(LegacyOptions)(options) ? options.declared : [];
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
function resolved(root: string, file: string, config: ConfigInput, rules: ResolvedRules): ResolvedConfig {
|
|
50
|
+
return {
|
|
51
|
+
...rules,
|
|
52
|
+
baseline: config.baseline ?? "quality/baseline.jsonl",
|
|
53
|
+
biomeDeclarations: biomeDeclarations(config),
|
|
54
|
+
exceptions: config.exceptions ?? [],
|
|
55
|
+
exclude: [],
|
|
56
|
+
extensions: config.extensions ?? DEFAULT_EXTENSIONS,
|
|
57
|
+
file,
|
|
58
|
+
registry: config.registry ?? "quality/registry.json",
|
|
59
|
+
root,
|
|
60
|
+
sources: config.sources ?? ["."],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
58
63
|
|
|
59
|
-
export const loadConfig =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
64
|
+
export const loadConfig = Effect.fn("Config.loadConfig")(function* (
|
|
65
|
+
cwd: string,
|
|
66
|
+
path: string | undefined,
|
|
67
|
+
): Effect.fn.Return<ResolvedConfig, SetupFailure, FileSystem.FileSystem> {
|
|
68
|
+
const fs = yield* FileSystem.FileSystem;
|
|
69
|
+
const file = resolve(cwd, path ?? CONFIG_FILE);
|
|
70
|
+
const entries = yield* fs
|
|
71
|
+
.readDirectory(dirname(file))
|
|
72
|
+
.pipe(
|
|
73
|
+
Effect.catchTag("PlatformError", (error) =>
|
|
74
|
+
error.reason._tag === "NotFound"
|
|
75
|
+
? Effect.succeed<string[]>([])
|
|
76
|
+
: Effect.fail(new SetupFailure({ message: `cannot inspect ${file}: ${error.message}` })),
|
|
77
|
+
),
|
|
78
|
+
);
|
|
79
|
+
const present = entries.includes(basename(file));
|
|
80
|
+
if (!present && path !== undefined) {
|
|
81
|
+
return yield* new SetupFailure({ message: `no config at ${file}. Check the --config path.` });
|
|
82
|
+
}
|
|
83
|
+
const loaded = present ? yield* importDefault(file) : {};
|
|
84
|
+
const config = yield* validOrFail(file, yield* Effect.promise(() => decodeConfig(loaded)));
|
|
85
|
+
const rules = yield* validOrFail(file, yield* resolveRules(config));
|
|
86
|
+
return resolved(dirname(file), file, config, rules);
|
|
87
|
+
});
|
package/src/config/resolve.ts
CHANGED
|
@@ -12,14 +12,19 @@ export interface ResolvedRules extends RuleIndex {
|
|
|
12
12
|
|
|
13
13
|
type Setting = NonNullable<ConfigInput["rules"]>[string];
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
function messageOf(cause: unknown): string {
|
|
16
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
17
|
+
}
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
function optionsOf(setting: Setting | undefined): unknown {
|
|
20
|
+
return typeof setting === "object" ? setting.options : undefined;
|
|
21
|
+
}
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
rules.flatMap((rule, index) =>
|
|
23
|
+
function duplicateIssues(rules: readonly Rule[]): readonly string[] {
|
|
24
|
+
return rules.flatMap((rule, index) =>
|
|
21
25
|
rules.findIndex((other) => other.id === rule.id) === index ? [] : [`local: rule id "${rule.id}" is already defined`],
|
|
22
26
|
);
|
|
27
|
+
}
|
|
23
28
|
|
|
24
29
|
function activeRule(rule: Rule, check: ActiveRule["check"]): ActiveRule {
|
|
25
30
|
return {
|
|
@@ -32,8 +37,8 @@ function activeRule(rule: Rule, check: ActiveRule["check"]): ActiveRule {
|
|
|
32
37
|
};
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
Effect.tryPromise({ catch: messageOf, try: () => rule.configure(optionsOf(setting)) }).pipe(
|
|
40
|
+
function activate(rule: Rule, setting: Setting | undefined): Effect.Effect<Decoded<ActiveRule>> {
|
|
41
|
+
return Effect.tryPromise({ catch: messageOf, try: () => rule.configure(optionsOf(setting)) }).pipe(
|
|
37
42
|
Effect.map(
|
|
38
43
|
(configured): Decoded<ActiveRule> =>
|
|
39
44
|
configured._tag === "Invalid"
|
|
@@ -47,25 +52,25 @@ const activate = (rule: Rule, setting: Setting | undefined): Effect.Effect<Decod
|
|
|
47
52
|
Effect.succeed<Decoded<ActiveRule>>({ _tag: "Invalid", issues: [`rules.${rule.id}.options: validation threw: ${failure}`] }),
|
|
48
53
|
),
|
|
49
54
|
);
|
|
55
|
+
}
|
|
50
56
|
|
|
51
|
-
export const resolveRules = (config: ConfigInput): Effect.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
57
|
+
export const resolveRules = Effect.fn("Config.resolveRules")(function* (config: ConfigInput): Effect.fn.Return<Decoded<ResolvedRules>> {
|
|
58
|
+
const rules: readonly Rule[] = [...builtInRules, ...(config.local ?? [])];
|
|
59
|
+
const settings = config.rules ?? {};
|
|
60
|
+
const known = new Set(rules.map((rule) => rule.id));
|
|
61
|
+
const families = new Set(rules.filter((rule) => rule.family === true).map((rule) => rule.id));
|
|
62
|
+
const unknown = [
|
|
63
|
+
...Object.keys(settings)
|
|
64
|
+
.filter((id) => !known.has(id))
|
|
65
|
+
.map((id) => `rules.${id}`),
|
|
66
|
+
].map((path) => `${path}: no built-in or local rule has this id`);
|
|
67
|
+
const activated = yield* Effect.forEach(rules, (rule) => activate(rule, settings[rule.id]));
|
|
68
|
+
const issues = [...duplicateIssues(rules), ...unknown, ...activated.flatMap((result) => (result._tag === "Invalid" ? result.issues : []))];
|
|
69
|
+
if (issues.length > 0) {
|
|
70
|
+
return { _tag: "Invalid", issues };
|
|
71
|
+
}
|
|
72
|
+
const active = activated.flatMap((result) => (result._tag === "Valid" ? [result.value] : []));
|
|
73
|
+
const levels = new Map(rules.map((rule) => [rule.id, "error" as const]));
|
|
74
|
+
const unregistrable = new Set(rules.filter((rule) => rule.registrable === false).map((rule) => rule.id));
|
|
75
|
+
return { _tag: "Valid", value: { active, families, levels, unregistrable } };
|
|
76
|
+
});
|
package/src/config.ts
CHANGED
|
@@ -24,4 +24,6 @@ export interface QualityConfig<TLocal extends readonly Rule[] = readonly Rule[]>
|
|
|
24
24
|
readonly sources?: readonly string[];
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export
|
|
27
|
+
export function defineConfig<const TLocal extends readonly Rule[] = readonly []>(config: QualityConfig<TLocal>): QualityConfig<TLocal> {
|
|
28
|
+
return config;
|
|
29
|
+
}
|
package/src/decoded.ts
CHANGED
|
@@ -4,12 +4,13 @@ import { describeIssue, type StandardSchemaV1 } from "./standard-schema.ts";
|
|
|
4
4
|
|
|
5
5
|
export type Decoded<TValue> = { readonly _tag: "Valid"; readonly value: TValue } | { readonly _tag: "Invalid"; readonly issues: readonly string[] };
|
|
6
6
|
|
|
7
|
-
export
|
|
7
|
+
export async function decodeWith<TOutput>(schema: StandardSchemaV1<unknown, TOutput>, value: unknown): Promise<Decoded<TOutput>> {
|
|
8
8
|
const result = await schema["~standard"].validate(value);
|
|
9
9
|
return result.issues === undefined ? { _tag: "Valid", value: result.value } : { _tag: "Invalid", issues: result.issues.map(describeIssue) };
|
|
10
|
-
}
|
|
10
|
+
}
|
|
11
11
|
|
|
12
|
-
export
|
|
13
|
-
decoded._tag === "Valid"
|
|
12
|
+
export function validOrFail<TValue>(file: string, decoded: Decoded<TValue>): Effect.Effect<TValue, SetupFailure> {
|
|
13
|
+
return decoded._tag === "Valid"
|
|
14
14
|
? Effect.succeed(decoded.value)
|
|
15
15
|
: Effect.fail(new SetupFailure({ message: `${file} is invalid:\n${decoded.issues.map((issue) => ` - ${issue}`).join("\n")}` }));
|
|
16
|
+
}
|
|
@@ -12,16 +12,18 @@ export interface BaselineFile {
|
|
|
12
12
|
readonly raw: string | undefined;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export
|
|
16
|
-
Effect.mapError(readOptionalText(join(root, path)), (failure) => new SetupFailure({ message: failure.message }));
|
|
15
|
+
export function readInput(root: string, path: string): Effect.Effect<string | undefined, SetupFailure, FileSystem.FileSystem> {
|
|
16
|
+
return Effect.mapError(readOptionalText(join(root, path)), (failure) => new SetupFailure({ message: failure.message }));
|
|
17
|
+
}
|
|
17
18
|
|
|
18
|
-
export const readBaseline =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
}
|
|
19
|
+
export const readBaseline = Effect.fn("Engine.readBaseline")(function* (
|
|
20
|
+
config: ResolvedConfig,
|
|
21
|
+
): Effect.fn.Return<BaselineFile, SetupFailure, FileSystem.FileSystem> {
|
|
22
|
+
const raw = yield* readInput(config.root, config.baseline);
|
|
23
|
+
if (raw === undefined && config.baseline !== LEGACY_BASELINE && (yield* readInput(config.root, LEGACY_BASELINE)) !== undefined) {
|
|
24
|
+
return yield* new SetupFailure({
|
|
25
|
+
message: `${LEGACY_BASELINE} holds a baseline in the earlier JSON format. Run \`quality baseline migrate\` to move it to ${config.baseline}.`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return { entries: yield* validOrFail(config.baseline, yield* Effect.promise(() => decodeBaseline(raw))), raw };
|
|
29
|
+
});
|
package/src/engine/evaluate.ts
CHANGED
|
@@ -14,12 +14,12 @@ export interface Outcome {
|
|
|
14
14
|
readonly warnings: readonly Violation[];
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export
|
|
17
|
+
export function evaluate(
|
|
18
18
|
violations: readonly Violation[],
|
|
19
19
|
registry: readonly RegistryEntry[],
|
|
20
20
|
baseline: readonly BaselineEntry[],
|
|
21
21
|
rules: RuleIndex,
|
|
22
|
-
): Outcome
|
|
22
|
+
): Outcome {
|
|
23
23
|
const registered = applyRegistry(violations, registry, rules);
|
|
24
24
|
const baselined = applyBaseline(registered.kept, baseline, rules);
|
|
25
25
|
const kept = [...baselined.kept].sort(byLocation);
|
|
@@ -33,7 +33,8 @@ export const evaluate = (
|
|
|
33
33
|
staleRegistry: registered.stale,
|
|
34
34
|
warnings: kept.filter((violation) => violation.level === "warn"),
|
|
35
35
|
};
|
|
36
|
-
}
|
|
36
|
+
}
|
|
37
37
|
|
|
38
|
-
export
|
|
39
|
-
outcome.errors.length === 0 && outcome.staleBaseline.length === 0 && outcome.staleRegistry.length === 0;
|
|
38
|
+
export function passes(outcome: Outcome): boolean {
|
|
39
|
+
return outcome.errors.length === 0 && outcome.staleBaseline.length === 0 && outcome.staleRegistry.length === 0;
|
|
40
|
+
}
|
package/src/engine/run-rules.ts
CHANGED
|
@@ -14,10 +14,14 @@ export interface ActiveRule {
|
|
|
14
14
|
readonly registrable?: boolean;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
function messageOf(cause: unknown): string {
|
|
18
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
19
|
+
}
|
|
18
20
|
|
|
19
21
|
// Registry and baseline entries match on the path, so every finding names its file the same way.
|
|
20
|
-
|
|
22
|
+
function repositoryPath(root: string, file: string): string {
|
|
23
|
+
return posix(isAbsolute(file) ? relative(root, file) : file).replace(/^(?:\.\/)+/u, "");
|
|
24
|
+
}
|
|
21
25
|
|
|
22
26
|
function exceptionHint(rule: ActiveRule, finding: Finding, file: string, config: string): string {
|
|
23
27
|
const id = rule.family && finding.subject !== undefined ? `${rule.id}/${finding.subject}` : rule.id;
|
|
@@ -34,25 +38,29 @@ function exceptionHint(rule: ActiveRule, finding: Finding, file: string, config:
|
|
|
34
38
|
return ` For a permanent exception, add to exceptions in ${config}: ${shape}.`;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
41
|
+
function violationOf(rule: ActiveRule, root: string, finding: Finding, exceptionFile: string): Violation {
|
|
42
|
+
return {
|
|
43
|
+
...finding,
|
|
44
|
+
file: repositoryPath(root, finding.file),
|
|
45
|
+
level: rule.level,
|
|
46
|
+
message: finding.message + exceptionHint(rule, finding, repositoryPath(root, finding.file), exceptionFile),
|
|
47
|
+
rule: rule.family && finding.subject !== undefined ? `${rule.id}/${finding.subject}` : rule.id,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
Effect.map(
|
|
51
|
+
function runRule(rule: ActiveRule, inputs: RuleInputs, exceptionFile: string): Effect.Effect<readonly Violation[], SetupFailure> {
|
|
52
|
+
return Effect.map(
|
|
47
53
|
Effect.tryPromise({
|
|
48
54
|
catch: (cause) => new SetupFailure({ message: `rule ${rule.id} failed: ${messageOf(cause)}` }),
|
|
49
55
|
try: () => rule.check(inputs),
|
|
50
56
|
}),
|
|
51
57
|
(findings) => findings.map((finding) => violationOf(rule, inputs.root, finding, exceptionFile)),
|
|
52
58
|
);
|
|
59
|
+
}
|
|
53
60
|
|
|
54
|
-
export
|
|
55
|
-
Effect.map(
|
|
61
|
+
export function runRules(rules: readonly ActiveRule[], inputs: RuleInputs): Effect.Effect<readonly Violation[], SetupFailure> {
|
|
62
|
+
return Effect.map(
|
|
56
63
|
Effect.forEach(rules, (rule) => runRule(rule, inputs, inputs.configFile ?? "quality.config.ts"), { concurrency: "unbounded" }),
|
|
57
64
|
(results) => results.flat(),
|
|
58
65
|
);
|
|
66
|
+
}
|
package/src/engine/session.ts
CHANGED
|
@@ -19,32 +19,39 @@ export interface Session {
|
|
|
19
19
|
readonly violations: readonly Violation[];
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
function setup<TValue, TRequirements>(
|
|
23
23
|
effect: Effect.Effect<TValue, FilesystemFailure, TRequirements>,
|
|
24
|
-
): Effect.Effect<TValue, SetupFailure, TRequirements>
|
|
24
|
+
): Effect.Effect<TValue, SetupFailure, TRequirements> {
|
|
25
|
+
return Effect.mapError(effect, (failure) => new SetupFailure({ message: failure.message }));
|
|
26
|
+
}
|
|
25
27
|
|
|
26
|
-
export const scan =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
export const scan = Effect.fn("Engine.scan")(function* (
|
|
29
|
+
config: ResolvedConfig,
|
|
30
|
+
): Effect.fn.Return<Pick<Session, "inventory" | "violations">, SetupFailure, FileSystem.FileSystem> {
|
|
31
|
+
const inventory = yield* setup(collectInventory(config.root, config));
|
|
32
|
+
const services = yield* Effect.context<FileSystem.FileSystem>();
|
|
33
|
+
function readText(path: string): Promise<string | undefined> {
|
|
34
|
+
return Effect.runPromiseWith(services)(readOptionalText(resolve(config.root, path)));
|
|
35
|
+
}
|
|
36
|
+
const violations = yield* runRules(config.active, {
|
|
37
|
+
configFile: relative(config.root, config.file),
|
|
38
|
+
exceptions: config.exceptions,
|
|
39
|
+
files: inventory.files,
|
|
40
|
+
readText,
|
|
41
|
+
root: config.root,
|
|
42
|
+
sources: inventory.sources,
|
|
40
43
|
});
|
|
44
|
+
return { inventory, violations };
|
|
45
|
+
});
|
|
41
46
|
|
|
42
|
-
export const openSession =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
});
|
|
47
|
+
export const openSession = Effect.fn("Engine.openSession")(function* (
|
|
48
|
+
cwd: string,
|
|
49
|
+
configPath: string | undefined,
|
|
50
|
+
): Effect.fn.Return<Session, SetupFailure, FileSystem.FileSystem> {
|
|
51
|
+
const config = yield* loadConfig(cwd, configPath);
|
|
52
|
+
const registryRaw = yield* readInput(config.root, config.registry);
|
|
53
|
+
const registry = yield* validOrFail(config.registry, yield* Effect.promise(() => decodeRegistry(registryRaw)));
|
|
54
|
+
const baseline = yield* readBaseline(config);
|
|
55
|
+
const { inventory, violations } = yield* scan(config);
|
|
56
|
+
return { baseline, config, inventory, registry: [...registry, ...registryEntries(config.exceptions)], violations };
|
|
57
|
+
});
|