ts2esm icon indicating copy to clipboard operation
ts2esm copied to clipboard

Implement package exports and subpath imports handling

Open Copilot opened this issue 5 months ago • 1 comments

This PR implements smart handling of package exports and subpath imports to distinguish between legacy packages that need .js extensions and modern packages with exports field that should remain unchanged.

Problem

The current implementation adds .js extensions to all node_modules imports, but this doesn't work correctly for modern packages that use the exports field in their package.json. This causes issues where:

  • Legacy packages (like lodash) need .js extensions: 'lodash/omit''lodash/omit.js'
  • Modern packages (like firebase-functions) should remain unchanged: 'firebase-functions/v1/https' (already works correctly in ESM)

Solution

Added intelligent package detection that checks if a node_modules package has an exports field:

// Before: All packages got .js extensions
import omit from 'lodash/omit';           // → 'lodash/omit.js' (correct)
import {HttpsError} from 'firebase-functions/v1/https'; // → 'firebase-functions/v1/https.js' (incorrect!)

// After: Smart detection based on package.json exports field
import omit from 'lodash/omit';           // → 'lodash/omit.js' (legacy package)
import {HttpsError} from 'firebase-functions/v1/https'; // → unchanged (modern package)

Key Changes

  1. Added hasPackageExports() utility in PathUtil.ts that safely reads and parses package.json files to detect the exports field
  2. Enhanced replaceModulePath.ts to check package exports before adding file extensions
  3. Added support for scoped packages with proper parsing of package names like @types/node
  4. Comprehensive test coverage including mock packages for both scenarios

Testing

  • All existing tests continue to pass
  • New test fixture with realistic mock packages (lodash as legacy, firebase-functions as modern)
  • Manual validation confirms correct behavior for both package types
  • Added unit tests for new utility functions

This change maintains full backward compatibility while fixing the issue with modern packages that use the exports field.

Fixes #129.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot avatar Aug 09 '25 16:08 Copilot

@bennycode 👋 This repository doesn't have Copilot instructions. With Copilot instructions, I can understand the repository better, work faster and produce higher quality PRs.

I can generate a .github/copilot-instructions.md file for you automatically. Click here to open a pre-filled issue and assign it to me. I'll write the instructions, and then tag you for review.

Copilot avatar Aug 09 '25 16:08 Copilot