@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,634 @@
|
|
|
1
|
+
// @fitness-ignore-file file-length-limit -- behavior fixture suite; related scenarios stay together while checks are split into focused tests.
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Branch-behavior tests for medium-coverage checks (round 8).
|
|
4
|
+
*
|
|
5
|
+
* Targets the remaining uncovered branches surfaced by the v8 coverage
|
|
6
|
+
* report: the semgrep directive parser, the public-API reachability
|
|
7
|
+
* graph, CSP-header pattern matchers, and several config-consistency
|
|
8
|
+
* analyzers (node/docker version sync, dependency-version drift,
|
|
9
|
+
* duplicate-package detection, performance anti-patterns).
|
|
10
|
+
*/
|
|
11
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
12
|
+
import { tmpdir } from 'node:os';
|
|
13
|
+
import { dirname, join } from 'node:path';
|
|
14
|
+
import { fileCache } from '@opensip-cli/fitness';
|
|
15
|
+
import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest';
|
|
16
|
+
import { parseSemgrepDirectives } from '../checks/documentation/_directives/semgrep.js';
|
|
17
|
+
import { _resetPublicApiGraphCache, isInPublicApiSurface, } from '../checks/documentation/_public-api-graph.js';
|
|
18
|
+
import { checks } from '../index.js';
|
|
19
|
+
function findCheck(slug) {
|
|
20
|
+
const check = checks.find((c) => c.config.slug === slug);
|
|
21
|
+
if (!check)
|
|
22
|
+
throw new Error(`check not found: ${slug}`);
|
|
23
|
+
return check;
|
|
24
|
+
}
|
|
25
|
+
function makeFixtureDir(prefix) {
|
|
26
|
+
return mkdtempSync(join(tmpdir(), `cu-cov8-${prefix}-`));
|
|
27
|
+
}
|
|
28
|
+
function writeFixture(cwd, rel, content) {
|
|
29
|
+
const abs = join(cwd, rel);
|
|
30
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
31
|
+
writeFileSync(abs, content);
|
|
32
|
+
return abs;
|
|
33
|
+
}
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
fileCache.clear();
|
|
36
|
+
_resetPublicApiGraphCache();
|
|
37
|
+
});
|
|
38
|
+
// =============================================================================
|
|
39
|
+
// semgrep directive parser: every rule-id / reason branch
|
|
40
|
+
// =============================================================================
|
|
41
|
+
describe('parseSemgrepDirectives', () => {
|
|
42
|
+
it('returns no directives for lines without a comment', () => {
|
|
43
|
+
const directives = parseSemgrepDirectives('const x = 1', 'a.ts', 'a.ts');
|
|
44
|
+
expect(directives).toEqual([]);
|
|
45
|
+
});
|
|
46
|
+
it('returns no directives when the comment is not nosemgrep', () => {
|
|
47
|
+
const directives = parseSemgrepDirectives('const x = 1 // just a note', 'a.ts', 'a.ts');
|
|
48
|
+
expect(directives).toEqual([]);
|
|
49
|
+
});
|
|
50
|
+
it('defaults rule to * for a bare nosemgrep', () => {
|
|
51
|
+
const [d] = parseSemgrepDirectives('const x = 1 // nosemgrep', 'a.ts', 'a.ts');
|
|
52
|
+
expect(d?.rule).toBe('semgrep/*');
|
|
53
|
+
expect(d?.reason).toBe('');
|
|
54
|
+
});
|
|
55
|
+
it('captures a rule id after the colon with no reason', () => {
|
|
56
|
+
const [d] = parseSemgrepDirectives('const x = 1 // nosemgrep: rule.id', 'a.ts', 'a.ts');
|
|
57
|
+
expect(d?.rule).toBe('semgrep/rule.id');
|
|
58
|
+
expect(d?.reason).toBe('');
|
|
59
|
+
});
|
|
60
|
+
it('captures both rule id and reason after the colon', () => {
|
|
61
|
+
const [d] = parseSemgrepDirectives('const x = 1 // nosemgrep: rule.id -- validated by zod', 'a.ts', 'a.ts');
|
|
62
|
+
expect(d?.rule).toBe('semgrep/rule.id');
|
|
63
|
+
expect(d?.reason).toBe('validated by zod');
|
|
64
|
+
});
|
|
65
|
+
it('falls back to * when colon has an empty rule id before the reason', () => {
|
|
66
|
+
const [d] = parseSemgrepDirectives('const x = 1 // nosemgrep: -- reason here', 'a.ts', 'a.ts');
|
|
67
|
+
expect(d?.rule).toBe('semgrep/*');
|
|
68
|
+
expect(d?.reason).toBe('reason here');
|
|
69
|
+
});
|
|
70
|
+
it('captures a reason with no rule id when -- follows directly', () => {
|
|
71
|
+
const [d] = parseSemgrepDirectives('const x = 1 // nosemgrep -- bare reason', 'a.ts', 'a.ts');
|
|
72
|
+
expect(d?.rule).toBe('semgrep/*');
|
|
73
|
+
expect(d?.reason).toBe('bare reason');
|
|
74
|
+
});
|
|
75
|
+
it('skips a trailing empty line yielded by split', () => {
|
|
76
|
+
// The trailing '\n' yields a final '' entry; the loop must handle it.
|
|
77
|
+
const directives = parseSemgrepDirectives('// nosemgrep\n', 'a.ts', 'a.ts');
|
|
78
|
+
expect(directives).toHaveLength(1);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
// =============================================================================
|
|
82
|
+
// public-API reachability graph: isInPublicApiSurface branches
|
|
83
|
+
// =============================================================================
|
|
84
|
+
describe('isInPublicApiSurface', () => {
|
|
85
|
+
let cwd;
|
|
86
|
+
beforeAll(() => {
|
|
87
|
+
cwd = makeFixtureDir('pubapi');
|
|
88
|
+
// Package A: string exports -> dist/index.js mapped to src/index.ts,
|
|
89
|
+
// which re-exports ./lib.js (named) and ./star.js (star).
|
|
90
|
+
writeFixture(cwd, 'pkg-a/package.json', JSON.stringify({
|
|
91
|
+
name: '@org/a',
|
|
92
|
+
exports: './dist/index.js',
|
|
93
|
+
}));
|
|
94
|
+
writeFixture(cwd, 'pkg-a/src/index.ts', [
|
|
95
|
+
"export { foo } from './lib.js'",
|
|
96
|
+
"export * from './star.js'",
|
|
97
|
+
"export * as ns from './star-ns.js'",
|
|
98
|
+
"export type { T } from './types.js'",
|
|
99
|
+
"export { bare } from 'some-package'",
|
|
100
|
+
].join('\n'));
|
|
101
|
+
writeFixture(cwd, 'pkg-a/src/lib.ts', 'export const foo = 1');
|
|
102
|
+
writeFixture(cwd, 'pkg-a/src/star.ts', 'export const star = 1');
|
|
103
|
+
writeFixture(cwd, 'pkg-a/src/star-ns.ts', 'export const ns = 1');
|
|
104
|
+
writeFixture(cwd, 'pkg-a/src/types.ts', 'export type T = number');
|
|
105
|
+
writeFixture(cwd, 'pkg-a/src/internal.ts', 'export const hidden = 1');
|
|
106
|
+
// Package B: conditional + array + subpath exports object.
|
|
107
|
+
writeFixture(cwd, 'pkg-b/package.json', JSON.stringify({
|
|
108
|
+
name: '@org/b',
|
|
109
|
+
exports: {
|
|
110
|
+
'.': { import: ['./dist/main.js', './dist/main.js'], require: './dist/main.js' },
|
|
111
|
+
'./sub': './dist/sub.js',
|
|
112
|
+
'./glob/*': './dist/glob/*.js',
|
|
113
|
+
},
|
|
114
|
+
}));
|
|
115
|
+
writeFixture(cwd, 'pkg-b/src/main.ts', 'export const main = 1');
|
|
116
|
+
writeFixture(cwd, 'pkg-b/src/sub.ts', 'export const sub = 1');
|
|
117
|
+
// Package C: no exports, falls back to module/main fields.
|
|
118
|
+
writeFixture(cwd, 'pkg-c/package.json', JSON.stringify({
|
|
119
|
+
name: '@org/c',
|
|
120
|
+
module: './build/entry.js',
|
|
121
|
+
main: './build/entry.js',
|
|
122
|
+
}));
|
|
123
|
+
writeFixture(cwd, 'pkg-c/src/entry.ts', 'export const entry = 1');
|
|
124
|
+
// Package D: binary-only (bin, no exports/main/module) -> empty surface.
|
|
125
|
+
writeFixture(cwd, 'pkg-d/package.json', JSON.stringify({
|
|
126
|
+
name: '@org/d',
|
|
127
|
+
bin: { d: './dist/cli.js' },
|
|
128
|
+
}));
|
|
129
|
+
writeFixture(cwd, 'pkg-d/src/cli.ts', 'export const cli = 1');
|
|
130
|
+
// Package E: malformed package.json -> open-fail (everything public).
|
|
131
|
+
writeFixture(cwd, 'pkg-e/package.json', '{ not valid json');
|
|
132
|
+
writeFixture(cwd, 'pkg-e/src/anything.ts', 'export const x = 1');
|
|
133
|
+
// Package F: package.json is a JSON array (not an object) -> open-fail.
|
|
134
|
+
writeFixture(cwd, 'pkg-f/package.json', '[1, 2, 3]');
|
|
135
|
+
writeFixture(cwd, 'pkg-f/src/anything.ts', 'export const x = 1');
|
|
136
|
+
// Package G: exports present but only wildcard -> no entries -> open-fail.
|
|
137
|
+
writeFixture(cwd, 'pkg-g/package.json', JSON.stringify({
|
|
138
|
+
name: '@org/g',
|
|
139
|
+
exports: './dist/*.js',
|
|
140
|
+
}));
|
|
141
|
+
writeFixture(cwd, 'pkg-g/src/anything.ts', 'export const x = 1');
|
|
142
|
+
});
|
|
143
|
+
afterAll(() => rmSync(cwd, { recursive: true, force: true }));
|
|
144
|
+
it('marks re-exported files (named, star, star-as, type) as public', () => {
|
|
145
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-a/src/index.ts'))).toBe(true);
|
|
146
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-a/src/lib.ts'))).toBe(true);
|
|
147
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-a/src/star.ts'))).toBe(true);
|
|
148
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-a/src/star-ns.ts'))).toBe(true);
|
|
149
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-a/src/types.ts'))).toBe(true);
|
|
150
|
+
});
|
|
151
|
+
it('marks files not reachable via re-export as non-public', () => {
|
|
152
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-a/src/internal.ts'))).toBe(false);
|
|
153
|
+
});
|
|
154
|
+
it('resolves conditional + array + subpath export objects', () => {
|
|
155
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-b/src/main.ts'))).toBe(true);
|
|
156
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-b/src/sub.ts'))).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
it('falls back to module/main when exports is absent', () => {
|
|
159
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-c/src/entry.ts'))).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
it('treats binary-only packages as having an empty public surface', () => {
|
|
162
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-d/src/cli.ts'))).toBe(false);
|
|
163
|
+
});
|
|
164
|
+
it('open-fails (everything public) on malformed package.json', () => {
|
|
165
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-e/src/anything.ts'))).toBe(true);
|
|
166
|
+
});
|
|
167
|
+
it('open-fails when package.json is not a JSON object', () => {
|
|
168
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-f/src/anything.ts'))).toBe(true);
|
|
169
|
+
});
|
|
170
|
+
it('open-fails when only wildcard exports remain', () => {
|
|
171
|
+
expect(isInPublicApiSurface(join(cwd, 'pkg-g/src/anything.ts'))).toBe(true);
|
|
172
|
+
});
|
|
173
|
+
it('open-fails when no package.json exists above the file', () => {
|
|
174
|
+
const orphan = makeFixtureDir('orphan');
|
|
175
|
+
try {
|
|
176
|
+
// mkdtemp dirs live directly under the OS tmp root, which has no
|
|
177
|
+
// package.json — exercises the findPackageRoot -> undefined path.
|
|
178
|
+
expect(isInPublicApiSurface(join(orphan, 'lonely.ts'))).toBe(true);
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
rmSync(orphan, { recursive: true, force: true });
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
// =============================================================================
|
|
186
|
+
// csp-headers: pattern-matcher branches
|
|
187
|
+
// =============================================================================
|
|
188
|
+
describe('csp-headers patterns', () => {
|
|
189
|
+
let cwd;
|
|
190
|
+
beforeAll(() => {
|
|
191
|
+
cwd = makeFixtureDir('csp');
|
|
192
|
+
writeFixture(cwd, 'src/wildcard.ts', ['// helmet csp config', 'export const csp = {', " 'script-src': ['*'],", '}'].join('\n'));
|
|
193
|
+
writeFixture(cwd, 'src/missing-default.ts', [
|
|
194
|
+
'export const opts = {',
|
|
195
|
+
' contentSecurityPolicy: {',
|
|
196
|
+
' directives: {},',
|
|
197
|
+
' },',
|
|
198
|
+
'}',
|
|
199
|
+
].join('\n'));
|
|
200
|
+
writeFixture(cwd, 'src/has-default.ts', [
|
|
201
|
+
'export const opts = {',
|
|
202
|
+
' contentSecurityPolicy: { directives: { defaultSrc: ["\'self\'"] } },',
|
|
203
|
+
'}',
|
|
204
|
+
].join('\n'));
|
|
205
|
+
writeFixture(cwd, 'src/data-uri.ts', ['// csp helmet', "export const policy = { 'script-src': [\"'self'\", 'data:'] }"].join('\n'));
|
|
206
|
+
writeFixture(cwd, 'src/no-csp.ts', 'export const unrelated = 1');
|
|
207
|
+
});
|
|
208
|
+
afterAll(() => rmSync(cwd, { recursive: true, force: true }));
|
|
209
|
+
it('flags wildcard in a CSP directive', async () => {
|
|
210
|
+
const result = await findCheck('csp-headers').run(cwd, {
|
|
211
|
+
targetFiles: [join(cwd, 'src/wildcard.ts')],
|
|
212
|
+
});
|
|
213
|
+
expect(result.signals.length).toBeGreaterThan(0);
|
|
214
|
+
});
|
|
215
|
+
it('flags contentSecurityPolicy config missing default-src', async () => {
|
|
216
|
+
const result = await findCheck('csp-headers').run(cwd, {
|
|
217
|
+
targetFiles: [join(cwd, 'src/missing-default.ts')],
|
|
218
|
+
});
|
|
219
|
+
const types = result.signals.map((s) => s.message);
|
|
220
|
+
expect(types.some((m) => m.includes('default-src'))).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
it('does not flag a config that already declares default-src', async () => {
|
|
223
|
+
const result = await findCheck('csp-headers').run(cwd, {
|
|
224
|
+
targetFiles: [join(cwd, 'src/has-default.ts')],
|
|
225
|
+
});
|
|
226
|
+
const messages = result.signals.map((s) => s.message);
|
|
227
|
+
expect(messages.some((m) => m.includes('missing default-src'))).toBe(false);
|
|
228
|
+
});
|
|
229
|
+
it('flags data: URI in script-src', async () => {
|
|
230
|
+
const result = await findCheck('csp-headers').run(cwd, {
|
|
231
|
+
targetFiles: [join(cwd, 'src/data-uri.ts')],
|
|
232
|
+
});
|
|
233
|
+
expect(result.signals.length).toBeGreaterThan(0);
|
|
234
|
+
});
|
|
235
|
+
it('skips files without CSP references', async () => {
|
|
236
|
+
const result = await findCheck('csp-headers').run(cwd, {
|
|
237
|
+
targetFiles: [join(cwd, 'src/no-csp.ts')],
|
|
238
|
+
});
|
|
239
|
+
expect(result.signals.length).toBe(0);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
// =============================================================================
|
|
243
|
+
// node-version-consistency: the "matching" (no-violation) branches
|
|
244
|
+
// =============================================================================
|
|
245
|
+
describe('node-version-consistency matching versions', () => {
|
|
246
|
+
let cwd;
|
|
247
|
+
beforeAll(() => {
|
|
248
|
+
cwd = makeFixtureDir('node-match');
|
|
249
|
+
writeFixture(cwd, 'package.json', JSON.stringify({
|
|
250
|
+
name: 'root',
|
|
251
|
+
engines: { node: '>=24.0.0' },
|
|
252
|
+
}, null, 2));
|
|
253
|
+
// .nvmrc matches the root major -> no nvmrc violation.
|
|
254
|
+
writeFixture(cwd, '.nvmrc', '24');
|
|
255
|
+
// Workspace engines + @types/node match -> no workspace/types violation.
|
|
256
|
+
writeFixture(cwd, 'packages/a/package.json', JSON.stringify({
|
|
257
|
+
name: '@org/a',
|
|
258
|
+
engines: { node: '>=24.0.0' },
|
|
259
|
+
devDependencies: { '@types/node': '^24.0.0' },
|
|
260
|
+
}, null, 2));
|
|
261
|
+
// Workspace with NO engines.node -> early return inside checkWorkspaceEngines.
|
|
262
|
+
writeFixture(cwd, 'packages/b/package.json', JSON.stringify({
|
|
263
|
+
name: '@org/b',
|
|
264
|
+
dependencies: {},
|
|
265
|
+
}, null, 2));
|
|
266
|
+
// CI workflow node-version matches -> no CI violation.
|
|
267
|
+
writeFixture(cwd, '.github/workflows/ci.yml', ['jobs:', ' test:', ' steps:', " - run: node-version: '24'"].join('\n'));
|
|
268
|
+
// A non-workflow .yml file -> falls through every else-if.
|
|
269
|
+
writeFixture(cwd, 'config/app.yml', 'setting: value');
|
|
270
|
+
});
|
|
271
|
+
afterAll(() => rmSync(cwd, { recursive: true, force: true }));
|
|
272
|
+
it('reports no violations when every Node version matches', async () => {
|
|
273
|
+
const origCwd = process.cwd();
|
|
274
|
+
process.chdir(cwd);
|
|
275
|
+
try {
|
|
276
|
+
const result = await findCheck('node-version-consistency').run(cwd, {
|
|
277
|
+
targetFiles: [
|
|
278
|
+
join(cwd, 'package.json'),
|
|
279
|
+
join(cwd, '.nvmrc'),
|
|
280
|
+
join(cwd, 'packages/a/package.json'),
|
|
281
|
+
join(cwd, 'packages/b/package.json'),
|
|
282
|
+
join(cwd, '.github/workflows/ci.yml'),
|
|
283
|
+
join(cwd, 'config/app.yml'),
|
|
284
|
+
],
|
|
285
|
+
});
|
|
286
|
+
expect(result.signals.length).toBe(0);
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
process.chdir(origCwd);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
// =============================================================================
|
|
294
|
+
// docker-version-sync: dynamic-pnpm, hardcoded-mismatch, and node-match
|
|
295
|
+
// =============================================================================
|
|
296
|
+
describe('docker-version-sync dynamic and mismatch', () => {
|
|
297
|
+
let cwd;
|
|
298
|
+
beforeAll(() => {
|
|
299
|
+
cwd = makeFixtureDir('docker-sync');
|
|
300
|
+
writeFixture(cwd, 'package.json', JSON.stringify({
|
|
301
|
+
name: 'root',
|
|
302
|
+
engines: { node: '>=24.0.0' },
|
|
303
|
+
packageManager: 'pnpm@10.0.0+sha512.abc',
|
|
304
|
+
}, null, 2));
|
|
305
|
+
// Dynamic pnpm extraction line -> the PNPM_DYNAMIC_PATTERN true branch.
|
|
306
|
+
writeFixture(cwd, 'Dockerfile', [
|
|
307
|
+
'FROM node:24-alpine',
|
|
308
|
+
"RUN corepack prepare pnpm@10.0.0 --activate # require('./package.json').packageManager",
|
|
309
|
+
'',
|
|
310
|
+
].join('\n'));
|
|
311
|
+
// Node major mismatch + hardcoded pnpm version mismatch.
|
|
312
|
+
writeFixture(cwd, 'Dockerfile.bad', ['FROM node:20-alpine', 'RUN corepack prepare pnpm@9.0.0 --activate'].join('\n'));
|
|
313
|
+
// Non-node Dockerfile -> skipped entirely.
|
|
314
|
+
writeFixture(cwd, 'Dockerfile.hasura', ['FROM hasura/graphql-engine:latest', 'RUN echo hi'].join('\n'));
|
|
315
|
+
});
|
|
316
|
+
afterAll(() => rmSync(cwd, { recursive: true, force: true }));
|
|
317
|
+
it('does not flag a Dockerfile using dynamic pnpm extraction', async () => {
|
|
318
|
+
const origCwd = process.cwd();
|
|
319
|
+
process.chdir(cwd);
|
|
320
|
+
try {
|
|
321
|
+
const result = await findCheck('docker-version-sync').run(cwd, {
|
|
322
|
+
targetFiles: [join(cwd, 'Dockerfile')],
|
|
323
|
+
});
|
|
324
|
+
const types = result.signals.map((s) => s.metadata.type);
|
|
325
|
+
expect(types).not.toContain('pnpm-version-mismatch');
|
|
326
|
+
expect(types).not.toContain('pnpm-hardcoded-version');
|
|
327
|
+
}
|
|
328
|
+
finally {
|
|
329
|
+
process.chdir(origCwd);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
it('flags both node and pnpm version mismatches', async () => {
|
|
333
|
+
const origCwd = process.cwd();
|
|
334
|
+
process.chdir(cwd);
|
|
335
|
+
try {
|
|
336
|
+
const result = await findCheck('docker-version-sync').run(cwd, {
|
|
337
|
+
targetFiles: [join(cwd, 'Dockerfile.bad')],
|
|
338
|
+
});
|
|
339
|
+
const types = result.signals.map((s) => s.metadata.type);
|
|
340
|
+
expect(types).toEqual(expect.arrayContaining(['node-version-mismatch', 'pnpm-version-mismatch']));
|
|
341
|
+
}
|
|
342
|
+
finally {
|
|
343
|
+
process.chdir(origCwd);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
it('skips non-Node Dockerfiles', async () => {
|
|
347
|
+
const origCwd = process.cwd();
|
|
348
|
+
process.chdir(cwd);
|
|
349
|
+
try {
|
|
350
|
+
const result = await findCheck('docker-version-sync').run(cwd, {
|
|
351
|
+
targetFiles: [join(cwd, 'Dockerfile.hasura')],
|
|
352
|
+
});
|
|
353
|
+
expect(result.signals.length).toBe(0);
|
|
354
|
+
}
|
|
355
|
+
finally {
|
|
356
|
+
process.chdir(origCwd);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
// =============================================================================
|
|
361
|
+
// performance-anti-patterns: skip-path and rest-destructuring branches
|
|
362
|
+
// =============================================================================
|
|
363
|
+
describe('performance-anti-patterns skip paths', () => {
|
|
364
|
+
let cwd;
|
|
365
|
+
beforeAll(() => {
|
|
366
|
+
cwd = makeFixtureDir('perf-skip');
|
|
367
|
+
// Inside a fitness check dir -> skipped.
|
|
368
|
+
writeFixture(cwd, 'fitness/src/checks/some-check.ts', [
|
|
369
|
+
'export async function f(items: number[]) {',
|
|
370
|
+
' for (const i of items) { await use(i); }',
|
|
371
|
+
'}',
|
|
372
|
+
].join('\n'));
|
|
373
|
+
// Diagnostics path -> skipped.
|
|
374
|
+
writeFixture(cwd, 'src/diagnostics/probe.ts', [
|
|
375
|
+
'export async function f(items: number[]) {',
|
|
376
|
+
' for (const i of items) { await use(i); }',
|
|
377
|
+
'}',
|
|
378
|
+
].join('\n'));
|
|
379
|
+
// @sequential-ok marker -> skipped.
|
|
380
|
+
writeFixture(cwd, 'src/marked.ts', [
|
|
381
|
+
'// @sequential-ok intentional sequential processing',
|
|
382
|
+
'export async function f(items: number[]) {',
|
|
383
|
+
' for (const i of items) { await use(i); }',
|
|
384
|
+
'}',
|
|
385
|
+
].join('\n'));
|
|
386
|
+
// Rest-destructuring inside a loop should NOT be treated as spread.
|
|
387
|
+
writeFixture(cwd, 'src/rest-destructure.ts', [
|
|
388
|
+
'export function f(rows: Record<string, number>[]) {',
|
|
389
|
+
' const out = [];',
|
|
390
|
+
' for (const row of rows) {',
|
|
391
|
+
' const { id, ...rest } = row;',
|
|
392
|
+
' out.push(rest);',
|
|
393
|
+
' }',
|
|
394
|
+
' return out;',
|
|
395
|
+
'}',
|
|
396
|
+
].join('\n'));
|
|
397
|
+
});
|
|
398
|
+
afterAll(() => rmSync(cwd, { recursive: true, force: true }));
|
|
399
|
+
it('skips files inside a fitness check directory', async () => {
|
|
400
|
+
const result = await findCheck('performance-anti-patterns').run(cwd, {
|
|
401
|
+
targetFiles: [join(cwd, 'fitness/src/checks/some-check.ts')],
|
|
402
|
+
});
|
|
403
|
+
expect(result.signals.length).toBe(0);
|
|
404
|
+
});
|
|
405
|
+
it('skips diagnostics files', async () => {
|
|
406
|
+
const result = await findCheck('performance-anti-patterns').run(cwd, {
|
|
407
|
+
targetFiles: [join(cwd, 'src/diagnostics/probe.ts')],
|
|
408
|
+
});
|
|
409
|
+
expect(result.signals.length).toBe(0);
|
|
410
|
+
});
|
|
411
|
+
it('skips files marked @sequential-ok', async () => {
|
|
412
|
+
const result = await findCheck('performance-anti-patterns').run(cwd, {
|
|
413
|
+
targetFiles: [join(cwd, 'src/marked.ts')],
|
|
414
|
+
});
|
|
415
|
+
expect(result.signals.length).toBe(0);
|
|
416
|
+
});
|
|
417
|
+
it('does not flag rest-destructuring as a spread-in-loop', async () => {
|
|
418
|
+
const result = await findCheck('performance-anti-patterns').run(cwd, {
|
|
419
|
+
targetFiles: [join(cwd, 'src/rest-destructure.ts')],
|
|
420
|
+
});
|
|
421
|
+
const messages = result.signals.map((s) => s.message);
|
|
422
|
+
expect(messages.some((m) => m.toLowerCase().includes('spread'))).toBe(false);
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
// =============================================================================
|
|
426
|
+
// performance-anti-patterns: spread-ACCUMULATION precision
|
|
427
|
+
//
|
|
428
|
+
// The check must flag genuine O(n^2) accumulation (spreading a collection
|
|
429
|
+
// back into itself each iteration) while NOT flagging benign in-loop spreads
|
|
430
|
+
// — one-time defensive copies, spread call-args, and merges — which were
|
|
431
|
+
// previously false positives (and collided with eslint's prefer-spread).
|
|
432
|
+
// =============================================================================
|
|
433
|
+
describe('performance-anti-patterns spread accumulation', () => {
|
|
434
|
+
let cwd;
|
|
435
|
+
function spreadSignals(rel) {
|
|
436
|
+
return findCheck('performance-anti-patterns')
|
|
437
|
+
.run(cwd, { targetFiles: [join(cwd, rel)] })
|
|
438
|
+
.then((r) => r.signals.some((s) => s.message.toLowerCase().includes('spread')));
|
|
439
|
+
}
|
|
440
|
+
beforeAll(() => {
|
|
441
|
+
cwd = makeFixtureDir('perf-spread');
|
|
442
|
+
// --- ACCUMULATION (must flag) ---
|
|
443
|
+
writeFixture(cwd, 'src/acc-array.ts', [
|
|
444
|
+
'export function f(items: number[]): number[] {',
|
|
445
|
+
' let acc: number[] = [];',
|
|
446
|
+
' for (const x of items) {',
|
|
447
|
+
' acc = [...acc, x];', // self-referential array rebuild — O(n^2)
|
|
448
|
+
' }',
|
|
449
|
+
' return acc;',
|
|
450
|
+
'}',
|
|
451
|
+
].join('\n'));
|
|
452
|
+
writeFixture(cwd, 'src/acc-object.ts', [
|
|
453
|
+
'export function f(keys: string[]): Record<string, boolean> {',
|
|
454
|
+
' let state: Record<string, boolean> = {};',
|
|
455
|
+
' for (const k of keys) {',
|
|
456
|
+
' state = { ...state, [k]: true };', // self-referential object rebuild
|
|
457
|
+
' }',
|
|
458
|
+
' return state;',
|
|
459
|
+
'}',
|
|
460
|
+
].join('\n'));
|
|
461
|
+
writeFixture(cwd, 'src/acc-map-slot.ts', [
|
|
462
|
+
'export function f(rows: { k: string; v: number }[]): Map<string, number[]> {',
|
|
463
|
+
' const m = new Map<string, number[]>();',
|
|
464
|
+
' for (const r of rows) {',
|
|
465
|
+
' m.set(r.k, [...(m.get(r.k) ?? []), r.v]);', // grouping into a Map slot
|
|
466
|
+
' }',
|
|
467
|
+
' return m;',
|
|
468
|
+
'}',
|
|
469
|
+
].join('\n'));
|
|
470
|
+
// --- BENIGN (must NOT flag) ---
|
|
471
|
+
writeFixture(cwd, 'src/copy-then-sort.ts', [
|
|
472
|
+
'export function f(groups: number[][]): number[][] {',
|
|
473
|
+
' const out: number[][] = [];',
|
|
474
|
+
' for (const g of groups) {',
|
|
475
|
+
' const sorted = [...g].sort((a, b) => a - b);', // one-time defensive copy
|
|
476
|
+
' out.push(sorted);',
|
|
477
|
+
' }',
|
|
478
|
+
' return out;',
|
|
479
|
+
'}',
|
|
480
|
+
].join('\n'));
|
|
481
|
+
writeFixture(cwd, 'src/merge.ts', [
|
|
482
|
+
'export function f(pairs: [number[], number[]][]): number[][] {',
|
|
483
|
+
' const out: number[][] = [];',
|
|
484
|
+
' for (const [a, b] of pairs) {',
|
|
485
|
+
' const merged = [...a, ...b];', // one-time merge, LHS != either source
|
|
486
|
+
' out.push(merged);',
|
|
487
|
+
' }',
|
|
488
|
+
' return out;',
|
|
489
|
+
'}',
|
|
490
|
+
].join('\n'));
|
|
491
|
+
writeFixture(cwd, 'src/call-arg.ts', [
|
|
492
|
+
'export function f(batches: number[][]): number[] {',
|
|
493
|
+
' const out: number[] = [];',
|
|
494
|
+
' for (const batch of batches) {',
|
|
495
|
+
' out.push(...batch);', // spread call-args — the recommended fix, not a smell
|
|
496
|
+
' }',
|
|
497
|
+
' return out;',
|
|
498
|
+
'}',
|
|
499
|
+
].join('\n'));
|
|
500
|
+
});
|
|
501
|
+
afterAll(() => rmSync(cwd, { recursive: true, force: true }));
|
|
502
|
+
it('flags self-referential array accumulation (acc = [...acc, x])', async () => {
|
|
503
|
+
expect(await spreadSignals('src/acc-array.ts')).toBe(true);
|
|
504
|
+
});
|
|
505
|
+
it('flags self-referential object accumulation (state = { ...state, k })', async () => {
|
|
506
|
+
expect(await spreadSignals('src/acc-object.ts')).toBe(true);
|
|
507
|
+
});
|
|
508
|
+
it('flags grouping into a Map slot (m.set(k, [...m.get(k), v]))', async () => {
|
|
509
|
+
expect(await spreadSignals('src/acc-map-slot.ts')).toBe(true);
|
|
510
|
+
});
|
|
511
|
+
it('does NOT flag a one-time defensive copy ([...g].sort())', async () => {
|
|
512
|
+
expect(await spreadSignals('src/copy-then-sort.ts')).toBe(false);
|
|
513
|
+
});
|
|
514
|
+
it('does NOT flag a one-time merge ([...a, ...b])', async () => {
|
|
515
|
+
expect(await spreadSignals('src/merge.ts')).toBe(false);
|
|
516
|
+
});
|
|
517
|
+
it('does NOT flag spread call-arguments (push(...batch))', async () => {
|
|
518
|
+
expect(await spreadSignals('src/call-arg.ts')).toBe(false);
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
// =============================================================================
|
|
522
|
+
// dependency-version-consistency: matching, missing-name, and unparseable
|
|
523
|
+
// =============================================================================
|
|
524
|
+
describe('dependency-version-consistency edge branches', () => {
|
|
525
|
+
let cwd;
|
|
526
|
+
beforeAll(() => {
|
|
527
|
+
cwd = makeFixtureDir('dvc-edge');
|
|
528
|
+
writeFixture(cwd, 'package.json', JSON.stringify({
|
|
529
|
+
name: 'root',
|
|
530
|
+
devDependencies: { vitest: '^2.0.0', typescript: '^5.0.0' },
|
|
531
|
+
}, null, 2));
|
|
532
|
+
// Matches root canonical -> exercises canonical-version match branch.
|
|
533
|
+
writeFixture(cwd, 'packages/a/package.json', JSON.stringify({
|
|
534
|
+
name: '@org/a',
|
|
535
|
+
devDependencies: { vitest: '^2.0.0' },
|
|
536
|
+
}, null, 2));
|
|
537
|
+
// No name field -> pkgName falls back to directory basename.
|
|
538
|
+
writeFixture(cwd, 'packages/noname/package.json', JSON.stringify({
|
|
539
|
+
devDependencies: { typescript: '^5.0.0' },
|
|
540
|
+
}, null, 2));
|
|
541
|
+
// Unparseable package.json -> parse returns null, file is skipped.
|
|
542
|
+
writeFixture(cwd, 'packages/bad/package.json', '{ broken');
|
|
543
|
+
});
|
|
544
|
+
afterAll(() => rmSync(cwd, { recursive: true, force: true }));
|
|
545
|
+
it('reports no inconsistencies when every package matches root', async () => {
|
|
546
|
+
const origCwd = process.cwd();
|
|
547
|
+
process.chdir(cwd);
|
|
548
|
+
try {
|
|
549
|
+
const result = await findCheck('dependency-version-consistency').run(cwd, {
|
|
550
|
+
targetFiles: [join(cwd, 'package.json'), join(cwd, 'packages/a/package.json')],
|
|
551
|
+
});
|
|
552
|
+
const types = result.signals.map((s) => s.metadata.type);
|
|
553
|
+
expect(types).not.toContain('version-mismatch');
|
|
554
|
+
}
|
|
555
|
+
finally {
|
|
556
|
+
process.chdir(origCwd);
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
it('handles packages with no name and unparseable package.json without throwing', async () => {
|
|
560
|
+
const origCwd = process.cwd();
|
|
561
|
+
process.chdir(cwd);
|
|
562
|
+
try {
|
|
563
|
+
const result = await findCheck('dependency-version-consistency').run(cwd, {
|
|
564
|
+
targetFiles: [
|
|
565
|
+
join(cwd, 'package.json'),
|
|
566
|
+
join(cwd, 'packages/noname/package.json'),
|
|
567
|
+
join(cwd, 'packages/bad/package.json'),
|
|
568
|
+
],
|
|
569
|
+
});
|
|
570
|
+
expect(result.errors).toBe(0);
|
|
571
|
+
}
|
|
572
|
+
finally {
|
|
573
|
+
process.chdir(origCwd);
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
});
|
|
577
|
+
// =============================================================================
|
|
578
|
+
// no-duplicate-packages: keyword match, excluded path, name-part dedup
|
|
579
|
+
// =============================================================================
|
|
580
|
+
describe('no-duplicate-packages keyword/exclusion branches', () => {
|
|
581
|
+
let cwd;
|
|
582
|
+
beforeAll(() => {
|
|
583
|
+
cwd = makeFixtureDir('dup-pkg');
|
|
584
|
+
// Two packages whose NAMES do not match a pattern but whose KEYWORDS do
|
|
585
|
+
// (logging category) -> exercises the keyword-matching branch.
|
|
586
|
+
writeFixture(cwd, 'packages/alpha/package.json', JSON.stringify({
|
|
587
|
+
name: '@org/alpha',
|
|
588
|
+
keywords: ['logger'],
|
|
589
|
+
}));
|
|
590
|
+
writeFixture(cwd, 'packages/beta/package.json', JSON.stringify({
|
|
591
|
+
name: '@org/beta',
|
|
592
|
+
keywords: ['logging'],
|
|
593
|
+
}));
|
|
594
|
+
// An excluded package (under __fixtures__) -> getPackageInfo returns null.
|
|
595
|
+
writeFixture(cwd, 'packages/__fixtures__/logger/package.json', JSON.stringify({
|
|
596
|
+
name: '@org/fixture-logger',
|
|
597
|
+
keywords: ['logger'],
|
|
598
|
+
}));
|
|
599
|
+
// Scoped + unscoped variants of the same name part -> dedup collapses them.
|
|
600
|
+
writeFixture(cwd, 'packages/contracts/package.json', JSON.stringify({
|
|
601
|
+
name: '@org/contracts',
|
|
602
|
+
}));
|
|
603
|
+
writeFixture(cwd, 'packages/dup-contracts/package.json', JSON.stringify({
|
|
604
|
+
name: 'contracts',
|
|
605
|
+
}));
|
|
606
|
+
});
|
|
607
|
+
afterAll(() => rmSync(cwd, { recursive: true, force: true }));
|
|
608
|
+
it('detects duplicates via keywords and skips excluded fixture packages', async () => {
|
|
609
|
+
const result = await findCheck('no-duplicate-packages').run(cwd, {
|
|
610
|
+
targetFiles: [
|
|
611
|
+
join(cwd, 'packages/alpha/package.json'),
|
|
612
|
+
join(cwd, 'packages/beta/package.json'),
|
|
613
|
+
join(cwd, 'packages/__fixtures__/logger/package.json'),
|
|
614
|
+
],
|
|
615
|
+
});
|
|
616
|
+
const messages = result.signals.map((s) => s.message);
|
|
617
|
+
expect(messages.some((m) => m.includes('logging'))).toBe(true);
|
|
618
|
+
// The excluded fixture package must not appear in the duplicate list.
|
|
619
|
+
expect(messages.some((m) => m.includes('fixture-logger'))).toBe(false);
|
|
620
|
+
});
|
|
621
|
+
it('collapses scoped and unscoped packages sharing a name part', async () => {
|
|
622
|
+
const result = await findCheck('no-duplicate-packages').run(cwd, {
|
|
623
|
+
targetFiles: [
|
|
624
|
+
join(cwd, 'packages/contracts/package.json'),
|
|
625
|
+
join(cwd, 'packages/dup-contracts/package.json'),
|
|
626
|
+
],
|
|
627
|
+
});
|
|
628
|
+
// Both reduce to name part "contracts" -> only one entry -> below the
|
|
629
|
+
// 2-package warning threshold -> no duplicate-contracts violation.
|
|
630
|
+
const messages = result.signals.map((s) => s.message);
|
|
631
|
+
expect(messages.some((m) => m.includes('contracts/types') || m.includes('Duplicate contracts'))).toBe(false);
|
|
632
|
+
});
|
|
633
|
+
});
|
|
634
|
+
//# sourceMappingURL=behavior-fixtures-8.test.js.map
|