Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mocha / Node.js inline require option? #59

Open
ccorcos opened this issue Oct 19, 2022 · 5 comments
Open

Mocha / Node.js inline require option? #59

ccorcos opened this issue Oct 19, 2022 · 5 comments
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@ccorcos
Copy link

ccorcos commented Oct 19, 2022

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.

@rsms rsms added enhancement New feature or request good first issue Good for newcomers labels Oct 24, 2022
@rsms
Copy link
Owner

rsms commented Oct 24, 2022

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.

@ccorcos
Copy link
Author

ccorcos commented Oct 25, 2022

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
Copy link
Author

ccorcos commented Oct 25, 2022

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
Copy link
Author

ccorcos commented Oct 25, 2022

Ah, just needed format: "cjs",

@ccorcos
Copy link
Author

ccorcos commented Oct 25, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants