@boringnode/transmit
Version:
A framework agnostic Server-Sent-Event library
53 lines (52 loc) • 1.79 kB
JavaScript
/*
* @boringnode/transmit
*
* @license MIT
* @copyright Boring Node
*/
import { Transform } from 'node:stream';
import { dataToString } from './utils.js';
export class Stream extends Transform {
#uid;
constructor(uid, request) {
super({ objectMode: true });
this.#uid = uid;
if (request?.socket) {
request.socket.setKeepAlive(true);
request.socket.setNoDelay(true);
request.socket.setTimeout(0);
}
}
getUid() {
return this.#uid;
}
pipe(destination, options, injectResponseHeaders = {}) {
if (destination.writeHead) {
// @see https://github.com/dunglas/mercure/blob/9e080c8dc9a141d4294412d14efdecfb15bf7f43/subscribe.go#L219
destination.writeHead(200, {
...injectResponseHeaders,
'Cache-Control': 'private, no-cache, no-store, must-revalidate, max-age=0, no-transform',
'Connection': 'keep-alive',
'Content-Type': 'text/event-stream',
'Expire': '0',
'Pragma': 'no-cache',
// @see https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-buffering
'X-Accel-Buffering': 'no',
});
destination.flushHeaders?.();
}
// Some clients (Safari) don't trigger onopen until the first frame is received.
destination.write(':ok\n\n');
return super.pipe(destination, options);
}
_transform(message, _encoding, callback) {
if (message.data) {
this.push(dataToString(message.data));
}
this.push('\n');
callback();
}
writeMessage(message, encoding, cb) {
return this.write(message, encoding, cb);
}
}