From b483e401b3f5b9aacd3797da3f96b1c664a4e02c Mon Sep 17 00:00:00 2001 From: Luke Edwards Date: Tue, 26 Oct 2021 19:22:53 -0700 Subject: [PATCH] fix: support new API for ESM loader hooks (#16) * chore(loader): rename `load` ~> `toConfig` helper * chore(loader): add deprecated note to self * fix(loader): add new `load` hook for new API design; - Closes #13 --- .github/workflows/ci.yml | 2 +- src/loader.ts | 45 +++++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08059c4..fec0e23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: timeout-minutes: 3 strategy: matrix: - nodejs: [12, 14, 16] + nodejs: [12, 14, 16.11, 16] os: [ubuntu-latest, windows-latest] steps: - uses: actions/checkout@v2 diff --git a/src/loader.ts b/src/loader.ts index 546c4db..6f0b195 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -1,4 +1,4 @@ -import { existsSync } from 'fs'; +import { existsSync, promises as fs } from 'fs'; import { fileURLToPath, URL } from 'url'; import * as tsm from './utils.js'; @@ -22,7 +22,10 @@ type Resolve = ( parentURL?: string; }, fallback: Resolve -) => Promisable<{ url: string }>; +) => Promisable<{ + url: string; + format?: Format; +}>; type Inspect = ( url: string, @@ -36,7 +39,16 @@ type Transform = ( fallback: Transform ) => Promisable<{ source: Source }>; -async function load(): Promise { +type Load = ( + url: string, + context: { format?: Format }, + fallback: Load +) => Promisable<{ + format: Format; + source: Source; +}>; + +async function toConfig(): Promise { let mod = await setup; mod = mod && mod.default || mod; return (tsm as TSM).$finalize(env, mod); @@ -46,7 +58,7 @@ const EXTN = /\.\w+(?=\?|$)/; const isTS = /\.[mc]?tsx?(?=\?|$)/; const isJS = /\.([mc])?js$/; async function toOptions(uri: string): Promise { - config = config || await load(); + config = config || await toConfig(); let [extn] = EXTN.exec(uri) || []; return config[extn as `.${string}`]; } @@ -91,7 +103,7 @@ export const resolve: Resolve = async function (ident, context, fallback) { } } - config = config || await load(); + config = config || await toConfig(); for (ext in config) { path = check(output.href + ext); @@ -101,12 +113,35 @@ export const resolve: Resolve = async function (ident, context, fallback) { return fallback(ident, context, fallback); } +export const load: Load = async function (uri, context, fallback) { + // note: inline `getFormat` + let options = await toOptions(uri); + if (options == null) return fallback(uri, context, fallback); + let format: Format = options.format === 'cjs' ? 'commonjs' : 'module'; + + // TODO: decode SAB/U8 correctly + let path = fileURLToPath(uri); + let source = await fs.readFile(path); + + // note: inline `transformSource` + esbuild = esbuild || await import('esbuild'); + let result = await esbuild.transform(source.toString(), { + ...options, + sourcefile: path, + format: format === 'module' ? 'esm' : 'cjs', + }); + + return { format, source: result.code }; +} + +/** @deprecated */ export const getFormat: Inspect = async function (uri, context, fallback) { let options = await toOptions(uri); if (options == null) return fallback(uri, context, fallback); return { format: options.format === 'cjs' ? 'commonjs' : 'module' }; } +/** @deprecated */ export const transformSource: Transform = async function (source, context, xform) { let options = await toOptions(context.url); if (options == null) return xform(source, context, xform);