@cloudamqp/amqp-client
Version:
AMQP 0-9-1 client, both for browsers (WebSocket) and node (TCP Socket)
157 lines • 7.75 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AMQPSession = exports.VERSION = exports.AMQPView = exports.AMQPMessage = exports.AMQPError = exports.AMQPConsumer = exports.AMQPChannel = exports.AMQPBaseClient = exports.AMQPWebSocketClient = void 0;
const amqp_base_client_js_1 = require("./amqp-base-client.js");
Object.defineProperty(exports, "AMQPBaseClient", { enumerable: true, get: function () { return amqp_base_client_js_1.AMQPBaseClient; } });
Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return amqp_base_client_js_1.VERSION; } });
const amqp_view_js_1 = require("./amqp-view.js");
Object.defineProperty(exports, "AMQPView", { enumerable: true, get: function () { return amqp_view_js_1.AMQPView; } });
const amqp_error_js_1 = require("./amqp-error.js");
Object.defineProperty(exports, "AMQPError", { enumerable: true, get: function () { return amqp_error_js_1.AMQPError; } });
const amqp_channel_js_1 = require("./amqp-channel.js");
Object.defineProperty(exports, "AMQPChannel", { enumerable: true, get: function () { return amqp_channel_js_1.AMQPChannel; } });
const amqp_consumer_js_1 = require("./amqp-consumer.js");
Object.defineProperty(exports, "AMQPConsumer", { enumerable: true, get: function () { return amqp_consumer_js_1.AMQPConsumer; } });
const amqp_message_js_1 = require("./amqp-message.js");
Object.defineProperty(exports, "AMQPMessage", { enumerable: true, get: function () { return amqp_message_js_1.AMQPMessage; } });
class AMQPWebSocketClient extends amqp_base_client_js_1.AMQPBaseClient {
constructor(url, vhost = "/", username = "guest", password = "guest", name, frameMax = amqp_base_client_js_1.MIN_FRAME_SIZE, heartbeat = 0, logger) {
let channelMax = 0;
if (typeof url === "object") {
vhost = url.vhost ?? vhost;
username = url.username ?? username;
password = url.password ?? password;
name = url.name ?? name;
frameMax = url.frameMax ?? frameMax;
heartbeat = url.heartbeat ?? heartbeat;
channelMax = url.channelMax ?? channelMax;
logger = url.logger ?? logger;
url = url.url;
}
super(vhost, username, password, name, AMQPWebSocketClient.platform(), frameMax, heartbeat, channelMax, logger);
this.framePos = 0;
this.frameSize = 0;
this.url = url;
this.frameBuffer = new Uint8Array(frameMax);
}
connect() {
this.framePos = 0;
this.frameSize = 0;
this.channels = [new amqp_channel_js_1.AMQPChannel(this, 0)];
const socket = new WebSocket(this.url);
this.socket = socket;
socket.binaryType = "arraybuffer";
socket.onmessage = this.handleMessage.bind(this);
return new Promise((resolve, reject) => {
this.connectPromise = [resolve, reject];
socket.addEventListener("close", reject);
socket.addEventListener("error", reject);
socket.addEventListener("open", () => {
socket.addEventListener("error", (ev) => {
if (!this.closed) {
const err = new amqp_error_js_1.AMQPError(ev.toString(), this);
this.closed = true;
this.channels.forEach((ch) => ch?.setClosed(err));
this.channels = [new amqp_channel_js_1.AMQPChannel(this, 0)];
this.onerror(err);
this.ondisconnect?.(err);
this.socket = undefined;
}
});
socket.addEventListener("close", (ev) => {
const clientClosed = this.closed;
this.closed = true;
if (!(ev.wasClean && clientClosed)) {
const err = new amqp_error_js_1.AMQPError(`connection not cleanly closed (${ev.code})`, this);
this.channels.forEach((ch) => ch?.setClosed(err));
this.channels = [new amqp_channel_js_1.AMQPChannel(this, 0)];
this.onerror(err);
if (!clientClosed) {
this.ondisconnect?.(err);
}
}
else {
this.channels.forEach((ch) => ch?.setClosed());
this.channels = [new amqp_channel_js_1.AMQPChannel(this, 0)];
}
this.socket = undefined;
});
socket.send(new Uint8Array([65, 77, 81, 80, 0, 0, 9, 1]));
});
});
}
send(bytes) {
return new Promise((resolve, reject) => {
if (this.socket) {
try {
this.socket.send(bytes);
resolve();
}
catch (err) {
this.closeSocket();
reject(err);
}
}
else {
reject(new amqp_error_js_1.AMQPError("Socket not connected", this));
}
});
}
closeSocket() {
this.closed = true;
if (this.socket)
this.socket.close();
this.socket = undefined;
}
handleMessage(event) {
const buf = event.data;
const bufView = new DataView(buf);
let bufPos = 0;
while (bufPos < buf.byteLength) {
if (this.frameSize === 0) {
if (this.framePos !== 0) {
const len = 7 - this.framePos;
this.frameBuffer.set(new Uint8Array(buf, bufPos, len), this.framePos);
this.frameSize = new DataView(this.frameBuffer.buffer).getInt32(bufPos + 3) + 8;
this.framePos += len;
bufPos += len;
continue;
}
if (bufPos + 3 + 4 > buf.byteLength) {
const len = buf.byteLength - bufPos;
this.frameBuffer.set(new Uint8Array(buf, bufPos), this.framePos);
this.framePos += len;
break;
}
this.frameSize = bufView.getInt32(bufPos + 3) + 8;
if (buf.byteLength - bufPos >= this.frameSize) {
const view = new amqp_view_js_1.AMQPView(buf, bufPos, this.frameSize);
this.parseFrames(view);
bufPos += this.frameSize;
this.frameSize = 0;
continue;
}
}
const leftOfFrame = this.frameSize - this.framePos;
const copyBytes = Math.min(leftOfFrame, buf.byteLength - bufPos);
this.frameBuffer.set(new Uint8Array(buf, bufPos, copyBytes), this.framePos);
this.framePos += copyBytes;
bufPos += copyBytes;
if (this.framePos === this.frameSize) {
const view = new amqp_view_js_1.AMQPView(this.frameBuffer.buffer, 0, this.frameSize);
this.parseFrames(view);
this.frameSize = this.framePos = 0;
}
}
}
static platform() {
if (typeof navigator !== "undefined")
return navigator.userAgent;
else
return `${process.release.name} ${process.version} ${process.platform} ${process.arch}`;
}
}
exports.AMQPWebSocketClient = AMQPWebSocketClient;
var amqp_session_js_1 = require("./amqp-session.js");
Object.defineProperty(exports, "AMQPSession", { enumerable: true, get: function () { return amqp_session_js_1.AMQPSession; } });
//# sourceMappingURL=amqp-websocket-client.js.map