@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,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Project-wide import graph builder.
|
|
3
|
+
*
|
|
4
|
+
* Builds a file-level dependency graph from a set of TypeScript/JavaScript
|
|
5
|
+
* source files, plus a Tarjan's strongly-connected-components implementation
|
|
6
|
+
* for cycle detection. Used by structural-drift checks like
|
|
7
|
+
* circular-import-detection and module-coupling-fan-out.
|
|
8
|
+
*
|
|
9
|
+
* Module resolution is deliberately a heuristic: relative imports are
|
|
10
|
+
* resolved by trying common extension/index.ts suffixes; bare specifiers
|
|
11
|
+
* (npm packages) are dropped; tsconfig path aliases are NOT resolved
|
|
12
|
+
* (treated as unresolved — they simply don't appear as edges in the graph).
|
|
13
|
+
*
|
|
14
|
+
* This matches the heuristic the existing `phantom-dependency-detection`
|
|
15
|
+
* check uses, which has been shipping reliably. Adding tsconfig-aware
|
|
16
|
+
* resolution is a follow-up plan.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import * as path from 'node:path'
|
|
20
|
+
|
|
21
|
+
import ts from 'typescript'
|
|
22
|
+
|
|
23
|
+
import { getSharedSourceFile } from './parse-cache.js'
|
|
24
|
+
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// PUBLIC TYPES
|
|
27
|
+
// =============================================================================
|
|
28
|
+
|
|
29
|
+
/** A file-level import graph for a project. */
|
|
30
|
+
export interface ImportGraph {
|
|
31
|
+
/** All node file paths (absolute, as supplied by the caller). */
|
|
32
|
+
readonly nodes: ReadonlySet<string>
|
|
33
|
+
/** Adjacency: file → set of files it imports (intra-project edges only). */
|
|
34
|
+
readonly outbound: ReadonlyMap<string, ReadonlySet<string>>
|
|
35
|
+
/** Reverse adjacency: file → set of files that import it. */
|
|
36
|
+
readonly inbound: ReadonlyMap<string, ReadonlySet<string>>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// PUBLIC API
|
|
41
|
+
// =============================================================================
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Build an import graph from a collection of file paths and their content.
|
|
45
|
+
*
|
|
46
|
+
* Each file's TS AST is walked for top-level `import` and `export ... from`
|
|
47
|
+
* declarations. Relative specifiers (`./foo`, `../bar/baz.js`) are resolved
|
|
48
|
+
* against the importing file's directory using the heuristic in
|
|
49
|
+
* `resolveRelativeSpecifier`. Bare specifiers (`react`, `lodash`) are
|
|
50
|
+
* dropped — they don't represent intra-project edges.
|
|
51
|
+
*
|
|
52
|
+
* Files that fail to parse are still added as nodes (with no edges) so the
|
|
53
|
+
* graph remains complete.
|
|
54
|
+
*/
|
|
55
|
+
export function buildImportGraph(files: ReadonlyMap<string, string>): ImportGraph {
|
|
56
|
+
const nodes = new Set<string>(files.keys())
|
|
57
|
+
const outbound = new Map<string, Set<string>>()
|
|
58
|
+
const inbound = new Map<string, Set<string>>()
|
|
59
|
+
|
|
60
|
+
// Initialize empty edge sets for every node so callers can safely
|
|
61
|
+
// outbound.get(file) without checking for undefined.
|
|
62
|
+
for (const node of nodes) {
|
|
63
|
+
outbound.set(node, new Set())
|
|
64
|
+
inbound.set(node, new Set())
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const [filePath, content] of files) {
|
|
68
|
+
const specifiers = extractImportSpecifiers(filePath, content)
|
|
69
|
+
for (const spec of specifiers) {
|
|
70
|
+
const resolved = resolveRelativeSpecifier(filePath, spec, nodes)
|
|
71
|
+
if (resolved !== null) {
|
|
72
|
+
outbound.get(filePath)!.add(resolved)
|
|
73
|
+
inbound.get(resolved)!.add(filePath)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return { nodes, outbound, inbound }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Find strongly-connected components in the graph using Tarjan's algorithm.
|
|
83
|
+
*
|
|
84
|
+
* Returns an array of SCCs, each represented as an array of node names. SCCs
|
|
85
|
+
* of size 1 represent a node with no cycle (or a self-loop, which is rare in
|
|
86
|
+
* import graphs). Cycle-detection callers typically filter to `scc.length > 1`
|
|
87
|
+
* to get only real multi-file cycles.
|
|
88
|
+
*
|
|
89
|
+
* Algorithm: standard iterative Tarjan's SCC. O(V + E), single pass.
|
|
90
|
+
*/
|
|
91
|
+
export function findStronglyConnectedComponents(
|
|
92
|
+
graph: ImportGraph,
|
|
93
|
+
): readonly (readonly string[])[] {
|
|
94
|
+
const indexOf = new Map<string, number>()
|
|
95
|
+
const lowlinkOf = new Map<string, number>()
|
|
96
|
+
const onStack = new Set<string>()
|
|
97
|
+
const stack: string[] = []
|
|
98
|
+
const sccs: string[][] = []
|
|
99
|
+
let nextIndex = 0
|
|
100
|
+
|
|
101
|
+
// Iterative Tarjan's — recursive form blows the stack on large graphs.
|
|
102
|
+
// State machine: we replay each node's adjacency from where we left off.
|
|
103
|
+
interface Frame {
|
|
104
|
+
node: string
|
|
105
|
+
neighbors: string[]
|
|
106
|
+
next: number
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity -- iterative Tarjan SCC: explicit stack to avoid recursion; the algorithm is canonical and reads cleanest as a single function
|
|
110
|
+
function strongConnect(start: string): void {
|
|
111
|
+
const callStack: Frame[] = []
|
|
112
|
+
|
|
113
|
+
indexOf.set(start, nextIndex)
|
|
114
|
+
lowlinkOf.set(start, nextIndex)
|
|
115
|
+
nextIndex++
|
|
116
|
+
stack.push(start)
|
|
117
|
+
onStack.add(start)
|
|
118
|
+
callStack.push({
|
|
119
|
+
node: start,
|
|
120
|
+
neighbors: [...(graph.outbound.get(start) ?? [])],
|
|
121
|
+
next: 0,
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
while (callStack.length > 0) {
|
|
125
|
+
const frame = callStack.at(-1)!
|
|
126
|
+
|
|
127
|
+
if (frame.next < frame.neighbors.length) {
|
|
128
|
+
const w = frame.neighbors[frame.next]
|
|
129
|
+
frame.next++
|
|
130
|
+
|
|
131
|
+
if (!indexOf.has(w)) {
|
|
132
|
+
// Recurse into w.
|
|
133
|
+
indexOf.set(w, nextIndex)
|
|
134
|
+
lowlinkOf.set(w, nextIndex)
|
|
135
|
+
nextIndex++
|
|
136
|
+
stack.push(w)
|
|
137
|
+
onStack.add(w)
|
|
138
|
+
callStack.push({
|
|
139
|
+
node: w,
|
|
140
|
+
neighbors: [...(graph.outbound.get(w) ?? [])],
|
|
141
|
+
next: 0,
|
|
142
|
+
})
|
|
143
|
+
continue
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (onStack.has(w)) {
|
|
147
|
+
// Back edge — update v's lowlink.
|
|
148
|
+
const vLow = lowlinkOf.get(frame.node)!
|
|
149
|
+
const wIdx = indexOf.get(w)!
|
|
150
|
+
if (wIdx < vLow) lowlinkOf.set(frame.node, wIdx)
|
|
151
|
+
}
|
|
152
|
+
continue
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// All neighbors processed — finalize this node.
|
|
156
|
+
const v = frame.node
|
|
157
|
+
const vLow = lowlinkOf.get(v)!
|
|
158
|
+
const vIdx = indexOf.get(v)!
|
|
159
|
+
|
|
160
|
+
if (vLow === vIdx) {
|
|
161
|
+
// v is the root of an SCC — pop until v is removed.
|
|
162
|
+
const scc: string[] = []
|
|
163
|
+
let w: string
|
|
164
|
+
do {
|
|
165
|
+
w = stack.pop()!
|
|
166
|
+
onStack.delete(w)
|
|
167
|
+
scc.push(w)
|
|
168
|
+
} while (w !== v)
|
|
169
|
+
sccs.push(scc)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
callStack.pop()
|
|
173
|
+
|
|
174
|
+
// Propagate lowlink up to the parent frame.
|
|
175
|
+
if (callStack.length > 0) {
|
|
176
|
+
const parent = callStack.at(-1)!
|
|
177
|
+
const parentLow = lowlinkOf.get(parent.node)!
|
|
178
|
+
if (vLow < parentLow) lowlinkOf.set(parent.node, vLow)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
for (const node of graph.nodes) {
|
|
184
|
+
if (!indexOf.has(node)) {
|
|
185
|
+
strongConnect(node)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return sccs
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// =============================================================================
|
|
193
|
+
// INTERNAL HELPERS
|
|
194
|
+
// =============================================================================
|
|
195
|
+
|
|
196
|
+
/** Walk the AST and collect top-level import / export-from specifiers. */
|
|
197
|
+
function extractImportSpecifiers(filePath: string, content: string): string[] {
|
|
198
|
+
const sourceFile = getSharedSourceFile(filePath, content)
|
|
199
|
+
if (sourceFile === null) return []
|
|
200
|
+
|
|
201
|
+
const specifiers: string[] = []
|
|
202
|
+
for (const stmt of sourceFile.statements) {
|
|
203
|
+
// import foo from './bar'; import './side-effect'; import * as ns from './m';
|
|
204
|
+
if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier)) {
|
|
205
|
+
specifiers.push(stmt.moduleSpecifier.text)
|
|
206
|
+
continue
|
|
207
|
+
}
|
|
208
|
+
// export * from './foo'; export { x } from './foo';
|
|
209
|
+
if (
|
|
210
|
+
ts.isExportDeclaration(stmt) &&
|
|
211
|
+
stmt.moduleSpecifier !== undefined &&
|
|
212
|
+
ts.isStringLiteral(stmt.moduleSpecifier)
|
|
213
|
+
) {
|
|
214
|
+
specifiers.push(stmt.moduleSpecifier.text)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return specifiers
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Resolve a module specifier to an actual file path in the project, or
|
|
222
|
+
* return null if the specifier is non-relative (npm package, path alias) or
|
|
223
|
+
* doesn't resolve to a known project file.
|
|
224
|
+
*
|
|
225
|
+
* Supports:
|
|
226
|
+
* - `./foo` → `<dir>/foo.ts`, `.tsx`, `/index.ts`, `/index.tsx`
|
|
227
|
+
* - `./foo.js` → `<dir>/foo.ts` (ESM extension swap, common in TS+ESM)
|
|
228
|
+
* - `./foo.ts` → `<dir>/foo.ts` (literal)
|
|
229
|
+
* - `../bar/baz` → resolved relative to importer's directory
|
|
230
|
+
*
|
|
231
|
+
* Does NOT support:
|
|
232
|
+
* - tsconfig `paths` aliases (deferred per plan)
|
|
233
|
+
* - npm packages (correctly dropped — out of scope for intra-project graph)
|
|
234
|
+
*/
|
|
235
|
+
function resolveRelativeSpecifier(
|
|
236
|
+
importerPath: string,
|
|
237
|
+
specifier: string,
|
|
238
|
+
knownPaths: ReadonlySet<string>,
|
|
239
|
+
): string | null {
|
|
240
|
+
// Only relative specifiers participate in the intra-project graph.
|
|
241
|
+
if (!specifier.startsWith('.')) return null
|
|
242
|
+
|
|
243
|
+
const importerDir = path.dirname(importerPath)
|
|
244
|
+
const base = path.resolve(importerDir, specifier)
|
|
245
|
+
|
|
246
|
+
// Try the candidate paths in priority order. The first one that exists in
|
|
247
|
+
// the project's file set wins.
|
|
248
|
+
const candidates: string[] = [ base]
|
|
249
|
+
|
|
250
|
+
// 1. Literal path (specifier already includes extension).
|
|
251
|
+
|
|
252
|
+
// 2. ESM extension swap: `.js` → `.ts` / `.tsx` (TypeScript ESM convention).
|
|
253
|
+
if (base.endsWith('.js')) {
|
|
254
|
+
candidates.push(base.slice(0, -3) + '.ts', base.slice(0, -3) + '.tsx')
|
|
255
|
+
}
|
|
256
|
+
if (base.endsWith('.jsx')) {
|
|
257
|
+
candidates.push(base.slice(0, -4) + '.tsx')
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// 3. Append common extensions if the specifier was extension-less.
|
|
261
|
+
const hasExt = path.extname(base) !== ''
|
|
262
|
+
if (!hasExt) {
|
|
263
|
+
// Direct extensions and index resolution.
|
|
264
|
+
candidates.push(
|
|
265
|
+
base + '.ts',
|
|
266
|
+
base + '.tsx',
|
|
267
|
+
base + '.js',
|
|
268
|
+
base + '.jsx',
|
|
269
|
+
path.join(base, 'index.ts'),
|
|
270
|
+
path.join(base, 'index.tsx'),
|
|
271
|
+
path.join(base, 'index.js'),
|
|
272
|
+
path.join(base, 'index.jsx'),
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
for (const candidate of candidates) {
|
|
277
|
+
if (knownPaths.has(candidate)) return candidate
|
|
278
|
+
}
|
|
279
|
+
return null
|
|
280
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Memory profiler for fitness checks
|
|
3
|
+
*
|
|
4
|
+
* Always-on, low-overhead memory tracking for check execution.
|
|
5
|
+
* Collects per-check profiles for trending analysis.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Point-in-time snapshot of Node.js memory usage */
|
|
9
|
+
interface MemorySnapshot {
|
|
10
|
+
readonly heapUsed: number
|
|
11
|
+
readonly heapTotal: number
|
|
12
|
+
readonly external: number
|
|
13
|
+
readonly arrayBuffers: number
|
|
14
|
+
readonly rss: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Memory usage profile recorded for a single check execution */
|
|
18
|
+
export interface CheckMemoryProfile {
|
|
19
|
+
readonly checkId: string
|
|
20
|
+
readonly memoryBeforeMB: number
|
|
21
|
+
readonly memoryAfterMB: number
|
|
22
|
+
readonly memoryDeltaMB: number
|
|
23
|
+
readonly violationCount: number
|
|
24
|
+
readonly durationMs: number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Aggregated memory profiling summary across all check executions */
|
|
28
|
+
interface MemoryProfileSummary {
|
|
29
|
+
readonly prewarmMemoryMB: number
|
|
30
|
+
readonly peakMemoryMB: number
|
|
31
|
+
readonly checksExceedingThreshold: number
|
|
32
|
+
readonly topConsumers: readonly CheckMemoryProfile[]
|
|
33
|
+
readonly allProfiles: readonly CheckMemoryProfile[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const DEFAULT_MEMORY_WARNING_THRESHOLD_MB = 200
|
|
37
|
+
|
|
38
|
+
/** Low-overhead memory profiler that tracks per-check heap usage during fitness runs */
|
|
39
|
+
class MemoryProfiler {
|
|
40
|
+
private readonly profiles: CheckMemoryProfile[] = []
|
|
41
|
+
private prewarmMemoryMB = 0
|
|
42
|
+
private peakMemoryMB = 0
|
|
43
|
+
private readonly warningThresholdMB: number
|
|
44
|
+
|
|
45
|
+
constructor(warningThresholdMB = DEFAULT_MEMORY_WARNING_THRESHOLD_MB) {
|
|
46
|
+
this.warningThresholdMB = warningThresholdMB
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private takeSnapshot(): MemorySnapshot {
|
|
50
|
+
const mem = process.memoryUsage()
|
|
51
|
+
return {
|
|
52
|
+
heapUsed: mem.heapUsed,
|
|
53
|
+
heapTotal: mem.heapTotal,
|
|
54
|
+
external: mem.external,
|
|
55
|
+
arrayBuffers: mem.arrayBuffers,
|
|
56
|
+
rss: mem.rss,
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private bytesToMB(bytes: number): number {
|
|
61
|
+
return bytes / 1024 / 1024
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Record memory baseline after cache prewarm completes */
|
|
65
|
+
recordPrewarmComplete(): void {
|
|
66
|
+
const snapshot = this.takeSnapshot()
|
|
67
|
+
this.prewarmMemoryMB = this.bytesToMB(snapshot.heapUsed)
|
|
68
|
+
this.peakMemoryMB = this.prewarmMemoryMB
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Return current heap usage in megabytes */
|
|
72
|
+
getCurrentMemoryMB(): number {
|
|
73
|
+
const snapshot = this.takeSnapshot()
|
|
74
|
+
return this.bytesToMB(snapshot.heapUsed)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Record memory before a check starts; returns the pre-check heap in MB */
|
|
78
|
+
recordCheckStart(): number {
|
|
79
|
+
return this.getCurrentMemoryMB()
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Record memory after a check completes and return the check's memory profile */
|
|
83
|
+
recordCheckComplete(
|
|
84
|
+
checkId: string,
|
|
85
|
+
memoryBeforeMB: number,
|
|
86
|
+
violationCount: number,
|
|
87
|
+
durationMs: number,
|
|
88
|
+
): CheckMemoryProfile {
|
|
89
|
+
const memoryAfterMB = this.getCurrentMemoryMB()
|
|
90
|
+
const memoryDeltaMB = memoryAfterMB - memoryBeforeMB
|
|
91
|
+
|
|
92
|
+
if (memoryAfterMB > this.peakMemoryMB) {
|
|
93
|
+
this.peakMemoryMB = memoryAfterMB
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const profile: CheckMemoryProfile = {
|
|
97
|
+
checkId,
|
|
98
|
+
memoryBeforeMB: Math.round(memoryBeforeMB * 100) / 100,
|
|
99
|
+
memoryAfterMB: Math.round(memoryAfterMB * 100) / 100,
|
|
100
|
+
memoryDeltaMB: Math.round(memoryDeltaMB * 100) / 100,
|
|
101
|
+
violationCount,
|
|
102
|
+
durationMs,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
this.profiles.push(profile)
|
|
106
|
+
return profile
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Check whether a memory delta exceeds the configured warning threshold */
|
|
110
|
+
exceedsThreshold(deltaMB: number): boolean {
|
|
111
|
+
return deltaMB > this.warningThresholdMB
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Return the configured warning threshold in megabytes */
|
|
115
|
+
getWarningThresholdMB(): number {
|
|
116
|
+
return this.warningThresholdMB
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Build and return an aggregated summary of all recorded check profiles */
|
|
120
|
+
getSummary(): MemoryProfileSummary {
|
|
121
|
+
const sortedProfiles = [...this.profiles].sort((a, b) => b.memoryDeltaMB - a.memoryDeltaMB)
|
|
122
|
+
|
|
123
|
+
const checksExceedingThreshold = this.profiles.filter(
|
|
124
|
+
(p) => p.memoryDeltaMB > this.warningThresholdMB,
|
|
125
|
+
).length
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
prewarmMemoryMB: Math.round(this.prewarmMemoryMB * 100) / 100,
|
|
129
|
+
peakMemoryMB: Math.round(this.peakMemoryMB * 100) / 100,
|
|
130
|
+
checksExceedingThreshold,
|
|
131
|
+
topConsumers: sortedProfiles.slice(0, 10),
|
|
132
|
+
allProfiles: this.profiles,
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Reset all recorded profiles and counters */
|
|
137
|
+
reset(): void {
|
|
138
|
+
this.profiles.length = 0
|
|
139
|
+
this.prewarmMemoryMB = 0
|
|
140
|
+
this.peakMemoryMB = 0
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Shared singleton memory profiler instance used across fitness check runs */
|
|
145
|
+
export const memoryProfiler = new MemoryProfiler()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Re-export from the language-aware parse cache.
|
|
3
|
+
*
|
|
4
|
+
* The init/clear lifecycle and getParseTree API live in
|
|
5
|
+
* core/src/languages/parse-cache.ts. This file forwards those calls
|
|
6
|
+
* for backward compatibility with code that imported from this path.
|
|
7
|
+
*
|
|
8
|
+
* getSharedSourceFile remains as a TS-specific convenience wrapper
|
|
9
|
+
* that resolves the TypeScript adapter from the language registry.
|
|
10
|
+
* Phase 2 moved the canonical TS AST helpers to
|
|
11
|
+
* @opensip-tools/lang-typescript; this shim is retained for the
|
|
12
|
+
* core framework/import-graph.ts internal use case.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
import { getParseTree, defaultLanguageRegistry } from '@opensip-tools/core'
|
|
17
|
+
import ts from 'typescript'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get a TypeScript SourceFile via the language-aware cache when the TS
|
|
21
|
+
* adapter is registered, falling back to a direct parse otherwise.
|
|
22
|
+
*
|
|
23
|
+
* @internal Used by framework/import-graph.ts. New TS check authors
|
|
24
|
+
* should import getSharedSourceFile from @opensip-tools/lang-typescript.
|
|
25
|
+
*/
|
|
26
|
+
export function getSharedSourceFile(filePath: string, content: string): ts.SourceFile | null {
|
|
27
|
+
const adapter = defaultLanguageRegistry.get('typescript')
|
|
28
|
+
if (adapter) {
|
|
29
|
+
return getParseTree(adapter, filePath, content) as ts.SourceFile | null
|
|
30
|
+
}
|
|
31
|
+
// No adapter registered yet (e.g. unit tests that run without CLI bootstrap).
|
|
32
|
+
// Fall back to direct parse — preserves prior behavior.
|
|
33
|
+
try {
|
|
34
|
+
return ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
|
|
35
|
+
} catch {
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview PathMatcher - Strategy pattern for file matching
|
|
3
|
+
*
|
|
4
|
+
* Provides glob-based file matching with include/exclude patterns.
|
|
5
|
+
* Supports lazy evaluation and composition.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as path from 'node:path'
|
|
9
|
+
|
|
10
|
+
import { glob } from 'glob'
|
|
11
|
+
import { minimatch } from 'minimatch'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Options for PathMatcher.
|
|
15
|
+
*/
|
|
16
|
+
export interface PathMatcherOptions {
|
|
17
|
+
/** Root directory to search from */
|
|
18
|
+
readonly cwd: string
|
|
19
|
+
/** Glob patterns to include */
|
|
20
|
+
readonly include: readonly string[]
|
|
21
|
+
/** Glob patterns to exclude */
|
|
22
|
+
readonly exclude: readonly string[]
|
|
23
|
+
/** Additional exclusion patterns (combined with exclude) */
|
|
24
|
+
readonly additionalExcludes?: readonly string[]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Result of file matching operation.
|
|
29
|
+
*/
|
|
30
|
+
export interface MatchResult {
|
|
31
|
+
/** Matched files (absolute paths) */
|
|
32
|
+
readonly files: readonly string[]
|
|
33
|
+
/** Files that were excluded */
|
|
34
|
+
readonly excluded: readonly string[]
|
|
35
|
+
/** Time taken for glob operation in ms */
|
|
36
|
+
readonly durationMs: number
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Strategy for matching files based on glob patterns.
|
|
41
|
+
* Supports both custom patterns and composition.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const matcher = PathMatcher.create({
|
|
46
|
+
* cwd: '/path/to/repo',
|
|
47
|
+
* include: ['src/**\/*.ts'],
|
|
48
|
+
* exclude: ['**\/__tests__/**'],
|
|
49
|
+
* });
|
|
50
|
+
* const files = await matcher.files();
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export class PathMatcher {
|
|
54
|
+
private constructor(private readonly options: PathMatcherOptions) {}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Create a PathMatcher from options.
|
|
58
|
+
*/
|
|
59
|
+
static create(options: PathMatcherOptions): PathMatcher {
|
|
60
|
+
return new PathMatcher(options)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get all matching files.
|
|
65
|
+
* @returns Array of absolute file paths matching the patterns
|
|
66
|
+
*/
|
|
67
|
+
async files(): Promise<readonly string[]> {
|
|
68
|
+
const result = await this.match()
|
|
69
|
+
return result.files
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get detailed match result including timing.
|
|
74
|
+
*/
|
|
75
|
+
async match(): Promise<MatchResult> {
|
|
76
|
+
const start = Date.now()
|
|
77
|
+
|
|
78
|
+
const allExcludes = [...this.options.exclude, ...(this.options.additionalExcludes ?? [])]
|
|
79
|
+
|
|
80
|
+
// Run glob for all include patterns
|
|
81
|
+
const matchedSets = await Promise.all(
|
|
82
|
+
this.options.include.map((pattern) =>
|
|
83
|
+
glob(pattern, {
|
|
84
|
+
cwd: this.options.cwd,
|
|
85
|
+
absolute: true,
|
|
86
|
+
nodir: true,
|
|
87
|
+
ignore: allExcludes,
|
|
88
|
+
}),
|
|
89
|
+
),
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
// Combine and deduplicate results
|
|
93
|
+
const allMatched = new Set<string>()
|
|
94
|
+
for (const matches of matchedSets) {
|
|
95
|
+
for (const file of matches) {
|
|
96
|
+
allMatched.add(path.normalize(file))
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const files = [...allMatched].sort()
|
|
101
|
+
const durationMs = Date.now() - start
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
files,
|
|
105
|
+
excluded: [],
|
|
106
|
+
durationMs,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Check if a file matches the patterns.
|
|
112
|
+
* @param filePath - Absolute path to check
|
|
113
|
+
* @returns True if file matches include patterns and is not excluded
|
|
114
|
+
*/
|
|
115
|
+
matches(filePath: string): boolean {
|
|
116
|
+
const relativePath = path.relative(this.options.cwd, filePath)
|
|
117
|
+
|
|
118
|
+
const matchesInclude = this.options.include.some((pattern) =>
|
|
119
|
+
minimatch(relativePath, pattern, { dot: true }),
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
if (!matchesInclude) {
|
|
123
|
+
return false
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const allExcludes = [...this.options.exclude, ...(this.options.additionalExcludes ?? [])]
|
|
127
|
+
|
|
128
|
+
const matchesExclude = allExcludes.some((pattern) =>
|
|
129
|
+
minimatch(relativePath, pattern, { dot: true }),
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
return !matchesExclude
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Create a new PathMatcher with additional exclusions.
|
|
137
|
+
*/
|
|
138
|
+
withExcludes(additionalExcludes: readonly string[]): PathMatcher {
|
|
139
|
+
return new PathMatcher({
|
|
140
|
+
...this.options,
|
|
141
|
+
additionalExcludes: [...(this.options.additionalExcludes ?? []), ...additionalExcludes],
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Create a new PathMatcher that only includes TypeScript files.
|
|
147
|
+
*/
|
|
148
|
+
typescriptOnly(): PathMatcher {
|
|
149
|
+
return new PathMatcher({
|
|
150
|
+
...this.options,
|
|
151
|
+
include: this.options.include.map((pattern) => {
|
|
152
|
+
if (pattern.endsWith('/*') || pattern.endsWith('/**/*')) {
|
|
153
|
+
const base = pattern.replace(/\/\*+$/, '')
|
|
154
|
+
return `${base}/**/*.{ts,tsx}`
|
|
155
|
+
}
|
|
156
|
+
if (!pattern.includes('.')) {
|
|
157
|
+
return `${pattern}/**/*.{ts,tsx}`
|
|
158
|
+
}
|
|
159
|
+
return pattern
|
|
160
|
+
}),
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Create a new PathMatcher that excludes test files.
|
|
166
|
+
*/
|
|
167
|
+
noTests(): PathMatcher {
|
|
168
|
+
return this.withExcludes([
|
|
169
|
+
'**/__tests__/**',
|
|
170
|
+
'**/*.test.ts',
|
|
171
|
+
'**/*.test.tsx',
|
|
172
|
+
'**/*.spec.ts',
|
|
173
|
+
'**/*.spec.tsx',
|
|
174
|
+
])
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Get the current working directory. */
|
|
178
|
+
get cwd(): string {
|
|
179
|
+
return this.options.cwd
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Get the include patterns. */
|
|
183
|
+
get includePatterns(): readonly string[] {
|
|
184
|
+
return this.options.include
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Get the exclude patterns. */
|
|
188
|
+
get excludePatterns(): readonly string[] {
|
|
189
|
+
return [...this.options.exclude, ...(this.options.additionalExcludes ?? [])]
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Helper for registering checks with a namespace
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { defaultRegistry } from './registry.js';
|
|
6
|
+
|
|
7
|
+
import type { Check } from './check-types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Register an array of checks with a namespace into the default registry.
|
|
11
|
+
* @returns The number of checks registered.
|
|
12
|
+
*/
|
|
13
|
+
export function registerChecks(checks: Check[], namespace: string): number {
|
|
14
|
+
let count = 0;
|
|
15
|
+
for (const check of checks) {
|
|
16
|
+
defaultRegistry.register(check, namespace);
|
|
17
|
+
count++;
|
|
18
|
+
}
|
|
19
|
+
return count;
|
|
20
|
+
}
|