import ChannelCore, { ChPreparedData } from './ChannelCore'; import Bag from '../Bag'; import Socket from '../Socket'; import { UnsubscribeTrigger } from '../../main/channel/channelDefinitions'; import { DeepReadonly } from '../../main/utils/typeUtils'; import { ChannelConfig } from '../../main/config/definitions/parts/channelConfig'; import { ComplexTypesOption } from 'ziron-worker'; /** * Channels implements the subscribe/publish architecture. * They ideal for sending something to multiple clients. * When you want to reach that data should be kept up to date * on a client in real-time you should use Databoxes instead. * * Instead of the StaticChannel, the Chanel class allows you to have * multiple members that differ by a hashable value. * That is useful in many cases, for example, if you want to * have a Channel for user notifications. * Then, the members could be the ids of the users. * * You can override these methods: * - initialize * * events: * - onSubscription * - onUnsubscription * - onPublish * * middleware methods: * - memberMiddleware */ export default class Channel extends ChannelCore { /** * Maps the member to the sockets and kick out function. */ private readonly _regMembers; /** * Maps the sockets to the members. */ private readonly _socketMembers; private readonly _unregisterMemberTimeoutMap; private readonly _maxSocketMembers; private readonly _chIdPreFix; private readonly _onPublish; private readonly _onSubscription; private readonly _onUnsubscription; private readonly _memberMiddleware; constructor(identifier: string, bag: Bag, chPreparedData: ChPreparedData, apiLevel: number | undefined); private _addSocket; /** * Returns the socket member map or builds a new one and returns it. * @param member * @private */ private _buildSocketMemberMap; /** * Registers for listening to a new member. * @param member * @private */ private _registerMember; /** * Unregisters for listening to a member. * @param memberStr * @private */ private _unregisterMember; private _unsubscribeSocket; private _rmSocket; /** * Clears the timeout to unregister the member. * @param memberStr * @private */ private _clearUnregisterMemberTimeout; /** * Creates (set or renew) the timeout to unregister a member. * @param memberStr * @private */ private _createUnregisterMemberTimeout; /** * Processes an internal publish. * @private */ private _processPublish; /** * Close the member of this Channel. * @param memberStr * @param closePackage * @private */ private _close; private _internalClose; private _sendToServers; /** * **Not override this method.** * This method returns an array * with all members that the socket has subscribed. * @param socket */ getSocketSubMembers(socket: Socket): DeepReadonly[]; /** * **Not override this method.** * Publish into a member of this channel. * @param member * @param event * @param data * @param processComplexTypes * @param publisherSid * The publisher sid indicates the socket sid that publishes the data. * If you provide one the published data will not send to the publisher socket. */ publish(member: M, event: string, data?: any, { processComplexTypes, publisherSid }?: ComplexTypesOption & { publisherSid?: string; }): void; /** * **Not override this method.** * The close function will close a Channel member for every client on every server. * You optionally can provide a code or any other information for the client. * Usually, the close function is used when the data is completely deleted from the system. * For example, a chat that doesn't exist anymore. * @param member The member you want to close. * @param code * @param metadata * @param forEveryServer * @return The returned promise is resolved when * the close is fully processed on the current server. */ close(member: M, code?: number | string, metadata?: any, forEveryServer?: boolean): Promise; /** * **Not override this method.** * Kicks out a socket from a member of this channel. * @param member * @param socket * @param metadata * @param data */ kickOut(member: M, socket: Socket, metadata?: number | string, data?: any): void; /** * With this function, you can do a recheck of all sockets on a specific member. * It can be useful when the access rights to member have changed, * and you want to kick out all sockets that not have access anymore. * Notice that the promise is resolved when the access was checked * on the current server and request sent to other servers. * @param member * @param forEveryServer */ recheckMemberAccess(member: M, forEveryServer?: boolean): Promise; /** * **Can be overridden.** * With the member middleware, you can protect your Channel against invalid members. * For example, when you have a Channel for user-notifications and the member represents * the user id you can block invalid user ids. * To block the member, you can return a Block instance or false or throwing a Block instance. * If you don't return anything, the member will be allowed. * The Bag instance can be securely accessed with the variable 'bag'. * @param member */ protected memberMiddleware(member: DeepReadonly): Promise | boolean | object | any; /** * **Can be overridden.** * A function that gets triggered when a socket subscribes to this channel. * @param member * @param socket */ protected onSubscription(member: DeepReadonly, socket: Socket): Promise | void; /** * **Can be overridden.** * A function that gets triggered when a socket unsubscribes this channel. * @param member * @param socket * @param trigger */ protected onUnsubscription(member: DeepReadonly, socket: Socket, trigger: UnsubscribeTrigger): Promise | void; /** * **Can be overridden.** * A function that gets triggered when data is published into this channel. * @param member * @param event * @param data */ protected onPublish(member: DeepReadonly, event: string, data: any): Promise | void; } export declare type ChannelClass = (new (...args: any[]) => Channel) & { config: ChannelConfig; prototype: Channel; };