Skip to content

Implement package exports and subpath imports handling #165

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link

@Copilot Copilot AI commented Aug 9, 2025

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.

Copy link
Author

Copilot AI commented Aug 9, 2025

@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 AI and others added 2 commits August 9, 2025 16:38
@Copilot Copilot AI changed the title [WIP] Uncovered cases explored from a project migration Implement package exports and subpath imports handling Aug 9, 2025
@Copilot Copilot AI requested a review from bennycode August 9, 2025 16:41
Copilot finished work on behalf of bennycode August 9, 2025 16:41
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.

Dynamic Imports are not handled
2 participants