2023-10-03 11:14:36 +08:00
import path , { dirname , resolve , extname , normalize , sep } from 'path' ;
import builtinList from 'builtin-modules' ;
import deepMerge from 'deepmerge' ;
import isModule from 'is-module' ;
import fs , { realpathSync } from 'fs' ;
import { promisify } from 'util' ;
import { pathToFileURL , fileURLToPath } from 'url' ;
import resolve$1 from 'resolve' ;
import { createFilter } from '@rollup/pluginutils' ;
const access = promisify ( fs . access ) ;
const readFile = promisify ( fs . readFile ) ;
const realpath = promisify ( fs . realpath ) ;
const stat = promisify ( fs . stat ) ;
async function exists ( filePath ) {
try {
await access ( filePath ) ;
return true ;
} catch {
return false ;
}
}
const onError = ( error ) => {
if ( error . code === 'ENOENT' ) {
return false ;
}
throw error ;
} ;
const makeCache = ( fn ) => {
const cache = new Map ( ) ;
const wrapped = async ( param , done ) => {
if ( cache . has ( param ) === false ) {
cache . set (
param ,
fn ( param ) . catch ( ( err ) => {
cache . delete ( param ) ;
throw err ;
} )
) ;
}
try {
const result = cache . get ( param ) ;
const value = await result ;
return done ( null , value ) ;
} catch ( error ) {
return done ( error ) ;
}
} ;
wrapped . clear = ( ) => cache . clear ( ) ;
return wrapped ;
} ;
const isDirCached = makeCache ( async ( file ) => {
try {
const stats = await stat ( file ) ;
return stats . isDirectory ( ) ;
} catch ( error ) {
return onError ( error ) ;
}
} ) ;
const isFileCached = makeCache ( async ( file ) => {
try {
const stats = await stat ( file ) ;
return stats . isFile ( ) ;
} catch ( error ) {
return onError ( error ) ;
}
} ) ;
const readCachedFile = makeCache ( readFile ) ;
// returns the imported package name for bare module imports
function getPackageName ( id ) {
if ( id . startsWith ( '.' ) || id . startsWith ( '/' ) ) {
return null ;
}
const split = id . split ( '/' ) ;
// @my-scope/my-package/foo.js -> @my-scope/my-package
// @my-scope/my-package -> @my-scope/my-package
if ( split [ 0 ] [ 0 ] === '@' ) {
return ` ${ split [ 0 ] } / ${ split [ 1 ] } ` ;
}
// my-package/foo.js -> my-package
// my-package -> my-package
return split [ 0 ] ;
}
function getMainFields ( options ) {
let mainFields ;
if ( options . mainFields ) {
( { mainFields } = options ) ;
} else {
mainFields = [ 'module' , 'main' ] ;
}
if ( options . browser && mainFields . indexOf ( 'browser' ) === - 1 ) {
return [ 'browser' ] . concat ( mainFields ) ;
}
if ( ! mainFields . length ) {
throw new Error ( 'Please ensure at least one `mainFields` value is specified' ) ;
}
return mainFields ;
}
function getPackageInfo ( options ) {
const {
cache ,
extensions ,
pkg ,
mainFields ,
preserveSymlinks ,
useBrowserOverrides ,
rootDir ,
ignoreSideEffectsForRoot
} = options ;
let { pkgPath } = options ;
if ( cache . has ( pkgPath ) ) {
return cache . get ( pkgPath ) ;
}
// browserify/resolve doesn't realpath paths returned in its packageFilter callback
if ( ! preserveSymlinks ) {
pkgPath = realpathSync ( pkgPath ) ;
}
const pkgRoot = dirname ( pkgPath ) ;
const packageInfo = {
// copy as we are about to munge the `main` field of `pkg`.
packageJson : { ... pkg } ,
// path to package.json file
packageJsonPath : pkgPath ,
// directory containing the package.json
root : pkgRoot ,
// which main field was used during resolution of this module (main, module, or browser)
resolvedMainField : 'main' ,
// whether the browser map was used to resolve the entry point to this module
browserMappedMain : false ,
// the entry point of the module with respect to the selected main field and any
// relevant browser mappings.
resolvedEntryPoint : ''
} ;
let overriddenMain = false ;
for ( let i = 0 ; i < mainFields . length ; i ++ ) {
const field = mainFields [ i ] ;
if ( typeof pkg [ field ] === 'string' ) {
pkg . main = pkg [ field ] ;
packageInfo . resolvedMainField = field ;
overriddenMain = true ;
break ;
}
}
const internalPackageInfo = {
cachedPkg : pkg ,
hasModuleSideEffects : ( ) => null ,
hasPackageEntry : overriddenMain !== false || mainFields . indexOf ( 'main' ) !== - 1 ,
packageBrowserField :
useBrowserOverrides &&
typeof pkg . browser === 'object' &&
Object . keys ( pkg . browser ) . reduce ( ( browser , key ) => {
let resolved = pkg . browser [ key ] ;
if ( resolved && resolved [ 0 ] === '.' ) {
resolved = resolve ( pkgRoot , resolved ) ;
}
/* eslint-disable no-param-reassign */
browser [ key ] = resolved ;
if ( key [ 0 ] === '.' ) {
const absoluteKey = resolve ( pkgRoot , key ) ;
browser [ absoluteKey ] = resolved ;
if ( ! extname ( key ) ) {
extensions . reduce ( ( subBrowser , ext ) => {
subBrowser [ absoluteKey + ext ] = subBrowser [ key ] ;
return subBrowser ;
} , browser ) ;
}
}
return browser ;
} , { } ) ,
packageInfo
} ;
const browserMap = internalPackageInfo . packageBrowserField ;
if (
useBrowserOverrides &&
typeof pkg . browser === 'object' &&
// eslint-disable-next-line no-prototype-builtins
browserMap . hasOwnProperty ( pkg . main )
) {
packageInfo . resolvedEntryPoint = browserMap [ pkg . main ] ;
packageInfo . browserMappedMain = true ;
} else {
// index.node is technically a valid default entrypoint as well...
packageInfo . resolvedEntryPoint = resolve ( pkgRoot , pkg . main || 'index.js' ) ;
packageInfo . browserMappedMain = false ;
}
if ( ! ignoreSideEffectsForRoot || rootDir !== pkgRoot ) {
const packageSideEffects = pkg . sideEffects ;
if ( typeof packageSideEffects === 'boolean' ) {
internalPackageInfo . hasModuleSideEffects = ( ) => packageSideEffects ;
} else if ( Array . isArray ( packageSideEffects ) ) {
internalPackageInfo . hasModuleSideEffects = createFilter ( packageSideEffects , null , {
resolve : pkgRoot
} ) ;
}
}
cache . set ( pkgPath , internalPackageInfo ) ;
return internalPackageInfo ;
}
function normalizeInput ( input ) {
if ( Array . isArray ( input ) ) {
return input ;
} else if ( typeof input === 'object' ) {
return Object . values ( input ) ;
}
// otherwise it's a string
return [ input ] ;
}
/* eslint-disable no-await-in-loop */
const fileExists = promisify ( fs . exists ) ;
function isModuleDir ( current , moduleDirs ) {
return moduleDirs . some ( ( dir ) => current . endsWith ( dir ) ) ;
}
async function findPackageJson ( base , moduleDirs ) {
const { root } = path . parse ( base ) ;
let current = base ;
while ( current !== root && ! isModuleDir ( current , moduleDirs ) ) {
const pkgJsonPath = path . join ( current , 'package.json' ) ;
if ( await fileExists ( pkgJsonPath ) ) {
const pkgJsonString = fs . readFileSync ( pkgJsonPath , 'utf-8' ) ;
return { pkgJson : JSON . parse ( pkgJsonString ) , pkgPath : current , pkgJsonPath } ;
}
current = path . resolve ( current , '..' ) ;
}
return null ;
}
function isUrl ( str ) {
try {
return ! ! new URL ( str ) ;
} catch ( _ ) {
return false ;
}
}
function isConditions ( exports ) {
return typeof exports === 'object' && Object . keys ( exports ) . every ( ( k ) => ! k . startsWith ( '.' ) ) ;
}
function isMappings ( exports ) {
return typeof exports === 'object' && ! isConditions ( exports ) ;
}
function isMixedExports ( exports ) {
const keys = Object . keys ( exports ) ;
return keys . some ( ( k ) => k . startsWith ( '.' ) ) && keys . some ( ( k ) => ! k . startsWith ( '.' ) ) ;
}
function createBaseErrorMsg ( importSpecifier , importer ) {
return ` Could not resolve import " ${ importSpecifier } " in ${ importer } ` ;
}
function createErrorMsg ( context , reason , internal ) {
const { importSpecifier , importer , pkgJsonPath } = context ;
const base = createBaseErrorMsg ( importSpecifier , importer ) ;
const field = internal ? 'imports' : 'exports' ;
return ` ${ base } using ${ field } defined in ${ pkgJsonPath } . ${ reason ? ` ${ reason } ` : '' } ` ;
}
class ResolveError extends Error { }
class InvalidConfigurationError extends ResolveError {
constructor ( context , reason ) {
super ( createErrorMsg ( context , ` Invalid "exports" field. ${ reason } ` ) ) ;
}
}
class InvalidModuleSpecifierError extends ResolveError {
constructor ( context , internal ) {
super ( createErrorMsg ( context , internal ) ) ;
}
}
class InvalidPackageTargetError extends ResolveError {
constructor ( context , reason ) {
super ( createErrorMsg ( context , reason ) ) ;
}
}
/* eslint-disable no-await-in-loop, no-undefined */
function includesInvalidSegments ( pathSegments , moduleDirs ) {
return pathSegments
. split ( '/' )
. slice ( 1 )
. some ( ( t ) => [ '.' , '..' , ... moduleDirs ] . includes ( t ) ) ;
}
async function resolvePackageTarget ( context , { target , subpath , pattern , internal } ) {
if ( typeof target === 'string' ) {
if ( ! pattern && subpath . length > 0 && ! target . endsWith ( '/' ) ) {
throw new InvalidModuleSpecifierError ( context ) ;
}
if ( ! target . startsWith ( './' ) ) {
if ( internal && ! [ '/' , '../' ] . some ( ( p ) => target . startsWith ( p ) ) && ! isUrl ( target ) ) {
// this is a bare package import, remap it and resolve it using regular node resolve
if ( pattern ) {
const result = await context . resolveId (
target . replace ( /\*/g , subpath ) ,
context . pkgURL . href
) ;
return result ? pathToFileURL ( result . location ) : null ;
}
const result = await context . resolveId ( ` ${ target } ${ subpath } ` , context . pkgURL . href ) ;
return result ? pathToFileURL ( result . location ) : null ;
}
throw new InvalidPackageTargetError ( context , ` Invalid mapping: " ${ target } ". ` ) ;
}
if ( includesInvalidSegments ( target , context . moduleDirs ) ) {
throw new InvalidPackageTargetError ( context , ` Invalid mapping: " ${ target } ". ` ) ;
}
const resolvedTarget = new URL ( target , context . pkgURL ) ;
if ( ! resolvedTarget . href . startsWith ( context . pkgURL . href ) ) {
throw new InvalidPackageTargetError (
context ,
` Resolved to ${ resolvedTarget . href } which is outside package ${ context . pkgURL . href } `
) ;
}
if ( includesInvalidSegments ( subpath , context . moduleDirs ) ) {
throw new InvalidModuleSpecifierError ( context ) ;
}
if ( pattern ) {
return resolvedTarget . href . replace ( /\*/g , subpath ) ;
}
return new URL ( subpath , resolvedTarget ) . href ;
}
if ( Array . isArray ( target ) ) {
let lastError ;
for ( const item of target ) {
try {
const resolved = await resolvePackageTarget ( context , {
target : item ,
subpath ,
pattern ,
internal
} ) ;
// return if defined or null, but not undefined
if ( resolved !== undefined ) {
return resolved ;
}
} catch ( error ) {
if ( ! ( error instanceof InvalidPackageTargetError ) ) {
throw error ;
} else {
lastError = error ;
}
}
}
if ( lastError ) {
throw lastError ;
}
return null ;
}
if ( target && typeof target === 'object' ) {
for ( const [ key , value ] of Object . entries ( target ) ) {
if ( key === 'default' || context . conditions . includes ( key ) ) {
const resolved = await resolvePackageTarget ( context , {
target : value ,
subpath ,
pattern ,
internal
} ) ;
// return if defined or null, but not undefined
if ( resolved !== undefined ) {
return resolved ;
}
}
}
return undefined ;
}
if ( target === null ) {
return null ;
}
throw new InvalidPackageTargetError ( context , ` Invalid exports field. ` ) ;
}
/* eslint-disable no-await-in-loop */
async function resolvePackageImportsExports ( context , { matchKey , matchObj , internal } ) {
if ( ! matchKey . endsWith ( '*' ) && matchKey in matchObj ) {
const target = matchObj [ matchKey ] ;
const resolved = await resolvePackageTarget ( context , { target , subpath : '' , internal } ) ;
return resolved ;
}
const expansionKeys = Object . keys ( matchObj )
. filter ( ( k ) => k . endsWith ( '/' ) || k . endsWith ( '*' ) )
. sort ( ( a , b ) => b . length - a . length ) ;
for ( const expansionKey of expansionKeys ) {
const prefix = expansionKey . substring ( 0 , expansionKey . length - 1 ) ;
if ( expansionKey . endsWith ( '*' ) && matchKey . startsWith ( prefix ) ) {
const target = matchObj [ expansionKey ] ;
const subpath = matchKey . substring ( expansionKey . length - 1 ) ;
const resolved = await resolvePackageTarget ( context , {
target ,
subpath ,
pattern : true ,
internal
} ) ;
return resolved ;
}
if ( matchKey . startsWith ( expansionKey ) ) {
const target = matchObj [ expansionKey ] ;
const subpath = matchKey . substring ( expansionKey . length ) ;
const resolved = await resolvePackageTarget ( context , { target , subpath , internal } ) ;
return resolved ;
}
}
throw new InvalidModuleSpecifierError ( context , internal ) ;
}
async function resolvePackageExports ( context , subpath , exports ) {
if ( isMixedExports ( exports ) ) {
throw new InvalidConfigurationError (
context ,
'All keys must either start with ./, or without one.'
) ;
}
if ( subpath === '.' ) {
let mainExport ;
// If exports is a String or Array, or an Object containing no keys starting with ".", then
if ( typeof exports === 'string' || Array . isArray ( exports ) || isConditions ( exports ) ) {
mainExport = exports ;
} else if ( isMappings ( exports ) ) {
mainExport = exports [ '.' ] ;
}
if ( mainExport ) {
const resolved = await resolvePackageTarget ( context , { target : mainExport , subpath : '' } ) ;
if ( resolved ) {
return resolved ;
}
}
} else if ( isMappings ( exports ) ) {
const resolvedMatch = await resolvePackageImportsExports ( context , {
matchKey : subpath ,
matchObj : exports
} ) ;
if ( resolvedMatch ) {
return resolvedMatch ;
}
}
throw new InvalidModuleSpecifierError ( context ) ;
}
async function resolvePackageImports ( {
importSpecifier ,
importer ,
moduleDirs ,
conditions ,
resolveId
} ) {
const result = await findPackageJson ( importer , moduleDirs ) ;
if ( ! result ) {
throw new Error ( createBaseErrorMsg ( '. Could not find a parent package.json.' ) ) ;
}
const { pkgPath , pkgJsonPath , pkgJson } = result ;
const pkgURL = pathToFileURL ( ` ${ pkgPath } / ` ) ;
const context = {
importer ,
importSpecifier ,
moduleDirs ,
pkgURL ,
pkgJsonPath ,
conditions ,
resolveId
} ;
const { imports } = pkgJson ;
if ( ! imports ) {
throw new InvalidModuleSpecifierError ( context , true ) ;
}
if ( importSpecifier === '#' || importSpecifier . startsWith ( '#/' ) ) {
throw new InvalidModuleSpecifierError ( context , 'Invalid import specifier.' ) ;
}
return resolvePackageImportsExports ( context , {
matchKey : importSpecifier ,
matchObj : imports ,
internal : true
} ) ;
}
const resolveImportPath = promisify ( resolve$1 ) ;
const readFile$1 = promisify ( fs . readFile ) ;
async function getPackageJson ( importer , pkgName , resolveOptions , moduleDirectories ) {
if ( importer ) {
const selfPackageJsonResult = await findPackageJson ( importer , moduleDirectories ) ;
if ( selfPackageJsonResult && selfPackageJsonResult . pkgJson . name === pkgName ) {
// the referenced package name is the current package
return selfPackageJsonResult ;
}
}
try {
const pkgJsonPath = await resolveImportPath ( ` ${ pkgName } /package.json ` , resolveOptions ) ;
const pkgJson = JSON . parse ( await readFile$1 ( pkgJsonPath , 'utf-8' ) ) ;
return { pkgJsonPath , pkgJson } ;
} catch ( _ ) {
return null ;
}
}
async function resolveId ( {
importer ,
importSpecifier ,
exportConditions ,
warn ,
packageInfoCache ,
extensions ,
mainFields ,
preserveSymlinks ,
useBrowserOverrides ,
baseDir ,
moduleDirectories ,
rootDir ,
ignoreSideEffectsForRoot
} ) {
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 ,
rootDir ,
ignoreSideEffectsForRoot
} ) ;
( { 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 ( importSpecifier ) ;
if ( importSpecifier . startsWith ( '#' ) ) {
// this is a package internal import, resolve using package imports field
const resolveResult = await resolvePackageImports ( {
importSpecifier ,
importer ,
moduleDirs : moduleDirectories ,
conditions : exportConditions ,
resolveId ( id , parent ) {
return resolveId ( {
importSpecifier : id ,
importer : parent ,
exportConditions ,
warn ,
packageInfoCache ,
extensions ,
mainFields ,
preserveSymlinks ,
useBrowserOverrides ,
baseDir ,
moduleDirectories
} ) ;
}
} ) ;
location = fileURLToPath ( resolveResult ) ;
} else if ( pkgName ) {
// it's a bare import, find the package.json and resolve using package exports if available
const result = await getPackageJson ( importer , pkgName , resolveOptions , moduleDirectories ) ;
if ( result && result . pkgJson . exports ) {
const { pkgJson , pkgJsonPath } = result ;
try {
const subpath =
pkgName === importSpecifier ? '.' : ` . ${ importSpecifier . substring ( pkgName . length ) } ` ;
const pkgDr = pkgJsonPath . replace ( 'package.json' , '' ) ;
const pkgURL = pathToFileURL ( pkgDr ) ;
const context = {
importer ,
importSpecifier ,
moduleDirs : moduleDirectories ,
pkgURL ,
pkgJsonPath ,
conditions : exportConditions
} ;
const resolvedPackageExport = await resolvePackageExports (
context ,
subpath ,
pkgJson . exports
) ;
location = fileURLToPath ( resolvedPackageExport ) ;
} catch ( error ) {
if ( error instanceof ResolveError ) {
return error ;
}
throw error ;
}
}
}
if ( ! location ) {
// package has no imports or exports, use classic node resolve
try {
location = await resolveImportPath ( importSpecifier , 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 ( {
importer ,
importSpecifierList ,
exportConditions ,
warn ,
packageInfoCache ,
extensions ,
mainFields ,
preserveSymlinks ,
useBrowserOverrides ,
baseDir ,
moduleDirectories ,
rootDir ,
ignoreSideEffectsForRoot
} ) {
let lastResolveError ;
for ( let i = 0 ; i < importSpecifierList . length ; i ++ ) {
// eslint-disable-next-line no-await-in-loop
const result = await resolveId ( {
importer ,
importSpecifier : importSpecifierList [ i ] ,
exportConditions ,
warn ,
packageInfoCache ,
extensions ,
mainFields ,
preserveSymlinks ,
useBrowserOverrides ,
baseDir ,
moduleDirectories ,
rootDir ,
ignoreSideEffectsForRoot
} ) ;
if ( result instanceof ResolveError ) {
lastResolveError = result ;
} else if ( result ) {
return result ;
}
}
if ( lastResolveError ) {
// only log the last failed resolve error
warn ( lastResolveError ) ;
}
return null ;
}
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 } ;
}
/* eslint-disable no-param-reassign, no-shadow, no-undefined */
const builtins = new Set ( builtinList ) ;
const ES6 _BROWSER _EMPTY = '\0node-resolve:empty.js' ;
const deepFreeze = ( object ) => {
Object . freeze ( object ) ;
for ( const value of Object . values ( object ) ) {
if ( typeof value === 'object' && ! Object . isFrozen ( value ) ) {
deepFreeze ( value ) ;
}
}
return object ;
} ;
const baseConditions = [ 'default' , 'module' ] ;
const baseConditionsEsm = [ ... baseConditions , 'import' ] ;
const baseConditionsCjs = [ ... baseConditions , 'require' ] ;
const defaults = {
dedupe : [ ] ,
// It's important that .mjs is listed before .js so that Rollup will interpret npm modules
// which deploy both ESM .mjs and CommonJS .js files as ESM.
extensions : [ '.mjs' , '.js' , '.json' , '.node' ] ,
resolveOnly : [ ] ,
moduleDirectories : [ 'node_modules' ] ,
ignoreSideEffectsForRoot : false
} ;
const DEFAULTS = deepFreeze ( deepMerge ( { } , defaults ) ) ;
function nodeResolve ( opts = { } ) {
const { warnings } = handleDeprecatedOptions ( opts ) ;
const options = { ... defaults , ... opts } ;
const { extensions , jail , moduleDirectories , ignoreSideEffectsForRoot } = options ;
const conditionsEsm = [ ... baseConditionsEsm , ... ( options . exportConditions || [ ] ) ] ;
const conditionsCjs = [ ... baseConditionsCjs , ... ( options . exportConditions || [ ] ) ] ;
const packageInfoCache = new Map ( ) ;
const idToPackageInfo = new Map ( ) ;
const mainFields = getMainFields ( options ) ;
const useBrowserOverrides = mainFields . indexOf ( 'browser' ) !== - 1 ;
const isPreferBuiltinsSet = options . preferBuiltins === true || options . preferBuiltins === false ;
const preferBuiltins = isPreferBuiltinsSet ? options . preferBuiltins : true ;
const rootDir = resolve ( options . rootDir || process . cwd ( ) ) ;
let { dedupe } = options ;
let rollupOptions ;
if ( typeof dedupe !== 'function' ) {
dedupe = ( importee ) =>
options . dedupe . includes ( importee ) || options . dedupe . includes ( getPackageName ( importee ) ) ;
}
const resolveOnly = options . resolveOnly . map ( ( pattern ) => {
if ( pattern instanceof RegExp ) {
return pattern ;
}
const normalized = pattern . replace ( /[\\^$*+?.()|[\]{}]/g , '\\$&' ) ;
return new RegExp ( ` ^ ${ normalized } $ ` ) ;
} ) ;
const browserMapCache = new Map ( ) ;
let preserveSymlinks ;
return {
name : 'node-resolve' ,
buildStart ( options ) {
rollupOptions = options ;
for ( const warning of warnings ) {
this . warn ( warning ) ;
}
( { preserveSymlinks } = options ) ;
} ,
generateBundle ( ) {
readCachedFile . clear ( ) ;
isFileCached . clear ( ) ;
isDirCached . clear ( ) ;
} ,
async resolveId ( importee , importer , opts ) {
if ( importee === ES6 _BROWSER _EMPTY ) {
return importee ;
}
// ignore IDs with null character, these belong to other plugins
if ( /\0/ . test ( importee ) ) return null ;
if ( /\0/ . test ( importer ) ) {
importer = undefined ;
}
// strip query params from import
const [ importPath , params ] = importee . split ( '?' ) ;
const importSuffix = ` ${ params ? ` ? ${ params } ` : '' } ` ;
importee = importPath ;
const baseDir = ! importer || dedupe ( importee ) ? rootDir : dirname ( importer ) ;
// https://github.com/defunctzombie/package-browser-field-spec
const browser = browserMapCache . get ( importer ) ;
if ( useBrowserOverrides && browser ) {
const resolvedImportee = resolve ( baseDir , importee ) ;
if ( browser [ importee ] === false || browser [ resolvedImportee ] === false ) {
return ES6 _BROWSER _EMPTY ;
}
const browserImportee =
browser [ importee ] ||
browser [ resolvedImportee ] ||
browser [ ` ${ resolvedImportee } .js ` ] ||
browser [ ` ${ resolvedImportee } .json ` ] ;
if ( browserImportee ) {
importee = browserImportee ;
}
}
const parts = importee . split ( /[/\\]/ ) ;
let id = parts . shift ( ) ;
let isRelativeImport = false ;
if ( id [ 0 ] === '@' && parts . length > 0 ) {
// scoped packages
id += ` / ${ parts . shift ( ) } ` ;
} else if ( id [ 0 ] === '.' ) {
// an import relative to the parent dir of the importer
id = resolve ( baseDir , importee ) ;
isRelativeImport = true ;
}
if (
! isRelativeImport &&
resolveOnly . length &&
! resolveOnly . some ( ( pattern ) => pattern . test ( id ) )
) {
if ( normalizeInput ( rollupOptions . input ) . includes ( importee ) ) {
return null ;
}
return false ;
}
const importSpecifierList = [ ] ;
if ( importer === undefined && ! importee [ 0 ] . match ( /^\.?\.?\// ) ) {
// For module graph roots (i.e. when importer is undefined), we
// need to handle 'path fragments` like `foo/bar` that are commonly
// found in rollup config files. If importee doesn't look like a
// relative or absolute path, we make it relative and attempt to
// resolve it. If we don't find anything, we try resolving it as we
// got it.
importSpecifierList . push ( ` ./ ${ importee } ` ) ;
}
const importeeIsBuiltin = builtins . has ( importee ) ;
if ( importeeIsBuiltin ) {
// The `resolve` library will not resolve packages with the same
// name as a node built-in module. If we're resolving something
// that's a builtin, and we don't prefer to find built-ins, we
// first try to look up a local module with that name. If we don't
// find anything, we resolve the builtin which just returns back
// the built-in's name.
importSpecifierList . push ( ` ${ importee } / ` ) ;
}
// TypeScript files may import '.js' to refer to either '.ts' or '.tsx'
if ( importer && importee . endsWith ( '.js' ) ) {
for ( const ext of [ '.ts' , '.tsx' ] ) {
if ( importer . endsWith ( ext ) && extensions . includes ( ext ) ) {
importSpecifierList . push ( importee . replace ( /.js$/ , ext ) ) ;
}
}
}
importSpecifierList . push ( importee ) ;
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 ( {
importer ,
importSpecifierList ,
exportConditions ,
warn ,
packageInfoCache ,
extensions ,
mainFields ,
preserveSymlinks ,
useBrowserOverrides ,
baseDir ,
moduleDirectories ,
rootDir ,
ignoreSideEffectsForRoot
} ) ;
const resolved =
importeeIsBuiltin && preferBuiltins
? {
packageInfo : undefined ,
hasModuleSideEffects : ( ) => null ,
hasPackageEntry : true ,
packageBrowserField : false
}
: resolvedWithoutBuiltins ;
if ( ! resolved ) {
return null ;
}
const { packageInfo , hasModuleSideEffects , hasPackageEntry , packageBrowserField } = resolved ;
let { location } = resolved ;
if ( packageBrowserField ) {
if ( Object . prototype . hasOwnProperty . call ( packageBrowserField , location ) ) {
if ( ! packageBrowserField [ location ] ) {
browserMapCache . set ( location , packageBrowserField ) ;
return ES6 _BROWSER _EMPTY ;
}
location = packageBrowserField [ location ] ;
}
browserMapCache . set ( location , packageBrowserField ) ;
}
if ( hasPackageEntry && ! preserveSymlinks ) {
const fileExists = await exists ( location ) ;
if ( fileExists ) {
location = await realpath ( location ) ;
}
}
idToPackageInfo . set ( location , packageInfo ) ;
if ( hasPackageEntry ) {
if ( importeeIsBuiltin && preferBuiltins ) {
if ( ! isPreferBuiltinsSet && resolvedWithoutBuiltins && resolved !== importee ) {
this . warn (
` 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 ;
}
}
if ( options . modulesOnly && ( await exists ( location ) ) ) {
const code = await readFile ( location , 'utf-8' ) ;
if ( isModule ( code ) ) {
return {
id : ` ${ location } ${ importSuffix } ` ,
moduleSideEffects : hasModuleSideEffects ( location )
} ;
}
return null ;
}
const result = {
id : ` ${ location } ${ importSuffix } ` ,
moduleSideEffects : hasModuleSideEffects ( location )
} ;
return result ;
} ,
load ( importee ) {
if ( importee === ES6 _BROWSER _EMPTY ) {
return 'export default {};' ;
}
return null ;
} ,
getPackageInfoForId ( id ) {
return idToPackageInfo . get ( id ) ;
}
} ;
}
export default nodeResolve ;
export { DEFAULTS , nodeResolve } ;