Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

213 Commits

Repository files navigation

esm-types

github releasenpmmodule type: esmlicenseconventional commitstypescriptvitestyarn

TypeScript definitions for ECMAScript modules

Contents

What is this?

This package contains TypeScript definitions for ECMAScript module utilities and loader hooks.

Install

This package is ESM only.

yarn add @flex-development/esm-types
yarn add -D @types/node

From Git:

yarn add @flex-development/esm-types@flex-development/esm-types
yarn add -D @types/node
See Git - Protocols | Yarn for details on requesting a specific branch, commit, or tag.

Use

touch loader.mjs
/** * @file Custom Loader Hooks * @module loader * @see https://nodejs.org/api/esm.html#loaders */import{DECORATOR_REGEX}from'@flex-development/decorator-regex'import*asesmfrom'@flex-development/esm-types'import*asmllyfrom'@flex-development/mlly'import*aspathefrom'@flex-development/pathe'import*astscufrom'@flex-development/tsconfig-utils'import*astutilsfrom'@flex-development/tutils'import*asesbuildfrom'esbuild'import{URL,fileURLToPath,pathToFileURL}from'node:url'importtsfrom'typescript'// add support for extensionless files in "bin" scripts// https://github.com/nodejs/modules/issues/488mlly.EXTENSION_FORMAT_MAP.set('',esm.Format.COMMONJS)/** * {@linkcode URL} of tsconfig file. * * @type {URL} * @const tsconfig */consttsconfig=mlly.toURL('tsconfig.json')/** * TypeScript compiler options. * * @type {tscu.CompilerOptions} * @const compilerOptions */constcompilerOptions=tscu.loadCompilerOptions(tsconfig)/** * Determines how the given module `url` should be interpreted, retrieved, and * parsed. * * @see {@linkcode esm.LoadHookContext} * @see {@linkcode esm.LoadHookResult} * @see {@linkcode esm.LoadHook} * @see {@linkcode esm.ResolvedModuleUrl} * @see https://nodejs.org/api/esm.html#loadurl-context-nextload * * @async * * @param {esm.ResolvedModuleUrl} url - Resolved module URL * @param {esm.LoadHookContext} context - Hook context * @return {Promise<esm.LoadHookResult>} Hook result */exportconstload=async(url,context)=>{// get module formatcontext.format=context.format??(awaitmlly.getFormat(url))// validate import assertionsmlly.validateAssertions(url,context.format,context.importAssertions)/** * File extension of {@linkcode url}. * * @type {pathe.Ext | tutils.EmptyString} * @const ext */constext=pathe.extname(url)/** * Module source code. * * @type {esm.Source<Uint8Array | string> | undefined} * @var source */letsource=awaitmlly.getSource(url,{format: context.format})// transform typescript filesif(/^\.(?:cts|mts|tsx?)$/.test(ext)&&!/\.d\.(?:cts|mts|ts)$/.test(url)){// push require condition for .cts files and update formatif(ext==='.cts'){context.conditions=context.conditions??[]context.conditions.unshift('require','node')context.format=esm.Format.MODULE}// resolve path aliasessource=awaittscu.resolvePaths(source,{conditions: context.conditions,ext: '',parent: url,
tsconfig
})// resolve modulessource=awaitmlly.resolveModules(source,{conditions: context.conditions,parent: url})// emit decorator metadataif(DECORATOR_REGEX.test(source)){const{ outputText }=ts.transpileModule(source,{compilerOptions: { ...compilerOptions,sourceMap: false},fileName: url})source=outputText}// transpile source codeconst{ code }=awaitesbuild.transform(source,{format: 'esm',loader: ext.slice(/^\.[cm]/.test(ext) ? 2 : 1),minify: false,sourcefile: fileURLToPath(url),sourcemap: 'inline',target: `node${process.versions.node}`,tsconfigRaw: { compilerOptions }})// set source code to transpiled sourcesource=code}return{format: context.format,shortCircuit: true, source }}/** * Resolves the given module `specifier`, and its module format as a hint to the * {@linkcode load} hook. * * Adds supports for: * * - Path alias resolution * - Extensionless file and directory index resolution * * @see {@linkcode esm.ResolveHookContext} * @see {@linkcode esm.ResolveHookResult} * @see {@linkcode esm.ResolveHook} * @see https://nodejs.org/api/esm.html#resolvespecifier-context-nextresolve * * @async * * @param {string} specifier - Module specifier * @param {esm.ResolveHookContext} context - Hook context * @return {Promise<esm.ResolveHookResult>} Hook result */exportconstresolve=async(specifier,context)=>{const{ conditions,parentURL: parent}=context// resolve path aliasspecifier=awaitmlly.resolveAlias(specifier,{aliases: compilerOptions.paths,
conditions,cwd: pathToFileURL(compilerOptions.baseUrl),
parent
})/** * Resolved module {@linkcode URL}. * * @type {URL} * @const url */consturl=awaitmlly.resolveModule(specifier,{
conditions,parent: parent?.startsWith('file:') ? parent : specifier})return{format: awaitmlly.getFormat(url),shortCircuit: true,url: url.href}}

API

This package exports the identifiers listed below.

There is no default export.

Enums

Hooks

Interfaces

Type Definitions

Related

Contribute

See CONTRIBUTING.md.

Releases

Sponsor this project

Packages

Used by

Contributors

Languages