Bundle external javascript lib on Nakama

Hello,
We are using Nakama with Typescript (with rollup configured) and we are having a hard time adding external libs to Nakama. I’m trying to find a schema validator that I can use to validate that the JSON payload is correct, and I tried several libs already zod, ajv, etc. None of them seems to work, I keep receiving some crazy errors like Cannot assign to read only property 'opts'. The weird thing here is that if I add the piece of code to the entrypoint server.ts, it works fine. If I add the same piece of code to the RPC function, it fails with the error above. I added a snippet with an example of the code I’m trying to use.

  1. Versions: Nakama 3.12, Docker
  2. Server Framework Runtime language: Typescript
import Ajv from 'ajv';

const ajv = new Ajv({ logger: false }); 

const schema = {
      type: 'object',
      properties: {
        foo: { type: 'integer' },
        bar: { type: 'string' },
      },
      required: ['foo'],
      additionalProperties: false,
    };

ajv.validate(schema, {});

:tv: Media:

Update: Apparently changing Nakama: Configuration | Heroic Labs Documentation to false fixed the issue. The libs that I was trying to use were using global variables and rewriting them, breaking the entire application. I still don’t know why it was working on server.ts and not in the RPCs.

Hello @thiagosalvatore, in v3.11.0 we introduced the js_read_only_globals flag, which when set to true (default), makes the JS VMs global state to be immutable. The reason for this change is that Nakama uses a pool of JS VMs for efficiency, and mutating the global state might cause it to differ between VM executions, potentially causing unexpected behaviour.

We made it the default as relying on global state is generally bad practice, and to prevent users from experiencing the above issue. It can be turned off as it can cause incompatibility with some libraries.

If js_read_only_globals is set to true, the global state is made immutable only after the InitModule function is executed to allow global constants to be set, but mutating it later will result in an exception.

1 Like