@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,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview A11y Semantic HTML Check
|
|
3
|
+
*
|
|
4
|
+
* Detects div-soup anti-patterns where View components have onPress handlers
|
|
5
|
+
* without proper accessibility role definitions.
|
|
6
|
+
*/
|
|
7
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
8
|
+
import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
|
|
9
|
+
import * as ts from 'typescript';
|
|
10
|
+
/**
|
|
11
|
+
* Press handler props that indicate interactive behavior on View components.
|
|
12
|
+
*/
|
|
13
|
+
const PRESS_HANDLER_PROPS = new Set(['onPress', 'onPressIn', 'onPressOut', 'onLongPress']);
|
|
14
|
+
/**
|
|
15
|
+
* Analyze a TSX file for View components with press handlers missing accessibilityRole
|
|
16
|
+
* @param {string} content - The content of the file to analyze
|
|
17
|
+
* @param {string} filePath - The absolute path of the TSX file
|
|
18
|
+
* @returns {CheckViolation[]} Array of semantic HTML violations found
|
|
19
|
+
*/
|
|
20
|
+
function analyzeFile(content, filePath) {
|
|
21
|
+
// Only check TSX files
|
|
22
|
+
if (!filePath.endsWith('.tsx')) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
const violations = [];
|
|
26
|
+
const sourceFile = getSharedSourceFile(filePath, content);
|
|
27
|
+
/* v8 ignore next -- defensive guard */
|
|
28
|
+
if (!sourceFile)
|
|
29
|
+
return violations;
|
|
30
|
+
const visit = (node) => {
|
|
31
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
32
|
+
const tagName = ts.isIdentifier(node.tagName) ? node.tagName.text : '';
|
|
33
|
+
if (tagName === 'View') {
|
|
34
|
+
const attributes = node.attributes.properties;
|
|
35
|
+
// Check if View has any press handler props
|
|
36
|
+
const hasPressHandler = attributes.some((attr) => ts.isJsxAttribute(attr) && PRESS_HANDLER_PROPS.has(attr.name.getText()));
|
|
37
|
+
if (hasPressHandler) {
|
|
38
|
+
// Check if View has accessibilityRole
|
|
39
|
+
const hasAccessibilityRole = attributes.some((attr) => ts.isJsxAttribute(attr) && attr.name.getText() === 'accessibilityRole');
|
|
40
|
+
if (!hasAccessibilityRole) {
|
|
41
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
42
|
+
const lineNum = line + 1;
|
|
43
|
+
const matchText = node.getText(sourceFile).slice(0, 100);
|
|
44
|
+
violations.push({
|
|
45
|
+
filePath,
|
|
46
|
+
line: lineNum,
|
|
47
|
+
column: character + 1,
|
|
48
|
+
message: `<View> with press handler missing accessibilityRole`,
|
|
49
|
+
severity: 'warning',
|
|
50
|
+
suggestion: `Use <Pressable> instead of <View onPress>, or add accessibilityRole="button" for screen reader support`,
|
|
51
|
+
type: 'missing-accessibility-role',
|
|
52
|
+
match: matchText,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
ts.forEachChild(node, visit);
|
|
59
|
+
};
|
|
60
|
+
visit(sourceFile);
|
|
61
|
+
return violations;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check: quality/a11y-semantic-html
|
|
65
|
+
*
|
|
66
|
+
* Detects View components with press handlers that lack accessibilityRole.
|
|
67
|
+
* This is a div-soup anti-pattern that hurts screen reader accessibility.
|
|
68
|
+
*/
|
|
69
|
+
export const a11ySemanticHtml = defineCheck({
|
|
70
|
+
id: 'edccd88f-214d-4720-8843-2a94c2d5b729',
|
|
71
|
+
slug: 'a11y-semantic-html',
|
|
72
|
+
scope: { languages: ['typescript', 'tsx'], concerns: ['frontend', 'ui'] },
|
|
73
|
+
confidence: 'high',
|
|
74
|
+
description: 'Detect View components with press handlers missing accessibilityRole',
|
|
75
|
+
longDescription: `**Purpose:** Detects the "div-soup" anti-pattern where \`<View>\` components act as interactive elements without declaring an accessibility role.
|
|
76
|
+
|
|
77
|
+
**Detects:** Analyzes each file individually using TypeScript AST traversal of JSX elements.
|
|
78
|
+
- \`<View>\` components that have any of \`onPress\`, \`onPressIn\`, \`onPressOut\`, \`onLongPress\` but lack an \`accessibilityRole\` prop
|
|
79
|
+
- Only scans \`.tsx\` files; excludes test files
|
|
80
|
+
|
|
81
|
+
**Why it matters:** Screen readers cannot announce interactive Views as buttons or links without an explicit \`accessibilityRole\`, making tap targets invisible to assistive technology.
|
|
82
|
+
|
|
83
|
+
**Scope:** General best practice`,
|
|
84
|
+
tags: ['quality', 'accessibility', 'frontend', 'semantic'],
|
|
85
|
+
fileTypes: ['ts', 'tsx'],
|
|
86
|
+
analyze: analyzeFile,
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=a11y-semantic-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"a11y-semantic-html.js","sourceRoot":"","sources":["../../../../src/checks/quality/frontend/a11y-semantic-html.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/frontend/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iCAAiC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/checks/quality/frontend/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Test-Only Frontend Modules Check
|
|
3
|
+
*
|
|
4
|
+
* Detects frontend code (hooks, stores, services, utils) that is only
|
|
5
|
+
* imported by test files, indicating potentially dead code.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check: quality/test-only-frontend-modules
|
|
9
|
+
*
|
|
10
|
+
* Detects frontend code only imported by test files.
|
|
11
|
+
*/
|
|
12
|
+
export declare const testOnlyFrontendModules: import("@opensip-cli/fitness").Check;
|
|
13
|
+
//# sourceMappingURL=test-only-frontend-modules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-only-frontend-modules.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/frontend/test-only-frontend-modules.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAkIH;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,sCAgDlC,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// @fitness-ignore-file toctou-race-condition -- TOCTOU acceptable in this non-concurrent context
|
|
2
|
+
// @fitness-ignore-file duplicate-implementation-detection -- intentionally co-located for check isolation
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Test-Only Frontend Modules Check
|
|
5
|
+
*
|
|
6
|
+
* Detects frontend code (hooks, stores, services, utils) that is only
|
|
7
|
+
* imported by test files, indicating potentially dead code.
|
|
8
|
+
*/
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { defineCheck, isTestFile, } from '@opensip-cli/fitness';
|
|
11
|
+
/**
|
|
12
|
+
* Type guard to validate a Map with array values.
|
|
13
|
+
* @param {unknown} value - Value to validate
|
|
14
|
+
* @returns {value is Map<string, string[]>} True if value is a valid Map with array values
|
|
15
|
+
*/
|
|
16
|
+
function validateImportMap(value) {
|
|
17
|
+
return value instanceof Map;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Safe regex pattern for extracting named imports (bounded to prevent ReDoS)
|
|
21
|
+
* Pattern is safe because:
|
|
22
|
+
* - Uses bounded negated character class [^'"]{1,500}
|
|
23
|
+
* - Has clear boundaries with quotes
|
|
24
|
+
*/
|
|
25
|
+
const NAMED_IMPORT_PATTERN = /from\s+['"]([^'"]{1,500})['"]/g;
|
|
26
|
+
/**
|
|
27
|
+
* Safe regex pattern for extracting side-effect imports (`import './foo.js'`)
|
|
28
|
+
* Pattern is safe because:
|
|
29
|
+
* - Uses bounded negated character class [^'"]{1,500}
|
|
30
|
+
* - Has clear boundaries with quotes
|
|
31
|
+
*/
|
|
32
|
+
const SIDE_EFFECT_IMPORT_PATTERN = /^import\s+['"]([^'"]{1,500})['"]/gm;
|
|
33
|
+
/**
|
|
34
|
+
* Extract import paths from file content
|
|
35
|
+
* @param content - File content
|
|
36
|
+
* @returns Array of import paths
|
|
37
|
+
*/
|
|
38
|
+
// @fitness-ignore-next-line duplicate-implementation-detection -- import extraction is intentionally co-located with each check for isolation; shared utility would couple unrelated checks
|
|
39
|
+
function extractImportPaths(content) {
|
|
40
|
+
const paths = [];
|
|
41
|
+
// Match named imports: import { x } from './path'
|
|
42
|
+
const namedPattern = new RegExp(NAMED_IMPORT_PATTERN.source, 'g');
|
|
43
|
+
let match;
|
|
44
|
+
while ((match = namedPattern.exec(content)) !== null) {
|
|
45
|
+
const importPath = match[1];
|
|
46
|
+
if (importPath && (importPath.startsWith('.') || importPath.startsWith('@'))) {
|
|
47
|
+
paths.push(importPath);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Match side-effect imports: import './path'
|
|
51
|
+
const sideEffectPattern = new RegExp(SIDE_EFFECT_IMPORT_PATTERN.source, 'gm');
|
|
52
|
+
while ((match = sideEffectPattern.exec(content)) !== null) {
|
|
53
|
+
const importPath = match[1];
|
|
54
|
+
if (importPath && (importPath.startsWith('.') || importPath.startsWith('@'))) {
|
|
55
|
+
paths.push(importPath);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return paths;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Build import map from files
|
|
62
|
+
* @param files - FileAccessor for lazy file loading
|
|
63
|
+
* @returns Map of import path to importer files
|
|
64
|
+
*/
|
|
65
|
+
async function buildImportMap(files) {
|
|
66
|
+
const importMap = new Map();
|
|
67
|
+
for (const fp of files.paths) {
|
|
68
|
+
try {
|
|
69
|
+
// @fitness-ignore-next-line performance-anti-patterns -- sequential file reading to control memory; FileAccessor is lazy
|
|
70
|
+
const content = await files.read(fp);
|
|
71
|
+
const importPaths = extractImportPaths(content);
|
|
72
|
+
for (const importPath of importPaths) {
|
|
73
|
+
/* v8 ignore next -- defensive nullish fallback */
|
|
74
|
+
const importers = importMap.get(importPath) ?? [];
|
|
75
|
+
importers.push(fp);
|
|
76
|
+
importMap.set(importPath, importers);
|
|
77
|
+
}
|
|
78
|
+
/* v8 ignore next 1 -- defensive catch: parse failures already handled */
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// @swallow-ok Skip unreadable files
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return importMap;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Find importers for a file
|
|
88
|
+
* @param filePath - File to find importers for
|
|
89
|
+
* @param importMap - Map of imports (Map iteration with .entries() provides safe access)
|
|
90
|
+
* @returns Array of importer file paths
|
|
91
|
+
*/
|
|
92
|
+
function findImporters(filePath, importMap) {
|
|
93
|
+
// Map parameter validation: iteration via .entries() handles undefined/null safely
|
|
94
|
+
if (!validateImportMap(importMap)) {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
// Validate Map size before iteration
|
|
98
|
+
if (importMap.size === 0) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
const basename = path.basename(filePath, path.extname(filePath));
|
|
102
|
+
const dirname = path.dirname(filePath);
|
|
103
|
+
const parentDir = path.basename(dirname);
|
|
104
|
+
const importers = [];
|
|
105
|
+
for (const [importPath, importerFiles] of importMap.entries()) {
|
|
106
|
+
const matchesBasename = importPath.includes(basename) || importPath.includes(`${parentDir}/${basename}`);
|
|
107
|
+
const hasValidImporters = Array.isArray(importerFiles) && importerFiles.length > 0;
|
|
108
|
+
if (matchesBasename && hasValidImporters) {
|
|
109
|
+
importers.push(...importerFiles);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return importers;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Check: quality/test-only-frontend-modules
|
|
116
|
+
*
|
|
117
|
+
* Detects frontend code only imported by test files.
|
|
118
|
+
*/
|
|
119
|
+
export const testOnlyFrontendModules = defineCheck({
|
|
120
|
+
id: '78a085b3-55c4-42d3-a74c-8dfaad8123f1',
|
|
121
|
+
slug: 'test-only-frontend-modules',
|
|
122
|
+
scope: { languages: ['typescript', 'tsx'], concerns: ['frontend', 'ui'] },
|
|
123
|
+
contentFilter: 'strip-strings',
|
|
124
|
+
confidence: 'medium',
|
|
125
|
+
description: 'Detects frontend code only imported by test files',
|
|
126
|
+
tags: ['quality', 'code-quality', 'maintainability'],
|
|
127
|
+
fileTypes: ['ts', 'tsx'],
|
|
128
|
+
async analyzeAll(files) {
|
|
129
|
+
const violations = [];
|
|
130
|
+
// Build import map
|
|
131
|
+
const importMap = await buildImportMap(files);
|
|
132
|
+
// Check each file to see if it's only imported by tests
|
|
133
|
+
for (const filePath of files.paths) {
|
|
134
|
+
// Skip files in test directories — they are test utilities by design
|
|
135
|
+
if (isTestFile(filePath)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const importers = findImporters(filePath, importMap);
|
|
139
|
+
if (importers.length === 0) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const productionImporters = importers.filter((f) => !isTestFile(f));
|
|
143
|
+
const testImporters = importers.filter((f) => isTestFile(f));
|
|
144
|
+
if (productionImporters.length === 0 && testImporters.length > 0) {
|
|
145
|
+
violations.push({
|
|
146
|
+
filePath,
|
|
147
|
+
line: 1,
|
|
148
|
+
column: 0,
|
|
149
|
+
message: `Only imported by test files (${testImporters.length} test imports, 0 production)`,
|
|
150
|
+
severity: 'error',
|
|
151
|
+
suggestion: 'This module is only used in tests. Either add production usage, move it to a test utilities folder, or delete it if no longer needed',
|
|
152
|
+
match: path.basename(filePath),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return violations;
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
//# sourceMappingURL=test-only-frontend-modules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-only-frontend-modules.js","sourceRoot":"","sources":["../../../../src/checks/quality/frontend/test-only-frontend-modules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Incomplete Regex Escaping Check
|
|
3
|
+
*
|
|
4
|
+
* Detects incomplete regex character escaping in .replace() calls.
|
|
5
|
+
* This is a security vulnerability that can lead to regex injection attacks.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check: quality/incomplete-regex-escaping
|
|
9
|
+
*
|
|
10
|
+
* Detects incomplete regex character escaping that can lead to security vulnerabilities.
|
|
11
|
+
*/
|
|
12
|
+
export declare const incompleteRegexEscaping: import("@opensip-cli/fitness").Check;
|
|
13
|
+
//# sourceMappingURL=incomplete-regex-escaping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incomplete-regex-escaping.d.ts","sourceRoot":"","sources":["../../../src/checks/quality/incomplete-regex-escaping.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAmKH;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,sCAmDlC,CAAC"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// @fitness-ignore-file unused-config-options -- Config options reserved for future use or environment-specific
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Incomplete Regex Escaping Check
|
|
4
|
+
*
|
|
5
|
+
* Detects incomplete regex character escaping in .replace() calls.
|
|
6
|
+
* This is a security vulnerability that can lead to regex injection attacks.
|
|
7
|
+
*/
|
|
8
|
+
import { defineCheck } from '@opensip-cli/fitness';
|
|
9
|
+
import { getSharedSourceFile } from '@opensip-cli/lang-typescript';
|
|
10
|
+
import * as ts from 'typescript';
|
|
11
|
+
/**
|
|
12
|
+
* All special regex characters that should be escaped
|
|
13
|
+
*/
|
|
14
|
+
const REQUIRED_SPECIAL_CHARS = new Set([
|
|
15
|
+
'\\',
|
|
16
|
+
'^',
|
|
17
|
+
'$',
|
|
18
|
+
'.',
|
|
19
|
+
'*',
|
|
20
|
+
'+',
|
|
21
|
+
'?',
|
|
22
|
+
'(',
|
|
23
|
+
')',
|
|
24
|
+
'[',
|
|
25
|
+
']',
|
|
26
|
+
'{',
|
|
27
|
+
'}',
|
|
28
|
+
'|',
|
|
29
|
+
]);
|
|
30
|
+
/**
|
|
31
|
+
* Strip regex delimiters from pattern text
|
|
32
|
+
*/
|
|
33
|
+
function stripRegexDelimiters(regexText) {
|
|
34
|
+
let pattern = regexText;
|
|
35
|
+
if (pattern.startsWith('/')) {
|
|
36
|
+
pattern = pattern.slice(1);
|
|
37
|
+
}
|
|
38
|
+
if (pattern.includes('/')) {
|
|
39
|
+
/* v8 ignore next -- defensive non-negative guard */
|
|
40
|
+
pattern = pattern.slice(0, Math.max(0, pattern.lastIndexOf('/')));
|
|
41
|
+
}
|
|
42
|
+
return pattern;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Extract character class content from a pattern starting with [
|
|
46
|
+
*/
|
|
47
|
+
function extractCharacterClass(pattern) {
|
|
48
|
+
let charClass = '';
|
|
49
|
+
let i = 1;
|
|
50
|
+
while (i < pattern.length) {
|
|
51
|
+
const currentChar = pattern[i];
|
|
52
|
+
if (!currentChar)
|
|
53
|
+
break;
|
|
54
|
+
if (currentChar === '\\' && i + 1 < pattern.length) {
|
|
55
|
+
const nextChar = pattern[i + 1];
|
|
56
|
+
if (nextChar)
|
|
57
|
+
charClass += currentChar + nextChar;
|
|
58
|
+
i += 2;
|
|
59
|
+
}
|
|
60
|
+
else if (currentChar === ']') {
|
|
61
|
+
return charClass;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
charClass += currentChar;
|
|
65
|
+
i++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check if a character is in the character class
|
|
72
|
+
*/
|
|
73
|
+
function isCharInClass(char, charClass) {
|
|
74
|
+
if (char === '\\')
|
|
75
|
+
return charClass.includes('\\\\');
|
|
76
|
+
if (char === ']')
|
|
77
|
+
return charClass.includes(String.raw `\]`);
|
|
78
|
+
if (char === '^') {
|
|
79
|
+
return (charClass.includes(String.raw `\^`) || (charClass.includes('^') && charClass.indexOf('^') > 0));
|
|
80
|
+
}
|
|
81
|
+
if (char === '-') {
|
|
82
|
+
return (charClass.includes(String.raw `\-`) || charClass.startsWith('-') || charClass.endsWith('-'));
|
|
83
|
+
}
|
|
84
|
+
return charClass.includes(char) || charClass.includes(`\\${char}`);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Find missing special characters in a regex pattern
|
|
88
|
+
*/
|
|
89
|
+
function findMissingChars(regexText) {
|
|
90
|
+
const pattern = stripRegexDelimiters(regexText);
|
|
91
|
+
if (!pattern.startsWith('[')) {
|
|
92
|
+
return [...REQUIRED_SPECIAL_CHARS];
|
|
93
|
+
}
|
|
94
|
+
const charClass = extractCharacterClass(pattern);
|
|
95
|
+
if (charClass === null) {
|
|
96
|
+
return [...REQUIRED_SPECIAL_CHARS];
|
|
97
|
+
}
|
|
98
|
+
const missingChars = [];
|
|
99
|
+
for (const char of REQUIRED_SPECIAL_CHARS) {
|
|
100
|
+
if (!isCharInClass(char, charClass)) {
|
|
101
|
+
missingChars.push(char);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return missingChars;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Check if a call expression is a .replace() with incomplete escaping
|
|
108
|
+
*/
|
|
109
|
+
function checkReplaceCall(node, sourceFile, _filePath) {
|
|
110
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
111
|
+
if (!ts.isPropertyAccessExpression(node.expression))
|
|
112
|
+
return null;
|
|
113
|
+
if (node.expression.name.text !== 'replace')
|
|
114
|
+
return null;
|
|
115
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
116
|
+
if (node.arguments.length < 2)
|
|
117
|
+
return null;
|
|
118
|
+
const firstArg = node.arguments[0];
|
|
119
|
+
if (!firstArg || !ts.isRegularExpressionLiteral(firstArg))
|
|
120
|
+
return null;
|
|
121
|
+
const secondArg = node.arguments[1];
|
|
122
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
123
|
+
if (!secondArg || !ts.isStringLiteral(secondArg))
|
|
124
|
+
return null;
|
|
125
|
+
if (secondArg.text !== String.raw `\$&`)
|
|
126
|
+
return null;
|
|
127
|
+
// Check context for intentional partial escaping
|
|
128
|
+
const fullText = sourceFile.getFullText();
|
|
129
|
+
const nodeStart = node.getFullStart();
|
|
130
|
+
const nodeEnd = node.getEnd();
|
|
131
|
+
/* v8 ignore next -- defensive non-negative guard */
|
|
132
|
+
const contextStart = Math.max(0, nodeStart - 500);
|
|
133
|
+
const contextText = fullText.slice(contextStart, nodeEnd);
|
|
134
|
+
if (/character class|lucene|search|opensearch|elasticsearch|query/i.test(contextText)) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const regexText = firstArg.text;
|
|
138
|
+
/* v8 ignore next -- defensive AST/type guard */
|
|
139
|
+
if (!regexText)
|
|
140
|
+
return null;
|
|
141
|
+
const missingChars = findMissingChars(regexText);
|
|
142
|
+
if (missingChars.length === 0)
|
|
143
|
+
return null;
|
|
144
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
145
|
+
return {
|
|
146
|
+
line: line + 1,
|
|
147
|
+
column: character + 1,
|
|
148
|
+
message: `Incomplete regex escaping: pattern '${regexText}' is missing special characters: ${missingChars.join(', ')}`,
|
|
149
|
+
severity: 'error',
|
|
150
|
+
type: 'incomplete-escaping',
|
|
151
|
+
suggestion: String.raw `Include all regex special characters in the escape pattern: \\ ^ $ . * + ? ( ) [ ] { } |. Use a library like escape-string-regexp for safety.`,
|
|
152
|
+
match: regexText,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Check: quality/incomplete-regex-escaping
|
|
157
|
+
*
|
|
158
|
+
* Detects incomplete regex character escaping that can lead to security vulnerabilities.
|
|
159
|
+
*/
|
|
160
|
+
export const incompleteRegexEscaping = defineCheck({
|
|
161
|
+
id: '62395bfb-8ece-4c82-a6e2-4150b827ac1f',
|
|
162
|
+
slug: 'incomplete-regex-escaping',
|
|
163
|
+
scope: { languages: ['typescript'], concerns: ['backend', 'frontend', 'cli'] },
|
|
164
|
+
contentFilter: 'raw',
|
|
165
|
+
confidence: 'high',
|
|
166
|
+
description: 'Detect incomplete regex character escaping that can lead to security vulnerabilities',
|
|
167
|
+
longDescription: `**Purpose:** Detects \`.replace()\` calls that use incomplete regex character class escaping, which can lead to regex injection vulnerabilities.
|
|
168
|
+
|
|
169
|
+
**Detects:**
|
|
170
|
+
- \`.replace(regex, '\\\\$&')\` calls where the regex pattern is missing special characters from the set: \`\\\\ ^ $ . * + ? ( ) [ ] { } |\`
|
|
171
|
+
- Uses TypeScript AST to find \`CallExpression\` nodes with \`replace\` property access, a regex literal first argument, and \`'\\\\$&'\` as second argument
|
|
172
|
+
- Skips patterns in Lucene/OpenSearch/Elasticsearch contexts (intentional partial escaping)
|
|
173
|
+
|
|
174
|
+
**Why it matters:** Incomplete regex escaping allows specially crafted input to break out of the intended pattern, enabling regex injection attacks.
|
|
175
|
+
|
|
176
|
+
**Scope:** General best practice. Analyzes each file individually (\`analyze\`). Targets production files.`,
|
|
177
|
+
tags: ['quality', 'security', 'best-practices'],
|
|
178
|
+
fileTypes: ['ts', 'tsx'],
|
|
179
|
+
analyze(content, filePath) {
|
|
180
|
+
// Quick filter: skip files without .replace() calls
|
|
181
|
+
if (!content.includes('.replace(')) {
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
const violations = [];
|
|
185
|
+
try {
|
|
186
|
+
const sourceFile = getSharedSourceFile(filePath, content);
|
|
187
|
+
/* v8 ignore next -- defensive guard */
|
|
188
|
+
if (!sourceFile)
|
|
189
|
+
return [];
|
|
190
|
+
const visit = (node) => {
|
|
191
|
+
if (ts.isCallExpression(node)) {
|
|
192
|
+
const violation = checkReplaceCall(node, sourceFile, filePath);
|
|
193
|
+
if (violation)
|
|
194
|
+
violations.push(violation);
|
|
195
|
+
}
|
|
196
|
+
ts.forEachChild(node, visit);
|
|
197
|
+
};
|
|
198
|
+
visit(sourceFile);
|
|
199
|
+
/* v8 ignore next 1 -- defensive catch: parse failures already handled */
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// @swallow-ok Skip files that fail to parse
|
|
203
|
+
}
|
|
204
|
+
return violations;
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
//# sourceMappingURL=incomplete-regex-escaping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"incomplete-regex-escaping.js","sourceRoot":"","sources":["../../../src/checks/quality/incomplete-regex-escaping.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './api/index.js';
|
|
2
|
+
export * from './code-structure/index.js';
|
|
3
|
+
export * from './data-integrity/index.js';
|
|
4
|
+
export * from './frontend/index.js';
|
|
5
|
+
export * from './incomplete-regex-escaping.js';
|
|
6
|
+
export * from './linting/index.js';
|
|
7
|
+
export * from './observability/index.js';
|
|
8
|
+
export * from './patterns/index.js';
|
|
9
|
+
export * from './stubbed-implementation-detection.js';
|
|
10
|
+
export * from './unused-config-options.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/checks/quality/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uCAAuC,CAAC;AACtD,cAAc,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './api/index.js';
|
|
2
|
+
export * from './code-structure/index.js';
|
|
3
|
+
export * from './data-integrity/index.js';
|
|
4
|
+
export * from './frontend/index.js';
|
|
5
|
+
export * from './incomplete-regex-escaping.js';
|
|
6
|
+
export * from './linting/index.js';
|
|
7
|
+
export * from './observability/index.js';
|
|
8
|
+
export * from './patterns/index.js';
|
|
9
|
+
export * from './stubbed-implementation-detection.js';
|
|
10
|
+
export * from './unused-config-options.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/checks/quality/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uCAAuC,CAAC;AACtD,cAAc,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/linting/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/checks/quality/linting/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TypeScript Frontend Compiler Check
|
|
3
|
+
*
|
|
4
|
+
* Validates TypeScript compilation for frontend apps (apps/*). Runs
|
|
5
|
+
* `tsc --noEmit` in each discovered `apps/<name>/` that has a `tsconfig.json`,
|
|
6
|
+
* and reports the parsed compiler errors. Because it shells out to an external
|
|
7
|
+
* toolchain (one invocation per app, in that app's own directory so its
|
|
8
|
+
* `tsconfig.json` resolves correctly), it is modelled as `analysisMode:'command'`
|
|
9
|
+
* using the same `sh -c` orchestration idiom as `dependency-vulnerability-audit`.
|
|
10
|
+
*/
|
|
11
|
+
import { type CheckViolation } from '@opensip-cli/fitness';
|
|
12
|
+
/**
|
|
13
|
+
* Parse the combined per-app tsc output into violations. Tracks the current app
|
|
14
|
+
* via `::app::` markers and finalizes it on the matching `::exit::` marker: a
|
|
15
|
+
* non-zero exit with parsed diagnostics yields those; a non-zero exit with no
|
|
16
|
+
* parseable diagnostics yields a single generic failure; a zero exit yields none.
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseTscOutput(stdout: string, cwd: string): CheckViolation[];
|
|
19
|
+
/**
|
|
20
|
+
* Check: quality/typescript-frontend
|
|
21
|
+
*
|
|
22
|
+
* Runs the TypeScript compiler for each frontend app under `apps/*`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const typescriptFrontend: import("@opensip-cli/fitness").Check;
|
|
25
|
+
//# sourceMappingURL=typescript-frontend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript-frontend.d.ts","sourceRoot":"","sources":["../../../../src/checks/quality/linting/typescript-frontend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAe,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA6ExE;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CA8C5E;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,sCA6B7B,CAAC"}
|