Skip to content

Conversation

@watsonarw
Copy link

@watsonarw watsonarw commented Dec 20, 2025

Closes #165

Summary

This PR adds Deno support by enabling the node: protocol for Node.js builtin imports in ESM builds. This allows the library to work with Deno without requiring import maps.

Changes

1. Upgrade tsdown to latest version

  • Upgraded tsdown from 0.12.5 to 0.18.1 to access latest features and the updated API

2. Enable node: protocol in ESM output

  • Split tsdown config into separate CJS and ESM configurations
  • Migrated from deprecated removeNodeProtocol option to nodeProtocol option
  • Enabled node: protocol in ESM output while keeping CJS output unchanged
  • Updated minimum Node.js version to 12.20.0 (when node: protocol was introduced)

3. Update source code to use node: prefix

  • Added node: prefix to all Node.js builtin imports in source files (16 imports across 12 files)
  • Aligns source code with ESM output for consistency
  • Provides additional security by preventing builtin package name squatting attacks

Breaking Changes

⚠️ Minimum Node.js version is now 12.20.0 (previously 12.0.0)

This is required to support the node: protocol for builtin imports.

Benefits

  • Works with Deno without import maps
  • Prevents supply chain attacks via builtin name squatting
  • Makes builtin vs third-party imports explicit
  • Follows Node.js best practices and recommendations

Testing

  • The tests aren't currently passing on master... This PR has not changed any functionality, just build outputs and import statements. The same tests failing on master fail on this branch, no new tests are failing. I actually tried fixing the tests, but realised that some might be actual bugs that I'm not familiar enough with the codebase to tackle properly, so I gave up...
  • I've manually compared the output files from npm run build before and after each change.
    • The upgrade to tsdown 0.18.1 resulted in a few non-functional changes to the output files
      • a few single use variables inlined
      • some if statements now have { } blocks where they previously didn't
    • The tsdown config change only added the node: prefix to the built-in imports in the ESM output, nothing else compared to above
    • Updating the imports in the source didn't change the build output (this is just to align the source with the build outputs for consistency).

- Split tsdown config for separate CJS and ESM builds
- Update deprecated removeNodeProtocol option in tsdown config
- Enable node: protocol in ESM output for cross-runtime compatibility
- Bump minimum Node version to v12.20.0 (when node: protocol was added)

This enables Deno support (without import maps) and protects against
builtin package name squatting attacks.

BREAKING CHANGE: Requires Node.js >=12.20.0
tsdown handles the node: protocol in build outputs, but making
source consistent with ESM output will be less confusing
@watsonarw
Copy link
Author

I notice that #151 was proposing bumping the minimum node version to >=16. If you're happy to go to >=16 (which was EOL in Sept 2023), I can amend this to also use the node: prefix for the CJS build. It's a breaking change either way, but only adding the node: prefix for the ESM build might impact less people.

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.

Use node: prefix for built-in module imports to support Deno

1 participant