@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 @@
|
|
|
1
|
+
{"version":3,"file":"dispose-pattern-completeness.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/dispose-pattern-completeness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Unified Error Handling Quality Check
|
|
3
|
+
*
|
|
4
|
+
* Detects silent error handling in both try/catch and Result patterns.
|
|
5
|
+
* Replaces: resilience/no-empty-catch, quality/error-swallowing-boolean
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check: quality/error-handling-quality
|
|
9
|
+
*
|
|
10
|
+
* Detects silent error handling in both try/catch and Result patterns.
|
|
11
|
+
* This is a unified check that replaces:
|
|
12
|
+
* - resilience/no-empty-catch
|
|
13
|
+
* - quality/error-swallowing-boolean
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
16
|
+
export declare const errorHandlingQuality: import("@opensip-cli/fitness").Check;
|
|
17
|
+
//# sourceMappingURL=error-handling-quality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handling-quality.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/error-handling-quality.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAkSH;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,sCAwD/B,CAAC"}
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
// @fitness-ignore-file canonical-result-usage -- References Result pattern in comments/JSDoc for pattern detection documentation, not actual Result usage
|
|
2
|
+
// @fitness-ignore-file logging-standards -- String literals in suggestion text reference logger calls, not actual logger usage
|
|
3
|
+
// @fitness-ignore-file error-handling-quality -- Fitness check implementation: catch blocks in AST analysis intentionally return empty results to skip unreadable files
|
|
4
|
+
/**
|
|
5
|
+
* @fileoverview Unified Error Handling Quality Check
|
|
6
|
+
*
|
|
7
|
+
* Detects silent error handling in both try/catch and Result patterns.
|
|
8
|
+
* Replaces: resilience/no-empty-catch, quality/error-swallowing-boolean
|
|
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
|
+
// WHITELIST PATTERNS
|
|
15
|
+
// =============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Patterns that indicate proper error handling (logging)
|
|
18
|
+
*/
|
|
19
|
+
const LOGGING_PATTERNS = [
|
|
20
|
+
/logger\.(error|warn|debug|info)\s*\(/,
|
|
21
|
+
/safeLogger\.(error|warn|debug|info)\s*\(/,
|
|
22
|
+
/console\.(error|warn)\s*\(/,
|
|
23
|
+
/\.log\s*\(/,
|
|
24
|
+
/unwrapOrLog\s*\(/,
|
|
25
|
+
/matchLog\s*\(/,
|
|
26
|
+
/handleErr\s*\(/,
|
|
27
|
+
];
|
|
28
|
+
/**
|
|
29
|
+
* Patterns that indicate intentional silent handling
|
|
30
|
+
*/
|
|
31
|
+
const MARKER_PATTERNS = [
|
|
32
|
+
/@swallow-ok/,
|
|
33
|
+
/@handles/,
|
|
34
|
+
/\/\/\s*intentionally/i,
|
|
35
|
+
/\/\/\s*expected/i,
|
|
36
|
+
/graceful/i,
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* Patterns that indicate error propagation
|
|
40
|
+
*/
|
|
41
|
+
const PROPAGATION_PATTERNS = [
|
|
42
|
+
/\berr\s*\(/,
|
|
43
|
+
/Result\.err\s*\(/,
|
|
44
|
+
/new\s+Failure\s*\(/,
|
|
45
|
+
/return\s+\S[^\n]*\.error\b/,
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Pattern for rethrow
|
|
49
|
+
*/
|
|
50
|
+
const RETHROW_PATTERN = /\bthrow\b/;
|
|
51
|
+
/**
|
|
52
|
+
* Sentinel return values that indicate silent error handling
|
|
53
|
+
*/
|
|
54
|
+
const SENTINEL_VALUES = new Set(['false', 'null', 'undefined', '[]', '{}']);
|
|
55
|
+
// =============================================================================
|
|
56
|
+
// HELPER FUNCTIONS
|
|
57
|
+
// =============================================================================
|
|
58
|
+
/**
|
|
59
|
+
* Check if text contains acceptable error handling
|
|
60
|
+
* @param text - Text to check
|
|
61
|
+
* @returns True if acceptable pattern found
|
|
62
|
+
*/
|
|
63
|
+
function hasAcceptablePattern(text) {
|
|
64
|
+
if (LOGGING_PATTERNS.some((p) => p.test(text)))
|
|
65
|
+
return true;
|
|
66
|
+
if (MARKER_PATTERNS.some((p) => p.test(text)))
|
|
67
|
+
return true;
|
|
68
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
69
|
+
if (PROPAGATION_PATTERNS.some((p) => p.test(text)))
|
|
70
|
+
return true;
|
|
71
|
+
if (RETHROW_PATTERN.test(text))
|
|
72
|
+
return true;
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get return value type from expression
|
|
77
|
+
* @param expr - TypeScript expression
|
|
78
|
+
* @param sourceFile - Source file for getting text
|
|
79
|
+
* @returns String representation or null if not a sentinel
|
|
80
|
+
*/
|
|
81
|
+
function getReturnValue(expr, sourceFile) {
|
|
82
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
83
|
+
if (!expr)
|
|
84
|
+
return 'undefined';
|
|
85
|
+
if (expr.kind === ts.SyntaxKind.FalseKeyword)
|
|
86
|
+
return 'false';
|
|
87
|
+
if (expr.kind === ts.SyntaxKind.NullKeyword)
|
|
88
|
+
return 'null';
|
|
89
|
+
if (ts.isIdentifier(expr) && expr.getText(sourceFile) === 'undefined')
|
|
90
|
+
return 'undefined';
|
|
91
|
+
if (ts.isArrayLiteralExpression(expr) && expr.elements.length === 0)
|
|
92
|
+
return '[]';
|
|
93
|
+
if (ts.isObjectLiteralExpression(expr) && expr.properties.length === 0)
|
|
94
|
+
return '{}';
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
// =============================================================================
|
|
98
|
+
// CHECK FUNCTIONS
|
|
99
|
+
// =============================================================================
|
|
100
|
+
/**
|
|
101
|
+
* Check a catch clause for violations
|
|
102
|
+
*/
|
|
103
|
+
function checkCatchClause(node, sourceFile) {
|
|
104
|
+
const violations = [];
|
|
105
|
+
const catchText = node.block.getText(sourceFile);
|
|
106
|
+
// Skip if has acceptable pattern
|
|
107
|
+
if (hasAcceptablePattern(catchText))
|
|
108
|
+
return violations;
|
|
109
|
+
const trimmed = catchText.replaceAll(/[{}]/g, '').trim();
|
|
110
|
+
// Strip leading single-line comments (`// ...` lines, including
|
|
111
|
+
// multi-line stacks) and block comments before testing for empty.
|
|
112
|
+
// The original regex `/^\/[/*]/` only checked the first character,
|
|
113
|
+
// which falsely flags `} catch { // comment\n actualHandler() }`
|
|
114
|
+
// patterns as empty even though real code follows the comment.
|
|
115
|
+
let codeOnly = trimmed;
|
|
116
|
+
while (true) {
|
|
117
|
+
if (codeOnly.startsWith('//')) {
|
|
118
|
+
const eol = codeOnly.indexOf('\n');
|
|
119
|
+
codeOnly = (eol === -1 ? '' : codeOnly.slice(eol + 1)).trim();
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (codeOnly.startsWith('/*')) {
|
|
123
|
+
const close = codeOnly.indexOf('*/');
|
|
124
|
+
codeOnly = (close === -1 ? '' : codeOnly.slice(close + 2)).trim();
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
// Empty catch - SEVERITY: ERROR
|
|
130
|
+
if (trimmed === '' || codeOnly === '') {
|
|
131
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
132
|
+
violations.push({
|
|
133
|
+
line: line + 1,
|
|
134
|
+
column: 0,
|
|
135
|
+
message: 'Empty catch block silently swallows errors',
|
|
136
|
+
severity: 'error',
|
|
137
|
+
suggestion: "Add logging: `logger.error({ evt: 'operation.failed', err })` or add `// @swallow-ok reason`",
|
|
138
|
+
match: 'catch',
|
|
139
|
+
});
|
|
140
|
+
return violations;
|
|
141
|
+
}
|
|
142
|
+
// Check for sentinel returns without logging
|
|
143
|
+
const visitReturn = (n) => {
|
|
144
|
+
if (ts.isReturnStatement(n)) {
|
|
145
|
+
const val = getReturnValue(n.expression, sourceFile);
|
|
146
|
+
if (val && SENTINEL_VALUES.has(val)) {
|
|
147
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(n.getStart());
|
|
148
|
+
violations.push({
|
|
149
|
+
line: line + 1,
|
|
150
|
+
column: 0,
|
|
151
|
+
message: `Catch returns ${val} without logging`,
|
|
152
|
+
severity: 'error',
|
|
153
|
+
suggestion: `Add logging before return: \`logger.warn({ evt: 'operation.failed', err })\``,
|
|
154
|
+
match: `return ${val}`,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
ts.forEachChild(n, visitReturn);
|
|
159
|
+
};
|
|
160
|
+
visitReturn(node.block);
|
|
161
|
+
return violations;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Check Result.isErr() usage for violations
|
|
165
|
+
*/
|
|
166
|
+
function checkResultIsErr(node, sourceFile) {
|
|
167
|
+
const violations = [];
|
|
168
|
+
const cond = node.expression.getText(sourceFile);
|
|
169
|
+
// @fitness-ignore-next-line error-handling-quality -- String literal check for '.isErr()', not actual Result error handling
|
|
170
|
+
if (!cond.includes('.isErr()'))
|
|
171
|
+
return violations;
|
|
172
|
+
const thenText = node.thenStatement.getText(sourceFile);
|
|
173
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
174
|
+
if (hasAcceptablePattern(thenText))
|
|
175
|
+
return violations;
|
|
176
|
+
// Check for silent sentinel returns
|
|
177
|
+
const visitReturn = (n) => {
|
|
178
|
+
if (ts.isReturnStatement(n)) {
|
|
179
|
+
const val = getReturnValue(n.expression, sourceFile);
|
|
180
|
+
if (val && SENTINEL_VALUES.has(val)) {
|
|
181
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
182
|
+
violations.push({
|
|
183
|
+
line: line + 1,
|
|
184
|
+
column: 0,
|
|
185
|
+
message: `Result error silently discarded - returns ${val}`,
|
|
186
|
+
severity: 'error',
|
|
187
|
+
suggestion: `Use: \`result.unwrapOrLog(${val}, { evt: 'operation.failed' })\``,
|
|
188
|
+
match: 'isErr()',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
if (ts.isBlock(node.thenStatement)) {
|
|
194
|
+
node.thenStatement.statements.forEach(visitReturn);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
visitReturn(node.thenStatement);
|
|
198
|
+
}
|
|
199
|
+
return violations;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Check Result methods for violations
|
|
203
|
+
*/
|
|
204
|
+
function checkResultMethods(node, sourceFile) {
|
|
205
|
+
const violations = [];
|
|
206
|
+
if (!ts.isPropertyAccessExpression(node.expression))
|
|
207
|
+
return violations;
|
|
208
|
+
const method = node.expression.name.getText(sourceFile);
|
|
209
|
+
// mapErr without logging - SEVERITY: ERROR
|
|
210
|
+
if (method === 'mapErr' && node.arguments.length > 0) {
|
|
211
|
+
const firstArg = node.arguments[0];
|
|
212
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
213
|
+
if (!firstArg)
|
|
214
|
+
return violations;
|
|
215
|
+
const callback = firstArg.getText(sourceFile);
|
|
216
|
+
if (!hasAcceptablePattern(callback)) {
|
|
217
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
218
|
+
violations.push({
|
|
219
|
+
line: line + 1,
|
|
220
|
+
column: 0,
|
|
221
|
+
message: 'mapErr() discards error without logging',
|
|
222
|
+
severity: 'error',
|
|
223
|
+
suggestion: 'Add logging: `mapErr(err => { logger.warn({ err }); return default; })`',
|
|
224
|
+
match: 'mapErr',
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// match() error handler without logging - SEVERITY: ERROR
|
|
229
|
+
if (method === 'match' && node.arguments.length >= 2) {
|
|
230
|
+
const secondArg = node.arguments[1];
|
|
231
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
232
|
+
if (!secondArg)
|
|
233
|
+
return violations;
|
|
234
|
+
const errHandler = secondArg.getText(sourceFile);
|
|
235
|
+
if (!hasAcceptablePattern(errHandler)) {
|
|
236
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
237
|
+
violations.push({
|
|
238
|
+
line: line + 1,
|
|
239
|
+
column: 0,
|
|
240
|
+
message: "match() error handler doesn't log",
|
|
241
|
+
severity: 'error',
|
|
242
|
+
suggestion: 'Use matchLog() instead, or add logging to error handler',
|
|
243
|
+
match: 'match',
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return violations;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Check a catch clause for unsafe `as Error` casts
|
|
251
|
+
*/
|
|
252
|
+
function checkCatchClauseAsErrorCast(node, sourceFile) {
|
|
253
|
+
const violations = [];
|
|
254
|
+
const catchText = node.block.getText(sourceFile);
|
|
255
|
+
// Skip if the catch block contains an instanceof Error guard
|
|
256
|
+
if (catchText.includes('instanceof Error'))
|
|
257
|
+
return violations;
|
|
258
|
+
// Check for `as Error` casts
|
|
259
|
+
if (catchText.includes('as Error')) {
|
|
260
|
+
const { line } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
261
|
+
const catchParam = node.variableDeclaration?.name.getText(sourceFile) ?? 'error';
|
|
262
|
+
violations.push({
|
|
263
|
+
line: line + 1,
|
|
264
|
+
column: 0,
|
|
265
|
+
message: 'Unsafe `as Error` cast in catch block without `instanceof Error` guard',
|
|
266
|
+
severity: 'warning',
|
|
267
|
+
suggestion: `Use \`if (${catchParam} instanceof Error)\` guard or normalize the error with a typed error utility`,
|
|
268
|
+
match: 'as Error',
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
return violations;
|
|
272
|
+
}
|
|
273
|
+
// =============================================================================
|
|
274
|
+
// CHECK IMPLEMENTATION
|
|
275
|
+
// =============================================================================
|
|
276
|
+
/**
|
|
277
|
+
* Check: quality/error-handling-quality
|
|
278
|
+
*
|
|
279
|
+
* Detects silent error handling in both try/catch and Result patterns.
|
|
280
|
+
* This is a unified check that replaces:
|
|
281
|
+
* - resilience/no-empty-catch
|
|
282
|
+
* - quality/error-swallowing-boolean
|
|
283
|
+
*
|
|
284
|
+
*/
|
|
285
|
+
export const errorHandlingQuality = defineCheck({
|
|
286
|
+
id: '6bae5be9-87f4-499e-a886-ca78a233cfb7',
|
|
287
|
+
slug: 'error-handling-quality',
|
|
288
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
|
|
289
|
+
contentFilter: 'strip-strings',
|
|
290
|
+
confidence: 'high',
|
|
291
|
+
description: 'Detect silent error handling in try/catch and Result patterns',
|
|
292
|
+
longDescription: `**Purpose:** Detects silent error handling in both try/catch blocks and Result pattern usage, ensuring errors are always logged or propagated.
|
|
293
|
+
|
|
294
|
+
**Detects:** Analyzes each file individually using TypeScript AST. Checks for:
|
|
295
|
+
- Empty catch blocks (no logging, no rethrow, no \`@swallow-ok\` marker)
|
|
296
|
+
- Catch blocks that return sentinel values (\`false\`, \`null\`, \`undefined\`, \`[]\`, \`{}\`) without logging
|
|
297
|
+
- \`result.isErr()\` branches that silently return sentinel values
|
|
298
|
+
- \`mapErr()\` callbacks without logging
|
|
299
|
+
- \`match()\` error handlers without logging (suggests \`matchLog()\` instead)
|
|
300
|
+
|
|
301
|
+
**Why it matters:** Silent error handling hides failures, making production debugging nearly impossible and allowing cascading failures to go undetected.
|
|
302
|
+
|
|
303
|
+
**Scope:** General best practice`,
|
|
304
|
+
tags: ['quality', 'resilience', 'error-handling', 'observability', 'result-pattern'],
|
|
305
|
+
fileTypes: ['ts'],
|
|
306
|
+
analyze(content, filePath) {
|
|
307
|
+
// Skip test files — as Error casts, match()/mapErr() calls are exercising APIs, not production error handling
|
|
308
|
+
if (isTestFile(filePath))
|
|
309
|
+
return [];
|
|
310
|
+
// Quick filter: must have catch or Result patterns
|
|
311
|
+
if (!content.includes('catch') && !content.includes('isErr') && !content.includes('.match(')) {
|
|
312
|
+
return [];
|
|
313
|
+
}
|
|
314
|
+
const violations = [];
|
|
315
|
+
const sourceFile = getSharedSourceFile(filePath, content);
|
|
316
|
+
/* v8 ignore next -- defensive guard */
|
|
317
|
+
if (!sourceFile)
|
|
318
|
+
return [];
|
|
319
|
+
const visit = (node) => {
|
|
320
|
+
if (ts.isCatchClause(node)) {
|
|
321
|
+
violations.push(...checkCatchClause(node, sourceFile), ...checkCatchClauseAsErrorCast(node, sourceFile));
|
|
322
|
+
}
|
|
323
|
+
if (ts.isIfStatement(node)) {
|
|
324
|
+
violations.push(...checkResultIsErr(node, sourceFile));
|
|
325
|
+
}
|
|
326
|
+
if (ts.isCallExpression(node)) {
|
|
327
|
+
violations.push(...checkResultMethods(node, sourceFile));
|
|
328
|
+
}
|
|
329
|
+
ts.forEachChild(node, visit);
|
|
330
|
+
};
|
|
331
|
+
visit(sourceFile);
|
|
332
|
+
return violations;
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
//# sourceMappingURL=error-handling-quality.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handling-quality.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/error-handling-quality.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './async-waterfall-detection.js';
|
|
2
|
+
export * from './dispose-pattern-completeness.js';
|
|
3
|
+
export * from './error-handling-quality.js';
|
|
4
|
+
export * from './lifecycle-cleanup-enforcement.js';
|
|
5
|
+
export * from './result-pattern-consistency.js';
|
|
6
|
+
export * from './silent-early-returns.js';
|
|
7
|
+
export * from './stream-buffer-size-limits.js';
|
|
8
|
+
export * from './throws-documentation.js';
|
|
9
|
+
export * from './toctou-race-condition.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './async-waterfall-detection.js';
|
|
2
|
+
export * from './dispose-pattern-completeness.js';
|
|
3
|
+
export * from './error-handling-quality.js';
|
|
4
|
+
export * from './lifecycle-cleanup-enforcement.js';
|
|
5
|
+
export * from './result-pattern-consistency.js';
|
|
6
|
+
export * from './silent-early-returns.js';
|
|
7
|
+
export * from './stream-buffer-size-limits.js';
|
|
8
|
+
export * from './throws-documentation.js';
|
|
9
|
+
export * from './toctou-race-condition.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Lifecycle Cleanup Enforcement check
|
|
3
|
+
*
|
|
4
|
+
* Detects resources with lifecycle methods (destroy, close, shutdown, stop, disconnect)
|
|
5
|
+
* that are created but never have their cleanup method called in the same scope.
|
|
6
|
+
* Unlike dispose-pattern-completeness (which checks IDisposable implementations),
|
|
7
|
+
* this check analyzes call-sites for proper resource cleanup.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Check: quality/lifecycle-cleanup-enforcement
|
|
11
|
+
*
|
|
12
|
+
* Detects resources with lifecycle methods (destroy, close, shutdown, stop, disconnect)
|
|
13
|
+
* created without cleanup. Uses a hardcoded registry of known lifecycle types.
|
|
14
|
+
*/
|
|
15
|
+
export declare const lifecycleCleanupEnforcement: import("@opensip-cli/fitness").Check;
|
|
16
|
+
//# sourceMappingURL=lifecycle-cleanup-enforcement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-cleanup-enforcement.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/lifecycle-cleanup-enforcement.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAmPH;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,sCA2BtC,CAAC"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Lifecycle Cleanup Enforcement check
|
|
3
|
+
*
|
|
4
|
+
* Detects resources with lifecycle methods (destroy, close, shutdown, stop, disconnect)
|
|
5
|
+
* that are created but never have their cleanup method called in the same scope.
|
|
6
|
+
* Unlike dispose-pattern-completeness (which checks IDisposable implementations),
|
|
7
|
+
* this check analyzes call-sites for proper resource cleanup.
|
|
8
|
+
*/
|
|
9
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
10
|
+
import { findEnclosingScope, getSharedSourceFile } from '@opensip-cli/lang-typescript';
|
|
11
|
+
import * as ts from 'typescript';
|
|
12
|
+
/**
|
|
13
|
+
* Hardcoded registry of known types with lifecycle methods.
|
|
14
|
+
* Extend this list as new lifecycle types are identified.
|
|
15
|
+
*/
|
|
16
|
+
const KNOWN_LIFECYCLE_TYPES = [
|
|
17
|
+
{ name: 'SipDataClient', methods: ['destroy'] },
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Set of all known type names for quick filtering.
|
|
21
|
+
*/
|
|
22
|
+
const KNOWN_TYPE_NAMES = new Set(KNOWN_LIFECYCLE_TYPES.map((t) => t.name));
|
|
23
|
+
/**
|
|
24
|
+
* Check if a node is a `new KnownType(...)` expression.
|
|
25
|
+
* @param node - The AST node to check
|
|
26
|
+
* @returns The matching LifecycleType or undefined
|
|
27
|
+
*/
|
|
28
|
+
function getLifecycleTypeFromNewExpression(node) {
|
|
29
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
30
|
+
if (!ts.isNewExpression(node)) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const expression = node.expression;
|
|
34
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
35
|
+
if (!ts.isIdentifier(expression)) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
const typeName = expression.text;
|
|
39
|
+
return KNOWN_LIFECYCLE_TYPES.find((t) => t.name === typeName);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if a scope contains a cleanup call for the given variable and method.
|
|
43
|
+
* Searches for patterns like: `variableName.method()`, `await variableName.method()`,
|
|
44
|
+
* or references within try/finally blocks.
|
|
45
|
+
* @param scope - The enclosing scope to search
|
|
46
|
+
* @param variableName - The variable name to check
|
|
47
|
+
* @param method - The lifecycle method to look for
|
|
48
|
+
* @param sourceFile - The source file for text extraction
|
|
49
|
+
* @returns True if a cleanup call was found
|
|
50
|
+
*/
|
|
51
|
+
function hasCleanupCallInScope(scope, variableName, method, sourceFile) {
|
|
52
|
+
let found = false;
|
|
53
|
+
const visit = (node) => {
|
|
54
|
+
if (found) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// Check for direct call: variableName.method()
|
|
58
|
+
if (ts.isCallExpression(node)) {
|
|
59
|
+
const expr = node.expression;
|
|
60
|
+
if (ts.isPropertyAccessExpression(expr) &&
|
|
61
|
+
ts.isIdentifier(expr.expression) &&
|
|
62
|
+
expr.expression.text === variableName &&
|
|
63
|
+
expr.name.text === method) {
|
|
64
|
+
found = true;
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Check for optional chaining: variableName?.method()
|
|
69
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
70
|
+
if (ts.isCallExpression(node)) {
|
|
71
|
+
const nodeText = node.getText(sourceFile);
|
|
72
|
+
if (nodeText.includes(`${variableName}?.${method}(`) ||
|
|
73
|
+
nodeText.includes(`${variableName}.${method}(`)) {
|
|
74
|
+
found = true;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
ts.forEachChild(node, visit);
|
|
79
|
+
};
|
|
80
|
+
ts.forEachChild(scope, visit);
|
|
81
|
+
return found;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check if the file defines (contains the class declaration for) any known lifecycle type.
|
|
85
|
+
* These files are the implementations, not consumers, and should be skipped.
|
|
86
|
+
* @param content - The file content
|
|
87
|
+
* @returns True if the file contains a class definition for a known type
|
|
88
|
+
*/
|
|
89
|
+
function isClassDefinitionFile(content) {
|
|
90
|
+
for (const typeName of KNOWN_TYPE_NAMES) {
|
|
91
|
+
if (content.includes(`class ${typeName}`)) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Find all resource creation sites in the AST.
|
|
99
|
+
* Looks for variable declarations where the initializer is `new KnownType(...)`.
|
|
100
|
+
* @param sourceFile - The parsed TypeScript source file
|
|
101
|
+
* @returns Array of resource creation records
|
|
102
|
+
*/
|
|
103
|
+
function findResourceCreations(sourceFile) {
|
|
104
|
+
const creations = [];
|
|
105
|
+
const visit = (node) => {
|
|
106
|
+
if (ts.isVariableDeclaration(node) && node.initializer) {
|
|
107
|
+
const lifecycleType = getLifecycleTypeFromNewExpression(node.initializer);
|
|
108
|
+
if (lifecycleType && ts.isIdentifier(node.name)) {
|
|
109
|
+
creations.push({
|
|
110
|
+
variableName: node.name.text,
|
|
111
|
+
lifecycleType,
|
|
112
|
+
node,
|
|
113
|
+
scope: findEnclosingScope(node),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
ts.forEachChild(node, visit);
|
|
118
|
+
};
|
|
119
|
+
visit(sourceFile);
|
|
120
|
+
return creations;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create a violation for a resource that is missing cleanup.
|
|
124
|
+
* @param ctx - Violation context
|
|
125
|
+
* @param creation - The resource creation record
|
|
126
|
+
* @param missingMethods - The lifecycle methods that were not called
|
|
127
|
+
* @returns CheckViolation object
|
|
128
|
+
*/
|
|
129
|
+
function createMissingCleanupViolation(ctx, creation, missingMethods) {
|
|
130
|
+
const { line: lineIdx, character } = ctx.sourceFile.getLineAndCharacterOfPosition(creation.node.getStart());
|
|
131
|
+
const line = lineIdx + 1;
|
|
132
|
+
const methodList = missingMethods.join(', ');
|
|
133
|
+
return {
|
|
134
|
+
line,
|
|
135
|
+
column: character + 1,
|
|
136
|
+
message: `Resource '${creation.variableName}' (${creation.lifecycleType.name}) is created but never cleaned up. Missing call to: ${methodList}`,
|
|
137
|
+
severity: 'warning',
|
|
138
|
+
suggestion: `Add '${creation.variableName}.${missingMethods[0]}()' in a finally block or cleanup handler to prevent resource leaks`,
|
|
139
|
+
type: 'missing-lifecycle-cleanup',
|
|
140
|
+
match: `new ${creation.lifecycleType.name}`,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Analyze a file for lifecycle cleanup coverage.
|
|
145
|
+
* Walks the AST to find resource creations and checks that cleanup methods are called.
|
|
146
|
+
* @param absolutePath - The file path
|
|
147
|
+
* @param content - The file content
|
|
148
|
+
* @returns Array of violations for uncleaned resources
|
|
149
|
+
*/
|
|
150
|
+
function analyzeCleanupCoverage(absolutePath, content) {
|
|
151
|
+
const violations = [];
|
|
152
|
+
// Skip files that define the lifecycle types themselves
|
|
153
|
+
if (isClassDefinitionFile(content)) {
|
|
154
|
+
return violations;
|
|
155
|
+
}
|
|
156
|
+
const sourceFile = getSharedSourceFile(absolutePath, content);
|
|
157
|
+
/* v8 ignore next -- defensive guard */
|
|
158
|
+
if (!sourceFile)
|
|
159
|
+
return [];
|
|
160
|
+
const ctx = { absolutePath, content, sourceFile };
|
|
161
|
+
const creations = findResourceCreations(sourceFile);
|
|
162
|
+
for (const creation of creations) {
|
|
163
|
+
const missingMethods = [];
|
|
164
|
+
for (const method of creation.lifecycleType.methods) {
|
|
165
|
+
if (!hasCleanupCallInScope(creation.scope, creation.variableName, method, sourceFile)) {
|
|
166
|
+
missingMethods.push(method);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (missingMethods.length > 0) {
|
|
170
|
+
violations.push(createMissingCleanupViolation(ctx, creation, missingMethods));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return violations;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Check: quality/lifecycle-cleanup-enforcement
|
|
177
|
+
*
|
|
178
|
+
* Detects resources with lifecycle methods (destroy, close, shutdown, stop, disconnect)
|
|
179
|
+
* created without cleanup. Uses a hardcoded registry of known lifecycle types.
|
|
180
|
+
*/
|
|
181
|
+
export const lifecycleCleanupEnforcement = defineCheck({
|
|
182
|
+
id: '6350ce24-8ccc-4607-a962-8b067633547c',
|
|
183
|
+
slug: 'lifecycle-cleanup-enforcement',
|
|
184
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'server'] },
|
|
185
|
+
confidence: 'high',
|
|
186
|
+
description: 'Detect resources with lifecycle methods (destroy/close/shutdown) created without cleanup',
|
|
187
|
+
longDescription: `**Purpose:** Detects resources with lifecycle methods that are created but never have their cleanup method called in the same scope.
|
|
188
|
+
|
|
189
|
+
**Detects:** Analyzes each file individually using TypeScript AST. Looks for \`new KnownType()\` variable declarations (currently: \`SipDataClient\`) and verifies that the required cleanup method (\`destroy()\`) is called on the variable within the enclosing function scope.
|
|
190
|
+
|
|
191
|
+
**Why it matters:** Resources without cleanup calls cause connection leaks, file descriptor exhaustion, and memory leaks that accumulate over the application lifetime.
|
|
192
|
+
|
|
193
|
+
**Scope:** Codebase-specific convention (hardcoded registry of known lifecycle types)`,
|
|
194
|
+
tags: ['quality', 'resources', 'memory', 'cleanup', 'lifecycle'],
|
|
195
|
+
fileTypes: ['ts'],
|
|
196
|
+
analyze(content, filePath) {
|
|
197
|
+
// Quick filter: skip files that do not reference any known lifecycle type
|
|
198
|
+
const hasKnownType = [...KNOWN_TYPE_NAMES].some((name) => content.includes(name));
|
|
199
|
+
if (!hasKnownType) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
return analyzeCleanupCoverage(filePath, content);
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
//# sourceMappingURL=lifecycle-cleanup-enforcement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle-cleanup-enforcement.js","sourceRoot":"","sources":["../../../../src/checks/quality/patterns/lifecycle-cleanup-enforcement.ts"],"names":[],"mappings":"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"}
|