Skip to content

Instantly share code, notes, and snippets.

@nsivertsen
Created July 26, 2020 09:40
Show Gist options
  • Save nsivertsen/ed3b9d1097cd06d6d6395fbb6daaeaec to your computer and use it in GitHub Desktop.
Save nsivertsen/ed3b9d1097cd06d6d6395fbb6daaeaec to your computer and use it in GitHub Desktop.
// Adapted from https://nodejs.org/dist/latest-v14.x/docs/api/esm.html#esm_transpiler_loader
import { readFileSync, writeFileSync } from 'fs'
import { dirname } from 'path'
import { URL, pathToFileURL, fileURLToPath } from 'url'
import esbuild from 'esbuild'
const baseURL = pathToFileURL(`${process.cwd()}/`).href
const tsExtensionRegex = /\.(tsx?)$/
function readJSON(path) {
try {
return JSON.parse(readFileSync(path))
} catch (err) {}
}
function getPackageJSON(base = baseURL) {
let packageJSONUrl = new URL('./package.json', base);
while (true) {
const packageJSONPath = packageJSONUrl.pathname;
if (packageJSONPath.endsWith('node_modules/package.json')) {
break
}
const packageConfig = readJSON(fileURLToPath(packageJSONUrl));
if (packageConfig !== undefined) {
return packageConfig
}
const lastPackageJSONUrl = packageJSONUrl;
packageJSONUrl = new URL('../package.json', packageJSONUrl);
if (packageJSONUrl.pathname === lastPackageJSONUrl.pathname) {
break
}
}
}
export function resolve(specifier, context, defaultResolve) {
const { parentURL = baseURL } = context
if (tsExtensionRegex.test(specifier)) {
return {
url: new URL(specifier, parentURL).href
}
}
return defaultResolve(specifier, context, defaultResolve)
}
export function getFormat(url, context, defaultGetFormat) {
if (tsExtensionRegex.test(url)) {
return {
format: 'module'
}
}
return defaultGetFormat(url, context, defaultGetFormat)
}
export function transformSource(contents, context, defaultTransformSource) {
const { url, format } = context
const match = url.match(tsExtensionRegex)
if (match) {
const sourcefile = fileURLToPath(url)
const resolveDir = dirname(sourcefile)
const [, loader] = match
const pkg = getPackageJSON()
const result = esbuild.buildSync({
platform: 'node',
format: 'esm',
bundle: true,
sourcemap: true,
write: false,
external: [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.devDependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
],
stdin: {
contents,
sourcefile,
resolveDir,
loader
}
})
// Uncomment to save build output to disk
writeFileSync('/Users/nsivertsen/Downloads/out.js', new TextDecoder("utf-8").decode(result.outputFiles[0].contents))
return {
source: result.outputFiles[0].contents
}
}
return defaultTransformSource(contents, context, defaultTransformSource)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment