Mocha / Node.js inline require option?
Admittedly, I'm not an expert on how this is supposed to work, but I know that you can run Typescript via node -r 'ts-node/register' as well as run tests via mocha -r 'ts-node/register'. But this is much slower than esbuild/estrella...
Any suggestions on how to do this with Estrella? It would be a nice feature if its simple enough to build.
Interesting idea! I'm quite busy at the moment but if someone wants to take a stab at this I'd be happy to review a PR.
I've got a nice start here:
register.js
// Reference:
// https://github.com/swc-project/swc-node/blob/master/packages/register/register.ts
const sourceMapSupport = require("source-map-support")
const { addHook } = require("pirates")
const esbuild = require("esbuild")
const Sourcemaps = new Map()
sourceMapSupport.install({
handleUncaughtExceptions: false,
environment: "node",
retrieveSourceMap(file) {
if (SourcemapMap.has(file)) {
return {
url: file,
map: SourcemapMap.get(file),
}
}
return null
},
})
function compile(sourcecode, filename) {
if (filename.endsWith(".d.ts")) {
return ""
}
const { code, map } = esbuild.transformSync(sourcecode, {
minify: false,
loader: "tsx",
sourcemap: true,
})
Sourcemaps.set(filename, map)
return code
}
function register() {
return addHook((code, filename) => compile(code, filename), {
exts: [".ts", ".tsx"],
})
}
register()
I've got a hello.ts file:
const x: string = "hello"
console.log("hello")
❯❯❯ node -r ./register.js hello.ts
hello
Looks like import statements don't compile down to require though...
hello.ts
import { hello } from "./hello2"
const x: string = "chet"
hello(x)
hello2.ts
export function hello(name: string) {
console.log("hello", name)
}
And I got rid of the pirates library...
// Reference:
// https://github.com/swc-project/swc-node/blob/master/packages/register/register.ts
const Module = require("module")
const sourceMapSupport = require("source-map-support")
// const { addHook } = require("pirates")
const esbuild = require("esbuild")
const Sourcemaps = new Map()
sourceMapSupport.install({
handleUncaughtExceptions: false,
environment: "node",
retrieveSourceMap(file) {
if (SourcemapMap.has(file)) {
return {
url: file,
map: SourcemapMap.get(file),
}
}
return null
},
})
function compileTs(sourcecode, filename) {
if (filename.endsWith(".d.ts")) {
return ""
}
const { code, map } = esbuild.transformSync(sourcecode, {
sourcefile: filename,
minify: false,
loader: filename.split(".").reverse()[0],
sourcemap: true,
})
Sourcemaps.set(filename, map)
return code
}
// https://github.com/danez/pirates/blob/main/src/index.js
const jsLoader = Module._extensions[".js"]
for (const ext of [".ts", ".tsx"]) {
Module._extensions[ext] = function newLoader(mod, filename) {
const oldCompile = mod._compile
mod._compile = function newCompile(code) {
const newCode = compileTs(code, filename)
mod._compile = oldCompile
return mod._compile(newCode, filename)
}
jsLoader(mod, filename)
}
}
>>> node -r ./register.js hello.ts
(node:87234) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/Users/chet/Code/js/html-editor/packages/desktop/hello.ts:1
import {hello} from "./hello2";
^^^^^^
SyntaxError: Cannot use import statement outside a module
(Use `node --trace-uncaught ...` to show where the exception was thrown)
Node.js v18.11.0
Ah, just needed format: "cjs",
Hell yeah
./node_modules/.bin/mocha -r './register.js' './src/**/*.test2.ts' --verbose 0.13s user 0.02s system 117% cpu 0.130 total
❯❯❯ time ./node_modules/.bin/mocha -r './register.js' '*.test2.ts' --verbose
Test Suite
✓ works
1 passing (1ms)
./node_modules/.bin/mocha -r './register.js' '*.test2.ts' --verbose 0.14s user 0.02s system 116% cpu 0.133 total
❯❯❯ time ./node_modules/.bin/mocha -r 'ts-node/register' '*.test2.ts' --verbose
Test Suite
✓ works
1 passing (2ms)
./node_modules/.bin/mocha -r 'ts-node/register' '*.test2.ts' --verbose 1.86s user 0.10s system 224% cpu 0.873 total
PR coming up.