I want to wrap a array, e.g. an Uint8Array
, into a NodeJS.WritableStream
so I can read its content later. How can I do that?
Background: For testing my winston logger, I want to set up a custom transport which just holds all the logged data in a manner I can evaluate it later. The example reads like this:
logger.add(new winston.transports.Stream({
stream: fs.createWriteStream('/dev/null')
/* other options */
}));
But if I create the stream like fs.createWriteStream('/dev/null')
, I cannot see its content, and it won't run under Windows (or at least I'm having issues here atm). And why would I need fs
anyway?
To give another illustration where I'm coming from, let's take this arbitraty example from Go:
buf := bytes.Buffer{}
// zerolog.New() expects an io.Writable, similar to a NodeJS.WritableStream
logger := zerolog.New(&buf)
logger.Info().Msg("Hello World")
// I can access the written data by acessing the underlying buffer
assert.Equal(t, buf.String(), "{\"level\":\"info\",\"message\":\"Hello World\"}\n")
Note this isn't a specific thing for zerolog
, but a illustration on how to set up an io.writer
in manner to access the underlying, "written" data. This is what I hope to achieve with a NodeJS.WritableStream
implementation as well.
I tried to find a way around with an event listener, but didn't suceed yet.
For completeness sake, here the solution @Bergi provided.
While it's not possible to set an underlying buffer as in Go oder Java, we work a callback to create a writable stream which can be evaluated. For that we have to create an own implementation of WritableStream
with the help of the (abstract) implementation Writable
:
import { Writable } from 'node:stream';
import * as winston from 'winston';
let logged: string = '';
const writable = new Writable({
write(chunk: Buffer, _encoding, done) {
logged += chunk.toString();
done();
},
});
// for my concrete use case
expect(logged).toEqual(winston.createLogger({transports: new winston.transports.Stream({ stream: writable })}).info('some text'))