DEP0151 warning on Node 22 ESM consumers — package.json missing `exports` field · Issue #421 · tree-sitter/tree-sitter-c-sharp · GitHub
Skip to content

DEP0151 warning on Node 22 ESM consumers — package.json missing exports field #421

Description

@azizur100389

Problem

On Node 22, an ESM consumer importing tree-sitter-c-sharp as a bare package specifier triggers a DEP0151 deprecation warning on every import:

(node:NNNN) [DEP0151] DeprecationWarning: Package .../tree-sitter-c-sharp/ has a "main" field set to "bindings/node" -- which does not include the file extension --
and no "exports" field.
Automatic extension resolution of the "main" field is deprecated for ES modules.

See Node DEP0151.

Root cause

The current package.json declares:

{
  "type": "module",
  "main": "bindings/node",
  "types": "bindings/node"
}

main has no file extension AND there is no exports field, so Node's ESM resolver falls back to the deprecated main-field auto-extension lookup and prints the warning. Because the package is "type": "module", this affects every ESM consumer; CJS consumers don't hit this path.

Affected versions

  • tree-sitter-c-sharp@0.23.1 (verified)
  • tree-sitter-c-sharp@0.23.5 (verified — current latest on npm)

Minimal repro

mkdir tsc-demo && cd tsc-demo
echo '{"type":"module"}' > package.json
npm install tree-sitter-c-sharp
cat > main.mjs <<'JS'
import CSharp from 'tree-sitter-c-sharp';
console.log('loaded', typeof CSharp);
JS
NODE_OPTIONS='--trace-deprecation --trace-warnings' node main.mjs

Observed: the DEP0151 warning prints before loaded object.

Proposed fix

Add an exports field to package.json:

{
  "type": "module",
  "main": "bindings/node",
  "types": "bindings/node",
  "exports": {
    ".": {
      "types": "./bindings/node/index.d.ts",
      "default": "./bindings/node/index.js"
    }
  }
}

That declaration makes the entry point explicit, bypasses the deprecated resolution path, and keeps the existing bare import (import CSharp from 'tree-sitter-c-sharp') working.

If the maintainers also want to keep existing subpath imports like 'tree-sitter-c-sharp/bindings/node/index.js' or 'tree-sitter-c-sharp/package.json' accessible (some downstream consumers use them as a local workaround for this exact warning), the exports map can include a passthrough:

"exports": {
  ".": { "types": "./bindings/node/index.d.ts", "default": "./bindings/node/index.js" },
  "./package.json": "./package.json",
  "./bindings/*": "./bindings/*"
}

Notes

  • This is a metadata-only change — no grammar or binding code touched.
  • Once the exports field is published, bare imports stop emitting the warning and downstream packages can simplify any explicit-subpath workarounds they've shipped.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions