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.runafter callingaddFileand 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
esmmodule Stop requiringts-node/registerRun mocha like this:TS_NODE_PROJECT=absolutepathtotsconfigfile "NODE_OPTIONS=--loader ts-node/esm" mochaTS_NODE_PROJECTis optional if you want it to load$PWD/tsconfig.jsonbecause that file will be auto-detected. You can get rid ofregister.tsUpgrade your node version.Invalid host defined optionsis a confusing node error which may be improved in a newer version.I strongly advise against using the
esmpackage, and certainly not both at the same time.esmwas 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-nodeis a CommonJS module. If so, then only default imports are supported.