diffusion
Version:
Diffusion JavaScript client
248 lines (247 loc) • 9.21 kB
JavaScript
;
/**
* @module V4Stack
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.writeToBuffer = exports.create = exports.parse = exports.WriteableMessage = exports.Message = exports.encoding = exports.types = void 0;
var errors_1 = require("./../../errors/errors");
var buffer_input_stream_1 = require("./../io/buffer-input-stream");
var buffer_output_stream_1 = require("./../io/buffer-output-stream");
var consts_1 = require("./../protocol/consts");
var Logger = require("./../util/logger");
var message_encoding_1 = require("./../util/message-encoding");
var object_1 = require("./../util/object");
var logger = Logger.create('Message');
var zlib;
if (consts_1.PROTOCOL.CAPABILITIES === 10) {
/* tslint:disable-next-line:no-var-requires */
zlib = require('../util/zlib-decompression');
}
else {
logger.warn('Per message compression is disabled because \'zlib\' bundle is not included');
zlib = null;
}
/**
* Message types
*/ // eslint-disable-next-line @typescript-eslint/naming-convention
var types;
(function (types) {
types[types["SERVICE_REQUEST"] = 0] = "SERVICE_REQUEST";
types[types["SERVICE_RESPONSE"] = 6] = "SERVICE_RESPONSE";
types[types["SERVICE_ERROR"] = 7] = "SERVICE_ERROR";
types[types["TOPIC_VALUE"] = 4] = "TOPIC_VALUE";
types[types["TOPIC_DELTA"] = 5] = "TOPIC_DELTA";
types[types["ABORT_NOTIFICATION"] = 28] = "ABORT_NOTIFICATION";
types[types["CLOSE_REQUEST"] = 29] = "CLOSE_REQUEST";
types[types["FETCH_REPLY"] = 34] = "FETCH_REPLY";
})(types = exports.types || (exports.types = {}));
/**
* Message encodings
*/ // eslint-disable-next-line @typescript-eslint/naming-convention
var encoding;
(function (encoding) {
encoding[encoding["NONE"] = 0] = "NONE";
encoding[encoding["ENCRYPTION_REQUESTED"] = 1] = "ENCRYPTION_REQUESTED";
encoding[encoding["COMPRESSION_REQUESTED"] = 2] = "COMPRESSION_REQUESTED";
encoding[encoding["BASE64_REQUESTED"] = 3] = "BASE64_REQUESTED";
encoding[encoding["ENCRYPTED"] = 17] = "ENCRYPTED";
encoding[encoding["COMPRESSED"] = 18] = "COMPRESSED";
encoding[encoding["BASE64"] = 19] = "BASE64";
})(encoding = exports.encoding || (exports.encoding = {}));
/**
* Basic message type
*/
var Message = /** @class */ (function () {
/**
* Create a new message
*
* @param type the message type
* @param encoding the message encoding
* @param fields optional message fields
* @param data the message's data
* @param headers additional message headers
*/
function Message(type, msgEncoding, fields, data, headers) {
this.type = type;
this.encoding = msgEncoding;
this.id = fields.id;
this.topic = fields.topic;
this.data = data;
this.headers = headers;
}
/**
* Create an input stream from the message's data
*
* @return an input stream that can be deserialised
*/
Message.prototype.getInputStream = function () {
return new buffer_input_stream_1.BufferInputStream(this.data);
};
return Message;
}());
exports.Message = Message;
/**
* A writable message that can be serialised into a {@link BufferOutputStream}
*/
var WriteableMessage = /** @class */ (function (_super) {
__extends(WriteableMessage, _super);
/**
* Create a writeable message
*
* @param the message fields in an object
*/
function WriteableMessage(fields) {
var _this = _super.call(this, fields.type, fields.encoding, fields, fields.buffer, fields.headers) || this;
_this.stream = new buffer_output_stream_1.BufferOutputStream(fields.buffer);
return _this;
}
/**
* Get the output stream
*
* @return the output stream that writes into the message's data buffer
*/
WriteableMessage.prototype.getStream = function () {
return this.stream;
};
/**
* Get the buffer
*
* @return the buffer that the output has been written into
*/
WriteableMessage.prototype.getBuffer = function () {
return this.stream.getBuffer();
};
return WriteableMessage;
}(Message));
exports.WriteableMessage = WriteableMessage;
/**
* Parse a message from a buffer
*
* @param buffer the buffer to parse
* @param callback a callback that is called when the message has been parsed
* or an error has occurred.
*/
function parse(buffer, callback) {
var bis = new buffer_input_stream_1.BufferInputStream(buffer);
var typeAndEncoding = bis.read();
var type = message_encoding_1.MessageEncoding.extractMessageType(typeAndEncoding);
var encodingType = message_encoding_1.MessageEncoding.extractMessageEncoding(typeAndEncoding);
/* tslint:disable-next-line:strict-type-predicates */
if (types[type] === undefined) {
callback(new Error("Invalid message type: " + type), null);
}
if (type === types.SERVICE_REQUEST || type === types.SERVICE_RESPONSE || type === types.SERVICE_ERROR) {
callback(null, parseServiceMessage(type, bis));
}
else if (type === types.TOPIC_VALUE || type === types.TOPIC_DELTA) {
parseClientTopicMessage(type, encodingType, bis, callback);
}
else {
var headers = bis.readUntil(0x01).toString().split('\u0002');
var body = bis.readMany(bis.count);
var topic = (type === types.FETCH_REPLY) ? headers.shift() : undefined;
callback(null, new Message(type, encoding.NONE, { topic: topic }, body, headers));
}
}
exports.parse = parse;
/**
* Helper function to create a service message
*
* @param type the message type to create
* @param bis the buffer that is passed into the {@link Message.data} property
* of the message
* @return the newly constructed message
*/
function parseServiceMessage(type, bis) {
var body = bis.readMany(bis.count);
return new Message(type, encoding.NONE, {}, body, []);
}
/**
* Helper function to create a client topic message
*
* @param type the message type to create
* @param encodingType the message encoding
* @param bis the buffer that is passed into the {@link Message.data} property
* @param callback a callback that is called when the message has been parsed
* or an error has occurred.
*/
function parseClientTopicMessage(type, encodingType, bis, callback) {
var headers = [];
var fields = { id: bis.readInt32() };
if (encodingType === message_encoding_1.EncodingType.ZLIB && zlib !== null) {
try {
var bytes = zlib.decompressSync(bis.readMany(bis.count));
callback(null, new Message(type, encoding.COMPRESSED, fields, bytes, headers));
}
catch (error) {
callback(error, null);
}
}
else {
callback(null, new Message(type, encoding.NONE, fields, bis.readMany(bis.count), headers));
}
}
/**
* Create a writeable Message.
*
* @param type provide a number to specify a message type; use an object to provide fields
* @return the created message
*/
function create(type) {
var fields;
/* tslint:disable-next-line:strict-type-predicates */
if (type === undefined || (typeof type === 'number' && types[type] === undefined)) {
throw new errors_1.InternalError("Invalid message type: " + type);
}
else if (object_1.isObjectAs(type)) {
fields = type;
}
else {
fields = { type: type };
}
fields.encoding = fields.encoding || 0;
fields.headers = fields.headers || [];
fields.buffer = fields.buffer || new Uint8Array(0);
return new WriteableMessage(fields);
}
exports.create = create;
/**
* Construct a header string
*
* @param message the message from which to construct the header string
* @return the string to be serialised in the header
*/
function getHeaderString(message) {
if (message.type !== types.FETCH_REPLY) {
return '';
}
var sh = [message.topic].concat(message.headers);
return sh.join('\u0002') + '\u0001';
}
/**
* Serialise a message into a buffer
*
* @param message the message to write
* @param bos the buffer to write into
*/
function writeToBuffer(message, bos) {
bos.write(message.type);
bos.writeString(getHeaderString(message));
bos.writeMany(message.getBuffer());
}
exports.writeToBuffer = writeToBuffer;