@opensip-cli/checks-universal 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +31 -0
- package/dist/__tests__/all-checks-execute.test.d.ts +17 -0
- package/dist/__tests__/all-checks-execute.test.d.ts.map +1 -0
- package/dist/__tests__/all-checks-execute.test.js +452 -0
- package/dist/__tests__/all-checks-execute.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-10.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-10.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-10.test.js +200 -0
- package/dist/__tests__/behavior-fixtures-10.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-11.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-11.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-11.test.js +120 -0
- package/dist/__tests__/behavior-fixtures-11.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-12.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-12.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-12.test.js +157 -0
- package/dist/__tests__/behavior-fixtures-12.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-2.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-2.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-2.test.js +785 -0
- package/dist/__tests__/behavior-fixtures-2.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-3.test.d.ts +6 -0
- package/dist/__tests__/behavior-fixtures-3.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-3.test.js +663 -0
- package/dist/__tests__/behavior-fixtures-3.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-4.test.d.ts +5 -0
- package/dist/__tests__/behavior-fixtures-4.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-4.test.js +612 -0
- package/dist/__tests__/behavior-fixtures-4.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-5.test.d.ts +5 -0
- package/dist/__tests__/behavior-fixtures-5.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-5.test.js +469 -0
- package/dist/__tests__/behavior-fixtures-5.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-6.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-6.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-6.test.js +591 -0
- package/dist/__tests__/behavior-fixtures-6.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-7.test.d.ts +5 -0
- package/dist/__tests__/behavior-fixtures-7.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-7.test.js +662 -0
- package/dist/__tests__/behavior-fixtures-7.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-8.test.d.ts +11 -0
- package/dist/__tests__/behavior-fixtures-8.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-8.test.js +634 -0
- package/dist/__tests__/behavior-fixtures-8.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-9.test.d.ts +11 -0
- package/dist/__tests__/behavior-fixtures-9.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-9.test.js +271 -0
- package/dist/__tests__/behavior-fixtures-9.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures.test.d.ts +14 -0
- package/dist/__tests__/behavior-fixtures.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures.test.js +1423 -0
- package/dist/__tests__/behavior-fixtures.test.js.map +1 -0
- package/dist/__tests__/checks.test.d.ts +2 -0
- package/dist/__tests__/checks.test.d.ts.map +1 -0
- package/dist/__tests__/checks.test.js +61 -0
- package/dist/__tests__/checks.test.js.map +1 -0
- package/dist/__tests__/env-var-validation.test.d.ts +14 -0
- package/dist/__tests__/env-var-validation.test.d.ts.map +1 -0
- package/dist/__tests__/env-var-validation.test.js +53 -0
- package/dist/__tests__/env-var-validation.test.js.map +1 -0
- package/dist/__tests__/file-length-limit.test.d.ts +2 -0
- package/dist/__tests__/file-length-limit.test.d.ts.map +1 -0
- package/dist/__tests__/file-length-limit.test.js +29 -0
- package/dist/__tests__/file-length-limit.test.js.map +1 -0
- package/dist/__tests__/fixture-coverage.allowlist.d.ts +18 -0
- package/dist/__tests__/fixture-coverage.allowlist.d.ts.map +1 -0
- package/dist/__tests__/fixture-coverage.allowlist.js +35 -0
- package/dist/__tests__/fixture-coverage.allowlist.js.map +1 -0
- package/dist/__tests__/fixture-coverage.test.d.ts +13 -0
- package/dist/__tests__/fixture-coverage.test.d.ts.map +1 -0
- package/dist/__tests__/fixture-coverage.test.js +57 -0
- package/dist/__tests__/fixture-coverage.test.js.map +1 -0
- package/dist/__tests__/iic.test.d.ts +15 -0
- package/dist/__tests__/iic.test.d.ts.map +1 -0
- package/dist/__tests__/iic.test.js +316 -0
- package/dist/__tests__/iic.test.js.map +1 -0
- package/dist/__tests__/no-skipped-tests.test.d.ts +14 -0
- package/dist/__tests__/no-skipped-tests.test.d.ts.map +1 -0
- package/dist/__tests__/no-skipped-tests.test.js +144 -0
- package/dist/__tests__/no-skipped-tests.test.js.map +1 -0
- package/dist/__tests__/no-todo-comments.test.d.ts +2 -0
- package/dist/__tests__/no-todo-comments.test.d.ts.map +1 -0
- package/dist/__tests__/no-todo-comments.test.js +31 -0
- package/dist/__tests__/no-todo-comments.test.js.map +1 -0
- package/dist/__tests__/no-unimplemented-markers.test.d.ts +2 -0
- package/dist/__tests__/no-unimplemented-markers.test.d.ts.map +1 -0
- package/dist/__tests__/no-unimplemented-markers.test.js +140 -0
- package/dist/__tests__/no-unimplemented-markers.test.js.map +1 -0
- package/dist/__tests__/public-api-jsdoc-scope.test.d.ts +10 -0
- package/dist/__tests__/public-api-jsdoc-scope.test.d.ts.map +1 -0
- package/dist/__tests__/public-api-jsdoc-scope.test.js +176 -0
- package/dist/__tests__/public-api-jsdoc-scope.test.js.map +1 -0
- package/dist/__tests__/resilience-fp.test.d.ts +14 -0
- package/dist/__tests__/resilience-fp.test.d.ts.map +1 -0
- package/dist/__tests__/resilience-fp.test.js +110 -0
- package/dist/__tests__/resilience-fp.test.js.map +1 -0
- package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.d.ts +2 -0
- package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.d.ts.map +1 -0
- package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.js +32 -0
- package/dist/checks/architecture/__tests__/no-kebab-option-indexing.test.js.map +1 -0
- package/dist/checks/architecture/__tests__/tool-has-manifest.test.d.ts +2 -0
- package/dist/checks/architecture/__tests__/tool-has-manifest.test.d.ts.map +1 -0
- package/dist/checks/architecture/__tests__/tool-has-manifest.test.js +152 -0
- package/dist/checks/architecture/__tests__/tool-has-manifest.test.js.map +1 -0
- package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.d.ts +2 -0
- package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.d.ts.map +1 -0
- package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.js +129 -0
- package/dist/checks/architecture/__tests__/vitest-config-required-with-tests.test.js.map +1 -0
- package/dist/checks/architecture/_yaml-doc-bindings.d.ts +23 -0
- package/dist/checks/architecture/_yaml-doc-bindings.d.ts.map +1 -0
- package/dist/checks/architecture/_yaml-doc-bindings.js +29 -0
- package/dist/checks/architecture/_yaml-doc-bindings.js.map +1 -0
- package/dist/checks/architecture/dependencies/index.d.ts +2 -0
- package/dist/checks/architecture/dependencies/index.d.ts.map +1 -0
- package/dist/checks/architecture/dependencies/index.js +2 -0
- package/dist/checks/architecture/dependencies/index.js.map +1 -0
- package/dist/checks/architecture/dependencies/no-duplicate-packages.d.ts +11 -0
- package/dist/checks/architecture/dependencies/no-duplicate-packages.d.ts.map +1 -0
- package/dist/checks/architecture/dependencies/no-duplicate-packages.js +171 -0
- package/dist/checks/architecture/dependencies/no-duplicate-packages.js.map +1 -0
- package/dist/checks/architecture/docker-best-practices.d.ts +23 -0
- package/dist/checks/architecture/docker-best-practices.d.ts.map +1 -0
- package/dist/checks/architecture/docker-best-practices.js +427 -0
- package/dist/checks/architecture/docker-best-practices.js.map +1 -0
- package/dist/checks/architecture/docker-ignore-validation.d.ts +18 -0
- package/dist/checks/architecture/docker-ignore-validation.d.ts.map +1 -0
- package/dist/checks/architecture/docker-ignore-validation.js +117 -0
- package/dist/checks/architecture/docker-ignore-validation.js.map +1 -0
- package/dist/checks/architecture/docker-version-sync.d.ts +16 -0
- package/dist/checks/architecture/docker-version-sync.d.ts.map +1 -0
- package/dist/checks/architecture/docker-version-sync.js +193 -0
- package/dist/checks/architecture/docker-version-sync.js.map +1 -0
- package/dist/checks/architecture/env-var-validation.d.ts +14 -0
- package/dist/checks/architecture/env-var-validation.d.ts.map +1 -0
- package/dist/checks/architecture/env-var-validation.js +289 -0
- package/dist/checks/architecture/env-var-validation.js.map +1 -0
- package/dist/checks/architecture/heavy-import-detection.d.ts +11 -0
- package/dist/checks/architecture/heavy-import-detection.d.ts.map +1 -0
- package/dist/checks/architecture/heavy-import-detection.js +91 -0
- package/dist/checks/architecture/heavy-import-detection.js.map +1 -0
- package/dist/checks/architecture/index.d.ts +16 -0
- package/dist/checks/architecture/index.d.ts.map +1 -0
- package/dist/checks/architecture/index.js +16 -0
- package/dist/checks/architecture/index.js.map +1 -0
- package/dist/checks/architecture/modules/empty-package-detection.d.ts +11 -0
- package/dist/checks/architecture/modules/empty-package-detection.d.ts.map +1 -0
- package/dist/checks/architecture/modules/empty-package-detection.js +277 -0
- package/dist/checks/architecture/modules/empty-package-detection.js.map +1 -0
- package/dist/checks/architecture/modules/index.d.ts +3 -0
- package/dist/checks/architecture/modules/index.d.ts.map +1 -0
- package/dist/checks/architecture/modules/index.js +3 -0
- package/dist/checks/architecture/modules/index.js.map +1 -0
- package/dist/checks/architecture/modules/interface-implementation-consistency.d.ts +12 -0
- package/dist/checks/architecture/modules/interface-implementation-consistency.d.ts.map +1 -0
- package/dist/checks/architecture/modules/interface-implementation-consistency.js +555 -0
- package/dist/checks/architecture/modules/interface-implementation-consistency.js.map +1 -0
- package/dist/checks/architecture/no-custom-event-emitter.d.ts +11 -0
- package/dist/checks/architecture/no-custom-event-emitter.d.ts.map +1 -0
- package/dist/checks/architecture/no-custom-event-emitter.js +123 -0
- package/dist/checks/architecture/no-custom-event-emitter.js.map +1 -0
- package/dist/checks/architecture/no-kebab-option-indexing.d.ts +33 -0
- package/dist/checks/architecture/no-kebab-option-indexing.d.ts.map +1 -0
- package/dist/checks/architecture/no-kebab-option-indexing.js +81 -0
- package/dist/checks/architecture/no-kebab-option-indexing.js.map +1 -0
- package/dist/checks/architecture/node-version-consistency.d.ts +22 -0
- package/dist/checks/architecture/node-version-consistency.d.ts.map +1 -0
- package/dist/checks/architecture/node-version-consistency.js +225 -0
- package/dist/checks/architecture/node-version-consistency.js.map +1 -0
- package/dist/checks/architecture/project-readme-existence.d.ts +13 -0
- package/dist/checks/architecture/project-readme-existence.d.ts.map +1 -0
- package/dist/checks/architecture/project-readme-existence.js +55 -0
- package/dist/checks/architecture/project-readme-existence.js.map +1 -0
- package/dist/checks/architecture/stale-build-artifacts.d.ts +10 -0
- package/dist/checks/architecture/stale-build-artifacts.d.ts.map +1 -0
- package/dist/checks/architecture/stale-build-artifacts.js +55 -0
- package/dist/checks/architecture/stale-build-artifacts.js.map +1 -0
- package/dist/checks/architecture/tool-has-manifest.d.ts +27 -0
- package/dist/checks/architecture/tool-has-manifest.d.ts.map +1 -0
- package/dist/checks/architecture/tool-has-manifest.js +135 -0
- package/dist/checks/architecture/tool-has-manifest.js.map +1 -0
- package/dist/checks/architecture/vitest-config-extends-base.d.ts +15 -0
- package/dist/checks/architecture/vitest-config-extends-base.d.ts.map +1 -0
- package/dist/checks/architecture/vitest-config-extends-base.js +104 -0
- package/dist/checks/architecture/vitest-config-extends-base.js.map +1 -0
- package/dist/checks/architecture/vitest-config-required-with-tests.d.ts +49 -0
- package/dist/checks/architecture/vitest-config-required-with-tests.d.ts.map +1 -0
- package/dist/checks/architecture/vitest-config-required-with-tests.js +199 -0
- package/dist/checks/architecture/vitest-config-required-with-tests.js.map +1 -0
- package/dist/checks/documentation/_directives/eslint.d.ts +9 -0
- package/dist/checks/documentation/_directives/eslint.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/eslint.js +168 -0
- package/dist/checks/documentation/_directives/eslint.js.map +1 -0
- package/dist/checks/documentation/_directives/fitness.d.ts +9 -0
- package/dist/checks/documentation/_directives/fitness.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/fitness.js +64 -0
- package/dist/checks/documentation/_directives/fitness.js.map +1 -0
- package/dist/checks/documentation/_directives/graph.d.ts +10 -0
- package/dist/checks/documentation/_directives/graph.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/graph.js +65 -0
- package/dist/checks/documentation/_directives/graph.js.map +1 -0
- package/dist/checks/documentation/_directives/graph.test.d.ts +2 -0
- package/dist/checks/documentation/_directives/graph.test.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/graph.test.js +54 -0
- package/dist/checks/documentation/_directives/graph.test.js.map +1 -0
- package/dist/checks/documentation/_directives/semgrep.d.ts +8 -0
- package/dist/checks/documentation/_directives/semgrep.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/semgrep.js +72 -0
- package/dist/checks/documentation/_directives/semgrep.js.map +1 -0
- package/dist/checks/documentation/_directives/types.d.ts +21 -0
- package/dist/checks/documentation/_directives/types.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/types.js +9 -0
- package/dist/checks/documentation/_directives/types.js.map +1 -0
- package/dist/checks/documentation/_directives/typescript.d.ts +10 -0
- package/dist/checks/documentation/_directives/typescript.d.ts.map +1 -0
- package/dist/checks/documentation/_directives/typescript.js +54 -0
- package/dist/checks/documentation/_directives/typescript.js.map +1 -0
- package/dist/checks/documentation/_public-api-graph.d.ts +30 -0
- package/dist/checks/documentation/_public-api-graph.d.ts.map +1 -0
- package/dist/checks/documentation/_public-api-graph.js +304 -0
- package/dist/checks/documentation/_public-api-graph.js.map +1 -0
- package/dist/checks/documentation/directive-audit.d.ts +26 -0
- package/dist/checks/documentation/directive-audit.d.ts.map +1 -0
- package/dist/checks/documentation/directive-audit.js +144 -0
- package/dist/checks/documentation/directive-audit.js.map +1 -0
- package/dist/checks/documentation/index.d.ts +3 -0
- package/dist/checks/documentation/index.d.ts.map +1 -0
- package/dist/checks/documentation/index.js +3 -0
- package/dist/checks/documentation/index.js.map +1 -0
- package/dist/checks/documentation/public-api-jsdoc.d.ts +10 -0
- package/dist/checks/documentation/public-api-jsdoc.d.ts.map +1 -0
- package/dist/checks/documentation/public-api-jsdoc.js +131 -0
- package/dist/checks/documentation/public-api-jsdoc.js.map +1 -0
- package/dist/checks/file-length-limit.d.ts +16 -0
- package/dist/checks/file-length-limit.d.ts.map +1 -0
- package/dist/checks/file-length-limit.js +47 -0
- package/dist/checks/file-length-limit.js.map +1 -0
- package/dist/checks/index.d.ts +16 -0
- package/dist/checks/index.d.ts.map +1 -0
- package/dist/checks/index.js +16 -0
- package/dist/checks/index.js.map +1 -0
- package/dist/checks/no-todo-comments.d.ts +18 -0
- package/dist/checks/no-todo-comments.d.ts.map +1 -0
- package/dist/checks/no-todo-comments.js +79 -0
- package/dist/checks/no-todo-comments.js.map +1 -0
- package/dist/checks/no-unimplemented-markers.d.ts +24 -0
- package/dist/checks/no-unimplemented-markers.d.ts.map +1 -0
- package/dist/checks/no-unimplemented-markers.js +198 -0
- package/dist/checks/no-unimplemented-markers.js.map +1 -0
- package/dist/checks/quality/api/graphql-offset-pagination.d.ts +9 -0
- package/dist/checks/quality/api/graphql-offset-pagination.d.ts.map +1 -0
- package/dist/checks/quality/api/graphql-offset-pagination.js +63 -0
- package/dist/checks/quality/api/graphql-offset-pagination.js.map +1 -0
- package/dist/checks/quality/api/index.d.ts +3 -0
- package/dist/checks/quality/api/index.d.ts.map +1 -0
- package/dist/checks/quality/api/index.js +3 -0
- package/dist/checks/quality/api/index.js.map +1 -0
- package/dist/checks/quality/api/zod-openapi-sync.d.ts +13 -0
- package/dist/checks/quality/api/zod-openapi-sync.d.ts.map +1 -0
- package/dist/checks/quality/api/zod-openapi-sync.js +88 -0
- package/dist/checks/quality/api/zod-openapi-sync.js.map +1 -0
- package/dist/checks/quality/code-structure/dead-code.d.ts +12 -0
- package/dist/checks/quality/code-structure/dead-code.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/dead-code.js +238 -0
- package/dist/checks/quality/code-structure/dead-code.js.map +1 -0
- package/dist/checks/quality/code-structure/index.d.ts +5 -0
- package/dist/checks/quality/code-structure/index.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/index.js +5 -0
- package/dist/checks/quality/code-structure/index.js.map +1 -0
- package/dist/checks/quality/code-structure/no-ai-attribution.d.ts +25 -0
- package/dist/checks/quality/code-structure/no-ai-attribution.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/no-ai-attribution.js +76 -0
- package/dist/checks/quality/code-structure/no-ai-attribution.js.map +1 -0
- package/dist/checks/quality/code-structure/no-console-log.d.ts +17 -0
- package/dist/checks/quality/code-structure/no-console-log.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/no-console-log.js +106 -0
- package/dist/checks/quality/code-structure/no-console-log.js.map +1 -0
- package/dist/checks/quality/code-structure/no-process-artifacts.d.ts +25 -0
- package/dist/checks/quality/code-structure/no-process-artifacts.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/no-process-artifacts.js +104 -0
- package/dist/checks/quality/code-structure/no-process-artifacts.js.map +1 -0
- package/dist/checks/quality/dependency-version-consistency.d.ts +20 -0
- package/dist/checks/quality/dependency-version-consistency.d.ts.map +1 -0
- package/dist/checks/quality/dependency-version-consistency.js +266 -0
- package/dist/checks/quality/dependency-version-consistency.js.map +1 -0
- package/dist/checks/quality/fitness-ignore-hygiene.d.ts +10 -0
- package/dist/checks/quality/fitness-ignore-hygiene.d.ts.map +1 -0
- package/dist/checks/quality/fitness-ignore-hygiene.js +93 -0
- package/dist/checks/quality/fitness-ignore-hygiene.js.map +1 -0
- package/dist/checks/quality/frontend/expo-vector-icons.d.ts +13 -0
- package/dist/checks/quality/frontend/expo-vector-icons.d.ts.map +1 -0
- package/dist/checks/quality/frontend/expo-vector-icons.js +80 -0
- package/dist/checks/quality/frontend/expo-vector-icons.js.map +1 -0
- package/dist/checks/quality/frontend/image-optimization.d.ts +13 -0
- package/dist/checks/quality/frontend/image-optimization.d.ts.map +1 -0
- package/dist/checks/quality/frontend/image-optimization.js +166 -0
- package/dist/checks/quality/frontend/image-optimization.js.map +1 -0
- package/dist/checks/quality/frontend/index.d.ts +4 -0
- package/dist/checks/quality/frontend/index.d.ts.map +1 -0
- package/dist/checks/quality/frontend/index.js +4 -0
- package/dist/checks/quality/frontend/index.js.map +1 -0
- package/dist/checks/quality/frontend/navigation-typing.d.ts +12 -0
- package/dist/checks/quality/frontend/navigation-typing.d.ts.map +1 -0
- package/dist/checks/quality/frontend/navigation-typing.js +77 -0
- package/dist/checks/quality/frontend/navigation-typing.js.map +1 -0
- package/dist/checks/quality/graph-ignore-hygiene.d.ts +10 -0
- package/dist/checks/quality/graph-ignore-hygiene.d.ts.map +1 -0
- package/dist/checks/quality/graph-ignore-hygiene.js +95 -0
- package/dist/checks/quality/graph-ignore-hygiene.js.map +1 -0
- package/dist/checks/quality/graph-ignore-hygiene.test.d.ts +14 -0
- package/dist/checks/quality/graph-ignore-hygiene.test.d.ts.map +1 -0
- package/dist/checks/quality/graph-ignore-hygiene.test.js +58 -0
- package/dist/checks/quality/graph-ignore-hygiene.test.js.map +1 -0
- package/dist/checks/quality/index.d.ts +16 -0
- package/dist/checks/quality/index.d.ts.map +1 -0
- package/dist/checks/quality/index.js +16 -0
- package/dist/checks/quality/index.js.map +1 -0
- package/dist/checks/quality/linting/eslint-justifications.d.ts +12 -0
- package/dist/checks/quality/linting/eslint-justifications.d.ts.map +1 -0
- package/dist/checks/quality/linting/eslint-justifications.js +328 -0
- package/dist/checks/quality/linting/eslint-justifications.js.map +1 -0
- package/dist/checks/quality/linting/index.d.ts +4 -0
- package/dist/checks/quality/linting/index.d.ts.map +1 -0
- package/dist/checks/quality/linting/index.js +4 -0
- package/dist/checks/quality/linting/index.js.map +1 -0
- package/dist/checks/quality/linting/semgrep-justifications.d.ts +16 -0
- package/dist/checks/quality/linting/semgrep-justifications.d.ts.map +1 -0
- package/dist/checks/quality/linting/semgrep-justifications.js +229 -0
- package/dist/checks/quality/linting/semgrep-justifications.js.map +1 -0
- package/dist/checks/quality/linting/typescript-directive-hygiene.d.ts +12 -0
- package/dist/checks/quality/linting/typescript-directive-hygiene.d.ts.map +1 -0
- package/dist/checks/quality/linting/typescript-directive-hygiene.js +142 -0
- package/dist/checks/quality/linting/typescript-directive-hygiene.js.map +1 -0
- package/dist/checks/quality/no-compatibility-layer-names.d.ts +13 -0
- package/dist/checks/quality/no-compatibility-layer-names.d.ts.map +1 -0
- package/dist/checks/quality/no-compatibility-layer-names.js +100 -0
- package/dist/checks/quality/no-compatibility-layer-names.js.map +1 -0
- package/dist/checks/quality/no-deprecated-tags.d.ts +11 -0
- package/dist/checks/quality/no-deprecated-tags.d.ts.map +1 -0
- package/dist/checks/quality/no-deprecated-tags.js +76 -0
- package/dist/checks/quality/no-deprecated-tags.js.map +1 -0
- package/dist/checks/quality/no-markdown-references.d.ts +16 -0
- package/dist/checks/quality/no-markdown-references.d.ts.map +1 -0
- package/dist/checks/quality/no-markdown-references.js +145 -0
- package/dist/checks/quality/no-markdown-references.js.map +1 -0
- package/dist/checks/quality/no-raw-regex-on-code.d.ts +9 -0
- package/dist/checks/quality/no-raw-regex-on-code.d.ts.map +1 -0
- package/dist/checks/quality/no-raw-regex-on-code.js +61 -0
- package/dist/checks/quality/no-raw-regex-on-code.js.map +1 -0
- package/dist/checks/quality/no-temporary-workarounds.d.ts +11 -0
- package/dist/checks/quality/no-temporary-workarounds.d.ts.map +1 -0
- package/dist/checks/quality/no-temporary-workarounds.js +69 -0
- package/dist/checks/quality/no-temporary-workarounds.js.map +1 -0
- package/dist/checks/quality/no-window-alert.d.ts +19 -0
- package/dist/checks/quality/no-window-alert.d.ts.map +1 -0
- package/dist/checks/quality/no-window-alert.js +74 -0
- package/dist/checks/quality/no-window-alert.js.map +1 -0
- package/dist/checks/quality/observability/index.d.ts +2 -0
- package/dist/checks/quality/observability/index.d.ts.map +1 -0
- package/dist/checks/quality/observability/index.js +2 -0
- package/dist/checks/quality/observability/index.js.map +1 -0
- package/dist/checks/quality/observability/pino-serializer-coverage.d.ts +15 -0
- package/dist/checks/quality/observability/pino-serializer-coverage.d.ts.map +1 -0
- package/dist/checks/quality/observability/pino-serializer-coverage.js +209 -0
- package/dist/checks/quality/observability/pino-serializer-coverage.js.map +1 -0
- package/dist/checks/quality/patterns/async-state-pattern.d.ts +14 -0
- package/dist/checks/quality/patterns/async-state-pattern.d.ts.map +1 -0
- package/dist/checks/quality/patterns/async-state-pattern.js +80 -0
- package/dist/checks/quality/patterns/async-state-pattern.js.map +1 -0
- package/dist/checks/quality/patterns/index.d.ts +4 -0
- package/dist/checks/quality/patterns/index.d.ts.map +1 -0
- package/dist/checks/quality/patterns/index.js +4 -0
- package/dist/checks/quality/patterns/index.js.map +1 -0
- package/dist/checks/quality/patterns/no-non-null-assertions.d.ts +10 -0
- package/dist/checks/quality/patterns/no-non-null-assertions.d.ts.map +1 -0
- package/dist/checks/quality/patterns/no-non-null-assertions.js +97 -0
- package/dist/checks/quality/patterns/no-non-null-assertions.js.map +1 -0
- package/dist/checks/quality/patterns/performance-anti-patterns.d.ts +16 -0
- package/dist/checks/quality/patterns/performance-anti-patterns.d.ts.map +1 -0
- package/dist/checks/quality/patterns/performance-anti-patterns.js +239 -0
- package/dist/checks/quality/patterns/performance-anti-patterns.js.map +1 -0
- package/dist/checks/resilience/_helpers/config-validation.d.ts +27 -0
- package/dist/checks/resilience/_helpers/config-validation.d.ts.map +1 -0
- package/dist/checks/resilience/_helpers/config-validation.js +61 -0
- package/dist/checks/resilience/_helpers/config-validation.js.map +1 -0
- package/dist/checks/resilience/batch-operations.d.ts +22 -0
- package/dist/checks/resilience/batch-operations.d.ts.map +1 -0
- package/dist/checks/resilience/batch-operations.js +422 -0
- package/dist/checks/resilience/batch-operations.js.map +1 -0
- package/dist/checks/resilience/cache-ttl-validation.d.ts +13 -0
- package/dist/checks/resilience/cache-ttl-validation.d.ts.map +1 -0
- package/dist/checks/resilience/cache-ttl-validation.js +222 -0
- package/dist/checks/resilience/cache-ttl-validation.js.map +1 -0
- package/dist/checks/resilience/catch-clause-safety.d.ts +12 -0
- package/dist/checks/resilience/catch-clause-safety.d.ts.map +1 -0
- package/dist/checks/resilience/catch-clause-safety.js +110 -0
- package/dist/checks/resilience/catch-clause-safety.js.map +1 -0
- package/dist/checks/resilience/dangerous-config-defaults.d.ts +11 -0
- package/dist/checks/resilience/dangerous-config-defaults.d.ts.map +1 -0
- package/dist/checks/resilience/dangerous-config-defaults.js +304 -0
- package/dist/checks/resilience/dangerous-config-defaults.js.map +1 -0
- package/dist/checks/resilience/error-code-registration.d.ts +11 -0
- package/dist/checks/resilience/error-code-registration.d.ts.map +1 -0
- package/dist/checks/resilience/error-code-registration.js +88 -0
- package/dist/checks/resilience/error-code-registration.js.map +1 -0
- package/dist/checks/resilience/event-patterns.d.ts +21 -0
- package/dist/checks/resilience/event-patterns.d.ts.map +1 -0
- package/dist/checks/resilience/event-patterns.js +232 -0
- package/dist/checks/resilience/event-patterns.js.map +1 -0
- package/dist/checks/resilience/exit-code-correctness.d.ts +12 -0
- package/dist/checks/resilience/exit-code-correctness.d.ts.map +1 -0
- package/dist/checks/resilience/exit-code-correctness.js +107 -0
- package/dist/checks/resilience/exit-code-correctness.js.map +1 -0
- package/dist/checks/resilience/index.d.ts +18 -0
- package/dist/checks/resilience/index.d.ts.map +1 -0
- package/dist/checks/resilience/index.js +18 -0
- package/dist/checks/resilience/index.js.map +1 -0
- package/dist/checks/resilience/no-hardcoded-timeouts.d.ts +10 -0
- package/dist/checks/resilience/no-hardcoded-timeouts.d.ts.map +1 -0
- package/dist/checks/resilience/no-hardcoded-timeouts.js +291 -0
- package/dist/checks/resilience/no-hardcoded-timeouts.js.map +1 -0
- package/dist/checks/resilience/no-process-exit-in-finally.d.ts +11 -0
- package/dist/checks/resilience/no-process-exit-in-finally.d.ts.map +1 -0
- package/dist/checks/resilience/no-process-exit-in-finally.js +89 -0
- package/dist/checks/resilience/no-process-exit-in-finally.js.map +1 -0
- package/dist/checks/resilience/readline-cleanup.d.ts +11 -0
- package/dist/checks/resilience/readline-cleanup.d.ts.map +1 -0
- package/dist/checks/resilience/readline-cleanup.js +107 -0
- package/dist/checks/resilience/readline-cleanup.js.map +1 -0
- package/dist/checks/resilience/recovery-patterns.d.ts +25 -0
- package/dist/checks/resilience/recovery-patterns.d.ts.map +1 -0
- package/dist/checks/resilience/recovery-patterns.js +273 -0
- package/dist/checks/resilience/recovery-patterns.js.map +1 -0
- package/dist/checks/resilience/reentrancy-guard.d.ts +12 -0
- package/dist/checks/resilience/reentrancy-guard.d.ts.map +1 -0
- package/dist/checks/resilience/reentrancy-guard.js +86 -0
- package/dist/checks/resilience/reentrancy-guard.js.map +1 -0
- package/dist/checks/resilience/retry-config-validation.d.ts +13 -0
- package/dist/checks/resilience/retry-config-validation.d.ts.map +1 -0
- package/dist/checks/resilience/retry-config-validation.js +159 -0
- package/dist/checks/resilience/retry-config-validation.js.map +1 -0
- package/dist/checks/resilience/sentry/_helpers/sentry.d.ts +25 -0
- package/dist/checks/resilience/sentry/_helpers/sentry.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/_helpers/sentry.js +68 -0
- package/dist/checks/resilience/sentry/_helpers/sentry.js.map +1 -0
- package/dist/checks/resilience/sentry/index.d.ts +8 -0
- package/dist/checks/resilience/sentry/index.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/index.js +8 -0
- package/dist/checks/resilience/sentry/index.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-dsn-configured.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-dsn-configured.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-dsn-configured.js +55 -0
- package/dist/checks/resilience/sentry/sentry-dsn-configured.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-environment-set.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-environment-set.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-environment-set.js +51 -0
- package/dist/checks/resilience/sentry/sentry-environment-set.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-error-boundary.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-error-boundary.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-error-boundary.js +75 -0
- package/dist/checks/resilience/sentry/sentry-error-boundary.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-pii-scrubbing.d.ts +13 -0
- package/dist/checks/resilience/sentry/sentry-pii-scrubbing.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-pii-scrubbing.js +125 -0
- package/dist/checks/resilience/sentry/sentry-pii-scrubbing.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-release-set.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-release-set.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-release-set.js +51 -0
- package/dist/checks/resilience/sentry/sentry-release-set.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-sample-rate.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-sample-rate.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-sample-rate.js +78 -0
- package/dist/checks/resilience/sentry/sentry-sample-rate.js.map +1 -0
- package/dist/checks/resilience/sentry/sentry-source-maps.d.ts +12 -0
- package/dist/checks/resilience/sentry/sentry-source-maps.d.ts.map +1 -0
- package/dist/checks/resilience/sentry/sentry-source-maps.js +83 -0
- package/dist/checks/resilience/sentry/sentry-source-maps.js.map +1 -0
- package/dist/checks/resilience/service-patterns.d.ts +18 -0
- package/dist/checks/resilience/service-patterns.d.ts.map +1 -0
- package/dist/checks/resilience/service-patterns.js +230 -0
- package/dist/checks/resilience/service-patterns.js.map +1 -0
- package/dist/checks/resilience/timer-lifecycle.d.ts +10 -0
- package/dist/checks/resilience/timer-lifecycle.d.ts.map +1 -0
- package/dist/checks/resilience/timer-lifecycle.js +78 -0
- package/dist/checks/resilience/timer-lifecycle.js.map +1 -0
- package/dist/checks/resilience/transaction-patterns.d.ts +21 -0
- package/dist/checks/resilience/transaction-patterns.d.ts.map +1 -0
- package/dist/checks/resilience/transaction-patterns.js +258 -0
- package/dist/checks/resilience/transaction-patterns.js.map +1 -0
- package/dist/checks/security/__tests__/no-hardcoded-secrets.test.d.ts +9 -0
- package/dist/checks/security/__tests__/no-hardcoded-secrets.test.d.ts.map +1 -0
- package/dist/checks/security/__tests__/no-hardcoded-secrets.test.js +37 -0
- package/dist/checks/security/__tests__/no-hardcoded-secrets.test.js.map +1 -0
- package/dist/checks/security/__tests__/package-supply-chain-policy.test.d.ts +2 -0
- package/dist/checks/security/__tests__/package-supply-chain-policy.test.d.ts.map +1 -0
- package/dist/checks/security/__tests__/package-supply-chain-policy.test.js +128 -0
- package/dist/checks/security/__tests__/package-supply-chain-policy.test.js.map +1 -0
- package/dist/checks/security/api-key-rotation.d.ts +10 -0
- package/dist/checks/security/api-key-rotation.d.ts.map +1 -0
- package/dist/checks/security/api-key-rotation.js +186 -0
- package/dist/checks/security/api-key-rotation.js.map +1 -0
- package/dist/checks/security/auth-middleware-coverage.d.ts +11 -0
- package/dist/checks/security/auth-middleware-coverage.d.ts.map +1 -0
- package/dist/checks/security/auth-middleware-coverage.js +210 -0
- package/dist/checks/security/auth-middleware-coverage.js.map +1 -0
- package/dist/checks/security/auth-route-guard.d.ts +12 -0
- package/dist/checks/security/auth-route-guard.d.ts.map +1 -0
- package/dist/checks/security/auth-route-guard.js +70 -0
- package/dist/checks/security/auth-route-guard.js.map +1 -0
- package/dist/checks/security/cors-configuration.d.ts +11 -0
- package/dist/checks/security/cors-configuration.d.ts.map +1 -0
- package/dist/checks/security/cors-configuration.js +126 -0
- package/dist/checks/security/cors-configuration.js.map +1 -0
- package/dist/checks/security/csp-headers.d.ts +11 -0
- package/dist/checks/security/csp-headers.d.ts.map +1 -0
- package/dist/checks/security/csp-headers.js +192 -0
- package/dist/checks/security/csp-headers.js.map +1 -0
- package/dist/checks/security/dependency-vulnerability-audit.d.ts +15 -0
- package/dist/checks/security/dependency-vulnerability-audit.d.ts.map +1 -0
- package/dist/checks/security/dependency-vulnerability-audit.js +184 -0
- package/dist/checks/security/dependency-vulnerability-audit.js.map +1 -0
- package/dist/checks/security/env-secret-exposure.d.ts +11 -0
- package/dist/checks/security/env-secret-exposure.d.ts.map +1 -0
- package/dist/checks/security/env-secret-exposure.js +127 -0
- package/dist/checks/security/env-secret-exposure.js.map +1 -0
- package/dist/checks/security/hasura-production-config.d.ts +11 -0
- package/dist/checks/security/hasura-production-config.d.ts.map +1 -0
- package/dist/checks/security/hasura-production-config.js +122 -0
- package/dist/checks/security/hasura-production-config.js.map +1 -0
- package/dist/checks/security/index.d.ts +17 -0
- package/dist/checks/security/index.d.ts.map +1 -0
- package/dist/checks/security/index.js +17 -0
- package/dist/checks/security/index.js.map +1 -0
- package/dist/checks/security/jwt-validation.d.ts +11 -0
- package/dist/checks/security/jwt-validation.d.ts.map +1 -0
- package/dist/checks/security/jwt-validation.js +294 -0
- package/dist/checks/security/jwt-validation.js.map +1 -0
- package/dist/checks/security/no-eval.d.ts +16 -0
- package/dist/checks/security/no-eval.d.ts.map +1 -0
- package/dist/checks/security/no-eval.js +83 -0
- package/dist/checks/security/no-eval.js.map +1 -0
- package/dist/checks/security/no-hardcoded-secrets.d.ts +28 -0
- package/dist/checks/security/no-hardcoded-secrets.d.ts.map +1 -0
- package/dist/checks/security/no-hardcoded-secrets.js +209 -0
- package/dist/checks/security/no-hardcoded-secrets.js.map +1 -0
- package/dist/checks/security/package-supply-chain-policy.d.ts +12 -0
- package/dist/checks/security/package-supply-chain-policy.d.ts.map +1 -0
- package/dist/checks/security/package-supply-chain-policy.js +534 -0
- package/dist/checks/security/package-supply-chain-policy.js.map +1 -0
- package/dist/checks/security/rate-limit-coverage.d.ts +10 -0
- package/dist/checks/security/rate-limit-coverage.d.ts.map +1 -0
- package/dist/checks/security/rate-limit-coverage.js +143 -0
- package/dist/checks/security/rate-limit-coverage.js.map +1 -0
- package/dist/checks/security/semgrep-scan.d.ts +13 -0
- package/dist/checks/security/semgrep-scan.d.ts.map +1 -0
- package/dist/checks/security/semgrep-scan.js +86 -0
- package/dist/checks/security/semgrep-scan.js.map +1 -0
- package/dist/checks/security/use-centralized-crypto.d.ts +11 -0
- package/dist/checks/security/use-centralized-crypto.d.ts.map +1 -0
- package/dist/checks/security/use-centralized-crypto.js +129 -0
- package/dist/checks/security/use-centralized-crypto.js.map +1 -0
- package/dist/checks/security/webhook-signature-verification.d.ts +10 -0
- package/dist/checks/security/webhook-signature-verification.d.ts.map +1 -0
- package/dist/checks/security/webhook-signature-verification.js +183 -0
- package/dist/checks/security/webhook-signature-verification.js.map +1 -0
- package/dist/checks/testing/index.d.ts +6 -0
- package/dist/checks/testing/index.d.ts.map +1 -0
- package/dist/checks/testing/index.js +6 -0
- package/dist/checks/testing/index.js.map +1 -0
- package/dist/checks/testing/no-skipped-tests.d.ts +40 -0
- package/dist/checks/testing/no-skipped-tests.d.ts.map +1 -0
- package/dist/checks/testing/no-skipped-tests.js +174 -0
- package/dist/checks/testing/no-skipped-tests.js.map +1 -0
- package/dist/checks/testing/no-stub-tests.d.ts +11 -0
- package/dist/checks/testing/no-stub-tests.d.ts.map +1 -0
- package/dist/checks/testing/no-stub-tests.js +103 -0
- package/dist/checks/testing/no-stub-tests.js.map +1 -0
- package/dist/checks/testing/test-convention-consistency.d.ts +14 -0
- package/dist/checks/testing/test-convention-consistency.d.ts.map +1 -0
- package/dist/checks/testing/test-convention-consistency.js +93 -0
- package/dist/checks/testing/test-convention-consistency.js.map +1 -0
- package/dist/checks/testing/test-file-naming.d.ts +13 -0
- package/dist/checks/testing/test-file-naming.d.ts.map +1 -0
- package/dist/checks/testing/test-file-naming.js +218 -0
- package/dist/checks/testing/test-file-naming.js.map +1 -0
- package/dist/checks/testing/test-file-pairing.d.ts +13 -0
- package/dist/checks/testing/test-file-pairing.d.ts.map +1 -0
- package/dist/checks/testing/test-file-pairing.js +274 -0
- package/dist/checks/testing/test-file-pairing.js.map +1 -0
- package/dist/display/architecture.d.ts +9 -0
- package/dist/display/architecture.d.ts.map +1 -0
- package/dist/display/architecture.js +29 -0
- package/dist/display/architecture.js.map +1 -0
- package/dist/display/index.d.ts +20 -0
- package/dist/display/index.d.ts.map +1 -0
- package/dist/display/index.js +30 -0
- package/dist/display/index.js.map +1 -0
- package/dist/display/quality.d.ts +7 -0
- package/dist/display/quality.d.ts.map +1 -0
- package/dist/display/quality.js +34 -0
- package/dist/display/quality.js.map +1 -0
- package/dist/display/resilience.d.ts +7 -0
- package/dist/display/resilience.d.ts.map +1 -0
- package/dist/display/resilience.js +36 -0
- package/dist/display/resilience.js.map +1 -0
- package/dist/display/security-testing.d.ts +9 -0
- package/dist/display/security-testing.d.ts.map +1 -0
- package/dist/display/security-testing.js +31 -0
- package/dist/display/security-testing.js.map +1 -0
- package/dist/display/types.d.ts +6 -0
- package/dist/display/types.d.ts.map +1 -0
- package/dist/display/types.js +6 -0
- package/dist/display/types.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// @fitness-ignore-file batch-operation-limits -- iterates bounded collection (workspace package roots and their dist/ siblings; small N per repo)
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Stale build artifact detection
|
|
4
|
+
* @module checks-builtin/checks/architecture/stale-build-artifacts
|
|
5
|
+
*
|
|
6
|
+
* Detects .js, .d.ts, and .js.map files in source directories that should
|
|
7
|
+
* only exist in dist/. These cause confusing import resolution bugs where
|
|
8
|
+
* the compiled artifact shadows the source file.
|
|
9
|
+
*/
|
|
10
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
11
|
+
const SOURCE_DIRS = ['src/', 'lib/'];
|
|
12
|
+
const ARTIFACT_EXTENSIONS = ['.js', '.d.ts', '.js.map'];
|
|
13
|
+
function isArtifactInSource(filePath) {
|
|
14
|
+
// Must be in a source directory
|
|
15
|
+
const inSource = SOURCE_DIRS.some((d) => filePath.includes(`/${d}`) || filePath.startsWith(d));
|
|
16
|
+
if (!inSource)
|
|
17
|
+
return null;
|
|
18
|
+
// Must not be in dist/, node_modules/, or .cache/
|
|
19
|
+
if (filePath.includes('/dist/') ||
|
|
20
|
+
filePath.includes('/node_modules/') ||
|
|
21
|
+
filePath.includes('/.cache/'))
|
|
22
|
+
return null;
|
|
23
|
+
for (const ext of ARTIFACT_EXTENSIONS) {
|
|
24
|
+
if (filePath.endsWith(ext))
|
|
25
|
+
return { ext };
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
export const staleBuildArtifacts = defineCheck({
|
|
30
|
+
id: '8d36209b-5aeb-4ab0-8255-3134a20fdfd5',
|
|
31
|
+
slug: 'stale-build-artifacts',
|
|
32
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
33
|
+
confidence: 'high',
|
|
34
|
+
description: 'Detects compiled .js/.d.ts/.js.map files in source directories that should only exist in dist/',
|
|
35
|
+
tags: ['architecture', 'build', 'hygiene'],
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- AnalyzeAllCheckConfig requires Promise<CheckViolation[]>; this implementation is synchronous
|
|
37
|
+
async analyzeAll(files) {
|
|
38
|
+
const violations = [];
|
|
39
|
+
for (const filePath of files.paths) {
|
|
40
|
+
const result = isArtifactInSource(filePath);
|
|
41
|
+
if (result) {
|
|
42
|
+
violations.push({
|
|
43
|
+
filePath,
|
|
44
|
+
line: 1,
|
|
45
|
+
message: `Stale build artifact (${result.ext}) found in source directory. This file should only exist in dist/.`,
|
|
46
|
+
severity: 'error',
|
|
47
|
+
suggestion: `Delete ${filePath} and ensure .gitignore excludes compiled files from source directories.`,
|
|
48
|
+
type: 'STALE_ARTIFACT',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return violations;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=stale-build-artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-build-artifacts.js","sourceRoot":"","sources":["../../../src/checks/architecture/stale-build-artifacts.ts"],"names":[],"mappings":"AAAA,kJAAkJ;AAClJ;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAA0C,MAAM,sBAAsB,CAAC;AAE3F,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AAExD,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,gCAAgC;IAChC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,kDAAkD;IAClD,IACE,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC3B,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QACnC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;QAE7B,OAAO,IAAI,CAAC;IAEd,KAAK,MAAM,GAAG,IAAI,mBAAmB,EAAE,CAAC;QACtC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IAC7C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;IAC7C,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,uBAAuB;IAC7B,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE;IAC9E,UAAU,EAAE,MAAM;IAClB,WAAW,EACT,gGAAgG;IAClG,IAAI,EAAE,CAAC,cAAc,EAAE,OAAO,EAAE,SAAS,CAAC;IAE1C,4JAA4J;IAC5J,KAAK,CAAC,UAAU,CAAC,KAAmB;QAClC,MAAM,UAAU,GAAqB,EAAE,CAAC;QAExC,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,MAAM,EAAE,CAAC;gBACX,UAAU,CAAC,IAAI,CAAC;oBACd,QAAQ;oBACR,IAAI,EAAE,CAAC;oBACP,OAAO,EAAE,yBAAyB,MAAM,CAAC,GAAG,oEAAoE;oBAChH,QAAQ,EAAE,OAAO;oBACjB,UAAU,EAAE,UAAU,QAAQ,yEAAyE;oBACvG,IAAI,EAAE,gBAAgB;iBACvB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type CheckViolation, type FileAccessor } from '@opensip-cli/fitness';
|
|
2
|
+
/** The `opensipTools` manifest block as declared in a tool's `package.json`. */
|
|
3
|
+
interface OpensipToolsBlock {
|
|
4
|
+
readonly kind?: unknown;
|
|
5
|
+
readonly id?: unknown;
|
|
6
|
+
readonly apiVersion?: unknown;
|
|
7
|
+
readonly commands?: unknown;
|
|
8
|
+
}
|
|
9
|
+
interface PackageJson {
|
|
10
|
+
readonly opensipTools?: OpensipToolsBlock;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Pure analysis over a single package.json's parsed content. Returns `[]` for
|
|
14
|
+
* any package that is NOT a tool package (no `opensipTools.kind === 'tool'`),
|
|
15
|
+
* so the check is self-targeting. Exported for unit tests.
|
|
16
|
+
*/
|
|
17
|
+
export declare function analyzeToolHasManifest(pkg: PackageJson, filePath: string): CheckViolation[];
|
|
18
|
+
/**
|
|
19
|
+
* Walk every `package.json` in the scanned set and validate each tool
|
|
20
|
+
* package's manifest. Self-targeting: non-tool packages and non-package.json
|
|
21
|
+
* files contribute nothing. Exported so unit tests can drive it with an
|
|
22
|
+
* in-memory `FileAccessor` without standing up the full Check framework.
|
|
23
|
+
*/
|
|
24
|
+
export declare function analyzeAllToolManifests(files: FileAccessor): Promise<CheckViolation[]>;
|
|
25
|
+
export declare const toolHasManifest: import("@opensip-cli/fitness").Check;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=tool-has-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-has-manifest.d.ts","sourceRoot":"","sources":["../../../src/checks/architecture/tool-has-manifest.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAe,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAQ3F,gFAAgF;AAChF,UAAU,iBAAiB;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC;CAC3C;AA4ED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAI3F;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAmB5F;AAED,eAAO,MAAM,eAAe,sCAS1B,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// @fitness-ignore-file performance-anti-patterns -- the only async op is reading the analyzed workspace's package.json files in parallel; concurrency is bounded by the package.json count (a handful, not attacker-controlled), matching register-tools.ts's identical bounded-IO waiver.
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Every first-party tool package must declare a conformant
|
|
4
|
+
* static plugin manifest (release 2.9.0, identity & compatibility — Phase 5).
|
|
5
|
+
*
|
|
6
|
+
* Per north-star Principle 6, the guardrail is the definition of done: this
|
|
7
|
+
* check is what prevents the next release from re-accumulating the
|
|
8
|
+
* undeclared-input drift the 2.x ladder paid down. A tool that the host admits through
|
|
9
|
+
* the single compatibility gate (`admitTool` in core) must first be readable
|
|
10
|
+
* as a static `ToolPluginManifest` — `package.json#opensipTools` with
|
|
11
|
+
* `kind:'tool'`, a non-empty `id`, a numeric `apiVersion`, and a non-empty
|
|
12
|
+
* `commands` array of `{ name, description }`. Without a conformant manifest
|
|
13
|
+
* the host cannot inspect the tool's identity + contract epoch BEFORE
|
|
14
|
+
* importing its runtime module, which is the whole point of the manifest.
|
|
15
|
+
*
|
|
16
|
+
* SELF-TARGETING — the check identifies a "first-party tool package" by the
|
|
17
|
+
* marker the manifest itself carries: any `package.json` whose
|
|
18
|
+
* `opensipTools.kind === 'tool'` IS a tool package and therefore must carry a
|
|
19
|
+
* conformant manifest. This is robust (it does not hard-code the three engine
|
|
20
|
+
* paths) and additive-safe (a future fourth tool is covered the moment it
|
|
21
|
+
* declares `kind:'tool'`). It runs over `analyzeAll` so it sees every
|
|
22
|
+
* `package.json` in the scanned set; `node_modules` is excluded by the
|
|
23
|
+
* `configs` target.
|
|
24
|
+
*
|
|
25
|
+
* SCOPE — opensip-cli' own monorepo. The marker (`opensipTools.kind`) is a
|
|
26
|
+
* platform convention, so the check is inert in adopter repos whose packages
|
|
27
|
+
* never declare it (zero `kind:'tool'` package.json → zero findings).
|
|
28
|
+
*/
|
|
29
|
+
import path from 'node:path';
|
|
30
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
31
|
+
function isJsonObject(value) {
|
|
32
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Validate the `commands` array (non-empty, each entry a `{ name, description }`
|
|
36
|
+
* record). Split out of {@link checkManifestBlock} so each function stays below
|
|
37
|
+
* the cognitive-complexity ceiling.
|
|
38
|
+
*/
|
|
39
|
+
function checkCommands(commands, push) {
|
|
40
|
+
if (!Array.isArray(commands) || commands.length === 0) {
|
|
41
|
+
push('commands', 'must be a non-empty array of { name, description }');
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
for (const [i, entry] of commands.entries()) {
|
|
45
|
+
if (!isJsonObject(entry)) {
|
|
46
|
+
push('commands', `entry [${i}] must be an object with { name, description }`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const cmd = entry;
|
|
50
|
+
if (typeof cmd.name !== 'string' || cmd.name === '') {
|
|
51
|
+
push('commands', `entry [${i}] is missing a non-empty string "name"`);
|
|
52
|
+
}
|
|
53
|
+
if (typeof cmd.description !== 'string') {
|
|
54
|
+
push('commands', `entry [${i}] is missing a string "description"`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function checkManifestBlock(block, filePath) {
|
|
59
|
+
const violations = [];
|
|
60
|
+
const relPath = path.relative(process.cwd(), filePath);
|
|
61
|
+
const push = (field, message) => {
|
|
62
|
+
violations.push({
|
|
63
|
+
line: 1,
|
|
64
|
+
filePath,
|
|
65
|
+
message: `${relPath}: opensipTools.${field} — ${message}`,
|
|
66
|
+
severity: 'error',
|
|
67
|
+
suggestion: 'A first-party tool must declare a conformant manifest the host can read ' +
|
|
68
|
+
'before importing it: { kind: "tool", id: "<id>", apiVersion: <number>, ' +
|
|
69
|
+
'commands: [{ name, description }, ...] } (release 3.0.0).',
|
|
70
|
+
type: `manifest-${field}`,
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
// kind — already 'tool' by selection, but assert explicitly so a future
|
|
74
|
+
// refactor of the selector cannot silently weaken the contract.
|
|
75
|
+
if (block.kind !== 'tool') {
|
|
76
|
+
push('kind', `must be the literal "tool" (got ${JSON.stringify(block.kind)})`);
|
|
77
|
+
}
|
|
78
|
+
if (typeof block.id !== 'string' || block.id === '') {
|
|
79
|
+
push('id', 'must be a non-empty string identifying the tool');
|
|
80
|
+
}
|
|
81
|
+
if (typeof block.apiVersion !== 'number') {
|
|
82
|
+
push('apiVersion', 'must be a number (the plugin-API epoch the tool targets)');
|
|
83
|
+
}
|
|
84
|
+
checkCommands(block.commands, push);
|
|
85
|
+
return violations;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Pure analysis over a single package.json's parsed content. Returns `[]` for
|
|
89
|
+
* any package that is NOT a tool package (no `opensipTools.kind === 'tool'`),
|
|
90
|
+
* so the check is self-targeting. Exported for unit tests.
|
|
91
|
+
*/
|
|
92
|
+
export function analyzeToolHasManifest(pkg, filePath) {
|
|
93
|
+
const block = pkg.opensipTools;
|
|
94
|
+
if (!isJsonObject(block) || block.kind !== 'tool')
|
|
95
|
+
return [];
|
|
96
|
+
return checkManifestBlock(block, filePath);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Walk every `package.json` in the scanned set and validate each tool
|
|
100
|
+
* package's manifest. Self-targeting: non-tool packages and non-package.json
|
|
101
|
+
* files contribute nothing. Exported so unit tests can drive it with an
|
|
102
|
+
* in-memory `FileAccessor` without standing up the full Check framework.
|
|
103
|
+
*/
|
|
104
|
+
export async function analyzeAllToolManifests(files) {
|
|
105
|
+
const violations = [];
|
|
106
|
+
// Sequential read over the analyzed workspace's package.json files (bounded by
|
|
107
|
+
// package count); the file-level performance-anti-patterns waiver above covers
|
|
108
|
+
// the await-in-loop — sequential avoids the no-unbounded-concurrency a
|
|
109
|
+
// Promise.all(map) would trip, and the read count is tiny.
|
|
110
|
+
for (const filePath of files.paths) {
|
|
111
|
+
if (path.basename(filePath) !== 'package.json')
|
|
112
|
+
continue;
|
|
113
|
+
let pkg;
|
|
114
|
+
try {
|
|
115
|
+
pkg = JSON.parse(await files.read(filePath));
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// A malformed package.json is some other check's concern; a tool
|
|
119
|
+
// manifest cannot be read from it either way, so skip silently.
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
violations.push(...analyzeToolHasManifest(pkg, filePath));
|
|
123
|
+
}
|
|
124
|
+
return violations;
|
|
125
|
+
}
|
|
126
|
+
export const toolHasManifest = defineCheck({
|
|
127
|
+
id: 'f1427a05-0d4d-4ad7-9077-c04292b630dc',
|
|
128
|
+
slug: 'tool-has-manifest',
|
|
129
|
+
description: 'Every first-party tool package must declare a conformant opensipTools manifest (kind/id/apiVersion/commands) the host can read before import (release 3.0.0)',
|
|
130
|
+
scope: { languages: ['typescript'], concerns: ['config'] },
|
|
131
|
+
tags: ['architecture'],
|
|
132
|
+
contentFilter: 'raw',
|
|
133
|
+
analyzeAll: analyzeAllToolManifests,
|
|
134
|
+
});
|
|
135
|
+
//# sourceMappingURL=tool-has-manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-has-manifest.js","sourceRoot":"","sources":["../../../src/checks/architecture/tool-has-manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type CheckViolation } from '@opensip-cli/fitness';
|
|
2
|
+
/** Input for the pure detector (fs + content injected for testability). */
|
|
3
|
+
export interface VitestExtendsBaseInput {
|
|
4
|
+
readonly vitestConfigPaths: readonly string[];
|
|
5
|
+
readonly exists: (filePath: string) => boolean;
|
|
6
|
+
readonly readContent: (filePath: string) => string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Pure detector. Returns a violation for each `vitest.config` that does NOT
|
|
10
|
+
* reference the shared base — but ONLY when a shared base exists in the repo
|
|
11
|
+
* (otherwise returns `[]`, keeping the check inert for non-adopters).
|
|
12
|
+
*/
|
|
13
|
+
export declare function detectConfigsNotExtendingBase(input: VitestExtendsBaseInput): CheckViolation[];
|
|
14
|
+
export declare const vitestConfigExtendsBase: import("@opensip-cli/fitness").Check;
|
|
15
|
+
//# sourceMappingURL=vitest-config-extends-base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-config-extends-base.d.ts","sourceRoot":"","sources":["../../../src/checks/architecture/vitest-config-extends-base.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAe,KAAK,cAAc,EAAqB,MAAM,sBAAsB,CAAC;AA8B3F,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAC/C,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACpD;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,sBAAsB,GAAG,cAAc,EAAE,CAoB7F;AAED,eAAO,MAAM,uBAAuB,sCA8BlC,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// @fitness-ignore-file fitness-check-standards -- Uses fs to detect the shared base config on disk, not source-file content
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Vitest config must extend the shared base check.
|
|
4
|
+
*
|
|
5
|
+
* Self-activating guardrail: ONLY when a repo centralizes its vitest defaults in
|
|
6
|
+
* `.config/vitest.base.{ts,mts}` does this check require every per-package
|
|
7
|
+
* `vitest.config.{ts,mts}` to extend it (import the base + `mergeConfig`). A repo
|
|
8
|
+
* with no shared base (most adopters) is unaffected — the check returns no
|
|
9
|
+
* findings, so it never fires on an unrelated project's vitest config.
|
|
10
|
+
*
|
|
11
|
+
* Rationale: opensip-cli' v2.7.0 release failed at the pre-publish gate because
|
|
12
|
+
* `hookTimeout` had never been set (10s default) in any of ~31 copy-pasted
|
|
13
|
+
* per-package vitest configs, and a catalog-building `beforeAll` blew it on a slow
|
|
14
|
+
* CI runner. The fix centralized the timeouts into `.config/vitest.base.ts`; this
|
|
15
|
+
* check is the regression guard — a new package that rolls its own config
|
|
16
|
+
* (omitting the base) would silently lose the shared timeouts/defaults, exactly
|
|
17
|
+
* the gap that caused the failure.
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'node:fs';
|
|
20
|
+
import * as path from 'node:path';
|
|
21
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
22
|
+
/** A per-package vitest config filename this check governs. Real-run fixture
|
|
23
|
+
* exclusion is handled by the project config's `globalExcludes` (the
|
|
24
|
+
* `__fixtures__` glob), NOT here — so the per-check fixture-coverage harness,
|
|
25
|
+
* which runs from inside a fixture tree, still exercises this check. */
|
|
26
|
+
function isVitestConfigPath(filePath) {
|
|
27
|
+
const base = path.basename(filePath);
|
|
28
|
+
return base === 'vitest.config.ts' || base === 'vitest.config.mts';
|
|
29
|
+
}
|
|
30
|
+
/** Shared-base filenames that satisfy "the repo centralizes vitest defaults". */
|
|
31
|
+
const BASE_REL_CANDIDATES = ['.config/vitest.base.ts', '.config/vitest.base.mts'];
|
|
32
|
+
/** Walk up from a config file to find a repo-root that holds the shared base. */
|
|
33
|
+
function findSharedBase(fromConfigPath, exists) {
|
|
34
|
+
let dir = path.dirname(path.resolve(fromConfigPath));
|
|
35
|
+
for (;;) {
|
|
36
|
+
if (BASE_REL_CANDIDATES.some((rel) => exists(path.join(dir, rel))))
|
|
37
|
+
return true;
|
|
38
|
+
const parent = path.dirname(dir);
|
|
39
|
+
if (parent === dir)
|
|
40
|
+
return false;
|
|
41
|
+
dir = parent;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Token a config must contain to count as "extends the base" — it appears in
|
|
45
|
+
* the base import specifier (`.../.config/vitest.base.js`). Loose by intent: any
|
|
46
|
+
* `.js`/`.ts`/`.mts` specifier and any relative depth match. */
|
|
47
|
+
const BASE_REFERENCE_TOKEN = 'vitest.base';
|
|
48
|
+
/**
|
|
49
|
+
* Pure detector. Returns a violation for each `vitest.config` that does NOT
|
|
50
|
+
* reference the shared base — but ONLY when a shared base exists in the repo
|
|
51
|
+
* (otherwise returns `[]`, keeping the check inert for non-adopters).
|
|
52
|
+
*/
|
|
53
|
+
export function detectConfigsNotExtendingBase(input) {
|
|
54
|
+
if (input.vitestConfigPaths.length === 0)
|
|
55
|
+
return [];
|
|
56
|
+
const baseExists = findSharedBase(input.vitestConfigPaths[0], input.exists);
|
|
57
|
+
if (!baseExists)
|
|
58
|
+
return [];
|
|
59
|
+
const violations = [];
|
|
60
|
+
for (const configPath of input.vitestConfigPaths) {
|
|
61
|
+
if (input.readContent(configPath).includes(BASE_REFERENCE_TOKEN))
|
|
62
|
+
continue;
|
|
63
|
+
violations.push({
|
|
64
|
+
filePath: configPath,
|
|
65
|
+
line: 1,
|
|
66
|
+
severity: 'error',
|
|
67
|
+
type: 'vitest-config-extends-base',
|
|
68
|
+
message: 'vitest.config does not extend the shared .config/vitest.base — its timeouts/defaults will diverge from the rest of the workspace (the gap that broke the v2.7.0 release).',
|
|
69
|
+
suggestion: "Import { vitestBase } from the repo's `.config/vitest.base.js` and `export default mergeConfig(vitestBase, defineConfig({ /* include + coverage only */ }))`.",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return violations;
|
|
73
|
+
}
|
|
74
|
+
export const vitestConfigExtendsBase = defineCheck({
|
|
75
|
+
id: 'f1b9c2e4-7a3d-4c8e-9b6f-2d5a1e8c4b07',
|
|
76
|
+
slug: 'vitest-config-extends-base',
|
|
77
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
78
|
+
confidence: 'high',
|
|
79
|
+
description: 'Per-package vitest configs must extend the shared .config/vitest.base (when one exists)',
|
|
80
|
+
longDescription: `**Purpose:** When a repo centralizes its vitest defaults in \`.config/vitest.base.{ts,mts}\`, every per-package \`vitest.config.{ts,mts}\` must extend it (import the base + \`mergeConfig\`), so shared settings like \`testTimeout\`/\`hookTimeout\` cannot silently diverge.
|
|
81
|
+
|
|
82
|
+
**Detects:**
|
|
83
|
+
- A \`vitest.config.ts\` / \`vitest.config.mts\` that does NOT reference the shared base, in a repo that has a \`.config/vitest.base.{ts,mts}\`.
|
|
84
|
+
|
|
85
|
+
**Self-activating / adopter-safe:** if the repo has no \`.config/vitest.base\`, the check returns no findings — it never fires on an unrelated project's vitest config.
|
|
86
|
+
|
|
87
|
+
**Why it matters:** opensip-cli' v2.7.0 release failed at the pre-publish test gate because \`hookTimeout\` was never set (10s default) across ~31 copy-pasted per-package configs and a catalog-building \`beforeAll\` blew it on a slow CI runner. Centralizing the timeouts fixed it; this check prevents a new package from re-introducing the gap by rolling its own config.`,
|
|
88
|
+
tags: ['architecture', 'testing'],
|
|
89
|
+
async analyzeAll(files) {
|
|
90
|
+
const vitestConfigPaths = files.paths.filter(isVitestConfigPath);
|
|
91
|
+
if (vitestConfigPaths.length === 0)
|
|
92
|
+
return [];
|
|
93
|
+
// Content via the framework's size-managed BATCH reader (not raw
|
|
94
|
+
// fs.readFileSync, and not a sequential await loop); fs is used ONLY for base
|
|
95
|
+
// existence (no content read, no OOM surface).
|
|
96
|
+
const contents = await files.readMany(vitestConfigPaths);
|
|
97
|
+
return detectConfigsNotExtendingBase({
|
|
98
|
+
vitestConfigPaths,
|
|
99
|
+
exists: (filePath) => fs.existsSync(filePath),
|
|
100
|
+
readContent: (filePath) => contents.get(filePath) ?? '',
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=vitest-config-extends-base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-config-extends-base.js","sourceRoot":"","sources":["../../../src/checks/architecture/vitest-config-extends-base.ts"],"names":[],"mappings":"AAAA,4HAA4H;AAC5H;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,WAAW,EAA0C,MAAM,sBAAsB,CAAC;AAE3F;;;yEAGyE;AACzE,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,OAAO,IAAI,KAAK,kBAAkB,IAAI,IAAI,KAAK,mBAAmB,CAAC;AACrE,CAAC;AAED,iFAAiF;AACjF,MAAM,mBAAmB,GAAG,CAAC,wBAAwB,EAAE,yBAAyB,CAAU,CAAC;AAE3F,iFAAiF;AACjF,SAAS,cAAc,CAAC,cAAsB,EAAE,MAA8B;IAC5E,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;IACrD,SAAS,CAAC;QACR,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,KAAK,CAAC;QACjC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED;;iEAEiE;AACjE,MAAM,oBAAoB,GAAG,aAAa,CAAC;AAS3C;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,KAA6B;IACzE,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACpD,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5E,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,UAAU,GAAqB,EAAE,CAAC;IACxC,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;QACjD,IAAI,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC;YAAE,SAAS;QAC3E,UAAU,CAAC,IAAI,CAAC;YACd,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,CAAC;YACP,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,4BAA4B;YAClC,OAAO,EACL,2KAA2K;YAC7K,UAAU,EACR,+JAA+J;SAClK,CAAC,CAAC;IACL,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,WAAW,CAAC;IACjD,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,4BAA4B;IAClC,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE;IAC9E,UAAU,EAAE,MAAM;IAClB,WAAW,EACT,yFAAyF;IAC3F,eAAe,EAAE;;;;;;;kXAO+V;IAChX,IAAI,EAAE,CAAC,cAAc,EAAE,SAAS,CAAC;IAEjC,KAAK,CAAC,UAAU,CAAC,KAAmB;QAClC,MAAM,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACjE,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC9C,iEAAiE;QACjE,8EAA8E;QAC9E,+CAA+C;QAC/C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;QACzD,OAAO,6BAA6B,CAAC;YACnC,iBAAiB;YACjB,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC7C,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE;SACxD,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Vitest config required with tests check
|
|
3
|
+
*
|
|
4
|
+
* Ensures every workspace package that contains test files
|
|
5
|
+
* (`*.test.ts` / `*.test.tsx`) ships a `vitest.config.ts` (or
|
|
6
|
+
* `vitest.config.mts`) at its package root — unless the workspace root
|
|
7
|
+
* centralizes a vitest config.
|
|
8
|
+
*
|
|
9
|
+
* Rationale: in a monorepo each package commonly owns its own
|
|
10
|
+
* `vitest.config.ts` carrying per-package coverage thresholds. A package
|
|
11
|
+
* that accrues tests but no config runs config-less with no coverage
|
|
12
|
+
* floor, letting coverage silently drift. This check catches that drift.
|
|
13
|
+
*/
|
|
14
|
+
import { type CheckViolation } from '@opensip-cli/fitness';
|
|
15
|
+
/**
|
|
16
|
+
* Filesystem port. Injected so the pure detector can be unit-tested
|
|
17
|
+
* without touching the real disk.
|
|
18
|
+
*/
|
|
19
|
+
export interface VitestConfigFsPort {
|
|
20
|
+
/** True if `filePath` exists. */
|
|
21
|
+
exists(filePath: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* True if at least one `*.test.ts` / `*.test.tsx` file exists anywhere
|
|
24
|
+
* under `packageDir` (excluding nested package roots, node_modules,
|
|
25
|
+
* fixtures, and build output).
|
|
26
|
+
*/
|
|
27
|
+
hasTestFiles(packageDir: string): boolean;
|
|
28
|
+
}
|
|
29
|
+
/** Default filesystem port backed by `node:fs`. */
|
|
30
|
+
export declare const nodeFsPort: VitestConfigFsPort;
|
|
31
|
+
/**
|
|
32
|
+
* Pure detector. Given the discovered package-root `package.json` paths and
|
|
33
|
+
* a filesystem port, returns one violation per package that has tests but no
|
|
34
|
+
* satisfying vitest config.
|
|
35
|
+
*
|
|
36
|
+
* A package is satisfied if it has a per-package config OR a centralized
|
|
37
|
+
* config exists at the workspace root (the common ancestor of all package
|
|
38
|
+
* roots, or one level above it).
|
|
39
|
+
*/
|
|
40
|
+
export declare function detectMissingVitestConfig(packageJsonPaths: readonly string[], port: VitestConfigFsPort): CheckViolation[];
|
|
41
|
+
/**
|
|
42
|
+
* Check: architecture/vitest-config-required-with-tests
|
|
43
|
+
*
|
|
44
|
+
* Every workspace package that contains test files must ship a
|
|
45
|
+
* `vitest.config.ts` (or `.mts`) at its package root, unless the
|
|
46
|
+
* workspace root centralizes a vitest config.
|
|
47
|
+
*/
|
|
48
|
+
export declare const vitestConfigRequiredWithTests: import("@opensip-cli/fitness").Check;
|
|
49
|
+
//# sourceMappingURL=vitest-config-required-with-tests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-config-required-with-tests.d.ts","sourceRoot":"","sources":["../../../src/checks/architecture/vitest-config-required-with-tests.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAe,KAAK,cAAc,EAAqB,MAAM,sBAAsB,CAAC;AA2B3F;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,iCAAiC;IACjC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC;;;;OAIG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3C;AA4CD,mDAAmD;AACnD,eAAO,MAAM,UAAU,EAAE,kBAGxB,CAAC;AAqCF;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,gBAAgB,EAAE,SAAS,MAAM,EAAE,EACnC,IAAI,EAAE,kBAAkB,GACvB,cAAc,EAAE,CAkDlB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,sCA4BxC,CAAC"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// @fitness-ignore-file fitness-check-standards -- Uses fs for directory walking / file existence, not source file content
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Vitest config required with tests check
|
|
4
|
+
*
|
|
5
|
+
* Ensures every workspace package that contains test files
|
|
6
|
+
* (`*.test.ts` / `*.test.tsx`) ships a `vitest.config.ts` (or
|
|
7
|
+
* `vitest.config.mts`) at its package root — unless the workspace root
|
|
8
|
+
* centralizes a vitest config.
|
|
9
|
+
*
|
|
10
|
+
* Rationale: in a monorepo each package commonly owns its own
|
|
11
|
+
* `vitest.config.ts` carrying per-package coverage thresholds. A package
|
|
12
|
+
* that accrues tests but no config runs config-less with no coverage
|
|
13
|
+
* floor, letting coverage silently drift. This check catches that drift.
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from 'node:fs';
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
18
|
+
/** Per-package vitest config filenames that satisfy the requirement. */
|
|
19
|
+
const PACKAGE_CONFIG_FILES = ['vitest.config.ts', 'vitest.config.mts'];
|
|
20
|
+
/**
|
|
21
|
+
* Workspace-root config filenames that, when present, satisfy the
|
|
22
|
+
* requirement for ALL packages (a repo may centralize vitest config).
|
|
23
|
+
*/
|
|
24
|
+
const WORKSPACE_CONFIG_FILES = [
|
|
25
|
+
'vitest.config.ts',
|
|
26
|
+
'vitest.config.mts',
|
|
27
|
+
'vitest.workspace.ts',
|
|
28
|
+
];
|
|
29
|
+
/** Directory names never descended into when scanning for test files. */
|
|
30
|
+
const SKIP_DIRS = new Set([
|
|
31
|
+
'node_modules',
|
|
32
|
+
'__fixtures__',
|
|
33
|
+
'__mocks__',
|
|
34
|
+
'fixtures',
|
|
35
|
+
'dist',
|
|
36
|
+
'build',
|
|
37
|
+
'coverage',
|
|
38
|
+
'.git',
|
|
39
|
+
]);
|
|
40
|
+
/** Is this filename a test file we care about? */
|
|
41
|
+
function isTestFile(name) {
|
|
42
|
+
return name.endsWith('.test.ts') || name.endsWith('.test.tsx');
|
|
43
|
+
}
|
|
44
|
+
/** Read directory entries, returning `null` when the directory is unreadable. */
|
|
45
|
+
function readEntries(dir) {
|
|
46
|
+
try {
|
|
47
|
+
return fs.readdirSync(dir, { withFileTypes: true });
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// @swallow-ok unreadable directory -> treat as no tests
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** True if a directory entry is a subdirectory we should descend into. */
|
|
55
|
+
function isDescendableDir(entry) {
|
|
56
|
+
return entry.isDirectory() && !SKIP_DIRS.has(entry.name);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Recursively search `dir` for a test file, stopping at the first hit.
|
|
60
|
+
* Does NOT descend into nested package roots (a dir containing its own
|
|
61
|
+
* `package.json`) so a parent package isn't blamed for a child's tests,
|
|
62
|
+
* nor into skip dirs (node_modules, fixtures, build output).
|
|
63
|
+
*/
|
|
64
|
+
function hasTestFilesIn(dir, isRoot) {
|
|
65
|
+
const entries = readEntries(dir);
|
|
66
|
+
if (entries === null)
|
|
67
|
+
return false;
|
|
68
|
+
// A nested package root owns its own tests; don't count them here.
|
|
69
|
+
const isNestedPackageRoot = !isRoot && entries.some((e) => e.isFile() && e.name === 'package.json');
|
|
70
|
+
if (isNestedPackageRoot)
|
|
71
|
+
return false;
|
|
72
|
+
if (entries.some((e) => e.isFile() && isTestFile(e.name)))
|
|
73
|
+
return true;
|
|
74
|
+
return entries
|
|
75
|
+
.filter(isDescendableDir)
|
|
76
|
+
.some((e) => hasTestFilesIn(path.join(dir, e.name), false));
|
|
77
|
+
}
|
|
78
|
+
/** Default filesystem port backed by `node:fs`. */
|
|
79
|
+
export const nodeFsPort = {
|
|
80
|
+
exists: (filePath) => fs.existsSync(filePath),
|
|
81
|
+
hasTestFiles: (packageDir) => hasTestFilesIn(packageDir, true),
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* The directory shared by every input path. For a single path this is its
|
|
85
|
+
* own directory. Used to locate the workspace-root region without relying
|
|
86
|
+
* on `process.cwd()` (which, under the in-process test harness, points at
|
|
87
|
+
* the runner's directory, not the project being analyzed).
|
|
88
|
+
*/
|
|
89
|
+
function commonAncestorDir(paths) {
|
|
90
|
+
if (paths.length === 0)
|
|
91
|
+
return null;
|
|
92
|
+
const segmentLists = paths.map((p) => path.dirname(p).split(path.sep));
|
|
93
|
+
const [first, ...rest] = segmentLists;
|
|
94
|
+
if (!first)
|
|
95
|
+
return null;
|
|
96
|
+
const common = [];
|
|
97
|
+
for (const [index, seg] of first.entries()) {
|
|
98
|
+
if (!rest.every((segs) => segs[index] === seg))
|
|
99
|
+
break;
|
|
100
|
+
common.push(seg);
|
|
101
|
+
}
|
|
102
|
+
const joined = common.join(path.sep);
|
|
103
|
+
return joined === '' ? path.sep : joined;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Candidate workspace-root directories: the common ancestor of all package
|
|
107
|
+
* roots, plus its immediate parent (covering both a flat root and the
|
|
108
|
+
* common `packages/*` layout where the centralized config sits one level
|
|
109
|
+
* above the shared `packages/` ancestor).
|
|
110
|
+
*/
|
|
111
|
+
function workspaceRootCandidates(packageDirs) {
|
|
112
|
+
const ancestor = commonAncestorDir(packageDirs.map((d) => path.join(d, 'x')));
|
|
113
|
+
if (ancestor === null)
|
|
114
|
+
return [];
|
|
115
|
+
const parent = path.dirname(ancestor);
|
|
116
|
+
return parent === ancestor ? [ancestor] : [ancestor, parent];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Pure detector. Given the discovered package-root `package.json` paths and
|
|
120
|
+
* a filesystem port, returns one violation per package that has tests but no
|
|
121
|
+
* satisfying vitest config.
|
|
122
|
+
*
|
|
123
|
+
* A package is satisfied if it has a per-package config OR a centralized
|
|
124
|
+
* config exists at the workspace root (the common ancestor of all package
|
|
125
|
+
* roots, or one level above it).
|
|
126
|
+
*/
|
|
127
|
+
export function detectMissingVitestConfig(packageJsonPaths, port) {
|
|
128
|
+
const packageDirs = packageJsonPaths.map((p) => path.dirname(p));
|
|
129
|
+
// A centralized workspace-root config satisfies every package.
|
|
130
|
+
const rootCandidates = workspaceRootCandidates(packageDirs);
|
|
131
|
+
const workspaceConfigSatisfies = rootCandidates.some((root) => WORKSPACE_CONFIG_FILES.some((f) => port.exists(path.join(root, f))));
|
|
132
|
+
if (workspaceConfigSatisfies) {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
const violations = [];
|
|
136
|
+
const rootSet = new Set(rootCandidates.map((r) => path.resolve(r)));
|
|
137
|
+
for (const packageJsonPath of packageJsonPaths) {
|
|
138
|
+
const packageDir = path.dirname(packageJsonPath);
|
|
139
|
+
// Skip a workspace-root package.json — it is not a leaf package, and the
|
|
140
|
+
// centralized-config branch above already covered its only satisfy path.
|
|
141
|
+
// (Only meaningful when there are multiple packages; with a single
|
|
142
|
+
// package its dir IS the ancestor and we must still evaluate it.)
|
|
143
|
+
if (packageDirs.length > 1 && rootSet.has(path.resolve(packageDir))) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (!port.hasTestFiles(packageDir)) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const hasPackageConfig = PACKAGE_CONFIG_FILES.some((f) => port.exists(path.join(packageDir, f)));
|
|
150
|
+
if (hasPackageConfig) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
violations.push({
|
|
154
|
+
filePath: packageJsonPath,
|
|
155
|
+
line: 1,
|
|
156
|
+
message: `Package '${path.basename(packageDir)}' contains test files but has no vitest.config.ts at its package root`,
|
|
157
|
+
severity: 'error',
|
|
158
|
+
suggestion: 'Add a vitest.config.ts (or vitest.config.mts) at the package root with explicit coverage thresholds, or centralize one at the workspace root. Without it, tests run config-less with no coverage floor and coverage can silently drift.',
|
|
159
|
+
match: path.basename(packageDir),
|
|
160
|
+
type: 'missing-vitest-config',
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return violations;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Check: architecture/vitest-config-required-with-tests
|
|
167
|
+
*
|
|
168
|
+
* Every workspace package that contains test files must ship a
|
|
169
|
+
* `vitest.config.ts` (or `.mts`) at its package root, unless the
|
|
170
|
+
* workspace root centralizes a vitest config.
|
|
171
|
+
*/
|
|
172
|
+
export const vitestConfigRequiredWithTests = defineCheck({
|
|
173
|
+
id: 'b7363db9-c3f7-47bc-8c25-1ddeebf53904',
|
|
174
|
+
slug: 'vitest-config-required-with-tests',
|
|
175
|
+
itemType: 'packages',
|
|
176
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
177
|
+
confidence: 'high',
|
|
178
|
+
description: 'Ensures packages with tests have a vitest.config at the package root',
|
|
179
|
+
longDescription: `**Purpose:** Ensures every workspace package that contains test files (\`*.test.ts\` / \`*.test.tsx\`) ships a \`vitest.config.ts\` (or \`vitest.config.mts\`) at its package root, so per-package coverage thresholds are actually applied.
|
|
180
|
+
|
|
181
|
+
**Detects:**
|
|
182
|
+
- A package root (a directory containing a \`package.json\`) that has at least one \`*.test.ts\` / \`*.test.tsx\` file anywhere beneath it, but no \`vitest.config.ts\` / \`vitest.config.mts\` at the package root.
|
|
183
|
+
|
|
184
|
+
**Satisfied by:**
|
|
185
|
+
- A per-package \`vitest.config.ts\` / \`vitest.config.mts\` at the package root, OR
|
|
186
|
+
- A centralized \`vitest.config.ts\` / \`vitest.config.mts\` / \`vitest.workspace.ts\` at the workspace root (a repo may centralize config).
|
|
187
|
+
|
|
188
|
+
**Why it matters:** When a package accrues tests but has no vitest config, its tests run config-less with no per-package coverage floor — letting coverage silently drift. This is a portable, package-name-agnostic structural check.
|
|
189
|
+
|
|
190
|
+
**Scope:** Cross-file analysis via \`analyzeAll\`. Package roots are discovered generically from \`package.json\` files; nested package roots, \`node_modules\`, fixtures, and build output are skipped when scanning for tests.`,
|
|
191
|
+
tags: ['architecture', 'testing'],
|
|
192
|
+
// @fitness-ignore-next-line concurrency-safety -- async keyword required by analyzeAll interface contract; synchronous analysis implementation
|
|
193
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- AnalyzeAllCheckConfig requires Promise<CheckViolation[]>; this implementation is synchronous
|
|
194
|
+
async analyzeAll(files) {
|
|
195
|
+
const packageJsonPaths = files.paths.filter((fp) => path.basename(fp) === 'package.json');
|
|
196
|
+
return detectMissingVitestConfig(packageJsonPaths, nodeFsPort);
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=vitest-config-required-with-tests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vitest-config-required-with-tests.js","sourceRoot":"","sources":["../../../src/checks/architecture/vitest-config-required-with-tests.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview ESLint directive parser
|
|
3
|
+
* (`eslint-disable`, `eslint-disable-next-line`, `eslint-disable-line`).
|
|
4
|
+
*
|
|
5
|
+
* Extracted from `directive-audit.ts` in Phase C4.
|
|
6
|
+
*/
|
|
7
|
+
import type { DirectiveInfo } from './types.js';
|
|
8
|
+
export declare function parseESLintDirectives(content: string, filePath: string, file: string): DirectiveInfo[];
|
|
9
|
+
//# sourceMappingURL=eslint.d.ts.map
|