export class API extends EventTarget { constructor() { super(); this.#socketOpen(); } /** @type {WebSocket} */ #socket; /** * Opens a new websocket connection, and adds all necessary listeners. */ #socketOpen() { this.#socket = new WebSocket("ws://" + location.host + "/ws"); this.#socket.onopen = event => { console.log(`Websocket connection opened.`) } this.#socket.onmessage = event => { /** @type {{type: string, payload: any}} */ const data = JSON.parse(event.data); switch (data.type) { case "QueueDeleteAt": { /** @type {CustomEventInit} */ const eventData = { detail: data.payload }; this.dispatchEvent(new CustomEvent("queuedeleteat", eventData)); break; } case "QueueInsertAt": { /** @type {CustomEventInit} */ const eventData = { detail: data.payload }; this.dispatchEvent(new CustomEvent("queueinsertat", eventData)); break; } case "QueueReplace": { /** @type {CustomEventInit} */ const eventData = { detail: data.payload }; this.dispatchEvent(new CustomEvent("queuereplace", eventData)); break; } case "QueueShiftAt": { /** @type {CustomEventInit} */ const eventData = { detail: data.payload }; this.dispatchEvent(new CustomEvent("queueshiftat", eventData)); break; } default: console.error(`Unknown websocket data type "${data.type}"`); break; } } this.#socket.onclose = event => { console.log(`Socket is closed. Reconnect will be attempted in 1 second. Code: ${event.code} Reason: ${event.reason} WasClean: ${event.wasClean}.`); setTimeout(() => { this.#socketOpen(); }, 1000); }; this.#socket.onerror = event => { console.error(`Socket encountered error: ${event}. Closing socket.`); this.#socket.close(); }; } /** * Sends a document queue delete request to the server. * @param {...number} ids Document ids. */ queueDelete(...ids) { if (this.#socket.readyState !== WebSocket.OPEN) { return } /** @type {{type: string, payload: import("./model").APIPacketQueueDelete}} */ const message = { type: "QueueDelete", payload: { ids: ids } }; this.#socket.send(JSON.stringify(message)); } /** * Sends a document queue shift request to the server. * @param {number} offset * @param {...number} ids Document ids. */ queueShift(offset, ...ids) { if (this.#socket.readyState !== WebSocket.OPEN) { return } /** @type {{type: string, payload: import("./model").APIPacketQueueShift}} */ const message = { type: "QueueShift", payload: { offset: offset, ids: ids } }; this.#socket.send(JSON.stringify(message)); } /** * * @param {"GET"|"POST"|"DELETE"|"UPDATE"} method * @param {string} url */ #ajaxRequest(method, url) { return new Promise(function (resolve, reject) { const xhr = new XMLHttpRequest(); xhr.open(method, url); xhr.onload = function () { if (this.status >= 200 && this.status < 300) { resolve(this.response); } else { reject({ status: this.status, statusText: this.statusText, }); } }; xhr.onerror = function () { reject({ status: this.status, statusText: this.statusText, }); }; xhr.send(); }); } }