JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 13965
  • Score
    100M100P100Q138188F
  • License MIT

resolve "imports" in package.json

Package Exports

  • resolve.imports
  • resolve.imports/package.json

Readme

resolve.imports

NPM version NPM downloads Codecov

Imports field resolver without file-system reliance.

It uses a new logic differs from resolve.exports which also handles:

This is used by @repobuddy/jest to resolve ESM packages correctly.

Install

# npm
npm install resolve.imports

# yarn
yarn add resolve.imports

# pnpm
pnpm add resolve.imports

# rush
rush add -p resolve.imports

Usage

Here is the API:

resolve(
  pjson: Record<string, unknown>,
  specifier: string,
  options?: { conditions?: string[] }
): string | string[] | undefined
  • pjson is the package.json object.
  • specifier is the entry to resolve.
  • options is optional. It contains:

It returns either a string, string[] (for array patterns) or undefined.

Subpath imports

Subpath imports are supported (the main purpose of this package):

Using chalk as an example:

import { resolve } from 'resolve.imports';

const chalkPackageJson = {
  "imports": {
    "#ansi-styles": "./source/vendor/ansi-styles/index.js",
    "#supports-color": {
      "node": "./source/vendor/supports-color/index.js",
      "default": "./source/vendor/supports-color/browser.js"
    }
  }
}

//=> `./source/vendor/ansi-styles/index.js`
resolve(chalkPackageJson, '#ansi-styles')

//=> `./source/vendor/supports-color/browser.js`
resolve(chalkPackageJson, '#supports-color')

//=> `./source/vendor/supports-color/index.js`
resolve(chalkPackageJson, '#supports-color', { conditions: ['node'] })

//=> `./source/vendor/supports-color/browser.js`
resolve(chalkPackageJson, '#supports-color', { conditions: ['default'] })

File extensions

File extensions are supported:

import { resolve } from 'resolve.imports';

const pjson = {
  imports: {
    '#internal/a.js': './src/internal/a.js',
}

resolve(pjson, '#internal/a.js') //=> `./src/internal/a.js`

Array patterns

import { resolve } from 'resolve.imports';

const pjson = {
  imports: {
    '#internal/*.js': ['./src/internal/*.js', './src/internal2/*.js']
}

resolve(pjson, '#internal/a.js') //=> ['./src/internal/foo.js', './src/internal2/foo.js']

Subpath patterns

Subpath patterns are supported:

import { resolve } from 'resolve.imports';

const pjson = {
  "imports": {
    "#internal/*.js": "./src/internal/*.js"
  }
}

resolve(pjson, '#internal/foo.js') //=> `./src/internal/foo.js`

Nested conditions

Nested conditions are supported:

import { resolve } from 'resolve.imports';

const pjson = {
  "imports": {
    '#feature': {
      "node": {
        "import": "./feature-node.mjs",
        "require": "./feature-node.cjs"
      },
      "default": "./feature.mjs"
    }
  }
}

resolve(pjson, '#feature') //=> `./feature.mjs`
resolve(pjson, '#feature', { conditions: ['node', 'import']}) //=> `./feature-node.mjs`

Recursive imports

Resolving recursive imports is not supported. i.e. the following does not work:

import { resolve } from 'resolve.imports';

const pjson = {
  "imports": {
    "#internal/*.js": "#another-internal/*.js",
    "#another-internal/*.js": "./src/path/*.js"
  }
}

resolve(pjson, '#internal/foo.js') //=> undefined

It is not supported because the spec does not support it. See resolver algorithm for more information.

Resolve Algorithm Specification

This module tries to follow the resolver algorithm as much as possible.

However, the spec describes the internal functions implementation instead of the abstract behavior. So some of the spec does not apply to this module.

Here are the key notes:

  • asserts are not checked, as this module needs to return undefined for other cases.
  • errors are not thrown, as the errors in the spec are internal to Node.js. undefined is returned instead.

PACKAGE_IMPORTS_RESOLVE

1. Assert: specifier begins with "#". // return `undefined`
2. If specifier is exactly equal to "#" or starts with "#/", then
  1. Throw an Invalid Module Specifier error. // return `undefined`
5. Throw a Package Import Not Defined error. // out of scope

PACKAGE_TARGET_RESOLVE

Return PACKAGE_RESOLVE(target with every instance of "*" replaced by patternMatch, packageURL + "/").

The phrase target with every instance of "*" replaced by patternMatch indicates it can contain multiple *s. This module supports multiple *s in the replacer pattern as described, but it is likely a bug in the spec, as the resulting string likely does not make sense.

PATTERN_KEY_COMPARE

Assert: keyA/B ends with "/" or contains only a single "*"

This is not correct as it supports file extensions (e.g. #a/b.js)

References