fix(pg-cloudflare): use conditional export to support bundlers that don't know about cloudflare:sockets (#3482)

This commit is contained in:
Henry Cai 2025-06-12 07:31:57 -07:00 committed by GitHub
parent 0ada72e608
commit 6b016b37d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 1061 additions and 16 deletions

View File

@ -0,0 +1,8 @@
import * as esbuild from 'esbuild'
await esbuild.build({
entryPoints: ['./src/index.mjs'],
bundle: true,
outfile: './dist/esbuild-cloudflare.js',
conditions: ['import', 'cloudflare'],
})

View File

@ -0,0 +1,7 @@
import * as esbuild from 'esbuild'
await esbuild.build({
entryPoints: ['./src/index.mjs'],
bundle: true,
outfile: './dist/esbuild-empty.js',
})

View File

@ -0,0 +1,25 @@
{
"name": "pg-bundler-test",
"version": "0.0.0",
"description": "Test bundlers with pg-cloudflare, https://github.com/brianc/node-postgres/issues/3452",
"license": "MIT",
"private": true,
"type": "module",
"devDependencies": {
"pg-cloudflare": "^1.2.5",
"webpack": "^5.99.9",
"webpack-cli": "^6.0.1",
"rollup": "^4.41.1",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-commonjs": "^28.0.3",
"vite": "^6.3.5",
"esbuild": "^0.25.5"
},
"scripts": {
"test": "yarn webpack && yarn rollup && yarn vite && yarn esbuild",
"webpack": "webpack --config webpack-empty.config.mjs && webpack --config webpack-cloudflare.config.mjs",
"rollup": "rollup --config rollup-empty.config.mjs --failAfterWarnings && rollup --config rollup-cloudflare.config.mjs --failAfterWarnings",
"vite": "[ $(node --version | sed 's/v//' | cut -d'.' -f1) -ge 18 ] && vite build --config vite-empty.config.mjs && vite build --config vite-cloudflare.config.mjs || echo 'Skip Vite test'",
"esbuild": "node esbuild-empty.config.mjs && node esbuild-cloudflare.config.mjs"
}
}

View File

@ -0,0 +1,13 @@
import { defineConfig } from 'rollup'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
export default defineConfig({
input: './src/index.mjs',
output: {
file: 'dist/rollup-cloudflare.js',
format: 'es',
},
plugins: [nodeResolve({ exportConditions: ['import', 'cloudflare'], preferBuiltins: true }), commonjs()],
external: ['cloudflare:sockets'],
})

View File

@ -0,0 +1,12 @@
import { defineConfig } from 'rollup'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
export default defineConfig({
input: './src/index.mjs',
output: {
file: 'dist/rollup-empty.js',
format: 'es',
},
plugins: [nodeResolve(), commonjs()],
})

View File

@ -0,0 +1 @@
import 'pg-cloudflare'

View File

@ -0,0 +1,20 @@
import { defineConfig } from 'vite'
import commonjs from '@rollup/plugin-commonjs'
export default defineConfig({
build: {
emptyOutDir: false,
lib: {
entry: './src/index.mjs',
fileName: 'vite-cloudflare',
formats: ['es'],
},
rollupOptions: {
external: ['cloudflare:sockets'],
},
},
resolve: {
conditions: ['import', 'cloudflare'],
},
plugins: [commonjs()],
})

View File

@ -0,0 +1,12 @@
import { defineConfig } from 'vite'
export default defineConfig({
build: {
emptyOutDir: false,
lib: {
entry: './src/index.mjs',
fileName: 'vite-empty',
formats: ['es'],
},
},
})

View File

@ -0,0 +1,16 @@
import webpack from 'webpack'
export default {
mode: 'production',
entry: './src/index.mjs',
output: {
filename: 'webpack-cloudflare.js',
},
resolve: { conditionNames: ['import', 'cloudflare'] },
plugins: [
// ignore cloudflare:sockets imports
new webpack.IgnorePlugin({
resourceRegExp: /^cloudflare:sockets$/,
}),
],
}

View File

@ -0,0 +1,7 @@
export default {
mode: 'production',
entry: './src/index.mjs',
output: {
filename: 'webpack-empty.js',
},
}

View File

@ -10,6 +10,59 @@
npm i --save-dev pg-cloudflare
```
The package uses conditional exports to support bundlers that don't know about
`cloudflare:sockets`, so the consumer code by default imports an empty file. To
enable the package, resolve to the `cloudflare` condition in your bundler's
config. For example:
- `webpack.config.js`
```js
export default {
...,
resolve: { conditionNames: [..., "cloudflare"] },
plugins: [
// ignore cloudflare:sockets imports
new webpack.IgnorePlugin({
resourceRegExp: /^cloudflare:sockets$/,
}),
],
}
```
- `vite.config.js`
```js
export default defineConfig({
...,
resolve: {
conditions: [..., "cloudflare"],
},
build: {
...,
// don't try to bundle cloudflare:sockets
rollupOptions: {
external: [..., 'cloudflare:sockets'],
},
},
})
```
- `rollup.config.js`
```js
export default defineConfig({
...,
plugins: [..., nodeResolve({ exportConditions: [..., 'cloudflare'] })],
// don't try to bundle cloudflare:sockets
external: [..., 'cloudflare:sockets'],
})
```
- `esbuild.config.js`
```js
await esbuild.build({
...,
conditions: [..., 'cloudflare'],
})
```
The concrete examples can be found in `packages/pg-bundler-test`.
## How to use conditionally, in non-Node.js environments
As implemented in `pg` [here](https://github.com/brianc/node-postgres/commit/07553428e9c0eacf761a5d4541a3300ff7859578#diff-34588ad868ebcb232660aba7ee6a99d1e02f4bc93f73497d2688c3f074e60533R5-R13), a typical use case might look as follows, where in a Node.js environment the `net` module is used, while in a non-Node.js environment, where `net` is unavailable, `pg-cloudflare` is used instead, providing an equivalent interface:
@ -21,7 +74,7 @@ module.exports.getStream = function getStream(ssl = false) {
return net.Socket()
}
const { CloudflareSocket } = require('pg-cloudflare')
return new CloudflareSocket(ssl);
return new CloudflareSocket(ssl)
}
```
@ -29,7 +82,6 @@ module.exports.getStream = function getStream(ssl = false) {
If you're looking for a way to rely on `connect()` as the interface you use to interact with raw sockets, but need this interface to be available in a Node.js environment, [`@arrowood.dev/socket`](https://github.com/Ethan-Arrowood/socket) provides a Node.js implementation of the Socket API.
### license
The MIT License (MIT)

View File

@ -11,9 +11,11 @@
},
"exports": {
".": {
"import": "./esm/index.mjs",
"require": "./dist/index.js",
"default": "./dist/index.js"
"cloudflare": {
"import": "./esm/index.mjs",
"require": "./dist/index.js"
},
"default": "./dist/empty.js"
}
},
"scripts": {

View File

@ -5,7 +5,7 @@
"main": "index.js",
"type": "module",
"scripts": {
"test": "node --test"
"test": "node --test --conditions=cloudflare"
},
"keywords": [
"postgres",

890
yarn.lock

File diff suppressed because it is too large Load Diff