@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,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Result Pattern Consistency Check
|
|
3
|
+
*
|
|
4
|
+
* Enforces consistent use of Result<T,E> vs throw based on error type:
|
|
5
|
+
* - Result<T,E> for expected failures (validation, not found, business rules)
|
|
6
|
+
* - throw for unexpected failures (system errors, security issues)
|
|
7
|
+
*
|
|
8
|
+
* @see CLAUDE.md Error Handling Policy
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Check: quality/result-pattern-consistency
|
|
12
|
+
*
|
|
13
|
+
* Ensures consistent use of Result<T,E> for expected failures and throw for unexpected failures.
|
|
14
|
+
*/
|
|
15
|
+
export declare const resultPatternConsistency: import("@opensip-cli/fitness").Check;
|
|
16
|
+
//# sourceMappingURL=result-pattern-consistency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-pattern-consistency.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/result-pattern-consistency.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AA8SH;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,sCAsEnC,CAAC"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
// @fitness-ignore-file canonical-result-usage -- References Result pattern in JSDoc for check documentation, not actual Result usage
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Result Pattern Consistency Check
|
|
4
|
+
*
|
|
5
|
+
* Enforces consistent use of Result<T,E> vs throw based on error type:
|
|
6
|
+
* - Result<T,E> for expected failures (validation, not found, business rules)
|
|
7
|
+
* - throw for unexpected failures (system errors, security issues)
|
|
8
|
+
*
|
|
9
|
+
* @see CLAUDE.md Error Handling Policy
|
|
10
|
+
*/
|
|
11
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
12
|
+
import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
|
|
13
|
+
import * as ts from 'typescript';
|
|
14
|
+
/**
|
|
15
|
+
* Expected error types that should use Result pattern
|
|
16
|
+
*/
|
|
17
|
+
const EXPECTED_ERROR_TYPES = [
|
|
18
|
+
'ValidationError',
|
|
19
|
+
'NotFoundError',
|
|
20
|
+
'BusinessRuleError',
|
|
21
|
+
'ConflictError',
|
|
22
|
+
'InvalidInputError',
|
|
23
|
+
'DuplicateError',
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Function name patterns where throwing is legitimate (validation/guard helpers
|
|
27
|
+
* + infrastructure-boundary factories, resolvers, loaders, parsers, mappers).
|
|
28
|
+
*
|
|
29
|
+
* Factory/resolver/loader helpers (`defineX`, `resolveX`, `loadX`, `parseX`,
|
|
30
|
+
* `mapXTo…`) are startup-time configuration entry points: a malformed input
|
|
31
|
+
* is a programmer error caught once at boot rather than a recoverable
|
|
32
|
+
* business-logic failure, so they throw eagerly. Forcing them to return
|
|
33
|
+
* `Result` would push a startup-error branch into every call site — a
|
|
34
|
+
* usability regression, not consistency.
|
|
35
|
+
*/
|
|
36
|
+
const LEGITIMATE_THROW_FUNCTION_PATTERNS = [
|
|
37
|
+
/^validate[A-Z]/,
|
|
38
|
+
/^assert[A-Z]/,
|
|
39
|
+
/^ensure[A-Z]/,
|
|
40
|
+
/^require[A-Z]/,
|
|
41
|
+
/^check[A-Z]/,
|
|
42
|
+
/^verify[A-Z]/,
|
|
43
|
+
/^must[A-Z]/,
|
|
44
|
+
/^define[A-Z]/,
|
|
45
|
+
/^resolve[A-Z]/,
|
|
46
|
+
/^load[A-Z]/,
|
|
47
|
+
/^parse[A-Z]/,
|
|
48
|
+
/^map[A-Z]\w*To[A-Z]/,
|
|
49
|
+
/Guard$/,
|
|
50
|
+
/Validator$/,
|
|
51
|
+
/Assertion$/,
|
|
52
|
+
];
|
|
53
|
+
/**
|
|
54
|
+
* Paths where throwing is expected (infrastructure boundaries per DEC-015).
|
|
55
|
+
* These are entry points that bridge external systems, CLI, or pipeline layers
|
|
56
|
+
* where callers can't meaningfully recover — throw is the correct pattern.
|
|
57
|
+
*/
|
|
58
|
+
const THROW_ALLOWED_PATHS = [
|
|
59
|
+
/\/routes\//,
|
|
60
|
+
/\/handlers\//,
|
|
61
|
+
/\/controllers\//,
|
|
62
|
+
/\/middleware\//,
|
|
63
|
+
/\/plugins?\//,
|
|
64
|
+
/\/bootstrap/,
|
|
65
|
+
/\/providers\//,
|
|
66
|
+
// Internal services
|
|
67
|
+
/\/services\/internal\//,
|
|
68
|
+
// Validation utilities
|
|
69
|
+
/\/utils\/validation/,
|
|
70
|
+
// LLM and external API adapters (bridge external services)
|
|
71
|
+
/\/llm\//,
|
|
72
|
+
/\/adapters\//,
|
|
73
|
+
/\/embeddings\//,
|
|
74
|
+
// CLI command entry points (bridge CLI to domain)
|
|
75
|
+
/\/commands\//,
|
|
76
|
+
// Pipeline governance and orchestration boundaries
|
|
77
|
+
/\/governor\//,
|
|
78
|
+
/\/prompt\//,
|
|
79
|
+
// ID parsing/validation (infrastructure boundary for data integrity)
|
|
80
|
+
/\/ids\//,
|
|
81
|
+
// Infrastructure boundary packages and patterns (DEC-015: throw is correct)
|
|
82
|
+
/packages\/infrastructure\//,
|
|
83
|
+
/\/stores\//,
|
|
84
|
+
/\/registry\//,
|
|
85
|
+
];
|
|
86
|
+
/**
|
|
87
|
+
* File name patterns where throwing is legitimate (infrastructure boundary classes)
|
|
88
|
+
*/
|
|
89
|
+
const INFRASTRUCTURE_FILE_PATTERNS = [/registry/i, /-registry/i, /store/i, /-store/i, /adapter/i];
|
|
90
|
+
/**
|
|
91
|
+
* Check if a file path is in a throw-allowed context
|
|
92
|
+
*/
|
|
93
|
+
function isThrowAllowedPath(filePath) {
|
|
94
|
+
if (THROW_ALLOWED_PATHS.some((pattern) => pattern.test(filePath))) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
// Check file name against infrastructure patterns (registries, stores, adapters)
|
|
98
|
+
/* v8 ignore next -- defensive nullish fallback */
|
|
99
|
+
const fileName = filePath.split('/').pop() ?? '';
|
|
100
|
+
return INFRASTRUCTURE_FILE_PATTERNS.some((pattern) => pattern.test(fileName));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if a function name indicates it's a validation/guard helper
|
|
104
|
+
*/
|
|
105
|
+
function isValidationHelper(funcName) {
|
|
106
|
+
return LEGITIMATE_THROW_FUNCTION_PATTERNS.some((pattern) => pattern.test(funcName));
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if a throw statement is inside a catch block (re-throw pattern)
|
|
110
|
+
*/
|
|
111
|
+
function isInCatchBlock(node) {
|
|
112
|
+
let current = node.parent;
|
|
113
|
+
while (current) {
|
|
114
|
+
if (ts.isCatchClause(current)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
current = current.parent;
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get the containing function name for a node
|
|
123
|
+
*/
|
|
124
|
+
function getContainingFunctionName(node, sourceFile) {
|
|
125
|
+
let current = node.parent;
|
|
126
|
+
while (current) {
|
|
127
|
+
if (ts.isFunctionDeclaration(current) && current.name) {
|
|
128
|
+
return current.name.getText(sourceFile);
|
|
129
|
+
}
|
|
130
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
131
|
+
if (ts.isMethodDeclaration(current) && current.name) {
|
|
132
|
+
return current.name.getText(sourceFile);
|
|
133
|
+
}
|
|
134
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
135
|
+
if (ts.isArrowFunction(current) || ts.isFunctionExpression(current)) {
|
|
136
|
+
const parent = current.parent;
|
|
137
|
+
if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {
|
|
138
|
+
return parent.name.getText(sourceFile);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
current = current.parent;
|
|
142
|
+
}
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if a node is inside a constructor (constructors should throw, not return Result)
|
|
147
|
+
*/
|
|
148
|
+
function isInConstructor(node) {
|
|
149
|
+
let current = node.parent;
|
|
150
|
+
while (current) {
|
|
151
|
+
if (ts.isConstructorDeclaration(current)) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
current = current.parent;
|
|
155
|
+
}
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check if a node is inside a private method (private methods may throw for internal consistency)
|
|
160
|
+
*/
|
|
161
|
+
function isInPrivateMethod(node) {
|
|
162
|
+
let current = node.parent;
|
|
163
|
+
while (current) {
|
|
164
|
+
if (ts.isMethodDeclaration(current)) {
|
|
165
|
+
const modifiers = ts.getModifiers(current);
|
|
166
|
+
if (modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword)) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
current = current.parent;
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Checks a throw statement for expected error types that should use Result pattern
|
|
176
|
+
*/
|
|
177
|
+
function checkThrowStatement(options) {
|
|
178
|
+
const { node, sourceFile, filePath } = options;
|
|
179
|
+
// Skip files in throw-allowed paths (routes, handlers, plugins)
|
|
180
|
+
if (isThrowAllowedPath(filePath)) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
// Skip re-throws in catch blocks (error wrapping is legitimate)
|
|
184
|
+
if (isInCatchBlock(node)) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
// Skip constructors (constructor validation should throw, not return Result)
|
|
188
|
+
if (isInConstructor(node)) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
// Skip private methods (internal consistency checks may throw)
|
|
192
|
+
if (isInPrivateMethod(node)) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
// Skip validation/guard helper functions
|
|
196
|
+
const funcName = getContainingFunctionName(node, sourceFile);
|
|
197
|
+
if (funcName && isValidationHelper(funcName)) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
const throwText = node.expression.getText(sourceFile);
|
|
201
|
+
// Find the first matching expected error type
|
|
202
|
+
const matchedErrorType = EXPECTED_ERROR_TYPES.find((errorType) => throwText.includes(errorType));
|
|
203
|
+
if (!matchedErrorType) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
207
|
+
const lineNum = line + 1;
|
|
208
|
+
const matchText = node.getText(sourceFile);
|
|
209
|
+
return {
|
|
210
|
+
line: lineNum,
|
|
211
|
+
column: character + 1,
|
|
212
|
+
message: `Throwing ${matchedErrorType} instead of returning Result`,
|
|
213
|
+
severity: 'warning',
|
|
214
|
+
suggestion: `Replace 'throw new ${matchedErrorType}(...)' with 'return err(new ${matchedErrorType}(...))' and update the function return type to Result<T, ${matchedErrorType}>`,
|
|
215
|
+
match: matchText,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Checks function body for thrown expected errors when return type is Result
|
|
220
|
+
*/
|
|
221
|
+
function checkResultFunctionBody(options) {
|
|
222
|
+
const { bodyText, node, sourceFile, filePath } = options;
|
|
223
|
+
// Skip files in throw-allowed paths
|
|
224
|
+
if (isThrowAllowedPath(filePath)) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
// Skip private methods (internal consistency checks may throw)
|
|
228
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
229
|
+
if (ts.isMethodDeclaration(node)) {
|
|
230
|
+
const modifiers = ts.getModifiers(node);
|
|
231
|
+
if (modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword)) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Get function name
|
|
236
|
+
const funcName = ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node)
|
|
237
|
+
? node.name?.getText(sourceFile)
|
|
238
|
+
: undefined;
|
|
239
|
+
// Skip validation helper functions
|
|
240
|
+
if (funcName && isValidationHelper(funcName)) {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
for (const errorType of EXPECTED_ERROR_TYPES) {
|
|
244
|
+
if (!bodyText.includes(`throw new ${errorType}`))
|
|
245
|
+
continue;
|
|
246
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
247
|
+
const lineNum = line + 1;
|
|
248
|
+
const matchText = `throw new ${errorType}`;
|
|
249
|
+
return {
|
|
250
|
+
line: lineNum,
|
|
251
|
+
column: character + 1,
|
|
252
|
+
message: `Function returns Result but throws ${errorType}`,
|
|
253
|
+
severity: 'error',
|
|
254
|
+
suggestion: `This function declares Result<T,E> return type but throws ${errorType}. Replace 'throw new ${errorType}(...)' with 'return err(new ${errorType}(...))' for consistency`,
|
|
255
|
+
match: matchText,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Check: quality/result-pattern-consistency
|
|
262
|
+
*
|
|
263
|
+
* Ensures consistent use of Result<T,E> for expected failures and throw for unexpected failures.
|
|
264
|
+
*/
|
|
265
|
+
export const resultPatternConsistency = defineCheck({
|
|
266
|
+
id: '137e8d24-8b06-4d1f-b5f0-e7542d932679',
|
|
267
|
+
slug: 'result-pattern-consistency',
|
|
268
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
|
|
269
|
+
contentFilter: 'strip-strings',
|
|
270
|
+
confidence: 'high',
|
|
271
|
+
description: 'Ensures consistent use of Result<T,E> for expected failures and throw for unexpected failures',
|
|
272
|
+
longDescription: `**Purpose:** Enforces that expected failures (validation, not-found, business rules) use \`Result<T,E>\` while \`throw\` is reserved for unexpected failures (DEC-015).
|
|
273
|
+
|
|
274
|
+
**Detects:** Analyzes each file individually using TypeScript AST. Checks for:
|
|
275
|
+
- \`throw new\` statements using expected error types (\`ValidationError\`, \`NotFoundError\`, \`BusinessRuleError\`, \`ConflictError\`, \`InvalidInputError\`, \`DuplicateError\`) outside catch blocks and non-validation helper functions
|
|
276
|
+
- Functions with \`Result\` return type that also contain \`throw new <ExpectedError>\` statements
|
|
277
|
+
|
|
278
|
+
**Why it matters:** Mixing throw and Result for the same error category forces callers to handle both patterns, creating inconsistent and fragile error handling.
|
|
279
|
+
|
|
280
|
+
**Scope:** Codebase-specific convention (see CLAUDE.md Error Handling Policy)`,
|
|
281
|
+
tags: ['error-handling', 'quality', 'best-practices'],
|
|
282
|
+
fileTypes: ['ts'],
|
|
283
|
+
analyze(content, filePath) {
|
|
284
|
+
// Quick filter: skip files without error patterns
|
|
285
|
+
const hasErrorPatterns = content.includes('throw') || content.includes('Result');
|
|
286
|
+
if (!hasErrorPatterns) {
|
|
287
|
+
return [];
|
|
288
|
+
}
|
|
289
|
+
const violations = [];
|
|
290
|
+
const sourceFile = getSharedSourceFile(filePath, content);
|
|
291
|
+
/* v8 ignore next -- defensive guard */
|
|
292
|
+
if (!sourceFile)
|
|
293
|
+
return [];
|
|
294
|
+
const visit = (node) => {
|
|
295
|
+
ts.forEachChild(node, visit);
|
|
296
|
+
// Check throw statements for expected error types
|
|
297
|
+
if (ts.isThrowStatement(node)) {
|
|
298
|
+
const violation = checkThrowStatement({ node, sourceFile, filePath });
|
|
299
|
+
if (violation) {
|
|
300
|
+
violations.push(violation);
|
|
301
|
+
}
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
// Check functions that return Result but also throw expected errors
|
|
305
|
+
if (!ts.isFunctionDeclaration(node) && !ts.isMethodDeclaration(node))
|
|
306
|
+
return;
|
|
307
|
+
const returnType = node.type?.getText(sourceFile);
|
|
308
|
+
// Require the canonical generic form `Result<…>` (also matches
|
|
309
|
+
// `Promise<Result<…>>`). A bare substring match for "Result"
|
|
310
|
+
// misclassifies domain types like `GateCompareResult`, `AnalyzeResult`,
|
|
311
|
+
// or `ParseResult` as Result-returning and produces false positives
|
|
312
|
+
// wherever such a function throws on a legitimate infrastructure
|
|
313
|
+
// boundary. Word-boundary + `<` preserves the intent without matching
|
|
314
|
+
// unrelated trailing-token names.
|
|
315
|
+
if (!returnType || !/\bResult\s*</.test(returnType))
|
|
316
|
+
return;
|
|
317
|
+
/* v8 ignore next -- defensive nullish fallback */
|
|
318
|
+
const bodyText = node.body?.getText(sourceFile) ?? '';
|
|
319
|
+
const violation = checkResultFunctionBody({ bodyText, node, sourceFile, filePath });
|
|
320
|
+
if (violation) {
|
|
321
|
+
violations.push(violation);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
visit(sourceFile);
|
|
325
|
+
return violations;
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
//# sourceMappingURL=result-pattern-consistency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-pattern-consistency.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/result-pattern-consistency.ts"],"names":[],"mappings":"AAAA,qIAAqI;AACrI;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAuB,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC;;GAEG;AACH,MAAM,oBAAoB,GAAG;IAC3B,iBAAiB;IACjB,eAAe;IACf,mBAAmB;IACnB,eAAe;IACf,mBAAmB;IACnB,gBAAgB;CACjB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,kCAAkC,GAAG;IACzC,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,eAAe;IACf,aAAa;IACb,cAAc;IACd,YAAY;IACZ,cAAc;IACd,eAAe;IACf,YAAY;IACZ,aAAa;IACb,qBAAqB;IACrB,QAAQ;IACR,YAAY;IACZ,YAAY;CACb,CAAC;AAEF;;;;GAIG;AACH,MAAM,mBAAmB,GAAG;IAC1B,YAAY;IACZ,cAAc;IACd,iBAAiB;IACjB,gBAAgB;IAChB,cAAc;IACd,aAAa;IACb,eAAe;IACf,oBAAoB;IACpB,wBAAwB;IACxB,uBAAuB;IACvB,qBAAqB;IACrB,2DAA2D;IAC3D,SAAS;IACT,cAAc;IACd,gBAAgB;IAChB,kDAAkD;IAClD,cAAc;IACd,mDAAmD;IACnD,cAAc;IACd,YAAY;IACZ,qEAAqE;IACrE,SAAS;IACT,4EAA4E;IAC5E,4BAA4B;IAC5B,YAAY;IACZ,cAAc;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,4BAA4B,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAElG;;GAEG;AACH,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAClE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iFAAiF;IACjF,kDAAkD;IAClD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IACjD,OAAO,4BAA4B,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,OAAO,kCAAkC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtF,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,IAAa;IACnC,IAAI,OAAO,GAAwB,IAAI,CAAC,MAAM,CAAC;IAE/C,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,yBAAyB,CAAC,IAAa,EAAE,UAAyB;IACzE,IAAI,OAAO,GAAwB,IAAI,CAAC,MAAM,CAAC;IAE/C,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACtD,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;QAED,gDAAgD;QAChD,IAAI,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACpD,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;QACD,gDAAgD;QAChD,IAAI,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;YACpE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9B,IAAI,EAAE,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrE,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,IAAa;IACpC,IAAI,OAAO,GAAwB,IAAI,CAAC,MAAM,CAAC;IAE/C,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,EAAE,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,IAAa;IACtC,IAAI,OAAO,GAAwB,IAAI,CAAC,MAAM,CAAC;IAE/C,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;YACpC,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBACpE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AASD;;GAEG;AACH,SAAS,mBAAmB,CAAC,OAAmC;IAC9D,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAE/C,gEAAgE;IAChE,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gEAAgE;IAChE,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAC7E,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+DAA+D;IAC/D,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,yCAAyC;IACzC,MAAM,QAAQ,GAAG,yBAAyB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7D,IAAI,QAAQ,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEtD,8CAA8C;IAC9C,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IACjG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACtF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC;IACzB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAE3C,OAAO;QACL,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,SAAS,GAAG,CAAC;QACrB,OAAO,EAAE,YAAY,gBAAgB,8BAA8B;QACnE,QAAQ,EAAE,SAAS;QACnB,UAAU,EAAE,sBAAsB,gBAAgB,+BAA+B,gBAAgB,4DAA4D,gBAAgB,GAAG;QAChL,KAAK,EAAE,SAAS;KACjB,CAAC;AACJ,CAAC;AAUD;;GAEG;AACH,SAAS,uBAAuB,CAAC,OAAuC;IACtE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAEzD,oCAAoC;IACpC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+DAA+D;IAC/D,gDAAgD;IAChD,IAAI,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YACpE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,MAAM,QAAQ,GACZ,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC;QAC5D,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC;QAChC,CAAC,CAAC,SAAS,CAAC;IAEhB,mCAAmC;IACnC,IAAI,QAAQ,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,MAAM,SAAS,IAAI,oBAAoB,EAAE,CAAC;QAC7C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,SAAS,EAAE,CAAC;YAAE,SAAS;QAE3D,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC;QACzB,MAAM,SAAS,GAAG,aAAa,SAAS,EAAE,CAAC;QAE3C,OAAO;YACL,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,SAAS,GAAG,CAAC;YACrB,OAAO,EAAE,sCAAsC,SAAS,EAAE;YAC1D,QAAQ,EAAE,OAAO;YACjB,UAAU,EAAE,6DAA6D,SAAS,wBAAwB,SAAS,+BAA+B,SAAS,yBAAyB;YACpL,KAAK,EAAE,SAAS;SACjB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,WAAW,CAAC;IAClD,EAAE,EAAE,sCAAsC;IAC1C,IAAI,EAAE,4BAA4B;IAClC,KAAK,EAAE,EAAE,SAAS,EAAE,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE;IACrE,aAAa,EAAE,eAAe;IAE9B,UAAU,EAAE,MAAM;IAClB,WAAW,EACT,+FAA+F;IACjG,eAAe,EAAE;;;;;;;;8EAQ2D;IAC5E,IAAI,EAAE,CAAC,gBAAgB,EAAE,SAAS,EAAE,gBAAgB,CAAC;IACrD,SAAS,EAAE,CAAC,IAAI,CAAC;IAEjB,OAAO,CAAC,OAAO,EAAE,QAAQ;QACvB,kDAAkD;QAClD,MAAM,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACjF,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,UAAU,GAAqB,EAAE,CAAC;QAExC,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,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAE7B,kDAAkD;YAClD,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,MAAM,SAAS,GAAG,mBAAmB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACtE,IAAI,SAAS,EAAE,CAAC;oBACd,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC7B,CAAC;gBACD,OAAO;YACT,CAAC;YAED,oEAAoE;YACpE,IAAI,CAAC,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC;gBAAE,OAAO;YAE7E,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;YAClD,+DAA+D;YAC/D,6DAA6D;YAC7D,wEAAwE;YACxE,oEAAoE;YACpE,iEAAiE;YACjE,sEAAsE;YACtE,kCAAkC;YAClC,IAAI,CAAC,UAAU,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC;gBAAE,OAAO;YAE5D,kDAAkD;YAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;YACtD,MAAM,SAAS,GAAG,uBAAuB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;YACpF,IAAI,SAAS,EAAE,CAAC;gBACd,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC;QAEF,KAAK,CAAC,UAAU,CAAC,CAAC;QAClB,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Silent Early Returns Check
|
|
3
|
+
*
|
|
4
|
+
* Detects validation/guard paths that return silently without logging.
|
|
5
|
+
* These patterns make debugging difficult by hiding why code paths weren't executed.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check: quality/silent-early-returns
|
|
9
|
+
*
|
|
10
|
+
* Detects single-line early returns (if (!x) return null/false) without logging.
|
|
11
|
+
* These patterns make it impossible to know why a code path wasn't executed.
|
|
12
|
+
*
|
|
13
|
+
* Exceptions:
|
|
14
|
+
* - Type guards (functions that return `x is T`)
|
|
15
|
+
* - Boolean predicate functions (isXxx, hasXxx, canXxx, shouldXxx)
|
|
16
|
+
* - Predicate callbacks (filter, find, some, every, map, etc.) where false/null means "skip item"
|
|
17
|
+
* - Validation/utility functions (validate, verify, parse, check, get, test, compare, supports, etc.)
|
|
18
|
+
* - Code with `// @silent-ok` marker
|
|
19
|
+
* - Code with nearby logging
|
|
20
|
+
* - Fitness check and framework source files (excluded from scanning)
|
|
21
|
+
*/
|
|
22
|
+
export declare const silentEarlyReturns: import("@opensip-cli/fitness").Check;
|
|
23
|
+
//# sourceMappingURL=silent-early-returns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"silent-early-returns.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/silent-early-returns.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuQH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,sCAgD7B,CAAC"}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Silent Early Returns Check
|
|
3
|
+
*
|
|
4
|
+
* Detects validation/guard paths that return silently without logging.
|
|
5
|
+
* These patterns make debugging difficult by hiding why code paths weren't executed.
|
|
6
|
+
*/
|
|
7
|
+
import { logger } from '@opensip-cli/core';
|
|
8
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
9
|
+
import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
|
|
10
|
+
import * as ts from 'typescript';
|
|
11
|
+
/**
|
|
12
|
+
* Patterns that indicate logging is present
|
|
13
|
+
*/
|
|
14
|
+
const LOGGING_PATTERNS = [/logger\./, /console\./, /\.log\(/];
|
|
15
|
+
/**
|
|
16
|
+
* Patterns that indicate intentional silent return
|
|
17
|
+
*/
|
|
18
|
+
const MARKER_PATTERNS = [/@silent-ok/, /\/\/\s*type\s*guard/i];
|
|
19
|
+
/**
|
|
20
|
+
* Sentinel return value kinds
|
|
21
|
+
*/
|
|
22
|
+
const SENTINEL_KINDS = new Set([ts.SyntaxKind.NullKeyword, ts.SyntaxKind.FalseKeyword]);
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// HELPER FUNCTIONS
|
|
25
|
+
// =============================================================================
|
|
26
|
+
/**
|
|
27
|
+
* Find the enclosing function for a node.
|
|
28
|
+
*
|
|
29
|
+
* Intentionally narrower than `lang-typescript`'s `findEnclosingFunction` —
|
|
30
|
+
* skips past `ConstructorDeclaration` and `FunctionExpression` parents to
|
|
31
|
+
* find the next enclosing declaration/method/arrow whose name (if any) the
|
|
32
|
+
* downstream predicates (`isTypeGuard`, `isValidationOrParserFunction`) can
|
|
33
|
+
* inspect. Switching to the canonical helper would change behavior for
|
|
34
|
+
* `if (!x) return null` directly inside a constructor body.
|
|
35
|
+
*/
|
|
36
|
+
function findFunction(node) {
|
|
37
|
+
let current = node.parent;
|
|
38
|
+
while (current) {
|
|
39
|
+
if (ts.isFunctionDeclaration(current) ||
|
|
40
|
+
ts.isMethodDeclaration(current) ||
|
|
41
|
+
ts.isArrowFunction(current)) {
|
|
42
|
+
return current;
|
|
43
|
+
}
|
|
44
|
+
current = current.parent;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Check if a function is a type guard or boolean predicate
|
|
50
|
+
* - Type guards: functions that return `x is T`
|
|
51
|
+
* - Predicate functions: isXxx, hasXxx, canXxx, shouldXxx
|
|
52
|
+
*/
|
|
53
|
+
function isTypeGuard(fn, sourceFile) {
|
|
54
|
+
// Check return type predicate
|
|
55
|
+
if (fn.type?.getText(sourceFile).includes(' is ')) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
// Check function name matches predicate patterns
|
|
59
|
+
if ((ts.isFunctionDeclaration(fn) || ts.isMethodDeclaration(fn)) && fn.name) {
|
|
60
|
+
const name = fn.name.getText(sourceFile);
|
|
61
|
+
// Predicate function patterns: isXxx, hasXxx, canXxx, shouldXxx
|
|
62
|
+
if (/^(is|has|can|should)[A-Z]/.test(name)) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Check if a function is a validation/parsing function where silent returns are expected.
|
|
70
|
+
* These functions legitimately return null/false for invalid input.
|
|
71
|
+
*/
|
|
72
|
+
function isValidationOrParserFunction(fn, sourceFile) {
|
|
73
|
+
// Get function name if available
|
|
74
|
+
if ((ts.isFunctionDeclaration(fn) || ts.isMethodDeclaration(fn)) && fn.name) {
|
|
75
|
+
const name = fn.name.getText(sourceFile);
|
|
76
|
+
// Validation/parsing function patterns: validate*, verify*, parse*, check*, extract*, get*OrNull, etc.
|
|
77
|
+
if (
|
|
78
|
+
// eslint-disable-next-line sonarjs/regex-complexity -- exhaustive list of known validator/parser prefixes; readable as written
|
|
79
|
+
/^(validate|verify|parse|check|extract|try|attempt|find|get\w*OrNull|get|lookup|resolve|match|unregister|acquire|release|test|compare|supports)[A-Z]?/.test(name)) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Check return type - functions returning T | null or T | undefined are validators
|
|
84
|
+
if (fn.type) {
|
|
85
|
+
const returnType = fn.type.getText(sourceFile);
|
|
86
|
+
if (returnType.includes('| null') || returnType.includes('| undefined')) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if a return is a guard clause at the start of a function (first 3 statements).
|
|
94
|
+
* Early guard clauses are a common defensive coding pattern.
|
|
95
|
+
*/
|
|
96
|
+
function isEarlyGuardClause(returnNode, fn) {
|
|
97
|
+
const body = fn.body;
|
|
98
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
99
|
+
if (!body || !ts.isBlock(body))
|
|
100
|
+
return false;
|
|
101
|
+
const statements = body.statements;
|
|
102
|
+
for (let i = 0; i < Math.min(statements.length, 3); i++) {
|
|
103
|
+
if (statements[i] === returnNode) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Array predicate methods where returning false is intentional filtering
|
|
111
|
+
*/
|
|
112
|
+
const PREDICATE_METHODS = new Set([
|
|
113
|
+
'filter',
|
|
114
|
+
'find',
|
|
115
|
+
'findIndex',
|
|
116
|
+
'findLast',
|
|
117
|
+
'findLastIndex',
|
|
118
|
+
'some',
|
|
119
|
+
'every',
|
|
120
|
+
'map',
|
|
121
|
+
]);
|
|
122
|
+
/**
|
|
123
|
+
* Check if a function is a callback in an array predicate method
|
|
124
|
+
* Example: arr.filter(x => { if (!x) return false; ... })
|
|
125
|
+
*/
|
|
126
|
+
function isPredicateCallback(fn) {
|
|
127
|
+
// Only arrow functions can be predicate callbacks
|
|
128
|
+
if (!ts.isArrowFunction(fn))
|
|
129
|
+
return false;
|
|
130
|
+
// Check if parent is a call expression argument
|
|
131
|
+
const parent = fn.parent;
|
|
132
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
133
|
+
if (!ts.isCallExpression(parent))
|
|
134
|
+
return false;
|
|
135
|
+
// Check if the call is a method call
|
|
136
|
+
const callee = parent.expression;
|
|
137
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
138
|
+
if (!ts.isPropertyAccessExpression(callee))
|
|
139
|
+
return false;
|
|
140
|
+
// Check if method name is a predicate method
|
|
141
|
+
const methodName = callee.name.getText();
|
|
142
|
+
return PREDICATE_METHODS.has(methodName);
|
|
143
|
+
}
|
|
144
|
+
function extractReturnStatement(node) {
|
|
145
|
+
if (ts.isReturnStatement(node.thenStatement)) {
|
|
146
|
+
return node.thenStatement;
|
|
147
|
+
}
|
|
148
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
149
|
+
if (ts.isBlock(node.thenStatement) && node.thenStatement.statements.length === 1) {
|
|
150
|
+
const statement = node.thenStatement.statements[0];
|
|
151
|
+
if (statement && ts.isReturnStatement(statement)) {
|
|
152
|
+
return statement;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
function isSentinelReturn(returnStatement) {
|
|
158
|
+
return Boolean(returnStatement?.expression && SENTINEL_KINDS.has(returnStatement.expression.kind));
|
|
159
|
+
}
|
|
160
|
+
function shouldSkipForFunction(node, sourceFile) {
|
|
161
|
+
const fn = findFunction(node);
|
|
162
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
163
|
+
if (!fn)
|
|
164
|
+
return false;
|
|
165
|
+
return (isTypeGuard(fn, sourceFile) ||
|
|
166
|
+
isPredicateCallback(fn) ||
|
|
167
|
+
isValidationOrParserFunction(fn, sourceFile) ||
|
|
168
|
+
isEarlyGuardClause(node, fn));
|
|
169
|
+
}
|
|
170
|
+
function hasLoggingOrMarkerInContext(node, content) {
|
|
171
|
+
/* v8 ignore next -- defensive non-negative guard */
|
|
172
|
+
const start = Math.max(0, node.getStart() - 200);
|
|
173
|
+
const context = content.slice(start, node.getEnd());
|
|
174
|
+
return (LOGGING_PATTERNS.some((p) => p.test(context)) || MARKER_PATTERNS.some((p) => p.test(context)));
|
|
175
|
+
}
|
|
176
|
+
function createSilentReturnViolation(node, returnStatement, sourceFile) {
|
|
177
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
178
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
179
|
+
const val = returnStatement.expression.kind === ts.SyntaxKind.NullKeyword ? 'null' : 'false';
|
|
180
|
+
return {
|
|
181
|
+
line: line + 1,
|
|
182
|
+
column: 0,
|
|
183
|
+
message: `Silent early return (${val}) without logging`,
|
|
184
|
+
severity: 'error',
|
|
185
|
+
// @fitness-ignore-next-line logging-standards -- String literal in suggestion text, not actual logger call
|
|
186
|
+
suggestion: `Add logging: \`if (cond) { logger.info({ evt: 'validation.failed' }); return ${val}; }\``,
|
|
187
|
+
match: `return ${val}`,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function checkSilentReturn(node, sourceFile, content) {
|
|
191
|
+
const returnStatement = extractReturnStatement(node);
|
|
192
|
+
if (!isSentinelReturn(returnStatement)) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
if (shouldSkipForFunction(node, sourceFile)) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
if (hasLoggingOrMarkerInContext(node, content)) {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
return createSilentReturnViolation(node, returnStatement, sourceFile);
|
|
202
|
+
}
|
|
203
|
+
// =============================================================================
|
|
204
|
+
// CHECK IMPLEMENTATION
|
|
205
|
+
// =============================================================================
|
|
206
|
+
/**
|
|
207
|
+
* Check: quality/silent-early-returns
|
|
208
|
+
*
|
|
209
|
+
* Detects single-line early returns (if (!x) return null/false) without logging.
|
|
210
|
+
* These patterns make it impossible to know why a code path wasn't executed.
|
|
211
|
+
*
|
|
212
|
+
* Exceptions:
|
|
213
|
+
* - Type guards (functions that return `x is T`)
|
|
214
|
+
* - Boolean predicate functions (isXxx, hasXxx, canXxx, shouldXxx)
|
|
215
|
+
* - Predicate callbacks (filter, find, some, every, map, etc.) where false/null means "skip item"
|
|
216
|
+
* - Validation/utility functions (validate, verify, parse, check, get, test, compare, supports, etc.)
|
|
217
|
+
* - Code with `// @silent-ok` marker
|
|
218
|
+
* - Code with nearby logging
|
|
219
|
+
* - Fitness check and framework source files (excluded from scanning)
|
|
220
|
+
*/
|
|
221
|
+
export const silentEarlyReturns = defineCheck({
|
|
222
|
+
id: '9585ae15-45ea-404c-91b5-91baad7b4de0',
|
|
223
|
+
slug: 'silent-early-returns',
|
|
224
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
|
|
225
|
+
contentFilter: 'strip-strings',
|
|
226
|
+
description: 'Detect single-line early returns without logging',
|
|
227
|
+
longDescription: `**Purpose:** Detects validation/guard paths that return sentinel values (\`null\` or \`false\`) without logging, making debugging difficult.
|
|
228
|
+
|
|
229
|
+
**Detects:** Analyzes each file individually using TypeScript AST. Finds \`if\` statements (without \`else\`) whose then-branch is a single \`return null\` or \`return false\` with no nearby logging (\`logger.\`, \`console.\`) or \`@silent-ok\` marker. Excludes type guards (\`is/has/can/should\` prefixes), predicate callbacks (\`filter\`, \`find\`, \`some\`, \`every\`, \`map\`), validation/parser/utility functions (validate, verify, parse, check, extract, try, attempt, find, get, lookup, resolve, match, unregister, acquire, release, test, compare, supports), early guard clauses (first 3 statements), and fitness check/framework source files.
|
|
230
|
+
|
|
231
|
+
**Why it matters:** Silent early returns make it impossible to diagnose why a code path was not executed, turning simple issues into hours-long debugging sessions.
|
|
232
|
+
|
|
233
|
+
**Scope:** General best practice`,
|
|
234
|
+
tags: ['quality', 'observability', 'validation'],
|
|
235
|
+
fileTypes: ['ts'],
|
|
236
|
+
confidence: 'medium',
|
|
237
|
+
analyze(content, filePath) {
|
|
238
|
+
logger.debug({
|
|
239
|
+
evt: 'fitness.check.silent_early_returns.analyze',
|
|
240
|
+
msg: 'Analyzing file for silent early return patterns',
|
|
241
|
+
filePath,
|
|
242
|
+
});
|
|
243
|
+
// Quick filter: must have potential silent returns
|
|
244
|
+
if (!content.includes('return null') && !content.includes('return false')) {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
const violations = [];
|
|
248
|
+
const sourceFile = getSharedSourceFile(filePath, content);
|
|
249
|
+
/* v8 ignore next -- defensive guard */
|
|
250
|
+
if (!sourceFile)
|
|
251
|
+
return [];
|
|
252
|
+
const visit = (node) => {
|
|
253
|
+
// Only check if statements without else (single-line guards)
|
|
254
|
+
if (ts.isIfStatement(node) && !node.elseStatement) {
|
|
255
|
+
const violation = checkSilentReturn(node, sourceFile, content);
|
|
256
|
+
if (violation) {
|
|
257
|
+
violations.push(violation);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
ts.forEachChild(node, visit);
|
|
261
|
+
};
|
|
262
|
+
visit(sourceFile);
|
|
263
|
+
return violations;
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
//# sourceMappingURL=silent-early-returns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"silent-early-returns.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/silent-early-returns.ts"],"names":[],"mappings":"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"}
|