diff --git a/packages/pg/lib/stream.js b/packages/pg/lib/stream.js index 67b1b3c81..cb0839878 100644 --- a/packages/pg/lib/stream.js +++ b/packages/pg/lib/stream.js @@ -1,28 +1,81 @@ +const { getStream, getSecureStream } = getStreamFuncs() + +module.exports = { + /** + * Get a socket stream compatible with the current runtime environment. + * @returns {Duplex} + */ + getStream, + /** + * Get a TLS secured socket, compatible with the current environment, + * using the socket and other settings given in `options`. + * @returns {Duplex} + */ + getSecureStream, +} + /** - * Get a socket stream compatible with the current runtime environment. - * @returns {Duplex} + * The stream functions that work in Node.js */ -module.exports.getStream = function getStream(ssl) { - const net = require('net') - if (typeof net.Socket === 'function') { +function getNodejsStreamFuncs() { + function getStream(ssl) { + const net = require('net') return new net.Socket() - } else { - const { CloudflareSocket } = require('pg-cloudflare') - return new CloudflareSocket(ssl) + } + + function getSecureStream(options) { + var tls = require('tls') + return tls.connect(options) + } + return { + getStream, + getSecureStream, } } /** - * Get a TLS secured socket, compatible with the current environment, - * using the socket and other settings given in `options`. - * @returns {Duplex} + * The stream functions that work in Cloudflare Workers */ -module.exports.getSecureStream = function getSecureStream(options) { - var tls = require('tls') - if (tls.connect) { - return tls.connect(options) - } else { +function getCloudflareStreamFuncs() { + function getStream(ssl) { + const { CloudflareSocket } = require('pg-cloudflare') + return new CloudflareSocket(ssl) + } + + function getSecureStream(options) { options.socket.startTls(options) return options.socket } + return { + getStream, + getSecureStream, + } +} + +/** + * Are we running in a Cloudflare Worker? + * + * @returns true if the code is currently running inside a Cloudflare Worker. + */ +function isCloudflareRuntime() { + // Since 2022-03-21 the `global_navigator` compatibility flag is on for Cloudflare Workers + // which means that `navigator.userAgent` will be defined. + if (typeof navigator === 'object' && navigator !== null && typeof navigator.userAgent === 'string') { + return navigator.userAgent === 'Cloudflare-Workers' + } + // In case `navigator` or `navigator.userAgent` is not defined then try a more sneaky approach + if (typeof Response === 'function') { + const resp = new Response(null, { cf: { thing: true } }) + if (typeof resp.cf === 'object' && resp.cf !== null && resp.cf.thing) { + return true + } + } + return false +} + +function getStreamFuncs() { + if (isCloudflareRuntime()) { + return getCloudflareStreamFuncs() + } + return getNodejsStreamFuncs() }