esm/helpers.d.ts imports 'apache-arrow/Arrow.node.js' which can't be resolved
Category: Bug
### 🐛 Bug report
using the ES|QL Arrow helpers from an ESM TypeScript project doesnt compile. The shipped `esm/helpers.d.ts` imports the Arrow types from `apache-arrow/Arrow.node.js` and that path can't be resolved. `lib/helpers.d.ts` uses `apache-arrow/Arrow.node` without the extension and works fine, so this only affects ESM consumers .
With `skipLibCheck` off (TypeScript's default) tsc fails with TS2307. With `skipLibCheck` on the error disappears, but `Table` ends up as `any`, so a typo on the table object compiles clean. The same file in a CJS project catches it.
I had a look at why. `tsc-esm-fix` adds the `.js` to both `esm/helpers.js` and `esm/helpers.d.ts`, and `scripts/fix-esm-require.js` only puts it back for the runtime filebecause its regex looks for `require('apache-arrow/Arrow.node.js')`. apache-arrow maps `./*` to `./*.d.ts`, so `Arrow.node.js` would need an `Arrow.node.js.d.ts`, which doesn't exist. Only `Arrow.node.d.ts` does.
Adding the same replacement for `esm/helpers.d.ts` in that script fixes both cases for me
locally. I will send a PR if thats the direction you want.
### To reproduce
An ESM TypeScript project with apache-arrow installed:
```bash
mkdir es-arrow-esm && cd es-arrow-esm
npm init -y
npm pkg set type=module
npm i @elastic/elasticsearch@9.5.0 apache-arrow@21 typescript@5.9.3 @types/node@22
```
```ts
// fixture.ts
import { Client } from '@elastic/elasticsearch'
const client = new Client({ node: 'http://localhost:9200' })
export async function go () {
const table = await client.helpers.esql({ query: 'FROM x' }).toArrowTable()
return table.numRows
}
```
```bash
npx tsc fixture.ts --module nodenext --moduleResolution nodenext --target es2022 --strict --noEmit
```
```
node_modules/@elastic/elasticsearch/esm/helpers.d.ts(3,67): error TS2307: Cannot find module 'apache-arrow/Arrow.node.js' or its corresponding type declarations.
```
The two declaration files disagree, and the runtime ESM file already has the right specifier:
```
$ grep -n apache-arrow node_modules/@elastic/elasticsearch/lib/helpers.d.ts
3:import type { Table, TypeMap, AsyncRecordBatchStreamReader } from 'apache-arrow/Arrow.node';
$ grep -n apache-arrow node_modules/@elastic/elasticsearch/esm/helpers.d.ts
3:import type { Table, TypeMap, AsyncRecordBatchStreamReader } from 'apache-arrow/Arrow.node.js';
$ grep -n apache-arrow node_modules/@elastic/elasticsearch/esm/helpers.js
14: return require('apache-arrow/Arrow.node');
```
Turning on `skipLibCheck` hides the error instead of fixing it. With `thisPropertyDoesNotExist`, which isn't a real property on Arrow's `Table`:
```ts
// fixture2.ts
import { Client } from '@elastic/elasticsearch'
const client = new Client({ node: 'http://localhost:9200' })
export async function go () {
const table = await client.helpers.esql({ query: 'FROM x' }).toArrowTable()
return table.thisPropertyDoesNotExist
}
```
```bash
npx tsc fixture2.ts --module nodenext --moduleResolution nodenext --target es2022 --strict --noEmit --skipLibCheck
```
```
ESM project ("type": "module"): exit 0, no error
CJS project (no "type" field): fixture2.ts(7,16): error TS2339: Property 'thisPropertyDoesNotExist' does not exist on type 'Table<TypeMap>'.
```
So an ESM project either won't compile, or compiles with no Arrow typing at all.
No Elasticsearch instance needed. Same on main (dcc98b2e), and the specifier is the same in 9.3.0 through 9.5.0.
### Expected behavior
`esm/helpers.d.ts` should use the same specifier as `lib/helpers.d.ts` (`apache-arrow/Arrow.node`), so ESM consumers get the Arrow types that CJS consumers already get.
### Node.js version
22.22.2
### @elastic/elasticsearch version
9.5.0
### Operating system
macOS 26.6
### Any other relevant environment information
TypeScript 5.9.3, apache-arrow 21.1.0, @elastic/transport 9.4.0. Consumer project is "type": "module" with moduleResolution nodenext.
2 条评论