@shivaedev/quality 0.23.0 → 0.25.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 +18 -0
- package/README.md +6 -2
- package/dist/baseline/compare.d.ts +2 -2
- package/dist/baseline/compare.d.ts.map +1 -1
- package/dist/baseline/compare.js +6 -4
- 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 +27 -21
- package/dist/baseline/update.js.map +1 -1
- package/dist/cli/args.d.ts +2 -4
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +19 -18
- 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 +35 -41
- package/dist/cli/fix.js.map +1 -1
- package/dist/cli/lint.d.ts +1 -2
- package/dist/cli/lint.d.ts.map +1 -1
- package/dist/cli/lint.js +1 -2
- package/dist/cli/lint.js.map +1 -1
- package/dist/cli/messages.d.ts +1 -1
- package/dist/cli/messages.d.ts.map +1 -1
- package/dist/cli/messages.js +2 -2
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/migrate.js +2 -2
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/migrateExceptions.js +1 -1
- package/dist/cli/migrateExceptions.js.map +1 -1
- package/dist/cli/program.js +1 -1
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/{run-main.d.ts → runMain.d.ts} +1 -1
- package/dist/cli/runMain.d.ts.map +1 -0
- package/dist/cli/{run-main.js → runMain.js} +3 -3
- package/dist/cli/runMain.js.map +1 -0
- 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 +1 -1
- 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 +23 -3
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +19 -11
- package/dist/config/resolve.js.map +1 -1
- package/dist/config.d.ts +3 -3
- 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 +3 -3
- package/dist/decoded.d.ts.map +1 -1
- package/dist/decoded.js +8 -6
- package/dist/decoded.js.map +1 -1
- package/dist/engine/{baseline-file.d.ts → baselineFile.d.ts} +2 -2
- package/dist/engine/baselineFile.d.ts.map +1 -0
- package/dist/engine/{baseline-file.js → baselineFile.js} +5 -3
- package/dist/engine/baselineFile.js.map +1 -0
- package/dist/engine/evaluate.d.ts +2 -3
- package/dist/engine/evaluate.d.ts.map +1 -1
- package/dist/engine/evaluate.js +6 -5
- package/dist/engine/evaluate.js.map +1 -1
- package/dist/engine/{run-rules.d.ts → runRules.d.ts} +2 -2
- package/dist/engine/runRules.d.ts.map +1 -0
- package/dist/engine/runRules.js +44 -0
- package/dist/engine/runRules.js.map +1 -0
- package/dist/engine/session.d.ts +1 -1
- package/dist/engine/session.d.ts.map +1 -1
- package/dist/engine/session.js +10 -6
- package/dist/engine/session.js.map +1 -1
- package/dist/engine/violation.d.ts +8 -8
- package/dist/engine/violation.d.ts.map +1 -1
- package/dist/engine/violation.js +23 -11
- 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/hooks/preCommit.js +1 -1
- package/dist/hooks/preCommit.js.map +1 -1
- package/dist/imports/generated.js +1 -1
- package/dist/imports/generated.js.map +1 -1
- package/dist/imports/{pnpm-workspace.d.ts → pnpmWorkspacePatterns.d.ts} +1 -1
- package/dist/imports/pnpmWorkspacePatterns.d.ts.map +1 -0
- package/dist/imports/{pnpm-workspace.js → pnpmWorkspacePatterns.js} +1 -1
- package/dist/imports/pnpmWorkspacePatterns.js.map +1 -0
- package/dist/imports/resolve.js +1 -1
- package/dist/imports/resolve.js.map +1 -1
- package/dist/imports/workspace.js +1 -1
- package/dist/imports/workspace.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 +8 -6
- 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/ignoreScope.d.ts +17 -0
- package/dist/inventory/ignoreScope.d.ts.map +1 -0
- package/dist/inventory/{ignore-scope.js → ignoreScope.js} +19 -10
- package/dist/inventory/ignoreScope.js.map +1 -0
- package/dist/inventory/walk.d.ts +1 -1
- package/dist/inventory/walk.d.ts.map +1 -1
- package/dist/inventory/walk.js +1 -1
- package/dist/inventory/walk.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 +15 -17
- 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 -3
- package/dist/report/render.d.ts.map +1 -1
- package/dist/report/render.js +30 -32
- 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 +14 -14
- package/dist/rule.d.ts.map +1 -1
- package/dist/rule.js +11 -9
- package/dist/rule.js.map +1 -1
- package/dist/rules/{built-in.d.ts → builtIn.d.ts} +3 -3
- package/dist/rules/builtIn.d.ts.map +1 -0
- package/dist/rules/{built-in.js → builtIn.js} +17 -13
- package/dist/rules/builtIn.js.map +1 -0
- package/dist/rules/comments/{pattern-rule.d.ts → definePattern.d.ts} +2 -2
- package/dist/rules/comments/definePattern.d.ts.map +1 -0
- package/dist/rules/comments/definePattern.js +18 -0
- package/dist/rules/comments/definePattern.js.map +1 -0
- 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 → maxPerFile.d.ts} +1 -1
- package/dist/rules/comments/maxPerFile.d.ts.map +1 -0
- package/dist/rules/comments/{max-per-file.js → maxPerFile.js} +14 -10
- package/dist/rules/comments/maxPerFile.js.map +1 -0
- package/dist/rules/comments/{no-banner.d.ts → noBanner.d.ts} +1 -1
- package/dist/rules/comments/noBanner.d.ts.map +1 -0
- package/dist/rules/comments/{no-banner.js → noBanner.js} +2 -2
- package/dist/rules/comments/noBanner.js.map +1 -0
- package/dist/rules/comments/{no-environment-pragma.d.ts → noEnvironmentPragma.d.ts} +1 -1
- package/dist/rules/comments/noEnvironmentPragma.d.ts.map +1 -0
- package/dist/rules/comments/{no-environment-pragma.js → noEnvironmentPragma.js} +2 -2
- package/dist/rules/comments/noEnvironmentPragma.js.map +1 -0
- package/dist/rules/comments/{no-jsdoc.d.ts → noJsdoc.d.ts} +1 -1
- package/dist/rules/comments/noJsdoc.d.ts.map +1 -0
- package/dist/rules/comments/{no-jsdoc.js → noJsdoc.js} +1 -1
- package/dist/rules/comments/noJsdoc.js.map +1 -0
- package/dist/rules/comments/{no-line-reference.d.ts → noLineReference.d.ts} +1 -1
- package/dist/rules/comments/noLineReference.d.ts.map +1 -0
- package/dist/rules/comments/{no-line-reference.js → noLineReference.js} +2 -2
- package/dist/rules/comments/noLineReference.js.map +1 -0
- package/dist/rules/comments/{no-pr-reference.d.ts → noPrReference.d.ts} +1 -1
- package/dist/rules/comments/noPrReference.d.ts.map +1 -0
- package/dist/rules/comments/{no-pr-reference.js → noPrReference.js} +2 -2
- package/dist/rules/comments/noPrReference.js.map +1 -0
- package/dist/rules/comments/{no-todo.d.ts → noTodo.d.ts} +1 -1
- package/dist/rules/comments/noTodo.d.ts.map +1 -0
- package/dist/rules/comments/{no-todo.js → noTodo.js} +2 -2
- package/dist/rules/comments/noTodo.js.map +1 -0
- 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/{manifests-sorted.d.ts → manifestsSorted.d.ts} +1 -1
- package/dist/rules/manifestsSorted.d.ts.map +1 -0
- package/dist/rules/{manifests-sorted.js → manifestsSorted.js} +1 -1
- package/dist/rules/manifestsSorted.js.map +1 -0
- package/dist/rules/manifestsSourceFirst.d.ts +2 -0
- package/dist/rules/manifestsSourceFirst.d.ts.map +1 -0
- package/dist/rules/manifestsSourceFirst.js +43 -0
- package/dist/rules/manifestsSourceFirst.js.map +1 -0
- package/dist/rules/{max-lines.d.ts → maxLines.d.ts} +1 -1
- package/dist/rules/maxLines.d.ts.map +1 -0
- package/dist/rules/{max-lines.js → maxLines.js} +13 -11
- package/dist/rules/maxLines.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 → biomeOverrides.d.ts} +1 -1
- package/dist/rules/suppressions/biomeOverrides.d.ts.map +1 -0
- package/dist/rules/suppressions/biomeOverrides.js +75 -0
- package/dist/rules/suppressions/biomeOverrides.js.map +1 -0
- 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 → noDoubleCast.d.ts} +1 -1
- package/dist/rules/suppressions/noDoubleCast.d.ts.map +1 -0
- package/dist/rules/suppressions/{no-double-cast.js → noDoubleCast.js} +15 -11
- package/dist/rules/suppressions/noDoubleCast.js.map +1 -0
- package/dist/rules/suppressions/noIgnoreDeprecations.js +1 -1
- package/dist/rules/suppressions/noIgnoreDeprecations.js.map +1 -1
- package/dist/rules/suppressions/{no-inline.d.ts → noInline.d.ts} +1 -1
- package/dist/rules/suppressions/noInline.d.ts.map +1 -0
- package/dist/rules/suppressions/{no-inline.js → noInline.js} +10 -8
- package/dist/rules/suppressions/noInline.js.map +1 -0
- package/dist/rules/suppressions/stylesheetComments.d.ts +4 -0
- package/dist/rules/suppressions/stylesheetComments.d.ts.map +1 -0
- package/dist/rules/suppressions/{stylesheet-comments.js → stylesheetComments.js} +12 -6
- package/dist/rules/suppressions/stylesheetComments.js.map +1 -0
- 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 → standardSchema.d.ts} +7 -7
- package/dist/standardSchema.d.ts.map +1 -0
- package/dist/{standard-schema.js → standardSchema.js} +1 -1
- package/dist/standardSchema.js.map +1 -0
- package/docs/debt-and-hooks.md +2 -2
- package/docs/modules.md +27 -24
- package/docs/roadmap.md +1 -1
- package/docs/rules.md +2 -0
- package/package.json +2 -3
- package/src/baseline/compare.ts +6 -4
- 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 +23 -19
- package/src/cli/args.ts +20 -21
- package/src/cli/baseline.ts +36 -35
- package/src/cli/fix.ts +40 -43
- package/src/cli/lint.ts +17 -21
- package/src/cli/messages.ts +2 -2
- package/src/cli/migrate.ts +21 -22
- package/src/cli/migrateExceptions.ts +1 -1
- package/src/cli/program.ts +1 -1
- package/src/cli/{run-main.ts → runMain.ts} +2 -2
- package/src/cli/shrink.ts +11 -8
- package/src/cli.ts +1 -1
- package/src/config/decode.ts +15 -10
- package/src/config/load.ts +44 -37
- package/src/config/resolve.ts +34 -29
- package/src/config.ts +5 -3
- package/src/decoded.ts +6 -5
- package/src/engine/baselineFile.ts +29 -0
- package/src/engine/evaluate.ts +7 -8
- package/src/engine/{run-rules.ts → runRules.ts} +22 -14
- package/src/engine/session.ts +34 -27
- package/src/engine/violation.ts +24 -13
- 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/hooks/preCommit.ts +1 -1
- package/src/imports/generated.ts +1 -1
- package/src/imports/resolve.ts +1 -1
- package/src/imports/workspace.ts +1 -1
- package/src/inventory/collect.ts +40 -35
- package/src/inventory/filesystem.ts +38 -30
- package/src/inventory/{ignore-scope.ts → ignoreScope.ts} +20 -10
- package/src/inventory/walk.ts +1 -1
- package/src/manifests/sorted.ts +19 -19
- package/src/report/plural.ts +3 -1
- package/src/report/render.ts +24 -39
- package/src/report/stale.ts +33 -25
- package/src/rule.ts +26 -20
- package/src/rules/{built-in.ts → builtIn.ts} +16 -12
- package/src/rules/comments/{pattern-rule.ts → definePattern.ts} +5 -4
- package/src/rules/comments/kinds.ts +16 -9
- package/src/rules/comments/{max-per-file.ts → maxPerFile.ts} +15 -11
- package/src/rules/comments/{no-banner.ts → noBanner.ts} +1 -1
- package/src/rules/comments/{no-environment-pragma.ts → noEnvironmentPragma.ts} +1 -1
- package/src/rules/comments/{no-line-reference.ts → noLineReference.ts} +1 -1
- package/src/rules/comments/{no-pr-reference.ts → noPrReference.ts} +1 -1
- package/src/rules/comments/{no-todo.ts → noTodo.ts} +1 -1
- package/src/rules/comments/scan.ts +18 -15
- package/src/rules/manifestsSourceFirst.ts +48 -0
- package/src/rules/{max-lines.ts → maxLines.ts} +3 -2
- 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 → biomeOverrides.ts} +32 -22
- package/src/rules/suppressions/directives.ts +5 -4
- package/src/rules/suppressions/{no-double-cast.ts → noDoubleCast.ts} +14 -10
- package/src/rules/suppressions/noIgnoreDeprecations.ts +1 -1
- package/src/rules/suppressions/{no-inline.ts → noInline.ts} +6 -5
- package/src/rules/suppressions/{stylesheet-comments.ts → stylesheetComments.ts} +11 -6
- package/src/rules/syntax.ts +2 -2
- package/src/{standard-schema.ts → standardSchema.ts} +4 -4
- package/dist/cli/run-main.d.ts.map +0 -1
- package/dist/cli/run-main.js.map +0 -1
- package/dist/engine/baseline-file.d.ts.map +0 -1
- package/dist/engine/baseline-file.js.map +0 -1
- package/dist/engine/run-rules.d.ts.map +0 -1
- package/dist/engine/run-rules.js +0 -34
- package/dist/engine/run-rules.js.map +0 -1
- package/dist/imports/pnpm-workspace.d.ts.map +0 -1
- package/dist/imports/pnpm-workspace.js.map +0 -1
- package/dist/inventory/ignore-scope.d.ts +0 -17
- package/dist/inventory/ignore-scope.d.ts.map +0 -1
- package/dist/inventory/ignore-scope.js.map +0 -1
- package/dist/rules/built-in.d.ts.map +0 -1
- package/dist/rules/built-in.js.map +0 -1
- package/dist/rules/comments/max-per-file.d.ts.map +0 -1
- package/dist/rules/comments/max-per-file.js.map +0 -1
- package/dist/rules/comments/no-banner.d.ts.map +0 -1
- package/dist/rules/comments/no-banner.js.map +0 -1
- package/dist/rules/comments/no-environment-pragma.d.ts.map +0 -1
- package/dist/rules/comments/no-environment-pragma.js.map +0 -1
- package/dist/rules/comments/no-jsdoc.d.ts.map +0 -1
- package/dist/rules/comments/no-jsdoc.js.map +0 -1
- package/dist/rules/comments/no-line-reference.d.ts.map +0 -1
- package/dist/rules/comments/no-line-reference.js.map +0 -1
- package/dist/rules/comments/no-pr-reference.d.ts.map +0 -1
- package/dist/rules/comments/no-pr-reference.js.map +0 -1
- package/dist/rules/comments/no-todo.d.ts.map +0 -1
- package/dist/rules/comments/no-todo.js.map +0 -1
- package/dist/rules/comments/pattern-rule.d.ts.map +0 -1
- package/dist/rules/comments/pattern-rule.js +0 -16
- package/dist/rules/comments/pattern-rule.js.map +0 -1
- package/dist/rules/manifests-sorted.d.ts.map +0 -1
- package/dist/rules/manifests-sorted.js.map +0 -1
- package/dist/rules/max-lines.d.ts.map +0 -1
- package/dist/rules/max-lines.js.map +0 -1
- package/dist/rules/suppressions/biome-overrides.d.ts.map +0 -1
- package/dist/rules/suppressions/biome-overrides.js +0 -63
- package/dist/rules/suppressions/biome-overrides.js.map +0 -1
- package/dist/rules/suppressions/no-double-cast.d.ts.map +0 -1
- package/dist/rules/suppressions/no-double-cast.js.map +0 -1
- package/dist/rules/suppressions/no-inline.d.ts.map +0 -1
- package/dist/rules/suppressions/no-inline.js.map +0 -1
- package/dist/rules/suppressions/stylesheet-comments.d.ts +0 -4
- package/dist/rules/suppressions/stylesheet-comments.d.ts.map +0 -1
- package/dist/rules/suppressions/stylesheet-comments.js.map +0 -1
- package/dist/standard-schema.d.ts.map +0 -1
- package/dist/standard-schema.js.map +0 -1
- package/src/engine/baseline-file.ts +0 -27
- /package/src/imports/{pnpm-workspace.ts → pnpmWorkspacePatterns.ts} +0 -0
- /package/src/rules/comments/{no-jsdoc.ts → noJsdoc.ts} +0 -0
- /package/src/rules/{manifests-sorted.ts → manifestsSorted.ts} +0 -0
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
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import type { Decoded } from "#decoded.ts";
|
|
3
|
-
import type { ActiveRule } from "#engine/
|
|
3
|
+
import type { ActiveRule } from "#engine/runRules.ts";
|
|
4
4
|
import type { RuleIndex } from "#engine/violation.ts";
|
|
5
5
|
import type { Rule } from "#rule.ts";
|
|
6
|
-
import { builtInRules } from "#rules/
|
|
6
|
+
import { builtInRules } from "#rules/builtIn.ts";
|
|
7
7
|
import type { ConfigInput } from "./decode.ts";
|
|
8
8
|
|
|
9
9
|
export interface ResolvedRules extends RuleIndex {
|
|
@@ -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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ExceptionDeclaration } from "#exceptions/declaration.ts";
|
|
2
|
-
import type { builtInRules } from "#rules/
|
|
2
|
+
import type { builtInRules } from "#rules/builtIn.ts";
|
|
3
3
|
import type { Rule } from "./rule.ts";
|
|
4
4
|
|
|
5
|
-
export type Level = "error"
|
|
5
|
+
export type Level = "error";
|
|
6
6
|
|
|
7
7
|
export type RuleSetting<TInput> = "error" | { readonly level?: "error"; readonly options?: TInput };
|
|
8
8
|
|
|
@@ -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
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
import { SetupFailure } from "./failure.ts";
|
|
3
|
-
import { describeIssue, type StandardSchemaV1 } from "./
|
|
3
|
+
import { describeIssue, type StandardSchemaV1 } from "./standardSchema.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
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { Effect, type FileSystem } from "effect";
|
|
3
|
+
import { type BaselineEntry, decodeBaseline } from "#baseline/format.ts";
|
|
4
|
+
import { LEGACY_BASELINE } from "#baseline/legacy.ts";
|
|
5
|
+
import type { ResolvedConfig } from "#config/load.ts";
|
|
6
|
+
import { validOrFail } from "#decoded.ts";
|
|
7
|
+
import { SetupFailure } from "#failure.ts";
|
|
8
|
+
import { readOptionalText } from "#inventory/filesystem.ts";
|
|
9
|
+
|
|
10
|
+
export interface BaselineFile {
|
|
11
|
+
readonly entries: readonly BaselineEntry[];
|
|
12
|
+
readonly raw: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
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
|
+
}
|
|
18
|
+
|
|
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
|
@@ -11,29 +11,28 @@ export interface Outcome {
|
|
|
11
11
|
readonly regressions: readonly Regression[];
|
|
12
12
|
readonly staleBaseline: readonly StaleBaselineEntry[];
|
|
13
13
|
readonly staleRegistry: readonly StaleRegistryEntry[];
|
|
14
|
-
readonly warnings: readonly Violation[];
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
export
|
|
16
|
+
export function evaluate(
|
|
18
17
|
violations: readonly Violation[],
|
|
19
18
|
registry: readonly RegistryEntry[],
|
|
20
19
|
baseline: readonly BaselineEntry[],
|
|
21
20
|
rules: RuleIndex,
|
|
22
|
-
): Outcome
|
|
21
|
+
): Outcome {
|
|
23
22
|
const registered = applyRegistry(violations, registry, rules);
|
|
24
23
|
const baselined = applyBaseline(registered.kept, baseline, rules);
|
|
25
24
|
const kept = [...baselined.kept].sort(byLocation);
|
|
26
25
|
return {
|
|
27
26
|
baselined: baselined.baselined,
|
|
28
|
-
errors: kept
|
|
27
|
+
errors: kept,
|
|
29
28
|
looseBaseline: baselined.loose,
|
|
30
29
|
registered: registered.registered,
|
|
31
30
|
regressions: baselined.regressions,
|
|
32
31
|
staleBaseline: baselined.stale,
|
|
33
32
|
staleRegistry: registered.stale,
|
|
34
|
-
warnings: kept.filter((violation) => violation.level === "warn"),
|
|
35
33
|
};
|
|
36
|
-
}
|
|
34
|
+
}
|
|
37
35
|
|
|
38
|
-
export
|
|
39
|
-
outcome.errors.length === 0 && outcome.staleBaseline.length === 0 && outcome.staleRegistry.length === 0;
|
|
36
|
+
export function passes(outcome: Outcome): boolean {
|
|
37
|
+
return outcome.errors.length === 0 && outcome.staleBaseline.length === 0 && outcome.staleRegistry.length === 0;
|
|
38
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isAbsolute, relative } from "node:path";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { SetupFailure } from "#failure.ts";
|
|
4
|
-
import { posix } from "#inventory/
|
|
4
|
+
import { posix } from "#inventory/ignoreScope.ts";
|
|
5
5
|
import type { Finding, Findings, RuleInputs } from "#rule.ts";
|
|
6
6
|
import type { ActiveLevel, Violation } from "./violation.ts";
|
|
7
7
|
|
|
@@ -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
|
@@ -7,8 +7,8 @@ import { registryEntries } from "#exceptions/registryEntries.ts";
|
|
|
7
7
|
import { SetupFailure } from "#failure.ts";
|
|
8
8
|
import { collectInventory, type Inventory } from "#inventory/collect.ts";
|
|
9
9
|
import { type FilesystemFailure, readOptionalText } from "#inventory/filesystem.ts";
|
|
10
|
-
import { type BaselineFile, readBaseline, readInput } from "./
|
|
11
|
-
import { runRules } from "./
|
|
10
|
+
import { type BaselineFile, readBaseline, readInput } from "./baselineFile.ts";
|
|
11
|
+
import { runRules } from "./runRules.ts";
|
|
12
12
|
import type { Violation } from "./violation.ts";
|
|
13
13
|
|
|
14
14
|
export interface Session {
|
|
@@ -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
|
+
});
|
package/src/engine/violation.ts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import type { Level } from "#config.ts";
|
|
2
2
|
import type { Finding } from "#rule.ts";
|
|
3
3
|
|
|
4
|
-
export type ActiveLevel = "error"
|
|
4
|
+
export type ActiveLevel = "error";
|
|
5
5
|
|
|
6
6
|
export interface Violation extends Finding {
|
|
7
7
|
readonly level: ActiveLevel;
|
|
8
8
|
readonly rule: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export
|
|
11
|
+
export function keyOf(rule: string, file: string): string {
|
|
12
|
+
return `${rule}\u0000${file}`;
|
|
13
|
+
}
|
|
12
14
|
|
|
13
|
-
export
|
|
14
|
-
left.rule.localeCompare(right.rule) || left.file.localeCompare(right.file) || (left.line ?? 0) - (right.line ?? 0);
|
|
15
|
+
export function byLocation(left: Violation, right: Violation): number {
|
|
16
|
+
return left.rule.localeCompare(right.rule) || left.file.localeCompare(right.file) || (left.line ?? 0) - (right.line ?? 0);
|
|
17
|
+
}
|
|
15
18
|
|
|
16
|
-
export
|
|
19
|
+
export function groupBy<TItem>(items: readonly TItem[], key: (item: TItem) => string): ReadonlyMap<string, readonly TItem[]> {
|
|
17
20
|
const groups = new Map<string, TItem[]>();
|
|
18
21
|
for (const item of items) {
|
|
19
22
|
const group = groups.get(key(item));
|
|
@@ -24,7 +27,7 @@ export const groupBy = <TItem>(items: readonly TItem[], key: (item: TItem) => st
|
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
return groups;
|
|
27
|
-
}
|
|
30
|
+
}
|
|
28
31
|
|
|
29
32
|
export interface RuleIndex {
|
|
30
33
|
readonly families: ReadonlySet<string>;
|
|
@@ -32,18 +35,26 @@ export interface RuleIndex {
|
|
|
32
35
|
readonly unregistrable: ReadonlySet<string>;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
export
|
|
38
|
+
export function covers(name: string, rule: string): boolean {
|
|
39
|
+
return rule === name || rule.startsWith(`${name}/`);
|
|
40
|
+
}
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
function ownerOf(index: RuleIndex, rule: string): string {
|
|
43
|
+
return [...index.families].find((family) => covers(family, rule)) ?? rule;
|
|
44
|
+
}
|
|
38
45
|
|
|
39
|
-
export
|
|
46
|
+
export function levelOf(index: RuleIndex, rule: string): Level | undefined {
|
|
47
|
+
return index.levels.get(ownerOf(index, rule));
|
|
48
|
+
}
|
|
40
49
|
|
|
41
|
-
export
|
|
50
|
+
export function registrable(index: RuleIndex, rule: string): boolean {
|
|
51
|
+
return !index.unregistrable.has(ownerOf(index, rule));
|
|
52
|
+
}
|
|
42
53
|
|
|
43
|
-
export
|
|
54
|
+
export function unusedEntryProblem(index: RuleIndex, rule: string, unused: string): string {
|
|
44
55
|
const level = levelOf(index, rule);
|
|
45
56
|
if (level === undefined) {
|
|
46
57
|
return "names no known rule";
|
|
47
58
|
}
|
|
48
|
-
return
|
|
49
|
-
}
|
|
59
|
+
return unused;
|
|
60
|
+
}
|
|
@@ -15,8 +15,9 @@ const standard = Schema.toStandardSchemaV1(Schema.fromJsonString(Schema.Array(Re
|
|
|
15
15
|
parseOptions: { errors: "all", onExcessProperty: "error" },
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
export
|
|
19
|
-
raw === undefined ? Promise.resolve({ _tag: "Valid", value: [] }) : decodeWith(standard, raw);
|
|
18
|
+
export function decodeRegistry(raw: string | undefined): Promise<Decoded<readonly RegistryEntry[]>> {
|
|
19
|
+
return raw === undefined ? Promise.resolve({ _tag: "Valid", value: [] }) : decodeWith(standard, raw);
|
|
20
|
+
}
|
|
20
21
|
|
|
21
22
|
export interface StaleRegistryEntry {
|
|
22
23
|
readonly entry: RegistryEntry;
|
|
@@ -29,17 +30,18 @@ export interface RegistryCheck {
|
|
|
29
30
|
readonly stale: readonly StaleRegistryEntry[];
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
entry.rule === violation.rule && entry.file === violation.file && (entry.subject === undefined || entry.subject === violation.subject);
|
|
33
|
+
function covers(entry: RegistryEntry, violation: Violation): boolean {
|
|
34
|
+
return entry.rule === violation.rule && entry.file === violation.file && (entry.subject === undefined || entry.subject === violation.subject);
|
|
35
|
+
}
|
|
34
36
|
|
|
35
37
|
const UNREGISTRABLE = "names a rule that takes no exceptions. Fix the code, or baseline the violations while the repository adopts the rule";
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
function coveringEntry(entries: readonly RegistryEntry[], violation: Violation): RegistryEntry | undefined {
|
|
38
40
|
const matching = entries.filter((entry) => covers(entry, violation));
|
|
39
41
|
return matching.find((entry) => entry.subject !== undefined) ?? matching[0];
|
|
40
|
-
}
|
|
42
|
+
}
|
|
41
43
|
|
|
42
|
-
export
|
|
44
|
+
export function applyRegistry(violations: readonly Violation[], entries: readonly RegistryEntry[], rules: RuleIndex): RegistryCheck {
|
|
43
45
|
const usable = entries.filter((entry) => registrable(rules, entry.rule));
|
|
44
46
|
const used = new Set<RegistryEntry>();
|
|
45
47
|
const kept = violations.filter((violation) => {
|
|
@@ -56,4 +58,4 @@ export const applyRegistry = (violations: readonly Violation[], entries: readonl
|
|
|
56
58
|
problem: registrable(rules, entry.rule) ? unusedEntryProblem(rules, entry.rule, "matches no violation") : UNREGISTRABLE,
|
|
57
59
|
}));
|
|
58
60
|
return { kept, registered: violations.length - kept.length, stale };
|
|
59
|
-
}
|
|
61
|
+
}
|