fix(package): resolve extensionless hook subpaths - #1694
Conversation
`@react-hookz/web/useToggle` mapped to `./dist/useToggle`, a directory, so it failed with ERR_UNSUPPORTED_DIR_IMPORT; only the documented `useToggle/index.js` form worked. `./*` now points at the directory's entry file and a new `./*.js` pattern keeps explicit file paths (`useToggle/index.js`, `types.js`, `util/const.js`) resolving as before. `./*/` stays for the trailing-slash form. It triggers DEP0155 on use, but dropping it would break callers that adopted it while the extensionless form was unusable.
The extensionless subpath now resolves, and it is the form consumers reach for first.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1694 +/- ##
=======================================
Coverage 83.19% 83.19%
=======================================
Files 62 62
Lines 839 839
Branches 151 151
=======================================
Hits 698 698
Misses 16 16
Partials 125 125 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR updates @react-hookz/web’s package export map so extensionless hook subpath imports (e.g. @react-hookz/web/useToggle) resolve to the hook directory entry file instead of a directory path, and updates the README to document the shorter import form.
Changes:
- Adjust
package.json#exportsso./*resolves to./dist/*/index.js(fixingERR_UNSUPPORTED_DIR_IMPORTfor extensionless hook imports). - Add a
./*.jsexport pattern to preserve explicit.jsdeep imports (includinguseX/index.jsforms). - Update README direct-import example to use
@react-hookz/web/useMountEffectinstead of the explicit.../index.jspath.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| README.md | Updates docs to show the now-supported extensionless single-hook import. |
| package.json | Fixes subpath export resolution by mapping extensionless subpaths to each hook’s index.js, while preserving explicit .js deep imports. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
🎉 This PR is included in version 26.1.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Fixes the subpath resolution problem found while reviewing #1670.
Problem
"./*": "./dist/*"mapsuseToggleonto a directory, so the natural extensionless specifier has never worked — only theuseToggle/index.jsform the README documented, or theuseToggle/trailing-slash form, which Node warns about:Change
"exports": { ".": "./dist/index.js", "./package.json": "./package.json", - "./*/": "./dist/*/index.js", - "./*": "./dist/*" + "./*.js": "./dist/*.js", + "./*": "./dist/*/index.js", + "./*/": "./dist/*/index.js" }./*now targets the directory's entry file, and./*.jspreserves explicit file paths — its*matches slashes, souseToggle/index.jsstill lands ondist/useToggle/index.js. Exact keys and pattern specificity ordering are handled by Node, not by key order../*/is kept deliberately. It is deprecated, but it is the only form that worked for people who wanted a directory-style import, and dropping it would break them for no gain — it warns only when used.Purely additive: every specifier that resolved before resolves to the same file.
Verification
Packed the tarball, installed it into a scratch consumer with react 19, and resolved each form (Node 26):
@react-hookz/web@react-hookz/web/useToggle@react-hookz/web/useToggle/index.js@react-hookz/web/useMeasure@react-hookz/web/types.js@react-hookz/web/util/const.js@react-hookz/web/package.json@react-hookz/web/useToggle/Types follow the same map —
tscundermoduleResolution: NodeNextacceptsimport {useToggle} from '@react-hookz/web/useToggle'andimport type {Measures} from '@react-hookz/web/useMeasure'against the packed tarball (exit 0).README's direct-import example switches to the short form.