node-red-nodes icon indicating copy to clipboard operation
node-red-nodes copied to clipboard

node-red-node-cbor cannot handle BigInt

Open matthias-heinisch opened this issue 4 months ago • 7 comments

Which node are you reporting and issue on?

node-red-node-cbor

What are the steps to reproduce?

send a timestamp as integer to decode - the decoder exits with the error message "Bad Decode"

What happens?

the node-red-node-cbor plugin serializes the decoded result with JSON: https://github.com/node-red/node-red-nodes/blob/06a9c48395ab8ba707a0f265162df5c0c81dd74b/parsers/cbor/70-cbor.js#L19

As JSON does not support BigInt, this creates an error message when you are decoding a timestamp for example.

What did you expect to happen?

  1. The decoder should decode correctly sent buffers without error message.
  2. The error message should correspond to the actual error.

Proposed solution

  1. I propose to add a replacer function and convert BigInt and other unsupported formats.
  2. The error message "not a cbor buffer" is not always correct. I would prefer to use the actual error message.

Additionally, cbor-x library is out of date and should be updated.

matthias-heinisch avatar Aug 04 '25 09:08 matthias-heinisch

Can you provide a simple example flow that shows this ? If I use a simple timestamp it appears to work fine

Image

dceejay avatar Aug 04 '25 13:08 dceejay

Are you using second or milliseconds for your timestamp

hardillb avatar Aug 04 '25 13:08 hardillb

OK - tried a few "real" bigints and yes - it's just the status that is failing... the actual conversion is fine. Pushed v1.0.2

dceejay avatar Aug 04 '25 16:08 dceejay

Thank you for your instant response. I wanted to propose something like that:

// convert types that JSON stringify does not support
function replacer(key, value) {
    if (typeof value === 'bigint') {
        return value.toString();
    }
    if (value instanceof Buffer || value instanceof Uint8Array) {
        return value.toString('base64');
    }
    if (value instanceof Map) {
        return Array.from(value.entries());
    }
    if (value instanceof Set) {
        return Array.from(value);
    }
    if (value instanceof RegExp) {
        return value.toString();
    }
    return value;
}

in combination with JSON.stringify(value, replacer) and

catch (e) {
  node.error(`Bad decode - ${e.message}`, msg);
}

matthias-heinisch avatar Aug 04 '25 18:08 matthias-heinisch

Looks good - will implement later - or happy to accept a PR if you like.

dceejay avatar Aug 05 '25 07:08 dceejay

Great. I'll try a PR (please be patient, I have to learn the process for our organization first)

matthias-heinisch avatar Aug 05 '25 08:08 matthias-heinisch

No problem - shout if you get stuck.

dceejay avatar Aug 07 '25 12:08 dceejay