@phnq/message
Version:
Asynchronous, incremental messaging client and server
123 lines (122 loc) • 5.22 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClientWebSocketTransport = exports.ServerWebSocketTransport = void 0;
require("ws"); // need to explicitly import this so it gets loaded as a dependency
const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
const serialize_1 = require("../serialize");
class ServerWebSocketTransport {
constructor(socket) {
this.socket = socket;
}
send(message) {
return __awaiter(this, void 0, void 0, function* () {
this.socket.send((0, serialize_1.serialize)(message));
});
}
onReceive(receive) {
this.socket.addListener('message', data => {
receive((0, serialize_1.deserialize)(data.toString()));
});
}
close() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise(resolve => {
this.socket.addListener('close', resolve);
this.socket.close();
});
});
}
}
exports.ServerWebSocketTransport = ServerWebSocketTransport;
class ClientWebSocketTransport {
constructor(url) {
this.url = url;
}
send(message) {
return __awaiter(this, void 0, void 0, function* () {
yield this.connect();
if (this.socket) {
this.socket.send((0, serialize_1.serialize)(message));
}
});
}
onReceive(onReceiveFn) {
this.onReceiveFn = onReceiveFn;
}
close() {
return __awaiter(this, void 0, void 0, function* () {
return new Promise(resolve => {
if (this.socket) {
this.socket.addEventListener('close', resolve);
this.socket.close(1000);
}
else {
resolve();
}
});
});
}
isOpen() {
return this.socket !== undefined && this.socket.readyState === isomorphic_ws_1.default.OPEN;
}
connect() {
return __awaiter(this, void 0, void 0, function* () {
if (this.socket && this.socket.readyState === isomorphic_ws_1.default.OPEN) {
return;
}
else if (this.socket && this.socket.readyState === isomorphic_ws_1.default.CONNECTING) {
return new Promise(resolve => {
this.socket && this.socket.addEventListener('open', resolve);
});
}
yield new Promise((resolve, reject) => {
try {
this.socket = new isomorphic_ws_1.default(this.url);
this.socket.addEventListener('message', event => {
if (this.onReceiveFn) {
this.onReceiveFn((0, serialize_1.deserialize)(event.data.toString()));
}
});
this.socket.addEventListener('close', () => {
if (this.onClose) {
this.onClose();
}
this.socket = undefined;
});
this.socket.addEventListener('open', resolve);
this.socket.addEventListener('error', event => {
var _a;
const errorMessage = `Socket error (${this.url}): ${((_a = event === null || event === void 0 ? void 0 : event.error) === null || _a === void 0 ? void 0 : _a.message) || 'unknown error'}`;
reject(new Error(errorMessage));
});
}
catch (err) {
const errorMessage = `Error creating WebSocket (${this.url}): ${err instanceof Error ? err.message : String(err)}`;
reject(new Error(errorMessage));
}
});
if (this.socket && this.socket.readyState === isomorphic_ws_1.default.CLOSING) {
return new Promise((_, reject) => {
if (this.socket) {
this.socket.addEventListener('close', event => {
reject(new Error(`Socket closed by server (${event.reason})`));
});
}
});
}
});
}
}
exports.ClientWebSocketTransport = ClientWebSocketTransport;