@tomkoooo/tbase
Version:
A JavaScript-based socket client for out-of-the-box backend for React
1,257 lines (1,112 loc) • 47.2 kB
text/typescript
// utils/socket.ts
import { io, Socket } from "socket.io-client";
import bcrypt from "bcryptjs";
declare global {
interface Navigator {
standalone?: boolean;
}
}
interface ConnectionInfo {
url?: string;
dbName?: string;
user?: string;
password?: string;
host?: string;
database?: string;
port?: number;
}
interface ActionBuilder {
query(queryCode: string): ActionBuilder;
setState(setter: React.Dispatch<React.SetStateAction<any[]>>): ActionBuilder;
callback(fn: (data: any) => void): ActionBuilder;
execute(): void; // Explicit execute a lánc végén
}
interface ListenOptions {
usePolling?: boolean;
pollInterval?: number;
}
export class Client {
private socket: Socket;
private dbType: string | null = null;
private connectionInfo: ConnectionInfo | null = null;
public publicVapidKey: string;
private isInitialized = false;
private initializePromise: Promise<void> | null = null;
constructor(url: string = "localhost:3000") {
this.socket = io(url);
this.publicVapidKey = process.env.NEXT_PUBLIC_VAPID_PUBLIC!;
if (!this.publicVapidKey) {
throw new Error("Public Vapid Key is not set");
}
}
token() {
return localStorage.getItem("t_auth");
}
urlBase64ToUint8Array(base64String: string) {
console.log("Converting base64 to Uint8Array...", base64String);
if (!base64String) throw new Error('Invalid base64 string');
const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
public database(type: "mongodb" | "mysql"): Client {
this.dbType = type;
return this;
}
public connection(connectionInfo: any): Promise<this> {
this.connectionInfo = connectionInfo;
return new Promise((resolve, reject) => {
if (!this.dbType || !this.connectionInfo) {
reject(new Error("Database type and connection info must be provided."));
return;
}
this.socket.emit("initialize", {
dbType: this.dbType,
connectionInfo: this.connectionInfo,
});
this.socket.once("initialized", () => {
console.log("Socket initialized");
this.isInitialized = true;
resolve(this);
});
this.socket.once("error", (error: any) => {
this.isInitialized = false;
reject(new Error(error.message));
});
});
}
private initialize() {
if (!this.dbType || !this.connectionInfo) {
throw new Error("Database type and connection info must be provided.");
}
this.socket.emit("initialize", {
dbType: this.dbType,
connectionInfo: this.connectionInfo,
});
}
private initializeAsync(): Promise<void> {
// Ha már inicializálva van, vagy folyamatban van az inicializálás, várjuk meg
if (this.isInitialized) {
return Promise.resolve();
}
if (this.initializePromise) {
return this.initializePromise;
}
if (!this.dbType || !this.connectionInfo) {
return Promise.reject(new Error("Database type and connection info must be provided."));
}
// Új Promise létrehozása az inicializáláshoz
this.initializePromise = new Promise((resolve, reject) => {
this.socket.emit("initialize", {
dbType: this.dbType,
connectionInfo: this.connectionInfo,
});
this.socket.once("initialized", () => {
console.log("Socket initialized");
this.isInitialized = true;
resolve();
});
// Hibakezelés, ha az inicializálás sikertelen
this.socket.once("error", (error: any) => {
this.isInitialized = false;
this.initializePromise = null; // Reseteljük, hogy újra próbálkozhassunk
reject(new Error(error.message));
});
});
return this.initializePromise;
}
// Biztosítja, hogy az inicializálás megtörténjen, mielőtt bármilyen műveletet végrehajtunk
private async ensureInitialized(): Promise<void> {
if (this.connectionInfo) {
await this.initializeAsync();
}
}
private initializeNotification() {
if (!this.dbType || !this.connectionInfo) {
throw new Error("Database type and connection info must be provided.");
}
this.socket.emit("initializeNotification", {
dbType: this.dbType,
connectionInfo: this.connectionInfo,
});
}
private closeConnection() {
this.socket.emit("close");
}
//------ SOCKET SCOPE ------
public subscribe(channel: string, callback: (data: any) => void): Client {
this.initialize();
this.socket.emit("subscribe", channel);
this.socket.on(channel, callback);
return this;
}
public listen(channel: string, callback: (data: any) => void): Client {
this.initialize();
this.socket.emit("listen", channel);
this.socket.on(channel, callback);
return this;
}
public unsubscribe(channel: string): Client {
this.socket.emit("unsubscribe", channel);
this.socket.off(channel);
return this;
}
public send(channel: string, data: any): Client {
this.socket.emit("message", { channel, data });
return this;
}
//------ DATABASE SCOPE ------
public execute(channel: string, query: string, callback: (data:any) => void): Client {
this.socket.emit("action", { action: "execute", channel, code: query, method: "" });
this.socket.on(`${channel}:result`, callback);
return this;
}
private createActionBuilder(
channel: string,
method: "insert" | "delete" | "update" | "get",
client: Client
): ActionBuilder {
let code: string | undefined;
let setState: React.Dispatch<React.SetStateAction<any[]>> | undefined;
let callback: ((data: any) => void) | undefined;
const closeConnection = () => {
client.socket.emit("close");
console.log("Socket connection closed");
};
const builder: ActionBuilder = {
query(queryCode: string): ActionBuilder {
code = queryCode;
console.log("Query set:", queryCode);
return this;
},
setState(setter: React.Dispatch<React.SetStateAction<any[]>>): ActionBuilder {
setState = setter;
console.log("setState set");
return this;
},
callback(fn: (data: any) => void): ActionBuilder {
callback = fn;
console.log("Callback set");
return this;
},
execute(): void {
if (!code) {
console.error("Query code is required but not provided");
return;
}
client.initialize();
console.log("Action executed:", { channel, method, code });
client.socket.emit("action", {
action: "execute",
channel,
method,
code,
});
if (setState || callback) {
client.socket.once(`${channel}:result`, (response) => {
console.log(`${method} response:`, response);
if (response.status === "success") {
const res = response.result;
if (setState) {
switch (method) {
case "insert":
if (res.insertedId) {
const newItem = { _id: res.insertedId, ...res.insertedDoc };
setState((prev) => [...prev, newItem]);
}
break;
case "delete":
if (res.deletedCount > 0 || res.affectedRows > 0) {
const idMatch = res.id;
console.log("Deleting item with ID:", idMatch);
if (idMatch) {
setState((prev) => {
const newState = prev.filter(
(item) => item._id !== idMatch && item.id != idMatch
);
console.log(prev.filter((item) => item._id !== idMatch && item.id != idMatch));
console.log("New state after delete:", newState);
return newState;
});
}
}
break;
case "update":
if (res.updatedId && res.updatedDoc) {
console.log("Updating item with ID:", res.updatedId);
setState((prev) => {
const newState = prev.map((item) =>
item._id === res.updatedId || item.id == res.updatedId
? { ...item, ...res.updatedDoc }
: item
);
console.log("New state after update:", newState);
return newState;
});
}
break;
case "get":
console.log("Setting state with get result:", res);
setState(res || []);
break;
}
}
if (callback) callback(response);
} else {
console.error(`${method} failed:`, response.message);
if (callback) callback(response);
}
});
}
},
};
return builder;
}
public get(channel: string): ActionBuilder {
return this.createActionBuilder(channel, "get", this);
}
public delete(channel: string): ActionBuilder {
return this.createActionBuilder(channel, "delete", this);
}
public update(channel: string): ActionBuilder {
return this.createActionBuilder(channel, "update", this);
}
public add(channel: string): ActionBuilder {
console.log("Creating action builder for", channel);
return this.createActionBuilder(channel, "insert", this);
}
//------ NOTIFICATIONS SCOPE ------
public async subscribeToNotification(userId: string) {
if(this.connectionInfo) {
this.initializeNotification();
}
if (!userId) {
console.log('Error: User ID is required');
throw new Error('User ID is required');
};
// Service Worker ellenőrzése
if (!('serviceWorker' in navigator)) {
console.log('Error: ServiceWorker is not supported in this environment');
throw new Error('ServiceWorker is not supported in this environment');
}
// További ellenőrzés és logika
if (!('PushManager' in window)) {
console.log('Error: PushManager is not supported in this environment');
throw new Error('PushManager is not supported in this environment');
}
try {
const permission = await Notification.requestPermission();
if (permission !== 'granted') {
console.log('Error: Notification permission denied');
throw new Error('Notification permission denied');
}
const registration = await navigator.serviceWorker.register('/service-worker.js');
console.log('Service Worker registered successfully');
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: this.urlBase64ToUint8Array(this.publicVapidKey),
});
this.socket.emit('subscribe:not', { userId, subscription });
console.log(`User ${userId} subscribed to push notifications`);
} catch (error: any) {
alert(`Subscription failed: ${error.message}`);
throw error;
}
}
public async unsubscribeFromNotification(userId: string): Promise<void> {
if(this.connectionInfo) {
this.initializeNotification();
}
if (!userId) throw new Error('User ID is required');
const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.getSubscription();
if (subscription) {
await subscription.unsubscribe();
this.socket.emit('unsubscribe:not', { userId, subscription });
console.log(`User ${userId} unsubscribed from push notifications`);
}
}
public sendNotification(userId: string, notificationBody: { title: string; message: string }): void {
if(this.connectionInfo) {
this.initializeNotification();
}
if (!notificationBody || typeof notificationBody !== 'object') {
throw new Error('Notification body must be a valid object');
}
this.socket.emit('sendNotification', { userId, notification: notificationBody });
}
// ACCOUNT SCOPE
public signUp(email: string, password: string, callback: (data: any) => void): Client {
this.initialize();
const salt = bcrypt.genSaltSync(10);
const hashedPassword = bcrypt.hashSync(password, salt);
const userData = { email, password: hashedPassword, createdAt: new Date() };
this.socket.emit("account:action", {
action: "signup",
data: userData,
});
this.socket.on("account:result", (response) => {
console.log("SignUp response:", response);
if (response.status === "success" && response.token && response.sessionId) {
document.cookie = `t_auth=${response.sessionId} ; path=/`;
localStorage.setItem("t_auth", response.token);
}
callback(response);
});
return this;
}
public signIn(email: string, password: string, callback: (data: any) => void): Client {
this.initialize();
this.socket.emit("account:action", {
action: "signin",
data: { email, password },
});
this.socket.on("account:result", (response) => {
console.log("SignIn response:", response);
if (response.status === "success" && response.token && response.sessionId) {
document.cookie = `t_auth_super=${response.sessionId} ; path=/`;
localStorage.setItem("t_auth_super", response.token);
}
callback(response); // Hibák esetén is továbbítjuk a választ
});
return this;
}
public signUpSuper(email: string, password: string, callback: (data: any) => void): Client {
this.initialize();
const salt = bcrypt.genSaltSync(10);
const hashedPassword = bcrypt.hashSync(password, salt);
const userData = { email, password: hashedPassword, createdAt: new Date() };
this.socket.emit("account:action", {
action: "signupSuper",
data: userData,
});
this.socket.on("account:result", (response) => {
console.log("SignUp response:", response);
if (response.status === "success" && response.token && response.sessionId) {
document.cookie = `t_auth=${response.sessionId} ; path=/`;
localStorage.setItem("t_auth", response.token);
document.cookie = `t_auth_super=${response.sessionId} ; path=/`;
localStorage.setItem("t_auth_super", response.token);
}
callback(response);
});
return this;
}
public signInSuper(email: string, password: string, callback: (data: any) => void): Client {
this.initialize();
this.socket.emit("account:action", {
action: "signinSuper",
data: { email, password },
});
this.socket.on("account:result", (response) => {
console.log("SignIn response:", response);
if (response.status === "success" && response.token && response.sessionId) {
document.cookie = `t_auth=${response.sessionId} ; path=/`;
localStorage.setItem("t_auth", response.token);
document.cookie = `t_auth_super=${response.sessionId} ; path=/`;
localStorage.setItem("t_auth_super", response.token);
}
callback(response); // Hibák esetén is továbbítjuk a választ
});
return this;
}
public validate(token: string, callback: (data: any) => void): Client {
this.initialize();
this.socket.emit("account:action", { action: "validate", token });
this.socket.on("account:result", (response) => {
console.log("Validate response:", response);
callback(response);
});
return this;
}
public account(): {
get: (callback: (data: any) => void) => Client;
getSession: (callback: (data: any) => void) => Client;
getSessions: (callback: (data: any) => void) => Client;
setSession: (sessionData: string, callback: (data: any) => void) => Client;
killSession: (callback: (data: any) => void) => Client;
killSessions: (callback: (data: any) => void) => Client;
changeSession: (newSessionString: string, callback: (data: any) => void) => Client;
setLabels: (labels: string[], callback: (data: any) => void) => Client;
getLabels: (callback: (data: any) => void) => Client;
deleteLabels: (callback: (data: any) => void) => Client;
setPreference: (key: string, value: any, callback: (data: any) => void) => Client;
updatePreference: (key: string, value: any, callback: (data: any) => void) => Client;
deletePreferenceKey: (key: string, callback: (data: any) => void) => Client;
getPreferences: (callback: (data: any) => void) => Client;
} {
this.initialize();
function getCookie(cname: string) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
return {
get: (callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("account:action", { action: "getAccount", token });
this.socket.on("account:get", (response) => {
console.log("Get account response:", response);
callback(response);
});
return this;
},
getSession: (callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
const session = getCookie("t_auth");
this.socket.emit("account:action", { action: "getSession", token, session });
this.socket.on("account:session", (response) => {
console.log("Get session response:", response);
callback(response);
});
return this;
},
getSessions: (callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("account:action", { action: "getSessions", token });
this.socket.on("account:session", (response) => {
console.log("Get session response:", response);
callback(response);
});
return this;
},
setSession: (sessionData: string, callback: (data: any) => void): Client => {
const session = getCookie("t_auth");
this.socket.emit("account:action", { action: "setSessions", session, data: sessionData });
this.socket.on("account:result", (response) => {
console.log("Set session response:", response);
callback(response);
});
return this;
},
killSession: (callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
const session = getCookie("t_auth");
this.socket.emit("account:action", { action: "killSession", token, session });
this.socket.on("account:result", (response) => {
console.log("Kill session response:", response);
if (response.status === "success") {
document.cookie = "t_auth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
localStorage.removeItem("t_auth");
}
callback(response);
});
return this;
},
killSessions: (callback: (data: any) => void): Client => {
const session = getCookie("t_auth");
this.socket.emit("account:action", { action: "killSessions", session });
this.socket.on("account:result", (response) => {
console.log("Kill session response:", response);
if (response.status === "success") {
document.cookie = "t_auth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
localStorage.removeItem("t_auth");
}
callback(response);
});
return this;
},
changeSession: (newSessionString: string, callback: (data: any) => void): Client => {
const session = getCookie("t_auth");
this.socket.emit("account:action", { action: "changeSession", session, data: newSessionString });
this.socket.on("account:result", (response) => {
console.log("Change session response:", response);
callback(response);
});
return this;
},
// Labels Management
setLabels: (labels: string[], callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("labels:action", { action: "setLabels", token, labels });
this.socket.on("labels:result", (response) => {
console.log("Set labels response:", response);
callback(response);
});
return this;
},
getLabels: (callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("labels:action", { action: "getLabels", token });
this.socket.on("labels:result", (response) => {
console.log("Get labels response:", response);
callback(response);
});
return this;
},
deleteLabels: (callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("labels:action", { action: "deleteLabels", token });
this.socket.on("labels:result", (response) => {
console.log("Delete labels response:", response);
callback(response);
});
return this;
},
// Preferences Management
setPreference: (key: string, value: any, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("preferences:action", { action: "setPreference", token, key, value });
this.socket.on("preferences:result", (response) => {
console.log("Set preference response:", response);
callback(response);
});
return this;
},
updatePreference: (key: string, value: any, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("preferences:action", { action: "updatePreference", token, key, value });
this.socket.on("preferences:result", (response) => {
console.log("Update preference response:", response);
callback(response);
});
return this;
},
deletePreferenceKey: (key: string, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("preferences:action", { action: "deletePreferenceKey", token, key });
this.socket.on("preferences:result", (response) => {
console.log("Delete preference key response:", response);
callback(response);
});
return this;
},
getPreferences: (callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("preferences:action", { action: "getPreferences", token });
this.socket.on("preferences:result", (response) => {
console.log("Get preferences response:", response);
callback(response);
});
return this;
},
};
}
public listenToAccountUpdates(callback: (data: any) => void): Client {
this.socket.on("account:updates", (update) => {
console.log("Account update received:", update);
callback(update);
});
return this;
}
//------ USERS SCOPE ------
public users(): {
listAll: (callback: (data: any[]) => void) => Client;
listOnline: (callback: (data: any[]) => void) => Client;
listenOnlineUsers: (callback: (data: any[]) => void) => Client;
getUser: (userId: string, callback: (data: any) => void) => Client;
getUsers: (userIds: string[], callback: (data: any) => void) => Client;
// Labels Management
setLabels: (userId: string, labels: string[], callback: (data: any) => void) => Client;
getLabels: (userId: string, callback: (data: any) => void) => Client;
deleteLabels: (userId: string, callback: (data: any) => void) => Client;
// Preferences Management
setPreference: (userId: string, key: string, value: any, callback: (data: any) => void) => Client;
updatePreference: (userId: string, key: string, value: any, callback: (data: any) => void) => Client;
deletePreferenceKey: (userId: string, key: string, callback: (data: any) => void) => Client;
getPreferences: (userId: string, callback: (data: any) => void) => Client;
} {
this.initialize();
return {
listAll: (callback: (data: any[]) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("users:action", { action: "listAll", token });
this.socket.on("users:result", (response) => {
console.log("List all users response:", response);
if (response.status === "success") {
callback(response.data);
} else {
callback([]);
}
});
return this;
},
listOnline: (callback: (data: any[]) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("users:action", { action: "listOnline", token });
this.socket.on("users:online", (response) => {
console.log("List online users response:", response);
if (response.status === "success") {
console.log("Online users:", response.data);
callback(response.data);
} else {
callback([]);
}
});
return this;
},
listenOnlineUsers: (callback: (data: any[]) => void): Client => {
this.socket.emit("subscribe", "users:onlineChanged");
this.socket.on("users:onlineChanged", (onlineUsersData) => {
console.log("Online users changed:", onlineUsersData);
callback(onlineUsersData);
});
return this;
},
getUser: (userId: string, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("users:action", { action: "getUser", token, userId });
this.socket.on("users:get-user", (response) => {
console.log("Get user response:", response);
callback(response);
});
return this;
},
getUsers: (userIds: string[], callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("users:action", { action: "getUsers", token, userIds });
this.socket.on("users:get-users", (response) => {
console.log("Get users response:", response);
callback(response);
});
return this;
},
// Labels Management
setLabels: (userId: string, labels: string[], callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("labels:action", { action: "setLabels", token, userId, labels });
this.socket.on("labels:result", (response) => {
console.log("Set labels response:", response);
callback(response);
});
return this;
},
getLabels: (userId: string, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("labels:action", { action: "getLabels", token, userId });
this.socket.on("labels:result", (response) => {
console.log("Get labels response:", response);
callback(response);
});
return this;
},
deleteLabels: (userId: string, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("labels:action", { action: "deleteLabels", token, userId });
this.socket.on("labels:result", (response) => {
console.log("Delete labels response:", response);
callback(response);
});
return this;
},
// Preferences Management
setPreference: (userId: string, key: string, value: any, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("preferences:action", { action: "setPreference", token, userId, key, value });
this.socket.on("preferences:result", (response) => {
console.log("Set preference response:", response);
callback(response);
});
return this;
},
updatePreference: (userId: string, key: string, value: any, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("preferences:action", { action: "updatePreference", token, userId, key, value });
this.socket.on("preferences:result", (response) => {
console.log("Update preference response:", response);
callback(response);
});
return this;
},
deletePreferenceKey: (userId: string, key: string, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("preferences:action", { action: "deletePreferenceKey", token, userId, key });
this.socket.on("preferences:result", (response) => {
console.log("Delete preference key response:", response);
callback(response);
});
return this;
},
getPreferences: (userId: string, callback: (data: any) => void): Client => {
const token = localStorage.getItem("t_auth");
this.socket.emit("preferences:action", { action: "getPreferences", token, userId });
this.socket.on("preferences:result", (response) => {
console.log("Get preferences response:", response);
callback(response);
});
return this;
},
};
}
//------- BUCKET SCOPE -------
public async createBucket(): Promise<string> {
if (this.connectionInfo) {
this.initialize();
}
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit('bucket:action', { action: 'create', token });
this.socket.once('bucket:created', ({ bucketId }: { bucketId: string }) => {
console.log(`Bucket created: ${bucketId}`);
resolve(bucketId);
});
this.socket.once('error', ({ message }: { message: string }) => {
console.log(`Error creating bucket: ${message}`);
reject(new Error(message));
});
});
}
public async uploadFile(bucketId: string, file: { name: string; type: string; data: ArrayBuffer }): Promise<string> {
if (this.connectionInfo) {
this.initialize();
}
const token = localStorage.getItem("t_auth");
if (!bucketId || !file || !file.name || !file.type || !file.data) {
console.log('Uploading file to bucket:', bucketId, file);
console.log('Error: Bucket ID and file details (name, type, data) are required');
throw new Error('Bucket ID and file details are required');
}
return new Promise((resolve, reject) => {
this.socket.emit('bucket:action', {action: 'upload', bucketId, file, token });
this.socket.once('file:uploaded', ({ bucketId: returnedBucketId, fileId }: { bucketId: string; fileId: string }) => {
console.log(`File uploaded to ${returnedBucketId}: ${fileId}`);
resolve(fileId);
});
this.socket.once('error', ({ message }: { message: string }) => {
console.log(`Error uploading file: ${message}`);
reject(new Error(message));
});
});
}
public async getFile(bucketId: string, fileId: string): Promise<{ fileName: string; fileType: string; fileData: ArrayBuffer }> {
if (this.connectionInfo) {
this.initialize();
}
if (!bucketId || !fileId) {
console.log('Error: Bucket ID and file ID are required');
throw new Error('Bucket ID and file ID are required');
}
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit('bucket:action', {action: 'get', bucketId, fileId, token });
this.socket.once('file:retrieved', (retrievedFile: { fileName: string; fileType: string; fileData: ArrayBuffer }) => {
console.log(`File retrieved from ${bucketId}: ${retrievedFile.fileName}`);
resolve(retrievedFile);
});
this.socket.once('error', ({ message }: { message: string }) => {
console.log(`Error retrieving file: ${message}`);
reject(new Error(message));
});
});
}
public async listFiles(bucketId: string): Promise<{ id: string; fileName: string; fileType: string; createdAt: string; updatedAt: string }[]> {
if (this.connectionInfo) {
this.initialize();
}
if (!bucketId) {
console.log('Error: Bucket ID is required');
throw new Error('Bucket ID is required');
}
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit('bucket:action', {action:'list', bucketId, token });
this.socket.once('file:listed', ({ bucketId: returnedBucketId, files }: { bucketId: string; files: any[] }) => {
console.log(`Listed ${files.length} files in ${returnedBucketId}`);
resolve(files);
});
this.socket.once('error', ({ message }: { message: string }) => {
console.log(`Error listing files: ${message}`);
reject(new Error(message));
});
});
}
public async deleteFile(bucketId: string, fileId: string): Promise<void> {
if (this.connectionInfo) {
this.initialize();
}
if (!bucketId || !fileId) {
console.log('Error: Bucket ID and file ID are required');
throw new Error('Bucket ID and file ID are required');
}
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit('bucket:action', {action: 'deleteFile', bucketId, fileId, token});
this.socket.once('file:delete', ({ bucketId: returnedBucketId, fileId: deletedFileId }: { bucketId: string; fileId: string }) => {
console.log(`File ${deletedFileId} deleted from ${returnedBucketId}`);
resolve();
});
this.socket.once('error', ({ message }: { message: string }) => {
console.log(`Error deleting file: ${message}`);
reject(new Error(message));
});
});
}
public async listBuckets(): Promise<string[]> {
if (this.connectionInfo) {
this.initialize();
}
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("bucket:action", { action: "bucketList", token});
this.socket.once("bucket:listed", ({ buckets }: { buckets: string[] }) => {
console.log(`Listed ${buckets.length} buckets`);
resolve(buckets);
});
this.socket.once("error", ({ message }: { message: string }) => {
console.log(`Error listing buckets: ${message}`);
reject(new Error(message));
});
});
}
public async deleteBucket(bucketId: string): Promise<void> {
if (this.connectionInfo) {
this.initialize();
}
if (!bucketId) {
console.log("Error: Bucket ID is required");
throw new Error("Bucket ID is required");
}
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("bucket:action", {action: 'delete', bucketId, token });
this.socket.once("bucket:deleted", ({ bucketId: deletedBucketId }: { bucketId: string }) => {
console.log(`Bucket ${deletedBucketId} deleted`);
resolve();
});
this.socket.once("error", ({ message }: { message: string }) => {
console.log(`Error deleting bucket: ${message}`);
reject(new Error(message));
});
});
}
public async renameBucket(oldBucketId: string, newBucketId: string): Promise<void> {
if (this.connectionInfo) {
this.initialize();
}
if (!oldBucketId || !newBucketId) {
console.log("Error: Old and new bucket IDs are required");
throw new Error("Old and new bucket IDs are required");
}
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("bucket:action", {action: 'rename', bucketId: oldBucketId, newBucketId, token });
this.socket.once("bucket:renamed", ({ oldBucketId: oldId, newBucketId: newId }: { oldBucketId: string; newBucketId: string }) => {
console.log(`Bucket renamed from ${oldId} to ${newId}`);
resolve();
});
this.socket.once("error", ({ message }: { message: string }) => {
console.log(`Error renaming bucket: ${message}`);
reject(new Error(message));
});
});
}
//------ PERMISSION SCOPE ------
public async createPermission(itemId: string, requireAction: string, requireRole: string | null): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("permission", { action: "create", itemId, requireAction, requireRole });
this.socket.once("permissionCreated", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async getPermission(permissionId: string): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("permission", { action: "get", permissionId });
this.socket.once("permission", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async getPermissions(itemId: string | null): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("permission", { action: "getAll", itemId });
this.socket.once("permissions", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async updatePermission(permissionId: string, itemId: string, requireAction: string, requireRole: string | null): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("permission", { action: "update", permissionId, itemId, requireAction, requireRole });
this.socket.once("permissionUpdated", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async deletePermission(permissionId: string): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("permission", { action: "delete", permissionId });
this.socket.once("permissionDeleted", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async createUserPermission(userId: string, onDoc: string, permission: string): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("userPermission", { action: "create", userId, onDoc, permission });
this.socket.once("userPermissionCreated", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async getUserPermissions(userId: string, onDoc: string | null): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("userPermission", { action: "getAll", userId, onDoc });
this.socket.once("userPermissions", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async updateUserPermission(permissionId: string, onDoc: string, permission: string): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("userPermission", { action: "update", permissionId, onDoc, permission });
this.socket.once("userPermissionUpdated", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async deleteUserPermission(permissionId: string): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("userPermission", { action: "delete", permissionId });
this.socket.once("userPermissionDeleted", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async checkUserPermission(userId: string, onDoc: string, requiredPermission: string): Promise<any> {
if (this.connectionInfo) {
this.initialize();
}
return new Promise((resolve, reject) => {
this.socket.emit("userPermission", { action: "check", userId, onDoc, requiredPermission });
this.socket.once("userPermissionCheck", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
//------ TEAMS SCOPE ------
public async createTeam(name: string, styling: string, creatorId: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "create", name, styling, creatorId, token });
this.socket.once("teamCreated", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async getTeam(teamId: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "get", teamId, token });
this.socket.once("team", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async getTeams(userId: string | null): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "getAll", userId, token });
this.socket.once("teams", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async updateTeam(teamId: string, name: string, styling: string, userId: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "update", teamId, name, styling, userId, token });
this.socket.once("teamUpdated", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async deleteTeam(teamId: string, userId: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "delete", teamId, userId, token });
this.socket.once("teamDeleted", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async addTeamUser(teamId: string, userId: string, role: string, addedBy: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "addUser", teamId, userId, role, addedBy, token });
this.socket.once("teamUserAdded", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async removeTeamUser(teamId: string, userId: string, removedBy: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "removeUser", teamId, userId, removedBy, token });
this.socket.once("teamUserRemoved", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async updateTeamUserRole(teamId: string, userId: string, role: string, updatedBy: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "updateUserRole", teamId, userId, role, updatedBy, token });
this.socket.once("teamUserRoleUpdated", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async updateTeamUserLabels(teamId: string, userId: string, labels: string[], updatedBy: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "updateUserLabels", teamId, userId, labels, updatedBy, token });
this.socket.once("teamUserLabelsUpdated", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async leaveTeam(teamId: string, userId: string): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "leave", teamId, userId, token });
this.socket.once("teamUserLeft", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public async listTeams(): Promise<any> {
if (this.connectionInfo) this.initialize();
const token = localStorage.getItem("t_auth");
return new Promise((resolve, reject) => {
this.socket.emit("teams", { action: "listAll", token });
this.socket.once("teams", (data: any) => resolve(data));
this.socket.once("error", (error: any) => reject(new Error(error.message)));
});
}
public close(): void {
this.socket.close();
}
}