Deviopath › Node.js

package.json "exports" Resolution

Hard · Modules

Modern packages decide which files can be imported through the "exports" field in package.json, with different files for import and require. Implement how Node.js resolves it (PACKAGE_EXPORTS_RESOLVE in the Node ESM docs).

resolveExport(pkg, specifier, conditions): pkg is { name, exports }, specifier looks like "pkg", "pkg/utils" or "@scope/pkg/a/b", and conditions lists the active conditions (like ["node", "import"]). Return the target path (like "./dist/index.js"), or throw an error with a code.

- The package name is the first segment, or the first two for scoped names (@scope/pkg). The subpath is "." plus the rest: "pkg" gives ".", "pkg/utils" gives "./utils".

- If exports is an object mixing keys that start with . and keys that do not, throw ERR_INVALID_PACKAGE_CONFIG.

- Subpath ".": the main export is exports itself if it is a string or an object without . keys (only conditions), otherwise exports["."].

- Other subpaths (only if the keys start with .): an exact key without * wins. Otherwise try the keys containing one *, most specific first: the longer part before * first, then the longer key. A key matches if the subpath starts with the part before *, ends with the part after *, and at least one character is left in between. The text in between replaces every * in the target (it may contain /).

- Resolving a target: a string must start with ./ (else ERR_INVALID_PACKAGE_TARGET). null means blocked. An object is a set of conditions: go through its keys in object order and take the first key that is "default" or in conditions, resolving its value the same way (conditions can be nested). If that value resolves to nothing (a nested condition object where no key matched), continue with the next key. A null value stops the search (blocked).

- If nothing resolves (no matching key, null, or no condition matched), throw ERR_PACKAGE_PATH_NOT_EXPORTED.

Array targets are not used here. The driver resolveAll(pkg, specifiers, conditions) returns the target or the error code for each specifier.

Next: In-Memory REST API