node-postgres icon indicating copy to clipboard operation
node-postgres copied to clipboard

New exports break TypeScript "bundler" compilation

Open pfumagalli opened this issue 7 months ago • 4 comments

https://github.com/brianc/node-postgres/blob/9bfc967e91d4c347d7a58f0f3732c2514f272afa/packages/pg-protocol/package.json#L7-L18

It seems that by adding the new "exports" flags to package.json, now when compiling anything depending on pg (and relatively @types/pg) using the bundler module resolution fails with:

│ /home/runner/work/lib-sqs/lib-sqs/node_modules/@types/pg/index.d.ts
│   12:31  Cannot find module 'pg-protocol/dist/messages' or its corresponding type declarations. [TS2307]
│          | import { NoticeMessage } from 'pg-protocol/dist/messages';

I think the correct definition for the dist export in package.json should be something like the following:

"exports": {
  ".": {
    "import": "./esm/index.js",
    "types": "./dist/index.d.ts",
    "require": "./dist/index.js",
    "default": "./dist/index.js"
  },
  "./dist/*": {
    "types": "./dist/*.d.ts",
    "require": "./dist/*.js"
  }
}

Nothing in dist seems to be an ESM module (so no "import") and types and extensions should be explicit...

pfumagalli avatar May 05 '25 14:05 pfumagalli

ah okay thanks for that report and thanks for the suggested changes! Any idea how I could repro this locally so I can test my fix works? Otherwise i'll just be kinda blindly publishing changes to npm hoping it fixes your issue.

brianc avatar May 05 '25 17:05 brianc

Upon further inspection, this might not be a bug in pg-protocolo but rather in the plethora of cross dependencies between all pg packages and related.

Spent some time to try and find a minimal reproduction (wasn't easy). It stems from here:

https://github.com/getsentry/sentry-javascript/issues/16196

Now, it seems that @sentry/node imports @opentelemetry/[email protected], and that imports:

To cut the story short, the problem is when an older version of the @types/pg (pre 8.11) is imported somewhere in the tree.

Version 8.10.9 of @types/pg imports simply the following:

import { NoticeMessage } from "pg-protocol/dist/messages";

rather than the newer:

import { NoticeMessage } from "pg-protocol/dist/messages.js";

Without the new exports field TypeScript was free to resolve all sorts of stuff and it somehow found the types, with when this was introduced, it now behaves a lot more strictly, and can't ultimately resolve the messages.d.ts file.

And given that dependencies to pg-protocol are associated with the * version, and this breaking change happened in a minor version, NPM gets lost, dedupes what it shouldn't, and the whole thing falls over!

The above changes definitely fix the problem for now but I wouldn't know if they will introduce some issues in the future.

I'd say that if anyone stumbles on this issue, they should make sure that there are no pre-8.11 versions of @types/pg in their tree or (as I did) should locally declare a dependency to pg-protocol to a version <1.9.

The minimal repro is attached. Basically, a simple package with two dependencies:

    "@types/pg": "<8.11"
    "pg": "<8.11"

makes compilation fail in bundler, nodenext and possibly other modes.

Here's the zip file.

pfumagalli avatar May 05 '25 18:05 pfumagalli

It looks like the updated types were released yesterday in v8.15.1 of @types/pg. This has fixed the above error for me.

WolfyUK avatar May 09 '25 04:05 WolfyUK

@pfumagalli @WolfyUK thanks for the diagnosis!

Workaround is to use overrides to override the version explicitly in your package.json:

{
    "name": "mypackage",
    "version": "1.2.3",
    ...

    "overrides": {
        "@types/pg": "8.15.1"
    },
    ...
    "devDependencies": {
    ...
}

phillipuniverse avatar May 29 '25 20:05 phillipuniverse