Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: build pg-cloudflare as a CommonJS module #3168

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mrbbot
Copy link

@mrbbot mrbbot commented Mar 12, 2024

Hey! 👋 We're currently working on an integration between Cloudflare Workers and Vitest, allowing you to run your Vitest tests inside the Workers runtime. A community member tried out an early version of this integration and uncovered an issue with pg/pg-cloudflare (cloudflare/workers-sdk#5127 (comment)).

In pg/lib/stream.js, pg-cloudflare is require()ed...

const { CloudflareSocket } = require('pg-cloudflare')

...but pg-cloudflare is compiled to an ES module. ES modules can't be require()d so this shouldn't work. Fortunately, Workers are usually bundled with esbuild which papers over differences between the module formats and allowed this to work. Our Vitest integration uses a "bundle-less" approach that imports modules at runtime from disk more like Node. This meant pg-cloudflare couldn't be require()d by pg, failing any Workers tests using pg.

This PR updates pg-cloudflare's tsconfig.json to compile to CommonJS instead, fixing this issue. 👍

/cc @petebacondarwin

@mrbbot mrbbot changed the title fix: build pg-cloudflare to a CommonJS module fix: build pg-cloudflare as a CommonJS module Mar 12, 2024
Copy link
Collaborator

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Collaborator

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@petebacondarwin
Copy link
Collaborator

The problem with converting this module to CommonJS is this line:

const { connect } = await import('cloudflare:sockets')

If we compile this code to CommonJS this becomes a dynamic require, which the Wrangler bundler then complains about, since the esbuild output results in a dynamic `require("cloudflare:sockets") call.

Could we solve this instead by marking the package as an ESM module (i.e. "type": "module" in its package.json)?
Surely Vite(st) can handle packages that are declared ESM?

@mrbbot
Copy link
Author

mrbbot commented Mar 13, 2024

Surely Vite(st) can handle packages that are declared ESM?

Not in this case. These files don't get transformed by Vite, and are imported using the workerd module fallback service. This means they have strict module semantics, and require() can't be used to import an ES module. We should be able to keep the dynamic import() in the output rather than converting this to a require(). Not quite sure what the tsconfig.json incantation is though, will investigate more tomorrow. 👍

@mrbbot mrbbot force-pushed the pg-cloudflare-common-js branch from 1951ca2 to 8d97107 Compare March 13, 2024 23:05
@mrbbot
Copy link
Author

mrbbot commented Mar 13, 2024

Looks like the magic incantation is "module": "Node16" and "moduleResolution": "Node16". This compiles to a CommonJS module, but keeps dynamic import()s in the output. 👍

@unicoder88
Copy link

unicoder88 commented Oct 20, 2024

Hey @petebacondarwin ! I'm also struggling with this issue - node-pg not working under Vitest.

Could we solve this instead by marking the package as an ESM module (i.e. "type": "module" in its package.json)? Surely Vite(st) can handle packages that are declared ESM?

I actually tried this, but then this line fails - https://github.com/brianc/node-postgres/blob/master/packages/pg/lib/stream.js#L41

const { CloudflareSocket } = require('pg-cloudflare')
image

As a proof of concept, I manually converted compiled node/modules/pg-cloudflare/dist/index.js to CommonJS syntax, and my test finally went through.

const { EventEmitter } = require('events'); // import { EventEmitter } from 'events';

class CloudflareSocket extends EventEmitter {
  // ...
}

module.exports.CloudflareSocket = CloudflareSocket;

Is there any research I should do to help push this through?

@petebacondarwin
Copy link
Collaborator

@unicoder88 - are you trying to get the library to work with Vitest in general or using the Cloudflare vitest-pool-workers integration?

@unicoder88
Copy link

@petebacondarwin , right, it's specifically Cloudflare vitest-pool-workers

@petebacondarwin
Copy link
Collaborator

We have a similar concern with the Vite Environments integration that we are working on.
Hopefully we can resolve this in a general way in the next few weeks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants