@salutejs/jazz-sdk-electron
Version:
Jazz SDK Electron
769 lines (741 loc) • 22.9 kB
TypeScript
import {
JazzSdkOptions,
JazzSdk,
JazzActivityEvent,
JazzRoomEventParticipantLeft,
JazzRoomEventParticipantJoined,
JazzRoomEventParticipantUpdate,
JazzRoomEventParticipants,
JazzRoomEventLocalParticipantChanged,
JazzRoomEventLocalParticipantId,
JazzRoomEventDisconnecting,
JazzRoomParticipantId,
JazzSdkAdditionalPlugins,
JazzRoom,
JazzClient,
JazzSdkPlugin,
} from '@salutejs/jazz-sdk-web';
import { Container } from 'ditox';
import { IpcRenderer } from 'electron';
/**
* Creates Jazz SDK for electron applications.
*/
declare function createJazzSdkElectron(
options?: JazzSdkOptions,
): Promise<JazzSdk>;
type TransportEventRegisterEndpoint = {
type: 'registerEndpoint';
payload: {
endpointName: string;
};
};
type TransportEventUnregisterEndpoint = {
type: 'unregisterEndpoint';
payload: {
endpointName: string;
};
};
type TransportEventHandsRaised = {
type: 'handsRaised';
payload: {
handsRaised: JazzRoomParticipantId[];
};
};
type ElectronVersion = {
major: number;
minor: number;
patch: number;
};
type MetaInfo = Readonly<{
electronVersion: ElectronVersion;
}>;
type TransportEventMetaIn = Readonly<{
type: 'electron:meta:out';
payload: MetaInfo;
}>;
type TransportEventMetaOut = Readonly<{
type: 'electron:meta:in';
}>;
type TransportEvent = (
| JazzActivityEvent
| JazzRoomEventParticipantLeft
| JazzRoomEventParticipantJoined
| JazzRoomEventParticipantUpdate
| JazzRoomEventParticipants
| JazzRoomEventLocalParticipantChanged
| JazzRoomEventLocalParticipantId
| JazzRoomEventDisconnecting
| TransportEventRegisterEndpoint
| TransportEventUnregisterEndpoint
| TransportEventUnregisterEndpoint
| TransportEventHandsRaised
| TransportEventMetaIn
| TransportEventMetaOut
) &
EventLike$1;
/**
* experimental
*/
type TransportInvokeEvent =
| {
type: 'someType1';
payload: {
foo: 'bar';
};
response: {
bar: 'foo';
};
}
| {
type: 'someType2';
response: {
bar: 'foo';
};
};
type EventLike$1 = {
type: string;
to?: string;
};
type EventLikeWithResponse = {
type: string;
payload?: unknown;
response: unknown;
};
type EventLikeWithResponsePayload = {
type: string;
payload: unknown;
response: unknown;
};
/**
* @deprecated use elebus + multiWindowTransport MULTI_WINDOW_TRANSPORT_SERVICE_TOKEN
*/
type TransportService<
M extends EventLike$1 = TransportEvent,
I extends EventLikeWithResponse = TransportInvokeEvent,
> = {
once: <
Type extends M['type'],
Result extends M & {
type: Type;
},
>(
key: Type,
callback: (
...args: Result extends {
payload: infer S;
}
? [S]
: []
) => void,
) => () => void;
on: <
Type extends M['type'],
Result extends M & {
type: Type;
},
>(
key: Type,
callback: (
...args: Result extends {
payload: infer S;
}
? [S]
: []
) => void,
) => () => void;
off: <
Type extends M['type'],
Result extends M & {
type: Type;
},
>(
key: Type,
callback: (
...args: Result extends {
payload: infer S;
}
? [S]
: []
) => void,
) => void;
/**
* reference to "on"
*/
subscribe: <
Type extends M['type'],
Result extends M & {
type: Type;
},
>(
key: Type,
callback: (
...args: Result extends {
payload: infer S;
}
? [S]
: []
) => void,
) => () => void;
addListener: <
Type extends M['type'],
Result extends M & {
type: Type;
},
>(
key: Type,
callback: (
...args: Result extends {
payload: infer S;
}
? [S]
: []
) => void,
) => void;
/**
* reference to "off"
*/
removeListener: <
Type extends M['type'],
Result extends M & {
type: Type;
},
>(
key: Type,
callback: (
...args: Result extends {
payload: infer S;
}
? [S]
: []
) => void,
) => void;
send: (event: M) => void;
/**
* experimental
*/
__invoke: <
Type extends I['type'],
Payload extends I & {
type: Type;
},
Response extends (I & {
type: Type;
})['response'],
>(
params: Payload extends EventLikeWithResponsePayload
? {
type: Type;
payload: Payload['payload'];
}
: {
type: Type;
},
) => Promise<Response>;
withType: <
S extends EventLike$1 | undefined | void | null,
O extends EventLikeWithResponse | undefined | void | null = void,
>() => S extends EventLike$1
? O extends EventLikeWithResponse
? TransportService<M | S, I | O>
: TransportService<M | S, I>
: O extends EventLikeWithResponse
? TransportService<M, I | O>
: TransportService<M, I>;
};
type JazzSdkElectronBridge = {
transport: TransportService;
};
type JazzSdkElectronEndpointOptions = Readonly<{
container?: Container;
/** Extensions for the SDK */
plugins?: JazzSdkAdditionalPlugins;
endpointName: string;
bridge?: () => JazzSdkElectronBridge;
ipcRenderer?: IpcRenderer;
}>;
type JazzSdkElectronEndpoint = Readonly<{
container: Container;
destroy: () => void;
}>;
/**
* Creates Jazz SDK for browserWindows of electron.
*/
declare function createJazzSdkElectronEndpoint(
options: JazzSdkElectronEndpointOptions,
): Promise<JazzSdkElectronEndpoint>;
declare function getJazzSdkMetaInfo(jazzSdk: JazzSdk): MetaInfo;
/**
* Event name for subscribe to all events in transport
*/
declare type AllEventTypes = '*';
declare interface BaseEventBusReadonly<EVENTS extends EventLike>
extends BaseEventBusSubscriber<EVENTS> {
name?: string;
}
declare interface BaseEventBusSubscriber<EVENTS extends EventLike> {
/**
* Method for subscribing to bus events.
* In addition to events of the type, you can also specify the * event,
* which will allow you to subscribe to all bus events.
* The method returns a function for unsubscribing the callback
* (this can also be done via the off or removeEventListener methods).
*
* If the onSubscribe lifecycle method is passed,
* it will be called when this event is sent.
*
* If the transport was destroyed, this method will do nothing.
*
* @example
* ```ts
* type Events = { event: string };
* const eventBus = createBaseEventBus<Events>();
*
* const unsubscriber = eventBus.on('event', (event, payload) => console.log(payload));
* unsubscriber();
*
* eventBus.send('event', 'test');
* ```
*/
on<EVENT extends string & keyof EVENTS>(
event: EVENT,
callback: (event: EVENT, payload: EVENTS[EVENT]) => void,
): Unsubscriber;
/**
* unsubscribe from an event.
* If there are no subscribers left for the event, we remove it from the map.
*
* If the onUnsubscribe lifecycle callback is passed,
* it will be called each time this function is called.
*
* If the transport was destroyed, the method does not work.
*
* @example
* ```ts
* type Events = { event: string };
* const eventBus = createBaseEventBus<Events>();
*
* function handler(type: string, payload: string): void {}
*
* eventBus.on('event', handler);
* eventBus.off('event', handler);
* ```
*/
off<EVENT extends string & keyof EVENTS>(
event: EVENT,
callback: (event: EVENT, payload: EVENTS[EVENT]) => void,
): void;
}
declare interface BaseTransportNodeReadonly {
name?: string;
__isRoot: Readonly<false>;
/**
* A property indicating that a class has been destroyed.
* Once resolved, all methods in it stop working and the data is cleared.
*/
isDestroyed: boolean;
/**
* Method to get the root node object referenced by the node.
*/
getTransports: () => TransportRootNodes;
}
declare interface BaseTransportRoot extends DestroyedNode {
name?: string;
__isRoot: Readonly<true>;
}
/**
* A node that has a cleanup mechanism. After the method chchchch is executed,
* the node becomes inactive because event subscriptions and message sending stop functioning.
*/
declare interface DestroyedNode {
/**
* whether the transport is destroyed.
* If the transport is destroyed,
* then subscriptions and event sending do not work, and the subscriber list is destroyed.
* Also, all dependent nodes are automatically unsubscribed from the destroyed node.
*/
isDestroyed: boolean;
destroy(): void;
}
declare type EventLike = Record<string, unknown>;
declare type Namespace = string;
declare type TransportLifecycleEvents<EVENTS extends EventLike> = {
/**
* The transport was cleared. After that,
* it stops functioning and all data in it is cleared.
*/
destroy: undefined;
/**
* Subscribed to some event.
* The object indicates what event was subscribed to and whether it is the first.
*/
subscribe: {
event: string & keyof EVENTS;
mode: 'on' | 'once';
subscriber: Parameters<TransportRootSubscribers<EVENTS>['on']>[1];
subscribersCount: number;
};
/**
* Unsubscribed from some event.
* The object indicates what event was unsubscribed from and whether there are more subscribers.
*/
unsubscribe: {
event: string & keyof EVENTS;
mode: 'on' | 'once';
subscriber: Parameters<TransportRootSubscribers<EVENTS>['off']>[1];
subscribersCount: number;
};
};
declare interface TransportReadonlyNode<EVENTS extends EventLike>
extends TransportReadonlyNodeBase<EVENTS> {
lifecycle: TransportRoot<EVENTS>['lifecycle'];
}
declare type TransportReadonlyNodeBase<EVENTS extends EventLike> =
TransportRootSubscribers<EVENTS> & BaseTransportNodeReadonly;
declare interface TransportRoot<EVENTS extends EventLike>
extends TransportRootBase<EVENTS> {
/**
* Sync mode sending events
*
* @default false
*/
sync?: Readonly<boolean>;
/**
* Method for sending an event to listeners.
* If the transport was destroyed,
* or no one is subscribed to this event, the method will do nothing.
*
* If there are subscribers to *,
* they will listen to all events that were forwarded.
*
* The method works in 2 modes: synchronous and asynchronous (asynchronous mode is enabled by default).
* To change this, you need to pass the 3rd argument.
*
* @example
* ```ts
* type Events = { event: string, event_empty: undefined };
* const transport = createTransport<Events>();
*
* transport.on('event', (event, payload) => console.log(payload));
* transport.on('event_empty', (event, payload) => console.log(payload));
* transport.on('*', (event, payload) => console.log(payload));
*
* transport.send('event', 'test');
* transport.send('event_empty');
* transport.send('event_empty', undefined);
* ```
*/
send<
TYPE extends string & keyof EVENTS,
PARAMETERS extends EVENTS[TYPE] extends undefined
? (payload?: EVENTS[TYPE]) => void
: (payload: EVENTS[TYPE]) => void,
>(
type: TYPE,
...other: Parameters<PARAMETERS>
): void;
/**
* Method for getting a node that has only subscription interfaces (on/once/off).
* Recommended for use in public API services to hide methods
* for direct control of transport state from the outside.
*/
asReadonly(): TransportReadonlyNode<EVENTS>;
}
declare type TransportRootBase<EVENTS extends EventLike> =
TransportRootSubscribers<EVENTS> &
BaseTransportRoot & {
/**
* Transport lifecycle event bus. You can subscribe to 3 events:
* 1) destroy - the transport was cleared. After that, it stops functioning and all data in it is cleared.
* 2) subscribe - subscribed to some event. The object indicates what event was subscribed to and whether it is the first.
* 3) unsubscribe - unsubscribed from some event. The object indicates what event was unsubscribed from and whether there are more subscribers.
*
* When the main transport is destroyed, the lifecycle event bus also dies.
*
* @example
* ```ts
* const transport = createTransport<Events>();
*
* transport.lifecycle.on('destroy', () => console.log('transport is destroy'));
* transport.lifecycle.on('subscribe', ({ event, isFirstSubscribe }) => console.log(`subscribe to event ${event} isFirst=${isFirstSubscribe}`));
* transport.lifecycle.on('unubscribe', ({ event, isHasSubscribers }) => console.log(`unsubscribe from event ${event} isHasSubscribers=${isHasSubscribers}`));
*
* const unsubscriber1 = transport.on('event1', () => {}) // subscribe to event event1 isFirst=true
* const unsubscriber2 = transport.on('event1', () => {}) // subscribe to event event1 isFirst=false
* const unsubscriber3 = transport.on('event2', () => {}) // subscribe to event event2 isFirst=true
*
* unsubscriber3() // unsubscribe from event event2 isHasSubscribers=false
* unsubscriber2() // unsubscribe from event event1 isHasSubscribers=true
* unsubscriber1() // unsubscribe from event event1 isHasSubscribers=false
*
* transport.destroy(); // transport is destroy
* ```
*/
lifecycle: Readonly<
BaseEventBusReadonly<TransportLifecycleEvents<EVENTS>>
>;
};
/**
* List of nodes the node is subscribed to.
*/
declare type TransportRootNodes = Record<Namespace, Array<TransportRoot<any>>>;
declare interface TransportRootSubscribers<EVENTS extends EventLike> {
/**
* Method for subscribing to bus events.
* In addition to events of the type, you can also specify the * event,
* which will allow you to subscribe to all bus events.
* The method returns a function for unsubscribing the callback
* (this can also be done via the off or removeEventListener methods).
*
* If the onSubscribe lifecycle method is passed,
* it will be called when this event is sent.
*
* If the transport was destroyed, this method will do nothing.
*
* @example
* ```ts
* type Events = { event: string };
* const transport = createTransport<Events>();
*
* transport.on('event', (event, payload) => console.log(payload));
* const unsubscriber = transport.on('*', (event, payload) => console.log(payload));
* unsubscriber();
*
* transport.send('event', 'test');
* ```
*/
on<
EVENT_TYPE extends string & (keyof EVENTS | AllEventTypes),
EVENT extends EVENT_TYPE extends AllEventTypes
? string & keyof EVENTS
: EVENT_TYPE,
CB extends {
[TYPE in EVENT]: [TYPE, EVENTS[TYPE]];
},
>(
event: EVENT_TYPE,
callback: (...args: CB[EVENT]) => void,
): Unsubscriber;
/**
* A method for one-time subscription to bus events.
* In addition to events of the type, you can also specify an event *,
* which will allow you to subscribe to all bus events.
* The method returns a function for unsubscribing the callback
* (this can also be done via the off or removeEventListener methods).
*
* If the onSubscribe lifecycle method is passed,
* it will be called when this event is sent.
*
* If the transport was destroyed, this method will do nothing.
*
* @example
* ```ts
* type Events = { event: string };
* const transport = createTransport<Events>();
*
* transport.once('event', (event, payload) => console.log(payload));
* const unsubscriber = transport.once('*', (event, payload) => console.log(payload));
* unsubscriber();
*
* transport.send('event', 'test');
* transport.send('event', 'test'); // not call subscribers
* ```
*/
once<
EVENT_TYPE extends string & (keyof EVENTS | AllEventTypes),
EVENT extends EVENT_TYPE extends AllEventTypes
? string & keyof EVENTS
: EVENT_TYPE,
CB extends {
[TYPE in EVENT]: [TYPE, EVENTS[TYPE]];
},
>(
event: EVENT_TYPE,
callback: (...args: CB[EVENT]) => void,
): Unsubscriber;
/**
* unsubscribe from an event.
* If there are no subscribers left for the event, we remove it from the map.
*
* If the onUnsubscribe lifecycle callback is passed,
* it will be called each time this function is called.
*
* If the transport was destroyed, the method does not work.
*
* @example
* ```ts
* type Events = { event: string };
* const transport = createTransport<Events>();
*
* function handler(type: string, payload: string): void {}
*
* transport.on('event', handler);
* transport.off('event', handler);
* ```
*/
off<EVENT_TYPE extends string & (keyof EVENTS | AllEventTypes)>(
event: EVENT_TYPE,
callback: (...args: any[]) => void,
): void;
}
/**
* unsubscribe function to unsubscribe from an event.
*/
declare type Unsubscriber = () => void;
type MultiWindowTransportWindowName = LooseAutocomplete<
MainProcessWindowName | MainWindowName
>;
type MultiWindowTransportTransportName = string;
type MainProcessWindowName = 'main_process';
/**
* Зарезервированное имя по умолчанию для сервиса в render процессе
*/
type MainWindowName = 'mainWindow';
type LooseAutocomplete<T extends string> = T | (string & {});
type MultiWindowTransportSendTo =
| LooseAutocomplete<'*' | MainProcessWindowName | MainWindowName>
| MultiWindowTransportWindowName[];
type MultiWindowTransportServiceGetEventsForTransport = {
isReady: undefined;
'service:register': {
window: MultiWindowTransportWindowName;
};
'service:unregister': {
window: MultiWindowTransportWindowName;
};
'service:initialized': {
window: MultiWindowTransportWindowName;
};
'transport:register': {
transport: MultiWindowTransportTransportName;
window: MultiWindowTransportWindowName;
};
'transport:unregister': {
transport: MultiWindowTransportTransportName;
window: MultiWindowTransportWindowName;
};
'transport:event:subscribe': {
transport: MultiWindowTransportTransportName;
window: MultiWindowTransportWindowName;
event: string;
};
'transport:event:unsubscribe': {
transport: MultiWindowTransportTransportName;
window: MultiWindowTransportWindowName;
event: string;
};
};
type MultiWindowTransportModify<
INITIAL_TYPE extends EventLike,
MODIFY_TYPE extends EventLike = INITIAL_TYPE,
> = {
/**
* Модификация отправляемых данных в другие окна
*/
send: <
TYPE extends keyof INITIAL_TYPE & string,
PAYLOAD extends INITIAL_TYPE[TYPE],
>(
type: TYPE,
payload: PAYLOAD,
) => Promise<MODIFY_TYPE>;
/**
* Модификация событий, полученных из других окон приложения
*/
get: <
TYPE extends keyof MODIFY_TYPE & string,
PAYLOAD extends MODIFY_TYPE[TYPE],
>(
type: TYPE,
payload: PAYLOAD,
) => Promise<INITIAL_TYPE>;
};
type MultiWindowTransportUnsubscribe = () => void;
type MultiWindowTransportRegisterOptions<
INITIAL_TYPE extends EventLike,
MODIFY_TYPE extends EventLike = INITIAL_TYPE,
> = {
/**
* под каким именем будет использоваться транспорт.
* Если параметр не передан, то имя будет взято из транспорта.
*/
name?: MultiWindowTransportWindowName;
/**
* elebus шина событий
*/
transport: TransportRoot<INITIAL_TYPE>;
/**
* Модификация отправляемых и получаем событий из других окон приложения
* Нужно, если нужно видоизменить данные. Особенно важно, если событие
* содержит не сериализуемые/дессириализуемые данные (классы)
*/
modify?: MultiWindowTransportModify<INITIAL_TYPE, MODIFY_TYPE>;
/**
* В какие окна должны пересылаться события
* По умолчанию они отправляются во все окна подписчики
* (см параметр name при регистрации плагина)
*
* @default '*'
*/
to?: MultiWindowTransportSendTo;
};
type MultiWindowTransportRegisterInfo = {
unsubscribe: MultiWindowTransportUnsubscribe;
};
type MultiWindowTransportService = {
register: <INITIAL_TYPE extends EventLike, MODIFY_TYPE extends EventLike>(
options: MultiWindowTransportRegisterOptions<INITIAL_TYPE, MODIFY_TYPE>,
) => MultiWindowTransportRegisterInfo;
unregister: <EVENTS extends EventLike>(
transport: TransportRoot<EVENTS>,
) => void;
/**
* Проинициализирован ли сервис до конца
*/
getIsReady: () => boolean;
/**
* Подписка на события сервиса
*/
on: TransportRoot<MultiWindowTransportServiceGetEventsForTransport>['on'];
once: TransportRoot<MultiWindowTransportServiceGetEventsForTransport>['once'];
off: TransportRoot<MultiWindowTransportServiceGetEventsForTransport>['off'];
};
type MultiWindowTransportPluginSettings = {
/**
* Имя сервиса. Для каждого окна оно должно быть уникальным
* Если имя не передано, то будет использоваться значение по умолчанию
*
* `WARNING`: несколько окон с одним именем не должно существовать
* Зарезервировано 2 имени:
* `main_process` - для сервиса на уровне main процесса в electron
* `mainWindow` - для главного окна приложения
*/
name?: MultiWindowTransportTransportName;
/**
* Если у нас идет в окне изоляция и мы не можем получить доступ
* к preload слою, то передаем в плагин ipcRender,
* чтоб создать свой бридж
*/
ipcRenderer?: IpcRenderer;
};
declare function getMultiWindowTransport(
sdk: JazzRoom | JazzClient | JazzSdk,
): MultiWindowTransportService;
declare function multiWindowTransportPlugin(
settings?: MultiWindowTransportPluginSettings,
): JazzSdkPlugin;
export {
type JazzSdkElectronEndpoint,
type JazzSdkElectronEndpointOptions,
type MultiWindowTransportModify,
type MultiWindowTransportPluginSettings,
type MultiWindowTransportRegisterInfo,
type MultiWindowTransportRegisterOptions,
type MultiWindowTransportSendTo,
type MultiWindowTransportService,
type MultiWindowTransportUnsubscribe,
createJazzSdkElectron,
createJazzSdkElectronEndpoint,
getJazzSdkMetaInfo,
getMultiWindowTransport,
multiWindowTransportPlugin,
};