mocha: TypeError: Invalid host defined options - Cannot Use TypeScript, JavaScript, ESM, and TS-Node
Hello!
I tried reaching out on Gitter
, but wasnβt able to elicit any help.
I am in the process of trying to migrate my teamβs code base to TypeScript
in small chunks. Which means I need to have JavaScript
and TypeScript
supported while this is performed. Additionally I am trying to align the standards for that move.
Is there anyone who can provide insight on how to get mocha
to run for a typescript
project that has Javascript
in it using ESM module support
?
Also quick disclaimer: This is not the palantir
related to Peter Thiel π, My team mates just really like Lord of the Rings and chose a poor name for our project.
I have a directory structure like so
All my test files have a .js
extension on them
.
βββ .mocharc.json
βββ package.json
βββ register.ts
βββ src
βΒ Β βββ ...
βββ test
βΒ Β βββ runner.js
βΒ Β βββ tsconfig.json
βΒ Β βββ ...
βββ tsconfig.json
βββ webpack.config.js
I have a package.json
file with these contents
{
"name": "palantir-api",
// ...
"scripts": {
"build": "yarn transpile && webpack",
"bumpversion": "yarn version --no-git-tag-version --no-commit-hooks",
"dev": "export DB_HOST=localhost && nodemon ./src/app.js",
"format": "prettier --write \"./**/*.md\" \"./**/*.json\" \"./**/*.js\" \"./**/*.ts\" \"./**/*.yaml\" \"./**/*.yml\"",
"open_api": "redoc-cli bundle ./api/palantir_api.yaml --output ./docs/index.html",
"preopen_api": "node -e \"console.log(require('./package.json').version)\" > api/version.yaml",
"postbumpversion": "node -e \"console.log(require('./package.json').version)\" > VERSION",
"prod": "node dist/api.bundle.js",
"runner": "node --loader ts-node/esm ./test/runner.js",
"start": "nodemon --exec babel-node ./src/app.js",
"start_db_server": "pg_ctl -D /usr/local/var/postgres start",
"stop_db_server": "pg_ctl -D /usr/local/var/postgres stop",
"transpile": "tsc",
"test": "yarn runner --t system",
"unit_test": "nyc yarn runner --t unit"
},
// ...
"dependencies": {
"@babel/core": "^7.10.4",
"@babel/node": "^7.10.4",
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/preset-env": "^7.10.4",
"@hapi/joi": "^17.1.1",
"@types/dotenv": "^8.2.0",
"@types/express-xml-bodyparser": "^0.3.1",
"bcrypt": "^5.0.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-validator": "^6.6.1",
"express-winston": "^4.0.3",
"express-xml-bodyparser": "^0.3.0",
"jsonwebtoken": "^8.5.1",
"nodemon": "^2.0.4",
"pg": "^8.2.1",
"serve-favicon": "^2.5.0",
"trim-request-body": "^1.0.1",
"uuid": "^8.2.0",
"winston": "^3.3.3"
},
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.10.4",
"@babel/polyfill": "^7.10.4",
"@babel/preset-react": "^7.10.4",
"@types/pg": "^7.14.10",
"babel-loader": "^8.1.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-runtime": "^6.23.0",
"chai": "^4.2.0",
"chai-http": "^4.3.0",
"esm": "^3.2.25",
"faker": "^5.1.0",
"mocha": "^8.0.1",
"mocha-junit-reporter": "^2.0.0",
"mocha-multi-reporters": "^1.1.7",
"nyc": "^15.1.0",
"palantir-test-data-helpers": "^0.0.4",
"prettier": "^2.2.1",
"redoc-cli": "^0.9.8",
"reify": "^0.20.12",
"sinon": "^9.0.2",
"ts-node-dev": "1.1.1",
"typescript": "4.1.3",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12",
"webpack-node-externals": "^1.7.2",
"yargs": "^15.4.0"
},
"type": "module"
}
I have a default tsconfig.json
file with these contents
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"lib": ["dom", "es6"],
"module": "es6",
"moduleResolution": "node",
"noImplicitAny": true,
"outDir": "./typescript_build",
"paths": {
"*": ["./node_modules/@types", "./custom_types"]
},
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"strictPropertyInitialization": false,
"target": "es6"
}
}
Which is inherited by the test/tsconfig.json
and looks like this
{
"extends": "../tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"experimentalDecorators": true,
"isolatedModules": false,
"paths": {
"*": ["../node_modules/@types", "../custom_types"]
},
"resolveJsonModule": true
},
"exclude": ["../node_modules"],
"include": ["./**/*.ts", "../custom_types"]
}
And then I have a .mocharc.json
configured with these options
{
"extension": ["js", "ts"],
"resolveJsonModule": true,
"require": ["./register.ts", "esm", "ts-node/register"]
}
And finally I have a register.ts
file with these configurations
import * as tsNode from "ts-node";
import testTSConfig from "./test/tsconfig.json";
tsNode.register({
files: true,
project: "./test/tsconfig.json"
});
Additionally there is a webpack file here:
import path from "path";
import nodeExternals from "webpack-node-externals";
module.exports = {
entry: "./typescript_build/src/app.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "api.bundle.js"
},
target: "node",
mode: "production",
node: {
// Need this when working with express, otherwise the build fails
__dirname: false, // if you don't put this is, __dirname
__filename: false // and __filename return blank or /
},
externals: [nodeExternals()], // Need this to avoid error when working with Express
module: {
rules: [
{
test: /(\.js[\S]{0,1})$/i,
exclude: /node_modules/,
loader: "babel-loader",
query: {
presets: ["@babel/preset-react", "@babel/preset-env"],
plugins: ["@babel/proposal-class-properties"]
}
}
]
}
};
When I run this command
env TS_NODE_PROJECT=test/tsconfig.json \
yarn run mocha --config ./.mocharc.json --test unit
I am provided this output
β lknecht ξ° ~/Repositories/palantir-api ξ° ξ do_not_use/prototyping_mocha_typescript-dev Β±β ξ° β¬‘ v12.17.0 ξ° env TS_NODE_PROJECT=test/tsconfig.json \
yarn run mocha --config ./.mocharc.json --test system --full-trace
yarn run v1.22.10
$ /Users/lknecht/Repositories/palantir-api/node_modules/.bin/mocha --config ./.mocharc.json --test system --full-trace
TypeError: Invalid host defined options
at formattedImport (/Users/lknecht/Repositories/palantir-api/node_modules/mocha/lib/esm-utils.js:6:23)
at Object.exports.requireOrImport (/Users/lknecht/Repositories/palantir-api/node_modules/mocha/lib/esm-utils.js:23:14)
at Object.exports.loadFilesAsync (/Users/lknecht/Repositories/palantir-api/node_modules/mocha/lib/esm-utils.js:33:34)
at Mocha.loadFilesAsync (/Users/lknecht/Repositories/palantir-api/node_modules/mocha/lib/mocha.js:431:19)
at singleRun (/Users/lknecht/Repositories/palantir-api/node_modules/mocha/lib/cli/run-helpers.js:125:15)
at exports.runMocha (/Users/lknecht/Repositories/palantir-api/node_modules/mocha/lib/cli/run-helpers.js:190:10)
at Object.exports.handler (/Users/lknecht/Repositories/palantir-api/node_modules/mocha/lib/cli/run.js:362:11)
at /Users/lknecht/Repositories/palantir-api/node_modules/mocha/node_modules/yargs/lib/command.js:241:49
at process.runNextTicks [as _tickCallback] (internal/process/task_queues.js:62:5)
at /Users/lknecht/Repositories/palantir-api/node_modules/esm/esm.js:1:34535
at /Users/lknecht/Repositories/palantir-api/node_modules/esm/esm.js:1:34176
at process.<anonymous> (/Users/lknecht/Repositories/palantir-api/node_modules/esm/esm.js:1:34506)
at Function.<anonymous> (/Users/lknecht/Repositories/palantir-api/node_modules/esm/esm.js:1:296856)
at Function.<anonymous> (/Users/lknecht/Repositories/palantir-api/node_modules/esm/esm.js:1:296555)
at Function.<anonymous> (/Users/lknecht/Repositories/palantir-api/node_modules/esm/esm.js:1:284879)
at Object.apply (/Users/lknecht/Repositories/palantir-api/node_modules/esm/esm.js:1:199341)
at internal/main/run_main_module.js:17:47
error Command failed with exit code 1.
I have been testing different configurations non-stop trying to get
- mocha
- javascript
- typescript
- ecma script modules
- etc
to all play nicely.
By default I CAN get the api to stand itself up, but the second mocha
gets involved this blows up! π¦
Can anyone provide any guidance?
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 16 (9 by maintainers)
@juergba and @cspotcode There we go! π π π π π
The final trick was the requirement of calling
loadFilesAsync
!Prior to this change. The previous version called
mocha.run
after callingaddFile
and that caused errors to be thrown!Thank you so much for your time, your patience, the example project, and everything in between!
On node, you have 2x options:
You should commit to one or the other, and then I can give you a configuration that will work. The first option β using nodeβs CommonJS support β is by far the recommended option.
If you absolutely must use the second option β native ESM support β then do the following:
Remove the
esm
module Stop requiringts-node/register
Run mocha like this:TS_NODE_PROJECT=absolutepathtotsconfigfile "NODE_OPTIONS=--loader ts-node/esm" mocha
TS_NODE_PROJECT
is optional if you want it to load$PWD/tsconfig.json
because that file will be auto-detected. You can get rid ofregister.ts
Upgrade your node version.Invalid host defined options
is a confusing node error which may be improved in a newer version.I strongly advise against using the
esm
package, and certainly not both at the same time.esm
was excellent when we were young and beautiful, now you should go with Nodeβs native ESM implementation.see ts-node/esm, maybe @cspotcode can give you a hint.
import * as tsNode from 'ts-node';
I donβt know wetherts-node
is a CommonJS module. If so, then only default imports are supported.