npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

resolve.imports

v2.0.3

Published

resolve "imports" in package.json

Downloads

54,672

Readme

resolve.imports

NPM version NPM downloads Codecov

Imports field resolver without file-system reliance.

It tracks closely with the implementation in Node.js.

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(
  manifest: ImportsFieldManifest,
  specifier: string,
  options?: { conditions?: string[] }
): string | string[] | undefined
  • manifest is the package.json manifest to resolve the specifier from. It contains:
    • content is the package.json content.
    • path is the optional package.json path. Used for error handling only.
    • base is the optional base path of the import. Used for error handling only.
  • 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 manifest = {
  content: {
    "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"
      }
    }
  },
  // optional
  path: './node_modules/chalk/',
  base: '<cwd>'
}

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

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

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

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

File extensions

File extensions are supported:

import { resolve } from 'resolve.imports';

const manifest = {
  content: {
    imports: {
      '#internal/a.js': './src/internal/a.js'
    }
  }
}


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

Array patterns

import { resolve } from 'resolve.imports';

const manifest = {
  content: {
    imports: {
      '#internal/*.js': ['./src/internal/*.js', './src/internal2/*.js'],
      '#utils/*.js': [{ node: './src/utils/*.js' }, './src/utils2/*.js']
    }
  }
}

//=> './src/internal/foo.js'
resolve(manifest, '#internal/a.js')

//=> './src/utils/foo.js'
resolve(manifest, '#utils/a.js', { conditions: ['node'] })

//=> './src/utils2/foo.js'
resolve(manifest, '#utils/a.js')
import { resolve } from 'resolve.imports';

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

//=> './src/internal/foo.js'
resolve(manifest, '#internal/a.js')

Subpath patterns

Subpath patterns are supported:

import { resolve } from 'resolve.imports';

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

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

Nested conditions

Nested conditions are supported:

import { resolve } from 'resolve.imports';

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

//=> `./feature.mjs`
resolve(manifest, '#feature')

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

Recursive imports

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

import { resolve } from 'resolve.imports';

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

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

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.

References