UNPKG

sc-formatter

Version:

Module for serializing and unserializing SocketCluster messages

95 lines (85 loc) 3.21 kB
const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const validJSONStartRegex = /^[ \n\r\t]*[{\[]/; let arrayBufferToBase64 = function (arraybuffer) { let bytes = new Uint8Array(arraybuffer); let len = bytes.length; let base64 = ''; for (let i = 0; i < len; i += 3) { base64 += base64Chars[bytes[i] >> 2]; base64 += base64Chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; base64 += base64Chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; base64 += base64Chars[bytes[i + 2] & 63]; } if ((len % 3) === 2) { base64 = base64.substring(0, base64.length - 1) + '='; } else if (len % 3 === 1) { base64 = base64.substring(0, base64.length - 2) + '=='; } return base64; }; let binaryToBase64Replacer = function (key, value) { if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { return { base64: true, data: arrayBufferToBase64(value) }; } else if (typeof Buffer !== 'undefined') { if (value instanceof Buffer){ return { base64: true, data: value.toString('base64') }; } // Some versions of Node.js convert Buffers to Objects before they are passed to // the replacer function - Because of this, we need to rehydrate Buffers // before we can convert them to base64 strings. if (value && value.type === 'Buffer' && Array.isArray(value.data)) { let rehydratedBuffer; if (Buffer.from) { rehydratedBuffer = Buffer.from(value.data); } else { rehydratedBuffer = new Buffer(value.data); } return { base64: true, data: rehydratedBuffer.toString('base64') }; } } return value; }; // Decode the data which was transmitted over the wire to a JavaScript Object in a format which SC understands. // See encode function below for more details. module.exports.decode = function (encodedMessage) { if (encodedMessage == null) { return null; } // Leave ping or pong message as is if (encodedMessage === '#1' || encodedMessage === '#2') { return encodedMessage; } let message = encodedMessage.toString(); // Performance optimization to detect invalid JSON packet sooner. if (!validJSONStartRegex.test(message)) { return message; } try { return JSON.parse(message); } catch (err) {} return message; }; // Encode raw data (which is in the SC protocol format) into a format for // transfering it over the wire. In this case, we just convert it into a simple JSON string. // If you want to create your own custom codec, you can encode the object into any format // (e.g. binary ArrayBuffer or string with any kind of compression) so long as your decode // function is able to rehydrate that object back into its original JavaScript Object format // (which adheres to the SC protocol). // See https://github.com/SocketCluster/socketcluster/blob/master/socketcluster-protocol.md // for details about the SC protocol. module.exports.encode = function (rawData) { // Leave ping or pong message as is if (rawData === '#1' || rawData === '#2') { return rawData; } return JSON.stringify(rawData, binaryToBase64Replacer); };