Bare Docs

bare-addon-resolve

Low-level addon resolution algorithm for Bare

Documented against v1.11.0
stable

bare-addon-resolve — Low-level addon resolution algorithm for Bare.

npm i bare-addon-resolve

Usage

For synchronous resolution:

const resolve = require('bare-addon-resolve')

function readPackage(url) {
  // Read and parse `url` if it exists, otherwise `null`
}

for (const resolution of resolve('./addon', new URL('file:///directory/'), readPackage)) {
  console.log(resolution)
}

For asynchronous resolution:

const resolve = require('bare-addon-resolve')

async function readPackage(url) {
  // Read and parse `url` if it exists, otherwise `null`
}

for await (const resolution of resolve('./addon', new URL('file:///directory/'), readPackage)) {
  console.log(resolution)
}

API

Functions

resolve

resolve(specifier: string, parentURL: URL, readPackage?: (url: URL) => JSON | null): Iterable<URL>

Resolve specifier relative to parentURL, which must be a WHATWG URL instance. readPackage is called with a URL instance for every package manifest to be read and must either return the parsed JSON package manifest, if it exists, or null. If readPackage returns a promise, synchronous iteration is not supported. To set options, pass a ResolveOptions object between parentURL and readPackage: resolve(specifier, parentURL, opts, readPackage).

Parameters

ParameterTypeDefaultDescription
specifierstring—The module specifier to resolve.
parentURLURL—The URL to resolve specifier relative to.
readPackage?(url: URL) => JSON | null—Called with the URL of each package manifest encountered; must return the parsed manifest or null. Returning a promise disables synchronous iteration.

Returns Iterable<URL> — Yields candidate resolution URLs for the caller to test, in the order the algorithm tries them.

Throws

  • INVALID_ADDON_SPECIFIER — the specifier is empty, is a scoped name without a /, or has a package name that starts with . or contains \ or %. It is also thrown when parentURL is a file: URL and a relative or absolute specifier contains a percent-encoded / or \ (%2f or %5c, in either case).
  • INVALID_PACKAGE_NAME — a package manifest's name field contains __.

resolve.addon(specifier: string, parentURL: URL, opts?: ResolveOptions): Resolver

One step of the resolution algorithm, exposed for fine-grained use: resolve specifier as an addon — a relative or absolute specifier resolves via resolve.file/resolve.directory, otherwise via resolve.package.

Parameters

ParameterTypeDefaultDescription
specifierstring—The addon specifier to resolve.
parentURLURL—The URL to resolve specifier relative to.
opts?ResolveOptions—Options; see ResolveOptions. If opts.resolutions is set, it is checked first and a matching entry short-circuits the rest of the algorithm, unless the entry is a deferred: URL. A deferred: entry is ignored and resolution continues as if there were no entry. Changed in v1.11.0: a deferred: entry was resolved with the module algorithm, so deferred:. yielded a JavaScript file such as the package's index.js instead of an addon.

Returns Resolver — A Resolver yielding the candidate resolutions.

resolve.directory

resolve.directory(dirname: string, version: string, parentURL: URL, opts?: ResolveOptions): Resolver

Resolve the addon of the package in the directory dirname, relative to parentURL. It reads the package.json in that directory and resolves nothing when there is none, when its name is missing or empty, or when version is set and the manifest has a different version. The addon name is the manifest name with a leading @ removed and every / replaced by __.

It yields candidates in the order of these steps. A builtin match in step 1 ends the resolution. After that, it stops after the first step in which the caller reported a candidate as existing. A step goes through every host before it stops, so several hosts can each resolve to their own prebuild:

  1. A builtin, when the name matches an entry of opts.builtins: builtin:<name>@<version>, or builtin:<name> when neither the package nor the entry has a version. An entry with a version matches only a package with that version, or a package with none. opts.builtinProtocol sets the protocol.
  2. Native prebuilds: prebuilds/<host>/<name>@<version>.<ext> when the package has a version, and prebuilds/<host>/<name>.<ext> when the specifier named none, for each host that does not start with wasi- and each of opts.extensions. For darwin-arm64, darwin-x64, ios-arm64-simulator, and ios-x64-simulator, the same names are also tried with universal in place of the architecture, such as darwin-universal. The prebuilds directory is looked up in dirname and then in each parent directory.
  3. A linked addon, as resolve.linked yields them, unless opts.linked is false.
  4. WebAssembly prebuilds: the same file names as step 2, for each host that starts with wasi-, such as wasi-wasm32. They always use the .wasm extension, whatever opts.extensions is.

Added in v1.11.0: step 4. Before, a wasi- host was looked up like a native one, with opts.extensions, in the same pass as the native hosts and before any linked addon.

const resolve = require('bare-addon-resolve')

function readPackage(url) {
  if (url.href === 'file:///a/package.json') return { name: 'e', version: '1.2.3' }
  return null
}

const options = { hosts: ['linux-x64', 'wasi-wasm32'], extensions: ['.bare'] }

for (const resolution of resolve('.', new URL('file:///a/index.js'), options, readPackage)) {
  console.log(resolution.href)
}
file:///a/prebuilds/linux-x64/e@1.2.3.bare
file:///a/prebuilds/linux-x64/e.bare
file:///prebuilds/linux-x64/e@1.2.3.bare
file:///prebuilds/linux-x64/e.bare
linked:libe.1.2.3.so
linked:libe.so
file:///a/prebuilds/wasi-wasm32/e@1.2.3.wasm
file:///a/prebuilds/wasi-wasm32/e.wasm
file:///prebuilds/wasi-wasm32/e@1.2.3.wasm
file:///prebuilds/wasi-wasm32/e.wasm

A for...of loop reports no candidate as existing, so it lists them all. A caller that drives the generator and passes true back for a candidate that exists stops at the step that resolved, so the WebAssembly candidates are only reached when no native prebuild and no linked addon exists. See the Algorithm section of the README for the full lookup.

Parameters

ParameterTypeDefaultDescription
dirnamestring—The directory of the package, relative to parentURL. It must hold a package.json.
versionstring—The package version, if the specifier carried one, else null.
parentURLURL—The URL to resolve dirname relative to.
opts?ResolveOptions—Options; see ResolveOptions.

Returns Resolver — A Resolver yielding the candidate resolutions.

resolve.file(filename: string, parentURL: URL, opts?: ResolveOptions): Resolver

Resolve filename as a file addon candidate relative to parentURL, trying each of opts.extensions in turn.

Parameters

ParameterTypeDefaultDescription
filenamestring—The file addon candidate, without an extension.
parentURLURL—The URL to resolve filename relative to.
opts?ResolveOptions—Options; extensions lists the candidate extensions to try, in order.

Returns Resolver — A Resolver yielding the candidate resolutions.

resolve.linked(name: string, version?: string, opts?: ResolveOptions): Resolver

Resolve name to a linked: specifier, for runtimes that link addons ahead of time by platform (for example iOS or Android) rather than resolving a prebuild at runtime.

Parameters

ParameterTypeDefaultDescription
namestring—The addon name to resolve to a linked: specifier.
version?string—The addon version, if any.
opts?ResolveOptions—Options; linked must not be false and hosts (or host) must be set, or resolution is skipped. linkedProtocol overrides the 'linked:' prefix.

Returns Resolver — A Resolver yielding the candidate linked: resolutions.

resolve.package

resolve.package(packageSpecifier: string, packageVersion: string, parentURL: URL, opts?: ResolveOptions): Resolver

Resolve packageSpecifier (optionally @packageVersion) as a package name, locating the addon within it.

Parameters

ParameterTypeDefaultDescription
packageSpecifierstring—The package name to resolve the addon within.
packageVersionstring—The package version, if the specifier carried one, else null.
parentURLURL—The URL to resolve the package from.
opts?ResolveOptions—Options; see ResolveOptions.

Returns Resolver — A Resolver yielding the candidate resolutions.

resolve.packageSelf

resolve.packageSelf(packageName: string, packageSubpath: string, packageVersion: string, parentURL: URL, opts?: ResolveOptions): Resolver

Resolve packageSubpath against the package named packageName, for when parentURL lies within that package's own scope — a package requiring its own addon by name.

Parameters

ParameterTypeDefaultDescription
packageNamestring—The package's own name, matched against each candidate scope's manifest.
packageSubpathstring—The addon subpath to resolve within the matching package.
packageVersionstring—The package version, if the specifier carried one, else null.
parentURLURL—A URL within the package's own scope to search upward from.
opts?ResolveOptions—Options; see ResolveOptions.

Returns Resolver — A Resolver yielding the candidate resolutions.

resolve.url(specifier: string, parentURL: URL, opts?: ResolveOptions): Resolver

Resolve specifier as an absolute URL, yielding it as a single candidate.

Parameters

ParameterTypeDefaultDescription
specifierstring—An absolute URL specifier.
parentURLURL—Unused; accepted for a consistent step-function signature.
opts?ResolveOptions—Options; see ResolveOptions.

Returns Resolver — A Resolver yielding the candidate resolution.

Constants and variables

resolve.constants

resolve.constants: {
    UNRESOLVED: number
    YIELDED: number
    RESOLVED: number
  }

The generator status codes yielded by each resolution step: UNRESOLVED, YIELDED, and RESOLVED.

Types

resolve.Resolver

type Resolver = Generator<
    { resolution: URL } | { package: URL },
    number,
    void | boolean | JSON | null
  >

The shared generator type every resolve.* step function returns.

ResolveOptions

interface ResolveOptions {
  builtinProtocol?: string
  builtins?: Builtins
  conditions?: Conditions
  extensions?: string[]
  host?: string
  hosts?: string[]
  linked?: boolean
  linkedProtocol?: string
  matchedConditions?: string[]
  resolutions?: ResolutionsMap
}

hosts lists the <platform>-<arch>[-<environment>] combinations to look for prebuilds under, such as Bare.Addon.host in Bare. host is shorthand for a list of one. Added in v1.11.0: a host that starts with wasi- is a WebAssembly host. It is looked up after the native hosts and linked addons, as .wasm files whatever extensions is. See resolve.directory.

bare-addon-resolve/errors

AddonResolveError

AddonResolveError.INVALID_ADDON_SPECIFIER(msg: string): AddonResolveError

Parameters

ParameterTypeDefaultDescription
msgstring—The error message.

Returns AddonResolveError — A new AddonResolveError with code INVALID_ADDON_SPECIFIER.

AddonResolveError.INVALID_PACKAGE_NAME(msg: string): AddonResolveError

Parameters

ParameterTypeDefaultDescription
msgstring—The error message.

Returns AddonResolveError — A new AddonResolveError with code INVALID_PACKAGE_NAME.

code: string

See also

  • Builds on bare-module-resolve and bare-semver.
  • The resolved addon is the first candidate resolve yields that exists as a file on the file system. Native prebuilds come first, then linked addons, then WebAssembly prebuilds.
  • The resolve.* step functions are subject to change between minor releases; if using them directly, specify a tilde range (for example ~1.11.0) when declaring the module dependency. The README lists the steps of each one.
  • Addons normally resolve through the runtime or are bundled by bare-pack; reach for this module directly only when building tooling on the resolution algorithm itself, such as bare-module-traverse, which uses it to pick a package's WebAssembly build.
  • Bare modules — the full bare-* catalog.
  • Bare runtime API — the runtime these modules extend.

Last updated on

Was this helpful?

On this page