TypeError: Invalid host defined options - Cannot Use TypeScript, JavaScript, ESM, and TS-Node

See original GitHub issue

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?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:16 (9 by maintainers)

github_iconTop GitHub Comments

2reactions
loganknechtcommented, Mar 8, 2021

@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 calling addFile and that caused errors to be thrown!

Thank you so much for your time, your patience, the example project, and everything in between!

1reaction
juergbacommented, Mar 5, 2021

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 wether ts-node is a CommonJS module. If so, then only default imports are supported.

Read more comments on GitHub >

github_iconTop Results From Across the Web

copy-webpack-plugin error: Invalid host defined options
The plugin version 10 started using dynamically imported ES Modules. This has somewhat subpar support in various tools still.
Read more >
Error: Not Supported - Dave Lage
This occurs using async dynamic ESModule loading (which is recommended to ... TypeError: Invalid host defined options at module.exports (.
Read more >
Configuring Jest
To read TypeScript configuration files Jest requires ts-node . ... This options cannot be used in projects which use watchman.
Read more >
RegisterOptions | ts-node - TypeStrong Β· GitHub
Use TypeScript's compiler host API instead of the language service API. default. false. Optional compilerOptions. compilerOptions?: object. InheritedΒ ...
Read more >
ts-node-dev - npm
Compiles your TS app and restarts when files are modified.. Latest version: 2.0.0, last published: 7 months ago. Start using ts-node-dev inΒ ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found