system-prompts-and-models-o.../unified-ai-platform/node_modules/resolve.exports/readme.md
dopeuni444 b5a22951ae nhj
more
2025-07-31 12:23:33 +04:00

9.0 KiB
Raw Blame History

resolve.exports CI licenses codecov

A tiny (952b), correct, general-purpose, and configurable "exports" and "imports" resolver without file-system reliance

Why?

Hopefully, this module may serve as a reference point (and/or be used directly) so that the varying tools and bundlers within the ecosystem can share a common approach with one another as well as with the native Node.js implementation.

With the push for ESM, we must be very careful and avoid fragmentation. If we, as a community, begin propagating different dialects of the resolution algorithm, then we're headed for deep trouble. It will make supporting (and using) "exports" nearly impossible, which may force its abandonment and along with it, its benefits.

Let's have nice things.

Install

$ npm install resolve.exports

Usage

Please see /test/ for examples.

import * as resolve from 'resolve.exports';

// package.json contents
const pkg = {
  "name": "foobar",
  "module": "dist/module.mjs",
  "main": "dist/require.js",
  "imports": {
    "#hash": {
      "import": {
        "browser": "./hash/web.mjs",
        "node": "./hash/node.mjs",
      },
      "default": "./hash/detect.js"
    }
  },
  "exports": {
    ".": {
      "import": "./dist/module.mjs",
      "require": "./dist/require.js"
    },
    "./lite": {
      "worker": {
        "browser": "./lite/worker.browser.js",
        "node": "./lite/worker.node.js"
      },
      "import": "./lite/module.mjs",
      "require": "./lite/require.js"
    }
  }
};

// ---
// Exports
// ---

// entry: "foobar" === "." === default
// conditions: ["default", "import", "node"]
resolve.exports(pkg);
resolve.exports(pkg, '.');
resolve.exports(pkg, 'foobar');
//=> ["./dist/module.mjs"]

// entry: "foobar/lite" === "./lite"
// conditions: ["default", "import", "node"]
resolve.exports(pkg, 'foobar/lite');
resolve.exports(pkg, './lite');
//=> ["./lite/module.mjs"]

// Enable `require` condition
// conditions: ["default", "require", "node"]
resolve.exports(pkg, 'foobar', { require: true }); //=> ["./dist/require.js"]
resolve.exports(pkg, './lite', { require: true }); //=> ["./lite/require.js"]

// Throws "Missing <entry> specifier in <name> package" Error
resolve.exports(pkg, 'foobar/hello');
resolve.exports(pkg, './hello/world');

// Add custom condition(s)
// conditions: ["default", "worker", "import", "node"]
resolve.exports(pkg, 'foobar/lite', {
  conditions: ['worker']
}); //=> ["./lite/worker.node.js"]

// Toggle "browser" condition
// conditions: ["default", "worker", "import", "browser"]
resolve.exports(pkg, 'foobar/lite', {
  conditions: ['worker'],
  browser: true
}); //=> ["./lite/worker.browser.js"]

// Disable non-"default" condition activate
// NOTE: breaks from Node.js default behavior
// conditions: ["default", "custom"]
resolve.exports(pkg, 'foobar/lite', {
  conditions: ['custom'],
  unsafe: true,
});
//=> Error: No known conditions for "./lite" specifier in "foobar" package

// ---
// Imports
// ---

// conditions: ["default", "import", "node"]
resolve.imports(pkg, '#hash');
resolve.imports(pkg, 'foobar/#hash');
//=> ["./hash/node.mjs"]

// conditions: ["default", "import", "browser"]
resolve.imports(pkg, '#hash', { browser: true });
resolve.imports(pkg, 'foobar/#hash');
//=> ["./hash/web.mjs"]

// conditions: ["default"]
resolve.imports(pkg, '#hash', { unsafe: true });
resolve.imports(pkg, 'foobar/#hash');
//=> ["./hash/detect.mjs"]

resolve.imports(pkg, '#hello/world');
resolve.imports(pkg, 'foobar/#hello/world');
//=> Error: Missing "#hello/world" specifier in "foobar" package

// ---
// Legacy
// ---

// prefer "module" > "main" (default)
resolve.legacy(pkg); //=> "dist/module.mjs"

// customize fields order
resolve.legacy(pkg, {
  fields: ['main', 'module']
}); //=> "dist/require.js"

API

The resolve(), exports(), and imports() functions share similar API signatures:

export function resolve(pkg: Package, entry?: string, options?: Options): string[] | undefined;
export function exports(pkg: Package, entry?: string, options?: Options): string[] | undefined;
export function imports(pkg: Package, target: string, options?: Options): string[] | undefined;
//                                         ^ not optional!

All three:

  • accept a package.json file's contents as a JSON object
  • accept a target/entry identifier
  • may accept an Options object
  • return string[], string, or undefined

The only difference is that imports() must accept a target identifier as there can be no inferred default.

See below for further API descriptions.

Note: There is also a Legacy Resolver API


resolve(pkg, entry?, options?)

Returns: string[] or undefined

A convenience helper which automatically reroutes to exports() or imports() depending on the entry value.

When unspecified, entry defaults to the "." identifier, which means that exports() will be invoked.

import * as r from 'resolve.exports';

let pkg = {
  name: 'foobar',
  // ...
};

r.resolve(pkg);
//~> r.exports(pkg, '.');

r.resolve(pkg, 'foobar');
//~> r.exports(pkg, '.');

r.resolve(pkg, 'foobar/subpath');
//~> r.exports(pkg, './subpath');

r.resolve(pkg, '#hash/md5');
//~> r.imports(pkg, '#hash/md5');

r.resolve(pkg, 'foobar/#hash/md5');
//~> r.imports(pkg, '#hash/md5');

exports(pkg, entry?, options?)

Returns: string[] or undefined

Traverse the "exports" within the contents of a package.json file.
If the contents does not contain an "exports" map, then undefined will be returned.

Successful resolutions will always result in a string or string[] value. This will be the value of the resolved mapping itself which means that the output is a relative file path.

This function may throw an Error if:

  • the requested entry cannot be resolved (aka, not defined in the "exports" map)
  • an entry is defined but no known conditions were matched (see options.conditions)

pkg

Type: object
Required: true

The package.json contents.

entry

Type: string
Required: false
Default: . (aka, root)

The desired target entry, or the original import path.

When entry is not a relative path (aka, does not start with '.'), then entry is given the './' prefix.

When entry begins with the package name (determined via the pkg.name value), then entry is truncated and made relative.

When entry is already relative, it is accepted as is.

Examples

Assume we have a module named "foobar" and whose pkg contains "name": "foobar".

entry value treated as reason
null / undefined '.' default
'.' '.' value was relative
'foobar' '.' value was pkg.name
'foobar/lite' './lite' value had pkg.name prefix
'./lite' './lite' value was relative
'lite' './lite' value was not relative & did not have pkg.name prefix

imports(pkg, target, options?)

Returns: string[] or undefined

Traverse the "imports" within the contents of a package.json file.
If the contents does not contain an "imports" map, then undefined will be returned.

Successful resolutions will always result in a string or string[] value. This will be the value of the resolved mapping itself which means that the output is a relative file path.

This function may throw an Error if:

  • the requested target cannot be resolved (aka, not defined in the "imports" map)
  • an target is defined but no known conditions were matched (see options.conditions)

pkg

Type: object
Required: true

The package.json contents.

target

Type: string
Required: true

The target import identifier; for example, #hash or #hash/md5.

Import specifiers must begin with the # character, as required by the resolution specification. However, if target begins with the package name (determined by the pkg.name value), then resolve.exports will trim it from the target identifier. For example, "foobar/#hash/md5" will be treated as "#hash/md5" for the "foobar" package.

Options

The resolve(), imports(), and exports() functions share these options. All properties are optional and you are not required to pass an options argument.

Collectively, the options are used to assemble a list of conditions that should be activated while resolving your