@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,298 @@
|
|
|
1
|
+
// @fitness-ignore-file correlation-id-coverage -- Fitness check implementation, not an API handler
|
|
2
|
+
// @fitness-ignore-file fastify-schema-coverage -- schema definitions to be added in schema coverage sprint
|
|
3
|
+
// @fitness-ignore-file duplicate-utility-functions -- reviewed: route-analysis and validation-detection helpers are check-specific logic, not general-purpose utilities
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Fastify Route Validation Check
|
|
6
|
+
*
|
|
7
|
+
* Ensures all Fastify POST/PATCH/PUT route handlers validate request bodies
|
|
8
|
+
* using Zod schemas.
|
|
9
|
+
*/
|
|
10
|
+
import { defineCheck, isTestFile } from '@opensip-cli/fitness';
|
|
11
|
+
import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
|
|
12
|
+
import * as ts from 'typescript';
|
|
13
|
+
/**
|
|
14
|
+
* Quick filter regex to check if file might contain Fastify routes
|
|
15
|
+
*/
|
|
16
|
+
const QUICK_FILTER_PATTERNS = /fastify\.(post|patch|put)|\.post\(|\.patch\(|\.put\(/i;
|
|
17
|
+
/**
|
|
18
|
+
* Patterns that indicate Zod validation is present
|
|
19
|
+
*/
|
|
20
|
+
const ZOD_VALIDATION_PATTERNS = [
|
|
21
|
+
/\.parse\s*\(/,
|
|
22
|
+
/\.safeParse\s*\(/,
|
|
23
|
+
/Schema\.parse/,
|
|
24
|
+
/Schema\.safeParse/,
|
|
25
|
+
/z\.\w+\(\)/,
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Patterns that indicate other validation libraries are present
|
|
29
|
+
*/
|
|
30
|
+
const OTHER_VALIDATION_PATTERNS = [
|
|
31
|
+
/\.validate\s*\(/,
|
|
32
|
+
/validateBody\s*\(/,
|
|
33
|
+
/validateRequest\s*\(/,
|
|
34
|
+
/validateInput\s*\(/,
|
|
35
|
+
];
|
|
36
|
+
/**
|
|
37
|
+
* Extract route information from a call expression
|
|
38
|
+
* @param node - TypeScript CallExpression node to extract from
|
|
39
|
+
* @param sourceFile - TypeScript SourceFile for position information
|
|
40
|
+
* @returns RouteInfo object if this is a route call, null otherwise
|
|
41
|
+
*/
|
|
42
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity -- AST traversal with multiple node-type checks and nested property extraction
|
|
43
|
+
function extractRouteInfo(node, sourceFile) {
|
|
44
|
+
if (!ts.isPropertyAccessExpression(node.expression)) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const methodName = node.expression.name.text.toLowerCase();
|
|
48
|
+
if (!['post', 'patch', 'put'].includes(methodName)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const method = methodName.toUpperCase();
|
|
52
|
+
const args = node.arguments;
|
|
53
|
+
if (args.length < 2) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
let routePath = 'unknown';
|
|
57
|
+
const firstArg = args[0];
|
|
58
|
+
if (firstArg && ts.isStringLiteral(firstArg)) {
|
|
59
|
+
routePath = firstArg.text;
|
|
60
|
+
}
|
|
61
|
+
let handlerNode = null;
|
|
62
|
+
let hasSchemaOption = false;
|
|
63
|
+
const secondArg = args[1];
|
|
64
|
+
if (secondArg) {
|
|
65
|
+
if (ts.isArrowFunction(secondArg) || ts.isFunctionExpression(secondArg)) {
|
|
66
|
+
handlerNode = secondArg;
|
|
67
|
+
}
|
|
68
|
+
else if (ts.isObjectLiteralExpression(secondArg)) {
|
|
69
|
+
// Check for schema: { body: ... } in the options object (fastify-type-provider-zod pattern)
|
|
70
|
+
hasSchemaOption = secondArg.properties.some((prop) => {
|
|
71
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
72
|
+
if (!ts.isPropertyAssignment(prop))
|
|
73
|
+
return false;
|
|
74
|
+
const name = prop.name;
|
|
75
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
76
|
+
if (!ts.isIdentifier(name) || name.text !== 'schema')
|
|
77
|
+
return false;
|
|
78
|
+
// Check if the schema object has a 'body' property
|
|
79
|
+
if (ts.isObjectLiteralExpression(prop.initializer)) {
|
|
80
|
+
return prop.initializer.properties.some((schemaProp) => ts.isPropertyAssignment(schemaProp) &&
|
|
81
|
+
ts.isIdentifier(schemaProp.name) &&
|
|
82
|
+
schemaProp.name.text === 'body');
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
});
|
|
86
|
+
if (args[2]) {
|
|
87
|
+
const thirdArg = args[2];
|
|
88
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
89
|
+
if (ts.isArrowFunction(thirdArg) || ts.isFunctionExpression(thirdArg)) {
|
|
90
|
+
handlerNode = thirdArg;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Other argument types - handler not found
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
99
|
+
return {
|
|
100
|
+
method,
|
|
101
|
+
path: routePath,
|
|
102
|
+
line: line + 1,
|
|
103
|
+
handlerNode,
|
|
104
|
+
hasSchemaOption,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if text matches any validation pattern
|
|
109
|
+
* @param text - Text to check against patterns
|
|
110
|
+
* @param patterns - Array of patterns to test
|
|
111
|
+
* @returns true if any pattern matches
|
|
112
|
+
*/
|
|
113
|
+
function matchesAnyPattern(text, patterns) {
|
|
114
|
+
return patterns.some((pattern) => pattern.test(text));
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if handler has validation after request.body access
|
|
118
|
+
* @param handlerText - Handler text to analyze
|
|
119
|
+
* @returns true if validation found after body access
|
|
120
|
+
*/
|
|
121
|
+
function hasValidationAfterBodyAccess(handlerText) {
|
|
122
|
+
if (!handlerText.includes('request.body')) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
const bodyAccessIndex = handlerText.indexOf('request.body');
|
|
126
|
+
const afterBodyAccess = handlerText.slice(bodyAccessIndex);
|
|
127
|
+
const allPatterns = [...ZOD_VALIDATION_PATTERNS, ...OTHER_VALIDATION_PATTERNS];
|
|
128
|
+
if (matchesAnyPattern(afterBodyAccess, allPatterns)) {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
// Check for manual validation with if statement - simple non-backtracking check
|
|
132
|
+
return afterBodyAccess.includes('if') && afterBodyAccess.includes('!');
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if handler has 400 status response with validation message
|
|
136
|
+
* @param handlerText - Handler text to analyze
|
|
137
|
+
* @returns true if validation response pattern found
|
|
138
|
+
*/
|
|
139
|
+
function hasValidationResponse(handlerText) {
|
|
140
|
+
// Use indexOf for simple string checks to avoid regex complexity
|
|
141
|
+
const has400Code = handlerText.includes('reply.code') && handlerText.includes('400');
|
|
142
|
+
const hasValidationMessage = handlerText.includes('Missing') ||
|
|
143
|
+
handlerText.includes('Invalid') ||
|
|
144
|
+
handlerText.includes('required');
|
|
145
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
146
|
+
return has400Code && hasValidationMessage;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Check if a handler has validation
|
|
150
|
+
* @param handlerNode - TypeScript node of the handler or null
|
|
151
|
+
* @param sourceFile - TypeScript SourceFile for context
|
|
152
|
+
* @param fullContent - Full file content as string
|
|
153
|
+
* @returns true if validation is found, false otherwise
|
|
154
|
+
*/
|
|
155
|
+
function checkForValidation(handlerNode, sourceFile, fullContent) {
|
|
156
|
+
if (!handlerNode) {
|
|
157
|
+
return hasValidationInContent(fullContent);
|
|
158
|
+
}
|
|
159
|
+
const handlerText = handlerNode.getText(sourceFile);
|
|
160
|
+
if (matchesAnyPattern(handlerText, ZOD_VALIDATION_PATTERNS)) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
if (matchesAnyPattern(handlerText, OTHER_VALIDATION_PATTERNS)) {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
if (hasValidationAfterBodyAccess(handlerText)) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
return hasValidationResponse(handlerText);
|
|
170
|
+
}
|
|
171
|
+
function hasValidationInContent(content) {
|
|
172
|
+
if (content.includes('contracts') && content.includes('Schema')) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
if (content.includes('zod') && content.includes('.parse(')) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Create a violation for a route missing validation
|
|
182
|
+
* @param routeInfo - Route information
|
|
183
|
+
* @param filePath - Path to the file
|
|
184
|
+
* @returns CheckViolation object
|
|
185
|
+
*/
|
|
186
|
+
function createMissingValidationViolation(routeInfo, filePath) {
|
|
187
|
+
return {
|
|
188
|
+
filePath,
|
|
189
|
+
line: routeInfo.line,
|
|
190
|
+
column: 0,
|
|
191
|
+
message: `${routeInfo.method} ${routeInfo.path} - Route handler accepts request body without Zod schema validation`,
|
|
192
|
+
severity: 'error',
|
|
193
|
+
type: 'missing-validation',
|
|
194
|
+
suggestion: 'Add Zod schema validation for request body. Import schema from shared contract schemas and use schema.parse(request.body).',
|
|
195
|
+
match: `${routeInfo.method} ${routeInfo.path}`,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Check a single call expression for route validation issues
|
|
200
|
+
* @param options - The options for the check
|
|
201
|
+
* @returns Violation if found, null otherwise
|
|
202
|
+
*/
|
|
203
|
+
function checkCallExpressionForViolation(options) {
|
|
204
|
+
const { node, sourceFile, content, filePath } = options;
|
|
205
|
+
const routeInfo = extractRouteInfo(node, sourceFile);
|
|
206
|
+
if (!routeInfo) {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
// Routes using fastify-type-provider-zod pass schema in options — validation is automatic
|
|
210
|
+
if (routeInfo.hasSchemaOption) {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
const hasValidation = checkForValidation(routeInfo.handlerNode, sourceFile, content);
|
|
214
|
+
if (hasValidation) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
return createMissingValidationViolation(routeInfo, filePath);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Analyze a file for Fastify routes missing validation
|
|
221
|
+
* @param content - File content to analyze
|
|
222
|
+
* @param filePath - Path to the file being analyzed
|
|
223
|
+
* @returns Array of violations found in the file
|
|
224
|
+
*/
|
|
225
|
+
function analyzeFile(content, filePath) {
|
|
226
|
+
const violations = [];
|
|
227
|
+
try {
|
|
228
|
+
const sourceFile = getSharedSourceFile(filePath, content);
|
|
229
|
+
/* v8 ignore next -- defensive guard */
|
|
230
|
+
if (!sourceFile)
|
|
231
|
+
return [];
|
|
232
|
+
const visit = (node) => {
|
|
233
|
+
if (ts.isCallExpression(node)) {
|
|
234
|
+
const violation = checkCallExpressionForViolation({ node, sourceFile, content, filePath });
|
|
235
|
+
if (violation) {
|
|
236
|
+
violations.push(violation);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
ts.forEachChild(node, visit);
|
|
240
|
+
};
|
|
241
|
+
visit(sourceFile);
|
|
242
|
+
/* v8 ignore next 1 -- defensive catch: parse failures already handled */
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
// @swallow-ok Skip files that fail to parse
|
|
246
|
+
}
|
|
247
|
+
return violations;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Check if file is a route file
|
|
251
|
+
*/
|
|
252
|
+
function isRouteFile(file) {
|
|
253
|
+
return file.includes('/routes/') && !isTestFile(file) && !file.endsWith('.d.ts');
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Check: quality/fastify-route-validation
|
|
257
|
+
*
|
|
258
|
+
* Ensures all Fastify POST/PATCH/PUT route handlers validate request bodies
|
|
259
|
+
* with Zod schemas.
|
|
260
|
+
*/
|
|
261
|
+
export const fastifyRouteValidation = defineCheck({
|
|
262
|
+
id: '0de8bce9-e6fd-45c2-83ea-013bedfd3346',
|
|
263
|
+
slug: 'fastify-route-validation',
|
|
264
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
|
|
265
|
+
// 'raw', not 'strip-strings': the check extracts the route *path string literal*
|
|
266
|
+
// value (first arg to fastify.post/patch/put) to embed the real path in the
|
|
267
|
+
// violation message, and uses content includes() on import/usage strings for
|
|
268
|
+
// fallback validation detection when no inline handler. Stripping blanks those,
|
|
269
|
+
// producing useless messages (e.g. "POST - ...") and false violations.
|
|
270
|
+
// See auth-route-guard.ts for identical rationale on route paths.
|
|
271
|
+
contentFilter: 'raw',
|
|
272
|
+
confidence: 'high',
|
|
273
|
+
description: 'Ensure all Fastify POST/PATCH/PUT routes validate request bodies with Zod schemas',
|
|
274
|
+
longDescription: `**Purpose:** Ensures every Fastify POST, PATCH, and PUT route handler validates the request body using Zod or an equivalent validation library.
|
|
275
|
+
|
|
276
|
+
**Detects:**
|
|
277
|
+
- Route handlers registered via \`fastify.post(\`, \`.patch(\`, \`.put(\` (matched by \`/fastify\\.(post|patch|put)|\\.(post|patch|put)\\(/i\`) that lack validation
|
|
278
|
+
- Missing Zod calls (\`.parse(\`, \`.safeParse(\`, \`z.\\w+()\`) and alternative validators (\`.validate(\`, \`validateBody(\`, \`validateRequest(\`, \`validateInput(\`)
|
|
279
|
+
- Handlers that access \`request.body\` without subsequent validation or 400-status error responses
|
|
280
|
+
|
|
281
|
+
**Why it matters:** Unvalidated request bodies allow malformed or malicious payloads to reach business logic, causing runtime errors and security vulnerabilities.
|
|
282
|
+
|
|
283
|
+
**Scope:** General best practice. Analyzes each file individually using TypeScript AST parsing. Only processes files under \`/routes/\` directories.`,
|
|
284
|
+
tags: ['quality', 'security', 'code-quality', 'fastify', 'validation'],
|
|
285
|
+
fileTypes: ['ts'],
|
|
286
|
+
analyze(content, filePath) {
|
|
287
|
+
// Filter to only route files
|
|
288
|
+
if (!isRouteFile(filePath)) {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
// Quick filter: skip files that don't contain route patterns
|
|
292
|
+
if (!QUICK_FILTER_PATTERNS.test(content)) {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
return analyzeFile(content, filePath);
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
//# sourceMappingURL=fastify-route-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify-route-validation.js","sourceRoot":"","sources":["../../../../src/checks/quality/api/fastify-route-validation.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,2GAA2G;AAC3G,wKAAwK;AACxK;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAuB,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC;;GAEG;AACH,MAAM,qBAAqB,GAAG,uDAAuD,CAAC;AAEtF;;GAEG;AACH,MAAM,uBAAuB,GAAG;IAC9B,cAAc;IACd,kBAAkB;IAClB,eAAe;IACf,mBAAmB;IACnB,YAAY;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,yBAAyB,GAAG;IAChC,iBAAiB;IACjB,mBAAmB;IACnB,sBAAsB;IACtB,oBAAoB;CACrB,CAAC;AAUF;;;;;GAKG;AACH,uIAAuI;AACvI,SAAS,gBAAgB,CAAC,IAAuB,EAAE,UAAyB;IAC1E,IAAI,CAAC,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAC3D,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAA8B,CAAC;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;IAC5B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,SAAS,GAAG,SAAS,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,QAAQ,IAAI,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7C,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC5B,CAAC;IAED,IAAI,WAAW,GAAmB,IAAI,CAAC;IACvC,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,EAAE,CAAC;YACxE,WAAW,GAAG,SAAS,CAAC;QAC1B,CAAC;aAAM,IAAI,EAAE,CAAC,yBAAyB,CAAC,SAAS,CAAC,EAAE,CAAC;YACnD,4FAA4F;YAC5F,eAAe,GAAG,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;gBACnD,gDAAgD;gBAChD,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC;oBAAE,OAAO,KAAK,CAAC;gBACjD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;gBACvB,gDAAgD;gBAChD,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;oBAAE,OAAO,KAAK,CAAC;gBACnE,mDAAmD;gBACnD,IAAI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;oBACnD,OAAO,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CACrC,CAAC,UAAU,EAAE,EAAE,CACb,EAAE,CAAC,oBAAoB,CAAC,UAAU,CAAC;wBACnC,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;wBAChC,UAAU,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAClC,CAAC;gBACJ,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC,CAAC,CAAC;YACH,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBACzB,gDAAgD;gBAChD,IAAI,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACtE,WAAW,GAAG,QAAQ,CAAC;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,2CAA2C;QAC7C,CAAC;IACH,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE3E,OAAO;QACL,MAAM;QACN,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,IAAI,GAAG,CAAC;QACd,WAAW;QACX,eAAe;KAChB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,IAAY,EAAE,QAA2B;IAClE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,SAAS,4BAA4B,CAAC,WAAmB;IACvD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,eAAe,GAAG,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5D,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,CAAC,GAAG,uBAAuB,EAAE,GAAG,yBAAyB,CAAC,CAAC;IAE/E,IAAI,iBAAiB,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gFAAgF;IAChF,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACzE,CAAC;AAED;;;;GAIG;AACH,SAAS,qBAAqB,CAAC,WAAmB;IAChD,iEAAiE;IACjE,MAAM,UAAU,GAAG,WAAW,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrF,MAAM,oBAAoB,GACxB,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC/B,WAAW,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC/B,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAEnC,gDAAgD;IAChD,OAAO,UAAU,IAAI,oBAAoB,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CACzB,WAA2B,EAC3B,UAAyB,EACzB,WAAmB;IAEnB,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,sBAAsB,CAAC,WAAW,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEpD,IAAI,iBAAiB,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,CAAC;QAC5D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,iBAAiB,CAAC,WAAW,EAAE,yBAAyB,CAAC,EAAE,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,4BAA4B,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,qBAAqB,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAe;IAC7C,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,gCAAgC,CAAC,SAAoB,EAAE,QAAgB;IAC9E,OAAO;QACL,QAAQ;QACR,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,MAAM,EAAE,CAAC;QACT,OAAO,EAAE,GAAG,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,qEAAqE;QACnH,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,oBAAoB;QAC1B,UAAU,EACR,4HAA4H;QAC9H,KAAK,EAAE,GAAG,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE;KAC/C,CAAC;AACJ,CAAC;AAYD;;;;GAIG;AACH,SAAS,+BAA+B,CACtC,OAAmC;IAEnC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IACxD,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACrD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0FAA0F;IAC1F,IAAI,SAAS,CAAC,eAAe,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,kBAAkB,CAAC,SAAS,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACrF,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,gCAAgC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,OAAe,EAAE,QAAgB;IACpD,MAAM,UAAU,GAAqB,EAAE,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1D,uCAAuC;QACvC,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAE3B,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;YACpC,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,MAAM,SAAS,GAAG,+BAA+B,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC3F,IAAI,SAAS,EAAE,CAAC;oBACd,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC7B,CAAC;YACH,CAAC;YACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,KAAK,CAAC,UAAU,CAAC,CAAC;QAClB,yEAAyE;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;IAC9C,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACnF,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAAC;IAChD,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,0BAA0B;IAChC,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE;IACrE,iFAAiF;IACjF,4EAA4E;IAC5E,6EAA6E;IAC7E,gFAAgF;IAChF,8EAA8E;IAC9E,kEAAkE;IAClE,aAAa,EAAE,KAAK;IAEpB,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,mFAAmF;IAChG,eAAe,EAAE;;;;;;;;;qJASkI;IACnJ,IAAI,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,CAAC;IACtE,SAAS,EAAE,CAAC,IAAI,CAAC;IAEjB,OAAO,CAAC,OAAO,EAAE,QAAQ;QACvB,6BAA6B;QAC7B,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,6DAA6D;QAC7D,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACxC,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Fastify Schema Coverage Check
|
|
3
|
+
*
|
|
4
|
+
* Validates Fastify routes have proper schema coverage:
|
|
5
|
+
* - Routes without schema option (unless Zod validation is present)
|
|
6
|
+
* - Routes with body but missing body schema
|
|
7
|
+
* - Routes with response but missing response schema
|
|
8
|
+
* - Recognizes Zod .parse()/.safeParse() on request properties as equivalent coverage
|
|
9
|
+
*/
|
|
10
|
+
export declare const fastifySchemaCoverage: import("@opensip-cli/fitness").Check;
|
|
11
|
+
//# sourceMappingURL=fastify-schema-coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify-schema-coverage.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/api/fastify-schema-coverage.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAkUH,eAAO,MAAM,qBAAqB,sCAwChC,CAAC"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
// @fitness-ignore-file correlation-id-coverage -- Fitness check implementation, not an API handler
|
|
2
|
+
// @fitness-ignore-file fastify-schema-coverage -- Fitness check definition file; references Fastify schema patterns for detection, not actual routes
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Fastify Schema Coverage Check
|
|
5
|
+
*
|
|
6
|
+
* Validates Fastify routes have proper schema coverage:
|
|
7
|
+
* - Routes without schema option (unless Zod validation is present)
|
|
8
|
+
* - Routes with body but missing body schema
|
|
9
|
+
* - Routes with response but missing response schema
|
|
10
|
+
* - Recognizes Zod .parse()/.safeParse() on request properties as equivalent coverage
|
|
11
|
+
*/
|
|
12
|
+
import { defineCheck, isTestFile } from '@opensip-cli/fitness';
|
|
13
|
+
import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
|
|
14
|
+
import * as ts from 'typescript';
|
|
15
|
+
const BODY_METHODS = new Set(['POST', 'PUT', 'PATCH']);
|
|
16
|
+
function createSchemaViolation(options, type, message, suggestion) {
|
|
17
|
+
const { method, line, filePath, routePath } = options;
|
|
18
|
+
return {
|
|
19
|
+
filePath,
|
|
20
|
+
line,
|
|
21
|
+
column: 0,
|
|
22
|
+
message,
|
|
23
|
+
severity: 'warning',
|
|
24
|
+
type,
|
|
25
|
+
suggestion,
|
|
26
|
+
match: `${method} ${routePath}`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function hasProperty(routeText, propertyName) {
|
|
30
|
+
return routeText.includes(`${propertyName}:`) || routeText.includes(`${propertyName} :`);
|
|
31
|
+
}
|
|
32
|
+
function detectZodValidation(routeText) {
|
|
33
|
+
const bodyPattern = /\.(?:safe)?[Pp]arse\(\s{0,5}(?:request|req)\.body\s{0,5}\)/;
|
|
34
|
+
const queryPattern = /\.(?:safe)?[Pp]arse\(\s{0,5}(?:request|req)\.query\s{0,5}\)/;
|
|
35
|
+
const paramsPattern = /\.(?:safe)?[Pp]arse\(\s{0,5}(?:request|req)\.params\s{0,5}\)/;
|
|
36
|
+
const responsePattern = /[A-Z]\w{0,60}Schema\.parse\(/;
|
|
37
|
+
const generalPattern = /[A-Z]\w{0,60}Schema\.(?:safe)?[Pp]arse\(/;
|
|
38
|
+
const hasBody = bodyPattern.test(routeText);
|
|
39
|
+
const hasQuery = queryPattern.test(routeText);
|
|
40
|
+
const hasParams = paramsPattern.test(routeText);
|
|
41
|
+
const hasResponse = responsePattern.test(routeText);
|
|
42
|
+
const hasGeneral = generalPattern.test(routeText);
|
|
43
|
+
return {
|
|
44
|
+
hasAny: hasBody || hasQuery || hasParams || hasResponse || hasGeneral,
|
|
45
|
+
hasBody,
|
|
46
|
+
hasQuery,
|
|
47
|
+
hasParams,
|
|
48
|
+
hasResponse,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function checkMissingSchema(options, zodResult) {
|
|
52
|
+
if (hasProperty(options.routeText, 'schema')) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
if (zodResult.hasAny) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return createSchemaViolation(options, 'missing-schema', `Route ${options.method} ${options.routePath} has no schema option`, 'Add schema option with body, response, params, and querystring as needed for request validation and OpenAPI documentation. Alternatively, use Zod Schema.parse() or Schema.safeParse() on request properties in the handler.');
|
|
59
|
+
}
|
|
60
|
+
function handlerReadsBody(routeText) {
|
|
61
|
+
// The route's text passed in here covers the full call expression,
|
|
62
|
+
// including the handler body. If neither `request.body` nor `req.body`
|
|
63
|
+
// appears, the handler doesn't consume a request body — POST/PUT/PATCH
|
|
64
|
+
// routes triggered purely by URL params (state-transition actions like
|
|
65
|
+
// `/dispatch`, `/replay`, `/dismiss`) legitimately have no body schema
|
|
66
|
+
// because there is no body. Flagging those is a false positive.
|
|
67
|
+
return routeText.includes('request.body') || routeText.includes('req.body');
|
|
68
|
+
}
|
|
69
|
+
function checkMissingBodySchema(options, zodResult) {
|
|
70
|
+
if (!BODY_METHODS.has(options.method)) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
if (hasProperty(options.routeText, 'body')) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
if (zodResult.hasBody) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
if (!handlerReadsBody(options.routeText)) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return createSchemaViolation(options, 'missing-body-schema', `Route ${options.method} ${options.routePath} missing body schema`, 'Add body schema to validate request payload. Use Zod schema from shared contract schemas.');
|
|
83
|
+
}
|
|
84
|
+
function checkMissingResponseSchema(options, zodResult) {
|
|
85
|
+
if (hasProperty(options.routeText, 'response')) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
if (zodResult.hasResponse) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
return createSchemaViolation(options, 'missing-response-schema', `Route ${options.method} ${options.routePath} missing response schema`, 'Add response schema for proper API documentation and type safety. Define schemas for 200, 400, 500 status codes.');
|
|
92
|
+
}
|
|
93
|
+
function checkMissingParamsSchema(options, zodResult) {
|
|
94
|
+
const hasParams = options.routePath.includes(':');
|
|
95
|
+
if (!hasParams) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
if (hasProperty(options.routeText, 'params')) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
if (zodResult.hasParams) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return createSchemaViolation(options, 'missing-params-schema', `Route ${options.method} ${options.routePath} has path params but no params schema`, 'Add params schema to validate path parameters. Use Zod schema to validate param types.');
|
|
105
|
+
}
|
|
106
|
+
function checkMissingQuerySchema(options, zodResult) {
|
|
107
|
+
const accessesQuery = options.routeText.includes('request.query') || options.routeText.includes('req.query');
|
|
108
|
+
if (!accessesQuery) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
if (hasProperty(options.routeText, 'querystring')) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
if (zodResult.hasQuery) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
return createSchemaViolation(options, 'missing-querystring-schema', `Route ${options.method} ${options.routePath} accesses query but no querystring schema`, 'Add querystring schema to validate query parameters. Use Zod schema to validate and coerce query string values.');
|
|
118
|
+
}
|
|
119
|
+
function checkRouteSchema(options) {
|
|
120
|
+
const violations = [];
|
|
121
|
+
const zodResult = detectZodValidation(options.routeText);
|
|
122
|
+
const missingSchemaViolation = checkMissingSchema(options, zodResult);
|
|
123
|
+
if (missingSchemaViolation) {
|
|
124
|
+
violations.push(missingSchemaViolation);
|
|
125
|
+
return violations;
|
|
126
|
+
}
|
|
127
|
+
const bodyViolation = checkMissingBodySchema(options, zodResult);
|
|
128
|
+
if (bodyViolation) {
|
|
129
|
+
violations.push(bodyViolation);
|
|
130
|
+
}
|
|
131
|
+
const responseViolation = checkMissingResponseSchema(options, zodResult);
|
|
132
|
+
if (responseViolation) {
|
|
133
|
+
violations.push(responseViolation);
|
|
134
|
+
}
|
|
135
|
+
const paramsViolation = checkMissingParamsSchema(options, zodResult);
|
|
136
|
+
if (paramsViolation) {
|
|
137
|
+
violations.push(paramsViolation);
|
|
138
|
+
}
|
|
139
|
+
const queryViolation = checkMissingQuerySchema(options, zodResult);
|
|
140
|
+
if (queryViolation) {
|
|
141
|
+
violations.push(queryViolation);
|
|
142
|
+
}
|
|
143
|
+
return violations;
|
|
144
|
+
}
|
|
145
|
+
function matchObjectMethod(nodeText) {
|
|
146
|
+
const match = /method\s{0,5}:\s{0,5}['"]?(GET|POST|PUT|PATCH|DELETE)['"]?/i.exec(nodeText);
|
|
147
|
+
return match?.[1]?.toUpperCase() ?? null;
|
|
148
|
+
}
|
|
149
|
+
function matchObjectUrl(nodeText) {
|
|
150
|
+
const match = /url\s{0,5}:\s{0,5}['"`]([^'"`]{1,200})['"`]/.exec(nodeText);
|
|
151
|
+
return match?.[1] ?? null;
|
|
152
|
+
}
|
|
153
|
+
function matchShorthandMethod(callText) {
|
|
154
|
+
const match = /(?:fastify|app|server)\.(get|post|put|patch|delete)\s{0,5}\(/i.exec(callText);
|
|
155
|
+
return match?.[1]?.toUpperCase() ?? null;
|
|
156
|
+
}
|
|
157
|
+
function matchPathArgument(callText) {
|
|
158
|
+
const match = /\(\s{0,5}['"`]([^'"`]{1,200})['"`]/.exec(callText);
|
|
159
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
160
|
+
return match?.[1] ?? null;
|
|
161
|
+
}
|
|
162
|
+
function analyzeObjectLiteral(node, sourceFile, filePath) {
|
|
163
|
+
const nodeText = node.getText(sourceFile);
|
|
164
|
+
const method = matchObjectMethod(nodeText);
|
|
165
|
+
const routePath = matchObjectUrl(nodeText);
|
|
166
|
+
if (!method || !routePath) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
170
|
+
return checkRouteSchema({
|
|
171
|
+
routeText: nodeText,
|
|
172
|
+
method,
|
|
173
|
+
line: line + 1,
|
|
174
|
+
filePath,
|
|
175
|
+
routePath,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function analyzeCallExpression(node, sourceFile, filePath) {
|
|
179
|
+
const callText = node.getText(sourceFile);
|
|
180
|
+
const method = matchShorthandMethod(callText);
|
|
181
|
+
if (!method) {
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
185
|
+
/* v8 ignore next -- defensive nullish fallback */
|
|
186
|
+
const routePath = matchPathArgument(callText) ?? '';
|
|
187
|
+
return checkRouteSchema({
|
|
188
|
+
routeText: callText,
|
|
189
|
+
method,
|
|
190
|
+
line: line + 1,
|
|
191
|
+
filePath,
|
|
192
|
+
routePath,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
function analyzeFile(content, filePath) {
|
|
196
|
+
const violations = [];
|
|
197
|
+
try {
|
|
198
|
+
const sourceFile = getSharedSourceFile(filePath, content);
|
|
199
|
+
/* v8 ignore next -- defensive guard */
|
|
200
|
+
if (!sourceFile)
|
|
201
|
+
return [];
|
|
202
|
+
const visit = (node) => {
|
|
203
|
+
if (ts.isObjectLiteralExpression(node)) {
|
|
204
|
+
violations.push(...analyzeObjectLiteral(node, sourceFile, filePath));
|
|
205
|
+
}
|
|
206
|
+
else if (ts.isCallExpression(node)) {
|
|
207
|
+
violations.push(...analyzeCallExpression(node, sourceFile, filePath));
|
|
208
|
+
}
|
|
209
|
+
ts.forEachChild(node, visit);
|
|
210
|
+
};
|
|
211
|
+
visit(sourceFile);
|
|
212
|
+
/* v8 ignore next 1 -- defensive catch: parse failures already handled */
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// @swallow-ok Skip files that fail to parse
|
|
216
|
+
}
|
|
217
|
+
return violations;
|
|
218
|
+
}
|
|
219
|
+
function isRouteFile(file) {
|
|
220
|
+
const hasRouteKeyword = file.includes('route') || file.includes('controller') || file.includes('endpoint');
|
|
221
|
+
const isTypeFile = file.endsWith('.d.ts');
|
|
222
|
+
return hasRouteKeyword && !isTestFile(file) && !isTypeFile;
|
|
223
|
+
}
|
|
224
|
+
export const fastifySchemaCoverage = defineCheck({
|
|
225
|
+
id: '16f14276-7a70-43bb-8097-181dd277371c',
|
|
226
|
+
slug: 'fastify-schema-coverage',
|
|
227
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
|
|
228
|
+
contentFilter: 'strip-strings',
|
|
229
|
+
confidence: 'high',
|
|
230
|
+
description: 'Validate that Fastify routes have proper request/response schema validation',
|
|
231
|
+
longDescription: `**Purpose:** Validates that Fastify route definitions include complete schema options for request and response validation.
|
|
232
|
+
|
|
233
|
+
**Detects:**
|
|
234
|
+
- Routes (both object-literal \`{ method: 'POST', url: '...' }\` and shorthand \`fastify.post(...)\` styles) missing the \`schema\` option entirely
|
|
235
|
+
- POST/PUT/PATCH routes missing a \`body:\` schema property when the handler reads \`request.body\` (state-transition routes triggered by URL params with no body access are not flagged)
|
|
236
|
+
- Routes missing a \`response:\` schema property
|
|
237
|
+
- Routes with path parameters (containing \`:\`) missing a \`params:\` schema property
|
|
238
|
+
- Routes accessing \`request.query\`/\`req.query\` missing a \`querystring:\` schema property
|
|
239
|
+
|
|
240
|
+
**Zod validation support:** Routes using Zod-based validation in the handler body are recognized as having equivalent schema coverage:
|
|
241
|
+
- \`Schema.safeParse(request.body)\` / \`Schema.parse(request.body)\` — counts as body validation
|
|
242
|
+
- \`Schema.safeParse(request.query)\` / \`Schema.parse(request.query)\` — counts as querystring validation
|
|
243
|
+
- \`Schema.safeParse(request.params)\` / \`Schema.parse(request.params)\` — counts as params validation
|
|
244
|
+
- \`Schema.parse(result)\` (any \`*Schema.parse()\` call) — counts as response validation
|
|
245
|
+
|
|
246
|
+
**Why it matters:** Missing schema properties disable Fastify's built-in request validation and omit routes from OpenAPI documentation, leading to undocumented and unvalidated endpoints.
|
|
247
|
+
|
|
248
|
+
**Scope:** General best practice. Analyzes each file individually using TypeScript AST parsing. Only processes route/controller/endpoint files.`,
|
|
249
|
+
tags: ['quality', 'code-quality', 'best-practices', 'security', 'fastify', 'schema'],
|
|
250
|
+
fileTypes: ['ts'],
|
|
251
|
+
analyze(content, filePath) {
|
|
252
|
+
if (!isRouteFile(filePath)) {
|
|
253
|
+
return [];
|
|
254
|
+
}
|
|
255
|
+
if (!content.includes('fastify') && !content.includes('route')) {
|
|
256
|
+
return [];
|
|
257
|
+
}
|
|
258
|
+
return analyzeFile(content, filePath);
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
//# sourceMappingURL=fastify-schema-coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify-schema-coverage.js","sourceRoot":"","sources":["../../../../src/checks/quality/api/fastify-schema-coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/api/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/checks/quality/api/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Duplicate Utility Functions check
|
|
3
|
+
*
|
|
4
|
+
* Detects duplicate utility functions that should be consolidated.
|
|
5
|
+
* Flags TWO types of issues:
|
|
6
|
+
* 1. Identical implementations - true duplicates that must be deduplicated
|
|
7
|
+
* 2. Same-named functions with different implementations - consolidation opportunities
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Recipe-config shape for the duplicate-utility-functions check. Augments
|
|
11
|
+
* the built-in {@link DOMAIN_SPECIFIC_FUNCTIONS} list with project-specific
|
|
12
|
+
* names that are deliberately distinct implementations sharing a name.
|
|
13
|
+
*
|
|
14
|
+
* Project-specific functions like `getCurrentCorrelationId`, `formatDuration`,
|
|
15
|
+
* `getRemoteUrl`, `sanitizeForPrompt`, etc. belong in a recipe's
|
|
16
|
+
* `checks.config['duplicate-utility-functions'].additionalDomainSpecificFunctions`
|
|
17
|
+
* block, NOT in built-in defaults.
|
|
18
|
+
*/
|
|
19
|
+
export interface DuplicateUtilityFunctionsConfig extends Record<string, unknown> {
|
|
20
|
+
/** Function names that should be skipped (treated as domain-specific by design). */
|
|
21
|
+
additionalDomainSpecificFunctions?: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check: quality/duplicate-utility-functions
|
|
25
|
+
*
|
|
26
|
+
* Detects utility functions that should be consolidated across the codebase.
|
|
27
|
+
* Reports two types of issues:
|
|
28
|
+
* - IDENTICAL: Same name, same implementation (true duplicates)
|
|
29
|
+
* - SIMILAR: Same name, different implementation (consolidation opportunities)
|
|
30
|
+
*/
|
|
31
|
+
export declare const duplicateUtilityFunctions: import("@opensip-cli/fitness").Check;
|
|
32
|
+
//# sourceMappingURL=duplicate-utility-functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-utility-functions.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/code-structure/duplicate-utility-functions.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAcH;;;;;;;;;GASG;AACH,MAAM,WAAW,+BAAgC,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC9E,oFAAoF;IACpF,iCAAiC,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACvD;AAmdD;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,sCAkCpC,CAAC"}
|