@opensip-tools/fitness 1.0.4
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/.turbo/turbo-build.log +4 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/LICENSE +21 -0
- package/dist/__tests__/gate.test.d.ts +13 -0
- package/dist/__tests__/gate.test.d.ts.map +1 -0
- package/dist/__tests__/gate.test.js +422 -0
- package/dist/__tests__/gate.test.js.map +1 -0
- package/dist/__tests__/sarif.test.d.ts +2 -0
- package/dist/__tests__/sarif.test.d.ts.map +1 -0
- package/dist/__tests__/sarif.test.js +169 -0
- package/dist/__tests__/sarif.test.js.map +1 -0
- package/dist/cli/dashboard.d.ts +6 -0
- package/dist/cli/dashboard.d.ts.map +1 -0
- package/dist/cli/dashboard.js +77 -0
- package/dist/cli/dashboard.js.map +1 -0
- package/dist/cli/fit.d.ts +37 -0
- package/dist/cli/fit.d.ts.map +1 -0
- package/dist/cli/fit.js +539 -0
- package/dist/cli/fit.js.map +1 -0
- package/dist/cli/list-checks.d.ts +6 -0
- package/dist/cli/list-checks.d.ts.map +1 -0
- package/dist/cli/list-checks.js +23 -0
- package/dist/cli/list-checks.js.map +1 -0
- package/dist/cli/list-recipes.d.ts +6 -0
- package/dist/cli/list-recipes.d.ts.map +1 -0
- package/dist/cli/list-recipes.js +31 -0
- package/dist/cli/list-recipes.js.map +1 -0
- package/dist/framework/__tests__/ast-utilities.test.d.ts +2 -0
- package/dist/framework/__tests__/ast-utilities.test.d.ts.map +1 -0
- package/dist/framework/__tests__/ast-utilities.test.js +153 -0
- package/dist/framework/__tests__/ast-utilities.test.js.map +1 -0
- package/dist/framework/__tests__/check-config.test.d.ts +2 -0
- package/dist/framework/__tests__/check-config.test.d.ts.map +1 -0
- package/dist/framework/__tests__/check-config.test.js +56 -0
- package/dist/framework/__tests__/check-config.test.js.map +1 -0
- package/dist/framework/__tests__/command-executor.test.d.ts +2 -0
- package/dist/framework/__tests__/command-executor.test.d.ts.map +1 -0
- package/dist/framework/__tests__/command-executor.test.js +71 -0
- package/dist/framework/__tests__/command-executor.test.js.map +1 -0
- package/dist/framework/__tests__/content-filter-dispatch.test.d.ts +2 -0
- package/dist/framework/__tests__/content-filter-dispatch.test.d.ts.map +1 -0
- package/dist/framework/__tests__/content-filter-dispatch.test.js +104 -0
- package/dist/framework/__tests__/content-filter-dispatch.test.js.map +1 -0
- package/dist/framework/__tests__/content-filter.test.d.ts +2 -0
- package/dist/framework/__tests__/content-filter.test.d.ts.map +1 -0
- package/dist/framework/__tests__/content-filter.test.js +126 -0
- package/dist/framework/__tests__/content-filter.test.js.map +1 -0
- package/dist/framework/__tests__/define-check.test.d.ts +2 -0
- package/dist/framework/__tests__/define-check.test.d.ts.map +1 -0
- package/dist/framework/__tests__/define-check.test.js +155 -0
- package/dist/framework/__tests__/define-check.test.js.map +1 -0
- package/dist/framework/__tests__/directive-inventory.test.d.ts +2 -0
- package/dist/framework/__tests__/directive-inventory.test.d.ts.map +1 -0
- package/dist/framework/__tests__/directive-inventory.test.js +44 -0
- package/dist/framework/__tests__/directive-inventory.test.js.map +1 -0
- package/dist/framework/__tests__/execution-context.test.d.ts +2 -0
- package/dist/framework/__tests__/execution-context.test.d.ts.map +1 -0
- package/dist/framework/__tests__/execution-context.test.js +62 -0
- package/dist/framework/__tests__/execution-context.test.js.map +1 -0
- package/dist/framework/__tests__/file-accessor.test.d.ts +2 -0
- package/dist/framework/__tests__/file-accessor.test.d.ts.map +1 -0
- package/dist/framework/__tests__/file-accessor.test.js +106 -0
- package/dist/framework/__tests__/file-accessor.test.js.map +1 -0
- package/dist/framework/__tests__/file-cache.test.d.ts +2 -0
- package/dist/framework/__tests__/file-cache.test.d.ts.map +1 -0
- package/dist/framework/__tests__/file-cache.test.js +122 -0
- package/dist/framework/__tests__/file-cache.test.js.map +1 -0
- package/dist/framework/__tests__/import-graph.test.d.ts +15 -0
- package/dist/framework/__tests__/import-graph.test.d.ts.map +1 -0
- package/dist/framework/__tests__/import-graph.test.js +164 -0
- package/dist/framework/__tests__/import-graph.test.js.map +1 -0
- package/dist/framework/__tests__/path-matcher.test.d.ts +2 -0
- package/dist/framework/__tests__/path-matcher.test.d.ts.map +1 -0
- package/dist/framework/__tests__/path-matcher.test.js +113 -0
- package/dist/framework/__tests__/path-matcher.test.js.map +1 -0
- package/dist/framework/__tests__/register-helpers.test.d.ts +2 -0
- package/dist/framework/__tests__/register-helpers.test.d.ts.map +1 -0
- package/dist/framework/__tests__/register-helpers.test.js +42 -0
- package/dist/framework/__tests__/register-helpers.test.js.map +1 -0
- package/dist/framework/__tests__/registry.test.d.ts +2 -0
- package/dist/framework/__tests__/registry.test.d.ts.map +1 -0
- package/dist/framework/__tests__/registry.test.js +208 -0
- package/dist/framework/__tests__/registry.test.js.map +1 -0
- package/dist/framework/__tests__/result-builder.test.d.ts +2 -0
- package/dist/framework/__tests__/result-builder.test.d.ts.map +1 -0
- package/dist/framework/__tests__/result-builder.test.js +153 -0
- package/dist/framework/__tests__/result-builder.test.js.map +1 -0
- package/dist/framework/__tests__/scope-resolver.test.d.ts +2 -0
- package/dist/framework/__tests__/scope-resolver.test.d.ts.map +1 -0
- package/dist/framework/__tests__/scope-resolver.test.js +140 -0
- package/dist/framework/__tests__/scope-resolver.test.js.map +1 -0
- package/dist/framework/__tests__/severity-mapping.test.d.ts +2 -0
- package/dist/framework/__tests__/severity-mapping.test.d.ts.map +1 -0
- package/dist/framework/__tests__/severity-mapping.test.js +42 -0
- package/dist/framework/__tests__/severity-mapping.test.js.map +1 -0
- package/dist/framework/__tests__/strip-literals.test.d.ts +2 -0
- package/dist/framework/__tests__/strip-literals.test.d.ts.map +1 -0
- package/dist/framework/__tests__/strip-literals.test.js +87 -0
- package/dist/framework/__tests__/strip-literals.test.js.map +1 -0
- package/dist/framework/abortable-exec.d.ts +34 -0
- package/dist/framework/abortable-exec.d.ts.map +1 -0
- package/dist/framework/abortable-exec.js +136 -0
- package/dist/framework/abortable-exec.js.map +1 -0
- package/dist/framework/ast-utilities.d.ts +41 -0
- package/dist/framework/ast-utilities.d.ts.map +1 -0
- package/dist/framework/ast-utilities.js +106 -0
- package/dist/framework/ast-utilities.js.map +1 -0
- package/dist/framework/check-config.d.ts +171 -0
- package/dist/framework/check-config.d.ts.map +1 -0
- package/dist/framework/check-config.js +114 -0
- package/dist/framework/check-config.js.map +1 -0
- package/dist/framework/check-types.d.ts +57 -0
- package/dist/framework/check-types.d.ts.map +1 -0
- package/dist/framework/check-types.js +35 -0
- package/dist/framework/check-types.js.map +1 -0
- package/dist/framework/command-executor.d.ts +25 -0
- package/dist/framework/command-executor.d.ts.map +1 -0
- package/dist/framework/command-executor.js +63 -0
- package/dist/framework/command-executor.js.map +1 -0
- package/dist/framework/constants.d.ts +9 -0
- package/dist/framework/constants.d.ts.map +1 -0
- package/dist/framework/constants.js +16 -0
- package/dist/framework/constants.js.map +1 -0
- package/dist/framework/content-filter.d.ts +33 -0
- package/dist/framework/content-filter.d.ts.map +1 -0
- package/dist/framework/content-filter.js +236 -0
- package/dist/framework/content-filter.js.map +1 -0
- package/dist/framework/define-check.d.ts +38 -0
- package/dist/framework/define-check.d.ts.map +1 -0
- package/dist/framework/define-check.js +252 -0
- package/dist/framework/define-check.js.map +1 -0
- package/dist/framework/directive-inventory.d.ts +34 -0
- package/dist/framework/directive-inventory.d.ts.map +1 -0
- package/dist/framework/directive-inventory.js +77 -0
- package/dist/framework/directive-inventory.js.map +1 -0
- package/dist/framework/directive-parsing.d.ts +20 -0
- package/dist/framework/directive-parsing.d.ts.map +1 -0
- package/dist/framework/directive-parsing.js +121 -0
- package/dist/framework/directive-parsing.js.map +1 -0
- package/dist/framework/execution-context.d.ts +95 -0
- package/dist/framework/execution-context.d.ts.map +1 -0
- package/dist/framework/execution-context.js +122 -0
- package/dist/framework/execution-context.js.map +1 -0
- package/dist/framework/file-accessor.d.ts +20 -0
- package/dist/framework/file-accessor.d.ts.map +1 -0
- package/dist/framework/file-accessor.js +122 -0
- package/dist/framework/file-accessor.js.map +1 -0
- package/dist/framework/file-cache.d.ts +70 -0
- package/dist/framework/file-cache.d.ts.map +1 -0
- package/dist/framework/file-cache.js +178 -0
- package/dist/framework/file-cache.js.map +1 -0
- package/dist/framework/file-type-filter.d.ts +11 -0
- package/dist/framework/file-type-filter.d.ts.map +1 -0
- package/dist/framework/file-type-filter.js +21 -0
- package/dist/framework/file-type-filter.js.map +1 -0
- package/dist/framework/ignore-processing.d.ts +22 -0
- package/dist/framework/ignore-processing.d.ts.map +1 -0
- package/dist/framework/ignore-processing.js +241 -0
- package/dist/framework/ignore-processing.js.map +1 -0
- package/dist/framework/import-graph.d.ts +51 -0
- package/dist/framework/import-graph.d.ts.map +1 -0
- package/dist/framework/import-graph.js +216 -0
- package/dist/framework/import-graph.js.map +1 -0
- package/dist/framework/memory-profiler.d.ts +53 -0
- package/dist/framework/memory-profiler.d.ts.map +1 -0
- package/dist/framework/memory-profiler.js +92 -0
- package/dist/framework/memory-profiler.js.map +1 -0
- package/dist/framework/parse-cache.d.ts +23 -0
- package/dist/framework/parse-cache.d.ts.map +1 -0
- package/dist/framework/parse-cache.js +37 -0
- package/dist/framework/parse-cache.js.map +1 -0
- package/dist/framework/path-matcher.d.ts +86 -0
- package/dist/framework/path-matcher.d.ts.map +1 -0
- package/dist/framework/path-matcher.js +138 -0
- package/dist/framework/path-matcher.js.map +1 -0
- package/dist/framework/register-helpers.d.ts +10 -0
- package/dist/framework/register-helpers.d.ts.map +1 -0
- package/dist/framework/register-helpers.js +17 -0
- package/dist/framework/register-helpers.js.map +1 -0
- package/dist/framework/registry.d.ts +41 -0
- package/dist/framework/registry.d.ts.map +1 -0
- package/dist/framework/registry.js +103 -0
- package/dist/framework/registry.js.map +1 -0
- package/dist/framework/result-builder.d.ts +74 -0
- package/dist/framework/result-builder.d.ts.map +1 -0
- package/dist/framework/result-builder.js +154 -0
- package/dist/framework/result-builder.js.map +1 -0
- package/dist/framework/scope-resolver.d.ts +23 -0
- package/dist/framework/scope-resolver.d.ts.map +1 -0
- package/dist/framework/scope-resolver.js +201 -0
- package/dist/framework/scope-resolver.js.map +1 -0
- package/dist/framework/severity-mapping.d.ts +13 -0
- package/dist/framework/severity-mapping.d.ts.map +1 -0
- package/dist/framework/severity-mapping.js +51 -0
- package/dist/framework/severity-mapping.js.map +1 -0
- package/dist/framework/strip-literals.d.ts +48 -0
- package/dist/framework/strip-literals.d.ts.map +1 -0
- package/dist/framework/strip-literals.js +188 -0
- package/dist/framework/strip-literals.js.map +1 -0
- package/dist/gate.d.ts +74 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +257 -0
- package/dist/gate.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/__tests__/check-package-discovery.test.d.ts +2 -0
- package/dist/plugins/__tests__/check-package-discovery.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/check-package-discovery.test.js +170 -0
- package/dist/plugins/__tests__/check-package-discovery.test.js.map +1 -0
- package/dist/plugins/__tests__/lang-domain.test.d.ts +2 -0
- package/dist/plugins/__tests__/lang-domain.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/lang-domain.test.js +171 -0
- package/dist/plugins/__tests__/lang-domain.test.js.map +1 -0
- package/dist/plugins/__tests__/loader.test.d.ts +2 -0
- package/dist/plugins/__tests__/loader.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/loader.test.js +194 -0
- package/dist/plugins/__tests__/loader.test.js.map +1 -0
- package/dist/plugins/check-package-discovery.d.ts +73 -0
- package/dist/plugins/check-package-discovery.d.ts.map +1 -0
- package/dist/plugins/check-package-discovery.js +212 -0
- package/dist/plugins/check-package-discovery.js.map +1 -0
- package/dist/plugins/loader.d.ts +31 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +290 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/types.d.ts +23 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +9 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/recipes/__tests__/built-in-recipes.test.d.ts +2 -0
- package/dist/recipes/__tests__/built-in-recipes.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/built-in-recipes.test.js +93 -0
- package/dist/recipes/__tests__/built-in-recipes.test.js.map +1 -0
- package/dist/recipes/__tests__/check-config.test.d.ts +5 -0
- package/dist/recipes/__tests__/check-config.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/check-config.test.js +37 -0
- package/dist/recipes/__tests__/check-config.test.js.map +1 -0
- package/dist/recipes/__tests__/check-resolution.test.d.ts +2 -0
- package/dist/recipes/__tests__/check-resolution.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/check-resolution.test.js +135 -0
- package/dist/recipes/__tests__/check-resolution.test.js.map +1 -0
- package/dist/recipes/__tests__/registry.test.d.ts +2 -0
- package/dist/recipes/__tests__/registry.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/registry.test.js +97 -0
- package/dist/recipes/__tests__/registry.test.js.map +1 -0
- package/dist/recipes/__tests__/retry.test.d.ts +2 -0
- package/dist/recipes/__tests__/retry.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/retry.test.js +75 -0
- package/dist/recipes/__tests__/retry.test.js.map +1 -0
- package/dist/recipes/__tests__/service.test.d.ts +11 -0
- package/dist/recipes/__tests__/service.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/service.test.js +482 -0
- package/dist/recipes/__tests__/service.test.js.map +1 -0
- package/dist/recipes/built-in-recipes.d.ts +14 -0
- package/dist/recipes/built-in-recipes.d.ts.map +1 -0
- package/dist/recipes/built-in-recipes.js +247 -0
- package/dist/recipes/built-in-recipes.js.map +1 -0
- package/dist/recipes/check-config.d.ts +40 -0
- package/dist/recipes/check-config.d.ts.map +1 -0
- package/dist/recipes/check-config.js +61 -0
- package/dist/recipes/check-config.js.map +1 -0
- package/dist/recipes/check-resolution.d.ts +21 -0
- package/dist/recipes/check-resolution.d.ts.map +1 -0
- package/dist/recipes/check-resolution.js +121 -0
- package/dist/recipes/check-resolution.js.map +1 -0
- package/dist/recipes/check-result-processor.d.ts +51 -0
- package/dist/recipes/check-result-processor.d.ts.map +1 -0
- package/dist/recipes/check-result-processor.js +158 -0
- package/dist/recipes/check-result-processor.js.map +1 -0
- package/dist/recipes/parallel-execution.d.ts +33 -0
- package/dist/recipes/parallel-execution.d.ts.map +1 -0
- package/dist/recipes/parallel-execution.js +142 -0
- package/dist/recipes/parallel-execution.js.map +1 -0
- package/dist/recipes/registry.d.ts +81 -0
- package/dist/recipes/registry.d.ts.map +1 -0
- package/dist/recipes/registry.js +131 -0
- package/dist/recipes/registry.js.map +1 -0
- package/dist/recipes/retry.d.ts +25 -0
- package/dist/recipes/retry.d.ts.map +1 -0
- package/dist/recipes/retry.js +44 -0
- package/dist/recipes/retry.js.map +1 -0
- package/dist/recipes/sequential-execution.d.ts +10 -0
- package/dist/recipes/sequential-execution.d.ts.map +1 -0
- package/dist/recipes/sequential-execution.js +122 -0
- package/dist/recipes/sequential-execution.js.map +1 -0
- package/dist/recipes/service-types.d.ts +84 -0
- package/dist/recipes/service-types.d.ts.map +1 -0
- package/dist/recipes/service-types.js +8 -0
- package/dist/recipes/service-types.js.map +1 -0
- package/dist/recipes/service.d.ts +71 -0
- package/dist/recipes/service.d.ts.map +1 -0
- package/dist/recipes/service.js +331 -0
- package/dist/recipes/service.js.map +1 -0
- package/dist/recipes/types.d.ts +154 -0
- package/dist/recipes/types.d.ts.map +1 -0
- package/dist/recipes/types.js +54 -0
- package/dist/recipes/types.js.map +1 -0
- package/dist/sarif.d.ts +34 -0
- package/dist/sarif.d.ts.map +1 -0
- package/dist/sarif.js +192 -0
- package/dist/sarif.js.map +1 -0
- package/dist/signalers/__tests__/loader.test.d.ts +2 -0
- package/dist/signalers/__tests__/loader.test.d.ts.map +1 -0
- package/dist/signalers/__tests__/loader.test.js +74 -0
- package/dist/signalers/__tests__/loader.test.js.map +1 -0
- package/dist/signalers/index.d.ts +8 -0
- package/dist/signalers/index.d.ts.map +1 -0
- package/dist/signalers/index.js +9 -0
- package/dist/signalers/index.js.map +1 -0
- package/dist/signalers/loader.d.ts +24 -0
- package/dist/signalers/loader.d.ts.map +1 -0
- package/dist/signalers/loader.js +108 -0
- package/dist/signalers/loader.js.map +1 -0
- package/dist/signalers/schema.d.ts +288 -0
- package/dist/signalers/schema.d.ts.map +1 -0
- package/dist/signalers/schema.js +99 -0
- package/dist/signalers/schema.js.map +1 -0
- package/dist/signalers/types.d.ts +13 -0
- package/dist/signalers/types.d.ts.map +1 -0
- package/dist/signalers/types.js +5 -0
- package/dist/signalers/types.js.map +1 -0
- package/dist/targets/__tests__/loader.test.d.ts +2 -0
- package/dist/targets/__tests__/loader.test.d.ts.map +1 -0
- package/dist/targets/__tests__/loader.test.js +127 -0
- package/dist/targets/__tests__/loader.test.js.map +1 -0
- package/dist/targets/__tests__/resolver.test.d.ts +2 -0
- package/dist/targets/__tests__/resolver.test.d.ts.map +1 -0
- package/dist/targets/__tests__/resolver.test.js +54 -0
- package/dist/targets/__tests__/resolver.test.js.map +1 -0
- package/dist/targets/__tests__/target-registry.test.d.ts +2 -0
- package/dist/targets/__tests__/target-registry.test.d.ts.map +1 -0
- package/dist/targets/__tests__/target-registry.test.js +89 -0
- package/dist/targets/__tests__/target-registry.test.js.map +1 -0
- package/dist/targets/index.d.ts +10 -0
- package/dist/targets/index.d.ts.map +1 -0
- package/dist/targets/index.js +12 -0
- package/dist/targets/index.js.map +1 -0
- package/dist/targets/loader.d.ts +19 -0
- package/dist/targets/loader.d.ts.map +1 -0
- package/dist/targets/loader.js +159 -0
- package/dist/targets/loader.js.map +1 -0
- package/dist/targets/resolver.d.ts +19 -0
- package/dist/targets/resolver.d.ts.map +1 -0
- package/dist/targets/resolver.js +37 -0
- package/dist/targets/resolver.js.map +1 -0
- package/dist/targets/target-registry.d.ts +61 -0
- package/dist/targets/target-registry.d.ts.map +1 -0
- package/dist/targets/target-registry.js +93 -0
- package/dist/targets/target-registry.js.map +1 -0
- package/dist/targets/types.d.ts +85 -0
- package/dist/targets/types.d.ts.map +1 -0
- package/dist/targets/types.js +5 -0
- package/dist/targets/types.js.map +1 -0
- package/dist/tool.d.ts +17 -0
- package/dist/tool.d.ts.map +1 -0
- package/dist/tool.js +282 -0
- package/dist/tool.js.map +1 -0
- package/dist/types/findings.d.ts +117 -0
- package/dist/types/findings.d.ts.map +1 -0
- package/dist/types/findings.js +93 -0
- package/dist/types/findings.js.map +1 -0
- package/dist/types/severity.d.ts +15 -0
- package/dist/types/severity.d.ts.map +1 -0
- package/dist/types/severity.js +36 -0
- package/dist/types/severity.js.map +1 -0
- package/package.json +45 -0
- package/src/__tests__/gate.test.ts +537 -0
- package/src/__tests__/sarif.test.ts +201 -0
- package/src/cli/dashboard.ts +93 -0
- package/src/cli/fit.ts +612 -0
- package/src/cli/list-checks.ts +32 -0
- package/src/cli/list-recipes.ts +38 -0
- package/src/framework/__tests__/ast-utilities.test.ts +157 -0
- package/src/framework/__tests__/check-config.test.ts +65 -0
- package/src/framework/__tests__/command-executor.test.ts +79 -0
- package/src/framework/__tests__/content-filter-dispatch.test.ts +132 -0
- package/src/framework/__tests__/content-filter.test.ts +136 -0
- package/src/framework/__tests__/define-check.test.ts +180 -0
- package/src/framework/__tests__/directive-inventory.test.ts +53 -0
- package/src/framework/__tests__/execution-context.test.ts +80 -0
- package/src/framework/__tests__/file-accessor.test.ts +121 -0
- package/src/framework/__tests__/file-cache.test.ts +142 -0
- package/src/framework/__tests__/import-graph.test.ts +282 -0
- package/src/framework/__tests__/path-matcher.test.ts +130 -0
- package/src/framework/__tests__/register-helpers.test.ts +51 -0
- package/src/framework/__tests__/registry.test.ts +243 -0
- package/src/framework/__tests__/result-builder.test.ts +178 -0
- package/src/framework/__tests__/scope-resolver.test.ts +208 -0
- package/src/framework/__tests__/severity-mapping.test.ts +50 -0
- package/src/framework/__tests__/strip-literals.test.ts +109 -0
- package/src/framework/abortable-exec.ts +177 -0
- package/src/framework/ast-utilities.ts +112 -0
- package/src/framework/check-config.ts +339 -0
- package/src/framework/check-types.ts +77 -0
- package/src/framework/command-executor.ts +100 -0
- package/src/framework/constants.ts +16 -0
- package/src/framework/content-filter.ts +288 -0
- package/src/framework/define-check.ts +336 -0
- package/src/framework/directive-inventory.ts +110 -0
- package/src/framework/directive-parsing.ts +152 -0
- package/src/framework/execution-context.ts +247 -0
- package/src/framework/file-accessor.ts +171 -0
- package/src/framework/file-cache.ts +220 -0
- package/src/framework/file-type-filter.ts +25 -0
- package/src/framework/ignore-processing.ts +350 -0
- package/src/framework/import-graph.ts +280 -0
- package/src/framework/memory-profiler.ts +145 -0
- package/src/framework/parse-cache.ts +38 -0
- package/src/framework/path-matcher.ts +191 -0
- package/src/framework/register-helpers.ts +20 -0
- package/src/framework/registry.ts +125 -0
- package/src/framework/result-builder.ts +225 -0
- package/src/framework/scope-resolver.ts +262 -0
- package/src/framework/severity-mapping.ts +56 -0
- package/src/framework/strip-literals.ts +200 -0
- package/src/gate.ts +337 -0
- package/src/index.ts +110 -0
- package/src/plugins/__tests__/check-package-discovery.test.ts +204 -0
- package/src/plugins/__tests__/lang-domain.test.ts +198 -0
- package/src/plugins/__tests__/loader.test.ts +226 -0
- package/src/plugins/check-package-discovery.ts +242 -0
- package/src/plugins/loader.ts +327 -0
- package/src/plugins/types.ts +25 -0
- package/src/recipes/__tests__/built-in-recipes.test.ts +107 -0
- package/src/recipes/__tests__/check-config.test.ts +51 -0
- package/src/recipes/__tests__/check-resolution.test.ts +185 -0
- package/src/recipes/__tests__/registry.test.ts +115 -0
- package/src/recipes/__tests__/retry.test.ts +83 -0
- package/src/recipes/__tests__/service.test.ts +572 -0
- package/src/recipes/built-in-recipes.ts +273 -0
- package/src/recipes/check-config.ts +64 -0
- package/src/recipes/check-resolution.ts +169 -0
- package/src/recipes/check-result-processor.ts +258 -0
- package/src/recipes/parallel-execution.ts +220 -0
- package/src/recipes/registry.ts +192 -0
- package/src/recipes/retry.ts +69 -0
- package/src/recipes/sequential-execution.ts +139 -0
- package/src/recipes/service-types.ts +105 -0
- package/src/recipes/service.ts +400 -0
- package/src/recipes/types.ts +247 -0
- package/src/sarif.ts +232 -0
- package/src/signalers/__tests__/loader.test.ts +99 -0
- package/src/signalers/index.ts +9 -0
- package/src/signalers/loader.ts +141 -0
- package/src/signalers/schema.ts +117 -0
- package/src/signalers/types.ts +15 -0
- package/src/targets/__tests__/loader.test.ts +170 -0
- package/src/targets/__tests__/resolver.test.ts +74 -0
- package/src/targets/__tests__/target-registry.test.ts +103 -0
- package/src/targets/index.ts +13 -0
- package/src/targets/loader.ts +214 -0
- package/src/targets/resolver.ts +44 -0
- package/src/targets/target-registry.ts +111 -0
- package/src/targets/types.ts +89 -0
- package/src/tool.ts +302 -0
- package/src/types/findings.ts +239 -0
- package/src/types/severity.ts +39 -0
- package/tsconfig.json +8 -0
- package/vitest.config.ts +33 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check registry — central registration and discovery.
|
|
3
|
+
*
|
|
4
|
+
* Supports namespaced slugs: checks are stored as `namespace:slug` when
|
|
5
|
+
* a namespace is provided. Bare slug lookups resolve via a reverse index,
|
|
6
|
+
* with a warning logged on ambiguity.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { NotFoundError , logger } from '@opensip-tools/core';
|
|
10
|
+
|
|
11
|
+
import type { Check } from './check-types.js';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export class CheckRegistry {
|
|
16
|
+
/** Primary store: key is `namespace:slug` or bare `slug` */
|
|
17
|
+
private readonly checks = new Map<string, Check>();
|
|
18
|
+
/** Reverse index: bare slug → list of namespaced keys */
|
|
19
|
+
private readonly bareSlugIndex = new Map<string, string[]>();
|
|
20
|
+
|
|
21
|
+
register(check: Check, namespace?: string): void {
|
|
22
|
+
const bareSlug = check.config.slug;
|
|
23
|
+
const key = namespace ? `${namespace}:${bareSlug}` : bareSlug;
|
|
24
|
+
|
|
25
|
+
if (this.checks.has(key)) {
|
|
26
|
+
// Silently skip duplicate — same check imported multiple times
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.checks.set(key, check);
|
|
31
|
+
|
|
32
|
+
// Update bare slug index
|
|
33
|
+
const existing = this.bareSlugIndex.get(bareSlug) ?? [];
|
|
34
|
+
existing.push(key);
|
|
35
|
+
this.bareSlugIndex.set(bareSlug, existing);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Get a check by slug. Supports both namespaced and bare slugs. */
|
|
39
|
+
get(slug: string): Check {
|
|
40
|
+
const check = this.resolve(slug);
|
|
41
|
+
if (!check) throw new NotFoundError(`Check not found: ${slug}`);
|
|
42
|
+
return check;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Check whether a slug is registered (namespaced or bare). */
|
|
46
|
+
has(slug: string): boolean {
|
|
47
|
+
return this.resolve(slug) !== undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
list(): Check[] {
|
|
51
|
+
return [...this.checks.values()];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Get the namespace a check was registered under. Returns undefined for bare slugs. */
|
|
55
|
+
getNamespace(bareSlug: string): string | undefined {
|
|
56
|
+
const keys = this.bareSlugIndex.get(bareSlug);
|
|
57
|
+
if (!keys || keys.length === 0) return undefined;
|
|
58
|
+
const key = keys[0];
|
|
59
|
+
const colonIdx = key.indexOf(':');
|
|
60
|
+
return colonIdx === -1 ? undefined : key.slice(0, colonIdx);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
listEnabled(): Check[] {
|
|
64
|
+
return this.list().filter(c => !c.config.disabled);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
byTag(tag: string): Check[] {
|
|
68
|
+
return this.listEnabled().filter(c => c.config.tags?.includes(tag));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Get a check by slug, returning undefined if not found. */
|
|
72
|
+
getBySlug(slug: string): Check | undefined {
|
|
73
|
+
return this.resolve(slug);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Return all registered keys (namespaced where applicable). */
|
|
77
|
+
listSlugs(): string[] {
|
|
78
|
+
return [...this.checks.keys()];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Return all checks with a given bare slug across all namespaces. */
|
|
82
|
+
listByBareSlug(bareSlug: string): Check[] {
|
|
83
|
+
const keys = this.bareSlugIndex.get(bareSlug) ?? [];
|
|
84
|
+
return keys.map(k => this.checks.get(k)).filter((c): c is Check => c !== undefined);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get size(): number {
|
|
88
|
+
return this.checks.size;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Resolve a slug to a Check.
|
|
93
|
+
* - If slug contains ':', exact lookup.
|
|
94
|
+
* - If bare slug, use reverse index. Single match → return. Multiple → warn + return first.
|
|
95
|
+
*/
|
|
96
|
+
private resolve(slug: string): Check | undefined {
|
|
97
|
+
// Exact match (namespaced or bare)
|
|
98
|
+
const exact = this.checks.get(slug);
|
|
99
|
+
if (exact) return exact;
|
|
100
|
+
|
|
101
|
+
// If it contains ':', it was a namespaced lookup that didn't match
|
|
102
|
+
if (slug.includes(':')) return undefined;
|
|
103
|
+
|
|
104
|
+
// Bare slug → reverse index
|
|
105
|
+
const candidates = this.bareSlugIndex.get(slug);
|
|
106
|
+
if (!candidates || candidates.length === 0) return undefined;
|
|
107
|
+
|
|
108
|
+
if (candidates.length > 1) {
|
|
109
|
+
logger.warn({
|
|
110
|
+
evt: 'plugin.registry.collision',
|
|
111
|
+
module: 'core:registry',
|
|
112
|
+
bareSlug: slug,
|
|
113
|
+
candidates,
|
|
114
|
+
msg: `Ambiguous slug '${slug}' matches ${candidates.length} checks — using first registered`,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return this.checks.get(candidates[0]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Default global registry — checks auto-register here on import */
|
|
123
|
+
export const defaultRegistry = new CheckRegistry();
|
|
124
|
+
|
|
125
|
+
export {type Check} from './check-types.js';
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview ResultBuilder - Builder pattern for check results
|
|
3
|
+
*
|
|
4
|
+
* Provides a fluent API for constructing check results with signals,
|
|
5
|
+
* metadata, and display information.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
CheckInfoFactory,
|
|
11
|
+
createResultWithSignals,
|
|
12
|
+
createErrorResult,
|
|
13
|
+
getItemTypeLabel,
|
|
14
|
+
} from '../types/findings.js'
|
|
15
|
+
import { countErrors, countWarnings } from '../types/severity.js'
|
|
16
|
+
|
|
17
|
+
import type {
|
|
18
|
+
CheckResult,
|
|
19
|
+
CheckInfo,
|
|
20
|
+
ItemType,
|
|
21
|
+
} from '../types/findings.js'
|
|
22
|
+
import type { Signal } from '@opensip-tools/core'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Options for building results.
|
|
26
|
+
*/
|
|
27
|
+
export interface ResultBuilderOptions {
|
|
28
|
+
/** Check ID */
|
|
29
|
+
readonly checkId: string
|
|
30
|
+
/** Item type for display (files, modules, etc.) */
|
|
31
|
+
readonly itemType: ItemType
|
|
32
|
+
/** Custom unit label (overrides itemType) */
|
|
33
|
+
readonly unit?: string | undefined
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Builder for constructing check results.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const result = ResultBuilder.create({ checkId: 'my-check', itemType: 'files' })
|
|
42
|
+
* .totalItems(100)
|
|
43
|
+
* .addSignal(signal1)
|
|
44
|
+
* .build();
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export class ResultBuilder {
|
|
48
|
+
private _totalItems = 0
|
|
49
|
+
private readonly _signals: Signal[] = []
|
|
50
|
+
private _ignoredCount = 0
|
|
51
|
+
private _durationMs?: number
|
|
52
|
+
private _filesScanned?: number
|
|
53
|
+
private _extra?: Record<string, unknown>
|
|
54
|
+
|
|
55
|
+
private constructor(private readonly options: ResultBuilderOptions) {}
|
|
56
|
+
|
|
57
|
+
static create(
|
|
58
|
+
options: ResultBuilderOptions,
|
|
59
|
+
): ResultBuilder {
|
|
60
|
+
return new ResultBuilder(options)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
totalItems(count: number): this {
|
|
64
|
+
this._totalItems = count
|
|
65
|
+
return this
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
filesScanned(count: number): this {
|
|
69
|
+
this._filesScanned = count
|
|
70
|
+
return this
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
addSignal(signal: Signal): this {
|
|
74
|
+
this._signals.push(signal)
|
|
75
|
+
return this
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
addSignals(signals: readonly Signal[]): this {
|
|
79
|
+
if (signals.length === 0) {
|
|
80
|
+
return this
|
|
81
|
+
}
|
|
82
|
+
this._signals.push(...signals)
|
|
83
|
+
return this
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ignoredCount(count: number): this {
|
|
87
|
+
this._ignoredCount = count
|
|
88
|
+
return this
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
incrementIgnored(by = 1): this {
|
|
92
|
+
this._ignoredCount += by
|
|
93
|
+
return this
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
duration(ms: number): this {
|
|
97
|
+
this._durationMs = ms
|
|
98
|
+
return this
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
extra(data: Record<string, unknown>): this {
|
|
102
|
+
this._extra = { ...this._extra, ...data }
|
|
103
|
+
return this
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
build(): CheckResult {
|
|
107
|
+
const unit = this.options.unit ?? this.options.itemType
|
|
108
|
+
const errors = countErrors(this._signals)
|
|
109
|
+
const warnings = countWarnings(this._signals)
|
|
110
|
+
|
|
111
|
+
const info = this.buildInfo(errors, warnings, unit)
|
|
112
|
+
|
|
113
|
+
const buildOptions: {
|
|
114
|
+
ignoredCount?: number
|
|
115
|
+
durationMs?: number
|
|
116
|
+
filesScanned?: number
|
|
117
|
+
itemType?: string
|
|
118
|
+
extra?: Record<string, unknown>
|
|
119
|
+
} = {}
|
|
120
|
+
|
|
121
|
+
if (this._ignoredCount > 0) {
|
|
122
|
+
buildOptions.ignoredCount = this._ignoredCount
|
|
123
|
+
}
|
|
124
|
+
if (this._durationMs !== undefined) {
|
|
125
|
+
buildOptions.durationMs = this._durationMs
|
|
126
|
+
}
|
|
127
|
+
if (this._filesScanned !== undefined) {
|
|
128
|
+
buildOptions.filesScanned = this._filesScanned
|
|
129
|
+
}
|
|
130
|
+
buildOptions.itemType = this.options.itemType
|
|
131
|
+
if (this._extra !== undefined) {
|
|
132
|
+
buildOptions.extra = this._extra
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return createResultWithSignals(
|
|
136
|
+
info,
|
|
137
|
+
this._signals,
|
|
138
|
+
this._totalItems,
|
|
139
|
+
Object.keys(buildOptions).length > 0 ? buildOptions : undefined,
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
buildError(message: string, error?: Error): CheckResult {
|
|
144
|
+
return createErrorResult(message, error)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private buildInfo(errors: number, warnings: number, unit: string): CheckInfo {
|
|
148
|
+
if (this._totalItems > 0) {
|
|
149
|
+
// Clamp to 0: analyzeAll-mode checks can surface violations against
|
|
150
|
+
// files outside the scanned set, which would otherwise produce a
|
|
151
|
+
// negative "-N/M compliant" label.
|
|
152
|
+
const compliantItems = Math.max(0, this._totalItems - this.getUniqueFileCount())
|
|
153
|
+
return CheckInfoFactory.compliance(compliantItems, this._totalItems, unit)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const total = errors + warnings
|
|
157
|
+
return CheckInfoFactory.violations(total, getItemTypeLabel('violations', total))
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private getUniqueFileCount(): number {
|
|
161
|
+
const files = new Set(this._signals.map((s) => s.code?.file).filter(Boolean))
|
|
162
|
+
return files.size
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
get signalCount(): number {
|
|
166
|
+
return this._signals.length
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
get errorCount(): number {
|
|
170
|
+
return countErrors(this._signals)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
get warningCount(): number {
|
|
174
|
+
return countWarnings(this._signals)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
get hasSignals(): boolean {
|
|
178
|
+
return this._signals.length > 0
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
get willPass(): boolean {
|
|
182
|
+
return this.errorCount === 0
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// =============================================================================
|
|
187
|
+
// SNIPPET UTILITIES
|
|
188
|
+
// =============================================================================
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Extract a code snippet with context lines around a target line.
|
|
192
|
+
*/
|
|
193
|
+
export function extractSnippet(
|
|
194
|
+
content: string,
|
|
195
|
+
line: number,
|
|
196
|
+
contextLines = 2,
|
|
197
|
+
): { snippet: string; contextLines: number } {
|
|
198
|
+
const lines = content.split('\n')
|
|
199
|
+
const startLine = Math.max(0, line - 1 - contextLines)
|
|
200
|
+
const endLine = Math.min(lines.length, line + contextLines)
|
|
201
|
+
const snippetLines = lines.slice(startLine, endLine)
|
|
202
|
+
const snippet = snippetLines.map((l, i) => `${startLine + i + 1} | ${l}`).join('\n')
|
|
203
|
+
return { snippet, contextLines }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Get line number from content string and character index.
|
|
208
|
+
*/
|
|
209
|
+
export function getLineNumber(content: string, index: number): number {
|
|
210
|
+
return content.slice(0, Math.max(0, index)).split('\n').length
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Default patterns for identifying API-related files.
|
|
215
|
+
*/
|
|
216
|
+
const DEFAULT_API_FILE_PATTERNS = ['/api/', '/routes/', '-handler.ts', '.handler.ts'] as const
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Check if a file path matches API file patterns.
|
|
220
|
+
*/
|
|
221
|
+
export function isAPIFile(filePath: string): boolean {
|
|
222
|
+
return DEFAULT_API_FILE_PATTERNS.some((pattern) =>
|
|
223
|
+
pattern.startsWith('/') ? filePath.includes(pattern) : filePath.endsWith(pattern),
|
|
224
|
+
)
|
|
225
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Scope-based file resolution for fitness checks
|
|
3
|
+
*
|
|
4
|
+
* Checks declare intent (languages + concerns), targets declare reality
|
|
5
|
+
* (languages + concerns + globs), and this module resolves the match.
|
|
6
|
+
*
|
|
7
|
+
* Performance: all targets are globbed once upfront in buildScopeBasedFileMap.
|
|
8
|
+
* Per-check resolution is a pure in-memory lookup — no redundant I/O.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { relative, resolve } from 'node:path'
|
|
12
|
+
|
|
13
|
+
import { globSync } from 'glob'
|
|
14
|
+
import { minimatch, Minimatch } from 'minimatch'
|
|
15
|
+
|
|
16
|
+
import type { CheckScope } from './check-config.js'
|
|
17
|
+
import type { TargetRegistry } from '../targets/target-registry.js'
|
|
18
|
+
import type { Target, TargetsConfig } from '../targets/types.js'
|
|
19
|
+
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// Pre-resolved target file cache
|
|
22
|
+
// =============================================================================
|
|
23
|
+
|
|
24
|
+
/** Assemble a single target's file list from pre-resolved pattern results, applying excludes. */
|
|
25
|
+
function assembleTargetFiles(
|
|
26
|
+
targetConfig: { include: readonly string[]; exclude: readonly string[]; name: string },
|
|
27
|
+
patternResults: Map<string, readonly string[]>,
|
|
28
|
+
compiledGlobalExcludes: Minimatch[],
|
|
29
|
+
rootDir: string,
|
|
30
|
+
): readonly string[] {
|
|
31
|
+
const files = new Set<string>()
|
|
32
|
+
for (const pattern of targetConfig.include) {
|
|
33
|
+
const matches = patternResults.get(pattern) ?? []
|
|
34
|
+
for (const match of matches) {
|
|
35
|
+
files.add(match)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (targetConfig.exclude.length > 0 || compiledGlobalExcludes.length > 0) {
|
|
40
|
+
const compiledTargetExcludes = targetConfig.exclude.map((ex) => new Minimatch(ex, { dot: true }))
|
|
41
|
+
const allExcludes = [...compiledTargetExcludes, ...compiledGlobalExcludes]
|
|
42
|
+
for (const filePath of files) {
|
|
43
|
+
const rel = relative(rootDir, filePath)
|
|
44
|
+
if (allExcludes.some((m) => m.match(rel))) {
|
|
45
|
+
files.delete(filePath)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return [...files].sort()
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Collect all unique glob patterns and ignore patterns from all targets,
|
|
55
|
+
* run a single deduplicated glob pass, then partition results per target.
|
|
56
|
+
*
|
|
57
|
+
* This avoids redundant filesystem traversals when targets share common
|
|
58
|
+
* patterns (e.g. multiple targets including "packages/star/src/starstar/star.ts").
|
|
59
|
+
*/
|
|
60
|
+
function preResolveAllTargets(
|
|
61
|
+
registry: TargetRegistry,
|
|
62
|
+
config: TargetsConfig,
|
|
63
|
+
rootDir: string,
|
|
64
|
+
): Map<string, readonly string[]> {
|
|
65
|
+
const targets = registry.getAll()
|
|
66
|
+
if (targets.length === 0) return new Map()
|
|
67
|
+
|
|
68
|
+
// Collect all unique include patterns across targets
|
|
69
|
+
const allPatterns = new Set<string>()
|
|
70
|
+
for (const target of targets) {
|
|
71
|
+
for (const pattern of target.config.include) {
|
|
72
|
+
allPatterns.add(pattern)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Single glob pass for each unique pattern — deduplicated across targets.
|
|
77
|
+
// Common infrastructure dirs are always ignored to prevent expensive traversals.
|
|
78
|
+
const COMMON_IGNORE = ['**/node_modules/**', '**/dist/**', '**/.git/**']
|
|
79
|
+
const patternResults = new Map<string, readonly string[]>()
|
|
80
|
+
for (const pattern of allPatterns) {
|
|
81
|
+
const matches = globSync(pattern, {
|
|
82
|
+
cwd: rootDir,
|
|
83
|
+
absolute: true,
|
|
84
|
+
nodir: true,
|
|
85
|
+
ignore: COMMON_IGNORE,
|
|
86
|
+
})
|
|
87
|
+
patternResults.set(pattern, matches.map((m) => resolve(m)))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Pre-compile globalExcludes matchers for reuse across all targets
|
|
91
|
+
const { globalExcludes } = config
|
|
92
|
+
const compiledExcludes = globalExcludes.map((pattern) => new Minimatch(pattern, { dot: true }))
|
|
93
|
+
|
|
94
|
+
// Assemble per-target file lists by combining pattern results and filtering excludes.
|
|
95
|
+
// Both target-specific excludes AND globalExcludes are applied here so that
|
|
96
|
+
// per-check resolution is a pure in-memory lookup with no minimatch calls.
|
|
97
|
+
const result = new Map<string, readonly string[]>()
|
|
98
|
+
for (const target of targets) {
|
|
99
|
+
const files = assembleTargetFiles(
|
|
100
|
+
{ include: target.config.include, exclude: target.config.exclude, name: target.config.name },
|
|
101
|
+
patternResults, compiledExcludes, rootDir,
|
|
102
|
+
)
|
|
103
|
+
result.set(target.config.name, files)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return result
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Resolve a single target's include/exclude globs to absolute file paths.
|
|
111
|
+
* Used by the resolveFilesForCheck fallback path (single-check mode).
|
|
112
|
+
*/
|
|
113
|
+
function resolveTargetGlobs(target: Target, rootDir: string): string[] {
|
|
114
|
+
const files = new Set<string>()
|
|
115
|
+
const { include, exclude } = target.config
|
|
116
|
+
|
|
117
|
+
for (const pattern of include) {
|
|
118
|
+
const matches = globSync(pattern, {
|
|
119
|
+
cwd: rootDir,
|
|
120
|
+
ignore: [...exclude],
|
|
121
|
+
absolute: true,
|
|
122
|
+
})
|
|
123
|
+
for (const match of matches) {
|
|
124
|
+
files.add(resolve(match))
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return [...files].sort()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Look up pre-resolved files for a set of target names, union and deduplicate.
|
|
133
|
+
*/
|
|
134
|
+
function unionTargetFiles(
|
|
135
|
+
targetNames: readonly string[],
|
|
136
|
+
resolvedTargets: Map<string, readonly string[]>,
|
|
137
|
+
): string[] {
|
|
138
|
+
if (targetNames.length === 1) {
|
|
139
|
+
return [...(resolvedTargets.get(targetNames[0]) ?? [])]
|
|
140
|
+
}
|
|
141
|
+
const files = new Set<string>()
|
|
142
|
+
for (const name of targetNames) {
|
|
143
|
+
const targetFiles = resolvedTargets.get(name)
|
|
144
|
+
if (targetFiles) {
|
|
145
|
+
for (const f of targetFiles) files.add(f)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return [...files].sort()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// =============================================================================
|
|
152
|
+
// Global excludes
|
|
153
|
+
// =============================================================================
|
|
154
|
+
|
|
155
|
+
function applyGlobalExcludes(
|
|
156
|
+
files: readonly string[],
|
|
157
|
+
rootDir: string,
|
|
158
|
+
globalExcludes: readonly string[],
|
|
159
|
+
): readonly string[] {
|
|
160
|
+
if (globalExcludes.length === 0) return files
|
|
161
|
+
|
|
162
|
+
return files.filter((filePath) => {
|
|
163
|
+
const relativePath = relative(rootDir, filePath)
|
|
164
|
+
return !globalExcludes.some((pattern) => minimatch(relativePath, pattern, { dot: true }))
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// =============================================================================
|
|
169
|
+
// Per-check resolution (pure in-memory, no I/O)
|
|
170
|
+
// =============================================================================
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Resolve file paths for a single check using pre-resolved target files.
|
|
174
|
+
*
|
|
175
|
+
* Resolution order:
|
|
176
|
+
* 1. If checkOverrides has an entry for this slug, use those target(s) directly
|
|
177
|
+
* 2. If scope is declared, match against all targets by languages + concerns
|
|
178
|
+
* 3. If no scope and no override, return undefined (check uses file cache fallback)
|
|
179
|
+
*
|
|
180
|
+
* When pre-resolved targets are provided (from buildScopeBasedFileMap), globalExcludes
|
|
181
|
+
* have already been applied during pre-resolution and are skipped here.
|
|
182
|
+
* When called without pre-resolved targets (single-check fallback), globalExcludes
|
|
183
|
+
* are applied after direct globbing.
|
|
184
|
+
*/
|
|
185
|
+
function resolveFilesForCheck(
|
|
186
|
+
slug: string,
|
|
187
|
+
scope: CheckScope | undefined,
|
|
188
|
+
registry: TargetRegistry,
|
|
189
|
+
config: TargetsConfig,
|
|
190
|
+
rootDir: string,
|
|
191
|
+
resolvedTargets?: Map<string, readonly string[]>,
|
|
192
|
+
): readonly string[] | undefined {
|
|
193
|
+
const { globalExcludes, checkOverrides } = config
|
|
194
|
+
|
|
195
|
+
// When resolvedTargets is provided, globalExcludes are pre-applied — skip re-filtering
|
|
196
|
+
const maybeApplyExcludes = (files: readonly string[]): readonly string[] =>
|
|
197
|
+
resolvedTargets ? files : applyGlobalExcludes(files, rootDir, globalExcludes)
|
|
198
|
+
|
|
199
|
+
// Use pre-resolved cache when available, otherwise fall back to direct glob
|
|
200
|
+
const lookupFiles = (targetRef: string | readonly string[]): string[] => {
|
|
201
|
+
const names = typeof targetRef === 'string' ? [targetRef] : targetRef
|
|
202
|
+
if (resolvedTargets) {
|
|
203
|
+
return unionTargetFiles(names, resolvedTargets)
|
|
204
|
+
}
|
|
205
|
+
// Fallback: resolve directly (single-check mode without precomputed cache)
|
|
206
|
+
const targets = names
|
|
207
|
+
.map((name) => registry.getByName(name))
|
|
208
|
+
.filter((t): t is NonNullable<typeof t> => t !== undefined)
|
|
209
|
+
const files = new Set<string>()
|
|
210
|
+
for (const target of targets) {
|
|
211
|
+
for (const f of resolveTargetGlobs(target, rootDir)) files.add(f)
|
|
212
|
+
}
|
|
213
|
+
return [...files].sort()
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 1. Check overrides take priority (for marketplace/third-party checks)
|
|
217
|
+
const override = checkOverrides[slug]
|
|
218
|
+
if (override) {
|
|
219
|
+
return maybeApplyExcludes(lookupFiles(override))
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// 2. Scope-based matching
|
|
223
|
+
if (scope && (scope.languages.length > 0 || scope.concerns.length > 0)) {
|
|
224
|
+
const matchedTargets = registry.findByScope(scope.languages, scope.concerns)
|
|
225
|
+
if (matchedTargets.length === 0) {
|
|
226
|
+
return []
|
|
227
|
+
}
|
|
228
|
+
const names = matchedTargets.map((t) => t.config.name)
|
|
229
|
+
return maybeApplyExcludes(lookupFiles(names))
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 3. No scope, no override — undefined signals "use file cache fallback"
|
|
233
|
+
return undefined
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Build the complete check-to-files map for all checks with scopes or overrides.
|
|
238
|
+
*
|
|
239
|
+
* All targets are globbed once upfront. Per-check resolution is a pure
|
|
240
|
+
* in-memory lookup against the pre-resolved file lists.
|
|
241
|
+
*/
|
|
242
|
+
export function buildScopeBasedFileMap(
|
|
243
|
+
checks: readonly { slug: string; scope?: CheckScope }[],
|
|
244
|
+
registry: TargetRegistry,
|
|
245
|
+
config: TargetsConfig,
|
|
246
|
+
rootDir: string,
|
|
247
|
+
): Map<string, readonly string[]> {
|
|
248
|
+
// Pre-resolve all targets once — deduplicated glob pass across all targets.
|
|
249
|
+
// GlobalExcludes are applied during pre-resolution so per-check lookups are pure in-memory.
|
|
250
|
+
const resolvedTargets = preResolveAllTargets(registry, config, rootDir)
|
|
251
|
+
|
|
252
|
+
const result = new Map<string, readonly string[]>()
|
|
253
|
+
|
|
254
|
+
for (const check of checks) {
|
|
255
|
+
const files = resolveFilesForCheck(check.slug, check.scope, registry, config, rootDir, resolvedTargets)
|
|
256
|
+
if (files !== undefined) {
|
|
257
|
+
result.set(check.slug, files)
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return result
|
|
262
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// @fitness-ignore-file project-readme-existence -- internal module, not a package root
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Shared severity and category mapping for fitness checks
|
|
4
|
+
*
|
|
5
|
+
* Maps FindingSeverity to SignalSeverity and check category strings
|
|
6
|
+
* to SignalCategory. Used by defineCheck and PatternDetector.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { FindingSeverity } from '../types/findings.js'
|
|
10
|
+
import type { SignalSeverity, SignalCategory } from '@opensip-tools/core'
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/** Map FindingSeverity to SignalSeverity */
|
|
14
|
+
export function mapFindingSeverity(severity: FindingSeverity): SignalSeverity {
|
|
15
|
+
switch (severity) {
|
|
16
|
+
case 'error': {
|
|
17
|
+
return 'high'
|
|
18
|
+
}
|
|
19
|
+
case 'warning': {
|
|
20
|
+
return 'medium'
|
|
21
|
+
}
|
|
22
|
+
default: {
|
|
23
|
+
return 'medium'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Map check tags to SignalCategory (first matching tag wins) */
|
|
29
|
+
export function mapTagsToSignalCategory(tags: readonly string[]): SignalCategory {
|
|
30
|
+
for (const tag of tags) {
|
|
31
|
+
switch (tag) {
|
|
32
|
+
case 'security': {
|
|
33
|
+
return 'security'
|
|
34
|
+
}
|
|
35
|
+
case 'performance': {
|
|
36
|
+
return 'performance'
|
|
37
|
+
}
|
|
38
|
+
case 'architecture': {
|
|
39
|
+
return 'architecture'
|
|
40
|
+
}
|
|
41
|
+
case 'quality': {
|
|
42
|
+
return 'warning'
|
|
43
|
+
}
|
|
44
|
+
case 'resilience': {
|
|
45
|
+
return 'resilience'
|
|
46
|
+
}
|
|
47
|
+
case 'testing': {
|
|
48
|
+
return 'testing'
|
|
49
|
+
}
|
|
50
|
+
case 'documentation': {
|
|
51
|
+
return 'documentation'
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return 'warning'
|
|
56
|
+
}
|