Skip to content

module: support pattern trailers

This implements an extension to exports (and imports) patterns to support LHS matches consisting of trailing strings.

The use case for this came out of discussion with @ljharb, in order to support packages that want to provide "exports" support while enabling subpaths that can support both extensioned and unextensioned forms.

For example, with this PR, the following exports field can be used to expose a features folder with optional extensions:

{
  "exports": {
    "./features/*": "./features/*.js",
    "./features/*.js": "./features/*.js"
  }
}

While we would still encourage package authors to decide on a single pattern, often packages don't have a choice when backwards compatibility is required, so this can also allow for smoother interface transitions if deprecating one or the other pattern as well.

This was left out of the initial implementation to keep the initial implementation as simple as possible. Most of the work is just clearly defining pattern specificity and handling edge cases.

This PR also refines the following edge cases:

  1. Trailing "/" exports that resolve to files will now give the trailing "/" deprecation warning.
  2. Given the two exports keys "./x/" and "./x*", the second pattern will take precedence over the path for resolving ./x/y according to the specificity rules.
  3. Multiple * can't be matched in patterns, so given "exports": { "./*/*.js": "./*.js" } this will no longer match import './*/x.js' and instead throw an unexported error. It is of course possible to resolve a * as part of the user specifier component, it just won't be supported as a string character in exports.

Merge request reports

Loading