Skip to content

feat: add exports field to package.json for ESM subpath resolution#483

Merged
megahertz merged 3 commits into
megahertz:masterfrom
kucheruk:feat/exports-field
May 13, 2026
Merged

feat: add exports field to package.json for ESM subpath resolution#483
megahertz merged 3 commits into
megahertz:masterfrom
kucheruk:feat/exports-field

Conversation

@kucheruk

Copy link
Copy Markdown
Contributor

Summary

Adds an exports field to package.json so that ESM consumers can use the documented bare subpath imports (electron-log/main, electron-log/renderer, electron-log/preload, electron-log/node) without having to append .js.

Closes #482.

Why

electron-log@5.4.3 does not declare an exports field. Node's ESM resolver does not auto-append .js for subpath imports, so projects with "type": "module" (e.g. Electron apps bundled by electron-vite after Electron 28+ ESM support) currently have to write electron-log/main.js, contradicting the README and the shipped .d.ts files. Without .js, resolution fails with ERR_MODULE_NOT_FOUND only in production bundles, which is a confusing footgun.

What changed

Only package.json:

"exports": {
  ".":           { "types": "./src/index.d.ts", "default": "./src/index.js" },
  "./main":      { "types": "./main.d.ts",      "import": "./main.js",     "require": "./main.js" },
  "./renderer":  { "types": "./renderer.d.ts",  "import": "./renderer.js", "require": "./renderer.js" },
  "./preload":   {                              "import": "./preload.js",  "require": "./preload.js" },
  "./node":      { "types": "./node.d.ts",      "import": "./node.js",     "require": "./node.js" },
  "./package.json": "./package.json"
}
  • main / browser fields are left in place for legacy resolution paths.
  • Both import and require conditions map to the same file (the package is CJS at the implementation level), so this is purely additive — no breaking change for existing CJS users.
  • ./package.json is exported because Node's package self-reference rules become strict once exports is present, and downstream tooling sometimes wants to read it.

Verification

Locally I npm install'd the patched package into a fresh ESM project ("type": "module", Node 24) and reran the repro from #482:

# Before this change:
$ node --input-type=module -e "import log from 'electron-log/main'"
ERR_MODULE_NOT_FOUND

# After this change:
$ node --input-type=module -e "import log from 'electron-log/main'; console.log(typeof log)"
# resolves OK (the only error is the missing 'electron' peer dep at runtime,
# which is expected outside an Electron context — resolution itself succeeds)

CJS continued to work for require('electron-log'), require('electron-log/preload'), require('electron-log/node').

I have not run npm run test:full because the e2e suite requires Electron and a display; happy to do so or to adjust the exports shape if you prefer different conditions.

Notes

  • No source changes.
  • No public-API change for current consumers.
  • Lets downstream projects drop their .js workaround in subpath imports.

kucheruk and others added 2 commits May 12, 2026 17:10
Without an exports field, Node's ESM resolver does not auto-append .js to
subpath imports. Consumers with "type": "module" had to write
'electron-log/main.js' instead of 'electron-log/main' (as the README and
.d.ts files imply) or hit ERR_MODULE_NOT_FOUND at production resolve time.

Adding a minimal exports map mirrors the existing top-level entry files
(main, renderer, preload, node) plus the root entry and package.json,
keeping both 'import' and 'require' conditions to preserve CJS behavior.
Existing main/browser fields are left intact for legacy resolution paths.

Refs: #482

Copilot AI left a comment

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.

Pull request overview

Adds an exports map to package.json to make the documented ESM bare subpath imports (e.g. electron-log/main) resolvable without requiring consumers to append .js, addressing ESM resolution behavior in Node/Electron tooling.

Changes:

  • Added exports entries for the package root (".") and documented subpath entry points (./main, ./renderer, ./preload, ./node).
  • Added a wildcard subpath export ("./*": "./*") to permit arbitrary subpath access under exports.
Comments suppressed due to low confidence (1)

package.json:58

  • The PR description/issue proposal mentions explicitly exporting ./package.json and using import/require conditions for subpaths, but the actual exports map here adds a ./* wildcard and doesn’t include an explicit ./package.json entry. Please align the implementation with the described shape (or update the PR description) so the intended compatibility surface is unambiguous.
    "./*": "./*",
    "./main": {
      "types": "./main.d.ts",
      "default": "./main.js"
    },

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread package.json
Comment thread package.json
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@megahertz megahertz merged commit 73319b4 into megahertz:master May 13, 2026
@megahertz

Copy link
Copy Markdown
Owner

Thank you!

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.

Add exports field to package.json for ESM subpath resolution

3 participants