@rollup/plugin-node-resolve
Advanced tools
+18
-0
| # @rollup/plugin-node-resolve ChangeLog | ||
| ## v11.0.0 | ||
| _2020-11-30_ | ||
| ### Breaking Changes | ||
| - refactor!: simplify builtins and remove `customResolveOptions` (#656) | ||
| - feat!: Mark built-ins as external (#627) | ||
| - feat!: support package entry points (#540) | ||
| ### Bugfixes | ||
| - fix: refactor handling builtins, do not log warning if no local version (#637) | ||
| ### Updates | ||
| - docs: fix import statements in examples in README.md (#646) | ||
| ## v10.0.0 | ||
@@ -4,0 +22,0 @@ |
+357
-97
@@ -11,7 +11,8 @@ 'use strict'; | ||
| var util = require('util'); | ||
| var resolve = require('resolve'); | ||
| var pluginutils = require('@rollup/pluginutils'); | ||
| var resolveModule = require('resolve'); | ||
| function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
| var path__default = /*#__PURE__*/_interopDefaultLegacy(path); | ||
| var builtinList__default = /*#__PURE__*/_interopDefaultLegacy(builtinList); | ||
@@ -21,3 +22,3 @@ var deepMerge__default = /*#__PURE__*/_interopDefaultLegacy(deepMerge); | ||
| var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); | ||
| var resolveModule__default = /*#__PURE__*/_interopDefaultLegacy(resolveModule); | ||
| var resolve__default = /*#__PURE__*/_interopDefaultLegacy(resolve); | ||
@@ -83,4 +84,2 @@ const exists = util.promisify(fs__default['default'].exists); | ||
| const resolveId = util.promisify(resolveModule__default['default']); | ||
| // returns the imported package name for bare module imports | ||
@@ -138,3 +137,3 @@ function getPackageName(id) { | ||
| // copy as we are about to munge the `main` field of `pkg`. | ||
| packageJson: Object.assign({}, pkg), | ||
| packageJson: { ...pkg }, | ||
@@ -237,33 +236,302 @@ // path to package.json file | ||
| // Resolve module specifiers in order. Promise resolves to the first module that resolves | ||
| // successfully, or the error that resulted from the last attempted module resolution. | ||
| function resolveImportSpecifiers(importSpecifierList, resolveOptions) { | ||
| let promise = Promise.resolve(); | ||
| const resolveImportPath = util.promisify(resolve__default['default']); | ||
| const readFile$1 = util.promisify(fs__default['default'].readFile); | ||
| for (let i = 0; i < importSpecifierList.length; i++) { | ||
| // eslint-disable-next-line no-loop-func | ||
| promise = promise.then(async (value) => { | ||
| // if we've already resolved to something, just return it. | ||
| if (value) { | ||
| return value; | ||
| const pathNotFoundError = (subPath, pkgPath) => | ||
| new Error(`Package subpath '${subPath}' is not defined by "exports" in ${pkgPath}`); | ||
| function findExportKeyMatch(exportMap, subPath) { | ||
| for (const key of Object.keys(exportMap)) { | ||
| if (key.endsWith('*')) { | ||
| // star match: "./foo/*": "./foo/*.js" | ||
| const keyWithoutStar = key.substring(0, key.length - 1); | ||
| if (subPath.startsWith(keyWithoutStar)) { | ||
| return key; | ||
| } | ||
| } | ||
| let result = await resolveId(importSpecifierList[i], resolveOptions); | ||
| if (!resolveOptions.preserveSymlinks) { | ||
| if (await exists(result)) { | ||
| result = await realpath(result); | ||
| } | ||
| if (key.endsWith('/') && subPath.startsWith(key)) { | ||
| // directory match (deprecated by node): "./foo/": "./foo/.js" | ||
| return key; | ||
| } | ||
| if (key === subPath) { | ||
| // literal match | ||
| return key; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| function mapSubPath(pkgJsonPath, subPath, key, value) { | ||
| if (typeof value === 'string') { | ||
| if (typeof key === 'string' && key.endsWith('*')) { | ||
| // star match: "./foo/*": "./foo/*.js" | ||
| const keyWithoutStar = key.substring(0, key.length - 1); | ||
| const subPathAfterKey = subPath.substring(keyWithoutStar.length); | ||
| return value.replace(/\*/g, subPathAfterKey); | ||
| } | ||
| if (value.endsWith('/')) { | ||
| // directory match (deprecated by node): "./foo/": "./foo/.js" | ||
| return `${value}${subPath.substring(key.length)}`; | ||
| } | ||
| // mapping is a string, for example { "./foo": "./dist/foo.js" } | ||
| return value; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| // mapping is an array with fallbacks, for example { "./foo": ["foo:bar", "./dist/foo.js"] } | ||
| return value.find((v) => v.startsWith('./')); | ||
| } | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| function findEntrypoint(pkgJsonPath, subPath, exportMap, conditions, key) { | ||
| if (typeof exportMap !== 'object') { | ||
| return mapSubPath(pkgJsonPath, subPath, key, exportMap); | ||
| } | ||
| // iterate conditions recursively, find the first that matches all conditions | ||
| for (const [condition, subExportMap] of Object.entries(exportMap)) { | ||
| if (conditions.includes(condition)) { | ||
| const mappedSubPath = findEntrypoint(pkgJsonPath, subPath, subExportMap, conditions, key); | ||
| if (mappedSubPath) { | ||
| return mappedSubPath; | ||
| } | ||
| return result; | ||
| } | ||
| } | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| function findEntrypointTopLevel(pkgJsonPath, subPath, exportMap, conditions) { | ||
| if (typeof exportMap !== 'object') { | ||
| // the export map shorthand, for example { exports: "./index.js" } | ||
| if (subPath !== '.') { | ||
| // shorthand only supports a main entrypoint | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| return mapSubPath(pkgJsonPath, subPath, null, exportMap); | ||
| } | ||
| // export map is an object, the top level can be either conditions or sub path mappings | ||
| const keys = Object.keys(exportMap); | ||
| const isConditions = keys.every((k) => !k.startsWith('.')); | ||
| const isMappings = keys.every((k) => k.startsWith('.')); | ||
| if (!isConditions && !isMappings) { | ||
| throw new Error( | ||
| `Invalid package config ${pkgJsonPath}, "exports" cannot contain some keys starting with '.'` + | ||
| ' and some not. The exports object must either be an object of package subpath keys or an object of main entry' + | ||
| ' condition name keys only.' | ||
| ); | ||
| } | ||
| let key = null; | ||
| let exportMapForSubPath; | ||
| if (isConditions) { | ||
| // top level is conditions, for example { "import": ..., "require": ..., "module": ... } | ||
| if (subPath !== '.') { | ||
| // package with top level conditions means it only supports a main entrypoint | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| exportMapForSubPath = exportMap; | ||
| } else { | ||
| // top level is sub path mappings, for example { ".": ..., "./foo": ..., "./bar": ... } | ||
| key = findExportKeyMatch(exportMap, subPath); | ||
| if (!key) { | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| exportMapForSubPath = exportMap[key]; | ||
| } | ||
| return findEntrypoint(pkgJsonPath, subPath, exportMapForSubPath, conditions, key); | ||
| } | ||
| async function resolveId({ | ||
| importPath, | ||
| exportConditions, | ||
| warn, | ||
| packageInfoCache, | ||
| extensions, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides, | ||
| baseDir, | ||
| moduleDirectories | ||
| }) { | ||
| let hasModuleSideEffects = () => null; | ||
| let hasPackageEntry = true; | ||
| let packageBrowserField = false; | ||
| let packageInfo; | ||
| const filter = (pkg, pkgPath) => { | ||
| const info = getPackageInfo({ | ||
| cache: packageInfoCache, | ||
| extensions, | ||
| pkg, | ||
| pkgPath, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides | ||
| }); | ||
| // swallow MODULE_NOT_FOUND errors | ||
| promise = promise.catch((error) => { | ||
| ({ packageInfo, hasModuleSideEffects, hasPackageEntry, packageBrowserField } = info); | ||
| return info.cachedPkg; | ||
| }; | ||
| const resolveOptions = { | ||
| basedir: baseDir, | ||
| readFile: readCachedFile, | ||
| isFile: isFileCached, | ||
| isDirectory: isDirCached, | ||
| extensions, | ||
| includeCoreModules: false, | ||
| moduleDirectory: moduleDirectories, | ||
| preserveSymlinks, | ||
| packageFilter: filter | ||
| }; | ||
| let location; | ||
| const pkgName = getPackageName(importPath); | ||
| if (pkgName) { | ||
| let pkgJsonPath; | ||
| let pkgJson; | ||
| try { | ||
| pkgJsonPath = await resolveImportPath(`${pkgName}/package.json`, resolveOptions); | ||
| pkgJson = JSON.parse(await readFile$1(pkgJsonPath, 'utf-8')); | ||
| } catch (_) { | ||
| // if there is no package.json we defer to regular resolve behavior | ||
| } | ||
| if (pkgJsonPath && pkgJson && pkgJson.exports) { | ||
| try { | ||
| const packageSubPath = | ||
| pkgName === importPath ? '.' : `.${importPath.substring(pkgName.length)}`; | ||
| const mappedSubPath = findEntrypointTopLevel( | ||
| pkgJsonPath, | ||
| packageSubPath, | ||
| pkgJson.exports, | ||
| exportConditions | ||
| ); | ||
| const pkgDir = path__default['default'].dirname(pkgJsonPath); | ||
| location = path__default['default'].join(pkgDir, mappedSubPath); | ||
| } catch (error) { | ||
| warn(error); | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
| if (!location) { | ||
| try { | ||
| location = await resolveImportPath(importPath, resolveOptions); | ||
| } catch (error) { | ||
| if (error.code !== 'MODULE_NOT_FOUND') { | ||
| throw error; | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| if (!preserveSymlinks) { | ||
| if (await exists(location)) { | ||
| location = await realpath(location); | ||
| } | ||
| } | ||
| return { | ||
| location, | ||
| hasModuleSideEffects, | ||
| hasPackageEntry, | ||
| packageBrowserField, | ||
| packageInfo | ||
| }; | ||
| } | ||
| // Resolve module specifiers in order. Promise resolves to the first module that resolves | ||
| // successfully, or the error that resulted from the last attempted module resolution. | ||
| async function resolveImportSpecifiers({ | ||
| importSpecifierList, | ||
| exportConditions, | ||
| warn, | ||
| packageInfoCache, | ||
| extensions, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides, | ||
| baseDir, | ||
| moduleDirectories | ||
| }) { | ||
| for (let i = 0; i < importSpecifierList.length; i++) { | ||
| // eslint-disable-next-line no-await-in-loop | ||
| const resolved = await resolveId({ | ||
| importPath: importSpecifierList[i], | ||
| exportConditions, | ||
| warn, | ||
| packageInfoCache, | ||
| extensions, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides, | ||
| baseDir, | ||
| moduleDirectories | ||
| }); | ||
| if (resolved) { | ||
| return resolved; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| return promise; | ||
| function handleDeprecatedOptions(opts) { | ||
| const warnings = []; | ||
| if (opts.customResolveOptions) { | ||
| const { customResolveOptions } = opts; | ||
| if (customResolveOptions.moduleDirectory) { | ||
| // eslint-disable-next-line no-param-reassign | ||
| opts.moduleDirectories = Array.isArray(customResolveOptions.moduleDirectory) | ||
| ? customResolveOptions.moduleDirectory | ||
| : [customResolveOptions.moduleDirectory]; | ||
| warnings.push( | ||
| 'node-resolve: The `customResolveOptions.moduleDirectory` option has been deprecated. Use `moduleDirectories`, which must be an array.' | ||
| ); | ||
| } | ||
| if (customResolveOptions.preserveSymlinks) { | ||
| throw new Error( | ||
| 'node-resolve: `customResolveOptions.preserveSymlinks` is no longer an option. We now always use the rollup `preserveSymlinks` option.' | ||
| ); | ||
| } | ||
| [ | ||
| 'basedir', | ||
| 'package', | ||
| 'extensions', | ||
| 'includeCoreModules', | ||
| 'readFile', | ||
| 'isFile', | ||
| 'isDirectory', | ||
| 'realpath', | ||
| 'packageFilter', | ||
| 'pathFilter', | ||
| 'paths', | ||
| 'packageIterator' | ||
| ].forEach((resolveOption) => { | ||
| if (customResolveOptions[resolveOption]) { | ||
| throw new Error( | ||
| `node-resolve: \`customResolveOptions.${resolveOption}\` is no longer an option. If you need this, please open an issue.` | ||
| ); | ||
| } | ||
| }); | ||
| } | ||
| return { warnings }; | ||
| } | ||
@@ -275,3 +543,2 @@ | ||
| const ES6_BROWSER_EMPTY = '\0node-resolve:empty.js'; | ||
| const nullFn = () => null; | ||
| const deepFreeze = (object) => { | ||
@@ -288,4 +555,7 @@ Object.freeze(object); | ||
| }; | ||
| const baseConditions = ['default', 'module']; | ||
| const baseConditionsEsm = [...baseConditions, 'import']; | ||
| const baseConditionsCjs = [...baseConditions, 'require']; | ||
| const defaults = { | ||
| customResolveOptions: {}, | ||
| dedupe: [], | ||
@@ -295,3 +565,4 @@ // It's important that .mjs is listed before .js so that Rollup will interpret npm modules | ||
| extensions: ['.mjs', '.js', '.json', '.node'], | ||
| resolveOnly: [] | ||
| resolveOnly: [], | ||
| moduleDirectories: ['node_modules'] | ||
| }; | ||
@@ -301,5 +572,8 @@ const DEFAULTS = deepFreeze(deepMerge__default['default']({}, defaults)); | ||
| function nodeResolve(opts = {}) { | ||
| const options = Object.assign({}, defaults, opts); | ||
| const { customResolveOptions, extensions, jail } = options; | ||
| const warnings = []; | ||
| const { warnings } = handleDeprecatedOptions(opts); | ||
| const options = { ...defaults, ...opts }; | ||
| const { extensions, jail, moduleDirectories } = options; | ||
| const conditionsEsm = [...baseConditionsEsm, ...(options.exportConditions || [])]; | ||
| const conditionsCjs = [...baseConditionsCjs, ...(options.exportConditions || [])]; | ||
| const packageInfoCache = new Map(); | ||
@@ -315,7 +589,2 @@ const idToPackageInfo = new Map(); | ||
| if (options.only) { | ||
| warnings.push('node-resolve: The `only` options is deprecated, please use `resolveOnly`'); | ||
| options.resolveOnly = options.only; | ||
| } | ||
| if (typeof dedupe !== 'function') { | ||
@@ -356,3 +625,3 @@ dedupe = (importee) => | ||
| async resolveId(importee, importer) { | ||
| async resolveId(importee, importer, opts) { | ||
| if (importee === ES6_BROWSER_EMPTY) { | ||
@@ -373,3 +642,3 @@ return importee; | ||
| const basedir = !importer || dedupe(importee) ? rootDir : path.dirname(importer); | ||
| const baseDir = !importer || dedupe(importee) ? rootDir : path.dirname(importer); | ||
@@ -379,3 +648,3 @@ // https://github.com/defunctzombie/package-browser-field-spec | ||
| if (useBrowserOverrides && browser) { | ||
| const resolvedImportee = path.resolve(basedir, importee); | ||
| const resolvedImportee = path.resolve(baseDir, importee); | ||
| if (browser[importee] === false || browser[resolvedImportee] === false) { | ||
@@ -403,3 +672,3 @@ return ES6_BROWSER_EMPTY; | ||
| // an import relative to the parent dir of the importer | ||
| id = path.resolve(basedir, importee); | ||
| id = path.resolve(baseDir, importee); | ||
| isRelativeImport = true; | ||
@@ -419,36 +688,2 @@ } | ||
| let hasModuleSideEffects = nullFn; | ||
| let hasPackageEntry = true; | ||
| let packageBrowserField = false; | ||
| let packageInfo; | ||
| const filter = (pkg, pkgPath) => { | ||
| const info = getPackageInfo({ | ||
| cache: packageInfoCache, | ||
| extensions, | ||
| pkg, | ||
| pkgPath, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides | ||
| }); | ||
| ({ packageInfo, hasModuleSideEffects, hasPackageEntry, packageBrowserField } = info); | ||
| return info.cachedPkg; | ||
| }; | ||
| let resolveOptions = { | ||
| basedir, | ||
| packageFilter: filter, | ||
| readFile: readCachedFile, | ||
| isFile: isFileCached, | ||
| isDirectory: isDirCached, | ||
| extensions | ||
| }; | ||
| if (preserveSymlinks !== undefined) { | ||
| resolveOptions.preserveSymlinks = preserveSymlinks; | ||
| } | ||
| const importSpecifierList = []; | ||
@@ -468,3 +703,3 @@ | ||
| if (importeeIsBuiltin && (!preferBuiltins || !isPreferBuiltinsSet)) { | ||
| if (importeeIsBuiltin) { | ||
| // The `resolve` library will not resolve packages with the same | ||
@@ -489,5 +724,30 @@ // name as a node built-in module. If we're resolving something | ||
| importSpecifierList.push(importee); | ||
| resolveOptions = Object.assign(resolveOptions, customResolveOptions); | ||
| let resolved = await resolveImportSpecifiers(importSpecifierList, resolveOptions); | ||
| const warn = (...args) => this.warn(...args); | ||
| const isRequire = | ||
| opts && opts.custom && opts.custom['node-resolve'] && opts.custom['node-resolve'].isRequire; | ||
| const exportConditions = isRequire ? conditionsCjs : conditionsEsm; | ||
| const resolvedWithoutBuiltins = await resolveImportSpecifiers({ | ||
| importSpecifierList, | ||
| exportConditions, | ||
| warn, | ||
| packageInfoCache, | ||
| extensions, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides, | ||
| baseDir, | ||
| moduleDirectories | ||
| }); | ||
| const resolved = | ||
| importeeIsBuiltin && preferBuiltins | ||
| ? { | ||
| packageInfo: undefined, | ||
| hasModuleSideEffects: () => null, | ||
| hasPackageEntry: true, | ||
| packageBrowserField: false | ||
| } | ||
| : resolvedWithoutBuiltins; | ||
| if (!resolved) { | ||
@@ -497,43 +757,43 @@ return null; | ||
| const { packageInfo, hasModuleSideEffects, hasPackageEntry, packageBrowserField } = resolved; | ||
| let { location } = resolved; | ||
| if (packageBrowserField) { | ||
| if (Object.prototype.hasOwnProperty.call(packageBrowserField, resolved)) { | ||
| if (!packageBrowserField[resolved]) { | ||
| browserMapCache.set(resolved, packageBrowserField); | ||
| if (Object.prototype.hasOwnProperty.call(packageBrowserField, location)) { | ||
| if (!packageBrowserField[location]) { | ||
| browserMapCache.set(location, packageBrowserField); | ||
| return ES6_BROWSER_EMPTY; | ||
| } | ||
| resolved = packageBrowserField[resolved]; | ||
| location = packageBrowserField[location]; | ||
| } | ||
| browserMapCache.set(resolved, packageBrowserField); | ||
| browserMapCache.set(location, packageBrowserField); | ||
| } | ||
| if (hasPackageEntry && !preserveSymlinks) { | ||
| const fileExists = await exists(resolved); | ||
| const fileExists = await exists(location); | ||
| if (fileExists) { | ||
| resolved = await realpath(resolved); | ||
| location = await realpath(location); | ||
| } | ||
| } | ||
| idToPackageInfo.set(resolved, packageInfo); | ||
| idToPackageInfo.set(location, packageInfo); | ||
| if (hasPackageEntry) { | ||
| if (builtins.has(resolved) && preferBuiltins && isPreferBuiltinsSet) { | ||
| return null; | ||
| } else if (importeeIsBuiltin && preferBuiltins) { | ||
| if (!isPreferBuiltinsSet) { | ||
| if (importeeIsBuiltin && preferBuiltins) { | ||
| if (!isPreferBuiltinsSet && resolvedWithoutBuiltins && resolved !== importee) { | ||
| this.warn( | ||
| `preferring built-in module '${importee}' over local alternative at '${resolved}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning` | ||
| `preferring built-in module '${importee}' over local alternative at '${resolvedWithoutBuiltins.location}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning` | ||
| ); | ||
| } | ||
| return false; | ||
| } else if (jail && location.indexOf(path.normalize(jail.trim(path.sep))) !== 0) { | ||
| return null; | ||
| } else if (jail && resolved.indexOf(path.normalize(jail.trim(path.sep))) !== 0) { | ||
| return null; | ||
| } | ||
| } | ||
| if (options.modulesOnly && (await exists(resolved))) { | ||
| const code = await readFile(resolved, 'utf-8'); | ||
| if (options.modulesOnly && (await exists(location))) { | ||
| const code = await readFile(location, 'utf-8'); | ||
| if (isModule__default['default'](code)) { | ||
| return { | ||
| id: `${resolved}${importSuffix}`, | ||
| moduleSideEffects: hasModuleSideEffects(resolved) | ||
| id: `${location}${importSuffix}`, | ||
| moduleSideEffects: hasModuleSideEffects(location) | ||
| }; | ||
@@ -544,4 +804,4 @@ } | ||
| const result = { | ||
| id: `${resolved}${importSuffix}`, | ||
| moduleSideEffects: hasModuleSideEffects(resolved) | ||
| id: `${location}${importSuffix}`, | ||
| moduleSideEffects: hasModuleSideEffects(location) | ||
| }; | ||
@@ -548,0 +808,0 @@ return result; |
+356
-97
@@ -1,2 +0,2 @@ | ||
| import { dirname, resolve, extname, normalize, sep } from 'path'; | ||
| import path, { dirname, resolve, extname, normalize, sep } from 'path'; | ||
| import builtinList from 'builtin-modules'; | ||
@@ -7,4 +7,4 @@ import deepMerge from 'deepmerge'; | ||
| import { promisify } from 'util'; | ||
| import resolve$1 from 'resolve'; | ||
| import { createFilter } from '@rollup/pluginutils'; | ||
| import resolveModule from 'resolve'; | ||
@@ -70,4 +70,2 @@ const exists = promisify(fs.exists); | ||
| const resolveId = promisify(resolveModule); | ||
| // returns the imported package name for bare module imports | ||
@@ -125,3 +123,3 @@ function getPackageName(id) { | ||
| // copy as we are about to munge the `main` field of `pkg`. | ||
| packageJson: Object.assign({}, pkg), | ||
| packageJson: { ...pkg }, | ||
@@ -224,33 +222,302 @@ // path to package.json file | ||
| // Resolve module specifiers in order. Promise resolves to the first module that resolves | ||
| // successfully, or the error that resulted from the last attempted module resolution. | ||
| function resolveImportSpecifiers(importSpecifierList, resolveOptions) { | ||
| let promise = Promise.resolve(); | ||
| const resolveImportPath = promisify(resolve$1); | ||
| const readFile$1 = promisify(fs.readFile); | ||
| for (let i = 0; i < importSpecifierList.length; i++) { | ||
| // eslint-disable-next-line no-loop-func | ||
| promise = promise.then(async (value) => { | ||
| // if we've already resolved to something, just return it. | ||
| if (value) { | ||
| return value; | ||
| const pathNotFoundError = (subPath, pkgPath) => | ||
| new Error(`Package subpath '${subPath}' is not defined by "exports" in ${pkgPath}`); | ||
| function findExportKeyMatch(exportMap, subPath) { | ||
| for (const key of Object.keys(exportMap)) { | ||
| if (key.endsWith('*')) { | ||
| // star match: "./foo/*": "./foo/*.js" | ||
| const keyWithoutStar = key.substring(0, key.length - 1); | ||
| if (subPath.startsWith(keyWithoutStar)) { | ||
| return key; | ||
| } | ||
| } | ||
| let result = await resolveId(importSpecifierList[i], resolveOptions); | ||
| if (!resolveOptions.preserveSymlinks) { | ||
| if (await exists(result)) { | ||
| result = await realpath(result); | ||
| } | ||
| if (key.endsWith('/') && subPath.startsWith(key)) { | ||
| // directory match (deprecated by node): "./foo/": "./foo/.js" | ||
| return key; | ||
| } | ||
| if (key === subPath) { | ||
| // literal match | ||
| return key; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| function mapSubPath(pkgJsonPath, subPath, key, value) { | ||
| if (typeof value === 'string') { | ||
| if (typeof key === 'string' && key.endsWith('*')) { | ||
| // star match: "./foo/*": "./foo/*.js" | ||
| const keyWithoutStar = key.substring(0, key.length - 1); | ||
| const subPathAfterKey = subPath.substring(keyWithoutStar.length); | ||
| return value.replace(/\*/g, subPathAfterKey); | ||
| } | ||
| if (value.endsWith('/')) { | ||
| // directory match (deprecated by node): "./foo/": "./foo/.js" | ||
| return `${value}${subPath.substring(key.length)}`; | ||
| } | ||
| // mapping is a string, for example { "./foo": "./dist/foo.js" } | ||
| return value; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| // mapping is an array with fallbacks, for example { "./foo": ["foo:bar", "./dist/foo.js"] } | ||
| return value.find((v) => v.startsWith('./')); | ||
| } | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| function findEntrypoint(pkgJsonPath, subPath, exportMap, conditions, key) { | ||
| if (typeof exportMap !== 'object') { | ||
| return mapSubPath(pkgJsonPath, subPath, key, exportMap); | ||
| } | ||
| // iterate conditions recursively, find the first that matches all conditions | ||
| for (const [condition, subExportMap] of Object.entries(exportMap)) { | ||
| if (conditions.includes(condition)) { | ||
| const mappedSubPath = findEntrypoint(pkgJsonPath, subPath, subExportMap, conditions, key); | ||
| if (mappedSubPath) { | ||
| return mappedSubPath; | ||
| } | ||
| return result; | ||
| } | ||
| } | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| function findEntrypointTopLevel(pkgJsonPath, subPath, exportMap, conditions) { | ||
| if (typeof exportMap !== 'object') { | ||
| // the export map shorthand, for example { exports: "./index.js" } | ||
| if (subPath !== '.') { | ||
| // shorthand only supports a main entrypoint | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| return mapSubPath(pkgJsonPath, subPath, null, exportMap); | ||
| } | ||
| // export map is an object, the top level can be either conditions or sub path mappings | ||
| const keys = Object.keys(exportMap); | ||
| const isConditions = keys.every((k) => !k.startsWith('.')); | ||
| const isMappings = keys.every((k) => k.startsWith('.')); | ||
| if (!isConditions && !isMappings) { | ||
| throw new Error( | ||
| `Invalid package config ${pkgJsonPath}, "exports" cannot contain some keys starting with '.'` + | ||
| ' and some not. The exports object must either be an object of package subpath keys or an object of main entry' + | ||
| ' condition name keys only.' | ||
| ); | ||
| } | ||
| let key = null; | ||
| let exportMapForSubPath; | ||
| if (isConditions) { | ||
| // top level is conditions, for example { "import": ..., "require": ..., "module": ... } | ||
| if (subPath !== '.') { | ||
| // package with top level conditions means it only supports a main entrypoint | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| exportMapForSubPath = exportMap; | ||
| } else { | ||
| // top level is sub path mappings, for example { ".": ..., "./foo": ..., "./bar": ... } | ||
| key = findExportKeyMatch(exportMap, subPath); | ||
| if (!key) { | ||
| throw pathNotFoundError(subPath, pkgJsonPath); | ||
| } | ||
| exportMapForSubPath = exportMap[key]; | ||
| } | ||
| return findEntrypoint(pkgJsonPath, subPath, exportMapForSubPath, conditions, key); | ||
| } | ||
| async function resolveId({ | ||
| importPath, | ||
| exportConditions, | ||
| warn, | ||
| packageInfoCache, | ||
| extensions, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides, | ||
| baseDir, | ||
| moduleDirectories | ||
| }) { | ||
| let hasModuleSideEffects = () => null; | ||
| let hasPackageEntry = true; | ||
| let packageBrowserField = false; | ||
| let packageInfo; | ||
| const filter = (pkg, pkgPath) => { | ||
| const info = getPackageInfo({ | ||
| cache: packageInfoCache, | ||
| extensions, | ||
| pkg, | ||
| pkgPath, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides | ||
| }); | ||
| // swallow MODULE_NOT_FOUND errors | ||
| promise = promise.catch((error) => { | ||
| ({ packageInfo, hasModuleSideEffects, hasPackageEntry, packageBrowserField } = info); | ||
| return info.cachedPkg; | ||
| }; | ||
| const resolveOptions = { | ||
| basedir: baseDir, | ||
| readFile: readCachedFile, | ||
| isFile: isFileCached, | ||
| isDirectory: isDirCached, | ||
| extensions, | ||
| includeCoreModules: false, | ||
| moduleDirectory: moduleDirectories, | ||
| preserveSymlinks, | ||
| packageFilter: filter | ||
| }; | ||
| let location; | ||
| const pkgName = getPackageName(importPath); | ||
| if (pkgName) { | ||
| let pkgJsonPath; | ||
| let pkgJson; | ||
| try { | ||
| pkgJsonPath = await resolveImportPath(`${pkgName}/package.json`, resolveOptions); | ||
| pkgJson = JSON.parse(await readFile$1(pkgJsonPath, 'utf-8')); | ||
| } catch (_) { | ||
| // if there is no package.json we defer to regular resolve behavior | ||
| } | ||
| if (pkgJsonPath && pkgJson && pkgJson.exports) { | ||
| try { | ||
| const packageSubPath = | ||
| pkgName === importPath ? '.' : `.${importPath.substring(pkgName.length)}`; | ||
| const mappedSubPath = findEntrypointTopLevel( | ||
| pkgJsonPath, | ||
| packageSubPath, | ||
| pkgJson.exports, | ||
| exportConditions | ||
| ); | ||
| const pkgDir = path.dirname(pkgJsonPath); | ||
| location = path.join(pkgDir, mappedSubPath); | ||
| } catch (error) { | ||
| warn(error); | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
| if (!location) { | ||
| try { | ||
| location = await resolveImportPath(importPath, resolveOptions); | ||
| } catch (error) { | ||
| if (error.code !== 'MODULE_NOT_FOUND') { | ||
| throw error; | ||
| } | ||
| return null; | ||
| } | ||
| } | ||
| if (!preserveSymlinks) { | ||
| if (await exists(location)) { | ||
| location = await realpath(location); | ||
| } | ||
| } | ||
| return { | ||
| location, | ||
| hasModuleSideEffects, | ||
| hasPackageEntry, | ||
| packageBrowserField, | ||
| packageInfo | ||
| }; | ||
| } | ||
| // Resolve module specifiers in order. Promise resolves to the first module that resolves | ||
| // successfully, or the error that resulted from the last attempted module resolution. | ||
| async function resolveImportSpecifiers({ | ||
| importSpecifierList, | ||
| exportConditions, | ||
| warn, | ||
| packageInfoCache, | ||
| extensions, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides, | ||
| baseDir, | ||
| moduleDirectories | ||
| }) { | ||
| for (let i = 0; i < importSpecifierList.length; i++) { | ||
| // eslint-disable-next-line no-await-in-loop | ||
| const resolved = await resolveId({ | ||
| importPath: importSpecifierList[i], | ||
| exportConditions, | ||
| warn, | ||
| packageInfoCache, | ||
| extensions, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides, | ||
| baseDir, | ||
| moduleDirectories | ||
| }); | ||
| if (resolved) { | ||
| return resolved; | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
| return promise; | ||
| function handleDeprecatedOptions(opts) { | ||
| const warnings = []; | ||
| if (opts.customResolveOptions) { | ||
| const { customResolveOptions } = opts; | ||
| if (customResolveOptions.moduleDirectory) { | ||
| // eslint-disable-next-line no-param-reassign | ||
| opts.moduleDirectories = Array.isArray(customResolveOptions.moduleDirectory) | ||
| ? customResolveOptions.moduleDirectory | ||
| : [customResolveOptions.moduleDirectory]; | ||
| warnings.push( | ||
| 'node-resolve: The `customResolveOptions.moduleDirectory` option has been deprecated. Use `moduleDirectories`, which must be an array.' | ||
| ); | ||
| } | ||
| if (customResolveOptions.preserveSymlinks) { | ||
| throw new Error( | ||
| 'node-resolve: `customResolveOptions.preserveSymlinks` is no longer an option. We now always use the rollup `preserveSymlinks` option.' | ||
| ); | ||
| } | ||
| [ | ||
| 'basedir', | ||
| 'package', | ||
| 'extensions', | ||
| 'includeCoreModules', | ||
| 'readFile', | ||
| 'isFile', | ||
| 'isDirectory', | ||
| 'realpath', | ||
| 'packageFilter', | ||
| 'pathFilter', | ||
| 'paths', | ||
| 'packageIterator' | ||
| ].forEach((resolveOption) => { | ||
| if (customResolveOptions[resolveOption]) { | ||
| throw new Error( | ||
| `node-resolve: \`customResolveOptions.${resolveOption}\` is no longer an option. If you need this, please open an issue.` | ||
| ); | ||
| } | ||
| }); | ||
| } | ||
| return { warnings }; | ||
| } | ||
@@ -262,3 +529,2 @@ | ||
| const ES6_BROWSER_EMPTY = '\0node-resolve:empty.js'; | ||
| const nullFn = () => null; | ||
| const deepFreeze = (object) => { | ||
@@ -275,4 +541,7 @@ Object.freeze(object); | ||
| }; | ||
| const baseConditions = ['default', 'module']; | ||
| const baseConditionsEsm = [...baseConditions, 'import']; | ||
| const baseConditionsCjs = [...baseConditions, 'require']; | ||
| const defaults = { | ||
| customResolveOptions: {}, | ||
| dedupe: [], | ||
@@ -282,3 +551,4 @@ // It's important that .mjs is listed before .js so that Rollup will interpret npm modules | ||
| extensions: ['.mjs', '.js', '.json', '.node'], | ||
| resolveOnly: [] | ||
| resolveOnly: [], | ||
| moduleDirectories: ['node_modules'] | ||
| }; | ||
@@ -288,5 +558,8 @@ const DEFAULTS = deepFreeze(deepMerge({}, defaults)); | ||
| function nodeResolve(opts = {}) { | ||
| const options = Object.assign({}, defaults, opts); | ||
| const { customResolveOptions, extensions, jail } = options; | ||
| const warnings = []; | ||
| const { warnings } = handleDeprecatedOptions(opts); | ||
| const options = { ...defaults, ...opts }; | ||
| const { extensions, jail, moduleDirectories } = options; | ||
| const conditionsEsm = [...baseConditionsEsm, ...(options.exportConditions || [])]; | ||
| const conditionsCjs = [...baseConditionsCjs, ...(options.exportConditions || [])]; | ||
| const packageInfoCache = new Map(); | ||
@@ -302,7 +575,2 @@ const idToPackageInfo = new Map(); | ||
| if (options.only) { | ||
| warnings.push('node-resolve: The `only` options is deprecated, please use `resolveOnly`'); | ||
| options.resolveOnly = options.only; | ||
| } | ||
| if (typeof dedupe !== 'function') { | ||
@@ -343,3 +611,3 @@ dedupe = (importee) => | ||
| async resolveId(importee, importer) { | ||
| async resolveId(importee, importer, opts) { | ||
| if (importee === ES6_BROWSER_EMPTY) { | ||
@@ -360,3 +628,3 @@ return importee; | ||
| const basedir = !importer || dedupe(importee) ? rootDir : dirname(importer); | ||
| const baseDir = !importer || dedupe(importee) ? rootDir : dirname(importer); | ||
@@ -366,3 +634,3 @@ // https://github.com/defunctzombie/package-browser-field-spec | ||
| if (useBrowserOverrides && browser) { | ||
| const resolvedImportee = resolve(basedir, importee); | ||
| const resolvedImportee = resolve(baseDir, importee); | ||
| if (browser[importee] === false || browser[resolvedImportee] === false) { | ||
@@ -390,3 +658,3 @@ return ES6_BROWSER_EMPTY; | ||
| // an import relative to the parent dir of the importer | ||
| id = resolve(basedir, importee); | ||
| id = resolve(baseDir, importee); | ||
| isRelativeImport = true; | ||
@@ -406,36 +674,2 @@ } | ||
| let hasModuleSideEffects = nullFn; | ||
| let hasPackageEntry = true; | ||
| let packageBrowserField = false; | ||
| let packageInfo; | ||
| const filter = (pkg, pkgPath) => { | ||
| const info = getPackageInfo({ | ||
| cache: packageInfoCache, | ||
| extensions, | ||
| pkg, | ||
| pkgPath, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides | ||
| }); | ||
| ({ packageInfo, hasModuleSideEffects, hasPackageEntry, packageBrowserField } = info); | ||
| return info.cachedPkg; | ||
| }; | ||
| let resolveOptions = { | ||
| basedir, | ||
| packageFilter: filter, | ||
| readFile: readCachedFile, | ||
| isFile: isFileCached, | ||
| isDirectory: isDirCached, | ||
| extensions | ||
| }; | ||
| if (preserveSymlinks !== undefined) { | ||
| resolveOptions.preserveSymlinks = preserveSymlinks; | ||
| } | ||
| const importSpecifierList = []; | ||
@@ -455,3 +689,3 @@ | ||
| if (importeeIsBuiltin && (!preferBuiltins || !isPreferBuiltinsSet)) { | ||
| if (importeeIsBuiltin) { | ||
| // The `resolve` library will not resolve packages with the same | ||
@@ -476,5 +710,30 @@ // name as a node built-in module. If we're resolving something | ||
| importSpecifierList.push(importee); | ||
| resolveOptions = Object.assign(resolveOptions, customResolveOptions); | ||
| let resolved = await resolveImportSpecifiers(importSpecifierList, resolveOptions); | ||
| const warn = (...args) => this.warn(...args); | ||
| const isRequire = | ||
| opts && opts.custom && opts.custom['node-resolve'] && opts.custom['node-resolve'].isRequire; | ||
| const exportConditions = isRequire ? conditionsCjs : conditionsEsm; | ||
| const resolvedWithoutBuiltins = await resolveImportSpecifiers({ | ||
| importSpecifierList, | ||
| exportConditions, | ||
| warn, | ||
| packageInfoCache, | ||
| extensions, | ||
| mainFields, | ||
| preserveSymlinks, | ||
| useBrowserOverrides, | ||
| baseDir, | ||
| moduleDirectories | ||
| }); | ||
| const resolved = | ||
| importeeIsBuiltin && preferBuiltins | ||
| ? { | ||
| packageInfo: undefined, | ||
| hasModuleSideEffects: () => null, | ||
| hasPackageEntry: true, | ||
| packageBrowserField: false | ||
| } | ||
| : resolvedWithoutBuiltins; | ||
| if (!resolved) { | ||
@@ -484,43 +743,43 @@ return null; | ||
| const { packageInfo, hasModuleSideEffects, hasPackageEntry, packageBrowserField } = resolved; | ||
| let { location } = resolved; | ||
| if (packageBrowserField) { | ||
| if (Object.prototype.hasOwnProperty.call(packageBrowserField, resolved)) { | ||
| if (!packageBrowserField[resolved]) { | ||
| browserMapCache.set(resolved, packageBrowserField); | ||
| if (Object.prototype.hasOwnProperty.call(packageBrowserField, location)) { | ||
| if (!packageBrowserField[location]) { | ||
| browserMapCache.set(location, packageBrowserField); | ||
| return ES6_BROWSER_EMPTY; | ||
| } | ||
| resolved = packageBrowserField[resolved]; | ||
| location = packageBrowserField[location]; | ||
| } | ||
| browserMapCache.set(resolved, packageBrowserField); | ||
| browserMapCache.set(location, packageBrowserField); | ||
| } | ||
| if (hasPackageEntry && !preserveSymlinks) { | ||
| const fileExists = await exists(resolved); | ||
| const fileExists = await exists(location); | ||
| if (fileExists) { | ||
| resolved = await realpath(resolved); | ||
| location = await realpath(location); | ||
| } | ||
| } | ||
| idToPackageInfo.set(resolved, packageInfo); | ||
| idToPackageInfo.set(location, packageInfo); | ||
| if (hasPackageEntry) { | ||
| if (builtins.has(resolved) && preferBuiltins && isPreferBuiltinsSet) { | ||
| return null; | ||
| } else if (importeeIsBuiltin && preferBuiltins) { | ||
| if (!isPreferBuiltinsSet) { | ||
| if (importeeIsBuiltin && preferBuiltins) { | ||
| if (!isPreferBuiltinsSet && resolvedWithoutBuiltins && resolved !== importee) { | ||
| this.warn( | ||
| `preferring built-in module '${importee}' over local alternative at '${resolved}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning` | ||
| `preferring built-in module '${importee}' over local alternative at '${resolvedWithoutBuiltins.location}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning` | ||
| ); | ||
| } | ||
| return false; | ||
| } else if (jail && location.indexOf(normalize(jail.trim(sep))) !== 0) { | ||
| return null; | ||
| } else if (jail && resolved.indexOf(normalize(jail.trim(sep))) !== 0) { | ||
| return null; | ||
| } | ||
| } | ||
| if (options.modulesOnly && (await exists(resolved))) { | ||
| const code = await readFile(resolved, 'utf-8'); | ||
| if (options.modulesOnly && (await exists(location))) { | ||
| const code = await readFile(location, 'utf-8'); | ||
| if (isModule(code)) { | ||
| return { | ||
| id: `${resolved}${importSuffix}`, | ||
| moduleSideEffects: hasModuleSideEffects(resolved) | ||
| id: `${location}${importSuffix}`, | ||
| moduleSideEffects: hasModuleSideEffects(location) | ||
| }; | ||
@@ -531,4 +790,4 @@ } | ||
| const result = { | ||
| id: `${resolved}${importSuffix}`, | ||
| moduleSideEffects: hasModuleSideEffects(resolved) | ||
| id: `${location}${importSuffix}`, | ||
| moduleSideEffects: hasModuleSideEffects(location) | ||
| }; | ||
@@ -535,0 +794,0 @@ return result; |
+3
-3
| { | ||
| "name": "@rollup/plugin-node-resolve", | ||
| "version": "10.0.0", | ||
| "version": "11.0.0", | ||
| "publishConfig": { | ||
@@ -62,3 +62,3 @@ "access": "public" | ||
| "is-module": "^1.0.0", | ||
| "resolve": "^1.17.0" | ||
| "resolve": "^1.19.0" | ||
| }, | ||
@@ -69,3 +69,3 @@ "devDependencies": { | ||
| "@rollup/plugin-babel": "^5.1.0", | ||
| "@rollup/plugin-commonjs": "^14.0.0", | ||
| "@rollup/plugin-commonjs": "^16.0.0", | ||
| "@rollup/plugin-json": "^4.1.0", | ||
@@ -72,0 +72,0 @@ "es5-ext": "^0.10.53", |
+42
-22
@@ -47,2 +47,13 @@ [npm]: https://img.shields.io/npm/v/@rollup/plugin-node-resolve | ||
| ### `exportConditions` | ||
| Type: `Array[...String]`<br> | ||
| Default: `[]` | ||
| Additional conditions of the package.json exports field to match when resolving modules. By default, this plugin looks for the `['default', 'module', 'import']` conditions when resolving imports. | ||
| When using `@rollup/plugin-commonjs` v16 or higher, this plugin will use the `['default', 'module', 'require']` conditions when resolving require statements. | ||
| Setting this option will add extra conditions on top of the default conditions. See https://nodejs.org/api/packages.html#packages_conditional_exports for more information. | ||
| ### `browser` | ||
@@ -55,15 +66,9 @@ | ||
| ### `customResolveOptions` | ||
| ### `moduleDirectories` | ||
| Type: `Object`<br> | ||
| Default: `null` | ||
| Type: `Array[...String]`<br> | ||
| Default: `['node_modules']` | ||
| An `Object` that specifies additional options that should be passed through to [`resolve`](https://www.npmjs.com/package/resolve). | ||
| One or more directories in which to recursively look for modules. | ||
| ``` | ||
| customResolveOptions: { | ||
| moduleDirectory: 'js_modules' | ||
| } | ||
| ``` | ||
| ### `dedupe` | ||
@@ -106,3 +111,3 @@ | ||
| Locks the module search within specified path (e.g. chroot). Modules defined outside this path will be marked as external. | ||
| Locks the module search within specified path (e.g. chroot). Modules defined outside this path will be ignored by this plugin. | ||
@@ -117,10 +122,6 @@ ### `mainFields` | ||
| ### `only` | ||
| DEPRECATED: use "resolveOnly" instead | ||
| ### `preferBuiltins` | ||
| Type: `Boolean`<br> | ||
| Default: `true` | ||
| Default: `true` (with warnings if a builtin module is used over a local version. Set to `true` to disable warning.) | ||
@@ -157,2 +158,6 @@ If `true`, the plugin will prefer built-in modules (e.g. `fs`, `path`). If `false`, the plugin will look for locally installed modules of the same name. | ||
| ## Preserving symlinks | ||
| This plugin honours the rollup [`preserveSymlinks`](https://rollupjs.org/guide/en/#preservesymlinks) option. | ||
| ## Using with @rollup/plugin-commonjs | ||
@@ -164,3 +169,3 @@ | ||
| // rollup.config.js | ||
| import resolve from '@rollup/plugin-node-resolve'; | ||
| import { nodeResolve } from '@rollup/plugin-node-resolve'; | ||
| import commonjs from '@rollup/plugin-commonjs'; | ||
@@ -175,3 +180,3 @@ | ||
| }, | ||
| plugins: [resolve(), commonjs()] | ||
| plugins: [nodeResolve(), commonjs()] | ||
| }; | ||
@@ -182,12 +187,14 @@ ``` | ||
| This plugin won't resolve any builtins (e.g. `fs`). If you need to resolve builtins you can install local modules and set `preferBuiltins` to `false`, or install a plugin like [rollup-plugin-node-polyfills](https://github.com/ionic-team/rollup-plugin-node-polyfills) which provides stubbed versions of these methods. | ||
| By default this plugin will prefer built-ins over local modules, marking them as external. | ||
| If you want to silence warnings about builtins, you can add the list of builtins to the `externals` option; like so: | ||
| See [`preferBuiltins`](#preferbuiltins). | ||
| To provide stubbed versions of Node built-ins, yse a plugin like [rollup-plugin-node-polyfills](https://github.com/ionic-team/rollup-plugin-node-polyfills) or use [`builtin-modules`](https://github.com/sindresorhus/builtin-modules) with `external`, and set `preferBuiltins` to `false`. e.g. | ||
| ```js | ||
| import resolve from '@rollup/plugin-node-resolve'; | ||
| import { nodeResolve } from '@rollup/plugin-node-resolve'; | ||
| import builtins from 'builtin-modules' | ||
| export default ({ | ||
| input: ..., | ||
| plugins: [resolve()], | ||
| plugins: [nodeResolve()], | ||
| external: builtins, | ||
@@ -198,2 +205,15 @@ output: ... | ||
| ## Resolving require statements | ||
| According to [NodeJS module resolution](https://nodejs.org/api/packages.html#packages_package_entry_points) `require` statements should resolve using the `require` condition in the package exports field, while es modules should use the `import` condition. | ||
| The node resolve plugin uses `import` by default, you can opt into using the `require` semantics by passing an extra option to the resolve function: | ||
| ```js | ||
| this.resolve(importee, importer, { | ||
| skipSelf: true, | ||
| custom: { 'node-resolve': { isRequire: true } } | ||
| }); | ||
| ``` | ||
| ## Meta | ||
@@ -200,0 +220,0 @@ |
+15
-11
@@ -1,4 +0,1 @@ | ||
| import { Plugin } from 'rollup'; | ||
| import { AsyncOpts } from 'resolve'; | ||
| export const DEFAULTS: { | ||
@@ -13,2 +10,14 @@ customResolveOptions: {}; | ||
| /** | ||
| * Additional conditions of the package.json exports field to match when resolving modules. | ||
| * By default, this plugin looks for the `'default', 'module', 'import']` conditions when resolving imports. | ||
| * | ||
| * When using `@rollup/plugin-commonjs` v16 or higher, this plugin will use the | ||
| * `['default', 'module', 'import']` conditions when resolving require statements. | ||
| * | ||
| * Setting this option will add extra conditions on top of the default conditions. | ||
| * See https://nodejs.org/api/packages.html#packages_conditional_exports for more information. | ||
| */ | ||
| exportConditions?: string[]; | ||
| /** | ||
| * If `true`, instructs the plugin to use the `"browser"` property in `package.json` | ||
@@ -24,5 +33,6 @@ * files to specify alternative files to load for bundling. This is useful when | ||
| /** | ||
| * An `Object` that specifies additional options that should be passed through to `node-resolve`. | ||
| * One or more directories in which to recursively look for modules. | ||
| * @default ['node_modules'] | ||
| */ | ||
| customResolveOptions?: AsyncOpts; | ||
| moduleDirectories?: string[]; | ||
@@ -63,8 +73,2 @@ /** | ||
| /** | ||
| * @deprecated use "resolveOnly" instead | ||
| * @default null | ||
| */ | ||
| only?: ReadonlyArray<string | RegExp> | null; | ||
| /** | ||
| * If `true`, the plugin will prefer built-in modules (e.g. `fs`, `path`). If `false`, | ||
@@ -71,0 +75,0 @@ * the plugin will look for locally installed modules of the same name. |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
71321
31.95%1466
47.19%215
10.26%8
60%Updated