nats-io / nats.ws

WebSocket NATS
Apache License 2.0
329 stars 29 forks source link

atob issue when using kv #156

Closed jmordica closed 2 years ago

jmordica commented 2 years ago

Issue: When using this module in NodeJS you have to shim atob similar to how you do the Websocket library (or you get the following below):

ReferenceError: atob is not defined which references nats.ws/esm/nats.js:6732:20

Here's the block:

_parse(s) {
    const bs = atob(s);
    const len = bs.length;
    const bytes = new Uint8Array(len);
    for(let i58 = 0; i58 < len; i58++){
        bytes[i58] = bs.charCodeAt(i58);
    }
    return bytes;
}

A workaround is to:

npm install atob

Then before importing nats.ws:

import atob from 'atob';
globalThis.atob = atob;

If additional info is needed I can provide. Maybe this is not even an issue but just something that needs to be added to the README?

Thanks!

aricart commented 2 years ago

currently, nats.ws is not shimming anything directly and instead requests the shim be added by the client code (like for the w3c WebSocket support). What entry point are you using? from your workaround, it seems to the esm.

jmordica commented 2 years ago

Ok no worries then. Yes ESM.

aricart commented 2 years ago

For the websocket tests, I use ava (so they are running on node.js), and the issue with atob is not present, likely because it is shimmed by browser-env

aricart commented 2 years ago

@jmordica what node version are you using - on 16x, I am able to only have a single dependency:

globalThis.WebSocket = require("websocket").w3cwebsocket;
const { connect, Events } = require("../");
const { Empty } = require('../test/index.js')

// process.on("unhandledRejection", (reason, promise) => {
//   console.log("unhandledRejection", reason?.message);
//   console.log(reason?.stack);
// });

const payload = new Uint8Array(128);

connect({servers: ["ws://localhost:9222"], maxReconnectAttempts: -1, reconnectTimeWait: 1000})
  .then(async (nc) => {
    (async () => {
      console.info(`connected ${nc.getServer()}`);
      for await (const s of nc.status()) {
        console.info(`${s.type}: ${s.data}`);
      }
    })().then();

    const js = nc.jetstream();
    const kv = await js.views.kv("test");
    const v = await kv.put("hello", Empty);
    console.log(`added key hello with seq ${v}`);

    const vv = await kv.get("hello");
    console.log(vv);

    await nc.close();
    console.log("done");

  });

node kv.js connected localhost:9222

jetstream's materialized views functionality in nats.ws is beta functionality added key hello with seq 1 { bucket: 'test', key: 'hello', value: Uint8Array(0) [], delta: 0, created: 2022-08-01T14:22:44.717Z, revision: 1, operation: 'PUT', length: 0 } done

aricart commented 2 years ago

doh that is require - let me try esm

aricart commented 2 years ago

Yes not sure what is going on:

import w3c from "websocket";
globalThis.WebSocket = w3c.w3cwebsocket;
import { connect, Empty } from "../esm/nats.js"

connect({servers: ["ws://localhost:9222"], maxReconnectAttempts: -1, reconnectTimeWait: 1000})
  .then(async (nc) => {
    (async () => {
      console.info(`connected ${nc.getServer()}`);
      for await (const s of nc.status()) {
        console.info(`${s.type}: ${s.data}`);
      }
    })().then();

    const js = nc.jetstream();
    const kv = await js.views.kv("test");
    const v = await kv.put("hello", Empty);
    console.log(`added key hello with seq ${v}`);

    const vv = await kv.get("hello");
    console.log(vv);

    await nc.close();
    console.log("done");

  });

The above works for me....

jmordica commented 2 years ago

Interesting. I can test on 16.x. I was on 14.x when testing. Closing this since you are able to get it working without a change on 16.

Thanks!!