@opensip-cli/checks-typescript 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 +12 -0
- package/dist/__tests__/all-checks-execute.test.d.ts.map +1 -0
- package/dist/__tests__/all-checks-execute.test.js +846 -0
- package/dist/__tests__/all-checks-execute.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-2.test.d.ts +9 -0
- package/dist/__tests__/behavior-fixtures-2.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-2.test.js +625 -0
- package/dist/__tests__/behavior-fixtures-2.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-3.test.d.ts +7 -0
- package/dist/__tests__/behavior-fixtures-3.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-3.test.js +658 -0
- package/dist/__tests__/behavior-fixtures-3.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-4.test.d.ts +8 -0
- package/dist/__tests__/behavior-fixtures-4.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-4.test.js +590 -0
- package/dist/__tests__/behavior-fixtures-4.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-5.test.d.ts +7 -0
- package/dist/__tests__/behavior-fixtures-5.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-5.test.js +548 -0
- package/dist/__tests__/behavior-fixtures-5.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures-6.test.d.ts +18 -0
- package/dist/__tests__/behavior-fixtures-6.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures-6.test.js +1700 -0
- package/dist/__tests__/behavior-fixtures-6.test.js.map +1 -0
- package/dist/__tests__/behavior-fixtures.test.d.ts +10 -0
- package/dist/__tests__/behavior-fixtures.test.d.ts.map +1 -0
- package/dist/__tests__/behavior-fixtures.test.js +812 -0
- package/dist/__tests__/behavior-fixtures.test.js.map +1 -0
- package/dist/__tests__/branch-fixtures-2.test.d.ts +6 -0
- package/dist/__tests__/branch-fixtures-2.test.d.ts.map +1 -0
- package/dist/__tests__/branch-fixtures-2.test.js +1369 -0
- package/dist/__tests__/branch-fixtures-2.test.js.map +1 -0
- package/dist/__tests__/branch-fixtures-3.test.d.ts +7 -0
- package/dist/__tests__/branch-fixtures-3.test.d.ts.map +1 -0
- package/dist/__tests__/branch-fixtures-3.test.js +877 -0
- package/dist/__tests__/branch-fixtures-3.test.js.map +1 -0
- package/dist/__tests__/branch-fixtures.test.d.ts +6 -0
- package/dist/__tests__/branch-fixtures.test.d.ts.map +1 -0
- package/dist/__tests__/branch-fixtures.test.js +1072 -0
- package/dist/__tests__/branch-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 +39 -0
- package/dist/__tests__/checks.test.js.map +1 -0
- package/dist/__tests__/fixture-coverage.allowlist.d.ts +19 -0
- package/dist/__tests__/fixture-coverage.allowlist.d.ts.map +1 -0
- package/dist/__tests__/fixture-coverage.allowlist.js +27 -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__/no-bootstrap-tool-import.test.d.ts +2 -0
- package/dist/__tests__/no-bootstrap-tool-import.test.d.ts.map +1 -0
- package/dist/__tests__/no-bootstrap-tool-import.test.js +75 -0
- package/dist/__tests__/no-bootstrap-tool-import.test.js.map +1 -0
- package/dist/__tests__/phantom-dependency-detection.test.d.ts +12 -0
- package/dist/__tests__/phantom-dependency-detection.test.d.ts.map +1 -0
- package/dist/__tests__/phantom-dependency-detection.test.js +112 -0
- package/dist/__tests__/phantom-dependency-detection.test.js.map +1 -0
- package/dist/__tests__/typescript-frontend.test.d.ts +8 -0
- package/dist/__tests__/typescript-frontend.test.d.ts.map +1 -0
- package/dist/__tests__/typescript-frontend.test.js +57 -0
- package/dist/__tests__/typescript-frontend.test.js.map +1 -0
- package/dist/checks/architecture/circular-import-detection.d.ts +14 -0
- package/dist/checks/architecture/circular-import-detection.d.ts.map +1 -0
- package/dist/checks/architecture/circular-import-detection.js +55 -0
- package/dist/checks/architecture/circular-import-detection.js.map +1 -0
- package/dist/checks/architecture/contracts-schema-consistency.d.ts +11 -0
- package/dist/checks/architecture/contracts-schema-consistency.d.ts.map +1 -0
- package/dist/checks/architecture/contracts-schema-consistency.js +75 -0
- package/dist/checks/architecture/contracts-schema-consistency.js.map +1 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.d.ts +12 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.d.ts.map +1 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.js +92 -0
- package/dist/checks/architecture/drizzle-orm-migration-guardrails.js.map +1 -0
- package/dist/checks/architecture/index.d.ts +10 -0
- package/dist/checks/architecture/index.d.ts.map +1 -0
- package/dist/checks/architecture/index.js +10 -0
- package/dist/checks/architecture/index.js.map +1 -0
- package/dist/checks/architecture/missing-type-exports.d.ts +13 -0
- package/dist/checks/architecture/missing-type-exports.d.ts.map +1 -0
- package/dist/checks/architecture/missing-type-exports.js +245 -0
- package/dist/checks/architecture/missing-type-exports.js.map +1 -0
- package/dist/checks/architecture/module-coupling-fan-out.d.ts +20 -0
- package/dist/checks/architecture/module-coupling-fan-out.d.ts.map +1 -0
- package/dist/checks/architecture/module-coupling-fan-out.js +120 -0
- package/dist/checks/architecture/module-coupling-fan-out.js.map +1 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.d.ts +38 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.d.ts.map +1 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.js +95 -0
- package/dist/checks/architecture/no-bootstrap-tool-import.js.map +1 -0
- package/dist/checks/architecture/package-json-exports-field.d.ts +10 -0
- package/dist/checks/architecture/package-json-exports-field.d.ts.map +1 -0
- package/dist/checks/architecture/package-json-exports-field.js +56 -0
- package/dist/checks/architecture/package-json-exports-field.js.map +1 -0
- package/dist/checks/architecture/phantom-dependency-detection.d.ts +22 -0
- package/dist/checks/architecture/phantom-dependency-detection.d.ts.map +1 -0
- package/dist/checks/architecture/phantom-dependency-detection.js +330 -0
- package/dist/checks/architecture/phantom-dependency-detection.js.map +1 -0
- package/dist/checks/architecture/tsconfig-extends-validation.d.ts +10 -0
- package/dist/checks/architecture/tsconfig-extends-validation.d.ts.map +1 -0
- package/dist/checks/architecture/tsconfig-extends-validation.js +78 -0
- package/dist/checks/architecture/tsconfig-extends-validation.js.map +1 -0
- package/dist/checks/index.d.ts +6 -0
- package/dist/checks/index.d.ts.map +1 -0
- package/dist/checks/index.js +6 -0
- package/dist/checks/index.js.map +1 -0
- package/dist/checks/quality/api/api-contract-validation.d.ts +15 -0
- package/dist/checks/quality/api/api-contract-validation.d.ts.map +1 -0
- package/dist/checks/quality/api/api-contract-validation.js +316 -0
- package/dist/checks/quality/api/api-contract-validation.js.map +1 -0
- package/dist/checks/quality/api/api-response-validation.d.ts +14 -0
- package/dist/checks/quality/api/api-response-validation.d.ts.map +1 -0
- package/dist/checks/quality/api/api-response-validation.js +209 -0
- package/dist/checks/quality/api/api-response-validation.js.map +1 -0
- package/dist/checks/quality/api/fastify-route-validation.d.ts +14 -0
- package/dist/checks/quality/api/fastify-route-validation.d.ts.map +1 -0
- package/dist/checks/quality/api/fastify-route-validation.js +298 -0
- package/dist/checks/quality/api/fastify-route-validation.js.map +1 -0
- package/dist/checks/quality/api/fastify-schema-coverage.d.ts +11 -0
- package/dist/checks/quality/api/fastify-schema-coverage.d.ts.map +1 -0
- package/dist/checks/quality/api/fastify-schema-coverage.js +261 -0
- package/dist/checks/quality/api/fastify-schema-coverage.js.map +1 -0
- package/dist/checks/quality/api/index.d.ts +5 -0
- package/dist/checks/quality/api/index.d.ts.map +1 -0
- package/dist/checks/quality/api/index.js +5 -0
- package/dist/checks/quality/api/index.js.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts +32 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.js +451 -0
- package/dist/checks/quality/code-structure/duplicate-utility-functions.js.map +1 -0
- package/dist/checks/quality/code-structure/index.d.ts +3 -0
- package/dist/checks/quality/code-structure/index.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/index.js +3 -0
- package/dist/checks/quality/code-structure/index.js.map +1 -0
- package/dist/checks/quality/code-structure/no-any-types.d.ts +13 -0
- package/dist/checks/quality/code-structure/no-any-types.d.ts.map +1 -0
- package/dist/checks/quality/code-structure/no-any-types.js +116 -0
- package/dist/checks/quality/code-structure/no-any-types.js.map +1 -0
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.d.ts +15 -0
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js +51 -0
- package/dist/checks/quality/data-integrity/__tests__/null-safety-fp.test.js.map +1 -0
- package/dist/checks/quality/data-integrity/array-validation.d.ts +16 -0
- package/dist/checks/quality/data-integrity/array-validation.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/array-validation.js +508 -0
- package/dist/checks/quality/data-integrity/array-validation.js.map +1 -0
- package/dist/checks/quality/data-integrity/database-index-coverage.d.ts +14 -0
- package/dist/checks/quality/data-integrity/database-index-coverage.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/database-index-coverage.js +235 -0
- package/dist/checks/quality/data-integrity/database-index-coverage.js.map +1 -0
- package/dist/checks/quality/data-integrity/database-schema-validation.d.ts +16 -0
- package/dist/checks/quality/data-integrity/database-schema-validation.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/database-schema-validation.js +328 -0
- package/dist/checks/quality/data-integrity/database-schema-validation.js.map +1 -0
- package/dist/checks/quality/data-integrity/in-memory-repository-detection.d.ts +14 -0
- package/dist/checks/quality/data-integrity/in-memory-repository-detection.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/in-memory-repository-detection.js +157 -0
- package/dist/checks/quality/data-integrity/in-memory-repository-detection.js.map +1 -0
- package/dist/checks/quality/data-integrity/index.d.ts +8 -0
- package/dist/checks/quality/data-integrity/index.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/index.js +8 -0
- package/dist/checks/quality/data-integrity/index.js.map +1 -0
- package/dist/checks/quality/data-integrity/missing-input-validation.d.ts +12 -0
- package/dist/checks/quality/data-integrity/missing-input-validation.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/missing-input-validation.js +180 -0
- package/dist/checks/quality/data-integrity/missing-input-validation.js.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety.d.ts +33 -0
- package/dist/checks/quality/data-integrity/null-safety.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/null-safety.js +766 -0
- package/dist/checks/quality/data-integrity/null-safety.js.map +1 -0
- package/dist/checks/quality/data-integrity/numeric-validation.d.ts +12 -0
- package/dist/checks/quality/data-integrity/numeric-validation.d.ts.map +1 -0
- package/dist/checks/quality/data-integrity/numeric-validation.js +409 -0
- package/dist/checks/quality/data-integrity/numeric-validation.js.map +1 -0
- package/dist/checks/quality/frontend/a11y-form-labels.d.ts +14 -0
- package/dist/checks/quality/frontend/a11y-form-labels.d.ts.map +1 -0
- package/dist/checks/quality/frontend/a11y-form-labels.js +93 -0
- package/dist/checks/quality/frontend/a11y-form-labels.js.map +1 -0
- package/dist/checks/quality/frontend/a11y-semantic-html.d.ts +14 -0
- package/dist/checks/quality/frontend/a11y-semantic-html.d.ts.map +1 -0
- package/dist/checks/quality/frontend/a11y-semantic-html.js +88 -0
- package/dist/checks/quality/frontend/a11y-semantic-html.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/test-only-frontend-modules.d.ts +13 -0
- package/dist/checks/quality/frontend/test-only-frontend-modules.d.ts.map +1 -0
- package/dist/checks/quality/frontend/test-only-frontend-modules.js +159 -0
- package/dist/checks/quality/frontend/test-only-frontend-modules.js.map +1 -0
- package/dist/checks/quality/incomplete-regex-escaping.d.ts +13 -0
- package/dist/checks/quality/incomplete-regex-escaping.d.ts.map +1 -0
- package/dist/checks/quality/incomplete-regex-escaping.js +207 -0
- package/dist/checks/quality/incomplete-regex-escaping.js.map +1 -0
- package/dist/checks/quality/index.d.ts +11 -0
- package/dist/checks/quality/index.d.ts.map +1 -0
- package/dist/checks/quality/index.js +11 -0
- package/dist/checks/quality/index.js.map +1 -0
- package/dist/checks/quality/linting/index.d.ts +2 -0
- package/dist/checks/quality/linting/index.d.ts.map +1 -0
- package/dist/checks/quality/linting/index.js +2 -0
- package/dist/checks/quality/linting/index.js.map +1 -0
- package/dist/checks/quality/linting/typescript-frontend.d.ts +25 -0
- package/dist/checks/quality/linting/typescript-frontend.d.ts.map +1 -0
- package/dist/checks/quality/linting/typescript-frontend.js +159 -0
- package/dist/checks/quality/linting/typescript-frontend.js.map +1 -0
- package/dist/checks/quality/observability/index.d.ts +5 -0
- package/dist/checks/quality/observability/index.d.ts.map +1 -0
- package/dist/checks/quality/observability/index.js +5 -0
- package/dist/checks/quality/observability/index.js.map +1 -0
- package/dist/checks/quality/observability/logger-event-name-format.d.ts +12 -0
- package/dist/checks/quality/observability/logger-event-name-format.d.ts.map +1 -0
- package/dist/checks/quality/observability/logger-event-name-format.js +124 -0
- package/dist/checks/quality/observability/logger-event-name-format.js.map +1 -0
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.d.ts +5 -0
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.d.ts.map +1 -0
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.js +77 -0
- package/dist/checks/quality/observability/no-hardcoded-correlation-id.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.d.ts +11 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.js +107 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/analyzer.test.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.d.ts +12 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.js +94 -0
- package/dist/checks/quality/observability/observability-coverage/__tests__/logger-detector.test.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/analyzer.d.ts +13 -0
- package/dist/checks/quality/observability/observability-coverage/analyzer.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/analyzer.js +117 -0
- package/dist/checks/quality/observability/observability-coverage/analyzer.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/index.d.ts +4 -0
- package/dist/checks/quality/observability/observability-coverage/index.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/index.js +4 -0
- package/dist/checks/quality/observability/observability-coverage/index.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/logger-detector.d.ts +29 -0
- package/dist/checks/quality/observability/observability-coverage/logger-detector.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/logger-detector.js +111 -0
- package/dist/checks/quality/observability/observability-coverage/logger-detector.js.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/types.d.ts +64 -0
- package/dist/checks/quality/observability/observability-coverage/types.d.ts.map +1 -0
- package/dist/checks/quality/observability/observability-coverage/types.js +6 -0
- package/dist/checks/quality/observability/observability-coverage/types.js.map +1 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.d.ts +22 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.d.ts.map +1 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.js +212 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.js.map +1 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.test.d.ts +11 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.test.d.ts.map +1 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.test.js +46 -0
- package/dist/checks/quality/observability/pii-exposure-in-logs.test.js.map +1 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.d.ts +14 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.d.ts.map +1 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js +61 -0
- package/dist/checks/quality/patterns/__tests__/toctou-fp.test.js.map +1 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.d.ts +26 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.d.ts.map +1 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.js +410 -0
- package/dist/checks/quality/patterns/async-waterfall-detection.js.map +1 -0
- package/dist/checks/quality/patterns/dispose-pattern-completeness.d.ts +13 -0
- package/dist/checks/quality/patterns/dispose-pattern-completeness.d.ts.map +1 -0
- package/dist/checks/quality/patterns/dispose-pattern-completeness.js +220 -0
- package/dist/checks/quality/patterns/dispose-pattern-completeness.js.map +1 -0
- package/dist/checks/quality/patterns/error-handling-quality.d.ts +17 -0
- package/dist/checks/quality/patterns/error-handling-quality.d.ts.map +1 -0
- package/dist/checks/quality/patterns/error-handling-quality.js +335 -0
- package/dist/checks/quality/patterns/error-handling-quality.js.map +1 -0
- package/dist/checks/quality/patterns/index.d.ts +10 -0
- package/dist/checks/quality/patterns/index.d.ts.map +1 -0
- package/dist/checks/quality/patterns/index.js +10 -0
- package/dist/checks/quality/patterns/index.js.map +1 -0
- package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.d.ts +16 -0
- package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.d.ts.map +1 -0
- package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.js +205 -0
- package/dist/checks/quality/patterns/lifecycle-cleanup-enforcement.js.map +1 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.d.ts +16 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.d.ts.map +1 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.js +328 -0
- package/dist/checks/quality/patterns/result-pattern-consistency.js.map +1 -0
- package/dist/checks/quality/patterns/silent-early-returns.d.ts +23 -0
- package/dist/checks/quality/patterns/silent-early-returns.d.ts.map +1 -0
- package/dist/checks/quality/patterns/silent-early-returns.js +266 -0
- package/dist/checks/quality/patterns/silent-early-returns.js.map +1 -0
- package/dist/checks/quality/patterns/stream-buffer-size-limits.d.ts +13 -0
- package/dist/checks/quality/patterns/stream-buffer-size-limits.d.ts.map +1 -0
- package/dist/checks/quality/patterns/stream-buffer-size-limits.js +163 -0
- package/dist/checks/quality/patterns/stream-buffer-size-limits.js.map +1 -0
- package/dist/checks/quality/patterns/throws-documentation.d.ts +23 -0
- package/dist/checks/quality/patterns/throws-documentation.d.ts.map +1 -0
- package/dist/checks/quality/patterns/throws-documentation.js +519 -0
- package/dist/checks/quality/patterns/throws-documentation.js.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition.d.ts +48 -0
- package/dist/checks/quality/patterns/toctou-race-condition.d.ts.map +1 -0
- package/dist/checks/quality/patterns/toctou-race-condition.js +639 -0
- package/dist/checks/quality/patterns/toctou-race-condition.js.map +1 -0
- package/dist/checks/quality/stubbed-implementation-detection.d.ts +24 -0
- package/dist/checks/quality/stubbed-implementation-detection.d.ts.map +1 -0
- package/dist/checks/quality/stubbed-implementation-detection.js +355 -0
- package/dist/checks/quality/stubbed-implementation-detection.js.map +1 -0
- package/dist/checks/quality/unused-config-options.d.ts +12 -0
- package/dist/checks/quality/unused-config-options.d.ts.map +1 -0
- package/dist/checks/quality/unused-config-options.js +245 -0
- package/dist/checks/quality/unused-config-options.js.map +1 -0
- package/dist/checks/resilience/__tests__/callback-invocation-safe.test.d.ts +2 -0
- package/dist/checks/resilience/__tests__/callback-invocation-safe.test.d.ts.map +1 -0
- package/dist/checks/resilience/__tests__/callback-invocation-safe.test.js +79 -0
- package/dist/checks/resilience/__tests__/callback-invocation-safe.test.js.map +1 -0
- package/dist/checks/resilience/__tests__/context-leakage-fp.test.d.ts +12 -0
- package/dist/checks/resilience/__tests__/context-leakage-fp.test.d.ts.map +1 -0
- package/dist/checks/resilience/__tests__/context-leakage-fp.test.js +34 -0
- package/dist/checks/resilience/__tests__/context-leakage-fp.test.js.map +1 -0
- package/dist/checks/resilience/__tests__/context-mutation.test.d.ts +11 -0
- package/dist/checks/resilience/__tests__/context-mutation.test.d.ts.map +1 -0
- package/dist/checks/resilience/__tests__/context-mutation.test.js +54 -0
- package/dist/checks/resilience/__tests__/context-mutation.test.js.map +1 -0
- package/dist/checks/resilience/callback-invocation-safe.d.ts +34 -0
- package/dist/checks/resilience/callback-invocation-safe.d.ts.map +1 -0
- package/dist/checks/resilience/callback-invocation-safe.js +247 -0
- package/dist/checks/resilience/callback-invocation-safe.js.map +1 -0
- package/dist/checks/resilience/context-leakage.d.ts +25 -0
- package/dist/checks/resilience/context-leakage.d.ts.map +1 -0
- package/dist/checks/resilience/context-leakage.js +435 -0
- package/dist/checks/resilience/context-leakage.js.map +1 -0
- package/dist/checks/resilience/context-mutation.d.ts +21 -0
- package/dist/checks/resilience/context-mutation.d.ts.map +1 -0
- package/dist/checks/resilience/context-mutation.js +368 -0
- package/dist/checks/resilience/context-mutation.js.map +1 -0
- package/dist/checks/resilience/detached-promises.d.ts +40 -0
- package/dist/checks/resilience/detached-promises.d.ts.map +1 -0
- package/dist/checks/resilience/detached-promises.js +646 -0
- package/dist/checks/resilience/detached-promises.js.map +1 -0
- package/dist/checks/resilience/index.d.ts +7 -0
- package/dist/checks/resilience/index.d.ts.map +1 -0
- package/dist/checks/resilience/index.js +7 -0
- package/dist/checks/resilience/index.js.map +1 -0
- package/dist/checks/resilience/no-raw-fetch.d.ts +11 -0
- package/dist/checks/resilience/no-raw-fetch.d.ts.map +1 -0
- package/dist/checks/resilience/no-raw-fetch.js +110 -0
- package/dist/checks/resilience/no-raw-fetch.js.map +1 -0
- package/dist/checks/resilience/no-unbounded-concurrency.d.ts +11 -0
- package/dist/checks/resilience/no-unbounded-concurrency.d.ts.map +1 -0
- package/dist/checks/resilience/no-unbounded-concurrency.js +117 -0
- package/dist/checks/resilience/no-unbounded-concurrency.js.map +1 -0
- package/dist/checks/security/__tests__/sql-injection.test.d.ts +17 -0
- package/dist/checks/security/__tests__/sql-injection.test.d.ts.map +1 -0
- package/dist/checks/security/__tests__/sql-injection.test.js +97 -0
- package/dist/checks/security/__tests__/sql-injection.test.js.map +1 -0
- package/dist/checks/security/index.d.ts +4 -0
- package/dist/checks/security/index.d.ts.map +1 -0
- package/dist/checks/security/index.js +4 -0
- package/dist/checks/security/index.js.map +1 -0
- package/dist/checks/security/input-sanitization.d.ts +20 -0
- package/dist/checks/security/input-sanitization.d.ts.map +1 -0
- package/dist/checks/security/input-sanitization.js +255 -0
- package/dist/checks/security/input-sanitization.js.map +1 -0
- package/dist/checks/security/sql-injection.d.ts +24 -0
- package/dist/checks/security/sql-injection.d.ts.map +1 -0
- package/dist/checks/security/sql-injection.js +330 -0
- package/dist/checks/security/sql-injection.js.map +1 -0
- package/dist/checks/security/unsafe-secret-comparison.d.ts +17 -0
- package/dist/checks/security/unsafe-secret-comparison.d.ts.map +1 -0
- package/dist/checks/security/unsafe-secret-comparison.js +227 -0
- package/dist/checks/security/unsafe-secret-comparison.js.map +1 -0
- package/dist/checks/testing/index.d.ts +2 -0
- package/dist/checks/testing/index.d.ts.map +1 -0
- package/dist/checks/testing/index.js +2 -0
- package/dist/checks/testing/index.js.map +1 -0
- package/dist/checks/testing/mock-implementations-in-production.d.ts +12 -0
- package/dist/checks/testing/mock-implementations-in-production.d.ts.map +1 -0
- package/dist/checks/testing/mock-implementations-in-production.js +211 -0
- package/dist/checks/testing/mock-implementations-in-production.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 +18 -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 +39 -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 +13 -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 +14 -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 +55 -0
|
@@ -0,0 +1,877 @@
|
|
|
1
|
+
// @fitness-ignore-file file-length-limit -- behavior fixture suite; related scenarios stay together while checks are split into focused tests.
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Third branch-behavior fixture suite: uses recipe config injection
|
|
4
|
+
* to drive otherwise-unreachable defensive guard branches, plus targeted
|
|
5
|
+
* fixtures for highest-impact remaining files.
|
|
6
|
+
*/
|
|
7
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { tmpdir } from 'node:os';
|
|
9
|
+
import { dirname, join } from 'node:path';
|
|
10
|
+
import { RunScope, runWithScope } from '@opensip-cli/core';
|
|
11
|
+
import { fileCache, setCurrentRecipeCheckConfig, clearCurrentRecipeCheckConfig, } from '@opensip-cli/fitness';
|
|
12
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
13
|
+
import { checks } from '../index.js';
|
|
14
|
+
let cwd;
|
|
15
|
+
let written = [];
|
|
16
|
+
let testScope;
|
|
17
|
+
function fx(rel, content) {
|
|
18
|
+
const abs = join(cwd, rel);
|
|
19
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
20
|
+
writeFileSync(abs, content);
|
|
21
|
+
written.push(abs);
|
|
22
|
+
return abs;
|
|
23
|
+
}
|
|
24
|
+
function findCheck(slug) {
|
|
25
|
+
const c = checks.find((x) => x.config.slug === slug);
|
|
26
|
+
if (!c)
|
|
27
|
+
throw new Error(`check not found: ${slug}`);
|
|
28
|
+
return c;
|
|
29
|
+
}
|
|
30
|
+
async function runCheck(slug) {
|
|
31
|
+
const check = findCheck(slug);
|
|
32
|
+
await fileCache.prewarm(cwd, ['**/*']);
|
|
33
|
+
return check.run(cwd, { targetFiles: written });
|
|
34
|
+
}
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
cwd = mkdtempSync(join(tmpdir(), 'opensip-cov-bp3-'));
|
|
37
|
+
written = [];
|
|
38
|
+
testScope = new RunScope();
|
|
39
|
+
});
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
fileCache.clear();
|
|
42
|
+
clearCurrentRecipeCheckConfig(testScope);
|
|
43
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
44
|
+
});
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// detached-promises with recipe config — drive additionalSync* branches
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
describe('detached-promises — with recipe config', () => {
|
|
49
|
+
it('uses additionalSyncFunctions, additionalSyncReceivers, additionalSyncPrefixes', async () => {
|
|
50
|
+
await runWithScope(testScope, async () => {
|
|
51
|
+
setCurrentRecipeCheckConfig(testScope, {
|
|
52
|
+
'detached-promises': {
|
|
53
|
+
additionalSyncFunctions: ['mySpecialSync', 'anotherSync'],
|
|
54
|
+
additionalSyncReceivers: ['cliWriter', 'projectLogger'],
|
|
55
|
+
additionalSyncPrefixes: ['register', 'configure'],
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
fx('src/x/c.ts', [
|
|
59
|
+
'export async function f() {',
|
|
60
|
+
' mySpecialSync()',
|
|
61
|
+
' anotherSync()',
|
|
62
|
+
' cliWriter.print("hi")',
|
|
63
|
+
' projectLogger.info("there")',
|
|
64
|
+
' registerHandler()',
|
|
65
|
+
' configureRoute()',
|
|
66
|
+
' unknownCall()',
|
|
67
|
+
'}',
|
|
68
|
+
].join('\n'));
|
|
69
|
+
const result = await runCheck('detached-promises');
|
|
70
|
+
expect(result).toBeDefined();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// toctou-race-condition with recipe config — drive additionalSafeTOCTOUPaths
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
describe('toctou-race-condition — with recipe config', () => {
|
|
78
|
+
it('uses additionalSafeTOCTOUPaths', async () => {
|
|
79
|
+
await runWithScope(testScope, async () => {
|
|
80
|
+
setCurrentRecipeCheckConfig(testScope, {
|
|
81
|
+
'toctou-race-condition': {
|
|
82
|
+
additionalSafeTOCTOUPaths: ['/chain-walker/', '/audit-logs/'],
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
fx('src/chain-walker/walker.ts', ['export function walk(repo: any) {', ' const x = repo.find()', ' repo.set(1)', '}'].join('\n'));
|
|
86
|
+
fx('src/audit-logs/log.ts', ['export function log(repo: any) {', ' const x = repo.find()', ' repo.set(1)', '}'].join('\n'));
|
|
87
|
+
const result = await runCheck('toctou-race-condition');
|
|
88
|
+
expect(result).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// throws-documentation with recipe config — drive additionalSelfDocumentingSuffixes
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
describe('throws-documentation — with recipe config', () => {
|
|
96
|
+
it('uses additionalSelfDocumentingSuffixes', async () => {
|
|
97
|
+
await runWithScope(testScope, async () => {
|
|
98
|
+
setCurrentRecipeCheckConfig(testScope, {
|
|
99
|
+
'throws-documentation': {
|
|
100
|
+
additionalSelfDocumentingSuffixes: ['CompositionError', 'TransitionError'],
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
fx('src/x/t.ts', [
|
|
104
|
+
'class CompositionError extends Error {}',
|
|
105
|
+
'class TransitionError extends Error {}',
|
|
106
|
+
'export function a() { throw new CompositionError() }',
|
|
107
|
+
'export function b() { throw new TransitionError() }',
|
|
108
|
+
'export function c() { throw new Error("plain") }', // not self-documenting
|
|
109
|
+
].join('\n'));
|
|
110
|
+
const result = await runCheck('throws-documentation');
|
|
111
|
+
expect(result).toBeDefined();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// async-waterfall-detection — exercise more branches
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
describe('async-waterfall-detection — additional branches v3', () => {
|
|
119
|
+
it('various dependent-vs-independent await patterns', async () => {
|
|
120
|
+
fx('src/x/wf2.ts', [
|
|
121
|
+
'export async function withTry(): Promise<void> {',
|
|
122
|
+
' try {',
|
|
123
|
+
' const a = await fetchA()',
|
|
124
|
+
' const b = await fetchB()',
|
|
125
|
+
' const c = await fetchC()',
|
|
126
|
+
' console.log(a, b, c)',
|
|
127
|
+
' } catch (e) { console.error(e) }',
|
|
128
|
+
'}',
|
|
129
|
+
'export async function withFor(items: number[]): Promise<void> {',
|
|
130
|
+
' for (let i = 0; i < items.length; i++) {',
|
|
131
|
+
' await process(items[i])',
|
|
132
|
+
' }',
|
|
133
|
+
'}',
|
|
134
|
+
'export async function withForOf(items: number[]) {',
|
|
135
|
+
' for (const it of items) await process(it)',
|
|
136
|
+
'}',
|
|
137
|
+
'export async function withForIn(obj: Record<string, number>) {',
|
|
138
|
+
' for (const k in obj) await process(obj[k])',
|
|
139
|
+
'}',
|
|
140
|
+
'export async function nestedAsync(): Promise<void> {',
|
|
141
|
+
' return new Promise(async (resolve) => {',
|
|
142
|
+
' const a = await fetchA()',
|
|
143
|
+
' const b = await fetchB()',
|
|
144
|
+
' resolve(a + b)',
|
|
145
|
+
' })',
|
|
146
|
+
'}',
|
|
147
|
+
'export async function returnDirect() {',
|
|
148
|
+
' return await fetchA()',
|
|
149
|
+
'}',
|
|
150
|
+
'export async function noBlockBody(): Promise<number> {',
|
|
151
|
+
' return fetchA()',
|
|
152
|
+
'}',
|
|
153
|
+
'export async function multipleParallel() {',
|
|
154
|
+
' const a = fetchA()',
|
|
155
|
+
' const b = fetchB()',
|
|
156
|
+
' const c = fetchC()',
|
|
157
|
+
' return [await a, await b, await c]',
|
|
158
|
+
'}',
|
|
159
|
+
'export async function complexDep() {',
|
|
160
|
+
' const a = await fetchA()',
|
|
161
|
+
' const b = await fetchB(a, a + 1)',
|
|
162
|
+
' const c = await fetchC(b.x)',
|
|
163
|
+
' return c',
|
|
164
|
+
'}',
|
|
165
|
+
'export async function mixedDep() {',
|
|
166
|
+
' const a = await fetchA()',
|
|
167
|
+
' const b = await fetchB()', // independent of a
|
|
168
|
+
' const c = await fetchC(a)', // depends on a',
|
|
169
|
+
' return [a, b, c]',
|
|
170
|
+
'}',
|
|
171
|
+
].join('\n'));
|
|
172
|
+
const result = await runCheck('async-waterfall-detection');
|
|
173
|
+
expect(result).toBeDefined();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
// ---------------------------------------------------------------------------
|
|
177
|
+
// context-safety — drive many class shapes
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
describe('context-safety — additional branches v3', () => {
|
|
180
|
+
it('this binding scenarios across class methods, callbacks, decorators', async () => {
|
|
181
|
+
fx('src/x/cs.ts', [
|
|
182
|
+
'export class Foo {',
|
|
183
|
+
' data = "x"',
|
|
184
|
+
' arrow = () => this.data',
|
|
185
|
+
' bound = this.method.bind(this)',
|
|
186
|
+
' unbound = this.method',
|
|
187
|
+
' method() { return this.data }',
|
|
188
|
+
' async asyncMethod() { return this.data }',
|
|
189
|
+
' callbacks() {',
|
|
190
|
+
' setTimeout(() => this.method(), 100)',
|
|
191
|
+
' setTimeout(this.method.bind(this), 100)',
|
|
192
|
+
' setTimeout(this.method, 100)',
|
|
193
|
+
' Promise.resolve().then(() => this.method())',
|
|
194
|
+
' Promise.resolve().then(this.method)',
|
|
195
|
+
' [1].map(() => this.method())',
|
|
196
|
+
' [1].map(this.method)',
|
|
197
|
+
' }',
|
|
198
|
+
' static st() { return Foo.st }',
|
|
199
|
+
'}',
|
|
200
|
+
'export class WithThis {',
|
|
201
|
+
' log(this: WithThis, msg: string) { return msg }',
|
|
202
|
+
'}',
|
|
203
|
+
'export const arrow = function() { return this }', // function this',
|
|
204
|
+
'export class Inherits extends Foo {',
|
|
205
|
+
' constructor() { super() }',
|
|
206
|
+
' override method() { return super.method() }',
|
|
207
|
+
'}',
|
|
208
|
+
].join('\n'));
|
|
209
|
+
const result = await runCheck('context-leakage');
|
|
210
|
+
expect(result).toBeDefined();
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
// stubbed-implementation-detection — broader branches
|
|
215
|
+
// ---------------------------------------------------------------------------
|
|
216
|
+
describe('stubbed-implementation-detection — additional branches v3', () => {
|
|
217
|
+
it('common patterns across functions, methods, properties', async () => {
|
|
218
|
+
fx('src/x/s2.ts', [
|
|
219
|
+
'export class S {',
|
|
220
|
+
' m1(): null { return null }',
|
|
221
|
+
' m2() { return [] }',
|
|
222
|
+
' m3() { return {} }',
|
|
223
|
+
' m4(): never { throw new Error("stub") }',
|
|
224
|
+
' m5() {} // empty',
|
|
225
|
+
' async m6() { return null }',
|
|
226
|
+
' async m7() { return [] }',
|
|
227
|
+
' async m8(): Promise<void> {}',
|
|
228
|
+
' m9() { /* TODO */ return null }',
|
|
229
|
+
' m10() { /* FIXME */ return null }',
|
|
230
|
+
' m11() { throw new Error("not implemented yet") }',
|
|
231
|
+
' m12() { throw new Error("Not yet implemented") }',
|
|
232
|
+
' m13(): void { return }', // explicit early return',
|
|
233
|
+
' // realistic non-stub',
|
|
234
|
+
' realM(a: number) { if (a < 0) throw new RangeError("neg"); return a + 1 }',
|
|
235
|
+
'}',
|
|
236
|
+
'export const arr = () => null',
|
|
237
|
+
'export const arr2 = () => []',
|
|
238
|
+
'export const arr3 = () => ({})',
|
|
239
|
+
'export const arr4 = () => undefined',
|
|
240
|
+
'export const arr5 = (a: number) => { if (a < 0) throw new Error("x"); return a }',
|
|
241
|
+
'export function f1() { return null }',
|
|
242
|
+
'export function f2() { return [] }',
|
|
243
|
+
'export function f3() { return {} }',
|
|
244
|
+
'export function f4() { return undefined }',
|
|
245
|
+
'export function f5() { /* TODO */ }',
|
|
246
|
+
'export function realF(a: number) {',
|
|
247
|
+
' if (a < 0) throw new RangeError("neg")',
|
|
248
|
+
' let x = 0',
|
|
249
|
+
' for (let i = 0; i < a; i++) x += i',
|
|
250
|
+
' return x',
|
|
251
|
+
'}',
|
|
252
|
+
].join('\n'));
|
|
253
|
+
const result = await runCheck('stubbed-implementation-detection');
|
|
254
|
+
expect(result).toBeDefined();
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
// ---------------------------------------------------------------------------
|
|
258
|
+
// numeric-validation — broader cases
|
|
259
|
+
// ---------------------------------------------------------------------------
|
|
260
|
+
describe('numeric-validation — additional branches v3', () => {
|
|
261
|
+
it('parseInt/parseFloat, division, modulo, multiplication, with and without guards', async () => {
|
|
262
|
+
fx('src/x/n.ts', [
|
|
263
|
+
'export function divNoGuard(a: number, b: number) { return a / b }',
|
|
264
|
+
'export function divGuardZero(a: number, b: number) {',
|
|
265
|
+
' if (b === 0) throw new RangeError("div by zero")',
|
|
266
|
+
' return a / b',
|
|
267
|
+
'}',
|
|
268
|
+
'export function divGuardNotZero(a: number, b: number) {',
|
|
269
|
+
' if (b !== 0) return a / b',
|
|
270
|
+
' return 0',
|
|
271
|
+
'}',
|
|
272
|
+
'export function piRoundtrip(s: string) {',
|
|
273
|
+
' const n = parseInt(s, 10)',
|
|
274
|
+
' if (Number.isNaN(n)) return 0',
|
|
275
|
+
' return n',
|
|
276
|
+
'}',
|
|
277
|
+
'export function piNoRadix(s: string) { return parseInt(s) }',
|
|
278
|
+
'export function pfWithGuard(s: string) {',
|
|
279
|
+
' const n = parseFloat(s)',
|
|
280
|
+
' if (!Number.isFinite(n)) return 0',
|
|
281
|
+
' return n',
|
|
282
|
+
'}',
|
|
283
|
+
'export function withNumberCons(s: string) {',
|
|
284
|
+
' const n = Number(s)',
|
|
285
|
+
' if (Number.isNaN(n)) return 0',
|
|
286
|
+
' return n',
|
|
287
|
+
'}',
|
|
288
|
+
'export function modOp(a: number, b: number) { return a % b }',
|
|
289
|
+
'export function powOp(a: number, b: number) { return a ** b }',
|
|
290
|
+
'export function safeMod(a: number, b: number) {',
|
|
291
|
+
' if (b === 0) throw new Error("div0")',
|
|
292
|
+
' return a % b',
|
|
293
|
+
'}',
|
|
294
|
+
'export function bitwiseOp(a: number, b: number) { return (a & b) | (a ^ b) }',
|
|
295
|
+
'export function negOp(a: number) { return -a }',
|
|
296
|
+
'export function combo(a: number, b: number) {',
|
|
297
|
+
' if (Number.isFinite(a) && Number.isFinite(b)) return a * b',
|
|
298
|
+
' return 0',
|
|
299
|
+
'}',
|
|
300
|
+
].join('\n'));
|
|
301
|
+
const result = await runCheck('numeric-validation');
|
|
302
|
+
expect(result).toBeDefined();
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
// array-validation — broader patterns to drive remaining branches
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
describe('array-validation — additional branches v3', () => {
|
|
309
|
+
it('iteration methods, indexed access, spread, forwarding, sinks', async () => {
|
|
310
|
+
fx('src/x/a3.ts', [
|
|
311
|
+
'export function viaForOf(items: number[]) { for (const x of items) console.log(x) }',
|
|
312
|
+
'export function viaForLoop(items: number[]) { for (let i = 0; i < items.length; i++) console.log(items[i]) }',
|
|
313
|
+
'export function viaForEach(items: number[]) { items.forEach((x) => console.log(x)) }',
|
|
314
|
+
'export function viaMap(items: number[]) { return items.map((x) => x * 2) }',
|
|
315
|
+
'export function viaFilter(items: number[]) { return items.filter((x) => x > 0) }',
|
|
316
|
+
'export function viaReduce(items: number[]) { return items.reduce((a, b) => a + b, 0) }',
|
|
317
|
+
'export function viaSlice(items: number[]) { return items.slice(0, 5) }',
|
|
318
|
+
'export function viaIncludes(items: number[]) { return items.includes(1) }',
|
|
319
|
+
'export function viaIndexOf(items: number[]) { return items.indexOf(1) }',
|
|
320
|
+
'export function viaJoin(items: number[]) { return items.join(",") }',
|
|
321
|
+
'export function viaConcat(items: number[]) { return items.concat([4, 5]) }',
|
|
322
|
+
'export function viaFlat(items: number[][]) { return items.flat() }',
|
|
323
|
+
'export function viaSpread(items: number[]) { return [...items] }',
|
|
324
|
+
'export function viaSpreadCall(items: number[]) { return Math.max(...items) }',
|
|
325
|
+
'export function viaForward(items: number[]) { return doSomething(items) }',
|
|
326
|
+
'export function viaForwardCast(items: number[]) { return doSomething(items as any) }',
|
|
327
|
+
'export function viaShorthand(items: number[]) { return { items } }',
|
|
328
|
+
'export function viaIndexed(items: number[]) { return items[0] }',
|
|
329
|
+
'export function viaOptionalChain(items?: number[]) { return items?.[0] }',
|
|
330
|
+
'export function viaNullish(items: number[] | null) { return (items ?? [])[0] }',
|
|
331
|
+
'export function viaSink(bucket: number[]) { bucket.push(1) }',
|
|
332
|
+
'export function viaUnshift(bucket: number[]) { bucket.unshift(1) }',
|
|
333
|
+
'export function viaSplice(bucket: number[]) { bucket.splice(0, 1) }',
|
|
334
|
+
'export function _ignored(items: number[]) { return null }', // underscore param',
|
|
335
|
+
'export function destructured({ items }: { items: number[] }) { return items.length }',
|
|
336
|
+
'export function nestedTypes(items: Map<string, number[]>) { return items.get("a")?.length }',
|
|
337
|
+
'export function withZod(items: number[]) { z.array(z.number()).parse(items); return items[0] }',
|
|
338
|
+
'export function withCheck(items: number[]) { return checkAvailable(items) ? items[0] : null }',
|
|
339
|
+
'export function abstractMethod() {',
|
|
340
|
+
' abstract class A {',
|
|
341
|
+
' // dummy',
|
|
342
|
+
' }',
|
|
343
|
+
' return A',
|
|
344
|
+
'}',
|
|
345
|
+
].join('\n'));
|
|
346
|
+
const result = await runCheck('array-validation');
|
|
347
|
+
expect(result).toBeDefined();
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
// null-safety — broader patterns
|
|
352
|
+
// ---------------------------------------------------------------------------
|
|
353
|
+
describe('null-safety — additional branches v3', () => {
|
|
354
|
+
it('various null-handling patterns', async () => {
|
|
355
|
+
fx('src/x/ns.ts', [
|
|
356
|
+
'export function f1(x: string | null) { return x?.length ?? 0 }',
|
|
357
|
+
'export function f2(x: string | null) { if (x !== null) return x.length; return 0 }',
|
|
358
|
+
'export function f3(x: string | null) { if (x === null) return 0; return x.length }',
|
|
359
|
+
'export function f4(x: string | undefined) { return x ?? "default" }',
|
|
360
|
+
'export function f5(x: any) { return x.length }', // any-typed',
|
|
361
|
+
'export function f6(x: { a?: { b?: number } }) { return x.a?.b ?? 0 }',
|
|
362
|
+
'export function f7(x: number | null) { return Number(x) || 0 }',
|
|
363
|
+
'export function f8(x: { items?: number[] | null }) { return x.items?.[0] ?? 0 }',
|
|
364
|
+
'export function f9(x?: number) { return x! + 1 }', // non-null assertion',
|
|
365
|
+
'export function f10(x: string | null) {',
|
|
366
|
+
' if (typeof x === "string") return x.length',
|
|
367
|
+
' return 0',
|
|
368
|
+
'}',
|
|
369
|
+
'export function f11(x?: { a: string }) {',
|
|
370
|
+
' if (!x) throw new Error("required")',
|
|
371
|
+
' return x.a',
|
|
372
|
+
'}',
|
|
373
|
+
'export class K {',
|
|
374
|
+
' data?: { id: string }',
|
|
375
|
+
' m1() { return this.data?.id }',
|
|
376
|
+
' m2() { return this.data?.id ?? "anon" }',
|
|
377
|
+
' m3() { return this.data!.id }',
|
|
378
|
+
' m4() {',
|
|
379
|
+
' if (!this.data) return null',
|
|
380
|
+
' return this.data.id',
|
|
381
|
+
' }',
|
|
382
|
+
'}',
|
|
383
|
+
].join('\n'));
|
|
384
|
+
const result = await runCheck('null-safety');
|
|
385
|
+
expect(result).toBeDefined();
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
// ---------------------------------------------------------------------------
|
|
389
|
+
// throws-documentation v3 — exercise rethrows of different kinds
|
|
390
|
+
// ---------------------------------------------------------------------------
|
|
391
|
+
describe('throws-documentation — additional branches v3', () => {
|
|
392
|
+
it('various rethrow shapes', async () => {
|
|
393
|
+
fx('src/x/t3.ts', [
|
|
394
|
+
'class CustomError extends Error {}',
|
|
395
|
+
'export function r1() { try { return 1 } catch (err) { throw err } }',
|
|
396
|
+
'export function r2() { try { return 1 } catch (e) { throw e } }',
|
|
397
|
+
'export function r3() { try { return 1 } catch (ex) { throw ex } }',
|
|
398
|
+
'export function r4() { try { return 1 } catch (exception) { throw exception } }',
|
|
399
|
+
'export function r5() { try { return 1 } catch (err) { throw new CustomError() } }',
|
|
400
|
+
'export function r6() {',
|
|
401
|
+
' try { return 1 }',
|
|
402
|
+
' catch (err) { throw wrap(err) }',
|
|
403
|
+
'}',
|
|
404
|
+
'export function r7() {',
|
|
405
|
+
' try { return 1 }',
|
|
406
|
+
' catch (err) { throw err.unwrapErr() }',
|
|
407
|
+
'}',
|
|
408
|
+
'export function r8() {',
|
|
409
|
+
' try { return 1 }',
|
|
410
|
+
' catch (err) { throw err.unwrap() }',
|
|
411
|
+
'}',
|
|
412
|
+
'export function r9() {',
|
|
413
|
+
' try { return 1 }',
|
|
414
|
+
' catch (err) { throw err.someMethod() }',
|
|
415
|
+
'}',
|
|
416
|
+
'export class K {',
|
|
417
|
+
' error?: Error',
|
|
418
|
+
' cause?: Error',
|
|
419
|
+
' innerError?: Error',
|
|
420
|
+
' originalError?: Error',
|
|
421
|
+
' m1() { throw this.error }',
|
|
422
|
+
' m2() { throw this.cause }',
|
|
423
|
+
' m3() { throw this.innerError }',
|
|
424
|
+
' m4() { throw this.originalError }',
|
|
425
|
+
'}',
|
|
426
|
+
'export function freshError() { throw new Error("fresh") }',
|
|
427
|
+
'export function withReturnType(): never { throw new Error("never") }',
|
|
428
|
+
'export class C {',
|
|
429
|
+
' static st() { throw new Error("static") }',
|
|
430
|
+
'}',
|
|
431
|
+
'export const arrow = () => { throw new Error("arrow") }',
|
|
432
|
+
'export const namedArrow = function inner() { throw new Error("named") }',
|
|
433
|
+
'export function inCallback() { return [1].map(() => { throw new Error("cb") }) }',
|
|
434
|
+
].join('\n'));
|
|
435
|
+
const result = await runCheck('throws-documentation');
|
|
436
|
+
expect(result).toBeDefined();
|
|
437
|
+
});
|
|
438
|
+
});
|
|
439
|
+
// ---------------------------------------------------------------------------
|
|
440
|
+
// fastify-route-validation — exercise more shapes
|
|
441
|
+
// ---------------------------------------------------------------------------
|
|
442
|
+
describe('fastify-route-validation — additional branches v3', () => {
|
|
443
|
+
it('routes with various option shapes and handler types', async () => {
|
|
444
|
+
fx('src/r/v3.ts', [
|
|
445
|
+
'import type { FastifyInstance } from "fastify"',
|
|
446
|
+
'export async function reg(app: FastifyInstance) {',
|
|
447
|
+
' // schema with body — validated',
|
|
448
|
+
' app.post("/a", { schema: { body: { type: "object" } } }, async () => ({ ok: true }))',
|
|
449
|
+
' // schema without body — not validated',
|
|
450
|
+
' app.post("/b", { schema: { params: { type: "object" } } }, async () => ({ ok: true }))',
|
|
451
|
+
' // no schema, manual validation',
|
|
452
|
+
' app.post("/c", async (req, reply) => {',
|
|
453
|
+
' if (!request.body) return reply.code(400).send({ message: "Missing body" })',
|
|
454
|
+
' return { ok: true }',
|
|
455
|
+
' })',
|
|
456
|
+
' // no schema, no validation',
|
|
457
|
+
' app.post("/d", async (req) => req.body)',
|
|
458
|
+
' // function handler',
|
|
459
|
+
' app.post("/e", function(req, reply) { return req.body })',
|
|
460
|
+
' // object literal handler',
|
|
461
|
+
' app.post("/f", { handler: async () => ({}), schema: { body: {} } })',
|
|
462
|
+
' // single arg (skipped)',
|
|
463
|
+
' app.post("/g")',
|
|
464
|
+
' // body with zod parse',
|
|
465
|
+
' app.post("/h", async (req: any) => {',
|
|
466
|
+
' Schema.parse(req.body)',
|
|
467
|
+
' return { ok: true }',
|
|
468
|
+
' })',
|
|
469
|
+
' // body with contracts and Schema',
|
|
470
|
+
' app.post("/i", async (req: any) => {',
|
|
471
|
+
' contracts.UserSchema.parse(req.body)',
|
|
472
|
+
' return { ok: true }',
|
|
473
|
+
' })',
|
|
474
|
+
' // body with .parse',
|
|
475
|
+
' app.post("/j", async (req: any) => {',
|
|
476
|
+
' return zod.parse(req.body)',
|
|
477
|
+
' })',
|
|
478
|
+
' // body access with reply.code 400',
|
|
479
|
+
' app.put("/k", async (req: any, reply: any) => {',
|
|
480
|
+
' if (!req.body.id) return reply.code(400).send({ message: "Invalid: id required" })',
|
|
481
|
+
' return { ok: true }',
|
|
482
|
+
' })',
|
|
483
|
+
' app.patch("/l", async () => ({}))',
|
|
484
|
+
' app.get("/m", async () => ({}))', // GET — skipped
|
|
485
|
+
'}',
|
|
486
|
+
].join('\n'));
|
|
487
|
+
const result = await runCheck('fastify-route-validation');
|
|
488
|
+
expect(result).toBeDefined();
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
// ---------------------------------------------------------------------------
|
|
492
|
+
// di-static-inject-usage — broader shapes
|
|
493
|
+
// ---------------------------------------------------------------------------
|
|
494
|
+
// ---------------------------------------------------------------------------
|
|
495
|
+
// duplicate-utility-functions — additional shapes
|
|
496
|
+
// ---------------------------------------------------------------------------
|
|
497
|
+
describe('duplicate-utility-functions — additional branches v3', () => {
|
|
498
|
+
it('similar functions across files', async () => {
|
|
499
|
+
const sharedBody = 'return s.trim().toLowerCase()';
|
|
500
|
+
fx('src/u/a.ts', `export function clean(s: string): string { ${sharedBody} }`);
|
|
501
|
+
fx('src/u/b.ts', `export function clean(s: string): string { ${sharedBody} }`);
|
|
502
|
+
fx('src/u/c.ts', `export const cleanFn = (s: string): string => { ${sharedBody} }`);
|
|
503
|
+
fx('src/u/d.ts', `export const cleanFn = function(s: string): string { ${sharedBody} }`);
|
|
504
|
+
fx('src/u/e.ts', `export function uniqueClean(input: string): string {
|
|
505
|
+
// multi-step
|
|
506
|
+
const trimmed = input.trim()
|
|
507
|
+
const lower = trimmed.toLowerCase()
|
|
508
|
+
return lower
|
|
509
|
+
}`);
|
|
510
|
+
const result = await runCheck('duplicate-utility-functions');
|
|
511
|
+
expect(result).toBeDefined();
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
// ---------------------------------------------------------------------------
|
|
515
|
+
// incomplete-regex-escaping — additional branches v3
|
|
516
|
+
// ---------------------------------------------------------------------------
|
|
517
|
+
describe('incomplete-regex-escaping — additional branches v3', () => {
|
|
518
|
+
it('various RegExp patterns', async () => {
|
|
519
|
+
fx('src/x/re3.ts', [
|
|
520
|
+
'export function r1(input: string) { return new RegExp(input) }',
|
|
521
|
+
'export function r2(input: string) {',
|
|
522
|
+
' // safe escape',
|
|
523
|
+
' const escaped = input.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\\\$&")',
|
|
524
|
+
' return new RegExp(escaped)',
|
|
525
|
+
'}',
|
|
526
|
+
'export function r3(prefix: string, suffix: string) {',
|
|
527
|
+
' return new RegExp(`${prefix}.*${suffix}`)',
|
|
528
|
+
'}',
|
|
529
|
+
String.raw `export const literalRe = /[a-z]+\d{2}/`,
|
|
530
|
+
'export function r4(input: string) {',
|
|
531
|
+
' // Already escapes',
|
|
532
|
+
String.raw ` const e1 = input.replace(/\./g, "\\.")`,
|
|
533
|
+
' return new RegExp(e1)',
|
|
534
|
+
'}',
|
|
535
|
+
'export function r5(input: string) {',
|
|
536
|
+
' return input.match(new RegExp(input, "gi"))',
|
|
537
|
+
'}',
|
|
538
|
+
'export function r6(s: string, p: string) {',
|
|
539
|
+
' return s.split(new RegExp(p))',
|
|
540
|
+
'}',
|
|
541
|
+
'export function r7(s: string, p: string) {',
|
|
542
|
+
' return s.replace(new RegExp(p, "g"), "")',
|
|
543
|
+
'}',
|
|
544
|
+
'export function r8() {',
|
|
545
|
+
' // No new RegExp call',
|
|
546
|
+
' return /static/i',
|
|
547
|
+
'}',
|
|
548
|
+
'export const fromStr = new RegExp("[a-z]+", "i")',
|
|
549
|
+
].join('\n'));
|
|
550
|
+
const result = await runCheck('incomplete-regex-escaping');
|
|
551
|
+
expect(result).toBeDefined();
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
// ---------------------------------------------------------------------------
|
|
555
|
+
// silent-early-returns — broader v3
|
|
556
|
+
// ---------------------------------------------------------------------------
|
|
557
|
+
describe('silent-early-returns — additional branches v3', () => {
|
|
558
|
+
it('various return shapes with and without observability', async () => {
|
|
559
|
+
fx('src/x/ser3.ts', [
|
|
560
|
+
'export function f1(x: any) { if (!x) return null; return x }',
|
|
561
|
+
'export function f2(x: any) { if (!x) { logger.error("missing"); return null } return x }',
|
|
562
|
+
'export function f3(x: any) { if (!x) { console.log("log"); return null } return x }',
|
|
563
|
+
'export function f4(items: any[]) { if (items.length === 0) return; return items }',
|
|
564
|
+
'export function f5() { return undefined }',
|
|
565
|
+
'export function f6() { return null }',
|
|
566
|
+
'export function f7() { return [] }',
|
|
567
|
+
'export function f8() { return {} }',
|
|
568
|
+
'export function f9(): never { throw new Error("nope") }',
|
|
569
|
+
'export function f10(x: any) { return x ?? null }',
|
|
570
|
+
'export function f11(x: any) { return x || "default" }',
|
|
571
|
+
'export const arrow = (x: any) => x ? x.id : null',
|
|
572
|
+
'export class X {',
|
|
573
|
+
' m1(x: any) { if (!x) return null; return x }',
|
|
574
|
+
' m2(x: any) { if (!x) { this.emit("missing"); return null } return x }',
|
|
575
|
+
' emit(_: string) {}',
|
|
576
|
+
'}',
|
|
577
|
+
'export async function asyncEmpty() { return null }',
|
|
578
|
+
'export function withValidator(x: any) {',
|
|
579
|
+
' validate(x)',
|
|
580
|
+
' if (!isValid(x)) return null',
|
|
581
|
+
' return x.data',
|
|
582
|
+
'}',
|
|
583
|
+
].join('\n'));
|
|
584
|
+
const result = await runCheck('silent-early-returns');
|
|
585
|
+
expect(result).toBeDefined();
|
|
586
|
+
});
|
|
587
|
+
});
|
|
588
|
+
// ---------------------------------------------------------------------------
|
|
589
|
+
// missing-input-validation — broader v3
|
|
590
|
+
// ---------------------------------------------------------------------------
|
|
591
|
+
describe('missing-input-validation — additional branches v3', () => {
|
|
592
|
+
it('various handler shapes', async () => {
|
|
593
|
+
fx('src/h/h3.ts', [
|
|
594
|
+
'import { z } from "zod"',
|
|
595
|
+
'export async function h1(req: any) {',
|
|
596
|
+
' const Body = z.object({ id: z.string() })',
|
|
597
|
+
' return Body.parse(req.body)',
|
|
598
|
+
'}',
|
|
599
|
+
'export async function h2(req: any) {',
|
|
600
|
+
' return req.body.id', // direct access',
|
|
601
|
+
'}',
|
|
602
|
+
'export async function h3(req: any) {',
|
|
603
|
+
' const { id } = req.body', // destructured',
|
|
604
|
+
' return id',
|
|
605
|
+
'}',
|
|
606
|
+
'export async function h4(req: any) {',
|
|
607
|
+
' const Body = z.object({ id: z.string() })',
|
|
608
|
+
' const result = Body.safeParse(req.body)',
|
|
609
|
+
' if (!result.success) return null',
|
|
610
|
+
' return result.data',
|
|
611
|
+
'}',
|
|
612
|
+
'export const arrowH = async (req: any) => req.body',
|
|
613
|
+
'export class C {',
|
|
614
|
+
' async handle(req: any) { return req.body }',
|
|
615
|
+
' async safe(req: any) {',
|
|
616
|
+
' const Body = z.object({ id: z.string() })',
|
|
617
|
+
' return Body.parse(req.body)',
|
|
618
|
+
' }',
|
|
619
|
+
'}',
|
|
620
|
+
].join('\n'));
|
|
621
|
+
const result = await runCheck('missing-input-validation');
|
|
622
|
+
expect(result).toBeDefined();
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
// ---------------------------------------------------------------------------
|
|
626
|
+
// database-schema-validation — drive defaults/notNull/unique branches
|
|
627
|
+
// ---------------------------------------------------------------------------
|
|
628
|
+
describe('database-schema-validation — additional branches v3', () => {
|
|
629
|
+
it('table with various column shapes', async () => {
|
|
630
|
+
fx('src/db/sv3.ts', [
|
|
631
|
+
'import { pgTable, serial, text, varchar, integer, boolean, timestamp, json, jsonb, uuid, real } from "drizzle-orm/pg-core"',
|
|
632
|
+
'export const t = pgTable("t", {',
|
|
633
|
+
' id: serial("id").primaryKey(),',
|
|
634
|
+
' uuid: uuid("uuid").defaultRandom().notNull(),',
|
|
635
|
+
' name: text("name").notNull(),',
|
|
636
|
+
' email: varchar("email", { length: 255 }).notNull().unique(),',
|
|
637
|
+
' age: integer("age"),', // nullable int — no default
|
|
638
|
+
' active: boolean("active").default(true),',
|
|
639
|
+
' meta: jsonb("meta").default({}).notNull(),',
|
|
640
|
+
' amount: real("amount"),',
|
|
641
|
+
' createdAt: timestamp("created_at").defaultNow().notNull(),',
|
|
642
|
+
' updatedAt: timestamp("updated_at"),',
|
|
643
|
+
' notes: text("notes").default("none"),',
|
|
644
|
+
'})',
|
|
645
|
+
'export const t2 = pgTable("t2", {',
|
|
646
|
+
' id: text("id"), // missing primary key',
|
|
647
|
+
' data: text("data"), // missing notNull',
|
|
648
|
+
'})',
|
|
649
|
+
].join('\n'));
|
|
650
|
+
const result = await runCheck('database-schema-validation');
|
|
651
|
+
expect(result).toBeDefined();
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
// ---------------------------------------------------------------------------
|
|
655
|
+
// openapi-response-coverage — broader v3
|
|
656
|
+
// ---------------------------------------------------------------------------
|
|
657
|
+
// ---------------------------------------------------------------------------
|
|
658
|
+
// pii-exposure-in-logs — broader v3
|
|
659
|
+
// ---------------------------------------------------------------------------
|
|
660
|
+
describe('pii-exposure-in-logs — additional branches v3', () => {
|
|
661
|
+
it('various log methods and PII shapes', async () => {
|
|
662
|
+
fx('src/svc/log3.ts', [
|
|
663
|
+
'logger.info("Hello")',
|
|
664
|
+
'logger.info({ user: { email: x.email, name: x.name } })',
|
|
665
|
+
'logger.error({ password: x.password })',
|
|
666
|
+
'logger.warn({ ssn: x.ssn, dob: x.dob })',
|
|
667
|
+
'logger.debug({ creditCard: x.cc })',
|
|
668
|
+
'logger.trace({ phone: x.phone })',
|
|
669
|
+
'console.log("plain")',
|
|
670
|
+
'console.log({ event: "metric.recorded", value: 1 })',
|
|
671
|
+
'console.log(x.body)', // body included
|
|
672
|
+
'console.error("boom: " + x.message)',
|
|
673
|
+
'console.warn(`[${x.userId}] hi`)',
|
|
674
|
+
'pino.info("ok")',
|
|
675
|
+
'pino.error({ err: e })',
|
|
676
|
+
'log({ event: "x" })',
|
|
677
|
+
].join('\n'));
|
|
678
|
+
const result = await runCheck('pii-exposure-in-logs');
|
|
679
|
+
expect(result).toBeDefined();
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
// ---------------------------------------------------------------------------
|
|
683
|
+
// logger-event-name-format — broader v3
|
|
684
|
+
// ---------------------------------------------------------------------------
|
|
685
|
+
describe('logger-event-name-format — additional branches v3', () => {
|
|
686
|
+
it('various event name shapes and edge cases', async () => {
|
|
687
|
+
fx('src/svc/ev3.ts', [
|
|
688
|
+
'logger.info("user.created")',
|
|
689
|
+
'logger.info("auth.login.success")',
|
|
690
|
+
'logger.info("module.event_with_underscore")',
|
|
691
|
+
'logger.info("WrongFormat")',
|
|
692
|
+
'logger.info("wrong-format")',
|
|
693
|
+
'logger.info("")',
|
|
694
|
+
'logger.info({ event: "ok.snake_case" })',
|
|
695
|
+
'logger.info({ event: "OK.SNAKE_CASE" })',
|
|
696
|
+
'logger.info({ event: "" })',
|
|
697
|
+
'logger.info({ event: 123 })',
|
|
698
|
+
'logger.info({ x: 1 })', // no event field',
|
|
699
|
+
'logger.warn({ event: undefined })',
|
|
700
|
+
'logger.error({ event: null })',
|
|
701
|
+
].join('\n'));
|
|
702
|
+
const result = await runCheck('logger-event-name-format');
|
|
703
|
+
expect(result).toBeDefined();
|
|
704
|
+
});
|
|
705
|
+
});
|
|
706
|
+
// ---------------------------------------------------------------------------
|
|
707
|
+
// lazy-loading — broader v3
|
|
708
|
+
// ---------------------------------------------------------------------------
|
|
709
|
+
// ---------------------------------------------------------------------------
|
|
710
|
+
// unused-modules — broader v3
|
|
711
|
+
// ---------------------------------------------------------------------------
|
|
712
|
+
// ---------------------------------------------------------------------------
|
|
713
|
+
// missing-type-exports v3 — exercise file types and patterns
|
|
714
|
+
// ---------------------------------------------------------------------------
|
|
715
|
+
describe('missing-type-exports — additional branches v3', () => {
|
|
716
|
+
it('packages with different exports shapes', async () => {
|
|
717
|
+
// Conditional-only exports (no subpath keys)
|
|
718
|
+
fx('packages/p1/package.json', JSON.stringify({
|
|
719
|
+
name: '@s/p1',
|
|
720
|
+
version: '1.0.0',
|
|
721
|
+
exports: {
|
|
722
|
+
types: './dist/index.d.ts',
|
|
723
|
+
import: './dist/index.js',
|
|
724
|
+
default: './dist/index.cjs',
|
|
725
|
+
},
|
|
726
|
+
}, null, 2));
|
|
727
|
+
// Plain object exports
|
|
728
|
+
fx('packages/p2/package.json', JSON.stringify({
|
|
729
|
+
name: '@s/p2',
|
|
730
|
+
version: '1.0.0',
|
|
731
|
+
exports: {
|
|
732
|
+
'.': './dist/index.js',
|
|
733
|
+
'./sub': './dist/sub.js',
|
|
734
|
+
'./widgets/*': './dist/widgets/*.js',
|
|
735
|
+
},
|
|
736
|
+
}, null, 2));
|
|
737
|
+
// String exports (shorthand)
|
|
738
|
+
fx('packages/p3/package.json', JSON.stringify({
|
|
739
|
+
name: '@s/p3',
|
|
740
|
+
version: '1.0.0',
|
|
741
|
+
exports: './dist/index.js',
|
|
742
|
+
}, null, 2));
|
|
743
|
+
// No exports field at all
|
|
744
|
+
fx('packages/p4/package.json', JSON.stringify({
|
|
745
|
+
name: '@s/p4',
|
|
746
|
+
version: '1.0.0',
|
|
747
|
+
}, null, 2));
|
|
748
|
+
fx('packages/p4/src/index.ts', 'export const p4root = 1');
|
|
749
|
+
fx('packages/p4/src/internal.ts', 'export const inner = 1');
|
|
750
|
+
fx('packages/u/src/uses.ts', [
|
|
751
|
+
'import { x } from "@s/p1/anything"',
|
|
752
|
+
'import { y } from "@s/p2/widgets/foo"',
|
|
753
|
+
'import { z } from "@s/p2/notexposed"',
|
|
754
|
+
'import { a } from "@s/p3/anything"',
|
|
755
|
+
'import { p4root, inner } from "@s/p4/internal"',
|
|
756
|
+
'import { same } from "@s/p4"', // root-only
|
|
757
|
+
'import unscoped from "react"',
|
|
758
|
+
'import single from "@scope/single"', // pkg = "@scope/single", subpath = "."
|
|
759
|
+
'export const all = [x, y, z, a, p4root, inner, same, unscoped, single]',
|
|
760
|
+
].join('\n'));
|
|
761
|
+
fx('packages/u/src/x.test.ts', 'import { x } from "@s/p1/sub"\nexport const t = x');
|
|
762
|
+
fx('packages/u/__tests__/y.ts', 'import { y } from "@s/p1/sub"\nexport const t = y');
|
|
763
|
+
fx('packages/u/dist/z.ts', 'import { z } from "@s/p1/sub"');
|
|
764
|
+
fx('packages/u/node_modules/dep/x.ts', 'import { x } from "@s/p1/sub"');
|
|
765
|
+
const result = await runCheck('missing-type-exports');
|
|
766
|
+
expect(result).toBeDefined();
|
|
767
|
+
});
|
|
768
|
+
});
|
|
769
|
+
// ---------------------------------------------------------------------------
|
|
770
|
+
// result-pattern-consistency — broader v3
|
|
771
|
+
// ---------------------------------------------------------------------------
|
|
772
|
+
describe('result-pattern-consistency — additional branches v3', () => {
|
|
773
|
+
it('various Result types and throw mixing', async () => {
|
|
774
|
+
fx('src/x/r3.ts', [
|
|
775
|
+
'type Result<T, E> = { ok: true; value: T } | { ok: false; error: E }',
|
|
776
|
+
'export function ok<T>(v: T): Result<T, never> { return { ok: true, value: v } }',
|
|
777
|
+
'export function err<E>(e: E): Result<never, E> { return { ok: false, error: e } }',
|
|
778
|
+
'export function valid(): Result<number, string> { return ok(1) }',
|
|
779
|
+
'export function withErrTyped(): Result<number, string> { return err("nope") }',
|
|
780
|
+
'export function bothPattern(x: number): Result<number, string> {',
|
|
781
|
+
' if (x < 0) return err("neg")',
|
|
782
|
+
' if (x === 0) throw new Error("zero")', // mixed',
|
|
783
|
+
' return ok(x * 2)',
|
|
784
|
+
'}',
|
|
785
|
+
'export function caughtRethrow() {',
|
|
786
|
+
' try { return ok(1) }',
|
|
787
|
+
' catch (e) { throw e }',
|
|
788
|
+
'}',
|
|
789
|
+
'export function legitimateThrowTyped() {',
|
|
790
|
+
' throw new ValidationError("bad")',
|
|
791
|
+
'}',
|
|
792
|
+
'export function isValid(x: number): boolean {',
|
|
793
|
+
' if (!Number.isFinite(x)) throw new Error("not finite")',
|
|
794
|
+
' return x > 0',
|
|
795
|
+
'}',
|
|
796
|
+
'export function checkAvailable(): boolean { return true }',
|
|
797
|
+
'export function validateInput(): boolean { return true }',
|
|
798
|
+
'export function assertNonNull<T>(x: T | null): T {',
|
|
799
|
+
' if (x === null) throw new Error("null")',
|
|
800
|
+
' return x',
|
|
801
|
+
'}',
|
|
802
|
+
'export function arrowFn(x: number) { if (x < 0) throw new Error("neg") }',
|
|
803
|
+
].join('\n'));
|
|
804
|
+
const result = await runCheck('result-pattern-consistency');
|
|
805
|
+
expect(result).toBeDefined();
|
|
806
|
+
});
|
|
807
|
+
});
|
|
808
|
+
// ---------------------------------------------------------------------------
|
|
809
|
+
// sql-injection — broader v3
|
|
810
|
+
// ---------------------------------------------------------------------------
|
|
811
|
+
describe('sql-injection — additional branches v3', () => {
|
|
812
|
+
it('various injection vectors', async () => {
|
|
813
|
+
fx('src/db/i3.ts', [
|
|
814
|
+
'export async function f1(id: string) { return db.query(`SELECT * FROM x WHERE id = ${id}`) }',
|
|
815
|
+
'export async function f2(name: string) {',
|
|
816
|
+
' const sql = "SELECT * FROM x WHERE name = \'" + name + "\'"',
|
|
817
|
+
' return db.query(sql)',
|
|
818
|
+
'}',
|
|
819
|
+
'export async function f3(id: number) { return db.query(`SELECT * FROM x WHERE id = ${id}`) }',
|
|
820
|
+
'export async function f4(arr: any[]) {',
|
|
821
|
+
' return db.query(`INSERT INTO x VALUES (${arr.join(",")})`)',
|
|
822
|
+
'}',
|
|
823
|
+
'export async function safe(id: string) { return db.query("SELECT * FROM x WHERE id = $1", [id]) }',
|
|
824
|
+
'export async function safe2(name: string) { return db.prepare("SELECT * FROM x WHERE name = ?").execute([name]) }',
|
|
825
|
+
'export async function safeComment() {',
|
|
826
|
+
' // Comment containing SELECT * FROM x',
|
|
827
|
+
' return db.query("SELECT 1")',
|
|
828
|
+
'}',
|
|
829
|
+
'export async function noSql(name: string) { return name }',
|
|
830
|
+
].join('\n'));
|
|
831
|
+
const result = await runCheck('sql-injection');
|
|
832
|
+
expect(result).toBeDefined();
|
|
833
|
+
});
|
|
834
|
+
});
|
|
835
|
+
// ---------------------------------------------------------------------------
|
|
836
|
+
// input-sanitization — broader v3
|
|
837
|
+
// ---------------------------------------------------------------------------
|
|
838
|
+
describe('input-sanitization — additional branches v3', () => {
|
|
839
|
+
it('various source/sink combinations', async () => {
|
|
840
|
+
fx('src/api/u3.ts', [
|
|
841
|
+
'import * as fs from "fs"',
|
|
842
|
+
'import { exec } from "child_process"',
|
|
843
|
+
'export function f1(req: any) { return fs.readFileSync(req.body.file) }',
|
|
844
|
+
'export function f2(req: any) { return exec("echo " + req.body.x) }',
|
|
845
|
+
'export function f3(req: any) { return fetch(req.body.url) }',
|
|
846
|
+
'export function f4(req: any) { return `<div>${req.body.html}</div>` }',
|
|
847
|
+
'export function f5(req: any) { return `<a href="${req.body.url}">click</a>` }',
|
|
848
|
+
'export function f6(req: any) { return res.send(`<script>${req.body}</script>`) }',
|
|
849
|
+
'export function f7() { return fs.readFileSync("/etc/hosts") }', // safe',
|
|
850
|
+
].join('\n'));
|
|
851
|
+
const result = await runCheck('input-sanitization');
|
|
852
|
+
expect(result).toBeDefined();
|
|
853
|
+
});
|
|
854
|
+
});
|
|
855
|
+
// ---------------------------------------------------------------------------
|
|
856
|
+
// unsafe-secret-comparison — broader v3
|
|
857
|
+
// ---------------------------------------------------------------------------
|
|
858
|
+
describe('unsafe-secret-comparison — additional branches v3', () => {
|
|
859
|
+
it('various comparison patterns', async () => {
|
|
860
|
+
fx('src/auth/u3.ts', [
|
|
861
|
+
'import { timingSafeEqual } from "crypto"',
|
|
862
|
+
'export function f1(secret: string, token: string) { return secret === token }',
|
|
863
|
+
'export function f2(password: string, hash: string) { return password === hash }',
|
|
864
|
+
'export function f3(apiKey: string, expected: string) { return apiKey == expected }',
|
|
865
|
+
'export function f4(token: string, expected: string) { return token !== expected }',
|
|
866
|
+
'export function f5(a: Buffer, b: Buffer) { return a.equals(b) }',
|
|
867
|
+
'export function f6(a: Buffer, b: Buffer) { return timingSafeEqual(a, b) }',
|
|
868
|
+
'export function f7(unrelated: number, other: number) { return unrelated === other }',
|
|
869
|
+
].join('\n'));
|
|
870
|
+
const result = await runCheck('unsafe-secret-comparison');
|
|
871
|
+
expect(result).toBeDefined();
|
|
872
|
+
});
|
|
873
|
+
});
|
|
874
|
+
// ---------------------------------------------------------------------------
|
|
875
|
+
// postgres-n-plus-one — broader v3
|
|
876
|
+
// ---------------------------------------------------------------------------
|
|
877
|
+
//# sourceMappingURL=branch-fixtures-3.test.js.map
|