diff --git a/lib/commons.ts b/lib/commons.ts index 0109072..aaf5fba 100644 --- a/lib/commons.ts +++ b/lib/commons.ts @@ -12,6 +12,26 @@ Object.keys(PACKET_TYPES).forEach(key => { PACKET_TYPES_REVERSE[PACKET_TYPES[key]] = key; }); -const ERROR_PACKET = { type: "error", data: "parser error" }; +const ERROR_PACKET: Packet = { type: "error", data: "parser error" }; export { PACKET_TYPES, PACKET_TYPES_REVERSE, ERROR_PACKET }; + +export type PacketType = + | "open" + | "close" + | "ping" + | "pong" + | "message" + | "upgrade" + | "noop" + | "error"; + +export type RawData = string | Buffer | ArrayBuffer | ArrayBufferView | Blob; + +export interface Packet { + type: PacketType; + options?: { compress: boolean }; + data?: RawData; +} + +export type BinaryType = "nodebuffer" | "arraybuffer" | "blob"; diff --git a/lib/decodePacket.browser.ts b/lib/decodePacket.browser.ts index f8dd94f..71e3480 100644 --- a/lib/decodePacket.browser.ts +++ b/lib/decodePacket.browser.ts @@ -1,9 +1,18 @@ -import { ERROR_PACKET, PACKET_TYPES_REVERSE } from "./commons.js"; +import { + ERROR_PACKET, + PACKET_TYPES_REVERSE, + Packet, + BinaryType, + RawData +} from "./commons.js"; import { decode } from "@socket.io/base64-arraybuffer"; const withNativeArrayBuffer = typeof ArrayBuffer === "function"; -const decodePacket = (encodedPacket, binaryType) => { +const decodePacket = ( + encodedPacket: RawData, + binaryType?: BinaryType +): Packet => { if (typeof encodedPacket !== "string") { return { type: "message", diff --git a/lib/decodePacket.ts b/lib/decodePacket.ts index f48556f..e04a781 100644 --- a/lib/decodePacket.ts +++ b/lib/decodePacket.ts @@ -1,6 +1,15 @@ -import { ERROR_PACKET, PACKET_TYPES_REVERSE } from "./commons.js"; +import { + ERROR_PACKET, + PACKET_TYPES_REVERSE, + Packet, + BinaryType, + RawData +} from "./commons.js"; -const decodePacket = (encodedPacket, binaryType?) => { +const decodePacket = ( + encodedPacket: RawData, + binaryType?: BinaryType +): Packet => { if (typeof encodedPacket !== "string") { return { type: "message", @@ -28,7 +37,7 @@ const decodePacket = (encodedPacket, binaryType?) => { }; }; -const mapBinary = (data, binaryType) => { +const mapBinary = (data: RawData, binaryType?: BinaryType) => { const isBuffer = Buffer.isBuffer(data); switch (binaryType) { case "arraybuffer": @@ -39,7 +48,7 @@ const mapBinary = (data, binaryType) => { } }; -const toArrayBuffer = buffer => { +const toArrayBuffer = (buffer: Buffer): ArrayBuffer => { const arrayBuffer = new ArrayBuffer(buffer.length); const view = new Uint8Array(arrayBuffer); for (let i = 0; i < buffer.length; i++) { diff --git a/lib/encodePacket.browser.ts b/lib/encodePacket.browser.ts index 6ab82f5..e1c522e 100644 --- a/lib/encodePacket.browser.ts +++ b/lib/encodePacket.browser.ts @@ -1,4 +1,4 @@ -import { PACKET_TYPES } from "./commons.js"; +import { PACKET_TYPES, Packet, RawData } from "./commons.js"; const withNativeBlob = typeof Blob === "function" || @@ -13,7 +13,11 @@ const isView = obj => { : obj && obj.buffer instanceof ArrayBuffer; }; -const encodePacket = ({ type, data }, supportsBinary, callback) => { +const encodePacket = ( + { type, data }: Packet, + supportsBinary: boolean, + callback: (encodedPacket: RawData) => void +) => { if (withNativeBlob && data instanceof Blob) { if (supportsBinary) { return callback(data); @@ -34,7 +38,10 @@ const encodePacket = ({ type, data }, supportsBinary, callback) => { return callback(PACKET_TYPES[type] + (data || "")); }; -const encodeBlobAsBase64 = (data, callback) => { +const encodeBlobAsBase64 = ( + data: Blob, + callback: (encodedPacket: RawData) => void +) => { const fileReader = new FileReader(); fileReader.onload = function() { const content = (fileReader.result as string).split(",")[1]; diff --git a/lib/encodePacket.ts b/lib/encodePacket.ts index a05c466..0557532 100644 --- a/lib/encodePacket.ts +++ b/lib/encodePacket.ts @@ -1,6 +1,10 @@ -import { PACKET_TYPES } from "./commons.js"; +import { PACKET_TYPES, Packet, RawData } from "./commons.js"; -const encodePacket = ({ type, data }, supportsBinary, callback) => { +const encodePacket = ( + { type, data }: Packet, + supportsBinary: boolean, + callback: (encodedPacket: RawData) => void +) => { if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) { const buffer = toBuffer(data); return callback(encodeBuffer(buffer, supportsBinary)); @@ -20,7 +24,7 @@ const toBuffer = data => { }; // only 'message' packets can contain binary, so the type prefix is not needed -const encodeBuffer = (data, supportsBinary) => { +const encodeBuffer = (data: Buffer, supportsBinary: boolean): RawData => { return supportsBinary ? data : "b" + data.toString("base64"); }; diff --git a/lib/index.ts b/lib/index.ts index ae119a8..9280541 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,9 +1,13 @@ import encodePacket from "./encodePacket.js"; import decodePacket from "./decodePacket.js"; +import { Packet, PacketType, RawData, BinaryType } from "./commons"; const SEPARATOR = String.fromCharCode(30); // see https://en.wikipedia.org/wiki/Delimiter#ASCII_delimited_text -const encodePayload = (packets, callback) => { +const encodePayload = ( + packets: Packet[], + callback: (encodedPayload: string) => void +) => { // some packets may be added to the array while encoding, so the initial length must be saved const length = packets.length; const encodedPackets = new Array(length); @@ -20,7 +24,10 @@ const encodePayload = (packets, callback) => { }); }; -const decodePayload = (encodedPayload, binaryType?) => { +const decodePayload = ( + encodedPayload: string, + binaryType?: BinaryType +): Packet[] => { const encodedPackets = encodedPayload.split(SEPARATOR); const packets = []; for (let i = 0; i < encodedPackets.length; i++) { @@ -34,4 +41,13 @@ const decodePayload = (encodedPayload, binaryType?) => { }; export const protocol = 4; -export { encodePacket, encodePayload, decodePacket, decodePayload }; +export { + encodePacket, + encodePayload, + decodePacket, + decodePayload, + Packet, + PacketType, + RawData, + BinaryType +}; diff --git a/test/browser.ts b/test/browser.ts index ca62e89..1c630d3 100644 --- a/test/browser.ts +++ b/test/browser.ts @@ -1,4 +1,10 @@ -import { decodePacket, decodePayload, encodePacket, encodePayload } from ".."; +import { + decodePacket, + decodePayload, + encodePacket, + encodePayload, + Packet +} from ".."; import * as expect from "expect.js"; import { areArraysEqual, createArrayBuffer } from "./util"; @@ -8,7 +14,7 @@ describe("engine.io-parser (browser only)", () => { describe("single packet", () => { if (withNativeArrayBuffer) { it("should encode/decode an ArrayBuffer", done => { - const packet = { + const packet: Packet = { type: "message", data: createArrayBuffer([1, 2, 3, 4]) }; @@ -23,7 +29,7 @@ describe("engine.io-parser (browser only)", () => { }); it("should encode/decode an ArrayBuffer as base64", done => { - const packet = { + const packet: Packet = { type: "message", data: createArrayBuffer([1, 2, 3, 4]) }; @@ -49,7 +55,7 @@ describe("engine.io-parser (browser only)", () => { if (typeof Blob === "function") { it("should encode/decode a Blob", done => { - const packet = { + const packet: Packet = { type: "message", data: new Blob(["1234", createArrayBuffer([1, 2, 3, 4])]) }; @@ -63,7 +69,7 @@ describe("engine.io-parser (browser only)", () => { }); it("should encode/decode a Blob as base64", done => { - const packet = { + const packet: Packet = { type: "message", data: new Blob(["1234", createArrayBuffer([1, 2, 3, 4])]) }; @@ -81,7 +87,7 @@ describe("engine.io-parser (browser only)", () => { describe("payload", () => { if (withNativeArrayBuffer) { it("should encode/decode a string + ArrayBuffer payload", done => { - const packets = [ + const packets: Packet[] = [ { type: "message", data: "test" }, { type: "message", data: createArrayBuffer([1, 2, 3, 4]) } ]; diff --git a/test/index.ts b/test/index.ts index 7e7a615..a1b75f5 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,12 +1,18 @@ -import { decodePacket, decodePayload, encodePacket, encodePayload } from ".."; +import { + decodePacket, + decodePayload, + encodePacket, + encodePayload, + Packet +} from ".."; import * as expect from "expect.js"; import "./node"; describe("engine.io-parser", () => { describe("single packet", () => { it("should encode/decode a string", done => { - const packet = { type: "message", data: "test" }; - encodePacket(packet, {}, encodedPacket => { + const packet: Packet = { type: "message", data: "test" }; + encodePacket(packet, true, encodedPacket => { expect(encodedPacket).to.eql("4test"); expect(decodePacket(encodedPacket)).to.eql(packet); done(); @@ -14,11 +20,11 @@ describe("engine.io-parser", () => { }); it("should fail to decode a malformed packet", () => { - expect(decodePacket("", {})).to.eql({ + expect(decodePacket("")).to.eql({ type: "error", data: "parser error" }); - expect(decodePacket("a123", {})).to.eql({ + expect(decodePacket("a123")).to.eql({ type: "error", data: "parser error" }); @@ -27,7 +33,7 @@ describe("engine.io-parser", () => { describe("payload", () => { it("should encode/decode all packet types", done => { - const packets = [ + const packets: Packet[] = [ { type: "open" }, { type: "close" }, { type: "ping", data: "probe" }, diff --git a/test/node.ts b/test/node.ts index 5e7cdc1..6b9a9a6 100644 --- a/test/node.ts +++ b/test/node.ts @@ -1,29 +1,41 @@ -import { decodePacket, decodePayload, encodePacket, encodePayload } from ".."; +import { + decodePacket, + decodePayload, + encodePacket, + encodePayload, + Packet +} from ".."; import * as expect from "expect.js"; import { areArraysEqual } from "./util"; describe("engine.io-parser (node.js only)", () => { describe("single packet", () => { it("should encode/decode a Buffer", done => { - const packet = { type: "message", data: Buffer.from([1, 2, 3, 4]) }; + const packet: Packet = { + type: "message", + data: Buffer.from([1, 2, 3, 4]) + }; encodePacket(packet, true, encodedPacket => { expect(encodedPacket).to.eql(packet.data); // noop - expect(decodePacket(encodedPacket, {})).to.eql(packet); + expect(decodePacket(encodedPacket)).to.eql(packet); done(); }); }); it("should encode/decode a Buffer as base64", done => { - const packet = { type: "message", data: Buffer.from([1, 2, 3, 4]) }; + const packet: Packet = { + type: "message", + data: Buffer.from([1, 2, 3, 4]) + }; encodePacket(packet, false, encodedPacket => { expect(encodedPacket).to.eql("bAQIDBA=="); - expect(decodePacket(encodedPacket, "buffer")).to.eql(packet); + expect(decodePacket(encodedPacket, "nodebuffer")).to.eql(packet); done(); }); }); it("should encode/decode an ArrayBuffer", done => { - const packet = { + const packet: Packet = { type: "message", data: Int8Array.from([1, 2, 3, 4]).buffer }; @@ -38,7 +50,7 @@ describe("engine.io-parser (node.js only)", () => { }); it("should encode/decode an ArrayBuffer as base64", done => { - const packet = { + const packet: Packet = { type: "message", data: Int8Array.from([1, 2, 3, 4]).buffer }; @@ -83,13 +95,13 @@ describe("engine.io-parser (node.js only)", () => { describe("payload", () => { it("should encode/decode a string + Buffer payload", done => { - const packets = [ + const packets: Packet[] = [ { type: "message", data: "test" }, { type: "message", data: Buffer.from([1, 2, 3, 4]) } ]; encodePayload(packets, payload => { expect(payload).to.eql("4test\x1ebAQIDBA=="); - expect(decodePayload(payload, "buffer")).to.eql(packets); + expect(decodePayload(payload, "nodebuffer")).to.eql(packets); done(); }); });