hapijs / hapijs/lab

Dynamic import ESM based dependency in Typescript CJS based repo

Open
#1,077 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
JavaScript
Stars
736
Forks
177
PR merge metrics
No merged PRs in 30d

Description

### Runtime

node.js

### Runtime version

20.16.0

### Module version

25.3.1

### Last module version without issue

_No response_

### Used with

_No response_

### Any other relevant information

_No response_

### What are you trying to achieve or the steps to reproduce?

I have CJS based repo written in Typescript which needs to use ESM-only dependency. I do it by dynamically importing that dependency. Code works correctly when run, but fails to compile during test run.

I use lab with `typescript` option as advised by docs. In my `tsconfig.json` I use `compilerOptions.module: "Node16"` to enable native ECMAScript module support (as per [Typescript docs](https://www.typescriptlang.org/tsconfig/#node16nodenext)). When running test I get
```
Unexpected token 'export'
```
Reason is found in [typescript.js file](https://github.com/hapijs/lab/blob/master/lib/modules/typescript.js#L29), which is used when `typescript` option is passed. Mentioned line overrides repos tsconfig option and disables possibility to dynamically import ESM dependency. When I comment out that override, code compiles correctly during test run.

I am not sure whether it is a bug or intended behaviour. If it is intended what is designed way to run my scenario?

---
How to reproduce?

`package.json`

```
{
"name": "lab-test",
"version": "1.0.0",
"main": "./dist/src/index.js",
"scripts": {
"dist": "rm -rf dist && tsc",
"start": "node ./dist/src/index.js",
"test": "lab --typescript"
},
"files": ["dist", "src"],
"license": "ISC",
"devDependencies": {
"@hapi/code": "^9.0.3",
"@hapi/lab": "^25.3.1",
"@types/node": "^20.16.0",
"typescript": "^5.6.2"
},
"dependencies": {
"p-map": "^7.0.2"
}
}
```

`tsconfig.json`
```
{
"compilerOptions": {
"module": "Node16",
"moduleResolution": "Node16",
"target": "ES2023",
"outDir": "dist/",
"rootDir": "./",
"noEmit": false
},
"files": ["src/utils.ts", "src/index.ts"]
}
```

`src/index.ts`

```
import { isPMapImported } from './utils';

isPMapImported();
```

`src/utils.ts`
```
export const isPMapImported = async () => {
// p-map is ESM only dependency
const Pmap = (await import('p-map')).default;

console.log('Is Pmap imported: ', !!Pmap);
}
```

`test/utils.ts`
```
import * as Lab from "@hapi/lab";
import { expect } from "@hapi/code";

import { isPMapImported } from "../src/utils";

const lab = Lab.script();
const { describe, it, before } = lab;
export { lab };

describe("experiment", () => {
before(() => {});

it("is p-map imported", async () => {
await isPMapImported();

// assertion doesn't matter as compilation error will happen
expect(true).to.be.true();
});
});
```

When running:
- `npm run dist && npm run start` (runs dist index.js) I get log `Is Pmap imported: true`
- `npm run test` I get compilation error

When I comment out line 29 in node_modules/@hap/lab/lib/modules/typescript.js and run `npm run test` I get log `Is Pmap imported: true` and test succeeds

### What was the result you got?

Compilation error
```
Failed tests:

1) experiment is p-map imported:

Unexpected token 'export'

at wrapSafe (node:internal/modules/cjs/loader:1281:20)
at Module._compile (node:internal/modules/cjs/loader:1321:27)
at Object.require.extensions. [as .js] (/Users/leszek_pawlega/git/lab-test/node_modules/@hapi/lab/lib/modules/transform.js:41:28)
at Module.load (node:internal/modules/cjs/loader:1208:32)
at Function.Module._load (node:internal/modules/cjs/loader:1024:12)
at Module.require (node:internal/modules/cjs/loader:1233:19)
at require (node:internal/modules/helpers:179:18)
at /Users/leszek_pawlega/git/src/isPMapImported.ts:3:17
at isPMapImported (/Users/leszek_pawlega/git/src/isPMapImported.ts:3:17)
at /Users/leszek_pawlega/git/test/isPMapImported.ts:14:5
at Immediate. (/Users/leszek_pawlega/git/lab-test/node_modules/@hapi/lab/lib/runner.js:659:21)
```

### What result did you expect?

Test will pass

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.