ECMAScript module utilities.
- What is this?
- Install
- Use
- API
canParseUrl(input[, base])cwd()defaultConditionsdefaultExtensionsdefaultMainFieldsextensionFormatMapformatsgetSource<T>(id[, options])isAbsoluteSpecifier(value)isArrayIndex(value)isBareSpecifier(value)isDirectory<T>(id[, fs])isFile<T>(id[, fs])isImportsSubpath(value)isModuleId(value)isRelativeSpecifier(value)legacyMainResolve<T>(packageUrl[, manifest][, mainFields][, parent][, fs])lookupPackageScope<T>(url[, end][, fs])moduleResolve<T>(specifier, parent[, conditions][, mainFields][, preserveSymlinks][, fs])packageExportsResolve<T>(packageUrl, subpath, exports[, conditions][, parent][, fs])packageImportsExportsResolve<T>(matchKey, matchObject, packageUrl[, isImports][, conditions][, mainFields][, parent][, fs])packageImportsResolve<T>(specifier, parent[, conditions][, mainFields][, fs])packageResolve<T>(specifier, parent[, conditions][, mainFields][, fs])packageSelfResolve<T>(name, subpath, parent[, conditions][, fs])packageTargetResolve<T>(packageUrl, target, subpath[, patternMatch][, isImports][, conditions][, mainFields][, parent][, fs])patternKeyCompare(a, b)patternMatch(matchKey, matchObject)readPackageJson<T>(id[, specifier][, parent][, fs])resolveAlias(specifier[, options])resolveModule<T>(specifier, parent[, options])resolverroottoRelativeSpecifier(url, parent)toUrl(id[, parent])
- Types
AliasesAwaitable<T>BufferEncodingMapBufferEncodingChangeExtFn<[Ext]>ConditionMapConditionDotEmptyArrayEmptyObjectEmptyStringExtFileContentFileSystemGetSourceContextGetSourceHandlerGetSourceHandlersGetSourceOptionsIsDirectoryIsFileList<[T]>MainFieldMapMainFieldModuleFormatMapModuleFormatModuleIdNumericPatternKeyComparisonMapPatternKeyComparisonPatternMatchProtocolMapProtocolReadFileRealpathResolveAliasOptionsResolveModuleOptionsStatStats
- Additional Documentation
- Contribute
mlly is a set of ECMAScript module (ESM) utilities.
It exposes several tools to bridge the gap between developer experience and the current state of ECMAScript modules.
This package is ESM only.
In Node.js (version 20+) with yarn:
yarn add @flex-development/mllySee Git - Protocols | Yarn Β for details regarding installing from Git.
In Deno with esm.sh:
import { resolveModule } from 'https://esm.sh/@flex-development/mlly'In browsers with esm.sh:
<script type="module">
import { resolveModule } from 'https://esm.sh/@flex-development/mlly'
</script>import {
lookupPackageScope,
readPackageJson,
resolveModule,
type FileSystem
} from '@flex-development/mlly'
import pkg from '@flex-development/mlly/package.json' with { type: 'json' }
import type { PackageJson } from '@flex-development/pkg-types'
import nfs from 'node:fs'
/**
* A file system API with both asynchronous and synchronous methods.
*
* @const {FileSystem} fs
*/
const fs: FileSystem = {
readFile: nfs.promises.readFile,
realpath: nfs.promises.realpath,
stat: nfs.statSync
}
/**
* The URL of the package directory.
*
* @const {URL | null} scope
*/
const scope: URL | null = lookupPackageScope(import.meta.url, null, fs)
console.dir(scope) // file:///Users/lex/Projects/flex-development/mlly/
/**
* The package manifest.
*
* @const {PackageJson | null} manifest
*/
const manifest: PackageJson | null = await readPackageJson(
scope,
null,
import.meta.url,
fs
)
console.dir(manifest?.name === pkg.name) // true
console.dir(manifest) // `pkg`
/**
* A fully resolved URL.
*
* @const {URL} resolved
*/
const resolved = resolveModule(pkg.name, import.meta.url, {
conditions: new Set(['mlly']),
ext: null
})
console.dir(resolved) // file:///Users/lex/Projects/flex-development/mlly/src/mlly exports the identifiers listed below.
There is no default export.
Check if input can be parsed to a URL.
π Note: If
inputis relative,baseis required. Ifinputis absolute,baseis ignored.
id(unknown) β the input urlbase(unknown) β the base url to resolve against ifinputis not absolute
(boolean) true if input can be parsed to a URL, false otherwise
Get the URL of the current working directory.
(URL) The current working directory URL
The default list of conditions.
The default list of resolvable file extensions.
The default list of main fields.
Map<Ext, ModuleFormat>
Map, where each key is a file extension and each value is a default module format.
Default module formats (const enum).
const enum formats {
builtin = 'builtin',
commonjs = 'commonjs',
cts = 'commonjs-typescript',
json = 'json',
module = 'module',
mts = 'module-typescript',
wasm = 'wasm'
}Get the source code for a module.
π Note: Returns a promise if the handler for
idis async.
T(Awaitable<FileContent | null | undefined>) β the module source code
id(ModuleId|null|undefined) β the module idoptions(GetSourceOptions|null|undefined) β source code retrieval options
(T) The module source code
Check if value is an absolute specifier.
π Note: Only checks specifier syntax.
Does not guarantee the specifier references an existing module.
value(unknown) β the value to check
(boolean) true if value is absolute specifier, false otherwise
Check if value is a valid array index.
value(unknown) β the value to check
(value is Numeric) true if value is valid array index, false otherwise
Check if value is a bare specifier.
π Note: Only checks specifier syntax.
Does not guarantee the specifier references an existing module.
value(unknown) β the value to check
(boolean) true if value is bare specifier, false otherwise
Check if a directory exists.
π Note: Returns a promise if
fs.statis async.
T(Awaitable<boolean>) β the result of the check
id(ModuleId) β the module id to checkfs(FileSystem|null|undefined) β the file system api
(T) true if directory exists at id, false otherwise
Check if a file exists.
π Note: Returns a promise if
fs.statis async.
T(Awaitable<boolean>) β the result of the check
id(ModuleId) β the module id to checkfs(FileSystem|null|undefined) β the file system api
(T) true if file exists at id, false otherwise
Check if value is an imports subpath.
π Note: Only checks specifier syntax.
Does not guarantee the specifier references an existing module.
value(unknown) β the value to check
(value is ImportsSubpath) true if value is imports subpath, false otherwise
Check if value is a module id.
value(unknown) β the value to check
(value is ModuleId) true if value is module id, false otherwise
Check if value is a relative specifier.
π Note: Only checks specifier syntax.
Does not guarantee the specifier references an existing module.
value(unknown) β the value to check
(boolean) true if value is relative specifier, false otherwise
Resolve a main-like package entry point.
Implements the LEGACY_MAIN_RESOLVE resolution algorithm.
π Note: Returns a promise if
fs.statis async.
T(Awaitable<URL>) β the resolved entry point url
packageUrl(ModuleId) β the url of the package directory, thepackage.jsonfile, or a module in the same directory as apackage.jsonmanifest(PackageJson|null|undefined) β the package manifestmainFields(List<MainField>|null|undefined) β the list of legacy main fields- default:
defaultMainFields
- default:
parent(ModuleId|null|undefined) β the url of the parent modulefs(FileSystem|null|undefined) β the file system api
(T) The resolved entry point URL
Get the package scope URL for a module url.
Implements the LOOKUP_PACKAGE_SCOPE algorithm.
π Note: Returns a promise if
fs.statis async.
function lookupPackageScope(
this: void,
url: EmptyString | null | undefined,
end?: ModuleId | null | undefined,
fs?: FileSystem | null | undefined
): nullfunction lookupPackageScope<T extends Awaitable<URL | null>>(
this: void,
url: ModuleId | null | undefined,
end?: ModuleId | null | undefined,
fs?: FileSystem | null | undefined
): TT(Awaitable<URL | null>) β the resolved package scope url
id(ModuleId|null|undefined) β the url of the module to scopeend(ModuleId|null|undefined) β the url of the directory to end search at- default:
root
- default:
fs(FileSystem|null|undefined) β the file system api
(T) The URL of nearest directory containing a package.json file
Resolve a module specifier.
Implements the ESM_RESOLVE algorithm.
π Note: Returns a promise if
fs.realpathorfs.statis async, or one the following methods returns a promise:packageImportsResolve,packageResolve.
T(Awaitable<URL>) β the resolved url
specifier(string) β the module specifier to resolveparent(ModuleId) β the url of the parent moduleconditions(List<Condition>|null|undefined) β the list of export/import conditions- default:
defaultConditions
- default:
mainFields(List<MainField>|null|undefined) β the list of legacy main fields- default:
defaultMainFields
- default:
preserveSymlinks(boolean|null|undefined) β whether to keep symlinks instead of resolving themfs(FileSystem|null|undefined) β the file system api
(T) The resolved URL
Resolve a package export.
Implements the PACKAGE_EXPORTS_RESOLVE algorithm.
π Note: Never returns a promisee.
T(Awaitable<URL>) β the resolved package export url
packageUrl(ModuleId) β the url of the package directory, thepackage.jsonfile, or a module in the same directory as apackage.jsonsubpath(string) β the package subpathexports(Exports|undefined) β the package exportsconditions(List<Condition>|null|undefined) β the list of export/import conditions- default:
defaultConditions
- default:
parent(ModuleId|null|undefined) β the url of the parent modulefs(FileSystem|null|undefined) β the file system api
(T) The resolved package export URL
packageImportsExportsResolve<T>(matchKey, matchObject, packageUrl[, isImports][, conditions][, mainFields][, parent][, fs])
Resolve a package export or import.
Implements the PACKAGE_IMPORTS_EXPORTS_RESOLVE algorithm.
π Note: Returns a promise if
packageTargetResolve, returns a promise.
T(Awaitable<URL | null | undefined>) β the resolved package export or import url
matchKey(string) β the package subpath extracted from a module specifier, or a dot character (.)matchObject(ExportsObject|Imports|null|undefined) β the package exports or importspackageUrl(ModuleId) β the url of the directory containing thepackage.jsonfileisImports(boolean|null|undefined) β whethermatchObjectis internal to the packageconditions(List<Condition>|null|undefined) β the list of export/import conditions- default:
defaultConditions
- default:
mainFields(List<MainField>|null|undefined) β the list of legacy main fields- default:
defaultMainFields
- default:
parent(ModuleId|null|undefined) β the url of the parent modulefs(FileSystem|null|undefined) β the file system api
(T) The resolved package export or import URL
Resolve a package import.
Implements the PACKAGE_IMPORTS_RESOLVE algorithm.
π Note: Returns a promise if
lookupPackageScope,packageImportsExportsResolve, orreadPackageJsonreturns a promise.
T(Awaitable<URL>) β the resolved package import url
specifier(string) β the import specifier to resolveparent(ModuleId) β the url of the parent moduleconditions(List<Condition>|null|undefined) β the list of export conditions- default:
defaultConditions
- default:
mainFields(List<MainField>|null|undefined) β the list of legacy main fields- default:
defaultMainFields
- default:
fs(FileSystem|null|undefined) β the file system api
(T) The resolved package import URL
Resolve a bare specifier.
Implements the PACKAGE_RESOLVE algorithm.
Bare specifiers like
'some-package'or'some-package/shuffle'refer to the main entry point of a package by package name, or a specific feature module within a package prefixed by the package name. Including the file extension is only necessary for packages without anexportsfield.
π Note: Returns a promise if
fs.statis async or one of the following methods returns a promise:legacyMainResolve,packageExportsResolve,packageSelfResolve, orreadPackageJson.
T(Awaitable<URL>) β the resolved package url
specifier(string) β the package specifierparent(ModuleId) β the url of the parent moduleconditions(List<Condition>|null|undefined) β the list of export conditions- default:
defaultConditions
- default:
mainFields(List<MainField>|null|undefined) β the list of legacy main fields- default:
defaultMainFields
- default:
fs(FileSystem|null|undefined) β the file system api
(T) The resolved package URL
Resolve the self-import of a package.
Implements the PACKAGE_SELF_RESOLVE algorithm.
π Note: Returns a promise if
lookupPackageScope,packageExportsResolve, orreadPackageJsonreturns a promise.
T(Awaitable<URL | undefined>) β the resolved package url
name(string) β the package namesubpath(string) β the package subpathparent(ModuleId) β the url of the parent moduleconditions(List<Condition>|null|undefined) β the list of export conditions- default:
defaultConditions
- default:
fs(FileSystem|null|undefined) β the file system api
(T) The resolved package URL
packageTargetResolve<T>(packageUrl, target, subpath[, patternMatch][, isImports][, conditions][, mainFields][, parent][, fs])
Resolve a package target.
Implements the PACKAGE_TARGET_RESOLVE algorithm.
π Note: Returns a promise if
targetis internal to the package andpackageResolvereturns a promise.
T(Awaitable<URL | null | undefined>) β the resolved package target url
packageUrl(ModuleId) β the url of the directory containing thepackage.jsonfiletarget(unknown) β the package target (i.e. aexports/importsvalue)subpath(string) β the package subpath (i.e. aexports/importskey)patternMatch(string|null|undefined) β thesubpathpattern matchisImports(boolean|null|undefined) β whethertargetis internal to the packageconditions(List<Condition>|null|undefined) β the list of export/import conditions- default:
defaultConditions
- default:
mainFields(List<MainField>|null|undefined) β the list of legacy main fields- default:
defaultMainFields
- default:
parent(ModuleId) β the url of the parent modulefs(FileSystem|null|undefined) β the file system api
(T) The resolved package target URL
Compare two pattern keys and return a value indicating their order.
Implements the PATTERN_KEY_COMPARE algorithm.
a(string) β the first keyb(string) β the key to compare againsta
(PatternKeyComparison) The pattern key comparsion result
Get a subpath pattern match for matchKey.
matchKey(string) β the key to expandmatchObject(unknown) β the match keys object
(PatternMatch | null) List, where the first item is the key of a package exports or imports target
object, and the last is a subpath pattern match
Read a package.json file.
Implements the READ_PACKAGE_JSON algorithm.
π Note: Returns a promise if
fs.readFileorfs.statis async.
function readPackageJson(
this: void,
id: EmptyString | null | undefined,
specifier?: string | null | undefined,
parent?: ModuleId | null | undefined,
fs?: FileSystem | null | undefined
): nullfunction readPackageJson<T extends Awaitable<PackageJson | null>>(
this: void,
id: ModuleId | null | undefined,
specifier?: string | null | undefined,
parent?: ModuleId | null | undefined,
fs?: FileSystem | null | undefined
): TT(Awaitable<PackageJson | null>) β the parsed file contents
id(ModuleId|null|undefined) β the url of the package directory, thepackage.jsonfile, or a module in the same directory as apackage.jsonspecifier(string|null|undefined) β the module specifier that initiated the reading of thepackage.jsonfileπ note: should be a
file:url ifparentis not a urlparent(ModuleId|null|undefined) β the url of the parent modulefs(FileSystem|null|undefined) β the file system api
(T) The parsed file contents
Resolve an aliased specifier.
specifier(string) β the specifier using an aliasoptions(ResolveAliasOptions|null|undefined) β alias resolution options
(string | null) The specifier of the aliased module
Resolve a module specifier.
Implements the ESM_RESOLVE algorithm, mostly π.
Adds support for:
- Changing file extensions
- Directory index resolution
- Extensionless file resolution
- Path alias resolution
- Scopeless
@types/*resolution (i.e.unist->@types/unist)
π Note: Returns a promise if
moduleResolvereturns a promise.
T(Awaitable<URL>) β the resolved url
specifier(string) β the module specifier to resolveparent(ModuleId) β the url of the parent moduleoptions(ResolveModuleOptions) β module resolution options
(T) The resolved URL
An object containing resolution algorithm implementations.
legacyMainResolvemoduleResolvepackageExportsResolvepackageImportsExportsResolvepackageImportsResolvepackageResolvepackageSelfResolvepackageTargetResolve
URL
The URL of the file system root.
Turn url into a relative specifier.
π Note: The relative specifier will only have a file extension if
specifieralso has an extension.
(string) The relative specifier
Convert id to a URL.
π Note: If
idcannot be parsed as aURLand is also not a builtin module, it will be assumed to be a path and converted to afile:URL.
id(ModuleId) β the module id to convertparent(ModuleId|null|undefined) β the base url to resolve against ifidis not absolute
(URL) The new URL
This package is fully typed with TypeScript.
Record, where each key is a path alias or pattern
and each value is a path mapping configuration (interface).
interface Aliases {
[alias: string]: (string | null | undefined)[] | string | null | undefined
}When developing extensions that use additional aliases, augment Aliases to register custom aliases:
declare module '@flex-development/mlly' {
interface Aliases {
custom?: string[] | string | null
}
}Create a union of T and T as a promise-like object (type).
type Awaitable<T> = PromiseLike<T> | TT(any)- the value
Registry of character encodings that can be used when working with Buffer objects (interface).
When developing extensions that use additional encodings, augment BufferEncodingMap to register custom encodings:
declare module '@flex-development/mlly' {
interface BufferEncodingMap {
custom: 'custom'
}
}Union of values that can occur where a buffer encoding is expected (type).
To register new encodings, augment BufferEncodingMap.
They will be added to this union automatically.
type BufferEncoding = BufferEncodingMap[keyof BufferEncodingMap]Get a new file extension for url (type).
Returning an empty string (''), null, or undefined will remove the current file extension.
type ChangeExtFn<
Ext extends string | null | undefined = string | null | undefined
> = (this: void, url: URL, specifier: string) => ExtExt(string|null|undefined, optional) β the new file extension
url(URL) β the resolved module URLspecifier(string) β the module specifier being resolved
(Ext) The new file extension
Registry of export/import conditions (interface).
When developing extensions that use additional conditions, augment ConditionMap to register custom conditions:
declare module '@flex-development/mlly' {
interface ConditionMap {
custom: 'custom'
}
}Union of values that can occur where a export/import condition is expected (type).
To register new conditions, augment ConditionMap.
They will be added to this union automatically.
type Condition = ConditionMap[keyof ConditionMap]A dot character ('.') (type).
type Dot = '.'An empty array (type).
type EmptyArray = []An empty object (type).
type EmptyObject = { [tag]?: never }An empty string (type).
type EmptyString = ''A file extension (type).
type Ext = `${Dot}${string}`Union of values that can occur where file content is expected (type).
type FileContent = Uint8Array | stringThe file system API (interface).
readFile(ReadFile) β read the entire contents of a filerealpath(Realpath) β compute a canonical pathname by resolving.,.., and symbolic linksstat(Stat) β get information about a directory or file
Source code retrieval context (interface).
fs(FileSystem) β the file system apihandlers(GetSourceHandlers) β record, where each key is a url protocol and each value is a source code handlerreq(RequestInit) β request options for network based modulesschemes(Set<string>) β the list of supported url schemes
Get the source code for a module (type).
type GetSourceHandler = (
this: GetSourceContext,
url: URL
) => Awaitable<FileContent | null | undefined>this(GetSourceContext) β the retrieval contexturl(URL) β the module URL
(Awaitable<FileContent | null | undefined>) The source code
Record, where key is a URL protocol and each value is a source code handler (type).
type GetSourceHandlers = {
[H in Protocol]?: GetSourceHandler | null | undefined
}Options for retrieving source code (interface).
encoding?(BufferEncoding|null|undefined) β the encoding of the resultπ note: used when the
file:handler is calledformat?(ModuleFormat|null|undefined) β the module format hintfs?(FileSystem|null|undefined) β the file system apihandlers?(GetSourceHandlers|null|undefined) β record, where each key is a url protocol and each value is a source code handlerignoreErrors?(boolean|null|undefined) β whether to ignoreERR_UNSUPPORTED_ESM_URL_SCHEMEif thrownreq?(RequestInit|null|undefined) β request options for network based modulesschemes?(List<string>|null|undefined) β the list of supported url schemes- default:
['data', 'file', 'http', 'https', 'node']
- default:
Check if a stats object describes a directory (interface).
(boolean) true if stats describes directory, false otherwise
Check if a stats object describes a file (interface).
(boolean) true if stats describes regular file, false otherwise
A list (type).
type List<T = unknown> = ReadonlySet<T> | readonly T[]T(any, optional) β list item type
Registry of main fields (interface).
When developing extensions that use additional fields, augment MainFieldMap to register custom fields:
declare module '@flex-development/mlly' {
interface MainFieldMap {
unpkg: 'unpkg'
}
}Union of values that can occur where a main field is expected (type).
To register new main fields, augment MainFieldMap.
They will be added to this union automatically.
type MainField = MainFieldMap[keyof MainFieldMap]Registry of module formats (interface).
When developing extensions that use additional formats, augment ModuleFormatMap to register custom formats:
declare module '@flex-development/mlly' {
interface ModuleFormatMap {
custom: 'custom'
}
}Union of values that can occur where a module format is expected (type).
To register new main formats, augment ModuleFormatMap.
They will be added to this union automatically.
type ModuleFormat = ModuleFormatMap[keyof ModuleFormatMap]Union of values that can occur where a ECMAScript (ES) module identifier is expected (type).
type ModuleId = URL | stringA string that can be parsed to a valid number (type).
type Numeric = `${number}`Registry of PATTERN_KEY_COMPARE algorithm results (interface).
When developing extensions that use additional results, augment PatternKeyComparsionMap to register custom results:
declare module '@flex-development/mlly' {
interface PatternKeyComparsionMap {
afterThree: 3
}
}Union of values that can occur where a PATTERN_KEY_COMPARE algorithm result
is expected (type).
To register new results, augment PatternKeyComparisonMap.
They will be added to this union automatically.
type PatternKeyComparison =
PatternKeyComparisonMap[keyof PatternKeyComparisonMap]List, where the first item is the key of a package exports or imports target object,
and the last is a subpath pattern match (type).
type PatternMatch = [expansionKey: string, patternMatch: string | null]Registry of URL protocols (interface).
When developing extensions that use additional protocols, augment ProtocolMap to register custom protocols:
declare module '@flex-development/mlly' {
interface ProtocolMap {
custom: 'custom:'
}
}Union of values that can occur where a URL protocol is expected (type).
To register new results, augment ProtocolMap.
They will be added to this union automatically.
type Protocol = ProtocolMap[keyof ProtocolMap]Read the entire contents of a file (interface).
(id: ModuleId, encoding: BufferEncoding): Awaitable<string>
<T extends Awaitable<FileContent | null | undefined>>(id: ModuleId, encoding?: BufferEncoding | null | undefined): TT(Awaitable<FileContent | null | undefined>, optional) β the file contents- default:
Awaitable<FileContent>
- default:
id(ModuleId) β the module idencoding(BufferEncoding) β the encoding of the file contents
(T) The file contents
Compute a canonical pathname by resolving ., .., and symbolic links (interface).
π Note: A canonical pathname is not necessarily unique. Hard links and bind mounts can expose an entity through many pathnames.
T(Awaitable<string>, optional) β the canonical pathname
id(ModuleId) β the module id
(T) The canonical pathname
Options for path alias resolution (interface).
absolute?(boolean|null|undefined) β whether the resolved specifier should be absolute.
iftrue, the resolved specifier will be afile:URLaliases?(Aliases|null|undefined) β the path mappings dictionaryπ note: paths should be relative to
cwdcwd?(ModuleId|null|undefined) β the url of the directory to resolve non-absolute modules from- default:
cwd()
- default:
parent?(ModuleId|null|undefined) β the url of the parent module
Options for path alias resolution (interface).
aliases?(Aliases|null|undefined) β the path mappings dictionaryπ note: paths should be relative to
cwdconditions?(List<Condition>|null|undefined) β the list of export/import conditions- default:
defaultConditions
π note: should be sorted by priority
- default:
cwd?(ModuleId|null|undefined) β the url of the directory to resolve pathaliasesfrom- default:
cwd()
- default:
ext?(ChangeExtFn|string|null|undefined) β a replacement file extension or a function that returns a file extension.π note: an empty string (
'') ornullwill remove a file extensionextensions?(List<string>|null|undefined) β the module extensions to probe for- default:
defaultExtensions
π note: should be sorted by priority
- default:
fs?(FileSystem|null|undefined) β the file system apimainFields?(List<MainField>|null|undefined) β the list of legacymainfields- default:
defaultMainFields
π note: should be sorted by priority
- default:
preserveSymlinks?(boolean|null|undefined) β whether to keep symlinks instead of resolving them
Get information about a directory or file (interface).
T(Awaitable<Stats>, optional) β the info
id(ModuleId) β the module id
(T) The info
An object describing a directory or file (interface).
isDirectory(IsDirectory) β check if the stats object describes a directoryisFile(IsFile) β check if the stats object describes a file
See CONTRIBUTING.md.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.