@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,846 @@
|
|
|
1
|
+
// @fitness-ignore-file file-length-limit -- behavior fixture suite; related scenarios stay together while checks are split into focused tests.
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Parametric execution for every check in checks-typescript.
|
|
4
|
+
*
|
|
5
|
+
* Runs each check against a curated TS-AST fixture set. The fixtures
|
|
6
|
+
* include patterns each check is likely to inspect (drizzle-orm tables,
|
|
7
|
+
* react components, typed-inject containers, package.json exports,
|
|
8
|
+
* tsconfig variations) so per-check `analyze()` paths execute. Per-
|
|
9
|
+
* check correctness assertions belong in dedicated tests; this file's
|
|
10
|
+
* purpose is execution coverage.
|
|
11
|
+
*/
|
|
12
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { tmpdir } from 'node:os';
|
|
14
|
+
import { dirname, join } from 'node:path';
|
|
15
|
+
import { LanguageRegistry, RunScope, runWithScope } from '@opensip-cli/core';
|
|
16
|
+
import { fileCache } from '@opensip-cli/fitness';
|
|
17
|
+
import { typescriptAdapter } from '@opensip-cli/lang-typescript';
|
|
18
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
19
|
+
import { checks } from '../index.js';
|
|
20
|
+
// Production simulation: register the TS adapter so content filters are applied
|
|
21
|
+
// exactly as they are in real `opensip fit` runs (see behavior-fixtures.test.ts).
|
|
22
|
+
const langRegistry = new LanguageRegistry();
|
|
23
|
+
langRegistry.register(typescriptAdapter);
|
|
24
|
+
const testScope = new RunScope({ languages: langRegistry });
|
|
25
|
+
let cwd;
|
|
26
|
+
let allFixturePaths = [];
|
|
27
|
+
function fixture(rel, content) {
|
|
28
|
+
const abs = join(cwd, rel);
|
|
29
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
30
|
+
writeFileSync(abs, content);
|
|
31
|
+
return abs;
|
|
32
|
+
}
|
|
33
|
+
beforeAll(async () => {
|
|
34
|
+
cwd = mkdtempSync(join(tmpdir(), 'opensip-typescript-cov-'));
|
|
35
|
+
allFixturePaths = [
|
|
36
|
+
fixture('package.json', JSON.stringify({
|
|
37
|
+
name: 'demo',
|
|
38
|
+
version: '1.0.0',
|
|
39
|
+
type: 'module',
|
|
40
|
+
main: './dist/index.js',
|
|
41
|
+
types: './dist/index.d.ts',
|
|
42
|
+
exports: {
|
|
43
|
+
'.': { import: './dist/index.js', types: './dist/index.d.ts' },
|
|
44
|
+
},
|
|
45
|
+
dependencies: {
|
|
46
|
+
'drizzle-orm': '^0.30.0',
|
|
47
|
+
react: '^18.0.0',
|
|
48
|
+
'typed-inject': '^4.0.0',
|
|
49
|
+
},
|
|
50
|
+
devDependencies: {
|
|
51
|
+
typescript: '^5.0.0',
|
|
52
|
+
vitest: '^2.0.0',
|
|
53
|
+
},
|
|
54
|
+
scripts: { build: 'tsc' },
|
|
55
|
+
}, null, 2)),
|
|
56
|
+
fixture('tsconfig.json', JSON.stringify({
|
|
57
|
+
extends: './tsconfig.base.json',
|
|
58
|
+
compilerOptions: {
|
|
59
|
+
target: 'es2022',
|
|
60
|
+
module: 'esnext',
|
|
61
|
+
moduleResolution: 'node',
|
|
62
|
+
strict: true,
|
|
63
|
+
outDir: './dist',
|
|
64
|
+
},
|
|
65
|
+
include: ['src/**/*'],
|
|
66
|
+
}, null, 2)),
|
|
67
|
+
fixture('tsconfig.base.json', JSON.stringify({
|
|
68
|
+
compilerOptions: {
|
|
69
|
+
esModuleInterop: true,
|
|
70
|
+
skipLibCheck: true,
|
|
71
|
+
},
|
|
72
|
+
}, null, 2)),
|
|
73
|
+
fixture('src/index.ts', [
|
|
74
|
+
'export { add, divide } from "./lib/util.js";',
|
|
75
|
+
'export type { User } from "./types.js";',
|
|
76
|
+
].join('\n')),
|
|
77
|
+
fixture('src/lib/util.ts', [
|
|
78
|
+
'export function add(a: number, b: number): number {',
|
|
79
|
+
' return a + b;',
|
|
80
|
+
'}',
|
|
81
|
+
'export async function divide(a: number, b: number): Promise<number> {',
|
|
82
|
+
' if (b === 0) throw new Error("divide by zero");',
|
|
83
|
+
' return a / b;',
|
|
84
|
+
'}',
|
|
85
|
+
'export function complex(',
|
|
86
|
+
' a: number, b: number, c: number, d: number, e: number, f: number',
|
|
87
|
+
') { return a + b + c + d + e + f; }',
|
|
88
|
+
].join('\n')),
|
|
89
|
+
fixture('src/types.ts', [
|
|
90
|
+
'export interface User { id: string; email: string; }',
|
|
91
|
+
'export type UserList = readonly User[];',
|
|
92
|
+
].join('\n')),
|
|
93
|
+
fixture('src/components/Button.tsx', [
|
|
94
|
+
'import React, { useState, useEffect } from "react";',
|
|
95
|
+
'export function Button({ label, onClick }: { label: string; onClick: () => void }) {',
|
|
96
|
+
' const [count, setCount] = useState(0);',
|
|
97
|
+
' useEffect(() => { console.log(count); }, [count]);',
|
|
98
|
+
' return <button onClick={() => { setCount(c => c + 1); onClick(); }}>{label}</button>;',
|
|
99
|
+
'}',
|
|
100
|
+
].join('\n')),
|
|
101
|
+
fixture('src/db/schema.ts', [
|
|
102
|
+
'import { pgTable, text, integer } from "drizzle-orm/pg-core";',
|
|
103
|
+
'export const users = pgTable("users", {',
|
|
104
|
+
' id: integer("id").primaryKey(),',
|
|
105
|
+
' email: text("email").notNull(),',
|
|
106
|
+
'});',
|
|
107
|
+
].join('\n')),
|
|
108
|
+
fixture('src/api/handler.ts', [
|
|
109
|
+
'import express from "express";',
|
|
110
|
+
'export async function handler(req: any) {',
|
|
111
|
+
' // SQL injection example for the security checks',
|
|
112
|
+
' const sql = `SELECT * FROM users WHERE id = ${req.params.id}`;',
|
|
113
|
+
' console.log(req.body); // PII exposure',
|
|
114
|
+
' return sql;',
|
|
115
|
+
'}',
|
|
116
|
+
].join('\n')),
|
|
117
|
+
fixture('src/utils/secret.ts', [
|
|
118
|
+
'export function compareSecrets(a: string, b: string): boolean {',
|
|
119
|
+
' // Unsafe == comparison for secrets',
|
|
120
|
+
' return a === b;',
|
|
121
|
+
'}',
|
|
122
|
+
].join('\n')),
|
|
123
|
+
fixture('src/observability/metrics.ts', [
|
|
124
|
+
'export function record(name: string, value: number) {',
|
|
125
|
+
' // no observability instrumentation here',
|
|
126
|
+
' return { name, value };',
|
|
127
|
+
'}',
|
|
128
|
+
].join('\n')),
|
|
129
|
+
fixture('src/__tests__/util.test.ts', [
|
|
130
|
+
'import { describe, it, expect } from "vitest";',
|
|
131
|
+
'import { add } from "../lib/util.js";',
|
|
132
|
+
'describe("add", () => {',
|
|
133
|
+
' it.skip("adds", () => {',
|
|
134
|
+
' expect(add(1, 2)).toBe(3);',
|
|
135
|
+
' });',
|
|
136
|
+
'});',
|
|
137
|
+
].join('\n')),
|
|
138
|
+
fixture('src/circular/a.ts', 'import { b } from "./b.js"; export const a = b;'),
|
|
139
|
+
fixture('src/circular/b.ts', 'import { a } from "./a.js"; export const b = a;'),
|
|
140
|
+
// --- DRIZZLE ORM patterns ---
|
|
141
|
+
fixture('src/db/users.ts', [
|
|
142
|
+
'import { pgTable, serial, text, varchar, timestamp, integer, boolean } from "drizzle-orm/pg-core";',
|
|
143
|
+
'import { relations } from "drizzle-orm";',
|
|
144
|
+
'export const users = pgTable("users", {',
|
|
145
|
+
' id: serial("id").primaryKey(),',
|
|
146
|
+
' email: varchar("email", { length: 255 }).notNull().unique(),',
|
|
147
|
+
' createdAt: timestamp("created_at").defaultNow().notNull(),',
|
|
148
|
+
' isActive: boolean("is_active").default(true),',
|
|
149
|
+
' // missing index on a frequently-queried column',
|
|
150
|
+
'});',
|
|
151
|
+
'export const posts = pgTable("posts", {',
|
|
152
|
+
' id: serial("id").primaryKey(),',
|
|
153
|
+
' userId: integer("user_id").references(() => users.id),',
|
|
154
|
+
' title: text("title").notNull(),',
|
|
155
|
+
'});',
|
|
156
|
+
'export const usersRelations = relations(users, ({ many }) => ({',
|
|
157
|
+
' posts: many(posts),',
|
|
158
|
+
'}));',
|
|
159
|
+
].join('\n')),
|
|
160
|
+
fixture('src/db/migrations/001_create_users.ts', [
|
|
161
|
+
'import { sql } from "drizzle-orm";',
|
|
162
|
+
'export const up = sql`CREATE TABLE users (id SERIAL PRIMARY KEY)`;',
|
|
163
|
+
'export const down = sql`DROP TABLE users`;',
|
|
164
|
+
].join('\n')),
|
|
165
|
+
// --- TYPED-INJECT patterns ---
|
|
166
|
+
fixture('src/di/container.ts', [
|
|
167
|
+
'import { createInjector } from "typed-inject";',
|
|
168
|
+
'class UserService {',
|
|
169
|
+
' static inject = ["db"] as const;',
|
|
170
|
+
' constructor(private db: any) {}',
|
|
171
|
+
'}',
|
|
172
|
+
'export const container = createInjector()',
|
|
173
|
+
' .provideValue("db", { query: async () => [] })',
|
|
174
|
+
' .provideClass("userService", UserService);',
|
|
175
|
+
].join('\n')),
|
|
176
|
+
// --- COMPLEX EXPRESS routes (security checks) ---
|
|
177
|
+
fixture('src/routes/admin.ts', [
|
|
178
|
+
'import express from "express";',
|
|
179
|
+
'const router = express.Router();',
|
|
180
|
+
'router.get("/users", async (req, res) => {',
|
|
181
|
+
' // Missing auth guard — should flag',
|
|
182
|
+
' const all = await fetch("/api/users");',
|
|
183
|
+
' return res.json(await all.json());',
|
|
184
|
+
'});',
|
|
185
|
+
'router.post("/raw-html", (req, res) => {',
|
|
186
|
+
' // XSS-prone',
|
|
187
|
+
' res.send(`<div>${req.body.html}</div>`);',
|
|
188
|
+
'});',
|
|
189
|
+
'export default router;',
|
|
190
|
+
].join('\n')),
|
|
191
|
+
// --- FORM HANDLER without label ---
|
|
192
|
+
fixture('src/components/LoginForm.tsx', [
|
|
193
|
+
'import React from "react";',
|
|
194
|
+
'export function LoginForm() {',
|
|
195
|
+
' return (',
|
|
196
|
+
' <form>',
|
|
197
|
+
' <input type="text" />',
|
|
198
|
+
' <input type="password" />',
|
|
199
|
+
' <div onClick={() => undefined}>tap me</div>',
|
|
200
|
+
' <span style={{ cursor: "pointer" }}>also clickable</span>',
|
|
201
|
+
' <button>Submit</button>',
|
|
202
|
+
' </form>',
|
|
203
|
+
' );',
|
|
204
|
+
'}',
|
|
205
|
+
].join('\n')),
|
|
206
|
+
// --- N+1 candidate ---
|
|
207
|
+
fixture('src/db/n-plus-one.ts', [
|
|
208
|
+
'export async function listWithDetails(items: { id: number }[]) {',
|
|
209
|
+
' const out = [];',
|
|
210
|
+
' for (const item of items) {',
|
|
211
|
+
' out.push(await fetchDetail(item.id));',
|
|
212
|
+
' }',
|
|
213
|
+
' return out;',
|
|
214
|
+
'}',
|
|
215
|
+
'async function fetchDetail(id: number) { return { id }; }',
|
|
216
|
+
].join('\n')),
|
|
217
|
+
// --- DANGEROUS REGEX ---
|
|
218
|
+
fixture('src/regex/dangerous.ts', [
|
|
219
|
+
'export const RE = /(a+)+b/;',
|
|
220
|
+
'export const RE2 = new RegExp("(.*)*x");',
|
|
221
|
+
'export function match(s: string) {',
|
|
222
|
+
' return RE.test(s);',
|
|
223
|
+
'}',
|
|
224
|
+
].join('\n')),
|
|
225
|
+
// --- COMPLEX CYCLOMATIC functions ---
|
|
226
|
+
fixture('src/util/branch-heavy.ts', [
|
|
227
|
+
'export function classify(value: number, mode: string): string {',
|
|
228
|
+
' if (mode === "a") {',
|
|
229
|
+
' if (value < 0) return "neg-a";',
|
|
230
|
+
' if (value === 0) return "zero-a";',
|
|
231
|
+
' if (value < 10) return "small-a";',
|
|
232
|
+
' if (value < 100) return "med-a";',
|
|
233
|
+
' return "big-a";',
|
|
234
|
+
' }',
|
|
235
|
+
' if (mode === "b") {',
|
|
236
|
+
' if (value < 0) return "neg-b";',
|
|
237
|
+
' if (value > 100) return "big-b";',
|
|
238
|
+
' }',
|
|
239
|
+
' if (mode === "c") return value > 50 ? "high-c" : "low-c";',
|
|
240
|
+
' return "unknown";',
|
|
241
|
+
'}',
|
|
242
|
+
].join('\n')),
|
|
243
|
+
// --- TYPED-INJECT misuse: missing inject decorator ---
|
|
244
|
+
fixture('src/di/bad.ts', [
|
|
245
|
+
'export class BadService {',
|
|
246
|
+
' // No static inject — should flag',
|
|
247
|
+
' constructor(private dep: { query(): Promise<unknown> }) {}',
|
|
248
|
+
' async run() { return this.dep.query(); }',
|
|
249
|
+
'}',
|
|
250
|
+
].join('\n')),
|
|
251
|
+
// --- SUSPICIOUS comparison + secret usage ---
|
|
252
|
+
fixture('src/secrets/compare.ts', [
|
|
253
|
+
'import { createHmac } from "node:crypto";',
|
|
254
|
+
'export function checkSig(provided: string, expected: string) {',
|
|
255
|
+
' // Should use timingSafeEqual',
|
|
256
|
+
' return provided == expected;',
|
|
257
|
+
'}',
|
|
258
|
+
'export function badHmac(secret: string, body: string) {',
|
|
259
|
+
' const got = createHmac("sha256", secret).update(body).digest("hex");',
|
|
260
|
+
' return got === "expected-here";',
|
|
261
|
+
'}',
|
|
262
|
+
].join('\n')),
|
|
263
|
+
// --- API CONTRACT mismatch placeholder ---
|
|
264
|
+
fixture('src/api/contract.ts', [
|
|
265
|
+
'export interface UserDto {',
|
|
266
|
+
' id: string;',
|
|
267
|
+
' email: string;',
|
|
268
|
+
' createdAt: string;',
|
|
269
|
+
'}',
|
|
270
|
+
'export async function fetchUser(id: string): Promise<UserDto> {',
|
|
271
|
+
' return fetch(`/api/users/${id}`).then(r => r.json());',
|
|
272
|
+
'}',
|
|
273
|
+
].join('\n')),
|
|
274
|
+
// --- THROWS without docs ---
|
|
275
|
+
fixture('src/errors/maybe-throws.ts', [
|
|
276
|
+
'export function maybeThrow(arg: string) {',
|
|
277
|
+
' if (arg === "") throw new Error("empty");',
|
|
278
|
+
' if (arg.length > 100) throw new TypeError("too long");',
|
|
279
|
+
' return arg.toUpperCase();',
|
|
280
|
+
'}',
|
|
281
|
+
].join('\n')),
|
|
282
|
+
// --- MUTABLE STATE in module ---
|
|
283
|
+
fixture('src/state/global.ts', [
|
|
284
|
+
'export let counter = 0;',
|
|
285
|
+
'export const state: { items: string[] } = { items: [] };',
|
|
286
|
+
'export function increment() { counter++; }',
|
|
287
|
+
].join('\n')),
|
|
288
|
+
// --- ASYNC PATTERNS (waterfall + missing await) ---
|
|
289
|
+
fixture('src/async/waterfall.ts', [
|
|
290
|
+
'export async function loadAll() {',
|
|
291
|
+
' const a = await loadA();',
|
|
292
|
+
' const b = await loadB();',
|
|
293
|
+
' const c = await loadC();',
|
|
294
|
+
' return { a, b, c };',
|
|
295
|
+
'}',
|
|
296
|
+
'async function loadA() { return 1; }',
|
|
297
|
+
'async function loadB() { return 2; }',
|
|
298
|
+
'async function loadC() { return 3; }',
|
|
299
|
+
].join('\n')),
|
|
300
|
+
// --- LARGE FILE (file-size-limits) ---
|
|
301
|
+
fixture('src/big/manyfns.ts', Array.from({ length: 60 }, (_, i) => `export function fn${i}(x: number): number { return x + ${i}; }`).join('\n')),
|
|
302
|
+
// --- FASTIFY routes WITHOUT schema (fastify-schema-coverage) ---
|
|
303
|
+
fixture('src/routes/fastify-unvalidated.ts', [
|
|
304
|
+
'import fastify from "fastify";',
|
|
305
|
+
'const app = fastify();',
|
|
306
|
+
'app.post("/users", async (req, res) => {',
|
|
307
|
+
' const body = req.body as any;',
|
|
308
|
+
' return { id: body.id };',
|
|
309
|
+
'});',
|
|
310
|
+
'app.get("/search/:id", (req, res) => {',
|
|
311
|
+
' return res.send({ query: req.query });',
|
|
312
|
+
'});',
|
|
313
|
+
].join('\n')),
|
|
314
|
+
// --- ARRAY parameter validation (array-validation) ---
|
|
315
|
+
fixture('src/util/unvalidated-arrays.ts', [
|
|
316
|
+
'export function processItems(items: string[]): number {',
|
|
317
|
+
' // No length / type validation before access',
|
|
318
|
+
' return items.length + (items[0]?.length ?? 0);',
|
|
319
|
+
'}',
|
|
320
|
+
'export function findUser(ids: number[]): unknown {',
|
|
321
|
+
' return lookupUsers(ids);',
|
|
322
|
+
'}',
|
|
323
|
+
'async function lookupUsers(ids: number[]) { return ids.map((i) => ({ id: i })); }',
|
|
324
|
+
].join('\n')),
|
|
325
|
+
// --- TYPEORM @Entity missing standard columns (database-schema-validation) ---
|
|
326
|
+
fixture('src/entities/address.entity.ts', [
|
|
327
|
+
'import { Entity, Column } from "typeorm";',
|
|
328
|
+
'@Entity()',
|
|
329
|
+
'export class Address {',
|
|
330
|
+
' @Column({ nullable: true }) line1!: string;',
|
|
331
|
+
' @Column() city!: string;',
|
|
332
|
+
'}',
|
|
333
|
+
].join('\n')),
|
|
334
|
+
// --- ZOD schema without .satisfies (zod-schema-coverage) ---
|
|
335
|
+
fixture('src/schemas/no-satisfies.ts', [
|
|
336
|
+
'import { z } from "zod";',
|
|
337
|
+
'export const UserSchema = z.object({ id: z.string(), name: z.string() });',
|
|
338
|
+
'export const CreateUserSchema = z.object({ name: z.string() });',
|
|
339
|
+
].join('\n')),
|
|
340
|
+
// --- NUMERIC validation (numeric-validation) ---
|
|
341
|
+
fixture('src/util/unvalidated-numbers.ts', [
|
|
342
|
+
'export function scale(factor: number): number {',
|
|
343
|
+
' return factor * 2;',
|
|
344
|
+
'}',
|
|
345
|
+
'export function parsePort(portStr: string): number {',
|
|
346
|
+
' return Number.parseInt(portStr, 10);',
|
|
347
|
+
'}',
|
|
348
|
+
'export function divider(a: number, b: number): number {',
|
|
349
|
+
' return a / b; // no zero check',
|
|
350
|
+
'}',
|
|
351
|
+
].join('\n')),
|
|
352
|
+
// --- React .map fixture ---
|
|
353
|
+
fixture('src/components/ListWithoutMemo.tsx', [
|
|
354
|
+
'export function UserList({ users }: { users: { id: string; name: string }[] }) {',
|
|
355
|
+
' return (',
|
|
356
|
+
' <div>',
|
|
357
|
+
' {users.map((u) => <UserCard key={u.id} user={u} />)}',
|
|
358
|
+
' </div>',
|
|
359
|
+
' );',
|
|
360
|
+
'}',
|
|
361
|
+
'function UserCard({ user }: { user: { id: string; name: string } }) {',
|
|
362
|
+
' return <div>{user.name}</div>;',
|
|
363
|
+
'}',
|
|
364
|
+
].join('\n')),
|
|
365
|
+
// --- Silent early returns (silent-early-returns) ---
|
|
366
|
+
fixture('src/handlers/silent-returns.ts', [
|
|
367
|
+
'export function fetchUser(id: string) {',
|
|
368
|
+
' if (!id) return null;',
|
|
369
|
+
' if (id.length > 100) return false;',
|
|
370
|
+
' return { id };',
|
|
371
|
+
'}',
|
|
372
|
+
'export function findItem(items: { id: string }[], id: string) {',
|
|
373
|
+
' for (const item of items) {',
|
|
374
|
+
' if (item.id === id) return item;',
|
|
375
|
+
' }',
|
|
376
|
+
' return undefined;',
|
|
377
|
+
'}',
|
|
378
|
+
].join('\n')),
|
|
379
|
+
// --- Incomplete regex escaping (incomplete-regex-escaping) ---
|
|
380
|
+
fixture('src/util/bad-regex-escape.ts', [
|
|
381
|
+
'export function sanitize(input: string): string {',
|
|
382
|
+
String.raw ` return input.replaceAll(/[abc]/g, "\\$&");`,
|
|
383
|
+
'}',
|
|
384
|
+
'export function escape2(input: string) {',
|
|
385
|
+
' // Missing escape for special regex chars',
|
|
386
|
+
' return input.replaceAll(new RegExp("a.b"), "x");',
|
|
387
|
+
'}',
|
|
388
|
+
].join('\n')),
|
|
389
|
+
// --- Stream / buffer size limits (stream-buffer-size-limits) ---
|
|
390
|
+
fixture('src/streams/unbounded-buffer.ts', [
|
|
391
|
+
'export async function readStream(stream: AsyncIterable<Buffer>): Promise<Buffer> {',
|
|
392
|
+
' const chunks: Buffer[] = [];',
|
|
393
|
+
' for await (const chunk of stream) {',
|
|
394
|
+
' chunks.push(chunk);',
|
|
395
|
+
' }',
|
|
396
|
+
' return Buffer.concat(chunks);',
|
|
397
|
+
'}',
|
|
398
|
+
].join('\n')),
|
|
399
|
+
// --- Awaited fetch before validation fixture ---
|
|
400
|
+
fixture('src/handlers/fail-fast-violation.ts', [
|
|
401
|
+
'export async function validateAndFetch(userId: string) {',
|
|
402
|
+
' const user = await fetchFromDB(userId);',
|
|
403
|
+
' if (!userId) return null;',
|
|
404
|
+
' return user;',
|
|
405
|
+
'}',
|
|
406
|
+
'async function fetchFromDB(id: string) { return { id }; }',
|
|
407
|
+
].join('\n')),
|
|
408
|
+
// --- DEAD CODE / unused exports ---
|
|
409
|
+
fixture('src/unused/unused-export.ts', [
|
|
410
|
+
'export function unusedFunction() { return 42; }',
|
|
411
|
+
'export const UNUSED_CONSTANT = "never used";',
|
|
412
|
+
'export type UnusedType = { x: number };',
|
|
413
|
+
].join('\n')),
|
|
414
|
+
// --- DISPOSE pattern completeness ---
|
|
415
|
+
fixture('src/lifecycle/incomplete-dispose.ts', [
|
|
416
|
+
'export interface IDisposable {',
|
|
417
|
+
' dispose(): void;',
|
|
418
|
+
'}',
|
|
419
|
+
'export class ResourceHolder implements IDisposable {',
|
|
420
|
+
' private subscription = { unsubscribe() { /* */ } };',
|
|
421
|
+
' private interval = setInterval(() => undefined, 1000);',
|
|
422
|
+
' // No dispose body — should flag',
|
|
423
|
+
' dispose(): void {}',
|
|
424
|
+
'}',
|
|
425
|
+
].join('\n')),
|
|
426
|
+
// --- LIFECYCLE cleanup enforcement (timer / subscription / event-listener) ---
|
|
427
|
+
fixture('src/lifecycle/leaks.ts', [
|
|
428
|
+
'export function startWatcher() {',
|
|
429
|
+
' setInterval(() => console.log("tick"), 5000);',
|
|
430
|
+
' globalThis.addEventListener("beforeunload", () => undefined);',
|
|
431
|
+
' const ws = { close() { /* */ }, on() { /* */ } };',
|
|
432
|
+
' return ws;',
|
|
433
|
+
'}',
|
|
434
|
+
].join('\n')),
|
|
435
|
+
// --- ERROR handling quality (catch + log without rethrow / context) ---
|
|
436
|
+
fixture('src/errors/poor-handling.ts', [
|
|
437
|
+
'export async function poorlyHandled() {',
|
|
438
|
+
' try {',
|
|
439
|
+
' await fetch("/api");',
|
|
440
|
+
' } catch (e) {',
|
|
441
|
+
' console.error(e);',
|
|
442
|
+
' }',
|
|
443
|
+
' try {',
|
|
444
|
+
' JSON.parse("not json");',
|
|
445
|
+
' } catch (e) {',
|
|
446
|
+
' // swallowed',
|
|
447
|
+
' }',
|
|
448
|
+
'}',
|
|
449
|
+
].join('\n')),
|
|
450
|
+
// --- FLASHLIST enforcement (FlatList vs FlashList) ---
|
|
451
|
+
fixture('src/components/UserList.tsx', [
|
|
452
|
+
'import { FlatList } from "react-native";',
|
|
453
|
+
'export function UserList({ data }: { data: { id: string }[] }) {',
|
|
454
|
+
' return <FlatList data={data} renderItem={({ item }) => <></>} />;',
|
|
455
|
+
'}',
|
|
456
|
+
].join('\n')),
|
|
457
|
+
// --- ARRAY mutation ordering ---
|
|
458
|
+
fixture('src/util/mutation-ordering.ts', [
|
|
459
|
+
'export function mutate(items: number[]): number[] {',
|
|
460
|
+
' // Mutates the input then returns a sliced copy',
|
|
461
|
+
' items.sort((a, b) => a - b);',
|
|
462
|
+
' return items.slice();',
|
|
463
|
+
'}',
|
|
464
|
+
].join('\n')),
|
|
465
|
+
// --- ASYNC PATTERNS (forgotten await + parallel batch) ---
|
|
466
|
+
fixture('src/async/missing-await.ts', [
|
|
467
|
+
'export async function risky() {',
|
|
468
|
+
' // Missing await — fire and forget',
|
|
469
|
+
' fetch("/api/track");',
|
|
470
|
+
' // Sequential awaits where Promise.all would do',
|
|
471
|
+
' const a = await fetch("/api/a");',
|
|
472
|
+
' const b = await fetch("/api/b");',
|
|
473
|
+
' return [a, b];',
|
|
474
|
+
'}',
|
|
475
|
+
].join('\n')),
|
|
476
|
+
// --- THROWS-DOCUMENTATION (functions that throw without @throws JSDoc) ---
|
|
477
|
+
fixture('src/errors/thrower.ts', [
|
|
478
|
+
'export function validate(input: string) {',
|
|
479
|
+
' if (!input) throw new Error("empty input");',
|
|
480
|
+
' if (input.length > 1024) throw new RangeError("too long");',
|
|
481
|
+
' return input;',
|
|
482
|
+
'}',
|
|
483
|
+
].join('\n')),
|
|
484
|
+
// --- TOCTOU race condition (read-then-update on shared map) ---
|
|
485
|
+
fixture('src/cache/toctou.ts', [
|
|
486
|
+
'export class Counter {',
|
|
487
|
+
' private state = new Map<string, number>();',
|
|
488
|
+
' increment(key: string) {',
|
|
489
|
+
' const v = this.state.get(key) ?? 0;',
|
|
490
|
+
' this.state.set(key, v + 1);',
|
|
491
|
+
' }',
|
|
492
|
+
'}',
|
|
493
|
+
].join('\n')),
|
|
494
|
+
// --- STUBBED IMPLEMENTATION (NotImplemented / TODO function bodies) ---
|
|
495
|
+
fixture('src/api/stubs.ts', [
|
|
496
|
+
'export function notDone(): never {',
|
|
497
|
+
' throw new Error("Not implemented");',
|
|
498
|
+
'}',
|
|
499
|
+
'export async function todoFn() {',
|
|
500
|
+
' // TODO',
|
|
501
|
+
' return undefined;',
|
|
502
|
+
'}',
|
|
503
|
+
].join('\n')),
|
|
504
|
+
// --- CIRCULAR import detection (stronger pair) ---
|
|
505
|
+
fixture('src/cyc/x.ts', 'import { y } from "./y.js"; export const x = () => y();'),
|
|
506
|
+
fixture('src/cyc/y.ts', 'import { x } from "./x.js"; export const y = () => x();'),
|
|
507
|
+
// --- DUPLICATE UTILITY FUNCTIONS ---
|
|
508
|
+
fixture('src/utils/dup-a.ts', [
|
|
509
|
+
'export function camelCase(s: string) { return s.replaceAll(/_([a-z])/g, (_, c: string) => c.toUpperCase()); }',
|
|
510
|
+
].join('\n')),
|
|
511
|
+
fixture('src/utils/dup-b.ts', [
|
|
512
|
+
'export function camelCase(input: string) {',
|
|
513
|
+
' return input.replaceAll(/_([a-z])/g, (_, c: string) => c.toUpperCase());',
|
|
514
|
+
'}',
|
|
515
|
+
].join('\n')),
|
|
516
|
+
// --- API CONTRACT MISMATCH (drizzle field vs DTO) ---
|
|
517
|
+
fixture('src/api/dto-mismatch.ts', [
|
|
518
|
+
'import { pgTable, integer, text } from "drizzle-orm/pg-core";',
|
|
519
|
+
'export const products = pgTable("products", {',
|
|
520
|
+
' id: integer("id").primaryKey(),',
|
|
521
|
+
' name: text("name").notNull(),',
|
|
522
|
+
' internalCode: text("internal_code"),',
|
|
523
|
+
'});',
|
|
524
|
+
'// DTO is missing internalCode but the table has it',
|
|
525
|
+
'export interface ProductDto { id: number; name: string }',
|
|
526
|
+
].join('\n')),
|
|
527
|
+
// --- USE-CASE FUNCTIONS (silent / lazy) ---
|
|
528
|
+
fixture('src/usecase/listing-fail-fast.ts', [
|
|
529
|
+
'export async function createListing(input: { sellerId: string; title: string }) {',
|
|
530
|
+
' const seller = await fetch(`/api/sellers/${input.sellerId}`);',
|
|
531
|
+
' if (!input.title) return null;',
|
|
532
|
+
' return seller.json();',
|
|
533
|
+
'}',
|
|
534
|
+
].join('\n')),
|
|
535
|
+
// --- STREAM / network buffering ---
|
|
536
|
+
fixture('src/streams/big-buffer.ts', [
|
|
537
|
+
'export async function readEverything(req: { on: (e: string, cb: (c: Buffer) => void) => void }) {',
|
|
538
|
+
' return new Promise<Buffer>((resolve) => {',
|
|
539
|
+
' const chunks: Buffer[] = [];',
|
|
540
|
+
' req.on("data", (c) => { chunks.push(c); });',
|
|
541
|
+
' req.on("end", () => resolve(Buffer.concat(chunks)));',
|
|
542
|
+
' });',
|
|
543
|
+
'}',
|
|
544
|
+
].join('\n')),
|
|
545
|
+
// --- INCOMPLETE-REGEX-ESCAPING — `.replace(/[...]/, '\\$&')` shape ---
|
|
546
|
+
fixture('src/regex/escape-edges.ts', [
|
|
547
|
+
'export function bad1(s: string) {',
|
|
548
|
+
' // No char class — should flag',
|
|
549
|
+
String.raw ` return s.replace(/abc/g, "\\$&");`,
|
|
550
|
+
'}',
|
|
551
|
+
'export function bad2(s: string) {',
|
|
552
|
+
' // Char class missing many specials — should flag',
|
|
553
|
+
String.raw ` return s.replace(/[abc]/g, "\\$&");`,
|
|
554
|
+
'}',
|
|
555
|
+
'export function ok(s: string) {',
|
|
556
|
+
' // Char class includes all required specials',
|
|
557
|
+
String.raw ` return s.replace(/[\\\^$.*+?()[\]{}|]/g, "\\$&");`,
|
|
558
|
+
'}',
|
|
559
|
+
].join('\n')),
|
|
560
|
+
// --- FASTIFY edge cases (param without access; query without access) ---
|
|
561
|
+
fixture('src/routes/fastify-edges.ts', [
|
|
562
|
+
'import fastify from "fastify";',
|
|
563
|
+
'const app = fastify();',
|
|
564
|
+
'app.get("/users/:id", async (req, res) => {',
|
|
565
|
+
' return res.send({ message: "static" });',
|
|
566
|
+
'});',
|
|
567
|
+
'app.get("/filter", async (req, res) => {',
|
|
568
|
+
' const filter = (req.query as { search?: string }).search ?? "";',
|
|
569
|
+
' return res.send({ filter });',
|
|
570
|
+
'});',
|
|
571
|
+
'app.post("/users", async (request, reply) => {',
|
|
572
|
+
' // Reads request.body but no body schema',
|
|
573
|
+
' const body = request.body as { name: string };',
|
|
574
|
+
' return reply.send({ name: body.name });',
|
|
575
|
+
'});',
|
|
576
|
+
'app.put("/users/:id", async (request, reply) => {',
|
|
577
|
+
' // Reads body and params; no schema',
|
|
578
|
+
' const params = request.params as { id: string };',
|
|
579
|
+
' const body = request.body as { name: string };',
|
|
580
|
+
' return reply.send({ id: params.id, name: body.name });',
|
|
581
|
+
'});',
|
|
582
|
+
'app.patch("/users/:id", async (request) => {',
|
|
583
|
+
' return request.body;',
|
|
584
|
+
'});',
|
|
585
|
+
].join('\n')),
|
|
586
|
+
// Object-literal route style (matches the alternate fastify shape)
|
|
587
|
+
fixture('src/routes/fastify-object.ts', [
|
|
588
|
+
'import fastify from "fastify";',
|
|
589
|
+
'const app = fastify();',
|
|
590
|
+
'app.route({',
|
|
591
|
+
' method: "POST",',
|
|
592
|
+
' url: "/items",',
|
|
593
|
+
' handler: async (request, reply) => {',
|
|
594
|
+
' const body = request.body as { name: string };',
|
|
595
|
+
' return reply.send({ name: body.name });',
|
|
596
|
+
' },',
|
|
597
|
+
'});',
|
|
598
|
+
'app.route({',
|
|
599
|
+
' method: "GET",',
|
|
600
|
+
' url: "/items/:id",',
|
|
601
|
+
' handler: async (request, reply) => {',
|
|
602
|
+
' const params = request.params as { id: string };',
|
|
603
|
+
' return reply.send({ id: params.id });',
|
|
604
|
+
' },',
|
|
605
|
+
'});',
|
|
606
|
+
].join('\n')),
|
|
607
|
+
// --- TYPEORM EDGE entities (some columns/decorators present, some absent) ---
|
|
608
|
+
fixture('src/models/product.model.ts', [
|
|
609
|
+
'import { Entity, Column, CreateDateColumn, UpdateDateColumn } from "typeorm";',
|
|
610
|
+
'@Entity()',
|
|
611
|
+
'export class Product {',
|
|
612
|
+
' @Column({ nullable: true }) description?: string;',
|
|
613
|
+
' @CreateDateColumn() createdAt!: Date;',
|
|
614
|
+
' @UpdateDateColumn() updatedAt!: Date;',
|
|
615
|
+
'}',
|
|
616
|
+
'@Entity()',
|
|
617
|
+
'export class OrderRow {',
|
|
618
|
+
' @Column({ nullable: true, default: null }) notes?: string;',
|
|
619
|
+
'}',
|
|
620
|
+
].join('\n')),
|
|
621
|
+
// --- ERROR HANDLING — `as Error` cast in catch ---
|
|
622
|
+
fixture('src/errors/cast-in-catch.ts', [
|
|
623
|
+
'export async function unsafeCast() {',
|
|
624
|
+
' try {',
|
|
625
|
+
' await fetch("/api");',
|
|
626
|
+
' } catch (e) {',
|
|
627
|
+
' const err = e as Error;',
|
|
628
|
+
' console.log(err.message);',
|
|
629
|
+
' }',
|
|
630
|
+
'}',
|
|
631
|
+
'export async function safeCast() {',
|
|
632
|
+
' try {',
|
|
633
|
+
' JSON.parse("{}");',
|
|
634
|
+
' } catch (e) {',
|
|
635
|
+
' if (e instanceof Error) {',
|
|
636
|
+
' console.log(e.message);',
|
|
637
|
+
' }',
|
|
638
|
+
' }',
|
|
639
|
+
'}',
|
|
640
|
+
].join('\n')),
|
|
641
|
+
// --- LIFECYCLE cleanup with optional chaining ---
|
|
642
|
+
fixture('src/lifecycle/optional-chain.ts', [
|
|
643
|
+
'declare class SipDataClient { destroy?(): void; }',
|
|
644
|
+
'export function setup1() {',
|
|
645
|
+
' const client = new SipDataClient();',
|
|
646
|
+
' client?.destroy?.();',
|
|
647
|
+
'}',
|
|
648
|
+
'export function setup2() {',
|
|
649
|
+
' const client = new SipDataClient();',
|
|
650
|
+
' return client;',
|
|
651
|
+
'}',
|
|
652
|
+
].join('\n')),
|
|
653
|
+
// --- SILENT-EARLY-RETURNS — nested predicate map, validator name, beyond-third-statement ---
|
|
654
|
+
fixture('src/handlers/silent-edges.ts', [
|
|
655
|
+
'export function fourthGuard(x: number, y: number, z: number, w: number) {',
|
|
656
|
+
' if (x === 1) return null;',
|
|
657
|
+
' if (y === 2) return null;',
|
|
658
|
+
' if (z === 3) return null;',
|
|
659
|
+
' if (w === 4) return null;',
|
|
660
|
+
' return 1;',
|
|
661
|
+
'}',
|
|
662
|
+
'export function inPredicateMap() {',
|
|
663
|
+
' return [1, 2, 3].map((x) => {',
|
|
664
|
+
' if (x < 0) return null;',
|
|
665
|
+
' return x * 2;',
|
|
666
|
+
' });',
|
|
667
|
+
'}',
|
|
668
|
+
'export function getOrNull(id: string) {',
|
|
669
|
+
' if (!id) return null;',
|
|
670
|
+
' return { id };',
|
|
671
|
+
'}',
|
|
672
|
+
].join('\n')),
|
|
673
|
+
// --- STREAM BUFFER size with multiple chunk array names ---
|
|
674
|
+
fixture('src/streams/various-buffers.ts', [
|
|
675
|
+
'export async function variantA(stream: AsyncIterable<Buffer>) {',
|
|
676
|
+
' const dataChunks: Buffer[] = [];',
|
|
677
|
+
' for await (const chunk of stream) {',
|
|
678
|
+
' dataChunks.push(chunk);',
|
|
679
|
+
' }',
|
|
680
|
+
' return Buffer.concat(dataChunks);',
|
|
681
|
+
'}',
|
|
682
|
+
'export function variantB(req: { on: (e: string, cb: (c: Buffer) => void) => void }) {',
|
|
683
|
+
' const buffers: Buffer[] = [];',
|
|
684
|
+
' req.on("data", (d) => { buffers.push(d); });',
|
|
685
|
+
'}',
|
|
686
|
+
].join('\n')),
|
|
687
|
+
// --- DISPOSE PATTERN with subscription fields not all cleaned ---
|
|
688
|
+
fixture('src/lifecycle/observer.ts', [
|
|
689
|
+
'export interface IDisposable { dispose(): void; }',
|
|
690
|
+
'interface Sub { unsubscribe(): void; }',
|
|
691
|
+
'export class Observer implements IDisposable {',
|
|
692
|
+
' private subscription1?: Sub;',
|
|
693
|
+
' private subscription2?: Sub;',
|
|
694
|
+
' private listener?: () => void;',
|
|
695
|
+
' dispose(): void {',
|
|
696
|
+
' this.subscription1?.unsubscribe();',
|
|
697
|
+
' // subscription2 + listener uncleaned',
|
|
698
|
+
' }',
|
|
699
|
+
'}',
|
|
700
|
+
'export class CompletelyEmpty implements IDisposable {',
|
|
701
|
+
' private sub?: Sub;',
|
|
702
|
+
' dispose(): void {}',
|
|
703
|
+
'}',
|
|
704
|
+
].join('\n')),
|
|
705
|
+
// --- CONTEXT SAFETY (mutation patterns) ---
|
|
706
|
+
fixture('src/context/mutations.ts', [
|
|
707
|
+
'export function withMutations(req: any) {',
|
|
708
|
+
' req.ctx.userId = "123";',
|
|
709
|
+
' Object.assign(req.context, { newField: "value" });',
|
|
710
|
+
' req.context.items?.push("item");',
|
|
711
|
+
' delete req.ctx.oldField;',
|
|
712
|
+
'}',
|
|
713
|
+
'export function safeContext(entry: any) {',
|
|
714
|
+
' entry.context.violations = [];',
|
|
715
|
+
'}',
|
|
716
|
+
].join('\n')),
|
|
717
|
+
// --- A11Y FORM LABELS — variants ---
|
|
718
|
+
fixture('src/components/A11yForm.tsx', [
|
|
719
|
+
'import React from "react";',
|
|
720
|
+
'export function A11yForm() {',
|
|
721
|
+
' return (',
|
|
722
|
+
' <>',
|
|
723
|
+
' <TextInput accessibilityLabel="name" />',
|
|
724
|
+
' <Input />',
|
|
725
|
+
' <Select aria-label="country" />',
|
|
726
|
+
' <Picker accessibilityLabelledBy="label-1" />',
|
|
727
|
+
' <Input />',
|
|
728
|
+
' </>',
|
|
729
|
+
' );',
|
|
730
|
+
'}',
|
|
731
|
+
'function TextInput(_props: any) { return null; }',
|
|
732
|
+
'function Input(_props: any) { return null; }',
|
|
733
|
+
'function Select(_props: any) { return null; }',
|
|
734
|
+
'function Picker(_props: any) { return null; }',
|
|
735
|
+
].join('\n')),
|
|
736
|
+
// --- IN-MEMORY repository detection ---
|
|
737
|
+
fixture('src/repositories/listing-repository.ts', [
|
|
738
|
+
'export class ListingRepository {',
|
|
739
|
+
' private items = new Map<string, { id: string }>();',
|
|
740
|
+
' async findAll() { return [...this.items.values()]; }',
|
|
741
|
+
'}',
|
|
742
|
+
'export class ProfileStore {',
|
|
743
|
+
' private profiles: { id: string }[] = [];',
|
|
744
|
+
' add(p: { id: string }) { this.profiles.push(p); }',
|
|
745
|
+
'}',
|
|
746
|
+
].join('\n')),
|
|
747
|
+
// --- DYNAMODB scan detection ---
|
|
748
|
+
fixture('src/repositories/scan-heavy-repository.ts', [
|
|
749
|
+
'declare const ddb: { scan(args: unknown): Promise<unknown> };',
|
|
750
|
+
'export class AuditRepository {',
|
|
751
|
+
' async listAll() {',
|
|
752
|
+
' return ddb.scan({ TableName: "audit" });',
|
|
753
|
+
' }',
|
|
754
|
+
'}',
|
|
755
|
+
].join('\n')),
|
|
756
|
+
// --- PLATFORM CHECKS (Platform.OS pattern) ---
|
|
757
|
+
fixture('src/components/PlatformAware.tsx', [
|
|
758
|
+
'import { Platform } from "react-native";',
|
|
759
|
+
'export function PlatformAware() {',
|
|
760
|
+
' if (Platform.OS === "ios") return <></>;',
|
|
761
|
+
' if (Platform.OS === "android") return <></>;',
|
|
762
|
+
' return null;',
|
|
763
|
+
'}',
|
|
764
|
+
].join('\n')),
|
|
765
|
+
// --- TYPESCRIPT-FRONTEND tsconfig variations (jsx mode) ---
|
|
766
|
+
fixture('packages/web/tsconfig.json', JSON.stringify({
|
|
767
|
+
compilerOptions: {
|
|
768
|
+
target: 'es5',
|
|
769
|
+
module: 'commonjs',
|
|
770
|
+
jsx: 'react',
|
|
771
|
+
lib: ['dom', 'es2015'],
|
|
772
|
+
},
|
|
773
|
+
}, null, 2)),
|
|
774
|
+
// --- DATABASE INDEX COVERAGE — query patterns + find ops ---
|
|
775
|
+
fixture('src/repositories/user-repository.ts', [
|
|
776
|
+
'declare const db: {',
|
|
777
|
+
' query(sql: string): Promise<unknown>;',
|
|
778
|
+
' users: { find(where?: unknown): Promise<unknown>; findOne(where?: unknown): Promise<unknown> };',
|
|
779
|
+
'};',
|
|
780
|
+
'export async function searchUnbounded() {',
|
|
781
|
+
' return db.query("SELECT * FROM users");',
|
|
782
|
+
'}',
|
|
783
|
+
'export async function leadingWildcard() {',
|
|
784
|
+
' return db.query("SELECT id FROM users WHERE name LIKE \'%bob%\'");',
|
|
785
|
+
'}',
|
|
786
|
+
'export async function findWithoutWhere() {',
|
|
787
|
+
' return db.users.find();',
|
|
788
|
+
'}',
|
|
789
|
+
'export async function findOneNoWhere() {',
|
|
790
|
+
' return db.users.findOne();',
|
|
791
|
+
'}',
|
|
792
|
+
].join('\n')),
|
|
793
|
+
// --- DATABASE SCHEMA VALIDATION (Drizzle-side detection) ---
|
|
794
|
+
fixture('src/db/drizzle-edges.ts', [
|
|
795
|
+
'import { pgTable, text, integer, varchar } from "drizzle-orm/pg-core";',
|
|
796
|
+
'export const orders = pgTable("orders", {',
|
|
797
|
+
' customerId: integer("customer_id"),',
|
|
798
|
+
' orderNumber: integer("order_number"),',
|
|
799
|
+
' email: varchar("email", { length: 255 }),',
|
|
800
|
+
' notes: text("notes"),',
|
|
801
|
+
'});',
|
|
802
|
+
].join('\n')),
|
|
803
|
+
// --- PAYMENT / FINANCIAL ordering ---
|
|
804
|
+
fixture('src/payments/processor.ts', [
|
|
805
|
+
'declare const stripe: { charges: { create(args: { amount: number }): Promise<{ id: string }> } };',
|
|
806
|
+
'declare const paypal: { pay(args: { amount: number }): Promise<void> };',
|
|
807
|
+
'declare const repository: {',
|
|
808
|
+
' save(row: { id?: string; amount?: number; status?: string }): Promise<void>;',
|
|
809
|
+
' findOne(id: string): Promise<{ id: string }>;',
|
|
810
|
+
' update(id: string, patch: { status: string }): Promise<void>;',
|
|
811
|
+
'};',
|
|
812
|
+
'declare const processor: { refund(record: { id: string }): Promise<void> };',
|
|
813
|
+
'export class PaymentService {',
|
|
814
|
+
' async processPayment(amount: number) {',
|
|
815
|
+
' const result = await stripe.charges.create({ amount });',
|
|
816
|
+
' await repository.save({ id: result.id, amount });',
|
|
817
|
+
' }',
|
|
818
|
+
' async refund(id: string) {',
|
|
819
|
+
' const record = await repository.findOne(id);',
|
|
820
|
+
' await processor.refund(record);',
|
|
821
|
+
' await repository.update(id, { status: "REFUNDED" });',
|
|
822
|
+
' }',
|
|
823
|
+
'}',
|
|
824
|
+
].join('\n')),
|
|
825
|
+
];
|
|
826
|
+
await fileCache.prewarm(cwd, ['**/*']);
|
|
827
|
+
});
|
|
828
|
+
afterAll(() => {
|
|
829
|
+
fileCache.clear();
|
|
830
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
831
|
+
});
|
|
832
|
+
describe('checks-typescript — every check runs to completion', () => {
|
|
833
|
+
it.each(checks.map((c) => [c.config.slug, c]))('%s runs and returns a CheckResult', async (_slug, check) => {
|
|
834
|
+
const result = await runWithScope(testScope, () => check.run(cwd, { targetFiles: allFixturePaths }));
|
|
835
|
+
expect(result).toBeDefined();
|
|
836
|
+
expect(result.signals).toBeDefined();
|
|
837
|
+
expect(Array.isArray(result.signals)).toBe(true);
|
|
838
|
+
expect(typeof result.errors).toBe('number');
|
|
839
|
+
expect(typeof result.warnings).toBe('number');
|
|
840
|
+
expect(result.errors).toBeGreaterThanOrEqual(0);
|
|
841
|
+
expect(result.warnings).toBeGreaterThanOrEqual(0);
|
|
842
|
+
expect(result.info).toBeDefined();
|
|
843
|
+
expect(result.metadata).toBeDefined();
|
|
844
|
+
}, 20_000);
|
|
845
|
+
});
|
|
846
|
+
//# sourceMappingURL=all-checks-execute.test.js.map
|