estrella icon indicating copy to clipboard operation
estrella copied to clipboard

Mocha / Node.js inline require option?

Open ccorcos opened this issue 3 years ago • 5 comments

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.

ccorcos avatar Oct 19 '22 20:10 ccorcos

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.

rsms avatar Oct 24 '22 16:10 rsms

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

ccorcos avatar Oct 25 '22 19:10 ccorcos

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

ccorcos avatar Oct 25 '22 19:10 ccorcos

Ah, just needed format: "cjs",

ccorcos avatar Oct 25 '22 19:10 ccorcos

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.

ccorcos avatar Oct 25 '22 19:10 ccorcos