Socket
Socket
Sign inDemoInstall

load-plugin

Package Overview
Dependencies
42
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.1.0 to 6.0.0

lib/index.d.ts

44

index.d.ts

@@ -1,40 +0,4 @@

/**
* Load the plugin found using `resolvePlugin`.
*
* @param {string} name The name to import.
* @param {LoadOptions} [options]
* @returns {Promise<unknown>}
*/
export function loadPlugin(
name: string,
options?: LoadOptions | undefined
): Promise<unknown>
/**
* Find a plugin.
*
* See also:
* * https://docs.npmjs.com/files/folders#node-modules
* * https://github.com/sindresorhus/resolve-from
*
* Uses the standard node module loading strategy to find `$name` in each given
* `cwd` (and optionally the global `node_modules` directory).
*
* If a prefix is given and `$name` is not a path, `$prefix-$name` is also
* searched (preferring these over non-prefixed modules).
*
* @param {string} name
* @param {ResolveOptions} [options]
* @returns {Promise<string>}
*/
export function resolvePlugin(
name: string,
options?: ResolveOptions | undefined
): Promise<string>
export type ResolveOptions = {
prefix?: string | undefined
cwd?: string | string[] | undefined
global?: boolean | undefined
}
export type LoadOptions = ResolveOptions & {
key?: string | false
}
export type LoadOptions = import('./lib/index.js').LoadOptions;
export type ResolveOptions = import('./lib/index.js').ResolveOptions;
export { loadPlugin, resolvePlugin } from "./lib/index.js";
//# sourceMappingURL=index.d.ts.map
/**
* @typedef ResolveOptions
* @property {string} [prefix]
* @property {string|Array<string>} [cwd]
* @property {boolean} [global]
*
* @typedef {ResolveOptions & {key?: string|false}} LoadOptions
* @typedef {import('./lib/index.js').LoadOptions} LoadOptions
* @typedef {import('./lib/index.js').ResolveOptions} ResolveOptions
*/
import fs from 'fs'
import process from 'process'
import {pathToFileURL, fileURLToPath} from 'url'
import path from 'path'
// @ts-expect-error: untyped
import NpmConfig from '@npmcli/config'
import {resolve as esmResolve} from 'import-meta-resolve'
const electron = process.versions.electron !== undefined
const windows = process.platform === 'win32'
const argv = process.argv[1] || /* c8 ignore next */ ''
const nvm = process.env.NVM_BIN
/* c8 ignore next */
const globalsLibrary = windows ? '' : 'lib'
const config = new NpmConfig({definitions: {}})
config.loadGlobalPrefix()
/** @type {string} */
let npmPrefix = config.globalPrefix
// If there is no prefix defined, use the defaults
// See: <https://github.com/eush77/npm-prefix/blob/master/index.js>
/* c8 ignore next 5 */
if (!npmPrefix) {
npmPrefix = windows
? path.dirname(process.execPath)
: path.resolve(process.execPath, '../..')
}
const globalsDefault = electron || argv.indexOf(npmPrefix) === 0
let globalDir = path.resolve(npmPrefix, globalsLibrary, 'node_modules')
// If we’re in Electron, we’re running in a modified Node that cannot really
// install global node modules.
// To find the actual modules, the user has to set `prefix` somewhere in an
// `.npmrc` (which is picked up by `libnpmconfig`).
// Most people don’t do that, and some use NVM instead to manage different
// versions of Node.
// Luckily NVM leaks some environment variables that we can pick up on to try
// and detect the actual modules.
/* c8 ignore next 3 */
if (electron && nvm && !fs.existsSync(globalDir)) {
globalDir = path.resolve(nvm, '..', globalsLibrary, 'node_modules')
}
/**
* Load the plugin found using `resolvePlugin`.
*
* @param {string} name The name to import.
* @param {LoadOptions} [options]
* @returns {Promise<unknown>}
*/
export async function loadPlugin(name, options = {}) {
const {key = 'default', ...rest} = options
const fp = await resolvePlugin(name, rest)
/** @type {Record<string, unknown>} */
// Bug with coverage on Node@12.
/* c8 ignore next 3 */
const mod = await import(pathToFileURL(fp).href)
return key === false ? mod : mod[key]
}
/**
* Find a plugin.
*
* See also:
* * https://docs.npmjs.com/files/folders#node-modules
* * https://github.com/sindresorhus/resolve-from
*
* Uses the standard node module loading strategy to find `$name` in each given
* `cwd` (and optionally the global `node_modules` directory).
*
* If a prefix is given and `$name` is not a path, `$prefix-$name` is also
* searched (preferring these over non-prefixed modules).
*
* @param {string} name
* @param {ResolveOptions} [options]
* @returns {Promise<string>}
*/
export async function resolvePlugin(name, options = {}) {
const prefix = options.prefix
? options.prefix +
(options.prefix.charAt(options.prefix.length - 1) === '-' ? '' : '-')
: undefined
const cwd = options.cwd
const globals =
options.global === undefined || options.global === null
? globalsDefault
: options.global
const sources = Array.isArray(cwd) ? cwd.concat() : [cwd || process.cwd()]
/** @type {string|undefined} */
let plugin
/** @type {Error|undefined} */
let lastError
// Non-path.
if (name.charAt(0) !== '.') {
if (globals) {
sources.push(globalDir)
}
let scope = ''
// Unprefix module.
if (prefix) {
// Scope?
if (name.charAt(0) === '@') {
const slash = name.indexOf('/')
// Let’s keep the algorithm simple.
// No need to care if this is a “valid” scope (I think?).
// But we do check for the slash.
if (slash !== -1) {
scope = name.slice(0, slash + 1)
name = name.slice(slash + 1)
}
}
if (name.slice(0, prefix.length) !== prefix) {
plugin = scope + prefix + name
}
name = scope + name
}
}
let index = -1
/** @type {string|undefined} */
let fp
while (++index < sources.length) {
fp = plugin ? await attempt(sources[index], plugin) : undefined
if (fp) return fp
fp = await attempt(sources[index], name)
if (fp) return fp
}
// There’s always an error.
// Bug with coverage on Node@12.
/* c8 ignore next 8 */
throw lastError
/**
* @param {string} base
* @param {string} name
* @returns {Promise<string|undefined>}
*/
async function attempt(base, name) {
try {
// `import-meta-resolve` resolves from files, whereas `load-plugin` works
// on folders, which is why we add a `/` at the end.
return fileURLToPath(
await esmResolve(name, pathToFileURL(base).href + '/')
)
// Bug with coverage on Node@12.
/* c8 ignore next 1 */
} catch (error) {
lastError = /** @type {Error} */ (error)
}
}
}
export {loadPlugin, resolvePlugin} from './lib/index.js'
{
"name": "load-plugin",
"version": "5.1.0",
"version": "6.0.0",
"description": "Load a submodule, plugin, or file",

@@ -8,5 +8,5 @@ "license": "MIT",

"load",
"submodule",
"package",
"plugin"
"plugin",
"submodule"
],

@@ -25,16 +25,17 @@ "repository": "wooorm/load-plugin",

"type": "module",
"main": "index.js",
"types": "index.d.ts",
"exports": "./index.js",
"files": [
"lib/",
"index.d.ts",
"index.js"
"index.js",
"index.map"
],
"dependencies": {
"@npmcli/config": "^6.0.0",
"import-meta-resolve": "^2.0.0"
"@npmcli/config": "^8.0.0",
"import-meta-resolve": "^3.0.0"
},
"devDependencies": {
"@types/node": "^18.0.0",
"c8": "^7.0.0",
"prettier": "^2.0.0",
"@types/node": "^20.0.0",
"c8": "^8.0.0",
"prettier": "^3.0.0",
"remark-cli": "^11.0.0",

@@ -44,31 +45,24 @@ "remark-lint": "^9.0.0",

"type-coverage": "^2.0.0",
"typescript": "^4.0.0",
"xo": "^0.53.0"
"typescript": "^5.0.0",
"xo": "^0.56.0"
},
"scripts": {
"build": "tsc --build --clean && tsc --build && type-coverage",
"format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix",
"prepack": "npm run build && npm run format",
"build": "tsc --build --clean && tsc --build && type-coverage",
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
"test": "npm run build && npm run format && npm run test-coverage",
"test-api": "node --conditions development test/index.js",
"test-coverage": "c8 --check-coverage --100 --reporter lcov npm run test-api",
"test": "npm run build && npm run format && npm run test-coverage"
"test-coverage": "c8 --100 --reporter lcov npm run test-api"
},
"prettier": {
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": false,
"singleQuote": true,
"bracketSpacing": false,
"semi": false,
"trailingComma": "none"
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
},
"xo": {
"prettier": true,
"rules": {
"unicorn/prefer-node-protocol": "off",
"no-await-in-loop": "off"
}
},
"remarkConfig": {
"plugins": [
"preset-wooorm"
"remark-preset-wooorm"
]

@@ -79,5 +73,8 @@ },

"detail": true,
"strict": true,
"ignoreCatch": true
"ignoreCatch": true,
"strict": true
},
"xo": {
"prettier": true
}
}
# load-plugin
[![Build][build-badge]][build]
[![Coverage][coverage-badge]][coverage]
[![Downloads][downloads-badge]][downloads]
[![Build][badge-build-image]][badge-build-url]
[![Coverage][badge-coverage-image]][badge-coverage-url]
[![Downloads][badge-downloads-image]][badge-downloads-url]
Load submodules, plugins, or files.
Load a submodule, plugin, or file.

@@ -18,4 +18,6 @@ ## Contents

* [`resolvePlugin(name[, options])`](#resolvepluginname-options)
* [Types](#types)
* [`LoadOptions`](#loadoptions)
* [`ResolveOptions`](#resolveoptions)
* [Compatibility](#compatibility)
* [Security](#security)
* [Contribute](#contribute)

@@ -27,5 +29,7 @@ * [License](#license)

This package is useful when you want to load plugins.
It resolves things like Node.js does, but supports a prefix (e.g., when given a
prefix `remark` and the user provided value `gfm`, it can find `remark-gfm`),
can load from several places, and optionally global too.
It resolves things like Node.js does,
but supports a prefix (when given a prefix `remark` and the user provided value
`gfm` it can find `remark-gfm`),
can load from several places,
and optionally global too.

@@ -41,4 +45,5 @@ ## When to use this?

This package is [ESM only][esm].
In Node.js (version 14.14+, 16.0+), install with [npm][]:
This package is [ESM only][github-gist-esm].
In Node.js (version 16+),
install with [npm][npm-install]:

@@ -57,9 +62,11 @@ ```sh

console.log(await resolvePlugin('lint', {prefix: 'remark'}))
// => '/Users/tilde/projects/oss/load-plugin/node_modules/remark-lint/index.js'
// => 'file:///Users/tilde/Projects/oss/load-plugin/node_modules/remark-lint/index.js'
console.log(await resolvePlugin('validator-identifier', {prefix: '@babel/helper'}))
// => '/Users/tilde/Projects/oss/load-plugin/node_modules/@babel/helper-validator-identifier/lib/index.js'
console.log(
await resolvePlugin('validator-identifier', {prefix: '@babel/helper'})
)
// => 'file:///Users/tilde/Projects/oss/load-plugin/node_modules/@babel/helper-validator-identifier/lib/index.js'
console.log(await resolvePlugin('./index.js', {prefix: 'remark'}))
// => '/Users/tilde/projects/oss/load-plugin/index.js'
// => 'file:///Users/tilde/Projects/oss/load-plugin/index.js'

@@ -72,122 +79,152 @@ console.log(await loadPlugin('lint', {prefix: 'remark'}))

This package exports the identifiers `loadPlugin` and `resolvePlugin`.
This package exports the identifiers
[`loadPlugin`][api-load-plugin] and [`resolvePlugin`][api-resolve-plugin].
There is no default export.
It exports the [TypeScript][] types
[`LoadOptions`][api-load-options] and [`ResolveOptions`][api-resolve-options].
### `loadPlugin(name[, options])`
Uses Node’s [resolution algorithm][algo] (through
[`import-meta-resolve`][import-meta-resolve]) to load CJS and ESM packages and
files to import `name` in each given `cwd` (and optionally the global
`node_modules` directory).
Import `name` from `from` (and optionally the global `node_modules` directory).
If a `prefix` is given and `name` is not a path, `$prefix-$name` is also
searched (preferring these over non-prefixed modules).
If `name` starts with a scope (`@scope/name`), the prefix is applied after it:
`@scope/$prefix-name`.
Uses the Node.js [resolution algorithm][nodejs-resolution-algo] (through
[`import-meta-resolve`][github-import-meta-resolve]) to resolve CJS and ESM
packages and files.
##### `options`
If a `prefix` is given and `name` is not a path,
`$prefix-$name` is also searched (preferring these over non-prefixed
modules).
If `name` starts with a scope (`@scope/name`),
the prefix is applied after it: `@scope/$prefix-name`.
Configuration (optional).
###### Parameters
###### `options.prefix`
* `name` (`string`)
— specifier
* `options` ([`LoadOptions`][api-load-options], optional)
— configuration
Prefix to search for (`string`, optional).
###### Returns
###### `options.cwd`
Promise to a whole module or specific export (`Promise<unknown>`).
Place or places to search from (`string`, `Array<string>`, default:
`process.cwd()`).
### `resolvePlugin(name[, options])`
###### `options.global`
Resolve `name` from `from`.
Whether to look for `name` in [global places][global] (`boolean`, optional,
defaults to whether global is detected).
If this is nullish, `load-plugin` will detect if it’s currently running in
global mode: either because it’s in Electron, or because a globally installed
package is running it.
###### Parameters
Note: Electron runs its own version of Node instead of your system Node.
That means global packages cannot be found, unless you’ve [set-up][] a [`prefix`
in your `.npmrc`][prefix] or are using [nvm][] to manage your system node.
* `name` (`string`)
— specifier
* `options` ([`ResolveOptions`][api-resolve-options], optional)
— configuration
###### `options.key`
###### Returns
Identifier to take from the exports (`string` or `false`, default: `'default'`).
For example when given `'whatever'`, the value of `export const whatever = 1`
will be returned, when given `'default'`, the value of `export default …` is
used, and when `false` the whole module object is returned.
Promise to a file URL (`Promise<string>`).
###### Returns
### `LoadOptions`
Promise yielding the results of importing the first path that exists
(`Promise<unknown>`).
The promise rejects if importing an existing path fails, or if no existing
path exists.
Configuration for `loadPlugin` (TypeScript type).
### `resolvePlugin(name[, options])`
This type extends `ResolveOptions` and adds:
Search for `name`.
Accepts the same parameters as [`loadPlugin`][load-plugin] (except `key`) but
returns a promise resolving to an absolute URL (`string`) for `name` instead of
importing it.
Throws if `name` cannot be found.
###### Fields
## Types
* `key` (`boolean` or `string`, default: `'default'`)
— identifier to take from the exports;
for example when given `'x'`,
the value of `export const x = 1` will be returned;
when given `'default'`,
the value of `export default …` is used,
and when `false` the whole module object is returned
This package is fully typed with [TypeScript][].
It exports the additional types `ResolveOptions` and `LoadOptions`.
### `ResolveOptions`
Configuration for `resolvePlugin` (TypeScript type).
###### Fields
* `from` (`Array<URL | string> | URL | string`, optional)
— place or places to search from;
defaults to the current working directory
* `global` (`boolean`, default: whether global is detected)
— whether to look for `name` in [global places][npm-node-modules];
if this is nullish,
`load-plugin` will detect if it’s currently running in global mode: either
because it’s in Electron or because a globally installed package is running
it;
note that Electron runs its own version of Node instead of your system Node,
meaning global packages cannot be found,
unless you’ve set-up a [`prefix`][npm-prefix] in your `.npmrc` or are using
[nvm][github-nvm] to manage your system node
* `prefix` (`string`, optional)
— prefix to search for
## Compatibility
This package is at least compatible with all maintained versions of Node.js.
As of now, that is Node.js 14.14+ and 16.0+.
It also works in Deno and modern browsers.
This projects is compatible with maintained versions of Node.js.
When we cut a new major release,
we drop support for unmaintained versions of Node.
This means we try to keep the current release line,
`load-plugin@6`,
compatible with Node.js 16.
## Security
This package reads the file system and imports things into Node.js.
## Contribute
Yes please!
See [How to Contribute to Open Source][contribute].
See [How to Contribute to Open Source][open-source-guide-contribute].
## License
[MIT][license] © [Titus Wormer][author]
[MIT][file-license] © [Titus Wormer][wooorm]
<!-- Definitions -->
[build-badge]: https://github.com/wooorm/load-plugin/actions/workflows/main.yml/badge.svg
[api-load-plugin]: #loadpluginname-options
[build]: https://github.com/wooorm/load-plugin/actions
[api-load-options]: #loadoptions
[coverage-badge]: https://img.shields.io/codecov/c/github/wooorm/load-plugin.svg
[api-resolve-plugin]: #resolvepluginname-options
[coverage]: https://codecov.io/github/wooorm/load-plugin
[api-resolve-options]: #resolveoptions
[downloads-badge]: https://img.shields.io/npm/dm/load-plugin.svg
[badge-build-image]: https://github.com/wooorm/load-plugin/workflows/main/badge.svg
[downloads]: https://www.npmjs.com/package/load-plugin
[badge-build-url]: https://github.com/wooorm/load-plugin/actions
[npm]: https://docs.npmjs.com/cli/install
[badge-coverage-image]: https://img.shields.io/codecov/c/github/wooorm/load-plugin.svg
[license]: license
[badge-coverage-url]: https://codecov.io/github/wooorm/load-plugin
[author]: https://wooorm.com
[badge-downloads-image]: https://img.shields.io/npm/dm/load-plugin.svg
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[badge-downloads-url]: https://www.npmjs.com/package/load-plugin
[typescript]: https://www.typescriptlang.org
[file-license]: license
[contribute]: https://opensource.guide/how-to-contribute/
[github-gist-esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[global]: https://docs.npmjs.com/files/folders#node-modules
[github-import-meta-resolve]: https://github.com/wooorm/import-meta-resolve
[prefix]: https://docs.npmjs.com/misc/config#prefix
[github-nvm]: https://github.com/nvm-sh/nvm
[set-up]: https://github.com/sindresorhus/guides/blob/master/npm-global-without-sudo.md
[nodejs-resolution-algo]: https://nodejs.org/api/esm.html#esm_resolution_algorithm
[nvm]: https://github.com/creationix/nvm
[npm-install]: https://docs.npmjs.com/cli/install
[algo]: https://nodejs.org/api/esm.html#esm_resolution_algorithm
[npm-node-modules]: https://docs.npmjs.com/cli/v10/configuring-npm/folders#node-modules
[import-meta-resolve]: https://github.com/wooorm/import-meta-resolve
[npm-prefix]: https://docs.npmjs.com/cli/v10/using-npm/config
[load-plugin]: #loadpluginname-options
[open-source-guide-contribute]: https://opensource.guide/how-to-contribute/
[typescript]: https://www.typescriptlang.org
[wooorm]: https://wooorm.com
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc