@shivaedev/quality 0.22.0 → 0.23.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.23.0 - 2026-10-17
4
+
5
+ ### Added
6
+
7
+ - Built-in `nesting/max-depth` reports lines indented with eight or more tabs, except in declaration files. Built-in `structure/no-barrel` rejects `index.ts` and `index.tsx` modules, including those that define their own exports. Both run at error with no options. The existing wildcard export exposes the rules as `maxDepth` from `rules/maxDepth.ts` and `noBarrel` from `rules/noBarrel.ts`.
8
+
3
9
  ## 0.22.0 - 2026-10-16
4
10
 
5
11
  ### Added
@@ -0,0 +1,9 @@
1
+ import { Effect } from "effect";
2
+ import { SetupFailure } from "#failure.ts";
3
+ import type { Launch } from "#hooks/command.ts";
4
+ export interface Invocation {
5
+ readonly cwd: string;
6
+ readonly launch: Launch;
7
+ }
8
+ export declare const program: (args: readonly string[], args_1: Invocation) => Effect.Effect<void, import("#failure.ts").GateFailed | SetupFailure, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem>;
9
+ //# sourceMappingURL=program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,MAAM,QAAQ,CAAC;AAQzC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAKhD,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,OAAO,kOA8BlB,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { Console, Effect } from "effect";
2
+ import { parseCommand, USAGE } from "#cli/args.ts";
3
+ import { writeBaseline } from "#cli/baseline.ts";
4
+ import { fix } from "#cli/fix.ts";
5
+ import { lint } from "#cli/lint.ts";
6
+ import { migrateBaseline } from "#cli/migrate.ts";
7
+ import { migrateExceptions } from "#cli/migrateExceptions.ts";
8
+ import { pruneBaseline, tightenBaseline } from "#cli/shrink.ts";
9
+ import { SetupFailure } from "#failure.ts";
10
+ import { installHook } from "#hooks/install.ts";
11
+ import { preCommitHook } from "#hooks/preCommit.ts";
12
+ import { uninstallHook } from "#hooks/uninstall.ts";
13
+ export const program = Effect.fn("Cli.program")(function* (args, { cwd, launch }) {
14
+ const parsed = parseCommand(args);
15
+ if (parsed._tag === "Usage") {
16
+ return yield* new SetupFailure({ message: `${parsed.problem}\n\n${USAGE}` });
17
+ }
18
+ const command = parsed.command;
19
+ switch (command._tag) {
20
+ case "Help":
21
+ return yield* Console.log(USAGE);
22
+ case "Lint":
23
+ return yield* lint(cwd, command.config, command.warnings);
24
+ case "Fix":
25
+ return yield* fix(cwd, command.config);
26
+ case "BaselineWrite":
27
+ return yield* writeBaseline(cwd, command.config, command.rules);
28
+ case "BaselinePrune":
29
+ return yield* pruneBaseline(cwd, command.config, command.against);
30
+ case "BaselineTighten":
31
+ return yield* tightenBaseline(cwd, command.config, command.staged);
32
+ case "ExceptionsMigrate":
33
+ return yield* migrateExceptions(cwd, command.config, command.from);
34
+ case "BaselineMigrate":
35
+ return yield* migrateBaseline(cwd, command.config, command.from);
36
+ case "HooksInstall":
37
+ return yield* installHook({ config: command.config, cwd, force: command.force, launch });
38
+ case "HooksUninstall":
39
+ return yield* uninstallHook(cwd);
40
+ case "HooksPreCommit":
41
+ return yield* preCommitHook(cwd, command.config);
42
+ }
43
+ });
44
+ //# sourceMappingURL=program.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"program.js","sourceRoot":"","sources":["../../src/cli/program.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,9 @@
1
1
  import type { EventEmitter } from "node:events";
2
- import { Effect, type FileSystem } from "effect";
2
+ import { Effect, Exit, type FileSystem, Layer } from "effect";
3
3
  import type { Git } from "#git/command.ts";
4
+ export declare function exitCode(exit: Exit.Exit<unknown, unknown>): number;
4
5
  export declare function quietOnClosedPipe(stream: EventEmitter): void;
5
- export declare const runMain: <TValue, TError>(program: Effect.Effect<TValue, TError, FileSystem.FileSystem | Git>) => void;
6
+ export declare const services: Layer.Layer<import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | import("effect/Path").Path, never, never>;
7
+ export declare function explained<TValue, TError, TRequirements>(program: Effect.Effect<TValue, TError, TRequirements>): Effect.Effect<TValue, TError, TRequirements>;
8
+ export declare function runMain<TValue, TError>(program: Effect.Effect<TValue, TError, FileSystem.FileSystem | Git>): void;
6
9
  //# sourceMappingURL=run-main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-main.d.ts","sourceRoot":"","sources":["../../src/cli/run-main.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD,OAAO,EAAkB,MAAM,EAAQ,KAAK,UAAU,EAAkB,MAAM,QAAQ,CAAC;AAEvF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AA+B3C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAM5D;AAID,eAAO,MAAM,OAAO,GAAI,MAAM,EAAE,MAAM,WAAW,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,KAAG,IAK7G,CAAC"}
1
+ {"version":3,"file":"run-main.d.ts","sourceRoot":"","sources":["../../src/cli/run-main.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD,OAAO,EAAkB,MAAM,EAAE,IAAI,EAAE,KAAK,UAAU,EAAE,KAAK,EAAW,MAAM,QAAQ,CAAC;AAEvF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAiB3C,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,MAAM,CAKlE;AAUD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAM5D;AAED,eAAO,MAAM,QAAQ,kJAA+G,CAAC;AAErI,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EACtD,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,GACnD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAE9C;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,IAAI,CAIjH"}
@@ -7,20 +7,22 @@ import { Cause, Console, Effect, Exit, Layer, Runtime } from "effect";
7
7
  import { SetupFailure } from "#failure.ts";
8
8
  const INTERRUPTED = 130;
9
9
  const COULD_NOT_RUN = 2;
10
- const explain = (cause) => {
10
+ function explain(cause) {
11
11
  const error = Cause.squash(cause);
12
12
  if (error instanceof SetupFailure) {
13
13
  return Console.error(`quality: ${error.message}`);
14
14
  }
15
15
  return Runtime.getErrorReported(error) ? Console.error(`quality: internal error\n${Cause.pretty(cause)}`) : Effect.void;
16
- };
17
- const exitCodeOf = (error) => typeof error === "object" && error !== null && Runtime.errorExitCode in error ? Runtime.getErrorExitCode(error) : COULD_NOT_RUN;
18
- const exitCode = (exit) => {
16
+ }
17
+ function exitCodeOf(error) {
18
+ return typeof error === "object" && error !== null && Runtime.errorExitCode in error ? Runtime.getErrorExitCode(error) : COULD_NOT_RUN;
19
+ }
20
+ export function exitCode(exit) {
19
21
  if (Exit.isSuccess(exit)) {
20
22
  return 0;
21
23
  }
22
24
  return Cause.hasInterruptsOnly(exit.cause) ? INTERRUPTED : exitCodeOf(Cause.squash(exit.cause));
23
- };
25
+ }
24
26
  const teardown = (exit, onExit) => {
25
27
  process.stdout.write("", () => process.stderr.write("", () => onExit(exitCode(exit))));
26
28
  };
@@ -34,11 +36,13 @@ export function quietOnClosedPipe(stream) {
34
36
  }
35
37
  });
36
38
  }
37
- const services = NodeChildProcessSpawner.layer.pipe(Layer.provideMerge(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer)));
38
- export const runMain = (program) => {
39
+ export const services = NodeChildProcessSpawner.layer.pipe(Layer.provideMerge(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer)));
40
+ export function explained(program) {
41
+ return Effect.tapCause(program, (cause) => (Cause.hasInterruptsOnly(cause) ? Effect.void : explain(cause)));
42
+ }
43
+ export function runMain(program) {
39
44
  quietOnClosedPipe(process.stdout);
40
45
  quietOnClosedPipe(process.stderr);
41
- const explained = Effect.tapCause(program, (cause) => (Cause.hasInterruptsOnly(cause) ? Effect.void : explain(cause)));
42
- NodeRuntime.runMain(Effect.provide(explained, services), { disableErrorReporting: true, teardown });
43
- };
46
+ NodeRuntime.runMain(Effect.provide(explained(program), services), { disableErrorReporting: true, teardown });
47
+ }
44
48
  //# sourceMappingURL=run-main.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-main.js","sourceRoot":"","sources":["../../src/cli/run-main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-main.js","sourceRoot":"","sources":["../../src/cli/run-main.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -1,53 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import process from "node:process";
3
- import { Console, Effect } from "effect";
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.js";
16
- const parsed = parseCommand(process.argv.slice(2));
17
- const program = Effect.gen(function* () {
18
- if (parsed._tag === "Usage") {
19
- return yield* new SetupFailure({ message: `${parsed.problem}\n\n${USAGE}` });
20
- }
21
- const command = parsed.command;
22
- switch (command._tag) {
23
- case "Help":
24
- return yield* Console.log(USAGE);
25
- case "Lint":
26
- return yield* lint(process.cwd(), command.config, command.warnings);
27
- case "Fix":
28
- return yield* fix(process.cwd(), command.config);
29
- case "BaselineWrite":
30
- return yield* writeBaseline(process.cwd(), command.config, command.rules);
31
- case "BaselinePrune":
32
- return yield* pruneBaseline(process.cwd(), command.config, command.against);
33
- case "BaselineTighten":
34
- return yield* tightenBaseline(process.cwd(), command.config, command.staged);
35
- case "ExceptionsMigrate":
36
- return yield* migrateExceptions(process.cwd(), command.config, command.from);
37
- case "BaselineMigrate":
38
- return yield* migrateBaseline(process.cwd(), command.config, command.from);
39
- case "HooksInstall":
40
- return yield* installHook({
41
- config: command.config,
42
- cwd: process.cwd(),
43
- force: command.force,
44
- launch: { options: process.execArgv, script: process.argv[1] ?? "" },
45
- });
46
- case "HooksUninstall":
47
- return yield* uninstallHook(process.cwd());
48
- case "HooksPreCommit":
49
- return yield* preCommitHook(process.cwd(), command.config);
50
- }
51
- });
52
- runMain(program);
5
+ runMain(program(process.argv.slice(2), { cwd: process.cwd(), launch: { options: process.execArgv, script: process.argv[1] ?? "" } }));
53
6
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC"}
@@ -1,7 +1,7 @@
1
1
  export declare const builtInRules: readonly [import("../rule.ts").Rule<"structure/max-lines", {
2
2
  readonly source?: number;
3
3
  readonly test?: number;
4
- }>, import("../rule.ts").Rule<"comments/no-jsdoc", {
4
+ }>, import("../rule.ts").Rule<"nesting/max-depth", undefined>, import("../rule.ts").Rule<"structure/no-barrel", undefined>, import("../rule.ts").Rule<"comments/no-jsdoc", {
5
5
  readonly allow?: readonly string[];
6
6
  }>, import("../rule.ts").Rule<"comments/no-line-reference", undefined>, import("../rule.ts").Rule<"comments/no-pr-reference", undefined>, import("../rule.ts").Rule<"comments/no-banner", undefined>, import("../rule.ts").Rule<"comments/no-todo", undefined>, import("../rule.ts").Rule<"comments/no-environment-pragma", undefined>, import("../rule.ts").Rule<"comments/max-per-file", {
7
7
  readonly allow?: readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"built-in.d.ts","sourceRoot":"","sources":["../../src/rules/built-in.ts"],"names":[],"mappings":"AA8BA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8DA8Bf,CAAC"}
1
+ {"version":3,"file":"built-in.d.ts","sourceRoot":"","sources":["../../src/rules/built-in.ts"],"names":[],"mappings":"AAgCA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8DAgCf,CAAC"}
@@ -27,8 +27,12 @@ import { testsFollow } from "#rules/test-names/follow.ts";
27
27
  import { biome } from "./biome.js";
28
28
  import { manifestsSorted } from "./manifests-sorted.js";
29
29
  import { maxLines } from "./max-lines.js";
30
+ import { maxDepth } from "./maxDepth.js";
31
+ import { noBarrel } from "./noBarrel.js";
30
32
  export const builtInRules = [
31
33
  maxLines,
34
+ maxDepth,
35
+ noBarrel,
32
36
  noJsdoc,
33
37
  noLineReference,
34
38
  noPrReference,
@@ -1 +1 @@
1
- {"version":3,"file":"built-in.js","sourceRoot":"","sources":["../../src/rules/built-in.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B,QAAQ;IACR,OAAO;IACP,eAAe;IACf,aAAa;IACb,QAAQ;IACR,MAAM;IACN,mBAAmB;IACnB,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,oBAAoB;IACpB,cAAc;IACd,gBAAgB;IAChB,KAAK;IACL,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,iBAAiB;IACjB,eAAe;IACf,cAAc;IACd,UAAU;IACV,eAAe;IACf,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,UAAU;IACV,WAAW;IACX,cAAc;IACd,UAAU;CACD,CAAC"}
1
+ {"version":3,"file":"built-in.js","sourceRoot":"","sources":["../../src/rules/built-in.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AACnF,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,eAAe;IACf,aAAa;IACb,QAAQ;IACR,MAAM;IACN,mBAAmB;IACnB,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,oBAAoB;IACpB,cAAc;IACd,gBAAgB;IAChB,KAAK;IACL,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,iBAAiB;IACjB,eAAe;IACf,cAAc;IACd,UAAU;IACV,eAAe;IACf,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,UAAU;IACV,WAAW;IACX,cAAc;IACd,UAAU;CACD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const maxDepth: import("#rule.ts").Rule<"nesting/max-depth", undefined>;
2
+ //# sourceMappingURL=maxDepth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maxDepth.d.ts","sourceRoot":"","sources":["../../src/rules/maxDepth.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,QAAQ,yDAInB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { defineRule } from "#rule.ts";
2
+ const DECLARATION = /\.d\.[cm]?ts$/u;
3
+ const TOO_DEEP = /^\t{8,}/u;
4
+ function findingsOf(file) {
5
+ return file.lines.flatMap((text, index) => TOO_DEEP.test(text)
6
+ ? [
7
+ {
8
+ file: file.path,
9
+ line: index + 1,
10
+ message: "Indentation is 8+ tabs deep. Extract a named function or component.",
11
+ },
12
+ ]
13
+ : []);
14
+ }
15
+ export const maxDepth = defineRule({
16
+ check: ({ sources }) => sources.filter((file) => !DECLARATION.test(file.path)).flatMap(findingsOf),
17
+ description: "Extract a named function or component before indentation reaches eight tabs.",
18
+ id: "nesting/max-depth",
19
+ });
20
+ //# sourceMappingURL=maxDepth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maxDepth.js","sourceRoot":"","sources":["../../src/rules/maxDepth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAiC,MAAM,UAAU,CAAC;AAErE,MAAM,WAAW,GAAG,gBAAgB,CAAC;AACrC,MAAM,QAAQ,GAAG,UAAU,CAAC;AAE5B,SAAS,UAAU,CAAC,IAAgB;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACzC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAClB,CAAC,CAAC;YACA;gBACC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,KAAK,GAAG,CAAC;gBACf,OAAO,EAAE,qEAAqE;aAC9E;SACD;QACF,CAAC,CAAC,EAAE,CACL,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IAClG,WAAW,EAAE,8EAA8E;IAC3F,EAAE,EAAE,mBAAmB;CACvB,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const noBarrel: import("#rule.ts").Rule<"structure/no-barrel", undefined>;
2
+ //# sourceMappingURL=noBarrel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noBarrel.d.ts","sourceRoot":"","sources":["../../src/rules/noBarrel.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,QAAQ,2DAUnB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { posix } from "node:path";
2
+ import { defineRule } from "#rule.ts";
3
+ const BARREL_FILE = /^index\.tsx?$/u;
4
+ export const noBarrel = defineRule({
5
+ check: ({ sources }) => sources
6
+ .filter((file) => BARREL_FILE.test(posix.basename(file.path)))
7
+ .map((file) => ({
8
+ file: file.path,
9
+ message: "index.ts and index.tsx modules are banned. Name the module after its purpose and import it directly.",
10
+ })),
11
+ description: "Name TypeScript modules after their purpose instead of index.ts or index.tsx.",
12
+ id: "structure/no-barrel",
13
+ });
14
+ //# sourceMappingURL=noBarrel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noBarrel.js","sourceRoot":"","sources":["../../src/rules/noBarrel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAErC,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAC;IAClC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CACtB,OAAO;SACL,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;SAC7D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE,sGAAsG;KAC/G,CAAC,CAAC;IACL,WAAW,EAAE,+EAA+E;IAC5F,EAAE,EAAE,qBAAqB;CACzB,CAAC,CAAC"}
package/docs/modules.md CHANGED
@@ -30,9 +30,13 @@ A module link opens its source. Type and value declarations with the same name a
30
30
 
31
31
  | Module | Exported names |
32
32
  | --- | --- |
33
+ | [biome/exceptionConfig.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/biome/exceptionConfig.ts) | `exceptionConfig`, `withExceptionConfig` |
34
+ | [biome/nativeEffectCall.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/biome/nativeEffectCall.ts) | `nativeEffectCall` |
35
+ | [biome/recognizeDiagnostics.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/biome/recognizeDiagnostics.ts) | `recognizeDiagnostics` |
33
36
  | [biome/recommendedRules.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/biome/recommendedRules.ts) | `recommendedRules` |
34
37
  | [biome/report.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/biome/report.ts) | `Diagnostic`, `Report`, `biomeReport` |
35
38
  | [biome/run.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/biome/run.ts) | `BiomeRun`, `runBiome` |
39
+ | [biome/syntax.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/biome/syntax.ts) | `Syntax`, `syntaxOf`, `offsetOf`, `nodeAt` |
36
40
 
37
41
  ## cli
38
42
 
@@ -42,8 +46,11 @@ A module link opens its source. Type and value declarations with the same name a
42
46
  | [cli/baseline.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/baseline.ts) | `writeBaseline`, `shrinkBaseline` |
43
47
  | [cli/fix.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/fix.ts) | `MAX_FIX_ROUNDS`, `snapshotOf`, `Pass`, `Settling`, `settle`, `fix` |
44
48
  | [cli/lint.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/lint.ts) | `lint` |
49
+ | [cli/messages.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/messages.ts) | `USAGE`, `ADOPT_REMOVED` |
45
50
  | [cli/migrate.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/migrate.ts) | `migrateBaseline` |
46
- | [cli/run-main.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/run-main.ts) | `quietOnClosedPipe`, `runMain` |
51
+ | [cli/migrateExceptions.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/migrateExceptions.ts) | `migrateExceptions` |
52
+ | [cli/program.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/program.ts) | `Invocation`, `program` |
53
+ | [cli/run-main.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/run-main.ts) | `exitCode`, `quietOnClosedPipe`, `services`, `explained`, `runMain` |
47
54
  | [cli/shrink.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/cli/shrink.ts) | `pruneBaseline`, `tightenBaseline` |
48
55
 
49
56
  ## config
@@ -69,7 +76,10 @@ A module link opens its source. Type and value declarations with the same name a
69
76
 
70
77
  | Module | Exported names |
71
78
  | --- | --- |
79
+ | [exceptions/biomeFindings.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/exceptions/biomeFindings.ts) | `missingBiomeFiles`, `biomeExceptionHint` |
72
80
  | [exceptions/declaration.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/exceptions/declaration.ts) | `ExceptionDeclaration`, `decodeExceptions` |
81
+ | [exceptions/migrateBiome.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/exceptions/migrateBiome.ts) | `migrateBiome` |
82
+ | [exceptions/migrateConfig.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/exceptions/migrateConfig.ts) | `migrateConfig` |
73
83
  | [exceptions/registryEntries.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/exceptions/registryEntries.ts) | `registryEntries` |
74
84
  | [exceptions/registry.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/exceptions/registry.ts) | `RegistryEntry`, `decodeRegistry`, `StaleRegistryEntry`, `RegistryCheck`, `applyRegistry` |
75
85
 
@@ -97,6 +107,8 @@ A module link opens its source. Type and value declarations with the same name a
97
107
  | Module | Exported names |
98
108
  | --- | --- |
99
109
  | [imports/ambient.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/ambient.ts) | `Ambient`, `ambientModules` |
110
+ | [imports/browserGlobals.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/browserGlobals.ts) | `browserGlobals` |
111
+ | [imports/browserNames.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/browserNames.ts) | `browserNames` |
100
112
  | [imports/components.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/components.ts) | `cyclicComponents` |
101
113
  | [imports/departures.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/departures.ts) | `Departure`, `departures` |
102
114
  | [imports/extract.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/extract.ts) | `ImportKind`, `ImportRequest`, `importsOf` |
@@ -107,6 +119,7 @@ A module link opens its source. Type and value declarations with the same name a
107
119
  | [imports/pnpm-workspace.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/pnpm-workspace.ts) | `pnpmWorkspacePatterns` |
108
120
  | [imports/projects.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/projects.ts) | `Project`, `projectsFor` |
109
121
  | [imports/resolve.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/resolve.ts) | `Endpoint`, `builtinName`, `packageNameOf`, `isDeclarationFile`, `presumedTarget`, `resolveImport` |
122
+ | [imports/runtime.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/runtime.ts) | `Runtime`, `runtimeOf` |
110
123
  | [imports/specifiers.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/specifiers.ts) | `SpecifierSite`, `specifierSites` |
111
124
  | [imports/workspace.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/imports/workspace.ts) | `WorkspacePackage`, `workspacePackages`, `packageOf` |
112
125
 
@@ -204,8 +217,10 @@ A module link opens its source. Type and value declarations with the same name a
204
217
  | [rules/imports/aliased.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/imports/aliased.ts) | `importsAliased` |
205
218
  | [rules/imports/cycles.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/imports/cycles.ts) | `importCycles` |
206
219
  | [rules/imports/fences.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/imports/fences.ts) | `importFences` |
220
+ | [rules/imports/manifest.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/imports/manifest.ts) | `importsManifest` |
207
221
  | [rules/imports/noTestCode.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/imports/noTestCode.ts) | `noTestCode` |
208
222
  | [rules/imports/resolvable.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/imports/resolvable.ts) | `importsResolvable` |
223
+ | [rules/imports/runtime.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/imports/runtime.ts) | `importsRuntime` |
209
224
 
210
225
  ## rules/stories
211
226
 
@@ -230,6 +245,7 @@ A module link opens its source. Type and value declarations with the same name a
230
245
 
231
246
  | Module | Exported names |
232
247
  | --- | --- |
248
+ | [rules/suppressions/biome/ConsumerDeclaration.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/suppressions/biome/ConsumerDeclaration.ts) | `ConsumerDeclaration` |
233
249
  | [rules/suppressions/biome/configs.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/suppressions/biome/configs.ts) | `Preset`, `Layer`, `Chain`, `BiomeConfigs`, `biomeConfigs` |
234
250
  | [rules/suppressions/biome/declarations.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/suppressions/biome/declarations.ts) | `Declaration`, `PRESET_DECLARATIONS`, `decodeShipped`, `Scoped`, `matches`, `scoped`, `scopeText` |
235
251
  | [rules/suppressions/biome/json.ts](https://github.com/ShivaeDev/platform/blob/main/packages/quality/src/rules/suppressions/biome/json.ts) | `Json`, `Parsed`, `parseJsonc`, `member`, `entriesOf`, `itemsOf`, `textOf`, `isFalse` |
package/docs/roadmap.md CHANGED
@@ -16,12 +16,12 @@ This page owns Quality's shared policy, tooling, CLI and hook implementation sta
16
16
  - [x] Opt-in pre-commit hooks with per-worktree config and dependencies, conventional `typecheck` and `quality:commit` scripts, and explicit installation.
17
17
  - [x] Seeded-repository and real-command tests for the gate, import policies, Biome, baseline and git hooks, plus packed consumer checks for the CLI and presets.
18
18
  - [x] Separate shipped Biome declarations from consumer exceptions; reject whole-check, group and blanket-scope consumer declarations.
19
+ - [x] Shared nesting-depth and index-module checks; Platform's catalog, manifest and Codecov checks use the local-rule API and the same inventory, report and baseline.
19
20
 
20
21
  ## Next
21
22
 
22
23
  - [ ] Remove obsolete CLI warning-report controls; config levels are already enforced at `error`. Keep old-debt adoption in the baseline.
23
24
  - [ ] Reduce policy-tuning inputs to the ones checks need about a repository. Thresholds can only be lowered; local-rule APIs remain exposed. Review the remaining extension boundary.
24
- - [ ] Port reusable checks still in `script/lint/rules/` into the shared policy, so consumers do not copy Platform's scripts.
25
25
  - [ ] Split Grit implementation modules by the checks they own, without making consumers select competing presets; route Platform's remaining static checks through Quality.
26
26
  - [ ] Define the Effect-boundary rule's source and test scope before porting the repository's `try`/`async` restrictions.
27
27
  - [ ] Define the service-parameter policy before enforcing it against public helpers that accept services or `Context`.
package/docs/rules.md CHANGED
@@ -2,10 +2,18 @@
2
2
 
3
3
  Use the [README](../README.md) for the gate's mental model and workflow. Quality owns the shared policy; consuming repositories adopt its defaults. This reference gives each built-in rule's scope, findings and accepted options, including the exposed local-rule API. An option being accepted is not a recommendation to tune the shared standard. Supply repository facts, such as generated locations and import boundaries, when a check needs them. The [naming reference](./naming.md) covers names and test layout; [shared tooling](./tooling.md) covers the Biome, Vitest and TypeScript setup.
4
4
 
5
- ## File size
5
+ ## File structure
6
+
7
+ ### File size
6
8
 
7
9
  `structure/max-lines` keeps each module to one job: a source file may have 150 lines and [test code](./naming.md#test-code) 300, counted the way an editor numbers them. Declaration files are exempt. Its options are `source` and `test`: positive integer limits no greater than 150 and 300 respectively. Test code is identified by its conventional name or `test-support` folder; custom test-file patterns are rejected. A file over its limit counts one violation for each line above it: 168 lines under a limit of 150 count 18.
8
10
 
11
+ ### Nesting and module structure
12
+
13
+ `nesting/max-depth` reports each source line that starts with eight or more tabs. Extract a named function or component. Declaration files are exempt; indentation with spaces is outside this text check. It takes no options.
14
+
15
+ `structure/no-barrel` rejects every source module named `index.ts` or `index.tsx`, including modules that define their own exports. Name the module after its purpose. It takes no options. The shared Biome preset separately rejects re-exports regardless of the file name.
16
+
9
17
  ### Comments
10
18
 
11
19
  A comment says why, never what the code already says or what it used to be. Seven rules hold every comment to that:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/quality",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Repository quality gate with typed rules, a baseline of existing debt and a registry of reasoned exceptions",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/quality#readme",
6
6
  "bugs": {
@@ -62,7 +62,7 @@
62
62
  "@effect/platform-node": "4.0.4",
63
63
  "@effect/platform-node-shared": "4.0.4",
64
64
  "@effect/vitest": "4.0.4",
65
- "@types/node": "24.19.1",
65
+ "@types/node": "24.19.2",
66
66
  "@typescript/native": "npm:typescript@7.0.2",
67
67
  "effect": "4.0.4",
68
68
  "vitest": "5.0.3"
@@ -0,0 +1,50 @@
1
+ import { Console, Effect } from "effect";
2
+ import { parseCommand, USAGE } from "#cli/args.ts";
3
+ import { writeBaseline } from "#cli/baseline.ts";
4
+ import { fix } from "#cli/fix.ts";
5
+ import { lint } from "#cli/lint.ts";
6
+ import { migrateBaseline } from "#cli/migrate.ts";
7
+ import { migrateExceptions } from "#cli/migrateExceptions.ts";
8
+ import { pruneBaseline, tightenBaseline } from "#cli/shrink.ts";
9
+ import { SetupFailure } from "#failure.ts";
10
+ import type { Launch } from "#hooks/command.ts";
11
+ import { installHook } from "#hooks/install.ts";
12
+ import { preCommitHook } from "#hooks/preCommit.ts";
13
+ import { uninstallHook } from "#hooks/uninstall.ts";
14
+
15
+ export interface Invocation {
16
+ readonly cwd: string;
17
+ readonly launch: Launch;
18
+ }
19
+
20
+ export const program = Effect.fn("Cli.program")(function* (args: readonly string[], { cwd, launch }: Invocation) {
21
+ const parsed = parseCommand(args);
22
+ if (parsed._tag === "Usage") {
23
+ return yield* new SetupFailure({ message: `${parsed.problem}\n\n${USAGE}` });
24
+ }
25
+ const command = parsed.command;
26
+ switch (command._tag) {
27
+ case "Help":
28
+ return yield* Console.log(USAGE);
29
+ case "Lint":
30
+ return yield* lint(cwd, command.config, command.warnings);
31
+ case "Fix":
32
+ return yield* fix(cwd, command.config);
33
+ case "BaselineWrite":
34
+ return yield* writeBaseline(cwd, command.config, command.rules);
35
+ case "BaselinePrune":
36
+ return yield* pruneBaseline(cwd, command.config, command.against);
37
+ case "BaselineTighten":
38
+ return yield* tightenBaseline(cwd, command.config, command.staged);
39
+ case "ExceptionsMigrate":
40
+ return yield* migrateExceptions(cwd, command.config, command.from);
41
+ case "BaselineMigrate":
42
+ return yield* migrateBaseline(cwd, command.config, command.from);
43
+ case "HooksInstall":
44
+ return yield* installHook({ config: command.config, cwd, force: command.force, launch });
45
+ case "HooksUninstall":
46
+ return yield* uninstallHook(cwd);
47
+ case "HooksPreCommit":
48
+ return yield* preCommitHook(cwd, command.config);
49
+ }
50
+ });
@@ -11,23 +11,24 @@ import type { Git } from "#git/command.ts";
11
11
  const INTERRUPTED = 130;
12
12
  const COULD_NOT_RUN = 2;
13
13
 
14
- const explain = (cause: Cause.Cause<unknown>): Effect.Effect<void> => {
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
- const exitCodeOf = (error: unknown): number =>
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
- const exitCode = (exit: Exit.Exit<unknown, unknown>): number => {
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
  const teardown: Runtime.Teardown = (exit, onExit) => {
33
34
  process.stdout.write("", () => process.stderr.write("", () => onExit(exitCode(exit))));
@@ -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 const runMain = <TValue, TError>(program: Effect.Effect<TValue, TError, FileSystem.FileSystem | Git>): void => {
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
- const explained = Effect.tapCause(program, (cause) => (Cause.hasInterruptsOnly(cause) ? Effect.void : explain(cause)));
54
- NodeRuntime.runMain(Effect.provide(explained, services), { disableErrorReporting: true, teardown });
55
- };
60
+ NodeRuntime.runMain(Effect.provide(explained(program), services), { disableErrorReporting: true, teardown });
61
+ }
package/src/cli.ts CHANGED
@@ -1,55 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import process from "node:process";
3
- import { Console, Effect } from "effect";
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
- const parsed = parseCommand(process.argv.slice(2));
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] ?? "" } }));
@@ -27,9 +27,13 @@ import { testsFollow } from "#rules/test-names/follow.ts";
27
27
  import { biome } from "./biome.ts";
28
28
  import { manifestsSorted } from "./manifests-sorted.ts";
29
29
  import { maxLines } from "./max-lines.ts";
30
+ import { maxDepth } from "./maxDepth.ts";
31
+ import { noBarrel } from "./noBarrel.ts";
30
32
 
31
33
  export const builtInRules = [
32
34
  maxLines,
35
+ maxDepth,
36
+ noBarrel,
33
37
  noJsdoc,
34
38
  noLineReference,
35
39
  noPrReference,
@@ -0,0 +1,24 @@
1
+ import { defineRule, type Finding, type SourceFile } from "#rule.ts";
2
+
3
+ const DECLARATION = /\.d\.[cm]?ts$/u;
4
+ const TOO_DEEP = /^\t{8,}/u;
5
+
6
+ function findingsOf(file: SourceFile): readonly Finding[] {
7
+ return file.lines.flatMap((text, index) =>
8
+ TOO_DEEP.test(text)
9
+ ? [
10
+ {
11
+ file: file.path,
12
+ line: index + 1,
13
+ message: "Indentation is 8+ tabs deep. Extract a named function or component.",
14
+ },
15
+ ]
16
+ : [],
17
+ );
18
+ }
19
+
20
+ export const maxDepth = defineRule({
21
+ check: ({ sources }) => sources.filter((file) => !DECLARATION.test(file.path)).flatMap(findingsOf),
22
+ description: "Extract a named function or component before indentation reaches eight tabs.",
23
+ id: "nesting/max-depth",
24
+ });
@@ -0,0 +1,16 @@
1
+ import { posix } from "node:path";
2
+ import { defineRule } from "#rule.ts";
3
+
4
+ const BARREL_FILE = /^index\.tsx?$/u;
5
+
6
+ export const noBarrel = defineRule({
7
+ check: ({ sources }) =>
8
+ sources
9
+ .filter((file) => BARREL_FILE.test(posix.basename(file.path)))
10
+ .map((file) => ({
11
+ file: file.path,
12
+ message: "index.ts and index.tsx modules are banned. Name the module after its purpose and import it directly.",
13
+ })),
14
+ description: "Name TypeScript modules after their purpose instead of index.ts or index.tsx.",
15
+ id: "structure/no-barrel",
16
+ });