feat: ticket system base implementation

This commit is contained in:
2026-06-19 01:19:01 +05:30
parent a18fff4d6f
commit 8c3d19a429
19 changed files with 1400 additions and 27 deletions

View File

@@ -0,0 +1 @@
export * from './sse.service';

View File

@@ -0,0 +1,66 @@
import { ENV_CONSTANT } from '@/constants/secrect.constant';
export type SseEventHandler<T = unknown> = (
data: T,
event: MessageEvent,
) => void;
export type SseEventMap<TEvents extends Record<string, unknown>> = {
[EventName in keyof TEvents]: SseEventHandler<TEvents[EventName]>;
};
export interface SseConnection {
source: EventSource;
close: () => void;
}
function getSseUrl(path: string) {
if (/^https?:\/\//i.test(path)) return path;
const baseUrl = ENV_CONSTANT.BASE_API_URL ?? '';
const normalizedBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
return `${normalizedBase}${normalizedPath}`;
}
function parseEventData(event: MessageEvent) {
if (!event.data) return null;
try {
return JSON.parse(event.data);
} catch {
return event.data;
}
}
export const sseService = {
connect: <TEvents extends Record<string, unknown>>(
path: string,
events: SseEventMap<TEvents>,
): SseConnection => {
const source = new EventSource(getSseUrl(path));
const cleanups: Array<() => void> = [];
Object.entries(events).forEach(([eventName, handler]) => {
const listener = (event: Event) => {
const messageEvent = event as MessageEvent;
(handler as SseEventHandler)(
parseEventData(messageEvent),
messageEvent,
);
};
source.addEventListener(eventName, listener);
cleanups.push(() => source.removeEventListener(eventName, listener));
});
return {
source,
close: () => {
cleanups.forEach((cleanup) => cleanup());
source.close();
},
};
},
};