245 lines
5.7 KiB
JavaScript
245 lines
5.7 KiB
JavaScript
const axios = require("axios");
|
|
const WebSocket = require("ws");
|
|
const EventEmitter = require("events");
|
|
|
|
const API_BASE_URL = "https://kvs.wireway.ch/v2";
|
|
|
|
class WireKVSDatabase extends EventEmitter {
|
|
constructor(id, accessKey) {
|
|
super();
|
|
this.id = id;
|
|
this.accessKey = accessKey;
|
|
this.ws = null;
|
|
this.isConnected = false;
|
|
this.keepAliveInterval = null;
|
|
this._eventHandlers = new Map();
|
|
this._setupWebSocket();
|
|
}
|
|
|
|
_setupWebSocket() {
|
|
const wsUrl = `wss://kvs.wireway.ch/events/${
|
|
this.id
|
|
}?accessKey=${encodeURIComponent(this.accessKey)}`;
|
|
this.ws = new WebSocket(wsUrl);
|
|
|
|
this.ws.on("open", () => {
|
|
this.isConnected = true;
|
|
this.emit("connected");
|
|
});
|
|
|
|
this.ws.on("close", () => {
|
|
this.isConnected = false;
|
|
this.emit("disconnected");
|
|
if (this.keepAliveInterval) {
|
|
clearInterval(this.keepAliveInterval);
|
|
this.keepAliveInterval = null;
|
|
}
|
|
|
|
if (!this._disconnecting) {
|
|
setTimeout(() => this._setupWebSocket(), 5000);
|
|
}
|
|
});
|
|
|
|
this.ws.on("message", (data) => {
|
|
try {
|
|
const message = JSON.parse(data);
|
|
if (message.type === "ping") {
|
|
return;
|
|
}
|
|
if (message.type === "error") {
|
|
console.error("WebSocket error from server:", message.message);
|
|
this.emit("error", new Error(message.message));
|
|
if (
|
|
message.message === "KVSDB not found" ||
|
|
message.message === "Forbidden"
|
|
) {
|
|
this.disconnect();
|
|
return;
|
|
}
|
|
}
|
|
this.emit(message.type, message);
|
|
} catch (error) {
|
|
console.error("Error parsing WebSocket message:", error);
|
|
}
|
|
});
|
|
|
|
this.ws.on("error", (error) => {
|
|
console.error("WebSocket error:", error);
|
|
this.emit("error", error);
|
|
});
|
|
}
|
|
|
|
on(event, handler) {
|
|
super.on(event, handler);
|
|
if (!this._eventHandlers.has(event)) {
|
|
this._eventHandlers.set(event, new Set());
|
|
}
|
|
this._eventHandlers.get(event).add(handler);
|
|
return this;
|
|
}
|
|
|
|
off(event, handler) {
|
|
if (handler) {
|
|
super.removeListener(event, handler);
|
|
const handlers = this._eventHandlers.get(event);
|
|
if (handlers) {
|
|
handlers.delete(handler);
|
|
}
|
|
} else {
|
|
const handlers = this._eventHandlers.get(event);
|
|
if (handlers) {
|
|
handlers.forEach((h) => super.removeListener(event, h));
|
|
handlers.clear();
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
disconnect() {
|
|
this._disconnecting = true;
|
|
this._eventHandlers.forEach((handlers, event) => {
|
|
handlers.forEach((handler) => super.removeListener(event, handler));
|
|
});
|
|
this._eventHandlers.clear();
|
|
|
|
if (this.ws) {
|
|
if (this.keepAliveInterval) {
|
|
clearInterval(this.keepAliveInterval);
|
|
this.keepAliveInterval = null;
|
|
}
|
|
this.ws.close();
|
|
this.ws = null;
|
|
}
|
|
this.isConnected = false;
|
|
}
|
|
|
|
async getAllEntries() {
|
|
const response = await axios.get(`${API_BASE_URL}/database/${this.id}`, {
|
|
headers: { Authorization: this.accessKey },
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
async get(key) {
|
|
const response = await axios.get(
|
|
`${API_BASE_URL}/database/${this.id}/${key}`,
|
|
{
|
|
headers: { Authorization: this.accessKey },
|
|
}
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
async set(key, value) {
|
|
await axios.post(`${API_BASE_URL}/database/${this.id}/${key}`, value, {
|
|
headers: { Authorization: this.accessKey },
|
|
});
|
|
}
|
|
|
|
async update(key, value) {
|
|
await axios.patch(`${API_BASE_URL}/database/${this.id}/${key}`, value, {
|
|
headers: { Authorization: this.accessKey },
|
|
});
|
|
}
|
|
|
|
async delete(key) {
|
|
await axios.delete(`${API_BASE_URL}/database/${this.id}/${key}`, {
|
|
headers: { Authorization: this.accessKey },
|
|
});
|
|
}
|
|
|
|
async search(query) {
|
|
const response = await axios.post(
|
|
`${API_BASE_URL}/databaseSearch/${this.id}`,
|
|
query,
|
|
{
|
|
headers: { Authorization: this.accessKey },
|
|
}
|
|
);
|
|
return response.data;
|
|
}
|
|
}
|
|
|
|
class WireKVS {
|
|
constructor(token) {
|
|
this.token = token;
|
|
}
|
|
|
|
static connect(id, accessKey) {
|
|
return new WireKVSDatabase(id, accessKey);
|
|
}
|
|
|
|
async listDatabases() {
|
|
const response = await axios.get(`${API_BASE_URL}/databases`, {
|
|
headers: { Authorization: this.token },
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
async createDatabase({
|
|
name,
|
|
allowPublicWrites = false,
|
|
allowPublicReads = false,
|
|
allowPublicModifications = false,
|
|
allowSpecificPublicReads = false,
|
|
}) {
|
|
const response = await axios.post(
|
|
`${API_BASE_URL}/database`,
|
|
{
|
|
name,
|
|
allowPublicWrites,
|
|
allowPublicReads,
|
|
allowPublicModifications,
|
|
allowSpecificPublicReads,
|
|
},
|
|
{
|
|
headers: { Authorization: this.token },
|
|
}
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
async updateDatabase(
|
|
id,
|
|
{
|
|
name,
|
|
allowPublicWrites,
|
|
allowPublicReads,
|
|
allowPublicModifications,
|
|
allowSpecificPublicReads,
|
|
}
|
|
) {
|
|
const response = await axios.patch(
|
|
`${API_BASE_URL}/database/${id}`,
|
|
{
|
|
name,
|
|
allowPublicWrites,
|
|
allowPublicReads,
|
|
allowPublicModifications,
|
|
allowSpecificPublicReads,
|
|
},
|
|
{
|
|
headers: { Authorization: this.token },
|
|
}
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
async deleteDatabase(id) {
|
|
await axios.delete(`${API_BASE_URL}/database/${id}`, {
|
|
headers: { Authorization: this.token },
|
|
});
|
|
}
|
|
|
|
async truncateDatabase(id) {
|
|
await axios.delete(`${API_BASE_URL}/databaseTruncate/${id}`, {
|
|
headers: { Authorization: this.token },
|
|
});
|
|
}
|
|
|
|
database(id, accessKey) {
|
|
return new WireKVSDatabase(id, accessKey);
|
|
}
|
|
}
|
|
|
|
module.exports = WireKVS;
|