UNPKG

nudbclient

Version:

Universal Realtime Database for Node.js and Browser

132 lines (111 loc) 3.27 kB
class Nudb { constructor(wsUrl, options = {}) { this.wsUrl = wsUrl; this.socket = null; this.listeners = {}; this.dataCallbacks = {}; this.queue = []; this.headers = options.headers || {}; this.connect(); } connect() { const WebSocketImpl = typeof WebSocket !== "undefined" ? WebSocket : require("ws"); // fallback untuk Node.js this.socket = new WebSocketImpl(this.wsUrl); this.socket.onopen = () => { console.log("🟢 WebSocket connected"); while (this.queue.length > 0) { const action = this.queue.shift(); this.socket.send(JSON.stringify(action)); } Object.keys(this.listeners).forEach((path) => { this.sendMessage({ type: "subscribe", path }); }); }; this.socket.onmessage = (event) => { try { const msg = JSON.parse(event.data); if (msg.type === "update" && this.listeners[msg.path]) { this.listeners[msg.path].forEach((cb) => cb(msg.data)); } if (msg.type === "data" && this.dataCallbacks[msg.path]) { this.dataCallbacks[msg.path].forEach((cb) => cb(msg.data)); delete this.dataCallbacks[msg.path]; } } catch (err) { console.error("Error parsing message:", err); } }; this.socket.onclose = () => { console.warn("🔴 WebSocket disconnected. Reconnecting..."); setTimeout(() => this.connect(), 3000); }; } _generateId() { const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let str = ""; for (let i = 0; i < 17; i++) { str += chars.charAt(Math.floor(Math.random() * chars.length)); } return `${Date.now()}${str}`; } setHeader(key, value) { this.headers[key] = value; } sendMessage(msg) { const fullMsg = { ...msg, headers: this.headers }; if (this.socket.readyState === 1) { this.socket.send(JSON.stringify(fullMsg)); } else { this.queue.push(fullMsg); } } subscribe(path) { this.sendMessage({ type: "subscribe", path }); } on(path, callback) { if (!this.listeners[path]) { this.listeners[path] = []; this.subscribe(path); } this.listeners[path].push(callback); } get(path, callback) { if (!this.dataCallbacks[path]) { this.dataCallbacks[path] = []; } this.dataCallbacks[path].push(callback); this.sendMessage({ type: "get", path }); } set(path, data) { this.sendMessage({ type: "set", path, data }); } push(path, data) { const id = this._generateId(); this.set(`${path}/${id}`, data); return id; } update(path, data) { this.sendMessage({ type: "update", path, data }); } delete(path) { this.sendMessage({ type: "delete", path }); } off(path, callback) { if (!this.listeners[path]) return; // Hapus callback tertentu this.listeners[path] = this.listeners[path].filter((cb) => cb !== callback); // Jika tidak ada lagi listener, bisa kirim unsubscribe (opsional) if (this.listeners[path].length === 0) { delete this.listeners[path]; this.sendMessage({ type: "unsubscribe", path }); } } } export default Nudb; if (typeof window !== "undefined") { window.Nudb = Nudb; }