Repository navigation
pg 8.22.0 CJS entry can resolve pg-protocol as ESM under Cloudflare/Vite worker tests #3700
Description
Activity
- Does the earlier version of pg-protocol still not import correctly? Sorry this happened. It seems like the seemingly harmless upgrade of typescript might have broken this as well as another thing. Can you test out an older version? Say ***@***.*** and lmk if it still has problems?…On Thu, Jun 25, 2026 at 1:03 PM Alex Stanciu ***@***.***> wrote: *astanciu* created an issue (brianc/node-postgres#3700) <#3700> Summary When ***@***.*** is bundled by the @cloudflare/vitest-pool-workers / Vite worker-test pipeline in a pnpm workspace, the CommonJS entry can fail while loading pg-protocol from pg/lib/connection.js: SyntaxError: Cannot use import statement outside a module at ***@***.***/node_modules/pg/lib/connection.js?mf_vitest_no_cjs_esm_shim:5:30 at ***@***.***/node_modules/pg/lib/client.js?mf_vitest_no_cjs_esm_shim:10:20 at ***@***.***/node_modules/pg/lib/index.js The failing line is the CommonJS package-name require: const { parse, serialize } = require("pg-protocol") In this environment, that dependency can be resolved/transformed as an ES module, then loaded from a CJS wrapper. Environment - pg: 8.22.0 - pg-protocol: 1.15.0 - package manager: pnpm - test/bundler stack: @cloudflare/vitest-pool-workers + Vite + Miniflare/workerd - worker compatibility flag: nodejs_compat Local workaround We currently patch pg to force the CJS files to load the CJS dependency files directly from pnpm's sibling layout: -const { parse, serialize } = require("pg-protocol")+const { parse, serialize } = require("../../pg-protocol/dist/index.js") -const Pool = require("pg-pool")+const Pool = require("../../pg-pool/index.js") -const parse = require("pg-connection-string").parse+const parse = require("../../pg-connection-string/index.js").parse That patch is not a good general solution because it depends on pnpm's installed package layout. Ask Would pg consider an upstream change that makes the CommonJS entry robust in bundler/worker environments, for example by ensuring the CJS entry always resolves CJS-compatible dependency entrypoints for pg-protocol, pg-pool, and pg-connection-string? Happy to provide more details or test a candidate fix. — Reply to this email directly, view it on GitHub <#3700?email_source=notifications&email_token=AAAMHIK5RVUC36XRRLVPJO35BVSOVA5CNFSL4Z3JMQ5C6L3HNF2C22DVMIXUS43TOVSS6NBXGQ3DENJTHA2DPJTSMVQXG33OVJZXKYTTMNZGSYTFMSSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAAMHIKJKEINQ3Y6IUYJLAD5BVSOVAVCNFSNUABCKJSXA33TNF2G64TZHM4TSMJUG42TWSLTON2WKOZUG42DMMRVGM4DIN5BOYBA> . You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
@brianc the version you mentioned got obfuscated as an email, mind sending it again? I've had to patch this since at least since 8.20
Ah weird the email got eaten. I was wondering if v 8.19 or so also had the issue. I am fairly certain its due to the typescript compiler version change. Mildly frustrating how fragile that is. If you have a bit of time to bisect what version introduced the problem that would help me figure out an exact fix. Or a way to reproduce it locally. I have some esm/cjs import tests in the repository so not sure what didnt get caught.
Thanks. I tested this in a throwaway copy of our repo with the
pgpatch removed.Repro command:
pnpm test apps/request-svc/tests/request-worker.test.tsEnvironment is
@cloudflare/vitest-pool-workers+ Vite + Miniflare/workerd,nodejs_compat, pnpm 11.9.0.Results:
pg@8.22.0+pg-protocol@1.15.0: failspg@8.21.0+pg-protocol@1.15.0: failspg@8.20.0+pg-protocol@1.15.0: failspg@8.19.0: also fails in our workspace, though pnpm still resolvespg-protocol@1.15.0because we useresolutionMode: highest
I also forced older
pg-protocolversions:pg@8.22.0+pg-protocol@1.14.0: failspg@8.22.0+pg-protocol@1.12.0: fails
So I don't think this is only the TS 6-built
pg-protocol@1.15.0.The minimal fix I tested was changing only pg's CJS imports from:
require("pg-protocol")
to:
require("pg-protocol/dist/index.js")
in
pg/lib/connection.jsandpg/lib/index.js.That makes our worker test pass.
pg-protocolalready exports./dist/*.js, so this avoids our current pnpm-relative workaround.I reduced this to a small standalone repro. No database connection is needed; just importing
pginside the Cloudflare Vitest worker runtime is enough.Run:
pnpm install pnpm testpackage.json{ "name": "pg-worker-repro", "private": true, "type": "module", "packageManager": "pnpm@11.9.0", "scripts": { "test": "vitest run" }, "dependencies": { "pg": "8.22.0" }, "devDependencies": { "@cloudflare/vitest-pool-workers": "0.16.18", "typescript": "7.0.1-rc", "vitest": "4.1.9", "wrangler": "4.103.0" } }pnpm-workspace.yamlresolutionMode: highest allowBuilds: esbuild: true sharp: true workerd: true
wrangler.jsonc{ "$schema": "https://unpkg.com/wrangler@latest/config-schema.json", "name": "pg-worker-repro", "main": "src/worker.ts", "compatibility_date": "2026-02-24", "compatibility_flags": ["nodejs_compat"] }vitest.config.tsimport { cloudflareTest } from "@cloudflare/vitest-pool-workers"; import { defineConfig } from "vitest/config"; export default defineConfig({ plugins: [ cloudflareTest({ wrangler: { configPath: "./wrangler.jsonc", }, miniflare: { compatibilityFlags: ["nodejs_compat"], }, }), ], test: { include: ["src/**/*.test.ts"], server: { deps: { inline: ["pg", "pg-protocol"], }, }, ssr: { noExternal: ["pg", "pg-protocol"], }, }, });
src/worker.tsexport default { fetch() { return new Response("ok"); }, };
src/pg.test.tsimport { test, expect } from "vitest"; import pg from "pg"; test("pg imports in the Workers Vitest runtime", () => { expect(pg.Client).toBeTypeOf("function"); });
Failure:
SyntaxError: Cannot use import statement outside a module ❯ node_modules/.pnpm/pg@8.22.0/node_modules/pg/lib/connection.js?mf_vitest_no_cjs_esm_shim:5:30 ❯ node_modules/.pnpm/pg@8.22.0/node_modules/pg/lib/client.js?mf_vitest_no_cjs_esm_shim:10:20 ❯ node_modules/.pnpm/pg@8.22.0/node_modules/pg/lib/index.js:3:16I also verified the reduced repro passes if
pgchanges these two CJS imports:// pg/lib/connection.js -const { parse, serialize } = require("pg-protocol") +const { parse, serialize } = require("pg-protocol/dist/index.js") // pg/lib/index.js -const { DatabaseError } = require("pg-protocol") +const { DatabaseError } = require("pg-protocol/dist/index.js")
I traced this to @cloudflare/vitest-plugin, not to pg. Under Vite 8, the plugin resolves every CommonJS
require()with theimportcondition. It flags arequirethroughcustom['node-resolve'].isRequire, which Vite 8 ignores. That is cloudflare/workers-sdk#12984, with a draft fix in cloudflare/workers-sdk#13062.Evidence (pg 8.23.1, @cloudflare/vitest-plugin 1.3.6, vitest 4.1.11, Vite 8.3.3, no
deps.optimizerworkaround):require('pg-protocol')resolves topg-protocol/esm/index.js, the import entry.- With fix: use pg-protocol CommonJS entrypoint #3749,
require('pg-cloudflare')resolves toesm/index.mjsand returnsundefined, so the first query fails. - With
kind: isRequire ? 'require-call' : 'import-statement'added to the plugin'sviteResolve(), unmodified pg 8.23.1 runs a query. That works now that fix(binding): forward resolveId options.kind to callable builtin plugins rolldown/rolldown#10440 forwardskind.
Until the plugin is fixed: pre-bundle
pgwithtest.deps.optimizer.ssr(enabled: true,include: ['pg']), keepingnode:*built-ins external.
Summary
When
pg@8.22.0is bundled by the@cloudflare/vitest-pool-workers/ Vite worker-test pipeline in a pnpm workspace, the CommonJS entry can fail while loadingpg-protocolfrompg/lib/connection.js:The failing line is the CommonJS package-name require:
In this environment, that dependency can be resolved/transformed as an ES module, then loaded from a CJS wrapper.
Environment
pg:8.22.0pg-protocol:1.15.0pnpm@cloudflare/vitest-pool-workers+ Vite + Miniflare/workerdnodejs_compatLocal workaround
We currently patch
pgto force the CJS files to load the CJS dependency files directly from pnpm's sibling layout:That patch is not a good general solution because it depends on pnpm's installed package layout.
Ask
Would
pgconsider an upstream change that makes the CommonJS entry robust in bundler/worker environments, for example by ensuring the CJS entry always resolves CJS-compatible dependency entrypoints forpg-protocol,pg-pool, andpg-connection-string?Happy to provide more details or test a candidate fix.