Skip to content

Conversation

@tichopad
Copy link

Summary:

Sets output package.json type to be module when esModule: true is used. This ensures the output package is automatically ESM-compatible.

Also fixes ESM compat for the generated test_runner.js file by polyfilling require and __dirname in an ESM context.

Details:

Users targeting ESM output now have to explicitly add "type": "module" to the build function's configuration. This makes the output ESM compatible, but breaks the generated test runner.

This is potentially a breaking change because of "type": "module" implications in the output package.

Fixes #476

Checks:

  • Tests (deno task test) passing with Node versions 18-24
  • Formatter passing
  • Linter passing
  • CI passing

This change enables ES module compatibility by automatically adding "type": "module" to the generated package.json when ESM output is included. The test runner code has also been updated to handle ES module environments by adding the necessary import statements and compatibility shims.

Key changes:
- Modified package.json generation to include "type": "module" field when includeEsModule is true
- Updated test runner code generation to add ES module compatibility imports (createRequire, __dirname polyfill)
- Updated all test expectations to reflect the new "type": "module" field in generated package.json files

This ensures that generated npm packages work correctly in ES module environments while maintaining backward compatibility.
Comment on lines +15 to +22
if (options.includeEsModule) {
// ensure compatibility with esm ("type": "module")
writer.writeLine(`import { createRequire } from 'module';`);
writer.writeLine(`const require = createRequire(import.meta.url);`);
writer.writeLine(
`const __dirname = new URL(".", import.meta.url).pathname;`,
);
}
Copy link
Author

Choose a reason for hiding this comment

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

I considered polyfilling the safer way to enable ESM compatibility instead of outputting ES modules directly.

Comment on lines +39 to +45
const type = {
...(includeEsModule
? {
type: "module",
}
: {}),
};
Copy link
Author

Choose a reason for hiding this comment

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

Includes "type": "module" if esModule: true, otherwise doesn't add the type field at all.
It also still allows the user to explictly overwrite the type field via the build function's config.

// Copyright 2018-2024 the Deno authors. MIT license.

import { parse } from "jsr:@std/csv/parse";
import { parse } from "jsr:@std/csv@1.0.6/parse";
Copy link
Author

Choose a reason for hiding this comment

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

I added a version specifier to fix a linter error. The version used is based on the latest @std/csv version specified in deno.lock.

"no-explicit-any",
"camelcase"
"camelcase",
"no-import-prefix"
Copy link
Author

Choose a reason for hiding this comment

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

I've run into linter issues with the existing code using inline imports. This rule got added to the default ruleset in Deno 2.5.

My assumption is the project's okay with inline imports, so I decided to exclude the rule instead. Let me know if I should rather refactor inline imports instead.

@tichopad tichopad marked this pull request as ready for review September 20, 2025 11:42
@tichopad
Copy link
Author

tichopad commented Sep 20, 2025

Tests are failing on Windows. Let me take a look later 👍

@tichopad tichopad marked this pull request as draft September 20, 2025 11:57
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.

Output is not compatible with ESM with esModule: true

1 participant