Socket
Socket
Sign inDemoInstall

load-plugin

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

load-plugin - npm Package Compare versions

Comparing version 3.0.0 to 4.0.0

index.d.ts

194

index.js

@@ -1,22 +0,30 @@

'use strict'
/**
* @typedef ResolveOptions
* @property {string} [prefix]
* @property {string|string[]} [cwd]
* @property {boolean} [global]
*/
var fs = require('fs')
var path = require('path')
var resolve = require('resolve-from').silent
var readNpmConfig = require('libnpmconfig').read
/**
* @typedef {ResolveOptions & {key?: string|false}} LoadOptions
*/
module.exports = loadPlugin
loadPlugin.resolve = resolvePlugin
import fs from 'fs'
import {pathToFileURL, fileURLToPath} from 'url'
import path from 'path'
import {resolve as esmResolve} from 'import-meta-resolve'
import libNpmConfig from 'libnpmconfig'
var electron = process.versions.electron !== undefined
var windows = process.platform === 'win32'
const electron = process.versions.electron !== undefined
const windows = process.platform === 'win32'
var argv = process.argv[1] || /* istanbul ignore next */ ''
var nvm = process.env.NVM_BIN
var appData = process.env.APPDATA
const argv = process.argv[1] || /* c8 ignore next */ ''
const nvm = process.env.NVM_BIN
const appData = process.env.APPDATA
/* istanbul ignore next */
var globalsLibrary = windows ? '' : 'lib'
/* c8 ignore next */
const globalsLibrary = windows ? '' : 'lib'
var builtinNpmConfig
/** @type {{prefix?: string}} */
let builtinNpmConfig

@@ -26,3 +34,3 @@ // The prefix config defaults to the location where node is installed.

// pass to `libnpmconfig` explicitly:
/* istanbul ignore next */
/* c8 ignore next 4 */
if (windows && appData) {

@@ -32,7 +40,12 @@ builtinNpmConfig = {prefix: path.join(appData, 'npm')}

var npmPrefix = readNpmConfig(null, builtinNpmConfig).prefix
/**
* Note: `libnpmconfig` uses `figgy-pudding` which is slated for archival.
* Either `libnpmconfig` will switch to an alternative or we’ll have to.
* @type {string}
*/
let npmPrefix = libNpmConfig.read(null, builtinNpmConfig).prefix
// If there is no prefix defined, use the defaults
// See: <https://github.com/eush77/npm-prefix/blob/master/index.js>
/* istanbul ignore next */
/* c8 ignore next 5 */
if (!npmPrefix) {

@@ -44,4 +57,4 @@ npmPrefix = windows

var globally = electron || argv.indexOf(npmPrefix) === 0
var globals = path.resolve(npmPrefix, globalsLibrary, 'node_modules')
const globalsDefault = electron || argv.indexOf(npmPrefix) === 0
let globalDir = path.resolve(npmPrefix, globalsLibrary, 'node_modules')

@@ -56,59 +69,71 @@ // If we’re in Electron, we’re running in a modified Node that cannot really

// and detect the actual modules.
/* istanbul ignore next */
if (electron && nvm && !fs.existsSync(globals)) {
globals = path.resolve(nvm, '..', globalsLibrary, 'node_modules')
/* c8 ignore next 3 */
if (electron && nvm && !fs.existsSync(globalDir)) {
globalDir = path.resolve(nvm, '..', globalsLibrary, 'node_modules')
}
// Load the plugin found using `resolvePlugin`.
function loadPlugin(name, options) {
return require(resolvePlugin(name, options) || name)
/**
* 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)
console.log('resolved:', [name, fp, pathToFileURL(fp).href])
/** @type {Object.<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).
function resolvePlugin(name, options) {
var settings = options || {}
var prefix = settings.prefix
var cwd = settings.cwd
var global = settings.global
var filePath
var sources
var length
var index
var plugin
var slash
var scope = ''
/**
* 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} */
let plugin
/** @type {Error} */
let lastError
if (global === null || global === undefined) {
global = globally
}
if (cwd && typeof cwd === 'object') {
sources = cwd.concat()
} else {
sources = [cwd || process.cwd()]
}
// Non-path.
if (name.charAt(0) !== '.') {
if (global) {
sources.push(globals)
if (globals) {
sources.push(globalDir)
}
let scope = ''
// Unprefix module.
if (prefix) {
prefix = prefix.charAt(prefix.length - 1) === '-' ? prefix : prefix + '-'
// Scope?
if (name.charAt(0) === '@') {
slash = name.indexOf('/')
const slash = name.indexOf('/')

@@ -132,15 +157,38 @@ // Let’s keep the algorithm simple.

length = sources.length
index = -1
let index = -1
/** @type {string} */
let fp
while (++index < length) {
cwd = sources[index]
filePath = (plugin && resolve(cwd, plugin)) || resolve(cwd, name)
while (++index < sources.length) {
fp = plugin && (await attempt(sources[index], plugin))
if (fp) return fp
if (filePath) {
return filePath
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>}
*/
async function attempt(base, name) {
try {
console.log('try:', [name, base, pathToFileURL(base).href + '/'])
// `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 = error
}
}
return null
}
{
"name": "load-plugin",
"version": "3.0.0",
"version": "4.0.0",
"description": "Load a submodule, plugin, or file",

@@ -22,26 +22,34 @@ "license": "MIT",

],
"sideEffects": false,
"type": "module",
"main": "index.js",
"browser": "browser.js",
"types": "index.d.ts",
"files": [
"browser",
"index.d.ts",
"index.js"
],
"dependencies": {
"libnpmconfig": "^1.0.0",
"resolve-from": "^5.0.0"
"import-meta-resolve": "^1.0.0",
"libnpmconfig": "^1.0.0"
},
"devDependencies": {
"nyc": "^15.0.0",
"prettier": "^1.0.0",
"remark-cli": "^7.0.0",
"remark-lint": "^6.0.0",
"remark-preset-wooorm": "^6.0.0",
"tape": "^4.0.0",
"xo": "^0.25.0"
"@types/tape": "^4.0.0",
"c8": "^7.0.0",
"prettier": "^2.0.0",
"remark-cli": "^9.0.0",
"remark-lint": "^8.0.0",
"remark-preset-wooorm": "^8.0.0",
"rimraf": "^3.0.0",
"tape": "^5.0.0",
"type-coverage": "^2.0.0",
"typescript": "^4.0.0",
"xo": "^0.39.0"
},
"scripts": {
"format": "remark . -qfo && prettier --write \"**/*.js\" && xo --fix",
"test-api": "node test",
"test-coverage": "nyc --reporter lcov tape test/index.js",
"test": "npm run format && npm run test-coverage"
"prepack": "npm run build && npm run format",
"build": "rimraf \"{test/**,}*.d.ts\" && tsc && type-coverage",
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
"test-api": "node test/index.js",
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node test/index.js",
"test": "npm run build && npm run format && npm run test-coverage"
},

@@ -58,10 +66,6 @@ "prettier": {

"prettier": true,
"esnext": false
"rules": {
"no-await-in-loop": "off"
}
},
"nyc": {
"check-coverage": true,
"lines": 100,
"functions": 100,
"branches": 100
},
"remarkConfig": {

@@ -71,3 +75,9 @@ "plugins": [

]
},
"typeCoverage": {
"atLeast": 100,
"detail": true,
"strict": true,
"ignoreCatch": true
}
}

@@ -13,2 +13,5 @@ # load-plugin

This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c):
Node 12+ is needed to use it and it must be `import`ed instead of `require`d.
[npm][]:

@@ -20,5 +23,2 @@

When bundled for the browser, a small [file][browser] is included to warn that,
when any of the below functions are invoked, the action is unsupported.
## Use

@@ -28,16 +28,20 @@

```javascript
var load = require('load-plugin')
```js
import {loadPlugin, resolvePlugin} from 'load-plugin'
load.resolve('lint', {prefix: 'remark'})
// => '/Users/tilde/projects/oss/load-plugin/node_modules/remark-lint/index.js'
main()
load.resolve('@babel/function-name', {prefix: 'helper'})
// => '/Users/tilde/projects/oss/load-plugin/node_modules/@babel/helper-function-name/index.js'
async function main() {
await resolvePlugin('lint', {prefix: 'remark'})
// => '/Users/tilde/projects/oss/load-plugin/node_modules/remark-lint/index.js'
load.resolve('./index.js', {prefix: 'remark'})
// => '/Users/tilde/projects/oss/load-plugin/index.js'
await resolvePlugin('@babel/function-name', {prefix: 'helper'})
// => '/Users/tilde/projects/oss/load-plugin/node_modules/@babel/helper-function-name/lib/index.js'
load.require('lint', {prefix: 'remark'})
// => [Function: lint]
await resolvePlugin('./index.js', {prefix: 'remark'})
// => '/Users/tilde/projects/oss/load-plugin/index.js'
await loadPlugin('lint', {prefix: 'remark'})
// => [Function: lint]
}
```

@@ -47,11 +51,16 @@

This package exports the following identifiers: `loadPlugin`, `resolvePlugin`.
There is no default export.
### `loadPlugin(name[, options])`
Uses the standard node module loading strategy to require `name` in each given
`cwd` (and optionally the global `node_modules` directory).
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).
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`.
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`.

@@ -73,5 +82,5 @@ ##### `options`

defaults to whether global is detected).
If this is nully, `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.
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.

@@ -82,9 +91,15 @@ Note: Electron runs its own version of Node instead of your system Node.

###### Returns
###### `options.key`
The results of `require`ing the first path that exists.
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.
###### Throws
###### Returns
If `require`ing an existing path fails, or if no existing path exists.
`Promise.<unknown>` — Promise yielding the results of `require`ing the first
path that exists.
The promise rejects if `require`ing an existing path fails, or if no existing
path exists.

@@ -94,5 +109,6 @@ ### `loadPlugin.resolve(name[, options])`

Search for `name`.
Accepts the same parameters as [`loadPlugin`][load-plugin] but returns an
absolute path for `name` instead of requiring it, and `null` if it cannot be
found.
Accepts the same parameters as [`loadPlugin`][load-plugin] (except `key`) but
returns a promise resolving to an absolute path for `name` instead of importing
it.
Throws if `name` cannot be found.

@@ -105,5 +121,5 @@ ## License

[build-badge]: https://img.shields.io/travis/wooorm/load-plugin.svg
[build-badge]: https://github.com/wooorm/load-plugin/actions/workflows/main.yml/badge.svg
[build]: https://travis-ci.org/wooorm/load-plugin
[build]: https://github.com/wooorm/load-plugin/actions

@@ -128,4 +144,2 @@ [coverage-badge]: https://img.shields.io/codecov/c/github/wooorm/load-plugin.svg

[browser]: browser.js
[prefix]: https://docs.npmjs.com/misc/config#prefix

@@ -136,1 +150,5 @@

[nvm]: https://github.com/creationix/nvm
[algo]: https://nodejs.org/api/esm.html#esm_resolution_algorithm
[import-meta-resolve]: https://github.com/wooorm/import-meta-resolve
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc