Skip to content

feat(typescript): support .mts/.cts as TypeScript#310

Open
joptimus wants to merge 1 commit into
repowise-dev:mainfrom
joptimus:feat/mts-typescript-support
Open

feat(typescript): support .mts/.cts as TypeScript#310
joptimus wants to merge 1 commit into
repowise-dev:mainfrom
joptimus:feat/mts-typescript-support

Conversation

@joptimus
Copy link
Copy Markdown
Contributor

What

Index, resolve, and analyze .mts (ESM) and .cts (CommonJS) TypeScript module files as TypeScript instead of skipping them as unknown.

Why

The TypeScript language spec only mapped .ts/.tsx, so .mts/.cts files were detected as unknown and skipped by the indexer (issue #288). .cts is included because it is the paired CommonJS TypeScript module extension and shares the same parser and resolver path.

How

  • Detection/parsing: register .mts/.cts in the TypeScript language spec. They propagate to EXTENSION_TO_LANGUAGE automatically (it is derived from the spec registry) and route to the plain TypeScript grammar; only .tsx needs the JSX variant, so .mts/.cts fall through correctly.
  • Import resolution (all three resolvers): resolve extensionless imports to .mts/.cts, including directory-barrel index.mts/index.cts:
    • relative resolver (resolvers/typescript.py): probe list + /index.mts,/index.cts + the fake-extension fallback loop.
    • tsconfig path-alias resolution (tsconfig_resolver.py): _TS_EXTENSIONS, _INDEX_FILES.
    • workspace exports (resolvers/ts_workspace.py): _PROBE_EXTENSIONS.
  • Test-file classification: once .mts/.cts files are indexed they flow into analysis, so add .test.mts/.spec.cts etc. to every test-classification list to avoid misflagging: dead-code never-flag, health engine._is_test_file and engine._has_paired_test_file, hidden_coupling, coverage detector (_TEST_FILE_SUFFIXES and paired_test_file), and coverage_gap.

Tests

TDD for each layer: language detection, parser smoke tests, all three resolvers (direct + index-barrel, .mts and .cts), dead-code never-flag, and the health classifiers (including the engine paired-test helper for a .mts source). Full affected-area regression: 1136 passed, 2 xfailed.

Out of scope (follow-up)

Framework-edge route detection for module-script extensions (next_app.py, remix.py), and full Node ESM/CJS output-mapping semantics.

This change is Python-only and does not touch packages/web.

Closes #288

Files with the .mts (ESM) and .cts (CommonJS) TypeScript module extensions
were skipped by the indexer because the TypeScript language spec only mapped
.ts/.tsx, so they were detected as unknown (issue repowise-dev#288). .cts is included
because it is the paired CommonJS module extension and shares the parser and
resolver path.

- Register .mts/.cts in the TypeScript language spec; they propagate to
  EXTENSION_TO_LANGUAGE automatically and route to the plain TypeScript grammar
  (only .tsx needs the JSX variant).
- Resolve extensionless imports to .mts/.cts across all three resolvers: the
  relative resolver (probe list, directory-barrel /index.mts and /index.cts,
  and the fake-extension fallback), tsconfig path-alias resolution
  (_TS_EXTENSIONS, _INDEX_FILES), and workspace exports (_PROBE_EXTENSIONS).
- Recognize .mts/.cts test files (.test.mts, .spec.cts, etc.) in every
  test-classification list: dead-code never-flag, health engine _is_test_file
  and _has_paired_test_file, hidden_coupling, coverage detector
  (_TEST_FILE_SUFFIXES and paired_test_file), and coverage_gap.

Out of scope (follow-up): framework-edge route detection for module-script
extensions (next_app, remix), and full Node ESM/CJS output-mapping semantics.

Closes repowise-dev#288
@repowise-bot
Copy link
Copy Markdown

repowise-bot Bot commented May 29, 2026

✅ Health: 7.5 (unchanged)
2 files moved · 5 hotspots · 5 hidden couplings · 1 dead-code finding

File Score Δ Why
.../resolvers/ts_workspace.py 6.6 → 4.5 ▼ -2.1 score drifted on re-parse — no PR-attributable biomarkers
.../resolvers/typescript.py 9.3 → 8.6 ▼ -0.7 nested complexity, complex method

💡 .../resolvers/typescript.py: Flatten the control flow. Pull early-return guards to the top, extract the deepest branch into a helper, and consider replacing nested conditionals with a strategy table or dispatch dict.

🔥 Hotspot touched

  • .../parser/test_typescript.py — 1 commits/90d, 1 dependents · primary owner: Raghav Chamadiya (100%)
  • .../biomarkers/hidden_coupling.py — 1 commits/90d, 2 dependents · primary owner: Raghav Chamadiya (100%)
  • .../health/engine.py — 3 commits/90d, 1 dependents · primary owner: Raghav Chamadiya (100%)
2 more
  • .../ingestion/test_traverser.py — 5 commits/90d, 0 dependents · primary owner: RaghavChamadiya (58%)
  • .../dead_code/constants.py — 8 commits/90d, 1 dependents · primary owner: Raghav Chamadiya (88%)

🔗 Hidden coupling

  • .../dead_code/constants.py co-changes with these files (not in this PR):
    • .../dead_code/analyzer.py (7× — 🟢 routine)
    • .../ingestion/parser.py (5× — 🟢 routine)
  • .../ingestion/test_traverser.py co-changes with .../ingestion/traverser.py (3× — 🟢 routine) — not in this PR.
  • .../health/engine.py co-changes with these files (not in this PR):
    • docs/CODE_HEALTH.md (2× — 🟢 routine)
    • .../biomarkers/README.md (2× — 🟢 routine)

Dead code

  • 💀 .../resolvers/ts_workspace.py get_or_build_workspace_map (confidence 1.00)

👀 Suggested reviewers @RaghavChamadiya


📊 Full report · ⭐ Star Repowise · 📥 Install bot · Last updated 2026-05-29 15:30 UTC
Silence on a single PR with [skip repowise] in the title · Per-repo toggle on repowise.dev/settings?tab=bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] .mts support for Typescript

1 participant