129 lines
3.7 KiB
TypeScript
129 lines
3.7 KiB
TypeScript
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
|
|
export type SocketCallback = (data: unknown) => void;
|
|
|
|
/// XCU Media over QUIC (MoQ) / WebSocket Adapter
|
|
/// Menggantikan `ZeroSocket` dan `Socket.IO`
|
|
/// Fitur:
|
|
/// - Terhubung langsung ke mesin Rust (`xcu-neural-chat`) di port 8443
|
|
/// - Tidak menggunakan Redis PubSub
|
|
/// - Berjalan via WebSocket (fallback untuk WebTransport tanpa HTTPS certs)
|
|
export class XcuMoq {
|
|
private url: string;
|
|
private listeners: Record<string, SocketCallback[]> = {};
|
|
private ws: WebSocket | null = null;
|
|
public id: string;
|
|
private reconnectTimer: any;
|
|
|
|
constructor(url: string) {
|
|
this.url = url;
|
|
this.id = Math.random().toString(36).substring(2, 15);
|
|
}
|
|
|
|
connect() {
|
|
if (this.ws && (this.ws.readyState === WebSocket.CONNECTING || this.ws.readyState === WebSocket.OPEN)) return;
|
|
|
|
// Sambungkan langsung ke Alpha VPS atau localhost
|
|
let wsUrl = "ws://160.187.143.253:8443";
|
|
if (typeof window !== "undefined" && window.location.hostname === "localhost") {
|
|
wsUrl = "ws://127.0.0.1:8443";
|
|
}
|
|
|
|
try {
|
|
this.ws = new WebSocket(wsUrl);
|
|
|
|
this.ws.onopen = () => {
|
|
console.log("[XCU MoQ] Terhubung ke Neural Mesh Rust Engine.");
|
|
if (this.listeners["connect"]) {
|
|
this.listeners["connect"].forEach(fn => fn({}));
|
|
}
|
|
};
|
|
|
|
this.ws.onmessage = (e) => {
|
|
try {
|
|
const data = JSON.parse(e.data);
|
|
if (data.event && this.listeners[data.event]) {
|
|
this.listeners[data.event].forEach(fn => fn(data.payload));
|
|
}
|
|
} catch {
|
|
// Abaikan parse error
|
|
}
|
|
};
|
|
|
|
this.ws.onclose = () => {
|
|
console.warn("[XCU MoQ] Koneksi terputus. Neural link lost.");
|
|
if (this.listeners["disconnect"]) {
|
|
this.listeners["disconnect"].forEach(fn => fn({}));
|
|
}
|
|
// Auto-reconnect
|
|
clearTimeout(this.reconnectTimer);
|
|
this.reconnectTimer = setTimeout(() => this.connect(), 3000);
|
|
};
|
|
|
|
this.ws.onerror = (err) => {
|
|
console.error("[XCU MoQ] WebSocket Error:", err);
|
|
};
|
|
} catch (e) {
|
|
console.error("[XCU MoQ] Gagal inisialisasi:", e);
|
|
}
|
|
}
|
|
|
|
on(event: string, callback: SocketCallback) {
|
|
if (!this.listeners[event]) this.listeners[event] = [];
|
|
this.listeners[event].push(callback);
|
|
return this;
|
|
}
|
|
|
|
once(event: string, callback: SocketCallback) {
|
|
const onceWrapper = (data: unknown) => {
|
|
callback(data);
|
|
this.off(event, onceWrapper);
|
|
};
|
|
this.on(event, onceWrapper);
|
|
return this;
|
|
}
|
|
|
|
off(event: string, callback?: SocketCallback) {
|
|
if (!this.listeners[event]) return this;
|
|
if (callback) {
|
|
this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
|
|
} else {
|
|
delete this.listeners[event];
|
|
}
|
|
return this;
|
|
}
|
|
|
|
emit(event: string, payload: string | Record<string, unknown> = {}) {
|
|
const normalizedPayload = typeof payload === 'string' ? { value: payload } : payload;
|
|
|
|
// Kirim pesan ke mesin Rust via WebSocket
|
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
const msg = JSON.stringify({
|
|
client_id: this.id,
|
|
event,
|
|
payload: normalizedPayload
|
|
});
|
|
this.ws.send(msg);
|
|
} else {
|
|
console.warn("[XCU MoQ] Pesan di-drop: Tidak terhubung ke Neural Mesh.");
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
disconnect() {
|
|
if (this.ws) {
|
|
this.ws.close();
|
|
this.ws = null;
|
|
}
|
|
clearTimeout(this.reconnectTimer);
|
|
}
|
|
}
|
|
|
|
export const io = (url?: string, options?: any) => {
|
|
const socket = new XcuMoq(url || "");
|
|
socket.connect();
|
|
return socket;
|
|
};
|
|
|
|
export type Socket = XcuMoq;
|