Thanks @vincentkoc for starting this! I was just looking into this
myself. I started with your PR and added:
- make arrow 21 the default
- widen the peer range to <22 so if they release 21.3 that'll be
included
- have to do skipLibCheck in tsconfig.json, because of flatbuffers 25
which needs TypeScript 5.7
- fix override in Symbol.hasInstance
- support new types in Arrow 20-21 (LargeList, Utf8View, BinaryView,
IntervalMonthDayNano)
- arrow-compat job in nodejs.yml that runs tests with arrow 19 and 20
(adds 2 sec)
- put the list of arrow types in one place
- update NODEJS_THIRD_PARTY_LICENSES.md
- regenerated typescript docs (sorry about reorderings, one time cost)
- reformat arrow.test.ts (sorry, almost all whitespace, thanks to biome.
git diff -w shows 110 lines edited)
- fixed Sliced Utf8View / BinaryView serialization error, by just
converting them to Utf8 and Binary (as our rust code would anyway)
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
`pnpm audit` in `nodejs/` reported a number of vulnerable transitive
dependencies. Most were resolved by `pnpm audit --fix`, which bumped the
affected packages in the lockfile; the `minimumReleaseAgeExclude`
additions in `pnpm-workspace.yaml` are its bookkeeping, exempting the
specific patched versions from the repository's 24-hour hold on newly
published packages. Two findings needed handling by hand, because the
vulnerable package could not simply be moved to a newer release in
place.
`@opentelemetry/sdk-metrics` 1.30.1 pins `@opentelemetry/core` to its
own exact version, and the 1.x line is end-of-life, so
GHSA-8988-4f7v-96qf (unbounded memory allocation in W3C Baggage
propagation) has no fix available on 1.x. This PR moves the dependency
to 2.x, which brings in a patched `@opentelemetry/core`. It is a
dev-only dependency with a single consumer, `__test__/otel.test.ts`, and
the parts of the API that test uses are unchanged between 1.x and 2.x.
`@huggingface/transformers` pins `sharp: ^0.33.5`, and no released
version of transformers has moved past `^0.34.5` — every version in
those ranges inherits the libvips CVEs in GHSA-f88m-g3jw-g9cj, so there
is no upstream release to upgrade to. This PR adds a pnpm `overrides`
entry pinning sharp to the patched `^0.35.4` line instead.
`pnpm audit` now reports no known vulnerabilities.
## Not included
The sharp override only applies to this repository's own dependency
tree, since pnpm overrides are not published to npm. Anyone installing
`@lancedb/lancedb` together with the optional
`@huggingface/transformers` still resolves sharp 0.33.5, and will until
transformers itself moves to sharp 0.35. Practical exposure there is
low: the CVEs require decoding untrusted images, and LanceDB's
transformers embedding function is text-only.
`nodejs/examples/` is a separate install with its own lockfile and is
untouched here. It pins `sharp: "0.33.5"` directly and `pnpm audit`
reports 19 findings against it. Bumping sharp there is more involved
than it looks, because sharp 0.35 requires Node >= 20.9 while the
examples tests run on the Node 18/20 CI matrix, so it is left for
separate work.
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Xuanwo <github@xuanwo.io>
The bindings are built, installed and published with pnpm everywhere,
but a parallel npm dependency graph was still being maintained beside
it. This removes it, raises the supported Node floor to the versions we
actually test, and gives Dependabot the npm coverage it was missing.
## Dropping npm
`nodejs/package-lock.json` was regenerated by `ci/update_lockfiles.sh`
on every release commit and read by nothing — no workflow runs `npm ci`
or `npm install` in `nodejs/`, and npm never publishes a lockfile in a
package tarball. It could not even agree with the real install, since
npm does not see pnpm's `overrides`. Because GitHub's dependency graph
parses `package-lock.json`, it was also reporting vulnerabilities for a
tree we neither install nor ship.
`docs/package.json`, `docs/package-lock.json` and `docs/tsconfig.json`
go too. They depend on `file:../node` and
`file:../node/node_modules/apache-arrow` — the `node/` directory was
removed long ago — the tsconfig compiles `src/*.ts` where no TypeScript
files exist, and nothing installs any of it. `docs.yml` only referenced
the lockfile to configure an npm cache for an install it never ran.
Two `workflow_dispatch` workflows for regenerating those lockfiles are
removed as well. Both were already broken: they `uses:` composite
actions at `.github/workflows/update_package_lock{,_nodejs}` that do not
exist, so dispatching either failed immediately.
The remaining `npx` calls become direct `node_modules/.bin/...`
invocations. These were already running locally installed binaries
rather than resolving anything, but naming the binary removes the npm
CLI from the loop and does not depend on which Node version is active.
`dev.yml`'s commitlint check was the last place doing real npm
dependency resolution — an unpinned `npm install
@commitlint/config-conventional` that also bypassed the
`minimumReleaseAge` hold configured for `nodejs/` — and is now a pinned
`pnpm dlx`.
## Node support
Node 18 and 20 both reached end-of-life, in April 2025 and April 2026.
The matrix moves to 22, 24 and 26, and `engines` rises from `>= 18` to
`>= 22` so the declared floor is one the matrix actually covers. Node 22
is LTS until April 2027; 24 is LTS; 26 is Current and becomes LTS in
October 2026.
This also removes the reason the workflows reached for `npx` in the
first place: pnpm 11 requires Node >= 22.13, which every matrix version
now satisfies.
The prebuilt-binary smoke test in `npm-publish.yml` moves from Node 20
to Node 22 — the floor, where a napi ABI problem would surface first —
rather than fanning out across all three, to keep the publish matrix
from tripling.
## Dependabot
There were no npm-ecosystem entries at all, which is why the advisories
behind #4073 went unnoticed. Both pnpm lockfiles are now watched —
`nodejs/` and `nodejs/examples/`, which is a separate install — using
the same `lockfile-only` strategy as the existing cargo and pip entries,
so version ranges in `package.json` are left alone.
## Pre-commit biome
The hook ran `npx @biomejs/biome@1.8.3` while `nodejs/package.json`
resolved 1.9.4. The two disagree about formatting, so the hook rejected
code that `pnpm lint` accepts, and failed on unmodified `main` for
anyone touching `nodejs/`. It now uses the pnpm-managed biome, which
fixes the drift with no source changes.
## Testing
`dev.yml`'s commitlint job does not check out the repo, so it runs in an
empty workspace, and I could not verify `pnpm/action-setup` there
locally. It triggers on `pull_request_target`, so this PR exercises it
directly — worth confirming green before merge. I did verify the `pnpm
dlx` invocation itself locally: it accepts a conventional title and
rejects a non-conventional one with exit 1.
Node 26 is new enough that the examples job may surface gaps in prebuilt
native binaries (`onnxruntime-node`, `sharp`) before their maintainers
publish for it.
## Not included
`nodejs/examples/` still pins `sharp: "0.33.5"` and has its own audit
findings. Raising the Node floor unblocks that work — sharp 0.35
requires Node >= 20.9, which the matrix now satisfies — but it is a
dependency bump rather than tooling cleanup, so it is left separate.
## Breaking changes
`@lancedb/lancedb` now requires Node >= 22; previously >= 18. The
`@types/node` peer range moves from `>=18` to `>=22` to match. Users on
Node 18 or 20 must upgrade their runtime; both have been end-of-life for
some time. Existing installs are unaffected, since `engines` is only
checked on install.
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Summary
- require Node.js 18-compatible type declarations when TypeScript
consumers install them
- keep the type peer optional for JavaScript-only consumers
- add a regression test tying the Node type peer range to the supported
runtime
## Root cause
LanceDB requires Node.js 18 or newer, and its public types expose Apache
Arrow declarations that import built-ins through the node: scheme. The
package did not declare a matching @types/node peer requirement, so npm
accepted projects pinned to Node 12 declarations and TypeScript then
reported that node:stream and node:fs/promises did not exist.
## Validation
- pnpm lint
- pnpm build
- pnpm run docs
- pnpm test --runInBand (678 passed, 5 skipped)
- packed-package consumer probe rejects @types/node 12.20.55 and
installs with @types/node 18.19.130
Fixes#1713
<!-- lance-gatekeeper-fix:v1 agent=7a2b68f3daad20bed9e46cb8892d6e6c
generation=1 -->
Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>