Skip to content

fix: Add .js extensions to relative imports in ESM TypeScript projects#1957

Merged
Saga4 merged 1 commit intomainfrom
fix/esm-relative-import-extensions
Apr 2, 2026
Merged

fix: Add .js extensions to relative imports in ESM TypeScript projects#1957
Saga4 merged 1 commit intomainfrom
fix/esm-relative-import-extensions

Conversation

@mohammedahmed18
Copy link
Copy Markdown
Contributor

Summary

  • Fixes ERR_MODULE_NOT_FOUND errors in generated tests for ESM TypeScript projects
  • Adds .js extensions to relative imports (e.g., ./module./module.js)
  • Only affects ESM projects; CommonJS projects unchanged

Problem

Generated tests were importing from relative paths without .js extensions:

import TreeNode from '../../injector/topology-tree/tree-node';

This causes ERR_MODULE_NOT_FOUND in Node.js ESM, which requires explicit extensions for relative imports, even when source files are .ts.

Solution

Added add_js_extensions_to_relative_imports() function that:

  • Adds .js to relative imports without extensions
  • Preserves imports with existing extensions
  • Leaves node_modules imports unchanged
  • Integrated into test generation pipeline (ESM projects only)

Test Plan

  • Added 7 unit tests for the new function
  • All 35 module_system tests pass
  • All 315 JavaScript language tests pass
  • Manually verified fix resolves the issue for trace 17751b8f-fa61-48bc-bdee-b924f0c7afc4

Affected Trace IDs

17751b8f-fa61-48bc-bdee-b924f0c7afc4, 3b985200-a906-4c54-a685-df40361d6b2c, 91795877-3ccf-482c-86bd-748834b76f6e, 0298c59c-8980-4aed-b05d-b94940a6544f, ec2864a4-0de0-4ce9-9ec8-b545c82a4f53

🤖 Generated with Claude Code

## Problem
Generated tests for ESM TypeScript projects were importing from relative
paths without .js extensions (e.g., `import X from './module'`), causing
ERR_MODULE_NOT_FOUND errors when tests run.

Node.js ESM requires explicit .js extensions for relative imports, even
when the source files are .ts. This is a TypeScript/ESM specification
requirement.

## Solution
Added `add_js_extensions_to_relative_imports()` function that:
- Adds .js extensions to relative imports (./x or ../x) without extensions
- Preserves imports that already have extensions (.js, .ts, etc.)
- Leaves non-relative imports (node modules) unchanged
- Only runs for ESM projects (CommonJS doesn't need extensions)

Integrated into test processing pipeline after module system conversion.

## Testing
- Added 7 unit tests covering various import patterns
- All 35 module_system tests pass
- All 315 JavaScript language tests pass
- Verified fix resolves ERR_MODULE_NOT_FOUND for trace 17751b8f-fa61-48bc-bdee-b924f0c7afc4

## References
Trace IDs with this issue: 17751b8f-fa61-48bc-bdee-b924f0c7afc4,
3b985200-a906-4c54-a685-df40361d6b2c, 91795877-3ccf-482c-86bd-748834b76f6e,
0298c59c-8980-4aed-b05d-b94940a6544f, ec2864a4-0de0-4ce9-9ec8-b545c82a4f53

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Codeflash Bot seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Apr 1, 2026

Claude finished @mohammedahmed18's task in 5m 31s —— View job


PR Review Summary

  • Triage: LARGE (59 lines of production code)
  • Lint and typecheck: prek passes; mypy errors are pre-existing (unrelated to this PR)
  • Stale threads: none
  • Code review
  • Duplicate detection
  • Optimization PRs evaluated

Prek Checks

All ruff checks pass. No issues to fix.

Code Review

Regex misses import type syntax (medium)

import type { Foo } from './module' is a common TypeScript pattern. The regex's (?:\w+) alternative matches type as a default import name, but then \s+from\s+ fails to match since { Foo } from follows — so these imports never get .js added.

module_system.py:546 — the pattern could be extended:

# Before
r"(import\s+(?:(?:\{[^}]*\})|(?:\*\s+as\s+\w+)|(?:\w+))\s+from\s+)..."
# After
r"(import\s+(?:type\s+)?(?:(?:\{[^}]*\})|(?:\*\s+as\s+\w+)|(?:\w+))\s+from\s+)..."

Fix this →

Mixed default+named imports not matched (low)

import Default, { named } from './module' won't get .js added. Less common in generated tests but a gap worth noting.

Inconsistent import placement in support.py (low)

ModuleSystem is added to the existing from codeflash.languages.javascript.module_system import (...) block, but add_js_extensions_to_relative_imports is imported separately inside the if block at line ~2040. Both should be in the same import statement.
Fix this →

Docstrings on new functions (low)

add_js_extensions_to_relative_imports and the inner add_extension both have docstrings. Per project conventions (CLAUDE.md): "Do not add docstrings to new or changed code unless the user explicitly asks for them."

Duplicate Detection

import_resolver.py has extension-related logic but it resolves file paths on disk, not import strings. No duplicates detected.

Test Coverage

7 new unit tests added and all pass. Missing coverage for:

  • import type { Foo } from './module' (the regex gap above)
  • import Default, { named } from './module' (mixed imports)

Optimization PRs


Last updated: 2026-04-01

return "\n".join(lines)


def add_js_extensions_to_relative_imports(code: str) -> str:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is existing, the question remains that we are not following some conviction on function name and claude code end up creating the same functions quickly in some other helper file than searching for existing logics

@Saga4 Saga4 merged commit 857673d into main Apr 2, 2026
30 of 34 checks passed
@Saga4 Saga4 deleted the fix/esm-relative-import-extensions branch April 2, 2026 08:39
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.

3 participants