All files / sdk/utils pusher.ts

14.28% Statements 4/28
25% Branches 2/8
0% Functions 0/7
14.81% Lines 4/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 1169x   9x 9x                                                 9x                                                                                                                                                                              
import logger from "../../utils/logger";
 
const PUSHER_KEY = process.env.CLIENT_PUSHER_KEY || "ff9f18c208855d77a152"
const PUSHER_CLUSTER = "mt1"
 
type PusherClient = any;
 
export interface TriggerData {
    appName: string;
    clientId: number;
    payload: {};
    originalPayload: Record<string, any>;
    metadata: {
        id: string;
        connectionId: string;
        triggerName: string;
        triggerData: string;
        triggerConfig: Record<string, any>;
        connection: {
            id: string;
            integrationId: string;
            clientUniqueUserId: string;
            status: string;
        }
    }
}
 
 
export class PusherUtils {
 
    static pusherClient:  PusherClient;
 
    static getPusherClient(baseURL: string, apiKey: string):  PusherClient {
 
        Iif (!PusherUtils.pusherClient) {
            const PusherClient = require("pusher-js")
            PusherUtils.pusherClient = new PusherClient(PUSHER_KEY, {
                cluster: PUSHER_CLUSTER,
                channelAuthorization: {
                    endpoint: `${baseURL}/api/v1/client/auth/pusher_auth`,
                    headers: {
                        "x-api-key": apiKey
                    },
                    transport: "ajax",
                }
            });
            
        }
        return PusherUtils.pusherClient;
    }
    /**
     * Subscribes to a Pusher channel and binds an event to a callback function.
     * @param {string} channelName - The name of the channel to subscribe to.
     * @param {string} event - The event to bind to the channel.
     * @param {(data: any) => void} fn - The callback function to execute when the event is triggered.
     * @returns {PusherClient} The Pusher client instance.
     */
    static async subscribe(channelName: string, event: string, fn: (data: any) => void): Promise<void> {
        try {
            await PusherUtils.pusherClient.subscribe(channelName).bind(event, fn);
        } catch (error) {
            logger.error(`Error subscribing to ${channelName} with event ${event}: ${error}`);
        }
    }
 
    /**
     * Unsubscribes from a Pusher channel.
     * @param {string} channelName - The name of the channel to unsubscribe from.
     * @returns {void}
     */
    static async unsubscribe(channelName: string): Promise<void> {
        PusherUtils.pusherClient.unsubscribe(channelName);
    }
 
    /**
     * Binds an event to a channel with support for chunked messages.
     * @param {PusherClient} channel - The Pusher channel to bind the event to.
     * @param {string} event - The event to bind to the channel.
     * @param {(data: any) => void} callback - The callback function to execute when the event is triggered.
     */
    private static bindWithChunking(channel: PusherClient, event: string, callback: (data: any) => void): void {
        channel.bind(event, callback); // Allow normal unchunked events.
 
        // Now the chunked variation. Allows arbitrarily long messages.
        const events: { [key: string]: { chunks: string[], receivedFinal: boolean } } = {};
        channel.bind("chunked-" + event, (data: { id: string, index: number, chunk: string, final: boolean }) => {
            Iif (!events.hasOwnProperty(data.id)) {
                events[data.id] = { chunks: [], receivedFinal: false };
            }
            const ev = events[data.id];
            ev.chunks[data.index] = data.chunk;
            Iif (data.final) ev.receivedFinal = true;
            Iif (ev.receivedFinal && ev.chunks.length === Object.keys(ev.chunks).length) {
                callback(JSON.parse(ev.chunks.join("")));
                delete events[data.id];
            }
        });
    }
 
    /**
     * Subscribes to a trigger channel for a client and handles chunked data.
     * @param {string} clientId - The unique identifier for the client subscribing to the events.
     * @param {(data: any) => void} fn - The callback function to execute when trigger data is received.
     */
    static triggerSubscribe(clientId: string, fn: (data: TriggerData) => void): void {
        var channel = PusherUtils.pusherClient.subscribe(`private-${clientId}_triggers`);
        PusherUtils.bindWithChunking(channel, "trigger_to_client", fn);
 
        logger.info(`Subscribed to ${clientId}_triggers`);
    }
 
    static triggerUnsubscribe(clientId: string): void {
        PusherUtils.pusherClient.unsubscribe(`${clientId}_triggers`);
    }
}