Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Node — Loads modules using esbuild. — `node --experimental-loader ./esbuild-loader.js`
import { existsSync } from 'fs'
import { readFile } from 'fs/promises'
import { transform } from 'esbuild'
/** @typedef {{ conditions: string[], parentURL: string }} Context */
/** @typedef {(specifier: string, context: Context, defaultResolve: ResolveHook) => { url: string }} ResolveHook */
/** @typedef {(url: string, context: Context, defaultGetFormat: GetFormatHook) => { format: string }} GetFormatHook */
/** @typedef {(url: string, context: Context, defaultGetSource: GetSourceHook) => Promise<{ source: string | SharedArrayBuffer | Uint8Array }>} GetSourceHook */
/** Matches any JavaScript/TypeScript module. */
const matchJs = /\.[cm]?[jt]s(x?)$/i
/** Matches any TypeScript module. */
const matchTs = /\.(tsx?)$/i
/** Returns the resolved file URL for a given module specifier and parent URL. */
export const resolve = (
/** @type {string} */ specifier,
/** @type {Context} */ context,
/** @type {ResolveHook} */ defaultResolve,
url = new URL(specifier.replace(matchJs, '.ts$1'), context.parentURL || 'file:')
) => (
existsSync(url)
? { url: url.href }
: defaultResolve(specifier, context, defaultResolve)
)
/** Returns how a URL should be interpreted. */
export const getFormat = (
/** @type {string} */ url,
/** @type {Context} */ context,
/** @type {GetFormatHook} */ defaultGetFormat,
) => (
matchTs.test(url)
? { format: 'module' }
: defaultGetFormat(url, context, defaultGetFormat)
)
/** Returns the source code of an ES module specifier. */
export const getSource = (
/** @type {string} */ url,
/** @type {Context} */ context,
/** @type {GetSourceHook} */ defaultGetSource,
) => (
matchTs.test(url)
? readFile(new URL(url), 'utf8').then(
(code) => transform(code, { loader: url.match(matchTs)[1], format: 'esm', target: 'node16' }),
).then(
(out) => ({ source: out.code })
)
: defaultGetSource(url, context, defaultGetSource)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment