electric-sql / pglite

Lightweight WASM Postgres with real-time, reactive bindings.
https://pglite.dev
Apache License 2.0
8.33k stars 164 forks source link

missing WebSocket dependency for node environments #90

Closed nurturenature closed 1 month ago

nurturenature commented 4 months ago

Hi,

When trying to use PGlite with node:

{
    "dependencies": {
      "@electric-sql/pglite": "canary",
      "electric-sql": "canary"
  }
}
/* PGlite */
import { PGlite } from "@electric-sql/pglite";
import { electrify } from 'electric-sql/pglite'
import { schema } from './generated/client/index.js'
import { ElectricConfig } from "electric-sql/config"
import { insecureAuthToken } from 'electric-sql/auth'

/* create an electric conn, database, and client */
const config: ElectricConfig = {
    url: process.env.ELECTRIC_SERVICE || 'http://electric:5133',
    debug: true
}
const pglite = new PGlite()
const electric = await electrify(pglite, schema, config)
await electric.connect(insecureAuthToken({ "sub": "insecure" }))

And at runtime:

> electric-pglite-client@0.0.1 app:start
> node dist/index.js

Using Postgres version: PostgreSQL 15devel on aarch64-apple-darwin22.6.0, compiled by emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.56 (cf90417346b78455089e64eb909d71d091ecc055), 32-bit
applying migration: 0
applying migration: 1
applying migration: 2
no lsn retrieved from store
connecting to electric server
server returned an error while establishing connection: WebSocket is not defined
connectAndStartRetryHandler was cancelled: WebSocket is not defined
connectAndStartRetryHandler was cancelled: WebSocket is not defined
file://.../pglite/node_modules/electric-sql/dist/sockets/web.js:9
    const ws = new WebSocket(opts.url, [this.protocolVsn]);
               ^

ReferenceError: WebSocket is not defined
    at WebSocketWeb.makeSocket (file://.../pglite/node_modules/electric-sql/dist/sockets/web.js:9:16)
    at WebSocketWeb.open (file://.../pglite/node_modules/electric-sql/dist/sockets/genericSocket.js:25:24)
    at file://.../pglite/node_modules/electric-sql/dist/satellite/client.js:228:19
    at new Promise (<anonymous>)
    at SatelliteClient.connect (file://.../pglite/node_modules/electric-sql/dist/satellite/client.js:188:12)
    at SatelliteProcess._connect (file://.../pglite/node_modules/electric-sql/dist/satellite/process.js:602:25)
    at BackOff.request (file://.../pglite/node_modules/electric-sql/dist/satellite/process.js:559:18)
    at BackOff.<anonymous> (/.../pglite/node_modules/exponential-backoff/dist/backoff.js:76:51)
    at step (/.../pglite/node_modules/exponential-backoff/dist/backoff.js:33:23)
    at Object.next (/.../pglite/node_modules/exponential-backoff/dist/backoff.js:14:53)

Node.js v20.12.2

Adding:

{
    "dependencies": {
      "ws": "^8.17.0"
  }
}

and doing:

sed -i "1s/^/import { WebSocket } from 'ws';\\n/" "./node_modules/electric-sql/dist/sockets/web.js"

allows the application to run.

From searching for this error message, it seems that WebSocket is available in the browser runtime but must be depended on by node?

slaskis commented 4 months ago

you might also want to try a newer version of node, as they added native WebSocket support behind a flag in v20.10 and without a flag in v22: https://nodejs.org/docs/latest/api/globals.html#websocket

nurturenature commented 4 months ago

Upgrading node:

$ node -v
v22.2.0

and installing:

$ rm -rf src/generated dist node_modules
$ npm install

fails:

npm error code 1
npm error path .../node_modules/electric-sql/node_modules/better-sqlite3
npm error command failed
npm error command sh -c prebuild-install || node-gyp rebuild --release
npm error make: Entering directory '.../node_modules/electric-sql/node_modules/better-sqlite3/build'
npm error   TOUCH ba23eeee118cd63e16015df367567cb043fed872.intermediate
npm error   ACTION deps_sqlite3_gyp_locate_sqlite3_target_copy_builtin_sqlite3 ba23eeee118cd63e16015df367567cb043fed872.intermediate
npm error   TOUCH Release/obj.target/deps/locate_sqlite3.stamp
npm error   CC(target) Release/obj.target/sqlite3/gen/sqlite3/sqlite3.o
npm error rm -f Release/obj.target/deps/sqlite3.a Release/obj.target/deps/sqlite3.a.ar-file-list; mkdir -p `dirname Release/obj.target/deps/sqlite3.a`
npm error ar crs Release/obj.target/deps/sqlite3.a @Release/obj.target/deps/sqlite3.a.ar-file-list
npm error   COPY Release/sqlite3.a
npm error   CXX(target) Release/obj.target/better_sqlite3/src/better_sqlite3.o
npm error rm ba23eeee118cd63e16015df367567cb043fed872.intermediate
npm error make: Leaving directory '.../node_modules/electric-sql/node_modules/better-sqlite3/build'
npm error prebuild-install warn install No prebuilt binaries found (target=22.2.0 runtime=node arch=x64 libc= platform=linux)
npm error gyp info it worked if it ends with ok
npm error gyp info using node-gyp@10.1.0
npm error gyp info using node@22.2.0 | linux | x64
npm error gyp info find Python using Python version 3.11.2 found at "/usr/bin/python3"
npm error gyp info spawn /usr/bin/python3
npm error gyp info spawn args [
npm error gyp info spawn args '/usr/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
npm error gyp info spawn args 'binding.gyp',
npm error gyp info spawn args '-f',
npm error gyp info spawn args 'make',
npm error gyp info spawn args '-I',
npm error gyp info spawn args '.../node_modules/electric-sql/node_modules/better-sqlite3/build/config.gypi',
npm error gyp info spawn args '-I',
npm error gyp info spawn args '/usr/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
npm error gyp info spawn args '-I',
npm error gyp info spawn args '.../.cache/node-gyp/22.2.0/include/node/common.gypi',
npm error gyp info spawn args '-Dlibrary=shared_library',
npm error gyp info spawn args '-Dvisibility=default',
npm error gyp info spawn args '-Dnode_root_dir=.../.cache/node-gyp/22.2.0',
npm error gyp info spawn args '-Dnode_gyp_dir=/usr/lib/node_modules/npm/node_modules/node-gyp',
npm error gyp info spawn args '-Dnode_lib_file=.../.cache/node-gyp/22.2.0/<(target_arch)/node.lib',
npm error gyp info spawn args '-Dmodule_root_dir=.../node_modules/electric-sql/node_modules/better-sqlite3',
npm error gyp info spawn args '-Dnode_engine=v8',
npm error gyp info spawn args '--depth=.',
npm error gyp info spawn args '--no-parallel',
npm error gyp info spawn args '--generator-output',
npm error gyp info spawn args 'build',
npm error gyp info spawn args '-Goutput_dir=.'
npm error gyp info spawn args ]
npm error gyp info spawn make
npm error gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
npm error In file included from ./src/better_sqlite3.lzz:11,
npm error                  from ../src/better_sqlite3.cpp:4:
npm error .../.cache/node-gyp/22.2.0/include/node/node.h:1248:7: warning: cast between incompatible function types from ‘void (*)(v8::Local<v8::Object>, v8::Local<v8::Value>, v8::Local<v8::Context>)’ to ‘node::addon_context_register_func’ {aka ‘void (*)(v8::Local<v8::Object>, v8::Local<v8::Value>, v8::Local<v8::Context>, void*)’} [-Wcast-function-type]
npm error  1248 |       (node::addon_context_register_func) (regfunc),                  \
npm error       |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
npm error .../.cache/node-gyp/22.2.0/include/node/node.h:1266:3: note: in expansion of macro ‘NODE_MODULE_CONTEXT_AWARE_X’
npm error  1266 |   NODE_MODULE_CONTEXT_AWARE_X(modname, regfunc, NULL, 0)
npm error       |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~
npm error .../.cache/node-gyp/22.2.0/include/node/node.h:1297:3: note: in expansion of macro ‘NODE_MODULE_CONTEXT_AWARE’
npm error  1297 |   NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME,                     \
npm error       |   ^~~~~~~~~~~~~~~~~~~~~~~~~
npm error ./src/better_sqlite3.lzz:67:1: note: in expansion of macro ‘NODE_MODULE_INIT’
npm error ./src/util/macros.lzz: In function ‘void SetPrototypeGetter(v8::Isolate*, v8::Local<v8::External>, v8::Local<v8::FunctionTemplate>, const char*, v8::AccessorGetterCallback)’:
npm error ./src/util/macros.lzz:150:46: error: no matching function for call to ‘v8::ObjectTemplate::SetAccessor(v8::Local<v8::String>, void (*&)(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&), int, v8::Local<v8::External>&, v8::AccessControl, v8::PropertyAttribute)’
npm error In file included from .../.cache/node-gyp/22.2.0/include/node/v8-function.h:15,
npm error                  from .../.cache/node-gyp/22.2.0/include/node/v8.h:33,
npm error                  from .../.cache/node-gyp/22.2.0/include/node/node.h:73:
npm error .../.cache/node-gyp/22.2.0/include/node/v8-template.h:1055:8: note: candidate: ‘void v8::ObjectTemplate::SetAccessor(v8::Local<v8::Name>, v8::AccessorNameGetterCallback, v8::AccessorNameSetterCallback, v8::Local<v8::Value>, v8::PropertyAttribute, v8::SideEffectType, v8::SideEffectType)’
npm error  1055 |   void SetAccessor(
npm error       |        ^~~~~~~~~~~
npm error .../.cache/node-gyp/22.2.0/include/node/v8-template.h:1058:61: note:   no known conversion for argument 5 from ‘v8::AccessControl’ to ‘v8::PropertyAttribute’
npm error  1058 |       Local<Value> data = Local<Value>(), PropertyAttribute attribute = None,
npm error       |                                           ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
npm error .../.cache/node-gyp/22.2.0/include/node/v8-template.h:1049:8: note: candidate: ‘void v8::ObjectTemplate::SetAccessor(v8::Local<v8::String>, v8::AccessorGetterCallback, v8::AccessorSetterCallback, v8::Local<v8::Value>, v8::PropertyAttribute, v8::SideEffectType, v8::SideEffectType)’
npm error  1049 |   void SetAccessor(
npm error       |        ^~~~~~~~~~~
npm error .../.cache/node-gyp/22.2.0/include/node/v8-template.h:1052:61: note:   no known conversion for argument 5 from ‘v8::AccessControl’ to ‘v8::PropertyAttribute’
npm error  1052 |       Local<Value> data = Local<Value>(), PropertyAttribute attribute = None,
npm error       |                                           ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
npm error ./src/util/data.lzz: In function ‘v8::Local<v8::Value> Data::GetValueJS(v8::Isolate*, sqlite3_stmt*, int, bool)’:
npm error ./src/util/data.lzz:73:92: warning: this statement may fall through [-Wimplicit-fallthrough=]
npm error ./src/util/data.lzz:73:197: note: here
npm error ./src/util/data.lzz: In function ‘v8::Local<v8::Value> Data::GetValueJS(v8::Isolate*, sqlite3_value*, bool)’:
npm error ./src/util/data.lzz:77:81: warning: this statement may fall through [-Wimplicit-fallthrough=]
npm error ./src/util/data.lzz:77:175: note: here
npm error make: *** [better_sqlite3.target.mk:120: Release/obj.target/better_sqlite3/src/better_sqlite3.o] Error 1
npm error gyp ERR! build error 
npm error gyp ERR! stack Error: `make` failed with exit code: 2
npm error gyp ERR! stack at ChildProcess.<anonymous> (/usr/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:209:23)
npm error gyp ERR! System Linux 6.1.0-21-amd64
npm error gyp ERR! command "/usr/bin/node" "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--release"
npm error gyp ERR! cwd .../node_modules/electric-sql/node_modules/better-sqlite3
npm error gyp ERR! node -v v22.2.0
npm error gyp ERR! node-gyp -v v10.1.0
npm error gyp ERR! not ok
samwillis commented 1 month ago

This error is related to the legacy Electric sync and so I'm going to close.