stream.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. const { getStream, getSecureStream } = getStreamFuncs()
  2. module.exports = {
  3. /**
  4. * Get a socket stream compatible with the current runtime environment.
  5. * @returns {Duplex}
  6. */
  7. getStream,
  8. /**
  9. * Get a TLS secured socket, compatible with the current environment,
  10. * using the socket and other settings given in `options`.
  11. * @returns {Duplex}
  12. */
  13. getSecureStream,
  14. }
  15. /**
  16. * The stream functions that work in Node.js
  17. */
  18. function getNodejsStreamFuncs() {
  19. function getStream(ssl) {
  20. const net = require('net')
  21. return new net.Socket()
  22. }
  23. function getSecureStream(options) {
  24. const tls = require('tls')
  25. return tls.connect(options)
  26. }
  27. return {
  28. getStream,
  29. getSecureStream,
  30. }
  31. }
  32. /**
  33. * The stream functions that work in Cloudflare Workers
  34. */
  35. function getCloudflareStreamFuncs() {
  36. function getStream(ssl) {
  37. const { CloudflareSocket } = require('pg-cloudflare')
  38. return new CloudflareSocket(ssl)
  39. }
  40. function getSecureStream(options) {
  41. options.socket.startTls(options)
  42. return options.socket
  43. }
  44. return {
  45. getStream,
  46. getSecureStream,
  47. }
  48. }
  49. /**
  50. * Are we running in a Cloudflare Worker?
  51. *
  52. * @returns true if the code is currently running inside a Cloudflare Worker.
  53. */
  54. function isCloudflareRuntime() {
  55. // Since 2022-03-21 the `global_navigator` compatibility flag is on for Cloudflare Workers
  56. // which means that `navigator.userAgent` will be defined.
  57. // eslint-disable-next-line no-undef
  58. if (typeof navigator === 'object' && navigator !== null && typeof navigator.userAgent === 'string') {
  59. // eslint-disable-next-line no-undef
  60. return navigator.userAgent === 'Cloudflare-Workers'
  61. }
  62. // In case `navigator` or `navigator.userAgent` is not defined then try a more sneaky approach
  63. if (typeof Response === 'function') {
  64. const resp = new Response(null, { cf: { thing: true } })
  65. if (typeof resp.cf === 'object' && resp.cf !== null && resp.cf.thing) {
  66. return true
  67. }
  68. }
  69. return false
  70. }
  71. function getStreamFuncs() {
  72. if (isCloudflareRuntime()) {
  73. return getCloudflareStreamFuncs()
  74. }
  75. return getNodejsStreamFuncs()
  76. }